From patchwork Mon Nov 14 15:07:15 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 82127 Delivered-To: patch@linaro.org Received: by 10.140.97.165 with SMTP id m34csp1052273qge; Mon, 14 Nov 2016 07:07:43 -0800 (PST) X-Received: by 10.99.65.65 with SMTP id o62mr45911530pga.73.1479136063103; Mon, 14 Nov 2016 07:07:43 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id f67si22508115pgc.288.2016.11.14.07.07.42 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 Nov 2016 07:07:43 -0800 (PST) Received-SPF: pass (google.com: domain of libc-alpha-return-74712-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org; spf=pass (google.com: domain of libc-alpha-return-74712-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=libc-alpha-return-74712-patch=linaro.org@sourceware.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:from:subject:message-id:date:mime-version :content-type; q=dns; s=default; b=FnN0n4wnv8EeCHxfWu2QXsyrt1Snz kmANXBmwDQaPbuD9J+KzNy2zL1sMvAH4V22mhKhPaLpgwaruacTQ7/89MyamKMx7 14qOHgU0UfZEeLoBdTtWEV+dOAoSu2KSDeXi6RWJiuY0MfTNQnbRhDMw0vpk00im YeAETbxys2CE20= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:from:subject:message-id:date:mime-version :content-type; s=default; bh=yRNavK04fPvJifi6j6GrRKVLYfg=; b=qA6 opvW84F3D9UQKFWoK+HI2z8UBZGrqU6rds68jp08Oba6Auw4x6xvULiKXEdw/0Z8 pJX77d94HLmOXs24KwSHfol0wzEfr2WB0yjFQpNiGgd5mAS5Wa1QSjUR7ZMcmab9 RETYVngnVFHAnRh24CcjaCZ0N4kMpTe7JZlNZKDo= Received: (qmail 64892 invoked by alias); 14 Nov 2016 15:07:30 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 64874 invoked by uid 89); 14 Nov 2016 15:07:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=BAYES_50, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=audit, lives, sysv, Template X-HELO: mx1.redhat.com To: GNU C Library From: Florian Weimer Subject: [PATCH] Implement _dl_catch_error, _dl_signal_error in libc.so [BZ #16628] Message-ID: <7650651f-f268-6405-c04c-61aa18d166f9@redhat.com> Date: Mon, 14 Nov 2016 16:07:15 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 The attached patch depends on the elf/dl-load.c clean I posted today, and the addition of the __sigsetjmp hidden definitions on architectures which lack them. The removal of the two function pointers from libc.so (the one in rtld_global, and the receiver pointer internal to elf/dl-error.c) is desirable from a security perspective, too. Thanks, Florian 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. 2016-11-11 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, elf/dl-error-minimal.c: New files. * elf/Makefile (routines): Add dl-error. (dl-routines): Remove dl-error. (rtld-routines): Add dl-error-minimal. * 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. 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..99942e3 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 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/nptl/nptl-init.c b/nptl/nptl-init.c index bdbdfed..839e3fe 100644 --- a/nptl/nptl-init.c +++ b/nptl/nptl-init.c @@ -467,10 +467,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