The gdb Debugger

1.Building Programs for gdb

a.    Use the -g switch with gcc

2.Command line editing

a.    Control-a: move to beginning of line

b.    Control-e: move to end of line

c.    Control-d: delete character under cursor

d.    Control-u: erase entire line

e.    Control-b: move cursor back

f.    Control-f: move cursor forward

g.    Control-p: see “previous” commands

h.    Control-n: see “next” commands

i.    Also, right/left arrow keys work (but are so lame...)

j.    Tab completion is in effect, so if the command entered so far is unique enough, you can just press the tab key to complete it.

k.    Pressing the Enter key by itself will repeat the last command.

3.Getting help

a.    You can enter help at the gdb command line for a top-level list of items; enter help <item> to descend into the hierarchy of topics.

b.    To search for help on a particular topic, type apropos <topic> to see a list of potentially helpful topics.

4.Managing the Display

a.    There are two basic modes for gdb, command line mode and curses mode.

                                                          i.     By default gdb begins in command line mode; you can view source code being debugged with the list command.

                                                      ii.     To toggle the curses GUI mode, type Ctrl-x,a.

                                                  iii.     Once in curses mode, try these commands: layout next, focus and winheight (you can use help to see the possibilities).

5.Ways to debug a process

a.    Run a program directly through the debugger

b.    Attach to a running process

c.    Use a core file for post-mortem analysis

6.Running a program directly with gdb

a.    Type gdb at command line, followed by EXE name.

b.    At this point gdb is ready, but your program isn't. In order to load your program for the session, you need to enter a command:

                                                          i.     The run command will load and launch your program, which attempt to complete its execution (if it doesn't crash!).

                                                      ii.     The start command will run your debugged program until the beginning of the main procedure; most likely this is how you want to normally begin your session.


7.Controlling Program Flow

a.    To step use next. This will not trace into functions. If you append the optional integer argument, it will execute that many lines of code.

b.    To step into (trace into functions), use the step command. This command also takes an optional integer argument.

c.    Both next and step have corresponding instructions that work at the CPU instruction level, they're called nexti and stepi respectively.

                                                          i.     If you want to trace into shared library code (e.g., a call to printf), you can set/show enter set step-mode on to allow tracing into the code. show step-mode tells you if this stepping mode is on or off.

d.    To have your program run until a breakpoint is encountered or it simply ends, use continue (c for short).

e.    To complete the current stack frame and return to the caller, use the finish command.

f.    To stop your program use Ctrl-C.

8.Setting Breakpoints

a.    You can set breakpoints with the break command.

                                                          i.     You can specify the break location as a line number, function name or memory address.

                                                      ii.     You can also attach a condition for when the break should take effect: break <LOCATION> <if <condition> >

b.    To view all breakpoints, type info breakpoints; you'll see each breakpoint identified with a number.

c.    To delete a breakpoint, type delete <number of breakpoint>

d.    To temporarily disable a breakpoint, use the disable command; it can be followed by a space-separated list of breakpoint numbers, or entering the command with no breakpoint numbers will disable all breakpoints. To activate a disabled breakpoint, use the enable command.

9.Setting Watchpoints

a.    These are like breakpoints, but your program is only halted when the value of a variable is changed at runtime. This is especially useful to track down problems dealing with memory corruption.

b.    The syntax for creating, disabling and re-enabling watchpoints is the same as that for breakpoints.

10.Inspecting Data

a.    You can use the print command to display the value of just about anything.

                                                          i.     Local variables.

                                                      ii.     Addresses of local variables.

                                                  iii.     Addresses of functions (both your own and external libraries).

b.    You can also print expressions on the fly (e.g., counter + 100); type-casting is helpful to reinterpret expressions.

c.    Registers can be displayed with print, e.g., print $eax

d.    Formatting is supported with any of the format specifiers used to examine memory, using the x command (try help x for a complete list).


e.    The print command is helpful for inspecting arrays:

                                                          i.     If you use print on a struct or array allocated in the current stack frame, you'll see its entire contents.

                                                      ii.     If you have a pointer to an array, you can use the @ symbol to see a list of elements (e.g., print myArray@5).

                                                  iii.     Use set print array <on/off> to have arrays displayed one element to a line or not. The show print array command displays the current setting.

f.    The print command is helpful to see structure members. The set print pretty command allows you to control whether member data is dumped on one line or each member value to its own line; show print pretty displays the current setting.

g.    You can also use printf, just like a usual function call without the parentheses.

h.    The display command will display an expression as you step through the code, allowing you to see the expression being updated.

                                                          i.     Use display without any arguments to see all active display expressions.

                                                      ii.     Use undisplay to remove items from the display list.

i.    The whatis command can be used to tell you the data type of an expression.

11.Changing Variables

a.    You can change the value of a variable with the set command, e.g., set myInt = 22

b.    You can also change the values of registers, e.g., set $eax = 1

c.    If you want to show and/or set command line arguments, look at the show args and set args commands.

12.Inspecting Memory

a.    You can look directly into memory, which can be especially helpful if you have to debug a program that wasn't compiled with debug information.

b.    The command to examine memory is x, and the syntax is x /<format> <address>

                                                          i.     The format is a repeat count followed by a format letter and a size letter.

                                                      ii.     The address can be specified with literal address values, or symbolic addresses.

                                                  iii.     Use help x to see a complete list of format and size letters.

c.    For example, x /8xb 0x08048000 would display eight bytes in hexadecimal, beginning at address 0x08048000.

13.Inspecting Registers

a.    Use the info command to see registers, e.g. info registers

b.    To include floating-point and extended registers, use info registers all


14.Attaching to a Running Process

a.    First you must get the process ID (PID) of the target process:

                                                          i.     To search for your process, enter this from another console: ps aux | grep <EXE name>

1.  The second column lists the PIDs for each process.

                                                      ii.     If you're attaching to a process that you're in the midst of developing, you can insert a call to “getpid” in your code and have the program display its own PID.

1.  #include <unistd.h>

2.  pid_t getpid(void);

b.    Once you have the PID, start gdb and enter the command attach <PID>. This will suspend the other process so you can debug it.

15.Debugging with Core Files

a.    Core files contain the memory image of the process at the time when the core file was created:

                                                          i.     the process heap

                                                      ii.     stack

                                                  iii.     any writable memory segments that were in the process' address space at the time.

b.    Core files can be used long after a problem occurs to debug a program.

c.    The kernel will automatically create a core file if a process traps with a signal such as SIGSEGV (result of dereferencing a NULL pointer, memory corruption or out-of-bounds references).

d.    A core file will be generated only if the shell's resource limits allow it. To see the shell's default resource settings, use the ulimit -a command.

                                                          i.     The first entry displays the number of blocks dedicated to the generation of a core file; if it's set to zero then no core files will be generated.

                                                      ii.     You can set the block count to unlimited with ulimit -c unlimited; running your program again will allow the generation of the core.

                                                  iii.     To see what's in the core file, try readelf -all core | less.

e.    Once you have a core, you can load it into gdb with gdb a.out core; this will load the image up to the point of the crash. (You must have access to the EXE because a core file in itself is not in executable format.)

f.    Note that you can't use any of the execution commands while examining a core file, because the given program is not actually running, it's not a live process.

g.    If you want to save the current state of your program you can issue the command generate-core-file <filename>.


16.Inspecting the Stack

a.    You can see the call stack with the backtrace command.

                                                          i.     Can use bt as a shortcut.

                                                      ii.     Using bt all by itself shows you the current memory address and values of formal parameters.

                                                  iii.     Adding the argument full shows you local variables as well.

b.    The frame command (f for short) allows you to jump among the stack frames, just type f <frame# is optional, defaults to zero>. The top-most stack frame is at position zero. (The up and down commands also can be used to jump through frames.)

c.    Typing info frame <frame# is optional, defaults to zero> will display even more information, such as important registers, locations for local variables, caller and callee stack frames, etc.

d.    If you want a function to complete its execution and return to the caller, you can use the finish command.

17.Initializing Your gdb Session

a.    You can place any sequence of commands you would normally type at the gdb prompt in a text file named .gdbinit  If gdb finds this file in the current working directory, it will read the batch of commands and execute them.