【问题标题】:Tracking down the source code line of a crash from a non-debug built module从非调试构建的模块中追踪崩溃的源代码行
【发布时间】:2010-10-28 01:20:10
【问题描述】:

我有一个带有调用堆栈的寡妇崩溃转储,向我显示导致崩溃的函数的 module!functionname+offset。该模块是使用 gcc 构建的,没有调试信息

崩溃的原因是给定地址写入失败导致的异常,即访问冲突(05),写入冲突(01)

在我的开发机器上,我可以访问使用调试信息构建的相同模块。我正在寻找一种方法来追踪导致崩溃的相应源代码行,这是通过使用 module!functionname+offset 信息作为起点。

调用栈顶帧的方法名是类析构函数 损坏的函数名称是_ZN20ViewErrorDescriptionD0Ev+x79

运行 objdump -d 搜索 module!functionname+offset 给出:

.... call *%eax 
.... mov 0xffffffbc(%ebp), %eax
.... cmpl 0x0, 0x148(%eax)

试图在调试生成的文件中找到它没有匹配项

析构函数的源码只包含两个delete pointerX调用。

使用gdb加载debug构建的模块(sharedlibrary)然后调用info line给我一个起始和结束地址,在objdump输出上使用grep显示对应的反汇编代码,看起来还挺多的就像没有调试信息的模块中的那个一样,但仍然相差甚远。

!NB - 信息行的输出显示 _ZN20ViewErrorDescriptionD2Ev 而不是故障转储所说的 _ZN20ViewErrorDescriptionD0Ev

取自 ABI 文档: ::= D1 # 完整的对象析构函数 ::= D2 # 基础对象析构函数

我该去哪里?

最好的问候 克里斯托弗 H

【问题讨论】:

    标签: c++ debugging


    【解决方案1】:

    不幸的是,即使是调试/非调试版本也可能有不同的地址布局。我知道完成这样的事情的唯一方法是使用调试符号构建并保存该二进制文件的副本。然后你可以部署一个没有调试信息的stripped 版本。

    您尝试查找汇编代码的方法在这里似乎是最有希望的。尽管如此,我还是会扩展它:尝试查看崩溃文件中更大的程序集块,看看您是否可以自己生成更多上下文,而不是让计算机尝试匹配实际上可能略有不同的低级指令。

    【讨论】:

    • 我一直在计划这样做很长时间,现在我有一个有用的实际例子,谢谢。
    【解决方案2】:

    这是在 gcc 编译是 100% 确定性的假设下工作的。我不确定这个假设有多有效。但是,进一步假设您仍然拥有完全相同的源代码,您可以尝试启用 gcc 的 -S 命令行选项并重新构建。这将产生一组 .s 文件,每个源文件一个,包含汇编代码。然后,您可以在此搜索您要查找的代码机器代码。

    【讨论】:

      猜你喜欢
      • 2022-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-12
      相关资源
      最近更新 更多