Tru64 UNIX
Ladebug Debugger Manual


Previous Contents Index

17.3.1 Analyzing a Crash Dump

When the operating system crashes, the dump function copies core memory into swap partitions. Then at system reboot time, this copy of core memory is copied into the crash dump file, which you can analyze.

When the operating system hangs, you may need to force a crash dump.

17.4 Debugging Loadable Drivers

The procedure for debugging loadable drivers depends on whether you are doing local or remote kernel debugging.

Loadable Drivers and Local Kernel Debugging

For local kernel debugging, any loadable drivers already present in the kernel are automatically loaded into the debugger once when the debugger is started. Since the kernel is running, additional drivers can be loaded at any time. If you wish to obtain the most current list of loaded drivers, you can manually load any new driver information with the following command:


(ladebug) readsharedobj /driver-directory/driver.mod 

The list of drivers currently known to ladebug can be displayed as follows:


(ladebug) listobj 
 
ObjectName                        Start Addr           Size        Symbols 
                                                    (bytes)         Loaded 
---------------------------------------------------------------------------- 
/vmunix                    0xfffffc0000230000        2442992          Yes 
/var/subsys/dna_netman.mod 
                           0xffffffff90ce0000          49152          Yes 
/var/subsys/dna_dli.mod 
                           0xffffffff90cf0000          57344          Yes 
/var/subsys/dna_base.mod 
                           0xffffffff90d04000         393216          Yes 
/var/subsys/dna_xti.mod 
                           0xffffffff90b0a000           8192          Yes 

Loadable Drivers and Remote Kernel Debugging

For remote kernel debugging, you can debug loadable drivers as follows:

  1. On your remote machine, create a directory called (for example)


    /usr/opt/TMU100 
    

    Put both the source file and the loadable driver's .mod file into this directory. Assuming a loadable driver called tmux, get the tmux.mod file, and make sure you have permission to read, write, and execute the file.

  2. Configure your system as follows:
    Create a /usr/opt/TMU100/stanza.loadable file:


    tmux: 
       Subsystem_Description = TMUX device driver 
       Module_Config_Name = tmux 
       Module_Config1 = controller tmux0 at * 
       Module_Type = Dynamic 
       Module_Path = /usr/opt/TMU100/tmux.mod 
       Device_Dir = /dev/streams 
       Device_Char_Major = Any 
       Device_Char_Minor = 0 
       Device_Char_Files = tmux0 
    

    Run the sysconfigdb and sysconfig utilities:


    sysconfigdb -a -f /usr/opt/TMU100/stanza.loadable tmux 
    sysconfigdb -s 
    cp /usr/opt/TMU100/tmux.mod /subsys/tmux.mod 
    cd /subsys 
    ln -s device.mth tmux.mth 
    

  3. Ensure that there is a copy of the driver tmux.mod residing in the same directory on the local machine, for example, /subsys/tmux.mod.
  4. Start up Ladebug with the "-remote" option, and set a breakpoint in the routine subsys_preconfigure. Issue the run command:


        (ladebug) stop in subsys_preconfigure 
        [#1: stop in void subsys_preconfigure(caddr_t) ] 
        (ladebug) run 
    

    subsys_preconfigure is provided to assist developers in debugging configuration routines. It is needed because the debugger is not notified when a subsystem is loaded, and a user-defined breakpoint cannot be set until the load has occurred. subsys_preconfigure is guaranteed to be called following a subsystem load but prior to a configuration.
    If your kernel has been built with symbolic information, once stopped in subsys_preconfigure you can examine the variable subsys to see if this event corresponds to your driver being loaded:


        (ladebug) print subsys 
        0xfffffc0000620cd4="generic" 
    

    Depending on the number of subsystems being automatically loaded, you may stop in subsys_preconfigure many times. If your driver is being loaded last, or if you are manually loading your driver (see item #5, below), you may prefer to employ a more useful breakpoint that gets you closer to your desired stopping point, one that brings you closer to the subsys_preconfigure call that takes place immediately prior to your driver being loaded.

  5. If you are manually loading your driver, you will need to run the remote kernel to the point where you have the hash (#) single-user prompt. Once there, configure the driver as follows:


        # sysconfig -c tmux 
    

  6. Once your driver has been loaded into the kernel, the debugger will stop at your subsys_preconfigure breakpoint. At this time you can issue the following commands:


        (ladebug) print subsys 
        0xfffffc0000620cd4="tmux" 
        (ladebug) readsharedobj /subsys/tmux.mod 
    

    The readsharedobj command causes ladebug to retrieve the symbolic information associated with your driver. A lot of information is transferred over a serial line during this operation, so expect it to take several seconds to complete.

  7. Now Ladebug knows about your driver, so you can proceed with symbolic debugging as you would with any other program. For example:


    (ladebug) stop in tmux_configure 
    [#2: stop in int tmux_configure(cfg_op_t, caddr_t, ulong, caddr_t, ulong) ] 
    (ladebug) cont 
    [2] stopped at [int tmux_configure(cfg_op_t, caddr_t, ulong, caddr_t, 
      ulong):933 0xffffffff89a14028] 
        933     sa.sa_version       = OSF_STREAMS_11; 
    (ladebug) next 
    stopped at [int tmux_configure(cfg_op_t, caddr_t, ulong, caddr_t, 
      ulong):934 0xffffffff89a14034] 
        934     sa.sa_flags         = STR_IS_DEVICE | STR_SYSV4_OPEN; 
    (ladebug) print sa.sa_version 
    84107547 
    

Note

If you use sysconfig to unload and then subsequently reload a driver in a kernel actively being debugged by ladebug, any breakpoints previously present in that driver will be lost. To reestablish those breakpoints in the newly loaded subsystem, issue the following ladebug commands prior to continuing:


    (ladebug) disable * 
    (ladebug) enable * 
    (ladebug) cont 


Part V
Command Reference

This part explains the individual Ladebug commands.


ladebug


Name

ladebug --- Invokes the command interface of the debugger.

dxladebug --- Invokes the graphical user interface of the debugger.


Syntax (command-line)

ladebug [-I directory] [-c file]
[-prompt string]
[-nosharedobjs]
[-pid process_id executable_file]
[-rn node_or_address [,udp_port]]
[-rfn remote_executable_file]
[-ru remote_username]
[-rinsist]
[-k]
[-line serial_line]
[-remote]
[-rp remote_debug_protocol]
[-tty terminal_device]
[executable_file [core_file]]

Syntax (window interface)

dxladebug [-iow ] [-k | -kernel] [-P program_arguments]

Description

Ladebug is a symbolic source code debugger that debugs programs compiled by the DEC C, ACC, DEC C++, DEC Ada, DEC COBOL, DEC Fortran 90, and DEC Fortran 77 compilers. For full source-level debugging, compile the source code with the compiler option that includes the symbol table information in the compiled executable file.

Options and Parameters

The following table describes the options and parameters for the DIGITAL Ladebug debugger command line debugger:
-I Specifies the directory containing the source code for the target program. 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.
-c Specifies an initialization command file. The default initialization file is .dbxinit. By default, Ladebug searches for this file during startup, first in your home directory; if it is not there, Ladebug searches the current directory, and then the object directory of the executable image, if specified.
-prompt Specifies a debugger prompt. The default debugger prompt is (ladebug) . If the prompt argument contains spaces or special characters, enclose the argument in quotes (" ").
-nosharedobjs Prevents the reading of symbol table information for any shared objects loaded when the program executes. Later in the debug session, the user can enter the readsharedobj command to read in the symbol table information for a specified object.
-pid Specifies the process ID of the process to be debugged. You must also specify the binary value for that process. This option cannot be used with any remote or kernel debugging flags.
-rn Specifies the host name or Internet address of the machine on which the remote debugger server is running. Optionally, this specifies the UDP port on which to connect the server. Depending on your shell, it may be necessary to use quotation marks to avoid shell command-line interpretation on the local system. With remote kernel debugging, the default is localhost.
-rfn Specifies the file name (or other identifier) of the executable file to be loaded on the remote system. This option defaults to the local executable file name and is passed uninterpreted to the remote system. When using this option, specify the remote executable file using the syntax of the remote file system; use quotation marks to avoid shell command-line interpretation on the local system. Use only with -rn; do not combine with -pid.
-ru Specifies the user name to be used on the remote target machine. If the -ru option is not specified, the default is the local user name.
-rinsist Connects to a running remote process using the 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. Use only with -rn and -pid.
-k or -kernel Enables local kernel debugging.
-line Specifies the serial line for remote kernel debugging. This must be used with -remote or -rp kdebug (the default).
-remote Enables remote kernel debugging; for use with the kdebug kernel debugger.
-rp Specifies the remote debug protocol, either ladebug_preemptive or kdebug. -rp kdebug enables remote kernel debugging.
-tty Specifies the terminal device for remote kernel debugging. This must be used with -remote or -rp kdebug .
executable_file Specifies the program executable file. If the file is not in the current directory, specify the pathname.
core_file Specifies the core file. If the core file is not in the current directory, specify the pathname.

The following table describes the options and parameters for the dxladebug command:
-iow Invokes the graphical user interface to the debugger and displays a separate user program I/O window.
-k Enables local kernel debugging.
-P Specifies the arguments used by the program you are debugging.

1 General Instructions for Using Debugger Commands

You can enter more than one command on the same line by separating each command with a semicolon (;). Commands are executed in the same order in which they are entered on the command line.

Continue command input to another line by entering a backslash (\) at the end of each line. The maximum command-line length is 100,000 characters.

In debugger commands, the keywords in the following list must be surrounded by parentheses in expressions that use them as variables or type names:

For example, the commands print (thread) and print (thread* )t are valid. The parentheses enable the debugger to distinguish an identifier from a keyword. Example REF-1 shows how to enter multiple commands on a single line.

Example REF-1 Entering Multiple Commands on a Single Line

(ladebug) stop in main;run
[#1: stop in main ] 
[1] stopped at [main:4 0x120000a40]    
      4         for (i=1 ; i<3 ; i++) { 
(ladebug) where
>0  0x120000a40 in main() sample.c:4 
(ladebug) 

The debugger lets you use abbreviations for frequently used commands. These abbreviations are called aliases.

Several aliases are predefined by the debugger. A complete list of predefined aliases is in the description of the alias command in Part 5, Command Reference, and is also displayed by the debugger in response to the alias command with no arguments.

You can also create your own aliases. Example REF-2 creates an alias that sets a breakpoint, runs your program, and performs a stack trace.

Example REF-2 Creating an Alias

(ladebug) alias cs
alias cs is not defined 
(ladebug) alias cs "stop at 5; run; where"
(ladebug) alias cs
cs      stop at 5; run; where 
(ladebug) cs
.oS 
[#1: stop at "sample.c":5 ] 
[1] stopped at [main:5 0x120000b1c]    
      5         f = factorial(i); 
>0  0x120000b1c in main() sample.c:5 
(ladebug) 

Aliases may also contain parameters. In Example REF-3, the alias defined in Example REF-2 is modified to specify the breakpoint's line number when you enter the abbreviated alias command.

Example REF-3 Defining an Alias with a Parameter

 
(ladebug) alias cs(x) "stop at x; run; where"
(ladebug) alias cs
cs(x)   stop at x; run; where 
(ladebug) cs(5)
[#1: stop at "sample.c":5 ] 
[1] stopped at [main:5 0x120000b1c]    
      5         f = factorial(i); 
>0  0x120000b1c in main() sample.c:5 
(ladebug) 

You can nest aliases. You can define one alias and use that alias in the definition of another alias. In Example REF-4, such an alias is defined and then used in the definition of another alias.

Example REF-4 Nesting Aliases

 
(ladebug) alias begin "bp main; run"
(ladebug) alias sp(x,v) ""begin; stop at x; p v""
(ladebug) alias sp
sp(x, v)         begin; stop at x; print v 
(ladebug) sp(10,i)
[#4: stop in main ] 
[4] stopped at [main:4 0x120001180] 
      4     for (i=1 ; i<=3 ; i++) { 
0 
(ladebug) 

The debugger maintains a list of the commands you enter. Using an abbreviated command sequence, you can reenter a command without retyping the entire command (a history feature). Pressing the Return key at the debugger prompt repeats the last command, provided the $repeatmode variable is set to 1, which is the default. Entering two exclamation points (!!) at the debugger prompt also repeats the last command (regardless of the setting of the $repeatmode variable).

You can examine the list of recently entered commands by entering the history command at the debugger prompt.

You can also reenter a command by entering an exclamation point followed by the beginning of the command string. For example, to reenter the command deactivate 3, enter the command !dea. You can also use the arrow keys to reenter commands if $editline is set to 1, which is the default.

1.1 Executing System Commands from the Command Interface

The sh command allows you to execute Bourne shell commands without exiting the debugger.

Example REF-5 uses the shell command sh to list information about a file.

In Example REF-6 the grep shell command displays the lines containing PROGRAM in the Fortran source file data2.f90.

Example REF-5 Executing an Operating System Command

(ladebug) sh ls -l sample.c
-rw-r----- 1 Ladebug       259 May 15 13:08 sample.c 
(ladebug) 

Example REF-6 Displaying an Identifier Using an Operating System Command

(ladebug) sh grep PROGRAM data2.f90
   PROGRAM DATA 
    END PROGRAM DATA 

You can also spawn the Bourne shell from the debugger by issuing:


(ladebug) sh sh

1.2 Specifying the Debugger Prompt for the Command Interface

You can specify a debugger prompt when you start the debugger from the shell with the ladebug -prompt command. The default prompt is (ladebug) .

For example, in Example REF-7, the argument to the -prompt option is enclosed in quotes so that spaces at the end of the prompt will visually separate the prompt from the debugger commands.

Example REF-7 Specifying a Debugger Prompt

% ladebug -prompt ""debug   "" sample
Welcome to the Ladebug Debugger Version 4.0 
------------------ 
object file name: sample 
Reading symbolic information ...done 
debug   stop in main;r
[#1: stop in main ] 
debug 


Command Descriptions


startaddress, endaddress / mode
startaddress / count mode

Note that you must enter a space between "count" and "mode" if the language of the program being debugged is COBOL.

# comment


!!
! integer
!- integer
! text


/ string
? string


alias [aliasname]
alias aliasname [(argument)] "string"
unalias aliasname