early stage ldso: remove symbolic references via error handling function
authorRich Felker <dalias@aerifal.cx>
Tue, 19 Jul 2022 23:00:53 +0000 (19:00 -0400)
committerRich Felker <dalias@aerifal.cx>
Tue, 19 Jul 2022 23:00:53 +0000 (19:00 -0400)
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

index 14fdd29..cc67795 100644 (file)
@@ -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, ...)
+{
+}