Intel® Debugger (IDB) Manual

Legal Notices

Table of Contents


About This Manual

What Capabilities Does The Debugger Provide?

The debugger provides a command-line interface.

The debugger provides extensive support for debugging programs written in C, C++, and Fortran (77 and 90).

Obtaining an Install Kit

Kits, manuals, and answers to the frequently asked questions (FAQs) are available from the following sources:

  • TBD

Audience

This manual is intended for programmers who have a basic understanding of one of the programming languages that Intel IDB supports (C, C++, Fortran).

Organization

This manual is organized as follows:

  • Part I contains a quick introduction to the debugger.
    • Chapter 1 contains all the information you need to make simple use of the debugger.
  • Part II contains most of the information you need to make expert use of the debugger.
    • Chapter 2 describes preparing your program for debugging.
    • Chapter 3 describes starting the debugger.
    • Chapter 4 describes giving commands to the debugger.
    • Chapter 5 describes context for executing commands.
    • Chapter 6 describes running your program under debugger control.
    • Chapter 7 describes locating the site of the problem.
    • Chapter 8 describes how to examine the code, the data, and previously obtained information
    • Chapter 9 describes modifying the process.
    • Chapter 10 describes continuing execution of the process.
    • Chapter 11 describes snapshots as an undo mechanism.
    • Chapter 13 describes support limitations.
  • Part III contains advanced reference information.
  • The appendixes contain the following information:

Related Documentation

The following documents contain related information:

  • Man pages for the various compilers

Reporting Problems

TBD.

What to Report

Please provide the following information when you enter your problem report. Doing so will make it easier for us to reproduce and analyze your problem. If you do not provide this information, we may have to ask you for it.

  • A description of the problem. The clearer and more detailed the description, the easier it will be for us to reproduce and analyze your problem.

  • A transcript of the debugger output. You can obtain this by using the record io debugger command or by using the script(1) system command.

  • Operating system and version information. The output of uname -a is best.

  • Version information. The version number is in the welcome banner that displays when you invoke the debugger. You can also obtain the version number by invoking the debugger with the idb -V command.

  • The smallest source code example possible; build instructions (a Makefile is preferable); source languages, compiler versions, and so forth; and a pointer to a tar file containing sources or binaries that reproduce the problem. To obtain compiler versions, you can use the -V option if your compiler supports it (see the reference page for your compiler).

  • The exact debugger commands that cause the problem to occur.

  • Any other information that you think would be helpful.

The debugger development team can use ftp to fetch sources and executables if you can place them in an anonymous FTP area. If not, you may be asked to use another method.

Conventions

The following conventions are used in this manual:

Convention Meaning
% A percent sign represents the C shell system prompt.
# A pound sign represents the default superuser prompt.
UPPERCASE
lowercase
The operating system differentiates between lowercase and uppercase characters. On the operating system level, you must type examples, syntax descriptions, function definitions, and literal strings that appear in text exactly as shown.
Ctrl/C This symbol indicates that you must press the Ctrl key while you simultaneously press another key (in this case, C).
monospaced text This typeface indicates a routine, partition, pathname, directory, file, or non-terminal name. This typeface is also used in interactive examples.
monospaced bold text In interactive examples, this typeface indicates input that you enter. In syntax statements and text, this typeface indicates the exact name of a command or keyword.
monospaced italic text Monospaced italic type indicates variable values, place holders, and function argument names.
In syntax definitions, monospaced italic text indicates non-terminal names. When a non-terminal name consists of more than one word, the words are joined using the underscore (_), for example, breakpoint_command.
italic text Italic type indicates book names or emphasized terms.
foo_bar
    : item1
    | item2
    | item3
A colon (:) starts the syntax definition of a non-terminal name (in this example, foo_bar. Vertical bars (|) separating items that appear in syntax definitions indicate that you choose one item from among those listed.
[ ] In syntax definitions, brackets indicate items that are optional.
option ;...
option ,...
option  ...
A set of three horizontal ellipses indicates that you can enter additional parameters, options, or values. A semicolon, comma, or space preceding the ellipses indicates successive items must be separated by semicolons, commas, or spaces.
idb(1) Cross-references to online reference pages include the appropriate section number in parentheses. For example, idb(1) indicates that you can find the material on the idb command in Section 1 of the reference pages. The man command % man 1 idb shows the reference page for this command.

Part I
A Quick Introduction to Using Intel Debugger

Part I provides all the information you need to make simple use of the debugger.

Chapter 1 — Overview

Intel IDB supports DBX and GDB modes. In the GDB mode, Intel IDB operates like the GNU* Debugger, GDB*. See the Starting the Debugger section to get to know how to launch the debugger in the required mode.

You look for a bug by doing the following:

  1. Find a repeatable reproducer of the bug - the simpler the reproducer is, the simpler the following steps will be to do.
  2. Prepare your program for debugging.
  3. Start the debugger.
  4. Give commands to the debugger.
    • Command the debugger to either
      • Prepare to create a process running the program, or
      • Attach to and interrupt a process that you created using normal operating system specific methods.
    • Command the debugger to create breakpoints that will pause the process as close as possible to where the bug happened.
    • If you are using the debugger to create the process, tell it to create the process now.
  5. Do whatever it takes to reproduce the bug, so that the breakpoints will stop the process close to where the bug has caused something detectably wrong to happen.
  6. Look around to determine the location of the bug:
    • If the bug is in code where the debugger has stopped the process, exit the debugger and fix the bug.
    • If the bug has not happened yet, remove any breakpoints that are triggering too often, create other breakpoints that work better at locating the problem, and continue the process.
    • If the bug has already occurred, take the same steps of creating breakpoints and so on, except with the process running backward. Unfortunately, reverse execution is a difficult problem (how do you un-erase that disk?) so the compilers and the debugger do not support it. Instead, you have to rerun from an earlier position (a snapshot if you made one, or else the beginning of the program), first creating breakpoints that stop the process sooner.

1.1 Preparing a Program for Debugging

Compile and link your program using the -g switch.

% icc -g tmp.c

For more details see section 2.2.

1.2 Starting the Debugger

Before you start the debugger, make sure that you have correctly set the size information for your terminal; otherwise, the debugger's command line editing support may act unpredictably. For example, if your terminal is 47x80, you may need to set the following:

% stty rows 47 ; setenv LINES 47
% stty cols 80 ; setenv COLS 80

There are four basic alternatives for running the debugger on a process (see examples below):

  1. Have the debugger create the process using the shell command line to identify the executable to run. (dbx) (gdb)
  2. Have the debugger create the process using the debugger commands to identify the executable to run. (dbx) (gdb)
  3. Have the debugger attach to a running process using the shell command line to identify the process and the executable file that process is running. (dbx) (gdb)
  4. Have the debugger attach to a running process using the debugger commands to identify the process and the executable file that process is running. (dbx) (gdb)
DBX Mode

Intel IDB starts operating in DBX mode by default, so you do not have to specify any special options in the shell command line.

Examples:

  1. Creating the process using the shell command line.

    % idb a.out
    Linux Application Debugger for ..., Version ..., Build ...
    ------------------
    object file name: a.out
    Reading symbolic information ...done
    (idb) stop in main
    [#1: stop in int main(void) ]
    (idb) run
  2. Creating the process using the debugger commands.

    % idb
    Linux Application Debugger for ..., Version ..., Build ...
    ------------------
    (idb) load a.out
    Reading symbolic information ...done
    (idb) stop in main
    [#1: stop in int main(void) ]
    (idb) run
  3. Ataching to a running process using shell command line.

    % ./a.out &
    [1] 27859
    % jobs
    [1]+  Running                 ./a.out &
    % idb a.out -pid 27859
    Linux Application Debugger for ..., Version ..., Build ...
    ------------------
    Reading symbolic information ...done
    Attached to process id 27859  ....

    Press Ctrl/C to interrupt the process.

  4. Attaching to the process using the debugger commands.

    % ./a.out &
    [1] 27859
    % jobs
    [1]+  Running                 ./a.out &
    % idb
    Linux Application Debugger for ..., Version ..., Build ...
    ------------------
    (idb) attach 27859 a.out
    Reading symbolic information ...done
    Attached to process id 27859  ....

    Press Ctrl/C to interrupt the process.

GDB Mode

To start the debugger in the GDB mode, specify -gdb option in the shell command line.

Examples:

  1. Creating the process using the shell command line.

    % idb -gdb a.out
    Linux Application Debugger for ..., Version ..., Build ...
    ------------------
    object file name: a.out
    Reading symbols from a.out...done
    (idb) break main
    Breakpoint 1 at 0x80484f6: file qwerty.c, line 9.
    (idb) run
    
  2. Creating the process using the debugger commands.

    % idb -gdb
    Linux Application Debugger for ..., Version ..., Build ...
    -------------------
    (idb) file a.out
    Reading symbols from a.out...done.
    (idb) break main
    Breakpoint 1 at 0x80484f6: file qwerty.c, line 9.
    (idb) run
  3. Ataching to a running process using shell command line.

    % ./a.out &
    [1] 27859
    % jobs
    [1]+  Running                 ./a.out &
    % idb -gdb a.out -pid 27859
    Linux Application Debugger for ..., Version ..., Build ...
    ------------------
    object file name: a.out
    Reading symbols from a.out...done.
    Attached to process id 27859  ....

    Press Ctrl/C to interrupt the process.

  4. Attaching to the process using the debugger commands.

    % ./a.out &
    [1] 27859
    % jobs
    [1]+  Running                 ./a.out &
    % idb -gdb
    Linux Application Debugger for ..., Version ..., Build ...
    (idb) file a.out
    Reading symbols from a.out...done.
    (idb) attach 27859
    Attached to process id 27859  ....

    Press Ctrl/C to interrupt the process.

Note: In the case of Fortran, routine main at which your program stops is not your main program unit. Rather, it is a main routine supplied by the Fortran system that performs some initialization and then calls your code. Just step forward using the step command a couple of times (probably twice) and you will soon step into your code.

1.3 Entering Debugger Commands

The debugger issues a prompt when it is ready for the next command from the terminal:

(idb) you type here

When you enter commands, you use the left and right arrow keys to move within the line and the up and down arrow keys to recall previous commands for editing. When you finish entering a command, press the Enter key to submit the completed line to the debugger for processing.

You can continue a line by ending the line to be continued with a backslash (\) character.

On a blank line, press the Enter key to re-execute the most-recent valid command.

Following are two very useful commands available in both modes:

(idb) help
(idb) quit

1.4 Scripting or Repeating Previous Commands

DBX Mode

To execute debugger commands from a script, use the source command as follows:

(idb) source filename

The source command causes the debugger to read and execute debugger commands from filename.

GDB Mode

The source command is not yet available in the GDB mode.

1.5 Context for Executing Commands

Although the debugger supports debugging multiple processes, it operates only on a single process at a time, known as the current process.

Processes contain one or more threads of execution. The threads execute functions. Functions are sequences of instructions that come from source lines within source files.

As you enter debugger commands to manipulate your process, it would be very tedious to have to repeatedly specify which thread, source file, and so on you wish the command to be applied to. To prevent this, each time the debugger stops the process, it re-establishes a static context and a dynamic context for your commands. The components of the static context are independent of this run of your program; the components of the dynamic context are dependent on this run.

  • The static context consists of the following:
    • A current program
    • A current file
    • A current line
  • The dynamic context consists of the following:
    • A current call frame
    • A current thread
    • The particular thread executing the event that caused the debugger to gain control of the process

You can change most of these individually to point to other instances, as described in the relevant portions of this manual, and the debugger will modify the rest of the static and dynamic context to keep the various components consistent.

1.6 Running a Program Under Debugger Control

As was shown previously, you can tell the debugger to create a process or to attach to an existing process.

After you specify the program (either on the shell command line or by using the load(dbx) or file(gdb) command), but before you have requested the debugger to create the process, you can still do things that seem to require a running process; for example, you can create breakpoints and examine sources. Any breakpoints that you create will be inserted into the process as soon as possible after it executes your program.

To have the debugger create a process (rather than attach to an existing process), you request it to run, specifying, if necessary, any arguments and input and output redirection as follows:

% idb a.out
Linux Application Debugger for ..., Version ..., Build ...
...
(idb) run

or

(idb) run arguments

or

(idb) run arguments > output-file

or

(idb) run arguments < input-file > output-file

The result of using any of the preceding command variations is similar to having attached to a running process.

DBX Mode

The rerun command repeats the previous run command with the same arguments and file redirection.

GDB Mode

The run command without arguments repeats the previous run (with the same arguments, input and output redirections).

r is a shortcut for the run command.

1.7 Pausing the Process at the Problem

Following are the four most common ways to pause a process:

  1. Press Ctrl/C. (dbx) (gdb)
  2. Wait until the process raises some signal. It will do this when there is an arithmetic exception, an illegal instruction, or an unsatisfiable memory access, such as an attempt to write to memory for which protection is set to read-only. (dbx) (gdb)
  3. Create a breakpoint before you run or continue the process. (dbx) (gdb)
  4. Create a watchpoint before you run or continue the process. (dbx) (gdb)
DBX Mode
  1. Pressing Ctrl/C.

    (idb) run
    ^C
    Interrupt (for process)
    
    Stopping process localhost:27903 (a.out).
    Thread received signal INT
    stopped at [int main(int):5 0x120001138]
          5     while (argc < 2 && i < 10000000)
    
  2. Waiting until the process raises some signal.

    (idb) run
    Thread received signal SEGV
    stopped at [void buggy(char*, char*):13 0x8048b79]
         13         output[k] = input[k];
    
  3. Creating a breakpoint before running or continuing the process.

    (idb) stop in main
    [#1: stop in int main(void) ]
    (idb) run
    [1] stopped at [int main(void):182 0x1200023f8]
        182     List<Node> nodeList;
    
  4. Creating a watchpoint before running or continuing the process.

    (idb) watch variable nodeList._firstNode write
    [#2: watch variable nodeList._firstNode write ]
    (idb) cont
    [2] Address 0xbffff0fc was accessed at:
    List<Node>::List(void): x_list.cxx
     [line 121, 0x8057edd]	_ZN4ListI4NodeEC1Ev(...)+0xf:         movl     $0x0, (%eax)
    	0xbffff0fc: Old value = 0x080b0ba4
    	0xbffff0fc: New value = 0x00000000
    [2] stopped at [List<Node>::List(void):123 0x8057ee3]
        123 }
    
GDB Mode
  1. Pressing Ctrl/C.

    (idb) run
    ^C
    Interrupt (for process)
    
    Stopping process localhost:27903 (a.out).
    Thread received signal INT
    main(argc=1) at x_whatHappensOnControlC.cxx: 5
    5     while (argc < 2 && i < 10000000)
    
  2. Waiting until the process raises some signal.

    (idb) run
    Starting program: /usr/examples/x_segv
    Thread received signal SEGV
    buggy (input=0xbffff2f1 "/usr/examples/x_segv", output=0x0) at x_segv.cxx:13
    13	        output[k] = input[k];
    
  3. Creating a breakpoint before running or continuing the process.

    (idb) break main
    Breakpoint 1 at 0x8049f70: file x_list.cxx, line 182.
    (idb) run
    Starting program: /usr/examples/x_list
    
    Breakpoint 1, main () at x_list.cxx:182
    182	    List<Node> nodeList;
    
  4. Creating a watchpoint before running or continuing the process.

    (idb) watch nodeList._firstNode
    Hardware watchpoint 2: nodeList._firstNode
    (idb) continue
    Continuing.
    Old value = 0x80c0c044
    New value = 0x00000000
    
    Breakpoint 2, List<Node>::List (this=<no value>) at x_list.cxx:123
    123	}
    

1.8 Examining the Paused Process

This section describes how to examine components of the paused process.

1.8.1 Looking at the Source Files

You can perform the following operations on source files:

  • Tell the debugger where your sources are, if it cannot find them.
  • Find out the name of the current source file.
  • Switch to a different source file.
  • List lines in a source file.
  • Search within a source file.
DBX Mode

Following is an example that shows listing lines and using the / command to search for a string:

(idb) file
x_list.cxx
(idb) list 180: 10
    180 main()
    181 {
    182     List<Node> nodeList;
    183
    184     // add entries to list
    185     //
>   186     IntNode* newNode = new IntNode(1);
    187     nodeList.append(newNode);
    188
    189     CompoundNode* cNode = new CompoundNode(12.345, 2);
(idb) /CompoundNode
    192     CompoundNode* cNode1 = new CompoundNode(3.1415, 7);

Aliases are shorthand forms of longer commands. This example shows using the W alias, which lists up to 20 lines around the current line. Note that a right bracket (>) marks the current line.

(idb) alias W 
W       list $curline - 10:20
(idb) W 
    176
    177
    178 //  The driver for this test
    179 //
    180 main()
    181 {
    182     List<Node> nodeList;
    183
    184     // add entries to list
    185     //
>   186     IntNode* newNode = new IntNode(1);
    187     nodeList.append(newNode);
    188
    189     CompoundNode* cNode = new CompoundNode(12.345, 2);
    190     nodeList.append(cNode);
    191
    192     nodeList.append(new IntNode(3));
    193
    194     IntNode* newNode2 = new IntNode(4);
    195     nodeList.append(newNode2);
GDB Mode

Use info source, info line, and list comands for looking at source files:

(idb) info source
Current source file is x_list.cxx
(idb) list 180,10
180	main()
181	{
182	    List<Node> nodeList;
183
184	    // add entries to list
185	    //
186	    IntNode* newNode = new IntNode(1);
187	    nodeList.append(newNode);
188
189	    CompoundNode* cNode = new CompoundNode(12.345, 2);
(idb) forward-search CompoundNode
192	    CompoundNode* cNode1 = new CompoundNode(3.1415, 7);
1.8.2 Looking at the Threads

In a multithreaded application, you can obtain information about the thread that stopped or about all the threads, and you can then change the context to look more closely at a different thread. Note that a right bracket (>) marks the current thread. And the asterisk (*) marks the thread with return status.

DBX Mode
(idb) thread
  Thread Name                      State           Substate    Policy       Pri
  ------ ------------------------- --------------- ----------- ------------ ---
>*     1 default thread            running VP 3                SCHED_OTHER  19

(idb) show thread
  Thread Name                      State           Substate    Policy       Pri
  ------ ------------------------- --------------- ----------- ------------ ---
>*     1 default thread            running VP 3                SCHED_OTHER  19
      -1 manager thread            blk SCS                     SCHED_RR     19
      -2 null thread for slot 0    running VP 1                null thread  -1
      -3 null thread for slot 1    ready VP 3                  null thread  -1
      -4 null thread for slot 2    new             new         null thread  -1
      -5 null thread for slot 3    new             new         null thread  -1
       2 threads(0x140000798)      blocked         cond 3      SCHED_OTHER  19
       3 threads+8(0x1400007a0)    blocked         cond 3      SCHED_OTHER  19
       4 threads+16(0x1400007a8)   blocked         cond 3      SCHED_OTHER  19
       5 threads+24(0x1400007b0)   blocked         cond 3      SCHED_OTHER  19
       6 threads+32(0x1400007b8)   blocked         cond 3      SCHED_OTHER  19

You can select any thread to be the focus of commands that show things. For example:

(idb) thread 2
  Thread Name                      State           Substate    Policy       Pri
  ------ ------------------------- --------------- ----------- ------------ ---
>      2 threads(0x140000798)      blocked         cond 3      SCHED_OTHER  19

GDB Mode
Within the GDB mode, you can have a look at a particular thread by specifying the internal debugger thread number. The asterisk (*) marks the current thread. Or you can observe all threads while your program is running:
(idb) info threads
  0 Thread 1024 (LWP 19513)  0x804f8f6 in __sigsuspend from /tmp/pthread_manythreads
  1 Thread 2049 (LWP 19514)  0x805a42a in __clone from /tmp/pthread_manythreads
* 2 Thread 1026 (LWP 19515)  0x804f8f6 in __sigsuspend from /tmp/pthread_manythreads
  3 Thread 2051 (LWP 19516)  0x804f8f6 in __sigsuspend from /tmp/pthread_manythreads
  4 Thread 3076 (LWP 19517)  0x804f8f6 in __sigsuspend from /tmp/pthread_manythreads
  5 Thread 4101 (LWP 19518)  0x8048288 in prime_search at pthread_manythreads.c:79
This command provides the following information about known threads:
  • Number: Number of a thread from the debugger point of view. This number is not used for numbering again if a thread dies.
  • Thread TID: Thread identifier. TID is an identifier (non duplicated) assigned to each thread inside the thread library.
  • LWP PID: Light weight process identifier (non duplicated) assigned by the Linux kernel to each process in the system. LinuxThreads architecturally has PID for each thread in a multithread application.
  • Location: Location where the thread stopped. Its output is very similar to the backtrace location field.

You can select any thread to be the focus of commands that show things. For example:

(idb) thread 2
* 2 Thread 1026 (LWP 19515)  0x804f8f6 in __sigsuspend from /tmp/pthread_manythreads
1.8.3 Looking at the Call Stack

You can examine the call stack of any thread. Even if you are not using threads explicitly, your process will have one thread running your code. You can move up and down the stack, and examine the source being executed at each call.

DBX Mode
(idb) where 4
>0  0x804a519 in ((Node*)0x80c38f0)->Node::Node() "x_list.cxx":79
#1  0x804a568 in ((IntNode*)0x80c38f0)->IntNode::IntNode(data=2) "x_list.cxx":88
#2  0x804a61f in ((CompoundNode*)0x80c38f0)->CompoundNode::CompoundNode(fdata=12.3450003, idata=2) "x_list.cxx":103
#3  0x804a09e in main() "x_list.cxx":189
(idb) up 2
>2  0x804a61f in ((CompoundNode*)0x80c38f0)->CompoundNode::CompoundNode(fdata=12.3450003, idata=2) "x_list.cxx":103
    103     IntNode(idata),
(idb) list $curline - 10: 20
     93     cout << " type is integer, value is ";
     94     cout << _data << endl;
     95 }
     96
     97
     98 //=============================================================================
     99 // CompoundNode definition
    100 //
    101 CompoundNode::CompoundNode(float fdata, int idata)
    102   :
>   103     IntNode(idata),
    104     _fdata (fdata)
    105 {
    106 }
    107 void CompoundNode::printNodeData() const
    108 {
    109     cout << " type is compound, value is ";
    110     cout << _fdata << endl;
    111     cout << "       parent ";
    112     IntNode::printNodeData();
(idb) down 1
>1  0x804a568 in ((IntNode*)0x80c38f0)->IntNode::IntNode(data=2) "x_list.cxx":88
     88 IntNode::IntNode(int data) : _data(data)
GDB Mode
(idb) backtrace 4
>0  0x804a519   in ((Node*)(class Node *) 0x80c38f0)->Node::Node(this=(class Node *) 0x80c38f0) "x_list.cxx":79
#1  0x804a568   in ((IntNode*)(class IntNode *) 0x80c38f0)->IntNode::IntNode(this=(class IntNode *) 0x80c38f0, data=2) "x_list.cxx":88
#2  0x804a61f   in ((CompoundNode*)(class CompoundNode *) 0x80c38f0)->CompoundNode::CompoundNode(this=(class CompoundNode *) 0x80c38f0, fdata=12.345, idata=2) "x_list.cxx":103
#3  0x804a09e   in main() "x_list.cxx":189
(idb) up 2
>2  0x804a61f   in ((CompoundNode*)(class CompoundNode *) 0x80c38f0)->CompoundNode::CompoundNode(this=(class CompoundNode *) 0x80c38f0, fdata=12.345, idata=2) "x_list.cxx":103
103	    IntNode(idata),
(idb) list 93,112
93	    cout << " type is integer, value is ";
94	    cout << _data << endl;
95	}
96
97
98	//=============================================================================
99	// CompoundNode definition
100	//
101	CompoundNode::CompoundNode(float fdata, int idata)
102	  :
103	    IntNode(idata),
104	    _fdata (fdata)
105	{
106	}
107	void CompoundNode::printNodeData() const
108	{
109	    cout << " type is compound, value is ";
110	    cout << _fdata << endl;
111	    cout << "       parent ";
112	    IntNode::printNodeData();
(idb) down 1
>1  0x804a568   in ((IntNode*)(class IntNode *) 0x80c38f0)->IntNode::IntNode(this=(class IntNode *) 0x80c38f0, data=2) "x_list.cxx":88
88	IntNode::IntNode(int data) : _data(data)
1.8.4 Looking at the Data

You can look at variables and evaluate expressions involving them by using the print command.

DBX Mode
(idb) print fdata
12.3450003
(idb) print idata
2
(idb) print idata + 59
61
(idb) print this
0x80c3670
(idb) print *this
class CompoundNode {
  _fdata = 0;
  _data = 0;                      // class IntNode
  _nextNode = 0x0;                // class IntNode::Node
}
GDB Mode
(idb) print fdata
$2 = 12.345
(idb) print idata
$3 = 2
(idb) print idata + 59
$4 = 61
(idb) print this
$5 = (class CompoundNode *) 0x80c3670
(idb) print *this
$6 = {<IntNode> = {<Node> = {_nextNode = 0x0}, _data = 0}, _fdata = 0}

The p is a shortcut, and the inspect command is a synonym for the print command.

1.8.5 Looking at the Signal State

The debugger shows you the signal that stopped the thread.

DBX Mode
(idb) run
Thread received signal SEGV
stopped at [void buggy(char*, char*):13 0x8048b79]
     13         output[k] = input[k];

Information: idb allows you to restart the execution of your program
from saved positions. Enter "help snapshot" for details.

GDB Mode
(idb) run
Starting program: /usr/examples/x_segv
Thread received signal SEGV
buggy (input=0xbffff2f1 "/usr/examples/x_segv", output=0x0) at x_segv.cxx:13
13	        output[k] = input[k];

Information: idb allows you to restart the execution of your program
from saved positions. Enter "help snapshot" for details.

1.8.6 Looking at the Generated Code

You can print memory as instructions or as data.

DBX Mode

In the following example, the wi alias lists machine instructions before and after the current instruction. Note that the asterisk (*) marks the current instruction.

(idb) alias wi 
wi	($curpc - 20)/10 i
(idb) wi
CompoundNode::CompoundNode(float, int): x_list.cxx
 [line 105, 0x120002348]	cpys	$f17,$f17,$f0
 [line 105, 0x12000234c]	bis	r31, r18, r8
 [line 101, 0x120002350]	bis	r31, r19, r16
 [line 101, 0x120002354]	bis	r31, r8, r17
 [line 101, 0x120002358]	bsr	r26, IntNode::IntNode(int)
*[line 101, 0x12000235c]	ldq	r18, -32712(gp)
 [line 101, 0x120002360]	lda	r18, 48(r18)
 [line 101, 0x120002364]	stq	r18, 8(r19)
 [line 101, 0x120002368]	sts	$f0, 24(r19)
 [line 106, 0x12000236c]	bis	r31, r19, r0
(idb) $pc/10x 
0x12000235c: 0x8038 0xa65d 0x0030 0x2252 0x0008 0xb653 0x0018 0x9813
0x12000236c: 0x0400 0x47f3
(idb) $pc/6xx 
0x12000235c: 0xa65d8038 0x22520030 0xb6530008 0x98130018
0x12000236c: 0x47f30400 0x47f5041a
(idb) $pc/2X 
0x12000235c: 0x22520030a65d8038 0x98130018b6530008
GDB Mode

Use the x command to dump memory in various formats. The disassemble command also provides disassembling capability.

(idb) x /10i $pc
Dump of assembler code for function CompoundNode::CompoundNode(class CompoundNode * const, float, int):
0x804a60e <_ZN12CompoundNodeC1Efi(...)+24>:         addl     $-8, %esp
0x804a611 <_ZN12CompoundNodeC1Efi(...)+27>:         movl     -12(%ebp), %eax
0x804a614 <_ZN12CompoundNodeC1Efi(...)+30>:         movl     %eax, (%esp)
0x804a617 <_ZN12CompoundNodeC1Efi(...)+33>:         movl     -4(%ebp), %eax
0x804a61a <_ZN12CompoundNodeC1Efi(...)+36>:         movl     %eax, 0x4(%esp)
0x804a61e <_ZN12CompoundNodeC1Efi(...)+40>:         call     0x804a54e <_ZN7IntNodeC1Ei(...)>
0x804a623 <_ZN12CompoundNodeC1Efi(...)+45>:         addl     $0x8, %esp
0x804a626 <_ZN12CompoundNodeC1Efi(...)+48>:         movl     -12(%ebp), %eax
0x804a629 <_ZN12CompoundNodeC1Efi(...)+51>:         movl     $0x8087834, (%eax)
0x804a62f <_ZN12CompoundNodeC1Efi(...)+57>:         movl     -12(%ebp), %eax
(idb) x /10x $pc
0x804a60e: 0xc483 0x8bf8 0xf445 0x0489 0x8b24 0xfc45 0x4489 0x0424
0x804a61e: 0x2be8 0xffff
(idb) x /6w $pc
0x804a60e: 0x8bf8c483 0x0489f445 0xfc458b24 0x04244489
0x804a61e: 0xffff2be8 0x08c483ff
(idb) x /2g $pc
0x804a60e: 0x000000008bf8c483 0x00000000fc458b24

To examine individual registers, use the print command with name of register prepended with the dollar sign ($). Commands showing all (or subset of) the registers, are specific for the mode, see examples below.

DBX Mode

To look at all the registers, use the printregs command. For example:

(idb) print $eax
134942544
(idb) printx $eax
0x80b0f50
(idb) printregs
$eax           0x80b0f50	134942544
$ecx           0xa1	161
$edx           0x0	0
$ebx           0x401ae9e4	1075505636
$esp [$sp]     0xbffff53c	-1073744580
$ebp           0xbffff55c	-1073744548
$esi           0x40016b64	1073834852
$edi           0xbffff6bc	-1073744196
$eip [$pc]     0x804a628	134522408
$eflags        0x287	647
$cs            0x23	35
$ss            0x2b	43
$ds            0x2b	43
$es            0x2b	43
$fs            0x0	0
$gs            0x0	0
$orig_eax      0xffffffff	-1
$fctrl         0x37f	895
$fstat         0x0	0
$ftag          0x0	0
$fiseg         0x23	35
$fioff         0x804a619	134522393
$foseg         0x2b	43
$fooff         0xbffff554	-1073744556
$fop           0x0	0
$f0            0x00000000000000000000000000000000 0
$f1            0x0000000000003ffdf13a8dc3008792a0 0.47115
$f2            0x00000000000000000000000000000000 0
$f3            0x00000000000000000000000000000000 0
$f4            0x00000000000000000000000000000000 0
$f5            0x00000000000000000000000000000000 0
$f6            0x0000000000003ffb9700000000000000 0.0737305
$f7            0x0000000000004002c5851f0000000000 12.345
$xmm0          0x00000000000000000000000000000000
$xmm1          0x00000000000000000000000000000000
$xmm2          0x00000000000000000000000000000000
$xmm3          0x00000000000000000000000000000000
$xmm4          0x00000000000000000000000000000000
$xmm5          0x00000000000000000000000000000000
$xmm6          0x00000000000000000000000000000000
$xmm7          0x00000000000000000000000000000000
$mxcsr         0x1f80	8064
$vfp           0xbffff55c	0xbffff55c
GDB Mode

Following commands allow you to examine sets of registers:

  • info registers

For example:

(idb) print $eax
$11 = 134942544
(idb) print $eax
$12 = 0x80b0f50
(idb) info registers
$eax           0x80b0f50	134942544
$ecx           0xa1	161
$edx           0x0	0
$ebx           0x401ae9e4	1075505636
$esp [$sp]     0xbffff53c	-1073744580
$ebp           0xbffff55c	-1073744548
$esi           0x40016b64	1073834852
$edi           0xbffff6bc	-1073744196
$eip [$pc]     0x804a628	134522408
$eflags        0x287	647
$cs            0x23	35
$ss            0x2b	43
$ds            0x2b	43
$es            0x2b	43
$fs            0x0	0
$gs            0x0	0
$orig_eax      0xffffffff	-1
$fctrl         0x37f	895
$fstat         0x0	0
$ftag          0x0	0
$fiseg         0x23	35
$fioff         0x804a619	134522393
$foseg         0x2b	43
$fooff         0xbffff554	-1073744556
$fop           0x0	0
$f0            0x00000000000000000000000000000000 0
$f1            0x0000000000003ffdf13a8dc3008792a0 0.47115
$f2            0x00000000000000000000000000000000 0
$f3            0x00000000000000000000000000000000 0
$f4            0x00000000000000000000000000000000 0
$f5            0x00000000000000000000000000000000 0
$f6            0x0000000000003ffcdcd8000000000000 0.215668
$f7            0x0000000000004002c5851f0000000000 12.345
$xmm0          0x00000000000000000000000000000000
$xmm1          0x00000000000000000000000000000000
$xmm2          0x00000000000000000000000000000000
$xmm3          0x00000000000000000000000000000000
$xmm4          0x00000000000000000000000000000000
$xmm5          0x00000000000000000000000000000000
$xmm6          0x00000000000000000000000000000000
$xmm7          0x00000000000000000000000000000000
$mxcsr         0x1f80	8064
$vfp           0xbffff55c	0xbffff55c

1.9 Continuing Execution of the Process

After you are satisfied that you understand what is going on, you can move the process forward and see what happens. The following table shows the aliases and commands you can use to do this.

Desired Behavior Alias Command Can Take Repeat Count
Continue until another interesting thing happens c cont Yes*
Single step by line, but step over calls n next Yes
Single step to a new line, stepping into calls s step Yes
Continue until control returns to the caller None return(dbx), finish(gdb) No
Single step by instruction, over calls ni nexti Yes
Single step by instruction, into calls si stepi Yes

* In GDB mode repeat count has a differen meaning for the cont command. For the other commands repat count has the same meaning in both modes.

The following examples demonstrate stepping through lines of source code (dbx) (gdb) and stepping at the instruction level (dbx) (gdb).

DBX Mode

Stepping through lines of source code:

(idb) list $curline - 10: 20
    172
    173     if (i == 1) cout << "The list is empty ";
    174     cout << endl << endl;
    175 }
    176
    177
    178 //  The driver for this test
    179 //
    180 main()
    181 {
>   182     List<Node> nodeList;
    183
    184     // add entries to list
    185     //
    186     IntNode* newNode = new IntNode(1);
    187     nodeList.append(newNode);
    188
    189     CompoundNode* cNode = new CompoundNode(12.345, 2);
    190     nodeList.append(cNode);
    191
(idb) next
stopped at [int main(void):186 0x8049f82]
    186     IntNode* newNode = new IntNode(1);
(idb) next 10
stopped at [int main(void):201 0x804a3e0]
    201     nodeList.append(cNode2);
(idb) step
stopped at [void List<Node>::append(struct Node* const):148 0x805800a]
    148     if (!_firstNode)
(idb) list $curline - 2: 6
    146 {
    147
>   148     if (!_firstNode)
    149         _firstNode = node;
    150     else {
    151         Node* currentNode = _firstNode;
(idb) step
stopped at [void List<Node>::append(struct Node* const):151 0x805801d]
    151         Node* currentNode = _firstNode;
(idb) list $curline - 2: 5
    149         _firstNode = node;
    150     else {
>   151         Node* currentNode = _firstNode;
    152         while (currentNode->getNextNode())
    153             currentNode = currentNode->getNextNode();
(idb) return
stopped at [int main(void):201 0x804a3f8]
    201     nodeList.append(cNode2);
(idb) step
stopped at [int main(void):203 0x804a3fb]
    203     nodeList.print();
(idb) step
stopped at [void List<Node>::print(void):162 0x8058092]
    162     Node* currentNode = _firstNode;
(idb) list $curline: 8
>   162     Node* currentNode = _firstNode;
    163
    164     int i = 1;
    165     cout << "The list is: " << endl;
    166     while (currentNode) {
    167         cout << "Node " << i ;
    168         currentNode->printNodeData();
    169 	currentNode = currentNode->getNextNode();
(idb) step 2
stopped at [void List<Node>::print(void):165 0x80580a1]
    165     cout << "The list is: " << endl;

Stepping at the instruction level:

(idb) $curpc - 20/14i
void List<Node>::print(void): x_list.cxx
 [line 161, 0x805808d]	print+0x1:            movl     %esp, %ebp
 [line 161, 0x805808f]	print+0x3:            subl     $0x1c, %esp
 [line 162, 0x8058092]	print+0x6:            movl     0x8(%ebp), %eax
 [line 162, 0x8058095]	print+0x9:            movl     (%eax), %eax
 [line 162, 0x8058097]	print+0xb:            movl     %eax, -12(%ebp)
 [line 164, 0x805809a]	print+0xe:            movl     $0x1, -8(%ebp)
*[line 165, 0x80580a1]	print+0x15:           addl     $-8, %esp
 [line 165, 0x80580a4]	print+0x18:           movl     $0x80c2f54, (%esp)
 [line 165, 0x80580ab]	print+0x1f:           movl     $0x8085814, 0x4(%esp)
 [line 165, 0x80580b3]	print+0x27:           call     std::operator<<(struct std::basic_ostream<char,std::char_traits<char>>&, const char*)
 [line 165, 0x80580b8]	print+0x2c:           addl     $0x8, %esp
 [line 165, 0x80580bb]	print+0x2f:           movl     %eax, -28(%ebp)
 [line 165, 0x80580be]	print+0x32:           addl     $-8, %esp
 [line 165, 0x80580c1]	print+0x35:           movl     -28(%ebp), %eax
(idb) stepi 2
stopped at [void List<Node>::print(void):165 0x80580ab]	print+0x1f:           movl     $0x8085814, 0x4(%esp)
(idb) nexti
stopped at [void List<Node>::print(void):165 0x80580b3]	print+0x27:           call     std::operator<<(struct std::basic_ostream<char,std::char_traits<char>>&, const char*)
(idb) nexti
stopped at [void List<Node>::print(void):165 0x80580b8]	print+0x2c:           addl     $0x8, %esp
GDB Mode

Stepping through lines of source code:

(idb) list
172
173	    if (i == 1) cout << "The list is empty ";
174	    cout << endl << endl;
175	}
176
177
178	//  The driver for this test
179	//
180	main()
181	{
182	    List<Node> nodeList;
183
184	    // add entries to list
185	    //
186	    IntNode* newNode = new IntNode(1);
187	    nodeList.append(newNode);
188
189	    CompoundNode* cNode = new CompoundNode(12.345, 2);
190	    nodeList.append(cNode);
191
(idb) next
186	    IntNode* newNode = new IntNode(1);
(idb) next 10
201	    nodeList.append(cNode2);
(idb) step
List<Node>::append (this=(struct List<Node> *) 0xbfffed0c, node=(struct Node *) 0x80ba1c0) at x_list.cxx:148
148	    if (!_firstNode)
(idb) list -2,+6
141     }
142
143
144     template <class NODETYPE>
145     void List<NODETYPE>::append(NODETYPE* const node)
146     {
147
(idb) step
151	        Node* currentNode = _firstNode;
(idb) list -2,+5
144     template <class NODETYPE>
145     void List<NODETYPE>::append(NODETYPE* const node)
146     {
147
148         if (!_firstNode)
149             _firstNode = node;
(idb) finish
main () at x_list.cxx:201
201	    nodeList.append(cNode2);
(idb) step
203	    nodeList.print();
(idb) step
List<Node>::print (this=(const struct List<Node> *) 0xbfffed0c) at x_list.cxx:162
162	    Node* currentNode = _firstNode;
(idb) set listsize 8
(idb) list ,8
162	    Node* currentNode = _firstNode;
163
164	    int i = 1;
165	    cout << "The list is: " << endl;
166	    while (currentNode) {
167	        cout << "Node " << i ;
168	        currentNode->printNodeData();
169		currentNode = currentNode->getNextNode();
(idb) step 2
165	    cout << "The list is: " << endl;

Stepping at the instruction level:

(idb) x /14i $pc
Dump of assembler code for function void List<Node>::print(const struct List<Node> * const):
0x804aaf9 <print+21>:	add    $0xfffffff8,%esp
0x804aafc <print+24>:	movl   $0x80b9e14,(%esp,1)
0x804ab03 <print+31>:	movl   $0x8085994,0x4(%esp,1)
0x804ab0b <print+39>:	call   0x80503c4 <std::operator<<>
0x804ab10 <print+44>:	add    $0x8,%esp
0x804ab13 <print+47>:	mov    %eax,0xffffffe4(%ebp)
0x804ab16 <print+50>:	add    $0xfffffff8,%esp
0x804ab19 <print+53>:	mov    0xffffffe4(%ebp),%eax
0x804ab1c <print+56>:	mov    %eax,(%esp,1)
0x804ab1f <print+59>:	movl   $0x8050860,0x4(%esp,1)
0x804ab27 <print+67>:	call   0x804c864 <operator<<>
0x804ab2c <print+72>:	add    $0x8,%esp
0x804ab2f <print+75>:	mov    0xfffffff4(%ebp),%eax
0x804ab32 <print+78>:	test   %eax,%eax
(idb) stepi 2
165	    cout << "The list is: " << endl;
(idb) nexti
165	    cout << "The list is: " << endl;
(idb) nexti
165	    cout << "The list is: " << endl;

1.10 Snapshots as an Undo Mechanism

Often when you move the process forward, you accidentally go too far. For example, you may step over a call that you should have stepped into.

In a program that does not use multiple threads, you can use snapshots to save your state before you step over the call. Then clone that snapshot to position another process just before the call so you can step into it.

The following example shows the stages of a snapshot being used in this way:

  1. The first stage is to build the program and start debugging.

  2. The next stage is to stop the process just before the call and take a snapshot. You can see you are just before the call because the right bracket (>) to the left of the source list shows the line about to be executed.

    (idb) next 2
    stopped at [int main(void):187 0x1200024b8]
        187     nodeList.append(newNode);
    (idb) list $curline - 10: 20
        177
        178 //  The driver for this test
        179 //
        180 main()
        181 {
        182     List<Node> nodeList;
        183
        184     // add entries to list
        185     //
        186     IntNode* newNode = new IntNode(1);
    >   187     nodeList.append(newNode);
        188
        189     CompoundNode* cNode = new CompoundNode(12.345, 2);
        190     nodeList.append(cNode);
        191
        192     CompoundNode* cNode1 = new CompoundNode(3.1415, 7);
        193     nodeList.append(cNode1);
        194
        195     nodeList.append(new IntNode(3));
        196
    (idb) save snapshot
    # 1 saved at 08:41:46 (PID: 1012).
        stopped at [int main(void):187 0x1200024b8]
        187     nodeList.append(newNode);
    
  3. You now step over the call. The execution is now after the call, shown by the right bracket (>) being on the following source line.

    (idb) next
    stopped at [int main(void):189 0x1200024d0]
        189     CompoundNode* cNode = new CompoundNode(12.345, 2);
    (idb) list $curline - 10: 20
        179 //
        180 main()
        181 {
        182     List<Node> nodeList;
        183
        184     // add entries to list
        185     //
        186     IntNode* newNode = new IntNode(1);
        187     nodeList.append(newNode);
        188
    >   189     CompoundNode* cNode = new CompoundNode(12.345, 2);
        190     nodeList.append(cNode);
        191
        192     CompoundNode* cNode1 = new CompoundNode(3.1415, 7);
        193     nodeList.append(cNode1);
        194
        195     nodeList.append(new IntNode(3));
        196
        197     IntNode* newNode2 = new IntNode(4);
        198     nodeList.append(newNode2);
    
  4. Oh, how you wish you hadn't done that! No problem, just clone that snapshot you made.

    (idb) clone snapshot
    Process has exited
    Process 1009 cloned from Snapshot 1.
    # 1 saved at 08:41:46 (PID: 1012).
        stopped at [int main(void):187 0x1200024b8]
        187     nodeList.append(newNode);
    
  5. Now you are in a new process before the call is executed.

    (idb) list $curline - 10: 20
        177
        178 //  The driver for this test
        179 //
        180 main()
        181 {
        182     List<Node> nodeList;
        183
        184     // add entries to list
        185     //
        186     IntNode* newNode = new IntNode(1);
    >   187     nodeList.append(newNode);
        188
        189     CompoundNode* cNode = new CompoundNode(12.345, 2);
        190     nodeList.append(cNode);
        191
        192     CompoundNode* cNode1 = new CompoundNode(3.1415, 7);
        193     nodeList.append(cNode1);
        194
        195     nodeList.append(new IntNode(3));
        196
    

Note: fork() was used by the debugger both to create the snapshot and to clone it.


Part II
A Guide to Using Intel Debugger

Part II provides most of the information needed to make expert use of the debugger.

Some additional details have been moved to Part III: Advanced Topics so they do not hinder the reading of this section.

Chapter 2 — Preparing a Program for Debugging

To facilitate debugging, you can prepare your source code and the compiler and linker environment.

2.1 Preparing Your Source Code

You do not need to make changes to the source code to debug the program. However, you can do the following to make debugging easier:

  • If the source code has functions that can be called to output data structures, you can call them from the debugger; you may want to create such functions.
  • It is a good idea to make the following items part of your source code:
    • An initial stall point if you cannot create the process easily from within the debugger.
    • Assertions sprinkled liberally through the sources to help locate errors early.

2.2 Preparing the Compiler and Linker Environment

Debugging information is put into .o files by compilers. The level and format of information is controlled by compiler options. Use the -g option with the Intel® Compiler, for example:

% icc -g hello.c
...
% icpc -g hello.cpp
...

With GNU* Compiler, GCC*, use -gdwarf-2 option:

% gcc -gdwarf-2 hello.c
...
% g++ -gdwarf-2 hello.cpp
...

See your compiler's reference page for more details.

The debugging information is propagated into the a.out (executable) or .so (shared library) by the ld command. It is removed by the strip command. If you strip your programs, keep the unstripped version to use with the debugger.

The debugging information can cause .o files to be very large, causing long link times, but even so it can also be incomplete.

If you are debugging optimized code, refer to the appropriate compiler documentation for information about various -g switches and their relationship to optimization.

Chapter 3 — Starting the Debugger

You can start the debugger in the following ways:

This chapter also discusses the following topics:

3.1 Starting the Debugger from a Shell

When you invoke the debugger from a shell, you can bring a program or core file under debugger control, or you can attach to a running process.

The following is the shell syntax to invoke the debugger using the idb command:

idb
        [ -c file ]
        [ -gui ] 
        [ -gdb ]
        [ -i file ]
        [ -I directory ]
        [ -interactive ]
        [ -k ]      
        [ -line serial_line ] 
        [ -nosharedobjs ]
        [ -parallel ]  
        [ -pid process_id  ]
        [ -prompt string ]
        [ -remote ]  
        [ -rp remote_debug_protocol ]
        [ -tty terminal_device ] 
        [ -quiet ]
        [ -V ]
        [ executable_file [ core_file ] ]

The following table describes the idb command options and parameters:

Options and Parameters Description
-c file Specifies an initialization command file. The default initialization file is .dbxinit. During startup, the debugger searches for this file in the current directory. If it is not there, the debugger searches your home directory. This file is processed after the target process has been loaded or attached to.
-gdb Start working in the GDB mode.
-i file Specifies a pre-initialization command file. The default pre-initialization file is .idbrc. The debugger searches for this file during startup, first in the current directory and then in your home directory. This file is processed before the debugger has connected to the application being debugged, so that commands such as set $stoponattach = 1 will have taken effect when the connection is made.
-I directory Specifies the directory containing the source code for the target program, in a manner similar to the use command. Use multiple -I options to specify more than one directory. The debugger searches directories in the order in which they were specified on the command line.
-interactive Causes the debugger to act as though stdin is isatty(), regardless of whether or not it is. This flag is sometimes useful when using rsh to run the debugger. Currently, the only effect is to cause the debugger to output the prompt to stdout when it is ready for the next line of input.
-nosharedobjs Prevents the reading of symbol table information for any shared objects loaded when the process executes. Later in the debug session, you can enter the readsharedobj command to read the symbol table information for a specified object.
-pid process_id Specifies the process ID of the process to be debugged.
-prompt string

Specifies a debugger prompt. If the prompt argument contains spaces or special characters, en