Getting to know gdb
Nothing to hand in
Goals
- Get familiar with using the GNU Debugger (gdb) to explore and debug C programs
Documentation & tutorials
I have posted some potentially useful gdb resources on our Resources page.
What to do
Here are a few very rough steps to guide you through some gdb basics. You'll have questions, so write them down and ask them.
- Grab a copy of the gdb_test.c sample.
Compile it like so:
gcc -Wall -Werror -g -Og -o gdb_test gdb_test.cThe -g means "include debugging info in the executable". The "-Og" (that's a capital O, not a zero) means "optimize this code for the best debugging experience".
Try running the program to compute 6-factorial:
./gdb_test 6Fire up gdb
gdb gdb_test ...lots of notices... (gdb) [the gdb prompt]Run the program to compute 6! again:
(gdb) run 6Most gdb commands can be executed using abbreviations:
(gdb) r 6Show 10 lines (the default) of the source code:
(gdb) listThe list command makes guesses about which 10 lines you want to see. For example, it selects the "current" source file and starting line (whatever that might mean in context).
Show lines 10 through 25:
(gdb) list 10,25You can also explicitly name the source file if your executable comes from multiple sources (like qtest did on your queues assignment).
(gdb) list gdb_test.c:10,25For all gdb commands, if you hit return at the next prompt, gdb tries to repeat the previous command. So for example, try this:
(gdb) list 1,20 ...[listing of source code]... (gdb) [hit return] ...[what do you see?]...Let's set a breakpoint. That's a place where gdb will pause execution of your code and let you look at the variables, registers, and memory at that moment.
(gdb) br gdb_test.c:14 [or] (gdb) br 19 [if the file name is unambiguous](I picked 19 here so it will pause just before executing the recursive call factorial(n-1), but you can put a breakpoint anywhere.)
Run the program, which will pause at your breakpoint:
(gdb) r 6Look at the code just before and just after your breakpoint.
listLook at the current contents of a parameter or local variable:
(gdb) print nLook at the current "backtrace" (i.e. the list of function calls that are currently active—in this case, just main calling factorial(6), so far).
(gdb) btLet's continue the program execution:
(gdb) continue [or just] (gdb) cAgain, you'll break (i.e. pause) at line 14. Take a look at the backtrace (also known as a stack trace) and see that there's a new call to factorial(5) on the stack.
(gdb) btContinue and backtrace a couple more times until the top of the backtrace is factorial(3). Now, let's look at the system stack in memory. First, show the contents of the registers:
(gdb) info reg [or just] (gdb) i rTake special note of the stack-pointer register rsp. For me as I write this, factorial(3) is the most recent function call in the backtrace, and the value stored in rsp is 0x7fffffffe7a0.
Let's look at the system stack, starting where the rsp points:
(gdb) x/40wx 0x7fffffffe7a0 [i.e. whatever address you see in rsp]Here, the first "x" stands for "examine", the "w" is "show me 4-byte words", the 40 is how many words I want to see, and the second "x" is "show me the word values in hexadecimal". Check quick reference guides and documentation for more formats you can ask to see.
Study the memory contents. Can you see where the "n" variable for all of those successive calls to factorial(...) are stored? How many bytes seem to be in each of the function call's stack frame?
If you want to execute exactly one line of code, you can do "next" or "ni" (for "next instruction"):
(gdb) niNote that if the upcoming line of code includes a function call and there's a breakpoint inside that function, execution will pause before your "next" operation gets a chance to execute the entirety of line 19.
If you're paused at line 19 (result = factorial(n-1)) and you want to "step into" the function call factorial(n-1), you can use "si":
(gdb) siwhich in this case should take you to the first line of factorial, but with a smaller value of n.
Keep trying stuff!
Next up
We'll do this same thing, but in assembly language!