Tue Jun 4 02:25:44 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
[platform/upstream/glibc.git] / elf / dl-runtime.c
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.
4
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.
9
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.
14
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.  */
19
20 #include <link.h>
21 #include "dynamic-link.h"
22
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
35
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.  */
39
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));
46
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.  */
53
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)
60 {
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);
65
66   const PLTREL *const reloc
67     = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
68                       reloc_offset);
69
70   Elf32_Addr resolve (const Elf32_Sym **ref,
71                       Elf32_Addr reloc_addr, int noplt)
72     {
73       struct link_map *scope[2] = { _dl_loaded, NULL };
74       return _dl_lookup_symbol (strtab + (*ref)->st_name, ref,
75                                 scope, l->l_name, reloc_addr, noplt);
76     }
77
78   /* Perform the specified relocation.  */
79   elf_machine_relplt (l, reloc, &symtab[ELF32_R_SYM (reloc->r_info)], resolve);
80
81   return *(Elf32_Addr *) (l->l_addr + reloc->r_offset);
82 }
83
84
85 /* This macro is defined in dl-machine.h to define the entry point called
86    by the PLT.  The `fixup' function above does the real work, but a little
87    more twiddling is needed to get the stack right and jump to the address
88    finally resolved.  */
89
90 ELF_MACHINE_RUNTIME_TRAMPOLINE