HP.com home PA-RISC Procedure Calling Conventions Reference Manual > Appendix C The Stack Unwind Library

C.2 Unwind Utility Routines

MPE documents

Complete PDF
Table of Contents

Unwind utility routines provide the core functionality of the stack unwind mechanism. They can be used to create powerful unwind applications. These routines are present and have identical functionality on all PA-RISC systems running HP-UX or MPE XL.
  1. U_get_unwind_table

     struct utable {
       unsigned unwind_table_start;
       unsigned unwind_table_end;
     };
     struct utable U_get_unwind_table(unsigned int dp_value);
    
    Returns the code offsets of the start and end of the unwind table of a given object module. The unwind table is word-aligned. It takes the DP value for the object module where the unwind table is stored. It returns the offset of the start of the unwind table, and the offset of the first word beyond the unwind table.

    This is the interface for assembly programmers:

     ARGO:   DP value of routine being unwound to.
     RETO:   Offset (in space of routine being unwound to)
             of start of unwind table.
     RET1:   Offset (in space of routine being unwound to)
             of first word beyond end of unwind table.
    

  2. U_get_unwind_entry

     int U_get_unwind_entry(
             unsigned int PC;
             unsigned int Space_id;
             unsigned int table_start;
             unsigned int table_end);
    
    Given the PC_offset value of interest and the start and end of the associated unwind table, returns the code offset (in PC_space) of the associated unwind table entry. If no unwind table entry exists, -1 is returned. Typically the table_start and table_end is found using the U_qet_unwind_table routine.

    This is the interface for assembly programmers:

     ARG0:   PC value to look up.
     ARG1:   Space id of table.
     ARG2:   Offset of start of unwind table.
     ARG3:   Offset of first word beyond end of unwind table.
     RET0:   Offset of unwind table entry associated with PC value;
             -1 if none exists.
    
    This routine requires that the unwind table is sorted in increasing order of starting addresses. It does a binary search of the table to get to the entry corresponding to the input PC value.

  3. U_get_previous_frame

    
     struct current_frame_def {      
       unsigned  cur_frsize; /* Frame size of current routine.     */
       unsigned  cursp;    /* The current value of stack pointer.  */
       unsigned  currls;   /* PC_space of the calling routine.     */
       unsigned  currlo;   /* PC_offset of the calling routine.    */
       unsigned  curdp;    /* Data Pointer of the current routine. */
       unsigned  toprp;    /* Initial value of RP.                 */
       unsigned  topmrp;   /* Initial value of MRP.                */
       unsigned  topsr0;   /* Initial value of sr0.                */
       unsigned  topsr4;   /* Initial value of sr4                 */
       unsigned  r3;       /* Initial value of gr3                 */
       unsigned  cur_r19;  /* GR19 value of the calling routine.   */
     };                    /* Used only in HP-UX.                  */
    
     struct previous_frame_def {
       unsigned prev_frsize; /* frame size of calling routine.     */
       unsigned prevSP;   /* SP of calling routine.                */
       unsigned prevRLS;  /* PC_space of calling routine's caller. */
       unsigned prevRLO;  /* PC_offset of calling routine's caller.*/
       unsigned prevDP;   /* DP of calling routine.                */
       unsigned udescr0;  /* low word of calling routine's unwind  */
                          /* descriptor.                           */
       unsigned udescr1;  /* high word of calling routine's        */
                          /* unwind descriptor.                    */
       unsigned ustart;   /* start of the unwind region.           */
       unsigned uw_index; /* index into the unwind table.          */
       unsigned uend;     /* end of the unwind region.             */
       unsigned prev_r19; /* GR19 value of the caller's caller.    */
     };
    
     int U_get_previous_frame(
             struct current_frame_def   *curr.frame;
             struct previous_frame_def  *prev.frame);
    
    

Given a PC_space, a PC_offset value that is a return link to the caller, the frame size, and the DP and SP values of the called routine, these routines return the frame size, the DP and SP values of the caller's frame, and the (PC_space, PC_offset) value that is a return link to the caller's caller.

The routine returns:
0normal;
 
-1if curRLS, curRLO is nil, indicating stack was fully unwound;
 
-4if error occurs during linker stub unwinding other negative values less than -1 may be used in the future to indicate additional unexpected (internal) errors.
 
positiveif the frame is not unwindable for some reason.
Values currently used:
1 - no unwind_descriptor
0x7fffffff - cannot_unwind bit on in previous unwind descriptor
This is the interface for assembly programmers:
ARG0:Pointer to an eleven-word area of memory that contains the current frame info.
 
ARG1:Pointer to an eleven-word area of memory defined on exit as per definition of the previous_frame_info structure.
 
RET0:Return value defined on exit.
This routine is designed to enable access to the previous frame on the stack with input information about the current state. You may call this iteratively by setting the cur fields to the appropriate machine state, and then copying the first five prev values (and the prev_r19 value) into the corresponding fields for successive calls, until end-of-stack is reached.

When a nonzero value is returned, the fields that would normally get defined on exit are undefined.

If the frame of the called routine is the topmost frame on the stack when unwinding commences, cur_frsize should be zero on the initial call.




C.1 The Unwind Descriptor


C.3 Recover Utility Routines