the info command for getting application and debugger state
Setting conditional breakpoints and setting breakpoints in C++ methods
Keyboard shortcuts in gdb
invoking make in gdb
Advanced features debugging threaded programs, attaching to an already running process, debugging a child process after a fork, signal handling
Assembly code debugging (using gdb to debug at the assembly code level, and how to examine memory and register values)
Links to more gdb information
Some settings (and bug fixes) for ddd
Here are some of the usful actions that gdb can perform:
For C and C++ programs, gdb and ddd are debuggers that you can use.
ddd
is a easy-to-use GUI wrapper around an inferior debugger (gdb
for GNU compiled C or C++ code). ddd
allows you to interact
with the debugger by using either GUI menu options or the under-lying debugger's
command line interface. In addition, ddd
automatically displays source code when breakpoints are reached.
There are some example programs and some documentation on using gdb
to debug them that you can copy from here:
/home/newhall/public/gdb_examples/
-g
option can be debugged using GNU's debugger gdb
(actually, you
can use gdb on code that is not compiled with -g, but unless you like trying to
figure out how assembly code sequences map to your source code I wouldn't
recommend doing so). Also, do not compile with an optimization flag (i.e.
don't use -O2), or gdb will have a hard time mapping optimized machine code
to your source code. For example:
% gcc -g myprog.c
To start gdb, invoke gdb on the executable file. For example:
% gdb ./a.outIf your program terminates with an error, then the operating system will often dump a core file that contains information about the state of the program when it crashed. gdb can be used to examine the contents of a core file:
% gdb core ./a.outOne good way to get started when you are trying to track down a bug, is to set breakpoints at the start of every function. In this way, you will quickly be able to determine which function has the problem. Then you can restart the program and step through the offending function line-by-line until you locate the problem exactly.
ddd is invoked in a similar way:
% ddd ./a.out
gdb also understands abreviations of commands, so you can just type up to the unique part of a command name ("cont" for "continue", or "p" for "print", "n" for next, "s" for step, ...)
help <topic or command> Shows help available for topic or command help breakpoints Lists help information about breakpoints help print Lists help information about print command
break <line> Sets breakpoint at line number <line> break <func-name> Sets breakpoint at beginning of function <func-name> break main Sets breakpoint at beginning of main function
run command line args
step Execute next line of a program (stepping into a function) step <count> Executes next <count> lines of program
next Execute the next instruction next <count> Executes next <count> instructions
list Lists next few lines of program list <line> Lists lines around line number <line> of program list <start> <end> Lists line numbers <start> through <end> list <func-name> Lists lines at beginning of function <func-name>
frame <frame-num> Sets current stack frame to <frame-num> info frame Show state about current stack frame
disable [breakpoints] [bnums ...] Disable one or more breakpoints disable 3 # disable breakpoint number 3 (run info break to get bnums) enable [breakpoints] [bnums ...] Enable one or more breakpoints clear <line> Clears breakpoint at line number <line> clear <func-name> Clears breakpoint at beginning of function <func-name> delete <bp-num> Deletes breakpoint number <bp-num> delete Deletes all breakpoints
condition <bp-num> <exp> Sets breakpoint number <bp-num> to break only if conditional expression <exp> is true
print <exp> (or inspect <exp> Displays the value of expression <exp> To print in different formats: print/x <exp> print the value of the expression in hexidecimal (e.g. print/x 123 displays 0x7b) print/t <exp> print the value of the expression in binary (e.g. print/t 123 displays 1111011) print/d <exp> print the value of the expression as unsigned int format (e.g. print/d 0x1c displays 28) print/c <exp> print the ascii value of the expression (e.g. print/c 99 displays 'c') print (int)<exp> print the value of the expression as signed int format (e.g. print (int)'c' displays 99)To represent different formats in the expression (the default is decimal):
0x prefix for hex: 0x1c 0b prefix for binary: 0b101 print 0b101 # prints 5 print 0b101 + 3 # prints 8 (default is decimal) you can also re-cast expressions using C-style syntax (int)'c'You can use register values and values stored in memory locations in expressions:
print $eax # print the value stored in the eax register print *(int *)0x8ff4bc10 # print int value at memory address 0x8ff4bc10
x <var, memory address> x 0x5678 # examines the contents of memory location 0x5678 in decimal x &temp # can also use address of varible as argumentCan display in diffent formats (as an int, a char, a string, ...), and the format is sticky: specify the format once to set it and subsequent x command use it.
In general x takes up to three arguments (x/nfu memory_address), the order does not matter:
x/10dh 0x1234 # examine 10 short values in decimal starting at address 0x1234 x/wx &temp # examine 4-byte value at address of temp in hexidecimal x/a &ptr # examine the value stored at the address of ptr as an address # assume s1 = "Hello There" is at memory address 0x40062d: x/4c s1 # examine the first 4 chars in s1 0x40062d 72 'H' 101 'e' 108 'l' 108 'l' x/s s1 # examine the memory location associated with var s1 as a string 0x40062d "Hello There" x/wd s1 # examine the memory location assoc with var s1 as an int # because x formatting is sticky need to explicitly set # units to word (w) after doing x/s (which sets them to b) 0x40062d 72 x/8d s1 # the ascii values of the first 8 chars of s1 0x40062d: 72 101 108 108 111 32 84 104NOTE: format in examine is sticky, for example if you use the command x/c subsequent executions of x will use /c format. you therefore need to explicitly change the format to /d /c /s etc. for interpreting memory contents as differnt type from the previous call to x
display <exp> # display value of <exp> at every breakpoint display i+1
whatis <exp> Shows data type of expression <exp>
info locals Shows local variables in current stack frame info args Shows the argument variable of current stack frame info break Shows breakpoints help info Shows all the info options
set variable <variable> = <exp> Sets variable <variable> to expression <exp> set x = 123*y # set var x's value to 123*y
(gdb) help info # lists a bunch of info X commands (gdb) help status # lists more info and show commands (gdb) info frame # list information about the current stack frame (gdb) info locals # list local variable values of current stack frame (gdb) info args # list argument values of current stack frame (gdb) info registers # list register values (gdb) info breakpoints # list status of all breakpoints
Here are some gdb commands that are useful for debugging at the assembly code level (the Common Comands section has more general details about some of these commands, particularly formatting options for print and x):
disass list the assembly code for a function or range of addresses disass <func_name> lists assembly code for function disass <start> <end> lists assembly instructions between start and end address break Set a breakpoint at an instruction break *0x80dbef10 Sets breakpoint at the instruction at address 0x80dbef10 stepi, si Execute next machine code instruction, step into function call if it is a call instr nexti, ni Execute next machine code instruction, treats function call as single instr info info registers # list register values print print $eax # print the value stored in the eax register print *(int *)0x8ff4bc10 # print int value stored at memory addr 0x8ff4bc10 x Display the contents of the memory location given an address. NOTE: the format is sticky (need to explictly change it) x $ebp-4 # examine memory at address: (value stored in register ebp)-4 # if this location stores an address x/a, an int x/wd, a ... x/s 0x40062d # examine the memory location 0x40062d as a string 0x40062d "Hello There" x/4c 0x40062d # examine the first 4 char memory locations # starting at address 0x40062d 0x40062d 72 'H' 101 'e' 108 'l' 108 'l' x/d 0x40062d # examine the memory location 0x40062d in decimal 0x40062d 72 # NOTE: units is 1 byte, set by previous x/4c command x/wd 0x400000 # examine the memory location 0x400000 as 4-byte in decimal 0x400000 100 # NOTE: units was 1 byte set, need to reset to w set set the contents of memory locations and registers set $eax = 10 # set the value of register eax to 10 set $esp = $esp + 4 # pop a 4-byte value off the stack set *(int *)0x8ff4bc10 = 44 # at memory address 0x8ff4bc10 store int value 44 display at every breakpoint display the given expression display $eax
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/d $ebp+8 # examine the contents of memory at the given # address (/d: prints the value as an int) # display type in x is sticky: subsequent x commands # will display values in decimal until another type # is specified (e.g. x/x $ebp+8 # 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 dHere is some more information about assembly-level debugging in gdb, including a simple example session: Debugging IA32 Assembly Code with gdb (and ddd)
% gcc -g badprog.c #-- compile program with -g flag % gdb a.out #-- invoke gdb with the executable GNU gdb 6.4.90-debian Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) break main #-- set a breakpoint at start of the program's execution Breakpoint 1 at 0x8048436: file badprog.c, line 36. (gdb) run #-- run the program Starting program: /home/newhall/public/gdb_examples/a.out Breakpoint 1, main () at badprog.c:36 #-- gdb stops at breakpoint 36 int arr[5] = { 17, 21, 44, 2, 60 }; (gdb) list #-- list the source code near the break point 31 return 0; 32 } 33 34 int main(int argc, char *argv[]) { 35 36 int arr[5] = { 17, 21, 44, 2, 60 }; 37 38 int max = arr[0]; 39 40 if ( findAndReturnMax(arr, 5, max) != 0 ) { (gdb) list 11 #-- list source code around line 11 11 // this function should find the largest element in the array and 12 // "return" it through max 13 // array: array of integer values 14 // len: size of the array 15 // max: set to the largest value in the array 16 // reuturns: 0 on success and non-zero on an error 17 // 18 int findAndReturnMax(int *array1, int len, int max) { 19 20 int i; (gdb) list #-- list the next few lines of code 21 22 if(!array1 || (len <=0) ) { 23 return -1; 24 } 25 max = array1[0]; 26 for(i=1; i <= len; i++) { 27 if(max < array1[i]) { 28 max = array1[i]; 29 } 30 } (gdb) next #-- execute the next instruction 38 int max = arr[0]; (gdb) #-- hitting Enter executes the previous command #-- (next in this case) 40 if ( findAndReturnMax(arr, 5, max) != 0 ) { #-- also you can use the up and down arrows to scroll through previous commands (gdb) print max #-- print out the value of max $1 = 17 (gdb) p arr #-- p is short for the print command $2 = {17, 21, 44, 2, 60} (gdb) step #-- step into the function call #-- if had entered 'next', entire function call would be executed #-- 'step' takes us to the entry point of findAndReturnMax findAndReturnMax (array1=0xbfc5cb3c, len=5, max=17) at badprog.c:22 22 if(!array1 || (len <=0) ) { (gdb) print array1[0] #-- lets see what the param values are $3 = 17 (gdb) p max $4 = 17 (gdb) list 17 // 18 int findAndReturnMax(int *array1, int len, int max) { 19 20 int i; 21 22 if(!array1 || (len <=0) ) { 23 return -1; 24 } 25 max = array1[0]; 26 for(i=1; i <= len; i++) { (gdb) break 26 #-- set a breakpoint at line 26 (inside findAndReturnMax) Breakpoint 2 at 0x80483e7: file badprog.c, line 26. (gdb) cont #-- continue the execution Continuing. #-- gdb hits the next breakpoint Breakpoint 2, findAndReturnMax (array1=0xbfc5cb3c, len=5, max=17) at badprog.c:26 26 for(i=1; i <= len; i++) { (gdb) p i $5 = 0 (gdb) n #-- n is short for next 27 if(max < array1[i]) { (gdb) display max #-- display prints out value everytime a breakpoint hit 1: max = 17 (gdb) display array1[i] 2: array1[i] = 21 (gdb) break 27 #-- set a breakpoint inside the loop Breakpoint 3 at 0x80483f0: file badprog.c, line 27. (gdb) cont #-- continue execution Continuing. Breakpoint 3, findAndReturnMax (array1=0xbfc5cb3c, len=5, max=21) at badprog.c:27 27 if(max < array1[i]) { #-- display prints these out: 2: array1[i] = 44 1: max = 21 (gdb) cont Continuing. Breakpoint 3, findAndReturnMax (array1=0xbfc5cb3c, len=5, max=44) at badprog.c:27 27 if(max < array1[i]) { 2: array1[i] = 2 1: max = 44 (gdb) cont Continuing. Breakpoint 3, findAndReturnMax (array1=0xbfc5cb3c, len=5, max=44) at badprog.c:27 27 if(max < array1[i]) { 2: array1[i] = 60 1: max = 44 (gdb) cont Continuing. Breakpoint 3, findAndReturnMax (array1=0xbfc5cb3c, len=5, max=60) at badprog.c:27 27 if(max < array1[i]) { 2: array1[i] = 17 1: max = 60 #-- so max is 60 here (gdb) where #-- show the stack frames #-- findAndReturnMax is active function at line 27, was called by main at line 40: #0 findAndReturnMax (array1=0xbfd043ec, len=5, max=60) at badprog.c:27 #1 0x08048479 in main () at badprog.c:40 frame 1 #-- move into main's calling context (stack frame 1) to examine main's state #1 0x08048479 in main () at badprog.c:40 40 if ( findAndReturnMax(arr, 5, max) != 0 ) { (gdb) print max #-- in main's stack frame max is 17 $1 = 17 (gdb) cont #-- continue execution Continuing. max value in the array is 17 #-- main prints out max after function call #-- This looks like a bug:" #-- findAndReturnMax set max to 60, but 60 isn't getting "passed back" #-- to main after the call. To fix this we need to either have #-- findAndReturnMax return the value of max or pass max by reference (gdb) quit #-- quit gdb The program is running. Exit anyway? (y or n) y
To
% gdb segfaulter (gdb) run #-- just run segfaulter and let it seg fault Program received signal SIGSEGV, Segmentation fault. 0x080483e1 in initfunc (array=0x0, len=100) at segfaulter.c:15 15 array[i] = i; (gdb) where #--- let's see where it segfaulted #0 0x080483e1 in initfunc (array=0x0, len=100) at segfaulter.c:15 #1 0x0804846e in main () at segfaulter.c:38 (gdb) list #--- let's see code around segfaulting instruction 10 int initfunc(int *array, int len) { 11 12 int i; 13 14 for(i=1; i <= len; i++) { 15 array[i] = i; 16 } 17 return 0; 18 } 19 (gdb) p array[0] #--- let's print out some values and see what's going on Cannot access memory at address 0x0 #-- it looks like array is a bad address (0x0 is NULL) (gdb) p array $1 = (int *) 0x0 (gdb) frame 1 #--- let's see what main is passing to this funtion #1 0x0804846e in main () at segfaulter.c:38 38 if(initfunc(arr, 100) != 0 ) { (gdb) print arr #--- print out arr's value (what we pass to initfunc) $2 = (int *) 0x0 #--- oops, we are passing NULL to initfunc... #--- we forgot to initialize arr to point to valid memory
Also, you can give just the unique prefix of a command as the command and gdb will execute it. For example, rather than entering the command print x, you can just enter p x to print out the value of x.
The up and down arrow keys can be used to scroll through previous command lines, so you do not need to re-type them each time.
If you just hit RETURN at the gdb prompt, gdb will execute the
most recent previous command again. This is particularly useful if you are
steping through the execution, then you don't have to type next
each time you want to execute the next instruction, you can just type
it one time and then hit RETURN.
To set a condition on a breakpoint, use the condition command with the number of the breakpoint followed by the condition on which to trigger the breakpoint. Here is an example where I'm setting a conditional breakpoint in the loops.c program that will only be triggered when the condition (i >= 150) is true:
(gdb) break 28 # set breakpoint at line 28 (gdb) info break # list breakpoint information Num Type Disp Enb Address What 1 breakpoint keep y 0x080483a3 in foo at loops.c:28 (gdb) condition 1 (i >= 150) # set condition on breakpoint 1 (gdb) run (or continue if already running) Breakpoint 1, foo (val=200) at loops.c:28 # breakpoint 1 is reached 28 if(i > val) (gdb) print i # only when (i >= 150) $1 = 150
For example, to set a break point in funciton pinPage of the BufMgr class, I'd do the following:
(gdb) break 'BufMgr::pinPage(int, Page *&, int)'This looks pretty icky, but really I just type break 'BufMgr::p then hit TAB for automatic completion.
(gdb) break 'BufMgr:: <tab>will list all methods of the BufMgr class, then you can just pick from the list the method you want to put the breakpoint in.
# ps to get process's pid (lists all processes started in current shell): $ ps # list all processes pipe through grep for just those named a.out: $ ps -A | grep a.out PID TTY TIME CMD 12345 pts/3 00:00:00 a.out
# gdb <executable> <pid> $ gdb a.out 12345 # OR alternative syntax: # gdb attach <pid> <executable> $ gdb attach 12345 a.outAt this point the process is stopped by gdb; you have the gdb prompt that you can use issue gdb commands like setting breakpoints, or printing out program state before continuing execution.
(gdb) cont # try this first (gdb) singal SIGCONT # try this if the cont command doesn't work
(gdb) set follow-fork-mode childgdb will follow the child process after the fork. See debugging forks for more information.
(gdb) signal SIGCONT (gdb) signal SIGALARM ...Sometimes your process receives signals and you would like to have gdb perform some action when certain signals are delived to the debugged process. For example, if your program issues a bad adress, it will receive a SIGBUS signal and usually exit. The default behavior of gdb on a SIGBUS it to let the process exit. If, however, you want to examine program state when it recieves a SIGBUS, you can specify that gdb handle this singal differently:
(gdb) handle SIGBUS stop # if program gets a SIGBUS, gdb gets controlYou can list how gdb is handling signals using info:
(gdb) info signal # list info on all signals (gdb) info SIGALRM # list info just for the SIGALRM signal
rm -rf ~/.ddd