| 1 |
/* PowerPC-specific support for 32-bit ELF |
/* PowerPC-specific support for 32-bit ELF |
| 2 |
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, |
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, |
| 3 |
2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. |
2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. |
| 4 |
Written by Ian Lance Taylor, Cygnus Support. |
Written by Ian Lance Taylor, Cygnus Support. |
| 5 |
|
|
| 6 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
| 753 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
| 754 |
FALSE), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
| 755 |
|
|
| 756 |
/* Marker reloc for TLS. */ |
/* Marker relocs for TLS. */ |
| 757 |
HOWTO (R_PPC_TLS, |
HOWTO (R_PPC_TLS, |
| 758 |
0, /* rightshift */ |
0, /* rightshift */ |
| 759 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 768 |
0, /* dst_mask */ |
0, /* dst_mask */ |
| 769 |
FALSE), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
| 770 |
|
|
| 771 |
|
HOWTO (R_PPC_TLSGD, |
| 772 |
|
0, /* rightshift */ |
| 773 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 774 |
|
32, /* bitsize */ |
| 775 |
|
FALSE, /* pc_relative */ |
| 776 |
|
0, /* bitpos */ |
| 777 |
|
complain_overflow_dont, /* complain_on_overflow */ |
| 778 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 779 |
|
"R_PPC_TLSGD", /* name */ |
| 780 |
|
FALSE, /* partial_inplace */ |
| 781 |
|
0, /* src_mask */ |
| 782 |
|
0, /* dst_mask */ |
| 783 |
|
FALSE), /* pcrel_offset */ |
| 784 |
|
|
| 785 |
|
HOWTO (R_PPC_TLSLD, |
| 786 |
|
0, /* rightshift */ |
| 787 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 788 |
|
32, /* bitsize */ |
| 789 |
|
FALSE, /* pc_relative */ |
| 790 |
|
0, /* bitpos */ |
| 791 |
|
complain_overflow_dont, /* complain_on_overflow */ |
| 792 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 793 |
|
"R_PPC_TLSLD", /* name */ |
| 794 |
|
FALSE, /* partial_inplace */ |
| 795 |
|
0, /* src_mask */ |
| 796 |
|
0, /* dst_mask */ |
| 797 |
|
FALSE), /* pcrel_offset */ |
| 798 |
|
|
| 799 |
/* Computes the load module index of the load module that contains the |
/* Computes the load module index of the load module that contains the |
| 800 |
definition of its TLS sym. */ |
definition of its TLS sym. */ |
| 801 |
HOWTO (R_PPC_DTPMOD32, |
HOWTO (R_PPC_DTPMOD32, |
| 1382 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
| 1383 |
FALSE), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
| 1384 |
|
|
| 1385 |
|
HOWTO (R_PPC_IRELATIVE, /* type */ |
| 1386 |
|
0, /* rightshift */ |
| 1387 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 1388 |
|
32, /* bitsize */ |
| 1389 |
|
FALSE, /* pc_relative */ |
| 1390 |
|
0, /* bitpos */ |
| 1391 |
|
complain_overflow_bitfield, /* complain_on_overflow */ |
| 1392 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 1393 |
|
"R_PPC_IRELATIVE", /* name */ |
| 1394 |
|
FALSE, /* partial_inplace */ |
| 1395 |
|
0, /* src_mask */ |
| 1396 |
|
0xffffffff, /* dst_mask */ |
| 1397 |
|
FALSE), /* pcrel_offset */ |
| 1398 |
|
|
| 1399 |
/* A 16 bit relative relocation. */ |
/* A 16 bit relative relocation. */ |
| 1400 |
HOWTO (R_PPC_REL16, /* type */ |
HOWTO (R_PPC_REL16, /* type */ |
| 1401 |
0, /* rightshift */ |
0, /* rightshift */ |
| 1573 |
case BFD_RELOC_CTOR: r = R_PPC_ADDR32; break; |
case BFD_RELOC_CTOR: r = R_PPC_ADDR32; break; |
| 1574 |
case BFD_RELOC_PPC_TOC16: r = R_PPC_TOC16; break; |
case BFD_RELOC_PPC_TOC16: r = R_PPC_TOC16; break; |
| 1575 |
case BFD_RELOC_PPC_TLS: r = R_PPC_TLS; break; |
case BFD_RELOC_PPC_TLS: r = R_PPC_TLS; break; |
| 1576 |
|
case BFD_RELOC_PPC_TLSGD: r = R_PPC_TLSGD; break; |
| 1577 |
|
case BFD_RELOC_PPC_TLSLD: r = R_PPC_TLSLD; break; |
| 1578 |
case BFD_RELOC_PPC_DTPMOD: r = R_PPC_DTPMOD32; break; |
case BFD_RELOC_PPC_DTPMOD: r = R_PPC_DTPMOD32; break; |
| 1579 |
case BFD_RELOC_PPC_TPREL16: r = R_PPC_TPREL16; break; |
case BFD_RELOC_PPC_TPREL16: r = R_PPC_TPREL16; break; |
| 1580 |
case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC_TPREL16_LO; break; |
case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC_TPREL16_LO; break; |
| 2342 |
} |
} |
| 2343 |
|
|
| 2344 |
static bfd_boolean |
static bfd_boolean |
| 2345 |
is_pic_glink_stub (bfd *abfd, asection *glink, bfd_vma off) |
is_nonpic_glink_stub (bfd *abfd, asection *glink, bfd_vma off) |
| 2346 |
{ |
{ |
| 2347 |
bfd_byte buf[16]; |
bfd_byte buf[GLINK_ENTRY_SIZE]; |
|
unsigned int insn; |
|
| 2348 |
|
|
| 2349 |
if (!bfd_get_section_contents (abfd, glink, buf, off, 16)) |
if (!bfd_get_section_contents (abfd, glink, buf, off, GLINK_ENTRY_SIZE)) |
| 2350 |
return FALSE; |
return FALSE; |
| 2351 |
|
|
| 2352 |
insn = bfd_get_32 (abfd, buf); |
return ((bfd_get_32 (abfd, buf + 0) & 0xffff0000) == LIS_11 |
| 2353 |
if ((insn & 0xffff0000) == LWZ_11_30 |
&& (bfd_get_32 (abfd, buf + 4) & 0xffff0000) == LWZ_11_11 |
| 2354 |
&& bfd_get_32 (abfd, buf + 4) == MTCTR_11 |
&& bfd_get_32 (abfd, buf + 8) == MTCTR_11 |
| 2355 |
&& bfd_get_32 (abfd, buf + 8) == BCTR) |
&& bfd_get_32 (abfd, buf + 12) == BCTR); |
|
return TRUE; |
|
|
|
|
|
if ((insn & 0xffff0000) == ADDIS_11_30 |
|
|
&& (bfd_get_32 (abfd, buf + 4) & 0xffff0000) == LWZ_11_11 |
|
|
&& bfd_get_32 (abfd, buf + 8) == MTCTR_11 |
|
|
&& bfd_get_32 (abfd, buf + 12) == BCTR) |
|
|
return TRUE; |
|
|
return FALSE; |
|
| 2356 |
} |
} |
| 2357 |
|
|
| 2358 |
static bfd_boolean |
static bfd_boolean |
| 2489 |
multiple stubs for each plt entry. If that is the case then |
multiple stubs for each plt entry. If that is the case then |
| 2490 |
there is no way to associate stubs with their plt entries short |
there is no way to associate stubs with their plt entries short |
| 2491 |
of figuring out the GOT pointer value used in the stub. */ |
of figuring out the GOT pointer value used in the stub. */ |
| 2492 |
if (!bfd_get_section_contents (abfd, glink, buf, |
if (!is_nonpic_glink_stub (abfd, glink, |
| 2493 |
stub_vma - glink->vma, 4) |
glink_vma - GLINK_ENTRY_SIZE - glink->vma)) |
|
|| ((bfd_get_32 (abfd, buf) & 0xffff0000) != LIS_11 |
|
|
&& is_pic_glink_stub (abfd, glink, stub_vma - glink->vma - 16))) |
|
| 2494 |
return 0; |
return 0; |
| 2495 |
|
|
| 2496 |
slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table; |
slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table; |
| 2500 |
size = count * sizeof (asymbol); |
size = count * sizeof (asymbol); |
| 2501 |
p = relplt->relocation; |
p = relplt->relocation; |
| 2502 |
for (i = 0; i < count; i++, p++) |
for (i = 0; i < count; i++, p++) |
| 2503 |
size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt"); |
{ |
| 2504 |
|
size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt"); |
| 2505 |
|
if (p->addend != 0) |
| 2506 |
|
size += sizeof ("+0x") - 1 + 8; |
| 2507 |
|
} |
| 2508 |
|
|
| 2509 |
size += sizeof (asymbol) + sizeof ("__glink"); |
size += sizeof (asymbol) + sizeof ("__glink"); |
| 2510 |
|
|
| 2534 |
len = strlen ((*p->sym_ptr_ptr)->name); |
len = strlen ((*p->sym_ptr_ptr)->name); |
| 2535 |
memcpy (names, (*p->sym_ptr_ptr)->name, len); |
memcpy (names, (*p->sym_ptr_ptr)->name, len); |
| 2536 |
names += len; |
names += len; |
| 2537 |
|
if (p->addend != 0) |
| 2538 |
|
{ |
| 2539 |
|
memcpy (names, "+0x", sizeof ("+0x") - 1); |
| 2540 |
|
names += sizeof ("+0x") - 1; |
| 2541 |
|
bfd_sprintf_vma (abfd, names, p->addend); |
| 2542 |
|
names += strlen (names); |
| 2543 |
|
} |
| 2544 |
memcpy (names, "@plt", sizeof ("@plt")); |
memcpy (names, "@plt", sizeof ("@plt")); |
| 2545 |
names += sizeof ("@plt"); |
names += sizeof ("@plt"); |
| 2546 |
++s; |
++s; |
| 2690 |
#define TLS_DTPREL 8 /* DTPREL reloc, => LD. */ |
#define TLS_DTPREL 8 /* DTPREL reloc, => LD. */ |
| 2691 |
#define TLS_TLS 16 /* Any TLS reloc. */ |
#define TLS_TLS 16 /* Any TLS reloc. */ |
| 2692 |
#define TLS_TPRELGD 32 /* TPREL reloc resulting from GD->IE. */ |
#define TLS_TPRELGD 32 /* TPREL reloc resulting from GD->IE. */ |
| 2693 |
|
#define PLT_IFUNC 64 /* STT_GNU_IFUNC. */ |
| 2694 |
char tls_mask; |
char tls_mask; |
| 2695 |
|
|
| 2696 |
/* Nonzero if we have seen a small data relocation referring to this |
/* Nonzero if we have seen a small data relocation referring to this |
| 2712 |
asection *glink; |
asection *glink; |
| 2713 |
asection *plt; |
asection *plt; |
| 2714 |
asection *relplt; |
asection *relplt; |
| 2715 |
|
asection *iplt; |
| 2716 |
|
asection *reliplt; |
| 2717 |
asection *dynbss; |
asection *dynbss; |
| 2718 |
asection *relbss; |
asection *relbss; |
| 2719 |
asection *dynsbss; |
asection *dynsbss; |
| 2739 |
bfd_vma offset; |
bfd_vma offset; |
| 2740 |
} tlsld_got; |
} tlsld_got; |
| 2741 |
|
|
| 2742 |
/* Offset of PltResolve function in glink. */ |
/* Offset of branch table to PltResolve function in glink. */ |
| 2743 |
bfd_vma glink_pltresolve; |
bfd_vma glink_pltresolve; |
| 2744 |
|
|
| 2745 |
/* Size of reserved GOT entries. */ |
/* Size of reserved GOT entries. */ |
| 2763 |
/* The size of the first PLT entry. */ |
/* The size of the first PLT entry. */ |
| 2764 |
int plt_initial_entry_size; |
int plt_initial_entry_size; |
| 2765 |
|
|
| 2766 |
/* Small local sym to section mapping cache. */ |
/* Small local sym cache. */ |
| 2767 |
struct sym_sec_cache sym_sec; |
struct sym_cache sym_cache; |
| 2768 |
}; |
}; |
| 2769 |
|
|
| 2770 |
/* Get the PPC ELF linker hash table from a link_info structure. */ |
/* Get the PPC ELF linker hash table from a link_info structure. */ |
| 2873 |
return FALSE; |
return FALSE; |
| 2874 |
} |
} |
| 2875 |
|
|
| 2876 |
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY |
htab->relgot = bfd_get_section_by_name (abfd, ".rela.got"); |
| 2877 |
| SEC_LINKER_CREATED | SEC_READONLY); |
if (!htab->relgot) |
| 2878 |
htab->relgot = bfd_make_section_with_flags (abfd, ".rela.got", flags); |
abort (); |
| 2879 |
if (!htab->relgot |
|
| 2880 |
|| ! bfd_set_section_alignment (abfd, htab->relgot, 2)) |
return TRUE; |
| 2881 |
|
} |
| 2882 |
|
|
| 2883 |
|
static bfd_boolean |
| 2884 |
|
ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info) |
| 2885 |
|
{ |
| 2886 |
|
struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); |
| 2887 |
|
asection *s; |
| 2888 |
|
flagword flags; |
| 2889 |
|
|
| 2890 |
|
flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS |
| 2891 |
|
| SEC_IN_MEMORY | SEC_LINKER_CREATED); |
| 2892 |
|
s = bfd_make_section_anyway_with_flags (abfd, ".glink", flags); |
| 2893 |
|
htab->glink = s; |
| 2894 |
|
if (s == NULL |
| 2895 |
|
|| !bfd_set_section_alignment (abfd, s, 4)) |
| 2896 |
|
return FALSE; |
| 2897 |
|
|
| 2898 |
|
flags = SEC_ALLOC | SEC_LINKER_CREATED; |
| 2899 |
|
s = bfd_make_section_anyway_with_flags (abfd, ".iplt", flags); |
| 2900 |
|
htab->iplt = s; |
| 2901 |
|
if (s == NULL |
| 2902 |
|
|| !bfd_set_section_alignment (abfd, s, 4)) |
| 2903 |
return FALSE; |
return FALSE; |
| 2904 |
|
|
| 2905 |
|
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS |
| 2906 |
|
| SEC_IN_MEMORY | SEC_LINKER_CREATED); |
| 2907 |
|
s = bfd_make_section_with_flags (abfd, ".rela.iplt", flags); |
| 2908 |
|
htab->reliplt = s; |
| 2909 |
|
if (s == NULL |
| 2910 |
|
|| ! bfd_set_section_alignment (abfd, s, 2)) |
| 2911 |
|
return FALSE; |
| 2912 |
return TRUE; |
return TRUE; |
| 2913 |
} |
} |
| 2914 |
|
|
| 2932 |
if (!_bfd_elf_create_dynamic_sections (abfd, info)) |
if (!_bfd_elf_create_dynamic_sections (abfd, info)) |
| 2933 |
return FALSE; |
return FALSE; |
| 2934 |
|
|
| 2935 |
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS |
if (htab->glink == NULL |
| 2936 |
| SEC_IN_MEMORY | SEC_LINKER_CREATED); |
&& !ppc_elf_create_glink (abfd, info)) |
|
|
|
|
s = bfd_make_section_anyway_with_flags (abfd, ".glink", flags | SEC_CODE); |
|
|
htab->glink = s; |
|
|
if (s == NULL |
|
|
|| !bfd_set_section_alignment (abfd, s, 4)) |
|
| 2937 |
return FALSE; |
return FALSE; |
| 2938 |
|
|
| 2939 |
htab->dynbss = bfd_get_section_by_name (abfd, ".dynbss"); |
htab->dynbss = bfd_get_section_by_name (abfd, ".dynbss"); |
| 2946 |
if (! info->shared) |
if (! info->shared) |
| 2947 |
{ |
{ |
| 2948 |
htab->relbss = bfd_get_section_by_name (abfd, ".rela.bss"); |
htab->relbss = bfd_get_section_by_name (abfd, ".rela.bss"); |
| 2949 |
|
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS |
| 2950 |
|
| SEC_IN_MEMORY | SEC_LINKER_CREATED); |
| 2951 |
s = bfd_make_section_with_flags (abfd, ".rela.sbss", flags); |
s = bfd_make_section_with_flags (abfd, ".rela.sbss", flags); |
| 2952 |
htab->relsbss = s; |
htab->relsbss = s; |
| 2953 |
if (s == NULL |
if (s == NULL |
| 3121 |
*valp = sym->st_size; |
*valp = sym->st_size; |
| 3122 |
} |
} |
| 3123 |
|
|
| 3124 |
|
if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) |
| 3125 |
|
elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE; |
| 3126 |
|
|
| 3127 |
return TRUE; |
return TRUE; |
| 3128 |
} |
} |
| 3129 |
|
|
| 3272 |
return TRUE; |
return TRUE; |
| 3273 |
} |
} |
| 3274 |
|
|
| 3275 |
static bfd_boolean |
static struct plt_entry ** |
| 3276 |
update_local_sym_info (bfd *abfd, |
update_local_sym_info (bfd *abfd, |
| 3277 |
Elf_Internal_Shdr *symtab_hdr, |
Elf_Internal_Shdr *symtab_hdr, |
| 3278 |
unsigned long r_symndx, |
unsigned long r_symndx, |
| 3279 |
int tls_type) |
int tls_type) |
| 3280 |
{ |
{ |
| 3281 |
bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd); |
bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd); |
| 3282 |
|
struct plt_entry **local_plt; |
| 3283 |
char *local_got_tls_masks; |
char *local_got_tls_masks; |
| 3284 |
|
|
| 3285 |
if (local_got_refcounts == NULL) |
if (local_got_refcounts == NULL) |
| 3286 |
{ |
{ |
| 3287 |
bfd_size_type size = symtab_hdr->sh_info; |
bfd_size_type size = symtab_hdr->sh_info; |
| 3288 |
|
|
| 3289 |
size *= sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks); |
size *= (sizeof (*local_got_refcounts) |
| 3290 |
|
+ sizeof (*local_plt) |
| 3291 |
|
+ sizeof (*local_got_tls_masks)); |
| 3292 |
local_got_refcounts = bfd_zalloc (abfd, size); |
local_got_refcounts = bfd_zalloc (abfd, size); |
| 3293 |
if (local_got_refcounts == NULL) |
if (local_got_refcounts == NULL) |
| 3294 |
return FALSE; |
return NULL; |
| 3295 |
elf_local_got_refcounts (abfd) = local_got_refcounts; |
elf_local_got_refcounts (abfd) = local_got_refcounts; |
| 3296 |
} |
} |
| 3297 |
|
|
| 3298 |
local_got_refcounts[r_symndx] += 1; |
local_plt = (struct plt_entry **) (local_got_refcounts + symtab_hdr->sh_info); |
| 3299 |
local_got_tls_masks = (char *) (local_got_refcounts + symtab_hdr->sh_info); |
local_got_tls_masks = (char *) (local_plt + symtab_hdr->sh_info); |
| 3300 |
local_got_tls_masks[r_symndx] |= tls_type; |
local_got_tls_masks[r_symndx] |= tls_type; |
| 3301 |
return TRUE; |
if (tls_type != PLT_IFUNC) |
| 3302 |
|
local_got_refcounts[r_symndx] += 1; |
| 3303 |
|
return local_plt + r_symndx; |
| 3304 |
} |
} |
| 3305 |
|
|
| 3306 |
static bfd_boolean |
static bfd_boolean |
| 3307 |
update_plt_info (bfd *abfd, struct elf_link_hash_entry *h, |
update_plt_info (bfd *abfd, struct plt_entry **plist, |
| 3308 |
asection *sec, bfd_vma addend) |
asection *sec, bfd_vma addend) |
| 3309 |
{ |
{ |
| 3310 |
struct plt_entry *ent; |
struct plt_entry *ent; |
| 3311 |
|
|
| 3312 |
if (addend < 32768) |
for (ent = *plist; ent != NULL; ent = ent->next) |
|
sec = NULL; |
|
|
for (ent = h->plt.plist; ent != NULL; ent = ent->next) |
|
| 3313 |
if (ent->sec == sec && ent->addend == addend) |
if (ent->sec == sec && ent->addend == addend) |
| 3314 |
break; |
break; |
| 3315 |
if (ent == NULL) |
if (ent == NULL) |
| 3318 |
ent = bfd_alloc (abfd, amt); |
ent = bfd_alloc (abfd, amt); |
| 3319 |
if (ent == NULL) |
if (ent == NULL) |
| 3320 |
return FALSE; |
return FALSE; |
| 3321 |
ent->next = h->plt.plist; |
ent->next = *plist; |
| 3322 |
ent->sec = sec; |
ent->sec = sec; |
| 3323 |
ent->addend = addend; |
ent->addend = addend; |
| 3324 |
ent->plt.refcount = 0; |
ent->plt.refcount = 0; |
| 3325 |
h->plt.plist = ent; |
*plist = ent; |
| 3326 |
} |
} |
| 3327 |
ent->plt.refcount += 1; |
ent->plt.refcount += 1; |
| 3328 |
return TRUE; |
return TRUE; |
| 3329 |
} |
} |
| 3330 |
|
|
| 3331 |
static struct plt_entry * |
static struct plt_entry * |
| 3332 |
find_plt_ent (struct elf_link_hash_entry *h, asection *sec, bfd_vma addend) |
find_plt_ent (struct plt_entry **plist, asection *sec, bfd_vma addend) |
| 3333 |
{ |
{ |
| 3334 |
struct plt_entry *ent; |
struct plt_entry *ent; |
| 3335 |
|
|
| 3336 |
if (addend < 32768) |
if (addend < 32768) |
| 3337 |
sec = NULL; |
sec = NULL; |
| 3338 |
for (ent = h->plt.plist; ent != NULL; ent = ent->next) |
for (ent = *plist; ent != NULL; ent = ent->next) |
| 3339 |
if (ent->sec == sec && ent->addend == addend) |
if (ent->sec == sec && ent->addend == addend) |
| 3340 |
break; |
break; |
| 3341 |
return ent; |
return ent; |
| 3342 |
} |
} |
| 3343 |
|
|
| 3344 |
|
static bfd_boolean |
| 3345 |
|
is_branch_reloc (enum elf_ppc_reloc_type r_type) |
| 3346 |
|
{ |
| 3347 |
|
return (r_type == R_PPC_PLTREL24 |
| 3348 |
|
|| r_type == R_PPC_LOCAL24PC |
| 3349 |
|
|| r_type == R_PPC_REL24 |
| 3350 |
|
|| r_type == R_PPC_REL14 |
| 3351 |
|
|| r_type == R_PPC_REL14_BRTAKEN |
| 3352 |
|
|| r_type == R_PPC_REL14_BRNTAKEN |
| 3353 |
|
|| r_type == R_PPC_ADDR24 |
| 3354 |
|
|| r_type == R_PPC_ADDR14 |
| 3355 |
|
|| r_type == R_PPC_ADDR14_BRTAKEN |
| 3356 |
|
|| r_type == R_PPC_ADDR14_BRNTAKEN); |
| 3357 |
|
} |
| 3358 |
|
|
| 3359 |
static void |
static void |
| 3360 |
bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type) |
bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type) |
| 3361 |
{ |
{ |
| 3382 |
const Elf_Internal_Rela *rel; |
const Elf_Internal_Rela *rel; |
| 3383 |
const Elf_Internal_Rela *rel_end; |
const Elf_Internal_Rela *rel_end; |
| 3384 |
asection *got2, *sreloc; |
asection *got2, *sreloc; |
| 3385 |
|
struct elf_link_hash_entry *tga; |
| 3386 |
|
|
| 3387 |
if (info->relocatable) |
if (info->relocatable) |
| 3388 |
return TRUE; |
return TRUE; |
| 3408 |
ppc_elf_howto_init (); |
ppc_elf_howto_init (); |
| 3409 |
|
|
| 3410 |
htab = ppc_elf_hash_table (info); |
htab = ppc_elf_hash_table (info); |
| 3411 |
|
tga = elf_link_hash_lookup (&htab->elf, "__tls_get_addr", |
| 3412 |
|
FALSE, FALSE, TRUE); |
| 3413 |
symtab_hdr = &elf_symtab_hdr (abfd); |
symtab_hdr = &elf_symtab_hdr (abfd); |
| 3414 |
sym_hashes = elf_sym_hashes (abfd); |
sym_hashes = elf_sym_hashes (abfd); |
| 3415 |
got2 = bfd_get_section_by_name (abfd, ".got2"); |
got2 = bfd_get_section_by_name (abfd, ".got2"); |
| 3421 |
unsigned long r_symndx; |
unsigned long r_symndx; |
| 3422 |
enum elf_ppc_reloc_type r_type; |
enum elf_ppc_reloc_type r_type; |
| 3423 |
struct elf_link_hash_entry *h; |
struct elf_link_hash_entry *h; |
| 3424 |
int tls_type = 0; |
int tls_type; |
| 3425 |
|
struct plt_entry **ifunc; |
| 3426 |
|
|
| 3427 |
r_symndx = ELF32_R_SYM (rel->r_info); |
r_symndx = ELF32_R_SYM (rel->r_info); |
| 3428 |
if (r_symndx < symtab_hdr->sh_info) |
if (r_symndx < symtab_hdr->sh_info) |
| 3449 |
BFD_ASSERT (h == htab->elf.hgot); |
BFD_ASSERT (h == htab->elf.hgot); |
| 3450 |
} |
} |
| 3451 |
|
|
| 3452 |
|
tls_type = 0; |
| 3453 |
|
ifunc = NULL; |
| 3454 |
r_type = ELF32_R_TYPE (rel->r_info); |
r_type = ELF32_R_TYPE (rel->r_info); |
| 3455 |
|
if (!htab->is_vxworks && is_branch_reloc (r_type)) |
| 3456 |
|
{ |
| 3457 |
|
if (h != NULL && h == tga) |
| 3458 |
|
{ |
| 3459 |
|
if (rel != relocs |
| 3460 |
|
&& (ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSGD |
| 3461 |
|
|| ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSLD)) |
| 3462 |
|
/* We have a new-style __tls_get_addr call with a marker |
| 3463 |
|
reloc. */ |
| 3464 |
|
; |
| 3465 |
|
else |
| 3466 |
|
/* Mark this section as having an old-style call. */ |
| 3467 |
|
sec->has_tls_get_addr_call = 1; |
| 3468 |
|
} |
| 3469 |
|
|
| 3470 |
|
/* STT_GNU_IFUNC symbols must have a PLT entry. */ |
| 3471 |
|
if (h != NULL) |
| 3472 |
|
{ |
| 3473 |
|
if (h->type == STT_GNU_IFUNC) |
| 3474 |
|
{ |
| 3475 |
|
h->needs_plt = 1; |
| 3476 |
|
ifunc = &h->plt.plist; |
| 3477 |
|
} |
| 3478 |
|
} |
| 3479 |
|
else |
| 3480 |
|
{ |
| 3481 |
|
Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->sym_cache, |
| 3482 |
|
abfd, r_symndx); |
| 3483 |
|
if (isym == NULL) |
| 3484 |
|
return FALSE; |
| 3485 |
|
|
| 3486 |
|
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC) |
| 3487 |
|
{ |
| 3488 |
|
ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx, |
| 3489 |
|
PLT_IFUNC); |
| 3490 |
|
if (ifunc == NULL) |
| 3491 |
|
return FALSE; |
| 3492 |
|
} |
| 3493 |
|
} |
| 3494 |
|
if (ifunc != NULL) |
| 3495 |
|
{ |
| 3496 |
|
bfd_vma addend = 0; |
| 3497 |
|
|
| 3498 |
|
if (r_type == R_PPC_PLTREL24) |
| 3499 |
|
{ |
| 3500 |
|
ppc_elf_tdata (abfd)->makes_plt_call = 1; |
| 3501 |
|
addend = rel->r_addend; |
| 3502 |
|
} |
| 3503 |
|
if (!update_plt_info (abfd, ifunc, |
| 3504 |
|
addend < 32768 ? NULL : got2, addend)) |
| 3505 |
|
return FALSE; |
| 3506 |
|
|
| 3507 |
|
if (htab->glink == NULL) |
| 3508 |
|
{ |
| 3509 |
|
if (htab->elf.dynobj == NULL) |
| 3510 |
|
htab->elf.dynobj = abfd; |
| 3511 |
|
if (!ppc_elf_create_glink (htab->elf.dynobj, info)) |
| 3512 |
|
return FALSE; |
| 3513 |
|
} |
| 3514 |
|
} |
| 3515 |
|
} |
| 3516 |
|
|
| 3517 |
switch (r_type) |
switch (r_type) |
| 3518 |
{ |
{ |
| 3519 |
|
case R_PPC_TLSGD: |
| 3520 |
|
case R_PPC_TLSLD: |
| 3521 |
|
/* These special tls relocs tie a call to __tls_get_addr with |
| 3522 |
|
its parameter symbol. */ |
| 3523 |
|
break; |
| 3524 |
|
|
| 3525 |
case R_PPC_GOT_TLSLD16: |
case R_PPC_GOT_TLSLD16: |
| 3526 |
case R_PPC_GOT_TLSLD16_LO: |
case R_PPC_GOT_TLSLD16_LO: |
| 3527 |
case R_PPC_GOT_TLSLD16_HI: |
case R_PPC_GOT_TLSLD16_HI: |
| 3686 |
h->non_got_ref = TRUE; |
h->non_got_ref = TRUE; |
| 3687 |
break; |
break; |
| 3688 |
|
|
|
case R_PPC_PLT32: |
|
| 3689 |
case R_PPC_PLTREL24: |
case R_PPC_PLTREL24: |
| 3690 |
|
if (h == NULL || ifunc != NULL) |
| 3691 |
|
break; |
| 3692 |
|
/* Fall through */ |
| 3693 |
|
case R_PPC_PLT32: |
| 3694 |
case R_PPC_PLTREL32: |
case R_PPC_PLTREL32: |
| 3695 |
case R_PPC_PLT16_LO: |
case R_PPC_PLT16_LO: |
| 3696 |
case R_PPC_PLT16_HI: |
case R_PPC_PLT16_HI: |
| 3727 |
addend = rel->r_addend; |
addend = rel->r_addend; |
| 3728 |
} |
} |
| 3729 |
h->needs_plt = 1; |
h->needs_plt = 1; |
| 3730 |
if (!update_plt_info (abfd, h, got2, addend)) |
if (!update_plt_info (abfd, &h->plt.plist, |
| 3731 |
|
addend < 32768 ? NULL : got2, addend)) |
| 3732 |
return FALSE; |
return FALSE; |
| 3733 |
} |
} |
| 3734 |
break; |
break; |
| 3759 |
case R_PPC_EMB_MRKREF: |
case R_PPC_EMB_MRKREF: |
| 3760 |
case R_PPC_NONE: |
case R_PPC_NONE: |
| 3761 |
case R_PPC_max: |
case R_PPC_max: |
| 3762 |
|
case R_PPC_RELAX32: |
| 3763 |
|
case R_PPC_RELAX32PC: |
| 3764 |
|
case R_PPC_RELAX32_PLT: |
| 3765 |
|
case R_PPC_RELAX32PC_PLT: |
| 3766 |
break; |
break; |
| 3767 |
|
|
| 3768 |
/* These should only appear in dynamic objects. */ |
/* These should only appear in dynamic objects. */ |
| 3770 |
case R_PPC_GLOB_DAT: |
case R_PPC_GLOB_DAT: |
| 3771 |
case R_PPC_JMP_SLOT: |
case R_PPC_JMP_SLOT: |
| 3772 |
case R_PPC_RELATIVE: |
case R_PPC_RELATIVE: |
| 3773 |
|
case R_PPC_IRELATIVE: |
| 3774 |
break; |
break; |
| 3775 |
|
|
| 3776 |
/* These aren't handled yet. We'll report an error later. */ |
/* These aren't handled yet. We'll report an error later. */ |
| 3784 |
|
|
| 3785 |
/* This refers only to functions defined in the shared library. */ |
/* This refers only to functions defined in the shared library. */ |
| 3786 |
case R_PPC_LOCAL24PC: |
case R_PPC_LOCAL24PC: |
| 3787 |
if (h && h == htab->elf.hgot && htab->plt_type == PLT_UNSET) |
if (h != NULL && h == htab->elf.hgot && htab->plt_type == PLT_UNSET) |
| 3788 |
{ |
{ |
| 3789 |
htab->plt_type = PLT_OLD; |
htab->plt_type = PLT_OLD; |
| 3790 |
htab->old_bfd = abfd; |
htab->old_bfd = abfd; |
| 3836 |
reliably deduce the GOT pointer value needed for |
reliably deduce the GOT pointer value needed for |
| 3837 |
PLT call stubs. */ |
PLT call stubs. */ |
| 3838 |
asection *s; |
asection *s; |
| 3839 |
|
Elf_Internal_Sym *isym; |
| 3840 |
|
|
| 3841 |
s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, |
isym = bfd_sym_from_r_symndx (&htab->sym_cache, |
| 3842 |
r_symndx); |
abfd, r_symndx); |
| 3843 |
|
if (isym == NULL) |
| 3844 |
|
return FALSE; |
| 3845 |
|
|
| 3846 |
|
s = bfd_section_from_elf_index (abfd, isym->st_shndx); |
| 3847 |
if (s == got2) |
if (s == got2) |
| 3848 |
{ |
{ |
| 3849 |
htab->plt_type = PLT_OLD; |
htab->plt_type = PLT_OLD; |
| 3865 |
{ |
{ |
| 3866 |
/* We may need a plt entry if the symbol turns out to be |
/* We may need a plt entry if the symbol turns out to be |
| 3867 |
a function defined in a dynamic object. */ |
a function defined in a dynamic object. */ |
| 3868 |
if (!update_plt_info (abfd, h, NULL, 0)) |
if (!update_plt_info (abfd, &h->plt.plist, NULL, 0)) |
| 3869 |
return FALSE; |
return FALSE; |
| 3870 |
|
|
| 3871 |
/* We may need a copy reloc too. */ |
/* We may need a copy reloc too. */ |
| 3899 |
{ |
{ |
| 3900 |
/* We may need a plt entry if the symbol turns out to be |
/* We may need a plt entry if the symbol turns out to be |
| 3901 |
a function defined in a dynamic object. */ |
a function defined in a dynamic object. */ |
| 3902 |
if (!update_plt_info (abfd, h, NULL, 0)) |
h->needs_plt = 1; |
| 3903 |
|
if (ifunc == NULL |
| 3904 |
|
&& !update_plt_info (abfd, &h->plt.plist, NULL, 0)) |
| 3905 |
return FALSE; |
return FALSE; |
| 3906 |
break; |
break; |
| 3907 |
} |
} |
| 3973 |
/* Track dynamic relocs needed for local syms too. |
/* Track dynamic relocs needed for local syms too. |
| 3974 |
We really need local syms available to do this |
We really need local syms available to do this |
| 3975 |
easily. Oh well. */ |
easily. Oh well. */ |
|
|
|
| 3976 |
asection *s; |
asection *s; |
| 3977 |
void *vpp; |
void *vpp; |
| 3978 |
|
Elf_Internal_Sym *isym; |
| 3979 |
|
|
| 3980 |
s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, |
isym = bfd_sym_from_r_symndx (&htab->sym_cache, |
| 3981 |
sec, r_symndx); |
abfd, r_symndx); |
| 3982 |
if (s == NULL) |
if (isym == NULL) |
| 3983 |
return FALSE; |
return FALSE; |
| 3984 |
|
|
| 3985 |
|
s = bfd_section_from_elf_index (abfd, isym->st_shndx); |
| 3986 |
|
if (s == NULL) |
| 3987 |
|
s = sec; |
| 3988 |
|
|
| 3989 |
vpp = &elf_section_data (s)->local_dynrel; |
vpp = &elf_section_data (s)->local_dynrel; |
| 3990 |
head = (struct ppc_elf_dyn_relocs **) vpp; |
head = (struct ppc_elf_dyn_relocs **) vpp; |
| 3991 |
} |
} |
| 4410 |
} |
} |
| 4411 |
|
|
| 4412 |
r_type = ELF32_R_TYPE (rel->r_info); |
r_type = ELF32_R_TYPE (rel->r_info); |
| 4413 |
|
if (!htab->is_vxworks && is_branch_reloc (r_type)) |
| 4414 |
|
{ |
| 4415 |
|
struct plt_entry **ifunc = NULL; |
| 4416 |
|
if (h != NULL) |
| 4417 |
|
{ |
| 4418 |
|
if (h->type == STT_GNU_IFUNC) |
| 4419 |
|
ifunc = &h->plt.plist; |
| 4420 |
|
} |
| 4421 |
|
else if (local_got_refcounts != NULL) |
| 4422 |
|
{ |
| 4423 |
|
struct plt_entry **local_plt = (struct plt_entry **) |
| 4424 |
|
(local_got_refcounts + symtab_hdr->sh_info); |
| 4425 |
|
char *local_got_tls_masks = (char *) |
| 4426 |
|
(local_plt + symtab_hdr->sh_info); |
| 4427 |
|
if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0) |
| 4428 |
|
ifunc = local_plt + r_symndx; |
| 4429 |
|
} |
| 4430 |
|
if (ifunc != NULL) |
| 4431 |
|
{ |
| 4432 |
|
bfd_vma addend = r_type == R_PPC_PLTREL24 ? rel->r_addend : 0; |
| 4433 |
|
struct plt_entry *ent = find_plt_ent (ifunc, got2, addend); |
| 4434 |
|
if (ent->plt.refcount > 0) |
| 4435 |
|
ent->plt.refcount -= 1; |
| 4436 |
|
continue; |
| 4437 |
|
} |
| 4438 |
|
} |
| 4439 |
|
|
| 4440 |
switch (r_type) |
switch (r_type) |
| 4441 |
{ |
{ |
| 4442 |
case R_PPC_GOT_TLSLD16: |
case R_PPC_GOT_TLSLD16: |
| 4503 |
if (h != NULL) |
if (h != NULL) |
| 4504 |
{ |
{ |
| 4505 |
bfd_vma addend = r_type == R_PPC_PLTREL24 ? rel->r_addend : 0; |
bfd_vma addend = r_type == R_PPC_PLTREL24 ? rel->r_addend : 0; |
| 4506 |
struct plt_entry *ent = find_plt_ent (h, got2, addend); |
struct plt_entry *ent = find_plt_ent (&h->plt.plist, |
| 4507 |
|
got2, addend); |
| 4508 |
if (ent->plt.refcount > 0) |
if (ent->plt.refcount > 0) |
| 4509 |
ent->plt.refcount -= 1; |
ent->plt.refcount -= 1; |
| 4510 |
} |
} |
| 4517 |
return TRUE; |
return TRUE; |
| 4518 |
} |
} |
| 4519 |
|
|
| 4520 |
/* Set htab->tls_get_addr and call the generic ELF tls_setup function. */ |
/* Set plt output section type, htab->tls_get_addr, and call the |
| 4521 |
|
generic ELF tls_setup function. */ |
| 4522 |
|
|
| 4523 |
asection * |
asection * |
| 4524 |
ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) |
ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info) |
| 4539 |
return _bfd_elf_tls_setup (obfd, info); |
return _bfd_elf_tls_setup (obfd, info); |
| 4540 |
} |
} |
| 4541 |
|
|
| 4542 |
|
/* Return TRUE iff REL is a branch reloc with a global symbol matching |
| 4543 |
|
HASH. */ |
| 4544 |
|
|
| 4545 |
|
static bfd_boolean |
| 4546 |
|
branch_reloc_hash_match (const bfd *ibfd, |
| 4547 |
|
const Elf_Internal_Rela *rel, |
| 4548 |
|
const struct elf_link_hash_entry *hash) |
| 4549 |
|
{ |
| 4550 |
|
Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (ibfd); |
| 4551 |
|
enum elf_ppc_reloc_type r_type = ELF32_R_TYPE (rel->r_info); |
| 4552 |
|
unsigned int r_symndx = ELF32_R_SYM (rel->r_info); |
| 4553 |
|
|
| 4554 |
|
if (r_symndx >= symtab_hdr->sh_info && is_branch_reloc (r_type)) |
| 4555 |
|
{ |
| 4556 |
|
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd); |
| 4557 |
|
struct elf_link_hash_entry *h; |
| 4558 |
|
|
| 4559 |
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
| 4560 |
|
while (h->root.type == bfd_link_hash_indirect |
| 4561 |
|
|| h->root.type == bfd_link_hash_warning) |
| 4562 |
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
| 4563 |
|
if (h == hash) |
| 4564 |
|
return TRUE; |
| 4565 |
|
} |
| 4566 |
|
return FALSE; |
| 4567 |
|
} |
| 4568 |
|
|
| 4569 |
/* Run through all the TLS relocs looking for optimization |
/* Run through all the TLS relocs looking for optimization |
| 4570 |
opportunities. */ |
opportunities. */ |
| 4571 |
|
|
| 4690 |
|
|
| 4691 |
if (pass == 0) |
if (pass == 0) |
| 4692 |
{ |
{ |
| 4693 |
if (!expecting_tls_get_addr) |
if (!expecting_tls_get_addr |
| 4694 |
|
|| !sec->has_tls_get_addr_call) |
| 4695 |
continue; |
continue; |
| 4696 |
|
|
| 4697 |
if (rel + 1 < relend) |
if (rel + 1 < relend |
| 4698 |
{ |
&& branch_reloc_hash_match (ibfd, rel + 1, |
| 4699 |
enum elf_ppc_reloc_type r_type2; |
htab->tls_get_addr)) |
| 4700 |
unsigned long r_symndx2; |
continue; |
|
struct elf_link_hash_entry *h2; |
|
|
|
|
|
/* The next instruction should be a call to |
|
|
__tls_get_addr. Peek at the reloc to be sure. */ |
|
|
r_type2 = ELF32_R_TYPE (rel[1].r_info); |
|
|
r_symndx2 = ELF32_R_SYM (rel[1].r_info); |
|
|
if (r_symndx2 >= symtab_hdr->sh_info |
|
|
&& (r_type2 == R_PPC_REL14 |
|
|
|| r_type2 == R_PPC_REL14_BRTAKEN |
|
|
|| r_type2 == R_PPC_REL14_BRNTAKEN |
|
|
|| r_type2 == R_PPC_REL24 |
|
|
|| r_type2 == R_PPC_PLTREL24)) |
|
|
{ |
|
|
struct elf_link_hash_entry **sym_hashes; |
|
|
|
|
|
sym_hashes = elf_sym_hashes (ibfd); |
|
|
h2 = sym_hashes[r_symndx2 - symtab_hdr->sh_info]; |
|
|
while (h2->root.type == bfd_link_hash_indirect |
|
|
|| h2->root.type == bfd_link_hash_warning) |
|
|
h2 = ((struct elf_link_hash_entry *) |
|
|
h2->root.u.i.link); |
|
|
if (h2 == htab->tls_get_addr) |
|
|
continue; |
|
|
} |
|
|
} |
|
| 4701 |
|
|
| 4702 |
/* Uh oh, we didn't find the expected call. We |
/* Uh oh, we didn't find the expected call. We |
| 4703 |
could just mark this symbol to exclude it |
could just mark this symbol to exclude it |
| 4716 |
{ |
{ |
| 4717 |
Elf_Internal_Sym *sym; |
Elf_Internal_Sym *sym; |
| 4718 |
bfd_signed_vma *lgot_refs; |
bfd_signed_vma *lgot_refs; |
| 4719 |
|
struct plt_entry **local_plt; |
| 4720 |
char *lgot_masks; |
char *lgot_masks; |
| 4721 |
|
|
| 4722 |
if (locsyms == NULL) |
if (locsyms == NULL) |
| 4737 |
lgot_refs = elf_local_got_refcounts (ibfd); |
lgot_refs = elf_local_got_refcounts (ibfd); |
| 4738 |
if (lgot_refs == NULL) |
if (lgot_refs == NULL) |
| 4739 |
abort (); |
abort (); |
| 4740 |
lgot_masks = (char *) (lgot_refs + symtab_hdr->sh_info); |
local_plt = (struct plt_entry **) |
| 4741 |
|
(lgot_refs + symtab_hdr->sh_info); |
| 4742 |
|
lgot_masks = (char *) (local_plt + symtab_hdr->sh_info); |
| 4743 |
tls_mask = &lgot_masks[r_symndx]; |
tls_mask = &lgot_masks[r_symndx]; |
| 4744 |
got_count = &lgot_refs[r_symndx]; |
got_count = &lgot_refs[r_symndx]; |
| 4745 |
} |
} |
| 4755 |
{ |
{ |
| 4756 |
struct plt_entry *ent; |
struct plt_entry *ent; |
| 4757 |
|
|
| 4758 |
ent = find_plt_ent (htab->tls_get_addr, NULL, 0); |
ent = find_plt_ent (&htab->tls_get_addr->plt.plist, |
| 4759 |
|
NULL, 0); |
| 4760 |
if (ent != NULL && ent->plt.refcount > 0) |
if (ent != NULL && ent->plt.refcount > 0) |
| 4761 |
ent->plt.refcount -= 1; |
ent->plt.refcount -= 1; |
| 4762 |
} |
} |
| 4829 |
|
|
| 4830 |
/* Deal with function syms. */ |
/* Deal with function syms. */ |
| 4831 |
if (h->type == STT_FUNC |
if (h->type == STT_FUNC |
| 4832 |
|
|| h->type == STT_GNU_IFUNC |
| 4833 |
|| h->needs_plt) |
|| h->needs_plt) |
| 4834 |
{ |
{ |
| 4835 |
/* Clear procedure linkage table information for any symbol that |
/* Clear procedure linkage table information for any symbol that |
| 4839 |
if (ent->plt.refcount > 0) |
if (ent->plt.refcount > 0) |
| 4840 |
break; |
break; |
| 4841 |
if (ent == NULL |
if (ent == NULL |
| 4842 |
|| SYMBOL_CALLS_LOCAL (info, h) |
|| (h->type != STT_GNU_IFUNC |
| 4843 |
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
&& (SYMBOL_CALLS_LOCAL (info, h) |
| 4844 |
&& h->root.type == bfd_link_hash_undefweak)) |
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
| 4845 |
|
&& h->root.type == bfd_link_hash_undefweak)))) |
| 4846 |
{ |
{ |
| 4847 |
/* A PLT entry is not required/allowed when: |
/* A PLT entry is not required/allowed when: |
| 4848 |
|
|
| 5078 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
| 5079 |
|
|
| 5080 |
htab = ppc_elf_hash_table (info); |
htab = ppc_elf_hash_table (info); |
| 5081 |
if (htab->elf.dynamic_sections_created) |
if (htab->elf.dynamic_sections_created |
| 5082 |
|
|| h->type == STT_GNU_IFUNC) |
| 5083 |
{ |
{ |
| 5084 |
struct plt_entry *ent; |
struct plt_entry *ent; |
| 5085 |
bfd_boolean doneone = FALSE; |
bfd_boolean doneone = FALSE; |
| 5086 |
bfd_vma plt_offset = 0, glink_offset = 0; |
bfd_vma plt_offset = 0, glink_offset = 0; |
| 5087 |
|
bfd_boolean dyn; |
| 5088 |
|
|
| 5089 |
for (ent = h->plt.plist; ent != NULL; ent = ent->next) |
for (ent = h->plt.plist; ent != NULL; ent = ent->next) |
| 5090 |
if (ent->plt.refcount > 0) |
if (ent->plt.refcount > 0) |
| 5091 |
{ |
{ |
| 5092 |
/* Make sure this symbol is output as a dynamic symbol. */ |
/* Make sure this symbol is output as a dynamic symbol. */ |
| 5093 |
if (h->dynindx == -1 |
if (h->dynindx == -1 |
| 5094 |
&& !h->forced_local) |
&& !h->forced_local |
| 5095 |
|
&& !h->def_regular |
| 5096 |
|
&& htab->elf.dynamic_sections_created) |
| 5097 |
{ |
{ |
| 5098 |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
| 5099 |
return FALSE; |
return FALSE; |
| 5100 |
} |
} |
| 5101 |
|
|
| 5102 |
|
dyn = htab->elf.dynamic_sections_created; |
| 5103 |
if (info->shared |
if (info->shared |
| 5104 |
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) |
|| h->type == STT_GNU_IFUNC |
| 5105 |
|
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)) |
| 5106 |
{ |
{ |
| 5107 |
asection *s = htab->plt; |
asection *s = htab->plt; |
| 5108 |
|
if (!dyn) |
| 5109 |
|
s = htab->iplt; |
| 5110 |
|
|
| 5111 |
if (htab->plt_type == PLT_NEW) |
if (htab->plt_type == PLT_NEW || !dyn) |
| 5112 |
{ |
{ |
| 5113 |
if (!doneone) |
if (!doneone) |
| 5114 |
{ |
{ |
| 5186 |
/* We also need to make an entry in the .rela.plt section. */ |
/* We also need to make an entry in the .rela.plt section. */ |
| 5187 |
if (!doneone) |
if (!doneone) |
| 5188 |
{ |
{ |
| 5189 |
htab->relplt->size += sizeof (Elf32_External_Rela); |
if (!htab->elf.dynamic_sections_created) |
| 5190 |
|
htab->reliplt->size += sizeof (Elf32_External_Rela); |
| 5191 |
if (htab->plt_type == PLT_VXWORKS) |
else |
| 5192 |
{ |
{ |
| 5193 |
/* Allocate space for the unloaded relocations. */ |
htab->relplt->size += sizeof (Elf32_External_Rela); |
| 5194 |
if (!info->shared) |
|
| 5195 |
|
if (htab->plt_type == PLT_VXWORKS) |
| 5196 |
{ |
{ |
| 5197 |
if (ent->plt.offset |
/* Allocate space for the unloaded relocations. */ |
| 5198 |
== (bfd_vma) htab->plt_initial_entry_size) |
if (!info->shared |
| 5199 |
|
&& htab->elf.dynamic_sections_created) |
| 5200 |
{ |
{ |
| 5201 |
|
if (ent->plt.offset |
| 5202 |
|
== (bfd_vma) htab->plt_initial_entry_size) |
| 5203 |
|
{ |
| 5204 |
|
htab->srelplt2->size |
| 5205 |
|
+= (sizeof (Elf32_External_Rela) |
| 5206 |
|
* VXWORKS_PLTRESOLVE_RELOCS); |
| 5207 |
|
} |
| 5208 |
|
|
| 5209 |
htab->srelplt2->size |
htab->srelplt2->size |
| 5210 |
+= sizeof (Elf32_External_Rela) |
+= (sizeof (Elf32_External_Rela) |
| 5211 |
* VXWORKS_PLTRESOLVE_RELOCS; |
* VXWORKS_PLT_NON_JMP_SLOT_RELOCS); |
| 5212 |
} |
} |
| 5213 |
|
|
| 5214 |
htab->srelplt2->size |
/* Every PLT entry has an associated GOT entry in |
| 5215 |
+= sizeof (Elf32_External_Rela) |
.got.plt. */ |
| 5216 |
* VXWORKS_PLT_NON_JMP_SLOT_RELOCS; |
htab->sgotplt->size += 4; |
| 5217 |
} |
} |
|
|
|
|
/* Every PLT entry has an associated GOT entry in |
|
|
.got.plt. */ |
|
|
htab->sgotplt->size += 4; |
|
| 5218 |
} |
} |
| 5219 |
doneone = TRUE; |
doneone = TRUE; |
| 5220 |
} |
} |
| 5246 |
/* Make sure this symbol is output as a dynamic symbol. */ |
/* Make sure this symbol is output as a dynamic symbol. */ |
| 5247 |
if (eh->elf.dynindx == -1 |
if (eh->elf.dynindx == -1 |
| 5248 |
&& !eh->elf.forced_local |
&& !eh->elf.forced_local |
| 5249 |
|
&& !eh->elf.def_regular |
| 5250 |
&& htab->elf.dynamic_sections_created) |
&& htab->elf.dynamic_sections_created) |
| 5251 |
{ |
{ |
| 5252 |
if (!bfd_elf_link_record_dynamic_symbol (info, &eh->elf)) |
if (!bfd_elf_link_record_dynamic_symbol (info, &eh->elf)) |
| 5362 |
/* Make sure undefined weak symbols are output as a dynamic |
/* Make sure undefined weak symbols are output as a dynamic |
| 5363 |
symbol in PIEs. */ |
symbol in PIEs. */ |
| 5364 |
else if (h->dynindx == -1 |
else if (h->dynindx == -1 |
| 5365 |
&& !h->forced_local) |
&& !h->forced_local |
| 5366 |
|
&& !h->def_regular) |
| 5367 |
{ |
{ |
| 5368 |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
| 5369 |
return FALSE; |
return FALSE; |
| 5382 |
/* Make sure this symbol is output as a dynamic symbol. |
/* Make sure this symbol is output as a dynamic symbol. |
| 5383 |
Undefined weak syms won't yet be marked as dynamic. */ |
Undefined weak syms won't yet be marked as dynamic. */ |
| 5384 |
if (h->dynindx == -1 |
if (h->dynindx == -1 |
| 5385 |
&& !h->forced_local) |
&& !h->forced_local |
| 5386 |
|
&& !h->def_regular) |
| 5387 |
{ |
{ |
| 5388 |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
| 5389 |
return FALSE; |
return FALSE; |
| 5473 |
{ |
{ |
| 5474 |
bfd_signed_vma *local_got; |
bfd_signed_vma *local_got; |
| 5475 |
bfd_signed_vma *end_local_got; |
bfd_signed_vma *end_local_got; |
| 5476 |
|
struct plt_entry **local_plt; |
| 5477 |
|
struct plt_entry **end_local_plt; |
| 5478 |
char *lgot_masks; |
char *lgot_masks; |
| 5479 |
bfd_size_type locsymcount; |
bfd_size_type locsymcount; |
| 5480 |
Elf_Internal_Shdr *symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
| 5525 |
symtab_hdr = &elf_symtab_hdr (ibfd); |
symtab_hdr = &elf_symtab_hdr (ibfd); |
| 5526 |
locsymcount = symtab_hdr->sh_info; |
locsymcount = symtab_hdr->sh_info; |
| 5527 |
end_local_got = local_got + locsymcount; |
end_local_got = local_got + locsymcount; |
| 5528 |
lgot_masks = (char *) end_local_got; |
local_plt = (struct plt_entry **) end_local_got; |
| 5529 |
|
end_local_plt = local_plt + locsymcount; |
| 5530 |
|
lgot_masks = (char *) end_local_plt; |
| 5531 |
for (; local_got < end_local_got; ++local_got, ++lgot_masks) |
for (; local_got < end_local_got; ++local_got, ++lgot_masks) |
| 5532 |
if (*local_got > 0) |
if (*local_got > 0) |
| 5533 |
{ |
{ |
| 5557 |
} |
} |
| 5558 |
else |
else |
| 5559 |
*local_got = (bfd_vma) -1; |
*local_got = (bfd_vma) -1; |
| 5560 |
|
|
| 5561 |
|
if (htab->is_vxworks) |
| 5562 |
|
continue; |
| 5563 |
|
|
| 5564 |
|
/* Allocate space for calls to local STT_GNU_IFUNC syms in .iplt. */ |
| 5565 |
|
for (; local_plt < end_local_plt; ++local_plt) |
| 5566 |
|
{ |
| 5567 |
|
struct plt_entry *ent; |
| 5568 |
|
bfd_boolean doneone = FALSE; |
| 5569 |
|
bfd_vma plt_offset = 0, glink_offset = 0; |
| 5570 |
|
|
| 5571 |
|
for (ent = *local_plt; ent != NULL; ent = ent->next) |
| 5572 |
|
if (ent->plt.refcount > 0) |
| 5573 |
|
{ |
| 5574 |
|
asection *s = htab->iplt; |
| 5575 |
|
|
| 5576 |
|
if (!doneone) |
| 5577 |
|
{ |
| 5578 |
|
plt_offset = s->size; |
| 5579 |
|
s->size += 4; |
| 5580 |
|
} |
| 5581 |
|
ent->plt.offset = plt_offset; |
| 5582 |
|
|
| 5583 |
|
s = htab->glink; |
| 5584 |
|
if (!doneone || info->shared || info->pie) |
| 5585 |
|
{ |
| 5586 |
|
glink_offset = s->size; |
| 5587 |
|
s->size += GLINK_ENTRY_SIZE; |
| 5588 |
|
} |
| 5589 |
|
ent->glink_offset = glink_offset; |
| 5590 |
|
|
| 5591 |
|
if (!doneone) |
| 5592 |
|
{ |
| 5593 |
|
htab->reliplt += sizeof (Elf32_External_Rela); |
| 5594 |
|
doneone = TRUE; |
| 5595 |
|
} |
| 5596 |
|
} |
| 5597 |
|
else |
| 5598 |
|
ent->plt.offset = (bfd_vma) -1; |
| 5599 |
|
} |
| 5600 |
} |
} |
| 5601 |
|
|
| 5602 |
/* Allocate space for global sym dynamic relocs. */ |
/* Allocate space for global sym dynamic relocs. */ |
| 5630 |
htab->elf.hgot->root.u.def.value = g_o_t; |
htab->elf.hgot->root.u.def.value = g_o_t; |
| 5631 |
} |
} |
| 5632 |
|
|
| 5633 |
if (htab->glink != NULL && htab->glink->size != 0) |
if (htab->glink != NULL |
| 5634 |
|
&& htab->glink->size != 0 |
| 5635 |
|
&& htab->elf.dynamic_sections_created) |
| 5636 |
{ |
{ |
| 5637 |
htab->glink_pltresolve = htab->glink->size; |
htab->glink_pltresolve = htab->glink->size; |
| 5638 |
/* Space for the branch table. */ |
/* Space for the branch table. */ |
| 5688 |
continue; |
continue; |
| 5689 |
|
|
| 5690 |
if (s == htab->plt |
if (s == htab->plt |
| 5691 |
|| s == htab->glink |
|| s == htab->got) |
|
|| s == htab->got |
|
|
|| s == htab->sgotplt |
|
|
|| s == htab->sbss |
|
|
|| s == htab->dynbss |
|
|
|| s == htab->dynsbss) |
|
| 5692 |
{ |
{ |
| 5693 |
/* We'd like to strip these sections if they aren't needed, but if |
/* We'd like to strip these sections if they aren't needed, but if |
| 5694 |
we've exported dynamic symbols from them we must leave them. |
we've exported dynamic symbols from them we must leave them. |
| 5695 |
It's too late to tell BFD to get rid of the symbols. */ |
It's too late to tell BFD to get rid of the symbols. */ |
| 5696 |
if ((s == htab->plt || s == htab->got) && htab->elf.hplt != NULL) |
if (htab->elf.hplt != NULL) |
| 5697 |
strip_section = FALSE; |
strip_section = FALSE; |
| 5698 |
/* Strip this section if we don't need it; see the |
/* Strip this section if we don't need it; see the |
| 5699 |
comment below. */ |
comment below. */ |
| 5700 |
} |
} |
| 5701 |
else if (s == htab->sdata[0].section |
else if (s == htab->iplt |
| 5702 |
|
|| s == htab->glink |
| 5703 |
|
|| s == htab->sgotplt |
| 5704 |
|
|| s == htab->sbss |
| 5705 |
|
|| s == htab->dynbss |
| 5706 |
|
|| s == htab->dynsbss |
| 5707 |
|
|| s == htab->sdata[0].section |
| 5708 |
|| s == htab->sdata[1].section) |
|| s == htab->sdata[1].section) |
| 5709 |
{ |
{ |
| 5710 |
/* Strip these too. */ |
/* Strip these too. */ |
| 5866 |
Elf_Internal_Rela *internal_relocs = NULL; |
Elf_Internal_Rela *internal_relocs = NULL; |
| 5867 |
Elf_Internal_Rela *irel, *irelend; |
Elf_Internal_Rela *irel, *irelend; |
| 5868 |
struct one_fixup *fixups = NULL; |
struct one_fixup *fixups = NULL; |
| 5869 |
bfd_boolean changed; |
unsigned changes = 0; |
| 5870 |
struct ppc_elf_link_hash_table *htab; |
struct ppc_elf_link_hash_table *htab; |
| 5871 |
bfd_size_type trampoff; |
bfd_size_type trampoff; |
| 5872 |
asection *got2; |
asection *got2; |
| 5880 |
|| isec->reloc_count == 0) |
|| isec->reloc_count == 0) |
| 5881 |
return TRUE; |
return TRUE; |
| 5882 |
|
|
| 5883 |
|
/* We cannot represent the required PIC relocs in the output, so don't |
| 5884 |
|
do anything. The linker doesn't support mixing -shared and -r |
| 5885 |
|
anyway. */ |
| 5886 |
|
if (link_info->relocatable && link_info->shared) |
| 5887 |
|
return TRUE; |
| 5888 |
|
|
| 5889 |
trampoff = (isec->size + 3) & (bfd_vma) -4; |
trampoff = (isec->size + 3) & (bfd_vma) -4; |
| 5890 |
/* Space for a branch around any trampolines. */ |
/* Space for a branch around any trampolines. */ |
| 5891 |
trampoff += 4; |
trampoff += 4; |
| 5951 |
} |
} |
| 5952 |
isym = isymbuf + ELF32_R_SYM (irel->r_info); |
isym = isymbuf + ELF32_R_SYM (irel->r_info); |
| 5953 |
if (isym->st_shndx == SHN_UNDEF) |
if (isym->st_shndx == SHN_UNDEF) |
| 5954 |
continue; /* We can't do anything with undefined symbols. */ |
tsec = bfd_und_section_ptr; |
| 5955 |
else if (isym->st_shndx == SHN_ABS) |
else if (isym->st_shndx == SHN_ABS) |
| 5956 |
tsec = bfd_abs_section_ptr; |
tsec = bfd_abs_section_ptr; |
| 5957 |
else if (isym->st_shndx == SHN_COMMON) |
else if (isym->st_shndx == SHN_COMMON) |
| 5980 |
if (r_type == R_PPC_PLTREL24 |
if (r_type == R_PPC_PLTREL24 |
| 5981 |
&& htab->plt != NULL) |
&& htab->plt != NULL) |
| 5982 |
{ |
{ |
| 5983 |
struct plt_entry *ent = find_plt_ent (h, got2, irel->r_addend); |
struct plt_entry *ent = find_plt_ent (&h->plt.plist, |
| 5984 |
|
got2, irel->r_addend); |
| 5985 |
|
|
| 5986 |
if (ent != NULL) |
if (ent != NULL) |
| 5987 |
{ |
{ |
| 6005 |
tsec = h->root.u.def.section; |
tsec = h->root.u.def.section; |
| 6006 |
toff = h->root.u.def.value; |
toff = h->root.u.def.value; |
| 6007 |
} |
} |
| 6008 |
|
else if (h->root.type == bfd_link_hash_undefined |
| 6009 |
|
|| h->root.type == bfd_link_hash_undefweak) |
| 6010 |
|
{ |
| 6011 |
|
tsec = bfd_und_section_ptr; |
| 6012 |
|
toff = 0; |
| 6013 |
|
} |
| 6014 |
else |
else |
| 6015 |
continue; |
continue; |
| 6016 |
|
|
| 6070 |
reladdr = isec->output_section->vma + isec->output_offset + roff; |
reladdr = isec->output_section->vma + isec->output_offset + roff; |
| 6071 |
|
|
| 6072 |
/* If the branch is in range, no need to do anything. */ |
/* If the branch is in range, no need to do anything. */ |
| 6073 |
if (symaddr - reladdr + max_branch_offset < 2 * max_branch_offset) |
if (tsec != bfd_und_section_ptr |
| 6074 |
|
&& (!link_info->relocatable |
| 6075 |
|
/* A relocatable link may have sections moved during |
| 6076 |
|
final link, so do not presume they remain in range. */ |
| 6077 |
|
|| tsec->output_section == isec->output_section) |
| 6078 |
|
&& symaddr - reladdr + max_branch_offset < 2 * max_branch_offset) |
| 6079 |
continue; |
continue; |
| 6080 |
|
|
| 6081 |
/* Look for an existing fixup to this address. */ |
/* Look for an existing fixup to this address. */ |
| 6131 |
fixups = f; |
fixups = f; |
| 6132 |
|
|
| 6133 |
trampoff += size; |
trampoff += size; |
| 6134 |
|
changes++; |
| 6135 |
} |
} |
| 6136 |
else |
else |
| 6137 |
{ |
{ |
| 6182 |
} |
} |
| 6183 |
|
|
| 6184 |
/* Write out the trampolines. */ |
/* Write out the trampolines. */ |
|
changed = fixups != NULL; |
|
| 6185 |
if (fixups != NULL) |
if (fixups != NULL) |
| 6186 |
{ |
{ |
| 6187 |
const int *stub; |
const int *stub; |
| 6247 |
if (contents != NULL |
if (contents != NULL |
| 6248 |
&& elf_section_data (isec)->this_hdr.contents != contents) |
&& elf_section_data (isec)->this_hdr.contents != contents) |
| 6249 |
{ |
{ |
| 6250 |
if (!changed && !link_info->keep_memory) |
if (!changes && !link_info->keep_memory) |
| 6251 |
free (contents); |
free (contents); |
| 6252 |
else |
else |
| 6253 |
{ |
{ |
| 6256 |
} |
} |
| 6257 |
} |
} |
| 6258 |
|
|
| 6259 |
if (elf_section_data (isec)->relocs != internal_relocs) |
if (changes != 0) |
| 6260 |
{ |
{ |
| 6261 |
if (!changed) |
/* Append sufficient NOP relocs so we can write out relocation |
| 6262 |
|
information for the trampolines. */ |
| 6263 |
|
Elf_Internal_Rela *new_relocs = bfd_malloc ((changes + isec->reloc_count) |
| 6264 |
|
* sizeof (*new_relocs)); |
| 6265 |
|
unsigned ix; |
| 6266 |
|
|
| 6267 |
|
if (!new_relocs) |
| 6268 |
|
goto error_return; |
| 6269 |
|
memcpy (new_relocs, internal_relocs, |
| 6270 |
|
isec->reloc_count * sizeof (*new_relocs)); |
| 6271 |
|
for (ix = changes; ix--;) |
| 6272 |
|
{ |
| 6273 |
|
irel = new_relocs + ix + isec->reloc_count; |
| 6274 |
|
|
| 6275 |
|
irel->r_info = ELF32_R_INFO (0, R_PPC_NONE); |
| 6276 |
|
} |
| 6277 |
|
if (internal_relocs != elf_section_data (isec)->relocs) |
| 6278 |
free (internal_relocs); |
free (internal_relocs); |
| 6279 |
else |
elf_section_data (isec)->relocs = new_relocs; |
| 6280 |
elf_section_data (isec)->relocs = internal_relocs; |
isec->reloc_count += changes; |
| 6281 |
|
elf_section_data (isec)->rel_hdr.sh_size |
| 6282 |
|
+= changes * elf_section_data (isec)->rel_hdr.sh_entsize; |
| 6283 |
} |
} |
| 6284 |
|
else if (elf_section_data (isec)->relocs != internal_relocs) |
| 6285 |
|
free (internal_relocs); |
| 6286 |
|
|
| 6287 |
*again = changed; |
*again = changes != 0; |
| 6288 |
|
if (!*again && link_info->relocatable) |
| 6289 |
|
{ |
| 6290 |
|
/* Convert the internal relax relocs to external form. */ |
| 6291 |
|
for (irel = internal_relocs; irel < irelend; irel++) |
| 6292 |
|
if (ELF32_R_TYPE (irel->r_info) == R_PPC_RELAX32) |
| 6293 |
|
{ |
| 6294 |
|
unsigned long r_symndx = ELF32_R_SYM (irel->r_info); |
| 6295 |
|
|
| 6296 |
|
/* Rewrite the reloc and convert one of the trailing nop |
| 6297 |
|
relocs to describe this relocation. */ |
| 6298 |
|
BFD_ASSERT (ELF32_R_TYPE (irelend[-1].r_info) == R_PPC_NONE); |
| 6299 |
|
/* The relocs are at the bottom 2 bytes */ |
| 6300 |
|
irel[0].r_offset += 2; |
| 6301 |
|
memmove (irel + 1, irel, (irelend - irel - 1) * sizeof (*irel)); |
| 6302 |
|
irel[0].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA); |
| 6303 |
|
irel[1].r_offset += 4; |
| 6304 |
|
irel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO); |
| 6305 |
|
irel++; |
| 6306 |
|
} |
| 6307 |
|
} |
| 6308 |
|
|
| 6309 |
return TRUE; |
return TRUE; |
| 6310 |
|
|
| 6311 |
error_return: |
error_return: |
| 6397 |
return relocation - linker_section_ptr->addend; |
return relocation - linker_section_ptr->addend; |
| 6398 |
} |
} |
| 6399 |
|
|
| 6400 |
|
#define PPC_LO(v) ((v) & 0xffff) |
| 6401 |
|
#define PPC_HI(v) (((v) >> 16) & 0xffff) |
| 6402 |
|
#define PPC_HA(v) PPC_HI ((v) + 0x8000) |
| 6403 |
|
|
| 6404 |
|
static void |
| 6405 |
|
write_glink_stub (struct plt_entry *ent, asection *plt_sec, |
| 6406 |
|
struct bfd_link_info *info) |
| 6407 |
|
{ |
| 6408 |
|
struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info); |
| 6409 |
|
bfd *output_bfd = info->output_bfd; |
| 6410 |
|
bfd_vma plt; |
| 6411 |
|
unsigned char *p; |
| 6412 |
|
|
| 6413 |
|
plt = ((ent->plt.offset & ~1) |
| 6414 |
|
+ plt_sec->output_section->vma |
| 6415 |
|
+ plt_sec->output_offset); |
| 6416 |
|
p = (unsigned char *) htab->glink->contents + ent->glink_offset; |
| 6417 |
|
|
| 6418 |
|
if (info->shared || info->pie) |
| 6419 |
|
{ |
| 6420 |
|
bfd_vma got = 0; |
| 6421 |
|
|
| 6422 |
|
if (ent->addend >= 32768) |
| 6423 |
|
got = (ent->addend |
| 6424 |
|
+ ent->sec->output_section->vma |
| 6425 |
|
+ ent->sec->output_offset); |
| 6426 |
|
else if (htab->elf.hgot != NULL) |
| 6427 |
|
got = SYM_VAL (htab->elf.hgot); |
| 6428 |
|
|
| 6429 |
|
plt -= got; |
| 6430 |
|
|
| 6431 |
|
if (plt + 0x8000 < 0x10000) |
| 6432 |
|
{ |
| 6433 |
|
bfd_put_32 (output_bfd, LWZ_11_30 + PPC_LO (plt), p); |
| 6434 |
|
p += 4; |
| 6435 |
|
bfd_put_32 (output_bfd, MTCTR_11, p); |
| 6436 |
|
p += 4; |
| 6437 |
|
bfd_put_32 (output_bfd, BCTR, p); |
| 6438 |
|
p += 4; |
| 6439 |
|
bfd_put_32 (output_bfd, NOP, p); |
| 6440 |
|
p += 4; |
| 6441 |
|
} |
| 6442 |
|
else |
| 6443 |
|
{ |
| 6444 |
|
bfd_put_32 (output_bfd, ADDIS_11_30 + PPC_HA (plt), p); |
| 6445 |
|
p += 4; |
| 6446 |
|
bfd_put_32 (output_bfd, LWZ_11_11 + PPC_LO (plt), p); |
| 6447 |
|
p += 4; |
| 6448 |
|
bfd_put_32 (output_bfd, MTCTR_11, p); |
| 6449 |
|
p += 4; |
| 6450 |
|
bfd_put_32 (output_bfd, BCTR, p); |
| 6451 |
|
p += 4; |
| 6452 |
|
} |
| 6453 |
|
} |
| 6454 |
|
else |
| 6455 |
|
{ |
| 6456 |
|
bfd_put_32 (output_bfd, LIS_11 + PPC_HA (plt), p); |
| 6457 |
|
p += 4; |
| 6458 |
|
bfd_put_32 (output_bfd, LWZ_11_11 + PPC_LO (plt), p); |
| 6459 |
|
p += 4; |
| 6460 |
|
bfd_put_32 (output_bfd, MTCTR_11, p); |
| 6461 |
|
p += 4; |
| 6462 |
|
bfd_put_32 (output_bfd, BCTR, p); |
| 6463 |
|
p += 4; |
| 6464 |
|
} |
| 6465 |
|
} |
| 6466 |
|
|
| 6467 |
/* The RELOCATE_SECTION function is called by the ELF backend linker |
/* The RELOCATE_SECTION function is called by the ELF backend linker |
| 6468 |
to handle the relocations for a section. |
to handle the relocations for a section. |
| 6469 |
|
|
| 6557 |
bfd_boolean unresolved_reloc; |
bfd_boolean unresolved_reloc; |
| 6558 |
bfd_boolean warned; |
bfd_boolean warned; |
| 6559 |
unsigned int tls_type, tls_mask, tls_gd; |
unsigned int tls_type, tls_mask, tls_gd; |
| 6560 |
|
struct plt_entry **ifunc; |
| 6561 |
|
|
| 6562 |
r_type = ELF32_R_TYPE (rel->r_info); |
r_type = ELF32_R_TYPE (rel->r_info); |
| 6563 |
sym = NULL; |
sym = NULL; |
| 6618 |
for the final instruction stream. */ |
for the final instruction stream. */ |
| 6619 |
tls_mask = 0; |
tls_mask = 0; |
| 6620 |
tls_gd = 0; |
tls_gd = 0; |
| 6621 |
if (IS_PPC_TLS_RELOC (r_type)) |
if (h != NULL) |
| 6622 |
{ |
tls_mask = ((struct ppc_elf_link_hash_entry *) h)->tls_mask; |
| 6623 |
if (h != NULL) |
else if (local_got_offsets != NULL) |
| 6624 |
tls_mask = ((struct ppc_elf_link_hash_entry *) h)->tls_mask; |
{ |
| 6625 |
else if (local_got_offsets != NULL) |
struct plt_entry **local_plt; |
| 6626 |
{ |
char *lgot_masks; |
| 6627 |
char *lgot_masks; |
local_plt |
| 6628 |
lgot_masks = (char *) (local_got_offsets + symtab_hdr->sh_info); |
= (struct plt_entry **) (local_got_offsets + symtab_hdr->sh_info); |
| 6629 |
tls_mask = lgot_masks[r_symndx]; |
lgot_masks = (char *) (local_plt + symtab_hdr->sh_info); |
| 6630 |
} |
tls_mask = lgot_masks[r_symndx]; |
| 6631 |
} |
} |
| 6632 |
|
|
| 6633 |
/* Ensure reloc mapping code below stays sane. */ |
/* Ensure reloc mapping code below stays sane. */ |
| 6647 |
|
|
| 6648 |
case R_PPC_GOT_TPREL16: |
case R_PPC_GOT_TPREL16: |
| 6649 |
case R_PPC_GOT_TPREL16_LO: |
case R_PPC_GOT_TPREL16_LO: |
| 6650 |
if (tls_mask != 0 |
if ((tls_mask & TLS_TLS) != 0 |
| 6651 |
&& (tls_mask & TLS_TPREL) == 0) |
&& (tls_mask & TLS_TPREL) == 0) |
| 6652 |
{ |
{ |
| 6653 |
bfd_vma insn; |
bfd_vma insn; |
| 6661 |
break; |
break; |
| 6662 |
|
|
| 6663 |
case R_PPC_TLS: |
case R_PPC_TLS: |
| 6664 |
if (tls_mask != 0 |
if ((tls_mask & TLS_TLS) != 0 |
| 6665 |
&& (tls_mask & TLS_TPREL) == 0) |
&& (tls_mask & TLS_TPREL) == 0) |
| 6666 |
{ |
{ |
| 6667 |
bfd_vma insn, rtra; |
bfd_vma insn, rtra; |
| 6708 |
case R_PPC_GOT_TLSGD16_HI: |
case R_PPC_GOT_TLSGD16_HI: |
| 6709 |
case R_PPC_GOT_TLSGD16_HA: |
case R_PPC_GOT_TLSGD16_HA: |
| 6710 |
tls_gd = TLS_TPRELGD; |
tls_gd = TLS_TPRELGD; |
| 6711 |
if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) |
if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0) |
| 6712 |
goto tls_gdld_hi; |
goto tls_gdld_hi; |
| 6713 |
break; |
break; |
| 6714 |
|
|
| 6715 |
case R_PPC_GOT_TLSLD16_HI: |
case R_PPC_GOT_TLSLD16_HI: |
| 6716 |
case R_PPC_GOT_TLSLD16_HA: |
case R_PPC_GOT_TLSLD16_HA: |
| 6717 |
if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) |
if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0) |
| 6718 |
{ |
{ |
| 6719 |
tls_gdld_hi: |
tls_gdld_hi: |
| 6720 |
if ((tls_mask & tls_gd) != 0) |
if ((tls_mask & tls_gd) != 0) |
| 6733 |
case R_PPC_GOT_TLSGD16: |
case R_PPC_GOT_TLSGD16: |
| 6734 |
case R_PPC_GOT_TLSGD16_LO: |
case R_PPC_GOT_TLSGD16_LO: |
| 6735 |
tls_gd = TLS_TPRELGD; |
tls_gd = TLS_TPRELGD; |
| 6736 |
if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) |
if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0) |
| 6737 |
goto tls_ldgd_opt; |
goto tls_ldgd_opt; |
| 6738 |
break; |
break; |
| 6739 |
|
|
| 6740 |
case R_PPC_GOT_TLSLD16: |
case R_PPC_GOT_TLSLD16: |
| 6741 |
case R_PPC_GOT_TLSLD16_LO: |
case R_PPC_GOT_TLSLD16_LO: |
| 6742 |
if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) |
if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0) |
| 6743 |
{ |
{ |
| 6744 |
bfd_vma insn1, insn2; |
unsigned int insn1, insn2; |
| 6745 |
bfd_vma offset; |
bfd_vma offset; |
| 6746 |
|
|
| 6747 |
tls_ldgd_opt: |
tls_ldgd_opt: |
| 6748 |
offset = rel[1].r_offset; |
offset = (bfd_vma) -1; |
| 6749 |
insn1 = bfd_get_32 (output_bfd, |
/* If not using the newer R_PPC_TLSGD/LD to mark |
| 6750 |
contents + rel->r_offset - d_offset); |
__tls_get_addr calls, we must trust that the call |
| 6751 |
|
stays with its arg setup insns, ie. that the next |
| 6752 |
|
reloc is the __tls_get_addr call associated with |
| 6753 |
|
the current reloc. Edit both insns. */ |
| 6754 |
|
if (input_section->has_tls_get_addr_call |
| 6755 |
|
&& rel + 1 < relend |
| 6756 |
|
&& branch_reloc_hash_match (input_bfd, rel + 1, |
| 6757 |
|
htab->tls_get_addr)) |
| 6758 |
|
offset = rel[1].r_offset; |
| 6759 |
if ((tls_mask & tls_gd) != 0) |
if ((tls_mask & tls_gd) != 0) |
| 6760 |
{ |
{ |
| 6761 |
/* IE */ |
/* IE */ |
| 6762 |
|
insn1 = bfd_get_32 (output_bfd, |
| 6763 |
|
contents + rel->r_offset - d_offset); |
| 6764 |
insn1 &= (1 << 26) - 1; |
insn1 &= (1 << 26) - 1; |
| 6765 |
insn1 |= 32 << 26; /* lwz */ |
insn1 |= 32 << 26; /* lwz */ |
| 6766 |
insn2 = 0x7c631214; /* add 3,3,2 */ |
if (offset != (bfd_vma) -1) |
| 6767 |
rel[1].r_info |
{ |
| 6768 |
= ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info), R_PPC_NONE); |
rel[1].r_info |
| 6769 |
rel[1].r_addend = 0; |
= ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info), |
| 6770 |
|
R_PPC_NONE); |
| 6771 |
|
insn2 = 0x7c631214; /* add 3,3,2 */ |
| 6772 |
|
bfd_put_32 (output_bfd, insn2, contents + offset); |
| 6773 |
|
} |
| 6774 |
r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3) |
r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3) |
| 6775 |
+ R_PPC_GOT_TPREL16); |
+ R_PPC_GOT_TPREL16); |
| 6776 |
rel->r_info = ELF32_R_INFO (r_symndx, r_type); |
rel->r_info = ELF32_R_INFO (r_symndx, r_type); |
| 6779 |
{ |
{ |
| 6780 |
/* LE */ |
/* LE */ |
| 6781 |
insn1 = 0x3c620000; /* addis 3,2,0 */ |
insn1 = 0x3c620000; /* addis 3,2,0 */ |
|
insn2 = 0x38630000; /* addi 3,3,0 */ |
|
| 6782 |
if (tls_gd == 0) |
if (tls_gd == 0) |
| 6783 |
{ |
{ |
| 6784 |
/* Was an LD reloc. */ |
/* Was an LD reloc. */ |
| 6797 |
} |
} |
| 6798 |
r_type = R_PPC_TPREL16_HA; |
r_type = R_PPC_TPREL16_HA; |
| 6799 |
rel->r_info = ELF32_R_INFO (r_symndx, r_type); |
rel->r_info = ELF32_R_INFO (r_symndx, r_type); |
| 6800 |
rel[1].r_info = ELF32_R_INFO (r_symndx, |
if (offset != (bfd_vma) -1) |
| 6801 |
R_PPC_TPREL16_LO); |
{ |
| 6802 |
rel[1].r_offset += d_offset; |
rel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO); |
| 6803 |
rel[1].r_addend = rel->r_addend; |
rel[1].r_offset = offset + d_offset; |
| 6804 |
|
rel[1].r_addend = rel->r_addend; |
| 6805 |
|
insn2 = 0x38630000; /* addi 3,3,0 */ |
| 6806 |
|
bfd_put_32 (output_bfd, insn2, contents + offset); |
| 6807 |
|
} |
| 6808 |
} |
} |
| 6809 |
bfd_put_32 (output_bfd, insn1, |
bfd_put_32 (output_bfd, insn1, |
| 6810 |
contents + rel->r_offset - d_offset); |
contents + rel->r_offset - d_offset); |
|
bfd_put_32 (output_bfd, insn2, contents + offset); |
|
| 6811 |
if (tls_gd == 0) |
if (tls_gd == 0) |
| 6812 |
{ |
{ |
| 6813 |
/* We changed the symbol on an LD reloc. Start over |
/* We changed the symbol on an LD reloc. Start over |
| 6817 |
} |
} |
| 6818 |
} |
} |
| 6819 |
break; |
break; |
| 6820 |
|
|
| 6821 |
|
case R_PPC_TLSGD: |
| 6822 |
|
if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_GD) == 0) |
| 6823 |
|
{ |
| 6824 |
|
unsigned int insn2; |
| 6825 |
|
bfd_vma offset = rel->r_offset; |
| 6826 |
|
|
| 6827 |
|
if ((tls_mask & TLS_TPRELGD) != 0) |
| 6828 |
|
{ |
| 6829 |
|
/* IE */ |
| 6830 |
|
r_type = R_PPC_NONE; |
| 6831 |
|
insn2 = 0x7c631214; /* add 3,3,2 */ |
| 6832 |
|
} |
| 6833 |
|
else |
| 6834 |
|
{ |
| 6835 |
|
/* LE */ |
| 6836 |
|
r_type = R_PPC_TPREL16_LO; |
| 6837 |
|
rel->r_offset += d_offset; |
| 6838 |
|
insn2 = 0x38630000; /* addi 3,3,0 */ |
| 6839 |
|
} |
| 6840 |
|
rel->r_info = ELF32_R_INFO (r_symndx, r_type); |
| 6841 |
|
bfd_put_32 (output_bfd, insn2, contents + offset); |
| 6842 |
|
/* Zap the reloc on the _tls_get_addr call too. */ |
| 6843 |
|
BFD_ASSERT (offset == rel[1].r_offset); |
| 6844 |
|
rel[1].r_info = ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info), |
| 6845 |
|
R_PPC_NONE); |
| 6846 |
|
} |
| 6847 |
|
break; |
| 6848 |
|
|
| 6849 |
|
case R_PPC_TLSLD: |
| 6850 |
|
if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0) |
| 6851 |
|
{ |
| 6852 |
|
unsigned int insn2; |
| 6853 |
|
|
| 6854 |
|
for (r_symndx = 0; |
| 6855 |
|
r_symndx < symtab_hdr->sh_info; |
| 6856 |
|
r_symndx++) |
| 6857 |
|
if (local_sections[r_symndx] == sec) |
| 6858 |
|
break; |
| 6859 |
|
if (r_symndx >= symtab_hdr->sh_info) |
| 6860 |
|
r_symndx = 0; |
| 6861 |
|
rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET; |
| 6862 |
|
if (r_symndx != 0) |
| 6863 |
|
rel->r_addend -= (local_syms[r_symndx].st_value |
| 6864 |
|
+ sec->output_offset |
| 6865 |
|
+ sec->output_section->vma); |
| 6866 |
|
|
| 6867 |
|
rel->r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO); |
| 6868 |
|
rel->r_offset += d_offset; |
| 6869 |
|
insn2 = 0x38630000; /* addi 3,3,0 */ |
| 6870 |
|
bfd_put_32 (output_bfd, insn2, |
| 6871 |
|
contents + rel->r_offset - d_offset); |
| 6872 |
|
/* Zap the reloc on the _tls_get_addr call too. */ |
| 6873 |
|
BFD_ASSERT (rel->r_offset - d_offset == rel[1].r_offset); |
| 6874 |
|
rel[1].r_info = ELF32_R_INFO (ELF32_R_SYM (rel[1].r_info), |
| 6875 |
|
R_PPC_NONE); |
| 6876 |
|
rel--; |
| 6877 |
|
continue; |
| 6878 |
|
} |
| 6879 |
|
break; |
| 6880 |
} |
} |
| 6881 |
|
|
| 6882 |
/* Handle other relocations that tweak non-addend part of insn. */ |
/* Handle other relocations that tweak non-addend part of insn. */ |
| 6911 |
break; |
break; |
| 6912 |
} |
} |
| 6913 |
|
|
| 6914 |
|
ifunc = NULL; |
| 6915 |
|
if (!htab->is_vxworks && is_branch_reloc (r_type)) |
| 6916 |
|
{ |
| 6917 |
|
if (h != NULL) |
| 6918 |
|
{ |
| 6919 |
|
if (h->type == STT_GNU_IFUNC) |
| 6920 |
|
ifunc = &h->plt.plist; |
| 6921 |
|
} |
| 6922 |
|
else if (local_got_offsets != NULL) |
| 6923 |
|
{ |
| 6924 |
|
if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) |
| 6925 |
|
{ |
| 6926 |
|
struct plt_entry **local_plt = (struct plt_entry **) |
| 6927 |
|
(local_got_offsets + symtab_hdr->sh_info); |
| 6928 |
|
|
| 6929 |
|
ifunc = local_plt + r_symndx; |
| 6930 |
|
} |
| 6931 |
|
} |
| 6932 |
|
if (ifunc != NULL) |
| 6933 |
|
{ |
| 6934 |
|
struct plt_entry *ent = find_plt_ent (ifunc, got2, rel->r_addend); |
| 6935 |
|
|
| 6936 |
|
if (h == NULL && (ent->plt.offset & 1) == 0) |
| 6937 |
|
{ |
| 6938 |
|
Elf_Internal_Rela rela; |
| 6939 |
|
bfd_byte *loc; |
| 6940 |
|
|
| 6941 |
|
rela.r_offset = (htab->iplt->output_section->vma |
| 6942 |
|
+ htab->iplt->output_offset |
| 6943 |
|
+ ent->plt.offset); |
| 6944 |
|
rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE); |
| 6945 |
|
rela.r_addend = relocation; |
| 6946 |
|
loc = (htab->reliplt->contents |
| 6947 |
|
+ ent->plt.offset * sizeof (Elf32_External_Rela) / 4); |
| 6948 |
|
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
| 6949 |
|
|
| 6950 |
|
ent->plt.offset |= 1; |
| 6951 |
|
} |
| 6952 |
|
if (h == NULL && (ent->glink_offset & 1) == 0) |
| 6953 |
|
{ |
| 6954 |
|
write_glink_stub (ent, htab->iplt, info); |
| 6955 |
|
ent->glink_offset |= 1; |
| 6956 |
|
} |
| 6957 |
|
|
| 6958 |
|
unresolved_reloc = FALSE; |
| 6959 |
|
if (htab->plt_type == PLT_NEW |
| 6960 |
|
|| !htab->elf.dynamic_sections_created |
| 6961 |
|
|| h == NULL) |
| 6962 |
|
relocation = (htab->glink->output_section->vma |
| 6963 |
|
+ htab->glink->output_offset |
| 6964 |
|
+ (ent->glink_offset & ~1)); |
| 6965 |
|
else |
| 6966 |
|
relocation = (htab->plt->output_section->vma |
| 6967 |
|
+ htab->plt->output_offset |
| 6968 |
|
+ ent->plt.offset); |
| 6969 |
|
} |
| 6970 |
|
} |
| 6971 |
|
|
| 6972 |
addend = rel->r_addend; |
addend = rel->r_addend; |
| 6973 |
tls_type = 0; |
tls_type = 0; |
| 6974 |
howto = NULL; |
howto = NULL; |
| 6987 |
|
|
| 6988 |
case R_PPC_NONE: |
case R_PPC_NONE: |
| 6989 |
case R_PPC_TLS: |
case R_PPC_TLS: |
| 6990 |
|
case R_PPC_TLSGD: |
| 6991 |
|
case R_PPC_TLSLD: |
| 6992 |
case R_PPC_EMB_MRKREF: |
case R_PPC_EMB_MRKREF: |
| 6993 |
case R_PPC_GNU_VTINHERIT: |
case R_PPC_GNU_VTINHERIT: |
| 6994 |
case R_PPC_GNU_VTENTRY: |
case R_PPC_GNU_VTENTRY: |
| 7030 |
case R_PPC_GOT16_LO: |
case R_PPC_GOT16_LO: |
| 7031 |
case R_PPC_GOT16_HI: |
case R_PPC_GOT16_HI: |
| 7032 |
case R_PPC_GOT16_HA: |
case R_PPC_GOT16_HA: |
| 7033 |
|
tls_mask = 0; |
| 7034 |
dogot: |
dogot: |
| 7035 |
{ |
{ |
| 7036 |
/* Relocation is to the entry for this symbol in the global |
/* Relocation is to the entry for this symbol in the global |
| 7462 |
case R_PPC_RELAX32PC_PLT: |
case R_PPC_RELAX32PC_PLT: |
| 7463 |
case R_PPC_RELAX32_PLT: |
case R_PPC_RELAX32_PLT: |
| 7464 |
{ |
{ |
| 7465 |
struct plt_entry *ent = find_plt_ent (h, got2, addend); |
struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2, addend); |
| 7466 |
|
|
| 7467 |
if (htab->plt_type == PLT_NEW) |
if (htab->plt_type == PLT_NEW) |
| 7468 |
relocation = (htab->glink->output_section->vma |
relocation = (htab->glink->output_section->vma |
| 7504 |
|
|
| 7505 |
bfd_put_32 (output_bfd, t0, contents + rel->r_offset); |
bfd_put_32 (output_bfd, t0, contents + rel->r_offset); |
| 7506 |
bfd_put_32 (output_bfd, t1, contents + rel->r_offset + 4); |
bfd_put_32 (output_bfd, t1, contents + rel->r_offset + 4); |
| 7507 |
|
|
| 7508 |
|
/* Rewrite the reloc and convert one of the trailing nop |
| 7509 |
|
relocs to describe this relocation. */ |
| 7510 |
|
BFD_ASSERT (ELF32_R_TYPE (relend[-1].r_info) == R_PPC_NONE); |
| 7511 |
|
/* The relocs are at the bottom 2 bytes */ |
| 7512 |
|
rel[0].r_offset += 2; |
| 7513 |
|
memmove (rel + 1, rel, (relend - rel - 1) * sizeof (*rel)); |
| 7514 |
|
rel[0].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA); |
| 7515 |
|
rel[1].r_offset += 4; |
| 7516 |
|
rel[1].r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO); |
| 7517 |
|
rel++; |
| 7518 |
} |
} |
| 7519 |
continue; |
continue; |
| 7520 |
|
|
| 7551 |
break; |
break; |
| 7552 |
|
|
| 7553 |
case R_PPC_PLTREL24: |
case R_PPC_PLTREL24: |
| 7554 |
|
if (h == NULL || ifunc != NULL) |
| 7555 |
|
break; |
| 7556 |
/* Relocation is to the entry for this symbol in the |
/* Relocation is to the entry for this symbol in the |
| 7557 |
procedure linkage table. */ |
procedure linkage table. */ |
| 7558 |
{ |
{ |
| 7559 |
struct plt_entry *ent = find_plt_ent (h, got2, addend); |
struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2, addend); |
| 7560 |
|
|
| 7561 |
addend = 0; |
addend = 0; |
| 7562 |
if (ent == NULL |
if (ent == NULL |
| 7723 |
case R_PPC_GLOB_DAT: |
case R_PPC_GLOB_DAT: |
| 7724 |
case R_PPC_JMP_SLOT: |
case R_PPC_JMP_SLOT: |
| 7725 |
case R_PPC_RELATIVE: |
case R_PPC_RELATIVE: |
| 7726 |
|
case R_PPC_IRELATIVE: |
| 7727 |
case R_PPC_PLT32: |
case R_PPC_PLT32: |
| 7728 |
case R_PPC_PLTREL32: |
case R_PPC_PLTREL32: |
| 7729 |
case R_PPC_PLT16_LO: |
case R_PPC_PLT16_LO: |
| 7859 |
return ret; |
return ret; |
| 7860 |
} |
} |
| 7861 |
|
|
|
#define PPC_LO(v) ((v) & 0xffff) |
|
|
#define PPC_HI(v) (((v) >> 16) & 0xffff) |
|
|
#define PPC_HA(v) PPC_HI ((v) + 0x8000) |
|
|
|
|
| 7862 |
/* Finish up dynamic symbol handling. We set the contents of various |
/* Finish up dynamic symbol handling. We set the contents of various |
| 7863 |
dynamic sections here. */ |
dynamic sections here. */ |
| 7864 |
|
|
| 7890 |
bfd_byte *loc; |
bfd_byte *loc; |
| 7891 |
bfd_vma reloc_index; |
bfd_vma reloc_index; |
| 7892 |
|
|
| 7893 |
if (htab->plt_type == PLT_NEW) |
if (htab->plt_type == PLT_NEW |
| 7894 |
|
|| !htab->elf.dynamic_sections_created) |
| 7895 |
reloc_index = ent->plt.offset / 4; |
reloc_index = ent->plt.offset / 4; |
| 7896 |
else |
else |
| 7897 |
{ |
{ |
| 7904 |
|
|
| 7905 |
/* This symbol has an entry in the procedure linkage table. |
/* This symbol has an entry in the procedure linkage table. |
| 7906 |
Set it up. */ |
Set it up. */ |
| 7907 |
if (htab->plt_type == PLT_VXWORKS) |
if (htab->plt_type == PLT_VXWORKS |
| 7908 |
|
&& htab->elf.dynamic_sections_created) |
| 7909 |
{ |
{ |
| 7910 |
bfd_vma got_offset; |
bfd_vma got_offset; |
| 7911 |
const bfd_vma *plt_entry; |
const bfd_vma *plt_entry; |
| 8027 |
} |
} |
| 8028 |
else |
else |
| 8029 |
{ |
{ |
| 8030 |
rela.r_offset = (htab->plt->output_section->vma |
asection *splt = htab->plt; |
| 8031 |
+ htab->plt->output_offset |
if (!htab->elf.dynamic_sections_created) |
| 8032 |
|
splt = htab->iplt; |
| 8033 |
|
|
| 8034 |
|
rela.r_offset = (splt->output_section->vma |
| 8035 |
|
+ splt->output_offset |
| 8036 |
+ ent->plt.offset); |
+ ent->plt.offset); |
| 8037 |
if (htab->plt_type == PLT_OLD) |
if (htab->plt_type == PLT_OLD |
| 8038 |
|
|| !htab->elf.dynamic_sections_created) |
| 8039 |
{ |
{ |
| 8040 |
/* We don't need to fill in the .plt. The ppc dynamic |
/* We don't need to fill in the .plt. The ppc dynamic |
| 8041 |
linker will fill it in. */ |
linker will fill it in. */ |
| 8046 |
+ htab->glink->output_section->vma |
+ htab->glink->output_section->vma |
| 8047 |
+ htab->glink->output_offset); |
+ htab->glink->output_offset); |
| 8048 |
bfd_put_32 (output_bfd, val, |
bfd_put_32 (output_bfd, val, |
| 8049 |
htab->plt->contents + ent->plt.offset); |
splt->contents + ent->plt.offset); |
| 8050 |
} |
} |
| 8051 |
} |
} |
| 8052 |
|
|
| 8053 |
/* Fill in the entry in the .rela.plt section. */ |
/* Fill in the entry in the .rela.plt section. */ |
|
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT); |
|
| 8054 |
rela.r_addend = 0; |
rela.r_addend = 0; |
| 8055 |
|
if (!htab->elf.dynamic_sections_created |
| 8056 |
|
|| h->dynindx == -1) |
| 8057 |
|
{ |
| 8058 |
|
BFD_ASSERT (h->type == STT_GNU_IFUNC |
| 8059 |
|
&& h->def_regular |
| 8060 |
|
&& (h->root.type == bfd_link_hash_defined |
| 8061 |
|
|| h->root.type == bfd_link_hash_defweak)); |
| 8062 |
|
rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE); |
| 8063 |
|
rela.r_addend = SYM_VAL (h); |
| 8064 |
|
} |
| 8065 |
|
else |
| 8066 |
|
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT); |
| 8067 |
|
|
| 8068 |
loc = (htab->relplt->contents |
if (!htab->elf.dynamic_sections_created) |
| 8069 |
+ reloc_index * sizeof (Elf32_External_Rela)); |
loc = htab->reliplt->contents; |
| 8070 |
|
else |
| 8071 |
|
loc = htab->relplt->contents; |
| 8072 |
|
loc += reloc_index * sizeof (Elf32_External_Rela); |
| 8073 |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
| 8074 |
|
|
| 8075 |
if (!h->def_regular) |
if (!h->def_regular) |
| 8095 |
doneone = TRUE; |
doneone = TRUE; |
| 8096 |
} |
} |
| 8097 |
|
|
| 8098 |
if (htab->plt_type == PLT_NEW) |
if (htab->plt_type == PLT_NEW |
| 8099 |
|
|| !htab->elf.dynamic_sections_created) |
| 8100 |
{ |
{ |
| 8101 |
bfd_vma plt; |
asection *splt = htab->plt; |
| 8102 |
unsigned char *p; |
if (!htab->elf.dynamic_sections_created) |
| 8103 |
|
splt = htab->iplt; |
| 8104 |
|
|
| 8105 |
plt = (ent->plt.offset |
write_glink_stub (ent, splt, info); |
|
+ htab->plt->output_section->vma |
|
|
+ htab->plt->output_offset); |
|
|
p = (unsigned char *) htab->glink->contents + ent->glink_offset; |
|
| 8106 |
|
|
| 8107 |
if (info->shared || info->pie) |
if (!info->shared && !info->pie) |
| 8108 |
{ |
/* We only need one non-PIC glink stub. */ |
| 8109 |
bfd_vma got = 0; |
break; |
|
|
|
|
if (ent->addend >= 32768) |
|
|
got = (ent->addend |
|
|
+ ent->sec->output_section->vma |
|
|
+ ent->sec->output_offset); |
|
|
else if (htab->elf.hgot != NULL) |
|
|
got = SYM_VAL (htab->elf.hgot); |
|
|
|
|
|
plt -= got; |
|
|
|
|
|
if (plt + 0x8000 < 0x10000) |
|
|
{ |
|
|
bfd_put_32 (output_bfd, LWZ_11_30 + PPC_LO (plt), p); |
|
|
p += 4; |
|
|
bfd_put_32 (output_bfd, MTCTR_11, p); |
|
|
p += 4; |
|
|
bfd_put_32 (output_bfd, BCTR, p); |
|
|
p += 4; |
|
|
bfd_put_32 (output_bfd, NOP, p); |
|
|
p += 4; |
|
|
} |
|
|
else |
|
|
{ |
|
|
bfd_put_32 (output_bfd, ADDIS_11_30 + PPC_HA (plt), p); |
|
|
p += 4; |
|
|
bfd_put_32 (output_bfd, LWZ_11_11 + PPC_LO (plt), p); |
|
|
p += 4; |
|
|
bfd_put_32 (output_bfd, MTCTR_11, p); |
|
|
p += 4; |
|
|
bfd_put_32 (output_bfd, BCTR, p); |
|
|
p += 4; |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
bfd_put_32 (output_bfd, LIS_11 + PPC_HA (plt), p); |
|
|
p += 4; |
|
|
bfd_put_32 (output_bfd, LWZ_11_11 + PPC_LO (plt), p); |
|
|
p += 4; |
|
|
bfd_put_32 (output_bfd, MTCTR_11, p); |
|
|
p += 4; |
|
|
bfd_put_32 (output_bfd, BCTR, p); |
|
|
p += 4; |
|
|
|
|
|
/* We only need one non-PIC glink stub. */ |
|
|
break; |
|
|
} |
|
| 8110 |
} |
} |
| 8111 |
else |
else |
| 8112 |
break; |
break; |
| 8377 |
} |
} |
| 8378 |
} |
} |
| 8379 |
|
|
| 8380 |
if (htab->glink != NULL && htab->glink->contents != NULL) |
if (htab->glink != NULL |
| 8381 |
|
&& htab->glink->contents != NULL |
| 8382 |
|
&& htab->elf.dynamic_sections_created) |
| 8383 |
{ |
{ |
| 8384 |
unsigned char *p; |
unsigned char *p; |
| 8385 |
unsigned char *endp; |
unsigned char *endp; |
| 8646 |
#define elf_backend_plt_sym_val ppc_elf_plt_sym_val |
#define elf_backend_plt_sym_val ppc_elf_plt_sym_val |
| 8647 |
#define elf_backend_action_discarded ppc_elf_action_discarded |
#define elf_backend_action_discarded ppc_elf_action_discarded |
| 8648 |
#define elf_backend_init_index_section _bfd_elf_init_1_index_section |
#define elf_backend_init_index_section _bfd_elf_init_1_index_section |
| 8649 |
|
#define elf_backend_post_process_headers _bfd_elf_set_osabi |
| 8650 |
|
|
| 8651 |
#include "elf32-target.h" |
#include "elf32-target.h" |
| 8652 |
|
|
| 8756 |
|
|
| 8757 |
#undef elf32_bed |
#undef elf32_bed |
| 8758 |
#define elf32_bed ppc_elf_vxworks_bed |
#define elf32_bed ppc_elf_vxworks_bed |
| 8759 |
|
#undef elf_backend_post_process_headers |
| 8760 |
|
|
| 8761 |
#include "elf32-target.h" |
#include "elf32-target.h" |