Debugger: Integrate core handling into TargetHostInterface.

{Local}TargetHostInterface:
- Add virtual method for requesting a debugger interface for a core file.
  Implement accordingly in LocalTargetHostInterface based on Ingo's
  previous implementation in the Debugger app.

TeamDebuggerOptions:
- Add an enum to define the type of team debugger request being made
  to explicitly make this clear rather than guessing based on the provided
  arguments. Set accordingly in the various cases.
- Add a parameter for the core file path.

Debugger:
- Refactor to fill in TeamDebuggerOptions appropriately for core file
  requests, and consequently simplify code.

This doesn't yet deal with the fact that a post-mortem team's ID can
clash with that of a live team, which may lead to issues when attempting
to attach to a live team in such a case.
This commit is contained in:
Rene Gollent
2016-04-25 16:48:37 -04:00
parent 0cb870a56c
commit 2c4195e840
5 changed files with 106 additions and 117 deletions
+14 -96
View File
@@ -116,6 +116,14 @@ set_debugger_options_from_options(TeamDebuggerOptions& _debuggerOptions,
_debuggerOptions.commandLineArgv = options.commandLineArgv;
_debuggerOptions.team = options.team;
_debuggerOptions.thread = options.thread;
_debuggerOptions.coreFilePath = options.coreFilePath;
if (options.coreFilePath != NULL)
_debuggerOptions.requestType = TEAM_DEBUGGER_REQUEST_LOAD_CORE;
else if (options.commandLineArgc != 0)
_debuggerOptions.requestType = TEAM_DEBUGGER_REQUEST_CREATE;
else
_debuggerOptions.requestType = TEAM_DEBUGGER_REQUEST_ATTACH;
}
@@ -256,8 +264,7 @@ global_init(TargetHostInterfaceRoster::Listener* listener)
class Debugger : public BApplication,
private TargetHostInterfaceRoster::Listener,
private TeamDebugger::Listener {
private TargetHostInterfaceRoster::Listener {
public:
Debugger();
~Debugger();
@@ -274,17 +281,9 @@ private:
// TargetHostInterfaceRoster::Listener
virtual void TeamDebuggerCountChanged(int32 count);
// TeamDebugger::Listener
virtual void TeamDebuggerStarted(TeamDebugger* debugger);
virtual void TeamDebuggerRestartRequested(
TeamDebugger* debugger);
virtual void TeamDebuggerQuit(TeamDebugger* debugger);
private:
status_t _StartNewTeam(TargetHostInterface* interface,
const char* teamPath, const char* args);
status_t _LoadCoreFile(const char* coreFilePath,
TeamDebuggerOptions debuggerOptions);
private:
SettingsManager fSettingsManager;
@@ -412,6 +411,7 @@ Debugger::MessageReceived(BMessage* message)
}
TeamDebuggerOptions options;
options.requestType = TEAM_DEBUGGER_REQUEST_ATTACH;
options.settingsManager = &fSettingsManager;
options.team = teamID;
status_t error = interface->StartTeamDebugger(options);
@@ -470,13 +470,9 @@ Debugger::ArgvReceived(int32 argc, char** argv)
set_debugger_options_from_options(debuggerOptions, options);
debuggerOptions.settingsManager = &fSettingsManager;
if (options.coreFilePath != NULL) {
_LoadCoreFile(options.coreFilePath, debuggerOptions);
} else {
TargetHostInterface* hostInterface
= TargetHostInterfaceRoster::Default()->ActiveInterfaceAt(0);
hostInterface->StartTeamDebugger(debuggerOptions);
}
TargetHostInterface* hostInterface
= TargetHostInterfaceRoster::Default()->ActiveInterfaceAt(0);
hostInterface->StartTeamDebugger(debuggerOptions);
}
@@ -518,30 +514,6 @@ Debugger::TeamDebuggerCountChanged(int32 count)
}
void
Debugger::TeamDebuggerStarted(TeamDebugger* debugger)
{
// TODO: Dummy for core file support. Managing team debuggers needs to work
// differently.
}
void
Debugger::TeamDebuggerRestartRequested(TeamDebugger* debugger)
{
// TODO: Dummy for core file support. Managing team debuggers needs to work
// differently.
}
void
Debugger::TeamDebuggerQuit(TeamDebugger* debugger)
{
// TODO: Dummy for core file support. Managing team debuggers needs to work
// differently.
}
status_t
Debugger::_StartNewTeam(TargetHostInterface* interface, const char* path,
const char* args)
@@ -558,6 +530,7 @@ Debugger::_StartNewTeam(TargetHostInterface* interface, const char* path,
argVector.Parse(data.String());
TeamDebuggerOptions options;
options.requestType = TEAM_DEBUGGER_REQUEST_CREATE;
options.settingsManager = &fSettingsManager;
options.commandLineArgc = argVector.ArgumentCount();
if (options.commandLineArgc <= 0)
@@ -576,61 +549,6 @@ Debugger::_StartNewTeam(TargetHostInterface* interface, const char* path,
}
status_t
Debugger::_LoadCoreFile(const char* coreFilePath,
TeamDebuggerOptions debuggerOptions)
{
// load the core file
CoreFile* coreFile = new(std::nothrow) CoreFile;
if (coreFile == NULL)
return B_NO_MEMORY;
ObjectDeleter<CoreFile> coreFileDeleter(coreFile);
status_t error = coreFile->Init(coreFilePath);
if (error != B_OK)
return error;
// create the user interface
UserInterface* userInterface = new(std::nothrow) GraphicalUserInterface;
if (userInterface == NULL) {
fprintf(stderr, "Error: Out of memory!\n");
return B_NO_MEMORY;
}
BReference<UserInterface> userInterfaceReference(userInterface, true);
// create the debugger interface
CoreFileDebuggerInterface* interface
= new(std::nothrow) CoreFileDebuggerInterface(coreFile);
if (interface == NULL)
return B_NO_MEMORY;
coreFileDeleter.Detach();
BReference<DebuggerInterface> interfaceReference(interface, true);
error = interface->Init();
if (error != B_OK)
return error;
// create the team debugger
TeamDebugger* debugger = new(std::nothrow) TeamDebugger(this, userInterface,
&fSettingsManager);
if (debugger == NULL)
return B_NO_MEMORY;
const CoreFileTeamInfo& teamInfo = coreFile->GetTeamInfo();
error = debugger->Init(interface, teamInfo.Id(), 0, NULL, false);
if (error != B_OK) {
fprintf(stderr, "Error: failed to init team debugger for core file "
"\"%s\": %s", coreFilePath, strerror(error));
delete debugger;
return error;
}
printf("team debugger for core file \"%s\" created and"
" initialized successfully!\n", coreFilePath);
return B_OK;
}
// #pragma mark - CliDebugger
@@ -20,12 +20,14 @@
TeamDebuggerOptions::TeamDebuggerOptions()
:
requestType(TEAM_DEBUGGER_REQUEST_UNKNOWN),
commandLineArgc(0),
commandLineArgv(NULL),
team(-1),
thread(-1),
settingsManager(NULL),
userInterface(NULL)
userInterface(NULL),
coreFilePath(NULL)
{
}
@@ -56,12 +58,12 @@ TargetHostInterface::StartTeamDebugger(const TeamDebuggerOptions& options)
{
// we only want to stop in main for teams we're responsible for
// creating ourselves.
bool stopInMain = options.commandLineArgv != NULL;
bool stopInMain = options.requestType == TEAM_DEBUGGER_REQUEST_CREATE;
team_id team = options.team;
thread_id thread = options.thread;
AutoLocker<TargetHostInterface> interfaceLocker(this);
if (options.commandLineArgc > 0) {
if (options.requestType == TEAM_DEBUGGER_REQUEST_CREATE) {
status_t error = CreateTeam(options.commandLineArgc,
options.commandLineArgv, team);
if (error != B_OK)
@@ -69,19 +71,22 @@ TargetHostInterface::StartTeamDebugger(const TeamDebuggerOptions& options)
thread = team;
}
if (team < 0 && thread < 0)
return B_BAD_VALUE;
if (options.requestType != TEAM_DEBUGGER_REQUEST_LOAD_CORE) {
if (team < 0) {
status_t error = FindTeamByThread(thread, team);
if (error != B_OK)
return error;
}
if (team < 0 && thread < 0)
return B_BAD_VALUE;
TeamDebugger* debugger = FindTeamDebugger(team);
if (debugger != NULL) {
debugger->Activate();
return B_OK;
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);
@@ -243,13 +248,24 @@ TargetHostInterface::_StartTeamDebugger(team_id 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;
status_t error = B_OK;
if (options.requestType != TEAM_DEBUGGER_REQUEST_LOAD_CORE) {
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;
}
} else {
error = LoadCore(options.coreFilePath, interface, threadID);
if (error != B_OK) {
fprintf(stderr, "Error: Failed to load core file '%s': %s!\n",
options.coreFilePath, strerror(error));
return error;
}
}
BReference<DebuggerInterface> debuggerInterfaceReference(interface,
true);
debugger = new(std::nothrow) TeamDebugger(this, userInterface,
@@ -47,10 +47,13 @@ public:
virtual status_t Attach(team_id id, thread_id threadID,
DebuggerInterface*& _interface) const = 0;
virtual status_t CreateTeam(int commandLineArgc,
const char* const* arguments,
team_id& _teamID) const = 0;
virtual status_t LoadCore(const char* coreFilePath,
DebuggerInterface*& _interface,
thread_id& _thread) const = 0;
virtual status_t FindTeamByThread(thread_id thread,
team_id& _teamID) const = 0;
@@ -104,14 +107,24 @@ public:
};
enum {
TEAM_DEBUGGER_REQUEST_UNKNOWN = 0,
TEAM_DEBUGGER_REQUEST_CREATE,
TEAM_DEBUGGER_REQUEST_ATTACH,
TEAM_DEBUGGER_REQUEST_LOAD_CORE
};
struct TeamDebuggerOptions {
TeamDebuggerOptions();
int requestType;
int commandLineArgc;
const char* const* commandLineArgv;
team_id team;
thread_id thread;
SettingsManager* settingsManager;
UserInterface* userInterface;
const char* coreFilePath;
};
@@ -1,5 +1,6 @@
/*
* Copyright 2016, Rene Gollent, [email protected].
* Copyright 2016, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
@@ -12,12 +13,15 @@
#include <image.h>
#include <AutoDeleter.h>
#include <AutoLocker.h>
#include <system_info.h>
#include <util/KMessage.h>
#include "debug_utils.h"
#include "CoreFile.h"
#include "CoreFileDebuggerInterface.h"
#include "LocalDebuggerInterface.h"
#include "TargetHost.h"
@@ -183,6 +187,41 @@ LocalTargetHostInterface::CreateTeam(int commandLineArgc,
}
status_t
LocalTargetHostInterface::LoadCore(const char* coreFilePath,
DebuggerInterface*& _interface, thread_id& _thread) const
{
// load the core file
CoreFile* coreFile = new(std::nothrow) CoreFile;
if (coreFile == NULL)
return B_NO_MEMORY;
ObjectDeleter<CoreFile> coreFileDeleter(coreFile);
status_t error = coreFile->Init(coreFilePath);
if (error != B_OK)
return error;
// create the debugger interface
CoreFileDebuggerInterface* interface
= new(std::nothrow) CoreFileDebuggerInterface(coreFile);
if (interface == NULL)
return B_NO_MEMORY;
coreFileDeleter.Detach();
BReference<DebuggerInterface> interfaceReference(interface, true);
error = interface->Init();
if (error != B_OK)
return error;
const CoreFileTeamInfo& teamInfo = coreFile->GetTeamInfo();
_thread = teamInfo.Id();
_interface = interface;
interfaceReference.Detach();
return B_OK;
}
status_t
LocalTargetHostInterface::FindTeamByThread(thread_id thread,
team_id& _teamID) const
@@ -23,10 +23,13 @@ public:
virtual status_t Attach(team_id id, thread_id threadID,
DebuggerInterface*& _interface) const;
virtual status_t CreateTeam(int commandLineArgc,
const char* const* arguments,
team_id& _teamID) const;
virtual status_t LoadCore(const char* coreFilePath,
DebuggerInterface*& _interface,
thread_id& _thread) const;
virtual status_t FindTeamByThread(thread_id thread,
team_id& _teamID) const;