libuv 编译使用,打印调用堆栈
libuv 编译选项:
CFLAGS='-g -O0 -funwind-tables' ./configure --disable-silent-rules --disable-udev --enable-debug-logmake -j8 V=1
其中 -funwind-tables 可以打印详细调用堆栈。
写程序使用:t1.cc
#include
#include
#include
#include
#include
#include
#include using namespace std;void handler(int sig)
{void* buffer[10];FILE* fp = fopen("callstack.txt", "w");backtrace_symbols_fd(buffer, backtrace(buffer, sizeof(buffer) / sizeof(buffer[0])), fileno(fp));fclose(fp);_exit(1);
}int main(void)
{signal(SIGSEGV, handler);auto loop = uv_default_loop();uv_tcp_t *tcp = (uv_tcp_t*)-1;uv_tcp_init(loop, tcp);return 0;
}/* 此处使用静态库,转化堆栈地址更直接,如果是动态库,首先要找到偏移地址,再加上移动地址,才是真正地址g++ -g -O0 -I./build/include -o t1 t1.cc ./.libs/libux.a -pthread
*/
运行:./t1
查看 callstack.txt
#如果是动态库,显示如下,拿第4行来看:这时真正地址为 uv_tcp_init_ex+0x74
#可以使用 nm /home/test/Desktop/libuv/.libs/libux.so.1 | grep uv_tcp_init_ex 来找到偏移地址(为16进制),这时再加上 0x74 即为真正地址./t1(+0xc1c)[0x557f338c1c]
linux-vdso.so.1(__kernel_rt_sigreturn+0x0)[0x7faaa866a0]
/home/test/Desktop/libuv/.libs/libux.so.1(+0x24510)[0x7faaa32510]
/home/test/Desktop/libuv/.libs/libux.so.1(uv_tcp_init_ex+0x74)[0x7faaa35da0]
/home/test/Desktop/libuv/.libs/libux.so.1(uv_tcp_init+0x20)[0x7faaa35e38]
./t1(+0xc84)[0x557f338c84]
/lib/aarch64-linux-gnu/libc.so.6(__libc_start_main+0xe0)[0x7faa8b46e0]
./t1(+0xb04)[0x557f338b04]#如果是静态库就简单多了,显示的就是真实地址./t1(+0x3e2c)[0x556a706e2c]
linux-vdso.so.1(__kernel_rt_sigreturn+0x0)[0x7f934366a0]
./t1(+0x10e7c)[0x556a713e7c]
./t1(+0x1470c)[0x556a71770c]
./t1(+0x147a4)[0x556a7177a4]
./t1(+0x3e94)[0x556a706e94]
/lib/aarch64-linux-gnu/libc.so.6(__libc_start_main+0xe0)[0x7f932856e0]
./t1(+0x3d14)[0x556a706d14]
使用 addr2line 查看堆栈信息:
addr2line -e ./t1 0x147a4
或者使用下面的工具查看:addrtool.cc
/* * Compile with g++ -std=c++11 -O2 -o addrtool addrtool.cc*/#include
#include
#include
#include
#include
#include using namespace std;#define ADDR2LINE "addr2line"string do_addr2line(const char *exec_file, const string &address)
{char cmd[256];char output[1035];snprintf(cmd, sizeof(cmd), "%s -e %s %s", ADDR2LINE, exec_file, address.c_str());FILE *fp = popen(cmd, "r");if (!fp) return string();if (!fgets(output, sizeof(output)-1, fp)){pclose(fp);return string();}pclose(fp);return string(output);
}int main(int argc, char *argv[])
{if (argc < 3){printf("Usage: %s \n", argv[0]);exit(1);}FILE *fp = fopen(argv[2], "r");if (!fp){fprintf(stderr, "Error: open %s error: %s\n", argv[1], strerror(errno));exit(1);}char line[1025];smatch sm1, sm2;const regex pat1("\\(\\+(0x[0-9a-f]+)\\)"), pat2("^\\?{0,}\\:\\?{0,}");printf("CallStack is\n==================================\n");while (fgets(line, sizeof(line)-1, fp) != nullptr){auto s = string(line);if (regex_search(s, sm1, pat1)){auto output = do_addr2line(argv[1], sm1[1].str());printf("%s", output.empty() || regex_search(output, sm2, pat2) ? line : output.c_str());}elseprintf("%s", line);}fclose(fp);return 0;
}
用法:addrtool ./t1 callstack.txt
test:~/Desktop/libuv$ ~/addrtool t1 callstack.txtCallStack is
==================================
/home/test/Desktop/libuv/t1.cc:17
linux-vdso.so.1(__kernel_rt_sigreturn+0x0)[0x7f934366a0]
/home/test/Desktop/libuv/uv/unix/stream.c:82
/home/test/Desktop/libuv/uv/unix/tcp.c:133
/home/test/Desktop/libuv/uv/unix/tcp.c:147
/home/test/Desktop/libuv/t1.cc:28
/lib/aarch64-linux-gnu/libc.so.6(__libc_start_main+0xe0)[0x7f932856e0]
./t1(+0x3d14)[0x556a706d14]
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
