GDB核心转储具有损坏的堆栈,显示“堆栈帧无法访问地址0x12处的内存”

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GDB核心转储具有损坏的堆栈,显示“堆栈帧无法访问地址0x12处的内存”相关的知识,希望对你有一定的参考价值。

我在我的应用程序中获得了一个核心转储,当我尝试分析时,它似乎有腐败堆栈。任何人都可以帮助我如何找到问题的根源。

Program terminated with signal 11, Segmentation fault.
#0  0x40173f54 in nanosleep () from /lib/libc.so.6
(gdb) bt
#0  0x40173f54 in nanosleep () from /lib/libc.so.6
#1  0x401b2a1c in __libc_enable_asynccancel () from /lib/libc.so.6
#2  0x0000cdb8 in ?? ()
Cannot access memory at address 0x12



(gdb) info frame
Stack level 0, frame at 0xbeaedbc0:
 pc = 0x40173f54 in nanosleep; saved pc 0x401b2a1c
 called by frame at 0xbeaedbd8
 Arglist at 0xbeaedbc0, args:
 Locals at 0xbeaedbc0, Previous frame's sp is 0xbeaedbc0
(gdb) info frame 1
Stack frame at 0xbeaedbd8:
 pc = 0x401b2a1c in __libc_enable_asynccancel; saved pc 0xcdb8
 called by frame at Cannot access memory at address 0x12
(gdb) info frame 2
Stack frame at Cannot access memory at address 0x12
答案

这个堆栈可能会或可能不会损坏,这也可能发生在-fomit-frame-pointer

对于它的价值,这是我目前的战略。我并不认为这是一个最佳策略,只是目前适合我的策略:

  1. 获取符号。您获得的有关代码的信息越多,您自己重新创建该信息所需的痛苦就越少。
  2. 我手动重新构建堆栈。为此,我通常开始将堆栈中找到的指针对齐值提供给“信息符号”,看看我是否可以获得任何有用的信息。缺少符号,解码在可能由值指向的存储器位置处找到的“指令”也是有用的,如果将其作为指针,则将接近已知的代码位置。这可以产生对具有符号的位置的调用。
  3. 当我的堆栈增长时(就像这里的情况一样),我发现查看哪些函数候选称为最后一个有效的函数会很有用。
  4. 我试着重现这个问题。如果我能让事情失败,那么一切都会变得更容易。
  5. 然后我查看堆栈并尝试确定损坏开始的偏移量。
  6. 我通过程序集查找函数候选者,以获得关于哪些数据结构存在于哪些偏移量的提示。
  7. 最后,有可能随机命中一块内存(例如,另一个线程吹过自己的堆栈,错过了可能的防护页面并击中了你的堆栈。)如果你还没有任何线索,那么它就是扫描内存的时候了。指向堆栈损坏部分的指针,然后对您找到的数据结构进行逆向工程。

以上是关于GDB核心转储具有损坏的堆栈,显示“堆栈帧无法访问地址0x12处的内存”的主要内容,如果未能解决你的问题,请参考以下文章

从核心转储中获取堆栈跟踪

如何获取 gdb 调用堆栈跟踪?

使用 gdb 分析核心转储帧

当 gcc 中的应用程序在没有 gdb 的情况下崩溃时,如何生成堆栈转储和转储的寄存器值?

有没有办法在gdb核心转储中获取线程的开始时间

GDB 损坏的堆栈帧 - 如何调试?