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