diff --git a/README.adoc b/README.adoc index c9cdc78..fb4f4f4 100644 --- a/README.adoc +++ b/README.adoc @@ -9815,6 +9815,33 @@ In graphic mode, make sure that you never click inside the QEMU graphic while de You can still send key presses to QEMU however even without the mouse capture, just either click on the title bar, or alt tab to give it focus. +==== Reverse debug the emulator + +While step debugging any complext program, you always end up feeling the need to step in reverse to reach the last call to some function before the failure point. + +While GDB "has" this feature, it is just too broken to be usable, and so we expose the amazing Mozilla RR tool conveniently in this repo: https://stackoverflow.com/questions/1470434/how-does-reverse-debugging-work/53063242#53063242 + +Before the first usage: + +.... +echo 'kernel.perf_event_paranoid=1' | sudo tee -a /etc/sysctl.conf +sudo sysctl -p +.... + +Then use it as: + +.... +./run --debug-vm-rr +.... + +Once you are left in the RR GDB shell, just continue: + +.... +continue +.... + +you can now reiably use reverse debugging commands such as `reverse-continue` and `reverse-next`! + ==== Debug gem5 Python scripts Start pdb at the first instruction: diff --git a/build b/build index a627afc..7500c63 100755 --- a/build +++ b/build @@ -439,6 +439,7 @@ Which components to build. Default: qemu-buildroot 'git', 'moreutils', # ts 'python3-pip', + 'rr', 'tmux', 'vinagre', 'wget', diff --git a/run b/run index 94e24b8..1989e9f 100755 --- a/run +++ b/run @@ -45,6 +45,14 @@ For --emulator native, this debugs the target program. default='', help='Pass arguments to GDB. Implies --debug-vm.' ) + self.add_argument( + '--debug-vm-rr', + default=False, + help=''' +Run the emulator through Mozilla RR, and then start replay with reverse debugging enabled: +https://cirosantilli.com/linux-kernel-module-cheat#reverse-debug-the-emulator +''' + ) self.add_argument( '--dtb', help='''\ @@ -340,7 +348,9 @@ Extra options to append at the end of the emulator command line. self.env['tmux_program'] = 'gdb' if self.env['tmux_args'] is not None or self.env['_args_given']['tmux_program']: self.env['tmux'] = True - if self.env['debug_vm'] or self.env['debug_vm_args']: + if self.env['debug_vm_rr']: + debug_vm = ['rr', 'record'] + elif self.env['debug_vm'] or self.env['debug_vm_args']: debug_vm = ['gdb', LF, '-q', LF] + self.sh.shlex_split(self.env['debug_vm_args']) + ['--args', LF] else: debug_vm = [] @@ -597,7 +607,7 @@ Extra options to append at the end of the emulator command line. else: extra_emulator_args.extend(extra_qemu_args) self.make_run_dirs() - if self.env['debug_vm']: + if debug_vm: serial_monitor = [] else: if self.env['background']: @@ -789,6 +799,12 @@ Extra options to append at the end of the emulator command line. raise_on_failure=False, show_stdout=show_stdout, ) + if self.env['debug_vm_rr']: + exit_status = self.sh.run_cmd( + ['rr', 'replay', '-o', '-q'], + raise_on_failure=False, + show_stdout=show_stdout, + ) if exit_status == 0: error_string_found = False exit_status = 0