1Debugging with the VIXL Simulator
2=================================
3
4The VIXL AArch64 simulator contains a basic debugger which can be used to debug
5simulated applications. The debugger supports basic debugging features such as
6setting breakpoints, stepping through simulated instructions and printing
7simulator specific information, for example: printing the values of a register
8or printing instructions at specified addresses.
9
10Using the Debugger
11------------------
12
13In order to use the debugger it first needs to be enabled in the simulator.
14
15```C++
16    Decoder decoder;
17    Simulator simulator(&decoder);
18    simulator.SetDebuggerEnabled(true);
19```
20
21Once enabled, the debugger will be activated whenever a breakpoint (brk) is
22encountered by the simulator. For example:
23
24```asm
25    add x1, x0, #5
26    mov x2, #2
27
28    brk 0   // Debugger activated here.
29
30    sub x3, x1, x2
31```
32
33Further breakpoints can be set either programmatically or interactively in the
34debugger itself. For example, to set breakpoints programmatically:
35
36```C++
37    // 'func' is an AARCH64 assembly function.
38    extern "C" void func();
39
40    Debugger* debugger = simulator.GetDebugger();
41
42    // Register a breakpoint at a fixed (absolute) address.
43    debugger->RegisterBreakpoint(0x00007ffbc6d38000);
44
45    // Register a breakpoint to an already existing assembly function.
46    debugger->RegisterBreakpoint(reinterpret_cast<uint64_t>(&func));
47```
48
49Or to set breakpoints interactively once the debugger has been activated:
50
51```sh
52    sim> break 0x00007ffbc6d38000
53```
54
55The debugger has a variety of useful commands to control program flow (e.g:
56step, next, continue) and inspect features of the running simulator (e.g:
57print, trace). To view a list of all supported commands
58use "help" at the debugger prompt.
59
60```sh
61    sim> help
62```
63
64Extending the Debugger
65----------------------
66
67The debugger can be extended with custom commands to allow for greater
68flexibility in debugging individual applications. This could be used for a
69variety of applications, for example printing out object specific information
70from an address.
71
72To create a custom debugger command, extend the DebuggerCmd class located in
73debugger-aarch64.h and implement its methods.
74
75```C++
76    class PrintObjectCmd : public DebuggerCmd {
77     public:
78      PrintObjectCmd(Simulator* sim)
79            : DebuggerCmd(sim,
80                          "printobject",
81                          "po",
82                          "<address>",
83                          "Print a custom object located at the given address.")
84      {}
85
86      // Called when the command word is given to the interactive debugger.
87      DebugReturn Action(const std::vector<std::string>& args) override {
88        // We want exactly 1 argument (an address) given to the printobject
89        // command.
90        if (args.size() != 1) {
91            fprintf(ostream_, "Error: incorrect command format.");
92            return DebugContinue;
93        }
94
95        auto addr = Debugger::ParseUint64String(args.front());
96        if (addr) {
97            fprintf(ostream_, "Error: could not get address from string.");
98            return DebugContinue;
99        }
100
101        // Convert the address given to a custom object and then print it.
102        CustomObject object = reinterpret_cast<CustomObject>(*addr);
103        object.print();
104      }
105    };
106```
107
108Then simply register the new command with the debugger.
109
110```C++
111    Debugger* debugger = simulator.GetDebugger();
112
113    debugger->RegisterCmd<PrintObjectCmd>();
114```
115