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