void get_callstack(size_t n, callstack *pbt) { pbt->alloc_size = n; pbt->count = 0; // static void *gHandle = NULL; // static unwindFn unwind_backtrace = NULL; // const char so_path[] = "/system/lib/libcorkscrew.so"; // if(gHandle == NULL) // gHandle = dlopen(so_path, RTLD_NOW); // if (gHandle != NULL && !unwind_backtrace) // unwind_backtrace = (unwindFn)dlsym(gHandle, "unwind_backtrace"); // if (unwind_backtrace == NULL) // return; // backtrace_frame_t stacks[20]; // int count = unwind_backtrace(stacks, 1, 20); // if (count <= 0) // return; // for (int i = 0; i < size; ++i) { // pbt->stacks[i] = stacks[i]; // stacks[i].absolute_pc; // } // pbt->count = size; _Unwind_Backtrace(unwind_callback, pbt); }
int __gnat_backtrace (void ** traceback, int max_len, void * exclude_min, void * exclude_max, int skip_frames) { #if defined (__USING_SJLJ_EXCEPTIONS__) /* We have no unwind material (tables) at hand with sjlj eh, and no way to retrieve complete and accurate call chain information from the context stack we maintain. */ return 0; #else uw_data_t uw_data; /* State carried over during the whole unwinding process. */ uw_data.traceback = traceback; uw_data.max_len = max_len; uw_data.exclude_min = exclude_min; uw_data.exclude_max = exclude_max; uw_data.n_frames_to_skip = skip_frames; uw_data.n_frames_skipped = 0; uw_data.n_entries_filled = 0; _Unwind_Backtrace ((_Unwind_Trace_Fn)trace_callback, &uw_data); return uw_data.n_entries_filled; #endif }
size_t captureBacktrace(void** buffer, size_t max) { test_debug::BacktraceState state = {buffer, buffer + max}; _Unwind_Backtrace(test_debug::unwindCallback, &state); return state.current - buffer; }
void Util_BacktraceToBuffer(uintptr_t *basePtr, // IN: uintptr_t *buffer, // IN: int len) // IN: { #if defined(UTIL_BACKTRACE_USE_UNWIND) struct UtilBacktraceToBufferData data; data.basePtr = (uintptr_t)basePtr; data.buffer = buffer; data.len = len; _Unwind_Backtrace(UtilBacktraceToBufferCallback, &data); #elif !defined(VM_X86_64) uintptr_t *x = basePtr; int i; for (i = 0; i < 256 && i < len; i++) { if (x < basePtr || (uintptr_t) x - (uintptr_t) basePtr > 0x8000) { break; } buffer[i] = x[1]; x = (uintptr_t *) x[0]; } #endif }
void FAndroidPlatformStackWalk::CaptureStackBackTrace(uint64* BackTrace, uint32 MaxDepth, void* Context) { // Make sure we have place to store the information if (BackTrace == NULL || MaxDepth == 0) { return; } // zero results FPlatformMemory::Memzero(BackTrace, MaxDepth*sizeof(uint64)); #if PLATFORM_ANDROID_ARM if (Context != nullptr) { // Android signal handlers always catch signals before user handlers and passes it down to user later // _Unwind_Backtrace does not use signal context and will produce wrong callstack in this case // We use code from libcorkscrew to unwind backtrace using actual signal context // Code taken from https://android.googlesource.com/platform/system/core/+/jb-dev/libcorkscrew/arch-arm/backtrace-arm.c unwind_backtrace_signal(Context, BackTrace, MaxDepth); return; } #endif //PLATFORM_ANDROID_ARM AndroidStackWalkHelpers::BackTrace = BackTrace; AndroidStackWalkHelpers::MaxDepth = MaxDepth; uint32 Depth = 0; _Unwind_Backtrace(AndroidStackWalkHelpers::BacktraceCallback, &Depth); }
/* Copy context infos (signal code, etc.) */ static void coffeecatch_copy_context(native_code_handler_struct *const t, const int code, siginfo_t *const si, void *const sc) { t->code = code; t->si = *si; if (sc != NULL) { ucontext_t *const uc = (ucontext_t*) sc; t->uc = *uc; } else { memset(&t->uc, 0, sizeof(t->uc)); } #ifdef USE_UNWIND /* Frame buffer initial position. */ t->frames_size = 0; /* Skip us and the caller. */ t->frames_skip = 2; /* Use the corkscrew library to extract the backtrace. */ #ifdef USE_CORKSCREW t->frames_size = coffeecatch_backtrace_signal(si, sc, t->frames, 0, BACKTRACE_FRAMES_MAX); #else /* Unwind frames (equivalent to backtrace()) */ _Unwind_Backtrace(coffeecatch_unwind_callback, t); #endif if (t->frames_size != 0) { DEBUG(print("called _Unwind_Backtrace()\n")); } else { DEBUG(print("called _Unwind_Backtrace(), but no traces\n")); } #endif }
int backtrace_full (struct backtrace_state *state, int skip, backtrace_full_callback callback, backtrace_error_callback error_callback, void *data) { struct backtrace_data bdata; void *p; bdata.skip = skip + 1; bdata.state = state; bdata.callback = callback; bdata.error_callback = error_callback; bdata.data = data; bdata.ret = 0; /* If we can't allocate any memory at all, don't try to produce file/line information. */ p = backtrace_alloc (state, 4096, NULL, NULL); if (p == NULL) bdata.can_alloc = 0; else { backtrace_free (state, p, 4096, NULL, NULL); bdata.can_alloc = 1; } _Unwind_Backtrace (unwind, &bdata); return bdata.ret; }
__LIBC_HIDDEN__ int get_backtrace(uintptr_t* frames, size_t max_depth) { ScopedDisableDebugCalls disable; stack_crawl_state_t state(frames, max_depth); _Unwind_Backtrace(trace_function, &state); return state.frame_count; }
void test_backtrace() { int n = 0; _Unwind_Backtrace(&callback, &n); if (n < EXPECTED_NUM_FRAMES) { abort(); } }
int xbt_backtrace_no_malloc(void **array, int size) { int i = 0; for(i=0; i < size; i++) array[i] = NULL; struct trace_arg arg = { .array = array, .size = size, .cnt = -1 }; if (size >= 1) _Unwind_Backtrace(backtrace_helper, &arg); /* _Unwind_Backtrace on IA-64 seems to put NULL address above _start. Fix it up here. */ if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL) --arg.cnt; return arg.cnt != -1 ? arg.cnt : 0; } void xbt_backtrace_current(xbt_ex_t * e) { e->used = backtrace((void **) e->bt, XBT_BACKTRACE_SIZE); if (e->used == 0) { fprintf(stderr, "The backtrace() function failed, which probably means that the memory is exhausted. Here is a crude dump of the exception that I was trying to build:"); fprintf(stderr, "%s(%d) [%s:%d] %s", e->procname, e->pid, e->file, e->line, e->msg); fprintf(stderr, "Bailing out now since there is nothing I can do without a decent amount of memory. Please go fix the memleaks\n"); exit(1); } }
void backtrace_startup() { ScopedDisableDebugCalls disable; g_map_data = MapData::Create(); if (g_map_data) { _Unwind_Backtrace(find_current_map, nullptr); } }
static inline int get_backtrace(intptr_t* addrs, size_t max_entries) { stack_crawl_state_t state; state.count = max_entries; state.addrs = (intptr_t*)addrs; _Unwind_Backtrace(trace_function, (void*)&state); return max_entries - state.count; }
int backtrace (void **array, int size) { struct trace_context t; t.array = array; t.size = size; t.index = 0; _Unwind_Backtrace(trace_fn, &t); return t.index - 1; }
int main (void) { /* Arrange for this test to be killed if _Unwind_Backtrace runs into an endless loop. We cannot use the test driver because the complete call chain needs to be compiled with -funwind-tables so that _Unwind_Backtrace is able to reach _start. */ alarm (DEFAULT_TIMEOUT); _Unwind_Backtrace (callback, 0); }
static int backtrace(const void** addrs, size_t ignore, size_t size) { stack_crawl_state_t state; state.count = size; state.ignore = ignore; state.addrs = addrs; _Unwind_Backtrace(trace_function, (void*)&state); return size - state.count; }
int32 runtime_callers (int32 skip, uintptr *pcbuf, int32 m) { struct callers_data arg; arg.skip = skip + 1; arg.pcbuf = pcbuf; arg.index = 0; arg.max = m; _Unwind_Backtrace (backtrace, &arg); return arg.index; }
HPX_API_EXPORT std::size_t trace(void **array,std::size_t n) { trace_data d(array,n); if (1 <= n) _Unwind_Backtrace(trace_callback, reinterpret_cast<void*>(&d)); if ((1 < d.count_) && d.array_[d.count_ - 1]) --d.count_; return (std::size_t(-1) != d.count_) ? d.count_ : 0; }
static tracy_force_inline void* Callstack( int depth ) { assert( depth >= 1 && depth < 63 ); auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) ); BacktraceState state = { (void**)(trace+1), (void**)(trace+1+depth) }; _Unwind_Backtrace( tracy_unwind_callback, &state ); *trace = (uintptr_t*)state.current - trace + 1; return trace; }
size_t backtrace(void **arr, size_t len) { struct tracer_context ctx; ctx.arr = arr; ctx.len = len; ctx.n = (size_t)~0; _Unwind_Backtrace(tracer, &ctx); if (ctx.n != (size_t)~0 && ctx.n > 0) ctx.arr[--ctx.n] = NULL; /* Skip frame below __start */ return ctx.n; }
int backtrace_simple (struct backtrace_state *state, int skip, backtrace_simple_callback callback, backtrace_error_callback error_callback, void *data) { struct backtrace_simple_data bdata; bdata.skip = skip + 1; bdata.state = state; bdata.callback = callback; bdata.error_callback = error_callback; bdata.data = data; bdata.ret = 0; _Unwind_Backtrace (simple_unwind, &bdata); return bdata.ret; }
void FAndroidPlatformStackWalk::CaptureStackBackTrace(uint64* BackTrace, uint32 MaxDepth, void* Context) { // Make sure we have place to store the information if (BackTrace == NULL || MaxDepth == 0) { return; } // zero results FPlatformMemory::Memzero(BackTrace, MaxDepth*sizeof(uint64)); // backtrace AndroidStackWalkHelpers::BackTrace = BackTrace; AndroidStackWalkHelpers::MaxDepth = MaxDepth; uint32 Depth = 0; _Unwind_Backtrace(AndroidStackWalkHelpers::BacktraceCallback, &Depth); }
isc_result_t isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) { trace_arg_t arg; /* Argument validation: see above. */ if (addrs == NULL || nframes == NULL) return (ISC_R_FAILURE); arg.skip_count = 1; arg.result = addrs; arg.max_depth = maxaddrs; arg.count = 0; _Unwind_Backtrace(btcallback, &arg); *nframes = arg.count; return (ISC_R_SUCCESS); }
int xbt_backtrace_no_malloc(void **array, int size) { int i = 0; for(i=0; i < size; i++) array[i] = nullptr; struct trace_arg arg; arg .array = array; arg.size = size; arg.cnt = -1; if (size >= 1) _Unwind_Backtrace(backtrace_helper, &arg); /* _Unwind_Backtrace on IA-64 seems to put nullptr address above _start. Fix it up here. */ if (arg.cnt > 1 && arg.array[arg.cnt - 1] == nullptr) --arg.cnt; return arg.cnt != -1 ? arg.cnt : 0; }
_Unwind_Reason_Code trace_fcn(_Unwind_Context *ctx, void *d) { int *depth = (int*)d; uintptr_t pc = _Unwind_GetIP(ctx); #ifdef CONFIG_ARCH_JUMP_ADDR_ODD if (pc == (((uintptr_t) &taskReturnFunction) - 1)) { #else if (pc == ((uintptr_t) &taskReturnFunction)) { #endif printf("\t#%d: End of Stack\n", *depth); return _URC_END_OF_STACK; } printf("\t#%d: program counter at 0x%x\n", *depth, pc); (*depth)++; return _URC_NO_REASON; } void backtrace() { int depth = 0; printf("Backtrace:\n"); _Unwind_Backtrace(&trace_fcn, &depth); }
int __gnat_backtrace (void ** traceback, int max_len, void * exclude_min, void * exclude_max, int skip_frames) { uw_data_t uw_data; /* State carried over during the whole unwinding process. */ uw_data.traceback = traceback; uw_data.max_len = max_len; uw_data.exclude_min = exclude_min; uw_data.exclude_max = exclude_max; uw_data.n_frames_to_skip = skip_frames; uw_data.n_frames_skipped = 0; uw_data.n_entries_filled = 0; _Unwind_Backtrace ((_Unwind_Trace_Fn)trace_callback, &uw_data); return uw_data.n_entries_filled; }
ssize_t unwind_backtrace(backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { ALOGV("Unwinding current thread %d.", gettid()); map_info_t* milist = acquire_my_map_info_list(); backtrace_state_t state; state.backtrace = backtrace; state.ignore_depth = ignore_depth; state.max_depth = max_depth; state.ignored_frames = 0; state.returned_frames = 0; init_memory(&state.memory, milist); _Unwind_Reason_Code rc = _Unwind_Backtrace(unwind_backtrace_callback, &state); release_my_map_info_list(milist); if (state.returned_frames) { return state.returned_frames; } return rc == _URC_END_OF_STACK ? 0 : -1; }
static void gum_gcc_backtracer_generate (GumBacktracer * backtracer, const GumCpuContext * cpu_context, GumReturnAddressArray * return_addresses) { GumGccBacktraceCtx btctx; btctx.return_addresses = return_addresses; if (cpu_context != NULL) { #ifdef HAVE_I386 btctx.start_address = GSIZE_TO_POINTER (GUM_CPU_CONTEXT_XSP (cpu_context)); #else btctx.start_address = GSIZE_TO_POINTER (cpu_context->sp); #endif } else { btctx.start_address = ((gsize *) &return_addresses) + 1; } return_addresses->len = 0; _Unwind_Backtrace (gum_gcc_backtracer_append_address, &btctx); }
void Util_BacktraceFromPointerWithFunc(uintptr_t *basePtr, // IN: Util_OutputFunc outFunc, // IN: void *outFuncData) // IN: { #if defined(UTIL_BACKTRACE_USE_UNWIND) struct UtilBacktraceFromPointerData data; data.basePtr = (uintptr_t)basePtr; data.outFunc = outFunc; data.outFuncData = outFuncData; data.frameNr = 0; data.skippedFrames = 0; _Unwind_Backtrace(UtilBacktraceFromPointerCallback, &data); #if !defined(_WIN32) && !defined(VMX86_TOOLS) /* * We do a separate pass here that includes symbols in order to * make sure the base backtrace that does not call dladdr() etc. * is safely produced. */ data.basePtr = (uintptr_t)basePtr; data.outFunc = outFunc; data.outFuncData = outFuncData; data.frameNr = 0; data.skippedFrames = 0; _Unwind_Backtrace(UtilSymbolBacktraceFromPointerCallback, &data); #endif #elif !defined(VM_X86_64) uintptr_t *x = basePtr; int i; #if !defined(_WIN32) && !defined(VMX86_TOOLS) && !defined(__ANDROID__) Dl_info dli; #endif for (i = 0; i < 256; i++) { if (x < basePtr || (uintptr_t) x - (uintptr_t) basePtr > 0x8000) { break; } outFunc(outFuncData, "Backtrace[%d] %#08x eip %#08x \n", i, x[0], x[1]); x = (uintptr_t *) x[0]; } #if !defined(_WIN32) && !defined(VMX86_TOOLS) && !defined(__ANDROID__) /* * We do a separate pass here that includes symbols in order to * make sure the base backtrace that does not call dladdr() etc. * is safely produced. */ x = basePtr; for (i = 0; i < 256; i++) { if (x < basePtr || (uintptr_t) x - (uintptr_t) basePtr > 0x8000) { break; } if (dladdr((uintptr_t *)x[1], &dli)) { outFunc(outFuncData, "SymBacktrace[%d] %#08x eip %#08x in function %s " "in object %s loaded at %#08x\n", i, x[0], x[1], dli.dli_sname, dli.dli_fname, dli.dli_fbase); } else { outFunc(outFuncData, "SymBacktrace[%d] %#08x eip %#08x \n", i, x[0], x[1]); } x = (uintptr_t *) x[0]; } #endif #endif }
void thumb_function_2(int*p) { int a = 0; printf("unwinding...\n"); _Unwind_Backtrace(trace_function, (void*)"backtrace!"); }
void assertStackDump(void) { printf("\nStack dump:\n"); int depth = 0; _Unwind_Backtrace(unwind_cb, &depth); }