Debugger: Add dedicated functions for global {un}init.
[haiku.git] / src / apps / debugger / target_host_interface / TargetHostInterface.cpp
blobd4034f3a9fb400d64a464b246c9a3e7b617b1e43
1 /*
2 * Copyright 2016, Rene Gollent, rene@gollent.com.
3 * Distributed under the terms of the MIT License.
4 */
6 #include "TargetHostInterface.h"
8 #include <stdio.h>
10 #include <AutoLocker.h>
12 #include "DebuggerInterface.h"
13 #include "MessageCodes.h"
14 #include "TeamDebugger.h"
17 // #pragma mark - TeamDebuggerOptions
20 TeamDebuggerOptions::TeamDebuggerOptions()
22 requestType(TEAM_DEBUGGER_REQUEST_UNKNOWN),
23 commandLineArgc(0),
24 commandLineArgv(NULL),
25 team(-1),
26 thread(-1),
27 settingsManager(NULL),
28 userInterface(NULL),
29 coreFilePath(NULL)
34 // #pragma mark - TargetHostInterface
37 TargetHostInterface::TargetHostInterface()
39 BLooper(),
40 fListeners(),
41 fTeamDebuggers(20, false)
46 TargetHostInterface::~TargetHostInterface()
48 for (ListenerList::Iterator it = fListeners.GetIterator();
49 Listener* listener = it.Next();) {
50 listener->TargetHostInterfaceQuit(this);
55 status_t
56 TargetHostInterface::StartTeamDebugger(const TeamDebuggerOptions& options)
58 // we only want to stop in main for teams we're responsible for
59 // creating ourselves.
60 bool stopInMain = options.requestType == TEAM_DEBUGGER_REQUEST_CREATE;
61 team_id team = options.team;
62 thread_id thread = options.thread;
64 AutoLocker<TargetHostInterface> interfaceLocker(this);
65 if (options.requestType == TEAM_DEBUGGER_REQUEST_CREATE) {
66 status_t error = CreateTeam(options.commandLineArgc,
67 options.commandLineArgv, team);
68 if (error != B_OK)
69 return error;
70 thread = team;
73 if (options.requestType != TEAM_DEBUGGER_REQUEST_LOAD_CORE) {
75 if (team < 0 && thread < 0)
76 return B_BAD_VALUE;
78 if (team < 0) {
79 status_t error = FindTeamByThread(thread, team);
80 if (error != B_OK)
81 return error;
84 TeamDebugger* debugger = FindTeamDebugger(team);
85 if (debugger != NULL) {
86 debugger->Activate();
87 return B_OK;
91 return _StartTeamDebugger(team, options, stopInMain);
95 int32
96 TargetHostInterface::CountTeamDebuggers() const
98 return fTeamDebuggers.CountItems();
102 TeamDebugger*
103 TargetHostInterface::TeamDebuggerAt(int32 index) const
105 return fTeamDebuggers.ItemAt(index);
109 TeamDebugger*
110 TargetHostInterface::FindTeamDebugger(team_id team) const
112 for (int32 i = 0; i < fTeamDebuggers.CountItems(); i++) {
113 TeamDebugger* debugger = fTeamDebuggers.ItemAt(i);
114 if (debugger->TeamID() == team && !debugger->IsPostMortem())
115 return debugger;
118 return NULL;
122 status_t
123 TargetHostInterface::AddTeamDebugger(TeamDebugger* debugger)
125 if (!fTeamDebuggers.BinaryInsert(debugger, &_CompareDebuggers))
126 return B_NO_MEMORY;
128 return B_OK;
132 void
133 TargetHostInterface::RemoveTeamDebugger(TeamDebugger* debugger)
135 for (int32 i = 0; i < fTeamDebuggers.CountItems(); i++) {
136 if (fTeamDebuggers.ItemAt(i) == debugger) {
137 fTeamDebuggers.RemoveItemAt(i);
138 break;
144 void
145 TargetHostInterface::AddListener(Listener* listener)
147 AutoLocker<TargetHostInterface> interfaceLocker(this);
148 fListeners.Add(listener);
152 void
153 TargetHostInterface::RemoveListener(Listener* listener)
155 AutoLocker<TargetHostInterface> interfaceLocker(this);
156 fListeners.Remove(listener);
160 void
161 TargetHostInterface::Quit()
163 if (fTeamDebuggers.CountItems() == 0)
164 BLooper::Quit();
168 void
169 TargetHostInterface::MessageReceived(BMessage* message)
171 switch (message->what) {
172 case MSG_TEAM_DEBUGGER_QUIT:
174 thread_id thread;
175 if (message->FindInt32("thread", &thread) == B_OK)
176 wait_for_thread(thread, NULL);
177 break;
179 case MSG_TEAM_RESTART_REQUESTED:
181 int32 teamID;
182 if (message->FindInt32("team", &teamID) != B_OK)
183 break;
185 TeamDebugger* debugger = FindTeamDebugger(teamID);
187 TeamDebuggerOptions options;
188 options.commandLineArgc = debugger->ArgumentCount();
189 options.commandLineArgv = debugger->Arguments();
190 options.settingsManager = debugger->GetSettingsManager();
191 status_t result = StartTeamDebugger(options);
192 if (result == B_OK)
193 debugger->PostMessage(B_QUIT_REQUESTED);
194 break;
196 default:
197 BLooper::MessageReceived(message);
198 break;
203 void
204 TargetHostInterface::TeamDebuggerStarted(TeamDebugger* debugger)
206 AutoLocker<TargetHostInterface> locker(this);
207 AddTeamDebugger(debugger);
208 _NotifyTeamDebuggerStarted(debugger);
212 void
213 TargetHostInterface::TeamDebuggerRestartRequested(TeamDebugger* debugger)
215 BMessage message(MSG_TEAM_RESTART_REQUESTED);
216 message.AddInt32("team", debugger->TeamID());
217 PostMessage(&message);
221 void
222 TargetHostInterface::TeamDebuggerQuit(TeamDebugger* debugger)
224 AutoLocker<TargetHostInterface> interfaceLocker(this);
225 RemoveTeamDebugger(debugger);
227 if (debugger->Thread() >= 0) {
228 _NotifyTeamDebuggerQuit(debugger);
229 BMessage message(MSG_TEAM_DEBUGGER_QUIT);
230 message.AddInt32("thread", debugger->Thread());
231 PostMessage(&message);
236 status_t
237 TargetHostInterface::_StartTeamDebugger(team_id teamID,
238 const TeamDebuggerOptions& options, bool stopInMain)
240 UserInterface* userInterface = options.userInterface;
241 if (userInterface == NULL) {
242 fprintf(stderr, "Error: Requested team debugger start without "
243 "valid user interface!\n");
244 return B_BAD_VALUE;
247 thread_id threadID = options.thread;
248 if (options.commandLineArgv != NULL)
249 threadID = teamID;
251 DebuggerInterface* interface = NULL;
252 TeamDebugger* debugger = NULL;
253 status_t error = B_OK;
254 if (options.requestType != TEAM_DEBUGGER_REQUEST_LOAD_CORE) {
255 error = Attach(teamID, options.thread, interface);
256 if (error != B_OK) {
257 fprintf(stderr, "Error: Failed to attach to team %" B_PRId32
258 ": %s!\n", teamID, strerror(error));
259 return error;
261 } else {
262 error = LoadCore(options.coreFilePath, interface, threadID);
263 if (error != B_OK) {
264 fprintf(stderr, "Error: Failed to load core file '%s': %s!\n",
265 options.coreFilePath, strerror(error));
266 return error;
270 BReference<DebuggerInterface> debuggerInterfaceReference(interface,
271 true);
272 debugger = new(std::nothrow) TeamDebugger(this, userInterface,
273 options.settingsManager);
274 if (debugger != NULL) {
275 error = debugger->Init(interface, threadID,
276 options.commandLineArgc, options.commandLineArgv, stopInMain);
279 if (error != B_OK) {
280 printf("Error: debugger for team %" B_PRId32 " on interface %s failed"
281 " to init: %s!\n", interface->TeamID(), Name(), strerror(error));
282 delete debugger;
283 debugger = NULL;
284 } else {
285 printf("debugger for team %" B_PRId32 " on interface %s created and"
286 " initialized successfully!\n", interface->TeamID(), Name());
289 return error;
293 void
294 TargetHostInterface::_NotifyTeamDebuggerStarted(TeamDebugger* debugger)
296 for (ListenerList::Iterator it = fListeners.GetIterator();
297 Listener* listener = it.Next();) {
298 listener->TeamDebuggerStarted(debugger);
303 void
304 TargetHostInterface::_NotifyTeamDebuggerQuit(TeamDebugger* debugger)
306 for (ListenerList::Iterator it = fListeners.GetIterator();
307 Listener* listener = it.Next();) {
308 listener->TeamDebuggerQuit(debugger);
313 /*static*/ int
314 TargetHostInterface::_CompareDebuggers(const TeamDebugger* a,
315 const TeamDebugger* b)
317 return a->TeamID() < b->TeamID() ? -1 : 1;
321 // #pragma mark - TargetHostInterface::Listener
324 TargetHostInterface::Listener::~Listener()
329 void
330 TargetHostInterface::Listener::TeamDebuggerStarted(TeamDebugger* debugger)
335 void
336 TargetHostInterface::Listener::TeamDebuggerQuit(TeamDebugger* debugger)
341 void
342 TargetHostInterface::Listener::TargetHostInterfaceQuit(
343 TargetHostInterface* interface)