powerpc __tls_get_addr call optimization
[glibc.git] / sysdeps / powerpc / powerpc64 / dl-machine.h
blob55ac73624bbcfc42becdf047d30a5dc9c19336c9
1 /* Machine-dependent ELF dynamic relocation inline functions.
2 PowerPC64 version.
3 Copyright 1995-2015 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If
18 not, see <http://www.gnu.org/licenses/>. */
20 #ifndef dl_machine_h
21 #define dl_machine_h
23 #define ELF_MACHINE_NAME "powerpc64"
25 #include <assert.h>
26 #include <sys/param.h>
27 #include <dl-tls.h>
28 #include <sysdep.h>
30 /* Translate a processor specific dynamic tag to the index
31 in l_info array. */
32 #define DT_PPC64(x) (DT_PPC64_##x - DT_LOPROC + DT_NUM)
34 #if _CALL_ELF != 2
35 /* A PowerPC64 function descriptor. The .plt (procedure linkage
36 table) and .opd (official procedure descriptor) sections are
37 arrays of these. */
38 typedef struct
40 Elf64_Addr fd_func;
41 Elf64_Addr fd_toc;
42 Elf64_Addr fd_aux;
43 } Elf64_FuncDesc;
44 #endif
46 #define ELF_MULT_MACHINES_SUPPORTED
48 /* Return nonzero iff ELF header is compatible with the running host. */
49 static inline int
50 elf_machine_matches_host (const Elf64_Ehdr *ehdr)
52 /* Verify that the binary matches our ABI version. */
53 if ((ehdr->e_flags & EF_PPC64_ABI) != 0)
55 #if _CALL_ELF != 2
56 if ((ehdr->e_flags & EF_PPC64_ABI) != 1)
57 return 0;
58 #else
59 if ((ehdr->e_flags & EF_PPC64_ABI) != 2)
60 return 0;
61 #endif
64 return ehdr->e_machine == EM_PPC64;
67 /* Return nonzero iff ELF header is compatible with the running host,
68 but not this loader. */
69 static inline int
70 elf_host_tolerates_machine (const Elf64_Ehdr *ehdr)
72 return ehdr->e_machine == EM_PPC;
75 /* Return nonzero iff ELF header is compatible with the running host,
76 but not this loader. */
77 static inline int
78 elf_host_tolerates_class (const Elf64_Ehdr *ehdr)
80 return ehdr->e_ident[EI_CLASS] == ELFCLASS32;
84 /* Return the run-time load address of the shared object, assuming it
85 was originally linked at zero. */
86 static inline Elf64_Addr
87 elf_machine_load_address (void) __attribute__ ((const));
89 static inline Elf64_Addr
90 elf_machine_load_address (void)
92 Elf64_Addr ret;
94 /* The first entry in .got (and thus the first entry in .toc) is the
95 link-time TOC_base, ie. r2. So the difference between that and
96 the current r2 set by the kernel is how far the shared lib has
97 moved. */
98 asm ( " ld %0,-32768(2)\n"
99 " subf %0,%0,2\n"
100 : "=r" (ret));
101 return ret;
104 /* Return the link-time address of _DYNAMIC. */
105 static inline Elf64_Addr
106 elf_machine_dynamic (void)
108 Elf64_Addr runtime_dynamic;
109 /* It's easier to get the run-time address. */
110 asm ( " addis %0,2,_DYNAMIC@toc@ha\n"
111 " addi %0,%0,_DYNAMIC@toc@l\n"
112 : "=b" (runtime_dynamic));
113 /* Then subtract off the load address offset. */
114 return runtime_dynamic - elf_machine_load_address() ;
117 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */
119 /* The PLT uses Elf64_Rela relocs. */
120 #define elf_machine_relplt elf_machine_rela
123 #ifdef HAVE_INLINED_SYSCALLS
124 /* We do not need _dl_starting_up. */
125 # define DL_STARTING_UP_DEF
126 #else
127 # define DL_STARTING_UP_DEF \
128 ".LC__dl_starting_up:\n" \
129 " .tc __GI__dl_starting_up[TC],__GI__dl_starting_up\n"
130 #endif
133 /* Initial entry point code for the dynamic linker. The C function
134 `_dl_start' is the real entry point; its return value is the user
135 program's entry point. */
136 #define RTLD_START \
137 asm (".pushsection \".text\"\n" \
138 " .align 2\n" \
139 " " ENTRY_2(_start) "\n" \
140 BODY_PREFIX "_start:\n" \
141 " " LOCALENTRY(_start) "\n" \
142 /* We start with the following on the stack, from top: \
143 argc (4 bytes); \
144 arguments for program (terminated by NULL); \
145 environment variables (terminated by NULL); \
146 arguments for the program loader. */ \
147 " mr 3,1\n" \
148 " li 4,0\n" \
149 " stdu 4,-128(1)\n" \
150 /* Call _dl_start with one parameter pointing at argc. */ \
151 " bl " DOT_PREFIX "_dl_start\n" \
152 " nop\n" \
153 /* Transfer control to _dl_start_user! */ \
154 " b " DOT_PREFIX "_dl_start_user\n" \
155 ".LT__start:\n" \
156 " .long 0\n" \
157 " .byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n" \
158 " .long .LT__start-" BODY_PREFIX "_start\n" \
159 " .short .LT__start_name_end-.LT__start_name_start\n" \
160 ".LT__start_name_start:\n" \
161 " .ascii \"_start\"\n" \
162 ".LT__start_name_end:\n" \
163 " .align 2\n" \
164 " " END_2(_start) "\n" \
165 " .pushsection \".toc\",\"aw\"\n" \
166 DL_STARTING_UP_DEF \
167 ".LC__rtld_local:\n" \
168 " .tc _rtld_local[TC],_rtld_local\n" \
169 ".LC__dl_argc:\n" \
170 " .tc _dl_argc[TC],_dl_argc\n" \
171 ".LC__dl_argv:\n" \
172 " .tc __GI__dl_argv[TC],__GI__dl_argv\n" \
173 ".LC__dl_fini:\n" \
174 " .tc _dl_fini[TC],_dl_fini\n" \
175 " .popsection\n" \
176 " " ENTRY_2(_dl_start_user) "\n" \
177 /* Now, we do our main work of calling initialisation procedures. \
178 The ELF ABI doesn't say anything about parameters for these, \
179 so we just pass argc, argv, and the environment. \
180 Changing these is strongly discouraged (not least because argc is \
181 passed by value!). */ \
182 BODY_PREFIX "_dl_start_user:\n" \
183 " " LOCALENTRY(_dl_start_user) "\n" \
184 /* the address of _start in r30. */ \
185 " mr 30,3\n" \
186 /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28. */ \
187 " ld 28,.LC__rtld_local@toc(2)\n" \
188 " ld 29,.LC__dl_argc@toc(2)\n" \
189 " ld 27,.LC__dl_argv@toc(2)\n" \
190 /* _dl_init (_dl_loaded, _dl_argc, _dl_argv, _dl_argv+_dl_argc+1). */ \
191 " ld 3,0(28)\n" \
192 " lwa 4,0(29)\n" \
193 " ld 5,0(27)\n" \
194 " sldi 6,4,3\n" \
195 " add 6,5,6\n" \
196 " addi 6,6,8\n" \
197 " bl " DOT_PREFIX "_dl_init\n" \
198 " nop\n" \
199 /* Now, to conform to the ELF ABI, we have to: \
200 Pass argc (actually _dl_argc) in r3; */ \
201 " lwa 3,0(29)\n" \
202 /* Pass argv (actually _dl_argv) in r4; */ \
203 " ld 4,0(27)\n" \
204 /* Pass argv+argc+1 in r5; */ \
205 " sldi 5,3,3\n" \
206 " add 6,4,5\n" \
207 " addi 5,6,8\n" \
208 /* Pass the auxiliary vector in r6. This is passed to us just after \
209 _envp. */ \
210 "2: ldu 0,8(6)\n" \
211 " cmpdi 0,0\n" \
212 " bne 2b\n" \
213 " addi 6,6,8\n" \
214 /* Pass a termination function pointer (in this case _dl_fini) in \
215 r7. */ \
216 " ld 7,.LC__dl_fini@toc(2)\n" \
217 /* Pass the stack pointer in r1 (so far so good), pointing to a NULL \
218 value. This lets our startup code distinguish between a program \
219 linked statically, which linux will call with argc on top of the \
220 stack which will hopefully never be zero, and a dynamically linked \
221 program which will always have a NULL on the top of the stack. \
222 Take the opportunity to clear LR, so anyone who accidentally \
223 returns from _start gets SEGV. Also clear the next few words of \
224 the stack. */ \
225 " li 31,0\n" \
226 " std 31,0(1)\n" \
227 " mtlr 31\n" \
228 " std 31,8(1)\n" \
229 " std 31,16(1)\n" \
230 " std 31,24(1)\n" \
231 /* Now, call the start function descriptor at r30... */ \
232 " .globl ._dl_main_dispatch\n" \
233 "._dl_main_dispatch:\n" \
234 " " PPC64_LOAD_FUNCPTR(30) "\n" \
235 " bctr\n" \
236 ".LT__dl_start_user:\n" \
237 " .long 0\n" \
238 " .byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n" \
239 " .long .LT__dl_start_user-" BODY_PREFIX "_dl_start_user\n" \
240 " .short .LT__dl_start_user_name_end-.LT__dl_start_user_name_start\n" \
241 ".LT__dl_start_user_name_start:\n" \
242 " .ascii \"_dl_start_user\"\n" \
243 ".LT__dl_start_user_name_end:\n" \
244 " .align 2\n" \
245 " " END_2(_dl_start_user) "\n" \
246 " .popsection");
248 /* ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to
249 one of the main executable's symbols, as for a COPY reloc.
251 To make function pointer comparisons work on most targets, the
252 relevant ABI states that the address of a non-local function in a
253 dynamically linked executable is the address of the PLT entry for
254 that function. This is quite reasonable since using the real
255 function address in a non-PIC executable would typically require
256 dynamic relocations in .text, something to be avoided. For such
257 functions, the linker emits a SHN_UNDEF symbol in the executable
258 with value equal to the PLT entry address. Normally, SHN_UNDEF
259 symbols have a value of zero, so this is a clue to ld.so that it
260 should treat these symbols specially. For relocations not in
261 ELF_RTYPE_CLASS_PLT (eg. those on function pointers), ld.so should
262 use the value of the executable SHN_UNDEF symbol, ie. the PLT entry
263 address. For relocations in ELF_RTYPE_CLASS_PLT (eg. the relocs in
264 the PLT itself), ld.so should use the value of the corresponding
265 defined symbol in the object that defines the function, ie. the
266 real function address. This complicates ld.so in that there are
267 now two possible values for a given symbol, and it gets even worse
268 because protected symbols need yet another set of rules.
270 On PowerPC64 we don't need any of this. The linker won't emit
271 SHN_UNDEF symbols with non-zero values. ld.so can make all
272 relocations behave "normally", ie. always use the real address
273 like PLT relocations. So always set ELF_RTYPE_CLASS_PLT. */
275 #if _CALL_ELF != 2
276 #define elf_machine_type_class(type) \
277 (ELF_RTYPE_CLASS_PLT | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
278 #else
279 /* And now that you have read that large comment, you can disregard it
280 all for ELFv2. ELFv2 does need the special SHN_UNDEF treatment. */
281 #define IS_PPC64_TLS_RELOC(R) \
282 (((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA) \
283 || ((R) >= R_PPC64_TPREL16_HIGH && (R) <= R_PPC64_DTPREL16_HIGHA))
285 #define elf_machine_type_class(type) \
286 ((((type) == R_PPC64_JMP_SLOT \
287 || (type) == R_PPC64_ADDR24 \
288 || IS_PPC64_TLS_RELOC (type)) * ELF_RTYPE_CLASS_PLT) \
289 | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
290 #endif
292 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
293 #define ELF_MACHINE_JMP_SLOT R_PPC64_JMP_SLOT
295 /* The PowerPC never uses REL relocations. */
296 #define ELF_MACHINE_NO_REL 1
297 #define ELF_MACHINE_NO_RELA 0
299 /* Stuff for the PLT. */
300 #if _CALL_ELF != 2
301 #define PLT_INITIAL_ENTRY_WORDS 3
302 #define PLT_ENTRY_WORDS 3
303 #define GLINK_INITIAL_ENTRY_WORDS 8
304 /* The first 32k entries of glink can set an index and branch using two
305 instructions; past that point, glink uses three instructions. */
306 #define GLINK_ENTRY_WORDS(I) (((I) < 0x8000)? 2 : 3)
307 #else
308 #define PLT_INITIAL_ENTRY_WORDS 2
309 #define PLT_ENTRY_WORDS 1
310 #define GLINK_INITIAL_ENTRY_WORDS 8
311 #define GLINK_ENTRY_WORDS(I) 1
312 #endif
314 #define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where) : "memory")
315 #define PPC_DCBT(where) asm volatile ("dcbt 0,%0" : : "r"(where) : "memory")
316 #define PPC_DCBF(where) asm volatile ("dcbf 0,%0" : : "r"(where) : "memory")
317 #define PPC_SYNC asm volatile ("sync" : : : "memory")
318 #define PPC_ISYNC asm volatile ("sync; isync" : : : "memory")
319 #define PPC_ICBI(where) asm volatile ("icbi 0,%0" : : "r"(where) : "memory")
320 #define PPC_DIE asm volatile ("tweq 0,0")
321 /* Use this when you've modified some code, but it won't be in the
322 instruction fetch queue (or when it doesn't matter if it is). */
323 #define MODIFIED_CODE_NOQUEUE(where) \
324 do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); } while (0)
325 /* Use this when it might be in the instruction queue. */
326 #define MODIFIED_CODE(where) \
327 do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); PPC_ISYNC; } while (0)
329 /* Set up the loaded object described by MAP so its unrelocated PLT
330 entries will jump to the on-demand fixup code in dl-runtime.c. */
331 static inline int __attribute__ ((always_inline))
332 elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
334 if (map->l_info[DT_JMPREL])
336 Elf64_Word i;
337 Elf64_Word *glink = NULL;
338 Elf64_Xword *plt = (Elf64_Xword *) D_PTR (map, l_info[DT_PLTGOT]);
339 Elf64_Word num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
340 / sizeof (Elf64_Rela));
341 Elf64_Addr l_addr = map->l_addr;
342 Elf64_Dyn **info = map->l_info;
343 char *p;
345 extern void _dl_runtime_resolve (void);
346 extern void _dl_profile_resolve (void);
348 /* Relocate the DT_PPC64_GLINK entry in the _DYNAMIC section.
349 elf_get_dynamic_info takes care of the standard entries but
350 doesn't know exactly what to do with processor specific
351 entries. */
352 if (info[DT_PPC64(GLINK)] != NULL)
353 info[DT_PPC64(GLINK)]->d_un.d_ptr += l_addr;
355 if (lazy)
357 Elf64_Word glink_offset;
358 Elf64_Word offset;
359 Elf64_Addr dlrr;
361 dlrr = (Elf64_Addr) (profile ? _dl_profile_resolve
362 : _dl_runtime_resolve);
363 if (profile && GLRO(dl_profile) != NULL
364 && _dl_name_match_p (GLRO(dl_profile), map))
365 /* This is the object we are looking for. Say that we really
366 want profiling and the timers are started. */
367 GL(dl_profile_map) = map;
369 #if _CALL_ELF != 2
370 /* We need to stuff the address/TOC of _dl_runtime_resolve
371 into doublewords 0 and 1 of plt_reserve. Then we need to
372 stuff the map address into doubleword 2 of plt_reserve.
373 This allows the GLINK0 code to transfer control to the
374 correct trampoline which will transfer control to fixup
375 in dl-machine.c. */
377 /* The plt_reserve area is the 1st 3 doublewords of the PLT. */
378 Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt;
379 Elf64_FuncDesc *resolve_fd = (Elf64_FuncDesc *) dlrr;
380 plt_reserve->fd_func = resolve_fd->fd_func;
381 plt_reserve->fd_toc = resolve_fd->fd_toc;
382 plt_reserve->fd_aux = (Elf64_Addr) map;
383 #ifdef RTLD_BOOTSTRAP
384 /* When we're bootstrapping, the opd entry will not have
385 been relocated yet. */
386 plt_reserve->fd_func += l_addr;
387 plt_reserve->fd_toc += l_addr;
388 #endif
390 #else
391 /* When we don't have function descriptors, the first doubleword
392 of the PLT holds the address of _dl_runtime_resolve, and the
393 second doubleword holds the map address. */
394 plt[0] = dlrr;
395 plt[1] = (Elf64_Addr) map;
396 #endif
398 /* Set up the lazy PLT entries. */
399 glink = (Elf64_Word *) D_PTR (map, l_info[DT_PPC64(GLINK)]);
400 offset = PLT_INITIAL_ENTRY_WORDS;
401 glink_offset = GLINK_INITIAL_ENTRY_WORDS;
402 for (i = 0; i < num_plt_entries; i++)
405 plt[offset] = (Elf64_Xword) &glink[glink_offset];
406 offset += PLT_ENTRY_WORDS;
407 glink_offset += GLINK_ENTRY_WORDS (i);
410 /* Now, we've modified data. We need to write the changes from
411 the data cache to a second-level unified cache, then make
412 sure that stale data in the instruction cache is removed.
413 (In a multiprocessor system, the effect is more complex.)
414 Most of the PLT shouldn't be in the instruction cache, but
415 there may be a little overlap at the start and the end.
417 Assumes that dcbst and icbi apply to lines of 16 bytes or
418 more. Current known line sizes are 16, 32, and 128 bytes. */
420 for (p = (char *) plt; p < (char *) &plt[offset]; p += 16)
421 PPC_DCBST (p);
422 PPC_SYNC;
425 return lazy;
428 #if _CALL_ELF == 2
429 /* If the PLT entry whose reloc is 'reloc' resolves to a function in
430 the same object, return the target function's local entry point
431 offset if usable. */
432 static inline Elf64_Addr __attribute__ ((always_inline))
433 ppc64_local_entry_offset (struct link_map *map, lookup_t sym_map,
434 const Elf64_Rela *reloc)
436 const Elf64_Sym *symtab;
437 const Elf64_Sym *sym;
439 /* If the target function is in a different object, we cannot
440 use the local entry point. */
441 if (sym_map != map)
442 return 0;
444 /* If the linker inserted multiple TOCs, we cannot use the
445 local entry point. */
446 if (map->l_info[DT_PPC64(OPT)]
447 && (map->l_info[DT_PPC64(OPT)]->d_un.d_val & PPC64_OPT_MULTI_TOC))
448 return 0;
450 /* Otherwise, we can use the local entry point. Retrieve its offset
451 from the symbol's ELF st_other field. */
452 symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
453 sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
455 /* If the target function is an ifunc then the local entry offset is
456 for the resolver, not the final destination. */
457 if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
458 return 0;
460 return PPC64_LOCAL_ENTRY_OFFSET (sym->st_other);
462 #endif
464 /* Change the PLT entry whose reloc is 'reloc' to call the actual
465 routine. */
466 static inline Elf64_Addr __attribute__ ((always_inline))
467 elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
468 const Elf64_Rela *reloc,
469 Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
471 #if _CALL_ELF != 2
472 Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
473 Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
474 Elf64_Addr offset = 0;
476 PPC_DCBT (&plt->fd_aux);
477 PPC_DCBT (&plt->fd_func);
478 PPC_DCBT (&rel->fd_aux);
479 PPC_DCBT (&rel->fd_func);
481 /* If sym_map is NULL, it's a weak undefined sym; Leave the plt zero. */
482 if (sym_map == NULL)
483 return 0;
485 /* If the opd entry is not yet relocated (because it's from a shared
486 object that hasn't been processed yet), then manually reloc it. */
487 if (map != sym_map && !sym_map->l_relocated
488 #if !defined RTLD_BOOTSTRAP && defined SHARED
489 /* Bootstrap map doesn't have l_relocated set for it. */
490 && sym_map != &GL(dl_rtld_map)
491 #endif
493 offset = sym_map->l_addr;
495 /* For PPC64, fixup_plt copies the function descriptor from opd
496 over the corresponding PLT entry.
497 Initially, PLT Entry[i] is set up for lazy linking, or is zero.
498 For lazy linking, the fd_toc and fd_aux entries are irrelevant,
499 so for thread safety we write them before changing fd_func. */
501 plt->fd_aux = rel->fd_aux + offset;
502 plt->fd_toc = rel->fd_toc + offset;
503 PPC_DCBF (&plt->fd_toc);
504 PPC_ISYNC;
506 plt->fd_func = rel->fd_func + offset;
507 PPC_DCBST (&plt->fd_func);
508 PPC_ISYNC;
509 #else
510 finaladdr += ppc64_local_entry_offset (map, sym_map, reloc);
511 *reloc_addr = finaladdr;
512 #endif
514 return finaladdr;
517 static inline void __attribute__ ((always_inline))
518 elf_machine_plt_conflict (struct link_map *map, lookup_t sym_map,
519 const Elf64_Rela *reloc,
520 Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
522 #if _CALL_ELF != 2
523 Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
524 Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
526 plt->fd_func = rel->fd_func;
527 plt->fd_aux = rel->fd_aux;
528 plt->fd_toc = rel->fd_toc;
529 PPC_DCBST (&plt->fd_func);
530 PPC_DCBST (&plt->fd_aux);
531 PPC_DCBST (&plt->fd_toc);
532 PPC_SYNC;
533 #else
534 finaladdr += ppc64_local_entry_offset (map, sym_map, reloc);
535 *reloc_addr = finaladdr;
536 #endif
539 /* Return the final value of a plt relocation. */
540 static inline Elf64_Addr
541 elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
542 Elf64_Addr value)
544 return value + reloc->r_addend;
548 /* Names of the architecture-specific auditing callback functions. */
549 #if _CALL_ELF != 2
550 #define ARCH_LA_PLTENTER ppc64_gnu_pltenter
551 #define ARCH_LA_PLTEXIT ppc64_gnu_pltexit
552 #else
553 #define ARCH_LA_PLTENTER ppc64v2_gnu_pltenter
554 #define ARCH_LA_PLTEXIT ppc64v2_gnu_pltexit
555 #endif
557 #endif /* dl_machine_h */
559 #ifdef RESOLVE_MAP
561 #define PPC_LO(v) ((v) & 0xffff)
562 #define PPC_HI(v) (((v) >> 16) & 0xffff)
563 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
564 #define PPC_HIGHER(v) (((v) >> 32) & 0xffff)
565 #define PPC_HIGHERA(v) PPC_HIGHER ((v) + 0x8000)
566 #define PPC_HIGHEST(v) (((v) >> 48) & 0xffff)
567 #define PPC_HIGHESTA(v) PPC_HIGHEST ((v) + 0x8000)
568 #define BIT_INSERT(var, val, mask) \
569 ((var) = ((var) & ~(Elf64_Addr) (mask)) | ((val) & (mask)))
571 #define dont_expect(X) __builtin_expect ((X), 0)
573 extern void _dl_reloc_overflow (struct link_map *map,
574 const char *name,
575 Elf64_Addr *const reloc_addr,
576 const Elf64_Sym *refsym)
577 attribute_hidden;
579 auto inline void __attribute__ ((always_inline))
580 elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
581 void *const reloc_addr_arg)
583 Elf64_Addr *const reloc_addr = reloc_addr_arg;
584 *reloc_addr = l_addr + reloc->r_addend;
587 /* This computes the value used by TPREL* relocs. */
588 auto inline Elf64_Addr __attribute__ ((always_inline, const))
589 elf_machine_tprel (struct link_map *map,
590 struct link_map *sym_map,
591 const Elf64_Sym *sym,
592 const Elf64_Rela *reloc)
594 #ifndef RTLD_BOOTSTRAP
595 if (sym_map)
597 CHECK_STATIC_TLS (map, sym_map);
598 #endif
599 return TLS_TPREL_VALUE (sym_map, sym, reloc);
600 #ifndef RTLD_BOOTSTRAP
602 #endif
603 return 0;
606 /* Call function at address VALUE (an OPD entry) to resolve ifunc relocs. */
607 auto inline Elf64_Addr __attribute__ ((always_inline))
608 resolve_ifunc (Elf64_Addr value,
609 const struct link_map *map, const struct link_map *sym_map)
611 #if _CALL_ELF != 2
612 #ifndef RESOLVE_CONFLICT_FIND_MAP
613 /* The function we are calling may not yet have its opd entry relocated. */
614 Elf64_FuncDesc opd;
615 if (map != sym_map
616 # if !defined RTLD_BOOTSTRAP && defined SHARED
617 /* Bootstrap map doesn't have l_relocated set for it. */
618 && sym_map != &GL(dl_rtld_map)
619 # endif
620 && !sym_map->l_relocated)
622 Elf64_FuncDesc *func = (Elf64_FuncDesc *) value;
623 opd.fd_func = func->fd_func + sym_map->l_addr;
624 opd.fd_toc = func->fd_toc + sym_map->l_addr;
625 opd.fd_aux = func->fd_aux;
626 /* GCC 4.9+ eliminates the branch as dead code, force the odp set
627 dependency. */
628 asm ("" : "=r" (value) : "0" (&opd), "X" (opd));
630 #endif
631 #endif
632 return ((Elf64_Addr (*) (unsigned long int)) value) (GLRO(dl_hwcap));
635 /* Perform the relocation specified by RELOC and SYM (which is fully
636 resolved). MAP is the object containing the reloc. */
637 auto inline void __attribute__ ((always_inline))
638 elf_machine_rela (struct link_map *map,
639 const Elf64_Rela *reloc,
640 const Elf64_Sym *sym,
641 const struct r_found_version *version,
642 void *const reloc_addr_arg,
643 int skip_ifunc)
645 Elf64_Addr *const reloc_addr = reloc_addr_arg;
646 const int r_type = ELF64_R_TYPE (reloc->r_info);
647 const Elf64_Sym *const refsym = sym;
648 union unaligned
650 uint16_t u2;
651 uint32_t u4;
652 uint64_t u8;
653 } __attribute__ ((__packed__));
655 if (r_type == R_PPC64_RELATIVE)
657 *reloc_addr = map->l_addr + reloc->r_addend;
658 return;
661 if (__glibc_unlikely (r_type == R_PPC64_NONE))
662 return;
664 /* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt
665 and STT_GNU_IFUNC. */
666 struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
667 Elf64_Addr value = ((sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value)
668 + reloc->r_addend);
670 if (sym != NULL
671 && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
672 && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
673 && __builtin_expect (!skip_ifunc, 1))
674 value = resolve_ifunc (value, map, sym_map);
676 /* For relocs that don't edit code, return.
677 For relocs that might edit instructions, break from the switch. */
678 switch (r_type)
680 case R_PPC64_ADDR64:
681 case R_PPC64_GLOB_DAT:
682 *reloc_addr = value;
683 return;
685 case R_PPC64_IRELATIVE:
686 if (__glibc_likely (!skip_ifunc))
687 value = resolve_ifunc (value, map, sym_map);
688 *reloc_addr = value;
689 return;
691 case R_PPC64_JMP_IREL:
692 if (__glibc_likely (!skip_ifunc))
693 value = resolve_ifunc (value, map, sym_map);
694 /* Fall thru */
695 case R_PPC64_JMP_SLOT:
696 #ifdef RESOLVE_CONFLICT_FIND_MAP
697 elf_machine_plt_conflict (map, sym_map, reloc, reloc_addr, value);
698 #else
699 elf_machine_fixup_plt (map, sym_map, reloc, reloc_addr, value);
700 #endif
701 return;
703 case R_PPC64_DTPMOD64:
704 if (map->l_info[DT_PPC64(OPT)]
705 && (map->l_info[DT_PPC64(OPT)]->d_un.d_val & PPC64_OPT_TLS))
707 #ifdef RTLD_BOOTSTRAP
708 reloc_addr[0] = 0;
709 reloc_addr[1] = (sym_map->l_tls_offset - TLS_TP_OFFSET
710 + TLS_DTV_OFFSET);
711 return;
712 #else
713 if (sym_map != NULL)
715 # ifndef SHARED
716 CHECK_STATIC_TLS (map, sym_map);
717 # else
718 if (TRY_STATIC_TLS (map, sym_map))
719 # endif
721 reloc_addr[0] = 0;
722 /* Set up for local dynamic. */
723 reloc_addr[1] = (sym_map->l_tls_offset - TLS_TP_OFFSET
724 + TLS_DTV_OFFSET);
725 return;
728 #endif
730 #ifdef RTLD_BOOTSTRAP
731 /* During startup the dynamic linker is always index 1. */
732 *reloc_addr = 1;
733 #else
734 /* Get the information from the link map returned by the
735 resolve function. */
736 if (sym_map != NULL)
737 *reloc_addr = sym_map->l_tls_modid;
738 #endif
739 return;
741 case R_PPC64_DTPREL64:
742 if (map->l_info[DT_PPC64(OPT)]
743 && (map->l_info[DT_PPC64(OPT)]->d_un.d_val & PPC64_OPT_TLS))
745 #ifdef RTLD_BOOTSTRAP
746 *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
747 return;
748 #else
749 if (sym_map != NULL)
751 /* This reloc is always preceded by R_PPC64_DTPMOD64. */
752 # ifndef SHARED
753 assert (HAVE_STATIC_TLS (map, sym_map));
754 # else
755 if (HAVE_STATIC_TLS (map, sym_map))
756 # endif
758 *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
759 return;
762 #endif
764 /* During relocation all TLS symbols are defined and used.
765 Therefore the offset is already correct. */
766 #ifndef RTLD_BOOTSTRAP
767 if (sym_map != NULL)
768 *reloc_addr = TLS_DTPREL_VALUE (sym, reloc);
769 #endif
770 return;
772 case R_PPC64_TPREL64:
773 *reloc_addr = elf_machine_tprel (map, sym_map, sym, reloc);
774 return;
776 case R_PPC64_TPREL16_LO_DS:
777 value = elf_machine_tprel (map, sym_map, sym, reloc);
778 if (dont_expect ((value & 3) != 0))
779 _dl_reloc_overflow (map, "R_PPC64_TPREL16_LO_DS", reloc_addr, refsym);
780 BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc);
781 break;
783 case R_PPC64_TPREL16_DS:
784 value = elf_machine_tprel (map, sym_map, sym, reloc);
785 if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
786 _dl_reloc_overflow (map, "R_PPC64_TPREL16_DS", reloc_addr, refsym);
787 BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc);
788 break;
790 case R_PPC64_TPREL16:
791 value = elf_machine_tprel (map, sym_map, sym, reloc);
792 if (dont_expect ((value + 0x8000) >= 0x10000))
793 _dl_reloc_overflow (map, "R_PPC64_TPREL16", reloc_addr, refsym);
794 *(Elf64_Half *) reloc_addr = PPC_LO (value);
795 break;
797 case R_PPC64_TPREL16_LO:
798 value = elf_machine_tprel (map, sym_map, sym, reloc);
799 *(Elf64_Half *) reloc_addr = PPC_LO (value);
800 break;
802 case R_PPC64_TPREL16_HI:
803 value = elf_machine_tprel (map, sym_map, sym, reloc);
804 if (dont_expect (value + 0x80000000 >= 0x100000000LL))
805 _dl_reloc_overflow (map, "R_PPC64_TPREL16_HI", reloc_addr, refsym);
806 *(Elf64_Half *) reloc_addr = PPC_HI (value);
807 break;
809 case R_PPC64_TPREL16_HIGH:
810 value = elf_machine_tprel (map, sym_map, sym, reloc);
811 *(Elf64_Half *) reloc_addr = PPC_HI (value);
812 break;
814 case R_PPC64_TPREL16_HA:
815 value = elf_machine_tprel (map, sym_map, sym, reloc);
816 if (dont_expect (value + 0x80008000 >= 0x100000000LL))
817 _dl_reloc_overflow (map, "R_PPC64_TPREL16_HA", reloc_addr, refsym);
818 *(Elf64_Half *) reloc_addr = PPC_HA (value);
819 break;
821 case R_PPC64_TPREL16_HIGHA:
822 value = elf_machine_tprel (map, sym_map, sym, reloc);
823 *(Elf64_Half *) reloc_addr = PPC_HA (value);
824 break;
826 case R_PPC64_TPREL16_HIGHER:
827 value = elf_machine_tprel (map, sym_map, sym, reloc);
828 *(Elf64_Half *) reloc_addr = PPC_HIGHER (value);
829 break;
831 case R_PPC64_TPREL16_HIGHEST:
832 value = elf_machine_tprel (map, sym_map, sym, reloc);
833 *(Elf64_Half *) reloc_addr = PPC_HIGHEST (value);
834 break;
836 case R_PPC64_TPREL16_HIGHERA:
837 value = elf_machine_tprel (map, sym_map, sym, reloc);
838 *(Elf64_Half *) reloc_addr = PPC_HIGHERA (value);
839 break;
841 case R_PPC64_TPREL16_HIGHESTA:
842 value = elf_machine_tprel (map, sym_map, sym, reloc);
843 *(Elf64_Half *) reloc_addr = PPC_HIGHESTA (value);
844 break;
846 #ifndef RTLD_BOOTSTRAP /* None of the following appear in ld.so */
847 case R_PPC64_ADDR16_LO_DS:
848 if (dont_expect ((value & 3) != 0))
849 _dl_reloc_overflow (map, "R_PPC64_ADDR16_LO_DS", reloc_addr, refsym);
850 BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc);
851 break;
853 case R_PPC64_ADDR16_LO:
854 *(Elf64_Half *) reloc_addr = PPC_LO (value);
855 break;
857 case R_PPC64_ADDR16_HI:
858 if (dont_expect (value + 0x80000000 >= 0x100000000LL))
859 _dl_reloc_overflow (map, "R_PPC64_ADDR16_HI", reloc_addr, refsym);
860 case R_PPC64_ADDR16_HIGH:
861 *(Elf64_Half *) reloc_addr = PPC_HI (value);
862 break;
864 case R_PPC64_ADDR16_HA:
865 if (dont_expect (value + 0x80008000 >= 0x100000000LL))
866 _dl_reloc_overflow (map, "R_PPC64_ADDR16_HA", reloc_addr, refsym);
867 case R_PPC64_ADDR16_HIGHA:
868 *(Elf64_Half *) reloc_addr = PPC_HA (value);
869 break;
871 case R_PPC64_ADDR30:
873 Elf64_Addr delta = value - (Elf64_Xword) reloc_addr;
874 if (dont_expect ((delta + 0x80000000) >= 0x100000000LL
875 || (delta & 3) != 0))
876 _dl_reloc_overflow (map, "R_PPC64_ADDR30", reloc_addr, refsym);
877 BIT_INSERT (*(Elf64_Word *) reloc_addr, delta, 0xfffffffc);
879 break;
881 case R_PPC64_COPY:
882 if (dont_expect (sym == NULL))
883 /* This can happen in trace mode when an object could not be found. */
884 return;
885 if (dont_expect (sym->st_size > refsym->st_size
886 || (GLRO(dl_verbose)
887 && sym->st_size < refsym->st_size)))
889 const char *strtab;
891 strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
892 _dl_error_printf ("%s: Symbol `%s' has different size" \
893 " in shared object," \
894 " consider re-linking\n",
895 RTLD_PROGNAME, strtab + refsym->st_name);
897 memcpy (reloc_addr_arg, (char *) value,
898 MIN (sym->st_size, refsym->st_size));
899 return;
901 case R_PPC64_UADDR64:
902 ((union unaligned *) reloc_addr)->u8 = value;
903 return;
905 case R_PPC64_UADDR32:
906 ((union unaligned *) reloc_addr)->u4 = value;
907 return;
909 case R_PPC64_ADDR32:
910 if (dont_expect ((value + 0x80000000) >= 0x100000000LL))
911 _dl_reloc_overflow (map, "R_PPC64_ADDR32", reloc_addr, refsym);
912 *(Elf64_Word *) reloc_addr = value;
913 return;
915 case R_PPC64_ADDR24:
916 if (dont_expect ((value + 0x2000000) >= 0x4000000 || (value & 3) != 0))
917 _dl_reloc_overflow (map, "R_PPC64_ADDR24", reloc_addr, refsym);
918 BIT_INSERT (*(Elf64_Word *) reloc_addr, value, 0x3fffffc);
919 break;
921 case R_PPC64_ADDR16:
922 if (dont_expect ((value + 0x8000) >= 0x10000))
923 _dl_reloc_overflow (map, "R_PPC64_ADDR16", reloc_addr, refsym);
924 *(Elf64_Half *) reloc_addr = value;
925 break;
927 case R_PPC64_UADDR16:
928 if (dont_expect ((value + 0x8000) >= 0x10000))
929 _dl_reloc_overflow (map, "R_PPC64_UADDR16", reloc_addr, refsym);
930 ((union unaligned *) reloc_addr)->u2 = value;
931 return;
933 case R_PPC64_ADDR16_DS:
934 if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
935 _dl_reloc_overflow (map, "R_PPC64_ADDR16_DS", reloc_addr, refsym);
936 BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc);
937 break;
939 case R_PPC64_ADDR16_HIGHER:
940 *(Elf64_Half *) reloc_addr = PPC_HIGHER (value);
941 break;
943 case R_PPC64_ADDR16_HIGHEST:
944 *(Elf64_Half *) reloc_addr = PPC_HIGHEST (value);
945 break;
947 case R_PPC64_ADDR16_HIGHERA:
948 *(Elf64_Half *) reloc_addr = PPC_HIGHERA (value);
949 break;
951 case R_PPC64_ADDR16_HIGHESTA:
952 *(Elf64_Half *) reloc_addr = PPC_HIGHESTA (value);
953 break;
955 case R_PPC64_ADDR14:
956 case R_PPC64_ADDR14_BRTAKEN:
957 case R_PPC64_ADDR14_BRNTAKEN:
959 if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
960 _dl_reloc_overflow (map, "R_PPC64_ADDR14", reloc_addr, refsym);
961 Elf64_Word insn = *(Elf64_Word *) reloc_addr;
962 BIT_INSERT (insn, value, 0xfffc);
963 if (r_type != R_PPC64_ADDR14)
965 insn &= ~(1 << 21);
966 if (r_type == R_PPC64_ADDR14_BRTAKEN)
967 insn |= 1 << 21;
968 if ((insn & (0x14 << 21)) == (0x04 << 21))
969 insn |= 0x02 << 21;
970 else if ((insn & (0x14 << 21)) == (0x10 << 21))
971 insn |= 0x08 << 21;
973 *(Elf64_Word *) reloc_addr = insn;
975 break;
977 case R_PPC64_REL32:
978 *(Elf64_Word *) reloc_addr = value - (Elf64_Addr) reloc_addr;
979 return;
981 case R_PPC64_REL64:
982 *reloc_addr = value - (Elf64_Addr) reloc_addr;
983 return;
984 #endif /* !RTLD_BOOTSTRAP */
986 default:
987 _dl_reloc_bad_type (map, r_type, 0);
988 return;
990 MODIFIED_CODE_NOQUEUE (reloc_addr);
993 auto inline void __attribute__ ((always_inline))
994 elf_machine_lazy_rel (struct link_map *map,
995 Elf64_Addr l_addr, const Elf64_Rela *reloc,
996 int skip_ifunc)
998 /* elf_machine_runtime_setup handles this. */
1002 #endif /* RESOLVE */