e26c2d544bc7d40c2c3e7b2e65122efd49a58c4b
[platform/upstream/glibc.git] / sysdeps / powerpc / powerpc32 / dl-machine.h
1 /* Machine-dependent ELF dynamic relocation inline functions.  PowerPC version.
2    Copyright (C) 1995-2002, 2003 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 #ifndef dl_machine_h
21 #define dl_machine_h
22
23 #define ELF_MACHINE_NAME "powerpc"
24
25 #include <assert.h>
26 #include <dl-tls.h>
27
28 /* Return nonzero iff ELF header is compatible with the running host.  */
29 static inline int
30 elf_machine_matches_host (const Elf32_Ehdr *ehdr)
31 {
32   return ehdr->e_machine == EM_PPC;
33 }
34
35
36 /* Return the link-time address of _DYNAMIC, stored as
37    the first value in the GOT. */
38 static inline Elf32_Addr
39 elf_machine_dynamic (void)
40 {
41   Elf32_Addr *got;
42   asm (" bl _GLOBAL_OFFSET_TABLE_-4@local"
43        : "=l"(got));
44   return *got;
45 }
46
47 /* Return the run-time load address of the shared object.  */
48 static inline Elf32_Addr
49 elf_machine_load_address (void)
50 {
51   unsigned int *got;
52   unsigned int *branchaddr;
53
54   /* This is much harder than you'd expect.  Possibly I'm missing something.
55      The 'obvious' way:
56
57        Apparently, "bcl 20,31,$+4" is what should be used to load LR
58        with the address of the next instruction.
59        I think this is so that machines that do bl/blr pairing don't
60        get confused.
61
62      asm ("bcl 20,31,0f ;"
63           "0: mflr 0 ;"
64           "lis %0,0b@ha;"
65           "addi %0,%0,0b@l;"
66           "subf %0,%0,0"
67           : "=b" (addr) : : "r0", "lr");
68
69      doesn't work, because the linker doesn't have to (and in fact doesn't)
70      update the @ha and @l references; the loader (which runs after this
71      code) will do that.
72
73      Instead, we use the following trick:
74
75      The linker puts the _link-time_ address of _DYNAMIC at the first
76      word in the GOT. We could branch to that address, if we wanted,
77      by using an @local reloc; the linker works this out, so it's safe
78      to use now. We can't, of course, actually branch there, because
79      we'd cause an illegal instruction exception; so we need to compute
80      the address ourselves. That gives us the following code: */
81
82   /* Get address of the 'b _DYNAMIC@local'...  */
83   asm ("bl 0f ;"
84        "b _DYNAMIC@local;"
85        "0:"
86        : "=l"(branchaddr));
87
88   /* ... and the address of the GOT.  */
89   asm (" bl _GLOBAL_OFFSET_TABLE_-4@local"
90        : "=l"(got));
91
92   /* So now work out the difference between where the branch actually points,
93      and the offset of that location in memory from the start of the file.  */
94   return ((Elf32_Addr)branchaddr - *got
95           + ((int)(*branchaddr << 6 & 0xffffff00) >> 6));
96 }
97
98 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */
99
100 /* The PLT uses Elf32_Rela relocs.  */
101 #define elf_machine_relplt elf_machine_rela
102
103 /* This code is used in dl-runtime.c to call the `fixup' function
104    and then redirect to the address it returns.  It is called
105    from code built in the PLT by elf_machine_runtime_setup.  */
106 #if !defined PROF
107 #define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
108         .section \".text\"      \n\
109         .align 2        \n\
110         .globl _dl_runtime_resolve      \n\
111         .type _dl_runtime_resolve,@function     \n\
112 _dl_runtime_resolve:    \n\
113  # We need to save the registers used to pass parameters, and register 0,\n\
114  # which is used by _mcount; the registers are saved in a stack frame.\n\
115         stwu 1,-64(1)   \n\
116         stw 0,12(1)     \n\
117         stw 3,16(1)     \n\
118         stw 4,20(1)     \n\
119  # The code that calls this has put parameters for `fixup' in r12 and r11.\n\
120         mr 3,12 \n\
121         stw 5,24(1)     \n\
122         mr 4,11 \n\
123         stw 6,28(1)     \n\
124         mflr 0  \n\
125  # We also need to save some of the condition register fields.\n\
126         stw 7,32(1)     \n\
127         stw 0,48(1)     \n\
128         stw 8,36(1)     \n\
129         mfcr 0  \n\
130         stw 9,40(1)     \n\
131         stw 10,44(1)    \n\
132         stw 0,8(1)      \n\
133         bl fixup@local  \n\
134  # 'fixup' returns the address we want to branch to.\n\
135         mtctr 3 \n\
136  # Put the registers back...\n\
137         lwz 0,48(1)     \n\
138         lwz 10,44(1)    \n\
139         lwz 9,40(1)     \n\
140         mtlr 0  \n\
141         lwz 8,36(1)     \n\
142         lwz 0,8(1)      \n\
143         lwz 7,32(1)     \n\
144         lwz 6,28(1)     \n\
145         mtcrf 0xFF,0    \n\
146         lwz 5,24(1)     \n\
147         lwz 4,20(1)     \n\
148         lwz 3,16(1)     \n\
149         lwz 0,12(1)     \n\
150  # ...unwind the stack frame, and jump to the PLT entry we updated.\n\
151         addi 1,1,64     \n\
152         bctr    \n\
153         .size    _dl_runtime_resolve,.-_dl_runtime_resolve      \n\
154         \n\
155         .align 2        \n\
156         .globl _dl_prof_resolve \n\
157         .type _dl_prof_resolve,@function        \n\
158 _dl_prof_resolve:       \n\
159  # We need to save the registers used to pass parameters, and register 0,\n\
160  # which is used by _mcount; the registers are saved in a stack frame.\n\
161         stwu 1,-64(1)   \n\
162         stw 0,12(1)     \n\
163         stw 3,16(1)     \n\
164         stw 4,20(1)     \n\
165  # The code that calls this has put parameters for `fixup' in r12 and r11.\n\
166         mr 3,12 \n\
167         stw 5,24(1)     \n\
168         mr 4,11 \n\
169         stw 6,28(1)     \n\
170         mflr 5  \n\
171  # We also need to save some of the condition register fields.\n\
172         stw 7,32(1)     \n\
173         stw 5,48(1)     \n\
174         stw 8,36(1)     \n\
175         mfcr 0  \n\
176         stw 9,40(1)     \n\
177         stw 10,44(1)    \n\
178         stw 0,8(1)      \n\
179         bl profile_fixup@local  \n\
180  # 'fixup' returns the address we want to branch to.\n\
181         mtctr 3 \n\
182  # Put the registers back...\n\
183         lwz 0,48(1)     \n\
184         lwz 10,44(1)    \n\
185         lwz 9,40(1)     \n\
186         mtlr 0  \n\
187         lwz 8,36(1)     \n\
188         lwz 0,8(1)      \n\
189         lwz 7,32(1)     \n\
190         lwz 6,28(1)     \n\
191         mtcrf 0xFF,0    \n\
192         lwz 5,24(1)     \n\
193         lwz 4,20(1)     \n\
194         lwz 3,16(1)     \n\
195         lwz 0,12(1)     \n\
196  # ...unwind the stack frame, and jump to the PLT entry we updated.\n\
197         addi 1,1,64     \n\
198         bctr    \n\
199         .size    _dl_prof_resolve,.-_dl_prof_resolve    \n\
200  # Undo '.section text'.\n\
201         .previous       \n\
202 ");
203 #else
204 # define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
205         .section \".text\"      \n\
206         .align 2        \n\
207         .globl _dl_runtime_resolve      \n\
208         .globl _dl_prof_resolve \n\
209         .type _dl_runtime_resolve,@function     \n\
210         .type _dl_prof_resolve,@function        \n\
211 _dl_runtime_resolve:    \n\
212 _dl_prof_resolve:       \n\
213  # We need to save the registers used to pass parameters, and register 0,\n\
214  # which is used by _mcount; the registers are saved in a stack frame.\n\
215         stwu 1,-64(1)   \n\
216         stw 0,12(1)     \n\
217         stw 3,16(1)     \n\
218         stw 4,20(1)     \n\
219  # The code that calls this has put parameters for `fixup' in r12 and r11.\n\
220         mr 3,12 \n\
221         stw 5,24(1)     \n\
222         mr 4,11 \n\
223         stw 6,28(1)     \n\
224         mflr 0  \n\
225  # We also need to save some of the condition register fields.\n\
226         stw 7,32(1)     \n\
227         stw 0,48(1)     \n\
228         stw 8,36(1)     \n\
229         mfcr 0  \n\
230         stw 9,40(1)     \n\
231         stw 10,44(1)    \n\
232         stw 0,8(1)      \n\
233         bl fixup@local  \n\
234  # 'fixup' returns the address we want to branch to.\n\
235         mtctr 3 \n\
236  # Put the registers back...\n\
237         lwz 0,48(1)     \n\
238         lwz 10,44(1)    \n\
239         lwz 9,40(1)     \n\
240         mtlr 0  \n\
241         lwz 8,36(1)     \n\
242         lwz 0,8(1)      \n\
243         lwz 7,32(1)     \n\
244         lwz 6,28(1)     \n\
245         mtcrf 0xFF,0    \n\
246         lwz 5,24(1)     \n\
247         lwz 4,20(1)     \n\
248         lwz 3,16(1)     \n\
249         lwz 0,12(1)     \n\
250  # ...unwind the stack frame, and jump to the PLT entry we updated.\n\
251         addi 1,1,64     \n\
252         bctr    \n\
253         .size    _dl_runtime_resolve,.-_dl_runtime_resolve      \n\
254 ");
255 #endif
256
257 /* Mask identifying addresses reserved for the user program,
258    where the dynamic linker should not map anything.  */
259 #define ELF_MACHINE_USER_ADDRESS_MASK   0xf0000000UL
260
261 /* The actual _start code is in dl-start.S.  Use a really
262    ugly bit of assembler to let dl-start.o see _dl_start.  */
263 #define RTLD_START asm (".globl _dl_start");
264
265 /* Decide where a relocatable object should be loaded.  */
266 extern ElfW(Addr)
267 __elf_preferred_address(struct link_map *loader, size_t maplength,
268                         ElfW(Addr) mapstartpref);
269 #define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) \
270   __elf_preferred_address (loader, maplength, mapstartpref)
271
272 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
273    PLT entries should not be allowed to define the value.
274    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
275    of the main executable's symbols, as for a COPY reloc.  */
276 /* We never want to use a PLT entry as the destination of a
277    reloc, when what is being relocated is a branch. This is
278    partly for efficiency, but mostly so we avoid loops.  */
279 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
280 #define elf_machine_type_class(type)                    \
281   ((((type) == R_PPC_JMP_SLOT                           \
282     || (type) == R_PPC_REL24                            \
283     || ((type) >= R_PPC_DTPMOD32 /* contiguous TLS */   \
284         && (type) <= R_PPC_DTPREL32)                    \
285     || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT)   \
286    | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY))
287 #else
288 #define elf_machine_type_class(type) \
289   ((((type) == R_PPC_JMP_SLOT                           \
290     || (type) == R_PPC_REL24                            \
291     || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT)   \
292    | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY))
293 #endif
294
295 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
296 #define ELF_MACHINE_JMP_SLOT    R_PPC_JMP_SLOT
297
298 /* The PowerPC never uses REL relocations.  */
299 #define ELF_MACHINE_NO_REL 1
300
301 /* Set up the loaded object described by L so its unrelocated PLT
302    entries will jump to the on-demand fixup code in dl-runtime.c.
303    Also install a small trampoline to be used by entries that have
304    been relocated to an address too far away for a single branch.  */
305 extern int __elf_machine_runtime_setup (struct link_map *map,
306                                         int lazy, int profile);
307 #define elf_machine_runtime_setup __elf_machine_runtime_setup
308
309 /* Change the PLT entry whose reloc is 'reloc' to call the actual routine.  */
310 extern Elf32_Addr __elf_machine_fixup_plt (struct link_map *map,
311                                            const Elf32_Rela *reloc,
312                                            Elf32_Addr *reloc_addr,
313                                            Elf32_Addr finaladdr);
314
315 static inline Elf32_Addr
316 elf_machine_fixup_plt (struct link_map *map, lookup_t t,
317                        const Elf32_Rela *reloc,
318                        Elf32_Addr *reloc_addr, Elf64_Addr finaladdr)
319 {
320   return __elf_machine_fixup_plt (map, reloc, reloc_addr, finaladdr);
321 }
322
323 /* Return the final value of a plt relocation.  */
324 static inline Elf32_Addr
325 elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
326                        Elf32_Addr value)
327 {
328   return value + reloc->r_addend;
329 }
330
331 #endif /* dl_machine_h */
332
333 #ifdef RESOLVE
334
335 /* Do the actual processing of a reloc, once its target address
336    has been determined.  */
337 extern void __process_machine_rela (struct link_map *map,
338                                     const Elf32_Rela *reloc,
339                                     struct link_map *sym_map,
340                                     const Elf32_Sym *sym,
341                                     const Elf32_Sym *refsym,
342                                     Elf32_Addr *const reloc_addr,
343                                     Elf32_Addr finaladdr,
344                                     int rinfo) attribute_hidden;
345
346 /* Call _dl_signal_error when a resolved value overflows a relocated area.  */
347 extern void _dl_reloc_overflow (struct link_map *map,
348                                 const char *name,
349                                 Elf32_Addr *const reloc_addr,
350                                 const Elf32_Sym *sym,
351                                 const Elf32_Sym *refsym) attribute_hidden;
352
353 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
354    LOADADDR is the load address of the object; INFO is an array indexed
355    by DT_* of the .dynamic section info.  */
356
357 inline void
358 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
359                   const Elf32_Sym *sym, const struct r_found_version *version,
360                   Elf32_Addr *const reloc_addr)
361 {
362   const Elf32_Sym *const refsym = sym;
363   Elf32_Addr value;
364   const int r_type = ELF32_R_TYPE (reloc->r_info);
365   struct link_map *sym_map = NULL;
366
367 #ifndef RESOLVE_CONFLICT_FIND_MAP
368   if (r_type == R_PPC_RELATIVE)
369     {
370       *reloc_addr = map->l_addr + reloc->r_addend;
371       return;
372     }
373
374   if (__builtin_expect (r_type == R_PPC_NONE, 0))
375     return;
376
377   /* binutils on ppc32 includes st_value in r_addend for relocations
378      against local symbols.  */
379   if (__builtin_expect (ELF32_ST_BIND (sym->st_info) == STB_LOCAL, 0)
380       && sym->st_shndx != SHN_UNDEF)
381     value = map->l_addr;
382   else
383     {
384 # if defined USE_TLS && !defined RTLD_BOOTSTRAP
385       sym_map = RESOLVE_MAP (&sym, version, r_type);
386       value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
387 # else
388       value = RESOLVE (&sym, version, r_type);
389 #  ifndef RTLD_BOOTSTRAP
390       if (sym != NULL)
391 #  endif
392         value += sym->st_value;
393 # endif
394     }
395   value += reloc->r_addend;
396 #else
397   value = reloc->r_addend;
398 #endif
399
400   /* A small amount of code is duplicated here for speed.  In libc,
401      more than 90% of the relocs are R_PPC_RELATIVE; in the X11 shared
402      libraries, 60% are R_PPC_RELATIVE, 24% are R_PPC_GLOB_DAT or
403      R_PPC_ADDR32, and 16% are R_PPC_JMP_SLOT (which this routine
404      wouldn't usually handle).  As an bonus, doing this here allows
405      the switch statement in __process_machine_rela to work.  */
406   switch (r_type)
407     {
408     case R_PPC_GLOB_DAT:
409     case R_PPC_ADDR32:
410       *reloc_addr = value;
411       break;
412
413 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD) \
414     && !defined RESOLVE_CONFLICT_FIND_MAP
415 # ifdef RTLD_BOOTSTRAP
416 #  define NOT_BOOTSTRAP 0
417 # else
418 #  define NOT_BOOTSTRAP 1
419 # endif
420
421     case R_PPC_DTPMOD32:
422       if (!NOT_BOOTSTRAP)
423         /* During startup the dynamic linker is always index 1.  */
424         *reloc_addr = 1;
425       else if (sym_map != NULL)
426         /* Get the information from the link map returned by the
427            RESOLVE_MAP function.  */
428         *reloc_addr = sym_map->l_tls_modid;
429       break;
430     case R_PPC_DTPREL32:
431       /* During relocation all TLS symbols are defined and used.
432          Therefore the offset is already correct.  */
433       if (NOT_BOOTSTRAP && sym_map != NULL)
434         *reloc_addr = TLS_DTPREL_VALUE (sym, reloc);
435       break;
436     case R_PPC_TPREL32:
437       if (!NOT_BOOTSTRAP || sym_map != NULL)
438         {
439           if (NOT_BOOTSTRAP)
440             CHECK_STATIC_TLS (map, sym_map);
441           *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
442         }
443       break;
444 #endif /* USE_TLS etc. */
445
446 #ifdef RESOLVE_CONFLICT_FIND_MAP
447     case R_PPC_JMP_SLOT:
448       RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
449       /* FALLTHROUGH */
450 #endif
451
452     default:
453       __process_machine_rela (map, reloc, sym_map, sym, refsym,
454                               reloc_addr, value, r_type);
455     }
456 }
457
458 static inline void
459 elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
460                            Elf32_Addr *const reloc_addr)
461 {
462   *reloc_addr = l_addr + reloc->r_addend;
463 }
464
465 static inline void
466 elf_machine_lazy_rel (struct link_map *map,
467                       Elf32_Addr l_addr, const Elf32_Rela *reloc)
468 {
469   /* elf_machine_runtime_setup handles this. */
470 }
471
472 /* The SVR4 ABI specifies that the JMPREL relocs must be inside the
473    DT_RELA table.  */
474 #define ELF_MACHINE_PLTREL_OVERLAP 1
475
476 #endif /* RESOLVE */