mdk*_*mdk 6 c c++ backtrace debug-backtrace addr2line
在我的应用程序中,我有设置信号处理程序来捕获Segfaults,并打印bactraces.进程启动时,我的应用程序会加载一些插件库.
如果我的应用程序崩溃了一个段错误,由于主可执行二进制文件中的错误,我可以用以下内容分析回溯:
addr2line -Cif -e ./myapplication 0x4...
Run Code Online (Sandbox Code Playgroud)
它准确地显示了函数和source_file:line_no
但是,如何分析是否由于插件中的错误而发生崩溃,如下面的回溯?
/opt/myapplication(_Z7sigsegvv+0x15)[0x504245]
/lib64/libpthread.so.0[0x3f1c40f500]
/opt/myapplication/modules/myplugin.so(_ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi+0x6af)[0x7f5588fe4bbf]
/opt/myapplication/modules/myplugin.so(_Z11myplugin_reqmodP12CONNECTION_TP7Filebuf+0x68)[0x7f5588fe51e8]
/opt/myapplication(_ZN10Processors7ExecuteEiP12CONNECTION_TP7Filebuf+0x5b)[0x4e584b]
/opt/myapplication(_Z15process_requestP12CONNECTION_TP7Filebuf+0x462)[0x4efa92]
/opt/myapplication(_Z14handle_requestP12CONNECTION_T+0x1c6d)[0x4d4ded]
/opt/myapplication(_Z13process_entryP12CONNECTION_T+0x240)[0x4d79c0]
/lib64/libpthread.so.0[0x3f1c407851]
/lib64/libc.so.6(clone+0x6d)[0x3f1bce890d]
Run Code Online (Sandbox Code Playgroud)
我的应用程序和插件库都使用gcc编译并且未被删除.我的应用程序在执行时,使用dlopen加载plugin.so不幸的是,崩溃发生在我无法在gdb下运行应用程序的站点上.
谷歌疯狂地搜索答案,但所有讨论回溯和addr2line的网站排除了可能需要分析错误插件的情况.我希望一些善良的黑客知道这个困境的解决方案,并且可以分享一些见解.对于其他程序员来说,这将是非常宝贵的.
提前谢谢.
以下是一些可能有助于您调试此提示的提示:
回溯中的地址是进程崩溃时地址空间中的地址.这意味着,如果您想将其转换为相对于.text库部分开头的"物理"地址,则必须pmap从回溯中的地址中减去相关部分的起始地址.
不幸的是,这意味着pmap在崩溃之前需要一个进程.我承认不知道如果你关闭并重新运行它,在单个系统上加载库的地址是否是不变的(可以想象有安全功能随机化这个),但它确实不能跨系统移植,正如你已经注意到的那样.
在你的位置,我会尝试:
c++filt -n或手动解码符号名称.我现在没有shell,所以这是我的手动尝试:_ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi是ICAPSection::process(CONNECTION_T *, Filebuf *, int).这可能已经有所帮助.如果不: objdump或nm(我很确定他们可以这样做)找到与受损名称对应的地址,然后将偏移量(+0x6af根据您的堆栈跟踪)添加到此,然后使用查找生成的地址addr2line.us2012 的答案是解决问题所需的技巧。我只是想在这里重申它只是为了帮助任何其他遇到同样问题的新手,或者如果有人希望提供改进。
在回溯中,可以清楚地看到 myplugin.so 的代码中存在该缺陷。并且回溯表明它存在于:
/opt/myapplication/modules/myplugin.so(_ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi+0x6af)[0x7f5588fe4bbf]
Run Code Online (Sandbox Code Playgroud)
该故障对应线路的定位问题不能简单地确定为:
addr2line -Cif -e /opt/myapplication/modules/myplugin.so 0x7f5588fe4bbf
Run Code Online (Sandbox Code Playgroud)
此处的正确过程是使用 nm 或 objdump 来确定指向损坏名称的地址。(此时并没有真正必要像 us2012 那样进行 Demangling)。所以使用:
nm -Dlan /opt/myapplication/modules/myplugin.so | grep "_ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi"
Run Code Online (Sandbox Code Playgroud)
我得到:
0000000000008510 T _ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi /usr/local/src/unstable/myapplication/sources/modules/myplugin/myplugin.cpp:518
Run Code Online (Sandbox Code Playgroud)
这里有趣的是 myplugin.cpp:518 实际上指向函数 ICAPSection::process(CONNECTION_T *, Filebuf *, int) 的开头“{”所在的行
接下来我们使用linux shell命令将0x6af添加到地址(由上面的nm输出显示)0000000000008510
printf '0x%x\n' $(( 0x0000000000008510 + 0x6af ))
Run Code Online (Sandbox Code Playgroud)
这导致0x8bbf
这是错误代码的实际 source_file:line_no ,可以使用 addr2line 精确确定为:
addr2line -Cif -e /opt/myapplication/modules/myplugin.so 0x8bbf
Run Code Online (Sandbox Code Playgroud)
其中显示:
std::char_traits<char>::length(char const*)
/usr/include/c++/4.4/bits/char_traits.h:263
std::string::assign(char const*)
/usr/include/c++/4.4/bits/basic_string.h:970
std::string::operator=(char const*)
/usr/include/c++/4.4/bits/basic_string.h:514
??
/usr/local/src/unstable/myapplication/sources/modules/myplugin/myplugin.cpp:622
Run Code Online (Sandbox Code Playgroud)
我不太确定为什么这里没有显示函数名称,但是myplugin.cpp:622非常准确地出现了错误所在。