* sysdeps/generic/ldsodefs.h (DL_LOOKUP_GSCOPE_LOCK): New definition.
[platform/upstream/glibc.git] / elf / dl-runtime.c
1 /* On-demand PLT fixup for shared objects.
2    Copyright (C) 1995-2006, 2007 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 Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the 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    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #define IN_DL_RUNTIME 1         /* This can be tested in dl-machine.h.  */
21
22 #include <alloca.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/param.h>
26 #include <ldsodefs.h>
27 #include <sysdep-cancel.h>
28 #include "dynamic-link.h"
29 #include <tls.h>
30
31
32 #if (!defined ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
33     || ELF_MACHINE_NO_REL
34 # define PLTREL  ElfW(Rela)
35 #else
36 # define PLTREL  ElfW(Rel)
37 #endif
38
39 #ifndef VERSYMIDX
40 # define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
41 #endif
42
43 /* The fixup functions might have need special attributes.  If none
44    are provided define the macro as empty.  */
45 #ifndef ARCH_FIXUP_ATTRIBUTE
46 # define ARCH_FIXUP_ATTRIBUTE
47 #endif
48
49
50 /* This function is called through a special trampoline from the PLT the
51    first time each PLT entry is called.  We must perform the relocation
52    specified in the PLT of the given shared object, and return the resolved
53    function address to the trampoline, which will restart the original call
54    to that address.  Future calls will bounce directly from the PLT to the
55    function.  */
56
57 #ifndef ELF_MACHINE_NO_PLT
58 DL_FIXUP_VALUE_TYPE
59 __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
60 _dl_fixup (
61 # ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
62            ELF_MACHINE_RUNTIME_FIXUP_ARGS,
63 # endif
64            /* GKM FIXME: Fix trampoline to pass bounds so we can do
65               without the `__unbounded' qualifier.  */
66            struct link_map *__unbounded l, ElfW(Word) reloc_offset)
67 {
68   const ElfW(Sym) *const symtab
69     = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
70   const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
71
72   const PLTREL *const reloc
73     = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
74   const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
75   void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
76   lookup_t result;
77   DL_FIXUP_VALUE_TYPE value;
78
79   /* Sanity check that we're really looking at a PLT relocation.  */
80   assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
81
82    /* Look up the target symbol.  If the normal lookup rules are not
83       used don't look in the global scope.  */
84   if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
85     {
86       const struct r_found_version *version = NULL;
87
88       if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
89         {
90           const ElfW(Half) *vernum =
91             (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
92           ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
93           version = &l->l_versions[ndx];
94           if (version->hash == 0)
95             version = NULL;
96         }
97
98       /* We need to keep the scope around so do some locking.  This is
99          not necessary for objects which cannot be unloaded or when
100          we are not using any threads (yet).  */
101       int flags = DL_LOOKUP_ADD_DEPENDENCY;
102       if (!RTLD_SINGLE_THREAD_P)
103         {
104           THREAD_GSCOPE_SET_FLAG ();
105           flags |= DL_LOOKUP_GSCOPE_LOCK;
106         }
107
108       result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
109                                     version, ELF_RTYPE_CLASS_PLT, flags, NULL);
110
111       /* We are done with the global scope.  */
112       if (!RTLD_SINGLE_THREAD_P)
113         THREAD_GSCOPE_RESET_FLAG ();
114
115       /* Currently result contains the base load address (or link map)
116          of the object that defines sym.  Now add in the symbol
117          offset.  */
118       value = DL_FIXUP_MAKE_VALUE (result,
119                                    sym ? (LOOKUP_VALUE_ADDRESS (result)
120                                           + sym->st_value) : 0);
121     }
122   else
123     {
124       /* We already found the symbol.  The module (and therefore its load
125          address) is also known.  */
126       value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + sym->st_value);
127       result = l;
128     }
129
130   /* And now perhaps the relocation addend.  */
131   value = elf_machine_plt_value (l, reloc, value);
132
133   /* Finally, fix up the plt itself.  */
134   if (__builtin_expect (GLRO(dl_bind_not), 0))
135     return value;
136
137   return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
138 }
139 #endif
140
141 #if !defined PROF && !defined ELF_MACHINE_NO_PLT && !__BOUNDED_POINTERS__
142
143 DL_FIXUP_VALUE_TYPE
144 __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
145 _dl_profile_fixup (
146 #ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
147                    ELF_MACHINE_RUNTIME_FIXUP_ARGS,
148 #endif
149                    struct link_map *l, ElfW(Word) reloc_offset,
150                    ElfW(Addr) retaddr, void *regs, long int *framesizep)
151 {
152   void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = INTUSE(_dl_mcount);
153
154   /* This is the address in the array where we store the result of previous
155      relocations.  */
156   struct reloc_result *reloc_result
157     = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
158   DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
159
160   DL_FIXUP_VALUE_TYPE value = *resultp;
161   if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0)
162     {
163       /* This is the first time we have to relocate this object.  */
164       const ElfW(Sym) *const symtab
165         = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
166       const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]);
167
168       const PLTREL *const reloc
169         = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
170       const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)];
171       const ElfW(Sym) *defsym = refsym;
172       lookup_t result;
173
174       /* Sanity check that we're really looking at a PLT relocation.  */
175       assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
176
177       /* Look up the target symbol.  If the symbol is marked STV_PROTECTED
178          don't look in the global scope.  */
179       if (__builtin_expect (ELFW(ST_VISIBILITY) (refsym->st_other), 0) == 0)
180         {
181           const struct r_found_version *version = NULL;
182
183           if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
184             {
185               const ElfW(Half) *vernum =
186                 (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
187               ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
188               version = &l->l_versions[ndx];
189               if (version->hash == 0)
190                 version = NULL;
191             }
192
193           /* We need to keep the scope around so do some locking.  This is
194              not necessary for objects which cannot be unloaded or when
195              we are not using any threads (yet).  */
196           int flags = DL_LOOKUP_ADD_DEPENDENCY;
197           if (!RTLD_SINGLE_THREAD_P)
198             {
199               THREAD_GSCOPE_SET_FLAG ();
200               flags |= DL_LOOKUP_GSCOPE_LOCK;
201             }
202
203           result = _dl_lookup_symbol_x (strtab + refsym->st_name, l,
204                                         &defsym, l->l_scope, version,
205                                         ELF_RTYPE_CLASS_PLT, flags, NULL);
206
207           /* We are done with the global scope.  */
208           if (!RTLD_SINGLE_THREAD_P)
209             THREAD_GSCOPE_RESET_FLAG ();
210
211           /* Currently result contains the base load address (or link map)
212              of the object that defines sym.  Now add in the symbol
213              offset.  */
214           value = DL_FIXUP_MAKE_VALUE (result,
215                                        defsym != NULL
216                                        ? LOOKUP_VALUE_ADDRESS (result)
217                                          + defsym->st_value : 0);
218         }
219       else
220         {
221           /* We already found the symbol.  The module (and therefore its load
222              address) is also known.  */
223           value = DL_FIXUP_MAKE_VALUE (l, l->l_addr + refsym->st_value);
224           result = l;
225         }
226       /* And now perhaps the relocation addend.  */
227       value = elf_machine_plt_value (l, reloc, value);
228
229 #ifdef SHARED
230       /* Auditing checkpoint: we have a new binding.  Provide the
231          auditing libraries the possibility to change the value and
232          tell us whether further auditing is wanted.  */
233       if (defsym != NULL && GLRO(dl_naudit) > 0)
234         {
235           reloc_result->bound = result;
236           /* Compute index of the symbol entry in the symbol table of
237              the DSO with the definition.  */
238           reloc_result->boundndx = (defsym
239                                     - (ElfW(Sym) *) D_PTR (result,
240                                                            l_info[DT_SYMTAB]));
241
242           /* Determine whether any of the two participating DSOs is
243              interested in auditing.  */
244           if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)
245             {
246               unsigned int altvalue = 0;
247               struct audit_ifaces *afct = GLRO(dl_audit);
248               /* Synthesize a symbol record where the st_value field is
249                  the result.  */
250               ElfW(Sym) sym = *defsym;
251               sym.st_value = DL_FIXUP_VALUE_ADDR (value);
252
253               /* Keep track whether there is any interest in tracing
254                  the call in the lower two bits.  */
255               assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
256               assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
257               reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
258
259               const char *strtab2 = (const void *) D_PTR (result,
260                                                           l_info[DT_STRTAB]);
261
262               for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
263                 {
264                   /* XXX Check whether both DSOs must request action or
265                      only one */
266                   if ((l->l_audit[cnt].bindflags & LA_FLG_BINDFROM) != 0
267                       && (result->l_audit[cnt].bindflags & LA_FLG_BINDTO) != 0)
268                     {
269                       unsigned int flags = altvalue;
270                       if (afct->symbind != NULL)
271                         {
272                           uintptr_t new_value
273                             = afct->symbind (&sym, reloc_result->boundndx,
274                                              &l->l_audit[cnt].cookie,
275                                              &result->l_audit[cnt].cookie,
276                                              &flags,
277                                              strtab2 + defsym->st_name);
278                           if (new_value != (uintptr_t) sym.st_value)
279                             {
280                               altvalue = LA_SYMB_ALTVALUE;
281                               sym.st_value = new_value;
282                             }
283                         }
284
285                       /* Remember the results for every audit library and
286                          store a summary in the first two bits.  */
287                       reloc_result->enterexit
288                         &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
289                       reloc_result->enterexit
290                         |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
291                             << ((cnt + 1) * 2));
292                     }
293                   else
294                     /* If the bind flags say this auditor is not interested,
295                        set the bits manually.  */
296                     reloc_result->enterexit
297                       |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
298                           << ((cnt + 1) * 2));
299
300                   afct = afct->next;
301                 }
302
303               reloc_result->flags = altvalue;
304               value = DL_FIXUP_ADDR_VALUE (sym.st_value);
305             }
306           else
307             /* Set all bits since this symbol binding is not interesting.  */
308             reloc_result->enterexit = (1u << DL_NNS) - 1;
309         }
310 #endif
311
312       /* Store the result for later runs.  */
313       if (__builtin_expect (! GLRO(dl_bind_not), 1))
314         *resultp = value;
315     }
316
317   /* By default we do not call the pltexit function.  */
318   long int framesize = -1;
319
320 #ifdef SHARED
321   /* Auditing checkpoint: report the PLT entering and allow the
322      auditors to change the value.  */
323   if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0
324       /* Don't do anything if no auditor wants to intercept this call.  */
325       && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
326     {
327       ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
328                                                 l_info[DT_SYMTAB])
329                            + reloc_result->boundndx);
330
331       /* Set up the sym parameter.  */
332       ElfW(Sym) sym = *defsym;
333       sym.st_value = DL_FIXUP_VALUE_ADDR (value);
334
335       /* Get the symbol name.  */
336       const char *strtab = (const void *) D_PTR (reloc_result->bound,
337                                                  l_info[DT_STRTAB]);
338       const char *symname = strtab + sym.st_name;
339
340       /* Keep track of overwritten addresses.  */
341       unsigned int altvalue = reloc_result->flags;
342
343       struct audit_ifaces *afct = GLRO(dl_audit);
344       for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
345         {
346           if (afct->ARCH_LA_PLTENTER != NULL
347               && (reloc_result->enterexit
348                   & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
349             {
350               unsigned int flags = altvalue;
351               long int new_framesize = -1;
352               uintptr_t new_value
353                 = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
354                                           &l->l_audit[cnt].cookie,
355                                           &reloc_result->bound->l_audit[cnt].cookie,
356                                           regs, &flags, symname,
357                                           &new_framesize);
358               if (new_value != (uintptr_t) sym.st_value)
359                 {
360                   altvalue = LA_SYMB_ALTVALUE;
361                   sym.st_value = new_value;
362                 }
363
364               /* Remember the results for every audit library and
365                  store a summary in the first two bits.  */
366               reloc_result->enterexit
367                 |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
368                     << (2 * (cnt + 1)));
369
370               if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
371                                               << (2 * (cnt + 1))))
372                   == 0 && new_framesize != -1 && framesize != -2)
373                 {
374                   /* If this is the first call providing information,
375                      use it.  */
376                   if (framesize == -1)
377                     framesize = new_framesize;
378                   /* If two pltenter calls provide conflicting information,
379                      use the larger value.  */
380                   else if (new_framesize != framesize)
381                     framesize = MAX (new_framesize, framesize);
382                 }
383             }
384
385           afct = afct->next;
386         }
387
388       value = DL_FIXUP_ADDR_VALUE (sym.st_value);
389     }
390 #endif
391
392   /* Store the frame size information.  */
393   *framesizep = framesize;
394
395   (*mcount_fct) (retaddr, DL_FIXUP_VALUE_CODE_ADDR (value));
396
397   return value;
398 }
399
400 #endif /* PROF && ELF_MACHINE_NO_PLT */
401
402
403 #include <stdio.h>
404 void
405 ARCH_FIXUP_ATTRIBUTE
406 _dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_offset,
407                   const void *inregs, void *outregs)
408 {
409 #ifdef SHARED
410   /* This is the address in the array where we store the result of previous
411      relocations.  */
412   // XXX Maybe the bound information must be stored on the stack since
413   // XXX with bind_not a new value could have been stored in the meantime.
414   struct reloc_result *reloc_result
415     = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
416   ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
417                                             l_info[DT_SYMTAB])
418                        + reloc_result->boundndx);
419
420   /* Set up the sym parameter.  */
421   ElfW(Sym) sym = *defsym;
422
423   /* Get the symbol name.  */
424   const char *strtab = (const void *) D_PTR (reloc_result->bound,
425                                              l_info[DT_STRTAB]);
426   const char *symname = strtab + sym.st_name;
427
428   struct audit_ifaces *afct = GLRO(dl_audit);
429   for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
430     {
431       if (afct->ARCH_LA_PLTEXIT != NULL
432           && (reloc_result->enterexit
433               & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
434         {
435           afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
436                                  &l->l_audit[cnt].cookie,
437                                  &reloc_result->bound->l_audit[cnt].cookie,
438                                  inregs, outregs, symname);
439         }
440
441       afct = afct->next;
442     }
443 #endif
444 }