diff --git a/src/apps/debugger/Debugger.cpp b/src/apps/debugger/Debugger.cpp index 5d2773edaa..a23de964a6 100644 --- a/src/apps/debugger/Debugger.cpp +++ b/src/apps/debugger/Debugger.cpp @@ -20,10 +20,8 @@ #include #include -#include "debug_utils.h" - #include "CommandLineUserInterface.h" -#include "LocalDebuggerInterface.h" +#include "DebuggerInterface.h" #include "GraphicalUserInterface.h" #include "ImageDebugLoadingStateHandlerRoster.h" #include "MessageCodes.h" @@ -31,6 +29,8 @@ #include "SettingsManager.h" #include "SignalSet.h" #include "StartTeamWindow.h" +#include "TargetHostInterface.h" +#include "TargetHostInterfaceRoster.h" #include "TeamDebugger.h" #include "TeamsWindow.h" #include "TypeHandlerRoster.h" @@ -101,13 +101,16 @@ struct Options { }; -struct DebuggedProgramInfo { - team_id team; - thread_id thread; - int commandLineArgc; - const char* const* commandLineArgv; - bool stopInMain; -}; +static void +set_debugger_options_from_options(TeamDebuggerOptions& _debuggerOptions, + const Options& options) +{ + _debuggerOptions.commandLineArgc = options.commandLineArgc; + _debuggerOptions.commandLineArgv = options.commandLineArgv; + _debuggerOptions.team = options.team; + _debuggerOptions.thread = options.thread; +} + static bool @@ -219,136 +222,27 @@ global_init() if (error != B_OK) return error; + error = TargetHostInterfaceRoster::CreateDefault(); + if (error != B_OK) + return error; + + // for now, always create an instance of the local interface + // by default + TargetHostInterface* hostInterface; + TargetHostInterfaceRoster* roster = TargetHostInterfaceRoster::Default(); + error = roster->CreateInterface(roster->InterfaceInfoAt(0), NULL, + hostInterface); + if (error != B_OK) + return error; + return B_OK; } -/** - * Finds or runs the program to debug, depending on the command line options. - * @param options The parsed command line options. - * @param _info The info for the program to fill in. Will only be filled in - * if successful. - * @return \c true, if the program has been found or ran. - */ -static bool -get_debugged_program(const Options& options, DebuggedProgramInfo& _info) -{ - team_id team = options.team; - thread_id thread = options.thread; - bool stopInMain = false; - - // If command line arguments were given, start the program. - if (options.commandLineArgc > 0) { - printf("loading program: \"%s\" ...\n", options.commandLineArgv[0]); - // TODO: What about the CWD? - thread = load_program(options.commandLineArgv, - options.commandLineArgc, false); - if (thread < 0) { - // TODO: Notify the user! - fprintf(stderr, "Error: Failed to load program \"%s\": %s\n", - options.commandLineArgv[0], strerror(thread)); - return false; - } - - team = thread; - // main thread ID == team ID - stopInMain = true; - } - - // no parameters given, prompt the user to attach to a team - if (team < 0 && thread < 0) - return false; - - // no team, but a thread -- get team - if (team < 0) { - printf("no team yet, getting thread info...\n"); - thread_info threadInfo; - status_t error = get_thread_info(thread, &threadInfo); - if (error != B_OK) { - // TODO: Notify the user! - fprintf(stderr, "Error: Failed to get info for thread \"%" B_PRId32 - "\": %s\n", thread, strerror(error)); - return false; - } - - team = threadInfo.team; - } - printf("team: %" B_PRId32 ", thread: %" B_PRId32 "\n", team, thread); - - _info.commandLineArgc = options.commandLineArgc; - _info.commandLineArgv = options.commandLineArgv; - _info.team = team; - _info.thread = thread; - _info.stopInMain = stopInMain; - return true; -} - - -/** - * Creates a TeamDebugger for the given team. If userInterface is given, - * that user interface is used (the caller retains its reference), otherwise - * a graphical user interface is created. - */ -static TeamDebugger* -start_team_debugger(team_id teamID, SettingsManager* settingsManager, - TeamDebugger::Listener* listener, thread_id threadID = -1, - int commandLineArgc = 0, const char* const* commandLineArgv = NULL, - bool stopInMain = false, UserInterface* userInterface = NULL, - status_t* _result = NULL) -{ - if (teamID < 0) - return NULL; - - BReference userInterfaceReference; - if (userInterface == NULL) { - userInterface = new(std::nothrow) GraphicalUserInterface; - if (userInterface == NULL) { - // TODO: Notify the user! - fprintf(stderr, "Error: Out of memory!\n"); - return NULL; - } - - userInterfaceReference.SetTo(userInterface, true); - } - - BReference interfaceReference; - DebuggerInterface* debuggerInterface - = new(std::nothrow) LocalDebuggerInterface(teamID); - if (debuggerInterface == NULL) - return NULL; - interfaceReference.SetTo(debuggerInterface, true); - - if (debuggerInterface->Init() != B_OK) - return NULL; - - status_t error = B_NO_MEMORY; - - TeamDebugger* debugger = new(std::nothrow) TeamDebugger(listener, - userInterface, settingsManager); - if (debugger != NULL) { - error = debugger->Init(debuggerInterface, threadID, commandLineArgc, - commandLineArgv, stopInMain); - } - - if (error != B_OK) { - printf("Error: debugger for team %" B_PRId32 " failed to init: %s!\n", - teamID, strerror(error)); - delete debugger; - debugger = NULL; - } else - printf("debugger for team %" B_PRId32 " created and initialized " - "successfully!\n", teamID); - - if (_result != NULL) - *_result = error; - return debugger; -} - - // #pragma mark - Debugger application class -class Debugger : public BApplication, private TeamDebugger::Listener { +class Debugger : public BApplication { public: Debugger(); ~Debugger(); @@ -359,27 +253,15 @@ public: virtual void ArgvReceived(int32 argc, char** argv); private: - typedef BObjectList TeamDebuggerList; - -private: - // TeamDebugger::Listener - virtual void TeamDebuggerStarted(TeamDebugger* debugger); - virtual void TeamDebuggerRestartRequested( - TeamDebugger* debugger); - virtual void TeamDebuggerQuit(TeamDebugger* debugger); - virtual bool QuitRequested(); virtual void Quit(); - TeamDebugger* _FindTeamDebugger(team_id teamID) const; - - status_t _StartNewTeam(const char* path, const char* args); - status_t _StartOrFindTeam(Options& options); +private: + status_t _StartNewTeam(TargetHostInterface* interface, + const char* teamPath, const char* args); private: SettingsManager fSettingsManager; - TeamDebuggerList fTeamDebuggers; - int32 fRunningTeamDebuggers; TeamsWindow* fTeamsWindow; StartTeamWindow* fStartTeamWindow; }; @@ -388,34 +270,20 @@ private: // #pragma mark - CliDebugger -class CliDebugger : private TeamDebugger::Listener { +class CliDebugger { public: CliDebugger(); ~CliDebugger(); bool Run(const Options& options); - -private: - // TeamDebugger::Listener - virtual void TeamDebuggerStarted(TeamDebugger* debugger); - virtual void TeamDebuggerRestartRequested( - TeamDebugger* debugger); - virtual void TeamDebuggerQuit(TeamDebugger* debugger); }; -class ReportDebugger : private TeamDebugger::Listener { +class ReportDebugger { public: ReportDebugger(); ~ReportDebugger(); bool Run(const Options& options); - -private: - // TeamDebugger::Listener - virtual void TeamDebuggerStarted(TeamDebugger* debugger); - virtual void TeamDebuggerRestartRequested( - TeamDebugger* debugger); - virtual void TeamDebuggerQuit(TeamDebugger* debugger); }; @@ -425,7 +293,6 @@ private: Debugger::Debugger() : BApplication(kDebuggerSignature), - fRunningTeamDebuggers(0), fTeamsWindow(NULL), fStartTeamWindow(NULL) { @@ -437,6 +304,7 @@ Debugger::~Debugger() ValueHandlerRoster::DeleteDefault(); TypeHandlerRoster::DeleteDefault(); ImageDebugLoadingStateHandlerRoster::DeleteDefault(); + TargetHostInterfaceRoster::DeleteDefault(); } @@ -480,9 +348,14 @@ Debugger::MessageReceived(BMessage* message) } case MSG_SHOW_START_TEAM_WINDOW: { + TargetHostInterface* hostInterface; + if (message->FindPointer("interface", + reinterpret_cast(&hostInterface)) != B_OK) { + break; + } BMessenger messenger(fStartTeamWindow); if (!messenger.IsValid()) { - fStartTeamWindow = StartTeamWindow::Create(); + fStartTeamWindow = StartTeamWindow::Create(hostInterface); if (fStartTeamWindow == NULL) break; fStartTeamWindow->Show(); @@ -497,56 +370,45 @@ Debugger::MessageReceived(BMessage* message) } case MSG_DEBUG_THIS_TEAM: { - int32 teamID; + team_id teamID; if (message->FindInt32("team", &teamID) != B_OK) break; - start_team_debugger(teamID, &fSettingsManager, this); + TargetHostInterface* interface; + if (message->FindPointer("interface", reinterpret_cast( + &interface)) != B_OK) { + break; + } + + TeamDebuggerOptions options; + options.settingsManager = &fSettingsManager; + options.team = teamID; + status_t error = interface->StartTeamDebugger(options); + if (error != B_OK) { + // TODO: notify user. + } break; } case MSG_START_NEW_TEAM: { + TargetHostInterface* interface; + if (message->FindPointer("interface", reinterpret_cast( + &interface)) != B_OK) { + break; + } + const char* teamPath = NULL; const char* args = NULL; message->FindString("path", &teamPath); message->FindString("arguments", &args); - status_t result = _StartNewTeam(teamPath, args); + status_t result = _StartNewTeam(interface, teamPath, args); BMessage reply; reply.AddInt32("status", result); message->SendReply(&reply); break; } - case MSG_TEAM_RESTART_REQUESTED: - { - int32 teamID; - if (message->FindInt32("team", &teamID) != B_OK) - break; - TeamDebugger* debugger = _FindTeamDebugger(teamID); - if (debugger == NULL) - break; - - Options options; - options.commandLineArgc = debugger->ArgumentCount(); - options.commandLineArgv = debugger->Arguments(); - - status_t result = _StartOrFindTeam(options); - if (result == B_OK) - debugger->PostMessage(B_QUIT_REQUESTED); - - break; - } - case MSG_TEAM_DEBUGGER_QUIT: - { - int32 threadID; - if (message->FindInt32("thread", &threadID) == B_OK) - wait_for_thread(threadID, NULL); - - --fRunningTeamDebuggers; - Quit(); - break; - } default: BApplication::MessageReceived(message); break; @@ -557,8 +419,10 @@ Debugger::MessageReceived(BMessage* message) void Debugger::ReadyToRun() { - if (fRunningTeamDebuggers == 0) - PostMessage(MSG_SHOW_TEAMS_WINDOW); + TargetHostInterfaceRoster* roster = TargetHostInterfaceRoster::Default(); + AutoLocker lock(roster); + if (roster->CountRunningTeamDebuggers() == 0) + PostMessage(MSG_SHOW_TEAMS_WINDOW); } @@ -571,51 +435,13 @@ Debugger::ArgvReceived(int32 argc, char** argv) return; } - _StartOrFindTeam(options); + TargetHostInterface* hostInterface + = TargetHostInterfaceRoster::Default()->ActiveInterfaceAt(0); -} - - -void -Debugger::TeamDebuggerStarted(TeamDebugger* debugger) -{ - printf("debugger for team %" B_PRId32 " started...\n", debugger->TeamID()); - - // Note: see TeamDebuggerQuit() note about locking - AutoLocker locker(this); - fTeamDebuggers.AddItem(debugger); - fRunningTeamDebuggers++; - locker.Unlock(); -} - - -void -Debugger::TeamDebuggerQuit(TeamDebugger* debugger) -{ - // Note: Locking here only works, since we're never locking the other - // way around. If we even need to do that, we'll have to introduce a - // separate lock to protect the list. - - printf("debugger for team %" B_PRId32 " quit.\n", debugger->TeamID()); - - AutoLocker locker(this); - fTeamDebuggers.RemoveItem(debugger); - locker.Unlock(); - - if (debugger->Thread() >= 0) { - BMessage message(MSG_TEAM_DEBUGGER_QUIT); - message.AddInt32("thread", debugger->Thread()); - PostMessage(&message); - } -} - - -void -Debugger::TeamDebuggerRestartRequested(TeamDebugger* debugger) -{ - BMessage message(MSG_TEAM_RESTART_REQUESTED); - message.AddInt32("team", debugger->TeamID()); - PostMessage(&message); + TeamDebuggerOptions debuggerOptions; + set_debugger_options_from_options(debuggerOptions, options); + debuggerOptions.settingsManager = &fSettingsManager; + hostInterface->StartTeamDebugger(debuggerOptions); } @@ -639,27 +465,17 @@ Debugger::QuitRequested() void Debugger::Quit() { + TargetHostInterfaceRoster* roster = TargetHostInterfaceRoster::Default(); + AutoLocker lock(roster); // don't quit before all team debuggers have been quit - if (fRunningTeamDebuggers <= 0 && fTeamsWindow == NULL) + if (roster->CountRunningTeamDebuggers() == 0 && fTeamsWindow == NULL) BApplication::Quit(); } -TeamDebugger* -Debugger::_FindTeamDebugger(team_id teamID) const -{ - for (int32 i = 0; TeamDebugger* debugger = fTeamDebuggers.ItemAt(i); - i++) { - if (debugger->TeamID() == teamID) - return debugger; - } - - return NULL; -} - - status_t -Debugger::_StartNewTeam(const char* path, const char* args) +Debugger::_StartNewTeam(TargetHostInterface* interface, const char* path, + const char* args) { if (path == NULL) return B_BAD_VALUE; @@ -672,7 +488,8 @@ Debugger::_StartNewTeam(const char* path, const char* args) ArgumentVector argVector; argVector.Parse(data.String()); - Options options; + TeamDebuggerOptions options; + options.settingsManager = &fSettingsManager; options.commandLineArgc = argVector.ArgumentCount(); if (options.commandLineArgc <= 0) return B_BAD_VALUE; @@ -682,31 +499,11 @@ Debugger::_StartNewTeam(const char* path, const char* args) options.commandLineArgv = argv; MemoryDeleter deleter(argv); - return _StartOrFindTeam(options); -} + status_t error = interface->StartTeamDebugger(options); + if (error == B_OK) + deleter.Detach(); - -status_t -Debugger::_StartOrFindTeam(Options& options) -{ - DebuggedProgramInfo programInfo; - if (!get_debugged_program(options, programInfo)) - return B_BAD_VALUE; - - TeamDebugger* debugger = _FindTeamDebugger(programInfo.team); - if (debugger != NULL) { - printf("There's already a debugger for team: %" B_PRId32 "\n", - programInfo.team); - debugger->Activate(); - return B_OK; - } - - status_t result; - start_team_debugger(programInfo.team, &fSettingsManager, this, - programInfo.thread, programInfo.commandLineArgc, - programInfo.commandLineArgv, programInfo.stopInMain, NULL, &result); - - return result; + return error; } @@ -756,18 +553,20 @@ CliDebugger::Run(const Options& options) } BReference userInterfaceReference(userInterface, true); - // get/run the program to be debugged and start the team debugger - DebuggedProgramInfo programInfo; - if (!get_debugged_program(options, programInfo)) - return false; - - TeamDebugger* teamDebugger = start_team_debugger(programInfo.team, - &settingsManager, this, programInfo.thread, - programInfo.commandLineArgc, programInfo.commandLineArgv, - programInfo.stopInMain, userInterface); - if (teamDebugger == NULL) + // TODO: once we support specifying a remote interface via command line + // args, this needs to be adjusted. For now, always assume actions + // are being taken via the local interface. + TargetHostInterface* hostInterface + = TargetHostInterfaceRoster::Default()->ActiveInterfaceAt(0); + + TeamDebuggerOptions debuggerOptions; + set_debugger_options_from_options(debuggerOptions, options); + debuggerOptions.userInterface = userInterface; + error = hostInterface->StartTeamDebugger(debuggerOptions); + if (error != B_OK) return false; + TeamDebugger* teamDebugger = hostInterface->TeamDebuggerAt(0); thread_id teamDebuggerThread = teamDebugger->Thread(); // run the input loop @@ -780,25 +579,6 @@ CliDebugger::Run(const Options& options) } -void -CliDebugger::TeamDebuggerStarted(TeamDebugger* debugger) -{ -} - - -void -CliDebugger::TeamDebuggerRestartRequested(TeamDebugger* debugger) -{ - // TODO: implement -} - - -void -CliDebugger::TeamDebuggerQuit(TeamDebugger* debugger) -{ -} - - // #pragma mark - ReportDebugger @@ -840,18 +620,17 @@ ReportDebugger::Run(const Options& options) } BReference userInterfaceReference(userInterface, true); - // get/run the program to be debugged and start the team debugger - DebuggedProgramInfo programInfo; - if (!get_debugged_program(options, programInfo)) - return false; - - TeamDebugger* teamDebugger = start_team_debugger(programInfo.team, - &settingsManager, this, programInfo.thread, - programInfo.commandLineArgc, programInfo.commandLineArgv, - programInfo.stopInMain, userInterface); - if (teamDebugger == NULL) + TargetHostInterface* hostInterface + = TargetHostInterfaceRoster::Default()->ActiveInterfaceAt(0); + + TeamDebuggerOptions debuggerOptions; + set_debugger_options_from_options(debuggerOptions, options); + debuggerOptions.userInterface = userInterface; + error = hostInterface->StartTeamDebugger(debuggerOptions); + if (error != B_OK) return false; + TeamDebugger* teamDebugger = hostInterface->TeamDebuggerAt(0); thread_id teamDebuggerThread = teamDebugger->Thread(); // run the input loop @@ -864,24 +643,6 @@ ReportDebugger::Run(const Options& options) } -void -ReportDebugger::TeamDebuggerStarted(TeamDebugger* debugger) -{ -} - - -void -ReportDebugger::TeamDebuggerRestartRequested(TeamDebugger* debugger) -{ -} - - -void -ReportDebugger::TeamDebuggerQuit(TeamDebugger* debugger) -{ -} - - // #pragma mark - diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index 7cce854a1e..f030618c43 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -55,6 +55,8 @@ public: { return fCommandLineArgc; } const char** Arguments() const { return fCommandLineArgv; } + SettingsManager* GetSettingsManager() const + { return fSettingsManager; } virtual void MessageReceived(BMessage* message); diff --git a/src/apps/debugger/target_host_interface/TargetHostInterface.cpp b/src/apps/debugger/target_host_interface/TargetHostInterface.cpp index c213c6a5f4..ac5ba67a5f 100644 --- a/src/apps/debugger/target_host_interface/TargetHostInterface.cpp +++ b/src/apps/debugger/target_host_interface/TargetHostInterface.cpp @@ -5,12 +5,37 @@ #include "TargetHostInterface.h" +#include + +#include + +#include "DebuggerInterface.h" +#include "GraphicalUserInterface.h" +#include "MessageCodes.h" #include "TeamDebugger.h" +// #pragma mark - TeamDebuggerOptions + + +TeamDebuggerOptions::TeamDebuggerOptions() + : + commandLineArgc(0), + commandLineArgv(NULL), + team(-1), + thread(-1), + settingsManager(NULL), + userInterface(NULL) +{ +} + + +// #pragma mark - TargetHostInterface + + TargetHostInterface::TargetHostInterface() : - BReferenceable(), + BLooper(), fTeamDebuggers(20, false) { } @@ -21,10 +46,40 @@ TargetHostInterface::~TargetHostInterface() } -void -TargetHostInterface::SetName(const BString& name) +status_t +TargetHostInterface::StartTeamDebugger(const TeamDebuggerOptions& options) { - fName = name; + // we only want to stop in main for teams we're responsible for + // creating ourselves. + bool stopInMain = options.commandLineArgv != NULL; + team_id team = options.team; + thread_id thread = options.thread; + + AutoLocker interfaceLocker(this); + if (options.commandLineArgc > 0) { + status_t error = CreateTeam(options.commandLineArgc, + options.commandLineArgv, team); + if (error != B_OK) + return error; + thread = team; + } + + if (team < 0 && thread < 0) + return B_BAD_VALUE; + + if (team < 0) { + status_t error = FindTeamByThread(thread, team); + if (error != B_OK) + return error; + } + + TeamDebugger* debugger = FindTeamDebugger(team); + if (debugger != NULL) { + debugger->Activate(); + return B_OK; + } + + return _StartTeamDebugger(team, options, stopInMain); } @@ -69,6 +124,133 @@ TargetHostInterface::RemoveTeamDebugger(TeamDebugger* debugger) } +void +TargetHostInterface::Quit() +{ + if (fTeamDebuggers.CountItems() == 0) + BLooper::Quit(); +} + + +void +TargetHostInterface::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_TEAM_DEBUGGER_QUIT: + { + thread_id thread; + if (message->FindInt32("thread", &thread) == B_OK) + wait_for_thread(thread, NULL); + break; + } + case MSG_TEAM_RESTART_REQUESTED: + { + int32 teamID; + if (message->FindInt32("team", &teamID) != B_OK) + break; + + TeamDebugger* debugger = FindTeamDebugger(teamID); + + TeamDebuggerOptions options; + options.commandLineArgc = debugger->ArgumentCount(); + options.commandLineArgv = debugger->Arguments(); + options.settingsManager = debugger->GetSettingsManager(); + status_t result = StartTeamDebugger(options); + if (result == B_OK) + debugger->PostMessage(B_QUIT_REQUESTED); + break; + } + default: + BLooper::MessageReceived(message); + break; + } +} + + +void +TargetHostInterface::TeamDebuggerStarted(TeamDebugger* debugger) +{ + AutoLocker locker(this); + AddTeamDebugger(debugger); +} + + +void +TargetHostInterface::TeamDebuggerRestartRequested(TeamDebugger* debugger) +{ + BMessage message(MSG_TEAM_RESTART_REQUESTED); + message.AddInt32("team", debugger->TeamID()); + PostMessage(&message); +} + + +void +TargetHostInterface::TeamDebuggerQuit(TeamDebugger* debugger) +{ + AutoLocker interfaceLocker(this); + RemoveTeamDebugger(debugger); + interfaceLocker.Unlock(); + + if (debugger->Thread() >= 0) { + BMessage message(MSG_TEAM_DEBUGGER_QUIT); + message.AddInt32("thread", debugger->Thread()); + PostMessage(&message); + } +} + + +status_t +TargetHostInterface::_StartTeamDebugger(team_id teamID, + const TeamDebuggerOptions& options, bool stopInMain) +{ + BReference userInterfaceReference; + UserInterface* userInterface = options.userInterface; + if (userInterface == NULL) { + userInterface = new(std::nothrow) GraphicalUserInterface; + if (userInterface == NULL) { + fprintf(stderr, "Error: Out of memory!\n"); + return B_NO_MEMORY; + } + + userInterfaceReference.SetTo(userInterface, true); + } + + thread_id threadID = options.thread; + if (options.commandLineArgv != NULL) + threadID = teamID; + + DebuggerInterface* interface = NULL; + TeamDebugger* debugger = NULL; + status_t error = Attach(teamID, options.thread, interface); + if (error != B_OK) { + fprintf(stderr, "Error: Failed to attach to team %" B_PRId32 ": %s!\n", + teamID, strerror(error)); + return error; + } + + BReference debuggerInterfaceReference(interface, + true); + debugger = new(std::nothrow) TeamDebugger(this, userInterface, + options.settingsManager); + if (debugger != NULL) { + error = debugger->Init(interface, threadID, + options.commandLineArgc, options.commandLineArgv, stopInMain); + } + + if (error != B_OK) { + printf("Error: debugger for team %" B_PRId32 " on interface %s failed" + " to init: %s!\n", interface->TeamID(), Name(), strerror(error)); + delete debugger; + debugger = NULL; + } else { + printf("debugger for team %" B_PRId32 " on interface %s created and" + " initialized successfully!\n", interface->TeamID(), Name()); + } + + return error; +} + + /*static*/ int TargetHostInterface::_CompareDebuggers(const TeamDebugger* a, const TeamDebugger* b) diff --git a/src/apps/debugger/target_host_interface/TargetHostInterface.h b/src/apps/debugger/target_host_interface/TargetHostInterface.h index d7d95d8f84..84b3576c9b 100644 --- a/src/apps/debugger/target_host_interface/TargetHostInterface.h +++ b/src/apps/debugger/target_host_interface/TargetHostInterface.h @@ -6,26 +6,28 @@ #define TARGET_HOST_INTERFACE_H #include -#include +#include #include -#include + +#include "TeamDebugger.h" class DebuggerInterface; class Settings; +class SettingsManager; class TargetHost; class TeamDebugger; +struct TeamDebuggerOptions; +class UserInterface; -class TargetHostInterface : public BReferenceable { +class TargetHostInterface : public BLooper, private TeamDebugger::Listener { public: TargetHostInterface(); virtual ~TargetHostInterface(); - const BString& Name() const { return fName; } - void SetName(const BString& name); - + status_t StartTeamDebugger(const TeamDebuggerOptions& options); int32 CountTeamDebuggers() const; TeamDebugger* TeamDebuggerAt(int32 index) const; @@ -36,18 +38,35 @@ public: virtual status_t Init(Settings* settings) = 0; virtual void Close() = 0; + virtual bool IsLocal() const = 0; virtual bool Connected() const = 0; virtual TargetHost* GetTargetHost() = 0; virtual status_t Attach(team_id id, thread_id threadID, - DebuggerInterface*& _interface) = 0; + DebuggerInterface*& _interface) const = 0; virtual status_t CreateTeam(int commandLineArgc, const char* const* arguments, - DebuggerInterface*& _interface) = 0; + team_id& _teamID) const = 0; + virtual status_t FindTeamByThread(thread_id thread, + team_id& _teamID) const = 0; + + // BLooper + virtual void Quit(); + virtual void MessageReceived(BMessage* message); private: + // TeamDebugger::Listener + virtual void TeamDebuggerStarted(TeamDebugger* debugger); + virtual void TeamDebuggerRestartRequested( + TeamDebugger* debugger); + virtual void TeamDebuggerQuit(TeamDebugger* debugger); + +private: + status_t _StartTeamDebugger(team_id teamID, + const TeamDebuggerOptions& options, + bool stopInMain); static int _CompareDebuggers(const TeamDebugger* a, const TeamDebugger* b); static int _FindDebuggerByKey(const team_id* team, @@ -56,9 +75,19 @@ private: typedef BObjectList TeamDebuggerList; private: - BString fName; TeamDebuggerList fTeamDebuggers; }; +struct TeamDebuggerOptions { + TeamDebuggerOptions(); + int commandLineArgc; + const char* const* commandLineArgv; + team_id team; + thread_id thread; + SettingsManager* settingsManager; + UserInterface* userInterface; +}; + + #endif // TARGET_HOST_INTERFACE_H diff --git a/src/apps/debugger/target_host_interface/TargetHostInterfaceRoster.cpp b/src/apps/debugger/target_host_interface/TargetHostInterfaceRoster.cpp index de8b644a2b..5305f7f866 100644 --- a/src/apps/debugger/target_host_interface/TargetHostInterfaceRoster.cpp +++ b/src/apps/debugger/target_host_interface/TargetHostInterfaceRoster.cpp @@ -130,12 +130,13 @@ TargetHostInterfaceRoster::CreateInterface(TargetHostInterfaceInfo* info, if (error != B_OK) return error; - BReference interfaceReference(interface, true); - if (!fActiveInterfaces.AddItem(interface)) + error = interface->Run(); + if (error < B_OK || !fActiveInterfaces.AddItem(interface)) { + delete interface; return B_NO_MEMORY; + } _interface = interface; - interfaceReference.Detach(); return B_OK; } @@ -153,3 +154,15 @@ TargetHostInterfaceRoster::ActiveInterfaceAt(int32 index) const return fActiveInterfaces.ItemAt(index); } + +int32 +TargetHostInterfaceRoster::CountRunningTeamDebuggers() const +{ + int32 total = 0; + for (int32 i = 0; TargetHostInterface* interface = ActiveInterfaceAt(i); + i++) { + total += interface->CountTeamDebuggers(); + } + + return total; +} diff --git a/src/apps/debugger/target_host_interface/TargetHostInterfaceRoster.h b/src/apps/debugger/target_host_interface/TargetHostInterfaceRoster.h index 6f3f12bbfc..d09ff9b242 100644 --- a/src/apps/debugger/target_host_interface/TargetHostInterfaceRoster.h +++ b/src/apps/debugger/target_host_interface/TargetHostInterfaceRoster.h @@ -42,6 +42,8 @@ public: int32 CountActiveInterfaces() const; TargetHostInterface* ActiveInterfaceAt(int32 index) const; + int32 CountRunningTeamDebuggers() const; + private: typedef BObjectList InfoList; typedef BObjectList InterfaceList; diff --git a/src/apps/debugger/target_host_interface/local/LocalTargetHostInterface.cpp b/src/apps/debugger/target_host_interface/local/LocalTargetHostInterface.cpp index e9a5a474b7..23cfd400bb 100644 --- a/src/apps/debugger/target_host_interface/local/LocalTargetHostInterface.cpp +++ b/src/apps/debugger/target_host_interface/local/LocalTargetHostInterface.cpp @@ -112,6 +112,13 @@ LocalTargetHostInterface::Close() } +bool +LocalTargetHostInterface::IsLocal() const +{ + return true; +} + + bool LocalTargetHostInterface::Connected() const { @@ -128,7 +135,7 @@ LocalTargetHostInterface::GetTargetHost() status_t LocalTargetHostInterface::Attach(team_id teamID, thread_id threadID, - DebuggerInterface*& _interface) + DebuggerInterface*& _interface) const { if (teamID < 0 && threadID < 0) return B_BAD_VALUE; @@ -161,13 +168,29 @@ LocalTargetHostInterface::Attach(team_id teamID, thread_id threadID, status_t LocalTargetHostInterface::CreateTeam(int commandLineArgc, - const char* const* arguments, DebuggerInterface*& _interface) + const char* const* arguments, team_id& _teamID) const { thread_id thread = load_program(arguments, commandLineArgc, false); if (thread < 0) return thread; - return Attach(-1, thread, _interface); + // main thread ID == team ID. + _teamID = thread; + return B_OK; +} + + +status_t +LocalTargetHostInterface::FindTeamByThread(thread_id thread, + team_id& _teamID) const +{ + thread_info info; + status_t error = get_thread_info(thread, &info); + if (error != B_OK) + return error; + + _teamID = info.team; + return B_OK; } diff --git a/src/apps/debugger/target_host_interface/local/LocalTargetHostInterface.h b/src/apps/debugger/target_host_interface/local/LocalTargetHostInterface.h index 00f02eedf0..c9f6e7021d 100644 --- a/src/apps/debugger/target_host_interface/local/LocalTargetHostInterface.h +++ b/src/apps/debugger/target_host_interface/local/LocalTargetHostInterface.h @@ -16,16 +16,20 @@ public: virtual status_t Init(Settings* settings); virtual void Close(); + virtual bool IsLocal() const; virtual bool Connected() const; virtual TargetHost* GetTargetHost(); virtual status_t Attach(team_id id, thread_id threadID, - DebuggerInterface*& _interface); + DebuggerInterface*& _interface) const; virtual status_t CreateTeam(int commandLineArgc, const char* const* arguments, - DebuggerInterface*& _interface); + team_id& _teamID) const; + virtual status_t FindTeamByThread(thread_id thread, + team_id& _teamID) const; + private: static status_t _PortLoop(void* arg); diff --git a/src/apps/debugger/target_host_interface/local/LocalTargetHostInterfaceInfo.cpp b/src/apps/debugger/target_host_interface/local/LocalTargetHostInterfaceInfo.cpp index 5ac0f128d3..8940496ff8 100644 --- a/src/apps/debugger/target_host_interface/local/LocalTargetHostInterfaceInfo.cpp +++ b/src/apps/debugger/target_host_interface/local/LocalTargetHostInterfaceInfo.cpp @@ -59,14 +59,13 @@ LocalTargetHostInterfaceInfo::CreateInterface(Settings* settings, if (interface == NULL) return B_NO_MEMORY; - BReference interfaceReference(interface, true); status_t error = interface->Init(settings); - if (error != B_OK) + if (error != B_OK) { + delete interface; return error; + } _interface = interface; - interfaceReference.Detach(); - return B_OK; } diff --git a/src/apps/debugger/user_interface/gui/teams_window/TeamsListView.cpp b/src/apps/debugger/user_interface/gui/teams_window/TeamsListView.cpp index daacb44a3b..029b1ead1b 100644 --- a/src/apps/debugger/user_interface/gui/teams_window/TeamsListView.cpp +++ b/src/apps/debugger/user_interface/gui/teams_window/TeamsListView.cpp @@ -279,7 +279,6 @@ TeamsListView::TeamsListView(const char* name, team_id currentTeam, fCurrentTeam(currentTeam), fInterface(interface) { - fInterface->AcquireReference(); AddColumn(new TeamsColumn("Name", 400, 100, 600, B_TRUNCATE_BEGINNING), kNameColumn); AddColumn(new TeamsColumn("ID", 80, 40, 100, @@ -290,7 +289,6 @@ TeamsListView::TeamsListView(const char* name, team_id currentTeam, TeamsListView::~TeamsListView() { - fInterface->ReleaseReference(); } diff --git a/src/apps/debugger/user_interface/gui/teams_window/TeamsWindow.cpp b/src/apps/debugger/user_interface/gui/teams_window/TeamsWindow.cpp index 53d599dae3..aaa9ae45ae 100644 --- a/src/apps/debugger/user_interface/gui/teams_window/TeamsWindow.cpp +++ b/src/apps/debugger/user_interface/gui/teams_window/TeamsWindow.cpp @@ -24,7 +24,8 @@ #include "MessageCodes.h" #include "SettingsManager.h" -#include "LocalTargetHostInterface.h" +#include "TargetHostInterface.h" +#include "TargetHostInterfaceRoster.h" #include "TeamsListView.h" @@ -51,8 +52,6 @@ TeamsWindow::TeamsWindow(SettingsManager* settingsManager) TeamsWindow::~TeamsWindow() { - if (fTargetHostInterface != NULL) - fTargetHostInterface->ReleaseReference(); } @@ -100,6 +99,7 @@ TeamsWindow::MessageReceived(BMessage* message) if (row != NULL) { BMessage message(MSG_DEBUG_THIS_TEAM); message.AddInt32("team", row->TeamID()); + message.AddPointer("interface", fTargetHostInterface); be_app_messenger.SendMessage(&message); } break; @@ -120,6 +120,14 @@ TeamsWindow::MessageReceived(BMessage* message) break; } + case MSG_SHOW_START_TEAM_WINDOW: + { + BMessage startMessage(*message); + startMessage.AddPointer("interface", fTargetHostInterface); + be_app_messenger.SendMessage(&startMessage); + break; + } + default: BWindow::MessageReceived(message); break; @@ -146,10 +154,8 @@ TeamsWindow::_Init() BMessage settings; _LoadSettings(settings); - fTargetHostInterface = new LocalTargetHostInterface(); - - if (fTargetHostInterface->Init(NULL) != B_OK) - throw std::bad_alloc(); + fTargetHostInterface = TargetHostInterfaceRoster::Default() + ->ActiveInterfaceAt(0); BRect frame; if (settings.FindRect("teams window frame", &frame) == B_OK) { @@ -175,7 +181,7 @@ TeamsWindow::_Init() MSG_TEAM_SELECTION_CHANGED)); fAttachTeamButton->SetEnabled(false); - fCreateTeamButton->SetTarget(be_app); + fCreateTeamButton->SetTarget(this); } diff --git a/src/apps/debugger/user_interface/gui/utility_windows/StartTeamWindow.cpp b/src/apps/debugger/user_interface/gui/utility_windows/StartTeamWindow.cpp index 43af440314..6f1b684ee9 100644 --- a/src/apps/debugger/user_interface/gui/utility_windows/StartTeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/utility_windows/StartTeamWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013, Rene Gollent, rene@gollent.com. + * Copyright 2013-2016, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #include "StartTeamWindow.h" @@ -24,7 +24,7 @@ enum { }; -StartTeamWindow::StartTeamWindow() +StartTeamWindow::StartTeamWindow(TargetHostInterface* hostInterface) : BWindow(BRect(), "Start new team", B_TITLED_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), @@ -34,7 +34,8 @@ StartTeamWindow::StartTeamWindow() fBrowseTeamButton(NULL), fBrowseTeamPanel(NULL), fStartButton(NULL), - fCancelButton(NULL) + fCancelButton(NULL), + fTargetHostInterface(hostInterface) { } @@ -46,9 +47,9 @@ StartTeamWindow::~StartTeamWindow() StartTeamWindow* -StartTeamWindow::Create() +StartTeamWindow::Create(TargetHostInterface* hostInterface) { - StartTeamWindow* self = new StartTeamWindow; + StartTeamWindow* self = new StartTeamWindow(hostInterface); try { self->_Init(); @@ -141,6 +142,7 @@ StartTeamWindow::MessageReceived(BMessage* message) appMessage.AddString("path", fTeamTextControl->TextView()->Text()); appMessage.AddString("arguments", fArgumentsTextControl->TextView() ->Text()); + appMessage.AddPointer("interface", fTargetHostInterface); BMessage reply; be_app_messenger.SendMessage(&appMessage, &reply); status_t error = reply.FindInt32("status"); diff --git a/src/apps/debugger/user_interface/gui/utility_windows/StartTeamWindow.h b/src/apps/debugger/user_interface/gui/utility_windows/StartTeamWindow.h index c81059e7b8..1f08f8e868 100644 --- a/src/apps/debugger/user_interface/gui/utility_windows/StartTeamWindow.h +++ b/src/apps/debugger/user_interface/gui/utility_windows/StartTeamWindow.h @@ -1,5 +1,5 @@ /* - * Copyright 2013, Rene Gollent, rene@gollent.com. + * Copyright 2013-2016, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef START_TEAM_WINDOW_H @@ -13,16 +13,18 @@ class BButton; class BFilePanel; class BStringView; class BTextControl; +class TargetHostInterface; class StartTeamWindow : public BWindow { public: - StartTeamWindow(); + StartTeamWindow( + TargetHostInterface* hostInterface); ~StartTeamWindow(); - static StartTeamWindow* Create(); + static StartTeamWindow* Create(TargetHostInterface* hostInterface); // throws @@ -42,6 +44,7 @@ private: BFilePanel* fBrowseTeamPanel; BButton* fStartButton; BButton* fCancelButton; + TargetHostInterface* fTargetHostInterface; }; #endif // START_TEAM_WINDOW_H