mirror of git://sourceware.org/git/glibc.git
Update.
2001-12-11 Jakub Jelinek <jakub@redhat.com> * elf/Makefile (dl-routines): Add conflict. (rtld-ldscript-in, rtld-ldscript, rtld-parms): Remove. (ld.so): Add _begin local symbol. * elf/elf.h (DT_VALTAGIDX, DT_VALNUM, DT_ADDRTAGIDX, DT_ADDRNUM): Define. * elf/dl-deps.c (_dl_build_local_scope): New. (_dl_map_object_deps): If LD_TRACE_PRELINKING, compute local scopes of all libraries. * elf/do-rel.h (VALIDX): Define. (elf_dynamic_do_rel): If ELF_MACHINE_PLT_REL is defined, don't do lazy binding for RELA. If DT_GNU_PRELINKED, DT_RELACOUNT relocations can be skipped. * elf/dl-conflict.c: New file. * elf/dl-lookup.c (_dl_debug_bindings): New. (_dl_lookup_symbol): Use _dl_debug_bindings. Reference_name is always non-NULL. (_dl_lookup_symbol_skip): Likewise. (_dl_lookup_versioned_symbol): Likewise. (_dl_lookup_versioned_symbol_skip): Likewise. * elf/dl-runtime.c (PLTREL): If ELF_MACHINE_PLT_REL is defined, define to ElfW(Rel). * elf/dynamic-link.h (elf_get_dynamic_info): Record selected dynamic tags in the DT_VALRNGLO..DT_VALRNGHI and DT_ADDRRNGLO..DT_ADDRRNGHI ranges. Don't adjust address dynamic tags if l_addr is 0. * elf/rtld.c (_dl_trace_prelink, _dl_trace_prelink_map): New variables. (_dl_start): Skip ELF_DYNAMIC_RELOCATE if ld.so is prelinked. (VALIDX, ADDRIDX): Define. (_dl_start_final): Initialize _dl_rtld_map's l_map_start and l_map_end. (dl_main): Print library list for LD_TRACE_PRELINKING. If prelinking information can be used, skip relocating libraries and call _dl_resolve_conflicts instead. (process_envvars): Handle LD_TRACE_PRELINKING envvar. * elf/dl-load.c (_dl_map_object): Don't create fake libs if LD_TRACE_PRELINKING. * include/link.h (struct link_map) [l_info]: Add DT_VALNUM + DT_ADDRNUM. * sysdeps/generic/ldsodefs.h (_dl_trace_prelink_map): New declaration. (DL_DEBUG_PRELINK): Define. (_dl_resolve_conflicts): Add prototype. * sysdeps/alpha/dl-machine.h (elf_machine_runtime_setup): Reinitialize .plt for prelinked libraries where prelinking info cannot be used. (elf_machine_rela): If relocating R_ALPHA_JMP_SLOT in .gnu.conflict section, use RESOLVE_CONFLICT_FIND_MAP to find out reloc's link_map. * sysdeps/arm/bits/link.h: New file. * sysdeps/arm/dl-machine.h (elf_machine_runtime_setup): Save original content of .got[1]. (ELF_MACHINE_NO_RELA): Only define if RTLD_BOOTSTRAP. (ELF_MACHINE_PLT_REL): Define. (elf_machine_rela, elf_machine_rela_relative): New. (elf_machine_lazy_rel): Reinitialize R_ARM_JUMP_SLOT address instead of adjusting it if prelinked and prelinking cannot be used. * sysdeps/i386/bits/link.h: New file. * sysdeps/i386/dl-machine.h (elf_machine_runtime_setup): Save original content of .got[1]. (ELF_MACHINE_NO_RELA): Only define if RTLD_BOOTSTRAP. (ELF_MACHINE_PLT_REL): Define. (elf_machine_rela, elf_machine_rela_relative): New. (elf_machine_lazy_rel): Reinitialize R_386_JUMP_SLOT address instead of adjusting it if prelinked and prelinking cannot be used. * sysdeps/powerpc/dl-machine.h (elf_machine_rela): If relocating conflicts, skip finaladdr computation. Use RESOLVE_CONFLICT_FIND_MAP to find out map for R_PPC_JMP_SLOT relocs. * sysdeps/sparc/sparc32/dl-machine.h (VALIDX): Define. (OPCODE_BA): Define. (elf_machine_runtime_setup): Reinitialize .plt for prelinked libraries where prelinking info cannot be used. (sparc_fixup_plt): Renamed from elf_machine_fixup_plt. (elf_machine_fixup_plt): Call sparc_fixup_plt. (elf_machine_rela): Set value to 0 if relocating conflicts. Call sparc_fixup_plt for R_SPARC_JMP_SLOT. * sysdeps/sparc/sparc64/dl-machine.h (VALIDX): Define. (sparc64_fixup_plt): Fix a typo. (elf_machine_rela): Set value to 0 if relocating conflicts. Handle R_SPARC_JMP_SLOT relocs when relocating conflicts. (elf_machine_runtime_setup): Reinitialize .plt for prelinked libraries where prelinking info cannot be used. * sysdeps/sh/bits/link.h: New file. * sysdeps/sh/dl-machine.h (elf_machine_runtime_setup): Save original content of .got[1]. (elf_machine_lazy_rel): Reinitialize R_SH_JMP_SLOT address instead of adjusting it if prelinked and prelinking cannot be used. * sysdeps/s390/s390-32/bits/link.h: New file. * sysdeps/s390/s390-32/dl-machine.h (elf_machine_runtime_setup): Save original content of .got[1]. (elf_machine_lazy_rel): Reinitialize R_390_JMP_SLOT address instead of adjusting it if prelinked and prelinking cannot be used. * sysdeps/s390/s390-64/bits/link.h: New file. * sysdeps/s390/s390-64/dl-machine.h (elf_machine_runtime_setup): Save original content of .got[1]. (elf_machine_lazy_rel): Reinitialize R_390_JMP_SLOT address instead of adjusting it if prelinked and prelinking cannot be used. * sysdeps/x86_64/bits/link.h: New file. * sysdeps/x86_64/dl-machine.h (elf_machine_runtime_setup): Save original content of .got[1]. (elf_machine_lazy_rel): Reinitialize R_X86_64_JMP_SLOT address instead of adjusting it if prelinked and prelinking cannot be used.
This commit is contained in:
parent
4be601a15e
commit
32e6df3621
101
ChangeLog
101
ChangeLog
|
@ -1,3 +1,104 @@
|
||||||
|
2001-12-11 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
* elf/Makefile (dl-routines): Add conflict.
|
||||||
|
(rtld-ldscript-in, rtld-ldscript, rtld-parms): Remove.
|
||||||
|
(ld.so): Add _begin local symbol.
|
||||||
|
* elf/elf.h (DT_VALTAGIDX, DT_VALNUM, DT_ADDRTAGIDX, DT_ADDRNUM):
|
||||||
|
Define.
|
||||||
|
* elf/dl-deps.c (_dl_build_local_scope): New.
|
||||||
|
(_dl_map_object_deps): If LD_TRACE_PRELINKING, compute local scopes
|
||||||
|
of all libraries.
|
||||||
|
* elf/do-rel.h (VALIDX): Define.
|
||||||
|
(elf_dynamic_do_rel): If ELF_MACHINE_PLT_REL is defined, don't do
|
||||||
|
lazy binding for RELA. If DT_GNU_PRELINKED, DT_RELACOUNT relocations
|
||||||
|
can be skipped.
|
||||||
|
* elf/dl-conflict.c: New file.
|
||||||
|
* elf/dl-lookup.c (_dl_debug_bindings): New.
|
||||||
|
(_dl_lookup_symbol): Use _dl_debug_bindings. Reference_name is always
|
||||||
|
non-NULL.
|
||||||
|
(_dl_lookup_symbol_skip): Likewise.
|
||||||
|
(_dl_lookup_versioned_symbol): Likewise.
|
||||||
|
(_dl_lookup_versioned_symbol_skip): Likewise.
|
||||||
|
* elf/dl-runtime.c (PLTREL): If ELF_MACHINE_PLT_REL is defined,
|
||||||
|
define to ElfW(Rel).
|
||||||
|
* elf/dynamic-link.h (elf_get_dynamic_info): Record selected dynamic
|
||||||
|
tags in the DT_VALRNGLO..DT_VALRNGHI and DT_ADDRRNGLO..DT_ADDRRNGHI
|
||||||
|
ranges.
|
||||||
|
Don't adjust address dynamic tags if l_addr is 0.
|
||||||
|
* elf/rtld.c (_dl_trace_prelink, _dl_trace_prelink_map): New variables.
|
||||||
|
(_dl_start): Skip ELF_DYNAMIC_RELOCATE if ld.so is prelinked.
|
||||||
|
(VALIDX, ADDRIDX): Define.
|
||||||
|
(_dl_start_final): Initialize _dl_rtld_map's l_map_start and l_map_end.
|
||||||
|
(dl_main): Print library list for LD_TRACE_PRELINKING.
|
||||||
|
If prelinking information can be used, skip relocating libraries and
|
||||||
|
call _dl_resolve_conflicts instead.
|
||||||
|
(process_envvars): Handle LD_TRACE_PRELINKING envvar.
|
||||||
|
* elf/dl-load.c (_dl_map_object): Don't create fake libs
|
||||||
|
if LD_TRACE_PRELINKING.
|
||||||
|
* include/link.h (struct link_map) [l_info]: Add DT_VALNUM
|
||||||
|
+ DT_ADDRNUM.
|
||||||
|
* sysdeps/generic/ldsodefs.h (_dl_trace_prelink_map): New declaration.
|
||||||
|
(DL_DEBUG_PRELINK): Define.
|
||||||
|
(_dl_resolve_conflicts): Add prototype.
|
||||||
|
|
||||||
|
* sysdeps/alpha/dl-machine.h (elf_machine_runtime_setup): Reinitialize
|
||||||
|
.plt for prelinked libraries where prelinking info cannot be used.
|
||||||
|
(elf_machine_rela): If relocating R_ALPHA_JMP_SLOT in .gnu.conflict
|
||||||
|
section, use RESOLVE_CONFLICT_FIND_MAP to find out reloc's link_map.
|
||||||
|
* sysdeps/arm/bits/link.h: New file.
|
||||||
|
* sysdeps/arm/dl-machine.h (elf_machine_runtime_setup): Save original
|
||||||
|
content of .got[1].
|
||||||
|
(ELF_MACHINE_NO_RELA): Only define if RTLD_BOOTSTRAP.
|
||||||
|
(ELF_MACHINE_PLT_REL): Define.
|
||||||
|
(elf_machine_rela, elf_machine_rela_relative): New.
|
||||||
|
(elf_machine_lazy_rel): Reinitialize R_ARM_JUMP_SLOT address instead
|
||||||
|
of adjusting it if prelinked and prelinking cannot be used.
|
||||||
|
* sysdeps/i386/bits/link.h: New file.
|
||||||
|
* sysdeps/i386/dl-machine.h (elf_machine_runtime_setup): Save original
|
||||||
|
content of .got[1].
|
||||||
|
(ELF_MACHINE_NO_RELA): Only define if RTLD_BOOTSTRAP.
|
||||||
|
(ELF_MACHINE_PLT_REL): Define.
|
||||||
|
(elf_machine_rela, elf_machine_rela_relative): New.
|
||||||
|
(elf_machine_lazy_rel): Reinitialize R_386_JUMP_SLOT address instead
|
||||||
|
of adjusting it if prelinked and prelinking cannot be used.
|
||||||
|
* sysdeps/powerpc/dl-machine.h (elf_machine_rela): If relocating
|
||||||
|
conflicts, skip finaladdr computation. Use RESOLVE_CONFLICT_FIND_MAP
|
||||||
|
to find out map for R_PPC_JMP_SLOT relocs.
|
||||||
|
* sysdeps/sparc/sparc32/dl-machine.h (VALIDX): Define.
|
||||||
|
(OPCODE_BA): Define.
|
||||||
|
(elf_machine_runtime_setup): Reinitialize .plt for prelinked
|
||||||
|
libraries where prelinking info cannot be used.
|
||||||
|
(sparc_fixup_plt): Renamed from elf_machine_fixup_plt.
|
||||||
|
(elf_machine_fixup_plt): Call sparc_fixup_plt.
|
||||||
|
(elf_machine_rela): Set value to 0 if relocating conflicts.
|
||||||
|
Call sparc_fixup_plt for R_SPARC_JMP_SLOT.
|
||||||
|
* sysdeps/sparc/sparc64/dl-machine.h (VALIDX): Define.
|
||||||
|
(sparc64_fixup_plt): Fix a typo.
|
||||||
|
(elf_machine_rela): Set value to 0 if relocating conflicts.
|
||||||
|
Handle R_SPARC_JMP_SLOT relocs when relocating conflicts.
|
||||||
|
(elf_machine_runtime_setup): Reinitialize .plt for prelinked
|
||||||
|
libraries where prelinking info cannot be used.
|
||||||
|
* sysdeps/sh/bits/link.h: New file.
|
||||||
|
* sysdeps/sh/dl-machine.h (elf_machine_runtime_setup): Save original
|
||||||
|
content of .got[1].
|
||||||
|
(elf_machine_lazy_rel): Reinitialize R_SH_JMP_SLOT address instead
|
||||||
|
of adjusting it if prelinked and prelinking cannot be used.
|
||||||
|
* sysdeps/s390/s390-32/bits/link.h: New file.
|
||||||
|
* sysdeps/s390/s390-32/dl-machine.h (elf_machine_runtime_setup):
|
||||||
|
Save original content of .got[1].
|
||||||
|
(elf_machine_lazy_rel): Reinitialize R_390_JMP_SLOT address instead
|
||||||
|
of adjusting it if prelinked and prelinking cannot be used.
|
||||||
|
* sysdeps/s390/s390-64/bits/link.h: New file.
|
||||||
|
* sysdeps/s390/s390-64/dl-machine.h (elf_machine_runtime_setup):
|
||||||
|
Save original content of .got[1].
|
||||||
|
(elf_machine_lazy_rel): Reinitialize R_390_JMP_SLOT address instead
|
||||||
|
of adjusting it if prelinked and prelinking cannot be used.
|
||||||
|
* sysdeps/x86_64/bits/link.h: New file.
|
||||||
|
* sysdeps/x86_64/dl-machine.h (elf_machine_runtime_setup):
|
||||||
|
Save original content of .got[1].
|
||||||
|
(elf_machine_lazy_rel): Reinitialize R_X86_64_JMP_SLOT address instead
|
||||||
|
of adjusting it if prelinked and prelinking cannot be used.
|
||||||
|
|
||||||
2001-12-11 Ulrich Drepper <drepper@redhat.com>
|
2001-12-11 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/ptsname.c (__ptsname_r): Use sizeof
|
* sysdeps/unix/sysv/linux/ptsname.c (__ptsname_r): Use sizeof
|
||||||
|
|
36
elf/Makefile
36
elf/Makefile
|
@ -29,7 +29,7 @@ routines = $(dl-routines) dl-open dl-close dl-support dl-iteratephdr \
|
||||||
# profiled libraries.
|
# profiled libraries.
|
||||||
dl-routines = $(addprefix dl-,load cache lookup object reloc deps \
|
dl-routines = $(addprefix dl-,load cache lookup object reloc deps \
|
||||||
runtime error init fini debug misc \
|
runtime error init fini debug misc \
|
||||||
version profile)
|
version profile conflict)
|
||||||
all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
|
all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
|
||||||
# But they are absent from the shared libc, because that code is in ld.so.
|
# But they are absent from the shared libc, because that code is in ld.so.
|
||||||
elide-routines.os = $(all-dl-routines) dl-support enbl-secure \
|
elide-routines.os = $(all-dl-routines) dl-support enbl-secure \
|
||||||
|
@ -154,30 +154,16 @@ $(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os)
|
||||||
$(objpfx)librtld.os: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a
|
$(objpfx)librtld.os: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a
|
||||||
$(reloc-link) '-Wl,-(' $^ -lgcc '-Wl,-)'
|
$(reloc-link) '-Wl,-(' $^ -lgcc '-Wl,-)'
|
||||||
|
|
||||||
# Do we need a linker script?
|
$(objpfx)ld.so: $(objpfx)librtld.os $(ld-map)
|
||||||
rtld-ldscript-in := $(firstword $(wildcard $(+sysdep_dirs:%=%/rtld-ldscript.in)))
|
$(LINK.o) -nostdlib -nostartfiles -shared \
|
||||||
|
$(LDFLAGS-rtld) -Wl,--verbose 2>&1 | \
|
||||||
ifneq (,$(rtld-ldscript-in))
|
sed -e '/^=========/,/^=========/!d;/^=========/d' \
|
||||||
rtld-ldscript = $(objpfx)rtld-ldscript
|
-e 's/\. = 0 + SIZEOF_HEADERS;/& _begin = . - SIZEOF_HEADERS;/' \
|
||||||
generated += rtld-ldscript
|
> $@.lds; \
|
||||||
|
$(LINK.o) -nostdlib -nostartfiles -shared -o $@ $(LDFLAGS-rtld) \
|
||||||
LDFLAGS-rtld = -T $(rtld-ldscript)
|
$(filter-out $(map-file),$^) $(load-map-file) \
|
||||||
before-compile += $(rtld-ldscript)
|
-Wl,-soname=$(rtld-installed-name) -T $@.lds; \
|
||||||
|
rm -f $@.lds
|
||||||
rtld-parms = $(wildcard $(+sysdep_dirs:%=%/rtld-parms))
|
|
||||||
include $(rtld-parms)
|
|
||||||
|
|
||||||
$(rtld-ldscript): $(rtld-ldscript-in) $(rtld-parms)
|
|
||||||
sed -e 's#@@rtld-oformat@@#$(rtld-oformat)#' \
|
|
||||||
-e 's#@@rtld-arch@@#$(rtld-arch)#' \
|
|
||||||
-e 's#@@rtld-entry@@#$(rtld-entry)#' \
|
|
||||||
-e 's#@@rtld-base@@#$(rtld-base)#' $< >$@
|
|
||||||
endif
|
|
||||||
|
|
||||||
$(objpfx)ld.so: $(objpfx)librtld.os $(rtld-ldscript) $(ld-map)
|
|
||||||
$(LINK.o) -nostdlib -nostartfiles -shared -o $@ $(LDFLAGS-rtld) \
|
|
||||||
$(filter-out $(rtld-ldscript) $(map-file),$^) \
|
|
||||||
$(load-map-file) -Wl,-soname=$(rtld-installed-name)
|
|
||||||
|
|
||||||
# interp.c exists just to get this string into the libraries.
|
# interp.c exists just to get this string into the libraries.
|
||||||
CFLAGS-interp.c = -D'RUNTIME_LINKER="$(slibdir)/$(rtld-installed-name)"'
|
CFLAGS-interp.c = -D'RUNTIME_LINKER="$(slibdir)/$(rtld-installed-name)"'
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
/* Resolve conflicts against already prelinked libraries.
|
||||||
|
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 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
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||||
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ldsodefs.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "dynamic-link.h"
|
||||||
|
|
||||||
|
extern unsigned long int _dl_num_cache_relocations; /* in dl-lookup.c */
|
||||||
|
|
||||||
|
void
|
||||||
|
_dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
|
||||||
|
ElfW(Rela) *conflictend)
|
||||||
|
{
|
||||||
|
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_RELOC, 0))
|
||||||
|
_dl_printf ("\nconflict processing: %s\n",
|
||||||
|
l->l_name[0] ? l->l_name : _dl_argv[0]);
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Do the conflict relocation of the object and library GOT and other
|
||||||
|
data. */
|
||||||
|
|
||||||
|
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||||
|
#define RESOLVE_MAP(ref, version, flags) (*ref = NULL, 0)
|
||||||
|
#define RESOLVE(ref, version, flags) (*ref = NULL, 0)
|
||||||
|
#define RESOLVE_CONFLICT_FIND_MAP(map, r_offset) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
while (resolve_conflict_map->l_map_end < (r_offset) \
|
||||||
|
|| resolve_conflict_map->l_map_start > (r_offset)) \
|
||||||
|
resolve_conflict_map \
|
||||||
|
= resolve_conflict_map->l_next; \
|
||||||
|
(map) = resolve_conflict_map; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
struct link_map *resolve_conflict_map = _dl_loaded;
|
||||||
|
|
||||||
|
#include "dynamic-link.h"
|
||||||
|
|
||||||
|
_dl_num_cache_relocations += conflictend - conflict;
|
||||||
|
|
||||||
|
for (; conflict < conflictend; ++conflict)
|
||||||
|
elf_machine_rela (l, conflict, NULL, NULL, (void *) conflict->r_offset);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,7 @@
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <libintl.h>
|
#include <libintl.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -70,6 +71,21 @@ openaux (void *a)
|
||||||
args->trace_mode, 0);
|
args->trace_mode, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ptrdiff_t
|
||||||
|
internal_function
|
||||||
|
_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
|
/* We use a very special kind of list to track the path
|
||||||
|
@ -491,6 +507,51 @@ _dl_map_object_deps (struct link_map *map,
|
||||||
runp->map->l_reserved = 0;
|
runp->map->l_reserved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__builtin_expect(_dl_debug_mask & DL_DEBUG_PRELINK, 0) != 0
|
||||||
|
&& map == _dl_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 (map->l_initfini, l);
|
||||||
|
assert (cnt <= nlist);
|
||||||
|
for (j = 0; j < cnt; j++)
|
||||||
|
map->l_initfini[j]->l_reserved = 0;
|
||||||
|
|
||||||
|
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, map->l_initfini,
|
||||||
|
cnt * sizeof (struct link_map *));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Maybe we can remove some relocation dependencies now. */
|
/* Maybe we can remove some relocation dependencies now. */
|
||||||
assert (map->l_searchlist.r_list[0] == map);
|
assert (map->l_searchlist.r_list[0] == map);
|
||||||
for (i = 0; i < map->l_reldepsact; ++i)
|
for (i = 0; i < map->l_reldepsact; ++i)
|
||||||
|
|
|
@ -1782,7 +1782,8 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
|
||||||
|
|
||||||
if (__builtin_expect (fd, 0) == -1)
|
if (__builtin_expect (fd, 0) == -1)
|
||||||
{
|
{
|
||||||
if (trace_mode)
|
if (trace_mode
|
||||||
|
&& __builtin_expect (_dl_debug_mask & DL_DEBUG_PRELINK, 0) == 0)
|
||||||
{
|
{
|
||||||
/* We haven't found an appropriate library. But since we
|
/* We haven't found an appropriate library. But since we
|
||||||
are only interested in the list of libraries this isn't
|
are only interested in the list of libraries this isn't
|
||||||
|
|
229
elf/dl-lookup.c
229
elf/dl-lookup.c
|
@ -194,6 +194,12 @@ _dl_do_lookup_versioned (const char *undef_name, unsigned long int hash,
|
||||||
const struct r_found_version *const version,
|
const struct r_found_version *const version,
|
||||||
struct link_map *skip, int type_class);
|
struct link_map *skip, int type_class);
|
||||||
|
|
||||||
|
static void
|
||||||
|
internal_function
|
||||||
|
_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
|
||||||
|
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
|
||||||
|
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
|
/* Search loaded objects' symbol tables for a definition of the symbol
|
||||||
UNDEF_NAME. */
|
UNDEF_NAME. */
|
||||||
|
@ -204,7 +210,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
|
||||||
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
|
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
|
||||||
int type_class, int explicit)
|
int type_class, int explicit)
|
||||||
{
|
{
|
||||||
unsigned long int hash = _dl_elf_hash (undef_name);
|
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||||
struct sym_val current_value = { NULL, NULL };
|
struct sym_val current_value = { NULL, NULL };
|
||||||
struct r_scope_elem **scope;
|
struct r_scope_elem **scope;
|
||||||
int protected;
|
int protected;
|
||||||
|
@ -241,7 +247,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
|
||||||
if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
|
if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
|
||||||
/* We could find no value for a strong reference. */
|
/* We could find no value for a strong reference. */
|
||||||
/* XXX We cannot translate the messages. */
|
/* XXX We cannot translate the messages. */
|
||||||
_dl_signal_cerror (0, (reference_name && reference_name[0]
|
_dl_signal_cerror (0, (reference_name[0]
|
||||||
? reference_name
|
? reference_name
|
||||||
: (_dl_argv[0] ?: "<main program>")),
|
: (_dl_argv[0] ?: "<main program>")),
|
||||||
N_("relocation error"),
|
N_("relocation error"),
|
||||||
|
@ -251,25 +257,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
|
||||||
}
|
}
|
||||||
|
|
||||||
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
||||||
|
if (__builtin_expect (protected != 0, 0))
|
||||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
|
|
||||||
{
|
|
||||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
|
||||||
|
|
||||||
_dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
|
|
||||||
(reference_name && reference_name[0]
|
|
||||||
? reference_name : (_dl_argv[0] ?: "<main program>")),
|
|
||||||
current_value.m->l_name[0]
|
|
||||||
? current_value.m->l_name : _dl_argv[0],
|
|
||||||
protected ? "protected" : "normal", undef_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__builtin_expect (protected == 0, 1))
|
|
||||||
{
|
|
||||||
*ref = current_value.s;
|
|
||||||
return LOOKUP_VALUE (current_value.m);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* It is very tricky. We need to figure out what value to
|
/* It is very tricky. We need to figure out what value to
|
||||||
return for the protected symbol */
|
return for the protected symbol */
|
||||||
|
@ -280,14 +268,20 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
|
||||||
0, NULL, ELF_RTYPE_CLASS_PLT))
|
0, NULL, ELF_RTYPE_CLASS_PLT))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
if (protected_value.s != NULL && protected_value.m != undef_map)
|
||||||
{
|
{
|
||||||
*ref = current_value.s;
|
current_value.s = *ref;
|
||||||
return LOOKUP_VALUE (current_value.m);
|
current_value.m = undef_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LOOKUP_VALUE (undef_map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__builtin_expect (_dl_debug_mask
|
||||||
|
& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
|
||||||
|
_dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
|
||||||
|
¤t_value, NULL, type_class, protected);
|
||||||
|
|
||||||
|
*ref = current_value.s;
|
||||||
|
return LOOKUP_VALUE (current_value.m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -303,7 +297,6 @@ _dl_lookup_symbol_skip (const char *undef_name,
|
||||||
struct r_scope_elem *symbol_scope[],
|
struct r_scope_elem *symbol_scope[],
|
||||||
struct link_map *skip_map)
|
struct link_map *skip_map)
|
||||||
{
|
{
|
||||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
|
||||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||||
struct sym_val current_value = { NULL, NULL };
|
struct sym_val current_value = { NULL, NULL };
|
||||||
struct r_scope_elem **scope;
|
struct r_scope_elem **scope;
|
||||||
|
@ -332,20 +325,7 @@ _dl_lookup_symbol_skip (const char *undef_name,
|
||||||
|
|
||||||
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
||||||
|
|
||||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
|
if (__builtin_expect (protected != 0, 0))
|
||||||
_dl_debug_printf ("binding file %s to %s: %s symbol `%s'\n",
|
|
||||||
(reference_name && reference_name[0]
|
|
||||||
? reference_name : (_dl_argv[0] ?: "<main program>")),
|
|
||||||
current_value.m->l_name[0]
|
|
||||||
? current_value.m->l_name : _dl_argv[0],
|
|
||||||
protected ? "protected" : "normal", undef_name);
|
|
||||||
|
|
||||||
if (__builtin_expect (protected == 0, 1))
|
|
||||||
{
|
|
||||||
*ref = current_value.s;
|
|
||||||
return LOOKUP_VALUE (current_value.m);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* It is very tricky. We need to figure out what value to
|
/* It is very tricky. We need to figure out what value to
|
||||||
return for the protected symbol. */
|
return for the protected symbol. */
|
||||||
|
@ -359,14 +339,20 @@ _dl_lookup_symbol_skip (const char *undef_name,
|
||||||
0, skip_map, ELF_RTYPE_CLASS_PLT))
|
0, skip_map, ELF_RTYPE_CLASS_PLT))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
if (protected_value.s != NULL && protected_value.m != undef_map)
|
||||||
{
|
{
|
||||||
*ref = current_value.s;
|
current_value.s = *ref;
|
||||||
return LOOKUP_VALUE (current_value.m);
|
current_value.m = undef_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LOOKUP_VALUE (undef_map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__builtin_expect (_dl_debug_mask
|
||||||
|
& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
|
||||||
|
_dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
|
||||||
|
¤t_value, NULL, 0, protected);
|
||||||
|
|
||||||
|
*ref = current_value.s;
|
||||||
|
return LOOKUP_VALUE (current_value.m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -383,7 +369,7 @@ _dl_lookup_versioned_symbol (const char *undef_name,
|
||||||
const struct r_found_version *version,
|
const struct r_found_version *version,
|
||||||
int type_class, int explicit)
|
int type_class, int explicit)
|
||||||
{
|
{
|
||||||
unsigned long int hash = _dl_elf_hash (undef_name);
|
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||||
struct sym_val current_value = { NULL, NULL };
|
struct sym_val current_value = { NULL, NULL };
|
||||||
struct r_scope_elem **scope;
|
struct r_scope_elem **scope;
|
||||||
int protected;
|
int protected;
|
||||||
|
@ -423,7 +409,7 @@ _dl_lookup_versioned_symbol (const char *undef_name,
|
||||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||||
|
|
||||||
/* XXX We cannot translate the message. */
|
/* XXX We cannot translate the message. */
|
||||||
_dl_signal_cerror (0, (reference_name && reference_name[0]
|
_dl_signal_cerror (0, (reference_name[0]
|
||||||
? reference_name
|
? reference_name
|
||||||
: (_dl_argv[0] ?: "<main program>")),
|
: (_dl_argv[0] ?: "<main program>")),
|
||||||
N_("relocation error"),
|
N_("relocation error"),
|
||||||
|
@ -447,7 +433,7 @@ _dl_lookup_versioned_symbol (const char *undef_name,
|
||||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||||
|
|
||||||
/* XXX We cannot translate the message. */
|
/* XXX We cannot translate the message. */
|
||||||
_dl_signal_cerror (0, (reference_name && reference_name[0]
|
_dl_signal_cerror (0, (reference_name[0]
|
||||||
? reference_name
|
? reference_name
|
||||||
: (_dl_argv[0] ?: "<main program>")), NULL,
|
: (_dl_argv[0] ?: "<main program>")), NULL,
|
||||||
make_string (undefined_msg, undef_name,
|
make_string (undefined_msg, undef_name,
|
||||||
|
@ -460,25 +446,7 @@ _dl_lookup_versioned_symbol (const char *undef_name,
|
||||||
|
|
||||||
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
||||||
|
|
||||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
|
if (__builtin_expect (protected != 0, 0))
|
||||||
{
|
|
||||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
|
||||||
|
|
||||||
_dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
|
|
||||||
(reference_name && reference_name[0]
|
|
||||||
? reference_name : (_dl_argv[0] ?: "<main program>")),
|
|
||||||
current_value.m->l_name[0]
|
|
||||||
? current_value.m->l_name : _dl_argv[0],
|
|
||||||
protected ? "protected" : "normal",
|
|
||||||
undef_name, version->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__builtin_expect (protected == 0, 1))
|
|
||||||
{
|
|
||||||
*ref = current_value.s;
|
|
||||||
return LOOKUP_VALUE (current_value.m);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* It is very tricky. We need to figure out what value to
|
/* It is very tricky. We need to figure out what value to
|
||||||
return for the protected symbol */
|
return for the protected symbol */
|
||||||
|
@ -490,14 +458,20 @@ _dl_lookup_versioned_symbol (const char *undef_name,
|
||||||
ELF_RTYPE_CLASS_PLT))
|
ELF_RTYPE_CLASS_PLT))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
if (protected_value.s != NULL && protected_value.m != undef_map)
|
||||||
{
|
{
|
||||||
*ref = current_value.s;
|
current_value.s = *ref;
|
||||||
return LOOKUP_VALUE (current_value.m);
|
current_value.m = undef_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LOOKUP_VALUE (undef_map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__builtin_expect (_dl_debug_mask
|
||||||
|
& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
|
||||||
|
_dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
|
||||||
|
¤t_value, version, type_class, protected);
|
||||||
|
|
||||||
|
*ref = current_value.s;
|
||||||
|
return LOOKUP_VALUE (current_value.m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -512,7 +486,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
|
||||||
const struct r_found_version *version,
|
const struct r_found_version *version,
|
||||||
struct link_map *skip_map)
|
struct link_map *skip_map)
|
||||||
{
|
{
|
||||||
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
const char *reference_name = undef_map->l_name;
|
||||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||||
struct sym_val current_value = { NULL, NULL };
|
struct sym_val current_value = { NULL, NULL };
|
||||||
struct r_scope_elem **scope;
|
struct r_scope_elem **scope;
|
||||||
|
@ -543,7 +517,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
|
||||||
__mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
|
__mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
|
||||||
undef_name, len + 1);
|
undef_name, len + 1);
|
||||||
/* XXX We cannot translate the messages. */
|
/* XXX We cannot translate the messages. */
|
||||||
_dl_signal_cerror (0, (reference_name && reference_name[0]
|
_dl_signal_cerror (0, (reference_name[0]
|
||||||
? reference_name
|
? reference_name
|
||||||
: (_dl_argv[0] ?: "<main program>")),
|
: (_dl_argv[0] ?: "<main program>")),
|
||||||
NULL, buf);
|
NULL, buf);
|
||||||
|
@ -554,21 +528,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
|
||||||
|
|
||||||
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
|
||||||
|
|
||||||
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 0))
|
if (__builtin_expect (protected != 0, 0))
|
||||||
_dl_debug_printf ("binding file %s to %s: %s symbol `%s' [%s]\n",
|
|
||||||
(reference_name && reference_name[0]
|
|
||||||
? reference_name : (_dl_argv[0] ?: "<main program>")),
|
|
||||||
current_value.m->l_name[0]
|
|
||||||
? current_value.m->l_name : _dl_argv[0],
|
|
||||||
protected ? "protected" : "normal",
|
|
||||||
undef_name, version->name);
|
|
||||||
|
|
||||||
if (__builtin_expect (protected == 0, 1))
|
|
||||||
{
|
|
||||||
*ref = current_value.s;
|
|
||||||
return LOOKUP_VALUE (current_value.m);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* It is very tricky. We need to figure out what value to
|
/* It is very tricky. We need to figure out what value to
|
||||||
return for the protected symbol */
|
return for the protected symbol */
|
||||||
|
@ -584,14 +544,20 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
|
||||||
skip_map, ELF_RTYPE_CLASS_PLT))
|
skip_map, ELF_RTYPE_CLASS_PLT))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (protected_value.s == NULL || protected_value.m == undef_map)
|
if (protected_value.s != NULL && protected_value.m != undef_map)
|
||||||
{
|
{
|
||||||
*ref = current_value.s;
|
current_value.s = *ref;
|
||||||
return LOOKUP_VALUE (current_value.m);
|
current_value.m = undef_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LOOKUP_VALUE (undef_map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__builtin_expect (_dl_debug_mask
|
||||||
|
& (DL_DEBUG_BINDINGS|DL_DEBUG_PRELINK), 0))
|
||||||
|
_dl_debug_bindings (undef_name, undef_map, ref, symbol_scope,
|
||||||
|
¤t_value, version, 0, protected);
|
||||||
|
|
||||||
|
*ref = current_value.s;
|
||||||
|
return LOOKUP_VALUE (current_value.m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -615,6 +581,79 @@ _dl_setup_hash (struct link_map *map)
|
||||||
map->l_chain = hash;
|
map->l_chain = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
internal_function
|
||||||
|
_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
|
||||||
|
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
|
||||||
|
struct sym_val *value, const struct r_found_version *version,
|
||||||
|
int type_class, int protected)
|
||||||
|
{
|
||||||
|
const char *reference_name = undef_map->l_name;
|
||||||
|
|
||||||
|
if (_dl_debug_mask & DL_DEBUG_BINDINGS)
|
||||||
|
{
|
||||||
|
_dl_debug_printf ("binding file %s to %s: %s symbol `%s'",
|
||||||
|
(reference_name[0]
|
||||||
|
? reference_name : (_dl_argv[0] ?: "<main program>")),
|
||||||
|
value->m->l_name[0] ? value->m->l_name : _dl_argv[0],
|
||||||
|
protected ? "protected" : "normal",
|
||||||
|
undef_name);
|
||||||
|
if (version)
|
||||||
|
_dl_debug_printf_c (" [%s]\n", version->name);
|
||||||
|
else
|
||||||
|
_dl_debug_printf_c ("\n");
|
||||||
|
}
|
||||||
|
#ifdef SHARED
|
||||||
|
if (_dl_debug_mask & DL_DEBUG_PRELINK)
|
||||||
|
{
|
||||||
|
int conflict = 0;
|
||||||
|
struct sym_val val = { NULL, NULL };
|
||||||
|
|
||||||
|
if ((_dl_trace_prelink_map == NULL
|
||||||
|
|| _dl_trace_prelink_map == _dl_loaded)
|
||||||
|
&& undef_map != _dl_loaded)
|
||||||
|
{
|
||||||
|
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||||
|
|
||||||
|
if (version == 0)
|
||||||
|
_dl_do_lookup (undef_name, hash, *ref, &val,
|
||||||
|
undef_map->l_local_scope[0], 0, NULL, type_class);
|
||||||
|
else
|
||||||
|
_dl_do_lookup_versioned (undef_name, hash, *ref, &val,
|
||||||
|
undef_map->l_local_scope[0], 0, version,
|
||||||
|
NULL, type_class);
|
||||||
|
|
||||||
|
if (val.s != value->s || val.m != value->m)
|
||||||
|
conflict = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conflict
|
||||||
|
|| _dl_trace_prelink_map == undef_map
|
||||||
|
|| _dl_trace_prelink_map == NULL)
|
||||||
|
{
|
||||||
|
_dl_printf ("%s 0x%0*Zx 0x%0*Zx -> 0x%0*Zx 0x%0*Zx ",
|
||||||
|
conflict ? "conflict" : "lookup",
|
||||||
|
(int) sizeof (ElfW(Addr)) * 2, undef_map->l_map_start,
|
||||||
|
(int) sizeof (ElfW(Addr)) * 2,
|
||||||
|
((ElfW(Addr)) *ref) - undef_map->l_map_start,
|
||||||
|
(int) sizeof (ElfW(Addr)) * 2,
|
||||||
|
(ElfW(Addr)) (value->s ? value->m->l_map_start : 0),
|
||||||
|
(int) sizeof (ElfW(Addr)) * 2,
|
||||||
|
(ElfW(Addr)) (value->s ? value->s->st_value : 0));
|
||||||
|
|
||||||
|
if (conflict)
|
||||||
|
_dl_printf ("x 0x%0*Zx 0x%0*Zx ",
|
||||||
|
(int) sizeof (ElfW(Addr)) * 2,
|
||||||
|
(ElfW(Addr)) (val.s ? val.m->l_map_start : 0),
|
||||||
|
(int) sizeof (ElfW(Addr)) * 2,
|
||||||
|
(ElfW(Addr)) (val.s ? val.s->st_value : 0));
|
||||||
|
|
||||||
|
_dl_printf ("/%x %s\n", type_class, undef_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* These are here so that we only inline do_lookup{,_versioned} in the common
|
/* These are here so that we only inline do_lookup{,_versioned} in the common
|
||||||
case, not everywhere. */
|
case, not everywhere. */
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -23,7 +23,8 @@
|
||||||
#include <ldsodefs.h>
|
#include <ldsodefs.h>
|
||||||
#include "dynamic-link.h"
|
#include "dynamic-link.h"
|
||||||
|
|
||||||
#if !defined ELF_MACHINE_NO_RELA || ELF_MACHINE_NO_REL
|
#if (!defined ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
|
||||||
|
|| ELF_MACHINE_NO_REL
|
||||||
# define PLTREL ElfW(Rela)
|
# define PLTREL ElfW(Rela)
|
||||||
#else
|
#else
|
||||||
# define PLTREL ElfW(Rel)
|
# define PLTREL ElfW(Rel)
|
||||||
|
|
11
elf/do-rel.h
11
elf/do-rel.h
|
@ -33,6 +33,10 @@
|
||||||
#ifndef VERSYMIDX
|
#ifndef VERSYMIDX
|
||||||
# define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
|
# define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef VALIDX
|
||||||
|
# define VALIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
|
||||||
|
+ DT_EXTRANUM + DT_VALTAGIDX (tag))
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Perform the relocations in MAP on the running program image as specified
|
/* Perform the relocations in MAP on the running program image as specified
|
||||||
by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT
|
by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT
|
||||||
|
@ -48,7 +52,7 @@ elf_dynamic_do_rel (struct link_map *map,
|
||||||
const ElfW(Rel) *end = (const void *) (reladdr + relsize);
|
const ElfW(Rel) *end = (const void *) (reladdr + relsize);
|
||||||
ElfW(Addr) l_addr = map->l_addr;
|
ElfW(Addr) l_addr = map->l_addr;
|
||||||
|
|
||||||
#ifndef RTLD_BOOTSTRAP
|
#if (!defined DO_RELA || !defined ELF_MACHINE_PLT_REL) && !defined RTLD_BOOTSTRAP
|
||||||
/* We never bind lazily during ld.so bootstrap. Unfortunately gcc is
|
/* We never bind lazily during ld.so bootstrap. Unfortunately gcc is
|
||||||
not clever enough to see through all the function calls to realize
|
not clever enough to see through all the function calls to realize
|
||||||
that. */
|
that. */
|
||||||
|
@ -81,8 +85,11 @@ elf_dynamic_do_rel (struct link_map *map,
|
||||||
/* Rela platforms get the offset from r_addend and this must
|
/* Rela platforms get the offset from r_addend and this must
|
||||||
be copied in the relocation address. Therefore we can skip
|
be copied in the relocation address. Therefore we can skip
|
||||||
the relative relocations only if this is for rel
|
the relative relocations only if this is for rel
|
||||||
relocations. */
|
relocations... */
|
||||||
if (l_addr != 0)
|
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
|
||||||
#endif
|
#endif
|
||||||
for (; relative < r; ++relative)
|
for (; relative < r; ++relative)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Inline functions for dynamic linking.
|
/* Inline functions for dynamic linking.
|
||||||
Copyright (C) 1995,96,97,98,99,2000 Free Software Foundation, Inc.
|
Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
@ -58,31 +58,39 @@ elf_get_dynamic_info (struct link_map *l)
|
||||||
else if ((Elf32_Word) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
|
else if ((Elf32_Word) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
|
||||||
info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
|
info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
|
||||||
+ DT_VERSIONTAGNUM] = dyn;
|
+ DT_VERSIONTAGNUM] = dyn;
|
||||||
|
else if ((Elf32_Word) DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
|
||||||
|
info[DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
|
||||||
|
+ DT_VERSIONTAGNUM + DT_EXTRANUM] = dyn;
|
||||||
|
else if ((Elf32_Word) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
|
||||||
|
info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
|
||||||
|
+ DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn;
|
||||||
else
|
else
|
||||||
assert (! "bad dynamic tag");
|
assert (! "bad dynamic tag");
|
||||||
++dyn;
|
++dyn;
|
||||||
}
|
}
|
||||||
#ifndef DL_RO_DYN_SECTION
|
#ifndef DL_RO_DYN_SECTION
|
||||||
if (info[DT_PLTGOT] != NULL)
|
/* Don't adjust .dynamic unnecessarily. */
|
||||||
info[DT_PLTGOT]->d_un.d_ptr += l_addr;
|
if (l_addr)
|
||||||
if (info[DT_STRTAB] != NULL)
|
|
||||||
info[DT_STRTAB]->d_un.d_ptr += l_addr;
|
|
||||||
if (info[DT_SYMTAB] != NULL)
|
|
||||||
info[DT_SYMTAB]->d_un.d_ptr += l_addr;
|
|
||||||
# if ! ELF_MACHINE_NO_RELA
|
|
||||||
if (info[DT_RELA] != NULL)
|
|
||||||
{
|
{
|
||||||
assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
|
if (info[DT_PLTGOT] != NULL)
|
||||||
info[DT_RELA]->d_un.d_ptr += l_addr;
|
info[DT_PLTGOT]->d_un.d_ptr += l_addr;
|
||||||
}
|
if (info[DT_STRTAB] != NULL)
|
||||||
|
info[DT_STRTAB]->d_un.d_ptr += l_addr;
|
||||||
|
if (info[DT_SYMTAB] != NULL)
|
||||||
|
info[DT_SYMTAB]->d_un.d_ptr += l_addr;
|
||||||
|
# if ! ELF_MACHINE_NO_RELA
|
||||||
|
if (info[DT_RELA] != NULL)
|
||||||
|
info[DT_RELA]->d_un.d_ptr += l_addr;
|
||||||
# endif
|
# endif
|
||||||
# if ! ELF_MACHINE_NO_REL
|
# if ! ELF_MACHINE_NO_REL
|
||||||
if (info[DT_REL] != NULL)
|
if (info[DT_REL] != NULL)
|
||||||
{
|
info[DT_REL]->d_un.d_ptr += l_addr;
|
||||||
assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
|
|
||||||
info[DT_REL]->d_un.d_ptr += l_addr;
|
|
||||||
}
|
|
||||||
# endif
|
# endif
|
||||||
|
if (info[DT_JMPREL] != NULL)
|
||||||
|
info[DT_JMPREL]->d_un.d_ptr += l_addr;
|
||||||
|
if (info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||||
|
info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr += l_addr;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (info[DT_PLTREL] != NULL)
|
if (info[DT_PLTREL] != NULL)
|
||||||
{
|
{
|
||||||
|
@ -95,12 +103,14 @@ elf_get_dynamic_info (struct link_map *l)
|
||||||
|| info[DT_PLTREL]->d_un.d_val == DT_RELA);
|
|| info[DT_PLTREL]->d_un.d_val == DT_RELA);
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
#ifndef DL_RO_DYN_SECTION
|
# if ! ELF_MACHINE_NO_RELA
|
||||||
if (info[DT_JMPREL] != NULL)
|
if (info[DT_RELA] != NULL)
|
||||||
info[DT_JMPREL]->d_un.d_ptr += l_addr;
|
assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
|
||||||
if (info[VERSYMIDX (DT_VERSYM)] != NULL)
|
# endif
|
||||||
info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr += l_addr;
|
# if ! ELF_MACHINE_NO_REL
|
||||||
#endif
|
if (info[DT_REL] != NULL)
|
||||||
|
assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
|
||||||
|
# endif
|
||||||
if (info[DT_FLAGS] != NULL)
|
if (info[DT_FLAGS] != NULL)
|
||||||
{
|
{
|
||||||
/* Flags are used. Translate to the old form where available.
|
/* Flags are used. Translate to the old form where available.
|
||||||
|
@ -177,8 +187,8 @@ elf_get_dynamic_info (struct link_map *l)
|
||||||
\
|
\
|
||||||
if ((map)->l_info[DT_##RELOC]) \
|
if ((map)->l_info[DT_##RELOC]) \
|
||||||
{ \
|
{ \
|
||||||
ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
|
ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
|
||||||
ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
|
ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
|
||||||
} \
|
} \
|
||||||
if ((map)->l_info[DT_PLTREL] \
|
if ((map)->l_info[DT_PLTREL] \
|
||||||
&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
|
&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
|
||||||
|
|
|
@ -676,6 +676,8 @@ typedef struct
|
||||||
#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
|
#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
|
||||||
#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
|
#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
|
||||||
#define DT_VALRNGHI 0x6ffffdff
|
#define DT_VALRNGHI 0x6ffffdff
|
||||||
|
#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */
|
||||||
|
#define DT_VALNUM 12
|
||||||
|
|
||||||
/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
|
/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
|
||||||
Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
|
Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
|
||||||
|
@ -692,6 +694,8 @@ typedef struct
|
||||||
#define DT_MOVETAB 0x6ffffefe /* Move table. */
|
#define DT_MOVETAB 0x6ffffefe /* Move table. */
|
||||||
#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */
|
#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */
|
||||||
#define DT_ADDRRNGHI 0x6ffffeff
|
#define DT_ADDRRNGHI 0x6ffffeff
|
||||||
|
#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */
|
||||||
|
#define DT_ADDRNUM 10
|
||||||
|
|
||||||
/* The versioning entry types. The next are defined as part of the
|
/* The versioning entry types. The next are defined as part of the
|
||||||
GNU extension. */
|
GNU extension. */
|
||||||
|
|
167
elf/rtld.c
167
elf/rtld.c
|
@ -67,6 +67,8 @@ struct r_search_path *_dl_search_paths;
|
||||||
const char *_dl_profile;
|
const char *_dl_profile;
|
||||||
const char *_dl_profile_output;
|
const char *_dl_profile_output;
|
||||||
struct link_map *_dl_profile_map;
|
struct link_map *_dl_profile_map;
|
||||||
|
const char *_dl_trace_prelink;
|
||||||
|
struct link_map *_dl_trace_prelink_map;
|
||||||
int _dl_lazy = 1;
|
int _dl_lazy = 1;
|
||||||
/* XXX I know about at least one case where we depend on the old weak
|
/* XXX I know about at least one case where we depend on the old weak
|
||||||
behavior (it has to do with librt). Until we get DSO groups implemented
|
behavior (it has to do with librt). Until we get DSO groups implemented
|
||||||
|
@ -183,10 +185,14 @@ _dl_start (void *arg)
|
||||||
ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info);
|
ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Relocate ourselves so we can do normal function calls and
|
if (bootstrap_map.l_addr || ! bootstrap_map.l_info[VALIDX(DT_GNU_PRELINKED)])
|
||||||
data access using the global offset table. */
|
{
|
||||||
|
/* Relocate ourselves so we can do normal function calls and
|
||||||
|
data access using the global offset table. */
|
||||||
|
|
||||||
|
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0);
|
|
||||||
/* Please note that we don't allow profiling of this object and
|
/* Please note that we don't allow profiling of this object and
|
||||||
therefore need not test whether we have to allocate the array
|
therefore need not test whether we have to allocate the array
|
||||||
for the relocation results (as done in dl-reloc.c). */
|
for the relocation results (as done in dl-reloc.c). */
|
||||||
|
@ -209,6 +215,15 @@ _dl_start (void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef VALIDX
|
||||||
|
# define VALIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
|
||||||
|
+ DT_EXTRANUM + DT_VALTAGIDX (tag))
|
||||||
|
#endif
|
||||||
|
#ifndef ADDRIDX
|
||||||
|
# define ADDRIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
|
||||||
|
+ DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag))
|
||||||
|
#endif
|
||||||
|
|
||||||
static ElfW(Addr)
|
static ElfW(Addr)
|
||||||
_dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
_dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
||||||
hp_timing_t start_time)
|
hp_timing_t start_time)
|
||||||
|
@ -218,6 +233,7 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
||||||
way to do this so we use this trick. gcc never inlines functions
|
way to do this so we use this trick. gcc never inlines functions
|
||||||
which use `alloca'. */
|
which use `alloca'. */
|
||||||
ElfW(Addr) *start_addr = alloca (sizeof (ElfW(Addr)));
|
ElfW(Addr) *start_addr = alloca (sizeof (ElfW(Addr)));
|
||||||
|
extern char _begin[], _end[];
|
||||||
|
|
||||||
if (HP_TIMING_AVAIL)
|
if (HP_TIMING_AVAIL)
|
||||||
{
|
{
|
||||||
|
@ -237,10 +253,8 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
|
||||||
sizeof _dl_rtld_map.l_info);
|
sizeof _dl_rtld_map.l_info);
|
||||||
_dl_setup_hash (&_dl_rtld_map);
|
_dl_setup_hash (&_dl_rtld_map);
|
||||||
_dl_rtld_map.l_mach = bootstrap_map_p->l_mach;
|
_dl_rtld_map.l_mach = bootstrap_map_p->l_mach;
|
||||||
|
_dl_rtld_map.l_map_start = (ElfW(Addr)) _begin;
|
||||||
/* Don't bother trying to work out how ld.so is mapped in memory. */
|
_dl_rtld_map.l_map_end = (ElfW(Addr)) _end;
|
||||||
_dl_rtld_map.l_map_start = ~0;
|
|
||||||
_dl_rtld_map.l_map_end = ~0;
|
|
||||||
|
|
||||||
/* Call the OS-dependent function to set up life so we can do things like
|
/* Call the OS-dependent function to set up life so we can do things like
|
||||||
file access. It will call `dl_main' (below) to do all the real work
|
file access. It will call `dl_main' (below) to do all the real work
|
||||||
|
@ -383,6 +397,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||||
char *file;
|
char *file;
|
||||||
int has_interp = 0;
|
int has_interp = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
int prelinked = 0;
|
||||||
int rtld_is_main = 0;
|
int rtld_is_main = 0;
|
||||||
#ifndef HP_TIMING_NONAVAIL
|
#ifndef HP_TIMING_NONAVAIL
|
||||||
hp_timing_t start;
|
hp_timing_t start;
|
||||||
|
@ -885,13 +900,42 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||||
{
|
{
|
||||||
struct link_map *l;
|
struct link_map *l;
|
||||||
|
|
||||||
for (l = _dl_loaded->l_next; l; l = l->l_next)
|
if (_dl_debug_mask & DL_DEBUG_PRELINK)
|
||||||
if (l->l_faked)
|
{
|
||||||
/* The library was not found. */
|
struct r_scope_elem *scope = &_dl_loaded->l_searchlist;
|
||||||
_dl_printf ("\t%s => not found\n", l->l_libname->name);
|
|
||||||
else
|
for (i = 0; i < scope->r_nlist; i++)
|
||||||
_dl_printf ("\t%s => %s (0x%0*Zx)\n", l->l_libname->name,
|
{
|
||||||
l->l_name, (int) sizeof l->l_addr * 2, l->l_addr);
|
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 (_dl_trace_prelink, l))
|
||||||
|
_dl_trace_prelink_map = l;
|
||||||
|
_dl_printf ("\t%s => %s (0x%0*Zx, 0x%0*Zx)\n",
|
||||||
|
l->l_libname->name[0] ? l->l_libname->name
|
||||||
|
: _dl_argv[0] ?: "<main program>",
|
||||||
|
l->l_name[0] ? l->l_name
|
||||||
|
: _dl_argv[0] ?: "<main program>",
|
||||||
|
(int) sizeof l->l_map_start * 2,
|
||||||
|
l->l_map_start,
|
||||||
|
(int) sizeof l->l_addr * 2,
|
||||||
|
l->l_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (l = _dl_loaded->l_next; l; l = l->l_next)
|
||||||
|
if (l->l_faked)
|
||||||
|
/* The library was not found. */
|
||||||
|
_dl_printf ("\t%s => not found\n", l->l_libname->name);
|
||||||
|
else
|
||||||
|
_dl_printf ("\t%s => %s (0x%0*Zx)\n", l->l_libname->name,
|
||||||
|
l->l_name, (int) sizeof l->l_map_start * 2,
|
||||||
|
l->l_map_start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__builtin_expect (mode, trace) != trace)
|
if (__builtin_expect (mode, trace) != trace)
|
||||||
|
@ -936,6 +980,10 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||||
}
|
}
|
||||||
l = l->l_prev;
|
l = l->l_prev;
|
||||||
} while (l);
|
} while (l);
|
||||||
|
|
||||||
|
if ((_dl_debug_mask & DL_DEBUG_PRELINK)
|
||||||
|
&& _dl_rtld_map.l_opencount > 1)
|
||||||
|
_dl_relocate_object (&_dl_rtld_map, _dl_loaded->l_scope, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED))
|
#define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED))
|
||||||
|
@ -1014,6 +1062,84 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||||
_exit (0);
|
_exit (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_dl_loaded->l_info [ADDRIDX (DT_GNU_LIBLIST)]
|
||||||
|
&& ! __builtin_expect (_dl_profile != NULL, 0))
|
||||||
|
{
|
||||||
|
ElfW(Lib) *liblist, *liblistend;
|
||||||
|
struct link_map **r_list, **r_listend, *l;
|
||||||
|
const char *strtab = (const void *)
|
||||||
|
D_PTR (_dl_loaded, l_info[DT_STRTAB]);
|
||||||
|
|
||||||
|
assert (_dl_loaded->l_info [VALIDX (DT_GNU_LIBLISTSZ)] != NULL);
|
||||||
|
liblist = (ElfW(Lib) *)
|
||||||
|
_dl_loaded->l_info [ADDRIDX (DT_GNU_LIBLIST)]->d_un.d_ptr;
|
||||||
|
liblistend = (ElfW(Lib) *)
|
||||||
|
((char *) liblist
|
||||||
|
+ _dl_loaded->l_info [VALIDX (DT_GNU_LIBLISTSZ)]->d_un.d_val);
|
||||||
|
r_list = _dl_loaded->l_searchlist.r_list;
|
||||||
|
r_listend = r_list + _dl_loaded->l_searchlist.r_nlist;
|
||||||
|
|
||||||
|
for (; r_list < r_listend && liblist < liblistend; r_list++)
|
||||||
|
{
|
||||||
|
l = *r_list;
|
||||||
|
|
||||||
|
if (l == _dl_loaded)
|
||||||
|
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 = 1;
|
||||||
|
|
||||||
|
if (__builtin_expect (_dl_debug_mask & DL_DEBUG_LIBS, 0))
|
||||||
|
_dl_printf ("\nprelink checking: %s\n", prelinked ? "ok" : "failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prelinked)
|
||||||
|
{
|
||||||
|
if (_dl_loaded->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL)
|
||||||
|
{
|
||||||
|
ElfW(Rela) *conflict, *conflictend;
|
||||||
|
#ifndef HP_TIMING_NONAVAIL
|
||||||
|
hp_timing_t start;
|
||||||
|
hp_timing_t stop;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HP_TIMING_NOW (start);
|
||||||
|
assert (_dl_loaded->l_info [VALIDX (DT_GNU_CONFLICTSZ)] != NULL);
|
||||||
|
conflict = (ElfW(Rela) *)
|
||||||
|
_dl_loaded->l_info [ADDRIDX (DT_GNU_CONFLICT)]->d_un.d_ptr;
|
||||||
|
conflictend = (ElfW(Rela) *)
|
||||||
|
((char *) conflict
|
||||||
|
+ _dl_loaded->l_info [VALIDX (DT_GNU_CONFLICTSZ)]->d_un.d_val);
|
||||||
|
_dl_resolve_conflicts (_dl_loaded, conflict, conflictend);
|
||||||
|
HP_TIMING_NOW (stop);
|
||||||
|
HP_TIMING_DIFF (relocate_time, start, stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
_dl_sysdep_start_cleanup ();
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* Now we have all the objects loaded. Relocate them all except for
|
/* 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
|
the dynamic linker itself. We do this in reverse order so that copy
|
||||||
|
@ -1094,7 +1220,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||||
_dl_main_searchlist = &_dl_loaded->l_searchlist;
|
_dl_main_searchlist = &_dl_loaded->l_searchlist;
|
||||||
_dl_global_scope[0] = &_dl_loaded->l_searchlist;
|
_dl_global_scope[0] = &_dl_loaded->l_searchlist;
|
||||||
|
|
||||||
/* Safe the information about the original global scope list since
|
/* Save the information about the original global scope list since
|
||||||
we need it in the memory handling later. */
|
we need it in the memory handling later. */
|
||||||
_dl_initial_searchlist = *_dl_main_searchlist;
|
_dl_initial_searchlist = *_dl_main_searchlist;
|
||||||
|
|
||||||
|
@ -1371,6 +1497,17 @@ process_envvars (enum mode *modep)
|
||||||
_dl_profile_output = &envline[15];
|
_dl_profile_output = &envline[15];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
/* The mode of the dynamic linker can be set. */
|
||||||
|
if (memcmp (envline, "TRACE_PRELINKING", 16) == 0)
|
||||||
|
{
|
||||||
|
mode = trace;
|
||||||
|
_dl_verbose = 1;
|
||||||
|
_dl_debug_mask |= DL_DEBUG_PRELINK;
|
||||||
|
_dl_trace_prelink = &envline[17];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 20:
|
case 20:
|
||||||
/* The mode of the dynamic linker can be set. */
|
/* The mode of the dynamic linker can be set. */
|
||||||
if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0)
|
if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0)
|
||||||
|
|
|
@ -132,14 +132,20 @@ struct link_map
|
||||||
/* Indexed pointers to dynamic section.
|
/* Indexed pointers to dynamic section.
|
||||||
[0,DT_NUM) are indexed by the processor-independent tags.
|
[0,DT_NUM) are indexed by the processor-independent tags.
|
||||||
[DT_NUM,DT_NUM+DT_THISPROCNUM) are indexed by the tag minus DT_LOPROC.
|
[DT_NUM,DT_NUM+DT_THISPROCNUM) are indexed by the tag minus DT_LOPROC.
|
||||||
[DT_NUM+DT_THISPROCNUM,DT_NUM+DT_THISPROCNUM+DT_EXTRANUM) are indexed
|
[DT_NUM+DT_THISPROCNUM,DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM) are
|
||||||
by DT_EXTRATAGIDX(tagvalue) and
|
indexed by DT_VERSIONTAGIDX(tagvalue).
|
||||||
[DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM,
|
[DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM,
|
||||||
DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM)
|
DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM) are indexed by
|
||||||
are indexed by DT_EXTRATAGIDX(tagvalue) (see <elf.h>). */
|
DT_EXTRATAGIDX(tagvalue).
|
||||||
|
[DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM,
|
||||||
|
DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM) are
|
||||||
|
indexed by DT_VALTAGIDX(tagvalue) and
|
||||||
|
[DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM,
|
||||||
|
DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM+DT_ADDRNUM)
|
||||||
|
are indexed by DT_ADDRTAGIDX(tagvalue), see <elf.h>. */
|
||||||
|
|
||||||
ElfW(Dyn) *l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM
|
ElfW(Dyn) *l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM
|
||||||
+ DT_EXTRANUM];
|
+ DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM];
|
||||||
const ElfW(Phdr) *l_phdr; /* Pointer to program header table in core. */
|
const ElfW(Phdr) *l_phdr; /* Pointer to program header table in core. */
|
||||||
ElfW(Addr) l_entry; /* Entry point location. */
|
ElfW(Addr) l_entry; /* Entry point location. */
|
||||||
ElfW(Half) l_phnum; /* Number of program header entries. */
|
ElfW(Half) l_phnum; /* Number of program header entries. */
|
||||||
|
|
|
@ -122,8 +122,30 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||||
*(Elf64_Addr *)(plt + 24) = (Elf64_Addr) l;
|
*(Elf64_Addr *)(plt + 24) = (Elf64_Addr) l;
|
||||||
|
|
||||||
/* If the first instruction of the plt entry is not
|
/* If the first instruction of the plt entry is not
|
||||||
"br $28, plt0", we cannot do lazy relocation. */
|
"br $28, plt0", we have to reinitialize .plt for lazy relocation. */
|
||||||
lazy = (*(unsigned int *)(plt + 32) == 0xc39ffff7);
|
if (*(unsigned int *)(plt + 32) != 0xc39ffff7)
|
||||||
|
{
|
||||||
|
unsigned int val = 0xc39ffff7;
|
||||||
|
unsigned int *slot, *end;
|
||||||
|
const Elf64_Rela *rela = D_PTR (l, l_info[DT_JMPREL]);
|
||||||
|
Elf64_Addr l_addr = l->l_addr;
|
||||||
|
|
||||||
|
/* br t12,.+4; ldq t12,12(t12); nop; jmp t12,(t12),.+4 */
|
||||||
|
*(unsigned long *)plt = 0xa77b000cc3600000;
|
||||||
|
*(unsigned long *)(plt + 8) = 0x6b7b000047ff041f;
|
||||||
|
slot = (unsigned int *)(plt + 32);
|
||||||
|
end = (unsigned int *)(plt + 32
|
||||||
|
+ l->l_info[DT_PLTRELSZ]->d_un.d_val / 2);
|
||||||
|
while (slot < end)
|
||||||
|
{
|
||||||
|
/* br at,.plt+0 */
|
||||||
|
*slot = val;
|
||||||
|
*(Elf64_Addr *) rela->r_offset = (Elf64_Addr) slot - l_addr;
|
||||||
|
val -= 3;
|
||||||
|
slot += 3;
|
||||||
|
++rela;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lazy;
|
return lazy;
|
||||||
|
@ -520,8 +542,23 @@ elf_machine_rela (struct link_map *map,
|
||||||
|
|
||||||
if (r_type == R_ALPHA_GLOB_DAT)
|
if (r_type == R_ALPHA_GLOB_DAT)
|
||||||
*reloc_addr = sym_value;
|
*reloc_addr = sym_value;
|
||||||
else if (r_type == R_ALPHA_JMP_SLOT)
|
#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, reloc, reloc_addr, sym_value);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
else if (r_type == R_ALPHA_JMP_SLOT)
|
||||||
elf_machine_fixup_plt (map, 0, reloc, reloc_addr, sym_value);
|
elf_machine_fixup_plt (map, 0, reloc, reloc_addr, sym_value);
|
||||||
|
#endif
|
||||||
#ifndef RTLD_BOOTSTRAP
|
#ifndef RTLD_BOOTSTRAP
|
||||||
else if (r_type == R_ALPHA_REFQUAD)
|
else if (r_type == R_ALPHA_REFQUAD)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
struct link_map_machine
|
||||||
|
{
|
||||||
|
Elf32_Addr plt; /* Address of .plt */
|
||||||
|
};
|
|
@ -92,6 +92,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||||
index into the .got section, load ip with &_GLOBAL_OFFSET_TABLE_[3],
|
index into the .got section, load ip with &_GLOBAL_OFFSET_TABLE_[3],
|
||||||
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
||||||
got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
||||||
|
/* If a library is prelinked but we have to relocate anyway,
|
||||||
|
we have to be able to undo the prelinking of .got.plt.
|
||||||
|
The prelinker saved us here address of .plt. */
|
||||||
|
if (got[1])
|
||||||
|
l->l_mach.plt = got[1] + l->l_addr;
|
||||||
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
|
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
|
||||||
|
|
||||||
/* The got[2] entry contains the address of a function which gets
|
/* The got[2] entry contains the address of a function which gets
|
||||||
|
@ -334,8 +339,9 @@ _dl_start_user:
|
||||||
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
|
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
|
||||||
#define ELF_MACHINE_JMP_SLOT R_ARM_JUMP_SLOT
|
#define ELF_MACHINE_JMP_SLOT R_ARM_JUMP_SLOT
|
||||||
|
|
||||||
/* The ARM never uses Elf32_Rela relocations. */
|
/* ARM never uses Elf32_Rela relocations for the dynamic linker.
|
||||||
#define ELF_MACHINE_NO_RELA 1
|
Prelinked libraries may use Elf32_Rela though. */
|
||||||
|
#define ELF_MACHINE_PLT_REL 1
|
||||||
|
|
||||||
/* We define an initialization functions. This is called very early in
|
/* We define an initialization functions. This is called very early in
|
||||||
_dl_sysdep_start. */
|
_dl_sysdep_start. */
|
||||||
|
@ -371,6 +377,12 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
|
||||||
|
|
||||||
#ifdef RESOLVE
|
#ifdef RESOLVE
|
||||||
|
|
||||||
|
/* ARM never uses Elf32_Rela relocations for the dynamic linker.
|
||||||
|
Prelinked libraries may use Elf32_Rela though. */
|
||||||
|
#ifdef RTLD_BOOTSTRAP
|
||||||
|
#define ELF_MACHINE_NO_RELA 1
|
||||||
|
#endif
|
||||||
|
|
||||||
extern char **_dl_argv;
|
extern char **_dl_argv;
|
||||||
|
|
||||||
/* Deal with an out-of-range PC24 reloc. */
|
/* Deal with an out-of-range PC24 reloc. */
|
||||||
|
@ -517,6 +529,64 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef RTLD_BOOTSTRAP
|
||||||
|
static inline void
|
||||||
|
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||||
|
const Elf32_Sym *sym, const struct r_found_version *version,
|
||||||
|
Elf32_Addr *const reloc_addr)
|
||||||
|
{
|
||||||
|
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
|
||||||
|
|
||||||
|
if (__builtin_expect (r_type == R_ARM_RELATIVE, 0))
|
||||||
|
*reloc_addr = map->l_addr + reloc->r_addend;
|
||||||
|
#ifndef RTLD_BOOTSTRAP
|
||||||
|
else if (__builtin_expect (r_type == R_ARM_NONE, 0))
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const Elf32_Sym *const refsym = sym;
|
||||||
|
Elf32_Addr value = RESOLVE (&sym, version, r_type);
|
||||||
|
if (sym)
|
||||||
|
value += sym->st_value;
|
||||||
|
|
||||||
|
switch (r_type)
|
||||||
|
{
|
||||||
|
case R_ARM_GLOB_DAT:
|
||||||
|
case R_ARM_JUMP_SLOT:
|
||||||
|
case R_ARM_ABS32:
|
||||||
|
*reloc_addr = value + reloc->r_addend;
|
||||||
|
break;
|
||||||
|
case R_ARM_PC24:
|
||||||
|
{
|
||||||
|
Elf32_Addr newvalue, topbits;
|
||||||
|
|
||||||
|
newvalue = value + reloc->r_addend - (Elf32_Addr)reloc_addr;
|
||||||
|
topbits = newvalue & 0xfe000000;
|
||||||
|
if (topbits != 0xfe000000 && topbits != 0x00000000)
|
||||||
|
{
|
||||||
|
newvalue = fix_bad_pc24(reloc_addr, value)
|
||||||
|
- (Elf32_Addr)reloc_addr + (addend << 2);
|
||||||
|
topbits = newvalue & 0xfe000000;
|
||||||
|
if (topbits != 0xfe000000 && topbits != 0x00000000)
|
||||||
|
{
|
||||||
|
_dl_signal_error (0, map->l_name, NULL,
|
||||||
|
"R_ARM_PC24 relocation out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newvalue >>= 2;
|
||||||
|
value = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
|
||||||
|
*reloc_addr = value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_dl_reloc_bad_type (map, r_type, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
|
elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
|
||||||
Elf32_Addr *const reloc_addr)
|
Elf32_Addr *const reloc_addr)
|
||||||
|
@ -524,6 +594,15 @@ elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
|
||||||
*reloc_addr += l_addr;
|
*reloc_addr += l_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef RTLD_BOOTSTRAP
|
||||||
|
static inline void
|
||||||
|
elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
|
||||||
|
Elf32_Addr *const reloc_addr)
|
||||||
|
{
|
||||||
|
*reloc_addr = l_addr + reloc->r_addend;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
elf_machine_lazy_rel (struct link_map *map,
|
elf_machine_lazy_rel (struct link_map *map,
|
||||||
Elf32_Addr l_addr, const Elf32_Rel *reloc)
|
Elf32_Addr l_addr, const Elf32_Rel *reloc)
|
||||||
|
@ -532,7 +611,12 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||||
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
|
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
|
||||||
/* Check for unexpected PLT reloc type. */
|
/* Check for unexpected PLT reloc type. */
|
||||||
if (__builtin_expect (r_type == R_ARM_JUMP_SLOT, 1))
|
if (__builtin_expect (r_type == R_ARM_JUMP_SLOT, 1))
|
||||||
*reloc_addr += l_addr;
|
{
|
||||||
|
if (__builtin_expect (map->l_mach.plt, 0) == 0)
|
||||||
|
*reloc_addr += l_addr;
|
||||||
|
else
|
||||||
|
*reloc_addr = map->l_mach.plt;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_dl_reloc_bad_type (map, r_type, 1);
|
_dl_reloc_bad_type (map, r_type, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,6 +207,8 @@ extern const char *_dl_profile;
|
||||||
extern struct link_map *_dl_profile_map;
|
extern struct link_map *_dl_profile_map;
|
||||||
/* Filename of the output file. */
|
/* Filename of the output file. */
|
||||||
extern const char *_dl_profile_output;
|
extern const char *_dl_profile_output;
|
||||||
|
/* Map of shared object to be prelink traced. */
|
||||||
|
extern struct link_map *_dl_trace_prelink_map;
|
||||||
|
|
||||||
/* If nonzero the appropriate debug information is printed. */
|
/* If nonzero the appropriate debug information is printed. */
|
||||||
extern int _dl_debug_mask;
|
extern int _dl_debug_mask;
|
||||||
|
@ -220,6 +222,7 @@ extern int _dl_debug_mask;
|
||||||
#define DL_DEBUG_STATISTICS (1 << 7)
|
#define DL_DEBUG_STATISTICS (1 << 7)
|
||||||
/* This one is used only internally. */
|
/* This one is used only internally. */
|
||||||
#define DL_DEBUG_HELP (1 << 8)
|
#define DL_DEBUG_HELP (1 << 8)
|
||||||
|
#define DL_DEBUG_PRELINK (1 << 9)
|
||||||
|
|
||||||
/* Expect cache ID. */
|
/* Expect cache ID. */
|
||||||
extern int _dl_correct_cache_id;
|
extern int _dl_correct_cache_id;
|
||||||
|
@ -435,6 +438,11 @@ extern void _dl_reloc_bad_type (struct link_map *map,
|
||||||
unsigned int type, int plt)
|
unsigned int type, int plt)
|
||||||
internal_function __attribute__ ((__noreturn__));
|
internal_function __attribute__ ((__noreturn__));
|
||||||
|
|
||||||
|
/* Resolve conflicts if prelinking. */
|
||||||
|
extern void _dl_resolve_conflicts (struct link_map *l,
|
||||||
|
ElfW(Rela) *conflict,
|
||||||
|
ElfW(Rela) *conflictend);
|
||||||
|
|
||||||
/* Check the version dependencies of all objects available through
|
/* Check the version dependencies of all objects available through
|
||||||
MAP. If VERBOSE print some more diagnostics. */
|
MAP. If VERBOSE print some more diagnostics. */
|
||||||
extern int _dl_check_all_versions (struct link_map *map, int verbose,
|
extern int _dl_check_all_versions (struct link_map *map, int verbose,
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
struct link_map_machine
|
||||||
|
{
|
||||||
|
Elf32_Addr plt; /* Address of .plt + 0x16 */
|
||||||
|
Elf32_Addr gotplt; /* Address of .got + 0x0c */
|
||||||
|
};
|
|
@ -87,6 +87,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||||
offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
|
offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
|
||||||
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
||||||
got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
||||||
|
/* If a library is prelinked but we have to relocate anyway,
|
||||||
|
we have to be able to undo the prelinking of .got.plt.
|
||||||
|
The prelinker saved us here address of .plt + 0x16. */
|
||||||
|
if (got[1])
|
||||||
|
{
|
||||||
|
l->l_mach.plt = got[1] + l->l_addr;
|
||||||
|
l->l_mach.gotplt = (Elf32_Addr) &got[3];
|
||||||
|
}
|
||||||
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
|
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
|
||||||
|
|
||||||
/* The got[2] entry contains the address of a function which gets
|
/* The got[2] entry contains the address of a function which gets
|
||||||
|
@ -258,8 +266,9 @@ _dl_start_user:\n\
|
||||||
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
|
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
|
||||||
#define ELF_MACHINE_JMP_SLOT R_386_JMP_SLOT
|
#define ELF_MACHINE_JMP_SLOT R_386_JMP_SLOT
|
||||||
|
|
||||||
/* The i386 never uses Elf32_Rela relocations. */
|
/* The i386 never uses Elf32_Rela relocations for the dynamic linker.
|
||||||
#define ELF_MACHINE_NO_RELA 1
|
Prelinked libraries may use Elf32_Rela though. */
|
||||||
|
#define ELF_MACHINE_PLT_REL 1
|
||||||
|
|
||||||
/* We define an initialization functions. This is called very early in
|
/* We define an initialization functions. This is called very early in
|
||||||
_dl_sysdep_start. */
|
_dl_sysdep_start. */
|
||||||
|
@ -295,6 +304,12 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
|
||||||
|
|
||||||
#ifdef RESOLVE
|
#ifdef RESOLVE
|
||||||
|
|
||||||
|
/* The i386 never uses Elf32_Rela relocations for the dynamic linker.
|
||||||
|
Prelinked libraries may use Elf32_Rela though. */
|
||||||
|
#ifdef RTLD_BOOTSTRAP
|
||||||
|
#define ELF_MACHINE_NO_RELA 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
|
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
|
||||||
MAP is the object containing the reloc. */
|
MAP is the object containing the reloc. */
|
||||||
|
|
||||||
|
@ -378,6 +393,41 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef RTLD_BOOTSTRAP
|
||||||
|
static inline void
|
||||||
|
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||||
|
const Elf32_Sym *sym, const struct r_found_version *version,
|
||||||
|
Elf32_Addr *const reloc_addr)
|
||||||
|
{
|
||||||
|
if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE)
|
||||||
|
*reloc_addr = map->l_addr + reloc->r_addend;
|
||||||
|
else if (ELF32_R_TYPE (reloc->r_info) != R_386_NONE)
|
||||||
|
{
|
||||||
|
/* const Elf32_Sym *const refsym = sym; */
|
||||||
|
Elf32_Addr value = RESOLVE (&sym, version, ELF32_R_TYPE (reloc->r_info));
|
||||||
|
if (sym)
|
||||||
|
value += sym->st_value;
|
||||||
|
|
||||||
|
switch (ELF32_R_TYPE (reloc->r_info))
|
||||||
|
{
|
||||||
|
case R_386_GLOB_DAT:
|
||||||
|
case R_386_JMP_SLOT:
|
||||||
|
case R_386_32:
|
||||||
|
*reloc_addr = value + reloc->r_addend;
|
||||||
|
break;
|
||||||
|
case R_386_PC32:
|
||||||
|
*reloc_addr = (value + reloc->r_addend - (Elf32_Addr) reloc_addr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* We add these checks in the version to relocate ld.so only
|
||||||
|
if we are still debugging. */
|
||||||
|
_dl_reloc_bad_type (map, ELFW(R_TYPE) (reloc->r_info), 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
|
elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
|
||||||
Elf32_Addr *const reloc_addr)
|
Elf32_Addr *const reloc_addr)
|
||||||
|
@ -386,6 +436,15 @@ elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
|
||||||
*reloc_addr += l_addr;
|
*reloc_addr += l_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef RTLD_BOOTSTRAP
|
||||||
|
static inline void
|
||||||
|
elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
|
||||||
|
Elf32_Addr *const reloc_addr)
|
||||||
|
{
|
||||||
|
*reloc_addr = l_addr + reloc->r_addend;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
elf_machine_lazy_rel (struct link_map *map,
|
elf_machine_lazy_rel (struct link_map *map,
|
||||||
Elf32_Addr l_addr, const Elf32_Rel *reloc)
|
Elf32_Addr l_addr, const Elf32_Rel *reloc)
|
||||||
|
@ -394,9 +453,26 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||||
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
|
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
|
||||||
/* Check for unexpected PLT reloc type. */
|
/* Check for unexpected PLT reloc type. */
|
||||||
if (__builtin_expect (r_type == R_386_JMP_SLOT, 1))
|
if (__builtin_expect (r_type == R_386_JMP_SLOT, 1))
|
||||||
*reloc_addr += l_addr;
|
{
|
||||||
|
if (__builtin_expect (map->l_mach.plt, 0) == 0)
|
||||||
|
*reloc_addr += l_addr;
|
||||||
|
else
|
||||||
|
*reloc_addr =
|
||||||
|
map->l_mach.plt
|
||||||
|
+ (((Elf32_Addr) reloc_addr) - map->l_mach.gotplt) * 4;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_dl_reloc_bad_type (map, r_type, 1);
|
_dl_reloc_bad_type (map, r_type, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef RTLD_BOOTSTRAP
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
elf_machine_lazy_rela (struct link_map *map,
|
||||||
|
Elf32_Addr l_addr, const Elf32_Rela *reloc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* RESOLVE */
|
#endif /* RESOLVE */
|
||||||
|
|
|
@ -347,6 +347,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||||
Elf32_Word loadbase, finaladdr;
|
Elf32_Word loadbase, finaladdr;
|
||||||
const int rinfo = ELF32_R_TYPE (reloc->r_info);
|
const int rinfo = ELF32_R_TYPE (reloc->r_info);
|
||||||
|
|
||||||
|
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||||
if (__builtin_expect (rinfo == R_PPC_NONE, 0))
|
if (__builtin_expect (rinfo == R_PPC_NONE, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -375,6 +376,11 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||||
finaladdr = (loadbase + (Elf32_Word) (char *) sym->st_value
|
finaladdr = (loadbase + (Elf32_Word) (char *) sym->st_value
|
||||||
+ reloc->r_addend);
|
+ reloc->r_addend);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
finaladdr = reloc->r_addend;
|
||||||
|
if (rinfo == R_PPC_JMP_SLOT)
|
||||||
|
RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* A small amount of code is duplicated here for speed. In libc,
|
/* A small amount of code is duplicated here for speed. In libc,
|
||||||
more than 90% of the relocs are R_PPC_RELATIVE; in the X11 shared
|
more than 90% of the relocs are R_PPC_RELATIVE; in the X11 shared
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
struct link_map_machine
|
||||||
|
{
|
||||||
|
Elf32_Addr plt; /* Address of .plt + 0x2c */
|
||||||
|
Elf32_Addr gotplt; /* Address of .got + 0x0c */
|
||||||
|
};
|
|
@ -92,6 +92,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||||
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
||||||
Elf32_Addr *got;
|
Elf32_Addr *got;
|
||||||
got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
||||||
|
/* If a library is prelinked but we have to relocate anyway,
|
||||||
|
we have to be able to undo the prelinking of .got.plt.
|
||||||
|
The prelinker saved us here address of .plt + 0x2c. */
|
||||||
|
if (got[1])
|
||||||
|
{
|
||||||
|
l->l_mach.plt = got[1] + l->l_addr;
|
||||||
|
l->l_mach.gotplt = (Elf32_Addr) &got[3];
|
||||||
|
}
|
||||||
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
|
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
|
||||||
|
|
||||||
/* The got[2] entry contains the address of a function which gets
|
/* The got[2] entry contains the address of a function which gets
|
||||||
|
@ -454,7 +462,14 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||||
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
|
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
|
||||||
/* Check for unexpected PLT reloc type. */
|
/* Check for unexpected PLT reloc type. */
|
||||||
if (__builtin_expect (r_type == R_390_JMP_SLOT, 1))
|
if (__builtin_expect (r_type == R_390_JMP_SLOT, 1))
|
||||||
*reloc_addr += l_addr;
|
{
|
||||||
|
if (__builtin_expect (map->l_mach.plt, 0) == 0)
|
||||||
|
*reloc_addr += l_addr;
|
||||||
|
else
|
||||||
|
*reloc_addr =
|
||||||
|
map->l_mach.plt
|
||||||
|
+ (((Elf32_Addr) reloc_addr) - map->l_mach.gotplt) * 8;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_dl_reloc_bad_type (map, r_type, 1);
|
_dl_reloc_bad_type (map, r_type, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
struct link_map_machine
|
||||||
|
{
|
||||||
|
Elf64_Addr plt; /* Address of .plt + 0x2e */
|
||||||
|
Elf64_Addr gotplt; /* Address of .got + 0x18 */
|
||||||
|
};
|
|
@ -85,6 +85,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||||
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
||||||
Elf64_Addr *got;
|
Elf64_Addr *got;
|
||||||
got = (Elf64_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
got = (Elf64_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
||||||
|
/* If a library is prelinked but we have to relocate anyway,
|
||||||
|
we have to be able to undo the prelinking of .got.plt.
|
||||||
|
The prelinker saved us here address of .plt + 0x2e. */
|
||||||
|
if (got[1])
|
||||||
|
{
|
||||||
|
l->l_mach.plt = got[1] + l->l_addr;
|
||||||
|
l->l_mach.gotplt = (Elf64_Addr) &got[3];
|
||||||
|
}
|
||||||
got[1] = (Elf64_Addr) l; /* Identify this shared object. */
|
got[1] = (Elf64_Addr) l; /* Identify this shared object. */
|
||||||
|
|
||||||
/* The got[2] entry contains the address of a function which gets
|
/* The got[2] entry contains the address of a function which gets
|
||||||
|
@ -434,7 +442,14 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||||
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
|
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
|
||||||
/* Check for unexpected PLT reloc type. */
|
/* Check for unexpected PLT reloc type. */
|
||||||
if (__builtin_expect (r_type == R_390_JMP_SLOT, 1))
|
if (__builtin_expect (r_type == R_390_JMP_SLOT, 1))
|
||||||
*reloc_addr += l_addr;
|
{
|
||||||
|
if (__builtin_expect (map->l_mach.plt, 0) == 0)
|
||||||
|
*reloc_addr += l_addr;
|
||||||
|
else
|
||||||
|
*reloc_addr =
|
||||||
|
map->l_mach.plt
|
||||||
|
+ (((Elf64_Addr) reloc_addr) - map->l_mach.gotplt) * 4;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_dl_reloc_bad_type (map, r_type, 1);
|
_dl_reloc_bad_type (map, r_type, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
struct link_map_machine
|
||||||
|
{
|
||||||
|
Elf32_Addr plt; /* Address of .plt + 36 */
|
||||||
|
Elf32_Addr gotplt; /* Address of .got + 0x0c */
|
||||||
|
};
|
|
@ -85,6 +85,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||||
offset into the .rela.plt section and _GLOBAL_OFFSET_TABLE_[1],
|
offset into the .rela.plt section and _GLOBAL_OFFSET_TABLE_[1],
|
||||||
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
||||||
got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
||||||
|
/* If a library is prelinked but we have to relocate anyway,
|
||||||
|
we have to be able to undo the prelinking of .got.plt.
|
||||||
|
The prelinker saved us here address of .plt + 36. */
|
||||||
|
if (got[1])
|
||||||
|
{
|
||||||
|
l->l_mach.plt = got[1] + l->l_addr;
|
||||||
|
l->l_mach.gotplt = (Elf32_Addr) &got[3];
|
||||||
|
}
|
||||||
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
|
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
|
||||||
|
|
||||||
/* The got[2] entry contains the address of a function which gets
|
/* The got[2] entry contains the address of a function which gets
|
||||||
|
@ -582,7 +590,14 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||||
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
|
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
|
||||||
/* Check for unexpected PLT reloc type. */
|
/* Check for unexpected PLT reloc type. */
|
||||||
if (ELF32_R_TYPE (reloc->r_info) == R_SH_JMP_SLOT)
|
if (ELF32_R_TYPE (reloc->r_info) == R_SH_JMP_SLOT)
|
||||||
*reloc_addr += l_addr;
|
{
|
||||||
|
if (__builtin_expect (map->l_mach.plt, 0) == 0)
|
||||||
|
*reloc_addr += l_addr;
|
||||||
|
else
|
||||||
|
*reloc_addr =
|
||||||
|
map->l_mach.plt
|
||||||
|
+ (((Elf32_Addr) reloc_addr) - map->l_mach.gotplt) * 7;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
|
_dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <ldsodefs.h>
|
#include <ldsodefs.h>
|
||||||
|
|
||||||
|
#ifndef VALIDX
|
||||||
|
# define VALIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
|
||||||
|
+ DT_EXTRANUM + DT_VALTAGIDX (tag))
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Some SPARC opcodes we need to use for self-modifying code. */
|
/* Some SPARC opcodes we need to use for self-modifying code. */
|
||||||
#define OPCODE_NOP 0x01000000 /* nop */
|
#define OPCODE_NOP 0x01000000 /* nop */
|
||||||
|
@ -30,6 +34,7 @@
|
||||||
#define OPCODE_SETHI_G1 0x03000000 /* sethi ?, %g1; add value>>10 */
|
#define OPCODE_SETHI_G1 0x03000000 /* sethi ?, %g1; add value>>10 */
|
||||||
#define OPCODE_JMP_G1 0x81c06000 /* jmp %g1+?; add lo 10 bits of value */
|
#define OPCODE_JMP_G1 0x81c06000 /* jmp %g1+?; add lo 10 bits of value */
|
||||||
#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */
|
#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */
|
||||||
|
#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */
|
||||||
|
|
||||||
/* Protect some broken versions of gcc from misinterpreting weak addresses. */
|
/* Protect some broken versions of gcc from misinterpreting weak addresses. */
|
||||||
#define WEAKADDR(x) ({ __typeof(x) *_px = &x; \
|
#define WEAKADDR(x) ({ __typeof(x) *_px = &x; \
|
||||||
|
@ -139,6 +144,37 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||||
plt[1] = OPCODE_CALL | ((rfunc - (Elf32_Addr) &plt[1]) >> 2);
|
plt[1] = OPCODE_CALL | ((rfunc - (Elf32_Addr) &plt[1]) >> 2);
|
||||||
plt[2] = OPCODE_NOP; /* Fill call delay slot. */
|
plt[2] = OPCODE_NOP; /* Fill call delay slot. */
|
||||||
plt[3] = (Elf32_Addr) l;
|
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. */
|
||||||
|
unsigned long *hwcap;
|
||||||
|
int do_flush;
|
||||||
|
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);
|
||||||
|
weak_extern (_dl_hwcap);
|
||||||
|
hwcap = WEAKADDR(_dl_hwcap);
|
||||||
|
do_flush = (!hwcap || (*hwcap & HWCAP_SPARC_FLUSH));
|
||||||
|
|
||||||
|
/* prelink must ensure there are no R_SPARC_NONE relocs left
|
||||||
|
in .rela.plt. */
|
||||||
|
while (rela < relaend)
|
||||||
|
{
|
||||||
|
*(unsigned int *) rela->r_offset
|
||||||
|
= OPCODE_SETHI_G1 | (rela->r_offset - (Elf32_Addr) plt);
|
||||||
|
*(unsigned int *) (rela->r_offset + 4)
|
||||||
|
= OPCODE_BA | ((((Elf32_Addr) plt
|
||||||
|
- rela->r_offset - 4) >> 2) & 0x3fffff);
|
||||||
|
if (do_flush)
|
||||||
|
{
|
||||||
|
__asm __volatile ("flush %0" : : "r"(rela->r_offset));
|
||||||
|
__asm __volatile ("flush %0+4" : : "r"(rela->r_offset));
|
||||||
|
}
|
||||||
|
++rela;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lazy;
|
return lazy;
|
||||||
|
@ -292,10 +328,10 @@ _dl_start_user:
|
||||||
.previous");
|
.previous");
|
||||||
|
|
||||||
static inline Elf32_Addr
|
static inline Elf32_Addr
|
||||||
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
sparc_fixup_plt (const Elf32_Rela *reloc, Elf32_Addr *reloc_addr,
|
||||||
const Elf32_Rela *reloc,
|
Elf32_Addr value, int t)
|
||||||
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
|
||||||
{
|
{
|
||||||
|
Elf32_Sword disp = value - (Elf32_Addr) reloc_addr;
|
||||||
#ifndef RTLD_BOOTSTRAP
|
#ifndef RTLD_BOOTSTRAP
|
||||||
/* Note that we don't mask the hwcap here, as the flush is essential to
|
/* Note that we don't mask the hwcap here, as the flush is essential to
|
||||||
functionality on those cpu's that implement it. */
|
functionality on those cpu's that implement it. */
|
||||||
|
@ -309,23 +345,44 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
ld.so will not execute corrupt PLT entry instructions. */
|
ld.so will not execute corrupt PLT entry instructions. */
|
||||||
const int do_flush = 1;
|
const int do_flush = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (0 && disp >= -0x800000 && disp < 0x800000)
|
||||||
|
{
|
||||||
|
/* Don't need to worry about thread safety. We're writing just one
|
||||||
|
instruction. */
|
||||||
|
|
||||||
/* For thread safety, write the instructions from the bottom and
|
reloc_addr[0] = OPCODE_BA | ((disp >> 2) & 0x3fffff);
|
||||||
flush before we overwrite the critical "b,a". This of course
|
if (do_flush)
|
||||||
need not be done during bootstrapping, since there are no threads.
|
__asm __volatile ("flush %0" : : "r"(reloc_addr));
|
||||||
But we also can't tell if we _can_ use flush, so don't. */
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* For thread safety, write the instructions from the bottom and
|
||||||
|
flush before we overwrite the critical "b,a". This of course
|
||||||
|
need not be done during bootstrapping, since there are no threads.
|
||||||
|
But we also can't tell if we _can_ use flush, so don't. */
|
||||||
|
|
||||||
reloc_addr[2] = OPCODE_JMP_G1 | (value & 0x3ff);
|
reloc_addr += t;
|
||||||
if (do_flush)
|
reloc_addr[1] = OPCODE_JMP_G1 | (value & 0x3ff);
|
||||||
__asm __volatile ("flush %0+8" : : "r"(reloc_addr));
|
if (do_flush)
|
||||||
|
__asm __volatile ("flush %0+4" : : "r"(reloc_addr));
|
||||||
|
|
||||||
reloc_addr[1] = OPCODE_SETHI_G1 | (value >> 10);
|
reloc_addr[0] = OPCODE_SETHI_G1 | (value >> 10);
|
||||||
if (do_flush)
|
if (do_flush)
|
||||||
__asm __volatile ("flush %0+4" : : "r"(reloc_addr));
|
__asm __volatile ("flush %0" : : "r"(reloc_addr));
|
||||||
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline Elf32_Addr
|
||||||
|
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
|
||||||
|
const Elf32_Rela *reloc,
|
||||||
|
Elf32_Addr *reloc_addr, Elf32_Addr value)
|
||||||
|
{
|
||||||
|
return sparc_fixup_plt (reloc, reloc_addr, value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the final value of a plt relocation. */
|
/* Return the final value of a plt relocation. */
|
||||||
static inline Elf32_Addr
|
static inline Elf32_Addr
|
||||||
elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
|
elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
|
||||||
|
@ -366,10 +423,11 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifndef RTLD_BOOTSTRAP
|
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
|
||||||
const Elf32_Sym *const refsym = sym;
|
const Elf32_Sym *const refsym = sym;
|
||||||
#endif
|
#endif
|
||||||
Elf32_Addr value;
|
Elf32_Addr value;
|
||||||
|
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||||
if (sym->st_shndx != SHN_UNDEF &&
|
if (sym->st_shndx != SHN_UNDEF &&
|
||||||
ELF32_ST_BIND (sym->st_info) == STB_LOCAL)
|
ELF32_ST_BIND (sym->st_info) == STB_LOCAL)
|
||||||
value = map->l_addr;
|
value = map->l_addr;
|
||||||
|
@ -379,11 +437,14 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||||
if (sym)
|
if (sym)
|
||||||
value += sym->st_value;
|
value += sym->st_value;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
value = 0;
|
||||||
|
#endif
|
||||||
value += reloc->r_addend; /* Assume copy relocs have zero addend. */
|
value += reloc->r_addend; /* Assume copy relocs have zero addend. */
|
||||||
|
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
{
|
{
|
||||||
#ifndef RTLD_BOOTSTRAP
|
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
|
||||||
case R_SPARC_COPY:
|
case R_SPARC_COPY:
|
||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
/* This can happen in trace mode if an object could not be
|
/* This can happen in trace mode if an object could not be
|
||||||
|
@ -410,7 +471,9 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||||
*reloc_addr = value;
|
*reloc_addr = value;
|
||||||
break;
|
break;
|
||||||
case R_SPARC_JMP_SLOT:
|
case R_SPARC_JMP_SLOT:
|
||||||
elf_machine_fixup_plt(map, 0, reloc, reloc_addr, value);
|
/* At this point we don't need to bother with thread safety,
|
||||||
|
so we can optimize the first instruction of .plt out. */
|
||||||
|
sparc_fixup_plt (reloc, reloc_addr, value, 0);
|
||||||
break;
|
break;
|
||||||
#ifndef RTLD_BOOTSTRAP
|
#ifndef RTLD_BOOTSTRAP
|
||||||
case R_SPARC_8:
|
case R_SPARC_8:
|
||||||
|
|
|
@ -24,6 +24,11 @@
|
||||||
#include <ldsodefs.h>
|
#include <ldsodefs.h>
|
||||||
#include <sysdep.h>
|
#include <sysdep.h>
|
||||||
|
|
||||||
|
#ifndef VALIDX
|
||||||
|
# define VALIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
|
||||||
|
+ DT_EXTRANUM + DT_VALTAGIDX (tag))
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ELF64_R_TYPE_ID(info) ((info) & 0xff)
|
#define ELF64_R_TYPE_ID(info) ((info) & 0xff)
|
||||||
#define ELF64_R_TYPE_DATA(info) ((info) >> 8)
|
#define ELF64_R_TYPE_DATA(info) ((info) >> 8)
|
||||||
|
|
||||||
|
@ -147,7 +152,7 @@ sparc64_fixup_plt (struct link_map *map, const Elf64_Rela *reloc,
|
||||||
insns[1] = 0x40000000 | (displacement >> 2);
|
insns[1] = 0x40000000 | (displacement >> 2);
|
||||||
__asm __volatile ("flush %0 + 4" : : "r" (insns));
|
__asm __volatile ("flush %0 + 4" : : "r" (insns));
|
||||||
|
|
||||||
insns[t] = 0x8210000f;
|
insns[0] = 0x8210000f;
|
||||||
__asm __volatile ("flush %0" : : "r" (insns));
|
__asm __volatile ("flush %0" : : "r" (insns));
|
||||||
}
|
}
|
||||||
/* Worst case, ho hum... */
|
/* Worst case, ho hum... */
|
||||||
|
@ -251,10 +256,11 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifndef RTLD_BOOTSTRAP
|
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
|
||||||
const Elf64_Sym *const refsym = sym;
|
const Elf64_Sym *const refsym = sym;
|
||||||
#endif
|
#endif
|
||||||
Elf64_Addr value;
|
Elf64_Addr value;
|
||||||
|
#ifndef RESOLVE_CONFLICT_FIND_MAP
|
||||||
if (sym->st_shndx != SHN_UNDEF &&
|
if (sym->st_shndx != SHN_UNDEF &&
|
||||||
ELF64_ST_BIND (sym->st_info) == STB_LOCAL)
|
ELF64_ST_BIND (sym->st_info) == STB_LOCAL)
|
||||||
value = map->l_addr;
|
value = map->l_addr;
|
||||||
|
@ -264,11 +270,14 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
|
||||||
if (sym)
|
if (sym)
|
||||||
value += sym->st_value;
|
value += sym->st_value;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
value = 0;
|
||||||
|
#endif
|
||||||
value += reloc->r_addend; /* Assume copy relocs have zero addend. */
|
value += reloc->r_addend; /* Assume copy relocs have zero addend. */
|
||||||
|
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
{
|
{
|
||||||
#ifndef RTLD_BOOTSTRAP
|
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
|
||||||
case R_SPARC_COPY:
|
case R_SPARC_COPY:
|
||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
/* This can happen in trace mode if an object could not be
|
/* This can happen in trace mode if an object could not be
|
||||||
|
@ -371,8 +380,18 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case R_SPARC_JMP_SLOT:
|
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,
|
sparc64_fixup_plt (map, reloc, reloc_addr, value,
|
||||||
reloc->r_addend, 0);
|
reloc->r_addend, 0);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
#ifndef RTLD_BOOTSTRAP
|
#ifndef RTLD_BOOTSTRAP
|
||||||
case R_SPARC_UA16:
|
case R_SPARC_UA16:
|
||||||
|
@ -536,6 +555,47 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||||
/* Now put the magic cookie at the beginning of .PLT2
|
/* Now put the magic cookie at the beginning of .PLT2
|
||||||
Entry .PLT3 is unused by this implementation. */
|
Entry .PLT3 is unused by this implementation. */
|
||||||
*((struct link_map **)(&plt[16 + 0])) = l;
|
*((struct link_map **)(&plt[16 + 0])) = 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 + 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
|
||||||
|
= (Elf64_Addr) plt
|
||||||
|
- (slot + ((rela->r_offset - ptr) / 8) * 24 + 4);
|
||||||
|
++rela;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(unsigned int *) rela->r_offset
|
||||||
|
= 0x03000000 | (rela->r_offset - (Elf64_Addr) plt);
|
||||||
|
*(unsigned int *) (rela->r_offset + 4)
|
||||||
|
= 0x30680000 | ((((Elf64_Addr) plt + 32
|
||||||
|
- rela->r_offset - 4) >> 2) & 0x7ffff);
|
||||||
|
__asm __volatile ("flush %0" : : "r" (rela->r_offset));
|
||||||
|
__asm __volatile ("flush %0+4" : : "r" (rela->r_offset));
|
||||||
|
++rela;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lazy;
|
return lazy;
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
struct link_map_machine
|
||||||
|
{
|
||||||
|
Elf64_Addr plt; /* Address of .plt + 0x16 */
|
||||||
|
Elf64_Addr gotplt; /* Address of .got + 0x18 */
|
||||||
|
};
|
|
@ -76,6 +76,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||||
offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
|
offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
|
||||||
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
|
||||||
got = (Elf64_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
got = (Elf64_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
|
||||||
|
/* If a library is prelinked but we have to relocate anyway,
|
||||||
|
we have to be able to undo the prelinking of .got.plt.
|
||||||
|
The prelinker saved us here address of .plt + 0x16. */
|
||||||
|
if (got[1])
|
||||||
|
{
|
||||||
|
l->l_mach.plt = got[1] + l->l_addr;
|
||||||
|
l->l_mach.gotplt = (Elf64_Addr) &got[3];
|
||||||
|
}
|
||||||
got[1] = (Elf64_Addr) l; /* Identify this shared object. */
|
got[1] = (Elf64_Addr) l; /* Identify this shared object. */
|
||||||
|
|
||||||
/* The got[2] entry contains the address of a function which gets
|
/* The got[2] entry contains the address of a function which gets
|
||||||
|
@ -409,7 +417,14 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||||
|
|
||||||
/* Check for unexpected PLT reloc type. */
|
/* Check for unexpected PLT reloc type. */
|
||||||
if (__builtin_expect (r_type == R_X86_64_JUMP_SLOT, 1))
|
if (__builtin_expect (r_type == R_X86_64_JUMP_SLOT, 1))
|
||||||
*reloc_addr += l_addr;
|
{
|
||||||
|
if (__builtin_expect (map->l_mach.plt, 0) == 0)
|
||||||
|
*reloc_addr += l_addr;
|
||||||
|
else
|
||||||
|
*reloc_addr =
|
||||||
|
map->l_mach.plt
|
||||||
|
+ (((Elf64_Addr) reloc_addr) - map->l_mach.gotplt) * 2;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_dl_reloc_bad_type (map, r_type, 1);
|
_dl_reloc_bad_type (map, r_type, 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue