87982638ee2937ad408b0f9696306fac75d8e190
[kopensolaris-gnu/glibc.git] / sysdeps / powerpc / powerpc64 / dl-machine.h
1 /* Machine-dependent ELF dynamic relocation inline functions.
2    PowerPC64 version.
3    Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    Free Software Foundation, Inc.
5    This file is part of the GNU C Library.
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16
17    You should have received a copy of the GNU Library General Public
18    License along with the GNU C Library; see the file COPYING.LIB.  If not,
19    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #ifndef dl_machine_h
23 #define dl_machine_h
24
25 #define ELF_MACHINE_NAME "powerpc64"
26
27 #include <assert.h>
28 #include <sys/param.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 /* A PowerPC64 function descriptor.  The .plt (procedure linkage
35    table) and .opd (official procedure descriptor) sections are
36    arrays of these.  */
37 typedef struct
38 {
39   Elf64_Addr fd_func;
40   Elf64_Addr fd_toc;
41   Elf64_Addr fd_aux;
42 } Elf64_FuncDesc;
43
44 #define ELF_MULT_MACHINES_SUPPORTED
45
46 /* Return nonzero iff ELF header is compatible with the running host.  */
47 static inline int
48 elf_machine_matches_host (const Elf64_Ehdr *ehdr)
49 {
50   return ehdr->e_machine == EM_PPC64;
51 }
52
53 /* Return nonzero iff ELF header is compatible with the running host,
54    but not this loader.  */
55 static inline int
56 elf_host_tolerates_machine (const Elf64_Ehdr *ehdr)
57 {
58   return ehdr->e_machine == EM_PPC;
59 }
60
61 /* Return nonzero iff ELF header is compatible with the running host,
62    but not this loader.  */
63 static inline int
64 elf_host_tolerates_class (const Elf64_Ehdr *ehdr)
65 {
66   return ehdr->e_ident[EI_CLASS] == ELFCLASS32;
67 }
68
69
70 /* Return the run-time load address of the shared object, assuming it
71    was originally linked at zero.  */
72 static inline Elf64_Addr
73 elf_machine_load_address (void) __attribute__ ((const));
74
75 static inline Elf64_Addr
76 elf_machine_load_address (void)
77 {
78   Elf64_Addr ret;
79
80   /* The first entry in .got (and thus the first entry in .toc) is the
81      link-time TOC_base, ie. r2.  So the difference between that and
82      the current r2 set by the kernel is how far the shared lib has
83      moved.  */
84   asm ( "       ld      %0,-32768(2)\n"
85         "       subf    %0,%0,2\n"
86         : "=r"  (ret));
87   return ret;
88 }
89
90 /* Return the link-time address of _DYNAMIC.  */
91 static inline Elf64_Addr
92 elf_machine_dynamic (void)
93 {
94   Elf64_Addr runtime_dynamic;
95   /* It's easier to get the run-time address.  */
96   asm ( "       addis   %0,2,_DYNAMIC@toc@ha\n"
97         "       addi    %0,%0,_DYNAMIC@toc@l\n"
98         : "=b"  (runtime_dynamic));
99   /* Then subtract off the load address offset.  */
100   return runtime_dynamic - elf_machine_load_address() ;
101 }
102
103 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */
104
105 /* The PLT uses Elf64_Rela relocs.  */
106 #define elf_machine_relplt elf_machine_rela
107
108 /* This code gets called via a .glink stub which loads PLT0.  It is
109    used in dl-runtime.c to call the `fixup' function and then redirect
110    to the address `fixup' returns.
111
112    Enter with r0 = plt reloc index,
113    r2 = ld.so tocbase,
114    r11 = ld.so link map.  */
115
116 #define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
117   asm (".section \".text\"\n"                                           \
118 "       .align  2\n"                                                    \
119 "       .globl  ." #tramp_name "\n"                                     \
120 "       .type   ." #tramp_name ",@function\n"                           \
121 "       .section \".opd\",\"aw\"\n"                                     \
122 "       .align  3\n"                                                    \
123 "       .globl  " #tramp_name "\n"                                      \
124 "       .size   " #tramp_name ",24\n"                                   \
125 #tramp_name ":\n"                                                       \
126 "       .quad   ." #tramp_name ",.TOC.@tocbase,0\n"                     \
127 "       .previous\n"                                                    \
128 "." #tramp_name ":\n"                                                   \
129 /* We need to save the registers used to pass parameters, ie. r3 thru   \
130    r10; the registers are saved in a stack frame.  */                   \
131 "       stdu    1,-128(1)\n"                                            \
132 "       std     3,48(1)\n"                                              \
133 "       mr      3,11\n"                                                 \
134 "       std     4,56(1)\n"                                              \
135 "       sldi    4,0,1\n"                                                \
136 "       std     5,64(1)\n"                                              \
137 "       add     4,4,0\n"                                                \
138 "       std     6,72(1)\n"                                              \
139 "       sldi    4,4,3\n"                                                \
140 "       std     7,80(1)\n"                                              \
141 "       mflr    0\n"                                                    \
142 "       std     8,88(1)\n"                                              \
143 /* Store the LR in the LR Save area of the previous frame.  */    \
144 "       std     0,128+16(1)\n"                                          \
145 "       mfcr    0\n"                                                    \
146 "       std     9,96(1)\n"                                              \
147 "       std     10,104(1)\n"                                            \
148 /* I'm almost certain we don't have to save cr...  be safe.  */    \
149 "       std     0,8(1)\n"                                               \
150 "       bl      ." #fixup_name "\n"                                     \
151 /* Put the registers back.  */                                          \
152 "       ld      0,128+16(1)\n"                                          \
153 "       ld      10,104(1)\n"                                            \
154 "       ld      9,96(1)\n"                                              \
155 "       ld      8,88(1)\n"                                              \
156 "       ld      7,80(1)\n"                                              \
157 "       mtlr    0\n"                                                    \
158 "       ld      0,8(1)\n"                                               \
159 "       ld      6,72(1)\n"                                              \
160 "       ld      5,64(1)\n"                                              \
161 "       ld      4,56(1)\n"                                              \
162 "       mtcrf   0xFF,0\n"                                               \
163 /* Load the target address, toc and static chain reg from the function  \
164    descriptor returned by fixup.  */                                    \
165 "       ld      0,0(3)\n"                                               \
166 "       ld      2,8(3)\n"                                               \
167 "       mtctr   0\n"                                                    \
168 "       ld      11,16(3)\n"                                             \
169 "       ld      3,48(1)\n"                                              \
170 /* Unwind the stack frame, and jump.  */                                \
171 "       addi    1,1,128\n"                                              \
172 "       bctr\n"                                                         \
173 ".LT_" #tramp_name ":\n"                                                \
174 "       .long 0\n"                                                      \
175 "       .byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n"                \
176 "       .long .LT_" #tramp_name "-."#tramp_name "\n"                    \
177 "       .short .LT_" #tramp_name "_name_end-.LT_" #tramp_name "_name_start\n" \
178 ".LT_" #tramp_name "_name_start:\n"                                     \
179 "       .ascii \"" #tramp_name "\"\n"                                   \
180 ".LT_" #tramp_name "_name_end:\n"                                       \
181 "       .align 2\n"                                                     \
182 "       .size   ." #tramp_name ",. - ." #tramp_name "\n"                \
183 "       .previous");
184
185 #ifndef PROF
186 #define ELF_MACHINE_RUNTIME_TRAMPOLINE                  \
187   TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);     \
188   TRAMPOLINE_TEMPLATE (_dl_profile_resolve, profile_fixup);
189 #else
190 #define ELF_MACHINE_RUNTIME_TRAMPOLINE                  \
191   TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);     \
192   void _dl_runtime_resolve (void);                      \
193   strong_alias (_dl_runtime_resolve, _dl_profile_resolve);
194 #endif
195
196
197 /* Initial entry point code for the dynamic linker.  The C function
198    `_dl_start' is the real entry point; its return value is the user
199    program's entry point.  */
200 #define RTLD_START \
201   asm (".section \".text\"\n"                                           \
202 "       .align  2\n"                                                    \
203 "       .globl  ._start\n"                                              \
204 "       .type   ._start,@function\n"                                    \
205 "       .section \".opd\",\"aw\"\n"                                     \
206 "       .align  3\n"                                                    \
207 "       .globl  _start\n"                                               \
208 "       .size   _start,24\n"                                            \
209 "_start:\n"                                                             \
210 "       .quad   ._start,.TOC.@tocbase,0\n"                              \
211 "       .previous\n"                                                    \
212 "._start:\n"                                                            \
213 /* We start with the following on the stack, from top:                  \
214    argc (4 bytes);                                                      \
215    arguments for program (terminated by NULL);                          \
216    environment variables (terminated by NULL);                          \
217    arguments for the program loader.  */                                \
218 "       mr      3,1\n"                                                  \
219 "       li      4,0\n"                                                  \
220 "       stdu    4,-128(1)\n"                                            \
221 /* Call _dl_start with one parameter pointing at argc.  */              \
222 "       bl      ._dl_start\n"                                           \
223 "       nop\n"                                                          \
224 /* Transfer control to _dl_start_user!  */                              \
225 "       b       ._dl_start_user\n"                                      \
226 ".LT__start:\n"  \
227 "       .long 0\n"      \
228 "       .byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n"                \
229 "       .long .LT__start-._start\n"                                     \
230 "       .short .LT__start_name_end-.LT__start_name_start\n"             \
231 ".LT__start_name_start:\n"                                              \
232 "       .ascii \"_start\"\n"                                            \
233 ".LT__start_name_end:\n"                                                \
234 "       .align 2\n"                                                     \
235 "       .size   ._start,.-._start\n"                                    \
236 "       .globl  _dl_start_user\n"                                       \
237 "       .section \".opd\",\"aw\"\n"                                     \
238 "_dl_start_user:\n"                                                     \
239 "       .quad   ._dl_start_user, .TOC.@tocbase, 0\n"                    \
240 "       .previous\n"                                                    \
241 "       .globl  ._dl_start_user\n"                                      \
242 "       .type   ._dl_start_user,@function\n"                            \
243 /* Now, we do our main work of calling initialisation procedures.  \
244    The ELF ABI doesn't say anything about parameters for these,  \
245    so we just pass argc, argv, and the environment.  \
246    Changing these is strongly discouraged (not least because argc is  \
247    passed by value!).  */  \
248 "._dl_start_user:\n"  \
249 /* the address of _start in r30.  */                                    \
250 "       mr      30,3\n"                                                 \
251 /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28.  */          \
252 "       ld      28,_rtld_global@got(2)\n"    \
253 "       ld      29,_dl_argc@got(2)\n"                                   \
254 "       ld      27,_dl_argv@got(2)\n"                                   \
255 /* _dl_init (_dl_loaded, _dl_argc, _dl_argv, _dl_argv+_dl_argc+1).  */  \
256 "       ld      3,0(28)\n"                                              \
257 "       lwa     4,0(29)\n"                                              \
258 "       ld      5,0(27)\n"                                              \
259 "       sldi    6,4,3\n"                                                \
260 "       add     6,5,6\n"                                                \
261 "       addi    6,6,8\n"                                                \
262 "       bl      ._dl_init\n"                                            \
263 "       nop\n"                                                          \
264 /* Now, to conform to the ELF ABI, we have to:                          \
265    Pass argc (actually _dl_argc) in r3;  */                             \
266 "       lwa     3,0(29)\n"                                              \
267 /* Pass argv (actually _dl_argv) in r4;  */                             \
268 "       ld      4,0(27)\n"                                              \
269 /* Pass argv+argc+1 in r5;  */                                          \
270 "       sldi    5,3,3\n"                                                \
271 "       add     6,4,5\n"                                                \
272 "       addi    5,6,8\n"                                                \
273 /* Pass the auxilary vector in r6. This is passed to us just after      \
274    _envp.  */                                                           \
275 "2:     ldu     0,8(6)\n"                                               \
276 "       cmpdi   0,0\n"                                                  \
277 "       bne     2b\n"                                                   \
278 "       addi    6,6,8\n"                                                \
279 /* Pass a termination function pointer (in this case _dl_fini) in       \
280    r7.  */                                                              \
281 "       ld      7,_dl_fini@got(2)\n"                                    \
282 "       ld      26,_dl_starting_up@got(2)\n"                            \
283 /* Pass the stack pointer in r1 (so far so good), pointing to a NULL    \
284    value.  This lets our startup code distinguish between a program     \
285    linked statically, which linux will call with argc on top of the     \
286    stack which will hopefully never be zero, and a dynamically linked   \
287    program which will always have a NULL on the top of the stack.       \
288    Take the opportunity to clear LR, so anyone who accidentally  \
289    returns from _start gets SEGV.  Also clear the next few words of     \
290    the stack.  */                                                       \
291 "       li      31,0\n"                                                 \
292 "       std     31,0(1)\n"                                              \
293 "       mtlr    31\n"                                                   \
294 "       std     31,8(1)\n"                                              \
295 "       std     31,16(1)\n"                                             \
296 "       std     31,24(1)\n"                                             \
297 /* Clear _dl_starting_up.  */                                           \
298 "       stw     31,0(26)\n"                                             \
299 /* Now, call the start function descriptor at r30...  */                \
300 "       .globl  ._dl_main_dispatch\n"  \
301 "._dl_main_dispatch:\n"  \
302 "       ld      0,0(30)\n"                                              \
303 "       ld      2,8(30)\n"                                              \
304 "       mtctr   0\n"                                                    \
305 "       ld      11,16(30)\n"                                            \
306 "       bctr\n"                                                         \
307 ".LT__dl_start_user:\n" \
308 "       .long 0\n"                                                      \
309 "       .byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n"                \
310 "       .long .LT__dl_start_user-._dl_start_user\n"                     \
311 "       .short .LT__dl_start_user_name_end-.LT__dl_start_user_name_start\n" \
312 ".LT__dl_start_user_name_start:\n"                                      \
313 "       .ascii \"_dl_start_user\"\n"                                    \
314 ".LT__dl_start_user_name_end:\n"                                        \
315 "       .align 2\n"                                                     \
316 "       .size   ._dl_start_user,.-._dl_start_user\n"                    \
317 "       .previous");
318
319 /* Nonzero iff TYPE should not be allowed to resolve to one of
320    the main executable's symbols, as for a COPY reloc.  */
321 #define elf_machine_lookup_noexec_p(type) ((type) == R_PPC64_COPY)
322
323 /* Nonzero iff TYPE describes relocation of a PLT entry, so
324    PLT entries should not be allowed to define the value.  */
325 #define elf_machine_lookup_noplt_p(type) ((type) == R_PPC64_JMP_SLOT)
326
327 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
328    PLT entries should not be allowed to define the value.
329    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
330    of the main executable's symbols, as for a COPY reloc.  */
331
332 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
333 #define elf_machine_type_class(type)                                          \
334   ((((type) == R_PPC64_DTPMOD64                                               \
335     || (type) == R_PPC64_DTPREL64                                             \
336     || (type) == R_PPC64_TPREL64                                              \
337     || (type) == R_PPC64_ADDR24) * ELF_RTYPE_CLASS_PLT)                       \
338    | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
339 #else
340 #define elf_machine_type_class(type) \
341   ((((type) == R_PPC64_ADDR24) * ELF_RTYPE_CLASS_PLT)   \
342    | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
343 #endif
344
345 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
346 #define ELF_MACHINE_JMP_SLOT    R_PPC64_JMP_SLOT
347
348 /* The PowerPC never uses REL relocations.  */
349 #define ELF_MACHINE_NO_REL 1
350
351 /* Stuff for the PLT.  */
352 #define PLT_INITIAL_ENTRY_WORDS 3
353 #define GLINK_INITIAL_ENTRY_WORDS 8
354
355 #define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where) : "memory")
356 #define PPC_SYNC asm volatile ("sync" : : : "memory")
357 #define PPC_ISYNC asm volatile ("sync; isync" : : : "memory")
358 #define PPC_ICBI(where) asm volatile ("icbi 0,%0" : : "r"(where) : "memory")
359 #define PPC_DIE asm volatile ("tweq 0,0")
360 /* Use this when you've modified some code, but it won't be in the
361    instruction fetch queue (or when it doesn't matter if it is). */
362 #define MODIFIED_CODE_NOQUEUE(where) \
363      do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); } while (0)
364 /* Use this when it might be in the instruction queue. */
365 #define MODIFIED_CODE(where) \
366      do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); PPC_ISYNC; } while (0)
367
368 /* Set up the loaded object described by MAP so its unrelocated PLT
369    entries will jump to the on-demand fixup code in dl-runtime.c.  */
370 static inline int
371 elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
372 {
373   if (map->l_info[DT_JMPREL])
374     {
375       Elf64_Word i;
376       Elf64_Word *glink = NULL;
377       Elf64_Xword *plt = (Elf64_Xword *) D_PTR (map, l_info[DT_PLTGOT]);
378       Elf64_Word num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
379                                     / sizeof (Elf64_Rela));
380       Elf64_Addr l_addr = map->l_addr;
381       Elf64_Dyn **info = map->l_info;
382       char *p;
383
384       extern void _dl_runtime_resolve (void);
385       extern void _dl_profile_resolve (void);
386
387       /* Relocate the DT_PPC64_GLINK entry in the _DYNAMIC section.
388          elf_get_dynamic_info takes care of the standard entries but
389          doesn't know exactly what to do with processor specific
390          entires.  */
391       if (info[DT_PPC64(GLINK)] != NULL)
392         info[DT_PPC64(GLINK)]->d_un.d_ptr += l_addr;
393
394       if (lazy)
395         {
396           /* The function descriptor of the appropriate trampline
397              routine is used to set the 1st and 2nd doubleword of the
398              plt_reserve.  */
399           Elf64_FuncDesc *resolve_fd;
400           Elf64_Word glink_offset;
401           /* the plt_reserve area is the 1st 3 doublewords of the PLT */
402           Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt;
403           Elf64_Word offset;
404
405           resolve_fd = (Elf64_FuncDesc *) (profile ? _dl_profile_resolve
406                                            : _dl_runtime_resolve);
407           if (profile && _dl_name_match_p (GL(dl_profile), map))
408             /* This is the object we are looking for.  Say that we really
409                want profiling and the timers are started.  */
410             GL(dl_profile_map) = map;
411
412
413           /* We need to stuff the address/TOC of _dl_runtime_resolve
414              into doublewords 0 and 1 of plt_reserve.  Then we need to
415              stuff the map address into doubleword 2 of plt_reserve.
416              This allows the GLINK0 code to transfer control to the
417              correct trampoline which will transfer control to fixup
418              in dl-machine.c.  */
419           plt_reserve->fd_func = resolve_fd->fd_func;
420           plt_reserve->fd_toc  = resolve_fd->fd_toc;
421           plt_reserve->fd_aux  = (Elf64_Addr) map;
422 #ifdef RTLD_BOOTSTRAP
423           /* When we're bootstrapping, the opd entry will not have
424              been relocated yet.  */
425           plt_reserve->fd_func += l_addr;
426           plt_reserve->fd_toc  += l_addr;
427 #endif
428
429           /* Set up the lazy PLT entries.  */
430           glink = (Elf64_Word *) D_PTR (map, l_info[DT_PPC64(GLINK)]);
431           offset = PLT_INITIAL_ENTRY_WORDS;
432           glink_offset = GLINK_INITIAL_ENTRY_WORDS;
433           for (i = 0; i < num_plt_entries; i++)
434             {
435
436               plt[offset] = (Elf64_Xword) &glink[glink_offset];
437               offset += 3;
438               /* The first 32k entries of glink can set an index and
439                  branch using two instructions;  Past that point,
440                  glink uses three instructions.  */
441               if (i < 0x8000)
442                 glink_offset += 2;
443               else
444                 glink_offset += 3;
445             }
446
447           /* Now, we've modified data.  We need to write the changes from
448              the data cache to a second-level unified cache, then make
449              sure that stale data in the instruction cache is removed.
450              (In a multiprocessor system, the effect is more complex.)
451              Most of the PLT shouldn't be in the instruction cache, but
452              there may be a little overlap at the start and the end.
453
454              Assumes that dcbst and icbi apply to lines of 16 bytes or
455              more.  Current known line sizes are 16, 32, and 128 bytes.  */
456
457           for (p = (char *) plt; p < (char *) &plt[offset]; p += 16)
458             PPC_DCBST (p);
459           PPC_SYNC;
460         }
461     }
462   return lazy;
463 }
464
465 /* Change the PLT entry whose reloc is 'reloc' to call the actual
466    routine.  */
467 static inline Elf64_Addr
468 elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
469                        const Elf64_Rela *reloc,
470                        Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
471 {
472   Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
473   Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
474   Elf64_Addr offset = 0;
475
476   /* If sym_map is NULL, it's a weak undefined sym;  Leave the plt zero.  */
477   if (sym_map == NULL)
478     return 0;
479
480   /* If the opd entry is not yet relocated (because it's from a shared
481      object that hasn't been processed yet), then manually reloc it.  */
482   if (map != sym_map && !sym_map->l_relocated
483 #if !defined RTLD_BOOTSTRAP && defined SHARED
484       /* Bootstrap map doesn't have l_relocated set for it.  */
485       && sym_map != &GL(dl_rtld_map)
486 #endif
487       )
488     offset = sym_map->l_addr;
489
490   /* For PPC64, fixup_plt copies the function descriptor from opd
491      over the corresponding PLT entry.
492      Initially, PLT Entry[i] is set up for lazy linking, or is zero.
493      For lazy linking, the fd_toc and fd_aux entries are irrelevant,
494      so for thread safety we write them before changing fd_func.  */
495
496   plt->fd_aux = rel->fd_aux + offset;
497   plt->fd_toc = rel->fd_toc + offset;
498   PPC_DCBST (&plt->fd_aux);
499   PPC_DCBST (&plt->fd_toc);
500   PPC_SYNC;
501
502   plt->fd_func = rel->fd_func + offset;
503   PPC_DCBST (&plt->fd_func);
504   PPC_SYNC;
505
506   return finaladdr;
507 }
508
509 /* Return the final value of a plt relocation.  */
510 static inline Elf64_Addr
511 elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
512                        Elf64_Addr value)
513 {
514   return value + reloc->r_addend;
515 }
516
517 #endif /* dl_machine_h */
518
519 #ifdef RESOLVE_MAP
520
521 #define PPC_LO(v) ((v) & 0xffff)
522 #define PPC_HI(v) (((v) >> 16) & 0xffff)
523 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
524 #define PPC_HIGHER(v) (((v) >> 32) & 0xffff)
525 #define PPC_HIGHERA(v) PPC_HIGHER ((v) + 0x8000)
526 #define PPC_HIGHEST(v) (((v) >> 48) & 0xffff)
527 #define PPC_HIGHESTA(v) PPC_HIGHEST ((v) + 0x8000)
528 #define BIT_INSERT(var, val, mask) \
529   ((var) = ((var) & ~(Elf64_Addr) (mask) | ((val) & (mask))))
530
531 #define dont_expect(X) __builtin_expect ((X), 0)
532
533 extern void _dl_reloc_overflow (struct link_map *map,
534                                 const char *name,
535                                 Elf64_Addr *const reloc_addr,
536                                 const Elf64_Sym *sym,
537                                 const Elf64_Sym *refsym)
538                                 attribute_hidden;
539
540 static inline void
541 elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
542                            Elf64_Addr *const reloc_addr)
543 {
544   *reloc_addr = l_addr + reloc->r_addend;
545 }
546
547 /* Perform the relocation specified by RELOC and SYM (which is fully
548    resolved).  MAP is the object containing the reloc.  */
549 static inline void
550 elf_machine_rela (struct link_map *map,
551                   const Elf64_Rela *reloc,
552                   const Elf64_Sym *sym,
553                   const struct r_found_version *version,
554                   Elf64_Addr *const reloc_addr)
555 {
556   const int r_type = ELF64_R_TYPE (reloc->r_info);
557   struct link_map *sym_map;
558   Elf64_Addr value;
559 #ifndef RTLD_BOOTSTRAP
560   const Elf64_Sym *const refsym = sym;
561 #endif
562
563   if (r_type == R_PPC64_RELATIVE)
564     {
565       *reloc_addr = map->l_addr + reloc->r_addend;
566       return;
567     }
568
569   if (__builtin_expect (r_type == R_PPC64_NONE, 0))
570     return;
571
572 #if defined USE_TLS && !defined RTLD_BOOTSTRAP
573   struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
574   value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
575 #else
576   value = RESOLVE (&sym, version, r_type);
577 # ifndef RTLD_BOOTSTRAP
578   if (sym != NULL)
579 # endif
580     value += sym->st_value;
581 #endif
582   value += reloc->r_addend;
583
584   /* For relocs that don't edit code, return.
585      For relocs that might edit instructions, break from the switch.  */
586   switch (r_type)
587     {
588     case R_PPC64_ADDR64:
589     case R_PPC64_GLOB_DAT:
590       *reloc_addr = value;
591       return;
592
593     case R_PPC64_JMP_SLOT:
594 #ifdef RESOLVE_CONFLICT_FIND_MAP
595       RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
596 #endif
597       elf_machine_fixup_plt (map, sym_map, reloc, reloc_addr, value);
598       return;
599
600 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
601     case R_PPC64_DTPMOD64:
602 # ifdef RTLD_BOOTSTRAP
603     /* During startup the dynamic linker is always index 1.  */
604       *reloc_addr = 1;
605 # else
606     /* Get the information from the link map returned by the
607        resolve function.  */
608       if (sym_map != NULL)
609         *reloc_addr = sym_map->l_tls_modid;
610 # endif
611       return;
612
613     case R_PPC_DTPREL64:
614       /* During relocation all TLS symbols are defined and used.
615          Therefore the offset is already correct.  */
616 # ifndef RTLD_BOOTSTRAP
617       *reloc_addr = TLS_DTPREL_VALUE (sym, reloc);
618 # endif
619       break;
620     case R_PPC_TPREL64:
621 # ifndef RTLD_BOOTSTRAP
622       if (sym_map)
623         {
624           CHECK_STATIC_TLS (map, sym_map);
625 # endif
626           *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
627 # ifndef RTLD_BOOTSTRAP
628         }
629 # endif
630       break;
631 #endif /* USE_TLS etc. */
632
633 #ifndef RTLD_BOOTSTRAP /* None of the following appear in ld.so */
634     case R_PPC64_ADDR16_LO_DS:
635       if (dont_expect ((value & 3) != 0))
636         _dl_reloc_overflow (map, "R_PPC64_ADDR16_LO_DS",
637                             reloc_addr, sym, refsym);
638       BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc);
639       break;
640
641     case R_PPC64_ADDR16_LO:
642       *(Elf64_Half *) reloc_addr = PPC_LO (value);
643       break;
644
645     case R_PPC64_ADDR16_HI:
646       *(Elf64_Half *) reloc_addr = PPC_HI (value);
647       break;
648
649     case R_PPC64_ADDR16_HA:
650       *(Elf64_Half *) reloc_addr = PPC_HA (value);
651       break;
652
653     case R_PPC64_REL24:
654       {
655         Elf64_Addr delta = value - (Elf64_Xword) reloc_addr;
656         if (dont_expect ((delta + 0x2000000) >= 0x4000000 || (delta & 3) != 0))
657           _dl_reloc_overflow (map, "R_PPC64_REL24", reloc_addr, sym, refsym);
658         BIT_INSERT (*(Elf64_Word *) reloc_addr, delta, 0x3fffffc);
659       }
660       break;
661
662     case R_PPC64_COPY:
663       if (dont_expect (sym == NULL))
664       /* This can happen in trace mode when an object could not be found. */
665         return;
666       if (dont_expect (sym->st_size > refsym->st_size
667         || (GL(dl_verbose) && sym->st_size < refsym->st_size)))
668               {
669           const char *strtab;
670
671           strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
672           _dl_error_printf ("%s: Symbol `%s' has different size" \
673                             " in shared object," \
674                             " consider re-linking\n",
675                             _dl_argv[0] ?: "<program name unknown>",
676                               strtab + refsym->st_name);
677               }
678       memcpy (reloc_addr, (char *) value, MIN (sym->st_size, refsym->st_size));
679       return;
680
681     case R_PPC64_UADDR64:
682       /* We are big-endian.  */
683       ((char *) reloc_addr)[0] = (value >> 56) & 0xff;
684       ((char *) reloc_addr)[1] = (value >> 48) & 0xff;
685       ((char *) reloc_addr)[2] = (value >> 40) & 0xff;
686       ((char *) reloc_addr)[3] = (value >> 32) & 0xff;
687       ((char *) reloc_addr)[4] = (value >> 24) & 0xff;
688       ((char *) reloc_addr)[5] = (value >> 16) & 0xff;
689       ((char *) reloc_addr)[6] = (value >> 8) & 0xff;
690       ((char *) reloc_addr)[7] = (value >> 0) & 0xff;
691       return;
692
693     case R_PPC64_UADDR32:
694       /* We are big-endian.  */
695       ((char *) reloc_addr)[0] = (value >> 24) & 0xff;
696       ((char *) reloc_addr)[1] = (value >> 16) & 0xff;
697       ((char *) reloc_addr)[2] = (value >> 8) & 0xff;
698       ((char *) reloc_addr)[3] = (value >> 0) & 0xff;
699       return;
700
701     case R_PPC64_ADDR24:
702       if (dont_expect ((value + 0x2000000) >= 0x4000000 || (value & 3) != 0))
703         _dl_reloc_overflow (map, "R_PPC64_ADDR24", reloc_addr, sym, refsym);
704       BIT_INSERT (*(Elf64_Word *) reloc_addr, value, 0x3fffffc);
705       break;
706
707     case R_PPC64_ADDR16:
708       if (dont_expect ((value + 0x8000) >= 0x10000))
709         _dl_reloc_overflow (map, "R_PPC64_ADDR16", reloc_addr, sym, refsym);
710       *(Elf64_Half *) reloc_addr = value;
711       break;
712
713     case R_PPC64_UADDR16:
714       if (dont_expect ((value + 0x8000) >= 0x10000))
715         _dl_reloc_overflow (map, "R_PPC64_UADDR16", reloc_addr, sym, refsym);
716       /* We are big-endian.  */
717       ((char *) reloc_addr)[0] = (value >> 8) & 0xff;
718       ((char *) reloc_addr)[1] = (value >> 0) & 0xff;
719       break;
720
721     case R_PPC64_ADDR16_DS:
722       if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
723         _dl_reloc_overflow (map, "R_PPC64_ADDR16_DS", reloc_addr, sym, refsym);
724       BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc);
725       break;
726
727     case R_PPC64_ADDR16_HIGHER:
728       *(Elf64_Half *) reloc_addr = PPC_HIGHER (value);
729       break;
730
731     case R_PPC64_ADDR16_HIGHEST:
732       *(Elf64_Half *) reloc_addr = PPC_HIGHEST (value);
733       break;
734
735     case R_PPC64_ADDR16_HIGHERA:
736       *(Elf64_Half *) reloc_addr = PPC_HIGHERA (value);
737       break;
738
739     case R_PPC64_ADDR16_HIGHESTA:
740       *(Elf64_Half *) reloc_addr = PPC_HIGHESTA (value);
741       break;
742
743     case R_PPC64_ADDR14:
744     case R_PPC64_ADDR14_BRTAKEN:
745     case R_PPC64_ADDR14_BRNTAKEN:
746       {
747         if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
748           _dl_reloc_overflow (map, "R_PPC64_ADDR14", reloc_addr, sym, refsym);
749         Elf64_Word insn = *(Elf64_Word *) reloc_addr;
750         BIT_INSERT (insn, value, 0xfffc);
751         if (r_type != R_PPC64_ADDR14)
752           {
753             insn &= ~(1 << 21);
754             if (r_type == R_PPC64_ADDR14_BRTAKEN)
755               insn |= 1 << 21;
756             if ((insn & (0x14 << 21)) == (0x04 << 21))
757               insn |= 0x02 << 21;
758             else if ((insn & (0x14 << 21)) == (0x10 << 21))
759               insn |= 0x08 << 21;
760           }
761         *(Elf64_Word *) reloc_addr = insn;
762       }
763       break;
764
765     case R_PPC64_REL32:
766       *(Elf64_Word *) reloc_addr = value - (Elf64_Xword) reloc_addr;
767       return;
768 #endif /* !RTLD_BOOTSTRAP */
769
770     default:
771       _dl_reloc_bad_type (map, r_type, 0);
772       return;
773     }
774   MODIFIED_CODE_NOQUEUE (reloc_addr);
775 }
776
777 static inline void
778 elf_machine_lazy_rel (struct link_map *map,
779                       Elf64_Addr l_addr, const Elf64_Rela *reloc)
780 {
781   /* elf_machine_runtime_setup handles this.  */
782 }
783
784 #endif /* RESOLVE */