Use MAP_ANON instead of MAP_ANONYMOUS.
[kopensolaris-gnu/glibc.git] / elf / dl-runtime.c
1 /* On-demand PLT fixup for shared objects.
2    Copyright (C) 1995, 1996, 1997, 1998 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 not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #include <unistd.h>
21 #include <elf/ldsodefs.h>
22 #include "dynamic-link.h"
23
24 #if !defined ELF_MACHINE_NO_RELA || ELF_MACHINE_NO_REL
25 # define PLTREL  ElfW(Rela)
26 #else
27 # define PLTREL  ElfW(Rel)
28 #endif
29
30 #ifndef VERSYMIDX
31 # define VERSYMIDX(sym) (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (sym))
32 #endif
33
34
35 /* This function is called through a special trampoline from the PLT the
36    first time each PLT entry is called.  We must perform the relocation
37    specified in the PLT of the given shared object, and return the resolved
38    function address to the trampoline, which will restart the original call
39    to that address.  Future calls will bounce directly from the PLT to the
40    function.  */
41
42 #ifndef ELF_MACHINE_NO_PLT
43 static ElfW(Addr) __attribute__ ((unused))
44 fixup (
45 # ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
46         ELF_MACHINE_RUNTIME_FIXUP_ARGS,
47 # endif
48        struct link_map *l, ElfW(Word) reloc_offset)
49 {
50   const ElfW(Sym) *const symtab
51     = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
52   const char *strtab =
53     (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
54
55   const PLTREL *const reloc
56     = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
57                       reloc_offset);
58   const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
59   void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
60   ElfW(Addr) value;
61
62   /* Sanity check that we're really looking at a PLT relocation.  */
63   assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
64
65    /* Look up the target symbol.  */
66   switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
67     {
68     default:
69       {
70         const ElfW(Half) *vernum = (const ElfW(Half) *)
71           (l->l_addr + l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
72         ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
73         const struct r_found_version *version = &l->l_versions[ndx];
74
75         if (version->hash != 0)
76           {
77             value = _dl_lookup_versioned_symbol(strtab + sym->st_name,
78                                                 &sym, l->l_scope, l->l_name,
79                                                 version, ELF_MACHINE_JMP_SLOT);
80             break;
81           }
82       }
83     case 0:
84       value = _dl_lookup_symbol (strtab + sym->st_name, &sym, l->l_scope,
85                                  l->l_name, ELF_MACHINE_JMP_SLOT);
86     }
87
88   /* Currently value contains the base load address of the object
89      that defines sym.  Now add in the symbol offset.  */
90   value = (sym ? value + sym->st_value : 0);
91
92   /* And now perhaps the relocation addend.  */
93   value = elf_machine_plt_value (l, reloc, value);
94
95   /* Finally, fix up the plt itself.  */
96   elf_machine_fixup_plt (l, reloc, rel_addr, value);
97
98   return value;
99 }
100 #endif
101
102 #if !defined PROF && !defined ELF_MACHINE_NO_PLT
103
104 static ElfW(Addr) __attribute__ ((unused))
105 profile_fixup (
106 #ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
107        ELF_MACHINE_RUNTIME_FIXUP_ARGS,
108 #endif
109        struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
110 {
111   void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
112   ElfW(Addr) *resultp;
113   ElfW(Addr) value;
114
115   /* This is the address in the array where we store the result of previous
116      relocations.  */
117   resultp = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
118
119   value = *resultp;
120   if (value == 0)
121     {
122       /* This is the first time we have to relocate this object.  */
123       const ElfW(Sym) *const symtab
124         = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
125       const char *strtab =
126         (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
127
128       const PLTREL *const reloc
129         = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
130                           reloc_offset);
131       const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
132
133       /* Sanity check that we're really looking at a PLT relocation.  */
134       assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
135
136       /* Look up the target symbol.  */
137       switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
138         {
139         default:
140           {
141             const ElfW(Half) *vernum = (const ElfW(Half) *)
142               (l->l_addr + l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
143             ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
144             const struct r_found_version *version = &l->l_versions[ndx];
145
146             if (version->hash != 0)
147               {
148                 value = _dl_lookup_versioned_symbol(strtab + sym->st_name,
149                                                     &sym, l->l_scope,
150                                                     l->l_name, version,
151                                                     ELF_MACHINE_JMP_SLOT);
152                 break;
153               }
154           }
155         case 0:
156           value = _dl_lookup_symbol (strtab + sym->st_name, &sym, l->l_scope,
157                                      l->l_name, ELF_MACHINE_JMP_SLOT);
158         }
159
160       /* Currently value contains the base load address of the object
161          that defines sym.  Now add in the symbol offset.  */
162       value = (sym ? value + sym->st_value : 0);
163
164       /* And now perhaps the relocation addend.  */
165       value = elf_machine_plt_value (l, reloc, value);
166
167       /* Store the result for later runs.  */
168       *resultp = value;
169     }
170
171   (*mcount_fct) (retaddr, value);
172
173   return value;
174 }
175
176 #endif /* PROF && ELF_MACHINE_NO_PLT */
177
178
179 /* This macro is defined in dl-machine.h to define the entry point called
180    by the PLT.  The `fixup' function above does the real work, but a little
181    more twiddling is needed to get the stack right and jump to the address
182    finally resolved.  */
183
184 ELF_MACHINE_RUNTIME_TRAMPOLINE