#include #include #include #include #include "stack.h" static void **_stack_area = 0; static void **_stack_curr = 0; static size_t _stack_size = 0; #if !defined(SOLARIS) && !defined(LINUX) void stack_init(int size) { fprintf(stderr, "stack error: platform not supported yet... functionality disabled\n"); } #else void stack_init(int size) { extern void * _mdbg_morecore(size_t); _stack_size = size; if (!(_stack_area = _mdbg_morecore(size))) { fprintf(stderr, "stack error: cannot get memory for stack... functionality disabled\n"); return; } _stack_curr = _stack_area; } #endif void *stack_curr_get() { return (void *) _stack_curr; } int stack_print(void *ptr) { Dl_info info; if (dladdr(ptr, &info)) { fprintf(stderr, " %08p file: %s\tfunction: %s\n", info.dli_saddr, info.dli_fname ? info.dli_fname : "???", info.dli_sname ? info.dli_sname : "???"); #ifdef LINUX if (!strcmp(info.dli_fname, "__libc_start_main ")) return 1; #endif } else return 1; // fprintf(stderr, "stack warning: dladdr failed to retrieve information\n"); return 0; } void stack_dump(int n, void *ptr) { int i; void **p; if (!_stack_area) return; if (n < 0 || n > _stack_size - 2) { fprintf(stderr, "stack error: bad stack count\n"); return; } p = (void **) ptr; if (p < _stack_area || p > _stack_curr) { fprintf(stderr, "stack error: bad stack pointer\n"); return; } for (i = 1; i < n - 1; i++) { Dl_info info; if (dladdr(p[i], &info)) { fprintf(stderr, " [%d] %08p file: %s\tfunction: %s\n", n - i - 1, info.dli_saddr, info.dli_fname ? info.dli_fname : "???", info.dli_sname ? info.dli_sname : "???"); } else fprintf(stderr, "stack warning: dladdr failed to retrieve information for %x\n", ptr); } } #if defined(SOLARIS) #include #else struct frame { struct frame *fr_savfp; void *fr_savpc; }; #define REG_SP REG_EBP #endif struct frame * _stack_frame_get() { ucontext_t u; (void) getcontext(&u); return (((struct frame *) u.uc_mcontext.gregs[REG_SP])->fr_savfp); } void _stack_live_trace(struct frame *fp) { /* skip upper function stack: */ if (fp) fp = fp->fr_savfp; /* descend stack: */ while (fp && !stack_print((void *) fp->fr_savpc)) { fp = fp->fr_savfp; } } void stack_live_dump() { _stack_live_trace(_stack_frame_get()); } int _stack_trace(struct frame *fp) { int i = 0; if (_stack_curr >= (_stack_area + _stack_size - 2)) { fprintf(stderr, "NO MORE ROOM FOR STACK TRACES\n"); return 0; } while (fp && _stack_curr < (_stack_area + _stack_size - 2)) { *_stack_curr = (void *) fp->fr_savpc; _stack_curr++; fp = fp->fr_savfp; i++; } return i; } int stack_trace() { if (!_stack_area) return 0; if (_stack_curr >= _stack_area + _stack_size - 2) return 0; return _stack_trace(_stack_frame_get()); }