Add a skip command to the AArch64 debugger.

Here is an example of user interaction:

    Hit breakpoint at pc=0xb3cc50.
    Next: 0x0000000000b3cc50  d4200000		brk #0x0
    vixl> disasm
    0x0000000000b3cc50  d4200000		brk #0x0
    0x0000000000b3cc54  d2800000		mov x0, #0x0
    0x0000000000b3cc58  d2800021		mov x1, #0x1
    0x0000000000b3cc5c  d2800042		mov x2, #0x2
    0x0000000000b3cc60  d2800063		mov x3, #0x3
    0x0000000000b3cc64  d2800084		mov x4, #0x4
    0x0000000000b3cc68  d28000a5		mov x5, #0x5
    0x0000000000b3cc6c  f100001f		cmp x0, #0x0 (0)
    0x0000000000b3cc70  da805400		cneg x0, x0, mi
    0x0000000000b3cc74  d65f03c0		ret
    vixl> stepi
    Next: 0x0000000000b3cc58  d2800021		mov x1, #0x1
    vixl> skip 3
    Skipping over 3 instructions:
    Skip: 0x0000000000b3cc58  d2800021		mov x1, #0x1
    Skip: 0x0000000000b3cc5c  d2800042		mov x2, #0x2
    Skip: 0x0000000000b3cc60  d2800063		mov x3, #0x3
    Next: 0x0000000000b3cc64  d2800084		mov x4, #0x4
    vixl>

Change-Id: I833cf6381edf94423f1e54dae636d206a93fed9f
This commit is contained in:
Alexandre Rames 2016-07-20 09:01:11 +01:00
parent 384fe09960
commit 80497ed4c9
2 changed files with 81 additions and 4 deletions

View File

@ -36,6 +36,7 @@ namespace aarch64 {
C(HelpCommand) \
C(ContinueCommand) \
C(StepCommand) \
C(SkipCommand) \
C(DisasmCommand) \
C(PrintCommand) \
C(ExamineCommand)
@ -329,6 +330,26 @@ class StepCommand : public DebugCommand {
IntegerToken* count_;
};
class SkipCommand : public DebugCommand {
public:
SkipCommand(Token* name, IntegerToken* count)
: DebugCommand(name), count_(count) {}
virtual ~SkipCommand() { delete count_; }
int64_t count() { return count_->value(); }
virtual bool Run(Debugger* debugger);
virtual void Print(FILE* out = stdout);
static DebugCommand* Build(std::vector<Token*> args);
static const char* kHelp;
static const char* kAliases[];
static const char* kArguments;
private:
IntegerToken* count_;
};
class DisasmCommand : public DebugCommand {
public:
static DebugCommand* Build(std::vector<Token*> args);
@ -434,6 +455,10 @@ const char* StepCommand::kAliases[] = {"stepi", "si", NULL};
const char* StepCommand::kArguments = "[n = 1]";
const char* StepCommand::kHelp = " Execute n next instruction(s).";
const char* SkipCommand::kAliases[] = {"skip", NULL};
const char* SkipCommand::kArguments = "[n = 1]";
const char* SkipCommand::kHelp = " Skip the next n instruction(s).";
const char* DisasmCommand::kAliases[] = {"disasm", "di", NULL};
const char* DisasmCommand::kArguments = "[n = 10]";
const char* DisasmCommand::kHelp =
@ -563,7 +588,9 @@ void Debugger::Run() {
}
void Debugger::PrintInstructions(const void* address, int64_t count) {
void Debugger::PrintInstructions(const void* address,
int64_t count,
const char* prefix) {
if (count == 0) {
return;
}
@ -577,6 +604,7 @@ void Debugger::PrintInstructions(const void* address, int64_t count) {
for (const Instruction* current = from; current < to;
current = current->GetNextInstruction()) {
printf("%s", prefix);
printer_->Decode(current);
}
}
@ -713,8 +741,7 @@ void Debugger::RunDebuggerShell() {
return;
}
printf("Next: ");
PrintInstructions(ReadPc());
PrintNextInstruction();
bool done = false;
while (!done) {
char buffer[kMaxDebugShellLine];
@ -1273,6 +1300,51 @@ DebugCommand* StepCommand::Build(std::vector<Token*> args) {
}
bool SkipCommand::Run(Debugger* debugger) {
VIXL_ASSERT(debugger->IsDebuggerRunning());
int64_t steps = count();
if (steps < 0) {
printf(" ** invalid value for steps: %" PRId64 " (<0) **\n", steps);
} else {
printf("Skipping over %" PRId64 " instructions:\n", steps);
debugger->PrintInstructions(debugger->ReadPc(), steps, "Skip: ");
debugger->WritePc(debugger->ReadPc() + steps * kInstructionSize);
debugger->PrintNextInstruction();
}
return false;
}
void SkipCommand::Print(FILE* out) {
fprintf(out, "%s %" PRId64 "", name(), count());
}
DebugCommand* SkipCommand::Build(std::vector<Token*> args) {
IntegerToken* count = NULL;
switch (args.size()) {
case 1: { // step [1]
count = new IntegerToken(1);
break;
}
case 2: { // step n
Token* first = args[1];
if (!first->IsInteger()) {
return new InvalidCommand(args, 1, "expects int");
}
count = IntegerToken::Cast(first);
break;
}
default:
return new InvalidCommand(args, -1, "too many arguments");
}
return new SkipCommand(args[0], count);
}
DebugCommand* DisasmCommand::Build(std::vector<Token*> args) {
IntegerToken* count = NULL;
switch (args.size()) {

View File

@ -106,7 +106,12 @@ class Debugger : public Simulator {
UpdatePendingRequestStatus();
}
void PrintInstructions(const void* address, int64_t count = 1);
void PrintInstructions(const void* address,
int64_t count = 1,
const char* prefix = "");
void PrintNextInstruction() {
PrintInstructions(ReadPc(), 1, "Next: ");
}
void PrintMemory(const uint8_t* address,
const FormatToken* format,
int64_t count = 1);