是否可以成功退出退出方法? [英] Is it possible to wrap the exit method successfully?

查看:172
本文介绍了是否可以成功退出退出方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前使用gcc 4.1.2,我有一个用例,其中我想使用链接器选项来包装退出方法。让我们立即抛开所有典型的回答/评论,你为什么要这样做?



我想知道的是,这个。我已经包装其他方法使用链接器没有任何问题。下面是我使用的__wrap_exit函数的一个快速示例:

  void __wrap_exit(int _status)
{
return;
}



当调用exit时,这个包装器确实被调用。




  • gcc在后台执行一些操作,比如当退出
    即使真正的退出函数没有被调用,只有
    的封装版本是?


  • 后面发生的一些细节

    gcc具有一个名为的语言扩展属性 __noreturn __ 。在< stdlib.h> 中,您可能有一个声明:

      extern void exit(int __status)__THROW __attribute__((__noreturn__)); 

    此属性表示函数不会以正常方式返回的承诺。 (也许它结束的过程,或者也许它 longjmp s,或者也许它引发一个C ++异常,或者也许它有一个无休止的循环...)



    所以当编译调用 exit 的代码时,gcc可以做一些优化,比如可能不打扰设置和/



    例如,下面是一个简单的函数,它调用一个库函数,然后在x86上装配,不带 -O 指定标志。

      void func1(void){
    srand(1);
    }

    .globl func1
    .type func1,@ function
    func1:
    pushl%ebp
    movl%esp,%ebp
    subl $ 8,%esp
    subl $ 12,%esp
    pushl $ 1
    call srand
    addl $ 16,%esp
    leave
    ret

    而且调用 exit

      void func2(void){
    exit(0);
    }

    .globl func2
    .type func2,@ function
    func2:
    pushl%ebp
    movl%esp,%ebp
    subl $ 8,%esp
    subl $ 12,%esp
    pushl $ 0
    call exit

    $ b b

    它开始是一样的,但是只是跳过 addl leave ret 指令,它在 func1 中告诉CPU如何回到执行任何函数当你偷偷地替换 exit 并破坏这个promise时,指令指针可能会到没有敏感代码的地方,或者堆栈结构可能无效等。在示例函数 func2 中,函数汇编实际上在调用 exit ,所以当你返回并且指令指针返回时,它将指向程序映像中接下来的任何数据,而不一定是可执行代码。 / p>

    I'm currently using gcc 4.1.2 and I have a use case where I want to use the linker options to wrap the exit method. Let's immediately put aside all the typical responses/comments of, "Why would you even want to do that?"

    What I want to know is if it's possible to even do this. I have wrapped other methods using the linker before without any issues. Below is a quick example of the __wrap_exit function I'm using:

    void __wrap_exit(int _status)
    {
       return;
    }
    

    When exit is called this wrapper is indeed called. However, the program hits a segmentation fault immediately after this __wrap_exit returns.

    • Does gcc do something behind the scenes like raise a signal when exit is called even though the real exit function is not called and only the wrapper version is?
    • Could some details of what's happening behind the scenes be provided as well?

    解决方案

    gcc has a language extension attribute called __noreturn__. In your <stdlib.h>, you probably have a declaration something like:

    extern void exit (int __status) __THROW __attribute__ ((__noreturn__));
    

    This attribute represents a promise that the function never returns in the normal way. (Maybe it ends the process, or maybe it longjmps, or maybe it throws a C++ exception, or maybe it has an unending loop...)

    So when compiling code that calls exit, gcc can make some optimizations, like maybe not bothering to set up and/or clean up stack pointers to make it possible to come back to the calling function.

    For example, here's a simple function that calls a library function, then its assembly on x86 with no -O flag specified.

    void func1(void) {
        srand(1);
    }
    
    .globl func1
            .type   func1,@function
    func1:
            pushl   %ebp
            movl    %esp, %ebp
            subl    $8, %esp
            subl    $12, %esp
            pushl   $1
            call    srand
            addl    $16, %esp
            leave
            ret
    

    And an almost identical function that calls exit instead:

    void func2(void) {
        exit(0);
    }
    
    .globl func2
            .type   func2,@function
    func2:
            pushl   %ebp
            movl    %esp, %ebp
            subl    $8, %esp
            subl    $12, %esp
            pushl   $0
            call    exit
    

    It starts out the same, but then just skips the addl, leave, and ret instructions, which in func1 tell the CPU how to go back to executing whatever function called func1.

    When you sneakily replace exit and break this promise, the instruction pointer might go somewhere that doesn't have sensible code, or the stack structure might be invalid, etc. In the example function func2, the function assembly actually ended at the call to exit, so when you return and the instruction pointer comes back, it will be pointing at whatever data happens to be next in the program image, not necessarily even executable code at all.

    这篇关于是否可以成功退出退出方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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