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