@@ -24,7 +24,7 @@ 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-sysdep dl-error \
+ dl-origin dl-libc dl-sym dl-sysdep \
dl-reloc-static-pie libc_early_init
# The core dynamic linking functions are in libc for the static and
@@ -34,7 +34,7 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps hwcaps \
version profile tls origin scope \
execstack open close trampoline \
exception sort-maps lookup-direct \
- call-libc-early-init)
+ call-libc-early-init catch)
ifeq (yes,$(use-ldconfig))
dl-routines += dl-cache
endif
@@ -59,7 +59,7 @@ elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
# 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 \
- dl-error-minimal dl-conflict
+ dl-conflict
all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines)
CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables
@@ -27,10 +27,6 @@ libc {
_dl_sym; _dl_vsym;
__libc_dlclose; __libc_dlopen_mode; __libc_dlsym; __libc_dlvsym;
__libc_early_init;
-
- # Internal error handling support. Interposes the functions in ld.so.
- _dl_signal_exception; _dl_catch_exception;
- _dl_signal_error; _dl_catch_error;
}
}
@@ -69,8 +65,6 @@ ld {
# Internal error handling support.
_dl_exception_create; _dl_exception_create_format; _dl_exception_free;
-
- # Internal error handling support. Interposed by libc.so.
_dl_signal_exception; _dl_catch_exception;
_dl_signal_error; _dl_catch_error;
similarity index 80%
rename from elf/dl-error-skeleton.c
rename to elf/dl-catch.c
@@ -1,4 +1,4 @@
-/* Template for error handling for runtime dynamic linker.
+/* Exception handling in the dynamic linker.
Copyright (C) 1995-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -16,16 +16,6 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-/* 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 <libintl.h>
#include <setjmp.h>
#include <stdbool.h>
@@ -34,39 +24,50 @@
#include <unistd.h>
#include <ldsodefs.h>
#include <stdio.h>
+#include <tls.h>
/* This structure communicates state between _dl_catch_error and
_dl_signal_error. */
-struct catch
+struct rtld_catch
{
struct dl_exception *exception; /* The exception data is stored there. */
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;
+/* 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. We use THREAD_GETMEM and THREAD_SETMEM
+ instead of ELF TLS because it exception handling must work before
+ the TCB and ELF TLS have been set up. */
+
+#if IS_IN (rtld)
+static struct rtld_catch *rtld_catch_notls;
#endif
-#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'.
+static struct rtld_catch *
+get_catch (void)
+{
+#if IS_IN (rtld)
+ if (!__rtld_tls_init_tp_called)
+ return rtld_catch_notls;
+ else
+#endif
+ return THREAD_GETMEM (THREAD_SELF, rtld_catch);
+}
- 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 */
+static void
+set_catch (struct rtld_catch *catch)
+{
+#if IS_IN (rtld)
+ if (!__rtld_tls_init_tp_called)
+ rtld_catch_notls = catch;
+ else
+#endif
+ THREAD_SETMEM (THREAD_SELF, rtld_catch, catch);
+}
/* Lossage while resolving the program's own symbols is always fatal. */
static void
@@ -89,7 +90,7 @@ void
_dl_signal_exception (int errcode, struct dl_exception *exception,
const char *occasion)
{
- struct catch *lcatch = catch_hook;
+ struct rtld_catch *lcatch = get_catch ();
if (lcatch != NULL)
{
*lcatch->exception = *exception;
@@ -101,13 +102,13 @@ _dl_signal_exception (int errcode, struct dl_exception *exception,
else
fatal_error (errcode, exception->objname, occasion, exception->errstring);
}
-libc_hidden_def (_dl_signal_exception)
+rtld_hidden_def (_dl_signal_exception)
void
_dl_signal_error (int errcode, const char *objname, const char *occation,
const char *errstring)
{
- struct catch *lcatch = catch_hook;
+ struct rtld_catch *lcatch = get_catch ();
if (! errstring)
errstring = N_("DYNAMIC LINKER BUG!!!");
@@ -123,10 +124,18 @@ _dl_signal_error (int errcode, const char *objname, const char *occation,
else
fatal_error (errcode, objname, occation, errstring);
}
-libc_hidden_def (_dl_signal_error)
+rtld_hidden_def (_dl_signal_error)
+#if IS_IN (rtld)
+/* 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;
-#if DL_ERROR_BOOTSTRAP
void
_dl_signal_cexception (int errcode, struct dl_exception *exception,
const char *occasion)
@@ -167,7 +176,23 @@ _dl_signal_cerror (int errcode, const char *objname, const char *occation,
else
_dl_signal_error (errcode, objname, occation, errstring);
}
-#endif /* DL_ERROR_BOOTSTRAP */
+
+void
+_dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args)
+{
+ struct rtld_catch *old_catch = get_catch ();
+ receiver_fct old_receiver = receiver;
+
+ /* Set the new values. */
+ set_catch (NULL);
+ receiver = fct;
+
+ (*operate) (args);
+
+ set_catch (old_catch);
+ receiver = old_receiver;
+}
+#endif
int
_dl_catch_exception (struct dl_exception *exception,
@@ -177,11 +202,11 @@ _dl_catch_exception (struct dl_exception *exception,
Exceptions during operate (args) are fatal. */
if (exception == NULL)
{
- struct catch *const old = catch_hook;
- catch_hook = NULL;
+ struct rtld_catch *old_catch = get_catch ();
+ set_catch (NULL);
operate (args);
/* If we get here, the operation was successful. */
- catch_hook = old;
+ set_catch (old_catch);
return 0;
}
@@ -194,19 +219,19 @@ _dl_catch_exception (struct dl_exception *exception,
in _dl_signal_error (before longjmp). */
volatile int errcode;
- struct catch c;
+ struct rtld_catch c;
/* Don't use an initializer since we don't need to clear C.env. */
c.exception = exception;
c.errcode = &errcode;
- struct catch *const old = catch_hook;
- catch_hook = &c;
+ struct rtld_catch *old = get_catch ();
+ set_catch (&c);
/* Do not save the signal mask. */
if (__builtin_expect (__sigsetjmp (c.env, 0), 0) == 0)
{
(*operate) (args);
- catch_hook = old;
+ set_catch (old);
*exception = (struct dl_exception) { NULL };
return 0;
}
@@ -214,10 +239,10 @@ _dl_catch_exception (struct dl_exception *exception,
/* We get here only if we longjmp'd out of OPERATE.
_dl_signal_exception has already stored values into
*EXCEPTION. */
- catch_hook = old;
+ set_catch (old);
return errcode;
}
-libc_hidden_def (_dl_catch_exception)
+rtld_hidden_def (_dl_catch_exception)
int
_dl_catch_error (const char **objname, const char **errstring,
@@ -230,22 +255,4 @@ _dl_catch_error (const char **objname, const char **errstring,
*mallocedp = exception.message_buffer == exception.errstring;
return errorcode;
}
-libc_hidden_def (_dl_catch_error)
-
-#if DL_ERROR_BOOTSTRAP
-void
-_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 */
+rtld_hidden_def (_dl_catch_error)
deleted file mode 100644
@@ -1,23 +0,0 @@
-/* Error handling for runtime dynamic linker, minimal version.
- Copyright (C) 1995-2020 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
- <https://www.gnu.org/licenses/>. */
-
-/* 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"
deleted file mode 100644
@@ -1,27 +0,0 @@
-/* Error handling for runtime dynamic linker, full version.
- Copyright (C) 1995-2020 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
- <https://www.gnu.org/licenses/>. */
-
-/* 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.
-
- The signal/catch mechanism is used by the audit framework, which
- means that even in ld.so, not all errors are fatal. */
-
-#define DL_ERROR_BOOTSTRAP 0
-#include "dl-error-skeleton.c"
@@ -395,6 +395,9 @@ struct pthread
masked.) */
sigset_t sigmask;
+ /* Used by the exception handling implementation in the dynamic loader. */
+ struct rtld_catch *rtld_catch;
+
/* Indicates whether is a C11 thread created by thrd_creat. */
bool c11;
@@ -815,13 +815,13 @@ rtld_hidden_proto (_dl_exception_free)
void _dl_signal_exception (int errcode, struct dl_exception *,
const char *occasion)
__attribute__ ((__noreturn__));
-libc_hidden_proto (_dl_signal_exception)
+rtld_hidden_proto (_dl_signal_exception)
/* Like _dl_signal_exception, but creates the exception first. */
extern void _dl_signal_error (int errcode, const char *object,
const char *occasion, const char *errstring)
__attribute__ ((__noreturn__));
-libc_hidden_proto (_dl_signal_error)
+rtld_hidden_proto (_dl_signal_error)
/* Like _dl_signal_exception, but may return when called in the
context of _dl_receive_error. This is only used during ld.so
@@ -874,7 +874,7 @@ 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);
-libc_hidden_proto (_dl_catch_error)
+rtld_hidden_proto (_dl_catch_error)
/* Call OPERATE (ARGS). If no error occurs, set *EXCEPTION to zero.
Otherwise, store a copy of the raised exception in *EXCEPTION,
@@ -883,7 +883,7 @@ libc_hidden_proto (_dl_catch_error)
disabled (so that exceptions are fatal). */
int _dl_catch_exception (struct dl_exception *exception,
void (*operate) (void *), void *args);
-libc_hidden_proto (_dl_catch_exception)
+rtld_hidden_proto (_dl_catch_exception)
/* Open the shared object NAME and map in its segments.
LOADER's DT_RPATH is used in searching for NAME.
@@ -7,8 +7,3 @@ libc.so: malloc
libc.so: memalign
libc.so: realloc
libm.so: matherr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -9,11 +9,6 @@ libc.so: malloc + REL R_386_GLOB_DAT
libc.so: memalign + REL R_386_GLOB_DAT
libc.so: realloc + REL R_386_GLOB_DAT
libm.so: matherr + 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
-ld.so: _dl_signal_exception + REL R_386_GLOB_DAT
-ld.so: _dl_catch_exception + REL R_386_GLOB_DAT
# The dynamic linker has its own versions of basic functions for initial loading
# of shared libraries. These need to be overriden by libc once loaded.
ld.so: __open ?
@@ -40,12 +35,16 @@ ld.so: __errno_location
# functions above which do need a PLT. These are thus currently expected.
ld.so: _dl_allocate_tls
ld.so: _dl_allocate_tls_init
+ld.so: _dl_catch_error
+ld.so: _dl_catch_exception
ld.so: _dl_exception_create
ld.so: _dl_exception_create_format
ld.so: _dl_exception_free
ld.so: _dl_find_dso_for_object
ld.so: _dl_init_first
ld.so: _dl_mcount
+ld.so: _dl_signal_error
+ld.so: _dl_signal_exception
ld.so: ___tls_get_addr
ld.so: __tunable_get_val
#
@@ -48,6 +48,9 @@ typedef struct
compatible with the i386 Linux version. */
mach_port_t reply_port; /* This thread's reply port. */
struct hurd_sigstate *_hurd_sigstate;
+
+ /* Used by the exception handling implementation in the dynamic loader. */
+ struct rtld_catch *rtld_catch;
} tcbhead_t;
#endif
@@ -9,8 +9,3 @@ libc.so: realloc
libm.so: matherr
# The dynamic loader needs __tls_get_addr for TLS.
ld.so: __tls_get_addr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -26,8 +26,3 @@ libm.so: matherr + RELA R_ALPHA_GLOB_DAT
libm.so: __atan2
# The dynamic loader needs __tls_get_addr for TLS.
ld.so: __tls_get_addr ?
-# 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
-ld.so: _dl_signal_exception + RELA R_ALPHA_GLOB_DAT
-ld.so: _dl_catch_exception + RELA R_ALPHA_GLOB_DAT
@@ -8,8 +8,3 @@ libm.so: matherr
libpthread.so: raise
# The dynamic loader needs __tls_get_addr for TLS.
ld.so: __tls_get_addr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -6,8 +6,3 @@ libc.so: free
libc.so: malloc
libc.so: memalign
libc.so: realloc
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -10,8 +10,3 @@ libc.so: __sigsetjmp
libc.so: _IO_funlockfile
libc.so: __errno_location
libm.so: matherr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -7,8 +7,3 @@ libc.so: malloc + REL R_386_GLOB_DAT
libc.so: memalign + REL R_386_GLOB_DAT
libc.so: realloc + REL R_386_GLOB_DAT
libm.so: matherr + 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
-ld.so: _dl_signal_exception + REL R_386_GLOB_DAT
-ld.so: _dl_catch_exception + REL R_386_GLOB_DAT
@@ -6,8 +6,3 @@ libc.so: realloc
libm.so: matherr
libm.so: matherrf
libm.so: matherrl
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -5,8 +5,3 @@ libc.so: malloc
libc.so: memalign
libc.so: realloc
libm.so: matherr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -6,8 +6,3 @@ libc.so: malloc
libc.so: memalign
libc.so: realloc
libm.so: matherr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -7,8 +7,3 @@ libc.so: realloc
libm.so: matherr
# The dynamic loader needs __tls_get_addr for TLS.
ld.so: __tls_get_addr ?
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -28,8 +28,3 @@ libc.so: __eqdf2
libc.so: __extendsfdf2
libc.so: __floatundidf ?
libm.so: matherr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -5,8 +5,3 @@ libc.so: malloc
libc.so: memalign
libc.so: realloc
libm.so: matherr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -36,8 +36,3 @@ libc.so: realloc
libm.so: copysignl ?
libm.so: fabsl
libm.so: matherr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -4,8 +4,3 @@ libc.so: malloc
libc.so: memalign
libc.so: realloc
libm.so: matherr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -6,8 +6,3 @@ libc.so: free
libc.so: malloc
libc.so: memalign
libc.so: realloc
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -5,8 +5,3 @@ libc.so: malloc
libc.so: memalign
libc.so: realloc
libm.so: matherr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -12,8 +12,3 @@ libc.so: __errno_location
libm.so: matherr
# Generated by the compiler because there is no trap insn pattern.
libc.so: abort ?
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -19,8 +19,3 @@ libc.so: malloc
libc.so: memalign
libc.so: realloc
libm.so: matherr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -18,8 +18,3 @@ libc.so: malloc
libc.so: memalign
libc.so: realloc
libm.so: matherr
-# The TLS-enabled version of these functions is interposed from libc.so.
-ld.so: _dl_signal_error
-ld.so: _dl_catch_error
-ld.so: _dl_signal_exception
-ld.so: _dl_catch_exception
@@ -9,8 +9,3 @@ libc.so: malloc + RELA R_X86_64_GLOB_DAT
libc.so: memalign + RELA R_X86_64_GLOB_DAT
libc.so: realloc + RELA R_X86_64_GLOB_DAT
libm.so: matherr + 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
-ld.so: _dl_signal_exception + RELA R_X86_64_GLOB_DAT
-ld.so: _dl_catch_exception + RELA R_X86_64_GLOB_DAT