1 /* Copyright (C) 2002, 2003, 2004, 2009 Red Hat, Inc.
2 Written by Jakub Jelinek <jakub@redhat.com>, 2002.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
34 GElf_Addr fn, toc, chain;
39 GElf_Addr start, size;
44 ppc64_adjust_section (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust)
46 if (dso->shdr[n].sh_type == SHT_PROGBITS
47 && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
48 dso->shdr[n].sh_name), ".got"))
52 /* .got[0]-0x8000 points to .got, it needs to be adjusted. */
53 data = read_ube64 (dso, dso->shdr[n].sh_addr);
54 if (addr_to_sec (dso, data - 0x8000) == n
55 && data - 0x8000 == dso->shdr[n].sh_addr)
56 write_be64 (dso, dso->shdr[n].sh_addr, data + adjust);
62 ppc64_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start,
65 if (dyn->d_tag == DT_PPC64_GLINK && dyn->d_un.d_ptr >= start)
67 dyn->d_un.d_ptr += adjust;
75 ppc64_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start,
78 error (0, 0, "%s: PowerPC64 doesn't support REL relocs", dso->filename);
83 ppc64_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start,
86 if (GELF_R_TYPE (rela->r_info) == R_PPC64_RELATIVE
87 || GELF_R_TYPE (rela->r_info) == R_PPC64_IRELATIVE)
89 GElf_Addr val = read_ube64 (dso, rela->r_offset);
91 if (val == rela->r_addend && val >= start)
92 write_be64 (dso, rela->r_offset, val + adjust);
93 if (rela->r_addend >= start)
94 rela->r_addend += adjust;
96 else if (GELF_R_TYPE (rela->r_info) == R_PPC64_JMP_IREL)
98 if (rela->r_addend >= start)
99 rela->r_addend += adjust;
105 ppc64_prelink_rel (struct prelink_info *info, GElf_Rel *rel,
108 error (0, 0, "%s: PowerPC64 doesn't support REL relocs", info->dso->filename);
113 ppc64_fixup_plt (struct prelink_info *info, GElf_Rela *rela, GElf_Addr value)
115 DSO *dso = info->dso;
126 else if ((sec = addr_to_sec (dso, value)) != -1)
128 rec.fn = read_ube64 (dso, value);
129 rec.toc = read_ube64 (dso, value + 8);
130 rec.chain = read_ube64 (dso, value + 16);
134 for (i = 0; i < info->ent->ndepends; ++i)
135 if (info->ent->depends[i]->opd
136 && info->ent->depends[i]->opd->start <= value
137 && (info->ent->depends[i]->opd->start
138 + info->ent->depends[i]->opd->size) > value)
141 if (i == info->ent->ndepends)
143 error (0, 0, "%s: R_PPC64_JMP_SLOT doesn't resolve to an .opd address",
147 if ((value - info->ent->depends[i]->opd->start) % 8)
149 error (0, 0, "%s: R_PPC64_JMP_SLOT doesn't resolve to valid .opd section location",
153 n = (value - info->ent->depends[i]->opd->start) / 8;
154 rec.fn = info->ent->depends[i]->opd->table[n];
155 rec.toc = info->ent->depends[i]->opd->table[n + 1];
156 rec.chain = info->ent->depends[i]->opd->table[n + 2];
158 write_be64 (dso, rela->r_offset, rec.fn);
159 write_be64 (dso, rela->r_offset + 8, rec.toc);
160 write_be64 (dso, rela->r_offset + 16, rec.chain);
165 ppc64_prelink_rela (struct prelink_info *info, GElf_Rela *rela,
168 DSO *dso = info->dso;
171 if (GELF_R_TYPE (rela->r_info) == R_PPC64_NONE
172 || GELF_R_TYPE (rela->r_info) == R_PPC64_IRELATIVE
173 || GELF_R_TYPE (rela->r_info) == R_PPC64_JMP_IREL)
175 else if (GELF_R_TYPE (rela->r_info) == R_PPC64_RELATIVE)
177 write_be64 (dso, rela->r_offset, rela->r_addend);
180 value = info->resolve (info, GELF_R_SYM (rela->r_info),
181 GELF_R_TYPE (rela->r_info));
182 value += rela->r_addend;
183 switch (GELF_R_TYPE (rela->r_info))
185 case R_PPC64_GLOB_DAT:
187 case R_PPC64_UADDR64:
188 write_be64 (dso, rela->r_offset, value);
190 case R_PPC64_DTPREL64:
191 write_be64 (dso, rela->r_offset, value - 0x8000);
194 case R_PPC64_UADDR32:
195 write_be32 (dso, rela->r_offset, value);
197 case R_PPC64_JMP_SLOT:
198 return ppc64_fixup_plt (info, rela, value);
200 case R_PPC64_UADDR16:
201 case R_PPC64_ADDR16_LO:
202 write_be16 (dso, rela->r_offset, value);
204 case R_PPC64_DTPREL16:
205 case R_PPC64_DTPREL16_LO:
206 write_be16 (dso, rela->r_offset, value - 0x8000);
208 case R_PPC64_ADDR16_HI:
209 case R_PPC64_DTPREL16_HA:
210 write_be16 (dso, rela->r_offset, value >> 16);
212 case R_PPC64_DTPREL16_HI:
213 write_be16 (dso, rela->r_offset, (value - 0x8000) >> 16);
215 case R_PPC64_ADDR16_HA:
216 write_be16 (dso, rela->r_offset, (value + 0x8000) >> 16);
218 case R_PPC64_ADDR16_HIGHER:
219 write_be16 (dso, rela->r_offset, value >> 32);
221 case R_PPC64_ADDR16_HIGHERA:
222 write_be16 (dso, rela->r_offset, (value + 0x8000) >> 32);
224 case R_PPC64_ADDR16_HIGHEST:
225 write_be16 (dso, rela->r_offset, value >> 48);
227 case R_PPC64_ADDR16_HIGHESTA:
228 write_be16 (dso, rela->r_offset, (value + 0x8000) >> 48);
230 case R_PPC64_ADDR16_LO_DS:
231 case R_PPC64_ADDR16_DS:
232 write_be16 (dso, rela->r_offset,
233 (value & 0xfffc) | read_ube16 (dso, rela->r_offset & 3));
236 write_be32 (dso, rela->r_offset,
238 | (read_ube32 (dso, rela->r_offset) & 0xfc000003));
241 write_be32 (dso, rela->r_offset,
243 | (read_ube32 (dso, rela->r_offset) & 0xffff0003));
245 case R_PPC64_ADDR14_BRTAKEN:
246 case R_PPC64_ADDR14_BRNTAKEN:
247 write_be32 (dso, rela->r_offset,
249 | (read_ube32 (dso, rela->r_offset) & 0xffdf0003)
250 | ((((GELF_R_TYPE (rela->r_info) == R_PPC64_ADDR14_BRTAKEN)
252 ^ (value >> 42)) & 0x00200000));
255 write_be32 (dso, rela->r_offset,
256 ((value - rela->r_offset) & 0x03fffffc)
257 | (read_ube32 (dso, rela->r_offset) & 0xfc000003));
260 write_be32 (dso, rela->r_offset, value - rela->r_offset);
263 write_be64 (dso, rela->r_offset, value - rela->r_offset);
265 /* DTPMOD64 and TPREL* is impossible to predict in shared libraries
266 unless prelink sets the rules. */
267 case R_PPC64_DTPMOD64:
268 if (dso->ehdr.e_type == ET_EXEC)
270 error (0, 0, "%s: R_PPC64_DTPMOD64 reloc in executable?",
275 case R_PPC64_TPREL64:
276 case R_PPC64_TPREL16:
277 case R_PPC64_TPREL16_LO:
278 case R_PPC64_TPREL16_HI:
279 case R_PPC64_TPREL16_HA:
280 if (dso->ehdr.e_type == ET_EXEC && info->resolvetls)
282 value += info->resolvetls->offset - 0x7000;
283 switch (GELF_R_TYPE (rela->r_info))
285 case R_PPC64_TPREL64:
286 write_be64 (dso, rela->r_offset, value);
288 case R_PPC64_TPREL16:
289 case R_PPC64_TPREL16_LO:
290 write_be16 (dso, rela->r_offset, value);
292 case R_PPC64_TPREL16_HI:
293 write_be16 (dso, rela->r_offset, value >> 16);
295 case R_PPC64_TPREL16_HA:
296 write_be16 (dso, rela->r_offset, (value + 0x8000) >> 16);
302 if (dso->ehdr.e_type == ET_EXEC)
303 /* COPY relocs are handled specially in generic code. */
305 error (0, 0, "%s: R_PPC64_COPY reloc in shared library?", dso->filename);
308 error (0, 0, "%s: Unknown ppc relocation type %d", dso->filename,
309 (int) GELF_R_TYPE (rela->r_info));
316 ppc64_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela,
317 char *buf, GElf_Addr dest_addr)
320 switch (GELF_R_TYPE (rela->r_info))
323 case R_PPC64_UADDR64:
324 buf_write_be64 (buf, rela->r_addend);
327 case R_PPC64_UADDR32:
328 buf_write_be32 (buf, rela->r_addend);
331 case R_PPC64_UADDR16:
332 buf_write_be16 (buf, rela->r_addend);
334 case R_PPC64_IRELATIVE:
337 ret = prelink_conflict_add_rela (info);
340 ret->r_offset = dest_addr;
341 ret->r_info = GELF_R_INFO (0, R_PPC64_IRELATIVE);
342 ret->r_addend = rela->r_addend;
351 ppc64_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf)
353 error (0, 0, "%s: PowerPC64 doesn't support REL relocs", info->dso->filename);
358 ppc64_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf)
362 value = info->resolve (info, GELF_R_SYM (rela->r_info),
363 GELF_R_TYPE (rela->r_info));
364 value += rela->r_addend;
365 switch (GELF_R_TYPE (rela->r_info))
369 case R_PPC64_GLOB_DAT:
371 case R_PPC64_UADDR64:
372 buf_write_be64 (buf, value);
375 case R_PPC64_UADDR32:
376 buf_write_be32 (buf, value);
378 case R_PPC64_ADDR16_HA:
381 case R_PPC64_ADDR16_HI:
385 case R_PPC64_UADDR16:
386 case R_PPC64_ADDR16_LO:
387 buf_write_be16 (buf, value);
389 case R_PPC64_ADDR16_HIGHERA:
392 case R_PPC64_ADDR16_HIGHER:
393 buf_write_be16 (buf, value >> 32);
395 case R_PPC64_ADDR16_HIGHESTA:
398 case R_PPC64_ADDR16_HIGHEST:
399 buf_write_be16 (buf, value >> 48);
401 case R_PPC64_ADDR16_LO_DS:
402 case R_PPC64_ADDR16_DS:
403 buf_write_be16 (buf, (value & 0xfffc)
404 | (buf_read_ube16 (buf) & 3));
407 buf_write_be32 (buf, (value & 0x03fffffc)
408 | (buf_read_ube32 (buf) & 0xfc000003));
411 buf_write_be32 (buf, (value & 0xfffc)
412 | (buf_read_ube32 (buf) & 0xffff0003));
414 case R_PPC64_ADDR14_BRTAKEN:
415 case R_PPC64_ADDR14_BRNTAKEN:
416 buf_write_be32 (buf, (value & 0xfffc)
417 | (buf_read_ube32 (buf) & 0xffdf0003)
418 | ((((GELF_R_TYPE (rela->r_info)
419 == R_PPC64_ADDR14_BRTAKEN) << 21)
420 ^ (value >> 42)) & 0x00200000));
423 buf_write_be32 (buf, ((value - rela->r_offset) & 0x03fffffc)
424 | (buf_read_ube32 (buf) & 0xfc000003));
427 buf_write_be32 (buf, value - rela->r_offset);
430 buf_write_be64 (buf, value - rela->r_offset);
432 case R_PPC64_RELATIVE:
433 error (0, 0, "%s: R_PPC64_RELATIVE in ET_EXEC object?",
434 info->dso->filename);
443 ppc64_prelink_conflict_rel (DSO *dso, struct prelink_info *info,
444 GElf_Rel *rel, GElf_Addr reladdr)
446 error (0, 0, "%s: PowerPC64 doesn't support REL relocs", dso->filename);
451 ppc64_prelink_conflict_rela (DSO *dso, struct prelink_info *info,
452 GElf_Rela *rela, GElf_Addr relaaddr)
455 struct prelink_conflict *conflict;
456 struct prelink_tls *tls;
460 if (GELF_R_TYPE (rela->r_info) == R_PPC64_RELATIVE
461 || GELF_R_TYPE (rela->r_info) == R_PPC64_NONE)
462 /* Fast path: nothing to do. */
464 conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info),
465 GELF_R_TYPE (rela->r_info));
466 if (conflict == NULL)
468 switch (GELF_R_TYPE (rela->r_info))
470 /* Even local DTPMOD and TPREL relocs need conflicts. */
471 case R_PPC64_DTPMOD64:
472 case R_PPC64_TPREL64:
473 case R_PPC64_TPREL16:
474 case R_PPC64_TPREL16_LO:
475 case R_PPC64_TPREL16_HI:
476 case R_PPC64_TPREL16_HA:
477 if (info->curtls == NULL || info->dso == dso)
480 /* Similarly IRELATIVE relocations always need conflicts. */
481 case R_PPC64_IRELATIVE:
482 case R_PPC64_JMP_IREL:
489 else if (info->dso == dso && !conflict->ifunc)
493 /* DTPREL wants to see only real conflicts, not lookups
494 with reloc_class RTYPE_CLASS_TLS. */
495 if (conflict->lookup.tls == conflict->conflict.tls
496 && conflict->lookupval == conflict->conflictval)
497 switch (GELF_R_TYPE (rela->r_info))
499 case R_PPC64_DTPREL64:
500 case R_PPC64_DTPREL16:
501 case R_PPC64_DTPREL16_LO:
502 case R_PPC64_DTPREL16_HI:
503 case R_PPC64_DTPREL16_HA:
507 value = conflict_lookup_value (conflict);
509 ret = prelink_conflict_add_rela (info);
512 ret->r_offset = rela->r_offset;
513 value += rela->r_addend;
514 r_type = GELF_R_TYPE (rela->r_info);
517 case R_PPC64_GLOB_DAT:
518 r_type = R_PPC64_ADDR64;
520 case R_PPC64_UADDR64:
521 if (conflict != NULL && conflict->ifunc)
522 r_type = R_PPC64_IRELATIVE;
524 case R_PPC64_IRELATIVE:
525 case R_PPC64_JMP_IREL:
527 case R_PPC64_JMP_SLOT:
528 if (conflict != NULL && conflict->ifunc)
529 r_type = R_PPC64_JMP_IREL;
532 case R_PPC64_UADDR32:
533 value = (Elf32_Sword) value;
535 case R_PPC64_ADDR16_HA:
538 case R_PPC64_ADDR16_HI:
542 case R_PPC64_UADDR16:
543 case R_PPC64_ADDR16_LO:
544 if (r_type != R_PPC64_UADDR16)
545 r_type = R_PPC64_ADDR16;
546 value = ((value & 0xffff) ^ 0x8000) - 0x8000;
548 case R_PPC64_ADDR16_HIGHERA:
551 case R_PPC64_ADDR16_HIGHER:
552 r_type = R_PPC64_ADDR16;
553 value = (((value >> 32) & 0xffff) ^ 0x8000) - 0x8000;
555 case R_PPC64_ADDR16_HIGHESTA:
558 case R_PPC64_ADDR16_HIGHEST:
559 r_type = R_PPC64_ADDR16;
560 value = ((Elf64_Sxword) value) >> 48;
562 case R_PPC64_ADDR16_LO_DS:
563 case R_PPC64_ADDR16_DS:
564 r_type = R_PPC64_ADDR16;
565 value = ((value & 0xffff) ^ 0x8000) - 0x8000;
566 value |= read_ube16 (dso, rela->r_offset) & 3;
569 r_type = R_PPC64_ADDR32;
570 value = (value & 0x03fffffc)
571 | (read_ube32 (dso, rela->r_offset) & 0xfc000003);
572 value = (Elf32_Sword) value;
575 r_type = R_PPC64_ADDR32;
576 value = (value & 0xfffc)
577 | (read_ube32 (dso, rela->r_offset) & 0xffff0003);
578 value = (Elf32_Sword) value;
580 case R_PPC64_ADDR14_BRTAKEN:
581 case R_PPC64_ADDR14_BRNTAKEN:
582 r_type = R_PPC64_ADDR32;
583 value = (value & 0xfffc)
584 | (read_ube32 (dso, rela->r_offset) & 0xffdf0003)
585 | ((((r_type == R_PPC64_ADDR14_BRTAKEN) << 21)
586 ^ (value >> 42)) & 0x00200000);
587 value = (Elf32_Sword) value;
590 r_type = R_PPC64_ADDR32;
591 value = ((value - rela->r_offset) & 0x03fffffc)
592 | (read_ube32 (dso, rela->r_offset) & 0xfc000003);
593 value = (Elf32_Sword) value;
596 r_type = R_PPC64_ADDR32;
597 value -= rela->r_offset;
598 value = (Elf32_Sword) value;
601 r_type = R_PPC64_ADDR64;
602 value -= rela->r_offset;
604 case R_PPC64_DTPMOD64:
605 case R_PPC64_DTPREL64:
606 case R_PPC64_DTPREL16:
607 case R_PPC64_DTPREL16_LO:
608 case R_PPC64_DTPREL16_HI:
609 case R_PPC64_DTPREL16_HA:
610 case R_PPC64_TPREL64:
611 case R_PPC64_TPREL16:
612 case R_PPC64_TPREL16_LO:
613 case R_PPC64_TPREL16_HI:
614 case R_PPC64_TPREL16_HA:
616 && (conflict->reloc_class != RTYPE_CLASS_TLS
617 || conflict->lookup.tls == NULL))
619 error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol",
623 tls = conflict ? conflict->lookup.tls : info->curtls;
624 r_type = R_PPC64_ADDR16;
625 switch (GELF_R_TYPE (rela->r_info))
627 case R_PPC64_DTPMOD64:
628 r_type = R_PPC64_ADDR64;
631 case R_PPC64_DTPREL64:
632 r_type = R_PPC64_ADDR64;
635 case R_PPC64_DTPREL16:
636 case R_PPC64_DTPREL16_LO:
639 case R_PPC64_DTPREL16_HI:
640 value = (value - 0x8000) >> 16;
642 case R_PPC64_DTPREL16_HA:
645 case R_PPC64_TPREL64:
646 r_type = R_PPC64_ADDR64;
647 value += tls->offset - 0x7000;
649 case R_PPC64_TPREL16:
650 case R_PPC64_TPREL16_LO:
651 value += tls->offset - 0x7000;
653 case R_PPC64_TPREL16_HI:
654 value = (value + tls->offset - 0x7000) >> 16;
656 case R_PPC64_TPREL16_HA:
657 value = (value + tls->offset - 0x7000 + 0x8000) >> 16;
660 if (r_type == R_PPC64_ADDR16)
661 value = ((value & 0xffff) ^ 0x8000) - 0x8000;
664 error (0, 0, "%s: Unknown PowerPC64 relocation type %d", dso->filename,
668 if (conflict != NULL && conflict->ifunc
669 && r_type != R_PPC64_IRELATIVE && r_type != R_PPC64_JMP_IREL)
671 error (0, 0, "%s: relocation %d against IFUNC symbol", dso->filename,
672 (int) GELF_R_TYPE (rela->r_info));
675 ret->r_info = GELF_R_INFO (0, r_type);
676 ret->r_addend = value;
681 ppc64_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela)
683 error (0, 0, "%s: PowerPC64 doesn't support REL relocs", dso->filename);
688 ppc64_need_rel_to_rela (DSO *dso, int first, int last)
694 ppc64_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr)
696 switch (GELF_R_TYPE (rela->r_info))
700 case R_PPC64_JMP_SLOT:
701 /* .plt section will become SHT_NOBITS. */
703 case R_PPC64_JMP_IREL:
704 /* .iplt section will become SHT_NOBITS. */
706 case R_PPC64_RELATIVE:
708 case R_PPC64_IRELATIVE:
709 write_be64 (dso, rela->r_offset, rela->r_addend);
711 case R_PPC64_GLOB_DAT:
712 case R_PPC64_UADDR64:
713 case R_PPC64_DTPREL64:
714 case R_PPC64_TPREL64:
715 case R_PPC64_DTPMOD64:
717 write_be64 (dso, rela->r_offset, 0);
720 case R_PPC64_UADDR32:
722 write_be32 (dso, rela->r_offset, 0);
724 case R_PPC64_ADDR16_HA:
725 case R_PPC64_DTPREL16_HA:
726 case R_PPC64_TPREL16_HA:
727 case R_PPC64_ADDR16_HI:
728 case R_PPC64_DTPREL16_HI:
729 case R_PPC64_TPREL16_HI:
731 case R_PPC64_UADDR16:
732 case R_PPC64_ADDR16_LO:
733 case R_PPC64_DTPREL16:
734 case R_PPC64_TPREL16:
735 case R_PPC64_DTPREL16_LO:
736 case R_PPC64_TPREL16_LO:
737 case R_PPC64_ADDR16_HIGHERA:
738 case R_PPC64_ADDR16_HIGHER:
739 case R_PPC64_ADDR16_HIGHESTA:
740 case R_PPC64_ADDR16_HIGHEST:
741 case R_PPC64_ADDR16_LO_DS:
742 case R_PPC64_ADDR16_DS:
743 write_be16 (dso, rela->r_offset, 0);
747 write_be32 (dso, rela->r_offset,
748 read_ube32 (dso, rela->r_offset) & 0xfc000003);
751 write_be32 (dso, rela->r_offset,
752 read_ube32 (dso, rela->r_offset) & 0xffff0003);
754 case R_PPC64_ADDR14_BRTAKEN:
755 case R_PPC64_ADDR14_BRNTAKEN:
756 write_be32 (dso, rela->r_offset,
757 read_ube32 (dso, rela->r_offset) & 0xffdf0003);
760 if (dso->ehdr.e_type == ET_EXEC)
761 /* COPY relocs are handled specially in generic code. */
763 error (0, 0, "%s: R_PPC64_COPY reloc in shared library?", dso->filename);
766 error (0, 0, "%s: Unknown ppc relocation type %d", dso->filename,
767 (int) GELF_R_TYPE (rela->r_info));
774 ppc64_reloc_size (int reloc_type)
779 case R_PPC64_UADDR16:
780 case R_PPC64_ADDR16_LO:
781 case R_PPC64_ADDR16_HA:
782 case R_PPC64_ADDR16_HI:
783 case R_PPC64_ADDR16_LO_DS:
784 case R_PPC64_ADDR16_DS:
785 case R_PPC64_ADDR16_HIGHER:
786 case R_PPC64_ADDR16_HIGHERA:
787 case R_PPC64_ADDR16_HIGHEST:
788 case R_PPC64_ADDR16_HIGHESTA:
789 case R_PPC64_DTPREL16:
790 case R_PPC64_DTPREL16_LO:
791 case R_PPC64_DTPREL16_HI:
792 case R_PPC64_DTPREL16_HA:
793 case R_PPC64_TPREL16:
794 case R_PPC64_TPREL16_LO:
795 case R_PPC64_TPREL16_HI:
796 case R_PPC64_TPREL16_HA:
798 case R_PPC64_GLOB_DAT:
800 case R_PPC64_UADDR64:
802 case R_PPC64_DTPMOD64:
803 case R_PPC64_DTPREL64:
804 case R_PPC64_TPREL64:
805 case R_PPC64_IRELATIVE:
814 ppc64_reloc_class (int reloc_type)
818 case R_PPC64_COPY: return RTYPE_CLASS_COPY | RTYPE_CLASS_PLT;
820 if (reloc_type >= R_PPC64_DTPMOD64
821 && reloc_type <= R_PPC64_TPREL16_HIGHESTA)
822 return RTYPE_CLASS_TLS;
823 return RTYPE_CLASS_PLT;
828 ppc64_read_opd (DSO *dso, struct prelink_entry *ent)
835 for (opd = 1; opd < dso->ehdr.e_shnum; ++opd)
836 if (dso->shdr[opd].sh_type == SHT_PROGBITS
837 && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
838 dso->shdr[opd].sh_name), ".opd"))
840 if (opd == dso->ehdr.e_shnum)
842 ent->opd = malloc (sizeof (struct opd_lib) + dso->shdr[opd].sh_size);
843 /* The error will happen only when we'll need the opd. */
844 if (ent->opd == NULL)
846 s = dso->shdr[opd].sh_addr;
847 for (n = 0; n < dso->shdr[opd].sh_size / 8; ++n, s += 8)
848 ent->opd->table[n] = read_ube64 (dso, s);
849 ent->opd->start = dso->shdr[opd].sh_addr;
850 ent->opd->size = dso->shdr[opd].sh_size;
855 ppc64_free_opd (struct prelink_entry *ent)
866 .alternate_machine = { EM_NONE },
867 .R_JMP_SLOT = R_PPC64_JMP_SLOT,
868 .R_COPY = R_PPC64_COPY,
869 .R_RELATIVE = R_PPC64_RELATIVE,
870 .rtype_class_valid = RTYPE_CLASS_PLT,
871 .dynamic_linker = "/lib64/ld64.so.1",
872 .adjust_section = ppc64_adjust_section,
873 .adjust_dyn = ppc64_adjust_dyn,
874 .adjust_rel = ppc64_adjust_rel,
875 .adjust_rela = ppc64_adjust_rela,
876 .prelink_rel = ppc64_prelink_rel,
877 .prelink_rela = ppc64_prelink_rela,
878 .prelink_conflict_rel = ppc64_prelink_conflict_rel,
879 .prelink_conflict_rela = ppc64_prelink_conflict_rela,
880 .apply_conflict_rela = ppc64_apply_conflict_rela,
881 .apply_rel = ppc64_apply_rel,
882 .apply_rela = ppc64_apply_rela,
883 .rel_to_rela = ppc64_rel_to_rela,
884 .need_rel_to_rela = ppc64_need_rel_to_rela,
885 .reloc_size = ppc64_reloc_size,
886 .reloc_class = ppc64_reloc_class,
887 .read_opd = ppc64_read_opd,
888 .free_opd = ppc64_free_opd,
890 .undo_prelink_rela = ppc64_undo_prelink_rela,
891 /* Although TASK_UNMAPPED_BASE is 0x8000000000, we leave some
892 area so that mmap of /etc/ld.so.cache and ld.so's malloc
893 does not take some library's VA slot.
894 Also, if this guard area isn't too small, typically
895 even dlopened libraries will get the slots they desire. */
896 .mmap_base = 0x8001000000LL,
897 .mmap_end = 0x8100000000LL,
898 .max_page_size = 0x10000,