4

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

  • 发现者:堆栈扫描
  • 发现者:调用框架信息
  • 发现者:在上下文中作为指令指针给出

它们之间有什么区别?更重要的是,他们如何在调试方面提供帮助?

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
4

1 回答 1

4

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

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

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

于 2015-12-22T22:45:51.070 回答