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] |