mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +00:00
elf: Remove prelink support
Prelinked binaries and libraries still work, the dynamic tags DT_GNU_PRELINKED, DT_GNU_LIBLIST, DT_GNU_CONFLICT just ignored (meaning the process is reallocated as default). The loader environment variable TRACE_PRELINKING is also removed, since it used solely on prelink. Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
This commit is contained in:
parent
8c8510ab27
commit
6628c742b2
4
NEWS
4
NEWS
@ -13,7 +13,9 @@ Major new features:
|
||||
|
||||
Deprecated and removed features, and other changes affecting compatibility:
|
||||
|
||||
[Add deprecations, removals and changes affecting compatibility here]
|
||||
* Support for prelink will be removed in the next release; this includes
|
||||
removal of the LD_TRACE_PRELINKING, and LD_USE_LOAD_BIAS, environment
|
||||
variables and their functionality in the dynamic loader.
|
||||
|
||||
Changes to build and runtime requirements:
|
||||
|
||||
|
16
elf/Makefile
16
elf/Makefile
@ -127,7 +127,6 @@ rtld-routines = \
|
||||
$(all-dl-routines) \
|
||||
dl-audit \
|
||||
dl-compat \
|
||||
dl-conflict \
|
||||
dl-diagnostics \
|
||||
dl-diagnostics-cpu \
|
||||
dl-diagnostics-kernel \
|
||||
@ -1103,14 +1102,6 @@ tests-special += $(objpfx)check-abi-ld.out
|
||||
update-abi: update-abi-ld
|
||||
update-all-abi: update-all-abi-ld
|
||||
|
||||
ifeq ($(have-glob-dat-reloc),yes)
|
||||
tests += tst-prelink
|
||||
tests-internal += tst-prelink-cmp
|
||||
# Don't compile tst-prelink.c with PIE for GLOB_DAT relocation.
|
||||
CFLAGS-tst-prelink.c += -fno-pie
|
||||
tst-prelink-no-pie = yes
|
||||
endif
|
||||
|
||||
# The test requires shared _and_ PIE because the executable
|
||||
# unit test driver must be able to link with the shared object
|
||||
# that is going to eventually go into an installed DSO.
|
||||
@ -2285,13 +2276,6 @@ $(objpfx)tst-tls-manydynamic: $(shared-thread-library)
|
||||
$(objpfx)tst-tls-manydynamic.out: \
|
||||
$(patsubst %,$(objpfx)%.so,$(tst-tls-many-dynamic-modules))
|
||||
|
||||
tst-prelink-ENV = LD_TRACE_PRELINKING=1
|
||||
|
||||
$(objpfx)tst-prelink-conflict.out: $(objpfx)tst-prelink.out
|
||||
grep stdout $< | grep conflict | $(AWK) '{ print $$10, $$11 }' > $@
|
||||
|
||||
$(objpfx)tst-prelink-cmp.out: $(objpfx)tst-prelink-conflict.out
|
||||
|
||||
$(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
|
||||
$(SHELL) $< '$(common-objpfx)' '$(test-wrapper-env)' \
|
||||
'$(run-program-env)' > $@; \
|
||||
|
@ -1,77 +0,0 @@
|
||||
/* Resolve conflicts against already prelinked libraries.
|
||||
Copyright (C) 2001-2022 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; see the file COPYING.LIB. If
|
||||
not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <libintl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include "dynamic-link.h"
|
||||
|
||||
/* Used at loading time solely for prelink executable. It is not called
|
||||
concurrently so it is be safe to defined as static. */
|
||||
static struct link_map *resolve_conflict_map __attribute__ ((__unused__));
|
||||
|
||||
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||
#define RESOLVE_MAP(map, scope, ref, version, flags) (*ref = NULL, NULL)
|
||||
#define RESOLVE(ref, version, flags) (*ref = NULL, 0)
|
||||
#define RESOLVE_CONFLICT_FIND_MAP(map, r_offset) \
|
||||
do { \
|
||||
while ((resolve_conflict_map->l_map_end < (ElfW(Addr)) (r_offset)) \
|
||||
|| (resolve_conflict_map->l_map_start > (ElfW(Addr)) (r_offset))) \
|
||||
resolve_conflict_map = resolve_conflict_map->l_next; \
|
||||
\
|
||||
(map) = resolve_conflict_map; \
|
||||
} while (0)
|
||||
|
||||
#include "dynamic-link.h"
|
||||
|
||||
void
|
||||
_dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
|
||||
ElfW(Rela) *conflictend)
|
||||
{
|
||||
#if ! ELF_MACHINE_NO_RELA
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
|
||||
_dl_debug_printf ("\nconflict processing: %s\n", DSO_FILENAME (l->l_name));
|
||||
|
||||
{
|
||||
/* Do the conflict relocation of the object and library GOT and other
|
||||
data. */
|
||||
|
||||
/* Prelinking makes no sense for anything but the main namespace. */
|
||||
assert (l->l_ns == LM_ID_BASE);
|
||||
resolve_conflict_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
|
||||
/* Override these, defined in dynamic-link.h. */
|
||||
#undef CHECK_STATIC_TLS
|
||||
#define CHECK_STATIC_TLS(ref_map, sym_map) ((void) 0)
|
||||
#undef TRY_STATIC_TLS
|
||||
#define TRY_STATIC_TLS(ref_map, sym_map) (0)
|
||||
|
||||
GL(dl_num_cache_relocations) += conflictend - conflict;
|
||||
|
||||
for (; conflict < conflictend; ++conflict)
|
||||
elf_machine_rela (l, NULL, conflict, NULL, NULL,
|
||||
(void *) conflict->r_offset, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
@ -68,22 +68,6 @@ openaux (void *a)
|
||||
args->map->l_ns);
|
||||
}
|
||||
|
||||
static ptrdiff_t
|
||||
_dl_build_local_scope (struct link_map **list, struct link_map *map)
|
||||
{
|
||||
struct link_map **p = list;
|
||||
struct link_map **q;
|
||||
|
||||
*p++ = map;
|
||||
map->l_reserved = 1;
|
||||
if (map->l_initfini)
|
||||
for (q = map->l_initfini + 1; *q; ++q)
|
||||
if (! (*q)->l_reserved)
|
||||
p += _dl_build_local_scope (p, *q);
|
||||
return p - list;
|
||||
}
|
||||
|
||||
|
||||
/* We use a very special kind of list to track the path
|
||||
through the list of loaded shared objects. We have to
|
||||
produce a flat list with unique members of all involved objects.
|
||||
@ -504,56 +488,6 @@ _dl_map_object_deps (struct link_map *map,
|
||||
runp->map->l_reserved = 0;
|
||||
}
|
||||
|
||||
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK, 0) != 0
|
||||
&& map == GL(dl_ns)[LM_ID_BASE]._ns_loaded)
|
||||
{
|
||||
/* If we are to compute conflicts, we have to build local scope
|
||||
for each library, not just the ultimate loader. */
|
||||
for (i = 0; i < nlist; ++i)
|
||||
{
|
||||
struct link_map *l = map->l_searchlist.r_list[i];
|
||||
unsigned int j, cnt;
|
||||
|
||||
/* The local scope has been already computed. */
|
||||
if (l == map
|
||||
|| (l->l_local_scope[0]
|
||||
&& l->l_local_scope[0]->r_nlist) != 0)
|
||||
continue;
|
||||
|
||||
if (l->l_info[AUXTAG] || l->l_info[FILTERTAG])
|
||||
{
|
||||
/* As current DT_AUXILIARY/DT_FILTER implementation needs to be
|
||||
rewritten, no need to bother with prelinking the old
|
||||
implementation. */
|
||||
_dl_signal_error (EINVAL, l->l_name, NULL, N_("\
|
||||
Filters not supported with LD_TRACE_PRELINKING"));
|
||||
}
|
||||
|
||||
cnt = _dl_build_local_scope (l_initfini, l);
|
||||
assert (cnt <= nlist);
|
||||
for (j = 0; j < cnt; j++)
|
||||
{
|
||||
l_initfini[j]->l_reserved = 0;
|
||||
if (j && __builtin_expect (l_initfini[j]->l_info[DT_SYMBOLIC]
|
||||
!= NULL, 0))
|
||||
l->l_symbolic_in_local_scope = true;
|
||||
}
|
||||
|
||||
l->l_local_scope[0] =
|
||||
(struct r_scope_elem *) malloc (sizeof (struct r_scope_elem)
|
||||
+ (cnt
|
||||
* sizeof (struct link_map *)));
|
||||
if (l->l_local_scope[0] == NULL)
|
||||
_dl_signal_error (ENOMEM, map->l_name, NULL,
|
||||
N_("cannot allocate symbol search list"));
|
||||
l->l_local_scope[0]->r_nlist = cnt;
|
||||
l->l_local_scope[0]->r_list =
|
||||
(struct link_map **) (l->l_local_scope[0] + 1);
|
||||
memcpy (l->l_local_scope[0]->r_list, l_initfini,
|
||||
cnt * sizeof (struct link_map *));
|
||||
}
|
||||
}
|
||||
|
||||
/* Maybe we can remove some relocation dependencies now. */
|
||||
struct link_map_reldeps *l_reldeps = NULL;
|
||||
if (map->l_reldeps != NULL)
|
||||
|
@ -132,7 +132,7 @@ _dl_signal_cexception (int errcode, struct dl_exception *exception,
|
||||
const char *occasion)
|
||||
{
|
||||
if (__builtin_expect (GLRO(dl_debug_mask)
|
||||
& ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0))
|
||||
& ~(DL_DEBUG_STATISTICS), 0))
|
||||
_dl_debug_printf ("%s: error: %s: %s (%s)\n",
|
||||
exception->objname, occasion,
|
||||
exception->errstring, receiver ? "continued" : "fatal");
|
||||
@ -153,7 +153,7 @@ _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_STATISTICS), 0))
|
||||
_dl_debug_printf ("%s: error: %s: %s (%s)\n", objname, occation,
|
||||
errstring, receiver ? "continued" : "fatal");
|
||||
|
||||
|
@ -2263,8 +2263,7 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||
|
||||
if (__glibc_unlikely (fd == -1))
|
||||
{
|
||||
if (trace_mode
|
||||
&& __glibc_likely ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) == 0))
|
||||
if (trace_mode)
|
||||
{
|
||||
/* We haven't found an appropriate library. But since we
|
||||
are only interested in the list of libraries this isn't
|
||||
|
161
elf/dl-lookup.c
161
elf/dl-lookup.c
@ -296,19 +296,6 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash,
|
||||
assert (!RTLD_CHECK_FOREIGN_CALL);
|
||||
#endif
|
||||
|
||||
#ifdef SHARED
|
||||
/* If tab->entries is NULL, but tab->size is not, it means
|
||||
this is the second, conflict finding, lookup for
|
||||
LD_TRACE_PRELINKING in _dl_debug_bindings. Don't
|
||||
allocate anything and don't enter anything into the
|
||||
hash table. */
|
||||
if (__glibc_unlikely (tab->size))
|
||||
{
|
||||
assert (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK);
|
||||
goto success;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define INITIAL_NUNIQUE_SYM_TABLE 31
|
||||
size = INITIAL_NUNIQUE_SYM_TABLE;
|
||||
entries = calloc (sizeof (struct unique_sym), size);
|
||||
@ -341,9 +328,6 @@ marking %s [%lu] as NODELETE due to unique symbol\n",
|
||||
}
|
||||
++tab->n_elements;
|
||||
|
||||
#ifdef SHARED
|
||||
success:
|
||||
#endif
|
||||
__rtld_lock_unlock_recursive (tab->lock);
|
||||
|
||||
result->s = sym;
|
||||
@ -818,12 +802,6 @@ marking %s [%lu] as NODELETE due to memory allocation failure\n",
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void
|
||||
_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
|
||||
const ElfW(Sym) **ref, struct sym_val *value,
|
||||
const struct r_found_version *version, int type_class,
|
||||
int protected);
|
||||
|
||||
|
||||
/* Search loaded objects' symbol tables for a definition of the symbol
|
||||
UNDEF_NAME, perhaps with a requested version for the symbol.
|
||||
@ -943,145 +921,6 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
|
||||
if (__glibc_unlikely (current_value.m->l_used == 0))
|
||||
current_value.m->l_used = 1;
|
||||
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask)
|
||||
& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK)))
|
||||
_dl_debug_bindings (undef_name, undef_map, ref,
|
||||
¤t_value, version, type_class, protected);
|
||||
|
||||
*ref = current_value.s;
|
||||
return LOOKUP_VALUE (current_value.m);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
|
||||
const ElfW(Sym) **ref, struct sym_val *value,
|
||||
const struct r_found_version *version, int type_class,
|
||||
int protected)
|
||||
{
|
||||
const char *reference_name = undef_map->l_name;
|
||||
|
||||
if (GLRO(dl_debug_mask) & DL_DEBUG_BINDINGS)
|
||||
{
|
||||
_dl_debug_printf ("binding file %s [%lu] to %s [%lu]: %s symbol `%s'",
|
||||
DSO_FILENAME (reference_name),
|
||||
undef_map->l_ns,
|
||||
DSO_FILENAME (value->m->l_name),
|
||||
value->m->l_ns,
|
||||
protected ? "protected" : "normal", undef_name);
|
||||
if (version)
|
||||
_dl_debug_printf_c (" [%s]\n", version->name);
|
||||
else
|
||||
_dl_debug_printf_c ("\n");
|
||||
}
|
||||
#ifdef SHARED
|
||||
if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
|
||||
{
|
||||
/* ELF_RTYPE_CLASS_XXX must match RTYPE_CLASS_XXX used by prelink with
|
||||
LD_TRACE_PRELINKING. */
|
||||
#define RTYPE_CLASS_VALID 8
|
||||
#define RTYPE_CLASS_PLT (8|1)
|
||||
#define RTYPE_CLASS_COPY (8|2)
|
||||
#define RTYPE_CLASS_TLS (8|4)
|
||||
#if ELF_RTYPE_CLASS_PLT != 0 && ELF_RTYPE_CLASS_PLT != 1
|
||||
# error ELF_RTYPE_CLASS_PLT must be 0 or 1!
|
||||
#endif
|
||||
#if ELF_RTYPE_CLASS_COPY != 0 && ELF_RTYPE_CLASS_COPY != 2
|
||||
# error ELF_RTYPE_CLASS_COPY must be 0 or 2!
|
||||
#endif
|
||||
int conflict = 0;
|
||||
struct sym_val val = { NULL, NULL };
|
||||
|
||||
if ((GLRO(dl_trace_prelink_map) == NULL
|
||||
|| GLRO(dl_trace_prelink_map) == GL(dl_ns)[LM_ID_BASE]._ns_loaded)
|
||||
&& undef_map != GL(dl_ns)[LM_ID_BASE]._ns_loaded)
|
||||
{
|
||||
const uint_fast32_t new_hash = dl_new_hash (undef_name);
|
||||
unsigned long int old_hash = 0xffffffff;
|
||||
struct unique_sym *saved_entries
|
||||
= GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries;
|
||||
|
||||
GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = NULL;
|
||||
do_lookup_x (undef_name, new_hash, &old_hash, *ref, &val,
|
||||
undef_map->l_local_scope[0], 0, version, 0, NULL,
|
||||
type_class, undef_map);
|
||||
if (val.s != value->s || val.m != value->m)
|
||||
conflict = 1;
|
||||
else if (__glibc_unlikely (undef_map->l_symbolic_in_local_scope)
|
||||
&& val.s
|
||||
&& __glibc_unlikely (ELFW(ST_BIND) (val.s->st_info)
|
||||
== STB_GNU_UNIQUE))
|
||||
{
|
||||
/* If it is STB_GNU_UNIQUE and undef_map's l_local_scope
|
||||
contains any DT_SYMBOLIC libraries, unfortunately there
|
||||
can be conflicts even if the above is equal. As symbol
|
||||
resolution goes from the last library to the first and
|
||||
if a STB_GNU_UNIQUE symbol is found in some late DT_SYMBOLIC
|
||||
library, it would be the one that is looked up. */
|
||||
struct sym_val val2 = { NULL, NULL };
|
||||
size_t n;
|
||||
struct r_scope_elem *scope = undef_map->l_local_scope[0];
|
||||
|
||||
for (n = 0; n < scope->r_nlist; n++)
|
||||
if (scope->r_list[n] == val.m)
|
||||
break;
|
||||
|
||||
for (n++; n < scope->r_nlist; n++)
|
||||
if (scope->r_list[n]->l_info[DT_SYMBOLIC] != NULL
|
||||
&& do_lookup_x (undef_name, new_hash, &old_hash, *ref,
|
||||
&val2,
|
||||
&scope->r_list[n]->l_symbolic_searchlist,
|
||||
0, version, 0, NULL, type_class,
|
||||
undef_map) > 0)
|
||||
{
|
||||
conflict = 1;
|
||||
val = val2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
GL(dl_ns)[LM_ID_BASE]._ns_unique_sym_table.entries = saved_entries;
|
||||
}
|
||||
|
||||
if (value->s)
|
||||
{
|
||||
/* Keep only ELF_RTYPE_CLASS_PLT and ELF_RTYPE_CLASS_COPY
|
||||
bits since since prelink only uses them. */
|
||||
type_class &= ELF_RTYPE_CLASS_PLT | ELF_RTYPE_CLASS_COPY;
|
||||
if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
|
||||
== STT_TLS))
|
||||
/* Clear the RTYPE_CLASS_VALID bit in RTYPE_CLASS_TLS. */
|
||||
type_class = RTYPE_CLASS_TLS & ~RTYPE_CLASS_VALID;
|
||||
else if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
|
||||
== STT_GNU_IFUNC))
|
||||
/* Set the RTYPE_CLASS_VALID bit. */
|
||||
type_class |= RTYPE_CLASS_VALID;
|
||||
}
|
||||
|
||||
if (conflict
|
||||
|| GLRO(dl_trace_prelink_map) == undef_map
|
||||
|| GLRO(dl_trace_prelink_map) == NULL
|
||||
|| type_class >= 4)
|
||||
{
|
||||
_dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
|
||||
conflict ? "conflict" : "lookup",
|
||||
(int) sizeof (ElfW(Addr)) * 2,
|
||||
(size_t) undef_map->l_map_start,
|
||||
(int) sizeof (ElfW(Addr)) * 2,
|
||||
(size_t) (((ElfW(Addr)) *ref) - undef_map->l_map_start),
|
||||
(int) sizeof (ElfW(Addr)) * 2,
|
||||
(size_t) (value->s ? value->m->l_map_start : 0),
|
||||
(int) sizeof (ElfW(Addr)) * 2,
|
||||
(size_t) (value->s ? value->s->st_value : 0));
|
||||
|
||||
if (conflict)
|
||||
_dl_printf ("x 0x%0*Zx 0x%0*Zx ",
|
||||
(int) sizeof (ElfW(Addr)) * 2,
|
||||
(size_t) (val.s ? val.m->l_map_start : 0),
|
||||
(int) sizeof (ElfW(Addr)) * 2,
|
||||
(size_t) (val.s ? val.s->st_value : 0));
|
||||
|
||||
_dl_printf ("/%x %s\n", type_class, undef_name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -105,9 +105,6 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
|
||||
relocations or rela relocations if they are computed as
|
||||
memory_loc += l_addr... */
|
||||
if (l_addr != 0)
|
||||
# else
|
||||
/* ...or we know the object has been prelinked. */
|
||||
if (l_addr != 0 || ! map->l_info[VALIDX(DT_GNU_PRELINKED)])
|
||||
# endif
|
||||
#endif
|
||||
for (; relative < r; ++relative)
|
||||
|
250
elf/rtld.c
250
elf/rtld.c
@ -565,7 +565,7 @@ _dl_start (void *arg)
|
||||
ELF_MACHINE_BEFORE_RTLD_RELOC (&bootstrap_map, bootstrap_map.l_info);
|
||||
#endif
|
||||
|
||||
if (bootstrap_map.l_addr || ! bootstrap_map.l_info[VALIDX(DT_GNU_PRELINKED)])
|
||||
if (bootstrap_map.l_addr)
|
||||
{
|
||||
/* Relocate ourselves so we can do normal function calls and
|
||||
data access using the global offset table. */
|
||||
@ -1322,7 +1322,6 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
size_t file_size;
|
||||
char *file;
|
||||
unsigned int i;
|
||||
bool prelinked = false;
|
||||
bool rtld_is_main = false;
|
||||
void *tcbp = NULL;
|
||||
|
||||
@ -2055,37 +2054,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
after relocation. */
|
||||
struct link_map *l;
|
||||
|
||||
if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
|
||||
{
|
||||
struct r_scope_elem *scope = &main_map->l_searchlist;
|
||||
|
||||
for (i = 0; i < scope->r_nlist; i++)
|
||||
{
|
||||
l = scope->r_list [i];
|
||||
if (l->l_faked)
|
||||
{
|
||||
_dl_printf ("\t%s => not found\n", l->l_libname->name);
|
||||
continue;
|
||||
}
|
||||
if (_dl_name_match_p (GLRO(dl_trace_prelink), l))
|
||||
GLRO(dl_trace_prelink_map) = l;
|
||||
_dl_printf ("\t%s => %s (0x%0*Zx, 0x%0*Zx)",
|
||||
DSO_FILENAME (l->l_libname->name),
|
||||
DSO_FILENAME (l->l_name),
|
||||
(int) sizeof l->l_map_start * 2,
|
||||
(size_t) l->l_map_start,
|
||||
(int) sizeof l->l_addr * 2,
|
||||
(size_t) l->l_addr);
|
||||
|
||||
if (l->l_tls_modid)
|
||||
_dl_printf (" TLS(0x%Zx, 0x%0*Zx)\n", l->l_tls_modid,
|
||||
(int) sizeof l->l_tls_offset * 2,
|
||||
(size_t) l->l_tls_offset);
|
||||
else
|
||||
_dl_printf ("\n");
|
||||
}
|
||||
}
|
||||
else if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)
|
||||
if (GLRO(dl_debug_mask) & DL_DEBUG_UNUSED)
|
||||
{
|
||||
/* Look through the dependencies of the main executable
|
||||
and determine which of them is not actually
|
||||
@ -2193,14 +2162,6 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
}
|
||||
}
|
||||
|
||||
if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
|
||||
&& rtld_multiple_ref)
|
||||
{
|
||||
/* Mark the link map as not yet relocated again. */
|
||||
GL(dl_rtld_map).l_relocated = 0;
|
||||
_dl_relocate_object (&GL(dl_rtld_map),
|
||||
main_map->l_scope, __RTLD_NOIFUNC, 0);
|
||||
}
|
||||
}
|
||||
#define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED))
|
||||
if (state.version_info)
|
||||
@ -2277,61 +2238,6 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
_exit (0);
|
||||
}
|
||||
|
||||
if (main_map->l_info[ADDRIDX (DT_GNU_LIBLIST)]
|
||||
&& ! __builtin_expect (GLRO(dl_profile) != NULL, 0)
|
||||
&& ! __builtin_expect (GLRO(dl_dynamic_weak), 0))
|
||||
{
|
||||
ElfW(Lib) *liblist, *liblistend;
|
||||
struct link_map **r_list, **r_listend, *l;
|
||||
const char *strtab = (const void *) D_PTR (main_map, l_info[DT_STRTAB]);
|
||||
|
||||
assert (main_map->l_info[VALIDX (DT_GNU_LIBLISTSZ)] != NULL);
|
||||
liblist = (ElfW(Lib) *)
|
||||
main_map->l_info[ADDRIDX (DT_GNU_LIBLIST)]->d_un.d_ptr;
|
||||
liblistend = (ElfW(Lib) *)
|
||||
((char *) liblist
|
||||
+ main_map->l_info[VALIDX (DT_GNU_LIBLISTSZ)]->d_un.d_val);
|
||||
r_list = main_map->l_searchlist.r_list;
|
||||
r_listend = r_list + main_map->l_searchlist.r_nlist;
|
||||
|
||||
for (; r_list < r_listend && liblist < liblistend; r_list++)
|
||||
{
|
||||
l = *r_list;
|
||||
|
||||
if (l == main_map)
|
||||
continue;
|
||||
|
||||
/* If the library is not mapped where it should, fail. */
|
||||
if (l->l_addr)
|
||||
break;
|
||||
|
||||
/* Next, check if checksum matches. */
|
||||
if (l->l_info [VALIDX(DT_CHECKSUM)] == NULL
|
||||
|| l->l_info [VALIDX(DT_CHECKSUM)]->d_un.d_val
|
||||
!= liblist->l_checksum)
|
||||
break;
|
||||
|
||||
if (l->l_info [VALIDX(DT_GNU_PRELINKED)] == NULL
|
||||
|| l->l_info [VALIDX(DT_GNU_PRELINKED)]->d_un.d_val
|
||||
!= liblist->l_time_stamp)
|
||||
break;
|
||||
|
||||
if (! _dl_name_match_p (strtab + liblist->l_name, l))
|
||||
break;
|
||||
|
||||
++liblist;
|
||||
}
|
||||
|
||||
|
||||
if (r_list == r_listend && liblist == liblistend)
|
||||
prelinked = true;
|
||||
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
|
||||
_dl_debug_printf ("\nprelink checking: %s\n",
|
||||
prelinked ? "ok" : "failed");
|
||||
}
|
||||
|
||||
|
||||
/* Now set up the variable which helps the assembler startup code. */
|
||||
GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist = &main_map->l_searchlist;
|
||||
|
||||
@ -2356,103 +2262,59 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
|
||||
_rtld_main_check (main_map, _dl_argv[0]);
|
||||
|
||||
if (prelinked)
|
||||
{
|
||||
if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL)
|
||||
{
|
||||
ElfW(Rela) *conflict, *conflictend;
|
||||
/* Now we have all the objects loaded. Relocate them all except for
|
||||
the dynamic linker itself. We do this in reverse order so that copy
|
||||
relocs of earlier objects overwrite the data written by later
|
||||
objects. We do not re-relocate the dynamic linker itself in this
|
||||
loop because that could result in the GOT entries for functions we
|
||||
call being changed, and that would break us. It is safe to relocate
|
||||
the dynamic linker out of order because it has no copy relocs (we
|
||||
know that because it is self-contained). */
|
||||
|
||||
RTLD_TIMING_VAR (start);
|
||||
rtld_timer_start (&start);
|
||||
int consider_profiling = GLRO(dl_profile) != NULL;
|
||||
|
||||
assert (main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)] != NULL);
|
||||
conflict = (ElfW(Rela) *)
|
||||
main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)]->d_un.d_ptr;
|
||||
conflictend = (ElfW(Rela) *)
|
||||
((char *) conflict
|
||||
+ main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)]->d_un.d_val);
|
||||
_dl_resolve_conflicts (main_map, conflict, conflictend);
|
||||
/* If we are profiling we also must do lazy reloaction. */
|
||||
GLRO(dl_lazy) |= consider_profiling;
|
||||
|
||||
rtld_timer_stop (&relocate_time, start);
|
||||
}
|
||||
RTLD_TIMING_VAR (start);
|
||||
rtld_timer_start (&start);
|
||||
{
|
||||
unsigned i = main_map->l_searchlist.r_nlist;
|
||||
while (i-- > 0)
|
||||
{
|
||||
struct link_map *l = main_map->l_initfini[i];
|
||||
|
||||
/* Set up the object lookup structures. */
|
||||
_dl_find_object_init ();
|
||||
/* While we are at it, help the memory handling a bit. We have to
|
||||
mark some data structures as allocated with the fake malloc()
|
||||
implementation in ld.so. */
|
||||
struct libname_list *lnp = l->l_libname->next;
|
||||
|
||||
/* The library defining malloc has already been relocated due to
|
||||
prelinking. Resolve the malloc symbols for the dynamic
|
||||
loader. */
|
||||
__rtld_malloc_init_real (main_map);
|
||||
while (__builtin_expect (lnp != NULL, 0))
|
||||
{
|
||||
lnp->dont_free = 1;
|
||||
lnp = lnp->next;
|
||||
}
|
||||
/* Also allocated with the fake malloc(). */
|
||||
l->l_free_initfini = 0;
|
||||
|
||||
/* Likewise for the locking implementation. */
|
||||
__rtld_mutex_init ();
|
||||
if (l != &GL(dl_rtld_map))
|
||||
_dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0,
|
||||
consider_profiling);
|
||||
|
||||
/* Mark all the objects so we know they have been already relocated. */
|
||||
for (struct link_map *l = main_map; l != NULL; l = l->l_next)
|
||||
{
|
||||
l->l_relocated = 1;
|
||||
if (l->l_relro_size)
|
||||
_dl_protect_relro (l);
|
||||
/* Add object to slot information data if necessasy. */
|
||||
if (l->l_tls_blocksize != 0 && tls_init_tp_called)
|
||||
_dl_add_to_slotinfo (l, true);
|
||||
}
|
||||
}
|
||||
rtld_timer_stop (&relocate_time, start);
|
||||
|
||||
/* Add object to slot information data if necessasy. */
|
||||
if (l->l_tls_blocksize != 0 && tls_init_tp_called)
|
||||
_dl_add_to_slotinfo (l, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Now we have all the objects loaded. Relocate them all except for
|
||||
the dynamic linker itself. We do this in reverse order so that copy
|
||||
relocs of earlier objects overwrite the data written by later
|
||||
objects. We do not re-relocate the dynamic linker itself in this
|
||||
loop because that could result in the GOT entries for functions we
|
||||
call being changed, and that would break us. It is safe to relocate
|
||||
the dynamic linker out of order because it has no copy relocs (we
|
||||
know that because it is self-contained). */
|
||||
|
||||
int consider_profiling = GLRO(dl_profile) != NULL;
|
||||
|
||||
/* If we are profiling we also must do lazy reloaction. */
|
||||
GLRO(dl_lazy) |= consider_profiling;
|
||||
|
||||
RTLD_TIMING_VAR (start);
|
||||
rtld_timer_start (&start);
|
||||
unsigned i = main_map->l_searchlist.r_nlist;
|
||||
while (i-- > 0)
|
||||
{
|
||||
struct link_map *l = main_map->l_initfini[i];
|
||||
|
||||
/* While we are at it, help the memory handling a bit. We have to
|
||||
mark some data structures as allocated with the fake malloc()
|
||||
implementation in ld.so. */
|
||||
struct libname_list *lnp = l->l_libname->next;
|
||||
|
||||
while (__builtin_expect (lnp != NULL, 0))
|
||||
{
|
||||
lnp->dont_free = 1;
|
||||
lnp = lnp->next;
|
||||
}
|
||||
/* Also allocated with the fake malloc(). */
|
||||
l->l_free_initfini = 0;
|
||||
|
||||
if (l != &GL(dl_rtld_map))
|
||||
_dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0,
|
||||
consider_profiling);
|
||||
|
||||
/* Add object to slot information data if necessasy. */
|
||||
if (l->l_tls_blocksize != 0 && tls_init_tp_called)
|
||||
_dl_add_to_slotinfo (l, true);
|
||||
}
|
||||
rtld_timer_stop (&relocate_time, start);
|
||||
|
||||
/* Now enable profiling if needed. Like the previous call,
|
||||
this has to go here because the calls it makes should use the
|
||||
rtld versions of the functions (particularly calloc()), but it
|
||||
needs to have _dl_profile_map set up by the relocator. */
|
||||
if (__glibc_unlikely (GL(dl_profile_map) != NULL))
|
||||
/* We must prepare the profiling. */
|
||||
_dl_start_profile ();
|
||||
}
|
||||
/* Now enable profiling if needed. Like the previous call,
|
||||
this has to go here because the calls it makes should use the
|
||||
rtld versions of the functions (particularly calloc()), but it
|
||||
needs to have _dl_profile_map set up by the relocator. */
|
||||
if (__glibc_unlikely (GL(dl_profile_map) != NULL))
|
||||
/* We must prepare the profiling. */
|
||||
_dl_start_profile ();
|
||||
|
||||
if ((!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0)
|
||||
|| count_modids != _dl_count_modids ())
|
||||
@ -2478,7 +2340,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
/* Make sure no new search directories have been added. */
|
||||
assert (GLRO(dl_init_all_dirs) == GL(dl_all_dirs));
|
||||
|
||||
if (! prelinked && rtld_multiple_ref)
|
||||
if (rtld_multiple_ref)
|
||||
{
|
||||
/* There was an explicit ref to the dynamic linker as a shared lib.
|
||||
Re-relocate ourselves with user-controlled symbol definitions.
|
||||
@ -2811,17 +2673,6 @@ process_envvars (struct dl_main_state *state)
|
||||
GLRO(dl_profile_output) = &envline[15];
|
||||
break;
|
||||
|
||||
case 16:
|
||||
/* The mode of the dynamic linker can be set. */
|
||||
if (memcmp (envline, "TRACE_PRELINKING", 16) == 0)
|
||||
{
|
||||
state->mode = rtld_mode_trace;
|
||||
GLRO(dl_verbose) = 1;
|
||||
GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK;
|
||||
GLRO(dl_trace_prelink) = &envline[17];
|
||||
}
|
||||
break;
|
||||
|
||||
case 20:
|
||||
/* The mode of the dynamic linker can be set. */
|
||||
if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0)
|
||||
@ -2955,9 +2806,8 @@ print_statistics (const hp_timing_t *rtld_total_timep)
|
||||
+= l->l_info[VERSYMIDX (DT_RELCOUNT)]->d_un.d_val;
|
||||
#ifndef ELF_MACHINE_REL_RELATIVE
|
||||
/* Relative relocations are processed on these architectures if
|
||||
library is loaded to different address than p_vaddr or
|
||||
if not prelinked. */
|
||||
if ((l->l_addr != 0 || !l->l_info[VALIDX(DT_GNU_PRELINKED)])
|
||||
library is loaded to different address than p_vaddr. */
|
||||
if ((l->l_addr != 0)
|
||||
&& l->l_info[VERSYMIDX (DT_RELACOUNT)])
|
||||
#else
|
||||
/* On e.g. IA-64 or Alpha, relative relocations are processed
|
||||
|
@ -1,49 +0,0 @@
|
||||
/* Test the output from the environment variable, LD_TRACE_PRELINKING,
|
||||
for prelink.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <ldsodefs.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xstdio.h>
|
||||
#include <support/support.h>
|
||||
#include <support/test-driver.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
#ifndef DL_EXTERN_PROTECTED_DATA
|
||||
return EXIT_UNSUPPORTED;
|
||||
#else
|
||||
char *src = xasprintf ("%s/elf/tst-prelink-conflict.out",
|
||||
support_objdir_root);
|
||||
FILE *f = xfopen (src,"r");
|
||||
size_t buffer_length = 0;
|
||||
char *buffer = NULL;
|
||||
|
||||
const char *expected = "/0 stdout\n";
|
||||
|
||||
xgetline (&buffer, &buffer_length, f);
|
||||
TEST_COMPARE_STRING (expected, buffer);
|
||||
|
||||
free (buffer);
|
||||
xfclose (f);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
@ -1,29 +0,0 @@
|
||||
/* Test the output from the environment variable, LD_TRACE_PRELINKING,
|
||||
for prelink.
|
||||
Copyright (C) 2015-2022 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
fprintf (stdout, "hello\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
@ -203,10 +203,6 @@ struct link_map
|
||||
unsigned int l_contiguous:1; /* Nonzero if inter-segment holes are
|
||||
mprotected or if no holes are present at
|
||||
all. */
|
||||
unsigned int l_symbolic_in_local_scope:1; /* Nonzero if l_local_scope
|
||||
during LD_TRACE_PRELINKING=1
|
||||
contains any DT_SYMBOLIC
|
||||
libraries. */
|
||||
unsigned int l_free_initfini:1; /* Nonzero if l_initfini can be
|
||||
freed, ie. not allocated with
|
||||
the dummy malloc in ld.so. */
|
||||
|
@ -423,23 +423,8 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
|
||||
if (r_type == R_ALPHA_GLOB_DAT)
|
||||
*reloc_addr = sym_value;
|
||||
#ifdef RESOLVE_CONFLICT_FIND_MAP
|
||||
/* In .gnu.conflict section, R_ALPHA_JMP_SLOT relocations have
|
||||
R_ALPHA_JMP_SLOT in lower 8 bits and the remaining 24 bits
|
||||
are .rela.plt index. */
|
||||
else if ((r_type & 0xff) == R_ALPHA_JMP_SLOT)
|
||||
{
|
||||
/* elf_machine_fixup_plt needs the map reloc_addr points into,
|
||||
while in _dl_resolve_conflicts map is _dl_loaded. */
|
||||
RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
|
||||
reloc = ((const Elf64_Rela *) D_PTR (map, l_info[DT_JMPREL]))
|
||||
+ (r_type >> 8);
|
||||
elf_machine_fixup_plt (map, 0, 0, 0, reloc, reloc_addr, sym_value);
|
||||
}
|
||||
#else
|
||||
else if (r_type == R_ALPHA_JMP_SLOT)
|
||||
elf_machine_fixup_plt (map, 0, 0, 0, reloc, reloc_addr, sym_value);
|
||||
#endif
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
else if (r_type == R_ALPHA_REFQUAD)
|
||||
{
|
||||
|
@ -521,9 +521,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
return;
|
||||
else
|
||||
{
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
const Elf32_Sym *const refsym = sym;
|
||||
# endif
|
||||
struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, r_type);
|
||||
Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
|
||||
|
||||
@ -535,7 +533,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
/* Not needed for dl-conflict.c. */
|
||||
case R_ARM_COPY:
|
||||
if (sym == NULL)
|
||||
@ -555,7 +552,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
memcpy (reloc_addr_arg, (void *) value,
|
||||
MIN (sym->st_size, refsym->st_size));
|
||||
break;
|
||||
# endif /* !RESOLVE_CONFLICT_FIND_MAP */
|
||||
case R_ARM_GLOB_DAT:
|
||||
case R_ARM_JUMP_SLOT:
|
||||
case R_ARM_ABS32:
|
||||
|
@ -562,7 +562,6 @@ struct rtld_global_ro
|
||||
#define DL_DEBUG_SCOPES (1 << 9)
|
||||
/* These two are used only internally. */
|
||||
#define DL_DEBUG_HELP (1 << 10)
|
||||
#define DL_DEBUG_PRELINK (1 << 11)
|
||||
|
||||
/* OS version. */
|
||||
EXTERN unsigned int _dl_osversion;
|
||||
@ -649,10 +648,6 @@ struct rtld_global_ro
|
||||
EXTERN const char *_dl_profile;
|
||||
/* Filename of the output file. */
|
||||
EXTERN const char *_dl_profile_output;
|
||||
/* Name of the object we want to trace the prelinking. */
|
||||
EXTERN const char *_dl_trace_prelink;
|
||||
/* Map of shared object to be prelink traced. */
|
||||
EXTERN struct link_map *_dl_trace_prelink_map;
|
||||
|
||||
/* All search directories defined at startup. This is assigned a
|
||||
non-NULL pointer by the ld.so startup code (after initialization
|
||||
@ -1096,12 +1091,6 @@ extern void _dl_reloc_bad_type (struct link_map *map,
|
||||
unsigned int type, int plt)
|
||||
attribute_hidden __attribute__ ((__noreturn__));
|
||||
|
||||
/* Resolve conflicts if prelinking. */
|
||||
extern void _dl_resolve_conflicts (struct link_map *l,
|
||||
ElfW(Rela) *conflict,
|
||||
ElfW(Rela) *conflictend)
|
||||
attribute_hidden;
|
||||
|
||||
/* Check the version dependencies of all objects available through
|
||||
MAP. If VERBOSE print some more diagnostics. */
|
||||
extern int _dl_check_all_versions (struct link_map *map, int verbose,
|
||||
|
@ -479,9 +479,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
*reloc_addr = map->l_addr + reloc->r_addend;
|
||||
else if (r_type != R_386_NONE)
|
||||
{
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
const Elf32_Sym *const refsym = sym;
|
||||
# endif
|
||||
struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version,
|
||||
r_type);
|
||||
Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
|
||||
@ -503,7 +501,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
case R_386_32:
|
||||
*reloc_addr = value + reloc->r_addend;
|
||||
break;
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
/* Not needed for dl-conflict.c. */
|
||||
case R_386_PC32:
|
||||
*reloc_addr = (value + reloc->r_addend - (Elf32_Addr) reloc_addr);
|
||||
@ -525,19 +522,19 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
struct tlsdesc volatile *td =
|
||||
(struct tlsdesc volatile *)reloc_addr;
|
||||
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
if (!sym)
|
||||
{
|
||||
td->arg = (void*)reloc->r_addend;
|
||||
td->entry = _dl_tlsdesc_undefweak;
|
||||
}
|
||||
else
|
||||
# endif
|
||||
# endif
|
||||
{
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
# ifndef SHARED
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
# ifndef SHARED
|
||||
CHECK_STATIC_TLS (map, sym_map);
|
||||
# else
|
||||
# else
|
||||
if (!TRY_STATIC_TLS (map, sym_map))
|
||||
{
|
||||
td->arg = _dl_make_tlsdesc_dynamic
|
||||
@ -545,8 +542,8 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
td->entry = _dl_tlsdesc_dynamic;
|
||||
}
|
||||
else
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
{
|
||||
td->arg = (void*)(sym->st_value - sym_map->l_tls_offset
|
||||
+ reloc->r_addend);
|
||||
@ -599,7 +596,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
memcpy (reloc_addr_arg, (void *) value,
|
||||
MIN (sym->st_size, refsym->st_size));
|
||||
break;
|
||||
# endif /* !RESOLVE_CONFLICT_FIND_MAP */
|
||||
case R_386_IRELATIVE:
|
||||
value = map->l_addr + reloc->r_addend;
|
||||
if (__glibc_likely (!skip_ifunc))
|
||||
|
@ -189,9 +189,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
return;
|
||||
else
|
||||
{
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
const Elf32_Sym *const refsym = sym;
|
||||
# endif
|
||||
struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version,
|
||||
r_type);
|
||||
Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
|
||||
@ -204,7 +202,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
case R_OR1K_COPY:
|
||||
if (sym == NULL)
|
||||
/* This can happen in trace mode if an object could not be
|
||||
@ -225,7 +222,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
memcpy (reloc_addr_arg, (void *) value,
|
||||
MIN (sym->st_size, refsym->st_size));
|
||||
break;
|
||||
# endif /* !RESOLVE_CONFLICT_FIND_MAP */
|
||||
case R_OR1K_32:
|
||||
/* Support relocations on mis-aligned offsets. */
|
||||
value += reloc->r_addend;
|
||||
|
@ -294,7 +294,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
const int r_type = ELF32_R_TYPE (reloc->r_info);
|
||||
struct link_map *sym_map = NULL;
|
||||
|
||||
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
if (r_type == R_PPC_RELATIVE)
|
||||
{
|
||||
*reloc_addr = map->l_addr + reloc->r_addend;
|
||||
@ -318,9 +317,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
value = SYMBOL_ADDRESS (sym_map, sym, true);
|
||||
}
|
||||
value += reloc->r_addend;
|
||||
#else
|
||||
value = reloc->r_addend;
|
||||
#endif
|
||||
|
||||
if (sym != NULL
|
||||
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
|
||||
@ -341,12 +337,11 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
*reloc_addr = value;
|
||||
break;
|
||||
|
||||
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
# ifdef RTLD_BOOTSTRAP
|
||||
# define NOT_BOOTSTRAP 0
|
||||
# else
|
||||
# define NOT_BOOTSTRAP 1
|
||||
# endif
|
||||
#ifdef RTLD_BOOTSTRAP
|
||||
# define NOT_BOOTSTRAP 0
|
||||
#else
|
||||
# define NOT_BOOTSTRAP 1
|
||||
#endif
|
||||
|
||||
case R_PPC_DTPMOD32:
|
||||
if (map->l_info[DT_PPC(OPT)]
|
||||
@ -361,11 +356,11 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
}
|
||||
else if (sym_map != NULL)
|
||||
{
|
||||
# ifndef SHARED
|
||||
#ifndef SHARED
|
||||
CHECK_STATIC_TLS (map, sym_map);
|
||||
# else
|
||||
#else
|
||||
if (TRY_STATIC_TLS (map, sym_map))
|
||||
# endif
|
||||
#endif
|
||||
{
|
||||
reloc_addr[0] = 0;
|
||||
/* Set up for local dynamic. */
|
||||
@ -395,11 +390,11 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
else if (sym_map != NULL)
|
||||
{
|
||||
/* This reloc is always preceded by R_PPC_DTPMOD32. */
|
||||
# ifndef SHARED
|
||||
#ifndef SHARED
|
||||
assert (HAVE_STATIC_TLS (map, sym_map));
|
||||
# else
|
||||
#else
|
||||
if (HAVE_STATIC_TLS (map, sym_map))
|
||||
# endif
|
||||
#endif
|
||||
{
|
||||
*reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
|
||||
break;
|
||||
@ -419,12 +414,8 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
*reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case R_PPC_JMP_SLOT:
|
||||
#ifdef RESOLVE_CONFLICT_FIND_MAP
|
||||
RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
|
||||
#endif
|
||||
if (map->l_info[DT_PPC(GOT)] != 0)
|
||||
{
|
||||
*reloc_addr = value;
|
||||
|
@ -537,36 +537,6 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
|
||||
return finaladdr;
|
||||
}
|
||||
|
||||
static inline void __attribute__ ((always_inline))
|
||||
elf_machine_plt_conflict (struct link_map *map, lookup_t sym_map,
|
||||
const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
|
||||
const Elf64_Rela *reloc,
|
||||
Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
|
||||
{
|
||||
#if _CALL_ELF != 2
|
||||
Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
|
||||
Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
|
||||
Elf64_FuncDesc zero_fd = {0, 0, 0};
|
||||
|
||||
if (sym_map == NULL)
|
||||
finaladdr = 0;
|
||||
|
||||
if (finaladdr == 0)
|
||||
rel = &zero_fd;
|
||||
|
||||
plt->fd_func = rel->fd_func;
|
||||
plt->fd_aux = rel->fd_aux;
|
||||
plt->fd_toc = rel->fd_toc;
|
||||
PPC_DCBST (&plt->fd_func);
|
||||
PPC_DCBST (&plt->fd_aux);
|
||||
PPC_DCBST (&plt->fd_toc);
|
||||
PPC_SYNC;
|
||||
#else
|
||||
finaladdr += ppc64_local_entry_offset (map, sym_map, refsym, sym);
|
||||
*reloc_addr = finaladdr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return the final value of a plt relocation. */
|
||||
static inline Elf64_Addr
|
||||
elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
|
||||
@ -639,7 +609,6 @@ resolve_ifunc (Elf64_Addr value,
|
||||
const struct link_map *map, const struct link_map *sym_map)
|
||||
{
|
||||
#if _CALL_ELF != 2
|
||||
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
/* The function we are calling may not yet have its opd entry relocated. */
|
||||
Elf64_FuncDesc opd;
|
||||
if (map != sym_map
|
||||
@ -657,7 +626,6 @@ resolve_ifunc (Elf64_Addr value,
|
||||
dependency. */
|
||||
asm ("" : "=r" (value) : "0" (&opd), "X" (opd));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return ((Elf64_Addr (*) (unsigned long int)) value) (GLRO(dl_hwcap));
|
||||
}
|
||||
@ -722,13 +690,8 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
value = resolve_ifunc (value, map, sym_map);
|
||||
/* Fall thru */
|
||||
case R_PPC64_JMP_SLOT:
|
||||
#ifdef RESOLVE_CONFLICT_FIND_MAP
|
||||
elf_machine_plt_conflict (map, sym_map, refsym, sym,
|
||||
reloc, reloc_addr, value);
|
||||
#else
|
||||
elf_machine_fixup_plt (map, sym_map, refsym, sym,
|
||||
reloc, reloc_addr, value);
|
||||
#endif
|
||||
return;
|
||||
|
||||
case R_PPC64_DTPMOD64:
|
||||
|
@ -352,7 +352,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
return;
|
||||
else
|
||||
{
|
||||
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
|
||||
#if !defined RTLD_BOOTSTRAP
|
||||
/* Only needed for R_390_COPY below. */
|
||||
const Elf32_Sym *const refsym = sym;
|
||||
#endif
|
||||
@ -380,34 +380,33 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
*reloc_addr = value + reloc->r_addend;
|
||||
break;
|
||||
|
||||
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
case R_390_TLS_DTPMOD:
|
||||
# ifdef RTLD_BOOTSTRAP
|
||||
#ifdef RTLD_BOOTSTRAP
|
||||
/* During startup the dynamic linker is always the module
|
||||
with index 1.
|
||||
XXX If this relocation is necessary move before RESOLVE
|
||||
call. */
|
||||
*reloc_addr = 1;
|
||||
# else
|
||||
#else
|
||||
/* Get the information from the link map returned by the
|
||||
resolv function. */
|
||||
if (sym_map != NULL)
|
||||
*reloc_addr = sym_map->l_tls_modid;
|
||||
# endif
|
||||
#endif
|
||||
break;
|
||||
case R_390_TLS_DTPOFF:
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
/* During relocation all TLS symbols are defined and used.
|
||||
Therefore the offset is already correct. */
|
||||
if (sym != NULL)
|
||||
*reloc_addr = sym->st_value + reloc->r_addend;
|
||||
# endif
|
||||
#endif
|
||||
break;
|
||||
case R_390_TLS_TPOFF:
|
||||
/* The offset is negative, forward from the thread pointer. */
|
||||
# ifdef RTLD_BOOTSTRAP
|
||||
#ifdef RTLD_BOOTSTRAP
|
||||
*reloc_addr = sym->st_value + reloc->r_addend - map->l_tls_offset;
|
||||
# else
|
||||
#else
|
||||
/* We know the offset of the object the symbol is contained in.
|
||||
It is a negative value which will be added to the
|
||||
thread pointer. */
|
||||
@ -419,10 +418,8 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#endif /* use TLS */
|
||||
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
/* Not needed in dl-conflict.c. */
|
||||
case R_390_COPY:
|
||||
if (sym == NULL)
|
||||
@ -443,7 +440,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
memcpy (reloc_addr_arg, (void *) value,
|
||||
MIN (sym->st_size, refsym->st_size));
|
||||
break;
|
||||
# endif
|
||||
case R_390_32:
|
||||
*reloc_addr = value + reloc->r_addend;
|
||||
break;
|
||||
@ -453,7 +449,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
case R_390_8:
|
||||
*(char *) reloc_addr = value + reloc->r_addend;
|
||||
break;
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
case R_390_PC32:
|
||||
*reloc_addr = value + reloc->r_addend - (Elf32_Addr) reloc_addr;
|
||||
break;
|
||||
@ -471,7 +466,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
break;
|
||||
case R_390_NONE:
|
||||
break;
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(RTLD_BOOTSTRAP) || defined(_NDEBUG)
|
||||
default:
|
||||
|
@ -299,7 +299,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
return;
|
||||
else
|
||||
{
|
||||
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
|
||||
#if !defined RTLD_BOOTSTRAP
|
||||
/* Only needed for R_390_COPY below. */
|
||||
const Elf64_Sym *const refsym = sym;
|
||||
#endif
|
||||
@ -327,34 +327,33 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
*reloc_addr = value + reloc->r_addend;
|
||||
break;
|
||||
|
||||
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
case R_390_TLS_DTPMOD:
|
||||
# ifdef RTLD_BOOTSTRAP
|
||||
#ifdef RTLD_BOOTSTRAP
|
||||
/* During startup the dynamic linker is always the module
|
||||
with index 1.
|
||||
XXX If this relocation is necessary move before RESOLVE
|
||||
call. */
|
||||
*reloc_addr = 1;
|
||||
# else
|
||||
#else
|
||||
/* Get the information from the link map returned by the
|
||||
resolv function. */
|
||||
if (sym_map != NULL)
|
||||
*reloc_addr = sym_map->l_tls_modid;
|
||||
# endif
|
||||
#endif
|
||||
break;
|
||||
case R_390_TLS_DTPOFF:
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
/* During relocation all TLS symbols are defined and used.
|
||||
Therefore the offset is already correct. */
|
||||
if (sym != NULL)
|
||||
*reloc_addr = sym->st_value + reloc->r_addend;
|
||||
# endif
|
||||
#endif
|
||||
break;
|
||||
case R_390_TLS_TPOFF:
|
||||
/* The offset is negative, forward from the thread pointer. */
|
||||
# ifdef RTLD_BOOTSTRAP
|
||||
#ifdef RTLD_BOOTSTRAP
|
||||
*reloc_addr = sym->st_value + reloc->r_addend - map->l_tls_offset;
|
||||
# else
|
||||
#else
|
||||
/* We know the offset of the object the symbol is contained in.
|
||||
It is a negative value which will be added to the
|
||||
thread pointer. */
|
||||
@ -366,10 +365,8 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#endif /* use TLS */
|
||||
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
/* Not needed for dl-conflict.c. */
|
||||
case R_390_COPY:
|
||||
if (sym == NULL)
|
||||
@ -390,7 +387,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
memcpy (reloc_addr_arg, (void *) value,
|
||||
MIN (sym->st_size, refsym->st_size));
|
||||
break;
|
||||
# endif
|
||||
case R_390_64:
|
||||
*reloc_addr = value + reloc->r_addend;
|
||||
break;
|
||||
@ -403,7 +399,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
case R_390_8:
|
||||
*(char *) reloc_addr = value + reloc->r_addend;
|
||||
break;
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
case R_390_PC64:
|
||||
*reloc_addr = value +reloc->r_addend - (Elf64_Addr) reloc_addr;
|
||||
break;
|
||||
@ -425,7 +420,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
break;
|
||||
case R_390_NONE:
|
||||
break;
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(RTLD_BOOTSTRAP) || defined(_NDEBUG)
|
||||
default:
|
||||
|
@ -391,7 +391,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
break;
|
||||
case R_SH_DIR32:
|
||||
{
|
||||
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
|
||||
#if !defined RTLD_BOOTSTRAP
|
||||
/* This is defined in rtld.c, but nowhere in the static
|
||||
libc.a; make the reference weak so static programs can
|
||||
still link. This declaration cannot be done when
|
||||
|
@ -142,44 +142,6 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
|
||||
plt[1] = 0x85c0a000 | (rfunc & 0x3ff);
|
||||
plt[2] = OPCODE_NOP; /* Fill call delay slot. */
|
||||
plt[3] = (Elf32_Addr) l;
|
||||
if (__builtin_expect (l->l_info[VALIDX(DT_GNU_PRELINKED)] != NULL, 0)
|
||||
|| __builtin_expect (l->l_info [VALIDX (DT_GNU_LIBLISTSZ)] != NULL, 0))
|
||||
{
|
||||
/* Need to reinitialize .plt to undo prelinking. */
|
||||
Elf32_Rela *rela = (Elf32_Rela *) D_PTR (l, l_info[DT_JMPREL]);
|
||||
Elf32_Rela *relaend
|
||||
= (Elf32_Rela *) ((char *) rela
|
||||
+ l->l_info[DT_PLTRELSZ]->d_un.d_val);
|
||||
#if !defined RTLD_BOOTSTRAP && !defined __sparc_v9__
|
||||
/* Note that we don't mask the hwcap here, as the flush is
|
||||
essential to functionality on those cpu's that implement it.
|
||||
For sparcv9 we can assume flush is present. */
|
||||
const int do_flush = GLRO(dl_hwcap) & HWCAP_SPARC_FLUSH;
|
||||
#else
|
||||
const int do_flush = 1;
|
||||
#endif
|
||||
|
||||
/* prelink must ensure there are no R_SPARC_NONE relocs left
|
||||
in .rela.plt. */
|
||||
while (rela < relaend)
|
||||
{
|
||||
*(unsigned int *) (rela->r_offset + l->l_addr)
|
||||
= OPCODE_SETHI_G1 | (rela->r_offset + l->l_addr
|
||||
- (Elf32_Addr) plt);
|
||||
*(unsigned int *) (rela->r_offset + l->l_addr + 4)
|
||||
= OPCODE_BA | ((((Elf32_Addr) plt
|
||||
- rela->r_offset - l->l_addr - 4) >> 2)
|
||||
& 0x3fffff);
|
||||
if (do_flush)
|
||||
{
|
||||
__asm __volatile ("flush %0" : : "r" (rela->r_offset
|
||||
+ l->l_addr));
|
||||
__asm __volatile ("flush %0+4" : : "r" (rela->r_offset
|
||||
+ l->l_addr));
|
||||
}
|
||||
++rela;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lazy;
|
||||
@ -334,14 +296,12 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
void *const reloc_addr_arg, int skip_ifunc)
|
||||
{
|
||||
Elf32_Addr *const reloc_addr = reloc_addr_arg;
|
||||
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
|
||||
#if !defined RTLD_BOOTSTRAP
|
||||
const Elf32_Sym *const refsym = sym;
|
||||
#endif
|
||||
Elf32_Addr value;
|
||||
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
|
||||
#if !defined RESOLVE_CONFLICT_FIND_MAP
|
||||
struct link_map *sym_map = NULL;
|
||||
#endif
|
||||
|
||||
#if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
|
||||
/* This is defined in rtld.c, but nowhere in the static libc.a; make the
|
||||
@ -372,7 +332,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
if (__builtin_expect (ELF32_ST_BIND (sym->st_info) == STB_LOCAL, 0)
|
||||
&& sym->st_shndx != SHN_UNDEF)
|
||||
{
|
||||
@ -384,9 +343,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
sym_map = RESOLVE_MAP (map, scope, &sym, version, r_type);
|
||||
value = SYMBOL_ADDRESS (sym_map, sym, true);
|
||||
}
|
||||
#else
|
||||
value = 0;
|
||||
#endif
|
||||
|
||||
value += reloc->r_addend; /* Assume copy relocs have zero addend. */
|
||||
|
||||
@ -400,7 +356,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
|
||||
#if !defined RTLD_BOOTSTRAP
|
||||
case R_SPARC_COPY:
|
||||
if (sym == NULL)
|
||||
/* This can happen in trace mode if an object could not be
|
||||
@ -450,7 +406,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
sparc_fixup_plt (reloc, reloc_addr, value, 0, do_flush);
|
||||
}
|
||||
break;
|
||||
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
case R_SPARC_TLS_DTPMOD32:
|
||||
/* Get the information from the link map returned by the
|
||||
resolv function. */
|
||||
@ -474,7 +429,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
+ reloc->r_addend;
|
||||
}
|
||||
break;
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
case R_SPARC_TLS_LE_HIX22:
|
||||
case R_SPARC_TLS_LE_LOX10:
|
||||
if (sym != NULL)
|
||||
@ -489,7 +444,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
| 0x1c00;
|
||||
}
|
||||
break;
|
||||
# endif
|
||||
#endif
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
case R_SPARC_8:
|
||||
|
@ -196,50 +196,6 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
|
||||
/* Now put the magic cookie at the beginning of .PLT2
|
||||
Entry .PLT3 is unused by this implementation. */
|
||||
*((struct link_map **)(&plt[16])) = l;
|
||||
|
||||
if (__builtin_expect (l->l_info[VALIDX(DT_GNU_PRELINKED)] != NULL, 0)
|
||||
|| __builtin_expect (l->l_info [VALIDX (DT_GNU_LIBLISTSZ)] != NULL, 0))
|
||||
{
|
||||
/* Need to reinitialize .plt to undo prelinking. */
|
||||
Elf64_Rela *rela = (Elf64_Rela *) D_PTR (l, l_info[DT_JMPREL]);
|
||||
Elf64_Rela *relaend
|
||||
= (Elf64_Rela *) ((char *) rela
|
||||
+ l->l_info[DT_PLTRELSZ]->d_un.d_val);
|
||||
|
||||
/* prelink must ensure there are no R_SPARC_NONE relocs left
|
||||
in .rela.plt. */
|
||||
while (rela < relaend)
|
||||
{
|
||||
if (__builtin_expect (rela->r_addend, 0) != 0)
|
||||
{
|
||||
Elf64_Addr slot = ((rela->r_offset + l->l_addr + 0x400
|
||||
- (Elf64_Addr) plt)
|
||||
/ 0x1400) * 0x1400
|
||||
+ (Elf64_Addr) plt - 0x400;
|
||||
/* ldx [%o7 + X], %g1 */
|
||||
unsigned int first_ldx = *(unsigned int *)(slot + 12);
|
||||
Elf64_Addr ptr = slot + (first_ldx & 0xfff) + 4;
|
||||
|
||||
*(Elf64_Addr *) (rela->r_offset + l->l_addr)
|
||||
= (Elf64_Addr) plt
|
||||
- (slot + ((rela->r_offset + l->l_addr - ptr) / 8) * 24
|
||||
+ 4);
|
||||
++rela;
|
||||
continue;
|
||||
}
|
||||
|
||||
*(unsigned int *) (rela->r_offset + l->l_addr)
|
||||
= 0x03000000 | (rela->r_offset + l->l_addr - (Elf64_Addr) plt);
|
||||
*(unsigned int *) (rela->r_offset + l->l_addr + 4)
|
||||
= 0x30680000 | ((((Elf64_Addr) plt + 32 - rela->r_offset
|
||||
- l->l_addr - 4) >> 2) & 0x7ffff);
|
||||
__asm __volatile ("flush %0" : : "r" (rela->r_offset
|
||||
+ l->l_addr));
|
||||
__asm __volatile ("flush %0+4" : : "r" (rela->r_offset
|
||||
+ l->l_addr));
|
||||
++rela;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lazy;
|
||||
@ -361,14 +317,12 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
void *const reloc_addr_arg, int skip_ifunc)
|
||||
{
|
||||
Elf64_Addr *const reloc_addr = reloc_addr_arg;
|
||||
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
|
||||
#if !defined RTLD_BOOTSTRAP
|
||||
const Elf64_Sym *const refsym = sym;
|
||||
#endif
|
||||
Elf64_Addr value;
|
||||
const unsigned long int r_type = ELF64_R_TYPE_ID (reloc->r_info);
|
||||
#if !defined RESOLVE_CONFLICT_FIND_MAP
|
||||
struct link_map *sym_map = NULL;
|
||||
#endif
|
||||
|
||||
#if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
|
||||
/* This is defined in rtld.c, but nowhere in the static libc.a; make the
|
||||
@ -399,7 +353,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
if (__builtin_expect (ELF64_ST_BIND (sym->st_info) == STB_LOCAL, 0)
|
||||
&& sym->st_shndx != SHN_UNDEF)
|
||||
{
|
||||
@ -411,9 +364,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
sym_map = RESOLVE_MAP (map, scope, &sym, version, r_type);
|
||||
value = SYMBOL_ADDRESS (sym_map, sym, true);
|
||||
}
|
||||
#else
|
||||
value = 0;
|
||||
#endif
|
||||
|
||||
value += reloc->r_addend; /* Assume copy relocs have zero addend. */
|
||||
|
||||
@ -425,7 +375,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
|
||||
#if !defined RTLD_BOOTSTRAP
|
||||
case R_SPARC_COPY:
|
||||
if (sym == NULL)
|
||||
/* This can happen in trace mode if an object could not be
|
||||
@ -459,26 +409,11 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap));
|
||||
/* 'high' is always zero, for large PLT entries the linker
|
||||
emits an R_SPARC_IRELATIVE. */
|
||||
#ifdef RESOLVE_CONFLICT_FIND_MAP
|
||||
sparc64_fixup_plt (NULL, reloc, reloc_addr, value, 0, 0);
|
||||
#else
|
||||
sparc64_fixup_plt (map, reloc, reloc_addr, value, 0, 0);
|
||||
#endif
|
||||
break;
|
||||
case R_SPARC_JMP_SLOT:
|
||||
#ifdef RESOLVE_CONFLICT_FIND_MAP
|
||||
/* R_SPARC_JMP_SLOT conflicts against .plt[32768+]
|
||||
relocs should be turned into R_SPARC_64 relocs
|
||||
in .gnu.conflict section.
|
||||
r_addend non-zero does not mean it is a .plt[32768+]
|
||||
reloc, instead it is the actual address of the function
|
||||
to call. */
|
||||
sparc64_fixup_plt (NULL, reloc, reloc_addr, value, 0, 0);
|
||||
#else
|
||||
sparc64_fixup_plt (map, reloc, reloc_addr, value, reloc->r_addend, 0);
|
||||
#endif
|
||||
break;
|
||||
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
case R_SPARC_TLS_DTPMOD64:
|
||||
/* Get the information from the link map returned by the
|
||||
resolv function. */
|
||||
@ -502,7 +437,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
+ reloc->r_addend;
|
||||
}
|
||||
break;
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
case R_SPARC_TLS_LE_HIX22:
|
||||
case R_SPARC_TLS_LE_LOX10:
|
||||
if (sym != NULL)
|
||||
@ -520,7 +455,6 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
|
||||
| 0x1c00);
|
||||
}
|
||||
break;
|
||||
# endif
|
||||
#endif
|
||||
#ifndef RTLD_BOOTSTRAP
|
||||
case R_SPARC_8:
|
||||
|
@ -346,59 +346,58 @@ and creates an unsatisfiable circular dependency.\n",
|
||||
*reloc_addr = value + reloc->r_addend;
|
||||
break;
|
||||
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
case R_X86_64_DTPMOD64:
|
||||
# ifdef RTLD_BOOTSTRAP
|
||||
# ifdef RTLD_BOOTSTRAP
|
||||
/* During startup the dynamic linker is always the module
|
||||
with index 1.
|
||||
XXX If this relocation is necessary move before RESOLVE
|
||||
call. */
|
||||
*reloc_addr = 1;
|
||||
# else
|
||||
# else
|
||||
/* Get the information from the link map returned by the
|
||||
resolve function. */
|
||||
if (sym_map != NULL)
|
||||
*reloc_addr = sym_map->l_tls_modid;
|
||||
# endif
|
||||
# endif
|
||||
break;
|
||||
case R_X86_64_DTPOFF64:
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
/* During relocation all TLS symbols are defined and used.
|
||||
Therefore the offset is already correct. */
|
||||
if (sym != NULL)
|
||||
{
|
||||
value = sym->st_value + reloc->r_addend;
|
||||
# ifdef __ILP32__
|
||||
# ifdef __ILP32__
|
||||
/* This relocation type computes a signed offset that is
|
||||
usually negative. The symbol and addend values are 32
|
||||
bits but the GOT entry is 64 bits wide and the whole
|
||||
64-bit entry is used as a signed quantity, so we need
|
||||
to sign-extend the computed value to 64 bits. */
|
||||
*(Elf64_Sxword *) reloc_addr = (Elf64_Sxword) (Elf32_Sword) value;
|
||||
# else
|
||||
# else
|
||||
*reloc_addr = value;
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
break;
|
||||
case R_X86_64_TLSDESC:
|
||||
{
|
||||
struct tlsdesc volatile *td =
|
||||
(struct tlsdesc volatile *)reloc_addr;
|
||||
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
if (! sym)
|
||||
{
|
||||
td->arg = (void*)reloc->r_addend;
|
||||
td->entry = _dl_tlsdesc_undefweak;
|
||||
}
|
||||
else
|
||||
# endif
|
||||
# endif
|
||||
{
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
# ifndef SHARED
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
# ifndef SHARED
|
||||
CHECK_STATIC_TLS (map, sym_map);
|
||||
# else
|
||||
# else
|
||||
if (!TRY_STATIC_TLS (map, sym_map))
|
||||
{
|
||||
td->arg = _dl_make_tlsdesc_dynamic
|
||||
@ -406,8 +405,8 @@ and creates an unsatisfiable circular dependency.\n",
|
||||
td->entry = _dl_tlsdesc_dynamic;
|
||||
}
|
||||
else
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
{
|
||||
td->arg = (void*)(sym->st_value - sym_map->l_tls_offset
|
||||
+ reloc->r_addend);
|
||||
@ -418,30 +417,29 @@ and creates an unsatisfiable circular dependency.\n",
|
||||
}
|
||||
case R_X86_64_TPOFF64:
|
||||
/* The offset is negative, forward from the thread pointer. */
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
if (sym != NULL)
|
||||
# endif
|
||||
# endif
|
||||
{
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
CHECK_STATIC_TLS (map, sym_map);
|
||||
# endif
|
||||
# endif
|
||||
/* We know the offset of the object the symbol is contained in.
|
||||
It is a negative value which will be added to the
|
||||
thread pointer. */
|
||||
value = (sym->st_value + reloc->r_addend
|
||||
- sym_map->l_tls_offset);
|
||||
# ifdef __ILP32__
|
||||
# ifdef __ILP32__
|
||||
/* The symbol and addend values are 32 bits but the GOT
|
||||
entry is 64 bits wide and the whole 64-bit entry is used
|
||||
as a signed quantity, so we need to sign-extend the
|
||||
computed value to 64 bits. */
|
||||
*(Elf64_Sxword *) reloc_addr = (Elf64_Sxword) (Elf32_Sword) value;
|
||||
# else
|
||||
# else
|
||||
*reloc_addr = value;
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
break;
|
||||
# endif
|
||||
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
case R_X86_64_64:
|
||||
@ -466,15 +464,12 @@ and creates an unsatisfiable circular dependency.\n",
|
||||
|
||||
fmt = "\
|
||||
%s: Symbol `%s' causes overflow in R_X86_64_32 relocation\n";
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
print_err:
|
||||
# endif
|
||||
strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
|
||||
|
||||
_dl_error_printf (fmt, RTLD_PROGNAME, strtab + refsym->st_name);
|
||||
}
|
||||
break;
|
||||
# ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||
/* Not needed for dl-conflict.c. */
|
||||
case R_X86_64_PC32:
|
||||
value += reloc->r_addend - (ElfW(Addr)) reloc_addr;
|
||||
@ -502,7 +497,6 @@ and creates an unsatisfiable circular dependency.\n",
|
||||
goto print_err;
|
||||
}
|
||||
break;
|
||||
# endif
|
||||
case R_X86_64_IRELATIVE:
|
||||
value = map->l_addr + reloc->r_addend;
|
||||
if (__glibc_likely (!skip_ifunc))
|
||||
|
Loading…
Reference in New Issue
Block a user