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