Fix typo.
[kopensolaris-gnu/glibc.git] / sysdeps / powerpc / dl-machine.h
1 /* Machine-dependent ELF dynamic relocation inline functions.  PowerPC version.
2    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #ifndef dl_machine_h
21 #define dl_machine_h
22
23 #define ELF_MACHINE_NAME "powerpc"
24
25 #include <assert.h>
26 #include <string.h>
27 #include <link.h>
28 #include <sys/param.h>
29
30
31 /* stuff for the PLT */
32 #define PLT_INITIAL_ENTRY_WORDS 18
33 #define PLT_LONGBRANCH_ENTRY_WORDS 10
34 #define PLT_DOUBLE_SIZE (1<<13)
35 #define PLT_ENTRY_START_WORDS(entry_number) \
36   (PLT_INITIAL_ENTRY_WORDS + (entry_number)*2 + \
37    ((entry_number) > PLT_DOUBLE_SIZE ? \
38     ((entry_number) - PLT_DOUBLE_SIZE)*2 : \
39     0))
40 #define PLT_DATA_START_WORDS(num_entries) PLT_ENTRY_START_WORDS(num_entries)
41
42 #define OPCODE_ADDI(rd,ra,simm) \
43   (0x38000000 | (rd) << 21 | (ra) << 16 | (simm) & 0xffff)
44 #define OPCODE_ADDIS(rd,ra,simm) \
45   (0x3c000000 | (rd) << 21 | (ra) << 16 | (simm) & 0xffff)
46 #define OPCODE_ADD(rd,ra,rb) \
47   (0x7c000214 | (rd) << 21 | (ra) << 16 | (rb) << 11)
48 #define OPCODE_B(target) (0x48000000 | (target) & 0x03fffffc)
49 #define OPCODE_BA(target) (0x48000002 | (target) & 0x03fffffc)
50 #define OPCODE_BCTR() 0x4e800420
51 #define OPCODE_LWZ(rd,d,ra) \
52   (0x80000000 | (rd) << 21 | (ra) << 16 | (d) & 0xffff)
53 #define OPCODE_MTCTR(rd) (0x7C0903A6 | (rd) << 21)
54 #define OPCODE_RLWINM(ra,rs,sh,mb,me) \
55   (0x54000000 | (rs) << 21 | (ra) << 16 | (sh) << 11 | (mb) << 6 | (me) << 1)
56
57 #define OPCODE_LI(rd,simm)    OPCODE_ADDI(rd,0,simm)
58 #define OPCODE_SLWI(ra,rs,sh) OPCODE_RLWINM(ra,rs,sh,0,31-sh)
59
60 #define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where))
61 #define PPC_SYNC asm volatile ("sync")
62 #define PPC_ISYNC asm volatile ("sync; isync")
63 #define PPC_ICBI(where) asm volatile ("icbi 0,%0" : : "r"(where))
64 #define PPC_DIE asm volatile ("tweq 0,0")
65
66 /* Use this when you've modified some code, but it won't be in the
67    instruction fetch queue (or when it doesn't matter if it is). */
68 #define MODIFIED_CODE_NOQUEUE(where) \
69      do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); } while (0)
70 /* Use this when it might be in the instruction queue. */
71 #define MODIFIED_CODE(where) \
72      do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); PPC_ISYNC; } while (0)
73
74
75 /* Return nonzero iff E_MACHINE is compatible with the running host.  */
76 static inline int
77 elf_machine_matches_host (Elf32_Half e_machine)
78 {
79   return e_machine == EM_PPC;
80 }
81
82
83 /* Return the link-time address of _DYNAMIC, stored as
84    the first value in the GOT. */
85 static inline Elf32_Addr
86 elf_machine_dynamic (void)
87 {
88   Elf32_Addr *got;
89   asm (" bl _GLOBAL_OFFSET_TABLE_-4@local"
90        : "=l"(got));
91   return *got;
92 }
93
94 /* Return the run-time load address of the shared object.  */
95 static inline Elf32_Addr
96 elf_machine_load_address (void)
97 {
98   unsigned *got;
99   unsigned *branchaddr;
100
101   /* This is much harder than you'd expect.  Possibly I'm missing something.
102      The 'obvious' way:
103
104        Apparently, "bcl 20,31,$+4" is what should be used to load LR
105        with the address of the next instruction.
106        I think this is so that machines that do bl/blr pairing don't
107        get confused.
108
109      asm ("bcl 20,31,0f ;"
110           "0: mflr 0 ;"
111           "lis %0,0b@ha;"
112           "addi %0,%0,0b@l;"
113           "subf %0,%0,0"
114           : "=b" (addr) : : "r0", "lr");
115
116      doesn't work, because the linker doesn't have to (and in fact doesn't)
117      update the @ha and @l references; the loader (which runs after this
118      code) will do that.
119
120      Instead, we use the following trick:
121
122      The linker puts the _link-time_ address of _DYNAMIC at the first
123      word in the GOT. We could branch to that address, if we wanted,
124      by using an @local reloc; the linker works this out, so it's safe
125      to use now. We can't, of course, actually branch there, because
126      we'd cause an illegal instruction exception; so we need to compute
127      the address ourselves. That gives us the following code: */
128
129   /* Get address of the 'b _DYNAMIC@local'...  */
130   asm ("bl 0f ;"
131        "b _DYNAMIC@local;"
132        "0:"
133        : "=l"(branchaddr));
134
135   /* ... and the address of the GOT.  */
136   asm (" bl _GLOBAL_OFFSET_TABLE_-4@local"
137        : "=l"(got));
138
139   /* So now work out the difference between where the branch actually points,
140      and the offset of that location in memory from the start of the file.  */
141   return ((Elf32_Addr)branchaddr - *got
142           + (*branchaddr & 0x3fffffc
143              | (int)(*branchaddr << 6 & 0x80000000) >> 6));
144 }
145
146 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) /* nothing */
147
148 /* The PLT uses Elf32_Rela relocs.  */
149 #define elf_machine_relplt elf_machine_rela
150
151 /* This code is used in dl-runtime.c to call the `fixup' function
152    and then redirect to the address it returns.  It is called
153    from code built in the PLT by elf_machine_runtime_setup.  */
154 #define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
155         .section \".text\"
156         .align 2
157         .globl _dl_runtime_resolve
158         .type _dl_runtime_resolve,@function
159 _dl_runtime_resolve:
160  # We need to save the registers used to pass parameters, and register 0,
161  # which is used by _mcount; the registers are saved in a stack frame.
162         stwu 1,-48(1)
163         stw 0,12(1)
164         stw 3,16(1)
165         stw 4,20(1)
166  # The code that calls this has put parameters for `fixup' in r12 and r11.
167         mr 3,12
168         stw 5,24(1)
169         mr 4,11
170         stw 6,28(1)
171         mflr 0
172  # We also need to save some of the condition register fields.
173         stw 7,32(1)
174         stw 0,52(1)
175         stw 8,36(1)
176         mfcr 0
177         stw 9,40(1)
178         stw 10,44(1)
179         stw 0,8(1)
180         bl fixup@local
181  # 'fixup' returns the address we want to branch to.
182         mtctr 3
183  # Put the registers back...
184         lwz 0,52(1)
185         lwz 10,44(1)
186         lwz 9,40(1)
187         mtlr 0
188         lwz 8,36(1)
189         lwz 0,8(1)
190         lwz 7,32(1)
191         lwz 6,28(1)
192         mtcrf 0xFF,0
193         lwz 5,24(1)
194         lwz 4,20(1)
195         lwz 3,16(1)
196         lwz 0,12(1)
197  # ...unwind the stack frame, and jump to the PLT entry we updated.
198         addi 1,1,48
199         bctr
200         .size    _dl_runtime_resolve,.-_dl_runtime_resolve
201
202         .align 2
203         .globl _dl_prof_resolve
204         .type _dl_prof_resolve,@function
205 _dl_prof_resolve:
206  # We need to save the registers used to pass parameters, and register 0,
207  # which is used by _mcount; the registers are saved in a stack frame.
208         stwu 1,-48(1)
209         stw 0,12(1)
210         stw 3,16(1)
211         stw 4,20(1)
212  # The code that calls this has put parameters for `fixup' in r12 and r11.
213         mr 3,12
214         stw 5,24(1)
215         mr 4,11
216         stw 6,28(1)
217         mflr 5
218  # We also need to save some of the condition register fields.
219         stw 7,32(1)
220         stw 5,52(1)
221         stw 8,36(1)
222         mfcr 0
223         stw 9,40(1)
224         stw 10,44(1)
225         stw 0,8(1)
226         bl profile_fixup@local
227  # 'fixup' returns the address we want to branch to.
228         mtctr 3
229  # Put the registers back...
230         lwz 0,52(1)
231         lwz 10,44(1)
232         lwz 9,40(1)
233         mtlr 0
234         lwz 8,36(1)
235         lwz 0,8(1)
236         lwz 7,32(1)
237         lwz 6,28(1)
238         mtcrf 0xFF,0
239         lwz 5,24(1)
240         lwz 4,20(1)
241         lwz 3,16(1)
242         lwz 0,12(1)
243  # ...unwind the stack frame, and jump to the PLT entry we updated.
244         addi 1,1,48
245         bctr
246         .size    _dl_prof_resolve,.-_dl_prof_resolve
247  # Undo '.section text'.
248         .previous
249 ");
250
251 /* Initial entry point code for the dynamic linker.
252    The C function `_dl_start' is the real entry point;
253    its return value is the user program's entry point.  */
254 #define RTLD_START \
255 static ElfW(Addr) _dl_start (void *arg) __attribute__((unused)); \
256 asm ("\
257         .section \".text\"
258         .align 2
259         .globl _start
260         .type _start,@function
261 _start:
262  # We start with the following on the stack, from top:
263  # argc (4 bytes);
264  # arguments for program (terminated by NULL);
265  # environment variables (terminated by NULL);
266  # arguments for the program loader.
267  # FIXME: perhaps this should do the same trick as elf/start.c?
268
269  # Call _dl_start with one parameter pointing at argc
270         mr   3,1
271  #  (we have to frob the stack pointer a bit to allow room for
272  #   _dl_start to save the link register)
273         li   4,0
274         addi 1,1,-16
275         stw  4,0(1)
276         bl   _dl_start@local
277
278  # Now, we do our main work of calling initialisation procedures.
279  # The ELF ABI doesn't say anything about parameters for these,
280  # so we just pass argc, argv, and the environment.
281  # Changing these is strongly discouraged (not least because argc is
282  # passed by value!).
283
284  #  Put our GOT pointer in r31,
285         bl   _GLOBAL_OFFSET_TABLE_-4@local
286         mflr 31
287  #  the address of _start in r30,
288         mr   30,3
289  #  &_dl_argc in 29, &_dl_argv in 27, and _dl_default_scope in 28.
290         lwz  28,_dl_default_scope@got(31)
291         lwz  29,_dl_argc@got(31)
292         lwz  27,_dl_argv@got(31)
293 0:
294  #  Set initfunc = _dl_init_next(_dl_default_scope[2])
295         lwz  3,8(28)
296         bl   _dl_init_next@plt
297  # If initfunc is NULL, we exit the loop; otherwise,
298         cmpwi 3,0
299         beq  1f
300  # call initfunc(_dl_argc, _dl_argv, _dl_argv+_dl_argc+1)
301         mtlr 3
302         lwz  3,0(29)
303         lwz  4,0(27)
304         slwi 5,3,2
305         add  5,4,5
306         addi 5,5,4
307         blrl
308  # and loop.
309         b    0b
310 1:
311  # Now, to conform to the ELF ABI, we have to:
312  # Pass argc (actually _dl_argc) in r3;
313         lwz  3,0(29)
314  # pass argv (actually _dl_argv) in r4;
315         lwz  4,0(27)
316  # pass envp (actually _dl_argv+_dl_argc+1) in r5;
317         slwi 5,3,2
318         add  6,4,5
319         addi 5,6,4
320  # pass the auxilary vector in r6. This is passed to us just after _envp.
321 2:      lwzu 0,4(6)
322         cmpwi 0,0,0
323         bne  2b
324         addi 6,6,4
325  # Pass a termination function pointer (in this case _dl_fini) in r7.
326         lwz  7,_dl_fini@got(31)
327  # Now, call the start function in r30...
328         mtctr 30
329         lwz  26,_dl_starting_up@got(31)
330  # Pass the stack pointer in r1 (so far so good), pointing to a NULL value.
331  # (This lets our startup code distinguish between a program linked statically,
332  # which linux will call with argc on top of the stack which will hopefully
333  # never be zero, and a dynamically linked program which will always have
334  # a NULL on the top of the stack).
335  # Take the opportunity to clear LR, so anyone who accidentally returns
336  # from _start gets SEGV.  Also clear the next few words of the stack.
337         li   31,0
338         stw  31,0(1)
339         mtlr 31
340         stw  31,4(1)
341         stw  31,8(1)
342         stw  31,12(1)
343  # Clear _dl_starting_up.
344         stw  31,0(26)
345  # Go do it!
346         bctr
347 0:
348         .size    _start,0b-_start
349  # Undo '.section text'.
350         .previous
351 ");
352
353 /* The idea here is that to conform to the ABI, we are supposed to try
354    to load dynamic objects between 0x10000 (we actually use 0x40000 as
355    the lower bound, to increase the chance of a memory reference from
356    a null pointer giving a segfault) and the program's load address.
357    Regrettably, in this code we can't find the program's load address,
358    so we punt and choose 0x01800000, which is below the ABI's
359    recommended default, and what GNU ld currently chooses. We only use
360    the address as a preference for mmap, so if we get it wrong the
361    worst that happens is that it gets mapped somewhere else.
362
363    FIXME: Unfortunately, 'somewhere else' is probably right after the
364    program's break, which causes malloc to fail.  We really need more
365    information here about the way memory is mapped.  */
366
367 #define ELF_PREFERRED_ADDRESS_DATA                                            \
368 static ElfW(Addr) _dl_preferred_address = 1
369
370 #define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref)                \
371 ( {                                                                           \
372    ElfW(Addr) prefd;                                                          \
373    if (mapstartpref != 0 && _dl_preferred_address == 1)                       \
374      _dl_preferred_address = mapstartpref;                                    \
375    if (mapstartpref != 0)                                                     \
376      prefd = mapstartpref;                                                    \
377    else if (_dl_preferred_address == 1)                                       \
378      prefd = _dl_preferred_address =                                          \
379           (0x01800000 - maplength - 0x10000) &                                \
380            ~(_dl_pagesize - 1);                                               \
381    else if (_dl_preferred_address < maplength + 0x50000)                      \
382      prefd = 0;                                                               \
383    else                                                                       \
384      prefd = _dl_preferred_address =                                          \
385        ((_dl_preferred_address - maplength - 0x10000)                         \
386         & ~(_dl_pagesize - 1));                                               \
387    prefd;                                                                     \
388 } )
389
390 #define ELF_FIXED_ADDRESS(loader, mapstart)                                   \
391 ( {                                                                           \
392    if (mapstart != 0 && _dl_preferred_address == 1)                           \
393      _dl_preferred_address = mapstart;                                        \
394 } )
395
396 /* Nonzero iff TYPE should not be allowed to resolve to one of
397    the main executable's symbols, as for a COPY reloc.  */
398 #define elf_machine_lookup_noexec_p(type) ((type) == R_PPC_COPY)
399
400 /* Nonzero iff TYPE describes relocation of a PLT entry, so
401    PLT entries should not be allowed to define the value.  */
402 /* We never want to use a PLT entry as the destination of a
403    reloc, when what is being relocated is a branch. This is
404    partly for efficiency, but mostly so we avoid loops.  */
405 #define elf_machine_lookup_noplt_p(type) ((type) == R_PPC_REL24 ||            \
406                                           (type) == R_PPC_ADDR24 ||           \
407                                           (type) == R_PPC_JMP_SLOT)
408
409 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
410 #define ELF_MACHINE_JMP_SLOT    R_PPC_JMP_SLOT
411
412 /* Nonzero iff TYPE describes relocation of a PLT entry, so
413    PLT entries should not be allowed to define the value.  */
414 #define elf_machine_pltrel_p(type) ((type) == R_PPC_JMP_SLOT)
415
416 /* Set up the loaded object described by L so its unrelocated PLT
417    entries will jump to the on-demand fixup code in dl-runtime.c.
418    Also install a small trampoline to be used by entries that have
419    been relocated to an address too far away for a single branch.  */
420
421 /* A PLT entry does one of three things:
422    (i)   Jumps to the actual routine. Such entries are set up above, in
423          elf_machine_rela.
424
425    (ii)  Jumps to the actual routine via glue at the start of the PLT.
426          We do this by putting the address of the routine in space
427          allocated at the end of the PLT, and when the PLT entry is
428          called we load the offset of that word (from the start of the
429          space) into r11, then call the glue, which loads the word and
430          branches to that address. These entries are set up in
431          elf_machine_rela, but the glue is set up here.
432
433    (iii) Loads the index of this PLT entry (we count the double-size
434          entries as one entry for this purpose) into r11, then
435          branches to code at the start of the PLT. This code then
436          calls `fixup', in dl-runtime.c, via the glue in the macro
437          ELF_MACHINE_RUNTIME_TRAMPOLINE, which resets the PLT entry to
438          be one of the above two types. These entries are set up here.  */
439 static inline int
440 elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
441 {
442   if (map->l_info[DT_JMPREL])
443     {
444       Elf32_Word i;
445       /* Fill in the PLT. Its initial contents are directed to a
446          function earlier in the PLT which arranges for the dynamic
447          linker to be called back.  */
448       Elf32_Word *plt = (Elf32_Word *) ((char *) map->l_addr
449                                         + map->l_info[DT_PLTGOT]->d_un.d_val);
450       Elf32_Word num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
451                                     / sizeof (Elf32_Rela));
452       Elf32_Word rel_offset_words = PLT_DATA_START_WORDS (num_plt_entries);
453       Elf32_Word size_modified;
454       extern void _dl_runtime_resolve (void);
455       extern void _dl_prof_resolve (void);
456       Elf32_Word dlrr;
457
458       dlrr = (Elf32_Word)(char *)(profile
459                                   ? _dl_prof_resolve
460                                   : _dl_runtime_resolve);
461
462       if (lazy)
463         for (i = 0; i < num_plt_entries; i++)
464         {
465           Elf32_Word offset = PLT_ENTRY_START_WORDS (i);
466
467           if (i >= PLT_DOUBLE_SIZE)
468             {
469               plt[offset  ] = OPCODE_LI (11, i * 4);
470               plt[offset+1] = OPCODE_ADDIS (11, 11, (i * 4 + 0x8000) >> 16);
471               plt[offset+2] = OPCODE_B (-(4 * (offset + 2)));
472             }
473           else
474             {
475               plt[offset  ] = OPCODE_LI (11, i * 4);
476               plt[offset+1] = OPCODE_B (-(4 * (offset + 1)));
477             }
478         }
479
480       /* Multiply index of entry by 3 (in r11).  */
481       plt[0] = OPCODE_SLWI (12, 11, 1);
482       plt[1] = OPCODE_ADD (11, 12, 11);
483       if (dlrr <= 0x01fffffc || dlrr >= 0xfe000000)
484         {
485           /* Load address of link map in r12.  */
486           plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) map);
487           plt[3] = OPCODE_ADDIS (12, 12, (((Elf32_Word) (char *) map
488                                            + 0x8000) >> 16));
489
490           /* Call _dl_runtime_resolve.  */
491           plt[4] = OPCODE_BA (dlrr);
492         }
493       else
494         {
495           /* Get address of _dl_runtime_resolve in CTR.  */
496           plt[2] = OPCODE_LI (12, dlrr);
497           plt[3] = OPCODE_ADDIS (12, 12, (dlrr + 0x8000) >> 16);
498           plt[4] = OPCODE_MTCTR (12);
499
500           /* Load address of link map in r12.  */
501           plt[5] = OPCODE_LI (12, (Elf32_Word) (char *) map);
502           plt[6] = OPCODE_ADDIS (12, 12, (((Elf32_Word) (char *) map
503                                            + 0x8000) >> 16));
504
505           /* Call _dl_runtime_resolve.  */
506           plt[7] = OPCODE_BCTR ();
507         }
508
509
510       /* Convert the index in r11 into an actual address, and get the
511          word at that address.  */
512       plt[PLT_LONGBRANCH_ENTRY_WORDS] =
513         OPCODE_ADDIS (11, 11, (((Elf32_Word) (char*) (plt + rel_offset_words)
514                                 + 0x8000) >> 16));
515       plt[PLT_LONGBRANCH_ENTRY_WORDS+1] =
516         OPCODE_LWZ (11, (Elf32_Word) (char*) (plt+rel_offset_words), 11);
517
518       /* Call the procedure at that address.  */
519       plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR (11);
520       plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR ();
521
522
523       /* Now, we've modified code (quite a lot of code, possibly).  We
524          need to write the changes from the data cache to a
525          second-level unified cache, then make sure that stale data in
526          the instruction cache is removed.  (In a multiprocessor
527          system, the effect is more complex.)
528
529          Assumes the cache line size is at least 32 bytes, or at least
530          that dcbst and icbi apply to 32-byte lines. At present, all
531          PowerPC processors have line sizes of exactly 32 bytes.  */
532
533       size_modified = lazy ? rel_offset_words : PLT_INITIAL_ENTRY_WORDS;
534       for (i = 0; i < size_modified; i+=8)
535         PPC_DCBST (plt + i);
536       PPC_SYNC;
537       for (i = 0; i < size_modified; i+=8)
538         PPC_ICBI (plt + i);
539       PPC_ISYNC;
540     }
541
542   return lazy;
543 }
544
545 static inline void
546 elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
547 {
548   /* elf_machine_runtime_setup handles this. */
549 }
550
551 static inline void
552 elf_machine_fixup_plt(struct link_map *map, const Elf32_Rela *reloc,
553                       Elf32_Addr *reloc_addr, Elf32_Addr finaladdr)
554 {
555   Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
556   if (delta << 6 >> 6 == delta)
557     *reloc_addr = OPCODE_B (delta);
558   else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000)
559     *reloc_addr = OPCODE_BA (finaladdr);
560   else
561     {
562       Elf32_Word *plt;
563       Elf32_Word index;
564
565       plt = (Elf32_Word *)((char *)map->l_addr
566                            + map->l_info[DT_PLTGOT]->d_un.d_val);
567       index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2;
568       if (index >= PLT_DOUBLE_SIZE)
569         {
570           /* Slots greater than or equal to 2^13 have 4 words available
571              instead of two.  */
572           /* FIXME: There are some possible race conditions in this code,
573              when called from 'fixup'.
574
575              1) Suppose that a lazy PLT entry is executing, a context switch
576              between threads (or a signal) occurs, and the new thread or
577              signal handler calls the same lazy PLT entry.  Then the PLT entry
578              would be changed while it's being run, which will cause a segfault
579              (almost always).
580
581              2) Suppose the reverse: that a lazy PLT entry is being updated,
582              a context switch occurs, and the new code calls the lazy PLT
583              entry that is being updated.  Then the half-fixed PLT entry will
584              be executed, which will also almost always cause a segfault.
585
586              These problems don't happen with the 2-word entries, because
587              only one of the two instructions are changed when a lazy entry
588              is retargeted at the actual PLT entry; the li instruction stays
589              the same (we have to update it anyway, because we might not be
590              updating a lazy PLT entry).  */
591
592           reloc_addr[0] = OPCODE_LI (11, finaladdr);
593           reloc_addr[1] = OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16);
594           reloc_addr[2] = OPCODE_MTCTR (11);
595           reloc_addr[3] = OPCODE_BCTR ();
596         }
597       else
598         {
599           Elf32_Word num_plt_entries;
600
601           num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
602                              / sizeof(Elf32_Rela));
603
604           plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr;
605           reloc_addr[0] = OPCODE_LI (11, index*4);
606           reloc_addr[1] = OPCODE_B (-(4*(index*2
607                                          + 1
608                                          - PLT_LONGBRANCH_ENTRY_WORDS
609                                          + PLT_INITIAL_ENTRY_WORDS)));
610         }
611     }
612   MODIFIED_CODE (reloc_addr);
613 }
614
615 /* Return the final value of a plt relocation.  */
616 static inline Elf32_Addr
617 elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
618                        Elf32_Addr value)
619 {
620   return value + reloc->r_addend;
621 }
622
623 #endif /* dl_machine_h */
624
625 #ifdef RESOLVE
626
627 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
628    LOADADDR is the load address of the object; INFO is an array indexed
629    by DT_* of the .dynamic section info.  */
630
631 static void
632 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
633                   const Elf32_Sym *sym, const struct r_found_version *version,
634                   Elf32_Addr *const reloc_addr)
635 {
636 #ifndef RTLD_BOOTSTRAP
637   const Elf32_Sym *const refsym = sym;
638   extern char **_dl_argv;
639 #endif
640   Elf32_Word loadbase, finaladdr;
641   const int rinfo = ELF32_R_TYPE (reloc->r_info);
642
643   if (rinfo == R_PPC_NONE)
644     return;
645
646   assert (sym != NULL);
647   /* The condition on the next two lines is a hack around a bug in Solaris
648      tools on Sparc.  It's not clear whether it should really be here at all,
649      but if not the binutils need to be changed.  */
650   if ((sym->st_shndx != SHN_UNDEF
651        && ELF32_ST_BIND (sym->st_info) == STB_LOCAL)
652       || rinfo == R_PPC_RELATIVE)
653     {
654       /* Has already been relocated.  */
655       loadbase = map->l_addr;
656       finaladdr = loadbase + reloc->r_addend;
657     }
658   else
659     {
660       loadbase = (Elf32_Word) (char *) (RESOLVE (&sym, version,
661                                                  ELF32_R_TYPE(reloc->r_info)));
662       if (sym == NULL)
663         {
664           /* Weak symbol that wasn't actually defined anywhere.  */
665           assert(loadbase == 0);
666           finaladdr = reloc->r_addend;
667         }
668       else
669         finaladdr = (loadbase + (Elf32_Word) (char *) sym->st_value
670                      + reloc->r_addend);
671     }
672
673   /* This is still an if/else if chain because GCC uses the GOT to find
674      the table for table-based switch statements, and we haven't set it
675      up yet.  */
676   if (rinfo == R_PPC_UADDR32 ||
677       rinfo == R_PPC_GLOB_DAT ||
678       rinfo == R_PPC_ADDR32 ||
679       rinfo == R_PPC_RELATIVE)
680     {
681       *reloc_addr = finaladdr;
682     }
683 #ifndef RTLD_BOOTSTRAP
684   else if (rinfo == R_PPC_ADDR16_LO)
685     {
686       *(Elf32_Half*) reloc_addr = finaladdr;
687     }
688   else if (rinfo == R_PPC_ADDR16_HI)
689     {
690       *(Elf32_Half*) reloc_addr = finaladdr >> 16;
691     }
692   else if (rinfo == R_PPC_ADDR16_HA)
693     {
694       *(Elf32_Half*) reloc_addr = (finaladdr + 0x8000) >> 16;
695     }
696   else if (rinfo == R_PPC_REL24)
697     {
698       Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
699       if (delta << 6 >> 6 != delta)
700         {
701           _dl_signal_error(0, map->l_name,
702                            "R_PPC_REL24 relocation out of range");
703         }
704       *reloc_addr = *reloc_addr & 0xfc000003 | delta & 0x3fffffc;
705     }
706   else if (rinfo == R_PPC_ADDR24)
707     {
708       if (finaladdr << 6 >> 6 != finaladdr)
709         {
710           _dl_signal_error(0, map->l_name,
711                            "R_PPC_ADDR24 relocation out of range");
712         }
713       *reloc_addr = *reloc_addr & 0xfc000003 | finaladdr & 0x3fffffc;
714     }
715   else if (rinfo == R_PPC_COPY)
716     {
717       if (sym == NULL)
718         /* This can happen in trace mode when an object could not be
719            found.  */
720         return;
721       if (sym->st_size > refsym->st_size
722           || (_dl_verbose && sym->st_size < refsym->st_size))
723         {
724           const char *strtab;
725
726           strtab = ((void *) map->l_addr
727                     + map->l_info[DT_STRTAB]->d_un.d_ptr);
728           _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>",
729                             ": Symbol `", strtab + refsym->st_name,
730                             "' has different size in shared object, "
731                             "consider re-linking\n", NULL);
732         }
733       memcpy (reloc_addr, (char *) finaladdr, MIN (sym->st_size,
734                                                    refsym->st_size));
735     }
736 #endif
737   else if (rinfo == R_PPC_REL32)
738     {
739       *reloc_addr = finaladdr - (Elf32_Word) (char *) reloc_addr;
740     }
741   else if (rinfo == R_PPC_JMP_SLOT)
742     {
743       elf_machine_fixup_plt (map, reloc, reloc_addr, finaladdr);
744     }
745   else
746     {
747 #ifdef RTLD_BOOTSTRAP
748       PPC_DIE;  /* There is no point calling _dl_sysdep_error, it
749                    almost certainly hasn't been relocated properly.  */
750 #else
751       _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>",
752                         ": Unknown relocation type\n", NULL);
753 #endif
754     }
755
756 #ifndef RTLD_BOOTSTRAP
757   if (rinfo == R_PPC_ADDR16_LO ||
758       rinfo == R_PPC_ADDR16_HI ||
759       rinfo == R_PPC_ADDR16_HA ||
760       rinfo == R_PPC_REL24 ||
761       rinfo == R_PPC_ADDR24)
762     MODIFIED_CODE_NOQUEUE (reloc_addr);
763 #endif
764 }
765
766 #define ELF_MACHINE_NO_REL 1
767
768 #endif /* RESOLVE */