From 9e78f6f6e7134a5f299cc8de77370218f8019237 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Wed, 30 Nov 2016 15:59:57 +0100 Subject: [PATCH] Implement _dl_catch_error, _dl_signal_error in libc.so [BZ #16628] This change moves the main implementation of _dl_catch_error, _dl_signal_error to libc.so, where TLS variables can be used directly. This removes a writable function pointer from the rtld_global variable. For use during initial relocation, minimal implementations of these functions are provided in ld.so. These are eventually interposed by the libc.so implementations. This is implemented by compiling elf/dl-error-skeleton.c twice, via elf/dl-error.c and elf/dl-error-minimal.c. As a side effect of this change, the static version of dl-error.c no longer includes support for the _dl_signal_cerror/_dl_receive_error mechanism because it is only used in ld.so. --- ChangeLog | 78 +++++++ dlfcn/dlerror.c | 4 +- dlfcn/dlinfo.c | 4 +- dlfcn/dlmopen.c | 4 +- dlfcn/dlopen.c | 2 +- elf/Makefile | 21 +- elf/Versions | 6 + elf/dl-close.c | 2 +- elf/dl-error-minimal.c | 23 +++ elf/dl-error-skeleton.c | 230 +++++++++++++++++++++ elf/dl-error.c | 210 +------------------ elf/dl-libc.c | 4 +- elf/dl-sym.c | 8 +- elf/dl-tsd.c | 53 ----- elf/rtld.c | 19 -- elf/tst-latepthread.c | 105 ++++++++++ elf/tst-latepthreadmod.c | 33 +++ nptl/nptl-init.c | 4 - sysdeps/generic/ldsodefs.h | 46 +++-- sysdeps/generic/localplt.data | 3 + sysdeps/unix/sysv/linux/aarch64/localplt.data | 3 + sysdeps/unix/sysv/linux/alpha/localplt.data | 3 + sysdeps/unix/sysv/linux/arm/localplt.data | 3 + sysdeps/unix/sysv/linux/hppa/localplt.data | 3 + sysdeps/unix/sysv/linux/i386/localplt.data | 3 + sysdeps/unix/sysv/linux/ia64/localplt.data | 3 + sysdeps/unix/sysv/linux/m68k/localplt.data | 3 + sysdeps/unix/sysv/linux/microblaze/localplt.data | 3 + sysdeps/unix/sysv/linux/nios2/localplt.data | 3 + .../sysv/linux/powerpc/powerpc32/fpu/localplt.data | 3 + .../linux/powerpc/powerpc32/nofpu/localplt.data | 3 + .../sysv/linux/powerpc/powerpc64/localplt.data | 3 + sysdeps/unix/sysv/linux/s390/localplt.data | 3 + sysdeps/unix/sysv/linux/sh/localplt.data | 3 + .../unix/sysv/linux/sparc/sparc32/localplt.data | 3 + .../unix/sysv/linux/sparc/sparc64/localplt.data | 3 + sysdeps/x86_64/localplt.data | 3 + 37 files changed, 595 insertions(+), 315 deletions(-) create mode 100644 elf/dl-error-minimal.c create mode 100644 elf/dl-error-skeleton.c delete mode 100644 elf/dl-tsd.c create mode 100644 elf/tst-latepthread.c create mode 100644 elf/tst-latepthreadmod.c diff --git a/ChangeLog b/ChangeLog index c2cb608..d017478 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,83 @@ 2016-11-30 Florian Weimer + [BZ #16628] + Implement _dl_catch_error, _dl_signal_error in libc.so. + * elf/dl-error-skeleton.c: Rename from elf/dl-error.c. + (catch_hook): Define as thread-local or regular variable, + depending on DL_ERROR_BOOTSTRAP. + (CATCH_HOOK): Remove. + (dl_signal_error, _dl_catch_error): Use + catch_hook. Add hidden definition for libc. + (_dl_receive_error, _dl_signal_cerror): Use catch_hook. Compile + for DL_ERROR_BOOTSTRAP only. + * elf/dl-error.c: New file. + * elf/dl-error-minimal.c: Likewise. + * elf/tst-latepthread.c: Likewise. + * elf/tst-latepthreadmod.c: Likewise. + * elf/Makefile (routines): Add dl-error. + (dl-routines): Remove dl-error. + (rtld-routines): Add dl-error-minimal. + [build-shared] (tests): Add tst-latepthread. + (module-names): Add tst-latepthreadmod. + (LDFLAGS-tst-latepthreadmod.so): Enable lazy binding to undefined + symbol. + (tst-latepthreadmod.so): Link against libpthread. + (tst-latepthread): Link against libdbl. + * elf/Versions [libc] (GLIBC_PRIVATE): Add _dl_signal_error, + _dl_catch_error. + [ld] (GLIBC_PRIVATE): Likewise. + * elf/dl-close.c (_dl_cose): Call _dl_signal_error directly. + * elf/dl-libc.c (dlerror_run): Call _dl_catch_error directly. + * elf/dl-sym.c (do_sym): Call _dl_signal_error, _dl_catch_error + directly. + * elf/dl-tsd.c: Remove file. + * elf/rtld.c (_rtld_global_ro): Remove initializers for + _dl_catch_error, _dl_signal_error. + (_dl_initial_error_catch_tsd): Remove definition. + (do_preload): Remove initialization of dl_error_catch_tsd. + * dlfcn/dlerror.c (_dlerror_run): Call _dl_catch_error directly. + * dlfcn/dlinfo.c (dlinfo_doit): Call _dl_signal_error directly. + * dlfcn/dlmopen.c (dlmopen_doit): Likewise. + * dlfcn/dlopen.c (dlopen_doit): Likewise. + * nptl/nptl-init.c (__pthread_initialize_minimal_internal): Do not + set dl_error_catch_tsd. + * sysdeps/generic/ldsodefs.h (struct rtld_global): Remove + _dl_error_catch_tsd member. + (struct rtld_global_ro): Remove _dl_catch_error, _dl_signal_error + members. + (_dl_initial_error_catch_tsd): Remove declaration. + (_dl_dprintf): Provide definition for use outside of ld.so. + [!rtld] (_dl_signal_cerror): Redirect to _dl_signal_error. + (_dl_signal_error, _dl_catch_error): Make public. Add hidden + prototype for libc. + * sysdeps/generic/localplt.data (ld.so): Add _dl_signal_error, + _dl_catch_error. + * sysdeps/unix/sysv/linux/aarch64/localplt.data (ld.so): Likewise. + * sysdeps/unix/sysv/linux/alpha/localplt.data (ld.so): Likewise. + * sysdeps/unix/sysv/linux/arm/localplt.data (ld.so): Likewise. + * sysdeps/unix/sysv/linux/hppa/localplt.data (ld.so): Likewise. + * sysdeps/unix/sysv/linux/i386/localplt.data (ld.so): Likewise. + * sysdeps/unix/sysv/linux/ia64/localplt.data (ld.so): Likewise. + * sysdeps/unix/sysv/linux/m68k/localplt.data (ld.so): Likewise. + * sysdeps/unix/sysv/linux/microblaze/localplt.data (ld.so): + Likewise. + * sysdeps/unix/sysv/linux/nios2/localplt.data (ld.so): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data + (ld.so): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data + (ld.so): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data (ld.so): + Likewise. + * sysdeps/unix/sysv/linux/s390/localplt.data (ld.so): Likewise. + * sysdeps/unix/sysv/linux/sh/localplt.data (ld.so): Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data (ld.so): + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data (ld.so): + Likewise. + * sysdeps/x86_64/localplt.data (ld.so): Likewise. + +2016-11-30 Florian Weimer + [BZ #4099] * libio/filedoalloc.c (_IO_file_doallocate): Limit buffer size to _IO_BUFSIZ (8192). diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c index 41b2bd6..e0e5648 100644 --- a/dlfcn/dlerror.c +++ b/dlfcn/dlerror.c @@ -160,8 +160,8 @@ _dlerror_run (void (*operate) (void *), void *args) result->errstring = NULL; } - result->errcode = GLRO(dl_catch_error) (&result->objname, &result->errstring, - &result->malloced, operate, args); + result->errcode = _dl_catch_error (&result->objname, &result->errstring, + &result->malloced, operate, args); /* If no error we mark that no error string is available. */ result->returned = result->errstring == NULL; diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c index eeba8da..794e354 100644 --- a/dlfcn/dlinfo.c +++ b/dlfcn/dlinfo.c @@ -60,7 +60,7 @@ dlinfo_doit (void *argsblock) break; if (l == NULL) - GLRO(dl_signal_error) (0, NULL, NULL, N_("\ + _dl_signal_error (0, NULL, NULL, N_("\ RTLD_SELF used in code not dynamically loaded")); } # endif @@ -69,7 +69,7 @@ RTLD_SELF used in code not dynamically loaded")); { case RTLD_DI_CONFIGADDR: default: - GLRO(dl_signal_error) (0, NULL, NULL, N_("unsupported dlinfo request")); + _dl_signal_error (0, NULL, NULL, N_("unsupported dlinfo request")); break; case RTLD_DI_LMID: diff --git a/dlfcn/dlmopen.c b/dlfcn/dlmopen.c index 6da0d0d..4eed513 100644 --- a/dlfcn/dlmopen.c +++ b/dlfcn/dlmopen.c @@ -60,12 +60,12 @@ dlmopen_doit (void *a) must be the main one. */ if (args->file == NULL) # endif - GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid namespace")); + _dl_signal_error (EINVAL, NULL, NULL, N_("invalid namespace")); /* It makes no sense to use RTLD_GLOBAL when loading a DSO into a namespace other than the base namespace. */ if (__glibc_unlikely (args->mode & RTLD_GLOBAL)) - GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid mode")); + _dl_signal_error (EINVAL, NULL, NULL, N_("invalid mode")); } args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN, diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c index 453efbd..5263fed 100644 --- a/dlfcn/dlopen.c +++ b/dlfcn/dlopen.c @@ -61,7 +61,7 @@ dlopen_doit (void *a) if (args->mode & ~(RTLD_BINDING_MASK | RTLD_NOLOAD | RTLD_DEEPBIND | RTLD_GLOBAL | RTLD_LOCAL | RTLD_NODELETE | __RTLD_SPROF)) - GLRO(dl_signal_error) (0, NULL, NULL, _("invalid mode parameter")); + _dl_signal_error (0, NULL, NULL, _("invalid mode parameter")); args->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN, args->caller, diff --git a/elf/Makefile b/elf/Makefile index 82c7e05..33b003b 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -24,12 +24,12 @@ include ../Makeconfig headers = elf.h bits/elfclass.h link.h bits/link.h routines = $(all-dl-routines) dl-support dl-iteratephdr \ dl-addr dl-addr-obj enbl-secure dl-profstub \ - dl-origin dl-libc dl-sym dl-tsd dl-sysdep + dl-origin dl-libc dl-sym dl-sysdep dl-error # The core dynamic linking functions are in libc for the static and # profiled libraries. dl-routines = $(addprefix dl-,load lookup object reloc deps hwcaps \ - runtime error init fini debug misc \ + runtime init fini debug misc \ version profile conflict tls origin scope \ execstack caller open close trampoline) ifeq (yes,$(use-ldconfig)) @@ -43,7 +43,8 @@ shared-only-routines += dl-caller # ld.so uses those routines, plus some special stuff for being the program # interpreter and operating independent of libc. -rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal +rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \ + dl-error-minimal all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines) CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables @@ -150,7 +151,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ tst-nodelete) \ tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ - tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload + tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ + tst-latepthread # reldep9 ifeq ($(build-hardcoded-path-in-tests),yes) tests += tst-dlopen-aout @@ -224,7 +226,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ tst-array5dep tst-null-argv-lib \ tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \ tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \ - tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 + tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \ + tst-latepthreadmod ifeq (yes,$(have-mtls-dialect-gnu2)) tests += tst-gnu2-tls1 modules-names += tst-gnu2-tls1mod @@ -1264,6 +1267,14 @@ tst-audit12-ENV = LD_AUDIT=$(objpfx)tst-auditmod12.so $(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map +# Override -z defs, so that we can reference an undefined symbol. +# Force lazy binding for the same reason. +LDFLAGS-tst-latepthreadmod.so = \ + -Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all +$(objpfx)tst-latepthreadmod.so: $(shared-thread-library) +$(objpfx)tst-latepthread: $(libdl) +$(objpfx)tst-latepthread.out: $(objpfx)tst-latepthreadmod.so + tst-prelink-ENV = LD_TRACE_PRELINKING=1 $(objpfx)tst-prelink-conflict.out: $(objpfx)tst-prelink.out diff --git a/elf/Versions b/elf/Versions index 23deda9..05e5449 100644 --- a/elf/Versions +++ b/elf/Versions @@ -26,6 +26,9 @@ libc { _dl_open_hook; _dl_sym; _dl_vsym; __libc_dlclose; __libc_dlopen_mode; __libc_dlsym; + + # Internal error handling support. Interposes the functions in ld.so. + _dl_signal_error; _dl_catch_error; } } @@ -64,5 +67,8 @@ ld { # Pointer protection. __pointer_chk_guard; + + # Internal error handling support. Interposed by libc.so. + _dl_signal_error; _dl_catch_error; } } diff --git a/elf/dl-close.c b/elf/dl-close.c index 687d7de..6489703 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -814,7 +814,7 @@ _dl_close (void *_map) } if (__builtin_expect (map->l_direct_opencount, 1) == 0) - GLRO(dl_signal_error) (0, map->l_name, NULL, N_("shared object not open")); + _dl_signal_error (0, map->l_name, NULL, N_("shared object not open")); /* Acquire the lock. */ __rtld_lock_lock_recursive (GL(dl_load_lock)); diff --git a/elf/dl-error-minimal.c b/elf/dl-error-minimal.c new file mode 100644 index 0000000..d535d65 --- /dev/null +++ b/elf/dl-error-minimal.c @@ -0,0 +1,23 @@ +/* Error handling for runtime dynamic linker, minimal version. + Copyright (C) 1995-2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* This version does lives in ld.so, does not use thread-local data + and supports _dl_signal_cerror and _dl_receive_error. */ + +#define DL_ERROR_BOOTSTRAP 1 +#include "dl-error-skeleton.c" diff --git a/elf/dl-error-skeleton.c b/elf/dl-error-skeleton.c new file mode 100644 index 0000000..beb31ae --- /dev/null +++ b/elf/dl-error-skeleton.c @@ -0,0 +1,230 @@ +/* Template for error handling for runtime dynamic linker. + Copyright (C) 1995-2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* The following macro needs to be defined before including this + skeleton file: + + DL_ERROR_BOOTSTRAP + + If 1, do not use TLS and implement _dl_signal_cerror and + _dl_receive_error. If 0, TLS is used, and the variants with + error callbacks are not provided. */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +/* This structure communicates state between _dl_catch_error and + _dl_signal_error. */ +struct catch + { + const char **objname; /* Object/File name. */ + const char **errstring; /* Error detail filled in here. */ + bool *malloced; /* Nonzero if the string is malloced + by the libc malloc. */ + volatile int *errcode; /* Return value of _dl_signal_error. */ + jmp_buf env; /* longjmp here on error. */ + }; + +/* Multiple threads at once can use the `_dl_catch_error' function. The + calls can come from `_dl_map_object_deps', `_dlerror_run', or from + any of the libc functionality which loads dynamic objects (NSS, iconv). + Therefore we have to be prepared to save the state in thread-local + memory. */ +#if !DL_ERROR_BOOTSTRAP +static __thread struct catch *catch_hook attribute_tls_model_ie; +#else +/* The version of this code in ld.so cannot use thread-local variables + and is used during bootstrap only. */ +static struct catch *catch_hook; +#endif + +/* This message we return as a last resort. We define the string in a + variable since we have to avoid freeing it and so have to enable + a pointer comparison. See below and in dlfcn/dlerror.c. */ +static const char _dl_out_of_memory[] = "out of memory"; + +#if DL_ERROR_BOOTSTRAP +/* This points to a function which is called when an continuable error is + received. Unlike the handling of `catch' this function may return. + The arguments will be the `errstring' and `objname'. + + Since this functionality is not used in normal programs (only in ld.so) + we do not care about multi-threaded programs here. We keep this as a + global variable. */ +static receiver_fct receiver; +#endif /* DL_ERROR_BOOTSTRAP */ + +void +internal_function +_dl_signal_error (int errcode, const char *objname, const char *occation, + const char *errstring) +{ + struct catch *lcatch = catch_hook; + + if (! errstring) + errstring = N_("DYNAMIC LINKER BUG!!!"); + + if (objname == NULL) + objname = ""; + if (lcatch != NULL) + { + /* We are inside _dl_catch_error. Return to it. We have to + duplicate the error string since it might be allocated on the + stack. The object name is always a string constant. */ + size_t len_objname = strlen (objname) + 1; + size_t len_errstring = strlen (errstring) + 1; + + char *errstring_copy = malloc (len_objname + len_errstring); + if (errstring_copy != NULL) + { + /* Make a copy of the object file name and the error string. */ + *lcatch->objname = memcpy (__mempcpy (errstring_copy, + errstring, len_errstring), + objname, len_objname); + *lcatch->errstring = errstring_copy; + + /* If the main executable is relocated it means the libc's malloc + is used. */ + bool malloced = true; +#ifdef SHARED + malloced = (GL(dl_ns)[LM_ID_BASE]._ns_loaded != NULL + && (GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_relocated != 0)); +#endif + *lcatch->malloced = malloced; + } + else + { + /* This is better than nothing. */ + *lcatch->objname = ""; + *lcatch->errstring = _dl_out_of_memory; + *lcatch->malloced = false; + } + + *lcatch->errcode = errcode; + + /* We do not restore the signal mask because none was saved. */ + __longjmp (lcatch->env[0].__jmpbuf, 1); + } + else + { + /* Lossage while resolving the program's own symbols is always fatal. */ + char buffer[1024]; + _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n", + RTLD_PROGNAME, + occation ?: N_("error while loading shared libraries"), + objname, *objname ? ": " : "", + errstring, errcode ? ": " : "", + (errcode + ? __strerror_r (errcode, buffer, sizeof buffer) + : "")); + } +} +libc_hidden_def (_dl_signal_error) + + +#if DL_ERROR_BOOTSTRAP +void +internal_function +_dl_signal_cerror (int errcode, const char *objname, const char *occation, + const char *errstring) +{ + if (__builtin_expect (GLRO(dl_debug_mask) + & ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0)) + _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation, + errstring, receiver ? "continued" : "fatal"); + + if (receiver) + { + /* We are inside _dl_receive_error. Call the user supplied + handler and resume the work. The receiver will still be + installed. */ + (*receiver) (errcode, objname, errstring); + } + else + _dl_signal_error (errcode, objname, occation, errstring); +} +#endif /* DL_ERROR_BOOTSTRAP */ + + +int +internal_function +_dl_catch_error (const char **objname, const char **errstring, + bool *mallocedp, void (*operate) (void *), void *args) +{ + /* We need not handle `receiver' since setting a `catch' is handled + before it. */ + + /* Only this needs to be marked volatile, because it is the only local + variable that gets changed between the setjmp invocation and the + longjmp call. All others are just set here (before setjmp) and read + in _dl_signal_error (before longjmp). */ + volatile int errcode; + + struct catch c; + /* Don't use an initializer since we don't need to clear C.env. */ + c.objname = objname; + c.errstring = errstring; + c.malloced = mallocedp; + c.errcode = &errcode; + + struct catch *const old = catch_hook; + catch_hook = &c; + + /* Do not save the signal mask. */ + if (__builtin_expect (__sigsetjmp (c.env, 0), 0) == 0) + { + (*operate) (args); + catch_hook = old; + *objname = NULL; + *errstring = NULL; + *mallocedp = false; + return 0; + } + + /* We get here only if we longjmp'd out of OPERATE. _dl_signal_error has + already stored values into *OBJNAME, *ERRSTRING, and *MALLOCEDP. */ + catch_hook = old; + return errcode; +} +libc_hidden_def (_dl_catch_error) + +#if DL_ERROR_BOOTSTRAP +void +internal_function +_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args) +{ + struct catch *old_catch = catch_hook; + receiver_fct old_receiver = receiver; + + /* Set the new values. */ + catch_hook = NULL; + receiver = fct; + + (*operate) (args); + + catch_hook = old_catch; + receiver = old_receiver; +} +#endif /* DL_ERROR_BOOTSTRAP */ diff --git a/elf/dl-error.c b/elf/dl-error.c index bd22ec6..7fe36b4 100644 --- a/elf/dl-error.c +++ b/elf/dl-error.c @@ -1,4 +1,4 @@ -/* Error handling for runtime dynamic linker. +/* Error handling for runtime dynamic linker, full version. Copyright (C) 1995-2016 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -16,206 +16,12 @@ License along with the GNU C Library; if not, see . */ -#include -#include -#include -#include -#include -#include -#include +/* This implementation lives in libc.so because it uses thread-local + data, which is not available in ld.so. It interposes the version + in dl-error-minimal.c after ld.so bootstrap. -/* This structure communicates state between _dl_catch_error and - _dl_signal_error. */ -struct catch - { - const char **objname; /* Object/File name. */ - const char **errstring; /* Error detail filled in here. */ - bool *malloced; /* Nonzero if the string is malloced - by the libc malloc. */ - volatile int *errcode; /* Return value of _dl_signal_error. */ - jmp_buf env; /* longjmp here on error. */ - }; + The signal/catch mechanism is used by the audit framework, which + means that even in ld.so, not all errors are fatal. */ -/* Multiple threads at once can use the `_dl_catch_error' function. The - calls can come from `_dl_map_object_deps', `_dlerror_run', or from - any of the libc functionality which loads dynamic objects (NSS, iconv). - Therefore we have to be prepared to save the state in thread-local - memory. The _dl_error_catch_tsd function pointer is reset by the thread - library so that it returns the address of a thread-local variable. */ - - -/* This message we return as a last resort. We define the string in a - variable since we have to avoid freeing it and so have to enable - a pointer comparison. See below and in dlfcn/dlerror.c. */ -static const char _dl_out_of_memory[] = "out of memory"; - - -/* This points to a function which is called when an continuable error is - received. Unlike the handling of `catch' this function may return. - The arguments will be the `errstring' and `objname'. - - Since this functionality is not used in normal programs (only in ld.so) - we do not care about multi-threaded programs here. We keep this as a - global variable. */ -static receiver_fct receiver; - -#ifdef _LIBC_REENTRANT -# define CATCH_HOOK (*(struct catch **) (*GL(dl_error_catch_tsd)) ()) -#else -static struct catch *catch_hook; -# define CATCH_HOOK catch_hook -#endif - -void -internal_function -_dl_signal_error (int errcode, const char *objname, const char *occation, - const char *errstring) -{ - struct catch *lcatch; - - if (! errstring) - errstring = N_("DYNAMIC LINKER BUG!!!"); - - lcatch = CATCH_HOOK; - if (objname == NULL) - objname = ""; - if (lcatch != NULL) - { - /* We are inside _dl_catch_error. Return to it. We have to - duplicate the error string since it might be allocated on the - stack. The object name is always a string constant. */ - size_t len_objname = strlen (objname) + 1; - size_t len_errstring = strlen (errstring) + 1; - - char *errstring_copy = malloc (len_objname + len_errstring); - if (errstring_copy != NULL) - { - /* Make a copy of the object file name and the error string. */ - *lcatch->objname = memcpy (__mempcpy (errstring_copy, - errstring, len_errstring), - objname, len_objname); - *lcatch->errstring = errstring_copy; - - /* If the main executable is relocated it means the libc's malloc - is used. */ - bool malloced = true; -#ifdef SHARED - malloced = (GL(dl_ns)[LM_ID_BASE]._ns_loaded != NULL - && (GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_relocated != 0)); -#endif - *lcatch->malloced = malloced; - } - else - { - /* This is better than nothing. */ - *lcatch->objname = ""; - *lcatch->errstring = _dl_out_of_memory; - *lcatch->malloced = false; - } - - *lcatch->errcode = errcode; - - /* We do not restore the signal mask because none was saved. */ - __longjmp (lcatch->env[0].__jmpbuf, 1); - } - else - { - /* Lossage while resolving the program's own symbols is always fatal. */ - char buffer[1024]; - _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n", - RTLD_PROGNAME, - occation ?: N_("error while loading shared libraries"), - objname, *objname ? ": " : "", - errstring, errcode ? ": " : "", - (errcode - ? __strerror_r (errcode, buffer, sizeof buffer) - : "")); - } -} - - -void -internal_function -_dl_signal_cerror (int errcode, const char *objname, const char *occation, - const char *errstring) -{ - if (__builtin_expect (GLRO(dl_debug_mask) - & ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0)) - _dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation, - errstring, receiver ? "continued" : "fatal"); - - if (receiver) - { - /* We are inside _dl_receive_error. Call the user supplied - handler and resume the work. The receiver will still be - installed. */ - (*receiver) (errcode, objname, errstring); - } - else - _dl_signal_error (errcode, objname, occation, errstring); -} - - -int -internal_function -_dl_catch_error (const char **objname, const char **errstring, - bool *mallocedp, void (*operate) (void *), void *args) -{ - /* We need not handle `receiver' since setting a `catch' is handled - before it. */ - - /* Only this needs to be marked volatile, because it is the only local - variable that gets changed between the setjmp invocation and the - longjmp call. All others are just set here (before setjmp) and read - in _dl_signal_error (before longjmp). */ - volatile int errcode; - - struct catch c; - /* Don't use an initializer since we don't need to clear C.env. */ - c.objname = objname; - c.errstring = errstring; - c.malloced = mallocedp; - c.errcode = &errcode; - - struct catch **const catchp = &CATCH_HOOK; - struct catch *const old = *catchp; - *catchp = &c; - - /* Do not save the signal mask. */ - if (__builtin_expect (__sigsetjmp (c.env, 0), 0) == 0) - { - (*operate) (args); - *catchp = old; - *objname = NULL; - *errstring = NULL; - *mallocedp = false; - return 0; - } - - /* We get here only if we longjmp'd out of OPERATE. _dl_signal_error has - already stored values into *OBJNAME, *ERRSTRING, and *MALLOCEDP. */ - *catchp = old; - return errcode; -} - - -void -internal_function -_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args) -{ - struct catch **const catchp = &CATCH_HOOK; - struct catch *old_catch; - receiver_fct old_receiver; - - old_catch = *catchp; - old_receiver = receiver; - - /* Set the new values. */ - *catchp = NULL; - receiver = fct; - - (*operate) (args); - - *catchp = old_catch; - receiver = old_receiver; -} +#define DL_ERROR_BOOTSTRAP 0 +#include "dl-error-skeleton.c" diff --git a/elf/dl-libc.c b/elf/dl-libc.c index d56de1a..dde44c8 100644 --- a/elf/dl-libc.c +++ b/elf/dl-libc.c @@ -43,8 +43,8 @@ dlerror_run (void (*operate) (void *), void *args) const char *last_errstring = NULL; bool malloced; - int result = (GLRO(dl_catch_error) (&objname, &last_errstring, &malloced, - operate, args) + int result = (_dl_catch_error (&objname, &last_errstring, &malloced, + operate, args) ?: last_errstring != NULL); if (result && malloced) diff --git a/elf/dl-sym.c b/elf/dl-sym.c index 6431c22..e00b286 100644 --- a/elf/dl-sym.c +++ b/elf/dl-sym.c @@ -123,8 +123,8 @@ do_sym (void *handle, const char *name, void *who, const char *objname; const char *errstring = NULL; bool malloced; - int err = GLRO(dl_catch_error) (&objname, &errstring, &malloced, - call_dl_lookup, &args); + int err = _dl_catch_error (&objname, &errstring, &malloced, + call_dl_lookup, &args); THREAD_GSCOPE_RESET_FLAG (); @@ -136,7 +136,7 @@ do_sym (void *handle, const char *name, void *who, if (malloced) free ((char *) errstring); - GLRO(dl_signal_error) (err, objname_dup, NULL, errstring_dup); + _dl_signal_error (err, objname_dup, NULL, errstring_dup); /* NOTREACHED */ } @@ -150,7 +150,7 @@ do_sym (void *handle, const char *name, void *who, if (match == NULL || caller < match->l_map_start || caller >= match->l_map_end) - GLRO(dl_signal_error) (0, NULL, NULL, N_("\ + _dl_signal_error (0, NULL, NULL, N_("\ RTLD_NEXT used in code not dynamically loaded")); } diff --git a/elf/dl-tsd.c b/elf/dl-tsd.c deleted file mode 100644 index 7181e1c..0000000 --- a/elf/dl-tsd.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Thread-local data used by error handling for runtime dynamic linker. - Copyright (C) 2002-2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#ifdef _LIBC_REENTRANT - -# include -# include - -# ifndef SHARED - -/* _dl_error_catch_tsd points to this for the single-threaded case. - It's reset by the thread library for multithreaded programs - if we're not using __thread. */ -void ** __attribute__ ((const)) -_dl_initial_error_catch_tsd (void) -{ - static __thread void *data; - return &data; -} -void **(*_dl_error_catch_tsd) (void) __attribute__ ((const)) - = &_dl_initial_error_catch_tsd; - -# else - -/* libpthread sets _dl_error_catch_tsd to point to this function. - We define it here instead of in libpthread so that it doesn't - need to have a TLS segment of its own just for this one pointer. */ - -void ** __attribute__ ((const)) -__libc_dl_error_tsd (void) -{ - static __thread void *data attribute_tls_model_ie; - return &data; -} - -# endif /* SHARED */ - -#endif /* _LIBC_REENTRANT */ diff --git a/elf/rtld.c b/elf/rtld.c index 647661c..4ec25d7 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -167,8 +167,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro = /* Function pointers. */ ._dl_debug_printf = _dl_debug_printf, - ._dl_catch_error = _dl_catch_error, - ._dl_signal_error = _dl_signal_error, ._dl_mcount = _dl_mcount, ._dl_lookup_symbol_x = _dl_lookup_symbol_x, ._dl_check_caller = _dl_check_caller, @@ -637,18 +635,6 @@ cannot allocate TLS data structures for initial thread"); return tcbp; } -#ifdef _LIBC_REENTRANT -/* _dl_error_catch_tsd points to this for the single-threaded case. - It's reset by the thread library for multithreaded programs. */ -void ** __attribute__ ((const)) -_dl_initial_error_catch_tsd (void) -{ - static void *data; - return &data; -} -#endif - - static unsigned int do_preload (const char *fname, struct link_map *main_map, const char *where) { @@ -752,11 +738,6 @@ dl_main (const ElfW(Phdr) *phdr, #endif void *tcbp = NULL; -#ifdef _LIBC_REENTRANT - /* Explicit initialization since the reloc would just be more work. */ - GL(dl_error_catch_tsd) = &_dl_initial_error_catch_tsd; -#endif - GL(dl_init_static_tls) = &_dl_nothread_init_static_tls; #if defined SHARED && defined _LIBC_REENTRANT \ diff --git a/elf/tst-latepthread.c b/elf/tst-latepthread.c new file mode 100644 index 0000000..9449ef6 --- /dev/null +++ b/elf/tst-latepthread.c @@ -0,0 +1,105 @@ +/* Test that loading libpthread does not break ld.so exceptions (bug 16628). + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include + +static int +do_test (void) +{ + void *handle = dlopen ("tst-latepthreadmod.so", RTLD_LOCAL | RTLD_LAZY); + if (handle == NULL) + { + printf ("error: dlopen failed: %s\n", dlerror ()); + return 1; + } + void *ptr = dlsym (handle, "trigger_dynlink_failure"); + if (ptr == NULL) + { + printf ("error: dlsym failed: %s\n", dlerror ()); + return 1; + } + int (*func) (void) = ptr; + + /* Run the actual test in a subprocess, to capture the error. */ + int fds[2]; + if (pipe (fds) < 0) + { + printf ("error: pipe: %m\n"); + return 1; + } + pid_t pid = fork (); + if (pid < 0) + { + printf ("error: fork: %m\n"); + return 1; + } + else if (pid == 0) + { + if (dup2 (fds[1], STDERR_FILENO) < 0) + _exit (2); + /* Trigger an abort. */ + func (); + _exit (3); + } + /* NB: This assumes that the abort message is so short that the pipe + does not block. */ + int status; + if (waitpid (pid, &status, 0) < 0) + { + printf ("error: waitpid: %m\n"); + return 1; + } + + /* Check the printed error message. */ + if (close (fds[1]) < 0) + { + printf ("error: close: %m\n"); + return 1; + } + char buf[512]; + /* Leave room for the NUL terminator. */ + ssize_t ret = read (fds[0], buf, sizeof (buf) - 1); + if (ret < 0) + { + printf ("error: read: %m\n"); + return 1; + } + if (ret > 0 && buf[ret - 1] == '\n') + --ret; + buf[ret] = '\0'; + printf ("info: exit status: %d, message: %s\n", status, buf); + if (strstr (buf, "undefined symbol: this_function_is_not_defined") == NULL) + { + printf ("error: message does not contain expected string\n"); + return 1; + } + if (!WIFEXITED (status) || WEXITSTATUS (status) != 127) + { + printf ("error: unexpected process exit status\n"); + return 1; + } + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/elf/tst-latepthreadmod.c b/elf/tst-latepthreadmod.c new file mode 100644 index 0000000..ce81206 --- /dev/null +++ b/elf/tst-latepthreadmod.c @@ -0,0 +1,33 @@ +/* DSO which links against libpthread and triggers a lazy binding. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* This file is compiled into a DSO which loads libpthread, but fails + the dynamic linker afterwards. */ + +#include + +/* Link in libpthread. */ +void *pthread_create_ptr = &pthread_create; + +int this_function_is_not_defined (void); + +int +trigger_dynlink_failure (void) +{ + return this_function_is_not_defined (); +} diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c index 48fab50..0fd54a0 100644 --- a/nptl/nptl-init.c +++ b/nptl/nptl-init.c @@ -456,10 +456,6 @@ __pthread_initialize_minimal_internal (void) lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE); #ifdef SHARED - /* Transfer the old value from the dynamic linker's internal location. */ - *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) (); - GL(dl_error_catch_tsd) = &__libc_dl_error_tsd; - /* Make __rtld_lock_{,un}lock_recursive use pthread_mutex_{,un}lock, keep the lock count from the ld.so implementation. */ GL(dl_rtld_lock_recursive) = (void *) __pthread_mutex_lock; diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index f68fdf4..288f5fe 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -357,10 +357,6 @@ struct rtld_global /* List of search directories. */ EXTERN struct r_search_path_elem *_dl_all_dirs; -#ifdef _LIBC_REENTRANT - EXTERN void **(*_dl_error_catch_tsd) (void) __attribute__ ((const)); -#endif - /* Structure describing the dynamic linker itself. We need to reserve memory for the data the audit libraries need. */ EXTERN struct link_map _dl_rtld_map; @@ -583,10 +579,6 @@ struct rtld_global_ro PLT relocations in libc.so. */ void (*_dl_debug_printf) (const char *, ...) __attribute__ ((__format__ (__printf__, 1, 2))); - int (internal_function *_dl_catch_error) (const char **, const char **, - bool *, void (*) (void *), void *); - void (internal_function *_dl_signal_error) (int, const char *, const char *, - const char *); void (*_dl_mcount) (ElfW(Addr) frompc, ElfW(Addr) selfpc); lookup_t (internal_function *_dl_lookup_symbol_x) (const char *, struct link_map *, @@ -632,13 +624,6 @@ extern const ElfW(Phdr) *_dl_phdr; extern size_t _dl_phnum; #endif -#if IS_IN (rtld) -/* This is the initial value of GL(dl_error_catch_tsd). - A non-TLS libpthread will change it. */ -extern void **_dl_initial_error_catch_tsd (void) __attribute__ ((const)) - attribute_hidden; -#endif - /* This is the initial value of GL(dl_make_stack_executable_hook). A threads library can change it. */ extern int _dl_make_stack_executable (void **stack_endp) internal_function; @@ -705,9 +690,20 @@ extern void _dl_debug_printf_c (const char *fmt, ...) /* Write a message on the specified descriptor FD. The parameters are interpreted as for a `printf' call. */ +#if IS_IN (rtld) || !defined (SHARED) extern void _dl_dprintf (int fd, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))) attribute_hidden; +#else +__attribute__ ((always_inline, __format__ (__printf__, 2, 3))) +static inline void +_dl_dprintf (int fd, const char *fmt, ...) +{ + /* Use local declaration to avoid includign . */ + extern int __dprintf(int fd, const char *format, ...) attribute_hidden; + __dprintf (fd, fmt, __builtin_va_arg_pack ()); +} +#endif /* Write a message on the specified descriptor standard output. The parameters are interpreted as for a `printf' call. */ @@ -737,13 +733,26 @@ extern void _dl_dprintf (int fd, const char *fmt, ...) problem. */ extern void _dl_signal_error (int errcode, const char *object, const char *occurred, const char *errstring) - internal_function __attribute__ ((__noreturn__)) attribute_hidden; + internal_function __attribute__ ((__noreturn__)); +libc_hidden_proto (_dl_signal_error) /* Like _dl_signal_error, but may return when called in the context of - _dl_receive_error. */ + _dl_receive_error. This is only used during ld.so bootstrap. In + static and profiled builds, this is equivalent to + _dl_signal_error. */ +#if IS_IN (rtld) extern void _dl_signal_cerror (int errcode, const char *object, const char *occation, const char *errstring) internal_function attribute_hidden; +#else +__attribute__ ((always_inline)) +static inline void +_dl_signal_cerror (int errcode, const char *object, + const char *occation, const char *errstring) +{ + _dl_signal_error (errcode, object, occation, errstring); +} +#endif /* Call OPERATE, receiving errors from `dl_signal_cerror'. Unlike `_dl_catch_error' the operation is resumed after the OPERATE @@ -764,7 +773,8 @@ extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *), extern int _dl_catch_error (const char **objname, const char **errstring, bool *mallocedp, void (*operate) (void *), void *args) - internal_function attribute_hidden; + internal_function; +libc_hidden_proto (_dl_catch_error) /* Open the shared object NAME and map in its segments. LOADER's DT_RPATH is used in searching for NAME. diff --git a/sysdeps/generic/localplt.data b/sysdeps/generic/localplt.data index 1a40cf9..5cf53a4 100644 --- a/sysdeps/generic/localplt.data +++ b/sysdeps/generic/localplt.data @@ -15,3 +15,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/aarch64/localplt.data b/sysdeps/unix/sysv/linux/aarch64/localplt.data index d7d6734..e431f36 100644 --- a/sysdeps/unix/sysv/linux/aarch64/localplt.data +++ b/sysdeps/unix/sysv/linux/aarch64/localplt.data @@ -16,3 +16,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/alpha/localplt.data b/sysdeps/unix/sysv/linux/alpha/localplt.data index 351596c..2984393 100644 --- a/sysdeps/unix/sysv/linux/alpha/localplt.data +++ b/sysdeps/unix/sysv/linux/alpha/localplt.data @@ -33,3 +33,6 @@ ld.so: malloc + RELA R_ALPHA_GLOB_DAT ld.so: calloc + RELA R_ALPHA_GLOB_DAT ld.so: realloc + RELA R_ALPHA_GLOB_DAT ld.so: free + RELA R_ALPHA_GLOB_DAT +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error + RELA R_ALPHA_GLOB_DAT +ld.so: _dl_catch_error + RELA R_ALPHA_GLOB_DAT diff --git a/sysdeps/unix/sysv/linux/arm/localplt.data b/sysdeps/unix/sysv/linux/arm/localplt.data index 4301703..a5ccd7f 100644 --- a/sysdeps/unix/sysv/linux/arm/localplt.data +++ b/sysdeps/unix/sysv/linux/arm/localplt.data @@ -16,3 +16,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/hppa/localplt.data b/sysdeps/unix/sysv/linux/hppa/localplt.data index 2a25ebc..fea8c9c 100644 --- a/sysdeps/unix/sysv/linux/hppa/localplt.data +++ b/sysdeps/unix/sysv/linux/hppa/localplt.data @@ -21,3 +21,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/i386/localplt.data b/sysdeps/unix/sysv/linux/i386/localplt.data index 4ce8447..48bcc42 100644 --- a/sysdeps/unix/sysv/linux/i386/localplt.data +++ b/sysdeps/unix/sysv/linux/i386/localplt.data @@ -15,3 +15,6 @@ ld.so: malloc + REL R_386_GLOB_DAT ld.so: calloc + REL R_386_GLOB_DAT ld.so: realloc + REL R_386_GLOB_DAT ld.so: free + REL R_386_GLOB_DAT +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error + REL R_386_GLOB_DAT +ld.so: _dl_catch_error + REL R_386_GLOB_DAT diff --git a/sysdeps/unix/sysv/linux/ia64/localplt.data b/sysdeps/unix/sysv/linux/ia64/localplt.data index b628ca4..df63530 100644 --- a/sysdeps/unix/sysv/linux/ia64/localplt.data +++ b/sysdeps/unix/sysv/linux/ia64/localplt.data @@ -14,3 +14,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/m68k/localplt.data b/sysdeps/unix/sysv/linux/m68k/localplt.data index 88124c4..abfbd34 100644 --- a/sysdeps/unix/sysv/linux/m68k/localplt.data +++ b/sysdeps/unix/sysv/linux/m68k/localplt.data @@ -14,3 +14,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/microblaze/localplt.data b/sysdeps/unix/sysv/linux/microblaze/localplt.data index 176d618..697fdd0 100644 --- a/sysdeps/unix/sysv/linux/microblaze/localplt.data +++ b/sysdeps/unix/sysv/linux/microblaze/localplt.data @@ -15,3 +15,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/nios2/localplt.data b/sysdeps/unix/sysv/linux/nios2/localplt.data index 6cf93cc..a7d774d 100644 --- a/sysdeps/unix/sysv/linux/nios2/localplt.data +++ b/sysdeps/unix/sysv/linux/nios2/localplt.data @@ -35,3 +35,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data index b25abf8..4ef5bf4 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data @@ -13,3 +13,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data index 8c4e65d..c919426 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data @@ -43,3 +43,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data index 49d5de6..2d43472 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data @@ -12,3 +12,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/s390/localplt.data b/sysdeps/unix/sysv/linux/s390/localplt.data index 1226413..bd1addd 100644 --- a/sysdeps/unix/sysv/linux/s390/localplt.data +++ b/sysdeps/unix/sysv/linux/s390/localplt.data @@ -20,3 +20,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/sh/localplt.data b/sysdeps/unix/sysv/linux/sh/localplt.data index 57f31c5..e6fb930 100644 --- a/sysdeps/unix/sysv/linux/sh/localplt.data +++ b/sysdeps/unix/sysv/linux/sh/localplt.data @@ -18,3 +18,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data index a208adf..d5b5895 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data @@ -24,3 +24,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data index 2323551..edceab5 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data @@ -26,3 +26,6 @@ ld.so: malloc ld.so: calloc ld.so: realloc ld.so: free +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error +ld.so: _dl_catch_error diff --git a/sysdeps/x86_64/localplt.data b/sysdeps/x86_64/localplt.data index f168b14..28096f8 100644 --- a/sysdeps/x86_64/localplt.data +++ b/sysdeps/x86_64/localplt.data @@ -17,3 +17,6 @@ ld.so: malloc + RELA R_X86_64_GLOB_DAT ld.so: calloc + RELA R_X86_64_GLOB_DAT ld.so: realloc + RELA R_X86_64_GLOB_DAT ld.so: free + RELA R_X86_64_GLOB_DAT +# The TLS-enabled version of these functions is interposed from libc.so. +ld.so: _dl_signal_error + RELA R_X86_64_GLOB_DAT +ld.so: _dl_catch_error + RELA R_X86_64_GLOB_DAT -- 2.7.4