通过GCC -fstack-check选项在C中引发了什么异常 [英] What exception is raised in C by GCC -fstack-check option

查看:1200
本文介绍了通过GCC -fstack-check选项在C中引发了什么异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据gcc文件

  -fstack-check 




生成代码以验证您是否超出堆栈边界。请注意,此开关实际上不会导致检查完成;操作系统必须这样做。该开关导致代码生成,以确保操作系统看到堆栈被扩展。

我的假设是这个额外的代码将生成让OS知道的例外。
当使用C语言时,我需要知道额外代码产生了什么异常。



Google也没什么帮助。关闭我知道的是,它在Ada语言的情况下会生成Storage_Error异常(参考)。



我正在处理那些需要捕获此异常的小OS /调度程序。我使用C / C ++。



我的GCC版本3.4.4

解决方案

它不直接生成任何异常。它生成的代码在堆栈被多个页面放大时,会为新分配的区域中的每个页面生成读写访问权限。这就是它的全部 。示例:

  extern void bar(char *); 
void foo(void)
{
char buf [4096 * 8];
bar(buf);





编译(使用gcc 4.9,在x86-64上,在<$ c $

  foo:
pushq%rbp
movq $ -32768,%r11
movq%rsp,%rbp
subq $ 4128,%rsp
addq%rsp,%r11
.LPSRL0:
cmpq% r11,%rsp
je .LPSRE0
subq $ 4096,%rsp
orq $ 0,(%rsp)
jmp .LPSRL0
.LPSRE0:
addq $ 4128,%rsp
leaq -32768(%rbp),%rdi
呼叫栏
离开
ret

orq $ 0,(%rsp)处的内存内容没有影响( %rsp),但CPU将它视为对该地址的读写访问权限。 (我不知道为什么GCC在循环期间偏移%rsp 4128字节,或者为什么它认为帧指针是必需的。)
理论是操作系统可以注意到这些访问并且在堆栈变得太大时做适当的事情。对于符合POSIX标准的操作系统,这将是一个 SIGSEGV 信号的交付。



您可能想知道<如何操作系统可以注意到这样的事情。硬件允许操作系统将地址空间的页面指定为完全不可访问;任何试图在这些页面上读或写内存的尝试都会触发操作系统可以处理的硬件故障(如果符合POSIX标准的操作系统,则交付 SIGSEGV ) 。这可以用来立即放置一个保护区,超过为堆栈预留的空间的末端。这就是为什么每个页面访问一次就足够了。



-fstack-check 是为了保护您,避免请注意,保护区非常小 - 也许只有一页 - 因此在堆栈上分配一个大缓冲区会将堆栈指针移动到该区域并进入另一个可访问RAM区域。如果程序发生后永远不会触及保护区内的存储器,则不会立即崩溃,但是您将在其他任何区域上乱涂乱画,导致延迟动作故障。


as per gcc documentation

-fstack-check

Generate code to verify that you do not go beyond the boundary of the stack. Note that this switch does not actually cause checking to be done; the operating system must do that. The switch causes generation of code to ensure that the operating system sees the stack being extended.

My assumption is that this extra code will generate exception to let OS know. When using C language I need to know what exception is being generated by the extra code.

Google is also not helping much. Close I came to know is that it generates Storage_Error exception in case of Ada language (Reference).

I am working on sort of small OS/scheduler where I need to catch this exception. I am using C/C++.

My GCC version 3.4.4

解决方案

It doesn't generate any exception directly. It generates code which, when the stack is enlarged by more than one page, generates a read-write access to each page in the newly allocated region. That's all it does. Example:

extern void bar(char *);
void foo(void)
{
    char buf[4096 * 8];
    bar(buf);
}

compiles (with gcc 4.9, on x86-64, at -O2) to:

foo:
        pushq   %rbp
        movq    $-32768, %r11
        movq    %rsp, %rbp
        subq    $4128, %rsp
        addq    %rsp, %r11
.LPSRL0:
        cmpq    %r11, %rsp
        je      .LPSRE0
        subq    $4096, %rsp
        orq     $0, (%rsp)
        jmp     .LPSRL0
.LPSRE0:
        addq    $4128, %rsp
        leaq    -32768(%rbp), %rdi
        call    bar
        leave
        ret

orq $0, (%rsp) has no effect on the contents of the memory at (%rsp), but the CPU treats it as a read-write access to that address anyway. (I don't know why GCC offsets %rsp by 4128 bytes during the loop, or why it thinks a frame pointer is necessary.) The theory is that the OS can notice these accesses and do something appropriate if the stack has become too large. For a POSIX-compliant operating system, that would be delivery of a SIGSEGV signal.

You may be wondering how the OS can notice such a thing. The hardware allows the OS to designate pages of address space as completely inaccessible; any attempt to read or write memory in those pages triggers a hardware fault which the OS can process as it sees fit (again, for a POSIX-compliant OS, delivery of SIGSEGV). This can be used to place a "guard area" immediately past the end of the space reserved for the stack. That's why one access per page is sufficient.

What -fstack-check is meant to protect you from, to be clear, is the situation where the "guard area" is very small - perhaps just one page - so allocating a large buffer on the stack moves the stack pointer past that area and into another region of accessible RAM. If the program then happens never to touch memory within the guard area, you won't get a prompt crash, but you will scribble on whatever that other region is, causing a delayed-action malfunction.

这篇关于通过GCC -fstack-check选项在C中引发了什么异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆