Abh*_*jit 5 c c++ linux gdb objdump
分析零售构建中的核心转储通常需要关联objdump
任何特定模块和源.通常,如果函数非常复杂,则将汇编转储与源关联起来会很麻烦.今天我尝试创建assembly listing
一个特定模块(带有编译选项-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)
Run Code Online (Sandbox Code Playgroud)
但无法理解如何解释喜欢.LVL2123
和指令之类的标签.loc 2 4863 0
注意
正如所描述的答案,通过汇编源阅读并直观地确定基于符号的模式(如函数调用,分支,返回语句)就是我通常所做的.我并不否认它不起作用,但是当一个函数非常复杂时,阅读汇编列表的页面是一件很痛苦的事情,并且你最终会因为函数内联或优化器被抛出而很少匹配列表.代码,因为它很高兴.我有一种感觉,看看如何有效地Valgrind
处理优化的二进制文件以及Windows WinDBG如何处理优化的二进制文件,我有些遗漏.所以我虽然我会从编译器输出开始并使用它来关联.如果我的编译器负责修改二进制文件,那么最好的人就是如何与源相关联,但不幸的是,这样做是没有用的,这.loc
真的是误导.不幸的是,我经常需要通过各种平台阅读不可重复的转储,而我花费的最少时间是通过WinDBG调试Windows Mini-dump,以及调试Linux Coredumps的相当长的时间.我虽然可能是因为我没有正确地做事所以我想出了这个问题.
是否可以与消息来源进行一一对应?
答:不可以,除非禁用所有优化。编译器最初可能会在每行发出一些指令组(或类似指令的东西),但优化器随后会重新排序、拆分、融合,并且通常会完全更改它们。
如果我要反汇编发布代码,我会查看与代码有清晰逻辑关系的指令。例如,
.LBB7924:
.loc 2 4880 0
testq %rdx, %rdx
je .L2680
Run Code Online (Sandbox Code Playgroud)
看起来像一个分支 if%rdx
为零,它来自第 4880 行。找到该行,识别正在测试的变量,记下它当前分配给%rdx
。
.LVL2123:
testl %ecx, %ecx
jle .L2680
Run Code Online (Sandbox Code Playgroud)
好的,所以这个测试和分支有相同的目标,所以接下来发生的任何事情都知道%rdx
并且%ecx
都是非零的。原始代码的结构可能如下:
if (a && b) {
Run Code Online (Sandbox Code Playgroud)
或者也许是:
if (!a || !b) {
Run Code Online (Sandbox Code Playgroud)
优化器重新排序了两个分支......
现在您已经有了一些可以与原始代码匹配的结构,您还可以找出寄存器分配。例如,如果您知道正在测试的东西是某个结构的数据成员,请向后读取以查看%rdx
从内存加载的位置:它是从固定偏移量加载到其他寄存器的吗?如果是这样,该寄存器可能就是对象地址。
祝你好运!