ESP 在 /proc/pid/maps 和二进制文件中不同

Posted

技术标签:

【中文标题】ESP 在 /proc/pid/maps 和二进制文件中不同【英文标题】:ESP different in /proc/pid/maps and binary 【发布时间】:2012-12-27 08:19:38 【问题描述】:

我正在调试崩溃,我看到以下行为 -

当我将 GDb 附加到进程并进行信息寄存器时,我看到 esp 的以下值 -

esp 0xfd2475d0 0xfd2475d0

在对崩溃的代码进行反汇编时,我看到以下内容 -

81c886a: c7 04 24 2c f9 8a 0c movl $0xc8af92c,(%esp)

如果我在 /proc//maps 中查看地图文件,我会看到堆栈地址范围为 -

fff39000-fff59000 rwxp 7ffffffde000 00:00 0 [堆栈]

显然,GDB 中 ESP 0xfd2475d0 的值与映射文件中的堆栈地址不同步。

这可能是崩溃的原因吗?我认为这应该是因为我正在获得 SIGSEGV。还有,这个问题怎么解决?

请帮忙

【问题讨论】:

【参考方案1】:

是的,这显然是分段错误的原因。实际上不抛出它是非常不明智的,因为英特尔架构支持分配单独的代码、数据和堆栈段——并且所有内存访问(使用基址寄存器 == ebp 或 esp)都会隐式地通过堆栈段。

因为编译器将使用不同的基址寄存器(和不同的隐式段寄存器)来读取任何其他任意指针,这会缩小对堆栈寄存器损坏的搜索范围。

比较少见的可能性是 堆栈粉碎 即。在当前函数范围内访问除局部变量之外的其他堆栈元素——在这种特殊情况下会破坏调用者的堆栈/帧指针。

void foo(int *p) 
   int a[2];
   a[4] = p;

更有可能的选择是过度分配。

 void foo()     
     double too_big[6000000];    // this would be located at 0xfd...... 
     int a;                      // this would be located at 0xfff3f000 ... 
 

【讨论】:

请注意,主流操作系统不使用分段,因此它们不会捕获指定堆栈区域之外的访问(仅适用于通常的内存保护)。如果您使用线程或 sigaltstack,这一点很重要,在这种情况下,其他一些内存块用作堆栈。

以上是关于ESP 在 /proc/pid/maps 和二进制文件中不同的主要内容,如果未能解决你的问题,请参考以下文章

/proc/$pid/maps 在 x86_64 linux 上显示没有 rwx 权限的页面

为啥我可以在 /proc/pid/maps 输出中看到几个相同的段?

/proc/$PID/maps文件解读

/proc/$pid/maps文件中各个空间段的意义

有关/proc/pid/maps

linux proc maps文件分析