This example runs through some gdb instruction level debugging using the very simple C program example:
// gcc -m32 -S simpleops.c void main() { int x, y; x = 1; x = x + 2; x = x - 14; y = x*100; x = x + y * 6; }Compile this using:
gcc -m32 -o simpleops simpleops.cWith this added flag, the generated IA32 code will be a little easier to read:
gcc -m32 -fno-asynchronous-unwind-tables -o simpleops simpleops.c
Start gdb on the executable simpleops. Add a breakpoint in main, and then start runing the program with (gdb) run:
gdb simipleops (gdb) break main (gdb) runIn gdb you can disassemble code using the disass command:
(gdb) disass mainYou can set a break point at a specific instruction:
(gdb) break *0x080483c1 # set breakpoint at specified address (gdb) cont (gdb) disassAnd you can step or next at the instruction level using ni or si (si steps into function calls, ni skips over them):
(gdb) ni # execute the next instruction then gdb gets control again (gdb) ni (gdb) ni (gdb) ni (gdb) ni (gdb) disassYou can print out the values of individual registers like this:
(gdb) print $eaxYou can also view all register values:
(gdb) info registersYou can also use the display command to automatically display values each time a breakpoint is reached:
(gdb) display $eax (gdb) display $edx
ddd simpleopsThe gdb prompt is in the bottom window. There are also menu options and buttons for gdb commands, but I find using the gdb prompt at the bottom easier to use.
You can view the assembly code by selecting the View->Machine Code Window menu option. You will want to resize this part to make it larger.
You can view the register values as the program runs
(choose Status->Registers to open the register window).
ddd a.out (gdb) break main (gdb) run 6 # run with the command line argument 6 (gdb) disass main # disassemble the main function (gdb) break sum # set a break point at the beginning of a function (gdb) cont # continue execution of the program (gdb) break *0x0804851a # set a break point at memory address 0x0804851a (gdb) ni # execute the next instruction (gdb) si # step into a function call (step instruction) (gdb) info registers # list the register contents (gdb) p $eax # print the value stored in register %eax (gdb) p *(int *)($ebp+8) # print out value of an int at addr (%ebp+8) (gdb) x/wd $ebp+8 # examine the contents of memory at the given address # as an int (w: word-size value d: in decimal) # display type in x is sticky: subsequent x commands # will display values in decimal until another type is # specified (ex. x/a $ebp+8 # as an address in hex) (gdb) x/s 0x0800004 # examine contents of memory at address as a string (gdb) x/wd 0xff5634 # after x/s, the unit size is 1 byte, so if want # to examine as an int specify both the width w and d