aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/Makefile2
-rw-r--r--elf/dl-addr.c85
-rw-r--r--elf/dl-runtime.c174
-rw-r--r--elf/dladdr.c64
-rw-r--r--elf/dlfcn.h2
-rw-r--r--elf/link.h4
-rw-r--r--elf/rtld.c2
7 files changed, 181 insertions, 152 deletions
diff --git a/elf/Makefile b/elf/Makefile
index fb85b85..5f78c5c 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -22,7 +22,7 @@ subdir := elf
headers = elf.h bits/elfclass.h bits/dlfcn.h link.h dlfcn.h
routines = $(dl-routines) dl-open dl-close dl-symbol dl-support \
- enbl-secure
+ dl-addr enbl-secure
# The core dynamic linking functions are in libc for the static and
# profiled libraries.
diff --git a/elf/dl-addr.c b/elf/dl-addr.c
new file mode 100644
index 0000000..d50cc4b
--- /dev/null
+++ b/elf/dl-addr.c
@@ -0,0 +1,85 @@
+/* Locate the shared object symbol nearest a given address.
+ Copyright (C) 1996, 1997 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
+ 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 <stddef.h>
+#include <link.h>
+#include <dlfcn.h>
+
+
+int
+_dl_addr (const void *address, Dl_info *info)
+{
+ const ElfW(Addr) addr = (ElfW(Addr)) address;
+ struct link_map *l, *match;
+ const ElfW(Sym) *symtab, *matchsym;
+ const char *strtab;
+
+ /* Find the highest-addressed object that ADDRESS is not below. */
+ match = NULL;
+ for (l = _dl_loaded; l; l = l->l_next)
+ if (addr >= l->l_addr && !match || match->l_addr < l->l_addr)
+ match = l;
+
+ if (match)
+ {
+ /* We know ADDRESS lies within MATCH if in any shared object.
+ Make sure it isn't past the end of MATCH's segments. */
+ size_t n = match->l_phnum;
+ do
+ --n;
+ while (match->l_phdr[n].p_type != PT_LOAD);
+ if (addr >= (match->l_addr +
+ match->l_phdr[n].p_vaddr + match->l_phdr[n].p_memsz))
+ /* Off the end of the highest-addressed shared object. */
+ return 0;
+ }
+ else
+ return 0;
+
+ /* Now we know what object the address lies in. */
+ info->dli_fname = match->l_name;
+ info->dli_fbase = (void *) match->l_addr;
+
+ symtab = ((void *) match->l_addr + match->l_info[DT_SYMTAB]->d_un.d_ptr);
+ strtab = ((void *) match->l_addr + match->l_info[DT_STRTAB]->d_un.d_ptr);
+
+ /* We assume that the string table follows the symbol table, because
+ there is no way in ELF to know the size of the dynamic symbol table!! */
+ for (matchsym = NULL; (void *) symtab < (void *) strtab; ++symtab)
+ if (addr >= match->l_addr + symtab->st_value && !matchsym ||
+ matchsym->st_value < symtab->st_value &&
+ ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL ||
+ ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
+ matchsym = symtab;
+
+ if (matchsym)
+ {
+ /* We found a symbol close by. Fill in its name and exact address. */
+ info->dli_sname = strtab + matchsym->st_name;
+ info->dli_saddr = (void *) (match->l_addr + matchsym->st_value);
+ }
+ else
+ {
+ /* No symbol matches. We return only the containing object. */
+ info->dli_sname = NULL;
+ info->dli_saddr = NULL;
+ }
+
+ return 1;
+}
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index e7132ed..3f09d72 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -70,37 +70,16 @@ _dl_object_relocation_scope (struct link_map *l)
#include "dynamic-link.h"
-/* Figure out the right type, Rel or Rela. */
-#define elf_machine_rel 1
-#define elf_machine_rela 2
-#if elf_machine_relplt == elf_machine_rel
-# define PLTREL ElfW(Rel)
-#elif elf_machine_relplt == elf_machine_rela
-# define PLTREL ElfW(Rela)
+#if !defined ELF_MACHINE_NO_RELA || ELF_MACHINE_NO_REL
+# define PLTREL ElfW(Rela)
#else
-# error "dl-machine.h bug: elf_machine_relplt not rel or rela"
+# define PLTREL ElfW(Rel)
#endif
-#undef elf_machine_rel
-#undef elf_machine_rela
#ifndef VERSYMIDX
# define VERSYMIDX(sym) (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (sym))
#endif
-#ifndef ELF_FIXUP_RETURN_VALUE
-#define ELF_FIXUP_RETURN_VALUE(map, result) (result)
-#endif
-
-/* We need to define the function as a local symbol so that the reference
- in the trampoline code will be a local PC-relative call. Tell the
- compiler not to worry that the function appears not to be called. */
-
-static ElfW(Addr) fixup (
-#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
- ELF_MACHINE_RUNTIME_FIXUP_ARGS,
-#endif
- struct link_map *l, ElfW(Word) reloc_offset)
- __attribute__ ((unused));
/* This function is called through a special trampoline from the PLT the
first time each PLT entry is called. We must perform the relocation
@@ -109,7 +88,7 @@ static ElfW(Addr) fixup (
to that address. Future calls will bounce directly from the PLT to the
function. */
-static ElfW(Addr)
+static ElfW(Addr) __attribute__ ((unused))
fixup (
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
@@ -124,57 +103,63 @@ fixup (
const PLTREL *const reloc
= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
reloc_offset);
- ElfW(Addr) *const rel_addr = (ElfW(Addr) *)(l->l_addr + reloc->r_offset);
+ const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
+ void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
+ ElfW(Addr) value;
/* Set up the scope to find symbols referenced by this object. */
struct link_map **scope = _dl_object_relocation_scope (l);
- {
- const struct r_found_version *here_version;
-
- /* This macro is used as a callback from the elf_machine_relplt code. */
-#define RESOLVE(ref, version, flags) \
- ((version) != NULL && (version)->hash != 0 \
- ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, (ref), scope, \
- l->l_name, (version), (flags)) \
- : _dl_lookup_symbol (strtab + (*ref)->st_name, (ref), scope, \
- l->l_name, (flags)))
-#include "dynamic-link.h"
+ /* Sanity check that we're really looking at a PLT relocation. */
+ assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
- /* Perform the specified relocation. */
- if (l->l_info[VERSYMIDX (DT_VERSYM)])
+ /* Look up the target symbol. */
+ switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
+ {
+ default:
{
- const ElfW(Half) *version =
- (const ElfW(Half) *) (l->l_addr +
- l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
- ElfW(Half) ndx = version[ELFW(R_SYM) (reloc->r_info)];
-
- here_version = &l->l_versions[ndx];
+ const ElfW(Half) *vernum = (const ElfW(Half) *)
+ (l->l_addr + 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,
+ &sym, scope, l->l_name,
+ version, ELF_MACHINE_JMP_SLOT);
+ break;
+ }
}
- else
- here_version = NULL;
+ case 0:
+ value = _dl_lookup_symbol (strtab + sym->st_name, &sym, scope,
+ l->l_name, 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);
+
+ /* And now the relocation addend. */
+#ifndef ELF_MACHINE_NO_RELA
+ if (l->l_info[DT_PLTRELSZ]->d_un.d_val == sizeof (ElfW(Rela)))
+ value += reloc->r_addend;
+#elif ELF_MACHINE_NO_REL
+ value += reloc->r_addend;
+#endif
- elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
- here_version, (void *) rel_addr);
- }
+ /* Finally, fix up the plt itself. */
+ elf_machine_fixup_plt (l, reloc, rel_addr, value);
*_dl_global_scope_end = NULL;
- /* Return the address that was written by the relocation. */
- return ELF_FIXUP_RETURN_VALUE(l, *rel_addr);
+ return value;
}
#ifndef PROF
-static ElfW(Addr)
-profile_fixup (
-#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
- ELF_MACHINE_RUNTIME_FIXUP_ARGS,
-#endif
- struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
- __attribute__ ((unused));
-static ElfW(Addr)
+static ElfW(Addr) __attribute__ ((unused))
profile_fixup (
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
@@ -182,6 +167,7 @@ profile_fixup (
struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
{
void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
+
const ElfW(Sym) *const symtab
= (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
const char *strtab =
@@ -190,47 +176,57 @@ profile_fixup (
const PLTREL *const reloc
= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
reloc_offset);
- ElfW(Addr) result;
+ const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
+ ElfW(Addr) value;
/* Set up the scope to find symbols referenced by this object. */
struct link_map **scope = _dl_object_relocation_scope (l);
- {
- const struct r_found_version *here_version;
+ /* Sanity check that we're really looking at a PLT relocation. */
+ assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
- /* This macro is used as a callback from the elf_machine_relplt code. */
-#define RESOLVE(ref, version, flags) \
- ((version) != NULL && (version)->hash != 0 \
- ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, (ref), scope, \
- l->l_name, (version), (flags)) \
- : _dl_lookup_symbol (strtab + (*ref)->st_name, (ref), scope, \
- l->l_name, (flags)))
-#include "dynamic-link.h"
-
- /* Perform the specified relocation. */
- if (l->l_info[VERSYMIDX (DT_VERSYM)])
+ /* Look up the target symbol. */
+ switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
+ {
+ default:
{
- const ElfW(Half) *version =
- (const ElfW(Half) *) (l->l_addr +
- l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
- ElfW(Half) ndx = version[ELFW(R_SYM) (reloc->r_info)];
-
- here_version = &l->l_versions[ndx];
+ const ElfW(Half) *vernum = (const ElfW(Half) *)
+ (l->l_addr + 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,
+ &sym, scope, l->l_name,
+ version, ELF_MACHINE_JMP_SLOT);
+ break;
+ }
}
- else
- here_version = NULL;
+ case 0:
+ value = _dl_lookup_symbol (strtab + sym->st_name, &sym, scope,
+ l->l_name, 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);
- elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)],
- here_version, (void *) &result);
- }
+ /* And now the relocation addend. */
+#ifndef ELF_MACHINE_NO_RELA
+ if (l->l_info[DT_PLTRELSZ]->d_un.d_val == sizeof (ElfW(Rela)))
+ value += reloc->r_addend;
+#elif ELF_MACHINE_NO_REL
+ value += reloc->r_addend;
+#endif
*_dl_global_scope_end = NULL;
- (*mcount_fct) (retaddr, ELF_FIXUP_RETURN_VALUE (l, result));
+ (*mcount_fct) (retaddr, value);
- /* Return the address that was written by the relocation. */
- return ELF_FIXUP_RETURN_VALUE (l, result);
+ return value;
}
-#endif
+
+#endif /* PROF */
/* This macro is defined in dl-machine.h to define the entry point called
diff --git a/elf/dladdr.c b/elf/dladdr.c
index 59e9783..d82a9e7 100644
--- a/elf/dladdr.c
+++ b/elf/dladdr.c
@@ -1,5 +1,5 @@
-/* dladdr -- Locate the shared object symbol nearest a given address.
- Copyright (C) 1996 Free Software Foundation, Inc.
+/* Locate the shared object symbol nearest a given address.
+ Copyright (C) 1996, 1997 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
@@ -23,63 +23,7 @@
int
-dladdr (void *address, Dl_info *info)
+dladdr (const void *address, Dl_info *info)
{
- const ElfW(Addr) addr = (ElfW(Addr)) address;
- struct link_map *l, *match;
- const ElfW(Sym) *symtab, *matchsym;
- const char *strtab;
-
- /* Find the highest-addressed object that ADDRESS is not below. */
- match = NULL;
- for (l = _dl_loaded; l; l = l->l_next)
- if (addr >= l->l_addr && !match || match->l_addr < l->l_addr)
- match = l;
-
- if (match)
- {
- /* We know ADDRESS lies within MATCH if in any shared object.
- Make sure it isn't past the end of MATCH's segments. */
- size_t n = match->l_phnum;
- do
- --n;
- while (match->l_phdr[n].p_type != PT_LOAD);
- if (addr >= (match->l_addr +
- match->l_phdr[n].p_vaddr + match->l_phdr[n].p_memsz))
- /* Off the end of the highest-addressed shared object. */
- return 0;
- }
- else
- return 0;
-
- /* Now we know what object the address lies in. */
- info->dli_fname = match->l_name;
- info->dli_fbase = (void *) match->l_addr;
-
- symtab = ((void *) match->l_addr + match->l_info[DT_SYMTAB]->d_un.d_ptr);
- strtab = ((void *) match->l_addr + match->l_info[DT_STRTAB]->d_un.d_ptr);
-
- /* We assume that the string table follows the symbol table, because
- there is no way in ELF to know the size of the dynamic symbol table!! */
- for (matchsym = NULL; (void *) symtab < (void *) strtab; ++symtab)
- if (addr >= match->l_addr + symtab->st_value && !matchsym ||
- matchsym->st_value < symtab->st_value &&
- ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL ||
- ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
- matchsym = symtab;
-
- if (matchsym)
- {
- /* We found a symbol close by. Fill in its name and exact address. */
- info->dli_sname = strtab + matchsym->st_name;
- info->dli_saddr = (void *) (match->l_addr + matchsym->st_value);
- }
- else
- {
- /* No symbol matches. We return only the containing object. */
- info->dli_sname = NULL;
- info->dli_saddr = NULL;
- }
-
- return 1;
+ return _dl_addr (address, info);
}
diff --git a/elf/dlfcn.h b/elf/dlfcn.h
index 9db5fb4..825b484 100644
--- a/elf/dlfcn.h
+++ b/elf/dlfcn.h
@@ -68,7 +68,7 @@ typedef struct
__const char *dli_sname; /* Name of nearest symbol. */
void *dli_saddr; /* Exact value of nearest symbol. */
} Dl_info;
-extern int dladdr __P ((void *__address, Dl_info *__info));
+extern int dladdr __P ((const void *__address, Dl_info *__info));
__END_DECLS
diff --git a/elf/link.h b/elf/link.h
index a90854a..c4b0a4f 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -27,6 +27,7 @@
#include <stddef.h>
#include <elf.h>
+#include <dlfcn.h>
__BEGIN_DECLS
@@ -358,6 +359,9 @@ extern ElfW(Addr) _dl_lookup_versioned_symbol_skip (const char *undef,
const struct r_found_version *version,
struct link_map *skip_this);
+/* Locate shared object containing the given address. */
+extern int _dl_addr (const void *address, Dl_info *info);
+
/* Look up symbol NAME in MAP's scope and return its run-time address. */
extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name);
diff --git a/elf/rtld.c b/elf/rtld.c
index 3e21f1a..74a8f3b 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -671,7 +671,7 @@ of this helper program; chances are you did not intend to run this program.\n",
ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
&_dl_default_scope[2],
"argument",
- ELF_MACHINE_RELOC_NOPLT);
+ ELF_MACHINE_JMP_SLOT);
char buf[20], *bp;
buf[sizeof buf - 1] = '\0';
bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);