A simple debug session

In this example, we'll be debugging our "Hello, world!" program via a TCP/IP link. We go through the following steps:

The buildfile for the image follows these sections.

Configure the target

Let's assume an x86 target using a basic TCP/IP configuration. The following lines (from the sample buildfile below) show what's needed to host the sample session:

io-pkt-v4 -dne2000 -ptcpip if=ndi0:10.0.1.172 &
devc-pty &
[+session] pdebug 8000 &

The above specifies that the host IP address is 10.0.1.172. The pdebug program is configured to use port 8000.

Compile for debugging

We'll be using the x86 compiler. Note the -g option, which makes the compiler include debugging information:

$ qcc -V gcc_ntox86 -g -o hello hello.c  

Start the debug session

For this simple example, the source can be found in our working directory. First, let's start the session; to reduce document clutter, we'll run the debugger in quiet mode:

ntox86-gdb -quiet

The gdb debugger provides its own shell; by default its prompt is (gdb). Specify the target IP address and the port used by pdebug:

(gdb) target qnx 10.0.1.172:8000
Remote debugging using 10.0.1.172:8000
0x0 in ?? ()

Upload the debug executable to the target. (This can be a slow operation. If the executable is large, you may prefer to build the executable into your target image.) Note that the file has to be in the target system's pathname space, so we can get the executable via a network filesystem, ftp, or, if no filesystem is present, via the upload command:

(gdb) upload hello /tmp/hello

Load the symbolic debug information from the current working directory (in this case, hello must reside on the host system):

(gdb) sym hello
Reading symbols from hello...done.

Start the program:

(gdb) run /tmp/hello
Starting program:  /tmp/hello
Trying to find symbol file for ldqnx.so.2
Retrying dynamic interpreter in libc.so.3

Set a breakpoint on main():

(gdb) break main
Breakpoint 1 at 0x80483ae: file hello.c, line 8.

Allow the program to continue to the breakpoint found at main():

(gdb) c
Continuing.
Breakpoint 1, main () at hello.c:8
8       setprio (0,9);

We're now ready to start the debug session:

(gdb)

Basic debugger commands

While you're in a debug session, you can use any of the following commands as the next action for starting the actual debugging of the project:

n
Step through the program, proceeding through subroutine calls.
l
List the specified function or line.
break
Set a breakpoint on the specified function or line.
help
Get the help main menu.
help data
Get the help data menu.
help inspect
Get help for the inspect command.
inspect y
Inspect the contents of variable y.
set y=3
Assign a value to variable y.
bt
Get a back trace.

For more information about these commands and their arguments, see the Using GDB appendix in this guide, or use the help cmd command in gdb.

Let's see how to use some of these basic commands. First, here's the list command:

(gdb) l
3
4   main () {
5
6       int x,y,z;
7
8       setprio (0,9);
9       printf ("Hi ya!\n");
10
11      x=3;
12      y=2;

Press Enter to repeat the last command:

(gdb) <enter>
13      z=3*2;
14
15      exit (0);
16
17  }

Break on line 11:

(gdb) break 11
Breakpoint 2 at 0x80483c7: file hello.c, line 11.

Continue until the first breakpoint:

(gdb) c
Continuing.
Hi ya!

Breakpoint 2, main () at hello.c:11
11      x=3;

Notice that the above command went past the printf() statement at line 9, so the output from the call is displayed on the screen.

Inspect variable y, using the short form of the inspect command:

(gdb) ins y
$1 = -1338755812

Get some help on the step and next commands:

(gdb) help s
Step program until it reaches a different source line.
Argument N means do this N times (or till program stops
for another reason).
(gdb) help n
Step program, proceeding through subroutine calls.
Like the "step" command as long as subroutine calls don't
happen; when they do, the call is treated as one instruction.
Argument N means do this N times (or till program stops
for another reason).

Go to the next line of execution:

(gdb) n
12      y=2;
(gdb) n
13      z=3*2;
(gdb) inspect z
$2 = 1
(gdb) n
15      exit (0);
(gdb) inspe z
$3 = 6

Continue program execution:

(gdb) continue
Continuing.

Program exited normally.

Quit the debugger session:

(gdb) quit
The program is running. Exit anyway? (y or n) y

Sample boot image

[virtual=x86,bios +compress] boot = {
    startup-bios -N node428
    PATH=/proc/boot:./ procnto
}

[+script] startup-script = {
# explicitly running in edited mode for the console link
    devc-ser8250 -e -b115200 &
    reopen
    display_msg Welcome to QNX Neutrino on a PC-compatible BIOS system 
# tcp/ip with a NE2000 Ethernet adaptor
    io-pkt-v4 -dne2000 -ptcpip if=ndi0:10.0.1.172 &
    waitfor /dev/socket
    pipe &
# pdebug needs devc-pty 
    devc-pty &
# Start pdebug on port 8000
    [+session] pdebug 8000 &
}

[type=link] /usr/lib/ldqnx.so.2=/proc/boot/libc.so.3
[type=link] /tmp=/dev/shmem         # tmp points to shared memory
[type=link] /dev/console=/dev/ser2  # no local terminal

[perms=+r,+x]         # Boot images made under MS-Windows need
                      # to be reminded of permissions.
devn-ne2000.so
devnp-shim.so
libc.so
fpemu.so
libsocket.so

[data=copy]            # All executables that can be restarted
                       # go below.
devc-ser8250 
io-pkt-v4
pipe 
devc-pty 
pdebug
esh
ping
ls