summaryrefslogtreecommitdiff
path: root/sysdeps/i386/dl-machine.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/i386/dl-machine.h')
-rw-r--r--sysdeps/i386/dl-machine.h51
1 files changed, 44 insertions, 7 deletions
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index d6fc038411..e517cff0ff 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -81,16 +81,20 @@ elf_machine_load_address (void)
destroys the passed register information. */
static ElfW(Addr) fixup (struct link_map *l, ElfW(Word) reloc_offset)
__attribute__ ((regparm (2), unused));
+static ElfW(Addr) profile_fixup (struct link_map *l, ElfW(Word) reloc_offset,
+ ElfW(Addr) retaddr)
+ __attribute__ ((regparm (3), unused));
#endif
/* Set up the loaded object described by L so its unrelocated PLT
entries will jump to the on-demand fixup code in dl-runtime.c. */
static inline int __attribute__ ((unused))
-elf_machine_runtime_setup (struct link_map *l, int lazy)
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
{
Elf32_Addr *got;
extern void _dl_runtime_resolve (Elf32_Word);
+ extern void _dl_runtime_profile (Elf32_Word);
if (l->l_info[DT_JMPREL] && lazy)
{
@@ -100,9 +104,23 @@ elf_machine_runtime_setup (struct link_map *l, int lazy)
and then jump to _GLOBAL_OFFSET_TABLE[2]. */
got = (Elf32_Addr *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);
got[1] = (Elf32_Addr) l; /* Identify this shared object. */
- /* This function will get called to fix up the GOT entry indicated by
- the offset on the stack, and then jump to the resolved address. */
- got[2] = (Elf32_Addr) &_dl_runtime_resolve;
+
+ /* The got[2] entry contains the address of a function which gets
+ called to get the address of a so far unresolved function and
+ jump to it. The profiling extension of the dynamic linker allows
+ to intercept the calls to collect information. In this case we
+ don't store the address in the GOT so that all future calls also
+ end in this function. */
+ if (profile)
+ {
+ got[2] = (Elf32_Addr) &_dl_runtime_profile;
+ /* Say that we really want profiling and the timers are started. */
+ _dl_profile_map = l;
+ }
+ else
+ /* This function will get called to fix up the GOT entry indicated by
+ the offset on the stack, and then jump to the resolved address. */
+ got[2] = (Elf32_Addr) &_dl_runtime_resolve;
}
return lazy;
@@ -126,12 +144,31 @@ _dl_runtime_resolve:
xchgl %eax, (%esp) # Get %eax contents end store function address.
ret $8 # Jump to function address.
.size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+ .globl _dl_runtime_profile
+ .type _dl_runtime_profile, @function
+_dl_runtime_profile:
+ pushl %eax # Preserve registers otherwise clobbered.
+ pushl %ecx
+ pushl %edx
+ movl 20(%esp), %ecx # Load return address
+ movl 16(%esp), %edx # Copy args pushed by PLT in register. Note
+ movl 12(%esp), %eax # that `fixup' takes its parameters in regs.
+ call profile_fixup # Call resolver.
+ popl %edx # Get register content back.
+ popl %ecx
+ xchgl %eax, (%esp) # Get %eax contents end store function address.
+ ret $8 # Jump to function address.
+ .size _dl_runtime_profile, .-_dl_runtime_profile
");
#else
# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
.globl _dl_runtime_resolve
+ .globl _dl_runtime_profile
.type _dl_runtime_resolve, @function
+ .type _dl_runtime_profile, @function
_dl_runtime_resolve:
+_dl_runtime_profile:
pushl %eax # Preserve registers otherwise clobbered.
pushl %ecx
pushl %edx
@@ -147,6 +184,7 @@ _dl_runtime_resolve:
xchgl %eax, (%esp) # Get %eax contents end store function address.
ret $8 # Jump to function address.
.size _dl_runtime_resolve, .-_dl_runtime_resolve
+ .size _dl_runtime_profile, .-_dl_runtime_profile
");
#endif
/* The PLT uses Elf32_Rel relocs. */
@@ -261,10 +299,9 @@ extern char **_dl_argv;
static inline void
elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
- const Elf32_Sym *sym, const struct r_found_version *version)
+ const Elf32_Sym *sym, const struct r_found_version *version,
+ Elf32_Addr *const reloc_addr)
{
- Elf32_Addr *const reloc_addr = (void *) (map->l_addr + reloc->r_offset);
-
if (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE)
{
#ifndef RTLD_BOOTSTRAP