glibc/sysdeps/i386/dl-runtime.c

95 lines
3.3 KiB
C
Raw Normal View History

/* On-demand PLT fixup for shared objects. i386 version.
Copyright (C) 1995 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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <link.h>
#include "dynamic-link.h"
/* This function is not called in the normal way. The PLT jumps here, not
using a call. The stack looks like this:
-->8(%esp) address to return to the caller of the function in the PLT
4(%esp) relocation offset for this PLT entry
0(%esp) identifier for this shared object (struct link_map *)
The user expects the real function the PLT refers to to be entered
with 8(%esp) as the top of stack. */
void
_dl_runtime_resolve (Elf32_Word reloc_offset)
{
__label__ return_insn;
struct link_map *l = (void *) (&reloc_offset)[-1];
const Elf32_Sym *const symtab
= (const Elf32_Sym *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
const char *strtab =
(const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
const Elf32_Rel *const reloc
= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
reloc_offset);
const Elf32_Sym *definer;
Elf32_Addr loadbase;
struct link_map *scope, *real_next;
/* Look up the symbol's run-time value. */
real_next = l->l_next;
if (l->l_info[DT_SYMBOLIC])
{
l->l_next = _dl_loaded;
Thu Jun 8 02:50:26 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> * elf/rtld.c [! NDEBUG] (__assert_perror_fail): New function. * hurd/hurdstartup.c (_hurd_startup): Fancier kludge to guess phdr and user entry point addresses. * elf/dl-load.c (open_path): Don't do strlen on DIRPATH if it's null. (_dl_map_object): DT_RPATH value is relative to DT_STRTAB value. * Makerules (install-lib.so): Don't include libc.so. [$(build-shared)=yes] (install): Depend on the installed libc.so file. [$(build-shared)=yes] (install-no-libc.a): Make this, rather than install, depend on the installed $(install-lib.so) files. [$(build-shared)=yes] (install-lib.so): Append libc.so after that rule. * sysdeps/mach/hurd/dl-sysdep.c (_dl_sysdep_start): Add kludge to allocate high addresses to avoid random mappings appearing there. (mmap): Comment out mask; always pass zero. Tue Jun 6 13:34:53 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> * sysdeps/i386/dl-machine.h (ELF_MACHINE_USER_ADDRESS_MASK): New macro. * sysdeps/mach/hurd/dl-sysdep.c (mmap): Use it as mask in vm_map call. * elf/dl-error.c (_dl_catch_error): Clear *ERRSTRING and *OBJNAME when successful. * sysdeps/mach/hurd/dl-sysdep.c (threadvars): New static variable. (__hurd_threadvar_max, __hurd_threadvar_stack_offset): Define these variables, using the `threadvars' buffer. * elf/dl-reloc.c: Don't dereference L->l_prev when it's null. * sysdeps/i386/dl-runtime.c: Likewise. * elf/rtld.c (dl_main): Add missing NULL terminating argument in _dl_sysdep_fatal call. (__assert_fail): Likewise. * locale/Makefile (localedef-modules): Renamed ctype to locale-ctype so as not to conflict with the object file for ctype/ctype.c in the build directory. * sysdeps/i386/dl-machine.h (elf_machine_rel): If MAP->l_type is lt_interpreter, first undo relocation done during bootstrapping.
1995-06-08 09:00:23 +00:00
if (l->l_prev)
l->l_prev->l_next = real_next;
scope = l;
}
else
scope = _dl_loaded;
definer = &symtab[ELF32_R_SYM (reloc->r_info)];
loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer,
scope, l->l_name, 0);
/* Restore list frobnication done above for DT_SYMBOLIC. */
l->l_next = real_next;
Thu Jun 8 02:50:26 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> * elf/rtld.c [! NDEBUG] (__assert_perror_fail): New function. * hurd/hurdstartup.c (_hurd_startup): Fancier kludge to guess phdr and user entry point addresses. * elf/dl-load.c (open_path): Don't do strlen on DIRPATH if it's null. (_dl_map_object): DT_RPATH value is relative to DT_STRTAB value. * Makerules (install-lib.so): Don't include libc.so. [$(build-shared)=yes] (install): Depend on the installed libc.so file. [$(build-shared)=yes] (install-no-libc.a): Make this, rather than install, depend on the installed $(install-lib.so) files. [$(build-shared)=yes] (install-lib.so): Append libc.so after that rule. * sysdeps/mach/hurd/dl-sysdep.c (_dl_sysdep_start): Add kludge to allocate high addresses to avoid random mappings appearing there. (mmap): Comment out mask; always pass zero. Tue Jun 6 13:34:53 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> * sysdeps/i386/dl-machine.h (ELF_MACHINE_USER_ADDRESS_MASK): New macro. * sysdeps/mach/hurd/dl-sysdep.c (mmap): Use it as mask in vm_map call. * elf/dl-error.c (_dl_catch_error): Clear *ERRSTRING and *OBJNAME when successful. * sysdeps/mach/hurd/dl-sysdep.c (threadvars): New static variable. (__hurd_threadvar_max, __hurd_threadvar_stack_offset): Define these variables, using the `threadvars' buffer. * elf/dl-reloc.c: Don't dereference L->l_prev when it's null. * sysdeps/i386/dl-runtime.c: Likewise. * elf/rtld.c (dl_main): Add missing NULL terminating argument in _dl_sysdep_fatal call. (__assert_fail): Likewise. * locale/Makefile (localedef-modules): Renamed ctype to locale-ctype so as not to conflict with the object file for ctype/ctype.c in the build directory. * sysdeps/i386/dl-machine.h (elf_machine_rel): If MAP->l_type is lt_interpreter, first undo relocation done during bootstrapping.
1995-06-08 09:00:23 +00:00
if (l->l_prev)
l->l_prev->l_next = l;
/* Apply the relocation with that value. */
elf_machine_rel (l, reloc, loadbase, definer);
/* The top of the stack is the word we set L from; but this location
holds the address we will return to. Store there the address of a
"ret" instruction, which will pop the stack and run the code at the
address in the next stack word. */
(&reloc_offset)[-1] = (Elf32_Word) &&return_insn;
/* The next stack word is our argument RELOC_OFFSET; but that "ret" will
pop and jump to this location, and the next stack word is the user's
return address. So store here the resolved address of the function
referred to by this PLT entry; once "ret" pops this address, the
function in the shared object will run with the stack arranged just as
when the user entered the PLT. */
(&reloc_offset)[0] = *(Elf32_Word *) (l->l_addr + reloc->r_offset);
return;
return_insn: asm volatile ("ret");
}