2 * Copyright 2016, Rene Gollent, rene@gollent.com.
3 * Distributed under the terms of the MIT License.
6 #include "TargetHostInterface.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
),
24 commandLineArgv(NULL
),
27 settingsManager(NULL
),
34 // #pragma mark - TargetHostInterface
37 TargetHostInterface::TargetHostInterface()
41 fTeamDebuggers(20, false)
46 TargetHostInterface::~TargetHostInterface()
48 for (ListenerList::Iterator it
= fListeners
.GetIterator();
49 Listener
* listener
= it
.Next();) {
50 listener
->TargetHostInterfaceQuit(this);
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
);
73 if (options
.requestType
!= TEAM_DEBUGGER_REQUEST_LOAD_CORE
) {
75 if (team
< 0 && thread
< 0)
79 status_t error
= FindTeamByThread(thread
, team
);
84 TeamDebugger
* debugger
= FindTeamDebugger(team
);
85 if (debugger
!= NULL
) {
91 return _StartTeamDebugger(team
, options
, stopInMain
);
96 TargetHostInterface::CountTeamDebuggers() const
98 return fTeamDebuggers
.CountItems();
103 TargetHostInterface::TeamDebuggerAt(int32 index
) const
105 return fTeamDebuggers
.ItemAt(index
);
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())
123 TargetHostInterface::AddTeamDebugger(TeamDebugger
* debugger
)
125 if (!fTeamDebuggers
.BinaryInsert(debugger
, &_CompareDebuggers
))
133 TargetHostInterface::RemoveTeamDebugger(TeamDebugger
* debugger
)
135 for (int32 i
= 0; i
< fTeamDebuggers
.CountItems(); i
++) {
136 if (fTeamDebuggers
.ItemAt(i
) == debugger
) {
137 fTeamDebuggers
.RemoveItemAt(i
);
145 TargetHostInterface::AddListener(Listener
* listener
)
147 AutoLocker
<TargetHostInterface
> interfaceLocker(this);
148 fListeners
.Add(listener
);
153 TargetHostInterface::RemoveListener(Listener
* listener
)
155 AutoLocker
<TargetHostInterface
> interfaceLocker(this);
156 fListeners
.Remove(listener
);
161 TargetHostInterface::Quit()
163 if (fTeamDebuggers
.CountItems() == 0)
169 TargetHostInterface::MessageReceived(BMessage
* message
)
171 switch (message
->what
) {
172 case MSG_TEAM_DEBUGGER_QUIT
:
175 if (message
->FindInt32("thread", &thread
) == B_OK
)
176 wait_for_thread(thread
, NULL
);
179 case MSG_TEAM_RESTART_REQUESTED
:
182 if (message
->FindInt32("team", &teamID
) != B_OK
)
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
);
193 debugger
->PostMessage(B_QUIT_REQUESTED
);
197 BLooper::MessageReceived(message
);
204 TargetHostInterface::TeamDebuggerStarted(TeamDebugger
* debugger
)
206 AutoLocker
<TargetHostInterface
> locker(this);
207 AddTeamDebugger(debugger
);
208 _NotifyTeamDebuggerStarted(debugger
);
213 TargetHostInterface::TeamDebuggerRestartRequested(TeamDebugger
* debugger
)
215 BMessage
message(MSG_TEAM_RESTART_REQUESTED
);
216 message
.AddInt32("team", debugger
->TeamID());
217 PostMessage(&message
);
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
);
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");
247 thread_id threadID
= options
.thread
;
248 if (options
.commandLineArgv
!= NULL
)
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
);
257 fprintf(stderr
, "Error: Failed to attach to team %" B_PRId32
258 ": %s!\n", teamID
, strerror(error
));
262 error
= LoadCore(options
.coreFilePath
, interface
, threadID
);
264 fprintf(stderr
, "Error: Failed to load core file '%s': %s!\n",
265 options
.coreFilePath
, strerror(error
));
270 BReference
<DebuggerInterface
> debuggerInterfaceReference(interface
,
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
);
280 printf("Error: debugger for team %" B_PRId32
" on interface %s failed"
281 " to init: %s!\n", interface
->TeamID(), Name(), strerror(error
));
285 printf("debugger for team %" B_PRId32
" on interface %s created and"
286 " initialized successfully!\n", interface
->TeamID(), Name());
294 TargetHostInterface::_NotifyTeamDebuggerStarted(TeamDebugger
* debugger
)
296 for (ListenerList::Iterator it
= fListeners
.GetIterator();
297 Listener
* listener
= it
.Next();) {
298 listener
->TeamDebuggerStarted(debugger
);
304 TargetHostInterface::_NotifyTeamDebuggerQuit(TeamDebugger
* debugger
)
306 for (ListenerList::Iterator it
= fListeners
.GetIterator();
307 Listener
* listener
= it
.Next();) {
308 listener
->TeamDebuggerQuit(debugger
);
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()
330 TargetHostInterface::Listener::TeamDebuggerStarted(TeamDebugger
* debugger
)
336 TargetHostInterface::Listener::TeamDebuggerQuit(TeamDebugger
* debugger
)
342 TargetHostInterface::Listener::TargetHostInterfaceQuit(
343 TargetHostInterface
* interface
)