简介
当前工作中有一部分工作需要解析出目标函数的调用栈以便进行进一步的分析,经过调研之后,发现libunwind较为符合要求,所以采用调用libunwind的接口来实现调用栈解析的功能,以此为记;
具体操作
1.下载libunwind
我下载的是1.4版本,下载链接:
http://download-mirror.savannah.gnu.org/releases/libunwind/
找到自己所需要的目标版本即可
2.编译
这里面由于我有特别的需求——在我生成的so里调用libunwind的接口——所以我需要进行相应的设置,如果没有特别需求的话,直接编译即可。我的编译步骤(进入libunwind的根目录):
CFLAGS=-fPIC ./configure --prefix=/usr --enable-shared
make CFLAGS=-fPIC
make CFLAGS=-fPIC install
参考链接:
https://blog.csdn.net/weixin_30487201/article/details/98542796
3.调用
我这里的调用比较简单:
unsigned int depth = 0;
unw_cursor_t cursor;
unw_context_t context;
unw_word_t pcArray[StackFrameDepthMax];
memset((void*)pcArray, 0, sizeof(pcArray));
unw_getcontext(&context);
unw_init_local(&cursor, &context);
while (unw_step(&cursor) > 0)
{
unw_get_reg(&cursor, UNW_REG_IP, &pcArray[depth]);
depth++;
}
//-----------------------------
while (unw_step(&cursor) > 0)
{
unw_get_reg(&cursor, UNW_REG_IP, &stackFrameItemArray[curStackIndex].pc);
unw_get_proc_name(&cursor, stackFrameItemArray[curStackIndex].symbols, SymbolsLenMax, &stackFrameItemArray[curStackIndex].offset);
//printf ("%d ====> 0x%llx : (%s+0x%x)\n", depth, stackFrameItemArray[curStackIndex].pc, stackFrameItemArray[curStackIndex].symbols, stackFrameItemArray[curStackIndex].offset);
depth++;
curStackIndex++;
}
网上很多可以参考的例子,由于我所用的功能实现较为复杂,在这里就不贴出所有的代码了,其他部分功能也不涉及libunwind的调用,只是需要把libunwind的结果进行分步处理以及后续的上报;
4.编译成so
编译这里稍微有点复杂,参考了:
https://izualzhy.cn/glog-source-how-to-get-stack-trace
我的编译命令:
gcc hook_so.c -o hook_so.so -fPIC --shared -I/home/admin/libunwind-1.4-rc1/include /home/admin/libunwind-1.4-rc1/src/.libs/libunwind-x86_64.a /home/admin/libunwind-1.4-rc1/src/.libs/libunwind.a -Wl,–no-whole-archive,–eh-frame-hdr -lpthread
简单来说就是需要把第三步编译生成的2个.a文件给链接进来
后记
今天由于想搞一个稳定版本,所以整理了之前放在调试环境上的代码,不小心误删了libunwind,然后恢复之后,虽然过程中没有报错,但是最终生成的so总是注入失败,只能另外找了一个环境重新搭建,记录一下!