next up previous contents
Next: RTEMS Specific GDB Commands Up: GDB Agent for RTEMS Previous: Building   Contents


Debugging Session



Code to be debugged must be compiled with the `-g' option. (preferrably everything)1.

Optimization Caveat: It is possible to use GDB with optimized code (I do it all the time) but this may change the flow of execution, subroutine calls (inlining) and may cause variables to `disappear' etc.


You want to use a GUI frontend together with cross-gdb, e.g.,
		ddd --debugger <cross_arch>-rtems-gdb

Note: you need to set PATH prior to starting ddd/gdb, see below.


GDB is a quite powerful program - make sure you know how to use it! The `rtems-remote' target only adds 2 new commands. Everything else is off-the shelf GDB. Note that not all available commands necessarily make sense on this specific target.

Path Settings

Cross-debugging involves both, a host computer and the target system executing the actual code. The host computer needs access to the same version of the object files that the target computer is executing.

Upon connection to the target, the host computer obtains a list of currently loaded object files from the target. In order for the host GDB being able to locate the necessary object files, the PATH environment variable must point to the directories containing these objects. Note that GDB doesn't define a dedicated path variable for `cross-architecture objects' but requires the user to set the ordinary PATH that is also searched for host executables! Note that PATH is an environment variable and cannot be changed from within a GDB session (GDB's environ and path commands only affect the PATH as seen by a native debuggee and don't have any effect in a cross-gdb session).

GDB also features a load command to instruct the target computer to load/link object modules. Since the target computer usually sees a directory tree that is different from the host, any path information is discarded from the load argument - instead, the target's PATH environment variable must contain the directory where the target can locate the object that is to be loaded.

Starting the Debugging Agent

On the target, the debugging agent must be running. It needs to be linked into the system and is started by calling
		rtems_gdb_start(int agent_priority, char *serial_name)

Passing a priority of 0 lets the daemon pick its default scheduling priority. The second argument defines the connection method to be used. A NULL pointer lets the daemon listen on TCP port 2159 (registered port number for the gdb remote protocol) for an incoming connection, if a string is passed, it must be the path to a serial device, e.g., /dev/ttyS1.

The agent can be stopped (rtems_gdb_stop()) and restarted with a different priority and/or communication method.

Note: rtems 4.6.2 requires a patch for this to work safely since the operation involves one task closing a socket on which another task is blocking.

Connecting to the Target

gdb can use either serial-port or TCP connections. Note that either uses certain resources on the target (e.g., the termios driver or the TCP/IP stack, respectively) and a debugging session may deadlock the system if the debugging agent needs a resource that is locked when the debuggee runs into a breakpoint.

The syntax for connecting to a target is (TCP)

		(gdb) target rtems-remote <target>:2159
		(gdb) target rtems-remote <com_port_on_host>
(serial) - note that the agent's serial port runs at 115200 8N1 - use GDB's remote baud command.

Note that rtems-remote is an extension of the standard GDB `remote' target - it adds support for Cexp modules (names, section addresses etc.).

Once connected to the target, the debugger is attached to a dummy thread context. All user and system threads are executing normally at this point.

Use the detach command to close the connection to the target at any time. All stopped threads will be resumed.

Sharing the Console Serial Line

If a priority less than zero is passed to rtems_gdb_start() the agent is executed in the context of the the caller, i.e., no separate task is created. Thus, the agent may be run from a shell (e.g., ``Cexp'') and take over the console line for the duration of the session, i.e., until the detach command is issued from GDB. In this ``foreground'' mode of operation, the agent terminates after a the session is ended returning control to the caller of rtems_gdb_start().

A sample session example:

	    GDB Daemon starting
	< scrambled output since terminal mode changed >
	< exit from terminal program and start gdb >
	    (gdb) target rtems-remote < /dev/ttySxx >
	    (gdb)    < session commands >
	    (gdb) detach
	    (gdb) quit
	< restart terminal program and resume Cexp session >

Switching Thread Context

In order to inspect a thread's stack, registers etc. it must be stopped. A thread is stopped either because it runs into a breakpoint or if the debugger is explicitely attached to it (thread command). If you want to attach to a specific thread you need to know its `id' (i.e., GDB's id which is orthogonal to the RTEMS task id - use info threads to obtain a task list).

Once stopped, a thread remains suspended until you issue the continue command or detach (terminate the session). Either of those operations lets all stopped threads resume.

You can hit <Ctrl>-C to interrupt the target; this only interrupts the `dummy'/`helper' thread and attaches GDB to it. I.e.,

		target rtems-remote xx:2159 //connect, attach to 'helper'
At this point, the helper is stopped - you can inspect its registers etc. everyone else continues normally
		info threads
		t 14             //switch to thread ID 14
Thread 14 is stopped. The helper remains stopped. Inspect T14's registers + stack
		t 12             //switch to thread ID 12
helper, T14 and T12 are stopped; inspect T12's registers + stack
		t 14             //switch back to thread ID 14
helper, T14 and T12 remain stopped; inspect T14's registers + stack
		cont             //resume everything
helper, T14 and T12 are resumed
		<Ctrl>-C         //interrupt
interrupt, stop helper and attach to it - same state as after connection was established.

Executing Subroutines on the Target

When evaluating expressions at the (gdb) command line (e.g., within a call or print command) gdb may need to execute a subroutine on the target. For example,
		(gdb) print printf("Hello\n")
invokes the printf routine on the target, retrieves the return value and prints it to the gdb console.

This is actually a pretty complex operation involving creating a dummy stack frame and appropriate arguments etc. on the target. Some targets' exception handlers may not expect modifications of the stack and might crash as a result of an attempt to call a routine on the target.

Also, it should be noted that the routine is always executed in the context of the ``current task''. Hence, the ``current task''

The `helper' task provides a suitable environment for the purpose of executing subroutines on the target.

DDD Note

After reloading any object on the target (using the rtems load or rtems sync-objs commands) the source code displayed by DDD may not be current (since the commands were performed at the GDB level, unnoticed by ddd). Use ddd's Reload Source menu entry from the Source pull-down menu or the equivalent accelerator key combination <Ctrl>-<Shift>-L (default) to refresh the display.

next up previous contents
Next: RTEMS Specific GDB Commands Up: GDB Agent for RTEMS Previous: Building   Contents
guest 2006-08-11