HP OpenVMS Systems Documentation

Content starts here

OpenVMS Delta/XDelta Debugger Manual


Previous Contents Index

1.7.2 Requesting Interrupts on Alpha Computers

On Alpha, to request an interrupt, perform the following steps:

  1. Halt the processor with the following command:


     ^P
    
  2. Request an IPL 14 software interrupt with the following command:


    >>> DEP SIRR E
    

    This command deposits a 1410 into the software interrupt request register.
  3. Reactivate the processor by issuing the CONTINUE command as follows:


    >>> CONT
    

The process should enter XDELTA as soon as IPL drops to 14.

The following message is displayed:


Brk 0 at address
address! instruction

At this point, the exception frame is on the stack. The saved PC/PS in the exception frame tells you where you were in the program when you requested the interrupt.

1.8 Accessing the Initial Breakpoint

On Alpha and VAX, when debugging a program, you can set a breakpoint in the code so that XDELTA gains control of program execution.

To set a breakpoint, place a call to the system routine INI$BRK in the source code.

The INI$BRK routine contains two instructions: BPT and a second instruction that is specific to the hardware system. On systems that are not booted with XDELTA, the BPT instruction in INI$BRK is replaced with a NOP instruction.

You can use the INI$BRK routine as a debugging tool, placing calls to this routine in any part of the source code you want to debug.

On VAX, the second instruction in INI$BRK is RSB. After the break is taken, the return address (the address in the program to which control returns when you proceed from the breakpoint) is on the top of the stack.

The following command calls the INI$BRK system routine to reach the breakpoint:


JSB G^INI$BRK


On Alpha, the second instruction in INI$BRK is JSR R31,(R26). After the break is taken, the return address (the address in the program to which control returns when you proceed from the breakpoint) is in R26.

The following C routine calls the INI$BRK system routine to reach the breakpoint:


extern void ini$brk(void);

main()
{
 ini$brk();
}


1.9 Proceeding from Initial XDELTA Breakpoints

On VAX, when XDELTA reaches one of its breakpoints, it displays the following message:


1 BRK AT nnnnnnnn

address/instruction operands


On Alpha, when XDELTA reaches one of its breakpoints, it displays the following message:


BRK 1 AT nnnnnnnn

address!instruction operands


On Alpha and VAX multiprocessor computers, the XDELTA breakpoint is taken on the processor upon which the XDELTA software interrupt was requested, which is generally the primary processor. At this point, XDELTA is waiting for input. If you want to proceed with program execution, enter the ;P command. If you want to do step-by-step program execution, enter the S command. If you know where you have set breakpoints, examine them using the ;B command. You can also set additional breakpoints or modify existing ones.

If you entered the ;P command to proceed with program execution and the system halts with a fatal bugcheck, the system prints the bugcheck information on the console terminal. Bugcheck information consists of the following:

  • Type of bugcheck
  • Contents of the registers
  • A dump of one or more stacks
  • A list of loaded executive images

The contents of the program counter (PC) and the stack indicate where the failure was detected. Then, if the system parameter BUGREBOOT was set to 0, XDELTA issues a prompt. You can examine the system's state further by entering XDELTA commands.

1.10 Exiting from XDELTA

On Alpha and VAX, XDELTA remains in memory with the operating system until you reboot without it.


Chapter 2
DELTA and XDELTA Symbols and Expressions

This chapter describes how to form the symbolic expressions used as arguments to many DELTA and XDELTA commands.

2.1 Symbols Supplied by DELTA and XDELTA

DELTA and XDELTA define symbols that are useful in forming expressions and referring to registers. These symbols are described in Table 2-1.

Table 2-1 DELTA/XDELTA Symbols
Symbol Description
. The address of the current location. The value of this symbol is set by the Open Location and Display Contents (/), Open Location and Display Instruction (!), and the Open Location and Display Indirect (TAB) commands.
Q The last value displayed. The value of Q is set by every command that causes DELTA or XDELTA to display the contents of memory or the value of an expression.
1Xn Base register n, where n can range from 0 to F (hexadecimal). These registers are used for storing values, most often the base addresses of data structures in memory.

For XDELTA only, XE and XF contain the addresses of two command strings that XDELTA stores in memory. See the Execute Command String (;E) command for more information.

For XDELTA only, registers X4 and X5 contain specific addresses. X4 contains the address of the location that contains the PCB address of the current process on the current processor. The address that X4 contains is that of the per-CPU database for the current processor. X5 contains SCH$GL_PCBVEC, the symbolic address of the start of the PCB vector, and the list of PCB slots.

2Xn Base register n, where n can range from 0 to 15 (decimal). These registers are used for storing values, most often the base addresses of data structures in memory.

For XDELTA only, X14 and X15 contain the addresses of two command strings that XDELTA stores in memory. See the Execute Command String (;E) command for more information.

For XDELTA only, registers X4 and X5 contain specific addresses. X4 contains the address of the location that contains the PCB address of the current process on the current processor. The address that X4 contains is that of the per-CPU database for the current processor. X5 contains SCH$GL_PCBVEC, the symbolic address of the start of the PCB vector, and the list of PCB slots.

1Rn General register n, where n can range from 0 to F (hexadecimal). RF+4 is the processor status longword (PSL), RE is the stack pointer, and RF is the program counter (PC).
2Rn General register n, where n can range from 0 to 31 (decimal). PS is the processor status and PC is the program counter.
1Pn The internal processor register at processor address n, where n can range from 0 to 3F (hexadecimal). See the VAX Architecture Reference Manual for a description of these processor registers.
2P(IPR name) The internal processor register at processor address IPR name. See the Alpha Architecture Reference Manual for the names and descriptions of these processor registers.
2FPCR The floating-point control register.
1G ^X80000000, the prefix for system space addresses. G2E, for example, is equivalent to ^X8000002E.
2G ^XFFFFFFFF80000000, the prefix for system space addresses.
H ^X7FFE0000, the prefix for addresses in the control region (P1 space). H2E, for example, is equivalent to ^X7FFE002E.
2PID:Rn The internal PID of another process that you want to look at. Rn represents the register that you want to read or write. Rn applies to R0-R29, PC, and PS. An address or address range can be specified instead of Rn for the / command, as described in Chapter 4.

1VAX specific
2Alpha specific

2.2 Floating-Point Register Support

On OpenVMS Alpha, 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, it may not be obvious which process is the current process. If the current process happens to have floating point enabled (because a floating-point instruction has executed and the image containing the floating-point instruction is 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 whether it needs to provide access to floating-point registers.

2.3 Forming Numeric Expressions

Expressions are combinations of numbers, symbols that have numeric values, and arithmetic operators.

On VAX, both DELTA and XDELTA store and display all numbers in hexadecimal. They also interpret all numbers as hexadecimal.

On Alpha, all numbers except integer and floating-point registers are stored and displayed in hexadecimal. These registers are stored and displayed in decimal.

On Alpha and VAX, expressions are formed using regular (infix) notation. Both DELTA and XDELTA ignore operators that trail the expression. The following is a typical expression (in hexadecimal):


G4A32+24
DELTA and XDELTA evaluate expressions from left to right. No operator takes precedence over any other.

DELTA and XDELTA recognize five binary arithmetic operators, one of which also acts as a unary operator. They are listed in Table 2-2.

Table 2-2 Arithmetic Operators
Operator Action
+ or SPACE Addition
- Subtraction when used as a binary operator, or negation when used as a unary operator
* Multiplication
% Division
@ Arithmetic shift

The following example shows the arguments required by the arithmetic-shift operator:


n@j

In this example, n is the number to be shifted, and j is the number of bits to shift it. If j is positive, n is shifted to the left; if j is negative, n is shifted to the right. Argument j must be less than 2016 and greater than -2016. Bits shifted beyond the limit of the longword are lost; therefore, the result must fit into a longword.


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:

  • Referencing addresses
  • Referencing registers, the PSL or PS, and the stack
  • Interpreting the error message
  • Debugging kernel mode code under certain conditions
  • Debugging an installed, protected, shareable image
  • Using XDELTA on multiprocessor computers
  • Debugging code when single-stepping fails (Alpha only)
  • Debugging code that does not match the compiler listings (Alpha only)

For examples of DELTA debugging sessions on VAX and Alpha, refer respectively to Appendix A and Appendix B.

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, refer to 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 (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. Refer to 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. Refer to 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. Refer to 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. Refer to 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
    
    
    

3.1.2 Referencing Addresses (Alpha Only)

On Alpha, to reference addresses during a DELTA debug session, use the following 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. Refer to 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. Refer to 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:

    Note

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


    Previous Next Contents Index