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