1 /* Machine-dependent ELF dynamic relocation inline functions.
3 Copyright 1995-2018 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/>. */
23 #define ELF_MACHINE_NAME "powerpc64"
26 #include <sys/param.h>
29 #include <hwcapinfo.h>
30 #include <cpu-features.c>
32 /* Translate a processor specific dynamic tag to the index
34 #define DT_PPC64(x) (DT_PPC64_##x - DT_LOPROC + DT_NUM)
37 /* A PowerPC64 function descriptor. The .plt (procedure linkage
38 table) and .opd (official procedure descriptor) sections are
48 #define ELF_MULT_MACHINES_SUPPORTED
50 /* Return nonzero iff ELF header is compatible with the running host. */
52 elf_machine_matches_host (const Elf64_Ehdr
*ehdr
)
54 /* Verify that the binary matches our ABI version. */
55 if ((ehdr
->e_flags
& EF_PPC64_ABI
) != 0)
58 if ((ehdr
->e_flags
& EF_PPC64_ABI
) != 1)
61 if ((ehdr
->e_flags
& EF_PPC64_ABI
) != 2)
66 return ehdr
->e_machine
== EM_PPC64
;
69 /* Return nonzero iff ELF header is compatible with the running host,
70 but not this loader. */
72 elf_host_tolerates_machine (const Elf64_Ehdr
*ehdr
)
74 return ehdr
->e_machine
== EM_PPC
;
77 /* Return nonzero iff ELF header is compatible with the running host,
78 but not this loader. */
80 elf_host_tolerates_class (const Elf64_Ehdr
*ehdr
)
82 return ehdr
->e_ident
[EI_CLASS
] == ELFCLASS32
;
86 /* Return the run-time load address of the shared object, assuming it
87 was originally linked at zero. */
88 static inline Elf64_Addr
89 elf_machine_load_address (void) __attribute__ ((const));
91 static inline Elf64_Addr
92 elf_machine_load_address (void)
96 /* The first entry in .got (and thus the first entry in .toc) is the
97 link-time TOC_base, ie. r2. So the difference between that and
98 the current r2 set by the kernel is how far the shared lib has
100 asm ( " ld %0,-32768(2)\n"
106 /* Return the link-time address of _DYNAMIC. */
107 static inline Elf64_Addr
108 elf_machine_dynamic (void)
110 Elf64_Addr runtime_dynamic
;
111 /* It's easier to get the run-time address. */
112 asm ( " addis %0,2,_DYNAMIC@toc@ha\n"
113 " addi %0,%0,_DYNAMIC@toc@l\n"
114 : "=b" (runtime_dynamic
));
115 /* Then subtract off the load address offset. */
116 return runtime_dynamic
- elf_machine_load_address() ;
119 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */
121 /* The PLT uses Elf64_Rela relocs. */
122 #define elf_machine_relplt elf_machine_rela
125 #ifdef HAVE_INLINED_SYSCALLS
126 /* We do not need _dl_starting_up. */
127 # define DL_STARTING_UP_DEF
129 # define DL_STARTING_UP_DEF \
130 ".LC__dl_starting_up:\n" \
131 " .tc __GI__dl_starting_up[TC],__GI__dl_starting_up\n"
135 /* Initial entry point code for the dynamic linker. The C function
136 `_dl_start' is the real entry point; its return value is the user
137 program's entry point. */
139 asm (".pushsection \".text\"\n" \
141 " " ENTRY_2(_start) "\n" \
142 BODY_PREFIX "_start:\n" \
143 " " LOCALENTRY(_start) "\n" \
144 /* We start with the following on the stack, from top: \
146 arguments for program (terminated by NULL); \
147 environment variables (terminated by NULL); \
148 arguments for the program loader. */ \
151 " stdu 4,-128(1)\n" \
152 /* Call _dl_start with one parameter pointing at argc. */ \
153 " bl " DOT_PREFIX "_dl_start\n" \
155 /* Transfer control to _dl_start_user! */ \
156 " b " DOT_PREFIX "_dl_start_user\n" \
159 " .byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n" \
160 " .long .LT__start-" BODY_PREFIX "_start\n" \
161 " .short .LT__start_name_end-.LT__start_name_start\n" \
162 ".LT__start_name_start:\n" \
163 " .ascii \"_start\"\n" \
164 ".LT__start_name_end:\n" \
166 " " END_2(_start) "\n" \
167 " .pushsection \".toc\",\"aw\"\n" \
169 ".LC__rtld_local:\n" \
170 " .tc _rtld_local[TC],_rtld_local\n" \
172 " .tc _dl_argc[TC],_dl_argc\n" \
174 " .tc __GI__dl_argv[TC],__GI__dl_argv\n" \
176 " .tc _dl_fini[TC],_dl_fini\n" \
178 " " ENTRY_2(_dl_start_user) "\n" \
179 /* Now, we do our main work of calling initialisation procedures. \
180 The ELF ABI doesn't say anything about parameters for these, \
181 so we just pass argc, argv, and the environment. \
182 Changing these is strongly discouraged (not least because argc is \
183 passed by value!). */ \
184 BODY_PREFIX "_dl_start_user:\n" \
185 " " LOCALENTRY(_dl_start_user) "\n" \
186 /* the address of _start in r30. */ \
188 /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28. */ \
189 " ld 28,.LC__rtld_local@toc(2)\n" \
190 " ld 29,.LC__dl_argc@toc(2)\n" \
191 " ld 27,.LC__dl_argv@toc(2)\n" \
192 /* _dl_init (_dl_loaded, _dl_argc, _dl_argv, _dl_argv+_dl_argc+1). */ \
199 " bl " DOT_PREFIX "_dl_init\n" \
201 /* Now, to conform to the ELF ABI, we have to: \
202 Pass argc (actually _dl_argc) in r3; */ \
204 /* Pass argv (actually _dl_argv) in r4; */ \
206 /* Pass argv+argc+1 in r5; */ \
210 /* Pass the auxiliary vector in r6. This is passed to us just after \
216 /* Pass a termination function pointer (in this case _dl_fini) in \
218 " ld 7,.LC__dl_fini@toc(2)\n" \
219 /* Pass the stack pointer in r1 (so far so good), pointing to a NULL \
220 value. This lets our startup code distinguish between a program \
221 linked statically, which linux will call with argc on top of the \
222 stack which will hopefully never be zero, and a dynamically linked \
223 program which will always have a NULL on the top of the stack. \
224 Take the opportunity to clear LR, so anyone who accidentally \
225 returns from _start gets SEGV. Also clear the next few words of \
233 /* Now, call the start function descriptor at r30... */ \
234 " .globl ._dl_main_dispatch\n" \
235 "._dl_main_dispatch:\n" \
236 " " PPC64_LOAD_FUNCPTR(30) "\n" \
238 ".LT__dl_start_user:\n" \
240 " .byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n" \
241 " .long .LT__dl_start_user-" BODY_PREFIX "_dl_start_user\n" \
242 " .short .LT__dl_start_user_name_end-.LT__dl_start_user_name_start\n" \
243 ".LT__dl_start_user_name_start:\n" \
244 " .ascii \"_dl_start_user\"\n" \
245 ".LT__dl_start_user_name_end:\n" \
247 " " END_2(_dl_start_user) "\n" \
250 /* ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to
251 one of the main executable's symbols, as for a COPY reloc.
253 To make function pointer comparisons work on most targets, the
254 relevant ABI states that the address of a non-local function in a
255 dynamically linked executable is the address of the PLT entry for
256 that function. This is quite reasonable since using the real
257 function address in a non-PIC executable would typically require
258 dynamic relocations in .text, something to be avoided. For such
259 functions, the linker emits a SHN_UNDEF symbol in the executable
260 with value equal to the PLT entry address. Normally, SHN_UNDEF
261 symbols have a value of zero, so this is a clue to ld.so that it
262 should treat these symbols specially. For relocations not in
263 ELF_RTYPE_CLASS_PLT (eg. those on function pointers), ld.so should
264 use the value of the executable SHN_UNDEF symbol, ie. the PLT entry
265 address. For relocations in ELF_RTYPE_CLASS_PLT (eg. the relocs in
266 the PLT itself), ld.so should use the value of the corresponding
267 defined symbol in the object that defines the function, ie. the
268 real function address. This complicates ld.so in that there are
269 now two possible values for a given symbol, and it gets even worse
270 because protected symbols need yet another set of rules.
272 On PowerPC64 we don't need any of this. The linker won't emit
273 SHN_UNDEF symbols with non-zero values. ld.so can make all
274 relocations behave "normally", ie. always use the real address
275 like PLT relocations. So always set ELF_RTYPE_CLASS_PLT. */
278 #define elf_machine_type_class(type) \
279 (ELF_RTYPE_CLASS_PLT | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
281 /* And now that you have read that large comment, you can disregard it
282 all for ELFv2. ELFv2 does need the special SHN_UNDEF treatment. */
283 #define IS_PPC64_TLS_RELOC(R) \
284 (((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA) \
285 || ((R) >= R_PPC64_TPREL16_HIGH && (R) <= R_PPC64_DTPREL16_HIGHA))
287 #define elf_machine_type_class(type) \
288 ((((type) == R_PPC64_JMP_SLOT \
289 || (type) == R_PPC64_ADDR24 \
290 || IS_PPC64_TLS_RELOC (type)) * ELF_RTYPE_CLASS_PLT) \
291 | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
294 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
295 #define ELF_MACHINE_JMP_SLOT R_PPC64_JMP_SLOT
297 /* The PowerPC never uses REL relocations. */
298 #define ELF_MACHINE_NO_REL 1
299 #define ELF_MACHINE_NO_RELA 0
301 /* We define an initialization function to initialize HWCAP/HWCAP2 and
302 platform data so it can be copied into the TCB later. This is called
303 very early in _dl_sysdep_start for dynamically linked binaries. */
304 #if defined(SHARED) && IS_IN (rtld)
305 # define DL_PLATFORM_INIT dl_platform_init ()
307 static inline void __attribute__ ((unused
))
308 dl_platform_init (void)
310 __tcb_parse_hwcap_and_convert_at_platform ();
311 init_cpu_features (&GLRO(dl_powerpc_cpu_features
));
315 /* Stuff for the PLT. */
317 #define PLT_INITIAL_ENTRY_WORDS 3
318 #define PLT_ENTRY_WORDS 3
319 #define GLINK_INITIAL_ENTRY_WORDS 8
320 /* The first 32k entries of glink can set an index and branch using two
321 instructions; past that point, glink uses three instructions. */
322 #define GLINK_ENTRY_WORDS(I) (((I) < 0x8000)? 2 : 3)
324 #define PLT_INITIAL_ENTRY_WORDS 2
325 #define PLT_ENTRY_WORDS 1
326 #define GLINK_INITIAL_ENTRY_WORDS 8
327 #define GLINK_ENTRY_WORDS(I) 1
330 #define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where) : "memory")
331 #define PPC_DCBT(where) asm volatile ("dcbt 0,%0" : : "r"(where) : "memory")
332 #define PPC_DCBF(where) asm volatile ("dcbf 0,%0" : : "r"(where) : "memory")
333 #define PPC_SYNC asm volatile ("sync" : : : "memory")
334 #define PPC_ISYNC asm volatile ("sync; isync" : : : "memory")
335 #define PPC_ICBI(where) asm volatile ("icbi 0,%0" : : "r"(where) : "memory")
336 #define PPC_DIE asm volatile ("tweq 0,0")
337 /* Use this when you've modified some code, but it won't be in the
338 instruction fetch queue (or when it doesn't matter if it is). */
339 #define MODIFIED_CODE_NOQUEUE(where) \
340 do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); } while (0)
341 /* Use this when it might be in the instruction queue. */
342 #define MODIFIED_CODE(where) \
343 do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); PPC_ISYNC; } while (0)
345 /* Set up the loaded object described by MAP so its unrelocated PLT
346 entries will jump to the on-demand fixup code in dl-runtime.c. */
347 static inline int __attribute__ ((always_inline
))
348 elf_machine_runtime_setup (struct link_map
*map
, int lazy
, int profile
)
350 if (map
->l_info
[DT_JMPREL
])
353 Elf64_Word
*glink
= NULL
;
354 Elf64_Xword
*plt
= (Elf64_Xword
*) D_PTR (map
, l_info
[DT_PLTGOT
]);
355 Elf64_Word num_plt_entries
= (map
->l_info
[DT_PLTRELSZ
]->d_un
.d_val
356 / sizeof (Elf64_Rela
));
357 Elf64_Addr l_addr
= map
->l_addr
;
358 Elf64_Dyn
**info
= map
->l_info
;
361 extern void _dl_runtime_resolve (void);
362 extern void _dl_profile_resolve (void);
364 /* Relocate the DT_PPC64_GLINK entry in the _DYNAMIC section.
365 elf_get_dynamic_info takes care of the standard entries but
366 doesn't know exactly what to do with processor specific
368 if (info
[DT_PPC64(GLINK
)] != NULL
)
369 info
[DT_PPC64(GLINK
)]->d_un
.d_ptr
+= l_addr
;
373 Elf64_Word glink_offset
;
377 dlrr
= (Elf64_Addr
) (profile
? _dl_profile_resolve
378 : _dl_runtime_resolve
);
379 if (profile
&& GLRO(dl_profile
) != NULL
380 && _dl_name_match_p (GLRO(dl_profile
), map
))
381 /* This is the object we are looking for. Say that we really
382 want profiling and the timers are started. */
383 GL(dl_profile_map
) = map
;
386 /* We need to stuff the address/TOC of _dl_runtime_resolve
387 into doublewords 0 and 1 of plt_reserve. Then we need to
388 stuff the map address into doubleword 2 of plt_reserve.
389 This allows the GLINK0 code to transfer control to the
390 correct trampoline which will transfer control to fixup
393 /* The plt_reserve area is the 1st 3 doublewords of the PLT. */
394 Elf64_FuncDesc
*plt_reserve
= (Elf64_FuncDesc
*) plt
;
395 Elf64_FuncDesc
*resolve_fd
= (Elf64_FuncDesc
*) dlrr
;
396 plt_reserve
->fd_func
= resolve_fd
->fd_func
;
397 plt_reserve
->fd_toc
= resolve_fd
->fd_toc
;
398 plt_reserve
->fd_aux
= (Elf64_Addr
) map
;
399 #ifdef RTLD_BOOTSTRAP
400 /* When we're bootstrapping, the opd entry will not have
401 been relocated yet. */
402 plt_reserve
->fd_func
+= l_addr
;
403 plt_reserve
->fd_toc
+= l_addr
;
407 /* When we don't have function descriptors, the first doubleword
408 of the PLT holds the address of _dl_runtime_resolve, and the
409 second doubleword holds the map address. */
411 plt
[1] = (Elf64_Addr
) map
;
414 /* Set up the lazy PLT entries. */
415 glink
= (Elf64_Word
*) D_PTR (map
, l_info
[DT_PPC64(GLINK
)]);
416 offset
= PLT_INITIAL_ENTRY_WORDS
;
417 glink_offset
= GLINK_INITIAL_ENTRY_WORDS
;
418 for (i
= 0; i
< num_plt_entries
; i
++)
421 plt
[offset
] = (Elf64_Xword
) &glink
[glink_offset
];
422 offset
+= PLT_ENTRY_WORDS
;
423 glink_offset
+= GLINK_ENTRY_WORDS (i
);
426 /* Now, we've modified data. We need to write the changes from
427 the data cache to a second-level unified cache, then make
428 sure that stale data in the instruction cache is removed.
429 (In a multiprocessor system, the effect is more complex.)
430 Most of the PLT shouldn't be in the instruction cache, but
431 there may be a little overlap at the start and the end.
433 Assumes that dcbst and icbi apply to lines of 16 bytes or
434 more. Current known line sizes are 16, 32, and 128 bytes. */
436 for (p
= (char *) plt
; p
< (char *) &plt
[offset
]; p
+= 16)
445 extern void attribute_hidden
_dl_error_localentry (struct link_map
*map
,
446 const Elf64_Sym
*refsym
);
448 /* If the PLT entry resolves to a function in the same object, return
449 the target function's local entry point offset if usable. */
450 static inline Elf64_Addr
__attribute__ ((always_inline
))
451 ppc64_local_entry_offset (struct link_map
*map
, lookup_t sym_map
,
452 const ElfW(Sym
) *refsym
, const ElfW(Sym
) *sym
)
454 /* If the target function is in a different object, we cannot
455 use the local entry point. */
458 /* Check that optimized plt call stubs for localentry:0 functions
459 are not being satisfied by a non-zero localentry symbol. */
460 if (map
->l_info
[DT_PPC64(OPT
)]
461 && (map
->l_info
[DT_PPC64(OPT
)]->d_un
.d_val
& PPC64_OPT_LOCALENTRY
) != 0
462 && refsym
->st_info
== ELFW(ST_INFO
) (STB_GLOBAL
, STT_FUNC
)
463 && (STO_PPC64_LOCAL_MASK
& refsym
->st_other
) == 0
464 && (STO_PPC64_LOCAL_MASK
& sym
->st_other
) != 0)
465 _dl_error_localentry (map
, refsym
);
470 /* If the linker inserted multiple TOCs, we cannot use the
471 local entry point. */
472 if (map
->l_info
[DT_PPC64(OPT
)]
473 && (map
->l_info
[DT_PPC64(OPT
)]->d_un
.d_val
& PPC64_OPT_MULTI_TOC
))
476 /* If the target function is an ifunc then the local entry offset is
477 for the resolver, not the final destination. */
478 if (__builtin_expect (ELFW(ST_TYPE
) (sym
->st_info
) == STT_GNU_IFUNC
, 0))
481 /* Otherwise, we can use the local entry point. Retrieve its offset
482 from the symbol's ELF st_other field. */
483 return PPC64_LOCAL_ENTRY_OFFSET (sym
->st_other
);
487 /* Change the PLT entry whose reloc is 'reloc' to call the actual
489 static inline Elf64_Addr
__attribute__ ((always_inline
))
490 elf_machine_fixup_plt (struct link_map
*map
, lookup_t sym_map
,
491 const ElfW(Sym
) *refsym
, const ElfW(Sym
) *sym
,
492 const Elf64_Rela
*reloc
,
493 Elf64_Addr
*reloc_addr
, Elf64_Addr finaladdr
)
496 Elf64_FuncDesc
*plt
= (Elf64_FuncDesc
*) reloc_addr
;
497 Elf64_FuncDesc
*rel
= (Elf64_FuncDesc
*) finaladdr
;
498 Elf64_Addr offset
= 0;
499 Elf64_FuncDesc zero_fd
= {0, 0, 0};
501 PPC_DCBT (&plt
->fd_aux
);
502 PPC_DCBT (&plt
->fd_func
);
504 /* If sym_map is NULL, it's a weak undefined sym; Set the plt to
505 zero. finaladdr should be zero already in this case, but guard
506 against invalid plt relocations with non-zero addends. */
510 /* Don't die here if finaladdr is zero, die if this plt entry is
511 actually called. Makes a difference when LD_BIND_NOW=1.
512 finaladdr may be zero for a weak undefined symbol, or when an
513 ifunc resolver returns zero. */
518 PPC_DCBT (&rel
->fd_aux
);
519 PPC_DCBT (&rel
->fd_func
);
522 /* If the opd entry is not yet relocated (because it's from a shared
523 object that hasn't been processed yet), then manually reloc it. */
524 if (finaladdr
!= 0 && map
!= sym_map
&& !sym_map
->l_relocated
525 #if !defined RTLD_BOOTSTRAP && defined SHARED
526 /* Bootstrap map doesn't have l_relocated set for it. */
527 && sym_map
!= &GL(dl_rtld_map
)
530 offset
= sym_map
->l_addr
;
532 /* For PPC64, fixup_plt copies the function descriptor from opd
533 over the corresponding PLT entry.
534 Initially, PLT Entry[i] is set up for lazy linking, or is zero.
535 For lazy linking, the fd_toc and fd_aux entries are irrelevant,
536 so for thread safety we write them before changing fd_func. */
538 plt
->fd_aux
= rel
->fd_aux
+ offset
;
539 plt
->fd_toc
= rel
->fd_toc
+ offset
;
540 PPC_DCBF (&plt
->fd_toc
);
543 plt
->fd_func
= rel
->fd_func
+ offset
;
544 PPC_DCBST (&plt
->fd_func
);
547 finaladdr
+= ppc64_local_entry_offset (map
, sym_map
, refsym
, sym
);
548 *reloc_addr
= finaladdr
;
554 static inline void __attribute__ ((always_inline
))
555 elf_machine_plt_conflict (struct link_map
*map
, lookup_t sym_map
,
556 const ElfW(Sym
) *refsym
, const ElfW(Sym
) *sym
,
557 const Elf64_Rela
*reloc
,
558 Elf64_Addr
*reloc_addr
, Elf64_Addr finaladdr
)
561 Elf64_FuncDesc
*plt
= (Elf64_FuncDesc
*) reloc_addr
;
562 Elf64_FuncDesc
*rel
= (Elf64_FuncDesc
*) finaladdr
;
563 Elf64_FuncDesc zero_fd
= {0, 0, 0};
571 plt
->fd_func
= rel
->fd_func
;
572 plt
->fd_aux
= rel
->fd_aux
;
573 plt
->fd_toc
= rel
->fd_toc
;
574 PPC_DCBST (&plt
->fd_func
);
575 PPC_DCBST (&plt
->fd_aux
);
576 PPC_DCBST (&plt
->fd_toc
);
579 finaladdr
+= ppc64_local_entry_offset (map
, sym_map
, refsym
, sym
);
580 *reloc_addr
= finaladdr
;
584 /* Return the final value of a plt relocation. */
585 static inline Elf64_Addr
586 elf_machine_plt_value (struct link_map
*map
, const Elf64_Rela
*reloc
,
589 return value
+ reloc
->r_addend
;
593 /* Names of the architecture-specific auditing callback functions. */
595 #define ARCH_LA_PLTENTER ppc64_gnu_pltenter
596 #define ARCH_LA_PLTEXIT ppc64_gnu_pltexit
598 #define ARCH_LA_PLTENTER ppc64v2_gnu_pltenter
599 #define ARCH_LA_PLTEXIT ppc64v2_gnu_pltexit
602 #endif /* dl_machine_h */
606 #define PPC_LO(v) ((v) & 0xffff)
607 #define PPC_HI(v) (((v) >> 16) & 0xffff)
608 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
609 #define PPC_HIGHER(v) (((v) >> 32) & 0xffff)
610 #define PPC_HIGHERA(v) PPC_HIGHER ((v) + 0x8000)
611 #define PPC_HIGHEST(v) (((v) >> 48) & 0xffff)
612 #define PPC_HIGHESTA(v) PPC_HIGHEST ((v) + 0x8000)
613 #define BIT_INSERT(var, val, mask) \
614 ((var) = ((var) & ~(Elf64_Addr) (mask)) | ((val) & (mask)))
616 #define dont_expect(X) __builtin_expect ((X), 0)
618 extern void attribute_hidden
_dl_reloc_overflow (struct link_map
*map
,
620 Elf64_Addr
*const reloc_addr
,
621 const Elf64_Sym
*refsym
);
623 auto inline void __attribute__ ((always_inline
))
624 elf_machine_rela_relative (Elf64_Addr l_addr
, const Elf64_Rela
*reloc
,
625 void *const reloc_addr_arg
)
627 Elf64_Addr
*const reloc_addr
= reloc_addr_arg
;
628 *reloc_addr
= l_addr
+ reloc
->r_addend
;
631 /* This computes the value used by TPREL* relocs. */
632 auto inline Elf64_Addr
__attribute__ ((always_inline
, const))
633 elf_machine_tprel (struct link_map
*map
,
634 struct link_map
*sym_map
,
635 const Elf64_Sym
*sym
,
636 const Elf64_Rela
*reloc
)
638 #ifndef RTLD_BOOTSTRAP
641 CHECK_STATIC_TLS (map
, sym_map
);
643 return TLS_TPREL_VALUE (sym_map
, sym
, reloc
);
644 #ifndef RTLD_BOOTSTRAP
650 /* Call function at address VALUE (an OPD entry) to resolve ifunc relocs. */
651 auto inline Elf64_Addr
__attribute__ ((always_inline
))
652 resolve_ifunc (Elf64_Addr value
,
653 const struct link_map
*map
, const struct link_map
*sym_map
)
656 #ifndef RESOLVE_CONFLICT_FIND_MAP
657 /* The function we are calling may not yet have its opd entry relocated. */
660 # if !defined RTLD_BOOTSTRAP && defined SHARED
661 /* Bootstrap map doesn't have l_relocated set for it. */
662 && sym_map
!= &GL(dl_rtld_map
)
664 && !sym_map
->l_relocated
)
666 Elf64_FuncDesc
*func
= (Elf64_FuncDesc
*) value
;
667 opd
.fd_func
= func
->fd_func
+ sym_map
->l_addr
;
668 opd
.fd_toc
= func
->fd_toc
+ sym_map
->l_addr
;
669 opd
.fd_aux
= func
->fd_aux
;
670 /* GCC 4.9+ eliminates the branch as dead code, force the odp set
672 asm ("" : "=r" (value
) : "0" (&opd
), "X" (opd
));
676 return ((Elf64_Addr (*) (unsigned long int)) value
) (GLRO(dl_hwcap
));
679 /* Perform the relocation specified by RELOC and SYM (which is fully
680 resolved). MAP is the object containing the reloc. */
681 auto inline void __attribute__ ((always_inline
))
682 elf_machine_rela (struct link_map
*map
,
683 const Elf64_Rela
*reloc
,
684 const Elf64_Sym
*sym
,
685 const struct r_found_version
*version
,
686 void *const reloc_addr_arg
,
689 Elf64_Addr
*const reloc_addr
= reloc_addr_arg
;
690 const int r_type
= ELF64_R_TYPE (reloc
->r_info
);
691 const Elf64_Sym
*const refsym
= sym
;
697 } __attribute__ ((__packed__
));
699 if (r_type
== R_PPC64_RELATIVE
)
701 *reloc_addr
= map
->l_addr
+ reloc
->r_addend
;
705 if (__glibc_unlikely (r_type
== R_PPC64_NONE
))
708 /* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt
709 and STT_GNU_IFUNC. */
710 struct link_map
*sym_map
= RESOLVE_MAP (&sym
, version
, r_type
);
711 Elf64_Addr value
= ((sym_map
== NULL
? 0 : sym_map
->l_addr
+ sym
->st_value
)
715 && __builtin_expect (ELFW(ST_TYPE
) (sym
->st_info
) == STT_GNU_IFUNC
, 0)
716 && __builtin_expect (sym
->st_shndx
!= SHN_UNDEF
, 1)
717 && __builtin_expect (!skip_ifunc
, 1))
718 value
= resolve_ifunc (value
, map
, sym_map
);
720 /* For relocs that don't edit code, return.
721 For relocs that might edit instructions, break from the switch. */
725 case R_PPC64_GLOB_DAT
:
729 case R_PPC64_IRELATIVE
:
730 if (__glibc_likely (!skip_ifunc
))
731 value
= resolve_ifunc (value
, map
, sym_map
);
735 case R_PPC64_JMP_IREL
:
736 if (__glibc_likely (!skip_ifunc
))
737 value
= resolve_ifunc (value
, map
, sym_map
);
739 case R_PPC64_JMP_SLOT
:
740 #ifdef RESOLVE_CONFLICT_FIND_MAP
741 elf_machine_plt_conflict (map
, sym_map
, refsym
, sym
,
742 reloc
, reloc_addr
, value
);
744 elf_machine_fixup_plt (map
, sym_map
, refsym
, sym
,
745 reloc
, reloc_addr
, value
);
749 case R_PPC64_DTPMOD64
:
750 if (map
->l_info
[DT_PPC64(OPT
)]
751 && (map
->l_info
[DT_PPC64(OPT
)]->d_un
.d_val
& PPC64_OPT_TLS
))
753 #ifdef RTLD_BOOTSTRAP
755 reloc_addr
[1] = (sym_map
->l_tls_offset
- TLS_TP_OFFSET
762 CHECK_STATIC_TLS (map
, sym_map
);
764 if (TRY_STATIC_TLS (map
, sym_map
))
768 /* Set up for local dynamic. */
769 reloc_addr
[1] = (sym_map
->l_tls_offset
- TLS_TP_OFFSET
776 #ifdef RTLD_BOOTSTRAP
777 /* During startup the dynamic linker is always index 1. */
780 /* Get the information from the link map returned by the
783 *reloc_addr
= sym_map
->l_tls_modid
;
787 case R_PPC64_DTPREL64
:
788 if (map
->l_info
[DT_PPC64(OPT
)]
789 && (map
->l_info
[DT_PPC64(OPT
)]->d_un
.d_val
& PPC64_OPT_TLS
))
791 #ifdef RTLD_BOOTSTRAP
792 *reloc_addr
= TLS_TPREL_VALUE (sym_map
, sym
, reloc
);
797 /* This reloc is always preceded by R_PPC64_DTPMOD64. */
799 assert (HAVE_STATIC_TLS (map
, sym_map
));
801 if (HAVE_STATIC_TLS (map
, sym_map
))
804 *reloc_addr
= TLS_TPREL_VALUE (sym_map
, sym
, reloc
);
810 /* During relocation all TLS symbols are defined and used.
811 Therefore the offset is already correct. */
812 #ifndef RTLD_BOOTSTRAP
814 *reloc_addr
= TLS_DTPREL_VALUE (sym
, reloc
);
818 case R_PPC64_TPREL64
:
819 *reloc_addr
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
822 case R_PPC64_TPREL16_LO_DS
:
823 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
824 if (dont_expect ((value
& 3) != 0))
825 _dl_reloc_overflow (map
, "R_PPC64_TPREL16_LO_DS", reloc_addr
, refsym
);
826 BIT_INSERT (*(Elf64_Half
*) reloc_addr
, value
, 0xfffc);
829 case R_PPC64_TPREL16_DS
:
830 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
831 if (dont_expect ((value
+ 0x8000) >= 0x10000 || (value
& 3) != 0))
832 _dl_reloc_overflow (map
, "R_PPC64_TPREL16_DS", reloc_addr
, refsym
);
833 BIT_INSERT (*(Elf64_Half
*) reloc_addr
, value
, 0xfffc);
836 case R_PPC64_TPREL16
:
837 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
838 if (dont_expect ((value
+ 0x8000) >= 0x10000))
839 _dl_reloc_overflow (map
, "R_PPC64_TPREL16", reloc_addr
, refsym
);
840 *(Elf64_Half
*) reloc_addr
= PPC_LO (value
);
843 case R_PPC64_TPREL16_LO
:
844 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
845 *(Elf64_Half
*) reloc_addr
= PPC_LO (value
);
848 case R_PPC64_TPREL16_HI
:
849 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
850 if (dont_expect (value
+ 0x80000000 >= 0x100000000LL
))
851 _dl_reloc_overflow (map
, "R_PPC64_TPREL16_HI", reloc_addr
, refsym
);
852 *(Elf64_Half
*) reloc_addr
= PPC_HI (value
);
855 case R_PPC64_TPREL16_HIGH
:
856 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
857 *(Elf64_Half
*) reloc_addr
= PPC_HI (value
);
860 case R_PPC64_TPREL16_HA
:
861 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
862 if (dont_expect (value
+ 0x80008000 >= 0x100000000LL
))
863 _dl_reloc_overflow (map
, "R_PPC64_TPREL16_HA", reloc_addr
, refsym
);
864 *(Elf64_Half
*) reloc_addr
= PPC_HA (value
);
867 case R_PPC64_TPREL16_HIGHA
:
868 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
869 *(Elf64_Half
*) reloc_addr
= PPC_HA (value
);
872 case R_PPC64_TPREL16_HIGHER
:
873 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
874 *(Elf64_Half
*) reloc_addr
= PPC_HIGHER (value
);
877 case R_PPC64_TPREL16_HIGHEST
:
878 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
879 *(Elf64_Half
*) reloc_addr
= PPC_HIGHEST (value
);
882 case R_PPC64_TPREL16_HIGHERA
:
883 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
884 *(Elf64_Half
*) reloc_addr
= PPC_HIGHERA (value
);
887 case R_PPC64_TPREL16_HIGHESTA
:
888 value
= elf_machine_tprel (map
, sym_map
, sym
, reloc
);
889 *(Elf64_Half
*) reloc_addr
= PPC_HIGHESTA (value
);
892 #ifndef RTLD_BOOTSTRAP /* None of the following appear in ld.so */
893 case R_PPC64_ADDR16_LO_DS
:
894 if (dont_expect ((value
& 3) != 0))
895 _dl_reloc_overflow (map
, "R_PPC64_ADDR16_LO_DS", reloc_addr
, refsym
);
896 BIT_INSERT (*(Elf64_Half
*) reloc_addr
, value
, 0xfffc);
899 case R_PPC64_ADDR16_LO
:
900 *(Elf64_Half
*) reloc_addr
= PPC_LO (value
);
903 case R_PPC64_ADDR16_HI
:
904 if (dont_expect (value
+ 0x80000000 >= 0x100000000LL
))
905 _dl_reloc_overflow (map
, "R_PPC64_ADDR16_HI", reloc_addr
, refsym
);
906 case R_PPC64_ADDR16_HIGH
:
907 *(Elf64_Half
*) reloc_addr
= PPC_HI (value
);
910 case R_PPC64_ADDR16_HA
:
911 if (dont_expect (value
+ 0x80008000 >= 0x100000000LL
))
912 _dl_reloc_overflow (map
, "R_PPC64_ADDR16_HA", reloc_addr
, refsym
);
913 case R_PPC64_ADDR16_HIGHA
:
914 *(Elf64_Half
*) reloc_addr
= PPC_HA (value
);
919 Elf64_Addr delta
= value
- (Elf64_Xword
) reloc_addr
;
920 if (dont_expect ((delta
+ 0x80000000) >= 0x100000000LL
921 || (delta
& 3) != 0))
922 _dl_reloc_overflow (map
, "R_PPC64_ADDR30", reloc_addr
, refsym
);
923 BIT_INSERT (*(Elf64_Word
*) reloc_addr
, delta
, 0xfffffffc);
928 if (dont_expect (sym
== NULL
))
929 /* This can happen in trace mode when an object could not be found. */
931 if (dont_expect (sym
->st_size
> refsym
->st_size
933 && sym
->st_size
< refsym
->st_size
)))
937 strtab
= (const void *) D_PTR (map
, l_info
[DT_STRTAB
]);
938 _dl_error_printf ("%s: Symbol `%s' has different size" \
939 " in shared object," \
940 " consider re-linking\n",
941 RTLD_PROGNAME
, strtab
+ refsym
->st_name
);
943 memcpy (reloc_addr_arg
, (char *) value
,
944 MIN (sym
->st_size
, refsym
->st_size
));
947 case R_PPC64_UADDR64
:
948 ((union unaligned
*) reloc_addr
)->u8
= value
;
951 case R_PPC64_UADDR32
:
952 ((union unaligned
*) reloc_addr
)->u4
= value
;
956 if (dont_expect ((value
+ 0x80000000) >= 0x100000000LL
))
957 _dl_reloc_overflow (map
, "R_PPC64_ADDR32", reloc_addr
, refsym
);
958 *(Elf64_Word
*) reloc_addr
= value
;
962 if (dont_expect ((value
+ 0x2000000) >= 0x4000000 || (value
& 3) != 0))
963 _dl_reloc_overflow (map
, "R_PPC64_ADDR24", reloc_addr
, refsym
);
964 BIT_INSERT (*(Elf64_Word
*) reloc_addr
, value
, 0x3fffffc);
968 if (dont_expect ((value
+ 0x8000) >= 0x10000))
969 _dl_reloc_overflow (map
, "R_PPC64_ADDR16", reloc_addr
, refsym
);
970 *(Elf64_Half
*) reloc_addr
= value
;
973 case R_PPC64_UADDR16
:
974 if (dont_expect ((value
+ 0x8000) >= 0x10000))
975 _dl_reloc_overflow (map
, "R_PPC64_UADDR16", reloc_addr
, refsym
);
976 ((union unaligned
*) reloc_addr
)->u2
= value
;
979 case R_PPC64_ADDR16_DS
:
980 if (dont_expect ((value
+ 0x8000) >= 0x10000 || (value
& 3) != 0))
981 _dl_reloc_overflow (map
, "R_PPC64_ADDR16_DS", reloc_addr
, refsym
);
982 BIT_INSERT (*(Elf64_Half
*) reloc_addr
, value
, 0xfffc);
985 case R_PPC64_ADDR16_HIGHER
:
986 *(Elf64_Half
*) reloc_addr
= PPC_HIGHER (value
);
989 case R_PPC64_ADDR16_HIGHEST
:
990 *(Elf64_Half
*) reloc_addr
= PPC_HIGHEST (value
);
993 case R_PPC64_ADDR16_HIGHERA
:
994 *(Elf64_Half
*) reloc_addr
= PPC_HIGHERA (value
);
997 case R_PPC64_ADDR16_HIGHESTA
:
998 *(Elf64_Half
*) reloc_addr
= PPC_HIGHESTA (value
);
1001 case R_PPC64_ADDR14
:
1002 case R_PPC64_ADDR14_BRTAKEN
:
1003 case R_PPC64_ADDR14_BRNTAKEN
:
1005 if (dont_expect ((value
+ 0x8000) >= 0x10000 || (value
& 3) != 0))
1006 _dl_reloc_overflow (map
, "R_PPC64_ADDR14", reloc_addr
, refsym
);
1007 Elf64_Word insn
= *(Elf64_Word
*) reloc_addr
;
1008 BIT_INSERT (insn
, value
, 0xfffc);
1009 if (r_type
!= R_PPC64_ADDR14
)
1012 if (r_type
== R_PPC64_ADDR14_BRTAKEN
)
1014 if ((insn
& (0x14 << 21)) == (0x04 << 21))
1016 else if ((insn
& (0x14 << 21)) == (0x10 << 21))
1019 *(Elf64_Word
*) reloc_addr
= insn
;
1024 *(Elf64_Word
*) reloc_addr
= value
- (Elf64_Addr
) reloc_addr
;
1028 *reloc_addr
= value
- (Elf64_Addr
) reloc_addr
;
1030 #endif /* !RTLD_BOOTSTRAP */
1033 _dl_reloc_bad_type (map
, r_type
, 0);
1036 MODIFIED_CODE_NOQUEUE (reloc_addr
);
1039 auto inline void __attribute__ ((always_inline
))
1040 elf_machine_lazy_rel (struct link_map
*map
,
1041 Elf64_Addr l_addr
, const Elf64_Rela
*reloc
,
1044 /* elf_machine_runtime_setup handles this. */
1048 #endif /* RESOLVE */