Wed May 22 17:22:14 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
[glibc.git] / elf / dl-runtime.c
blob3be90caa69ce9beaeb6d9d9083c63de376cd62c0
1 /* On-demand PLT fixup for shared objects.
2 Copyright (C) 1995, 1996 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA. */
20 #include <link.h>
21 #include "dynamic-link.h"
23 /* Figure out the right type, Rel or Rela. */
24 #define elf_machine_rel 1
25 #define elf_machine_rela 2
26 #if elf_machine_relplt == elf_machine_rel
27 #define PLTREL Elf32_Rel
28 #elif elf_machine_relplt == elf_machine_rela
29 #define PLTREL Elf32_Rela
30 #else
31 #error "dl-machine.h bug: elf_machine_relplt not rel or rela"
32 #endif
33 #undef elf_machine_rel
34 #undef elf_machine_rela
36 /* We need to define the function as a local symbol so that the reference
37 in the trampoline code will be a local PC-relative call. Tell the
38 compiler not to worry that the function appears not to be called. */
40 static Elf32_Addr fixup (
41 #ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
42 ELF_MACHINE_RUNTIME_FIXUP_ARGS,
43 #endif
44 struct link_map *l, Elf32_Word reloc_offset)
45 __attribute__ ((unused));
47 /* This function is called through a special trampoline from the PLT the
48 first time each PLT entry is called. We must perform the relocation
49 specified in the PLT of the given shared object, and return the resolved
50 function address to the trampoline, which will restart the original call
51 to that address. Future calls will bounce directly from the PLT to the
52 function. */
54 static Elf32_Addr
55 fixup (
56 #ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
57 ELF_MACHINE_RUNTIME_FIXUP_ARGS,
58 #endif
59 struct link_map *l, Elf32_Word reloc_offset)
61 const Elf32_Sym *const symtab
62 = (const Elf32_Sym *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
63 const char *strtab =
64 (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
66 const PLTREL *const reloc
67 = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
68 reloc_offset);
70 const Elf32_Sym *definer;
71 Elf32_Addr loadbase;
72 struct link_map *scope, *real_next;
74 /* Look up the symbol's run-time value. */
76 real_next = l->l_next;
77 if (l->l_info[DT_SYMBOLIC])
79 l->l_next = _dl_loaded;
80 if (l->l_prev)
81 l->l_prev->l_next = real_next;
82 scope = l;
84 else
85 scope = _dl_loaded;
87 definer = &symtab[ELF32_R_SYM (reloc->r_info)];
88 loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer,
89 scope, l->l_name, 0);
91 /* Restore list frobnication done above for DT_SYMBOLIC. */
92 l->l_next = real_next;
93 if (l->l_prev)
94 l->l_prev->l_next = l;
96 /* Apply the relocation with that value. */
97 elf_machine_relplt (l, reloc, loadbase, definer);
99 return *(Elf32_Addr *) (l->l_addr + reloc->r_offset);
103 /* This macro is defined in dl-machine.h to define the entry point called
104 by the PLT. The `fixup' function above does the real work, but a little
105 more twiddling is needed to get the stack right and jump to the address
106 finally resolved. */
108 ELF_MACHINE_RUNTIME_TRAMPOLINE