aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-runtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-runtime.c')
-rw-r--r--elf/dl-runtime.c320
1 files changed, 52 insertions, 268 deletions
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index ee2b8b5f6c..a0aecda2e8 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -1,5 +1,5 @@
/* On-demand PLT fixup for shared objects.
- Copyright (C) 1995-2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1995-2002, 2003, 2004 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
@@ -22,12 +22,8 @@
#include <alloca.h>
#include <stdlib.h>
#include <unistd.h>
-#include <sys/param.h>
#include <ldsodefs.h>
-#include <sysdep-cancel.h>
#include "dynamic-link.h"
-#include <tls.h>
-
#if (!defined ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
|| ELF_MACHINE_NO_REL
@@ -55,15 +51,15 @@
function. */
#ifndef ELF_MACHINE_NO_PLT
-DL_FIXUP_VALUE_TYPE
-__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
-_dl_fixup (
+static ElfW(Addr)
+__attribute ((used, noinline)) ARCH_FIXUP_ATTRIBUTE
+fixup (
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
- ELF_MACHINE_RUNTIME_FIXUP_ARGS,
+ ELF_MACHINE_RUNTIME_FIXUP_ARGS,
# endif
- /* GKM FIXME: Fix trampoline to pass bounds so we can do
- without the `__unbounded' qualifier. */
- struct link_map *__unbounded l, ElfW(Word) reloc_offset)
+ /* GKM FIXME: Fix trampoline to pass bounds so we can do
+ without the `__unbounded' qualifier. */
+ struct link_map *__unbounded l, ElfW(Word) reloc_offset)
{
const ElfW(Sym) *const symtab
= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
@@ -74,7 +70,7 @@ _dl_fixup (
const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
lookup_t result;
- DL_FIXUP_VALUE_TYPE value;
+ ElfW(Addr) value;
/* Sanity check that we're really looking at a PLT relocation. */
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
@@ -84,6 +80,8 @@ _dl_fixup (
if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
{
const struct r_found_version *version = NULL;
+ // XXX Why exactly do we have the differentiation of the flags here?
+ int flags = DL_LOOKUP_ADD_DEPENDENCY;
if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
@@ -93,35 +91,27 @@ _dl_fixup (
version = &l->l_versions[ndx];
if (version->hash == 0)
version = NULL;
+ else
+ flags = 0;
}
- /* We need to keep the scope around so do some locking. This is
- not necessary for objects which cannot be unloaded or when
- we are not using any threads (yet). */
- int flags = DL_LOOKUP_ADD_DEPENDENCY;
- if (!RTLD_SINGLE_THREAD_P)
- THREAD_GSCOPE_SET_FLAG ();
-
- result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
- version, ELF_RTYPE_CLASS_PLT, flags, NULL);
-
- /* We are done with the global scope. */
- if (!RTLD_SINGLE_THREAD_P)
- THREAD_GSCOPE_RESET_FLAG ();
+ result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
+ l->l_scope, version, ELF_RTYPE_CLASS_PLT,
+ DL_LOOKUP_ADD_DEPENDENCY, NULL);
/* Currently result contains the base load address (or link map)
of the object that defines sym. Now add in the symbol
offset. */
- value = DL_FIXUP_MAKE_VALUE (result,
- sym ? (LOOKUP_VALUE_ADDRESS (result)
- + sym->st_value) : 0);
+ value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
}
else
{
/* We already found the symbol. The module (and therefore its load
address) is also known. */
- value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + sym->st_value);
+ value = l->l_addr + sym->st_value;
+#ifdef DL_LOOKUP_RETURNS_MAP
result = l;
+#endif
}
/* And now perhaps the relocation addend. */
@@ -137,45 +127,45 @@ _dl_fixup (
#if !defined PROF && !defined ELF_MACHINE_NO_PLT && !__BOUNDED_POINTERS__
-DL_FIXUP_VALUE_TYPE
-__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
-_dl_profile_fixup (
+static ElfW(Addr)
+__attribute ((used, noinline)) ARCH_FIXUP_ATTRIBUTE
+profile_fixup (
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
- ELF_MACHINE_RUNTIME_FIXUP_ARGS,
+ ELF_MACHINE_RUNTIME_FIXUP_ARGS,
#endif
- struct link_map *l, ElfW(Word) reloc_offset,
- ElfW(Addr) retaddr, void *regs, long int *framesizep)
+ struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
{
void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = INTUSE(_dl_mcount);
+ ElfW(Addr) *resultp;
+ lookup_t result;
+ ElfW(Addr) value;
/* This is the address in the array where we store the result of previous
relocations. */
- struct reloc_result *reloc_result
- = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
- DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
+ resultp = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
- DL_FIXUP_VALUE_TYPE value = *resultp;
- if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0)
+ value = *resultp;
+ if (value == 0)
{
/* This is the first time we have to relocate this object. */
const ElfW(Sym) *const symtab
= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
- const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]);
+ const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
const PLTREL *const reloc
= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
- const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)];
- const ElfW(Sym) *defsym = refsym;
- lookup_t result;
+ const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
/* Sanity check that we're really looking at a PLT relocation. */
assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
/* Look up the target symbol. If the symbol is marked STV_PROTECTED
don't look in the global scope. */
- if (__builtin_expect (ELFW(ST_VISIBILITY) (refsym->st_other), 0) == 0)
+ if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
{
const struct r_found_version *version = NULL;
+ // XXX Why exactly do we have the differentiation of the flags here?
+ int flags = DL_LOOKUP_ADD_DEPENDENCY;
if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
{
@@ -185,208 +175,38 @@ _dl_profile_fixup (
version = &l->l_versions[ndx];
if (version->hash == 0)
version = NULL;
+ else
+ flags = 0;
}
- /* We need to keep the scope around so do some locking. This is
- not necessary for objects which cannot be unloaded or when
- we are not using any threads (yet). */
- int flags = DL_LOOKUP_ADD_DEPENDENCY;
- if (!RTLD_SINGLE_THREAD_P)
- THREAD_GSCOPE_SET_FLAG ();
-
- result = _dl_lookup_symbol_x (strtab + refsym->st_name, l,
- &defsym, l->l_scope, version,
- ELF_RTYPE_CLASS_PLT, flags, NULL);
-
- /* We are done with the global scope. */
- if (!RTLD_SINGLE_THREAD_P)
- THREAD_GSCOPE_RESET_FLAG ();
+ result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
+ l->l_scope, version,
+ ELF_RTYPE_CLASS_PLT,
+ DL_LOOKUP_ADD_DEPENDENCY, NULL);
/* Currently result contains the base load address (or link map)
of the object that defines sym. Now add in the symbol
offset. */
- value = DL_FIXUP_MAKE_VALUE (result,
- defsym != NULL
- ? LOOKUP_VALUE_ADDRESS (result)
- + defsym->st_value : 0);
+ value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
}
else
{
/* We already found the symbol. The module (and therefore its load
address) is also known. */
- value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + refsym->st_value);
+ value = l->l_addr + sym->st_value;
+#ifdef DL_LOOKUP_RETURNS_MAP
result = l;
+#endif
}
/* And now perhaps the relocation addend. */
value = elf_machine_plt_value (l, reloc, value);
-#ifdef SHARED
- /* Auditing checkpoint: we have a new binding. Provide the
- auditing libraries the possibility to change the value and
- tell us whether further auditing is wanted. */
- if (defsym != NULL && GLRO(dl_naudit) > 0)
- {
- reloc_result->bound = result;
- /* Compute index of the symbol entry in the symbol table of
- the DSO with the definition. */
- reloc_result->boundndx = (defsym
- - (ElfW(Sym) *) D_PTR (result,
- l_info[DT_SYMTAB]));
-
- /* Determine whether any of the two participating DSOs is
- interested in auditing. */
- if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)
- {
- unsigned int altvalue = 0;
- struct audit_ifaces *afct = GLRO(dl_audit);
- /* Synthesize a symbol record where the st_value field is
- the result. */
- ElfW(Sym) sym = *defsym;
- sym.st_value = DL_FIXUP_VALUE_ADDR (value);
-
- /* Keep track whether there is any interest in tracing
- the call in the lower two bits. */
- assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
- assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
- reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
-
- const char *strtab2 = (const void *) D_PTR (result,
- l_info[DT_STRTAB]);
-
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- /* XXX Check whether both DSOs must request action or
- only one */
- if ((l->l_audit[cnt].bindflags & LA_FLG_BINDFROM) != 0
- && (result->l_audit[cnt].bindflags & LA_FLG_BINDTO) != 0)
- {
- unsigned int flags = altvalue;
- if (afct->symbind != NULL)
- {
- uintptr_t new_value
- = afct->symbind (&sym, reloc_result->boundndx,
- &l->l_audit[cnt].cookie,
- &result->l_audit[cnt].cookie,
- &flags,
- strtab2 + defsym->st_name);
- if (new_value != (uintptr_t) sym.st_value)
- {
- altvalue = LA_SYMB_ALTVALUE;
- sym.st_value = new_value;
- }
- }
-
- /* Remember the results for every audit library and
- store a summary in the first two bits. */
- reloc_result->enterexit
- &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
- reloc_result->enterexit
- |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
- << ((cnt + 1) * 2));
- }
- else
- /* If the bind flags say this auditor is not interested,
- set the bits manually. */
- reloc_result->enterexit
- |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
- << ((cnt + 1) * 2));
-
- afct = afct->next;
- }
-
- reloc_result->flags = altvalue;
- value = DL_FIXUP_ADDR_VALUE (sym.st_value);
- }
- else
- /* Set all bits since this symbol binding is not interesting. */
- reloc_result->enterexit = (1u << DL_NNS) - 1;
- }
-#endif
-
/* Store the result for later runs. */
if (__builtin_expect (! GLRO(dl_bind_not), 1))
*resultp = value;
}
- /* By default we do not call the pltexit function. */
- long int framesize = -1;
-
-#ifdef SHARED
- /* Auditing checkpoint: report the PLT entering and allow the
- auditors to change the value. */
- if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0
- /* Don't do anything if no auditor wants to intercept this call. */
- && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
- {
- ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
- l_info[DT_SYMTAB])
- + reloc_result->boundndx);
-
- /* Set up the sym parameter. */
- ElfW(Sym) sym = *defsym;
- sym.st_value = DL_FIXUP_VALUE_ADDR (value);
-
- /* Get the symbol name. */
- const char *strtab = (const void *) D_PTR (reloc_result->bound,
- l_info[DT_STRTAB]);
- const char *symname = strtab + sym.st_name;
-
- /* Keep track of overwritten addresses. */
- unsigned int altvalue = reloc_result->flags;
-
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->ARCH_LA_PLTENTER != NULL
- && (reloc_result->enterexit
- & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
- {
- unsigned int flags = altvalue;
- long int new_framesize = -1;
- uintptr_t new_value
- = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
- &l->l_audit[cnt].cookie,
- &reloc_result->bound->l_audit[cnt].cookie,
- regs, &flags, symname,
- &new_framesize);
- if (new_value != (uintptr_t) sym.st_value)
- {
- altvalue = LA_SYMB_ALTVALUE;
- sym.st_value = new_value;
- }
-
- /* Remember the results for every audit library and
- store a summary in the first two bits. */
- reloc_result->enterexit
- |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
- << (2 * (cnt + 1)));
-
- if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
- << (2 * (cnt + 1))))
- == 0 && new_framesize != -1 && framesize != -2)
- {
- /* If this is the first call providing information,
- use it. */
- if (framesize == -1)
- framesize = new_framesize;
- /* If two pltenter calls provide conflicting information,
- use the larger value. */
- else if (new_framesize != framesize)
- framesize = MAX (new_framesize, framesize);
- }
- }
-
- afct = afct->next;
- }
-
- value = DL_FIXUP_ADDR_VALUE (sym.st_value);
- }
-#endif
-
- /* Store the frame size information. */
- *framesizep = framesize;
-
- (*mcount_fct) (retaddr, DL_FIXUP_VALUE_CODE_ADDR (value));
+ (*mcount_fct) (retaddr, value);
return value;
}
@@ -394,45 +214,9 @@ _dl_profile_fixup (
#endif /* PROF && ELF_MACHINE_NO_PLT */
-#include <stdio.h>
-void
-ARCH_FIXUP_ATTRIBUTE
-_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_offset,
- const void *inregs, void *outregs)
-{
-#ifdef SHARED
- /* This is the address in the array where we store the result of previous
- relocations. */
- // XXX Maybe the bound information must be stored on the stack since
- // XXX with bind_not a new value could have been stored in the meantime.
- struct reloc_result *reloc_result
- = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
- ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
- l_info[DT_SYMTAB])
- + reloc_result->boundndx);
-
- /* Set up the sym parameter. */
- ElfW(Sym) sym = *defsym;
-
- /* Get the symbol name. */
- const char *strtab = (const void *) D_PTR (reloc_result->bound,
- l_info[DT_STRTAB]);
- const char *symname = strtab + sym.st_name;
-
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->ARCH_LA_PLTEXIT != NULL
- && (reloc_result->enterexit
- & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
- {
- afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
- &l->l_audit[cnt].cookie,
- &reloc_result->bound->l_audit[cnt].cookie,
- inregs, outregs, symname);
- }
+/* This macro is defined in dl-machine.h to define the entry point called
+ by the PLT. The `fixup' function above does the real work, but a little
+ more twiddling is needed to get the stack right and jump to the address
+ finally resolved. */
- afct = afct->next;
- }
-#endif
-}
+ELF_MACHINE_RUNTIME_TRAMPOLINE