1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-09-01 05:02:03 +03:00
* include/link.h (struct link_map): Add l_lookup_cache element.
	* elf/dl-reloc.c (RESOLVE): Add symbol caching here.
	(RESOLVE_MAP): Likewise.
	(_dl_relocate_object): Remove cache initialization.
	* elf/dl-lookup.c: Rip out cache handling code.
	* sysdeps/generic/ldsodefs.h: Remove lookup_cache struct and variable
	declarations.

	* elf/dl-lookup.c (_dl_lookup_symbol): Reorder some conditions and
	remove some __builtin_expect.
	(_dl_lookup_versioned_symbol): Likewise.

	R_386_RELATIVE handling for ld.so startup.  Reduce RTLD_BOOTSTRAP
	case to almost no code.
This commit is contained in:
Ulrich Drepper
2001-08-26 10:50:26 +00:00
parent a711b01d34
commit 680254fe22
6 changed files with 83 additions and 107 deletions

View File

@@ -1,11 +1,24 @@
2001-08-26 Ulrich Drepper <drepper@redhat.com> 2001-08-26 Ulrich Drepper <drepper@redhat.com>
* include/link.h (struct link_map): Add l_lookup_cache element.
* elf/dl-reloc.c (RESOLVE): Add symbol caching here.
(RESOLVE_MAP): Likewise.
(_dl_relocate_object): Remove cache initialization.
* elf/dl-lookup.c: Rip out cache handling code.
* sysdeps/generic/ldsodefs.h: Remove lookup_cache struct and variable
declarations.
* elf/dl-lookup.c (_dl_lookup_symbol): Reorder some conditions and
remove some __builtin_expect.
(_dl_lookup_versioned_symbol): Likewise.
* config.h.in: Add HAVE_Z_COMBRELOC. * config.h.in: Add HAVE_Z_COMBRELOC.
* configure.in: Add test for -z combreloc. * configure.in: Add test for -z combreloc.
* sysdeps/i386/dl-machine.h (elf_machine_rel): Minor cleanups and * sysdeps/i386/dl-machine.h (elf_machine_rel): Minor cleanups and
optimizations. Use HAVE_Z_COMBRELOC to avoid generaton of optimizations. Use HAVE_Z_COMBRELOC to avoid generaton of
R_386_RELATIVE handling for ld.so startup. R_386_RELATIVE handling for ld.so startup. Reduce RTLD_BOOTSTRAP
case to almost no code.
2001-08-25 Ulrich Drepper <drepper@redhat.com> 2001-08-25 Ulrich Drepper <drepper@redhat.com>

View File

@@ -60,7 +60,6 @@ struct sym_val
/* Statistics function. */ /* Statistics function. */
unsigned long int _dl_num_relocations; unsigned long int _dl_num_relocations;
unsigned long int _dl_num_cache_relocations;
/* We have two different situations when looking up a simple: with or /* We have two different situations when looking up a simple: with or
@@ -185,8 +184,6 @@ _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 noexec, int noplt); struct link_map *skip, int noexec, int noplt);
struct lookup_cache _dl_lookup_cache;
struct lookup_cache _dl_lookup_cache_versioned;
/* 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. */
@@ -197,29 +194,15 @@ _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 reloc_type, int explicit) int reloc_type, int explicit)
{ {
unsigned long int hash; unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value; struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope; struct r_scope_elem **scope;
int protected; int protected;
int noexec = elf_machine_lookup_noexec_p (reloc_type); int noexec = elf_machine_lookup_noexec_p (reloc_type);
int noplt = elf_machine_lookup_noplt_p (reloc_type); int noplt = elf_machine_lookup_noplt_p (reloc_type);
/* First check if we can find it in the cache. */
if (__builtin_expect (*ref == _dl_lookup_cache.sym, 0)
&& _dl_lookup_cache.map == undef_map
&& _dl_lookup_cache.noexec == noexec
&& _dl_lookup_cache.noplt == noplt)
{
++_dl_num_cache_relocations;
*ref = _dl_lookup_cache.ret;
return _dl_lookup_cache.value;
}
++_dl_num_relocations; ++_dl_num_relocations;
hash = _dl_elf_hash (undef_name);
current_value = ((struct sym_val) { NULL, NULL });
/* Search the relevant loaded objects for a definition. */ /* Search the relevant loaded objects for a definition. */
for (scope = symbol_scope; *scope; ++scope) for (scope = symbol_scope; *scope; ++scope)
if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL, if (do_lookup (undef_name, hash, *ref, &current_value, *scope, 0, NULL,
@@ -229,13 +212,12 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
in the global scope which was dynamically loaded. In this case in the global scope which was dynamically loaded. In this case
we have to prevent the latter from being unloaded unless the we have to prevent the latter from being unloaded unless the
UNDEF_MAP object is also unloaded. */ UNDEF_MAP object is also unloaded. */
if (__builtin_expect (current_value.m->l_global, 0) if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
&& (__builtin_expect (current_value.m->l_type, lt_library) && current_value.m->l_global
== lt_loaded)
&& undef_map != current_value.m && undef_map != current_value.m
/* Don't do this for explicit lookups as opposed to implicit /* Don't do this for explicit lookups as opposed to implicit
runtime lookups. */ runtime lookups. */
&& __builtin_expect (! explicit, 1) && ! explicit
/* Add UNDEF_MAP to the dependencies. */ /* Add UNDEF_MAP to the dependencies. */
&& add_dependency (undef_map, current_value.m) < 0) && add_dependency (undef_map, current_value.m) < 0)
/* Something went wrong. Perhaps the object we tried to reference /* Something went wrong. Perhaps the object we tried to reference
@@ -246,11 +228,6 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
break; break;
} }
/* Update common information in the cache. */
_dl_lookup_cache.sym = *ref;
_dl_lookup_cache.noexec = noexec;
_dl_lookup_cache.noplt = noplt;
if (__builtin_expect (current_value.s == NULL, 0)) if (__builtin_expect (current_value.s == NULL, 0))
{ {
const char *reference_name = undef_map ? undef_map->l_name : NULL; const char *reference_name = undef_map ? undef_map->l_name : NULL;
@@ -262,8 +239,6 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
? reference_name ? reference_name
: (_dl_argv[0] ?: "<main program>")), : (_dl_argv[0] ?: "<main program>")),
make_string (undefined_msg, undef_name)); make_string (undefined_msg, undef_name));
_dl_lookup_cache.ret = NULL;
_dl_lookup_cache.value = 0;
*ref = NULL; *ref = NULL;
return 0; return 0;
} }
@@ -284,8 +259,6 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
if (__builtin_expect (protected == 0, 1)) if (__builtin_expect (protected == 0, 1))
{ {
_dl_lookup_cache.ret = current_value.s;
_dl_lookup_cache.value = LOOKUP_VALUE (current_value.m);
*ref = current_value.s; *ref = current_value.s;
return LOOKUP_VALUE (current_value.m); return LOOKUP_VALUE (current_value.m);
} }
@@ -302,13 +275,9 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
if (protected_value.s == NULL || protected_value.m == undef_map) if (protected_value.s == NULL || protected_value.m == undef_map)
{ {
_dl_lookup_cache.ret = current_value.s;
_dl_lookup_cache.value = LOOKUP_VALUE (current_value.m);
*ref = current_value.s; *ref = current_value.s;
return LOOKUP_VALUE (current_value.m); return LOOKUP_VALUE (current_value.m);
} }
_dl_lookup_cache.ret = *ref;
_dl_lookup_cache.value = LOOKUP_VALUE (undef_map);
return LOOKUP_VALUE (undef_map); return LOOKUP_VALUE (undef_map);
} }
@@ -407,30 +376,15 @@ _dl_lookup_versioned_symbol (const char *undef_name,
const struct r_found_version *version, const struct r_found_version *version,
int reloc_type, int explicit) int reloc_type, int explicit)
{ {
unsigned long int hash; unsigned long int hash = _dl_elf_hash (undef_name);
struct sym_val current_value; struct sym_val current_value = { NULL, NULL };
struct r_scope_elem **scope; struct r_scope_elem **scope;
int protected; int protected;
int noexec = elf_machine_lookup_noexec_p (reloc_type); int noexec = elf_machine_lookup_noexec_p (reloc_type);
int noplt = elf_machine_lookup_noplt_p (reloc_type); int noplt = elf_machine_lookup_noplt_p (reloc_type);
/* First check if we can find it in the cache. */
if (__builtin_expect (*ref == _dl_lookup_cache_versioned.sym, 0)
&& _dl_lookup_cache_versioned.map == undef_map
&& _dl_lookup_cache_versioned.noexec == noexec
&& _dl_lookup_cache_versioned.noplt == noplt
&& _dl_lookup_cache_versioned.version == version)
{
++_dl_num_cache_relocations;
*ref = _dl_lookup_cache_versioned.ret;
return _dl_lookup_cache_versioned.value;
}
++_dl_num_relocations; ++_dl_num_relocations;
hash = _dl_elf_hash (undef_name);
current_value = ((struct sym_val) { NULL, NULL });
/* Search the relevant loaded objects for a definition. */ /* Search the relevant loaded objects for a definition. */
for (scope = symbol_scope; *scope; ++scope) for (scope = symbol_scope; *scope; ++scope)
{ {
@@ -442,13 +396,12 @@ _dl_lookup_versioned_symbol (const char *undef_name,
in the global scope which was dynamically loaded. In this case in the global scope which was dynamically loaded. In this case
we have to prevent the latter from being unloaded unless the we have to prevent the latter from being unloaded unless the
UNDEF_MAP object is also unloaded. */ UNDEF_MAP object is also unloaded. */
if (__builtin_expect (current_value.m->l_global, 0) if (__builtin_expect (current_value.m->l_type == lt_loaded, 0)
&& (__builtin_expect (current_value.m->l_type, lt_library) && current_value.m->l_global
== lt_loaded)
&& undef_map != current_value.m && undef_map != current_value.m
/* Don't do this for explicit lookups as opposed to implicit /* Don't do this for explicit lookups as opposed to implicit
runtime lookups. */ runtime lookups. */
&& __builtin_expect (! explicit, 1) && ! explicit
/* Add UNDEF_MAP to the dependencies. */ /* Add UNDEF_MAP to the dependencies. */
&& add_dependency (undef_map, current_value.m) < 0) && add_dependency (undef_map, current_value.m) < 0)
/* Something went wrong. Perhaps the object we tried to reference /* Something went wrong. Perhaps the object we tried to reference
@@ -482,12 +435,6 @@ _dl_lookup_versioned_symbol (const char *undef_name,
} }
} }
/* Update common information in the cache. */
_dl_lookup_cache_versioned.sym = *ref;
_dl_lookup_cache_versioned.noexec = noexec;
_dl_lookup_cache_versioned.noplt = noplt;
_dl_lookup_cache_versioned.version = version;
if (__builtin_expect (current_value.s == NULL, 0)) if (__builtin_expect (current_value.s == NULL, 0))
{ {
if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) if (*ref == NULL || ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK)
@@ -503,9 +450,6 @@ _dl_lookup_versioned_symbol (const char *undef_name,
", version ", ", version ",
version->name ?: NULL)); version->name ?: NULL));
} }
_dl_lookup_cache_versioned.ret = NULL;
_dl_lookup_cache_versioned.value = 0;
*ref = NULL; *ref = NULL;
return 0; return 0;
} }
@@ -527,8 +471,6 @@ _dl_lookup_versioned_symbol (const char *undef_name,
if (__builtin_expect (protected == 0, 1)) if (__builtin_expect (protected == 0, 1))
{ {
_dl_lookup_cache_versioned.ret = current_value.s;
_dl_lookup_cache_versioned.value = LOOKUP_VALUE (current_value.m);
*ref = current_value.s; *ref = current_value.s;
return LOOKUP_VALUE (current_value.m); return LOOKUP_VALUE (current_value.m);
} }
@@ -545,14 +487,10 @@ _dl_lookup_versioned_symbol (const char *undef_name,
if (protected_value.s == NULL || protected_value.m == undef_map) if (protected_value.s == NULL || protected_value.m == undef_map)
{ {
_dl_lookup_cache_versioned.ret = current_value.s;
_dl_lookup_cache_versioned.value = LOOKUP_VALUE (current_value.m);
*ref = current_value.s; *ref = current_value.s;
return LOOKUP_VALUE (current_value.m); return LOOKUP_VALUE (current_value.m);
} }
_dl_lookup_cache_versioned.ret = *ref;
_dl_lookup_cache_versioned.value = LOOKUP_VALUE (undef_map);
return LOOKUP_VALUE (undef_map); return LOOKUP_VALUE (undef_map);
} }
} }

View File

@@ -27,6 +27,9 @@
#include <sys/types.h> #include <sys/types.h>
#include "dynamic-link.h" #include "dynamic-link.h"
/* Statistics function. */
unsigned long int _dl_num_cache_relocations;
void void
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
@@ -74,31 +77,51 @@ cannot make segment writable for relocation"));
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
#define RESOLVE_MAP(ref, version, flags) \ #define RESOLVE_MAP(ref, version, flags) \
(ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \ (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
? ((version) != NULL && (version)->hash != 0 \ ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref), \ && elf_machine_lookup_noexec_p (flags) == l->l_lookup_cache.noexec \
scope, (version), (flags), 0) \ && elf_machine_lookup_noplt_p (flags) == l->l_lookup_cache.noplt) \
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), scope, \ ? (++_dl_num_cache_relocations, \
(flags), 0)) \ (*ref) = l->l_lookup_cache.ret, \
l->l_lookup_cache.value) \
: ({ lookup_t _lr; \
l->l_lookup_cache.sym = (*ref); \
l->l_lookup_cache.noexec = elf_machine_lookup_noexec_p (flags); \
l->l_lookup_cache.noplt = elf_machine_lookup_noplt_p (flags); \
_lr = ((version) != NULL && (version)->hash != 0 \
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \
l, (ref), scope, \
(version), (flags), 0) \
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \
scope, (flags), 0)); \
l->l_lookup_cache.ret = (*ref); \
l->l_lookup_cache.value = _lr; })) \
: l) : l)
#define RESOLVE(ref, version, flags) \ #define RESOLVE(ref, version, flags) \
(ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \ (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
? ((version) != NULL && (version)->hash != 0 \ ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref), \ && elf_machine_lookup_noexec_p (flags) == l->l_lookup_cache.noexec \
scope, (version), (flags), 0) \ && elf_machine_lookup_noplt_p (flags) == l->l_lookup_cache.noplt) \
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), scope, \ ? (++_dl_num_cache_relocations, \
(flags), 0)) \ (*ref) = l->l_lookup_cache.ret, \
l->l_lookup_cache.value) \
: ({ lookup_t _lr; \
l->l_lookup_cache.sym = (*ref); \
l->l_lookup_cache.noexec = elf_machine_lookup_noexec_p (flags); \
l->l_lookup_cache.noplt = elf_machine_lookup_noplt_p (flags); \
_lr = ((version) != NULL && (version)->hash != 0 \
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, \
l, (ref), scope, \
(version), (flags), 0) \
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), \
scope, (flags), 0)); \
l->l_lookup_cache.ret = (*ref); \
l->l_lookup_cache.value = _lr; })) \
: l->l_addr) : l->l_addr)
#include "dynamic-link.h" #include "dynamic-link.h"
/* Start symbol lookup caching for this object. */
_dl_lookup_cache.map = l;
_dl_lookup_cache_versioned.map = l;
ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling); ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling);
_dl_lookup_cache.map = NULL;
_dl_lookup_cache_versioned.map = NULL;
if (__builtin_expect (consider_profiling, 0)) if (__builtin_expect (consider_profiling, 0))
{ {
/* Allocate the array which will contain the already found /* Allocate the array which will contain the already found

View File

@@ -1,6 +1,6 @@
/* Data structure for communication from the run-time dynamic linker for /* Data structure for communication from the run-time dynamic linker for
loaded ELF shared objects. 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. 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
@@ -34,6 +34,7 @@
#include <bits/elfclass.h> /* Defines __ELF_NATIVE_CLASS. */ #include <bits/elfclass.h> /* Defines __ELF_NATIVE_CLASS. */
#include <bits/link.h> #include <bits/link.h>
#include <dl-lookupcfg.h>
/* Rendezvous structure used by the run-time dynamic linker to communicate /* Rendezvous structure used by the run-time dynamic linker to communicate
details of shared object loading to the debugger. If the executable's details of shared object loading to the debugger. If the executable's
@@ -231,6 +232,19 @@ struct link_map
unsigned int l_idx; unsigned int l_idx;
struct link_map_machine l_mach; struct link_map_machine l_mach;
struct
{
const ElfW(Sym) *sym;
int noexec;
int noplt;
#ifdef DL_LOOKUP_RETURNS_MAP
struct link_map *value;
#else
ElfW(Addr) value;
#endif
const ElfW(Sym) *ret;
} l_lookup_cache;
}; };
struct dl_phdr_info struct dl_phdr_info

View File

@@ -327,21 +327,6 @@ extern void _dl_map_object_deps (struct link_map *map,
/* Cache the locations of MAP's hash table. */ /* Cache the locations of MAP's hash table. */
extern void _dl_setup_hash (struct link_map *map) internal_function; 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 _dl_lookup_cache;
extern struct lookup_cache _dl_lookup_cache_versioned;
/* Search loaded objects' symbol tables for a definition of the symbol /* Search loaded objects' symbol tables for a definition of the symbol
referred to by UNDEF. *SYM is the symbol table entry containing the referred to by UNDEF. *SYM is the symbol table entry containing the

View File

@@ -334,13 +334,16 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
if (sym) if (sym)
value += sym->st_value; value += sym->st_value;
#ifdef RTLD_BOOTSTRAP
assert (r_type == R_386_GLOB_DAT || r_type == R_386_JMP_SLOT);
*reloc_addr = value;
#else
switch (r_type) switch (r_type)
{ {
case R_386_GLOB_DAT: case R_386_GLOB_DAT:
case R_386_JMP_SLOT: case R_386_JMP_SLOT:
*reloc_addr = value; *reloc_addr = value;
break; break;
#ifndef RTLD_BOOTSTRAP
case R_386_32: case R_386_32:
*reloc_addr += value; *reloc_addr += value;
break; break;
@@ -372,8 +375,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
if we are still debugging. */ if we are still debugging. */
_dl_reloc_bad_type (map, r_type, 0); _dl_reloc_bad_type (map, r_type, 0);
break; break;
#endif
} }
#endif
} }
} }