Is it possible to successfully exit the exit method?

I am 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 me immediately put aside all the typical answers / comments: "Why do you even want to do this?"

I want to know if this can be done. I wrapped other methods using the linker, without any problems. The following is a brief example of the __wrap_exit function that I use:

void __wrap_exit(int _status) { return; } 

When a call is called, this shell is actually called. However, the program immediately detects a segmentation error after __wrap_exit is returned.

  • Does gcc do something behind the scenes, for example, picks up a signal when it is called, even if the actual function is not called, and only the wrapper version?
  • Could some details about what is going on behind the scenes also be presented?
0
source share
1 answer

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

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

This attribute is a promise that the function will never return in the usual way. (Perhaps it terminates the process, or maybe he longjmp s, or perhaps it generates C ++ exception or may have an infinite loop ...)

Thus, when compiling the code that calls exit , gcc can make some optimizations, for example, maybe not bother setting and / or clear the stack pointers so that you can return to the calling function.

For example, here is a simple function that calls a library function and then builds it on x86 without the -O flag.

 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 :

 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 with the same thing, but then just skips the addl , leave and ret instructions that in func1 tell the processor how to return to executing any function called func1 .

When you covertly replace exit and break that promise, the instruction pointer may go somewhere that does not have reasonable code, or the stack structure may be invalid, etc. In the func2 function example, the function assembly actually ended when exit called, so when you return and the instruction pointer returns, it will indicate what data will then be in the program image, and not even the executable code at all.

+4
source

Source: https://habr.com/ru/post/1236895/


All Articles