This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Hi!
First of all, I don't want this for glibc 2.2.4.
What I'm looking for is:
a) whether something like this could be acceptable for glibc 2.3
(with l_machine_specific replaced with what David Mosberger suggested,
ie. architecture specific sub-structure of link_map)
Note that non-REL architectures will probably need far less sysdep
changes than IA-32 (well, aside from mips)
b) if my choice of new SHT_ constant and new DT_ constants is right, or
whether that should be coordinated with Sun somehow, or whether I should
choose constants far from the numbers used by Sun
c) whether you agree on:
the format of .gnu.conflict (ie. ElfW(Rela) with ELFW(R_SYM) zero)
the format of .gnu.liblist (ie. ElfW(Lib))
conversion of REL to RELA on REL arches if necessary
(on IA-32 this is if there are any R_386_32 or R_386_PC32 relocs)
the choice/usage of dynamic tags (DT_CHECKSUM, DT_GNU_PRELINKED
plus address/size pairs for .gnu.conflict and .gnu.liblist for binaries)
I believe the rest are just implementation details.
More details in http://sources.redhat.com/ml/binutils/2001-07/msg00057.html
I know you're very busy but I'd very appreciate your feedback (and feedback
from others too).
Thanks.
--- libc/elf/dl-deps.c.jj Mon Jun 25 10:33:47 2001
+++ libc/elf/dl-deps.c Mon Jun 25 10:50:33 2001
@@ -21,6 +21,7 @@
#include <dlfcn.h>
#include <errno.h>
#include <libintl.h>
+#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -70,6 +71,21 @@ openaux (void *a)
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; *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
@@ -488,6 +504,47 @@ out:
/* Now clear all the mark bits we set in the objects on the search list
to avoid duplicates, so the next call starts fresh. */
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 = 1; 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->l_local_scope[0]
+ && l->l_local_scope[0]->r_nlist != 0)
+ continue;
+
+ if (l->l_info[AUXTAG] || l->l_info[FILTERTAG])
+ {
+ /* FIXME: This code does not handle filters yet. */
+ _dl_signal_error (EINVAL, l->l_name,
+ 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,
+ 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 *));
+ }
}
/* Now determine the order in which the initialization has to happen. */
--- libc/elf/rtld.c.jj Wed May 23 09:21:41 2001
+++ libc/elf/rtld.c Mon Jun 25 10:50:33 2001
@@ -66,6 +66,8 @@ struct r_search_path *_dl_search_paths;
const char *_dl_profile;
const char *_dl_profile_output;
struct link_map *_dl_profile_map;
+const char *_dl_trace_prelink;
+struct link_map *_dl_trace_prelink_map;
int _dl_lazy = 1;
/* 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
@@ -137,6 +139,13 @@ RTLD_START
#error "sysdeps/MACHINE/dl-machine.h fails to define RTLD_START"
#endif
+#ifndef VALIDX
+# define VALIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+ + DT_EXTRANUM + DT_VALTAGIDX (tag))
+# define ADDRIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+ + DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag))
+#endif
+
static ElfW(Addr)
_dl_start (void *arg)
{
@@ -175,10 +184,14 @@ _dl_start (void *arg)
ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info);
#endif
- /* Relocate ourselves so we can do normal function calls and
- data access using the global offset table. */
+ if (bootstrap_map.l_addr || ! bootstrap_map.l_info[VALIDX(DT_GNU_PRELINKED)])
+ {
+ /* 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
therefore need not test whether we have to allocate the array
for the relocation results (as done in dl-reloc.c). */
@@ -374,6 +387,7 @@ dl_main (const ElfW(Phdr) *phdr,
char *file;
int has_interp = 0;
unsigned int i;
+ int prelinked = 0;
int rtld_is_main = 0;
#ifndef HP_TIMING_NONAVAIL
hp_timing_t start;
@@ -873,14 +887,81 @@ of this helper program; chances are you
else
{
struct link_map *l;
+ ElfW(Addr) l_addr;
+
+ /* Try to figure dynamic linker's real map start (which may be
+ different than _dl_rtld_map.l_addr).
+ Assuming no target has page size less than 1024 bytes
+ and .hash being the first real section. */
+ if (_dl_rtld_map.l_info[DT_HASH]
+ && (l_addr = _dl_rtld_map.l_addr
+ + (_dl_rtld_map.l_info[DT_HASH]->d_un.d_ptr
+ & ~(ElfW(Addr))1023)),
+ memcmp ((char *) l_addr, ELFMAG, SELFMAG) == 0)
+ {
+ ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *) l_addr;
+ ElfW(Phdr) *ph, *phdr =
+ (ElfW(Phdr) *)(l_addr + ehdr->e_phoff);
+ ElfW(Half) phnum = ehdr->e_phnum;
- 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_addr * 2, l->l_addr);
+ if (((ElfW(Addr)) &phdr[phnum]) - l_addr
+ <= (_dl_rtld_map.l_info[DT_HASH]->d_un.d_ptr & 1023))
+ {
+ _dl_rtld_map.l_map_end = 0;
+ for (ph = phdr; ph < &phdr[phnum]; ++ph)
+ if (ph->p_type == PT_LOAD)
+ {
+ ElfW(Addr) mapstart, allocend;
+ mapstart = _dl_rtld_map.l_addr
+ + (ph->p_vaddr & ~(ph->p_align - 1));
+ allocend = _dl_rtld_map.l_addr
+ + ph->p_vaddr + ph->p_memsz;
+ if (_dl_rtld_map.l_map_start > mapstart)
+ _dl_rtld_map.l_map_start = mapstart;
+ if (_dl_rtld_map.l_map_end < allocend)
+ _dl_rtld_map.l_map_end = allocend;
+ }
+ if (_dl_rtld_map.l_map_end == 0)
+ _dl_rtld_map.l_map_end = ~0;
+ }
+ }
+
+ if (_dl_debug_mask & DL_DEBUG_PRELINK)
+ {
+ struct r_scope_elem *scope = &_dl_loaded->l_searchlist;
+
+ for (i = 0; i < scope->r_nlist; i++)
+ {
+ l = scope->r_list [i];
+ if (l->l_faked)
+ {
+ _dl_printf ("\t%s => not found\n", l->l_libname->name);
+ continue;
+ }
+ if (_dl_name_match_p (_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)
@@ -925,6 +1006,10 @@ of this helper program; chances are you
}
l = l->l_prev;
} 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))
@@ -1003,6 +1088,84 @@ of this helper program; chances are you
_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
the dynamic linker itself. We do this in reverse order so that copy
@@ -1083,7 +1246,7 @@ of this helper program; chances are you
_dl_main_searchlist = &_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. */
_dl_initial_searchlist = *_dl_main_searchlist;
@@ -1394,6 +1557,17 @@ process_envvars (enum mode *modep)
_dl_profile_output = &envline[18];
if (*_dl_profile_output == '\0')
_dl_profile_output = "/var/tmp";
+ }
+ break;
+
+ case 16:
+ /* The mode of the dynamic linker can be set. */
+ if (memcmp (&envline[3], "TRACE_PRELINKING", 16) == 0)
+ {
+ mode = trace;
+ _dl_verbose = 1;
+ _dl_debug_mask |= DL_DEBUG_PRELINK;
+ _dl_trace_prelink = &envline[20];
}
break;
--- libc/elf/dynamic-link.h.jj Wed May 23 09:21:39 2001
+++ libc/elf/dynamic-link.h Mon Jun 25 10:50:33 2001
@@ -1,5 +1,5 @@
/* 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.
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)
info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
+ 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
assert (! "bad dynamic tag");
++dyn;
}
#ifndef DL_RO_DYN_SECTION
- if (info[DT_PLTGOT] != NULL)
- 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)
+ /* Don't adjust .dynamic unnecessarily. */
+ if (l_addr)
{
- assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
- info[DT_RELA]->d_un.d_ptr += l_addr;
- }
+ if (info[DT_PLTGOT] != NULL)
+ 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
# if ! ELF_MACHINE_NO_REL
- if (info[DT_REL] != NULL)
- {
- assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
- info[DT_REL]->d_un.d_ptr += l_addr;
- }
+ if (info[DT_REL] != NULL)
+ info[DT_REL]->d_un.d_ptr += l_addr;
# 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
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);
# endif
}
-#ifndef DL_RO_DYN_SECTION
- 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
+# if ! ELF_MACHINE_NO_RELA
+ if (info[DT_RELA] != NULL)
+ assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela)));
+# endif
+# if ! ELF_MACHINE_NO_REL
+ if (info[DT_REL] != NULL)
+ assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
+# endif
if (info[DT_FLAGS] != NULL)
{
/* 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]) \
{ \
- 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].start = D_PTR ((map), l_info[DT_##RELOC]); \
+ ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
} \
if ((map)->l_info[DT_PLTREL] \
&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
--- libc/elf/elf.h.jj Mon Jun 25 10:33:47 2001
+++ libc/elf/elf.h Mon Jun 25 10:50:33 2001
@@ -316,6 +316,7 @@ typedef struct
#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
#define SHT_NUM 19 /* Number of defined types. */
#define SHT_LOOS 0x60000000 /* Start OS-specific */
+#define SHT_GNU_LIBLIST 0x6ffffff1 /* Prelink library list */
#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
#define SHT_SUNW_move 0x6ffffffa
@@ -649,6 +650,9 @@ typedef struct
Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
approach. */
#define DT_VALRNGLO 0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */
#define DT_CHECKSUM 0x6ffffdf8
#define DT_PLTPADSZ 0x6ffffdf9
#define DT_MOVEENT 0x6ffffdfa
@@ -659,6 +663,8 @@ typedef struct
#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
#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
Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
@@ -666,8 +672,17 @@ typedef struct
If any adjustment is made to the ELF object after it has been
built these entries will need to be adjusted. */
#define DT_ADDRRNGLO 0x6ffffe00
-#define DT_SYMINFO 0x6ffffeff /* syminfo table */
+#define DT_GNU_CONFLICT 0x6ffffef6 /* Start of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef7 /* Library list */
+#define DT_CONFIG 0x6ffffefa /* Configuration info */
+#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing */
+#define DT_AUDIT 0x6ffffefc /* Object auditing */
+#define DT_PLTPAD 0x6ffffefd /* PLT padding */
+#define DT_MOVETAB 0x6ffffefe /* Move table */
+#define DT_SYMINFO 0x6ffffeff /* Syminfo table */
#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
GNU extension. */
--- libc/elf/dl-lookup.c.jj Wed May 23 09:21:38 2001
+++ libc/elf/dl-lookup.c Mon Jun 25 15:33:39 2001
@@ -193,6 +193,15 @@ _dl_do_lookup_versioned (const char *und
const struct r_found_version *const version,
struct link_map *skip, int noexec, int noplt);
+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 reloc_type, int protected);
+
+struct lookup_cache lookup_cache;
+
/* Search loaded objects' symbol tables for a definition of the symbol
UNDEF_NAME. */
@@ -202,7 +211,7 @@ _dl_lookup_symbol (const char *undef_nam
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
int reloc_type, int explicit)
{
- 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);
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
@@ -212,6 +221,17 @@ _dl_lookup_symbol (const char *undef_nam
++_dl_num_relocations;
+ /* First check if we can find it in the cache. */
+ if (__builtin_expect (*ref == lookup_cache.sym, 0)
+ && lookup_cache.map == undef_map
+ && lookup_cache.noexec == noexec
+ && lookup_cache.noplt == noplt
+ && lookup_cache.version == NULL)
+ {
+ *ref = lookup_cache.ret;
+ return lookup_cache.value;
+ }
+
/* Search the relevant loaded objects for a definition. */
for (scope = symbol_scope; *scope; ++scope)
if (do_lookup (undef_name, hash, *ref, ¤t_value, *scope, 0, NULL,
@@ -238,35 +258,29 @@ _dl_lookup_symbol (const char *undef_nam
break;
}
+ lookup_cache.sym = *ref;
+ lookup_cache.noexec = noexec;
+ lookup_cache.noplt = noplt;
+ lookup_cache.version = NULL;
+
if (__builtin_expect (current_value.s == NULL, 0))
{
if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
/* We could find no value for a strong reference. */
/* XXX We cannot translate the messages. */
- _dl_signal_cerror (0, (reference_name && reference_name[0]
+ _dl_signal_cerror (0, (reference_name[0]
? reference_name
: (_dl_argv[0] ?: "<main program>")),
make_string (undefined_msg, undef_name));
+ lookup_cache.ret = NULL;
+ lookup_cache.value = 0;
*ref = NULL;
return 0;
}
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
- if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 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
+ if (__builtin_expect (protected != 0, 0))
{
/* It is very tricky. We need to figure out what value to
return for the protected symbol */
@@ -277,14 +291,22 @@ _dl_lookup_symbol (const char *undef_nam
0, NULL, 0, 1))
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;
- return LOOKUP_VALUE (current_value.m);
+ current_value.s = *ref;
+ 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, reloc_type, protected);
+
+ lookup_cache.ret = current_value.s;
+ lookup_cache.value = LOOKUP_VALUE (current_value.m);
+ *ref = current_value.s;
+ return LOOKUP_VALUE (current_value.m);
}
@@ -300,7 +322,7 @@ _dl_lookup_symbol_skip (const char *unde
struct r_scope_elem *symbol_scope[],
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);
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
@@ -329,20 +351,7 @@ _dl_lookup_symbol_skip (const char *unde
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
- if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 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
+ if (__builtin_expect (protected != 0, 0))
{
/* It is very tricky. We need to figure out what value to
return for the protected symbol. */
@@ -356,14 +365,20 @@ _dl_lookup_symbol_skip (const char *unde
0, skip_map, 0, 1))
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;
- return LOOKUP_VALUE (current_value.m);
+ current_value.s = *ref;
+ 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);
}
@@ -380,7 +395,7 @@ _dl_lookup_versioned_symbol (const char
const struct r_found_version *version,
int reloc_type, int explicit)
{
- 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);
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
@@ -390,6 +405,17 @@ _dl_lookup_versioned_symbol (const char
++_dl_num_relocations;
+ /* First check if we can find it in the cache. */
+ if (__builtin_expect (*ref == lookup_cache.sym, 0)
+ && lookup_cache.map == undef_map
+ && lookup_cache.noexec == noexec
+ && lookup_cache.noplt == noplt
+ && lookup_cache.version == version)
+ {
+ *ref = lookup_cache.ret;
+ return lookup_cache.value;
+ }
+
/* Search the relevant loaded objects for a definition. */
for (scope = symbol_scope; *scope; ++scope)
{
@@ -424,7 +450,7 @@ _dl_lookup_versioned_symbol (const char
/* Oh, oh. The file named in the relocation entry does not
contain the needed symbol. */
/* XXX We cannot translate the message. */
- _dl_signal_cerror (0, (reference_name && reference_name[0]
+ _dl_signal_cerror (0, (reference_name[0]
? reference_name
: (_dl_argv[0] ?: "<main program>")),
make_string ("symbol ", undef_name, ", version ",
@@ -439,37 +465,30 @@ _dl_lookup_versioned_symbol (const char
}
}
+ lookup_cache.sym = *ref;
+ lookup_cache.noexec = noexec;
+ lookup_cache.noplt = noplt;
+ lookup_cache.version = version;
+
if (__builtin_expect (current_value.s == NULL, 0))
{
if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
/* We could find no value for a strong reference. */
/* XXX We cannot translate the message. */
- _dl_signal_cerror (0, (reference_name && reference_name[0]
+ _dl_signal_cerror (0, (reference_name[0]
? reference_name
: (_dl_argv[0] ?: "<main program>")),
make_string (undefined_msg, undef_name,
", version ", version->name ?: NULL));
+ lookup_cache.ret = NULL;
+ lookup_cache.value = 0;
*ref = NULL;
return 0;
}
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
- if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 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
+ if (__builtin_expect (protected != 0, 0))
{
/* It is very tricky. We need to figure out what value to
return for the protected symbol */
@@ -480,14 +499,22 @@ _dl_lookup_versioned_symbol (const char
*scope, 0, version, NULL, 0, 1))
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;
- return LOOKUP_VALUE (current_value.m);
+ current_value.s = *ref;
+ 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, reloc_type, protected);
+
+ lookup_cache.ret = current_value.s;
+ lookup_cache.value = LOOKUP_VALUE (current_value.m);
+ *ref = current_value.s;
+ return LOOKUP_VALUE (current_value.m);
}
@@ -502,7 +529,7 @@ _dl_lookup_versioned_symbol_skip (const
const struct r_found_version *version,
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);
struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope;
@@ -533,7 +560,7 @@ _dl_lookup_versioned_symbol_skip (const
__mempcpy (__mempcpy (buf, undefined_msg, sizeof undefined_msg - 1),
undef_name, len + 1);
/* XXX We cannot translate the messages. */
- _dl_signal_cerror (0, (reference_name && reference_name[0]
+ _dl_signal_cerror (0, (reference_name[0]
? reference_name
: (_dl_argv[0] ?: "<main program>")), buf);
}
@@ -543,21 +570,7 @@ _dl_lookup_versioned_symbol_skip (const
protected = *ref && ELFW(ST_VISIBILITY) ((*ref)->st_other) == STV_PROTECTED;
- if (__builtin_expect (_dl_debug_mask & DL_DEBUG_BINDINGS, 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
+ if (__builtin_expect (protected != 0, 0))
{
/* It is very tricky. We need to figure out what value to
return for the protected symbol */
@@ -573,14 +586,20 @@ _dl_lookup_versioned_symbol_skip (const
skip_map, 0, 1))
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;
- return LOOKUP_VALUE (current_value.m);
+ current_value.s = *ref;
+ 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);
}
@@ -602,6 +621,82 @@ _dl_setup_hash (struct link_map *map)
map->l_buckets = hash;
hash += map->l_nbuckets;
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 reloc_type, 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);
+ int noexec = elf_machine_lookup_noexec_p (reloc_type);
+ int noplt = elf_machine_lookup_noplt_p (reloc_type);
+
+ if (version == 0)
+ _dl_do_lookup (undef_name, hash, *ref, &val,
+ undef_map->l_local_scope[0], 0, NULL, noexec,
+ noplt);
+ else
+ _dl_do_lookup_versioned (undef_name, hash, *ref, &val,
+ undef_map->l_local_scope[0], 0, version,
+ NULL, noexec, noplt);
+
+ 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", reloc_type, undef_name);
+ }
+ }
+#endif
}
/* These are here so that we only inline do_lookup{,_versioned} in the common
--- libc/elf/do-rel.h.jj Wed May 23 09:21:39 2001
+++ libc/elf/do-rel.h Mon Jun 25 10:50:33 2001
@@ -43,6 +43,7 @@ elf_dynamic_do_rel (struct link_map *map
const ElfW(Rel) *r = (const void *) reladdr;
const ElfW(Rel) *end = (const void *) (reladdr + relsize);
+#if !defined DO_RELA || !defined ELF_MACHINE_PLT_REL
if (lazy)
{
/* Doing lazy PLT relocations; they need very little info. */
@@ -51,6 +52,7 @@ elf_dynamic_do_rel (struct link_map *map
elf_machine_lazy_rel (map, l_addr, r);
}
else
+#endif
{
const ElfW(Sym) *const symtab =
(const void *) D_PTR (map, l_info[DT_SYMTAB]);
--- libc/elf/dl-runtime.c.jj Wed May 23 09:21:38 2001
+++ libc/elf/dl-runtime.c Mon Jun 25 10:50:33 2001
@@ -23,7 +23,8 @@
#include <ldsodefs.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)
#else
# define PLTREL ElfW(Rel)
--- libc/elf/dl-conflict.c.jj Mon Jun 25 10:50:33 2001
+++ libc/elf/dl-conflict.c Mon Jun 25 21:02:45 2001
@@ -0,0 +1,55 @@
+/* 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_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)
+
+#include "dynamic-link.h"
+
+ _dl_num_relocations += conflictend - conflict;
+
+ for (; conflict < conflictend; ++conflict)
+ elf_machine_rela (l, conflict, NULL, NULL, (void *) conflict->r_offset);
+ }
+}
--- libc/elf/Makefile.jj Wed May 23 09:21:37 2001
+++ libc/elf/Makefile Mon Jun 25 10:50:33 2001
@@ -28,7 +28,7 @@ routines = $(dl-routines) dl-open dl-clo
# profiled libraries.
dl-routines = $(addprefix dl-,load cache lookup object reloc deps \
runtime error init fini debug misc \
- version profile)
+ version profile conflict)
all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
# 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
--- libc/elf/dl-reloc.c.jj Wed May 23 09:21:38 2001
+++ libc/elf/dl-reloc.c Mon Jun 25 20:48:01 2001
@@ -89,7 +89,13 @@ cannot make segment writable for relocat
: l->l_addr)
#include "dynamic-link.h"
+
+ /* Start symbol lookup caching for this object. */
+ lookup_cache.map = (_dl_debug_mask & DL_DEBUG_PRELINK) ? NULL : l;
+
ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling);
+
+ lookup_cache.map = NULL;
if (__builtin_expect (_dl_profile != NULL, 0))
{
--- libc/include/link.h.jj Wed May 23 09:21:43 2001
+++ libc/include/link.h Mon Jun 25 10:50:33 2001
@@ -1,6 +1,6 @@
/* Data structure for communication from the run-time dynamic linker for
loaded ELF shared objects.
- Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -130,14 +130,20 @@ struct link_map
/* Indexed pointers to dynamic section.
[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_THISPROCNUM,DT_NUM+DT_THISPROCNUM+DT_EXTRANUM) are indexed
- by DT_EXTRATAGIDX(tagvalue) and
+ [DT_NUM+DT_THISPROCNUM,DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM) are
+ indexed by DT_VERSIONTAGIDX(tagvalue).
[DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM,
- DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM)
- are indexed by DT_EXTRATAGIDX(tagvalue) (see <elf.h>). */
+ DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM) are indexed by
+ 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
- + DT_EXTRANUM];
+ + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM];
const ElfW(Phdr) *l_phdr; /* Pointer to program header table in core. */
ElfW(Addr) l_entry; /* Entry point location. */
ElfW(Half) l_phnum; /* Number of program header entries. */
@@ -228,6 +234,9 @@ struct link_map
/* Temporarily used in `dl_close'. */
unsigned int l_idx;
+
+ /* Ugly. */
+ ElfW(Word) l_machine_specific[2];
};
#endif /* link.h */
--- libc/sysdeps/generic/ldsodefs.h.jj Fri Mar 16 10:01:25 2001
+++ libc/sysdeps/generic/ldsodefs.h Mon Jun 25 15:01:11 2001
@@ -185,6 +185,8 @@ extern const char *_dl_profile;
extern struct link_map *_dl_profile_map;
/* Filename of the output file. */
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. */
extern int _dl_debug_mask;
@@ -196,6 +198,7 @@ extern int _dl_debug_mask;
#define DL_DEBUG_RELOC (1 << 5)
#define DL_DEBUG_FILES (1 << 6)
#define DL_DEBUG_STATISTICS (1 << 7)
+#define DL_DEBUG_PRELINK (1 << 8)
/* Expect cache ID. */
extern int _dl_correct_cache_id;
@@ -316,6 +319,19 @@ extern void _dl_map_object_deps (struct
/* Cache the locations of MAP's hash table. */
extern void _dl_setup_hash (struct link_map *map) internal_function;
+/* This holds symbol lookup cache. */
+struct lookup_cache
+ {
+ const ElfW(Sym) *sym;
+ struct link_map *map;
+ const struct r_found_version *version;
+ int noexec;
+ int noplt;
+ lookup_t value;
+ const ElfW(Sym) *ret;
+ };
+
+extern struct lookup_cache lookup_cache;
/* Search loaded objects' symbol tables for a definition of the symbol
referred to by UNDEF. *SYM is the symbol table entry containing the
@@ -404,6 +420,11 @@ extern void _dl_reloc_bad_type (struct l
uint_fast8_t type, int plt)
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
MAP. If VERBOSE print some more diagnostics. */
--- libc/sysdeps/i386/dl-machine.h.jj Tue Apr 17 23:58:46 2001
+++ libc/sysdeps/i386/dl-machine.h Mon Jun 25 10:50:33 2001
@@ -87,6 +87,14 @@ elf_machine_runtime_setup (struct link_m
offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
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_machine_specific [0] = got[1] + l->l_addr;
+ l->l_machine_specific [1] = (Elf32_Word) &got[3];
+ }
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
/* 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. */
#define ELF_MACHINE_JMP_SLOT R_386_JMP_SLOT
-/* The i386 never uses Elf32_Rela relocations. */
-#define ELF_MACHINE_NO_RELA 1
+/* The i386 never uses Elf32_Rela relocations for the dynamic linker.
+ Prelinked libraries may use Elf32_Rela though. */
+#define ELF_MACHINE_PLT_REL 1
/* We define an initialization functions. This is called very early in
_dl_sysdep_start. */
@@ -295,6 +304,12 @@ elf_machine_plt_value (struct link_map *
#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).
MAP is the object containing the reloc. */
@@ -371,6 +386,41 @@ elf_machine_rel (struct link_map *map, c
}
}
+#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
elf_machine_lazy_rel (struct link_map *map,
Elf32_Addr l_addr, const Elf32_Rel *reloc)
@@ -379,9 +429,26 @@ elf_machine_lazy_rel (struct link_map *m
/* Check for unexpected PLT reloc type. */
if (__builtin_expect (ELF32_R_TYPE (reloc->r_info), R_386_JMP_SLOT)
== R_386_JMP_SLOT)
- *reloc_addr += l_addr;
+ {
+ if (__builtin_expect (map->l_machine_specific [0], 0) == 0)
+ *reloc_addr += l_addr;
+ else
+ *reloc_addr =
+ map->l_machine_specific [0]
+ + (((Elf32_Word) reloc_addr) - map->l_machine_specific [1]) * 4;
+ }
else
_dl_reloc_bad_type (map, ELFW(R_TYPE) (reloc->r_info), 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 */
Jakub
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |