mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-30 22:43:12 +03: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:
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>
|
2016-11-30 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
[BZ #4099]
|
[BZ #4099]
|
||||||
|
@ -160,8 +160,8 @@ _dlerror_run (void (*operate) (void *), void *args)
|
|||||||
result->errstring = NULL;
|
result->errstring = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
result->errcode = GLRO(dl_catch_error) (&result->objname, &result->errstring,
|
result->errcode = _dl_catch_error (&result->objname, &result->errstring,
|
||||||
&result->malloced, operate, args);
|
&result->malloced, operate, args);
|
||||||
|
|
||||||
/* If no error we mark that no error string is available. */
|
/* If no error we mark that no error string is available. */
|
||||||
result->returned = result->errstring == NULL;
|
result->returned = result->errstring == NULL;
|
||||||
|
@ -60,7 +60,7 @@ dlinfo_doit (void *argsblock)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (l == NULL)
|
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"));
|
RTLD_SELF used in code not dynamically loaded"));
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
@ -69,7 +69,7 @@ RTLD_SELF used in code not dynamically loaded"));
|
|||||||
{
|
{
|
||||||
case RTLD_DI_CONFIGADDR:
|
case RTLD_DI_CONFIGADDR:
|
||||||
default:
|
default:
|
||||||
GLRO(dl_signal_error) (0, NULL, NULL, N_("unsupported dlinfo request"));
|
_dl_signal_error (0, NULL, NULL, N_("unsupported dlinfo request"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTLD_DI_LMID:
|
case RTLD_DI_LMID:
|
||||||
|
@ -60,12 +60,12 @@ dlmopen_doit (void *a)
|
|||||||
must be the main one. */
|
must be the main one. */
|
||||||
if (args->file == NULL)
|
if (args->file == NULL)
|
||||||
# endif
|
# 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
|
/* It makes no sense to use RTLD_GLOBAL when loading a DSO into
|
||||||
a namespace other than the base namespace. */
|
a namespace other than the base namespace. */
|
||||||
if (__glibc_unlikely (args->mode & RTLD_GLOBAL))
|
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,
|
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
|
if (args->mode & ~(RTLD_BINDING_MASK | RTLD_NOLOAD | RTLD_DEEPBIND
|
||||||
| RTLD_GLOBAL | RTLD_LOCAL | RTLD_NODELETE
|
| RTLD_GLOBAL | RTLD_LOCAL | RTLD_NODELETE
|
||||||
| __RTLD_SPROF))
|
| __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->new = GLRO(dl_open) (args->file ?: "", args->mode | __RTLD_DLOPEN,
|
||||||
args->caller,
|
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
|
headers = elf.h bits/elfclass.h link.h bits/link.h
|
||||||
routines = $(all-dl-routines) dl-support dl-iteratephdr \
|
routines = $(all-dl-routines) dl-support dl-iteratephdr \
|
||||||
dl-addr dl-addr-obj enbl-secure dl-profstub \
|
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
|
# The core dynamic linking functions are in libc for the static and
|
||||||
# profiled libraries.
|
# profiled libraries.
|
||||||
dl-routines = $(addprefix dl-,load lookup object reloc deps hwcaps \
|
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 \
|
version profile conflict tls origin scope \
|
||||||
execstack caller open close trampoline)
|
execstack caller open close trampoline)
|
||||||
ifeq (yes,$(use-ldconfig))
|
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
|
# ld.so uses those routines, plus some special stuff for being the program
|
||||||
# interpreter and operating independent of libc.
|
# 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)
|
all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines)
|
||||||
|
|
||||||
CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
|
CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
|
||||||
@ -150,7 +151,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
|||||||
tst-nodelete) \
|
tst-nodelete) \
|
||||||
tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
|
tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
|
||||||
tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
|
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
|
# reldep9
|
||||||
ifeq ($(build-hardcoded-path-in-tests),yes)
|
ifeq ($(build-hardcoded-path-in-tests),yes)
|
||||||
tests += tst-dlopen-aout
|
tests += tst-dlopen-aout
|
||||||
@ -224,7 +226,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
|||||||
tst-array5dep tst-null-argv-lib \
|
tst-array5dep tst-null-argv-lib \
|
||||||
tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \
|
tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \
|
||||||
tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \
|
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))
|
ifeq (yes,$(have-mtls-dialect-gnu2))
|
||||||
tests += tst-gnu2-tls1
|
tests += tst-gnu2-tls1
|
||||||
modules-names += tst-gnu2-tls1mod
|
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
|
$(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so
|
||||||
LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map
|
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
|
tst-prelink-ENV = LD_TRACE_PRELINKING=1
|
||||||
|
|
||||||
$(objpfx)tst-prelink-conflict.out: $(objpfx)tst-prelink.out
|
$(objpfx)tst-prelink-conflict.out: $(objpfx)tst-prelink.out
|
||||||
|
@ -26,6 +26,9 @@ libc {
|
|||||||
_dl_open_hook;
|
_dl_open_hook;
|
||||||
_dl_sym; _dl_vsym;
|
_dl_sym; _dl_vsym;
|
||||||
__libc_dlclose; __libc_dlopen_mode; __libc_dlsym;
|
__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 protection.
|
||||||
__pointer_chk_guard;
|
__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)
|
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. */
|
/* Acquire the lock. */
|
||||||
__rtld_lock_lock_recursive (GL(dl_load_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.
|
Copyright (C) 1995-2016 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
@ -16,206 +16,12 @@
|
|||||||
License along with the GNU C Library; if not, see
|
License along with the GNU C Library; if not, see
|
||||||
<http://www.gnu.org/licenses/>. */
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#include <libintl.h>
|
/* This implementation lives in libc.so because it uses thread-local
|
||||||
#include <setjmp.h>
|
data, which is not available in ld.so. It interposes the version
|
||||||
#include <stdbool.h>
|
in dl-error-minimal.c after ld.so bootstrap.
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <ldsodefs.h>
|
|
||||||
|
|
||||||
/* This structure communicates state between _dl_catch_error and
|
The signal/catch mechanism is used by the audit framework, which
|
||||||
_dl_signal_error. */
|
means that even in ld.so, not all errors are fatal. */
|
||||||
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
|
#define DL_ERROR_BOOTSTRAP 0
|
||||||
calls can come from `_dl_map_object_deps', `_dlerror_run', or from
|
#include "dl-error-skeleton.c"
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
@ -43,8 +43,8 @@ dlerror_run (void (*operate) (void *), void *args)
|
|||||||
const char *last_errstring = NULL;
|
const char *last_errstring = NULL;
|
||||||
bool malloced;
|
bool malloced;
|
||||||
|
|
||||||
int result = (GLRO(dl_catch_error) (&objname, &last_errstring, &malloced,
|
int result = (_dl_catch_error (&objname, &last_errstring, &malloced,
|
||||||
operate, args)
|
operate, args)
|
||||||
?: last_errstring != NULL);
|
?: last_errstring != NULL);
|
||||||
|
|
||||||
if (result && malloced)
|
if (result && malloced)
|
||||||
|
@ -123,8 +123,8 @@ do_sym (void *handle, const char *name, void *who,
|
|||||||
const char *objname;
|
const char *objname;
|
||||||
const char *errstring = NULL;
|
const char *errstring = NULL;
|
||||||
bool malloced;
|
bool malloced;
|
||||||
int err = GLRO(dl_catch_error) (&objname, &errstring, &malloced,
|
int err = _dl_catch_error (&objname, &errstring, &malloced,
|
||||||
call_dl_lookup, &args);
|
call_dl_lookup, &args);
|
||||||
|
|
||||||
THREAD_GSCOPE_RESET_FLAG ();
|
THREAD_GSCOPE_RESET_FLAG ();
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ do_sym (void *handle, const char *name, void *who,
|
|||||||
if (malloced)
|
if (malloced)
|
||||||
free ((char *) errstring);
|
free ((char *) errstring);
|
||||||
|
|
||||||
GLRO(dl_signal_error) (err, objname_dup, NULL, errstring_dup);
|
_dl_signal_error (err, objname_dup, NULL, errstring_dup);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ do_sym (void *handle, const char *name, void *who,
|
|||||||
if (match == NULL
|
if (match == NULL
|
||||||
|| caller < match->l_map_start
|
|| caller < match->l_map_start
|
||||||
|| caller >= match->l_map_end)
|
|| 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"));
|
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. */
|
/* Function pointers. */
|
||||||
._dl_debug_printf = _dl_debug_printf,
|
._dl_debug_printf = _dl_debug_printf,
|
||||||
._dl_catch_error = _dl_catch_error,
|
|
||||||
._dl_signal_error = _dl_signal_error,
|
|
||||||
._dl_mcount = _dl_mcount,
|
._dl_mcount = _dl_mcount,
|
||||||
._dl_lookup_symbol_x = _dl_lookup_symbol_x,
|
._dl_lookup_symbol_x = _dl_lookup_symbol_x,
|
||||||
._dl_check_caller = _dl_check_caller,
|
._dl_check_caller = _dl_check_caller,
|
||||||
@ -637,18 +635,6 @@ cannot allocate TLS data structures for initial thread");
|
|||||||
return tcbp;
|
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
|
static unsigned int
|
||||||
do_preload (const char *fname, struct link_map *main_map, const char *where)
|
do_preload (const char *fname, struct link_map *main_map, const char *where)
|
||||||
{
|
{
|
||||||
@ -752,11 +738,6 @@ dl_main (const ElfW(Phdr) *phdr,
|
|||||||
#endif
|
#endif
|
||||||
void *tcbp = NULL;
|
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;
|
GL(dl_init_static_tls) = &_dl_nothread_init_static_tls;
|
||||||
|
|
||||||
#if defined SHARED && defined _LIBC_REENTRANT \
|
#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);
|
lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);
|
||||||
|
|
||||||
#ifdef SHARED
|
#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,
|
/* Make __rtld_lock_{,un}lock_recursive use pthread_mutex_{,un}lock,
|
||||||
keep the lock count from the ld.so implementation. */
|
keep the lock count from the ld.so implementation. */
|
||||||
GL(dl_rtld_lock_recursive) = (void *) __pthread_mutex_lock;
|
GL(dl_rtld_lock_recursive) = (void *) __pthread_mutex_lock;
|
||||||
|
@ -357,10 +357,6 @@ struct rtld_global
|
|||||||
/* List of search directories. */
|
/* List of search directories. */
|
||||||
EXTERN struct r_search_path_elem *_dl_all_dirs;
|
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
|
/* Structure describing the dynamic linker itself. We need to
|
||||||
reserve memory for the data the audit libraries need. */
|
reserve memory for the data the audit libraries need. */
|
||||||
EXTERN struct link_map _dl_rtld_map;
|
EXTERN struct link_map _dl_rtld_map;
|
||||||
@ -583,10 +579,6 @@ struct rtld_global_ro
|
|||||||
PLT relocations in libc.so. */
|
PLT relocations in libc.so. */
|
||||||
void (*_dl_debug_printf) (const char *, ...)
|
void (*_dl_debug_printf) (const char *, ...)
|
||||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
__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);
|
void (*_dl_mcount) (ElfW(Addr) frompc, ElfW(Addr) selfpc);
|
||||||
lookup_t (internal_function *_dl_lookup_symbol_x) (const char *,
|
lookup_t (internal_function *_dl_lookup_symbol_x) (const char *,
|
||||||
struct link_map *,
|
struct link_map *,
|
||||||
@ -632,13 +624,6 @@ extern const ElfW(Phdr) *_dl_phdr;
|
|||||||
extern size_t _dl_phnum;
|
extern size_t _dl_phnum;
|
||||||
#endif
|
#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).
|
/* This is the initial value of GL(dl_make_stack_executable_hook).
|
||||||
A threads library can change it. */
|
A threads library can change it. */
|
||||||
extern int _dl_make_stack_executable (void **stack_endp) internal_function;
|
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
|
/* Write a message on the specified descriptor FD. The parameters are
|
||||||
interpreted as for a `printf' call. */
|
interpreted as for a `printf' call. */
|
||||||
|
#if IS_IN (rtld) || !defined (SHARED)
|
||||||
extern void _dl_dprintf (int fd, const char *fmt, ...)
|
extern void _dl_dprintf (int fd, const char *fmt, ...)
|
||||||
__attribute__ ((__format__ (__printf__, 2, 3)))
|
__attribute__ ((__format__ (__printf__, 2, 3)))
|
||||||
attribute_hidden;
|
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
|
/* Write a message on the specified descriptor standard output. The
|
||||||
parameters are interpreted as for a `printf' call. */
|
parameters are interpreted as for a `printf' call. */
|
||||||
@ -737,13 +733,26 @@ extern void _dl_dprintf (int fd, const char *fmt, ...)
|
|||||||
problem. */
|
problem. */
|
||||||
extern void _dl_signal_error (int errcode, const char *object,
|
extern void _dl_signal_error (int errcode, const char *object,
|
||||||
const char *occurred, const char *errstring)
|
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
|
/* 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,
|
extern void _dl_signal_cerror (int errcode, const char *object,
|
||||||
const char *occation, const char *errstring)
|
const char *occation, const char *errstring)
|
||||||
internal_function attribute_hidden;
|
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
|
/* Call OPERATE, receiving errors from `dl_signal_cerror'. Unlike
|
||||||
`_dl_catch_error' the operation is resumed after the OPERATE
|
`_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,
|
extern int _dl_catch_error (const char **objname, const char **errstring,
|
||||||
bool *mallocedp, void (*operate) (void *),
|
bool *mallocedp, void (*operate) (void *),
|
||||||
void *args)
|
void *args)
|
||||||
internal_function attribute_hidden;
|
internal_function;
|
||||||
|
libc_hidden_proto (_dl_catch_error)
|
||||||
|
|
||||||
/* Open the shared object NAME and map in its segments.
|
/* Open the shared object NAME and map in its segments.
|
||||||
LOADER's DT_RPATH is used in searching for NAME.
|
LOADER's DT_RPATH is used in searching for NAME.
|
||||||
|
@ -15,3 +15,6 @@ ld.so: malloc
|
|||||||
ld.so: calloc
|
ld.so: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc + RELA R_ALPHA_GLOB_DAT
|
||||||
ld.so: realloc + RELA R_ALPHA_GLOB_DAT
|
ld.so: realloc + RELA R_ALPHA_GLOB_DAT
|
||||||
ld.so: free + 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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc + REL R_386_GLOB_DAT
|
||||||
ld.so: realloc + REL R_386_GLOB_DAT
|
ld.so: realloc + REL R_386_GLOB_DAT
|
||||||
ld.so: free + 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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc
|
||||||
ld.so: realloc
|
ld.so: realloc
|
||||||
ld.so: free
|
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: calloc + RELA R_X86_64_GLOB_DAT
|
||||||
ld.so: realloc + RELA R_X86_64_GLOB_DAT
|
ld.so: realloc + RELA R_X86_64_GLOB_DAT
|
||||||
ld.so: free + 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
|
||||||
|
Reference in New Issue
Block a user