Update.
* posix/unistd.h: Move declaration of __libc_enable_secure to... * include/unistd.h: ...here. * elf/dl-open.c (dl_open_worker): If DST is used in SUID program punt. * elf/dl-deps.c (expand_dst): Likewise. * elf/dynamic-link.h: Set DT_SYMBOLIC, DT_TEXTREL, and DT_BIND_NOW based on DT_FLAGS value. * elf/do-lookup.h: Remove reference_name parameter, add undef_map. Add test for symbols marked STV_HIDDEN. * elf/dl-lookup.c (_dl_lookup_symbol): Remove reference_name parameter, add undef_map. Compute reference_name locally. Update call to do_lookup. (_dl_lookup_symbol_skip): Likewise. (_dl_lookup_versioned_symbol): Likewise. (_dl_lookup_versioned_symbol_skip): Likewise. * elf/dl-libc.c: Update call to _dl_lookup_*symbol. * elf/dl-runtime.c: Likewise. * elf/dl-sym.c: Likewise. * elf/dl-symbol.c: Likewise. * elf/ldsodefs.h: Adjust prototypes. * elf/dl-reloc.c (RESOLV): Add test for STV_PROTECTED flag set and handle appropriately. Add comment about DT_TEXTREL. * elf/dl-runtime.c: Likewise.
This commit is contained in:
parent
fc9cfb28c0
commit
06535ae948
27
ChangeLog
27
ChangeLog
|
@ -13,6 +13,33 @@
|
||||||
DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ.
|
DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ.
|
||||||
Add DF_ORIGIN, DF_SYMBOLIC, DF_TEXTREL, and DF_BIND_NOW.
|
Add DF_ORIGIN, DF_SYMBOLIC, DF_TEXTREL, and DF_BIND_NOW.
|
||||||
|
|
||||||
|
* posix/unistd.h: Move declaration of __libc_enable_secure to...
|
||||||
|
* include/unistd.h: ...here.
|
||||||
|
|
||||||
|
* elf/dl-open.c (dl_open_worker): If DST is used in SUID program punt.
|
||||||
|
* elf/dl-deps.c (expand_dst): Likewise.
|
||||||
|
|
||||||
|
* elf/dynamic-link.h: Set DT_SYMBOLIC, DT_TEXTREL, and DT_BIND_NOW
|
||||||
|
based on DT_FLAGS value.
|
||||||
|
|
||||||
|
* elf/do-lookup.h: Remove reference_name parameter, add undef_map.
|
||||||
|
Add test for symbols marked STV_HIDDEN.
|
||||||
|
* elf/dl-lookup.c (_dl_lookup_symbol): Remove reference_name parameter,
|
||||||
|
add undef_map. Compute reference_name locally. Update call to
|
||||||
|
do_lookup.
|
||||||
|
(_dl_lookup_symbol_skip): Likewise.
|
||||||
|
(_dl_lookup_versioned_symbol): Likewise.
|
||||||
|
(_dl_lookup_versioned_symbol_skip): Likewise.
|
||||||
|
* elf/dl-libc.c: Update call to _dl_lookup_*symbol.
|
||||||
|
* elf/dl-runtime.c: Likewise.
|
||||||
|
* elf/dl-sym.c: Likewise.
|
||||||
|
* elf/dl-symbol.c: Likewise.
|
||||||
|
* elf/ldsodefs.h: Adjust prototypes.
|
||||||
|
|
||||||
|
* elf/dl-reloc.c (RESOLV): Add test for STV_PROTECTED flag set and
|
||||||
|
handle appropriately. Add comment about DT_TEXTREL.
|
||||||
|
* elf/dl-runtime.c: Likewise.
|
||||||
|
|
||||||
1999-07-21 Roland McGrath <roland@baalperazim.frob.com>
|
1999-07-21 Roland McGrath <roland@baalperazim.frob.com>
|
||||||
|
|
||||||
* elf/dl-reloc.c (_dl_reloc_bad_type): New function.
|
* elf/dl-reloc.c (_dl_reloc_bad_type): New function.
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <elf/ldsodefs.h>
|
#include <elf/ldsodefs.h>
|
||||||
|
|
||||||
|
@ -96,9 +97,15 @@ struct list
|
||||||
\
|
\
|
||||||
if (__cnt != 0) \
|
if (__cnt != 0) \
|
||||||
{ \
|
{ \
|
||||||
char *__newp = (char *) alloca (DL_DST_REQUIRED (l, __str, \
|
char *__newp; \
|
||||||
strlen (__str), \
|
\
|
||||||
__cnt)); \
|
/* DST must not appear in SUID/SGID programs. */ \
|
||||||
|
if (__libc_enable_secure) \
|
||||||
|
_dl_signal_error (0, __str, \
|
||||||
|
"DST not allowed in SUID/SGID programs"); \
|
||||||
|
\
|
||||||
|
__newp = (char *) alloca (DL_DST_REQUIRED (l, __str, strlen (__str), \
|
||||||
|
__cnt)); \
|
||||||
\
|
\
|
||||||
__result = DL_DST_SUBSTITUTE (l, __str, __newp, 0); \
|
__result = DL_DST_SUBSTITUTE (l, __str, __newp, 0); \
|
||||||
\
|
\
|
||||||
|
|
|
@ -82,9 +82,8 @@ do_dlsym (void *ptr)
|
||||||
{
|
{
|
||||||
struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
|
struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
|
||||||
args->ref = NULL;
|
args->ref = NULL;
|
||||||
args->loadbase = _dl_lookup_symbol (args->name, &args->ref,
|
args->loadbase = _dl_lookup_symbol (args->name, args->map, &args->ref,
|
||||||
args->map->l_local_scope,
|
args->map->l_local_scope, 0);
|
||||||
args->map->l_name, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -75,11 +75,11 @@ unsigned long int _dl_num_relocations;
|
||||||
|
|
||||||
ElfW(Addr)
|
ElfW(Addr)
|
||||||
internal_function
|
internal_function
|
||||||
_dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
_dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
|
||||||
struct r_scope_elem *symbol_scope[],
|
const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
|
||||||
const char *reference_name,
|
|
||||||
int reloc_type)
|
int reloc_type)
|
||||||
{
|
{
|
||||||
|
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||||
struct sym_val current_value = { NULL, NULL };
|
struct sym_val current_value = { NULL, NULL };
|
||||||
struct r_scope_elem **scope;
|
struct r_scope_elem **scope;
|
||||||
|
@ -88,8 +88,8 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
||||||
|
|
||||||
/* 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, ¤t_value,
|
if (do_lookup (undef_name, undef_map, hash, *ref, ¤t_value,
|
||||||
*scope, 0, reference_name, NULL, reloc_type))
|
*scope, 0, NULL, reloc_type))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (current_value.s == NULL)
|
if (current_value.s == NULL)
|
||||||
|
@ -125,11 +125,12 @@ _dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
||||||
SKIP_MAP is only skipped. */
|
SKIP_MAP is only skipped. */
|
||||||
ElfW(Addr)
|
ElfW(Addr)
|
||||||
internal_function
|
internal_function
|
||||||
_dl_lookup_symbol_skip (const char *undef_name, const ElfW(Sym) **ref,
|
_dl_lookup_symbol_skip (const char *undef_name,
|
||||||
|
struct link_map *undef_map, const ElfW(Sym) **ref,
|
||||||
struct r_scope_elem *symbol_scope[],
|
struct r_scope_elem *symbol_scope[],
|
||||||
const char *reference_name,
|
|
||||||
struct link_map *skip_map)
|
struct link_map *skip_map)
|
||||||
{
|
{
|
||||||
|
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||||
struct sym_val current_value = { NULL, NULL };
|
struct sym_val current_value = { NULL, NULL };
|
||||||
struct r_scope_elem **scope;
|
struct r_scope_elem **scope;
|
||||||
|
@ -143,11 +144,11 @@ _dl_lookup_symbol_skip (const char *undef_name, const ElfW(Sym) **ref,
|
||||||
assert (i < (*scope)->r_nduplist);
|
assert (i < (*scope)->r_nduplist);
|
||||||
|
|
||||||
if (i >= (*scope)->r_nlist
|
if (i >= (*scope)->r_nlist
|
||||||
|| ! do_lookup (undef_name, hash, *ref, ¤t_value,
|
|| ! do_lookup (undef_name, undef_map, hash, *ref, ¤t_value,
|
||||||
*scope, i, reference_name, skip_map, 0))
|
*scope, i, skip_map, 0))
|
||||||
while (*++scope)
|
while (*++scope)
|
||||||
if (do_lookup (undef_name, hash, *ref, ¤t_value,
|
if (do_lookup (undef_name, undef_map, hash, *ref, ¤t_value,
|
||||||
*scope, 0, reference_name, skip_map, 0))
|
*scope, 0, skip_map, 0))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (current_value.s == NULL)
|
if (current_value.s == NULL)
|
||||||
|
@ -177,12 +178,13 @@ _dl_lookup_symbol_skip (const char *undef_name, const ElfW(Sym) **ref,
|
||||||
XXX We'll see whether we need this separate function. */
|
XXX We'll see whether we need this separate function. */
|
||||||
ElfW(Addr)
|
ElfW(Addr)
|
||||||
internal_function
|
internal_function
|
||||||
_dl_lookup_versioned_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
_dl_lookup_versioned_symbol (const char *undef_name,
|
||||||
|
struct link_map *undef_map, const ElfW(Sym) **ref,
|
||||||
struct r_scope_elem *symbol_scope[],
|
struct r_scope_elem *symbol_scope[],
|
||||||
const char *reference_name,
|
|
||||||
const struct r_found_version *version,
|
const struct r_found_version *version,
|
||||||
int reloc_type)
|
int reloc_type)
|
||||||
{
|
{
|
||||||
|
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||||
struct sym_val current_value = { NULL, NULL };
|
struct sym_val current_value = { NULL, NULL };
|
||||||
struct r_scope_elem **scope;
|
struct r_scope_elem **scope;
|
||||||
|
@ -192,8 +194,8 @@ _dl_lookup_versioned_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
int res = do_lookup_versioned (undef_name, hash, *ref, ¤t_value,
|
int res = do_lookup_versioned (undef_name, undef_map, hash, *ref,
|
||||||
*scope, 0, reference_name, version, NULL,
|
¤t_value, *scope, 0, version, NULL,
|
||||||
reloc_type);
|
reloc_type);
|
||||||
if (res > 0)
|
if (res > 0)
|
||||||
break;
|
break;
|
||||||
|
@ -250,12 +252,13 @@ _dl_lookup_versioned_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
||||||
ElfW(Addr)
|
ElfW(Addr)
|
||||||
internal_function
|
internal_function
|
||||||
_dl_lookup_versioned_symbol_skip (const char *undef_name,
|
_dl_lookup_versioned_symbol_skip (const char *undef_name,
|
||||||
|
struct link_map *undef_map,
|
||||||
const ElfW(Sym) **ref,
|
const ElfW(Sym) **ref,
|
||||||
struct r_scope_elem *symbol_scope[],
|
struct r_scope_elem *symbol_scope[],
|
||||||
const char *reference_name,
|
|
||||||
const struct r_found_version *version,
|
const struct r_found_version *version,
|
||||||
struct link_map *skip_map)
|
struct link_map *skip_map)
|
||||||
{
|
{
|
||||||
|
const char *reference_name = undef_map ? undef_map->l_name : NULL;
|
||||||
const unsigned long int hash = _dl_elf_hash (undef_name);
|
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||||
struct sym_val current_value = { NULL, NULL };
|
struct sym_val current_value = { NULL, NULL };
|
||||||
struct r_scope_elem **scope;
|
struct r_scope_elem **scope;
|
||||||
|
@ -269,11 +272,13 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
|
||||||
assert (i < (*scope)->r_nduplist);
|
assert (i < (*scope)->r_nduplist);
|
||||||
|
|
||||||
if (i >= (*scope)->r_nlist
|
if (i >= (*scope)->r_nlist
|
||||||
|| ! do_lookup_versioned (undef_name, hash, *ref, ¤t_value, *scope,
|
|| ! do_lookup_versioned (undef_name, undef_map, hash, *ref,
|
||||||
i, reference_name, version, skip_map, 0))
|
¤t_value, *scope, i, version, skip_map,
|
||||||
|
0))
|
||||||
while (*++scope)
|
while (*++scope)
|
||||||
if (do_lookup_versioned (undef_name, hash, *ref, ¤t_value, *scope,
|
if (do_lookup_versioned (undef_name, undef_map, hash, *ref,
|
||||||
0, reference_name, version, skip_map, 0))
|
¤t_value, *scope, 0, version, skip_map,
|
||||||
|
0))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (current_value.s == NULL)
|
if (current_value.s == NULL)
|
||||||
|
|
|
@ -20,9 +20,10 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <libintl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <libintl.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h> /* Check whether MAP_COPY is defined. */
|
#include <sys/mman.h> /* Check whether MAP_COPY is defined. */
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <bits/libc-lock.h>
|
#include <bits/libc-lock.h>
|
||||||
|
@ -100,6 +101,12 @@ dl_open_worker (void *a)
|
||||||
struct link_map *call_map;
|
struct link_map *call_map;
|
||||||
char *new_file;
|
char *new_file;
|
||||||
|
|
||||||
|
/* DSTs must not appear in SUID/SGID programs. */
|
||||||
|
if (__libc_enable_secure)
|
||||||
|
/* This is an error. */
|
||||||
|
_dl_signal_error (0, "dlopen",
|
||||||
|
"DST not allowed in SUID/SGID programs");
|
||||||
|
|
||||||
/* We have to find out from which object the caller is calling.
|
/* We have to find out from which object the caller is calling.
|
||||||
Find the highest-addressed object that ADDRESS is not below. */
|
Find the highest-addressed object that ADDRESS is not below. */
|
||||||
call_map = NULL;
|
call_map = NULL;
|
||||||
|
|
|
@ -71,11 +71,13 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||||
|
|
||||||
/* 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(ref, version, flags) \
|
#define RESOLVE(ref, version, flags) \
|
||||||
((version) != NULL && (version)->hash != 0 \
|
(ELFW(ST_VISIBILITY) ((*ref)->st_other) != STV_PROTECTED \
|
||||||
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, (ref), scope, \
|
? ((version) != NULL && (version)->hash != 0 \
|
||||||
l->l_name, (version), (flags)) \
|
? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref), \
|
||||||
: _dl_lookup_symbol (strtab + (*ref)->st_name, (ref), scope, \
|
scope, (version), (flags)) \
|
||||||
l->l_name, (flags)))
|
: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), scope, \
|
||||||
|
(flags))) \
|
||||||
|
: l->l_addr)
|
||||||
|
|
||||||
#include "dynamic-link.h"
|
#include "dynamic-link.h"
|
||||||
ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling);
|
ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling);
|
||||||
|
@ -96,6 +98,9 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||||
/* Mark the object so we know this work has been done. */
|
/* Mark the object so we know this work has been done. */
|
||||||
l->l_relocated = 1;
|
l->l_relocated = 1;
|
||||||
|
|
||||||
|
/* DT_TEXTREL is now in level 2 and might phase out at some time.
|
||||||
|
But we rewrite the DT_FLAGS entry to make testing easier and
|
||||||
|
therefore it will be available at all time. */
|
||||||
if (l->l_info[DT_TEXTREL])
|
if (l->l_info[DT_TEXTREL])
|
||||||
{
|
{
|
||||||
/* Undo the protection change we made before relocating. */
|
/* Undo the protection change we made before relocating. */
|
||||||
|
|
110
elf/dl-runtime.c
110
elf/dl-runtime.c
|
@ -66,32 +66,40 @@ fixup (
|
||||||
/* Sanity check that we're really looking at a PLT relocation. */
|
/* Sanity check that we're really looking at a PLT relocation. */
|
||||||
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
|
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
|
||||||
|
|
||||||
/* Look up the target symbol. */
|
/* Look up the target symbol. If the symbol is marked STV_PROTEXTED
|
||||||
switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
don't look in the global scope. */
|
||||||
|
if (ELFW(ST_VISIBILITY) (sym->st_other) != STV_PROTECTED)
|
||||||
{
|
{
|
||||||
default:
|
switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||||
{
|
{
|
||||||
const ElfW(Half) *vernum =
|
default:
|
||||||
(const void *) l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr;
|
|
||||||
ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
|
|
||||||
const struct r_found_version *version = &l->l_versions[ndx];
|
|
||||||
|
|
||||||
if (version->hash != 0)
|
|
||||||
{
|
{
|
||||||
value = _dl_lookup_versioned_symbol(strtab + sym->st_name,
|
const ElfW(Half) *vernum =
|
||||||
&sym, l->l_scope, l->l_name,
|
(const void *) l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr;
|
||||||
version, ELF_MACHINE_JMP_SLOT);
|
ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
|
||||||
break;
|
const struct r_found_version *version = &l->l_versions[ndx];
|
||||||
}
|
|
||||||
}
|
|
||||||
case 0:
|
|
||||||
value = _dl_lookup_symbol (strtab + sym->st_name, &sym, l->l_scope,
|
|
||||||
l->l_name, ELF_MACHINE_JMP_SLOT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Currently value contains the base load address of the object
|
if (version->hash != 0)
|
||||||
that defines sym. Now add in the symbol offset. */
|
{
|
||||||
value = (sym ? value + sym->st_value : 0);
|
value = _dl_lookup_versioned_symbol(strtab + sym->st_name, l,
|
||||||
|
&sym, l->l_scope, version,
|
||||||
|
ELF_MACHINE_JMP_SLOT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 0:
|
||||||
|
value = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
|
||||||
|
l->l_scope, ELF_MACHINE_JMP_SLOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Currently value contains the base load address of the object
|
||||||
|
that defines sym. Now add in the symbol offset. */
|
||||||
|
value = (sym ? value + sym->st_value : 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* We already found the symbol. The module (and therefore its load
|
||||||
|
address) is also known. */
|
||||||
|
value = l->l_addr + sym->st_value;
|
||||||
|
|
||||||
/* And now perhaps the relocation addend. */
|
/* And now perhaps the relocation addend. */
|
||||||
value = elf_machine_plt_value (l, reloc, value);
|
value = elf_machine_plt_value (l, reloc, value);
|
||||||
|
@ -141,33 +149,41 @@ profile_fixup (
|
||||||
/* Sanity check that we're really looking at a PLT relocation. */
|
/* Sanity check that we're really looking at a PLT relocation. */
|
||||||
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
|
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
|
||||||
|
|
||||||
/* Look up the target symbol. */
|
/* Look up the target symbol. If the symbol is marked STV_PROTEXTED
|
||||||
switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
don't look in the global scope. */
|
||||||
|
if (ELFW(ST_VISIBILITY) (sym->st_other) != STV_PROTECTED)
|
||||||
{
|
{
|
||||||
default:
|
switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||||
{
|
{
|
||||||
const ElfW(Half) *vernum =
|
default:
|
||||||
(const void *) l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr;
|
|
||||||
ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
|
|
||||||
const struct r_found_version *version = &l->l_versions[ndx];
|
|
||||||
|
|
||||||
if (version->hash != 0)
|
|
||||||
{
|
{
|
||||||
value = _dl_lookup_versioned_symbol(strtab + sym->st_name,
|
const ElfW(Half) *vernum =
|
||||||
&sym, l->l_scope,
|
(const void *) l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr;
|
||||||
l->l_name, version,
|
ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
|
||||||
ELF_MACHINE_JMP_SLOT);
|
const struct r_found_version *version = &l->l_versions[ndx];
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 0:
|
|
||||||
value = _dl_lookup_symbol (strtab + sym->st_name, &sym, l->l_scope,
|
|
||||||
l->l_name, ELF_MACHINE_JMP_SLOT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Currently value contains the base load address of the object
|
if (version->hash != 0)
|
||||||
that defines sym. Now add in the symbol offset. */
|
{
|
||||||
value = (sym ? value + sym->st_value : 0);
|
value = _dl_lookup_versioned_symbol(strtab + sym->st_name,
|
||||||
|
l, &sym, l->l_scope,
|
||||||
|
version,
|
||||||
|
ELF_MACHINE_JMP_SLOT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 0:
|
||||||
|
value = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
|
||||||
|
l->l_scope, ELF_MACHINE_JMP_SLOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Currently value contains the base load address of the object
|
||||||
|
that defines sym. Now add in the symbol offset. */
|
||||||
|
value = (sym ? value + sym->st_value : 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* We already found the symbol. The module (and therefore its load
|
||||||
|
address) is also known. */
|
||||||
|
value = l->l_addr + sym->st_value;
|
||||||
|
|
||||||
/* And now perhaps the relocation addend. */
|
/* And now perhaps the relocation addend. */
|
||||||
value = elf_machine_plt_value (l, reloc, value);
|
value = elf_machine_plt_value (l, reloc, value);
|
||||||
|
|
22
elf/dl-sym.c
22
elf/dl-sym.c
|
@ -34,7 +34,7 @@ _dl_sym (void *handle, const char *name, void *who)
|
||||||
|
|
||||||
if (handle == RTLD_DEFAULT)
|
if (handle == RTLD_DEFAULT)
|
||||||
/* Search the global scope. */
|
/* Search the global scope. */
|
||||||
loadbase = _dl_lookup_symbol (name, &ref, _dl_global_scope, NULL, 0);
|
loadbase = _dl_lookup_symbol (name, NULL, &ref, _dl_global_scope, 0);
|
||||||
else if (handle == RTLD_NEXT)
|
else if (handle == RTLD_NEXT)
|
||||||
{
|
{
|
||||||
struct link_map *l, *match;
|
struct link_map *l, *match;
|
||||||
|
@ -54,15 +54,14 @@ RTLD_NEXT used in code not dynamically loaded"));
|
||||||
while (l->l_loader)
|
while (l->l_loader)
|
||||||
l = l->l_loader;
|
l = l->l_loader;
|
||||||
|
|
||||||
loadbase = _dl_lookup_symbol_skip (name, &ref, l->l_local_scope,
|
loadbase = _dl_lookup_symbol_skip (name, l, &ref, l->l_local_scope,
|
||||||
NULL, match);
|
match);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Search the scope of the given object. */
|
/* Search the scope of the given object. */
|
||||||
struct link_map *map = handle;
|
struct link_map *map = handle;
|
||||||
loadbase = _dl_lookup_symbol (name, &ref, map->l_local_scope,
|
loadbase = _dl_lookup_symbol (name, map, &ref, map->l_local_scope, 0);
|
||||||
map->l_name, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadbase)
|
if (loadbase)
|
||||||
|
@ -88,8 +87,8 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who)
|
||||||
|
|
||||||
if (handle == RTLD_DEFAULT)
|
if (handle == RTLD_DEFAULT)
|
||||||
/* Search the global scope. */
|
/* Search the global scope. */
|
||||||
loadbase = _dl_lookup_versioned_symbol (name, &ref, _dl_global_scope,
|
loadbase = _dl_lookup_versioned_symbol (name, NULL, &ref, _dl_global_scope,
|
||||||
NULL, &vers, 0);
|
&vers, 0);
|
||||||
else if (handle == RTLD_NEXT)
|
else if (handle == RTLD_NEXT)
|
||||||
{
|
{
|
||||||
struct link_map *l, *match;
|
struct link_map *l, *match;
|
||||||
|
@ -109,17 +108,16 @@ RTLD_NEXT used in code not dynamically loaded"));
|
||||||
while (l->l_loader)
|
while (l->l_loader)
|
||||||
l = l->l_loader;
|
l = l->l_loader;
|
||||||
|
|
||||||
loadbase = _dl_lookup_versioned_symbol_skip (name, &ref,
|
loadbase = _dl_lookup_versioned_symbol_skip (name, l, &ref,
|
||||||
l->l_local_scope,
|
l->l_local_scope,
|
||||||
NULL, &vers, match);
|
&vers, match);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Search the scope of the given object. */
|
/* Search the scope of the given object. */
|
||||||
struct link_map *map = handle;
|
struct link_map *map = handle;
|
||||||
loadbase = _dl_lookup_versioned_symbol (name, &ref,
|
loadbase = _dl_lookup_versioned_symbol (name, map, &ref,
|
||||||
map->l_local_scope,
|
map->l_local_scope, &vers, 0);
|
||||||
map->l_name, &vers, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadbase)
|
if (loadbase)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Look up a symbol's run-time value in the scope of a loaded object.
|
/* Look up a symbol's run-time value in the scope of a loaded object.
|
||||||
Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
|
Copyright (C) 1995, 1996, 1998, 1999 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
|
||||||
|
@ -28,7 +28,6 @@ _dl_symbol_value (struct link_map *map, const char *name)
|
||||||
{
|
{
|
||||||
ElfW(Addr) loadbase;
|
ElfW(Addr) loadbase;
|
||||||
const ElfW(Sym) *ref = NULL;
|
const ElfW(Sym) *ref = NULL;
|
||||||
loadbase = _dl_lookup_symbol (name, &ref, map->l_local_scope, map->l_name,
|
loadbase = _dl_lookup_symbol (name, map, &ref, map->l_local_scope, 0);
|
||||||
0);
|
|
||||||
return loadbase + ref->st_value;
|
return loadbase + ref->st_value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,10 @@
|
||||||
found the symbol, the value 0 if nothing is found and < 0 if
|
found the symbol, the value 0 if nothing is found and < 0 if
|
||||||
something bad happened. */
|
something bad happened. */
|
||||||
static inline int
|
static inline int
|
||||||
FCT (const char *undef_name, unsigned long int hash,
|
FCT (const char *undef_name, struct link_map *undef_map,
|
||||||
const ElfW(Sym) *ref, struct sym_val *result,
|
unsigned long int hash, const ElfW(Sym) *ref, struct sym_val *result,
|
||||||
struct r_scope_elem *scope, size_t i, const char *reference_name,
|
struct r_scope_elem *scope, size_t i, ARG struct link_map *skip,
|
||||||
ARG struct link_map *skip, int reloc_type)
|
int reloc_type)
|
||||||
{
|
{
|
||||||
struct link_map **list = scope->r_list;
|
struct link_map **list = scope->r_list;
|
||||||
size_t n = scope->r_nlist;
|
size_t n = scope->r_nlist;
|
||||||
|
@ -154,7 +154,12 @@ FCT (const char *undef_name, unsigned long int hash,
|
||||||
sym = num_versions == 1 ? versioned_sym : NULL;
|
sym = num_versions == 1 ? versioned_sym : NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sym != NULL)
|
if (sym != NULL
|
||||||
|
/* Don't allow binding if the symbol is hidden. When processor
|
||||||
|
specific definitions for STV_INTERNAL are defined we might
|
||||||
|
have to extend this conditional. */
|
||||||
|
&& (ELFW(ST_VISIBILITY) (sym->st_other) != STV_HIDDEN
|
||||||
|
|| map == undef_map))
|
||||||
{
|
{
|
||||||
found_it:
|
found_it:
|
||||||
switch (ELFW(ST_BIND) (sym->st_info))
|
switch (ELFW(ST_BIND) (sym->st_info))
|
||||||
|
|
|
@ -93,6 +93,19 @@ elf_get_dynamic_info (ElfW(Dyn) *dyn, ElfW(Addr) l_addr,
|
||||||
info[DT_JMPREL]->d_un.d_ptr += l_addr;
|
info[DT_JMPREL]->d_un.d_ptr += l_addr;
|
||||||
if (info[VERSYMIDX (DT_VERSYM)] != NULL)
|
if (info[VERSYMIDX (DT_VERSYM)] != NULL)
|
||||||
info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr += l_addr;
|
info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr += l_addr;
|
||||||
|
if (info[DT_FLAGS] != NULL)
|
||||||
|
{
|
||||||
|
/* Flags are used. Translate to the old form where available.
|
||||||
|
Since these l_info entries are only tested for NULL pointers it
|
||||||
|
is ok if they point to the DT_FLAGS entry. */
|
||||||
|
ElfW(Word) flags = info[DT_FLAGS]->d_un.d_val;
|
||||||
|
if (flags & DF_SYMBOLIC)
|
||||||
|
info[DT_SYMBOLIC] = info[DT_FLAGS];
|
||||||
|
if (flags & DF_TEXTREL)
|
||||||
|
info[DT_TEXTREL] = info[DT_FLAGS];
|
||||||
|
if (flags & DF_BIND_NOW)
|
||||||
|
info[DT_BIND_NOW] = info[DT_FLAGS];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RESOLVE
|
#ifdef RESOLVE
|
||||||
|
|
|
@ -260,35 +260,35 @@ extern void _dl_setup_hash (struct link_map *map) internal_function;
|
||||||
the `elf_machine_lookup_*_p' macros in dl-machine.h to affect which
|
the `elf_machine_lookup_*_p' macros in dl-machine.h to affect which
|
||||||
symbols can be chosen. */
|
symbols can be chosen. */
|
||||||
extern ElfW(Addr) _dl_lookup_symbol (const char *undef,
|
extern ElfW(Addr) _dl_lookup_symbol (const char *undef,
|
||||||
|
struct link_map *undef_map,
|
||||||
const ElfW(Sym) **sym,
|
const ElfW(Sym) **sym,
|
||||||
struct r_scope_elem *symbol_scope[],
|
struct r_scope_elem *symbol_scope[],
|
||||||
const char *reference_name,
|
|
||||||
int reloc_type)
|
int reloc_type)
|
||||||
internal_function;
|
internal_function;
|
||||||
|
|
||||||
/* Lookup versioned symbol. */
|
/* Lookup versioned symbol. */
|
||||||
extern ElfW(Addr) _dl_lookup_versioned_symbol (const char *undef,
|
extern ElfW(Addr) _dl_lookup_versioned_symbol (const char *undef,
|
||||||
|
struct link_map *undef_map,
|
||||||
const ElfW(Sym) **sym,
|
const ElfW(Sym) **sym,
|
||||||
struct r_scope_elem *symbol_scope[],
|
struct r_scope_elem *symbol_scope[],
|
||||||
const char *reference_name,
|
|
||||||
const struct r_found_version *version,
|
const struct r_found_version *version,
|
||||||
int reloc_type)
|
int reloc_type)
|
||||||
internal_function;
|
internal_function;
|
||||||
|
|
||||||
/* For handling RTLD_NEXT we must be able to skip shared objects. */
|
/* For handling RTLD_NEXT we must be able to skip shared objects. */
|
||||||
extern ElfW(Addr) _dl_lookup_symbol_skip (const char *undef,
|
extern ElfW(Addr) _dl_lookup_symbol_skip (const char *undef,
|
||||||
|
struct link_map *undef_map,
|
||||||
const ElfW(Sym) **sym,
|
const ElfW(Sym) **sym,
|
||||||
struct r_scope_elem *symbol_scope[],
|
struct r_scope_elem *symbol_scope[],
|
||||||
const char *reference_name,
|
|
||||||
struct link_map *skip_this)
|
struct link_map *skip_this)
|
||||||
internal_function;
|
internal_function;
|
||||||
|
|
||||||
/* For handling RTLD_NEXT with versioned symbols we must be able to
|
/* For handling RTLD_NEXT with versioned symbols we must be able to
|
||||||
skip shared objects. */
|
skip shared objects. */
|
||||||
extern ElfW(Addr) _dl_lookup_versioned_symbol_skip (const char *undef,
|
extern ElfW(Addr) _dl_lookup_versioned_symbol_skip (const char *undef,
|
||||||
|
struct link_map *undef_map,
|
||||||
const ElfW(Sym) **sym,
|
const ElfW(Sym) **sym,
|
||||||
struct r_scope_elem *symbol_scope[],
|
struct r_scope_elem *symbol_scope[],
|
||||||
const char *reference_name,
|
|
||||||
const struct r_found_version *version,
|
const struct r_found_version *version,
|
||||||
struct link_map *skip_this)
|
struct link_map *skip_this)
|
||||||
internal_function;
|
internal_function;
|
||||||
|
|
|
@ -63,4 +63,13 @@ extern int __profil __P ((unsigned short int *__sample_buffer, size_t __size,
|
||||||
size_t __offset, unsigned int __scale));
|
size_t __offset, unsigned int __scale));
|
||||||
extern int __getdtablesize __P ((void));
|
extern int __getdtablesize __P ((void));
|
||||||
extern int __brk __P ((__ptr_t __addr));
|
extern int __brk __P ((__ptr_t __addr));
|
||||||
|
|
||||||
|
|
||||||
|
/* This variable is set nonzero at startup if the process's effective
|
||||||
|
IDs differ from its real IDs, or it is otherwise indicated that
|
||||||
|
extra security should be used. When this is set the dynamic linker
|
||||||
|
and some functions contained in the C library ignore various
|
||||||
|
environment variables that normally affect them. */
|
||||||
|
extern int __libc_enable_secure;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -927,16 +927,7 @@ extern int lockf64 __P ((int __fd, int __cmd, __off64_t __len));
|
||||||
({ long int __result; \
|
({ long int __result; \
|
||||||
do __result = (long int) (expression); \
|
do __result = (long int) (expression); \
|
||||||
while (__result == -1L && errno == EINTR); \
|
while (__result == -1L && errno == EINTR); \
|
||||||
__result; })) \
|
__result; }))
|
||||||
|
|
||||||
|
|
||||||
/* This variable is set nonzero at startup if the process's effective
|
|
||||||
IDs differ from its real IDs, or it is otherwise indicated that
|
|
||||||
extra security should be used. When this is set the dynamic linker
|
|
||||||
and some functions contained in the C library ignore various
|
|
||||||
environment variables that normally affect them. */
|
|
||||||
extern int __libc_enable_secure;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined __USE_POSIX199309 || defined __USE_UNIX98
|
#if defined __USE_POSIX199309 || defined __USE_UNIX98
|
||||||
|
|
Loading…
Reference in New Issue