HP OpenVMS Delta/XDelta Debugger Manual


Previous Contents Index


Chapter 3
Debugging Programs

When you use DELTA or XDELTA, there are no prompts, few symbols, and one error message. You move through program code by referring directly to address locations. This chapter provides directions for the following actions:

For examples of DELTA debugging sessions on various OpenVMS platforms, see Appendix A for I64, Appendix B for Alpha, and Appendix C for VAX.

3.1 Referencing Addresses

When using DELTA or XDELTA to debug programs, you move through the code by referring to addresses. To help you identify address locations within your program, use a list file and a map file. The list file (.LIS) lists each instruction and its offset value from the base address of the program section. The full map file (.MAP) lists the base addresses for each section of your program. To determine the base address of a device driver program, see the OpenVMS VAX Device Support Manual1.

Once you have the base addresses of the program sections, locate the instruction in the list file where you want to start the debugging work. Add the offset from the list program to the base address from the map file. Remember that all calculations of address locations are done in hexadecimal. You can use DELTA/XDELTA to do the calculations for you with the = command.

To make address referencing easier, you can use offsets to a base address. Then you do not have to calculate all address locations. First, place the base address into a base register. Then move to a location using the offset to the base address stored in the register.

Whenever DELTA/XDELTA displays an address, it will display a relative address if the offset falls within the permitted range (see the ;X command in Chapter 4).

3.1.1 Referencing Addresses (I64 and Alpha Only)

On I64 and Alpha, to reference addresses during a DELTA debug session, use the following OpenVMS Alpha example as a guide. The example uses a simple C program (HELLO.C). You can also use the same commands in an XDELTA debug session.


 #include <stdio.h> 
 
 main() 
 { 
  printf("Hello world\n"); 
 } 

The following procedure generates information to assist you with the address referencing:

  1. Use the /LIST and /MACHINE_CODE qualifiers to compile the program and generate the list file containing the Alpha machine instructions.
    To generate the list file for the previous example, use the following command:


       $ cc/list/machine_code hello 
    

    The compiler will generate the following Alpha code in the machine code portion of the listing file:


       .PSECT $CODE, OCTA, PIC, CON, REL, LCL, SHR,- 
        EXE, NORD, NOWRT 
    0000    main::                                                      ; 000335 
    0000            LDA     SP, -32(SP)             ; SP, -32(SP) 
    0004            LDA     R16, 48(R27)            ; R16, 48(R27)      ; 000337 
    0008            STQ     R27, (SP)               ; R27, (SP)         ; 000335 
    000C            MOV     1, R25                  ; 1, R25            ; 000337 
    0010            STQ     R26, 8(SP)              ; R26, 8(SP)        ; 000335 
    0014            STQ     FP, 16(SP)              ; FP, 16(SP) 
    0018            LDQ     R26, 32(R27)            ; R26, 32(R27)      ; 000337 
    001C            MOV     SP, FP                  ; SP, FP            ; 000335 
    0020            LDQ     R27, 40(R27)            ; R27, 40(R27)      ; 000337 
    0024            JSR     R26, DECC$GPRINTF       ; R26, R26 
    0028            MOV     FP, SP                  ; FP, SP            ; 000338 
    002C            LDQ     R28, 8(FP)              ; R28, 8(FP) 
    0030            LDQ     FP, 16(FP)              ; FP, 16(FP) 
    0034            MOV     1, R0                   ; 1, R0 
    0038            LDA     SP, 32(SP)              ; SP, 32(SP) 
    003C            RET     R28                     ; R28 
    

    Notice the statement numbers on the far right of some of the lines. These numbers correspond to the source line statement numbers from the listing file as shown next:


    335 main() 
    336 { 
    337     printf("Hello world\n"); 
    338 } 
    

  2. Use the /MAP qualifier with the link command to generate the full map file (.MAP file). To produce a debuggable image, make sure that either /DEBUG or /TRACEBACK (the default) is also specified with the link command.
    To generate the map file for the example program, use the following command:


       $ LINK/MAP/FULL HELLO 
    

  3. See the Program Section Synopsis of the map file. Locate the code section that you want to debug and its base address.
    For the example program, the map file is HELLO.MAP. A portion of the Program Section Synopsis is shown below. The $CODE section of the program has a base address of 20000.


      +--------------------------+ 
      ! Program Section Synopsis ! 
      +--------------------------+ 
     
    Psect Name      Module Name       Base     End           Length 
    ----------      -----------       ----     ---           ------ 
    $LINKAGE                        00010000 0001007F 00000080 (        128.) 
                    HELLO           00010000 0001007F 00000080 (        128.) 
    $CODE                           00020000 000200BB 000000BC (        188.) 
                    HELLO           00020000 000200BB 000000BC (        188.) 
    

  4. See the list file for the location where you want to start debugging. First find the source line statement number. Next find that statement number in the machine code listing portion of the list file. This is the specific instruction where you want to start debugging.
    For the example program, source statement 337 is the following:


     printf("Hello world\n"); 
    

    Search the machine code listing for statement 337. The first occurrence is the instruction at offset 4 from the start of "main::" and the base of the $CODE PSECT.

  5. Enable DELTA using the following commands:


       $ DEFINE LIB$DEBUG SYS$LIBRARY:DELTA 
       $ RUN/DEBUG HELLO 
    

  6. If you want to store the base address in a base register, use the ;X command to load the base register.
    For the example program, use the following DELTA/XDELTA command to store the base address of 20000 in base register 0.


       20000,0;X  
    

  7. Now you can move to specific address locations.
    For example, if you want to place a breakpoint at offset 4, you would calculate the address as 20000 (base address) plus 4 (offset), or 20004, and specify the ;B command as follows:


       20004;B 
    

    Alternatively, if you stored the base address in the base register, you could use the address expression X0+4 (or "X0 4", where the + sign is implied) to set the breakpoint as follows:


       X0+4;B 
    

Reverse this technique to find an instruction displayed by DELTA/XDELTA in the .LIS file, as follows:

  1. Note the address of the instruction you want to locate in the .LIS file.
    For example, DELTA/XDELTA displays the following instruction at address 20020:


       20020!  LDQ             R27,#X0028(R27) 
    

    The following steps allow you to find this instruction in the .LIS file.

  2. See the .MAP file, and identify the psect and module where the address of the instruction is located. Check the base address value and the end address value of each psect and module. When the instruction address is between the base and end address values, record the psect and module names.
    In the example, the instruction address is located in the HELLO module ($CODE PSECT). The address, 20020, is between the base address 20000 and the end address 200BB.
  3. Subtract the base address from the instruction address. Remember that all calculations are in hexadecimal and that you can use the DELTA/XDELTA = command to do the calculations. The result is the offset.
    For example, subtract the base address of 20000 from the instruction address 20020. The offset is 20.
  4. See the .LIS file. Look up the module and then find the correct psect. Look for the offset value you calculated in the previous step.
    In the example, there are two psects and one module but only one $CODE psect. Look up the instruction at offset 20, and you will find the following in the .LIS file:


    0020        LDQ R27, 40(R27)            ; R27, 40(R27)      ; 000337 
     
     
    

3.1.2 Referencing Addresses (VAX Only)

On VAX, to reference addresses during a DELTA debug session, use the following example as a guide. The example uses a simple VAX MACRO program (EXAMPLE.MAR). You can also use the same commands in an XDELTA debugging session.


0000    1   .title  example 
0000    2 
0000    3   .entry  start   ^M<r3,r4> 
0002    4           clrl    r3 
0004    5           movl    #5,r4 
0007    6   10$:    addl    r4,r3 
000A    7           sobgtr  r4,10$ 
000D    8           ret 
000E    9 
000E   10   .end    start 

The following procedure generates information to assist you with address referencing:

  1. Use the /LIST qualifier to assemble the program and generate the list file.
    To generate the list file for the previous example, use the following command:


    $ MACRO/LIST EXAMPLE
    

  2. Use the /MAP qualifier with the link command to generate the full map file (.MAP file). Make sure that the default /DEBUG or /TRACEBACK qualifier is active for your link command. If not, specify /DEBUG or /TRACEBACK along with the /MAP qualifier.
    To generate the map file for the example program, use the following command:


    $ LINK/MAP EXAMPLE
    

  3. See the Program Section Synopsis of the map file, locate the section that you want to debug, and look up the base address.
    For the example program, the map file is EXAMPLE.MAP. A portion of the Program Section Synopsis is shown below. The first section of the program has a base address of 200.


                    +--------------------------+ 
                    ! Program Section Synopsis ! 
                    +--------------------------+ 
     
    Psect Name      Module Name   Base     End           Length 
    ----------      -----------   ----     ---           ------ 
     
    . BLANK .                   00000200 0000020D 0000000E (         14.) 
                    EXAMPLE     00000200 0000020D 0000000E (         14.) 
    

  4. See the list file for the location of the specific instruction where you want to start debugging.
    For the example program, start with the second instruction (MOVL #5,R4) with an offset of 4.
  5. Enable DELTA using the following commands:


    $ DEFINE LIB$DEBUG SYS$LIBRARY:DELTA
    $ RUN/DEBUG EXAMPLE
    

  6. If you want to store the base address in a base register, use the ;X command to load the base register.
    For the example program, use the following DELTA/XDELTA command to store the base address 200 in base register 0.


    200,0;X [Return]
    

  7. Now you can move to specific address locations.
    For example, if you want to place a breakpoint at the second instruction (MOVL #5,R4), you would calculate the address as 200 (base address) plus 4 (offset), or 204, and specify the ;B command as follows:


    204;B [Return]
    

    Alternatively, if you stored the base address in the base register, you could use the address expression X0+4 (or "X0 4", where the + sign is implied), as follows:


    X0+4;B [Return]
    

Reverse this technique to find an instruction displayed by DELTA/XDELTA in the .LIS file, as follows:

  1. Note the address of the instruction you want to locate in the .LIS file.
    For example, DELTA/XDELTA displays the following instruction at address 020A:


    20A!  sobgtr  r4,00000207 
    

    The following steps allow you to find the instruction at location 207:

  2. See the .MAP file and identify the PSECT and MODULE where the address of the instruction is located. Check the base address value and the end address value of each PSECT and MODULE. When the instruction address is between the base and end address values, record the PSECT and MODULE names.
    In the example, the instruction address is located in the EXAMPLE module (.BLANK. psect). The address instruction, 207, is between the base address 200 and the end address 20D.
  3. Subtract the base address from the instruction address. Remember that all calculations are in hexadecimal and that you can use the DELTA/XDELTA = command to do the calculations. The result is the offset.
    For the example, subtract the base address 200 from the instruction address 207. The offset is 7.
  4. See the .LIS file. Look up the MODULE and then find the correct PSECT. Look for the offset value you calculated in the previous step.
    In the example, there is only one PSECT and MODULE. Look up the instruction at offset 7. The program is branching to the following instruction:


    10$:   addl r4,r3 
     
     
    

Note

1 This manual has been archived but is available on the OpenVMS Docmentation CD-ROM.

3.2 Referencing Registers

When using DELTA or XDELTA to debug programs, you can view the contents of registers. The following sections describe the types of registers that are referenced by each OpenVMS platform.

3.2.1 Referencing Registers (I64 Only)

On I64, you can reference the following kinds of registers: integer, floating, application, branch, control, special purpose, and software equivilents of special OpenVMS symbolic locations.

Table 3-1 lists the Intel Itanium registers and symbols by which they are identified.

Table 3-1 Intel Itanium Registers and their Associated Symbols
Register Symbol
General R0 through R127
Floating FP0 through FP127
Branch BR0 through BR7
Predicate P0 through P63
Application AR16 (RSC), AR17 (BSP), AR18 (BSPSTORE), AR19 (RNAT), AR25 (CSD), AR26 (SSD), AR32 (CCV), AR36 (UNAT), AR64 (PFS), AR65 (LC), AR66 (EC)
Control CR0 (DCR), CR1 (ITM), CR2 (IVA), CR8 (PTA), CR16 (IPSR), CR17 (ISR), CR19 (IIP), CR20 (IFA), CR21 (ITIR), CR22 (IIPA), CR23 (IFS), CR24 (IIM), CR25 (IHA),CR65 (IVR)

In addition, there is a program counter (PC) register, which is obtained from the hardware IP register and the ri field of the PSR register.

3.2.2 Referencing Registers (Alpha Only)

On Alpha, to view the contents of the 32 integer registers, the program counter (PC), the stack pointer (SP), the processor status (PS), the 32 floating point registers, the floating point control register (FPCR), and the internal processor registers (IPRs), use the same DELTA/XDELTA commands that you use to view the contents of any memory location. These commands include /, LINEFEED, and ESC. The symbols for identifying these registers follow:

Floating point registers can be accessed from DELTA and from XDELTA but only if floating point arithmetic is enabled in the current process.

DELTA runs in the context of a process. Access to floating point registers is enabled as soon as the first floating point instruction in the code being examined is executed. Access is disabled as soon as that image completes execution.

When the system enters XDELTA, some process is the current process, and that current process may not be obvious. If that process happens to have floating point enabled at the time (because a floating point instruction had executed and the image containing the floating point instruction was still executing), then you can access the floating point registers. Otherwise, you cannot. XDELTA checks the FEN (floating point enable) IPR (internal processor register) to see if it needs to provide access to floating point registers.

3.2.3 Referencing Registers (VAX Only)

On VAX, to view the contents of the 16 general registers (including the program counter and the stack pointer) and the processor status longword (PSL), use the same DELTA/XDELTA commands as you use to view the contents of any memory location (for example, the /, LINEFEED, and the ESC commands). The symbols used to identify the locations of the registers and PSL are as follows:

3.3 Interpreting the Error Message

When you make an error entering a command in DELTA or XDELTA, you get the "Eh?" error message. This is the only error message generated by DELTA and XDELTA. It is displayed under the following circumstances:

On I64, the error message is also displayed if you are unable to step over a subroutine call due to no write access to the address of the next instruction.

On Alpha, the error message is also displayed if you are unable to single-step or proceed due to no write access to the address of the next instruction.

3.4 Debugging Kernel Mode Code Under Certain Conditions

Some programs exist which, while running in process space, change mode to kernel and raise IPL. Typically, this code is debugged with both DELTA and XDELTA. DELTA is used to debug the kernel mode code at IPL zero. XDELTA is used to debug the code at elevated IPL. (DELTA does not work at elevated IPL.)

Before you can debug such code with XDELTA, you must complete some setup work.


Previous Next Contents Index