xref: /haiku/src/apps/debugger/user_interface/gui/team_settings_window/ExceptionStopConfigView.cpp (revision 10b962261a1316c97dc6ca4c1e68e2109472d2d7)
1 /*
2  * Copyright 2013-2015, Rene Gollent, rene@gollent.com.
3  * Distributed under the terms of the MIT License.
4  */
5 #include "ExceptionStopConfigView.h"
6 
7 #include <CheckBox.h>
8 #include <LayoutBuilder.h>
9 
10 #include <AutoDeleter.h>
11 #include <AutoLocker.h>
12 
13 #include "FunctionInstance.h"
14 #include "Image.h"
15 #include "ImageDebugInfo.h"
16 #include "MessageCodes.h"
17 #include "UserInterface.h"
18 #include "Team.h"
19 
20 
21 enum {
22 	MSG_STOP_ON_THROWN_EXCEPTION_CHANGED	= 'stec',
23 	MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED	= 'scec',
24 };
25 
26 
ExceptionStopConfigView(::Team * team,UserInterfaceListener * listener)27 ExceptionStopConfigView::ExceptionStopConfigView(::Team* team,
28 	UserInterfaceListener* listener)
29 	:
30 	BGroupView(B_VERTICAL),
31 	fTeam(team),
32 	fListener(listener),
33 	fExceptionThrown(NULL),
34 	fExceptionCaught(NULL)
35 {
36 	SetName("Exceptions");
37 }
38 
39 
~ExceptionStopConfigView()40 ExceptionStopConfigView::~ExceptionStopConfigView()
41 {
42 }
43 
44 
45 ExceptionStopConfigView*
Create(::Team * team,UserInterfaceListener * listener)46 ExceptionStopConfigView::Create(::Team* team, UserInterfaceListener* listener)
47 {
48 	ExceptionStopConfigView* self = new ExceptionStopConfigView(
49 		team, listener);
50 
51 	try {
52 		self->_Init();
53 	} catch (...) {
54 		delete self;
55 		throw;
56 	}
57 
58 	return self;
59 
60 }
61 
62 
63 void
AttachedToWindow()64 ExceptionStopConfigView::AttachedToWindow()
65 {
66 	fExceptionThrown->SetTarget(this);
67 	fExceptionCaught->SetTarget(this);
68 
69 	AutoLocker< ::Team> teamLocker(fTeam);
70 	_UpdateExceptionState();
71 
72 	BGroupView::AttachedToWindow();
73 }
74 
75 
76 void
MessageReceived(BMessage * message)77 ExceptionStopConfigView::MessageReceived(BMessage* message)
78 {
79 	switch (message->what) {
80 		case MSG_STOP_ON_THROWN_EXCEPTION_CHANGED:
81 		{
82 			_UpdateThrownBreakpoints(fExceptionThrown->Value()
83 				== B_CONTROL_ON);
84 			break;
85 		}
86 		case MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED:
87 		{
88 			break;
89 		}
90 		default:
91 			BGroupView::MessageReceived(message);
92 			break;
93 	}
94 
95 }
96 
97 
98 void
_Init()99 ExceptionStopConfigView::_Init()
100 {
101 	BLayoutBuilder::Group<>(this, B_VERTICAL)
102 		.SetInsets(B_USE_DEFAULT_SPACING)
103 		.AddGlue()
104 		.Add(fExceptionThrown = new BCheckBox("exceptionThrown",
105 			"Stop when an exception is thrown",
106 			new BMessage(MSG_STOP_ON_THROWN_EXCEPTION_CHANGED)))
107 		.Add(fExceptionCaught = new BCheckBox("exceptionCaught",
108 			"Stop when an exception is caught",
109 			new BMessage(MSG_STOP_ON_CAUGHT_EXCEPTION_CHANGED)))
110 		.AddGlue();
111 
112 	// TODO: enable once implemented
113 	fExceptionCaught->SetEnabled(false);
114 }
115 
116 
117 void
_UpdateThrownBreakpoints(bool enable)118 ExceptionStopConfigView::_UpdateThrownBreakpoints(bool enable)
119 {
120 	AutoLocker< ::Team> teamLocker(fTeam);
121 	for (ImageList::ConstIterator it = fTeam->Images().GetIterator();
122 		it.HasNext();) {
123 		Image* image = it.Next();
124 
125 		ImageDebugInfo* info = image->GetImageDebugInfo();
126 		target_addr_t address;
127 		if (_FindExceptionFunction(info, address) != B_OK)
128 			continue;
129 
130 		if (enable)
131 			fListener->SetBreakpointRequested(address, true, true);
132 		else
133 			fListener->ClearBreakpointRequested(address);
134 	}
135 }
136 
137 
138 status_t
_FindExceptionFunction(ImageDebugInfo * info,target_addr_t & _foundAddress) const139 ExceptionStopConfigView::_FindExceptionFunction(ImageDebugInfo* info,
140 	target_addr_t& _foundAddress) const
141 {
142 	if (info != NULL) {
143 		FunctionInstance* instance = info->FunctionByName(
144 			"__cxa_allocate_exception");
145 		if (instance == NULL)
146 			instance = info->FunctionByName("__throw(void)");
147 
148 		if (instance != NULL) {
149 			_foundAddress = instance->Address();
150 			return B_OK;
151 		}
152 	}
153 
154 	return B_NAME_NOT_FOUND;
155 }
156 
157 
158 void
_UpdateExceptionState()159 ExceptionStopConfigView::_UpdateExceptionState()
160 {
161 	// check if the exception breakpoints are already installed
162 	for (ImageList::ConstIterator it = fTeam->Images().GetIterator();
163 		it.HasNext();) {
164 		Image* image = it.Next();
165 
166 		ImageDebugInfo* info = image->GetImageDebugInfo();
167 		target_addr_t address;
168 		if (_FindExceptionFunction(info, address) != B_OK)
169 			continue;
170 
171 		if (fTeam->BreakpointAtAddress(address) != NULL) {
172 			fExceptionThrown->SetValue(B_CONTROL_ON);
173 			break;
174 		}
175 	}
176 }
177