RTStack__PrevFrame (Frame* callee, Frame* caller) { PRUNTIME_FUNCTION fun; void *proc; char *file, *name; if (callee->lock != FrameLock) abort (); *caller = *callee; /* see if the unwind has any chance of working... */ fun = (PRUNTIME_FUNCTION) __exc_lookup_function_entry (callee->cxt.sc_pc); if (fun == 0) { caller->pc = caller->sp = caller->unwind = 0; return; } __exc_virtual_unwind (fun, &(caller->cxt)); caller->pc = caller->cxt.sc_pc; caller->sp = caller->cxt.sc_sp; RTProcedureSRC_FromPC((void *)(callee->pc), &proc, &file, &name); if (proc == RTHeapDep_Fault) { /* SIGNAL HANDLER: previous frame before signal trampoline */ caller->unwind = 0; /* unwind directly to handler */ } else if (caller->unwind) { caller->unwind = caller->pc; } if (caller->lock != FrameLock) abort (); }
void RTStack__PrevFrame (Frame* callee, Frame* caller) { ucontext_t *link; struct frame *link_sp, *link_fp; void *proc; char *file, *name; if (callee == 0) abort(); if (caller == 0) abort(); if (callee->lock != FrameLock) abort(); RTStack__Flush(); caller->lock = FrameLock; RTProcedureSRC_FromPC(callee->pc, &proc, &file, &name); if (proc == RTHeapDep_Fault) { /* SIGNAL HANDLER: previous frame information can be found in third argument of RTHeapDep_Fault */ link = (ucontext_t *)callee->sp->fr_arg[2]; caller->ctxt = *link; caller->pc = (void *)link->uc_mcontext.gregs[REG_PC]; caller->unwind = 0; /* unwind directly to handler */ if (caller->pc) { caller->sp = (struct frame *)link->uc_mcontext.gregs[REG_SP]; caller->fp = caller->sp->fr_savfp; } else caller->sp = caller->fp = 0; } else { caller->pc = (void *)callee->sp->fr_savpc; if (caller->pc) { (int)caller->unwind = (int)(caller->pc) + 8; /* for return address */ caller->fp = (caller->sp = callee->fp)->fr_savfp; } else caller->unwind = caller->sp = caller->fp = 0; caller->ctxt = callee->ctxt; } if (caller->lock != FrameLock) abort(); }