c++ - 将源代码与 C++ 程序的汇编列表相关联

标签 c++ c linux gdb objdump

在零售构建中分析核心转储通常需要关联任何特定模块的 objdump 和源代码。如果函数非常复杂,通常将程序集转储与源代码关联起来会很痛苦。 今天,我尝试创建一个特定模块的程序集列表(使用编译选项-S),希望我会看到一个带有程序集或某种相关性的交错源代码。不幸的是,该列表不够友好,无法关联,所以我想知道

  • 给定一个核心转储,我可以从中确定崩溃位置
  • objdump 通过重新编译失败的模块汇编列表
  • 带有 -S 选项的模块。

是否可以与源做一一对应?

例如,我将程序集列表视为

.LBE7923:
        .loc 2 4863 0
        movq    %rdi, %r14
        movl    %esi, %r12d
        movl    696(%rsp), %r15d
        movq    704(%rsp), %rbp
.LBB7924:
        .loc 2 4880 0
        testq   %rdx, %rdx
        je      .L2680
.LVL2123:
        testl   %ecx, %ecx
        jle     .L2680
        movslq  %ecx,%rax
        .loc 2 4882 0
        testl   %r15d, %r15d
        .loc 2 4880 0
        leaq    (%rax,%rax,4), %rax
        leaq    -40(%rdx,%rax,8), %rdx
        movq    %rdx, 64(%rsp)

但无法理解如何解释标签如 .LVL2123 和指令如 .loc 2 4863 0

注意 正如所描述的答案,阅读汇编源代码并根据符号(如函数调用、分支、返回语句)直观地确定模式是我通常做的。我不否认它不起作用,但是当一个函数非常复杂时,阅读汇编列表的页面是一件痛苦的事情,而且通常你最终会得到很少匹配的列表,要么是因为函数被内联,要么是优化器简单地扔掉了随心所欲的代码。我有一种感觉,看到 Valgrind 处理优化二进制文件的效率如何,以及 WinDBG 如何在 Windows 中处理优化二进制文件,我缺少一些东西。所以我虽然会从编译器输出开始并用它来关联。如果我的编译器负责破坏二进制文件,那么最好的人会说出如何与源代码相关联,但不幸的是,这是最没有帮助的,而且 .loc 确实具有误导性。 不幸的是,我经常不得不阅读各种平台上无法重现的转储,而我花费最少的时间是通过 WinDBG 调试 Windows Mini-dumps,以及调试 Linux Coredumps。我虽然那可能是我做事不正确,所以我提出了这个问题。

最佳答案

Is it possible to do a one-to-one correspondence with the source?

A:不会,除非禁用所有优化。 编译器最初可能会每行发出一些指令组(或类似指令的东西),但优化器随后会重新排序、拆分、融合并通常完全更改它们。


如果我正在反汇编发布代码,我会查看与代码应该具有清晰逻辑关系的说明。例如,

.LBB7924:
        .loc 2 4880 0
        testq   %rdx, %rdx
        je      .L2680

如果 %rdx 为零,它看起来像一个分支,它来自第 4880 行。找到该行,识别正在测试的变量,记下它当前分配给 %rdx

.LVL2123:
        testl   %ecx, %ecx
        jle     .L2680

好的,所以这个测试和分支有相同的目标,所以无论接下来发生什么都知道 %rdx%ecx 都是非零的。原始代码的结构可能如下:

if (a && b) {

或者可能是:

if (!a || !b) {

并且优化器重新排序了两个分支......

现在您已经有了一些可以与原始代码匹配的结构,您还可以计算出寄存器分配。例如,如果您知道被测试的东西是某个结构的数据成员,请向后阅读以查看 %rdx 从内存中加载的位置:它是从固定偏移量加载到其他寄存器吗?如果是这样,该寄存器可能就是对象地址。

祝你好运!

关于c++ - 将源代码与 C++ 程序的汇编列表相关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10414149/

相关文章:

c++ - 简单 C++ 程序上的过程入口点错误

c - 海湾合作委员会 : Return statement from a void function in C

linux - 调用 0x16 时出现段错误

c - 将图像划分为不规则区域

linux - 每 2 秒检查一次目录内容,如果 bash 中存在某个文件,则复制其内容

c - 使用 fork() 进行拆分过程-程序有什么问题

c++ - arduino 低 i2c 读取速度;

c++ - 粉刺 : Avoiding pointer to pointer with pimpl

c++ - 如何对这个数据结构进行拓扑排序

c - 通过 TCP 的字符串长度