Sat Feb 10 13:09:03 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
[platform/upstream/linaro-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 (struct link_map *l, Elf32_Word reloc_offset)
41      __attribute__ ((unused));
42
43 /* This function is called through a special trampoline from the PLT the
44    first time each PLT entry is called.  We must perform the relocation
45    specified in the PLT of the given shared object, and return the resolved
46    function address to the trampoline, which will restart the original call
47    to that address.  Future calls will bounce directly from the PLT to the
48    function.  */
49
50 static Elf32_Addr
51 fixup (
52 #ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
53        ELF_MACHINE_RUNTIME_FIXUP_ARGS,
54 #endif
55        struct link_map *l, Elf32_Word reloc_offset)
56 {
57   const Elf32_Sym *const symtab
58     = (const Elf32_Sym *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
59   const char *strtab =
60     (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
61
62   const PLTREL *const reloc
63     = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
64                       reloc_offset);
65
66   const Elf32_Sym *definer;
67   Elf32_Addr loadbase;
68   struct link_map *scope, *real_next;
69
70   /* Look up the symbol's run-time value.  */
71
72   real_next = l->l_next;
73   if (l->l_info[DT_SYMBOLIC])
74     {
75       l->l_next = _dl_loaded;
76       if (l->l_prev)
77         l->l_prev->l_next = real_next;
78       scope = l;
79     }
80   else
81     scope = _dl_loaded;
82
83   definer = &symtab[ELF32_R_SYM (reloc->r_info)];
84   loadbase = _dl_lookup_symbol (strtab + definer->st_name, &definer,
85                                 scope, l->l_name, 0);
86
87   /* Restore list frobnication done above for DT_SYMBOLIC.  */
88   l->l_next = real_next;
89   if (l->l_prev)
90     l->l_prev->l_next = l;
91
92   /* Apply the relocation with that value.  */
93   elf_machine_relplt (l, reloc, loadbase, definer);
94
95   return *(Elf32_Addr *) (l->l_addr + reloc->r_offset);
96 }
97
98
99 /* This macro is defined in dl-machine.h to define the entry point called
100    by the PLT.  The `fixup' function above does the real work, but a little
101    more twiddling is needed to get the stack right and jump to the address
102    finally resolved.  */
103
104 ELF_MACHINE_RUNTIME_TRAMPOLINE