Tru64 UNIX
Ladebug Debugger Manual


Previous Contents Index


Chapter 15
Machine-Level Debugging

The Ladebug debugger lets you debug your programs at the machine-code level as well as at the source-code level. Using debugger commands, you can examine and edit values in memory, print the values of all machine registers, and step through program execution one machine instruction at a time.

Only those users familiar with machine-language programming and executable-file-code structure will find low-level debugging useful.

For more information on the Ladebug commands mentioned in this chapter, see Part 5.

15.1 Examining Memory Addresses

You can examine the value contained at an address in memory as follows:

15.1.1 Using the <examine address> Command

The <examine address> command has two main syntaxes. The following syntax prints a range of addresses by specifying the beginning and end of the range:

start_address, end_address / mode

If a symbol precedes the slash (/) in an address expression, you may need to enclose the expression in parentheses. For example:


(ladebug) ($pc), ($pc+12) / i

The following command syntax prints a range of addresses by specifying the beginning address and the total number of memory locations display:

start_address / count mode

You can enter memory addresses in decimal or in hexadecimal by preceding the number with 0x. The mode variable determines how the values are displayed.

Example 15-1 shows how to disassemble a range of memory.

Example 15-1 Disassembling Values Contained in a Range of Addresses

(ladebug) 0x120001180, 0x120001185 / i
 [main:4, 0x120001180]  addq    zero, 0x1, t0 
 
 [main:4, 0x120001184]  stl     t0, 24(sp) 
(ladebug) 0x120001180 / 2 i
 [main:4, 0x120001180]  addq    zero, 0x1, t0 
 
 [main:4, 0x120001184]  stl     t0, 24(sp) 
(ladebug) 

In this example, the same range of addresses was accessed using start_address command in both the end_address syntax and the / count syntax.

15.1.2 Using Pointer Arithmetic

You can use C and C++ pointer-type conversions to display the contents of a single address in decimal. Using the print command, the syntax is as follows:
print *(int *)(address)

Using the same pointer arithmetic, you can use the assign command to alter the contents of a single address. Use the following syntax:
assign *(int *)(address) = value

Example 15-2 shows how to use pointer arithmetic to examine and change the contents of a single address.

Example 15-2 Using Pointer Arithmetic to Display and Change Values in Memory

(ladebug) print *(int*)(0x10000000)
4198916 
(ladebug) assign *(int*)(0x10000000) = 4194744
(ladebug) print *(int*)(0x10000000)
4194744 
(ladebug) 

15.2 Examining Machine-Level Registers

The printregs command prints the values of all machine-level registers. The registers displayed by the debugger are machine dependent. The values are in decimal or hexadecimal, depending on the value of the $hexints variable (the default is 0, decimal). The register aliases are shown; for example, $r1 [$t0].

Example 15-3 shows Tru64 UNIX Alpha machine-level registers.

Example 15-3 Printing Machine Registers on the Tru64 UNIX Alpha Platform

(ladebug) printregs
$r0  [$v0]  = 10                        $r1  [$t0]  = 1 
$r2  [$t1]  = 4831844048                $r3  [$t2]  = 5368719424 
$r4  [$t3]  = 0                         $r5  [$t4]  = 0 
$r6  [$t5]  = 4396972783304             $r7  [$t6]  = 2 
$r8  [$t7]  = 10                        $r9  [$s0]  = 337129856 
$r10 [$s1]  = 337127744                 $r11 [$s2]  = 4396973344608 
$r12 [$s3]  = 0                         $r13 [$s4]  = 5368847640 
$r14 [$s5]  = 5368753616                $r15 [$s6]  = 20 
$r16 [$a0]  = 1                         $r17 [$a1]  = 4831835496 
$r18 [$a2]  = 4831835512                $r19 [$a3]  = 4831835848 
$r20 [$a4]  = 4396981193976             $r21 [$a5]  = 5 
$r22 [$t8]  = 9                         $r23 [$t9]  = 9 
$r24 [$t10] = 4831842472                $r25 [$t11] = 1648 
$r26 [$ra]  = 4831842828                $r27 [$t12] = 4831842912 
$r28 [$at]  = 4396981208928             $r29 [$gp]  = 5368742064 
$r30 [$sp]  = 4831835408                $r31 [$zero]= 4831842928 
$f0         = 0.1                       $f1         = 0 
$f2         = 0                         $f3         = 0 
$f4         = 0                         $f5         = 0 
$f6         = 0                         $f7         = 0 
$f8         = 0                         $f9         = 0 
$f10        = 0                         $f11        = 0 
$f12        = 0                         $f13        = 0 
$f14        = 2.035550460865936e-320    $f15        = 4120 
$f16        = 0                         $f17        = 0 
$f18        = 0                         $f19        = 0 
$f20        = 0                         $f21        = 0 
$f22        = 0                         $f23        = 0 
$f24        = 0                         $f25        = 0 
$f26        = 0                         $f27        = 0 
$f28        = 0                         $f29        = 0 
$f30        = 0                         $f31        = 0 
$pc         = 0x120001270 
(ladebug) 

15.3 Stepping at the Machine Level

The stepi and nexti commands let you step through program execution incrementally, like the step and next commands described in the Command Reference section. The stepi and nexti commands execute one machine instruction at a time, as opposed to one line of source code. Example 15-4 shows stepping at the machine-instruction level.

Example 15-4 Stepping Through Program Execution One Machine Instruction at a Time

(ladebug) stop in main
[#1: stop in main ] 
(ladebug) run
[1] stopped at [main:4 0x120001180] 
      4     for (i=1 ; i<3 ; i++) { 
(ladebug) stepi
stopped at [main:4 0x120001184] stl     t0, 24(sp) 
(ladebug) [Return]
stopped at [main:5 0x120001188] ldl     a0, 24(sp) 
(ladebug) [Return]
stopped at [main:5 0x12000118c] ldq     t12, -32664(gp) 
(ladebug) [Return]
stopped at [main:5 0x120001190] bsr     ra, 
(ladebug) [Return]
stopped at [factorial:12 0x120001210]   ldah    gp, 8192(t12) 
 
(ladebug) 

At the machine-instruction level, you can step into, rather than over, a function's prolog. While within a function prolog, you may find that the stack trace, variable scope, and parameter list are not correct. Stepping out of the prolog and into the actual function updates the stack trace and variable information kept by the debugger.

Single-stepping through function prologs that initialize large local variables is slow. As a workaround, use the next command.


Chapter 16
Remote Debugging

This chapter describes debugging programs running on remote systems. A remote debugger consists of a server running on the target system and a client (the debugger) running on the host system. Once connected to the target system, you use Ladebug to debug your program in the same way you debug your programs running locally.

For a detailed description of writing a remote debugger server, see Appendix C.

16.1 Remote Debugging Environment

The remote debugging environment consists the following components that interact through the remote debugger protocol:

The functionality available in a remote debugging session depends in part on which debugger server you are using. For Tru64 UNIX Version 4.0-6, this server is the server for the EB64 Alpha Evaluation Board (see Section 16.6) or Tru64 UNIX, or a server that you write for your own Alpha environment (see Appendix C).

The Ladebug server provided with DIGITAL UNIX Version 4.0-6 (or later) is not compatible with versions of the debugger earlier than Version 4.0-6. (This incompatibility affects you only if you use remote debugging.) The incompatibility stems from a security enhancement introduced in Version 4.0-6: The server checks that a connect request is from a privileged port.

16.2 Reasons for Remote Debugging

There are several cases in which you would use a remote debugger:

  1. The target system does not have (or cannot run) a local debugger.
    The target system may be an embedded system that cannot support a debugger. You also may be debugging a part of the target's software that has to work before you can support a local debugger. A remote debugger server (that is, the software) requires less and different support from the target's operating system (if one exists) than the support required by a local debugger.
  2. The target system does not have the resources to run a local debugger.
    The target system may not be able to run a local debugger and simultaneously run the program being debugged. The remote debugger server uses less resources (particularly memory) than a resident Ladebug debugger.
  3. The source files for the program being debugged are not accessible from the target system.
    These sources are accessible from a host system from which you can remotely debug the target system.
  4. The target system's screen or keyboard cannot be used for debugging.
    A screen or keyboard interface may not exist because they are used by the program being debugged. Another possibility is that the target system's physical location is different from the user's.
  5. A local debugger may interfere with window-interface applications.
    On many interactive systems, it may be best to run a remote debugger. Alternatively, you may be able to run a local debugger that directs its input/output (I/O) to a screen on the remote system.
  6. You may want to debug a process running on another machine.

16.3 Client/Server Model for Remote Debugging

Remote debugging with Ladebug uses a client/server model. In this model, the host system, or client, initiates a connection to the target hardware and server software, which processes client requests.

Ladebug supports remote debugging in various client/server configurations. Figure 16-1 shows two configurations that use a single file system.

Figure 16-1 Client/Server Model with a Single or a Shared File System


In configuration A, the client and server are implemented on a single machine which connects to a file system.

In configuration B, a host system client is connected to a remote server through TCP/IP. Both host and target systems share the same file system.

A host system client can also be connected to a remote server in a configuration that employs separate file systems, as shown in Figure 16-2.

Note

In this case, you must specify the -rfn option with the remote file name and have a locally accessible binary with debugger information.

Figure 16-2 Client/Server Model with Separate File Systems


In configurations A, B, and C in Figure 16-1 and Figure 16-2, the user program resides on the target system. The host machine interacts with the target system in the following way:

  1. After starting the server deamon, a remote session is established when the host system connects to the target system.
  2. The Ladebug client on the host system interacts with the server on the target system to debug the user program. A new server is started for each user program being debugged.
  3. The debugger terminates the remote server when you end the debugging session.

Table 16-1 describes the client/server concepts for remote debugging. Section 16.4 describes the tasks for remote debugging.

Table 16-1 Client/Server Concepts for Remote Debugging
Client Server
Is Ladebug debugger. Is remote debugger server.
Runs on host system. Runs on target hardware (for example, EB64 or Tru64 UNIX Alpha. )
Makes requests to server. Controls the process being debugged.
Is responsible for all access to source files and symbol table. Is not responsible.
Uses debug protocol; sends protocol commands to the server. Uses debug protocol; receives protocol commands and sends responses.
Contains information about the process being debugged. Contains information about the processes' environment.
Does not control processes. Server controls a single process; server deamon controls multiple processes (messages to the server containing a server ID).

16.4 Tasks for Remote Debugging

This section describes general tasks to debug programs running on remote systems. The tasks include:

  1. Starting the server daemon
  2. Starting the debugger, user program, and connecting to the server
  3. Debugging the user program
  4. Exiting the debugger and disconnecting from the server

16.4.1 Starting the Server Daemon

The server daemon must be running on the target system before you can remotely debug programs on that target. You can start the server daemon either from a system startup file or interactively from the command line.

Note

Under certain conditions, running the server daemon negatively affects the security of your system. If you are running an old server, there may be a security problem (see the documentation for that server). An individual user ID can be protected by prohibiting remote access from a particular host (or from all hosts) in the .rhosts and the hosts.equiv files. On Tru64 UNIX machines, .rhosts must have rw privileges only for the owner, with no privileges for the group and others.

For example, to start the server daemon interactively and output system messages to a log file, log in as superuser then start the server daemon as follows:


$ /usr/bin/ladebug-server > ladebug-server.log &
Ladebug remote debug server deamon starting 
/usr/bin/ladebug-server : server is servdb.ptl.dss.com (11.18.49.164) 
... 

16.4.2 Starting the Debugger

When you start the debugger you also start the user program and connect to the server.

Use the -rn command-line option, which specifies the IP name or address of the machine on which the server deamon is running and on which you want your user program to run. Specifying this command-line option is the only difference between starting the debugger to debug a remote application and starting the debugger to debug a local one.

If you start the debugger without specifying the process ID (-pid) , it starts a debuggee process in the remote node running the indicated image file. If you do not specify the user name on the remote node (-ru) , it uses the local user name.

For example, if you are connecting to the target system servdb to debug the user program ~/work/test/hello and the file system is shared:


 
$  ladebug -rn servdb  /work/test/hello
Welcome to the Ladebug Debugger Version 3.0 
------------------ 
object file name: /usr/users/dss/work/test/hello 
machine name: servdb 
Reading symbolic information ...done 
 

If you start the debugger and specify a process ID, the debugger connects to the process in the remote node running the process. If the specified process ID does not exist, the server returns an error and refuses connection.

Note

If you are connecting to a server that does not share the same file system, specify the -rfn option with the -rn option. See Section 16.5 for detailed descriptions of all the remote debugging command-line options.

16.4.3 Debugging the User Program

You debug a user program running on the target system the same way as you would a local program. Note the following differences:

The following example shows the result of running user program ~/work/test/hello on remote node servdb:


(ladebug)  stop in main; run
[#1: stop in main ] 
[1] stopped at [main:6 0x120001fa0] 
      6   (void) printf("Hello, world !\n"); 
(ladebug)  cont
Thread has finished executing 
(ladebug) 

Note that the output of the program is not displayed after the cont command. With remote debugging, the program output is displayed on the target system. You can also redirect the output of the application to a log file.

The same program run locally would look like this:


$  ladebug  /work/test/hello
Welcome to the Ladebug Debugger Version 3.0 
------------------ 
object file name: /usr/users/dss/work/test/hello 
Reading symbolic information ...done 
(ladebug) stop in main; run
[#1: stop in main ] 
s[1] stopped at [main:6 0x120001fa0] 
      6   (void) printf("Hello, world !\n"); 
(ladebug) cont
Hello, world ! 
Thread has finished executing 
(ladebug) 

16.4.4 Exiting the Debugger and Disconnecting from the Server

The debugger quit command ends the remote debugger session and automatically disconnects from the server.

Note

The quit command does not terminate the process running on the target system. Use the kill command to terminate a running process and end the remote debugger session.

16.5 Command-Line Options for Remote Debugging

Table 16-2 lists the debugger command-line options that support remote debugging.

Table 16-2 Command Line Options for Remote Debugging
Option/Qualifier Meaning/Conditions
-rn 1 node_or_address [, udp_port 2 ] Specifies the internet node name or IP address of the machine on which the remote debugger server is running (that is, the node running the program to be debugged); optionally specifies the UDP port on which to connect the server. Either the node name or IP address is required; there is no default.
-pid process_id Specifies the process ID of the process to be debugged. When you specify this option, Ladebug debugs a running process rather than loading a new process.
-rfn 1 arbitrary_string Specifies the file name (or other identifier) of the image to be loaded on a remote system. This option defaults to the local image file name and it is passed to the remote system uninterpreted. Use only with -rn ; do not combine with -pid .
-rinsist Connects to a running remote process using the connect insist protocol message instead of the connect protocol message. This option functions as a request to the server to connect to the client, even if another client is already connected. (The previously connected client is disconnected.) Use only with with -rn and -pid .
-ru username Specifies the user name to be used on the remote system. The default is the local user name.


1Depending on your shell, it may be necessary to enclose this option in quotes to prevent the shell from interpreting the punctuation characters in the parameter.
2Current remote debugger servers use UDP port 410 (the default); older releases might use UDP port 21511.

The following examples show how to use the remote debugger command-line options.

Example 1


$  ladebug -rn 1.2.3.4 -ru brown program1

Connects to the server on the node with IP address 1.2.3.4 and asks the server to load a process called program1. The local copy of the object file is also called program1. The user name on the remote node is brown.

Example 2


$  ladebug -rn EB64 -rfn '**process name A**' program3

Connects to the server on the node with IP name EB64 and asks it to load the process called '**process name A**'. The local object file is called program3.


Previous Next Contents Index