Reputation: 2038
I am looking into the startup code in Glibc for x86-64, and I am curious about the below two places which I highlighted in the screenshot directly.
Code: https://github.com/bminor/glibc/blob/master/sysdeps/x86_64/start.S
Upvotes: 3
Views: 375
Reputation: 33694
pushq %rax
is needed for stack alignment: RSP % 16 == 0 before any call
instruction.
In current ELF version, ELF constructors and destructors are identifiable through dynamic tags (DT_INIT_ARRAY
and DT_FINI_ARRAY
is generally preferred because of improved unwinding support). In glibc before version 2.34, the statically linked startup code (of which the quoted assembler fragment is a part) actually had its own loop to process DT_INIT_ARRAY
. In glibc 2.34, this code was removed because it turned out that it contained a very generic jump-oriented programming (JOP) gadget.
The .init
function pointer is still passed as zero because this allows to share the implementation of __libc_start_main
(which is called further down) for old and new binaries. glibc versions 2.34 and later look at this function pointer and call it if non-null, else use DT_INIT
and DT_INIT_ARRAY
to find the functions to call.
Another reason for making the .init
change this way was that it was necessary to change the startup code on all 21 glibc architectures, and it is easier to change a parameter to zero than to remove it because it does not affect the function signature or calling convention.
Pretty much the same rationale applies to the .fini
change, except in this case, the old dynamically linked __libc_start_main
implementation already ignored it.
Upvotes: 3