2003-02-27 Roland McGrath <roland@redhat.com>
[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 #ifndef RTLD_BOOTSTRAP
476   weak_extern (GL(dl_rtld_map));
477 #endif
478
479   /* If sym_map is NULL, it's a weak undefined sym;  Leave the plt zero.  */
480   if (sym_map == NULL)
481     return 0;
482
483   /* If the opd entry is not yet relocated (because it's from a shared
484      object that hasn't been processed yet), then manually reloc it.  */
485   if (map != sym_map && !sym_map->l_relocated
486 #ifndef RTLD_BOOTSTRAP
487       /* Bootstrap map doesn't have l_relocated set for it.  */
488       && sym_map != &GL(dl_rtld_map)
489 #endif
490       )
491     offset = sym_map->l_addr;
492
493   /* For PPC64, fixup_plt copies the function descriptor from opd
494      over the corresponding PLT entry.
495      Initially, PLT Entry[i] is set up for lazy linking, or is zero.
496      For lazy linking, the fd_toc and fd_aux entries are irrelevant,
497      so for thread safety we write them before changing fd_func.  */
498
499   plt->fd_aux = rel->fd_aux + offset;
500   plt->fd_toc = rel->fd_toc + offset;
501   PPC_DCBST (&plt->fd_aux);
502   PPC_DCBST (&plt->fd_toc);
503   PPC_SYNC;
504
505   plt->fd_func = rel->fd_func + offset;
506   PPC_DCBST (&plt->fd_func);
507   PPC_SYNC;
508
509   return finaladdr;
510 }
511
512 /* Return the final value of a plt relocation.  */
513 static inline Elf64_Addr
514 elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
515                        Elf64_Addr value)
516 {
517   return value + reloc->r_addend;
518 }
519
520 #endif /* dl_machine_h */
521
522 #ifdef RESOLVE_MAP
523
524 #define PPC_LO(v) ((v) & 0xffff)
525 #define PPC_HI(v) (((v) >> 16) & 0xffff)
526 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
527 #define PPC_HIGHER(v) (((v) >> 32) & 0xffff)
528 #define PPC_HIGHERA(v) PPC_HIGHER ((v) + 0x8000)
529 #define PPC_HIGHEST(v) (((v) >> 48) & 0xffff)
530 #define PPC_HIGHESTA(v) PPC_HIGHEST ((v) + 0x8000)
531 #define BIT_INSERT(old, val, mask) ((old & ~(Elf64_Addr) mask) | (val & mask))
532
533 #define dont_expect(X) __builtin_expect ((X), 0)
534
535 extern void _dl_reloc_overflow (struct link_map *map,
536                                 const char *name,
537                                 Elf64_Addr *const reloc_addr,
538                                 const Elf64_Sym *sym,
539                                 const Elf64_Sym *refsym)
540                                 attribute_hidden;
541
542 static inline void
543 elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
544                            Elf64_Addr *const reloc_addr)
545 {
546   *reloc_addr = l_addr + reloc->r_addend;
547 }
548
549 /* Perform the relocation specified by RELOC and SYM (which is fully
550    resolved).  MAP is the object containing the reloc.  */
551 static inline void
552 elf_machine_rela (struct link_map *map,
553                   const Elf64_Rela *reloc,
554                   const Elf64_Sym *sym,
555                   const struct r_found_version *version,
556                   Elf64_Addr *const reloc_addr)
557 {
558   int r_type = ELF64_R_TYPE (reloc->r_info);
559   struct link_map *sym_map;
560   Elf64_Addr value, raw_value;
561 #ifndef RTLD_BOOTSTRAP
562   const Elf64_Sym *const refsym = sym;
563 #endif
564
565   if (r_type == R_PPC64_RELATIVE)
566     {
567       *reloc_addr = map->l_addr + reloc->r_addend;
568       return;
569     }
570
571   if (r_type == R_PPC64_NONE)
572     return;
573
574   sym_map = RESOLVE_MAP (&sym, version, r_type);
575   value = raw_value = reloc->r_addend;
576   if (sym_map)
577     {
578       raw_value += sym->st_value;
579       value = raw_value + sym_map->l_addr;
580     }
581
582   switch (r_type)
583     {
584     case R_PPC64_ADDR64:
585     case R_PPC64_GLOB_DAT:
586       *reloc_addr = value;
587       return;
588
589 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
590
591     case R_PPC64_DTPMOD64:
592 #ifdef RTLD_BOOTSTRAP
593     /* During startup the dynamic linker is always index 1.  */
594       *reloc_addr = 1;
595 #else
596     /* Get the information from the link map returned by the
597        resolve function.  */
598       if (sym_map != NULL)
599         *reloc_addr = sym_map->l_tls_modid;
600 #endif
601       return;
602
603     case R_PPC64_TPREL64:
604 #ifdef RTLD_BOOTSTRAP
605       *reloc_addr = (sym_map->l_tls_offset - TLS_TCB_SIZE
606                      + raw_value - TLS_TP_OFFSET);
607 #else
608       if (sym_map)
609         {
610           CHECK_STATIC_TLS (map, sym_map);
611           *reloc_addr = (sym_map->l_tls_offset - TLS_TCB_SIZE
612                          + raw_value - TLS_TP_OFFSET);
613         }
614 #endif
615       return;
616
617     case R_PPC64_DTPREL64:
618 #ifndef RTLD_BOOTSTRAP
619       /* During relocation all TLS symbols are defined and used.
620          Therefore the offset is already correct.  */
621       *reloc_addr = raw_value - TLS_DTV_OFFSET;
622 #endif
623       return;
624 #endif
625
626     case R_PPC64_JMP_SLOT:
627
628       elf_machine_fixup_plt (map, sym_map, reloc, reloc_addr, value);
629       return;
630
631 #ifndef RTLD_BOOTSTRAP /* None of the following appear in ld.so */
632     case R_PPC64_ADDR16_LO_DS:
633       if (dont_expect ((value & 3) != 0))
634         _dl_reloc_overflow (map, "R_PPC64_ADDR16_LO_DS",
635                             reloc_addr, sym, refsym);
636       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
637                                                value, 0xfffc);
638       break;
639
640     case R_PPC64_TPREL16_LO_DS:
641       if (dont_expect ((value & 3) != 0))
642         _dl_reloc_overflow (map, "R_PPC64_TPREL16_LO_DS",
643                             reloc_addr, sym, refsym);
644       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
645                                               value, 0xfffc);
646       break;
647
648     case R_PPC64_DTPREL16_LO_DS:
649       if (dont_expect ((value & 3) != 0))
650         _dl_reloc_overflow (map, "R_PPC64_DTPREL16_LO_DS",
651                             reloc_addr, sym, refsym);
652       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
653                                               value, 0xfffc);
654       break;
655
656     case R_PPC64_GOT_TPREL16_LO_DS:
657       if (dont_expect ((value & 3) != 0))
658         _dl_reloc_overflow (map, "R_PPC64_GOT_TPREL16_LO_DS",
659                             reloc_addr, sym, refsym);
660       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
661                                               value, 0xfffc);
662       break;
663
664     case R_PPC64_GOT_DTPREL16_LO_DS:
665       if (dont_expect ((value & 3) != 0))
666         _dl_reloc_overflow (map, "R_PPC64_GOT_DTPREL16_LO_DS",
667                             reloc_addr, sym, refsym);
668       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
669                                               value, 0xfffc);
670       break;
671
672     case R_PPC64_ADDR16_LO:
673     case R_PPC64_TPREL16_LO:
674     case R_PPC64_DTPREL16_LO:
675     case R_PPC64_GOT_TLSGD16_LO:
676     case R_PPC64_GOT_TLSLD16_LO:
677       *(Elf64_Half *) reloc_addr = PPC_LO (value);
678       break;
679
680     case R_PPC64_ADDR16_HI:
681     case R_PPC64_TPREL16_HI:
682     case R_PPC64_DTPREL16_HI:
683     case R_PPC64_GOT_TPREL16_HI:
684     case R_PPC64_GOT_DTPREL16_HI:
685     case R_PPC64_GOT_TLSGD16_HI:
686     case R_PPC64_GOT_TLSLD16_HI:
687       *(Elf64_Half *) reloc_addr = PPC_HI (value);
688       break;
689
690     case R_PPC64_ADDR16_HA:
691     case R_PPC64_TPREL16_HA:
692     case R_PPC64_DTPREL16_HA:
693     case R_PPC64_GOT_TLSGD16_HA:
694     case R_PPC64_GOT_TLSLD16_HA:
695       *(Elf64_Half *) reloc_addr = PPC_HA (value);
696       break;
697
698     case R_PPC64_REL24:
699       {
700         Elf64_Addr delta = value - (Elf64_Xword) reloc_addr;
701         if (dont_expect ((delta + 0x2000000) >= 0x4000000 || (delta & 3) != 0))
702           _dl_reloc_overflow (map, "R_PPC64_REL24", reloc_addr, sym, refsym);
703         *(Elf64_Word *) reloc_addr = BIT_INSERT (*(Elf64_Word *) reloc_addr,
704                                                 delta, 0x3fffffc);
705       }
706       break;
707
708     case R_PPC64_COPY:
709       if (dont_expect (sym == NULL))
710       /* This can happen in trace mode when an object could not be found. */
711         return;
712       if (dont_expect (sym->st_size > refsym->st_size
713         || (GL(dl_verbose) && sym->st_size < refsym->st_size)))
714               {
715           const char *strtab;
716
717           strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
718           _dl_error_printf ("%s: Symbol `%s' has different size" \
719                             " in shared object," \
720                             " consider re-linking\n",
721                             _dl_argv[0] ?: "<program name unknown>",
722                               strtab + refsym->st_name);
723               }
724       memcpy (reloc_addr, (char *) value, MIN (sym->st_size, refsym->st_size));
725       return;
726
727     case R_PPC64_UADDR64:
728       /* We are big-endian.  */
729       ((char *) reloc_addr)[0] = (value >> 56) & 0xff;
730       ((char *) reloc_addr)[1] = (value >> 48) & 0xff;
731       ((char *) reloc_addr)[2] = (value >> 40) & 0xff;
732       ((char *) reloc_addr)[3] = (value >> 32) & 0xff;
733       ((char *) reloc_addr)[4] = (value >> 24) & 0xff;
734       ((char *) reloc_addr)[5] = (value >> 16) & 0xff;
735       ((char *) reloc_addr)[6] = (value >> 8) & 0xff;
736       ((char *) reloc_addr)[7] = (value >> 0) & 0xff;
737       return;
738
739     case R_PPC64_UADDR32:
740       /* We are big-endian.  */
741       ((char *) reloc_addr)[0] = (value >> 24) & 0xff;
742       ((char *) reloc_addr)[1] = (value >> 16) & 0xff;
743       ((char *) reloc_addr)[2] = (value >> 8) & 0xff;
744       ((char *) reloc_addr)[3] = (value >> 0) & 0xff;
745       return;
746
747     case R_PPC64_ADDR24:
748       if (dont_expect ((value + 0x2000000) >= 0x4000000 || (value & 3) != 0))
749         _dl_reloc_overflow (map, "R_PPC64_ADDR24", reloc_addr, sym, refsym);
750       *(Elf64_Word *) reloc_addr = BIT_INSERT (*(Elf64_Word *) reloc_addr,
751                                                value, 0x3fffffc);
752       break;
753
754     case R_PPC64_ADDR16:
755       if (dont_expect ((value + 0x8000) >= 0x10000))
756         _dl_reloc_overflow (map, "R_PPC64_ADDR16", reloc_addr, sym, refsym);
757       *(Elf64_Half *) reloc_addr = value;
758       break;
759
760     case R_PPC64_UADDR16:
761       if (dont_expect ((value + 0x8000) >= 0x10000))
762         _dl_reloc_overflow (map, "R_PPC64_UADDR16", reloc_addr, sym, refsym);
763       /* We are big-endian.  */
764       ((char *) reloc_addr)[0] = (value >> 8) & 0xff;
765       ((char *) reloc_addr)[1] = (value >> 0) & 0xff;
766       break;
767
768     case R_PPC64_ADDR16_DS:
769       if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
770         _dl_reloc_overflow (map, "R_PPC64_ADDR16_DS", reloc_addr, sym, refsym);
771       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
772                                                value, 0xfffc);
773       break;
774
775     case R_PPC64_TPREL16_DS:
776       if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
777         _dl_reloc_overflow (map, "R_PPC64_TPREL16_DS", reloc_addr,
778                             sym, refsym);
779       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
780                                               value, 0xfffc);
781       break;
782
783     case R_PPC64_DTPREL16_DS:
784       if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
785         _dl_reloc_overflow (map, "R_PPC64_DTPREL16_DS", reloc_addr,
786                             sym, refsym);
787       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
788                                               value, 0xfffc);
789       break;
790
791     case R_PPC64_GOT_TPREL16_DS:
792       if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
793         _dl_reloc_overflow (map, "R_PPC64_GOT_TPREL16_DS", reloc_addr,
794                             sym, refsym);
795       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
796                                               value, 0xfffc);
797       break;
798
799     case R_PPC64_GOT_DTPREL16_DS:
800       if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
801         _dl_reloc_overflow (map, "R_PPC64_GOT_DTPREL16_DS",
802                             reloc_addr, sym, refsym);
803       *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr,
804                                               value, 0xfffc);
805       break;
806
807     case R_PPC64_ADDR16_HIGHER:
808     case R_PPC64_TPREL16_HIGHER:
809     case R_PPC64_DTPREL16_HIGHER:
810       *(Elf64_Half *) reloc_addr = PPC_HIGHER (value);
811       break;
812
813     case R_PPC64_ADDR16_HIGHEST:
814     case R_PPC64_TPREL16_HIGHEST:
815     case R_PPC64_DTPREL16_HIGHEST:
816       *(Elf64_Half *) reloc_addr = PPC_HIGHEST (value);
817       break;
818
819     case R_PPC64_ADDR16_HIGHERA:
820     case R_PPC64_TPREL16_HIGHERA:
821     case R_PPC64_DTPREL16_HIGHERA:
822       *(Elf64_Half *) reloc_addr = PPC_HIGHERA (value);
823       break;
824
825     case R_PPC64_ADDR16_HIGHESTA:
826     case R_PPC64_TPREL16_HIGHESTA:
827     case R_PPC64_DTPREL16_HIGHESTA:
828       *(Elf64_Half *) reloc_addr = PPC_HIGHESTA (value);
829       break;
830
831     case R_PPC64_ADDR14:
832     case R_PPC64_ADDR14_BRTAKEN:
833     case R_PPC64_ADDR14_BRNTAKEN:
834       {
835         Elf64_Word insn;
836         if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))
837                 _dl_reloc_overflow (map, "R_PPC64_ADDR14", reloc_addr, sym, refsym);
838         insn = BIT_INSERT (*(Elf64_Word *) reloc_addr, value, 0xfffc);
839         if (r_type != R_PPC64_ADDR14)
840                 {
841                   insn &= ~(1 << 21);
842                   if (r_type == R_PPC64_ADDR14_BRTAKEN)
843                     insn |= 1 << 21;
844                   if ((insn & (0x14 << 21)) == (0x04 << 21))
845                     insn |= 0x02 << 21;
846                   else if ((insn & (0x14 << 21)) == (0x10 << 21))
847                     insn |= 0x08 << 21;
848                 }
849         *(Elf64_Word *) reloc_addr = insn;
850       }
851       break;
852
853     case R_PPC64_REL32:
854       *(Elf64_Word *) reloc_addr = value - (Elf64_Xword) reloc_addr;
855       return;
856 #endif /* !RTLD_BOOTSTRAP */
857
858     default:
859       _dl_reloc_bad_type (map, r_type, 0);
860       return;
861     }
862   MODIFIED_CODE_NOQUEUE (reloc_addr);
863 }
864
865 static inline void
866 elf_machine_lazy_rel (struct link_map *map,
867                       Elf64_Addr l_addr, const Elf64_Rela *reloc)
868 {
869   /* elf_machine_runtime_setup handles this.  */
870 }
871
872 #endif /* RESOLVE */