mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 12:30:06 +00:00
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.
This commit is contained in:
parent
705a79f825
commit
9e78f6f6e7
78
ChangeLog
78
ChangeLog
@ -1,3 +1,81 @@
|
||||
2016-11-30 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
[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 <fweimer@redhat.com>
|
||||
|
||||
[BZ #4099]
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
21
elf/Makefile
21
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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
|
23
elf/dl-error-minimal.c
Normal file
23
elf/dl-error-minimal.c
Normal file
@ -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
|
||||
<http://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"
|
230
elf/dl-error-skeleton.c
Normal file
230
elf/dl-error-skeleton.c
Normal file
@ -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
|
||||
<http://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>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* 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 */
|
210
elf/dl-error.c
210
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
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <libintl.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
/* 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"
|
||||
|
@ -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)
|
||||
|
@ -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"));
|
||||
}
|
||||
|
||||
|
53
elf/dl-tsd.c
53
elf/dl-tsd.c
@ -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
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef _LIBC_REENTRANT
|
||||
|
||||
# include <ldsodefs.h>
|
||||
# include <tls.h>
|
||||
|
||||
# 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 */
|
19
elf/rtld.c
19
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 \
|
||||
|
105
elf/tst-latepthread.c
Normal file
105
elf/tst-latepthread.c
Normal file
@ -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
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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"
|
33
elf/tst-latepthreadmod.c
Normal file
33
elf/tst-latepthreadmod.c
Normal file
@ -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
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This file is compiled into a DSO which loads libpthread, but fails
|
||||
the dynamic linker afterwards. */
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* 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 ();
|
||||
}
|
@ -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;
|
||||
|
@ -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 <stdio.h>. */
|
||||
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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user