Update.
[glibc.git] / sysdeps / powerpc / powerpc32 / dl-machine.h
blob34858e5a4b0e8bc74ac7331509236bfc15e5ff0b
1 /* Machine-dependent ELF dynamic relocation inline functions. PowerPC version.
2 Copyright (C) 1995-2000,01,02 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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. */
20 #ifndef dl_machine_h
21 #define dl_machine_h
23 #define ELF_MACHINE_NAME "powerpc"
25 #include <assert.h>
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)
31 return ehdr->e_machine == EM_PPC;
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)
40 Elf32_Addr *got;
41 asm (" bl _GLOBAL_OFFSET_TABLE_-4@local"
42 : "=l"(got));
43 return *got;
46 /* Return the run-time load address of the shared object. */
47 static inline Elf32_Addr
48 elf_machine_load_address (void)
50 unsigned int *got;
51 unsigned int *branchaddr;
53 /* This is much harder than you'd expect. Possibly I'm missing something.
54 The 'obvious' way:
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.
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");
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.
72 Instead, we use the following trick:
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: */
81 /* Get address of the 'b _DYNAMIC@local'... */
82 asm ("bl 0f ;"
83 "b _DYNAMIC@local;"
84 "0:"
85 : "=l"(branchaddr));
87 /* ... and the address of the GOT. */
88 asm (" bl _GLOBAL_OFFSET_TABLE_-4@local"
89 : "=l"(got));
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));
97 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */
99 /* The PLT uses Elf32_Rela relocs. */
100 #define elf_machine_relplt elf_machine_rela
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\
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\
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\
254 #endif
256 /* Mask identifying addresses reserved for the user program,
257 where the dynamic linker should not map anything. */
258 #define ELF_MACHINE_USER_ADDRESS_MASK 0xf0000000UL
260 /* The actual _start code is in dl-start.S. Use a really
261 ugly bit of assembler to let dl-start.o see _dl_start. */
262 #define RTLD_START asm (".globl _dl_start");
264 /* Decide where a relocatable object should be loaded. */
265 extern ElfW(Addr)
266 __elf_preferred_address(struct link_map *loader, size_t maplength,
267 ElfW(Addr) mapstartpref);
268 #define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) \
269 __elf_preferred_address (loader, maplength, mapstartpref)
271 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
272 PLT entries should not be allowed to define the value.
273 ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
274 of the main executable's symbols, as for a COPY reloc. */
275 /* We never want to use a PLT entry as the destination of a
276 reloc, when what is being relocated is a branch. This is
277 partly for efficiency, but mostly so we avoid loops. */
278 #define elf_machine_type_class(type) \
279 ((((type) == R_PPC_JMP_SLOT \
280 || (type) == R_PPC_REL24 \
281 || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT) \
282 | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY))
284 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
285 #define ELF_MACHINE_JMP_SLOT R_PPC_JMP_SLOT
287 /* The PowerPC never uses REL relocations. */
288 #define ELF_MACHINE_NO_REL 1
290 /* Set up the loaded object described by L so its unrelocated PLT
291 entries will jump to the on-demand fixup code in dl-runtime.c.
292 Also install a small trampoline to be used by entries that have
293 been relocated to an address too far away for a single branch. */
294 extern int __elf_machine_runtime_setup (struct link_map *map,
295 int lazy, int profile);
296 #define elf_machine_runtime_setup __elf_machine_runtime_setup
298 static inline void
299 elf_machine_lazy_rel (struct link_map *map,
300 Elf32_Addr l_addr, const Elf32_Rela *reloc)
302 /* elf_machine_runtime_setup handles this. */
305 /* Change the PLT entry whose reloc is 'reloc' to call the actual routine. */
306 extern Elf32_Addr __elf_machine_fixup_plt (struct link_map *map,
307 const Elf32_Rela *reloc,
308 Elf32_Addr *reloc_addr,
309 Elf32_Addr finaladdr);
311 static inline Elf32_Addr
312 elf_machine_fixup_plt (struct link_map *map, lookup_t t,
313 const Elf32_Rela *reloc,
314 Elf32_Addr *reloc_addr, Elf64_Addr finaladdr)
316 return __elf_machine_fixup_plt (map, reloc, reloc_addr, finaladdr);
319 /* Return the final value of a plt relocation. */
320 static inline Elf32_Addr
321 elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
322 Elf32_Addr value)
324 return value + reloc->r_addend;
327 #endif /* dl_machine_h */
329 #ifdef RESOLVE
331 /* Do the actual processing of a reloc, once its target address
332 has been determined. */
333 extern void __process_machine_rela (struct link_map *map,
334 const Elf32_Rela *reloc,
335 const Elf32_Sym *sym,
336 const Elf32_Sym *refsym,
337 Elf32_Addr *const reloc_addr,
338 Elf32_Addr finaladdr,
339 int rinfo);
341 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
342 LOADADDR is the load address of the object; INFO is an array indexed
343 by DT_* of the .dynamic section info. */
345 inline void
346 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
347 const Elf32_Sym *sym, const struct r_found_version *version,
348 Elf32_Addr *const reloc_addr)
350 const Elf32_Sym *const refsym = sym;
351 Elf32_Word finaladdr;
352 const int rinfo = ELF32_R_TYPE (reloc->r_info);
354 #ifndef RESOLVE_CONFLICT_FIND_MAP
355 if (__builtin_expect (rinfo == R_PPC_NONE, 0))
356 return;
358 /* The condition on the next two lines is a hack around a bug in Solaris
359 tools on Sparc. It's not clear whether it should really be here at all,
360 but if not the binutils need to be changed. */
361 if (rinfo == R_PPC_RELATIVE
362 || (sym->st_shndx != SHN_UNDEF
363 && ELF32_ST_BIND (sym->st_info) == STB_LOCAL))
365 /* Has already been relocated. */
366 Elf32_Word loadbase = map->l_addr;
367 finaladdr = loadbase + reloc->r_addend;
369 else
371 Elf32_Word loadbase
372 = (Elf32_Word) (char *) (RESOLVE (&sym, version,
373 ELF32_R_TYPE(reloc->r_info)));
374 if (sym == NULL)
376 /* Weak symbol that wasn't actually defined anywhere. */
377 assert (loadbase == 0);
378 finaladdr = reloc->r_addend;
380 else
381 finaladdr = (loadbase + (Elf32_Word) (char *) sym->st_value
382 + reloc->r_addend);
384 #else
385 finaladdr = reloc->r_addend;
386 if (rinfo == R_PPC_JMP_SLOT)
387 RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
388 #endif
390 /* A small amount of code is duplicated here for speed. In libc,
391 more than 90% of the relocs are R_PPC_RELATIVE; in the X11 shared
392 libraries, 60% are R_PPC_RELATIVE, 24% are R_PPC_GLOB_DAT or
393 R_PPC_ADDR32, and 16% are R_PPC_JMP_SLOT (which this routine
394 wouldn't usually handle). As an bonus, doing this here allows
395 the switch statement in __process_machine_rela to work. */
396 if (rinfo == R_PPC_RELATIVE
397 || rinfo == R_PPC_GLOB_DAT
398 || rinfo == R_PPC_ADDR32)
400 *reloc_addr = finaladdr;
402 else
403 __process_machine_rela (map, reloc, sym, refsym,
404 reloc_addr, finaladdr, rinfo);
407 static inline void
408 elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
409 Elf32_Addr *const reloc_addr)
411 *reloc_addr = l_addr + reloc->r_addend;
414 /* The SVR4 ABI specifies that the JMPREL relocs must be inside the
415 DT_RELA table. */
416 #define ELF_MACHINE_PLTREL_OVERLAP 1
418 #endif /* RESOLVE */