Skip to content

Commit

Permalink
Debugger: Beginning of core file support
Browse files Browse the repository at this point in the history
* DebuggerInterface: Add method IsPostMortem() to be able to
  descriminate between live and post mortem debugging.
* Add DebuggerInterface implementation CoreFileDebuggerInterface which
  provides information from a core file.
* TeamDebugger: Don't start the debug event thread when debugging post
  mortem.
* Debugger: New command line variant "Debugger --core <file path>",
  which starts a team debugger using the core file.

There are a few issues:
* I didn't see an easy way to integrate with the new
  TargetHostInterface framework and I didn't want to get into Rene's
  way changing stuff. As a side effect core file debug windows are not
  counted and Debugger will quit when only those are left, respectively
  will additionally open a teams window on start-up.
* There aren't any symbols yet. We can't use the debug kit
  functionality, since it isn't bitness/endianess agnostic. So either
  it needs to be adjusted or ported over to Debugger.
  • Loading branch information
weinhold committed Apr 24, 2016
1 parent 3d26e83 commit 1a899ed
Show file tree
Hide file tree
Showing 7 changed files with 603 additions and 19 deletions.
123 changes: 114 additions & 9 deletions src/apps/debugger/Debugger.cpp
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2009-2016, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2011-2016, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
Expand All @@ -20,6 +20,8 @@
#include <AutoLocker.h>
#include <ObjectList.h>

#include "CoreFile.h"
#include "CoreFileDebuggerInterface.h"
#include "CommandLineUserInterface.h"
#include "DebuggerInterface.h"
#include "GraphicalUserInterface.h"
Expand All @@ -44,11 +46,12 @@ static const char* const kDebuggerSignature
= "application/x-vnd.Haiku-Debugger";


static const char* kUsage =
static const char* const kUsage =
"Usage: %s [ <options> ]\n"
" %s [ <options> ] <command line>\n"
" %s [ <options> ] --team <team>\n"
" %s [ <options> ] --thread <thread>\n"
" %s [ <options> ] --core <file>\n"
"\n"
"The first form starts the debugger displaying a requester to choose a\n"
"running team to debug respectively to specify the program to run and\n"
Expand All @@ -61,6 +64,8 @@ static const char* kUsage =
"The third and fourth forms attach the debugger to a running team. The\n"
"fourth form additionally stops the specified thread.\n"
"\n"
"The fifth form loads a core file.\n"
"\n"
"Options:\n"
" -h, --help - Print this usage info and exit.\n"
" -c, --cli - Use command line user interface\n"
Expand All @@ -73,7 +78,7 @@ static void
print_usage_and_exit(bool error)
{
fprintf(error ? stderr : stdout, kUsage, kProgramName, kProgramName,
kProgramName, kProgramName);
kProgramName, kProgramName, kProgramName);
exit(error ? 1 : 0);
}

Expand All @@ -86,6 +91,7 @@ struct Options {
bool useCLI;
bool saveReport;
const char* reportPath;
const char* coreFilePath;

Options()
:
Expand All @@ -95,7 +101,8 @@ struct Options {
thread(-1),
useCLI(false),
saveReport(false),
reportPath(NULL)
reportPath(NULL),
coreFilePath(NULL)
{
}
};
Expand Down Expand Up @@ -126,6 +133,7 @@ parse_arguments(int argc, const char* const* argv, bool noOutput,
{ "save-report", optional_argument, 0, 's' },
{ "team", required_argument, 0, 't' },
{ "thread", required_argument, 0, 'T' },
{ "core", required_argument, 0, 'C' },
{ 0, 0, 0, 0 }
};

Expand All @@ -140,6 +148,10 @@ parse_arguments(int argc, const char* const* argv, bool noOutput,
options.useCLI = true;
break;

case 'C':
options.coreFilePath = optarg;
break;

case 'h':
if (noOutput)
return false;
Expand Down Expand Up @@ -207,6 +219,7 @@ parse_arguments(int argc, const char* const* argv, bool noOutput,
return true;
}


static status_t
global_init(TargetHostInterfaceRoster::Listener* listener)
{
Expand Down Expand Up @@ -243,7 +256,8 @@ global_init(TargetHostInterfaceRoster::Listener* listener)


class Debugger : public BApplication,
private TargetHostInterfaceRoster::Listener {
private TargetHostInterfaceRoster::Listener,
private TeamDebugger::Listener {
public:
Debugger();
~Debugger();
Expand All @@ -260,9 +274,17 @@ class Debugger : public BApplication,
// 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;
Expand Down Expand Up @@ -444,13 +466,17 @@ Debugger::ArgvReceived(int32 argc, char** argv)
return;
}

TargetHostInterface* hostInterface
= TargetHostInterfaceRoster::Default()->ActiveInterfaceAt(0);

TeamDebuggerOptions debuggerOptions;
set_debugger_options_from_options(debuggerOptions, options);
debuggerOptions.settingsManager = &fSettingsManager;
hostInterface->StartTeamDebugger(debuggerOptions);

if (options.coreFilePath != NULL) {
_LoadCoreFile(options.coreFilePath, debuggerOptions);
} else {
TargetHostInterface* hostInterface
= TargetHostInterfaceRoster::Default()->ActiveInterfaceAt(0);
hostInterface->StartTeamDebugger(debuggerOptions);
}
}


Expand Down Expand Up @@ -492,6 +518,30 @@ 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)
Expand Down Expand Up @@ -526,6 +576,61 @@ 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


Expand Down
1 change: 1 addition & 0 deletions src/apps/debugger/Jamfile
Expand Up @@ -141,6 +141,7 @@ local sources =
DebuggerInterface.cpp

# debugger_interface/interfaces
CoreFileDebuggerInterface.cpp
LocalDebuggerInterface.cpp

# elf
Expand Down
22 changes: 12 additions & 10 deletions src/apps/debugger/controllers/TeamDebugger.cpp
Expand Up @@ -496,16 +496,18 @@ TeamDebugger::Init(DebuggerInterface* interface, thread_id threadID, int argc,
}
}

// create the debug event listener
char buffer[128];
snprintf(buffer, sizeof(buffer), "team %" B_PRId32 " debug listener",
fTeamID);
fDebugEventListener = spawn_thread(_DebugEventListenerEntry, buffer,
B_NORMAL_PRIORITY, this);
if (fDebugEventListener < 0)
return fDebugEventListener;
// create the debug event listener (for live debugging only)
if (!fDebuggerInterface->IsPostMortem()) {
char buffer[128];
snprintf(buffer, sizeof(buffer), "team %" B_PRId32 " debug listener",
fTeamID);
fDebugEventListener = spawn_thread(_DebugEventListenerEntry, buffer,
B_NORMAL_PRIORITY, this);
if (fDebugEventListener < 0)
return fDebugEventListener;

resume_thread(fDebugEventListener);
resume_thread(fDebugEventListener);
}

// run looper
thread_id looperThread = Run();
Expand All @@ -520,7 +522,7 @@ TeamDebugger::Init(DebuggerInterface* interface, thread_id threadID, int argc,
}

// if requested, stop the given thread
if (threadID >= 0) {
if (threadID >= 0 && !fDebuggerInterface->IsPostMortem()) {
if (stopInMain) {
SymbolInfo symbolInfo;
if (appImage != NULL && mainThreadHandler != NULL
Expand Down
10 changes: 10 additions & 0 deletions src/apps/debugger/debugger_interface/DebuggerInterface.cpp
Expand Up @@ -4,11 +4,21 @@
* Distributed under the terms of the MIT License.
*/


#include "DebuggerInterface.h"


// #pragma mark - DebuggerInterface


DebuggerInterface::~DebuggerInterface()
{
}


bool
DebuggerInterface::IsPostMortem() const
{
// only true for core file interfaces
return false;
}
2 changes: 2 additions & 0 deletions src/apps/debugger/debugger_interface/DebuggerInterface.h
Expand Up @@ -40,6 +40,8 @@ class DebuggerInterface : public TeamMemory {

virtual bool Connected() const = 0;

virtual bool IsPostMortem() const;

virtual team_id TeamID() const = 0;

virtual Architecture* GetArchitecture() const = 0;
Expand Down

0 comments on commit 1a899ed

Please sign in to comment.