📄 stack.c
字号:
/* Return a handle for the frame pointer at the current point in execution. */staticunsigned long *getframe(void){#if SYSTEM == SYSTEM_DRSNX || SYSTEM == SYSTEM_SOLARIS ucontext_t c;#endif /* SYSTEM */ unsigned long a;#if SYSTEM == SYSTEM_DRSNX || SYSTEM == SYSTEM_SOLARIS if (getcontext(&c) == -1) return NULL; a = c.uc_mcontext.gregs[R_SP];#else /* SYSTEM */ a = __mp_stackpointer();#endif /* SYSTEM */#if ENVIRON == ENVIRON_64 return (unsigned long *) (a + 0x7FF) + 14;#else /* ENVIRON */ return (unsigned long *) a + 14;#endif /* ENVIRON */}#endif /* ARCH */#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT && TARGET *//* Return a handle for the stack frame at the current point in execution * or the next stack frame in the call stack. */MP_GLOBALint__mp_getframe(stackinfo *p){#if MP_BUILTINSTACK_SUPPORT void *f;#elif MP_LIBRARYSTACK_SUPPORT#if TARGET == TARGET_UNIX#if SYSTEM == SYSTEM_HPUX frameinfo f;#elif SYSTEM == SYSTEM_TRU64 char *s;#endif /* SYSTEM */#elif TARGET == TARGET_WINDOWS jmp_buf j;#endif /* TARGET */#else /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */#if MP_SIGINFO_SUPPORT struct sigaction i;#endif /* MP_SIGINFO_SUPPORT */#if (TARGET == TARGET_UNIX && (ARCH == ARCH_IX86 || ARCH == ARCH_M68K || \ ARCH == ARCH_M88K || ARCH == ARCH_POWER || ARCH == ARCH_POWERPC || \ ARCH == ARCH_SPARC)) || ((TARGET == TARGET_WINDOWS || \ TARGET == TARGET_NETWARE) && ARCH == ARCH_IX86) unsigned long *f;#endif /* TARGET && ARCH */#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */ int r; r = 0;#if MP_BUILTINSTACK_SUPPORT if (p->index == 0) { /* We use the macros defined above to fill in the arrays of frame * pointers and return addresses. These macros rely on the fact that * if there are no more frames in the call stack then the builtin * functions will return NULL. If this is not the case then the * library will crash. */ frameaddresses(p->frames, f, MP_MAXSTACK); returnaddresses(p->addrs, f, MP_MAXSTACK); } if ((p->index++ < MP_MAXSTACK) && (p->frame = p->frames[p->index - 1])) { p->addr = p->addrs[p->index - 1]; r = 1; } else { p->frame = NULL; p->addr = NULL; p->index = MP_MAXSTACK; }#elif MP_LIBRARYSTACK_SUPPORT /* HP/UX, IRIX, Tru64 and Windows platforms provide a library for * traversing function call stack frames since the stack frame format * does not necessarily preserve frame pointers. On HP/UX this is done * via a special section which can be read by debuggers. */#if TARGET == TARGET_UNIX#if SYSTEM == SYSTEM_HPUX if (p->frame == NULL) { __mp_frameinfo(&p->next); if (U_get_previous_frame(&p->next, &f) == 0) { p->next.size = f.size; p->next.sp = f.sp; p->next.ps = f.ps; p->next.pc = f.pc; p->next.dp = f.dp; } else __mp_memset(&p->next, 0, sizeof(frameinfo)); } if (p->next.pc && (U_get_previous_frame(&p->next, &f) == 0)) { p->frame = (void *) p->next.sp; p->addr = (void *) (p->next.pc & ~3); p->next.size = f.size; p->next.sp = f.sp; p->next.ps = f.ps; p->next.pc = f.pc; p->next.dp = f.dp; r = 1; } else { p->frame = NULL; p->addr = NULL; }#elif SYSTEM == SYSTEM_IRIX || SYSTEM == SYSTEM_TRU64 /* On IRIX and Tru64, the unwind() function may call malloc(), free() and * some memory operation functions every time it is invoked. Despite the * fact that we guard against recursion here, it may slow down execution to * an unbearable pace, so it might be an idea to remove malloc.c from the * mpatrol library if you have the option of recompiling all of your * sources to include mpatrol.h. */ if (!recursive) { recursive = 1; if (p->frame == NULL) {#if SYSTEM == SYSTEM_IRIX exc_setjmp(&p->next);#elif SYSTEM == SYSTEM_TRU64 exc_capture_context(&p->next);#endif /* SYSTEM */ unwind(&p->next, NULL); } if (p->next.sc_pc != 0) { /* On IRIX, the sigcontext structure stores registers in 64-bit * format so we must be careful when converting them to 32-bit * quantities. */#if SYSTEM == SYSTEM_IRIX p->frame = (void *) p->next.sc_regs[CXT_SP];#elif SYSTEM == SYSTEM_TRU64 p->frame = (void *) p->next.sc_regs[R_SP];#endif /* SYSTEM */ p->addr = (void *) p->next.sc_pc;#if SYSTEM == SYSTEM_TRU64 /* On Tru64 we cannot reliably unwind the stack from file scope * initialisation or finalisation functions, or from exception- * handling support functions. Unfortunately, this means we must * look at the names of the calling functions, which is likely to * fail if the executable file has been stripped. */ if (((s = __mp_symbol(p->addr)) == NULL) || ((strncmp(s, "__INIT_00_add_", 14) != 0) && (strncmp(s, "__FINI_00_remove_", 17) != 0) && (strncmp(s, "__exc_add_", 10) != 0) && (strncmp(s, "__exc_remove_", 13) != 0))) {#endif /* SYSTEM */ unwind(&p->next, NULL); r = 1;#if SYSTEM == SYSTEM_TRU64 } else { p->frame = NULL; p->addr = NULL; }#endif /* SYSTEM */ } else { p->frame = NULL; p->addr = NULL; } recursive = 0; }#endif /* SYSTEM */#elif TARGET == TARGET_WINDOWS if (p->frame == NULL) { if (p->first == NULL) { setjmp(j); p->next.AddrPC.Offset = ((_JUMP_BUFFER *) &j)->Eip; p->next.AddrFrame.Offset = ((_JUMP_BUFFER *) &j)->Ebp; p->next.AddrStack.Offset = ((_JUMP_BUFFER *) &j)->Esp; } else { p->next.AddrPC.Offset = ((CONTEXT *) p->first)->Eip; p->next.AddrFrame.Offset = ((CONTEXT *) p->first)->Ebp; p->next.AddrStack.Offset = ((CONTEXT *) p->first)->Esp; } p->next.AddrPC.Mode = AddrModeFlat; p->next.AddrFrame.Mode = AddrModeFlat; p->next.AddrStack.Mode = AddrModeFlat; } if (StackWalk(IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), GetCurrentThread(), &p->next, NULL, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL) && p->next.AddrReturn.Offset) { p->frame = (void *) p->next.AddrFrame.Offset; p->addr = (void *) p->next.AddrReturn.Offset; r = 1; } else { p->frame = NULL; p->addr = NULL; __mp_memset(&p->next, 0, sizeof(STACKFRAME)); }#endif /* TARGET */#else /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */#if (TARGET == TARGET_UNIX && (ARCH == ARCH_IX86 || ARCH == ARCH_M68K || \ ARCH == ARCH_M88K || ARCH == ARCH_POWER || ARCH == ARCH_POWERPC || \ ARCH == ARCH_SPARC)) || ((TARGET == TARGET_WINDOWS || \ TARGET == TARGET_NETWARE) && ARCH == ARCH_IX86) /* This section is not complete in any way for the OS / processor * combinations it supports, as it is intended to be as portable as possible * without writing in assembler. In particular, optimised code is likely * to cause major problems for stack traversal on some platforms. */#if TARGET == TARGET_UNIX#if MP_SIGINFO_SUPPORT i.sa_flags = 0; (void *) i.sa_handler = (void *) stackhandler; sigfillset(&i.sa_mask); sigaction(SIGBUS, &i, &bushandler); sigaction(SIGSEGV, &i, &segvhandler);#else /* MP_SIGINFO_SUPPORT */ bushandler = signal(SIGBUS, stackhandler); segvhandler = signal(SIGSEGV, stackhandler);#endif /* MP_SIGINFO_SUPPORT */ if (setjmp(environment)) __mp_newframe(p, p->first); else#endif /* TARGET */ { if (p->frame == NULL) if (p->first == NULL)#if ARCH == ARCH_IX86 || ARCH == ARCH_M68K f = (unsigned long *) &p - 2;#elif ARCH == ARCH_M88K f = (unsigned long *) &p - 4;#elif ARCH == ARCH_POWER || ARCH == ARCH_POWERPC f = (unsigned long *) &p - 6;#elif ARCH == ARCH_SPARC f = getframe();#endif /* ARCH */ else f = (unsigned long *) p->first; else f = (unsigned long *) p->next; if (p->frame = f) { p->addr = getaddr(f); /* We cache the next frame pointer in the call stack since on some * systems it may be overwritten by another call. */#if ARCH == ARCH_IX86 || ARCH == ARCH_M68K || ARCH == ARCH_M88K || \ ARCH == ARCH_POWER || ARCH == ARCH_POWERPC#if SYSTEM == SYSTEM_LYNXOS if (!getaddr((unsigned long *) *f)) p->next = NULL; else#endif /* SYSTEM */ p->next = (void *) *f;#elif ARCH == ARCH_SPARC if (p->addr == NULL) p->next = NULL; else#if ENVIRON == ENVIRON_64 p->next = (void *) ((unsigned long *) (*f + 0x7FF) + 14);#else /* ENVIRON */ p->next = (void *) ((unsigned long *) *f + 14);#endif /* ENVIRON */#endif /* ARCH */ r = 1; } }#if TARGET == TARGET_UNIX#if MP_SIGINFO_SUPPORT sigaction(SIGBUS, &bushandler, NULL); sigaction(SIGSEGV, &segvhandler, NULL);#else /* MP_SIGINFO_SUPPORT */ signal(SIGBUS, bushandler); signal(SIGSEGV, segvhandler);#endif /* MP_SIGINFO_SUPPORT */#endif /* TARGET */#elif TARGET == TARGET_UNIX && ARCH == ARCH_MIPS /* For the MIPS architecture we perform code reading to determine the * frame pointers and the return addresses. */#if MP_SIGINFO_SUPPORT i.sa_flags = 0; (void *) i.sa_handler = (void *) stackhandler; sigfillset(&i.sa_mask); sigaction(SIGBUS, &i, &bushandler); sigaction(SIGSEGV, &i, &segvhandler);#else /* MP_SIGINFO_SUPPORT */ bushandler = signal(SIGBUS, stackhandler); segvhandler = signal(SIGSEGV, stackhandler);#endif /* MP_SIGINFO_SUPPORT */ if (setjmp(environment)) __mp_newframe(p, p->first); else { if (p->frame == NULL) unwind(&p->next); if ((p->next.ra) && unwind(&p->next)) { p->frame = (void *) p->next.sp; p->addr = (void *) (p->next.ra - 8); r = 1; } else { p->frame = NULL; p->addr = NULL; } }#if MP_SIGINFO_SUPPORT sigaction(SIGBUS, &bushandler, NULL); sigaction(SIGSEGV, &segvhandler, NULL);#else /* MP_SIGINFO_SUPPORT */ signal(SIGBUS, bushandler); signal(SIGSEGV, segvhandler);#endif /* MP_SIGINFO_SUPPORT */#endif /* TARGET && ARCH */#endif /* MP_BUILTINSTACK_SUPPORT && MP_LIBRARYSTACK_SUPPORT */ return r;}#ifdef __cplusplus}#endif /* __cplusplus */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -