]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/powerpc/powerpc64/dl-machine.h
Use glibc_likely instead __builtin_expect.
[thirdparty/glibc.git] / sysdeps / powerpc / powerpc64 / dl-machine.h
1 /* Machine-dependent ELF dynamic relocation inline functions.
2 PowerPC64 version.
3 Copyright 1995-2014 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5
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.
10
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.
15
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/>. */
19
20 #ifndef dl_machine_h
21 #define dl_machine_h
22
23 #define ELF_MACHINE_NAME "powerpc64"
24
25 #include <assert.h>
26 #include <sys/param.h>
27 #include <dl-tls.h>
28 #include <sysdep.h>
29
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)
33
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
39 {
40 Elf64_Addr fd_func;
41 Elf64_Addr fd_toc;
42 Elf64_Addr fd_aux;
43 } Elf64_FuncDesc;
44 #endif
45
46 #define ELF_MULT_MACHINES_SUPPORTED
47
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)
51 {
52 /* Verify that the binary matches our ABI version. */
53 if ((ehdr->e_flags & EF_PPC64_ABI) != 0)
54 {
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
62 }
63
64 return ehdr->e_machine == EM_PPC64;
65 }
66
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)
71 {
72 return ehdr->e_machine == EM_PPC;
73 }
74
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)
79 {
80 return ehdr->e_ident[EI_CLASS] == ELFCLASS32;
81 }
82
83
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));
88
89 static inline Elf64_Addr
90 elf_machine_load_address (void)
91 {
92 Elf64_Addr ret;
93
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;
102 }
103
104 /* Return the link-time address of _DYNAMIC. */
105 static inline Elf64_Addr
106 elf_machine_dynamic (void)
107 {
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() ;
115 }
116
117 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */
118
119 /* The PLT uses Elf64_Rela relocs. */
120 #define elf_machine_relplt elf_machine_rela
121
122
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 _dl_starting_up_internal[TC],_dl_starting_up_internal\n"
130 #endif
131
132
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 _dl_argv_internal[TC],_dl_argv_internal\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");
247
248 /* ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to
249 one of the main executable's symbols, as for a COPY reloc.
250
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.
269
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. */
274
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))
284
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
291
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
294
295 /* The PowerPC never uses REL relocations. */
296 #define ELF_MACHINE_NO_REL 1
297
298 /* Stuff for the PLT. */
299 #if _CALL_ELF != 2
300 #define PLT_INITIAL_ENTRY_WORDS 3
301 #define PLT_ENTRY_WORDS 3
302 #define GLINK_INITIAL_ENTRY_WORDS 8
303 /* The first 32k entries of glink can set an index and branch using two
304 instructions; past that point, glink uses three instructions. */
305 #define GLINK_ENTRY_WORDS(I) (((I) < 0x8000)? 2 : 3)
306 #else
307 #define PLT_INITIAL_ENTRY_WORDS 2
308 #define PLT_ENTRY_WORDS 1
309 #define GLINK_INITIAL_ENTRY_WORDS 8
310 #define GLINK_ENTRY_WORDS(I) 1
311 #endif
312
313 #define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where) : "memory")
314 #define PPC_DCBT(where) asm volatile ("dcbt 0,%0" : : "r"(where) : "memory")
315 #define PPC_DCBF(where) asm volatile ("dcbf 0,%0" : : "r"(where) : "memory")
316 #define PPC_SYNC asm volatile ("sync" : : : "memory")
317 #define PPC_ISYNC asm volatile ("sync; isync" : : : "memory")
318 #define PPC_ICBI(where) asm volatile ("icbi 0,%0" : : "r"(where) : "memory")
319 #define PPC_DIE asm volatile ("tweq 0,0")
320 /* Use this when you've modified some code, but it won't be in the
321 instruction fetch queue (or when it doesn't matter if it is). */
322 #define MODIFIED_CODE_NOQUEUE(where) \
323 do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); } while (0)
324 /* Use this when it might be in the instruction queue. */
325 #define MODIFIED_CODE(where) \
326 do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); PPC_ISYNC; } while (0)
327
328 /* Set up the loaded object described by MAP so its unrelocated PLT
329 entries will jump to the on-demand fixup code in dl-runtime.c. */
330 static inline int __attribute__ ((always_inline))
331 elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
332 {
333 if (map->l_info[DT_JMPREL])
334 {
335 Elf64_Word i;
336 Elf64_Word *glink = NULL;
337 Elf64_Xword *plt = (Elf64_Xword *) D_PTR (map, l_info[DT_PLTGOT]);
338 Elf64_Word num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
339 / sizeof (Elf64_Rela));
340 Elf64_Addr l_addr = map->l_addr;
341 Elf64_Dyn **info = map->l_info;
342 char *p;
343
344 extern void _dl_runtime_resolve (void);
345 extern void _dl_profile_resolve (void);
346
347 /* Relocate the DT_PPC64_GLINK entry in the _DYNAMIC section.
348 elf_get_dynamic_info takes care of the standard entries but
349 doesn't know exactly what to do with processor specific
350 entries. */
351 if (info[DT_PPC64(GLINK)] != NULL)
352 info[DT_PPC64(GLINK)]->d_un.d_ptr += l_addr;
353
354 if (lazy)
355 {
356 Elf64_Word glink_offset;
357 Elf64_Word offset;
358 Elf64_Addr dlrr;
359
360 dlrr = (Elf64_Addr) (profile ? _dl_profile_resolve
361 : _dl_runtime_resolve);
362 if (profile && GLRO(dl_profile) != NULL
363 && _dl_name_match_p (GLRO(dl_profile), map))
364 /* This is the object we are looking for. Say that we really
365 want profiling and the timers are started. */
366 GL(dl_profile_map) = map;
367
368 #if _CALL_ELF != 2
369 /* We need to stuff the address/TOC of _dl_runtime_resolve
370 into doublewords 0 and 1 of plt_reserve. Then we need to
371 stuff the map address into doubleword 2 of plt_reserve.
372 This allows the GLINK0 code to transfer control to the
373 correct trampoline which will transfer control to fixup
374 in dl-machine.c. */
375 {
376 /* The plt_reserve area is the 1st 3 doublewords of the PLT. */
377 Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt;
378 Elf64_FuncDesc *resolve_fd = (Elf64_FuncDesc *) dlrr;
379 plt_reserve->fd_func = resolve_fd->fd_func;
380 plt_reserve->fd_toc = resolve_fd->fd_toc;
381 plt_reserve->fd_aux = (Elf64_Addr) map;
382 #ifdef RTLD_BOOTSTRAP
383 /* When we're bootstrapping, the opd entry will not have
384 been relocated yet. */
385 plt_reserve->fd_func += l_addr;
386 plt_reserve->fd_toc += l_addr;
387 #endif
388 }
389 #else
390 /* When we don't have function descriptors, the first doubleword
391 of the PLT holds the address of _dl_runtime_resolve, and the
392 second doubleword holds the map address. */
393 plt[0] = dlrr;
394 plt[1] = (Elf64_Addr) map;
395 #endif
396
397 /* Set up the lazy PLT entries. */
398 glink = (Elf64_Word *) D_PTR (map, l_info[DT_PPC64(GLINK)]);
399 offset = PLT_INITIAL_ENTRY_WORDS;
400 glink_offset = GLINK_INITIAL_ENTRY_WORDS;
401 for (i = 0; i < num_plt_entries; i++)
402 {
403
404 plt[offset] = (Elf64_Xword) &glink[glink_offset];
405 offset += PLT_ENTRY_WORDS;
406 glink_offset += GLINK_ENTRY_WORDS (i);
407 }
408
409 /* Now, we've modified data. We need to write the changes from
410 the data cache to a second-level unified cache, then make
411 sure that stale data in the instruction cache is removed.
412 (In a multiprocessor system, the effect is more complex.)
413 Most of the PLT shouldn't be in the instruction cache, but
414 there may be a little overlap at the start and the end.
415
416 Assumes that dcbst and icbi apply to lines of 16 bytes or
417 more. Current known line sizes are 16, 32, and 128 bytes. */
418
419 for (p = (char *) plt; p < (char *) &plt[offset]; p += 16)
420 PPC_DCBST (p);
421 PPC_SYNC;
422 }
423 }
424 return lazy;
425 }
426
427 #if _CALL_ELF == 2
428 /* If the PLT entry whose reloc is 'reloc' resolves to a function in
429 the same object, return the target function's local entry point
430 offset if usable. */
431 static inline Elf64_Addr __attribute__ ((always_inline))
432 ppc64_local_entry_offset (struct link_map *map, lookup_t sym_map,
433 const Elf64_Rela *reloc)
434 {
435 const Elf64_Sym *symtab;
436 const Elf64_Sym *sym;
437
438 /* If the target function is in a different object, we cannot
439 use the local entry point. */
440 if (sym_map != map)
441 return 0;
442
443 /* If the linker inserted multiple TOCs, we cannot use the
444 local entry point. */
445 if (map->l_info[DT_PPC64(OPT)]
446 && (map->l_info[DT_PPC64(OPT)]->d_un.d_val & PPC64_OPT_MULTI_TOC))
447 return 0;
448
449 /* Otherwise, we can use the local entry point. Retrieve its offset
450 from the symbol's ELF st_other field. */
451 symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
452 sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
453
454 /* If the target function is an ifunc then the local entry offset is
455 for the resolver, not the final destination. */
456 if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
457 return 0;
458
459 return PPC64_LOCAL_ENTRY_OFFSET (sym->st_other);
460 }
461 #endif
462
463 /* Change the PLT entry whose reloc is 'reloc' to call the actual
464 routine. */
465 static inline Elf64_Addr __attribute__ ((always_inline))
466 elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
467 const Elf64_Rela *reloc,
468 Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
469 {
470 #if _CALL_ELF != 2
471 Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
472 Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
473 Elf64_Addr offset = 0;
474
475 PPC_DCBT (&plt->fd_aux);
476 PPC_DCBT (&plt->fd_func);
477 PPC_DCBT (&rel->fd_aux);
478 PPC_DCBT (&rel->fd_func);
479
480 /* If sym_map is NULL, it's a weak undefined sym; Leave the plt zero. */
481 if (sym_map == NULL)
482 return 0;
483
484 /* If the opd entry is not yet relocated (because it's from a shared
485 object that hasn't been processed yet), then manually reloc it. */
486 if (map != sym_map && !sym_map->l_relocated
487 #if !defined RTLD_BOOTSTRAP && defined SHARED
488 /* Bootstrap map doesn't have l_relocated set for it. */
489 && sym_map != &GL(dl_rtld_map)
490 #endif
491 )
492 offset = sym_map->l_addr;
493
494 /* For PPC64, fixup_plt copies the function descriptor from opd
495 over the corresponding PLT entry.
496 Initially, PLT Entry[i] is set up for lazy linking, or is zero.
497 For lazy linking, the fd_toc and fd_aux entries are irrelevant,
498 so for thread safety we write them before changing fd_func. */
499
500 plt->fd_aux = rel->fd_aux + offset;
501 plt->fd_toc = rel->fd_toc + offset;
502 PPC_DCBF (&plt->fd_toc);
503 PPC_ISYNC;
504
505 plt->fd_func = rel->fd_func + offset;
506 PPC_DCBST (&plt->fd_func);
507 PPC_ISYNC;
508 #else
509 finaladdr += ppc64_local_entry_offset (map, sym_map, reloc);
510 *reloc_addr = finaladdr;
511 #endif
512
513 return finaladdr;
514 }
515
516 static inline void __attribute__ ((always_inline))
517 elf_machine_plt_conflict (struct link_map *map, lookup_t sym_map,
518 const Elf64_Rela *reloc,
519 Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
520 {
521 #if _CALL_ELF != 2
522 Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
523 Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
524
525 plt->fd_func = rel->fd_func;
526 plt->fd_aux = rel->fd_aux;
527 plt->fd_toc = rel->fd_toc;
528 PPC_DCBST (&plt->fd_func);
529 PPC_DCBST (&plt->fd_aux);
530 PPC_DCBST (&plt->fd_toc);
531 PPC_SYNC;
532 #else
533 finaladdr += ppc64_local_entry_offset (map, sym_map, reloc);
534 *reloc_addr = finaladdr;
535 #endif
536 }
537
538 /* Return the final value of a plt relocation. */
539 static inline Elf64_Addr
540 elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
541 Elf64_Addr value)
542 {
543 return value + reloc->r_addend;
544 }
545
546
547 /* Names of the architecture-specific auditing callback functions. */
548 #if _CALL_ELF != 2
549 #define ARCH_LA_PLTENTER ppc64_gnu_pltenter
550 #define ARCH_LA_PLTEXIT ppc64_gnu_pltexit
551 #else
552 #define ARCH_LA_PLTENTER ppc64v2_gnu_pltenter
553 #define ARCH_LA_PLTEXIT ppc64v2_gnu_pltexit
554 #endif
555
556 #endif /* dl_machine_h */
557
558 #ifdef RESOLVE_MAP
559
560 #define PPC_LO(v) ((v) & 0xffff)
561 #define PPC_HI(v) (((v) >> 16) & 0xffff)
562 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
563 #define PPC_HIGHER(v) (((v) >> 32) & 0xffff)
564 #define PPC_HIGHERA(v) PPC_HIGHER ((v) + 0x8000)
565 #define PPC_HIGHEST(v) (((v) >> 48) & 0xffff)
566 #define PPC_HIGHESTA(v) PPC_HIGHEST ((v) + 0x8000)
567 #define BIT_INSERT(var, val, mask) \
568 ((var) = ((var) & ~(Elf64_Addr) (mask)) | ((val) & (mask)))
569
570 #define dont_expect(X) __builtin_expect ((X), 0)
571
572 extern void _dl_reloc_overflow (struct link_map *map,
573 const char *name,
574 Elf64_Addr *const reloc_addr,
575 const Elf64_Sym *refsym)
576 attribute_hidden;
577
578 auto inline void __attribute__ ((always_inline))
579 elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
580 void *const reloc_addr_arg)
581 {
582 Elf64_Addr *const reloc_addr = reloc_addr_arg;
583 *reloc_addr = l_addr + reloc->r_addend;
584 }
585
586 /* This computes the value used by TPREL* relocs. */
587 auto inline Elf64_Addr __attribute__ ((always_inline, const))
588 elf_machine_tprel (struct link_map *map,
589 struct link_map *sym_map,
590 const Elf64_Sym *sym,
591 const Elf64_Rela *reloc)
592 {
593 #ifndef RTLD_BOOTSTRAP
594 if (sym_map)
595 {
596 CHECK_STATIC_TLS (map, sym_map);
597 #endif
598 return TLS_TPREL_VALUE (sym_map, sym, reloc);
599 #ifndef RTLD_BOOTSTRAP
600 }
601 #endif
602 return 0;
603 }
604
605 /* Call function at address VALUE (an OPD entry) to resolve ifunc relocs. */
606 auto inline Elf64_Addr __attribute__ ((always_inline))
607 resolve_ifunc (Elf64_Addr value,
608 const struct link_map *map, const struct link_map *sym_map)
609 {
610 #if _CALL_ELF != 2
611 #ifndef RESOLVE_CONFLICT_FIND_MAP
612 /* The function we are calling may not yet have its opd entry relocated. */
613 Elf64_FuncDesc opd;
614 if (map != sym_map
615 # if !defined RTLD_BOOTSTRAP && defined SHARED
616 /* Bootstrap map doesn't have l_relocated set for it. */
617 && sym_map != &GL(dl_rtld_map)
618 # endif
619 && !sym_map->l_relocated)
620 {
621 Elf64_FuncDesc *func = (Elf64_FuncDesc *) value;
622 opd.fd_func = func->fd_func + sym_map->l_addr;
623 opd.fd_toc = func->fd_toc + sym_map->l_addr;
624 opd.fd_aux = func->fd_aux;
625 value = (Elf64_Addr) &opd;
626 }
627 #endif
628 #endif
629 return ((Elf64_Addr (*) (unsigned long int)) value) (GLRO(dl_hwcap));
630 }
631
632 /* Perform the relocation specified by RELOC and SYM (which is fully
633 resolved). MAP is the object containing the reloc. */
634 auto inline void __attribute__ ((always_inline))
635 elf_machine_rela (struct link_map *map,
636 const Elf64_Rela *reloc,
637 const Elf64_Sym *sym,
638 const struct r_found_version *version,
639 void *const reloc_addr_arg,
640 int skip_ifunc)
641 {
642 Elf64_Addr *const reloc_addr = reloc_addr_arg;
643 const int r_type = ELF64_R_TYPE (reloc->r_info);
644 const Elf64_Sym *const refsym = sym;
645 union unaligned
646 {
647 uint16_t u2;
648 uint32_t u4;
649 uint64_t u8;
650 } __attribute__ ((__packed__));
651
652 if (r_type == R_PPC64_RELATIVE)
653 {
654 *reloc_addr = map->l_addr + reloc->r_addend;
655 return;
656 }
657
658 if (__glibc_unlikely (r_type == R_PPC64_NONE))
659 return;
660
661 /* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt
662 and STT_GNU_IFUNC. */
663 struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
664 Elf64_Addr value = ((sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value)
665 + reloc->r_addend);
666
667 if (sym != NULL
668 && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
669 && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
670 && __builtin_expect (!skip_ifunc, 1))
671 value = resolve_ifunc (value, map, sym_map);
672
673 /* For relocs that don't edit code, return.
674 For relocs that might edit instructions, break from the switch. */
675 switch (r_type)
676 {
677 case R_PPC64_ADDR64:
678 case R_PPC64_GLOB_DAT:
679 *reloc_addr = value;
680 return;
681
682 case R_PPC64_IRELATIVE:
683 if (__glibc_likely (!skip_ifunc))
684 value = resolve_ifunc (value, map, sym_map);
685 *reloc_addr = value;
686 return;
687
688 case R_PPC64_JMP_IREL:
689 if (__glibc_likely (!skip_ifunc))
690 value = resolve_ifunc (value, map, sym_map);
691 /* Fall thru */
692 case R_PPC64_JMP_SLOT:
693 #ifdef RESOLVE_CONFLICT_FIND_MAP
694 elf_machine_plt_conflict (map, sym_map, reloc, reloc_addr, value);
695 #else
696 elf_machine_fixup_plt (map, sym_map, reloc, reloc_addr, value);
697 #endif
698 return;
699
700 case R_PPC64_DTPMOD64:
701 #ifdef RTLD_BOOTSTRAP
702 /* During startup the dynamic linker is always index 1. */
703 *reloc_addr = 1;
704 #else
705 /* Get the information from the link map returned by the
706 resolve function. */
707 if (sym_map != NULL)
708 *reloc_addr = sym_map->l_tls_modid;
709 #endif
710 return;
711
712 case R_PPC64_DTPREL64:
713 /* During relocation all TLS symbols are defined and used.
714 Therefore the offset is already correct. */
715 #ifndef RTLD_BOOTSTRAP
716 if (sym_map != NULL)
717 *reloc_addr = TLS_DTPREL_VALUE (sym, reloc);
718 #endif
719 return;
720
721 case R_PPC64_TPREL64:
722 *reloc_addr = elf_machine_tprel (map, sym_map, sym, reloc);
723 return;
724
725 case R_PPC64_TPREL16_LO_DS:
726 value = elf_machine_tprel (map, sym_map, sym, reloc);
727 if (dont_expect ((value & 3) != 0))
728 _dl_reloc_overflow (map, "R_PPC64_TPREL16_LO_DS", reloc_addr, refsym);
729 BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc);
730 break;
731
732 case R_PPC64_TPREL16_DS:
733 value = elf_machine_tprel (map, sym_map, sym, reloc);
734 if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
735 _dl_reloc_overflow (map, "R_PPC64_TPREL16_DS", reloc_addr, refsym);
736 BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc);
737 break;
738
739 case R_PPC64_TPREL16:
740 value = elf_machine_tprel (map, sym_map, sym, reloc);
741 if (dont_expect ((value + 0x8000) >= 0x10000))
742 _dl_reloc_overflow (map, "R_PPC64_TPREL16", reloc_addr, refsym);
743 *(Elf64_Half *) reloc_addr = PPC_LO (value);
744 break;
745
746 case R_PPC64_TPREL16_LO:
747 value = elf_machine_tprel (map, sym_map, sym, reloc);
748 *(Elf64_Half *) reloc_addr = PPC_LO (value);
749 break;
750
751 case R_PPC64_TPREL16_HI:
752 value = elf_machine_tprel (map, sym_map, sym, reloc);
753 if (dont_expect (value + 0x80000000 >= 0x100000000LL))
754 _dl_reloc_overflow (map, "R_PPC64_TPREL16_HI", reloc_addr, refsym);
755 *(Elf64_Half *) reloc_addr = PPC_HI (value);
756 break;
757
758 case R_PPC64_TPREL16_HIGH:
759 value = elf_machine_tprel (map, sym_map, sym, reloc);
760 *(Elf64_Half *) reloc_addr = PPC_HI (value);
761 break;
762
763 case R_PPC64_TPREL16_HA:
764 value = elf_machine_tprel (map, sym_map, sym, reloc);
765 if (dont_expect (value + 0x80008000 >= 0x100000000LL))
766 _dl_reloc_overflow (map, "R_PPC64_TPREL16_HA", reloc_addr, refsym);
767 *(Elf64_Half *) reloc_addr = PPC_HA (value);
768 break;
769
770 case R_PPC64_TPREL16_HIGHA:
771 value = elf_machine_tprel (map, sym_map, sym, reloc);
772 *(Elf64_Half *) reloc_addr = PPC_HA (value);
773 break;
774
775 case R_PPC64_TPREL16_HIGHER:
776 value = elf_machine_tprel (map, sym_map, sym, reloc);
777 *(Elf64_Half *) reloc_addr = PPC_HIGHER (value);
778 break;
779
780 case R_PPC64_TPREL16_HIGHEST:
781 value = elf_machine_tprel (map, sym_map, sym, reloc);
782 *(Elf64_Half *) reloc_addr = PPC_HIGHEST (value);
783 break;
784
785 case R_PPC64_TPREL16_HIGHERA:
786 value = elf_machine_tprel (map, sym_map, sym, reloc);
787 *(Elf64_Half *) reloc_addr = PPC_HIGHERA (value);
788 break;
789
790 case R_PPC64_TPREL16_HIGHESTA:
791 value = elf_machine_tprel (map, sym_map, sym, reloc);
792 *(Elf64_Half *) reloc_addr = PPC_HIGHESTA (value);
793 break;
794
795 #ifndef RTLD_BOOTSTRAP /* None of the following appear in ld.so */
796 case R_PPC64_ADDR16_LO_DS:
797 if (dont_expect ((value & 3) != 0))
798 _dl_reloc_overflow (map, "R_PPC64_ADDR16_LO_DS", reloc_addr, refsym);
799 BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc);
800 break;
801
802 case R_PPC64_ADDR16_LO:
803 *(Elf64_Half *) reloc_addr = PPC_LO (value);
804 break;
805
806 case R_PPC64_ADDR16_HI:
807 if (dont_expect (value + 0x80000000 >= 0x100000000LL))
808 _dl_reloc_overflow (map, "R_PPC64_ADDR16_HI", reloc_addr, refsym);
809 case R_PPC64_ADDR16_HIGH:
810 *(Elf64_Half *) reloc_addr = PPC_HI (value);
811 break;
812
813 case R_PPC64_ADDR16_HA:
814 if (dont_expect (value + 0x80008000 >= 0x100000000LL))
815 _dl_reloc_overflow (map, "R_PPC64_ADDR16_HA", reloc_addr, refsym);
816 case R_PPC64_ADDR16_HIGHA:
817 *(Elf64_Half *) reloc_addr = PPC_HA (value);
818 break;
819
820 case R_PPC64_ADDR30:
821 {
822 Elf64_Addr delta = value - (Elf64_Xword) reloc_addr;
823 if (dont_expect ((delta + 0x80000000) >= 0x100000000LL
824 || (delta & 3) != 0))
825 _dl_reloc_overflow (map, "R_PPC64_ADDR30", reloc_addr, refsym);
826 BIT_INSERT (*(Elf64_Word *) reloc_addr, delta, 0xfffffffc);
827 }
828 break;
829
830 case R_PPC64_COPY:
831 if (dont_expect (sym == NULL))
832 /* This can happen in trace mode when an object could not be found. */
833 return;
834 if (dont_expect (sym->st_size > refsym->st_size
835 || (GLRO(dl_verbose)
836 && sym->st_size < refsym->st_size)))
837 {
838 const char *strtab;
839
840 strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
841 _dl_error_printf ("%s: Symbol `%s' has different size" \
842 " in shared object," \
843 " consider re-linking\n",
844 RTLD_PROGNAME, strtab + refsym->st_name);
845 }
846 memcpy (reloc_addr_arg, (char *) value,
847 MIN (sym->st_size, refsym->st_size));
848 return;
849
850 case R_PPC64_UADDR64:
851 ((union unaligned *) reloc_addr)->u8 = value;
852 return;
853
854 case R_PPC64_UADDR32:
855 ((union unaligned *) reloc_addr)->u4 = value;
856 return;
857
858 case R_PPC64_ADDR32:
859 if (dont_expect ((value + 0x80000000) >= 0x100000000LL))
860 _dl_reloc_overflow (map, "R_PPC64_ADDR32", reloc_addr, refsym);
861 *(Elf64_Word *) reloc_addr = value;
862 return;
863
864 case R_PPC64_ADDR24:
865 if (dont_expect ((value + 0x2000000) >= 0x4000000 || (value & 3) != 0))
866 _dl_reloc_overflow (map, "R_PPC64_ADDR24", reloc_addr, refsym);
867 BIT_INSERT (*(Elf64_Word *) reloc_addr, value, 0x3fffffc);
868 break;
869
870 case R_PPC64_ADDR16:
871 if (dont_expect ((value + 0x8000) >= 0x10000))
872 _dl_reloc_overflow (map, "R_PPC64_ADDR16", reloc_addr, refsym);
873 *(Elf64_Half *) reloc_addr = value;
874 break;
875
876 case R_PPC64_UADDR16:
877 if (dont_expect ((value + 0x8000) >= 0x10000))
878 _dl_reloc_overflow (map, "R_PPC64_UADDR16", reloc_addr, refsym);
879 ((union unaligned *) reloc_addr)->u2 = value;
880 return;
881
882 case R_PPC64_ADDR16_DS:
883 if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
884 _dl_reloc_overflow (map, "R_PPC64_ADDR16_DS", reloc_addr, refsym);
885 BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc);
886 break;
887
888 case R_PPC64_ADDR16_HIGHER:
889 *(Elf64_Half *) reloc_addr = PPC_HIGHER (value);
890 break;
891
892 case R_PPC64_ADDR16_HIGHEST:
893 *(Elf64_Half *) reloc_addr = PPC_HIGHEST (value);
894 break;
895
896 case R_PPC64_ADDR16_HIGHERA:
897 *(Elf64_Half *) reloc_addr = PPC_HIGHERA (value);
898 break;
899
900 case R_PPC64_ADDR16_HIGHESTA:
901 *(Elf64_Half *) reloc_addr = PPC_HIGHESTA (value);
902 break;
903
904 case R_PPC64_ADDR14:
905 case R_PPC64_ADDR14_BRTAKEN:
906 case R_PPC64_ADDR14_BRNTAKEN:
907 {
908 if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
909 _dl_reloc_overflow (map, "R_PPC64_ADDR14", reloc_addr, refsym);
910 Elf64_Word insn = *(Elf64_Word *) reloc_addr;
911 BIT_INSERT (insn, value, 0xfffc);
912 if (r_type != R_PPC64_ADDR14)
913 {
914 insn &= ~(1 << 21);
915 if (r_type == R_PPC64_ADDR14_BRTAKEN)
916 insn |= 1 << 21;
917 if ((insn & (0x14 << 21)) == (0x04 << 21))
918 insn |= 0x02 << 21;
919 else if ((insn & (0x14 << 21)) == (0x10 << 21))
920 insn |= 0x08 << 21;
921 }
922 *(Elf64_Word *) reloc_addr = insn;
923 }
924 break;
925
926 case R_PPC64_REL32:
927 *(Elf64_Word *) reloc_addr = value - (Elf64_Addr) reloc_addr;
928 return;
929
930 case R_PPC64_REL64:
931 *reloc_addr = value - (Elf64_Addr) reloc_addr;
932 return;
933 #endif /* !RTLD_BOOTSTRAP */
934
935 default:
936 _dl_reloc_bad_type (map, r_type, 0);
937 return;
938 }
939 MODIFIED_CODE_NOQUEUE (reloc_addr);
940 }
941
942 auto inline void __attribute__ ((always_inline))
943 elf_machine_lazy_rel (struct link_map *map,
944 Elf64_Addr l_addr, const Elf64_Rela *reloc,
945 int skip_ifunc)
946 {
947 /* elf_machine_runtime_setup handles this. */
948 }
949
950
951 #endif /* RESOLVE */