在反汇编代码中跟踪调用堆栈

Posted

技术标签:

【中文标题】在反汇编代码中跟踪调用堆栈【英文标题】:Tracing call stack in disassembled code 【发布时间】:2014-05-29 20:34:24 【问题描述】:

我正在尝试调试一个棘手的核心转储(来自 -O2 优化的二进制文件)。

// Caller Function 
void caller(Container* c)

  std::list < Message*> msgs;
  if(!decoder.called(c->buf_, msgs))
  
   ....
   .....
  
// Called Function
bool
Decoder::called(Buffer* buf, list < Message*>& msgs)

   add_data(buf); // Inlined code to append buf to decoders buf chain
   while(m_data_in && m_data_in->length() > 0)
   
     .....
   

在调用者和被调用者中,第一个参数都被优化了,这意味着它必须在寄存器中的某个地方。 调用者反汇编:

推 %r15 移动 %rdi,%r15 推 %r14 推 %r13 推 %r12 推%rbp 推%rbx 低于 $0x68,%rsp 测试 %rsi,%rsi 0x8ccd62 cmpq $0x0,(%rsi) 0x8ccd62 lea 0x40(%rsp),%rax lea 0x1b8(%rdi),%rdi mov %rax,(%rsp) mov %rax,0x40(%rsp) mov %rax,%rdx mov %rax,0x48(%rsp) 移动 (%rsi),%rsi 呼叫 0x8cc820

来电登记信息:

rax 0x7fbfffc7e0 548682057696 rbx 0x2a97905ba0 182931446688 回复 0x0 0 rdx 0x2 2 rsi 0x1 1 rdi 0x7fbfffc7e2 548682057698 rbp 0x4f 0x4f 回复 0x7fbfffc870 0x7fbfffc870 r8 0x40 64 r9 0x20 32 r10 0x7fbfffc7e0 548682057696 r11 0x2abe466600 183580911104 r12 0x7fbfffd910 548682062096 // 这是持有 buf_ r13 0x7fbfffdec0 548682063552 r14 0x5dc 1500 r15 0x2a97905ba0 182931446688 撕裂 0x8cca89 0x8cca89 eflags 0x206 [PF IF] CS 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 GS 0x0 0

调用函数反汇编:

推 %r14 推 %r13 移动 %rdx,%r13 推 %r12 移动 %rdi,%r12 推%rbp 推%rbx 低于 $0x10,%rsp mov 0x8(%rdi),%rdx 测试 %rdx,%rdx jne 0x8cc843 jmpq 0x8cc9cb mov %rax,%rdx mov 0x8(%rdx),%rax 测试 %rax,%rax mov %rsi,0x8(%rdx) mov 0x8(%r12),%rax 测试 %rax,%rax 异或 %edx,%edx 添加 0x4(%rax),%edx mov 0x8(%rax),%rax lea 0x8(%rsp),%rsi 移动 %r12,%rdi movq $0x0,0x8(%rsp)

调用函数注册信息:

rax 0x7fbfffc7e0 548682057696 rbx 0x2abc49f9c0 183547591104 回复 0x0 0 rdx 0x2 2 rsi 0x1 1 rdi 0x7fbfffc7e2 548682057698 rbp 0xffffffff 0xffffffff 回复 0x7fbfffc830 0x7fbfffc830 r8 0x40 64 r9 0x20 32 r10 0x7fbfffc7e0 548682057696 r11 0x2abe466600 183580911104 r12 0x2a97905d58 18293144712​​8 r13 0x7fbfffc8b0 548682057904 r14 0x5dc 1500 r15 0x2a97905ba0 182931446688 撕裂 0x8cc88a 0x8cc88a eflags 0x206 [PF IF] CS 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 GS 0x0 0

问题是,在被调用的函数中,"add_data" 函数似乎什么也没做。 所以,想知道在被调用函数的反汇编中,我们是否看到"buf_"指针在任何地方被使用(在被调用函数中注册r12)。

我确实在一定程度上了解汇编,但所有这些代码内联都让我感到困惑。 希望能在消除被调用函数反汇编方面提供一些帮助。 更新: add_data 如下:

if (m_data_in) m_data_in->next = data; else m_data_in = data;

【问题讨论】:

首先,还要显示add_data()的来源。然后,确保您正在编译正确的源代码,而不是 add_data() 尚未完成的旧版本。 很难说不知道 add_databuf 的实际样子(并且在反汇编中没有地址也无济于事) @VáclavZeman:感谢您的回复。这段代码已经投入生产了大约 1.5 年。确定 add_data 已完成。 @MatsPetersson:感谢您的回复。这时候我只想知道,传入的buf_的地址是否在被调用函数的任何地方使用。 就像我说的,我们需要看看add_data 做了什么。 【参考方案1】:

这看起来像if (m_data_in)

mov    0x8(%rdi),%rdx
test   %rdx,%rdx
test   %rdx,%rdx
jne    0x8cc843 
jmpq   0x8cc9cb 

现在,我不太清楚 0x8cc8430x8cc9cb 在您的代码中的位置,因此无法真正进一步遵循代码。仍然没有足够的代码和信息来准确说明原始问题中发生了什么。如果提供更多信息,我很乐意填写更多此答案。

【讨论】:

非常感谢您在这方面的帮助。我将再次查看大会以检查您所说的内容。会回复你的:) 我心平气和地详细看了一下程序集,完全可以看到add_data函数的说明。但是,无法理解我在所谓的反汇编“movq $0x0,0x8(%rsp)”中发布的最后一条指令的目的。 "mov %rsi,0x8(%rdx)" 基本上是将我的第二个参数分配给被调用函数的指令到 next_ 字段。在此之后,我没有看到任何改变“rdx”值的指令。仍然在寄存器信息中显示看似不正确的 0x2 值。有什么可能的原因吗? 另外,我还没有发布整个程序集,因为它很大,但你可以相信我上面的评论:)。我已经完全经历过了 了解汇编代码。看起来不错,但我想我无法追查到底发生了什么。

以上是关于在反汇编代码中跟踪调用堆栈的主要内容,如果未能解决你的问题,请参考以下文章

反汇编 Visual Studio

STM32F101RG 软加密解密 反汇编

反汇编系列——堆栈篇

如何在keil调试中黄色箭头不出现汇编窗口而是停在main主函数上

GDB堆栈跟踪与汇编调试

自制反汇编工具使用实例 其二(使用xmm寄存器初始化对象,以及空的成员函数指针)