Debugger CLI: Add a bunch of new commands

* "thread": prints/sets the current thread.
* "continue", "stop": continue/stop the current thread.
* "sc"/"bt": Print a stack trace for the current thread. Very basic yet.
This commit is contained in:
Ingo Weinhold
2012-08-05 01:07:17 +02:00
parent 86b1039b42
commit 9b008d31ff
10 changed files with 333 additions and 1 deletions
+4
View File
@@ -174,6 +174,10 @@ Application Debugger :
# user_interface/cli
CliCommand.cpp
CliContext.cpp
CliContinueCommand.cpp
CliStackTraceCommand.cpp
CliStopCommand.cpp
CliThreadCommand.cpp
CliThreadsCommand.cpp
CliQuitCommand.cpp
CommandLineUserInterface.cpp
@@ -0,0 +1,45 @@
/*
* Copyright 2012, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "CliContinueCommand.h"
#include <stdio.h>
#include <AutoLocker.h>
#include "CliContext.h"
#include "MessageCodes.h"
#include "Team.h"
#include "UserInterface.h"
CliContinueCommand::CliContinueCommand()
:
CliCommand("continue the current thread",
"%s\n"
"Continues the current thread.")
{
}
void
CliContinueCommand::Execute(int argc, const char* const* argv,
CliContext& context)
{
AutoLocker<Team> teamLocker(context.GetTeam());
Thread* thread = context.CurrentThread();
if (thread == NULL) {
printf("Error: No current thread.\n");
return;
}
if (thread->State() != THREAD_STATE_STOPPED) {
printf("Error: The current thread is not stopped.\n");
return;
}
context.GetUserInterfaceListener()->ThreadActionRequested(thread->ID(),
MSG_THREAD_RUN);
}
@@ -0,0 +1,20 @@
/*
* Copyright 2012, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef CLI_CONTINUE_COMMAND_H
#define CLI_CONTINUE_COMMAND_H
#include "CliCommand.h"
class CliContinueCommand : public CliCommand {
public:
CliContinueCommand();
virtual void Execute(int argc, const char* const* argv,
CliContext& context);
};
#endif // CLI_CONTINUE_COMMAND_H
@@ -0,0 +1,86 @@
/*
* Copyright 2012, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "CliStackTraceCommand.h"
#include <stdio.h>
#include <AutoLocker.h>
#include "CliContext.h"
#include "FunctionInstance.h"
#include "StackTrace.h"
#include "Team.h"
CliStackTraceCommand::CliStackTraceCommand()
:
CliCommand("print a stack trace of the current thread",
"%s\n"
"Prints a stack trace for the current thread.")
{
}
void
CliStackTraceCommand::Execute(int argc, const char* const* argv,
CliContext& context)
{
// get the current thread
Team* team = context.GetTeam();
AutoLocker<Team> teamLocker(team);
Thread* thread = context.CurrentThread();
if (thread == NULL) {
printf("no current thread\n");
return;
}
if (thread->State() != THREAD_STATE_STOPPED) {
printf("Current thread is not stopped. Can't get stack trace.\n");
return;
}
// get its stack trace
StackTrace* stackTrace = thread->GetStackTrace();
if (stackTrace == NULL) {
// TODO: Wait for stack trace!
printf("Current thread doesn't have a stack trace. Waiting not "
"implemented yet\n");
return;
}
BReference<StackTrace> stackTraceReference(stackTrace);
// hold a reference until we're done
teamLocker.Unlock();
// print the stack trace
int32 frameCount = stackTrace->CountFrames();
for (int32 i = 0; i < frameCount; i++) {
StackFrame* frame = stackTrace->FrameAt(i);
printf("%3" B_PRId32 " %#" B_PRIx64 " %#" B_PRIx64, i,
(uint64)frame->FrameAddress(), (uint64)frame->InstructionPointer());
Image* image = frame->GetImage();
FunctionInstance* function = frame->Function();
if (image == NULL && function == NULL) {
printf(" ???\n");
continue;
}
BString name;
target_addr_t baseAddress;
if (function != NULL) {
name = function->PrettyName();
baseAddress = function->Address();
} else {
name = image->Name();
baseAddress = image->Info().TextBase();
}
printf(" %s + %#" B_PRIx64 "\n", name.String(),
uint64(frame->InstructionPointer() - baseAddress));
}
}
@@ -0,0 +1,20 @@
/*
* Copyright 2012, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef CLI_STACK_TRACE_COMMAND_H
#define CLI_STACK_TRACE_COMMAND_H
#include "CliCommand.h"
class CliStackTraceCommand : public CliCommand {
public:
CliStackTraceCommand();
virtual void Execute(int argc, const char* const* argv,
CliContext& context);
};
#endif // CLI_STACK_TRACE_COMMAND_H
@@ -0,0 +1,45 @@
/*
* Copyright 2012, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "CliStopCommand.h"
#include <stdio.h>
#include <AutoLocker.h>
#include "CliContext.h"
#include "MessageCodes.h"
#include "Team.h"
#include "UserInterface.h"
CliStopCommand::CliStopCommand()
:
CliCommand("stop the current thread",
"%s\n"
"Stops the current thread.")
{
}
void
CliStopCommand::Execute(int argc, const char* const* argv,
CliContext& context)
{
AutoLocker<Team> teamLocker(context.GetTeam());
Thread* thread = context.CurrentThread();
if (thread == NULL) {
printf("Error: No current thread.\n");
return;
}
if (thread->State() == THREAD_STATE_STOPPED) {
printf("Error: The current thread is already stopped.\n");
return;
}
context.GetUserInterfaceListener()->ThreadActionRequested(thread->ID(),
MSG_THREAD_STOP);
}
@@ -0,0 +1,20 @@
/*
* Copyright 2012, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef CLI_STOP_COMMAND_H
#define CLI_STOP_COMMAND_H
#include "CliCommand.h"
class CliStopCommand : public CliCommand {
public:
CliStopCommand();
virtual void Execute(int argc, const char* const* argv,
CliContext& context);
};
#endif // CLI_STOP_COMMAND_H
@@ -0,0 +1,58 @@
/*
* Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "CliThreadCommand.h"
#include <stdio.h>
#include <AutoLocker.h>
#include "CliContext.h"
#include "Team.h"
CliThreadCommand::CliThreadCommand()
:
CliCommand("set or print the current thread",
"%s [ <thread ID> ]\n"
"Sets the current thread to <thread ID>, if supplied. Otherwise prints "
"the\n"
"current thread.")
{
}
void
CliThreadCommand::Execute(int argc, const char* const* argv,
CliContext& context)
{
if (argc > 2) {
PrintUsage(argv[0]);
return;
}
if (argc < 2) {
// no arguments -- print the current thread
context.PrintCurrentThread();
return;
}
// parse the argument
char* endPointer;
long threadID = strtol(argv[1], &endPointer, 0);
if (*endPointer != '\0' || threadID < 0) {
printf("Error: Invalid parameter \"%s\"\n", argv[1]);
return;
}
// get the thread and change the current thread
Team* team = context.GetTeam();
AutoLocker<Team> teamLocker(team);
if (Thread* thread = team->ThreadByID(threadID))
context.SetCurrentThread(thread);
else
printf("Error: No thread with ID %ld\n", threadID);
}
@@ -0,0 +1,20 @@
/*
* Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef CLI_THREAD_COMMAND_H
#define CLI_THREAD_COMMAND_H
#include "CliCommand.h"
class CliThreadCommand : public CliCommand {
public:
CliThreadCommand();
virtual void Execute(int argc, const char* const* argv,
CliContext& context);
};
#endif // CLI_THREAD_COMMAND_H
@@ -16,7 +16,11 @@
#include <Referenceable.h>
#include "CliContext.h"
#include "CliContinueCommand.h"
#include "CliQuitCommand.h"
#include "CliStackTraceCommand.h"
#include "CliStopCommand.h"
#include "CliThreadCommand.h"
#include "CliThreadsCommand.h"
@@ -268,8 +272,18 @@ CommandLineUserInterface::_InputLoop()
status_t
CommandLineUserInterface::_RegisterCommands()
{
if (_RegisterCommand("help", new(std::nothrow) HelpCommand(this)) &&
BReference<CliCommand> stackTraceCommandReference(
new(std::nothrow) CliStackTraceCommand, true);
BReference<CliCommand> stackTraceCommandReference2(
stackTraceCommandReference.Get());
if (_RegisterCommand("bt", stackTraceCommandReference.Detach()) &&
_RegisterCommand("continue", new(std::nothrow) CliContinueCommand) &&
_RegisterCommand("help", new(std::nothrow) HelpCommand(this)) &&
_RegisterCommand("quit", new(std::nothrow) CliQuitCommand) &&
_RegisterCommand("sc", stackTraceCommandReference2.Detach()) &&
_RegisterCommand("stop", new(std::nothrow) CliStopCommand) &&
_RegisterCommand("thread", new(std::nothrow) CliThreadCommand) &&
_RegisterCommand("threads", new(std::nothrow) CliThreadsCommand)) {
return B_OK;
}