Commit 7c5e99c0 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[arm/sim] Add 'sim' gdb command and backtrace command

Port the recent arm64 simulator debugger improvements to arm:

  * [arm64/sim] Add a 'sim' gdb command
    https://crrev.com/c/2664448
  * [arm64/sim] Add a simple backtrace debug command
    https://crrev.com/c/2666688

Change-Id: Id58a49cfe8e643be0fb6718a0a149e2c7ea0bcaa
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2844659
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Dan Elphick <delphick@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarDan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74123}
parent fb51aa40
......@@ -50,6 +50,7 @@ class ArmDebugger {
public:
explicit ArmDebugger(Simulator* sim) : sim_(sim) {}
void Debug();
bool ExecDebugCommand(ArrayUniquePtr<char> line_ptr);
private:
static const Instr kBreakpointInstr =
......@@ -191,6 +192,31 @@ void ArmDebugger::Debug() {
intptr_t last_pc = -1;
bool done = false;
// Unset breakpoint while running in the debugger shell, making it invisible
// to all commands.
UndoBreakpoint();
while (!done && !sim_->has_bad_pc()) {
if (last_pc != sim_->get_pc()) {
disasm::NameConverter converter;
disasm::Disassembler dasm(converter);
// use a reasonably large buffer
v8::internal::EmbeddedVector<char, 256> buffer;
dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(sim_->get_pc()));
PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.begin());
last_pc = sim_->get_pc();
}
ArrayUniquePtr<char> line(ReadLine("sim> "));
done = ExecDebugCommand(std::move(line));
}
// Reinstall breakpoint to stop execution and enter the debugger shell when
// hit.
RedoBreakpoint();
}
bool ArmDebugger::ExecDebugCommand(ArrayUniquePtr<char> line_ptr) {
#define COMMAND_SIZE 63
#define ARG_SIZE 255
......@@ -207,31 +233,19 @@ void ArmDebugger::Debug() {
arg1[ARG_SIZE] = 0;
arg2[ARG_SIZE] = 0;
// Unset breakpoint while running in the debugger shell, making it invisible
// to all commands.
UndoBreakpoint();
if (line_ptr == nullptr) return true;
while (!done && !sim_->has_bad_pc()) {
if (last_pc != sim_->get_pc()) {
disasm::NameConverter converter;
disasm::Disassembler dasm(converter);
// use a reasonably large buffer
v8::internal::EmbeddedVector<char, 256> buffer;
dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(sim_->get_pc()));
PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.begin());
last_pc = sim_->get_pc();
}
char* line = ReadLine("sim> ");
if (line == nullptr) {
break;
} else {
char* last_input = sim_->last_debugger_input();
if (strcmp(line, "\n") == 0 && last_input != nullptr) {
// Repeat last command by default.
const char* line = line_ptr.get();
const char* last_input = sim_->last_debugger_input();
if (strcmp(line, "\n") == 0 && (last_input != nullptr)) {
line_ptr.reset();
line = last_input;
} else {
// Ownership is transferred to sim_;
sim_->set_last_debugger_input(line);
// Update the latest command ran
sim_->set_last_debugger_input(std::move(line_ptr));
}
// Use sscanf to parse the individual parts of the command line. At the
// moment no command expects more than two parameters.
int argc = SScanF(line,
......@@ -245,7 +259,7 @@ void ArmDebugger::Debug() {
// Execute the one instruction we broke at with breakpoints disabled.
sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
// Leave the debugger shell.
done = true;
return true;
} else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
int32_t value;
......@@ -256,8 +270,7 @@ void ArmDebugger::Debug() {
value = GetRegisterValue(i);
PrintF("%3s: 0x%08x %10d", RegisterName(Register::from_code(i)),
value, value);
if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 &&
(i % 2) == 0) {
if ((argc == 3 && strcmp(arg2, "fp") == 0) && i < 8 && (i % 2) == 0) {
dvalue = GetRegisterPairDoubleValue(i);
PrintF(" (%f)\n", dvalue);
} else {
......@@ -267,8 +280,8 @@ void ArmDebugger::Debug() {
for (int i = 0; i < DwVfpRegister::SupportedRegisterCount(); i++) {
dvalue = GetVFPDoubleRegisterValue(i);
uint64_t as_words = bit_cast<uint64_t>(dvalue);
PrintF("%3s: %f 0x%08x %08x\n", VFPRegisters::Name(i, true),
dvalue, static_cast<uint32_t>(as_words >> 32),
PrintF("%3s: %f 0x%08x %08x\n", VFPRegisters::Name(i, true), dvalue,
static_cast<uint32_t>(as_words >> 32),
static_cast<uint32_t>(as_words & 0xFFFFFFFF));
}
} else {
......@@ -289,8 +302,7 @@ void ArmDebugger::Debug() {
} else {
PrintF("print <register>\n");
}
} else if ((strcmp(cmd, "po") == 0) ||
(strcmp(cmd, "printobject") == 0)) {
} else if ((strcmp(cmd, "po") == 0) || (strcmp(cmd, "printobject") == 0)) {
if (argc == 2) {
int32_t value;
StdoutStream os;
......@@ -321,7 +333,7 @@ void ArmDebugger::Debug() {
int32_t value;
if (!GetValue(arg1, &value)) {
PrintF("%s unrecognized\n", arg1);
continue;
return false;
}
cur = reinterpret_cast<int32_t*>(value);
next_arg++;
......@@ -422,6 +434,28 @@ void ArmDebugger::Debug() {
} else {
PrintF("break <address>\n");
}
} else if (strcmp(cmd, "backtrace") == 0 || strcmp(cmd, "bt") == 0) {
int32_t pc = sim_->get_pc();
int32_t lr = sim_->get_register(Simulator::lr);
int32_t sp = sim_->get_register(Simulator::sp);
int32_t fp = sim_->get_register(Simulator::fp);
int i = 0;
while (true) {
PrintF("#%d: 0x%08x (sp=0x%08x, fp=0x%08x)\n", i, pc, sp, fp);
pc = lr;
sp = fp;
if (pc == Simulator::end_sim_pc) {
break;
}
lr = *(reinterpret_cast<int32_t*>(fp) + 1);
fp = *reinterpret_cast<int32_t*>(fp);
i++;
if (i > 100) {
PrintF("Too many frames\n");
break;
}
}
} else if (strcmp(cmd, "del") == 0) {
DeleteBreakpoint();
} else if (strcmp(cmd, "flags") == 0) {
......@@ -519,6 +553,8 @@ void ArmDebugger::Debug() {
PrintF(" enter gdb\n");
PrintF("break <address>\n");
PrintF(" set a break point on the address\n");
PrintF("backtrace / bt\n");
PrintF(" Walk the frame pointers, dumping the pc/sp/fp for each frame.\n");
PrintF("del\n");
PrintF(" delete the breakpoint\n");
PrintF("trace (alias 't')\n");
......@@ -547,12 +583,7 @@ void ArmDebugger::Debug() {
} else {
PrintF("Unknown command: %s\n", cmd);
}
}
}
// Reinstall breakpoint to stop execution and enter the debugger shell when
// hit.
RedoBreakpoint();
return false;
#undef COMMAND_SIZE
#undef ARG_SIZE
......@@ -577,11 +608,6 @@ static bool AllOnOnePage(uintptr_t start, int size) {
return start_page == end_page;
}
void Simulator::set_last_debugger_input(char* input) {
DeleteArray(last_debugger_input_);
last_debugger_input_ = input;
}
void Simulator::SetRedirectInstruction(Instruction* instruction) {
instruction->SetInstructionBits(al | (0xF * B24) | kCallRtRedirected);
}
......@@ -6499,4 +6525,26 @@ void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
} // namespace internal
} // namespace v8
//
// The following functions are used by our gdb macros.
//
V8_EXPORT_PRIVATE extern bool _v8_internal_Simulator_ExecDebugCommand(
const char* command) {
i::Isolate* isolate = i::Isolate::Current();
if (!isolate) {
fprintf(stderr, "No V8 Isolate found\n");
return false;
}
i::Simulator* simulator = i::Simulator::current(isolate);
if (!simulator) {
fprintf(stderr, "No Arm simulator found\n");
return false;
}
// Copy the command so that the simulator can take ownership of it.
size_t len = strlen(command);
i::ArrayUniquePtr<char> command_copy(i::NewArray<char>(len + 1));
i::MemCopy(command_copy.get(), command, len + 1);
return i::ArmDebugger(simulator).ExecDebugCommand(std::move(command_copy));
}
#endif // USE_SIMULATOR
......@@ -77,6 +77,7 @@ class Simulator : public SimulatorBase {
r14,
r15,
num_registers,
fp = 11,
sp = 13,
lr = 14,
pc = 15,
......@@ -255,8 +256,10 @@ class Simulator : public SimulatorBase {
uintptr_t PopAddress();
// Debugger input.
void set_last_debugger_input(char* input);
char* last_debugger_input() { return last_debugger_input_; }
void set_last_debugger_input(ArrayUniquePtr<char> input) {
last_debugger_input_ = std::move(input);
}
const char* last_debugger_input() { return last_debugger_input_.get(); }
// Redirection support.
static void SetRedirectInstruction(Instruction* instruction);
......@@ -468,7 +471,7 @@ class Simulator : public SimulatorBase {
int icount_;
// Debugger input.
char* last_debugger_input_;
ArrayUniquePtr<char> last_debugger_input_;
// Registered breakpoints.
Instruction* break_pc_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment