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

D.6 Advanced Example

MPE documents

Complete PDF
Table of Contents

This section presents an implementation, written in C and PA-RISC assembly language, of a routine to write a stack trace into a character string.

Since a full stack trace requires access to the symbol tables in the program file, we have omitted the symbols from the output. This example illustrates the use of U_get_previous_frame, which is the core of the unwind library.

  /* Start of cfile.c */
  #include <stdio.h>
    typedef 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.    */
  } UWREC;               /* Used only in HP-UX.                   */

  main()
  {
      char str[100];
      gen_stack_trace(str);
      printf("%s0\n", str);
  }

  gen_stack_trace(outstr)
  char *outstr;
  {
    unsigned sp, pc, rp;
    UWREC recl;
    int depth;

    sp = &outstr + 9;
    pc = (* (int *) (sp - 20)) & ~3;
    rp = 0;
    get_pcspace(&recl);
    recl.cursp = sp;
    rec1.currlo = pc;
    rec1.toprp = rp;

    for (depth = 0; rec1.currlo; depth++) {
      sprintf (outstr, "%s (%2d) 0x%x0\n",
        outstr, depth, rec1.currlo);
      if ( get_NextFrame (&rec1) == -1)
        return;
    }
  }

  /* Get information about the next frame on stack. */
  int get_NextFrame (precl)
  UWREC   *prec1;   /* sp to return */
  {
    int     stat;
    UVREC   rec2;

    stat = U_get_previous_frame (precl, &rec2);
    if (stat) {
      fprintf (stderr, "Stack_Trace: error while unwinding stack\n");
      return (-1);
    }

    prec1->currlo       = rec2.currlo    ;
    precl->cur_frsize   = rec2.cur_frsize;
    precl->cursp        = rec2.cursp     ;
    prec1->currls       = rec2.currls    ;
    precl->curdp        = rec2.curdp     ;

    return(0);
  } /* NextFrame */


  /*-----------------------------------------------------------------
  * Start of sfile.s
  */
  /*
  * get_pcspace is an assembly routine that fills the pcspace field
  * of current frame record with the sr4 value.
  */
        .space  $TEXT$
        .subspa $CODE$
        .export get_pcspace,code
  get_pcspace
        .proc
        .callinfo
        mfsp    sr4,r20
        bv      r0(rp)
        stw     r20,8(arg0)   ; store caller's PC space
        .procend
        .end




D.5 Unwinding Across an Interrupt Marker


Table of Contents