diff options
author | Rich Felker <dalias@aerifal.cx> | 2023-11-06 12:59:34 -0500 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2023-11-06 12:59:34 -0500 |
commit | 5baf2d92d3ed82960c419cb6093fbcdd028dde11 (patch) | |
tree | add0f8e3612b483f84a2fe2b6beda049dbd084fe | |
parent | 725e17ed6dff4d0cd22487bb64470881e86a92e7 (diff) | |
download | musl-5baf2d92d3ed82960c419cb6093fbcdd028dde11.tar.gz musl-5baf2d92d3ed82960c419cb6093fbcdd028dde11.tar.xz musl-5baf2d92d3ed82960c419cb6093fbcdd028dde11.zip |
ldso: use __ehdr_start if available to locate its own ELF headers
previously, the relative load address was used as the address at which to find the ELF headers. this only works if two conditions are met: ldso is linked to start at a virtual address of 0, and the linker is cooperative and includes the main ELF headers in a loadable segment. while in practice these are always met, modern linkers provide a __ehdr_start symbol pointing to the ELF headers, and can in principle use the reference to this symbol as an indication that they need to be mapped in a segment. this also should make it possible to link for a different starting virtual address, if that's ever desirable.
-rw-r--r-- | ldso/dynlink.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c index ceca3c98..bb02cd3c 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -157,6 +157,8 @@ static struct fdpic_dummy_loadmap app_dummy_loadmap; struct debug *_dl_debug_addr = &debug; +extern weak hidden char __ehdr_start[]; + extern hidden int __malloc_replaced; hidden void (*const __init_array_start)(void)=0, (*const __fini_array_start)(void)=0; @@ -1725,7 +1727,7 @@ hidden void __dls2(unsigned char *base, size_t *sp) } else { ldso.base = base; } - Ehdr *ehdr = (void *)ldso.base; + Ehdr *ehdr = __ehdr_start ? (void *)__ehdr_start : (void *)ldso.base; ldso.name = ldso.shortname = "libc.so"; ldso.phnum = ehdr->e_phnum; ldso.phdr = laddr(&ldso, ehdr->e_phoff); |