ClassRooms/gdbBasics

From Wiki.ooo4kids.org

Jump to: navigation, search


gdb basics

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.

Teacher information

Time 2 x 30 minutes (presentation + questions)
Pre-requisites Be able to use the shell Bash. gdb is supposed to be installed, and working. The libs are supposed including symbols
Associated tools DDD (gdb front end, more user-friendly)
Difficulty level TAG DEV LEVEL1.png

Goal

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.

Debugging with gdb

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) run
 Starting program: $home/Desktop/myprogram
 #type 'bt' and <enter>
 Type a command : 
 bt
 #prints a backtrace of the program stack
 #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
 (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
 (gdb) l
 #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
 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);
 #point the my_string pointer to the array of chars "buf"
 (gdb) set my_string=buf
 #the program is temporarily working
 (gdb) c
 Continuing.
 #The programs input
 Type a command : 
 hello world
 #The programs output
 you entered : hello world

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)

Customize .gdbinit

Helpers to display UNO objects or values

Original information form D .Tardon

TAG PROGRESS.png


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

Add this in your .gdbinit :

set print object on

def pu
    print $arg0._pInterface
end

Use it this way :

pu xSomething

Add this in your .gdbinit :

def xu
    if $arg0._pInterface
        print *$arg0._pInterface
    end
end

Use it this way :

xu xSomething

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox