【问题标题】:Segfault shows up only in GDB段错误仅出现在 GDB 中
【发布时间】:2012-10-24 06:23:01
【问题描述】:

为什么下面的程序在执行时没有崩溃,而是在 GDB 中出现段错误而崩溃?使用 GCC 4.5.2 在 32 位 x86(Athlon 64,如果需要的话)上编译。

#include <stdio.h>
#include <string.h>

int modify(void)
{
        __asm__("mov $0x41414141, %edx"); // Stray value.
        __asm__("mov $0xbffff2d4, %eax"); // Addr. of ret pointer for function().
        __asm__("mov %edx, (%eax)");
}

int function(void)
{
        modify();

        return 0;
}

int main(int argc, char **argv)
{
        function();

        return 0;
}

mov $0xbffff2d4, %eax 是使用 GDB 确定的,以查找存储“函数”函数的返回指针的地址。这在不同的系统上可能会有所不同。为此禁用了 ASLR。

当我执行程序时,什么也没有发生。也没有关于 dmesg 崩溃的报告。但是,当我在 GDB 中执行相同的程序时:

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
=> 0x41414141:  Cannot access memory at address 0x41414141

这也是我正常执行程序时所期望的。当其他程序崩溃时,我确实会像往常一样遇到段错误,而且我可以轻松编写一个小程序,该程序会因段错误而崩溃。但是为什么这个特定的程序不会因为段错误而崩溃呢?

【问题讨论】:

  • 0xbffff2d4是每次运行程序时函数返回指针的地址吗?对我来说似乎不是。
  • 该地址不应该是相对于某个偏移量的吗?
  • 根据 GDB,返回地址每次都存储在 0xbffff2d4。如果我启用了 ASLR,那显然会改变。在不同的计算机上也会有所不同。
  • 为什么地址应该是相对于某个偏移量的?

标签: c linux assembly x86 segmentation-fault


【解决方案1】:

即使完全禁用了 ASLR,您仍然可能会获得随机堆栈和堆。您可以使用norandmaps 内核引导参数全局关闭它,或者在运行时通过将/proc/sys/kernel/randomize_va_space 设置为零来关闭它。这也是过程个性的一部分。

在 GDB 中,您可以使用 disable-randomization 设置进行调整:

(gdb) help set disable-randomization
Set disabling of debuggee's virtual address space randomization.
When this mode is on (which is the default), randomization of the virtual
address space is disabled.  Standalone programs run with the randomization
enabled by default on some platforms.

作为一个小测试程序来说明这一点,可以打印一个局部变量的地址,比如:

#include <stdio.h>

int main(int argc, char **argv)
{
    printf("%p\n", &argc);
    return 0;
}

【讨论】:

  • 感谢您的意见。我已经验证了当我打印它时我得到了一个一致的 ESP 地址。我不认为我看到的行为的原因是堆栈不断移动。那么我希望看到我并不总是得到一致的 ESP 值。
  • 如果您在 GDB 中打印它,那么您当然会得到一致的值,因为正如我所引用的,默认情况下 GDB 会关闭随机化。
  • 我是通过实际执行程序打印出来的。
  • 好的,然后给你的程序添加一些延迟(比如等待用户输入),并将 GDB 附加到正在运行的实例。
猜你喜欢
  • 2017-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-11
相关资源
最近更新 更多