堆栈跟踪:堆栈扫描与调用帧vs在上下文中作为指令指针给出

时间:2014-12-25 16:17:10

标签: stack stack-trace google-breakpad

我在项目中使用breakpad来处理崩溃并生成堆栈跟踪。 在堆栈跟踪中,stackwalker发现函数调用信息的方式有很多种。此处描述的流程Finding_the_caller_frame

  • 发现者:堆栈扫描
  • 发现者:call frame info
  • 发现者:在上下文中作为指令指针给出

他们之间的区别是什么?更重要的是他们如何帮助调试?

Thread 0 (crashed)
  0  test_google_breakpad!crash [test_breakpad.cpp : 17 + 0x4]
      r4 = 0x00015530    r5 = 0xbea2cbe4    r6 = 0xffffff38    r7 = 0xbea2cb5c
      r8 = 0x00000000    r9 = 0x00000000   r10 = 0x00000000    fp = 0x00000000
      sp = 0xbea2cb50    lr = 0x00009025    pc = 0x00008f84
     Found by: given as instruction pointer in context
  1  test_google_breakpad!main [test_breakpad.cpp : 25 + 0x3]
      r4 = 0x00015530    r5 = 0xbea2cbe4    r6 = 0xffffff38    r7 = 0xbea2cb5c
      r8 = 0x00000000    r9 = 0x00000000   r10 = 0x00000000    fp = 0x00000000
      sp = 0xbea2cb50    pc = 0x00009025
     Found by: call frame info
  2  libc.so + 0x164e5
      r4 = 0x00008f64    r5 = 0xbea2cc34    r6 = 0x00000001    r7 = 0xbea2cc3c
      r8 = 0x00000000    r9 = 0x00000000   r10 = 0x00000000    fp = 0x00000000
      sp = 0xbea2cc18    pc = 0x400c34e7
     Found by: call frame info

1 个答案:

答案 0 :(得分:4)

指令指针方法意味着CPU寄存器已经指向函数的存储器位置,因此不需要搜索该函数。这是查找当前堆栈帧的最简单,最可靠的方法。

接下来使用调用帧技术,您可以通过查看存储返回地址的堆栈存储器中的位置来查找当前函数的调用者。这是"返回"的确切技术。会用来找到它的回归目的地。可以链接此技术,因为每个先前的调用也将其返回值放在堆栈上。这是非常可靠的,但如果某些堆栈内存损坏(可能是堆栈溢出,可能是错误的指针写入)并且一个或多个返回地址被删除,则可能会失败。

最后,最不可靠的技术是在堆栈内存中搜索看起来像函数地址的任何内容。这可以帮助您从损坏的堆栈中恢复,但是除了函数地址之外很难分辨数据(包括函数指针!),所以它的猜测。但是,如果找到一个,那么如果你发现一些没有被删除的堆栈,你通常可以链回到调用框架技术。