-
backtrace
-
简介
- 有的系统没有实现
backtrace
这个函数. - 常见的就有
linux
还有一些docker
的库.
- 有的系统没有实现
-
判断是否支持
backtrace
#include<stdio.h> #include<dlfcn.h> int main() { void * bt = dlsym(NULL,"backtrace"); if(NULL != bt) { printf("support\n"); } else { printf("not support\n"); } return 0; }
-
输出
[root@localhost bt_support]# gcc test.c -ldl -g [root@localhost bt_support]# ./a.out support
-
-
堆栈
-
获取堆栈
-
说明
- 堆栈一般是代码地址.
- 也可能是共享库的映射地址.
-
获取地址
#include <execinfo.h> void show() { void * s[30] = { 0}; backtrace(s,30); return; } void cool() { show(); } int main() { cool(); }
输出
(gdb) bt #0 show () at test.c:6 #1 0x0000000000400587 in cool () at test.c:11 #2 0x0000000000400597 in main () at test.c:16 (gdb) x /3xg s 0x7fffffffe320: 0x0000000000400576 0x0000000000400587 0x7fffffffe330: 0x0000000000400597 (gdb) p show $2 = { void ()} 0x40053d <show>
backtrace
获取到的地址和gdb bt
指令获取到的一样.
addr2line
[root@localhost bt_support]# addr2line -fap 0x0000000000400576 0x0000000000400587 0x0000000000400597 0x0000000000400576: show at /root/cfile/bt_support/test.c:6 0x0000000000400587: cool at /root/cfile/bt_support/test.c:12 0x0000000000400597: main at /root/cfile/bt_support/test.c:17
- 得到的结果基本相同.
-
-
动态库
-
获取堆栈
test.c
#define _GNU_SOURCE #include <dlfcn.h> #include <execinfo.h> void show() { void * s[30] = { 0}; int n = backtrace(s,30); int i; Dl_info info; for(i = 0 ; i < n; i++) { dladdr(s[i],&info); // info.dli_saddr 失效时可以用s[i]获取函数栈的指针,dladdr 主要是获取 so 的挂载起始地址。 i+=0; } return; } void cool() { show(); }
main.c
extern void cool(); int main() { cool(); }
编译
gcc -fPIC -shared -o test.so test.c -g gcc ./test.so main.c -g -ldl
调试输出
(gdb) p info $1 = { dli_fname = 0x7ffff7ff9640 "./test.so", dli_fbase = 0x7ffff7bd9000, dli_sname = 0x7ffff7bd942d "show", dli_saddr = 0x7ffff7bd9785 <show>} (gdb) printf "%x\n",info.dli_saddr - info.dli_fbase 785 (gdb) !addr2line -e ./test.so 806 /root/cfile/bt_support/test.c:21 (gdb) bt #0 show () at test.c:10 #1 0x00007ffff7bd9806 in cool () at test.c:20 #2 0x000000000040063b in main () at main.c:4
addr
信息需要借助dladdr
.获取某个地址的信息.
-
-
实现
backtrace
-
参考链接
-
应用场景
- 有的会没有这个函数,比如
android,docker
.
- 有的会没有这个函数,比如
-
堆栈
#include <unwind.h> struct BacktraceState { void** current; void** end; }; static _Unwind_Reason_Code unwindCallback(struct _Unwind_Context* context, void* arg) { BacktraceState* state = static_cast<BacktraceState*>(arg); uintptr_t pc = _Unwind_GetIP(context); if (pc) { if (state->current == state->end) { return _URC_END_OF_STACK; } else { *state->current++ = reinterpret_cast<void*>(pc); } } return _URC_NO_REASON; } } size_t captureBacktrace(void** buffer, size_t max) { BacktraceState state = { buffer, buffer + max}; _Unwind_Backtrace(unwindCallback, &state); return state.current - buffer; }
struct BacktraceState
,头尾指针的数组.存放void*
类型数据的指针数组._Unwind_Reason_Code
回调函数返回值.struct _Unwind_Context* context
回调函数第一参数.void* arg
用户用于存放数据的结构体,任意类型.unwindCallback
自定义的回调函数,传入堆栈信息content
,和用户的容器指针._Unwind_GetIP
获取栈指针._Unwind_Backtrace
实际函数,回调和容器.
-
android backtrace实现
Guess you like
Origin blog.csdn.net/rubikchen/article/details/120301446
Recommended
Ranking