From dbf6176481b6421517c612a9042f0c6d6e773046 Mon Sep 17 00:00:00 2001 From: justanothercatgirl Date: Fri, 9 May 2025 16:29:17 +0300 Subject: initial commit --- guides/debugging.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 guides/debugging.md (limited to 'guides/debugging.md') diff --git a/guides/debugging.md b/guides/debugging.md new file mode 100644 index 0000000..1e13191 --- /dev/null +++ b/guides/debugging.md @@ -0,0 +1,81 @@ +# This is a simple guide to using AVR-GDB with simavr +First of all, you can use the [Makefile](../Makefile) in the directory above. +But for the competeness sake, I'll list commands + +## Running simulation +QEMU: I don't personally prefer it, but here is a breakdown: +```sh +qemu-system-avr -M arduino-uno -bios -nographic -s -S +``` +* `-M`: machine to use, shorthand for `--machine`. Self-explanatory. +* `-bios`: the thing that you would flash onto your arduino. Note that this is + not a hex file, this must be an elf file, the one you get out of `ld`. +* `-nographic`: this should be default to be honest +* `-s`: shorthand for `-gdb tcp::1234`. Enables GDB debugging +* `-S`: suspend execution and wait for debugger to connect. +This should be everything you need. +[More documentation] (https://www.qemu.org/docs/master/system/target-avr.html) + +SIMAVR: This is the one I prefer + +First of all, the `--help` is actually not as big so it's easy to guess +everything yourself, but fine, here is the command: +```sh +simavr -m atmega328p -g +``` +I think you can already see why I like it more. Breakdown of flags: +* `-m, --mcu` stands for "MicroController Unit". atmega328p is the processor arduino + uno uses +* `-g, --gdb`: wait for gdb to connect on `:1234` +* `-f, --freq`: optionally specify the clock frequency, arduino uno has 16MHz +You can also interrupt the process to kill it! Qemu does not let you do that. + +## gdb +```sh +$ avr-gdb +(gdb) target remote :1234 +(gdb) c +``` +First of all, load the image. Then connect to the simulation. Since this is not +a program in a traditional sense, it's already running and you have to +`continue` instead of `run`. +* to break at an address, use `b *0x69`. also, 0x69 is odd, so you will not land + there. Instructions are either 16 bit or 32 bit on AVR, so almost any even + address is a valid instruction. +* to print instructions at some address, use `x/16i 0x420`, replace 16 with + amount of instructions and 0x420 with an actual address. you can also use + `$pc`, which stands for program counter (current instruction) as an address. + Also, unlike on intel/arm64, you can safely write `x/4i $pc-4` and get a valid + disassembly. +* To print register values, use `print $r16`, replace `r16` with any register + you want. For formatted printing, see `help x` in gdb shell, it is often + useful to `print/x` in hexadecimal or `print/t` in binary. +* use `displ` command. You will probably want to track current instruction, 1 or + 2 registers and some IO memory addresses. For me, a "must have" is + `displ/i $pc`, which displays an instruction to be executed each time the + execution avdances. really useful for stepping +* `si` command steps 1 assembly insstruction. you will find yourself using it a + lot +* To print IO registers, use `print *(unsigned char*)0xADD12E55`. NOTE that, if + you can use `in/out` instruction to access a memory location, gdb can't, it + will always use `sts/lds`. So don't forget `0x20` to all IO locations before + `0x3F`. For example, if you want to track `PORTB`, you'd often write + `displ/t *(unsigned char)0x25`, even though documentation says the `PORTB` is + at `0x05`. +* To restart the program without restarting the simulation, you can write + `set $pc = 0`. This will trick a processor into thinking that next instruction + is at `0x00`, which is a reset vector. Note that state of your registers does + not reset. The set command it useful in many places, for example you want a + loop to execute for a little longer - you can set the counter register to 0. +* you can safely put breakpoints at interrupts, at any labels you defined, + anywhere. +* I coudn't get `compile code` gdb instruction to work (to execute assembly + on-the-fly), because it can't find the avr C compiler. Maybe this is a + distribution misconfiguration. Didn't bother setting up stuff in a debian VM. + +This is it! Hope this was helpful. + +P.S.: Internet has a lof of `avr-gdb` guides, and even more "just `gdb`" guides, +which are as relevant. Search them up and have fun debugging! + +JAC, 2025 -- cgit v1.2.3-70-g09d2