From d16d7b10997e6f1c224c3de01b43868f0ce2cc3d Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 19 Jul 2022 19:00:53 -0400 Subject: early stage ldso: remove symbolic references via error handling function while the error handling function should not be reached in stage 2 (assuming ldso itself was linked correctly), this was not statically determinate from the compiler's perspective, and in theory a compiler performing LTO could lift the TLS references (errno and other things) out of the printf-family functions called in a stage where TLS is not yet initialized. instead, perform the call via a static-storage, internal-linkage function pointer which will be set to a no-op function until the stage where the real error handling function should be reachable. inspired by commit 63c67053a3e42e9dff788de432f82ff07d4d772a. --- ldso/dynlink.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'ldso') diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 14fdd29e..cc677952 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -29,7 +29,9 @@ #define realloc __libc_realloc #define free __libc_free -static void error(const char *, ...); +static void error_impl(const char *, ...); +static void error_noop(const char *, ...); +static void (*error)(const char *, ...) = error_noop; #define MAXP2(a,b) (-(-(a)&-(b))) #define ALIGN(x,y) ((x)+(y)-1 & -(y)) @@ -1758,6 +1760,9 @@ void __dls3(size_t *sp, size_t *auxv) env_preload = getenv("LD_PRELOAD"); } + /* Activate error handler function */ + error = error_impl; + /* If the main program was already loaded by the kernel, * AT_PHDR will point to some location other than the dynamic * linker's program headers. */ @@ -2347,7 +2352,7 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void return ret; } -static void error(const char *fmt, ...) +static void error_impl(const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -2361,3 +2366,7 @@ static void error(const char *fmt, ...) __dl_vseterr(fmt, ap); va_end(ap); } + +static void error_noop(const char *fmt, ...) +{ +} -- cgit v1.2.1