void fakegc() { std::cout << "GC\n"; unw_cursor_t cursor; unw_word_t ip, sp; unw_context_t uc; root_info_t root_info_ptr; unw_getcontext(&uc); unw_init_local(&cursor, &uc); do { unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); // printf("ip=%p sp=%p\n", ip, sp); if (stk_map.find_root_info((void*)ip, root_info_ptr)) { for(auto it : root_info_ptr) { int *cptr = *((int**)sp - it); printf("x=%p\n", cptr); printf("i=%d\n", *cptr); *cptr = *cptr + 1; } } } while (unw_step(&cursor) > 0); }
void dumpStack(FILE* file, unw_cursor_t cursor) { int nframe = 0; char buffer[100]; unw_word_t off; do { const char * name = !unw_get_proc_name(&cursor, buffer, 100, &off) ? buffer : "?"; int status; // Unmangle C++ names: char* realname = abi::__cxa_demangle(name, 0, 0, &status); #if defined(__x86_64__) unw_word_t rip = 0; unw_word_t rsp = 0; unw_get_reg(&cursor, UNW_X86_64_RIP, &rip); unw_get_reg(&cursor, UNW_X86_64_RSP, &rsp); fprintf(file, " %i: %s (RIP=0x%" PRIx64 " RSP=0x%" PRIx64 ")\n", nframe, realname ? realname : name, (std::uint64_t) rip, (std::uint64_t) rsp); #else fprintf(file, " %i: %s\n", nframe, realname ? realname : name); #endif free(realname); ++nframe; } while(unw_step(&cursor)); }
static int vmprof_unw_step(unw_cursor_t *cp, int first_run) { void* ip; void* sp; ptrdiff_t sp_offset; unw_get_reg (cp, UNW_REG_IP, (unw_word_t*)&ip); unw_get_reg (cp, UNW_REG_SP, (unw_word_t*)&sp); if (!first_run) // make sure we're pointing to the CALL and not to the first // instruction after. If the callee adjusts the stack for us // it's not safe to be at the instruction after ip -= 1; sp_offset = vmprof_unw_get_custom_offset(ip, cp); if (sp_offset == -1) { // it means that the ip is NOT in JITted code, so we can use the // stardard unw_step return unw_step(cp); } else { // this is a horrible hack to manually walk the stack frame, by // setting the IP and SP in the cursor vmprof_hacked_unw_cursor_t *cp2 = (vmprof_hacked_unw_cursor_t*)cp; void* bp = (void*)sp + sp_offset; cp2->sp = bp; bp -= sizeof(void*); cp2->ip = ((void**)bp)[0]; // the ret is on the top of the stack minus WORD return 1; } }
void VSDebugLib::printStack() { unw_cursor_t cursor; unw_context_t uc; unw_word_t ip, sp, off; unw_proc_info_t pi; char file[256], name[256]; int line; int status; unw_getcontext(&uc); unw_init_local(&cursor, &uc); while (unw_step(&cursor) > 0) { unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); unw_get_proc_name (&cursor, name, sizeof (name), &off); getFileAndLine((long)ip, file, 256, &line); if (line >= 0) { char *realname; realname = abi::__cxa_demangle(name, 0, 0, &status); if (realname) { printf("%s: %s, %d\n", realname, file, line); free(realname); } else { printf("%s: %s, %d\n", name, file, line); } } } }
void collectStackRoots(TraceStack *stack) { unw_cursor_t cursor; unw_context_t uc; unw_word_t ip, sp, bp; // force callee-save registers onto the stack: // Actually, I feel like this is pretty brittle: // collectStackRoots itself is allowed to save the callee-save registers // on its own stack. jmp_buf registers __attribute__((aligned(sizeof(void*)))); #ifdef VALGRIND memset(®isters, 0, sizeof(registers)); memset(&cursor, 0, sizeof(cursor)); memset(&uc, 0, sizeof(uc)); memset(&ip, 0, sizeof(ip)); memset(&sp, 0, sizeof(sp)); memset(&bp, 0, sizeof(bp)); #endif setjmp(registers); assert(sizeof(registers) % 8 == 0); //void* stack_bottom = __builtin_frame_address(0); collectRoots(®isters, ®isters + 1, stack); unw_getcontext(&uc); unw_init_local(&cursor, &uc); TraceStackGCVisitor visitor(stack); int code; while (true) { int code = unw_step(&cursor); assert(code > 0 && "something broke unwinding!"); unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); unw_get_reg(&cursor, UNW_TDEP_BP, &bp); void* cur_sp = (void*)sp; void* cur_bp = (void*)bp; //std::string name = g.func_addr_registry.getFuncNameAtAddress((void*)ip, true); //if (VERBOSITY()) printf("ip = %lx (%s), stack = [%p, %p)\n", (long) ip, name.c_str(), cur_sp, cur_bp); unw_proc_info_t pip; unw_get_proc_info(&cursor, &pip); if (pip.start_ip == (uintptr_t)&__libc_start_main) { break; } if (pip.start_ip == (intptr_t)interpretFunction) { // TODO Do we still need to crawl the interpreter itself? gatherInterpreterRootsForFrame(&visitor, cur_bp); } collectRoots(cur_sp, (char*)cur_bp, stack); } }
static void throw_exception (MonoObject *exc, guint64 rethrow) { unw_context_t unw_ctx; MonoContext ctx; MonoJitInfo *ji; unw_word_t ip, sp; int res; if (mono_object_isinst (exc, mono_defaults.exception_class)) { MonoException *mono_ex = (MonoException*)exc; if (!rethrow) { mono_ex->stack_trace = NULL; mono_ex->trace_ips = NULL; } } res = unw_getcontext (&unw_ctx); g_assert (res == 0); res = unw_init_local (&ctx.cursor, &unw_ctx); g_assert (res == 0); /* * Unwind until the first managed frame. This is needed since * mono_handle_exception expects the variables in the original context to * correspond to the method returned by mono_find_jit_info. */ while (TRUE) { res = unw_get_reg (&ctx.cursor, UNW_IA64_IP, &ip); g_assert (res == 0); res = unw_get_reg (&ctx.cursor, UNW_IA64_SP, &sp); g_assert (res == 0); ji = mini_jit_info_table_find (mono_domain_get (), (gpointer)ip, NULL); //printf ("UN: %s %lx %lx\n", ji ? jinfo_get_method (ji)->name : "", ip, sp); if (ji) break; res = unw_step (&ctx.cursor); if (res == 0) { /* * This means an unhandled exception during the compilation of a * topmost method like Main */ break; } g_assert (res >= 0); } ctx.precise_ip = FALSE; mono_handle_exception (&ctx, exc); restore_context (&ctx); g_assert_not_reached (); }
bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool resolve) { // The cursor structure is pretty large, do not put it on the stack. unw_cursor_t* cursor = new unw_cursor_t; int ret = unw_init_local(cursor, &context_); if (ret < 0) { BACK_LOGW("unw_init_local failed %d", ret); delete cursor; return false; } std::vector<backtrace_frame_data_t>* frames = GetFrames(); frames->reserve(MAX_BACKTRACE_FRAMES); size_t num_frames = 0; do { unw_word_t pc; ret = unw_get_reg(cursor, UNW_REG_IP, &pc); if (ret < 0) { BACK_LOGW("Failed to read IP %d", ret); break; } unw_word_t sp; ret = unw_get_reg(cursor, UNW_REG_SP, &sp); if (ret < 0) { BACK_LOGW("Failed to read SP %d", ret); break; } if (num_ignore_frames == 0) { frames->resize(num_frames+1); backtrace_frame_data_t* frame = &frames->at(num_frames); frame->num = num_frames; frame->pc = static_cast<uintptr_t>(pc); frame->sp = static_cast<uintptr_t>(sp); frame->stack_size = 0; if (num_frames > 0) { // Set the stack size for the previous frame. backtrace_frame_data_t* prev = &frames->at(num_frames-1); prev->stack_size = frame->sp - prev->sp; } if (resolve) { frame->func_name = GetFunctionName(frame->pc, &frame->func_offset); frame->map = FindMap(frame->pc); } else { frame->map = NULL; frame->func_offset = 0; } num_frames++; } else { num_ignore_frames--; } ret = unw_step (cursor); } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES); delete cursor; return true; }
int backtrace(void **trace, int size) { unw_cursor_t cursor; unw_context_t uc; unw_word_t ip; int n = 0; unw_getcontext(&uc); unw_init_local(&cursor, &uc); while (unw_step(&cursor) > 0) { unw_get_reg(&cursor, UNW_REG_IP, &ip); trace[n++] = (void *)ip; { char buf[256]; unw_get_proc_name(&cursor, buf, 256, &ip); if (strncmp("_sigtramp", buf, sizeof("_sigtramp")) == 0) { goto darwin_sigtramp; } } } return n; darwin_sigtramp: /* darwin's bundled libunwind doesn't support signal trampoline */ { ucontext_t *uctx; /* get _sigtramp's ucontext_t and set values to cursor * http://www.opensource.apple.com/source/Libc/Libc-825.25/i386/sys/_sigtramp.s * http://www.opensource.apple.com/source/libunwind/libunwind-35.1/src/unw_getcontext.s */ unw_get_reg(&cursor, UNW_X86_64_RBX, &ip); uctx = (ucontext_t *)ip; unw_set_reg(&cursor, UNW_X86_64_RAX, uctx->uc_mcontext->__ss.__rax); unw_set_reg(&cursor, UNW_X86_64_RBX, uctx->uc_mcontext->__ss.__rbx); unw_set_reg(&cursor, UNW_X86_64_RCX, uctx->uc_mcontext->__ss.__rcx); unw_set_reg(&cursor, UNW_X86_64_RDX, uctx->uc_mcontext->__ss.__rdx); unw_set_reg(&cursor, UNW_X86_64_RDI, uctx->uc_mcontext->__ss.__rdi); unw_set_reg(&cursor, UNW_X86_64_RSI, uctx->uc_mcontext->__ss.__rsi); unw_set_reg(&cursor, UNW_X86_64_RBP, uctx->uc_mcontext->__ss.__rbp); unw_set_reg(&cursor, UNW_X86_64_RSP, 8+(uctx->uc_mcontext->__ss.__rsp)); unw_set_reg(&cursor, UNW_X86_64_R8, uctx->uc_mcontext->__ss.__r8); unw_set_reg(&cursor, UNW_X86_64_R9, uctx->uc_mcontext->__ss.__r9); unw_set_reg(&cursor, UNW_X86_64_R10, uctx->uc_mcontext->__ss.__r10); unw_set_reg(&cursor, UNW_X86_64_R11, uctx->uc_mcontext->__ss.__r11); unw_set_reg(&cursor, UNW_X86_64_R12, uctx->uc_mcontext->__ss.__r12); unw_set_reg(&cursor, UNW_X86_64_R13, uctx->uc_mcontext->__ss.__r13); unw_set_reg(&cursor, UNW_X86_64_R14, uctx->uc_mcontext->__ss.__r14); unw_set_reg(&cursor, UNW_X86_64_R15, uctx->uc_mcontext->__ss.__r15); ip = *(unw_word_t*)uctx->uc_mcontext->__ss.__rsp; unw_set_reg(&cursor, UNW_REG_IP, ip); trace[n++] = (void *)uctx->uc_mcontext->__ss.__rip; trace[n++] = (void *)ip; } while (unw_step(&cursor) > 0) { unw_get_reg(&cursor, UNW_REG_IP, &ip); trace[n++] = (void *)ip; } return n; }
void jffi_longjmp (jmp_buf env, int val) { extern int _jffi_longjmp_cont; unw_context_t uc; unw_cursor_t c; unw_word_t sp, ip, bp = 0; uintptr_t *wp = (uintptr_t *) env; int i, setjmp_frame; if (unw_getcontext (&uc) < 0 || unw_init_local (&c, &uc) < 0) { debug("failed to get context"); abort (); } #ifdef __x86_86__ # define UNW_REG_BP UNW_X86_64_RBP #else # define UNW_REG_BP UNW_X86_EBP #endif setjmp_frame = 0; do { char name[256]; unw_proc_info_t pi; unw_word_t off; if (unw_get_reg (&c, UNW_REG_BP, &bp) < 0) { abort(); } if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0) { abort(); } if (unw_get_reg (&c, UNW_REG_IP, &ip) < 0) { abort(); } unw_get_proc_name(&c, name, sizeof(name), &off); unw_get_proc_info(&c, &pi); // debug("frame %s ip=%llx sp=%llx bp=%llx wp[RP]=%p wp[SP]=%p, pi.start_ip=%llx, pi.end_ip=%llx", // name, (long long) ip, (long long) sp, (long long) bp, (void *) wp[JB_RP], (void *) wp[JB_SP], // pi.start_ip, pi.end_ip); if (wp[JB_SP] > sp || wp[JB_RP] < pi.start_ip || wp[JB_RP] > pi.end_ip) continue; /* found the right frame: */ // debug("found frame to jump back to"); assert (UNW_NUM_EH_REGS >= 2); if (unw_set_reg (&c, UNW_REG_EH + 0, wp[JB_RP]) < 0 || unw_set_reg (&c, UNW_REG_EH + 1, val) < 0 || unw_set_reg (&c, UNW_REG_IP, (unw_word_t) (uintptr_t) &_jffi_longjmp_cont)) abort (); unw_resume (&c); // should not reach here abort (); } while (unw_step (&c) > 0); // debug("failed to find correct frame to jmp to"); }
bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) { if (context == nullptr) { BACK_LOGW("The context is needed for offline backtracing."); return false; } context_ = context; unw_addr_space_t addr_space = unw_create_addr_space(&accessors, 0); unw_cursor_t cursor; int ret = unw_init_remote(&cursor, addr_space, this); if (ret != 0) { BACK_LOGW("unw_init_remote failed %d", ret); unw_destroy_addr_space(addr_space); return false; } size_t num_frames = 0; do { unw_word_t pc; ret = unw_get_reg(&cursor, UNW_REG_IP, &pc); if (ret < 0) { BACK_LOGW("Failed to read IP %d", ret); break; } unw_word_t sp; ret = unw_get_reg(&cursor, UNW_REG_SP, &sp); if (ret < 0) { BACK_LOGW("Failed to read SP %d", ret); break; } if (num_ignore_frames == 0) { frames_.resize(num_frames + 1); backtrace_frame_data_t* frame = &frames_[num_frames]; frame->num = num_frames; frame->pc = static_cast<uintptr_t>(pc); frame->sp = static_cast<uintptr_t>(sp); frame->stack_size = 0; if (num_frames > 0) { backtrace_frame_data_t* prev = &frames_[num_frames - 1]; prev->stack_size = frame->sp - prev->sp; } frame->func_name = GetFunctionName(frame->pc, &frame->func_offset); FillInMap(frame->pc, &frame->map); num_frames++; } else { num_ignore_frames--; } ret = unw_step(&cursor); } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES); unw_destroy_addr_space(addr_space); context_ = nullptr; return true; }
static int jl_unw_step(bt_cursor_t *cursor, uintptr_t *ip, uintptr_t *sp) { unw_word_t reg; if (unw_get_reg(cursor, UNW_REG_IP, ®) < 0) return 0; *ip = reg; if (unw_get_reg(cursor, UNW_REG_SP, ®) < 0) return 0; *sp = reg; return unw_step(cursor) > 0; }
void AS_UTL_catchCrash(int sig_num, siginfo_t *info, void *ctx) { WRITE_STRING("\nFailed with '"); WRITE_STRING(strsignal(sig_num)); WRITE_STRING("'\n"); WRITE_STRING("\nBacktrace (mangled):\n\n"); unw_cursor_t cursor; unw_context_t uc; unw_word_t ip, sp; int depth = 0; unw_getcontext(&uc); // Get state unw_init_local(&cursor, &uc); // Initialize state cursor while (unw_step(&cursor) > 0) { unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); unw_word_t off; char name[256]; if (unw_get_proc_name (&cursor, name, sizeof (name), &off) == 0) { if (off) fprintf(stderr, "%02d <%s + 0x%lx> ip=%lx sp=%lx\n", depth, name, (long)off, ip, sp); else fprintf(stderr, "%02d <%s> ip=%lx sp=%lx\n", depth, name, ip, sp); } else { fprintf(stderr, "%02d <?> ip=%lx sp=%lx\n", depth, ip, sp); } depth++; } //WRITE_STRING("\nBacktrace (demangled):\n\n"); //WRITE_STRING("\nGDB:\n\n"); //AS_UTL_envokeGDB(); // Pass the signal through, only so a core file can get generated. struct sigaction sa; sa.sa_handler = SIG_DFL; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction(sig_num, &sa, NULL); raise(sig_num); }
// Update REGDISPLAY from the unw_cursor_t and unw_context_t void UnwindCursorToRegDisplay(unw_cursor_t *cursor, unw_context_t *unwContext, REGDISPLAY *regDisplay) { #define GET_CONTEXT_POINTER(unwReg, rdReg) GetContextPointer(cursor, unwContext, unwReg, ®Display->p##rdReg); GET_CONTEXT_POINTERS #undef GET_CONTEXT_POINTER #ifdef CAN_LINK_SHARED_LIBUNWIND unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) ®Display->IP); unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) ®Display->SP); #endif // CAN_LINK_SHARED_LIBUNWIND #if defined(_ARM_) || defined(_ARM64_) regDisplay->IP |= 1; #endif }
_Unwind_VRS_Result _Unwind_VRS_Get( _Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, void *valuep) { _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, regclass=%d reg=%d, rep=%d, " "value=0x%0llX)\n", context, regclass, regno, representation, *((uint32_t*)valuep)); unw_cursor_t *cursor = (unw_cursor_t *)context; switch (regclass) { case _UVRSC_CORE: { if (representation != _UVRSD_UINT32) _LIBUNWIND_ABORT("Core register representation must be _UVRSD_UINT32."); return unw_get_reg(cursor, regno, (unw_word_t*)valuep) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; } // FIXME: Are these right? See 4.7 on lazy-saving case _UVRSC_WMMXD: case _UVRSC_WMMXC: case _UVRSC_VFP: { unw_fpreg_t value; if (unw_get_fpreg(cursor, regno, &value) != UNW_ESUCCESS) return _UVRSR_FAILED; switch (representation) { case _UVRSD_VFPX: // TODO(ajwong): What does this mean? break; case _UVRSD_UINT64: { uint64_t tmp; memcpy(&tmp, &value, sizeof(tmp)); *(uint64_t*)valuep = tmp; break; } case _UVRSD_FLOAT: { float tmp; memcpy(&tmp, &value, sizeof(tmp)); *(float*)valuep = tmp; break; } case _UVRSD_DOUBLE: { double tmp; memcpy(&tmp, &value, sizeof(tmp)); *(double*)valuep = tmp; break; } case _UVRSD_UINT32: { uint32_t tmp; memcpy(&tmp, &value, sizeof(tmp)); *(uint32_t*)valuep = tmp; break; } default: _LIBUNWIND_ABORT("Invalid VFP data representation."); } return _UVRSR_OK; } } return _UVRSR_NOT_IMPLEMENTED; }
vector<long> StackUnwind::fullUnwind() { #ifdef MAKE_DYNA return dynaUnwind(); #endif unw_getcontext(&uc); unw_init_local(&cursor, &uc); vector<long> call_stack; /* Need to step twice to remove mention of WMTrace from the call stack */ if (unw_step(&cursor) <= 0) return call_stack; if (unw_step(&cursor) <= 0) return call_stack; int counter = 0; while (unw_step(&cursor) > 0 && counter < unw_max_depth) { unw_get_reg(&cursor, UNW_REG_IP, &ip); call_stack.push_back((long) ip); counter++; } return call_stack; }
int xbt_libunwind_backtrace(void** bt, int size){ int i = 0; for(i=0; i < size; i++) bt[i] = nullptr; i=0; unw_cursor_t c; unw_context_t uc; unw_getcontext (&uc); unw_init_local (&c, &uc); unw_word_t ip; unw_step(&c); while(unw_step(&c) >= 0 && i < size){ unw_get_reg(&c, UNW_REG_IP, &ip); bt[i] = (void*)(long)ip; i++; } return i; }
static void pybacktrace(unw_cursor_t cursor) { unw_word_t bp; PyFrameObject *frame; PyObject *fileobj, *funcobj; int depth = 0; unw_get_reg(&cursor, UNW_X86_64_RBP, &bp); frame = (PyFrameObject*)bp; while (frame && (depth < MAX_STACK_DEPTH)) { fileobj = PyUnicode_AsUTF8String(frame->f_code->co_filename); funcobj = PyUnicode_AsUTF8String(frame->f_code->co_name); printf("%s(%d): %s\n", fileobj?PyBytes_AsString(fileobj):"???", PyFrame_GetLineNumber(frame), funcobj?PyBytes_AsString(funcobj):"???"); if (fileobj) Py_DECREF(fileobj); if (funcobj) Py_DECREF(funcobj); frame = frame->f_back; depth++; } }
void backtrace() { unw_cursor_t cursor; unw_context_t context; // Initialize cursor to current frame for local unwinding. unw_getcontext(&context); unw_init_local(&cursor, &context); // Unwind frames one by one, going up the frame stack. while (unw_step(&cursor) > 0) { unw_word_t offset, pc; unw_get_reg(&cursor, UNW_REG_IP, &pc); if (pc == 0) { break; } printf("0x%lx:", pc); char sym[256]; if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) { char* nameptr = sym; int status; char* demangled = abi::__cxa_demangle(sym, nullptr, nullptr, &status); if (status == 0) { nameptr = demangled; } char file[256]; int line = 0; getFileAndLine((long)pc, file, 256, &line); printf(" (%s+0x%lx) in %s:%d\n", nameptr, offset, file, line); free(demangled); } else { printf(" -- error: unable to obtain symbol name for this frame\n"); } } }
static int addIP(struct Context* ctx, unw_cursor_t* cursor) { if (ctx->skip) { --ctx->skip; return 0; } unw_word_t ip; int r = unw_get_reg(cursor, UNW_REG_IP, &ip); int err = checkError("unw_get_reg", r); if (err) return err; if (ctx->trace->frameCount == ctx->capacity) { size_t newCapacity = (ctx->capacity < 8 ? 8 : ctx->capacity * 1.5); uintptr_t* newBlock = realloc(ctx->trace->frameIPs, newCapacity * sizeof(uintptr_t)); if (!newBlock) { return -ENOMEM; } ctx->trace->frameIPs = newBlock; ctx->capacity = newCapacity; } ctx->trace->frameIPs[ctx->trace->frameCount++] = ip; return 0; /* success */ }
static ALWAYS_INLINE int slow_backtrace (void **buffer, int size, unw_context_t *uc, int skip) { unw_cursor_t cursor; unw_word_t ip; int n = 0; if (unlikely (unw_init_local (&cursor, uc) < 0)) return 0; while (unw_step (&cursor) > 0) { if (n >= size) return n; if (unw_get_reg (&cursor, UNW_REG_IP, &ip) < 0) return n; if (skip > 0) skip--; else buffer[n++] = (void *) (uintptr_t) ip; } return n; }
UINT64 Extrae_get_caller (int offset) { int current_deep = 0; unw_cursor_t cursor; unw_context_t uc; unw_word_t ip; if (unw_getcontext(&uc) < 0) return 0; if (unw_init_local(&cursor, &uc)) return 0; offset --; /* Don't compute call to unw_getcontext */ while (current_deep <= offset) { if (unw_get_reg(&cursor, UNW_REG_IP, &ip) < 0) break; #if defined(DEBUG) fprintf (stderr, "DEBUG: offset %d depth %d address %08llx %c\n", offset, current_deep, ip, (offset == current_deep)?'*':' '); #endif if (unw_step (&cursor) <= 0) return 0; current_deep ++; } return (UINT64) ip; }
// // Called by personality handler during phase 2 to get register values // EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index) { unw_cursor_t* cursor = (unw_cursor_t*)context; unw_word_t result; unw_get_reg(cursor, index, &result); DEBUG_PRINT_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%llX\n", context, index, (uint64_t)result); return result; }
PROTECTED unsigned long _Unwind_GetCFA (struct _Unwind_Context *context) { unw_word_t val; unw_get_reg (&context->cursor, UNW_REG_SP, &val); return val; }
/// Called by personality handler during phase 2 to get instruction pointer. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_word_t result; unw_get_reg(cursor, UNW_REG_IP, &result); _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%llX\n", context, (uint64_t) result); return (uintptr_t)result; }
G_GNUC_UNUSED static void print_ctx (MonoContext *ctx) { char name[256]; unw_word_t off, ip, sp; unw_proc_info_t pi; int res; unw_get_proc_name (&ctx->cursor, name, 256, &off); unw_get_proc_info(&ctx->cursor, &pi); res = unw_get_reg (&ctx->cursor, UNW_IA64_IP, &ip); g_assert (res == 0); res = unw_get_reg (&ctx->cursor, UNW_IA64_SP, &sp); g_assert (res == 0); printf ("%s:%lx [%lx-%lx] SP: %lx\n", name, ip - pi.start_ip, pi.start_ip, pi.end_ip, sp); }
void unwindExc(Box* exc_obj) { unw_cursor_t cursor; unw_context_t uc; unw_word_t ip, sp; unw_getcontext(&uc); unw_init_local(&cursor, &uc); int code; unw_proc_info_t pip; while (unw_step(&cursor) > 0) { unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); printf("ip = %lx, sp = %lx\n", (long)ip, (long)sp); code = unw_get_proc_info(&cursor, &pip); RELEASE_ASSERT(code == 0, ""); // printf("%lx %lx %lx %lx %lx %lx %d %d %p\n", pip.start_ip, pip.end_ip, pip.lsda, pip.handler, pip.gp, // pip.flags, pip.format, pip.unwind_info_size, pip.unwind_info); assert((pip.lsda == 0) == (pip.handler == 0)); assert(pip.flags == 0); if (pip.handler == 0) { if (VERBOSITY()) printf("Skipping frame without handler\n"); continue; } printf("%lx %lx %lx\n", pip.lsda, pip.handler, pip.flags); // assert(pip.handler == (uintptr_t)__gxx_personality_v0 || pip.handler == (uintptr_t)__py_personality_v0); // auto handler_fn = (int (*)(int, int, uint64_t, void*, void*))pip.handler; ////handler_fn(1, 1 /* _UA_SEARCH_PHASE */, 0 /* exc_class */, NULL, NULL); // handler_fn(2, 2 /* _UA_SEARCH_PHASE */, 0 /* exc_class */, NULL, NULL); unw_set_reg(&cursor, UNW_REG_IP, 1); // TODO testing: // unw_resume(&cursor); } abort(); }
static void luw_backtrace() { unw_cursor_t cursor; unw_context_t context; unw_getcontext(&context); unw_init_local(&cursor, &context); std::stringstream output; output << "Traceback (most recent call first):" << std::endl; while (unw_step(&cursor) > 0) { unw_word_t pc; unw_get_reg(&cursor, UNW_REG_IP, &pc); if (pc == 0) break; const char *file = NULL; const char *func = NULL; unsigned line = 0; resolve(pc, &file, &line, &func); if (file != NULL) { if (strcmp("__cxa_throw", func) == 0) continue; if (strncmp(func, "_Z", 2) == 0) { // This is a C++ mangled name (as per the IA-64 spec) output << " 0x" << std::hex << pc << std::dec << " " << demangle(func) << " (" << file << ":" << line << ")" << std::endl; } else { output << " 0x" << std::hex << pc << std::dec << " " << func << " (" << file << ":" << line << ")" << std::endl; } // Try to load the file and print the offending line std::ifstream f; f.open(file); if (!f.is_open()) { output << " <unable to find file>" << std::endl; } else { seek_to_line(f, line); std::string line; std::getline(f, line); output << " " << line << std::endl; } } else { output << " <unknown> (<unknown file>:<unknown line>)" << std::endl; } } output << std::endl; __latest_backtrace = output.str(); }
PROTECTED unsigned long _Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn) { unw_word_t val; unw_get_reg (&context->cursor, UNW_REG_IP, &val); *ip_before_insn = unw_is_signal_frame (&context->cursor); return val; }
/// Called by personality handler during phase 2 to get register values. _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { unw_cursor_t *cursor = (unw_cursor_t *)context; unw_word_t result; unw_get_reg(cursor, index, &result); _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIx64 "\n", (void *)context, index, (uint64_t)result); return (uintptr_t)result; }
void log_stack_trace(const char *msg) { #ifdef USE_UNWIND unw_context_t ctx; unw_cursor_t cur; unw_word_t ip, off; unsigned level; char sym[512], *dsym; int status; const char *log = stack_trace_log.empty() ? NULL : stack_trace_log.c_str(); #endif if (msg) ST_LOG(msg); ST_LOG("Unwound call stack:"); #ifdef USE_UNWIND if (unw_getcontext(&ctx) < 0) { ST_LOG("Failed to create unwind context"); return; } if (unw_init_local(&cur, &ctx) < 0) { ST_LOG("Failed to find the first unwind frame"); return; } for (level = 1; level < 999; ++level) { // 999 for safety int ret = unw_step(&cur); if (ret < 0) { ST_LOG("Failed to find the next frame"); return; } if (ret == 0) break; if (unw_get_reg(&cur, UNW_REG_IP, &ip) < 0) { ST_LOG(" " << std::setw(4) << level); continue; } if (unw_get_proc_name(&cur, sym, sizeof(sym), &off) < 0) { ST_LOG(" " << std::setw(4) << level << std::setbase(16) << std::setw(20) << "0x" << ip); continue; } dsym = abi::__cxa_demangle(sym, NULL, NULL, &status); ST_LOG(" " << std::setw(4) << level << std::setbase(16) << std::setw(20) << "0x" << ip << " " << (!status && dsym ? dsym : sym) << " + " << "0x" << off); free(dsym); } #else std::stringstream ss; ss << el::base::debug::StackTrace(); std::vector<std::string> lines; std::string s = ss.str(); boost::split(lines, s, boost::is_any_of("\n")); for (const auto &line: lines) ST_LOG(line); #endif }