6

在我的应用程序中,我设置了信号处理程序来捕获 Segfaults 并打印 bactraces。当进程启动时,我的应用程序会加载一些插件库。

如果由于主可执行二进制文件中的错误,我的应用程序因段错误而崩溃,我可以使用以下方法分析回溯:

addr2line -Cif -e ./myapplication 0x4...

它准确地显示了函数和 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]

我的应用程序和插件库都已使用 gcc 编译并且未剥离。我的应用程序在执行时使用 dlopen 加载 plugin.so 不幸的是,崩溃发生在我无法在 gdb 下运行应用程序的站点上。

疯狂地在谷歌上搜索答案,但所有讨论回溯和 addr2line 的网站都排除了可能需要分析错误插件的场景。我希望一些好心的黑客知道解决这个困境的方法,并可以分享一些见解。对于其他程序员来说,这将是非常宝贵的。

提前致谢。

4

2 回答 2

6

以下是一些可以帮助您调试的提示:

回溯中的地址是进程崩溃时地址空间中的地址。这意味着,如果要将其转换为相对于库部分开头的“物理”地址,则必须从回溯中的地址中.text减去相关部分的起始地址。pmap

不幸的是,这意味着pmap在它崩溃之前你需要一个进程。我诚然不知道如果您关闭并重新运行它,单个系统上的库的加载地址是否是恒定的(可以想象有一些安全功能可以随机化它),但正如您所注意到的,它肯定不能跨系统移植。

在你的位置,我会尝试:

  • c++filt -n使用或 手动去除符号名称。我现在没有 shell,所以这是我的手动尝试:_ZN11ICAPSection7processEP12CONNECTION_TP7Filebufiis ICAPSection::process(CONNECTION_T *, Filebuf *, int). 这可能已经有所帮助。如果不:
  • 使用objdumpor nm(我很确定他们可以这样做)找到与损坏名称相对应的地址,然后将偏移量(+0x6af根据您的堆栈跟踪)添加到此地址,然后使用addr2line.
于 2013-09-19T13:23:21.657 回答
5

us2012 的答案是解决问题所需的技巧。我只是想在这里重申它只是为了帮助任何其他遇到同样问题的新手,或者如果有人希望提供改进。

在回溯中,可以清楚地看到 myplugin.so 的代码中存在缺陷。并且回溯表明它存在于:

/opt/myapplication/modules/myplugin.so(_ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi+0x6af)[0x7f5588fe4bbf]

定位该故障对应的线路的问题不能简单地确定为:

addr2line -Cif -e /opt/myapplication/modules/myplugin.so 0x7f5588fe4bbf

此处正确的过程是使用 nm 或 objdump 来确定指向损坏名称的地址。(此时,我们不需要像 us2012 那样进行拆解)。所以使用:

nm -Dlan /opt/myapplication/modules/myplugin.so | grep "_ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi"

我得到:

0000000000008510 T _ZN11ICAPSection7processEP12CONNECTION_TP7Filebufi   /usr/local/src/unstable/myapplication/sources/modules/myplugin/myplugin.cpp:518

这里需要注意的是 myplugin.cpp:518 实际上指向函数 ICAPSection::process(CONNECTION_T *, Filebuf *, int) 的开头“{”所在的行

接下来,我们使用 linux shell 命令将 0x6af 添加到地址(由上面的 nm 输出显示)0000000000008510

 printf '0x%x\n' $(( 0x0000000000008510 + 0x6af ))

这导致0x8bbf

这是错误代码的实际 source_file:line_no,可以使用 addr2line 精确确定为:

addr2line -Cif -e /opt/myapplication/modules/myplugin.so 0x8bbf

其中显示:

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

我不太清楚为什么这里没有显示函数名称,但是myplugin.cpp:622非常准确地出现在错误的位置。

于 2013-09-19T15:28:40.917 回答