|
|
GDB Tutorial
GNU Make Tutorial
Library with GCC
Vi Tutorial
Intended Audience
This tutorial gives an overview on basic features of GDB. It is assumed that audience is familiar with GCC and "GNU Make". It is also assumed that user has some prior experience with some Debugging Environment.
What is a Debugger
A debugger is a tool for tracing execution to help track down bugs. In more clear words, it is a computer program, whihc helps you to test and debug your programs. Some of the features which a debugger offers (in order to help you debug) are running a program step by step (single-stepping), stopping at certain point in code (by setting break-points), tracking value of variables (watch), trace the code flow (back trace).
Where GDB stands
GDB supports debugging applications written in C, C++, Objective-C, Pascal and Ada (And some more). GDB can run on Unix, MS Windows and Linux Variants. Using GDB you can debug program execute on the same machine as GDB (native) or on any other (remote) machine. In this particular tutorial we will take example of a C application running under Linux.
Building applications for GDB
When you want to debug the application through GDB, the application should be built with Debug Information. Debug information can be added using -g switch with GCC. Note that each file should be compiled with -g option and the -g option should also be used while linking the final executable.
Example Code
I have attached a simple example code which can be used to demonstrate the basic features of GDB. Download this example code and make the executable "example.out" by issuing command "Make all". In the following discussion I will assume that we are debugging "example.out". However you can also use any other executable built with Debug information.
Launching GDB
You can launch the GDB using "gdb" command:
gdb example.out
To run the program just issue the "run" command:
run
When you run the above command, you will observe the output of example.out on your terminal screen. In case your application needs any command line arguments, you need to provide those arguments while invoking run:
run arg1 arg2 ...
Debugging with GDB
- Setting BreakPoints
You can set breakpoint on a given line (in source file) by using command "break line-number" .
- Restarting the appliction
Once the application has been stopped (because of either a break-point or beacause of any other reason), you can resume it by using "continue" command.
- Stepping through the code
You can step through the code (one step at a time) using the "step" command.
- Viewing all the breakpoints.
Breakpoints are managed by their numbers. Each break-point which you set, has a number associated with it. You can print the information on all the available break-points at any time using "info break" command.
- Deleting Break Points
Breakpoint can be deleted using the "delete break-point-number" command.
Refer to the file example.c. To set the break-point at call to "DummyFunc()" in function main() (this corresponds to line number 21), use the "break" command, and run the code:
break 21
run
You can observe that the code execution stops at the line number 21. If you run the code again (using "continue" command):
continue
Code will be executed through one iteration of "for loop" and it will halt again at call to "DummyFunc()", i.e. where the break point is set. If you want to step through the code (instead of running it till next break-point) you can use the "step" command. Each time you enter "step" command, one instruction in code (called step) is executed. Now delete the breakpoint, using "delete" command and run the application again:
delete 1
run
You will observe that now application runs till end (without stopping at any break-point), this is so because all the breakpoints were removed.
More GDB Commands
- Next
"Next" Command is quite similar to "step" command. However there is a slight difference. The "step" command executes the current line of the code and stops on the next statement to be executed. If the current line of code had a function call, the program flow will go inside the function. Whereas, with "next" command, if the current line of the program contains a function call, it executes the function and stops at the next line.
- finish
The "finish" command keeps doing "nexts" untill you reach the end of current function. This command is not meaningful if the code flow is inside function "main()".
- backtrace
This commands provides you a backtrace of function calls. The sequence of function calls which brought the program to current function (from main() ) is printed on screen.
- list
List commands helps you to view the code sections immediately before and after the current line of code. By default 10 lines are printed. But you can specify different options to list. We will discuss more about list in the next section.
- frame
When used without any argument, this command prints a brief description of the currently selected stack frame. However for a detailed information about current frame you can use the command "info frame" , which will print:
- address of the current frame
- address of the next frame down (called by current frame)
- address of the next frame up (frame which called the current frame)
- language in which source code of current frame has been written
- address of the frame's arguments
- the program counter saved in current frame(the address of execution in the caller frame)
- list of registers which were saved in current frame
- print
The "print Expression" command can be used to print the value of any Expression (or variable) in a given frame.
- where
This command is equivalent of "backtrace" command.
More options with LIST
- As we discussed in the previous section, the "list" commands prints 10 lines centered around the current line (being executed in the code).
- The command "set listsize COUNT" can be used to change the number of lines to be printed (by default it was 10) when list command is issued. The "COUNT" value holds good for "list" command issued with any parameter (which we will discuss next.
- The "list line-number" commands prints lines centered around given "line-number" (instead of current line being executed).
- The "list +" command prints the lines just after the lines last printed.
- The "list -" command prints the lines just before the lines last printed.
- The "list start, end" prints lines from "start" to "end" ("start" and "end" are line numbers).
Quiting GDB
- kill : This option will quit the currently running program (if any). You can run the program again using "run" command.
- quit : This option will quit the currently running program (if any) and quit the GDB. You will need to invoke the GDB again (using "GDB program_name" command), before you can run the program.
More on Breakpoints
- Setting breakpoints with multiple source files
In case you have multiple source files in your application you set the break-points using command "break file-name:line-number".
- Setting breakpoints at Functions
You can also set break-points at functions (instead of line numbers) in a given file using the command "break file-name:function-name".
- conditional break points
A conditional break-point can be set using the "break ... if cond" command. This is equivalent to setting a given breakpoint, valuate the expression cond each time the breakpoint is reached, and stop only if the condition evaluates to true.
- Ignore breakpoints
The "ignore break-point-num ignore-count" can be used to ignore a given "break-point" (identified with break-point-number), "ignore-count" times. i.e. The code will not stop at given break-point for first "ignore-count" occurences.
- Wathpoints
Watchpoints are similar to breakpoints and are also known as "data breakpoints". A watch point is a break-point which is hit when the value of a given variable changes. Watchpoint on a given variable can be set using "watch variable-name" command. The code execution will stop whenever the value of variable "variable-name" changes. There are some variations to "watch" command. With "awatch" command, the break-point is hit whenever the value of given variable is read from or written into by the program. With "rwatch" command the break-point will be hit whenever the value of variable is read by the program.
connect to a running process
Till now discussed how we can debug applications which are run under GDB. However you can also connect the GDB to already running application (or process). Let us assume that you have a process name "user_proc" running in background with process ID of "user_proc_id". You can connect the GDB to this process, using one of the following ways:
- Launch GDB with information about running process
gdb user_proc user_proc_id
- Launch GDB and then use "attach" command to attach to the given process
gdb
attach proc_id
The .gdbinit file
Upon startup, GDB reads and executes an initialization file named .gdbinit. The .gdbinit file can contain any command for the GDB. For example if while debugging a particular application you need to set certain break-point and watch-points you can mention it in the .gdbinit file. This way you do not have to manually set them every time you quit and restart the GDB. You can also modify some options like "listsize" using ".gdbinit". The GDB searches for the .gdbinit file in home directory and the current working directory (current working directory has higher preference). So you can put the commands to be executed for all the projects in $home/.gdbinit file and project-specific commands in pwd/.gdbinit file.
|
|