From this question, I've seen a funny code which compile (although with warnings) and produce a segmentation fault (gcc 4.4.4; clang 2.8):
main;
If we expand it, here is the result:
int main = 0;
So what is the linker's behavior here?
The linker's behavior is that it defines a symbol called main
in either the program's data or BSS segment. It is 4 bytes long and initialized to 0. Ordinarily, it creates a symbol in the program's code segment (typically called .text
) with the executable code for the main
function.
The C runtime starts up at a fixed entry point (typically called _start
), initializes a bunch of stuff (e.g. sets up the program's arguments), and calls the main
function. When main
is executable code, this is all fine and dandy, but if it's instead 4 zero bytes, the program will transfer control to those zero bytes and try to execute them.
Typically, the data and BSS segments are marked as non-executable, so when you try to execute code there, the processor will raise an exception, which the OS will interpret and then terminate your program with a signal. If somehow the segment it's in is executable, then it will try to execute the machine instructions defined by 00 00 00 00
. In x86 and x86-64, that's an illegal instruction, so you'd also get a SIGILL
signal in POSIX OSes.
Under my system (CentOS 6.3), main is placed into the BSS and contains all 0's, hence the crash:
Program received signal SIGSEGV, Segmentation fault.
0x00000000006007f0 in main ()
(gdb) where
#0 0x00000000006007f0 in main ()
(gdb) l
"main" is not a function
(gdb) disass 0x6007f0
Dump of assembler code for function main:
=> 0x00000000006007f0 <+0>: add %al,(%rax)
0x00000000006007f2 <+2>: add %al,(%rax)
End of assembler dump.
(gdb) info symbol &main
main in section .bss of /home/ajd/tmp/x
(gdb) x/16b 0x6007f0
0x6007f0 <main>: 0 0 0 0 0 0 0 0
0x6007f8: 0 0 0 0 0 0 0 0
(gdb)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With