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