0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- FALSE, /* pc_relative */ /* FIXME: Does this apply to split relocs? */
+ FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_PPC_VLE_LO16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f00fff, /* dst_mask */
+ 0x1f007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* The 16 LSBS in split16d format. */
"R_PPC_VLE_HI16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f00fff, /* dst_mask */
+ 0x1f007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 split16d format. */
"R_PPC_VLE_HA16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f00fff, /* dst_mask */
+ 0x1f007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 (High Adjusted) in split16d format. */
"R_PPC_VLE_SDAREL_LO16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f00fff, /* dst_mask */
+ 0x1f007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* The 16 LSBS relative to _SDA_BASE_ in split16d format. */
"R_PPC_VLE_SDAREL_HI16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f00fff, /* dst_mask */
+ 0x1f007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 relative to _SDA_BASE_ in split16d format. */
"R_PPC_VLE_SDAREL_HA16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f00fff, /* dst_mask */
+ 0x1f007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 (HA) relative to _SDA_BASE split16d format. */
case BFD_RELOC_NONE: r = R_PPC_NONE; break;
case BFD_RELOC_32: r = R_PPC_ADDR32; break;
case BFD_RELOC_PPC_BA26: r = R_PPC_ADDR24; break;
+ case BFD_RELOC_PPC64_ADDR16_DS:
case BFD_RELOC_16: r = R_PPC_ADDR16; break;
+ case BFD_RELOC_PPC64_ADDR16_LO_DS:
case BFD_RELOC_LO16: r = R_PPC_ADDR16_LO; break;
case BFD_RELOC_HI16: r = R_PPC_ADDR16_HI; break;
case BFD_RELOC_HI16_S: r = R_PPC_ADDR16_HA; break;
case BFD_RELOC_PPC_B16: r = R_PPC_REL14; break;
case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC_REL14_BRTAKEN; break;
case BFD_RELOC_PPC_B16_BRNTAKEN: r = R_PPC_REL14_BRNTAKEN; break;
+ case BFD_RELOC_PPC64_GOT16_DS:
case BFD_RELOC_16_GOTOFF: r = R_PPC_GOT16; break;
+ case BFD_RELOC_PPC64_GOT16_LO_DS:
case BFD_RELOC_LO16_GOTOFF: r = R_PPC_GOT16_LO; break;
case BFD_RELOC_HI16_GOTOFF: r = R_PPC_GOT16_HI; break;
case BFD_RELOC_HI16_S_GOTOFF: r = R_PPC_GOT16_HA; break;
case BFD_RELOC_32_PCREL: r = R_PPC_REL32; break;
case BFD_RELOC_32_PLTOFF: r = R_PPC_PLT32; break;
case BFD_RELOC_32_PLT_PCREL: r = R_PPC_PLTREL32; break;
+ case BFD_RELOC_PPC64_PLT16_LO_DS:
case BFD_RELOC_LO16_PLTOFF: r = R_PPC_PLT16_LO; break;
case BFD_RELOC_HI16_PLTOFF: r = R_PPC_PLT16_HI; break;
case BFD_RELOC_HI16_S_PLTOFF: r = R_PPC_PLT16_HA; break;
case BFD_RELOC_GPREL16: r = R_PPC_SDAREL16; break;
+ case BFD_RELOC_PPC64_SECTOFF_DS:
case BFD_RELOC_16_BASEREL: r = R_PPC_SECTOFF; break;
+ case BFD_RELOC_PPC64_SECTOFF_LO_DS:
case BFD_RELOC_LO16_BASEREL: r = R_PPC_SECTOFF_LO; break;
case BFD_RELOC_HI16_BASEREL: r = R_PPC_SECTOFF_HI; break;
case BFD_RELOC_HI16_S_BASEREL: r = R_PPC_SECTOFF_HA; break;
case BFD_RELOC_CTOR: r = R_PPC_ADDR32; break;
+ case BFD_RELOC_PPC64_TOC16_DS:
case BFD_RELOC_PPC_TOC16: r = R_PPC_TOC16; break;
case BFD_RELOC_PPC_TLS: r = R_PPC_TLS; break;
case BFD_RELOC_PPC_TLSGD: r = R_PPC_TLSGD; break;
case BFD_RELOC_PPC_TLSLD: r = R_PPC_TLSLD; break;
case BFD_RELOC_PPC_DTPMOD: r = R_PPC_DTPMOD32; break;
+ case BFD_RELOC_PPC64_TPREL16_DS:
case BFD_RELOC_PPC_TPREL16: r = R_PPC_TPREL16; break;
+ case BFD_RELOC_PPC64_TPREL16_LO_DS:
case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC_TPREL16_LO; break;
case BFD_RELOC_PPC_TPREL16_HI: r = R_PPC_TPREL16_HI; break;
case BFD_RELOC_PPC_TPREL16_HA: r = R_PPC_TPREL16_HA; break;
case BFD_RELOC_PPC_TPREL: r = R_PPC_TPREL32; break;
+ case BFD_RELOC_PPC64_DTPREL16_DS:
case BFD_RELOC_PPC_DTPREL16: r = R_PPC_DTPREL16; break;
+ case BFD_RELOC_PPC64_DTPREL16_LO_DS:
case BFD_RELOC_PPC_DTPREL16_LO: r = R_PPC_DTPREL16_LO; break;
case BFD_RELOC_PPC_DTPREL16_HI: r = R_PPC_DTPREL16_HI; break;
case BFD_RELOC_PPC_DTPREL16_HA: r = R_PPC_DTPREL16_HA; break;
}
}
-static bfd_boolean
-ppc_elf_section_flags (flagword *flags ATTRIBUTE_UNUSED,
- const Elf_Internal_Shdr *hdr)
-{
- if (hdr->sh_flags & SHF_PPC_VLE)
- hdr->bfd_section->has_vle_insns = 1;
- return TRUE;
-}
-
static flagword
ppc_elf_lookup_section_flags (char *flag_name)
{
if (m->count == 0)
continue;
- sect0_vle = is_ppc_vle (m->sections[0]);
+ sect0_vle = (elf_section_flags (m->sections[0]) & SHF_PPC_VLE) != 0;
for (j = 1; j < m->count; ++j)
{
- if (is_ppc_vle (m->sections[j]) != sect0_vle)
+ sectj_vle = (elf_section_flags (m->sections[j]) & SHF_PPC_VLE) != 0;
+
+ if (sectj_vle != sect0_vle)
break;
}
if (j >= m->count)
continue;
- sectj_vle = is_ppc_vle (m->sections[j]);
-
/* sections 0..j-1 stay in this (current) segment,
the remainder are put in a new segment.
The scan resumes with the new segment. */
struct sym_cache sym_cache;
};
+/* Rename some of the generic section flags to better document how they
+ are used for ppc32. The flags are only valid for ppc32 elf objects. */
+
+/* Nonzero if this section has TLS related relocations. */
+#define has_tls_reloc sec_flg0
+
+/* Nonzero if this section has a call to __tls_get_addr. */
+#define has_tls_get_addr_call sec_flg1
+
/* Get the PPC ELF linker hash table from a link_info structure. */
#define ppc_elf_hash_table(p) \
return FALSE;
htab = ppc_elf_hash_table (info);
- htab->got = s = bfd_get_section_by_name (abfd, ".got");
+ htab->got = s = bfd_get_linker_section (abfd, ".got");
if (s == NULL)
abort ();
if (htab->is_vxworks)
{
- htab->sgotplt = bfd_get_section_by_name (abfd, ".got.plt");
+ htab->sgotplt = bfd_get_linker_section (abfd, ".got.plt");
if (!htab->sgotplt)
abort ();
}
return FALSE;
}
- htab->relgot = bfd_get_section_by_name (abfd, ".rela.got");
+ htab->relgot = bfd_get_linker_section (abfd, ".rela.got");
if (!htab->relgot)
abort ();
&& !ppc_elf_create_glink (abfd, info))
return FALSE;
- htab->dynbss = bfd_get_section_by_name (abfd, ".dynbss");
+ htab->dynbss = bfd_get_linker_section (abfd, ".dynbss");
s = bfd_make_section_anyway_with_flags (abfd, ".dynsbss",
SEC_ALLOC | SEC_LINKER_CREATED);
htab->dynsbss = s;
if (! info->shared)
{
- htab->relbss = bfd_get_section_by_name (abfd, ".rela.bss");
+ htab->relbss = bfd_get_linker_section (abfd, ".rela.bss");
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
s = bfd_make_section_anyway_with_flags (abfd, ".rela.sbss", flags);
&& !elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2))
return FALSE;
- htab->relplt = bfd_get_section_by_name (abfd, ".rela.plt");
- htab->plt = s = bfd_get_section_by_name (abfd, ".plt");
+ htab->relplt = bfd_get_linker_section (abfd, ".rela.plt");
+ htab->plt = s = bfd_get_linker_section (abfd, ".plt");
if (s == NULL)
abort ();
/* Set the contents of the .interp section to the interpreter. */
if (info->executable)
{
- s = bfd_get_section_by_name (htab->elf.dynobj, ".interp");
+ s = bfd_get_linker_section (htab->elf.dynobj, ".interp");
BFD_ASSERT (s != NULL);
s->size = sizeof ELF_DYNAMIC_INTERPRETER;
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
if (htab->glink != NULL
&& htab->glink->size != 0
&& htab->glink_eh_frame != NULL
- && !bfd_is_abs_section (htab->glink_eh_frame->output_section))
+ && !bfd_is_abs_section (htab->glink_eh_frame->output_section)
+ && _bfd_elf_eh_frame_present (info))
{
s = htab->glink_eh_frame;
s->size = sizeof (glink_eh_frame_cie) + 20;
}
#undef add_dynamic_entry
+ if (htab->glink_eh_frame != NULL
+ && htab->glink_eh_frame->contents != NULL)
+ {
+ unsigned char *p = htab->glink_eh_frame->contents;
+ bfd_vma val;
+
+ memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
+ /* CIE length (rewrite in case little-endian). */
+ bfd_put_32 (htab->elf.dynobj, sizeof (glink_eh_frame_cie) - 4, p);
+ p += sizeof (glink_eh_frame_cie);
+ /* FDE length. */
+ val = htab->glink_eh_frame->size - 4 - sizeof (glink_eh_frame_cie);
+ bfd_put_32 (htab->elf.dynobj, val, p);
+ p += 4;
+ /* CIE pointer. */
+ val = p - htab->glink_eh_frame->contents;
+ bfd_put_32 (htab->elf.dynobj, val, p);
+ p += 4;
+ /* Offset to .glink. Set later. */
+ p += 4;
+ /* .glink size. */
+ bfd_put_32 (htab->elf.dynobj, htab->glink->size, p);
+ p += 4;
+ /* Augmentation. */
+ p += 1;
+
+ if (info->shared
+ && htab->elf.dynamic_sections_created)
+ {
+ bfd_vma adv = (htab->glink->size - GLINK_PLTRESOLVE + 8) >> 2;
+ if (adv < 64)
+ *p++ = DW_CFA_advance_loc + adv;
+ else if (adv < 256)
+ {
+ *p++ = DW_CFA_advance_loc1;
+ *p++ = adv;
+ }
+ else if (adv < 65536)
+ {
+ *p++ = DW_CFA_advance_loc2;
+ bfd_put_16 (htab->elf.dynobj, adv, p);
+ p += 2;
+ }
+ else
+ {
+ *p++ = DW_CFA_advance_loc4;
+ bfd_put_32 (htab->elf.dynobj, adv, p);
+ p += 4;
+ }
+ *p++ = DW_CFA_register;
+ *p++ = 65;
+ p++;
+ *p++ = DW_CFA_advance_loc + 4;
+ *p++ = DW_CFA_restore_extended;
+ *p++ = 65;
+ }
+ BFD_ASSERT ((bfd_vma) ((p + 3 - htab->glink_eh_frame->contents) & -4)
+ == htab->glink_eh_frame->size);
+ }
+
return TRUE;
}
return insn;
}
+static bfd_boolean
+is_insn_ds_form (unsigned int insn)
+{
+ return ((insn & (0x3f << 26)) == 58u << 26 /* ld,ldu,lwa */
+ || (insn & (0x3f << 26)) == 62u << 26 /* std,stdu,stq */
+ || (insn & (0x3f << 26)) == 57u << 26 /* lfdp */
+ || (insn & (0x3f << 26)) == 61u << 26 /* stfdp */);
+}
+
+static bfd_boolean
+is_insn_dq_form (unsigned int insn)
+{
+ return (insn & (0x3f << 26)) == 56u << 26; /* lq */
+}
+
/* The RELOCATE_SECTION function is called by the ELF backend linker
to handle the relocations for a section.
;
else
{
+ BFD_ASSERT (h->dynindx != -1);
indx = h->dynindx;
unresolved_reloc = FALSE;
}
|| h->root.type == bfd_link_hash_undefweak))
|| !SYMBOL_REFERENCES_LOCAL (info, h))
{
+ BFD_ASSERT (h->dynindx != -1);
unresolved_reloc = FALSE;
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
outrel.r_addend = rel->r_addend;
Bits 0:15 are not used. */
addend += 0x8000;
break;
+
+ case R_PPC_ADDR16:
+ case R_PPC_ADDR16_LO:
+ case R_PPC_GOT16:
+ case R_PPC_GOT16_LO:
+ case R_PPC_SDAREL16:
+ case R_PPC_SECTOFF:
+ case R_PPC_SECTOFF_LO:
+ case R_PPC_DTPREL16:
+ case R_PPC_DTPREL16_LO:
+ case R_PPC_TPREL16:
+ case R_PPC_TPREL16_LO:
+ case R_PPC_GOT_TLSGD16:
+ case R_PPC_GOT_TLSGD16_LO:
+ case R_PPC_GOT_TLSLD16:
+ case R_PPC_GOT_TLSLD16_LO:
+ case R_PPC_GOT_DTPREL16:
+ case R_PPC_GOT_DTPREL16_LO:
+ case R_PPC_GOT_TPREL16:
+ case R_PPC_GOT_TPREL16_LO:
+ {
+ /* The 32-bit ABI lacks proper relocations to deal with
+ certain 64-bit instructions. Prevent damage to bits
+ that make up part of the insn opcode. */
+ unsigned int insn, mask, lobit;
+
+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset);
+ mask = 0;
+ if (is_insn_ds_form (insn))
+ mask = 3;
+ else if (is_insn_dq_form (insn))
+ mask = 15;
+ else
+ break;
+ lobit = mask & (relocation + addend);
+ if (lobit != 0)
+ {
+ addend -= lobit;
+ info->callbacks->einfo
+ (_("%P: %H: error: %s against `%s' not a multiple of %u\n"),
+ input_bfd, input_section, rel->r_offset,
+ howto->name, sym_name, mask + 1);
+ bfd_set_error (bfd_error_bad_value);
+ ret = FALSE;
+ }
+ addend += insn & mask;
+ }
+ break;
}
#ifdef DEBUG
htab->plt->contents + ent->plt.offset + 28);
/* Fill in the GOT entry corresponding to this PLT slot with
- the address immediately after the the "bctr" instruction
+ the address immediately after the "bctr" instruction
in this PLT entry. */
bfd_put_32 (output_bfd, (htab->plt->output_section->vma
+ htab->plt->output_offset
htab = ppc_elf_hash_table (info);
dynobj = elf_hash_table (info)->dynobj;
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
if (htab->is_vxworks)
- splt = bfd_get_section_by_name (dynobj, ".plt");
+ splt = bfd_get_linker_section (dynobj, ".plt");
else
splt = NULL;
unsigned char *p = htab->glink_eh_frame->contents;
bfd_vma val;
- memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
- /* CIE length (rewrite in case little-endian). */
- bfd_put_32 (htab->elf.dynobj, sizeof (glink_eh_frame_cie) - 4, p);
p += sizeof (glink_eh_frame_cie);
/* FDE length. */
- val = htab->glink_eh_frame->size - 4 - sizeof (glink_eh_frame_cie);
- bfd_put_32 (htab->elf.dynobj, val, p);
p += 4;
/* CIE pointer. */
- val = p - htab->glink_eh_frame->contents;
- bfd_put_32 (htab->elf.dynobj, val, p);
p += 4;
/* Offset to .glink. */
val = (htab->glink->output_section->vma
+ htab->glink_eh_frame->output_offset);
val -= p - htab->glink_eh_frame->contents;
bfd_put_32 (htab->elf.dynobj, val, p);
- p += 4;
- /* .glink size. */
- bfd_put_32 (htab->elf.dynobj, htab->glink->size, p);
- p += 4;
- /* Augmentation. */
- p += 1;
-
- if (info->shared
- && htab->elf.dynamic_sections_created)
- {
- bfd_vma adv = (htab->glink->size - GLINK_PLTRESOLVE + 8) >> 2;
- if (adv < 64)
- *p++ = DW_CFA_advance_loc + adv;
- else if (adv < 256)
- {
- *p++ = DW_CFA_advance_loc1;
- *p++ = adv;
- }
- else if (adv < 65536)
- {
- *p++ = DW_CFA_advance_loc2;
- bfd_put_16 (htab->elf.dynobj, adv, p);
- p += 2;
- }
- else
- {
- *p++ = DW_CFA_advance_loc4;
- bfd_put_32 (htab->elf.dynobj, adv, p);
- p += 4;
- }
- *p++ = DW_CFA_register;
- *p++ = 65;
- p++;
- *p++ = DW_CFA_advance_loc + 4;
- *p++ = DW_CFA_restore_extended;
- *p++ = 65;
- }
- BFD_ASSERT ((bfd_vma) ((p + 3 - htab->glink_eh_frame->contents) & -4)
- == htab->glink_eh_frame->size);
if (htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
&& !_bfd_elf_write_section_eh_frame (output_bfd, info,
#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_post_process_headers _bfd_elf_set_osabi
#define elf_backend_lookup_section_flags_hook ppc_elf_lookup_section_flags
-#define elf_backend_section_flags ppc_elf_section_flags
#define elf_backend_section_processing ppc_elf_section_processing
#include "elf32-target.h"