ClassRooms/gdbBasics

Back to ClassRooms

Here will be put a lesson about gdb, the GNU Debugger. Any improvement is welcome, and everybody is warmly welcome to participate.

Goal

 * Learn the gdb essentials
 * A student must be able to:
 * Launch an application using gdb, including arguments
 * Attach to a given process, and control it
 * Catch a stack
 * Detach from a given process, and quit
 * Set a breakpoint using file:line_number
 * Set a breakpoint using 'class::aMethod'
 * Set a conditional breakpoint
 * Print a given value, a pointer (address + content), a structure, its members ... and so on
 * Set a command in the execution context
 * Manage breakpoints
 * Read, and show a given memory address
 * Retrieve the type, and the content of a given address
 * Stop the execution and control a crash
 * Recognize important gdb options
 * Additional skills: customize gdb

Introduction
Debugging OpenOffice.org, or OOo4Kids, is not trivial, nor easy. One of the tool we can use in that purpose, is gdb.

The goal of this page is to present gdb basics, applied to OOo4Kids debugging, say the most important and usefull cases. For further information, please have a look at this gdb documentation.

Launching an Application Using gdb
There are two main ways we'll be using gdb with applications. Launching an applicaton using gdb and arguments, and launching the application and then using gdb to attach to the application with it's unique process ID.

Launch an Application Using gdb, Including Arguments
A compiled program can be launched using gdb in the following way: gdb --args app_name arg2 arg3 Here app_name is the name of the compiled program, and arg2 and arg3 are either omitted or replaced by arguments being passed to app_name. For example: gdb -q --args my_program # -q runs gdb in quiet mode, without verbose information This command starts gdb connected to my_program, but it does not run my_program. To tell gdb to run the program, at the (gdb) prompt run: (gdb) run This will attempt to execute the program. An alternative would have been to have run: (gdb) r This command is equivalent to the previous command. At this point gdb should display: Starting program: path_to_file/my_program This message will be followed by the content of the program, and any error output.

Another useful example is launching OOo4Kids with gdb. Access the OOo4Kids program directory and run: gdb -q --args soffice.bin This method is particularly useful when you anticipate needing to restart OOo4Kids to test your breakpoints or whatnot.

Attaching to a Given Process, and Controlling the Execution of the Process
For this example we will use the OOo4Kids "soffice.bin". With an instance of "soffice.bin" running we can use gdb to attach to, and control the execution of, the process. First launch OOo4Kids and determine the unique process ID. ./soffice ps ax | grep soffice.bin | grep -v grep The second command will return a single line with information about the "soffice.bin" process. Now we will launch gdb and attach to the "soffice.bin" process using the process ID that was returned. gdb -q # -q runs gdb in quiet mode, without verbose information With gdb running the shell prompt becomes (gdb). Now run the following command to attach to the "soffice.bin" process, replacing process_ID with the unique process ID acquired above. (gdb) attach process_ID When gdb attaches to the process, execution of the process is halted. To return control to the application run: (gdb) c To halt the process again press 'CTRL+c'. Do this a few times to ensure you understand when gdb has the application halted and when the application is running. Note: Even when control is returned to the application gdb is still attached to the process. To completely detach from the process see below.

Catching a Stack
Use the following command to print a backtrace of the program's stack: (gdb)bt When the stack is printed by gdb the top of the stack is denoted by #0 with #1, #2, etc. representing steps previously executed.

Here is an example of a stack trace of a program named "crash.c": #0 0x0018b418 in gets  from /lib/tls/i686/cmov/libc.so.6 #1 0x080484ef in read_string (s=0x0) at crash.c:30 #2 0x08048491 in main  at crash.c:16

Detaching from a Process, and Quitting
To detach gdb from a process, run: (gdb) detach To quit gdb entirely, run: (gdb) q

Setting a Breakpoint Using file:line_number
Breakpoints can be set using the format: (gdb) b file:line_number For example, while attached to the "soffice.bin" process we can then set a breakpoint in the file "appserv.cxx" (as long as the sfx2 library is built to use symbols). (gdb) b appserv.cxx:448 The preceding command will set a breakpoint in the file "appserv.cxx" at line number 448. To check the current breakpoints that we have set, run: (gdb) info breakpoints Note: The info command is very useful; by replacing "breakpoints" above with any command name we can acquire additional information about the given command.

Setting a Breakpoint Using 'class::aMethod'
Breakpoints can also be sent using the following format: (gdb)b 'class::aMethod'  For example, while attached to the "soffice.bin" process we can then set the following breakpoint (provided we have the sw library built to include symbols): (gdb)b 'SwDoc::GetFmtFromPool'

Setting a Conditional Breakpoint
Setting a conditional breakpoint for a library with symbols added follows the following format. To follow this example you must have the sw library built to include symbols. First, start OOo4Kids then gdb and use gdb to attach to the soffice.bin process. Next, instruct gdb to set a breakpoint: (gdb) b 'SwDoc::GetFmtFromPool' Then gdb should prompt with: Make breakpoint pending on future shared library load? (y or [n]) y Choose 'y' resulting in: Breakpoint 1 ('SwDoc::GetFmtFromPool') pending.

Check the breakpoint: (gdb) info b This prints out information regarding the breakpoint, such as: Num    Type           Disp Enb Address    What 1      breakpoint     keep y   0xb1c43747 in SwDoc::GetFmtFromPool(unsigned short) at /../../my_OOo4Kids/sw/source/core/doc/poolfmt.cxx:1104

Next, set the conditional breakpoint: (gdb) cond 1 (nId == 3074) In the above command the format is: cond breakpoint_number (variable == value). Now check the conditional breakpoint: (gdb) info b This displays: Num    Type           Disp Enb Address    What 1      breakpoint     keep y   0xb1c43747 in SwDoc::GetFmtFromPool(unsigned short) at /../../my_OOo4Kids/sw/source/core/doc/poolfmt.cxx:1104 stop only if (nId == 3074)

Next continue normal functioning of soffice: (gdb) c Continuing.

For this example, open a new document for OOo4Kids Writer then type and highlight the text "a over b", and click on the Insert Menu and then select Math Formula. Ooo4Kids should be temporarily paused, because of the breakpoint that was set. Press 'CTRL C' to restore the gdb prompt, then print the contents of nId variable: (gdb) p nId This displays: $1 = 3074

Setting a Conditional Breakpoint for a Constant
In the previous example 3074 could have been replaced by RES_POOL_FORMEL: (gdb) cond 1 (nId==RES_POOL_FORMEL) (gdb) c Continuing. The previous condition will display: No symbol "RES_POOL_FORMEL" in current context. Nonetheless, the breakpoint will still be hit during program execution. Use the Math Formula function again in OOo4Kids Writer to test this.

Check the breakpoint for the constant RES_POOL_FORMEL: (gdb) info b This should display something similar to: Num    Type           Disp Enb Address    What 1      breakpoint     keep y   0xb1c43747 in SwDoc::GetFmtFromPool(unsigned short) at /../../my_OOo4Kids/sw/source/core/doc/poolfmt.cxx:1104 stop only if (nId==RES_POOL_FORMEL) breakpoint already hit 2 times After hitting the breakpoint, verify the value of nId. (gdb) p nId $2 = 3074

Printing a given value, a pointer (address + content), a structure, its members ... and so on
We've already seen some examples of printing values in the previous sections. To print a given value you need to know the variable names used in the given program context. This has some limitations as we saw above in the conditional breakpoint example; gdb will not print constants when given the constants variable name. Above, running: (gdb) p RES_POOL_FORMEL Displayed: No symbol "RES_POOL_FORMEL" in current context. Whereas, running the same command with the variable name holding the actual value represented by RES_POOL_FORMEL: (gdb) p nId Displayed: $1 = 3074 Thus it is important to understand the precise variable and context you want to print.

Setting a Command in the Execution Context
In the following example we will show how to change the value of boolean variable in the execution context. For this example, we will consider the following code sample: static bool bIsActive = FALSE; if ( isActive ) { ...  } In the above code there is no way to enter into the body of the if statement during normal program execution, due to the fact that bIsActive is being set to FALSE immediately prior to it.

We can, however, use gdb to enter the body of the if statement. Suppose that the line "static bool bIsActive = FALSE;" is line number 344 in the file "aFile.cxx".

We then run: (gdb)b aFile.cxx:344 We then run the program, and execution will halt prior to the declaration of bIsActive.

We then execute the next line of code (344) by running: (gdb)n This processes the declaration and assignment of bIsActive.

Now we can change the value of bIsActive to TRUE and enter the body of the if statement by running: (gdb)set bIsActive=TRUE (gdb)c

The set command is not limited to boolean variables. The set command also works for pointers, strings and numeric types. For more information on using set run: (gdb)help set Note: There is no need to add "final" and some uses of set may require casting. The basic format for casting is: (gdb)set (aType)aVariable=aValue

Setting a Command in the Execution Context Using OOo4Kids
For this example we will need to have an installation of OOo4Kids with the vcl library built to include symbols. This example was run on Ubuntu 10.04, small adjustments may be required for different operating systems.

First we will start OOo4Kids with gdb from the OOo4Kids program directory: gdb -q --args soffice.bin (gdb)run This brings us to the OOo4Kids StartCenter; observe the fact that the Writer button is pre-highlighted, for this is what we will be examining in this example

Next, we will set a breakpoint using the 'class::method' format: b 'ToolBox::ImplChangeHighlight' # The source code is in: vcl/source/window/toobox.cxx Now, launch OOo4Kids again: (gdb)run Note: It is significant to observe that although OOo4Kids is being restarted, all breakpoints that have been set will be preserved. This allows us to hit our breakpoint prior to the opening of the StartCenter. If we want to remove breakpoints we must either quit the gdb session entirely, or use the following command: (gdb)d breakpoint_number # omitting breakpoint_number will delete ALL current breakpoints

Examining the output when the breakpoint is hit will include something similar to: Breakpoint 1, ToolBox::ImplChangeHighlight (this=0x140a0650, pItem=0x0, bNoGrabFocus=1 '\001') at ... Observe the "bNoGrabFocus=1" statement and then run: (gdb)c Examing the output when the breakpoint is hit again: Breakpoint 1, ToolBox::ImplChangeHighlight (this=0x140a0650, pItem=0x140ac600, bNoGrabFocus=0 '\000') at ... Observe that the statement is now "bNoGrabFocus=0".

To observe that it is the "bNoGrabFocus" value that describes whether or not something is highlighted, we want to set "bNoGrabFocus" to 1 and then continue execution of the program, but we must remove the breakpoint before the StartCenter can be observed. Thus we run the following commands: (gdb)set bNoGrabFocus=1 (gdb)d 1 (gdb)c

Managing Breakpoints
In the previous examples we have seen how to set breakpoints by file:line_number and 'class::method'.

We have seen how to set a condition on a breakpoint: cond breakpoint_number condition We have also seen how to delete breakpoints: d breakpoint_number To obtain the list of our current breakpoints we run: info b To obtain more information on using breakpoints we run: help breakpoints

Reading, and Displaying a Given Memory Address
To find out where a value is stored in memory run the command

(gdb) p &a_variable

The & is used to return the address of a_variable instead of its contents.

Then to read the contents, Where 0xffffffffff is your address returned by p &a_variable (this will vary each time the program is run)

(gdb) p 0xffffffffff

If we are dealing with pointers such as an int * a_variable; running the command p &a_variable will give you the address but if you do p 0xffffffffff you will not get the expected value of whatever a_variable is pointing to. You have to remember to dereference the address to get at its contents.

(gdb) p *0xffffffffff

Retrieving the Type, and the Content of a Given Address
We can determine the type of a given variable during gdb execution by running: (gdb)whatis aVariable

Stopping the Execution and Controlling a Crash
gdb -q --args myprogram #that should print Reading symbols from ~/Desktop/myprogram...done. #and the prompt (gdb)
 * GDB is able to pause the program at breakpoints and watch expressions.
 * For example for myprogram.c gdb can be use with:

(gdb) run Starting program: $home/Desktop/myprogram #type 'bt' and Type a command : bt #prints a backtrace of the program stack
 * Then run the program:

#0 0x0018b418 in gets  from /lib/tls/i686/cmov/libc.so.6 #1 0x080484ef in read_string (s=0x0) at myprogram.c:30 #2 0x08048491 in main  at myprogram.c:16
 * The printout of the programs stack will then be displayed:

(gdb) shell file myprogram myprogram: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
 * Check the status of the program with:

(gdb) l
 * To list the first 23 lines of the program use:

#and set a breakpoint on line 13 with (gdb) b 13 #that prints Breakpoint 1 at 0x804847d: file myprogram.c, line 13. #run the program again (gdb) r

#choose to start the program from the beginning, because program being debugged has been started already. Start it from the beginning? (y or n) y

Starting program: ~/Desktop/myprogram


 * Then gdb will stop the program at the breakpoint that was set:

Breakpoint 1, main at myprogram.c:13 13	   char           *my_string = NULL;

#print an expression with (gdb) p *my_string

#evaluates and prints in this example $1 = 124 '|'

(gdb) n #steps over function calls to arrive at a function call on line 16 16	   read_string(my_string);
 * Next to step passed the set breakpoint / expression:


 * By printing a list of the programs code or examining the breakpoint you might think that the my_string char pointer has a bug:

#point the my_string pointer to the array of chars "buf" (gdb) set my_string=buf #the program is temporarily working

(gdb) c Continuing.
 * Continue with the programs execution:

#The programs input Type a command : hello world

#The programs output you entered : hello world


 * a bug from myprogram.c has been found to be fixed in emacs editor.

Important gdb Options
We use -q to tell gdb to run in a non-verbose mode. We use --args to tell gdb to run in conjunction with a particular program.

Usefull links
Full documentation : Using The GNU GDB Debugger (By Peter Jay Salzman, edited by R. Somers)

Helpers to display UNO objects or values
Original information form D .Tardon

To display specific objects, it is possible to create new types in your ~/.gdbinit :


 * to get real C++ type of an XInterface

Add this in your .gdbinit :  set print object on

def pu   print $arg0._pInterface end 

Use it this way :  pu xSomething 


 * to display the content of the first XInterface argument

Add this in your .gdbinit :  def xu   if $arg0._pInterface print *$arg0._pInterface end end 

Use it this way :  xu xSomething 