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:
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user