# Debugging

## Introduction to debugging

To debug is human. To fix it is divine...

Well, the human part is what this section is about. The divine part is up to you!

When a program does not behave in the way it is supposed to, we say the program contains a bug or bugs. This does not refer to compilation errors — those are simply errors and they are relatively easy to clear, because the compiler tells you where the problems are. On the other hand, bugs are errors that happen during the execution of the program and they can be hard (sometimes very hard!) to detect.

Any program that you think is bug-free is never completely bug-free. All we can try to do is to reduce the number of bugs contained in the program. The process of removing bugs is known as debugging, and the tool that is used for debugging is called the debugger. Anjuta provides a very user-friendly and powerful debugging environment (actually, a GUI wrapper over gdb, a powerful command line debugging tool).

A debugger tracks and traces the execution of the program and provides various views of information needed to study the execution of the program.

### Debugger Targets

Before debugging, it is important to understand what debugging targets are. Debugging targets refer to those entities with which the debugger interacts during operation. There are four types of debugging targets:

1. Executable

2. Symbol table

3. Core file

4. Process

There can be only one target active for each of the four types of targets at any give time. All of the targets do not need to be active for the debugger to work, although certain combinations are required active for a useful debugging session. Example combinations may be [ executable, symbol table, and process ] or [ executable, symbol table and core file ].

The target Executable becomes active when an executable file is loaded into the debugger.

The target Symbol table is automatically loaded from the executable file, therefore it does not have to be handled separately. The symbol table is necessary for the debugger to identify the various symbols in the source code of the program. The information is included in the executable during the compilation (as long as the program is compiled with the Debug option enabled — see setting-compiler-options for details).

The target Core file becomes active when the core file is loaded into the debugger. A core file is the memory image of the program which was dumped by the kernel, usually because it had performed an illegal operation. The core file can provide information such as variable contents, register values, and stack trace of the program at the time of the error. By studying the core file it is possible to find out which part of the program has misbehaved and resulted in the core dump.

The target Process becomes active when the program is executed under the debugger or when you attach to an already running process.

### Starting and Stopping the Debugger

To start the debugger, choose the menu item Debug Start Debugger. This will start the debugger with the executable of the current project. If there is no project open, then it will load the executable of the currently active file. If there is no project open, and no active file, the debugger will start, but no executable will be loaded. The executable will have to be loaded manually.

Once the debugger is started, a debugging session will be entered. When debugging is complete, exit the debugging session by choosing the menu item Debug Stop Debugger.

### Loading Executables

The debugger will automatically load an executable if a project or a file is currently open. To load a different executable, choose the menu item Debug Load Executable …. A file selection dialog will open. Select the executable to debug and click on OK.

### Attaching to a Process

It is possible to attach to a running process for debugging. Choose the menu item Debug Attach to Process …. A list of all the process running on the system will appear.

#### Attach to Process dialog

Attach to Process dialog

Select the process to attach to and click OK. Ensure that the executable (and hence the symbol table) have already been loaded into the debugger.

If lots of question marks (??) appear during the debugging session, then the attached process and the executable do not match.

### Loading a Core file

Choose the menu item Debug Load Core file … to load the core file. Select the core file in the file selection dialog and click OK. When loading a core file, ensure that the executable file (and hence the symbol table) has already been loaded — otherwise, debugging may be tricky!

If lots of question marks (??) appear during the debugging session, then the core file and the executable do not match.

## Execution

Execution of a program in the debugger can be finely controlled. The program can be executed in single steps, or allowed to continue until it encounters a breakpoint. Executing like this is essential for tracking program behaviour. Like a video editing session, the program can be executed in slow motion with the ability to go forward, pause, stop, and so on.

The methods that can be used to execute a program in the debugger are described in the next few sections.

### Single stepping (step in)

Single stepping executes only one statement of the program (from the place where it has stopped) and then returns control. If the statement that is executed contains one or more functions, the debugger tries to step inside the functions (in the sequence in which the functions are executed). Once the statement is executed and control is passed back, it is possible to study the various program parameters.

If the program has not been started at the time single stepping is started, the program will be started and will be stopped at the first statement of the program (the first statement in the function main()).

Choose the menu item Debug Execution Step In or click on the Step In icon in the Debug toolbar to step into a program.

### Single stepping (step over)

Step over is similar to step in, except that it does not step inside any function in the statement being executed. The statement will be executed in one go.

Choose the menu item Debug Execution Step Over or click on the Step Over icon in the Debug toolbar to step over statements in a program.

### Single stepping (step out)

Step out will execute the current function until it returns. The program will be stopped once it exits from the function. Step out is not really single stepping, because it does not only execute a single statement — it executes the whole function until that function returns to the calling function.

Choose the menu item Debug Execution Step Out or click on the Step Out icon in the Debug toolbar to step out in a program.

### Run/Continue

This option will continue the execution of the program until a breakpoint is encountered, or the program exits.

If the program is not yet started, then the program will be started and executed until a breakpoint or program termination is reached.

Choose the menu item Debug Execution Run/Continue or click on the Run/Continue icon in the Debug toolbar to continue the execution of a program.

### Stop Program

This option will kill the program which is being debugged. Note that it is not possible to stop an attached process.

Choose the menu item Debug Stop Program or click on the Stop Program icon in the Debug toolbar to terminate the execution of a program.

### Restart Program

This option will stop the program and then restart it. All of the breakpoints will remain in effect. Note that it is not possible to restart an attached process.

Choose the menu item Debug Restart Program to restart the execution of a program.

## Breakpoints

When debugging a program, it is useful to be able to stop the execution of the program at a particular point, so that the state of the program can be examined at that location. Breakpoints enable this to happen. Breakpoints can be set at different locations in a source file, and then the program is allowed to run. When a breakpoint is encountered, the execution of the program is suspended, enabling expressions to be evaluated, variables to be inspected, the stack trace to be studied, and so on.

### Breakpoint dialog

Breakpoint dialog

Location, refers to the location of the code in the source file. Location can be specified in any of the following formats:

1. File_name:Line_number

2. Function_name

3. File:Function_name

The first one is obvious — The location refers to the line number Line_number in the source file File. The second refers to the first line of the function Function_name. The third is similar to the second, except that this notation is used where there is more than one function with the name Function_name in the program. It is possible to differentiate between them by providing the File, so the notation refers to the function Function_name in the file File.

Two parameters can be associated with each breakpoint:

1. Break condition

2. Pass count

The Break condition is a valid C expression which should evaluate to a Boolean value — that is, the evaluation of the expression should result in either TRUE(1) or FALSE(0). If the final evaluation value is not a Boolean value, then it will be appropriately type casted to a Boolean.

Every time the breakpoint is encountered during the execution, the break condition will be evaluated. The debugger will break the execution only if the evaluation results in a TRUE value, otherwise it will continue the execution as though there had been no breakpoint.

The default value of Break condition is always TRUE. The debugger will break the execution at the breakpoint location.

The Pass count is an integer (unsigned) value which tells the debugger to skip the breakpoint that number of times before it is considered. Pass count has a higher priority than the Break condition. Only when the Pass count reaches zero will the debugger evaluate the Break condition (if any condition is present). If there is no condition, the debugger will break the execution once the Pass count counts down to zero.

The default value of the Pass count is zero. The breakpoint will be considered when it is first encountered.

### Adding or Setting Breakpoints

The Breakpoint editing window can be opened by choosing View Breakpoints or Debug Breakpoints Breakpoints …. Click on Add. A dialog will appear.

#### Breakpoint add dialog

Breakpoint add dialog

Enter the location at which to set the breakpoint. Optionally, enter the Break condition and the Pass count in the appropriate entry boxes. Click OK to set the breakpoint.

A breakpoint may also be by highlighting the function name in the editor and choosing the menu item Debug Breakpoints Set Breakpoint (or by clicking on the Toggle breakpoint at cursor button on the Debug Toolbar).

### Editing Breakpoints

Open the Breakpoint editing window by choosing the menu item View Breakpoints or Debug Breakpoints Breakpoints …. Select the breakpoint to edit and click on Edit. A dialog will appear.

#### Breakpoint edit dialog

Breakpoint edit dialog

Edit the entries as required and click on OK to commit the changes.

### Deleting Breakpoints

Open the Breakpoint editing window by choosing the menu item View Breakpoints or Debug Breakpoints Breakpoints …. Select the breakpoint to delete and click on Delete. The breakpoint will be deleted.

To delete all breakpoints, click on Delete All.

### Enabling or Disabling Breakpoints

Open the Breakpoint editing window by choosing the menu item View Breakpoints or Debug Breakpoints Breakpoints …. Select the breakpoint to enable or disable and click on Toggle Enable. The breakpoint will be enabled or disabled, depending on the current state.

To enable all or disable all breakpoints, click on Enable All or Disable All.

#### Note

When the debugger is started, all breakpoints will be set. Any old breakpoints (where the source file is more recent than the breakpoint) will be disabled.

## Working with Expressions

FIXME:

### Evaluating expressions

When control is returned from a program — possibly at a breakpoint — it is possible to evaluate expressions or inspect the values of variables in the program. Choose the menu item Debug Inspect/Evaluate …, or click the Inspect button on the Debug Toolbar. A dialog prompting for the expression will appear. Supply a valid C expression, or a variable name, and click on OK.

#### Inspect/Evaluate dialog

Inspect/Evaluate dialog

A window will appear showing the result of the evaluation.

#### Evaluation result

Evaluation result

Alternatively, it is possible to highlight the expression in the editor and perform the above steps. This will save typing the expression in the Inspect dialog.

The expression may be any valid C expression and may include function calls from the program, library calls, system calls, etc..

### Expression Watch

Inspecting or evaluating an expression provides the result only once. To continuously monitor some variables or expressions, use expression watch.

Add all the expressions and variables to monitor in the watch. These values will be automatically updated and shown in the expression watch window.

#### Expression Watch window

Evaluation watch

#### Adding an expression to watch

Choose the menu item View Watch Window. Right-click on the expression watch window to open the Operation menu. Choose the menu item Add. A dialog prompting for the expression will appear. Enter the expression and click OK.

##### Add Expression dialog

Add Expression dialog

If the expression was selected in the editor prior to the addition, it will automatically appear in the dialog.

#### Removing an expression from watch

Choose the menu item View Watch Window. Right-click on the expression watch window to open the Operation menu. Choose the menu item Remove to remove the entry.

#### Clearing the watch

Choose the menu item View Watch Window. Right-click on the expression watch window to open the Operation menu. Choose the menu item Clear to update or clear.

### Local varables

Local variables of the current frame (the current funtion in which the program control is present), displayed and updated in the Locals pane of the message manager. During execution of the program (eg. during single stepping), local variables will be updated. If any varialble value was changed in the last debugging step, its value will be highlight in red. The variables are presented in a tree form for easy view.

#### Local variables

Local variables

### Varables tips

Variable tips is a quick way to find out the value of a variable. Hover the mouse cursor over the variable name whose value you would like to have and wait for a couple of seconds. The value of the variable (if availabe with the debugger) will be displayed as a tip.

#### variable-tip

Variable tip

## Stack Trace

### Stack Window

The Stack trace window shows the contents of the program stack. It lists all of the functions and their arguments in the sequence they were called. There is also a number representing each call. This number is called the Frame. Each call in the trace exists in a different frame. This starts from frame 0 (the last function called) and grows higher as the function nesting become deeper.

Choose the menu item View Program Stack, to open the stack trace for the program being debugged.

#### Stack trace window

Stack trace window

A small arrow points to the currently selected frame in the stack trace. By default, this will be frame 0, the last function called. All of the evaluation and inspection of expressions or variables will be with reference to this selected frame. The scope of the variables or expressions being evaluated will be limited to the selected frame only. The same applies for expressions in the watch.

### Setting the current frame

Double-clicking on any frame in the stack trace will set that frame as the currently selected frame (the arrow will point to the frame, indicating that it has been selected as the current frame). Alternatively, open the Operation menu by right-clicking on the Stack trace window, and choose the menu item Set frame to set the frame.

### Information about the current frame

It is possible to obtain information about the currently selected frame by choosing the menu item Debug Information Info Current Frame. A window will open describing the current frame.

#### Current Frame Information

Current Frame Information

### Updating Stack trace

Choose the menu item Update from the Operation menu (right-click on the Stack trace window) to refresh the Stack trace window.

## Others

There are a number of other debugger features which are used less frequently, but are nevertheless handy.

### Kernel Signals

Kernel signals are a way of signaling between processes in Linux. The list of signals available for a program can be displayed by choosing the menu item View Kernel Signals. A window will open which lists all of the signals available in the system along with a brief description of each signal.

#### Kernel Signals window

Kernel Signals window

There are three columns which specify what to do when the signal is received:

1. Stop — this tells the debugger whether to stop the program execution (and return control) when the program receives this signal.

2. Print — this tells the debugger whether to display the received signal.

3. Pass — this tells the debugger whether to pass the signal to the program.

#### Changing behaviour on signals

To change the way debugger behaves when a particular signal is received, select the signal in the list. Right-click to open the Operation menu. Choose Modify Signal. This will open a dialog. Set the three behaviours and click OK to commit the change.

##### Modify Kernel Signal dialog

Modify Kernel Signal dialog

#### Sending the signal to the program

To explicitly sent the signal to the program being debugged, select the signal in the given list. Right-click to open the Operation menu. Choose the menu item Send to process. A confirmation dialog will appear. Click OK to confirm and send the signal to the program.

#### Updating the signal list

Choose the menu item Update from the Operation menu (right-click in the Kernal Signals window to open) to refresh the Kernel Signals window.

### CPU registers

It is possible to examine the contents of the internal registers of the CPU (microprocessor). Choose the menu item View Registers. A window listing all of the available registers in the microprocessor and their corrosponding contents will appear.

#### CPU Registers window

CPU Registers window

### Dynamically loaded Libraries

To obtain a list of the dynamic libraries used by the program, choose the menu item View Shared Libraries. This will bring open a window which will list all the shared libraries the program has loaded and their locations in the memory. It also shows whether the symbol table is loaded or not (Yes/No).

#### Shared Libraries window

Shared Libraries window

### Interrupting the program

While the program is running and has control, no debugging tasks can be performed. To obtain control while the program is running, choose the menu item Debug Interrupt Program. This will interrupt the program and return control to the debugger.

For interruption to work properly, set the debugger behaviour for the interrupt signal (SIGINT) to the value [ Stop:Yes, Print:Yes, Pass:No ]. This is the default value.