110b96226SRene Gollent/*
210b96226SRene Gollent * Copyright 2013-2015, Rene Gollent, rene@gollent.com.
310b96226SRene Gollent * Distributed under the terms of the MIT License.
410b96226SRene Gollent */
510b96226SRene Gollent#include "ExceptionStopConfigView.h"
610b96226SRene Gollent
710b96226SRene Gollent#include <CheckBox.h>
810b96226SRene Gollent#include <LayoutBuilder.h>
910b96226SRene Gollent
1010b96226SRene Gollent#include <AutoDeleter.h>
1110b96226SRene Gollent#include <AutoLocker.h>
1210b96226SRene Gollent
1310b96226SRene Gollent#include "FunctionInstance.h"
1410b96226SRene Gollent#include "Image.h"
1510b96226SRene Gollent#include "ImageDebugInfo.h"
1610b96226SRene Gollent#include "MessageCodes.h"
1710b96226SRene Gollent#include "UserInterface.h"
1810b96226SRene Gollent#include "Team.h"
1910b96226SRene Gollent
2010b96226SRene Gollent
2110b96226SRene Gollentenum {
2210b96226SRene Gollent	MSG_STOP_ON_THROWN_EXCEPTION_CHANGED	= 'stec',
2310b96226SRene Gollent	MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED	= 'scec',
2410b96226SRene Gollent};
2510b96226SRene Gollent
2610b96226SRene Gollent
2710b96226SRene GollentExceptionStopConfigView::ExceptionStopConfigView(::Team* team,
2810b96226SRene Gollent	UserInterfaceListener* listener)
2910b96226SRene Gollent	:
3010b96226SRene Gollent	BGroupView(B_VERTICAL),
3110b96226SRene Gollent	fTeam(team),
3210b96226SRene Gollent	fListener(listener),
3310b96226SRene Gollent	fExceptionThrown(NULL),
3410b96226SRene Gollent	fExceptionCaught(NULL)
3510b96226SRene Gollent{
3610b96226SRene Gollent	SetName("Exceptions");
3710b96226SRene Gollent}
3810b96226SRene Gollent
3910b96226SRene Gollent
4010b96226SRene GollentExceptionStopConfigView::~ExceptionStopConfigView()
4110b96226SRene Gollent{
4210b96226SRene Gollent}
4310b96226SRene Gollent
4410b96226SRene Gollent
4510b96226SRene GollentExceptionStopConfigView*
4610b96226SRene GollentExceptionStopConfigView::Create(::Team* team, UserInterfaceListener* listener)
4710b96226SRene Gollent{
4810b96226SRene Gollent	ExceptionStopConfigView* self = new ExceptionStopConfigView(
4910b96226SRene Gollent		team, listener);
5010b96226SRene Gollent
5110b96226SRene Gollent	try {
5210b96226SRene Gollent		self->_Init();
5310b96226SRene Gollent	} catch (...) {
5410b96226SRene Gollent		delete self;
5510b96226SRene Gollent		throw;
5610b96226SRene Gollent	}
5710b96226SRene Gollent
5810b96226SRene Gollent	return self;
5910b96226SRene Gollent
6010b96226SRene Gollent}
6110b96226SRene Gollent
6210b96226SRene Gollent
6310b96226SRene Gollentvoid
6410b96226SRene GollentExceptionStopConfigView::AttachedToWindow()
6510b96226SRene Gollent{
6610b96226SRene Gollent	fExceptionThrown->SetTarget(this);
6710b96226SRene Gollent	fExceptionCaught->SetTarget(this);
6810b96226SRene Gollent
6910b96226SRene Gollent	AutoLocker< ::Team> teamLocker(fTeam);
7010b96226SRene Gollent	_UpdateExceptionState();
7110b96226SRene Gollent
7210b96226SRene Gollent	BGroupView::AttachedToWindow();
7310b96226SRene Gollent}
7410b96226SRene Gollent
7510b96226SRene Gollent
7610b96226SRene Gollentvoid
7710b96226SRene GollentExceptionStopConfigView::MessageReceived(BMessage* message)
7810b96226SRene Gollent{
7910b96226SRene Gollent	switch (message->what) {
8010b96226SRene Gollent		case MSG_STOP_ON_THROWN_EXCEPTION_CHANGED:
8110b96226SRene Gollent		{
8210b96226SRene Gollent			_UpdateThrownBreakpoints(fExceptionThrown->Value()
8310b96226SRene Gollent				== B_CONTROL_ON);
8410b96226SRene Gollent			break;
8510b96226SRene Gollent		}
8610b96226SRene Gollent		case MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED:
8710b96226SRene Gollent		{
8810b96226SRene Gollent			break;
8910b96226SRene Gollent		}
9010b96226SRene Gollent		default:
9110b96226SRene Gollent			BGroupView::MessageReceived(message);
9210b96226SRene Gollent			break;
9310b96226SRene Gollent	}
9410b96226SRene Gollent
9510b96226SRene Gollent}
9610b96226SRene Gollent
9710b96226SRene Gollent
9810b96226SRene Gollentvoid
9910b96226SRene GollentExceptionStopConfigView::_Init()
10010b96226SRene Gollent{
10110b96226SRene Gollent	BLayoutBuilder::Group<>(this, B_VERTICAL)
10210b96226SRene Gollent		.SetInsets(B_USE_DEFAULT_SPACING)
10310b96226SRene Gollent		.AddGlue()
10410b96226SRene Gollent		.Add(fExceptionThrown = new BCheckBox("exceptionThrown",
10510b96226SRene Gollent			"Stop when an exception is thrown",
10610b96226SRene Gollent			new BMessage(MSG_STOP_ON_THROWN_EXCEPTION_CHANGED)))
10710b96226SRene Gollent		.Add(fExceptionCaught = new BCheckBox("exceptionCaught",
10810b96226SRene Gollent			"Stop when an exception is caught",
10910b96226SRene Gollent			new BMessage(MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED)))
11010b96226SRene Gollent		.AddGlue();
11110b96226SRene Gollent
11210b96226SRene Gollent	// TODO: enable once implemented
11310b96226SRene Gollent	fExceptionCaught->SetEnabled(false);
11410b96226SRene Gollent}
11510b96226SRene Gollent
11610b96226SRene Gollent
11710b96226SRene Gollentvoid
11810b96226SRene GollentExceptionStopConfigView::_UpdateThrownBreakpoints(bool enable)
11910b96226SRene Gollent{
12010b96226SRene Gollent	AutoLocker< ::Team> teamLocker(fTeam);
12110b96226SRene Gollent	for (ImageList::ConstIterator it = fTeam->Images().GetIterator();
12210b96226SRene Gollent		it.HasNext();) {
12310b96226SRene Gollent		Image* image = it.Next();
12410b96226SRene Gollent
12510b96226SRene Gollent		ImageDebugInfo* info = image->GetImageDebugInfo();
12610b96226SRene Gollent		target_addr_t address;
12710b96226SRene Gollent		if (_FindExceptionFunction(info, address) != B_OK)
12810b96226SRene Gollent			continue;
12910b96226SRene Gollent
13010b96226SRene Gollent		if (enable)
13110b96226SRene Gollent			fListener->SetBreakpointRequested(address, true, true);
13210b96226SRene Gollent		else
13310b96226SRene Gollent			fListener->ClearBreakpointRequested(address);
13410b96226SRene Gollent	}
13510b96226SRene Gollent}
13610b96226SRene Gollent
13710b96226SRene Gollent
13810b96226SRene Gollentstatus_t
13910b96226SRene GollentExceptionStopConfigView::_FindExceptionFunction(ImageDebugInfo* info,
14010b96226SRene Gollent	target_addr_t& _foundAddress) const
14110b96226SRene Gollent{
14210b96226SRene Gollent	if (info != NULL) {
14310b96226SRene Gollent		FunctionInstance* instance = info->FunctionByName(
14410b96226SRene Gollent			"__cxa_allocate_exception");
14510b96226SRene Gollent		if (instance == NULL)
14610b96226SRene Gollent			instance = info->FunctionByName("__throw(void)");
14710b96226SRene Gollent
14810b96226SRene Gollent		if (instance != NULL) {
14910b96226SRene Gollent			_foundAddress = instance->Address();
15010b96226SRene Gollent			return B_OK;
15110b96226SRene Gollent		}
15210b96226SRene Gollent	}
15310b96226SRene Gollent
15410b96226SRene Gollent	return B_NAME_NOT_FOUND;
15510b96226SRene Gollent}
15610b96226SRene Gollent
15710b96226SRene Gollent
15810b96226SRene Gollentvoid
15910b96226SRene GollentExceptionStopConfigView::_UpdateExceptionState()
16010b96226SRene Gollent{
16110b96226SRene Gollent	// check if the exception breakpoints are already installed
16210b96226SRene Gollent	for (ImageList::ConstIterator it = fTeam->Images().GetIterator();
16310b96226SRene Gollent		it.HasNext();) {
16410b96226SRene Gollent		Image* image = it.Next();
16510b96226SRene Gollent
16610b96226SRene Gollent		ImageDebugInfo* info = image->GetImageDebugInfo();
16710b96226SRene Gollent		target_addr_t address;
16810b96226SRene Gollent		if (_FindExceptionFunction(info, address) != B_OK)
16910b96226SRene Gollent			continue;
17010b96226SRene Gollent
17110b96226SRene Gollent		if (fTeam->BreakpointAtAddress(address) != NULL) {
17210b96226SRene Gollent			fExceptionThrown->SetValue(B_CONTROL_ON);
17310b96226SRene Gollent			break;
17410b96226SRene Gollent		}
17510b96226SRene Gollent	}
17610b96226SRene Gollent}
177