/* PowerPC-specific support for 32-bit ELF
- Copyright (C) 1994-2016 Free Software Foundation, Inc.
+ Copyright (C) 1994-2017 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
#include "elf32-ppc.h"
#include "elf-vxworks.h"
#include "dwarf2.h"
+#include "opcode/ppc.h"
typedef enum split16_format_type
{
"R_PPC_VLE_LO16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f007ff, /* dst_mask */
+ 0x1f07ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* The 16 LSBS in split16d format. */
"R_PPC_VLE_LO16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f07ff, /* dst_mask */
+ 0x3e007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 split16a format. */
"R_PPC_VLE_HI16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f007ff, /* dst_mask */
+ 0x1f07ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 split16d format. */
"R_PPC_VLE_HI16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f07ff, /* dst_mask */
+ 0x3e007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 (High Adjusted) in split16a format. */
"R_PPC_VLE_HA16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f007ff, /* dst_mask */
+ 0x1f07ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 (High Adjusted) in split16d format. */
"R_PPC_VLE_HA16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f07ff, /* dst_mask */
+ 0x3e007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* This reloc is like R_PPC_EMB_SDA21 but only applies to e_add16i
"R_PPC_VLE_SDAREL_LO16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f007ff, /* dst_mask */
+ 0x1f07ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* The 16 LSBS relative to _SDA_BASE_ in split16d format. */
"R_PPC_VLE_SDAREL_LO16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f07ff, /* dst_mask */
+ 0x3e007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 relative to _SDA_BASE_ in split16a format. */
"R_PPC_VLE_SDAREL_HI16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f007ff, /* dst_mask */
+ 0x1f07ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 relative to _SDA_BASE_ in split16d format. */
"R_PPC_VLE_SDAREL_HI16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f07ff, /* dst_mask */
+ 0x3e007ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 (HA) relative to _SDA_BASE split16a format. */
"R_PPC_VLE_SDAREL_HA16A", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f007ff, /* dst_mask */
+ 0x1f07ff, /* dst_mask */
FALSE), /* pcrel_offset */
/* Bits 16-31 (HA) relative to _SDA_BASE split16d format. */
"R_PPC_VLE_SDAREL_HA16D", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
- 0x1f07ff, /* dst_mask */
+ 0x3e007ff, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_PPC_IRELATIVE, /* type */
r_type = ELF32_R_TYPE (dst->r_info);
if (r_type >= R_PPC_max)
{
+ /* xgettext:c-format */
_bfd_error_handler (_("%B: unrecognised PPC reloc number: %d"),
abfd, r_type);
bfd_set_error (bfd_error_bad_value);
ELF32_R_TYPE (dst->r_info) is necessarily a valid relocation. */
if (!cache_ptr->howto)
{
+ /* xgettext:c-format */
_bfd_error_handler (_("%B: invalid relocation type %d"),
abfd, r_type);
bfd_set_error (bfd_error_bad_value);
if (asec == NULL)
continue;
+ /* xgettext:c-format */
error_message = _("corrupt %s section in %B");
length = asec->size;
if (length < 20)
if (bfd_seek (ibfd, asec->filepos, SEEK_SET) != 0
|| (bfd_bread (buffer, length, ibfd) != length))
{
+ /* xgettext:c-format */
error_message = _("unable to read in %s section from %B");
goto fail;
}
if (asec && ! bfd_set_section_size (abfd, asec, 20 + num_entries * 4))
{
ibfd = abfd;
+ /* xgettext:c-format */
error_message = _("warning: unable to set size of %s section in %B");
}
}
struct ppc_elf_params *params;
/* Short-cuts to get to dynamic linker sections. */
- asection *got;
- asection *relgot;
asection *glink;
- asection *plt;
- asection *relplt;
- asection *iplt;
- asection *reliplt;
- asection *dynbss;
- asection *relbss;
asection *dynsbss;
asection *relsbss;
elf_linker_section_t sdata[2];
/* The (unloaded but important) .rela.plt.unloaded on VxWorks. */
asection *srelplt2;
- /* The .got.plt section (VxWorks only)*/
- asection *sgotplt;
-
/* Shortcut to __tls_get_addr. */
struct elf_link_hash_entry *tls_get_addr;
{
struct ppc_elf_link_hash_table *ret;
static struct ppc_elf_params default_params
- = { PLT_OLD, 0, 1, 0, 0, 12, 0, 0 };
+ = { PLT_OLD, 0, 1, 0, 0, 12, 0, 0, 0 };
ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table));
if (ret == NULL)
ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info)
{
struct ppc_elf_link_hash_table *htab;
- asection *s;
- flagword flags;
if (!_bfd_elf_create_got_section (abfd, info))
return FALSE;
htab = ppc_elf_hash_table (info);
- htab->got = s = bfd_get_linker_section (abfd, ".got");
- if (s == NULL)
- abort ();
-
- if (htab->is_vxworks)
- {
- htab->sgotplt = bfd_get_linker_section (abfd, ".got.plt");
- if (!htab->sgotplt)
- abort ();
- }
- else
+ if (!htab->is_vxworks)
{
/* The powerpc .got has a blrl instruction in it. Mark it
executable. */
- flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- if (!bfd_set_section_flags (abfd, s, flags))
+ flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ if (!bfd_set_section_flags (abfd, htab->elf.sgot, flags))
return FALSE;
}
- htab->relgot = bfd_get_linker_section (abfd, ".rela.got");
- if (!htab->relgot)
- abort ();
-
return TRUE;
}
flags = SEC_ALLOC | SEC_LINKER_CREATED;
s = bfd_make_section_anyway_with_flags (abfd, ".iplt", flags);
- htab->iplt = s;
+ htab->elf.iplt = s;
if (s == NULL
|| !bfd_set_section_alignment (abfd, s, 4))
return FALSE;
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.iplt", flags);
- htab->reliplt = s;
+ htab->elf.irelplt = s;
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, 2))
return FALSE;
htab = ppc_elf_hash_table (info);
- if (htab->got == NULL
+ if (htab->elf.sgot == NULL
&& !ppc_elf_create_got (abfd, info))
return FALSE;
&& !ppc_elf_create_glink (abfd, info))
return FALSE;
- 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 (! bfd_link_pic (info))
{
- 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_linker_section (abfd, ".rela.plt");
- htab->plt = s = bfd_get_linker_section (abfd, ".plt");
- if (s == NULL)
- abort ();
-
+ s = htab->elf.splt;
flags = SEC_ALLOC | SEC_CODE | SEC_LINKER_CREATED;
if (htab->plt_type == PLT_VXWORKS)
/* The VxWorks PLT is a loaded section with contents. */
&& edir->elf.dynamic_adjusted))
edir->elf.non_got_ref |= eind->elf.non_got_ref;
- edir->elf.ref_dynamic |= eind->elf.ref_dynamic;
+ if (edir->elf.versioned != versioned_hidden)
+ edir->elf.ref_dynamic |= eind->elf.ref_dynamic;
edir->elf.ref_regular |= eind->elf.ref_regular;
edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak;
edir->elf.needs_plt |= eind->elf.needs_plt;
bad_shared_reloc (bfd *abfd, enum elf_ppc_reloc_type r_type)
{
_bfd_error_handler
+ /* xgettext:c-format */
(_("%B: relocation %s cannot be used when making a shared object"),
abfd,
ppc_elf_howto_table[r_type]->name);
This shows up in particular in an R_PPC_ADDR32 in the eabi
startup code. */
if (h != NULL
- && htab->got == NULL
+ && htab->elf.sgot == NULL
&& strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
{
if (htab->elf.dynobj == NULL)
case R_PPC_GOT16_HI:
case R_PPC_GOT16_HA:
/* This symbol requires a global offset table entry. */
- if (htab->got == NULL)
+ if (htab->elf.sgot == NULL)
{
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
/* It does not make sense to have a procedure linkage
table entry for a non-ifunc local symbol. */
info->callbacks->einfo
- (_("%P: %H: %s reloc against local symbol\n"),
+ /* xgettext:c-format */
+ (_("%H: %s reloc against local symbol\n"),
abfd, sec, rel->r_offset,
ppc_elf_howto_table[r_type]->name);
bfd_set_error (bfd_error_bad_value);
}
else if (out_fp != 2 && in_fp == 2)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses hard float, %B uses soft float"), obfd, ibfd);
else if (out_fp == 2 && in_fp != 2)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses hard float, %B uses soft float"), ibfd, obfd);
else if (out_fp == 1 && in_fp == 3)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses double-precision hard float, "
"%B uses single-precision hard float"), obfd, ibfd);
else if (out_fp == 3 && in_fp == 1)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses double-precision hard float, "
"%B uses single-precision hard float"), ibfd, obfd);
}
else if (out_fp != 2 * 4 && in_fp == 2 * 4)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses 64-bit long double, "
"%B uses 128-bit long double"), ibfd, obfd);
else if (in_fp != 2 * 4 && out_fp == 2 * 4)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses 64-bit long double, "
"%B uses 128-bit long double"), obfd, ibfd);
else if (out_fp == 1 * 4 && in_fp == 3 * 4)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses IBM long double, "
"%B uses IEEE long double"), ibfd, obfd);
else if (out_fp == 3 * 4 && in_fp == 1 * 4)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses IBM long double, "
"%B uses IEEE long double"), obfd, ibfd);
}
}
else if (out_vec < in_vec)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses AltiVec vector ABI, %B uses SPE vector ABI"),
obfd, ibfd);
else if (out_vec > in_vec)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses AltiVec vector ABI, %B uses SPE vector ABI"),
ibfd, obfd);
}
}
else if (out_struct < in_struct)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses r3/r4 for small structure returns, "
"%B uses memory"), obfd, ibfd);
else if (out_struct > in_struct)
_bfd_error_handler
+ /* xgettext:c-format */
(_("Warning: %B uses r3/r4 for small structure returns, "
"%B uses memory"), ibfd, obfd);
}
{
error = TRUE;
_bfd_error_handler
+ /* xgettext:c-format */
(_("%B: uses different e_flags (0x%lx) fields "
"than previous modules (0x%lx)"),
ibfd, (long) new_flags, (long) old_flags);
}
static void
-ppc_elf_vle_split16 (bfd *output_bfd, bfd_byte *loc,
+ppc_elf_vle_split16 (bfd *input_bfd,
+ asection *input_section,
+ unsigned long offset,
+ bfd_byte *loc,
bfd_vma value,
- split16_format_type split16_format)
-
+ split16_format_type split16_format,
+ bfd_boolean fixup)
{
- unsigned int insn, top5;
-
- insn = bfd_get_32 (output_bfd, loc);
+ unsigned int insn, opcode, top5;
+
+ insn = bfd_get_32 (input_bfd, loc);
+ opcode = insn & 0xf300f800;
+ if (opcode == E_OR2I_INSN
+ || opcode == E_AND2I_DOT_INSN
+ || opcode == E_OR2IS_INSN
+ || opcode == E_LIS_INSN
+ || opcode == E_AND2IS_DOT_INSN)
+ {
+ if (split16_format != split16a_type)
+ {
+ if (fixup)
+ split16_format = split16a_type;
+ else
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B(%A+0x%lx): expected 16A style relocation on 0x%08x insn"),
+ input_bfd, input_section, offset, opcode);
+ }
+ }
+ else if (opcode == E_ADD2I_DOT_INSN
+ || opcode == E_ADD2IS_INSN
+ || opcode == E_CMP16I_INSN
+ || opcode == E_MULL2I_INSN
+ || opcode == E_CMPL16I_INSN
+ || opcode == E_CMPH16I_INSN
+ || opcode == E_CMPHL16I_INSN)
+ {
+ if (split16_format != split16d_type)
+ {
+ if (fixup)
+ split16_format = split16d_type;
+ else
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B(%A+0x%lx): expected 16D style relocation on 0x%08x insn"),
+ input_bfd, input_section, offset, opcode);
+ }
+ }
top5 = value & 0xf800;
- top5 = top5 << (split16_format == split16a_type ? 9 : 5);
- insn &= (split16_format == split16a_type ? ~0x1f007ff : ~0x1f07ff);
+ top5 = top5 << (split16_format == split16a_type ? 5 : 10);
+ insn &= (split16_format == split16a_type ? ~0x1f07ff : ~0x3e007ff);
insn |= top5;
insn |= value & 0x7ff;
- bfd_put_32 (output_bfd, insn, loc);
+ bfd_put_32 (input_bfd, insn, loc);
}
-
\f
/* Choose which PLT scheme to use, and set .plt flags appropriately.
Returns -1 on error, 0 for old PLT, 1 for new PLT. */
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
/* The new PLT is a loaded section. */
- if (htab->plt != NULL
- && !bfd_set_section_flags (htab->elf.dynobj, htab->plt, flags))
+ if (htab->elf.splt != NULL
+ && !bfd_set_section_flags (htab->elf.dynobj, htab->elf.splt, flags))
return -1;
/* The new GOT is not executable. */
- if (htab->got != NULL
- && !bfd_set_section_flags (htab->elf.dynobj, htab->got, flags))
+ if (htab->elf.sgot != NULL
+ && !bfd_set_section_flags (htab->elf.dynobj, htab->elf.sgot, flags))
return -1;
}
else
tga->root.type = bfd_link_hash_indirect;
tga->root.u.i.link = &opt->root;
ppc_elf_copy_indirect_symbol (info, opt, tga);
- opt->forced_local = 0;
+ opt->mark = 1;
if (opt->dynindx != -1)
{
/* Use __tls_get_addr_opt in dynamic relocations. */
htab->params->no_tls_get_addr_opt = TRUE;
}
if (htab->plt_type == PLT_NEW
- && htab->plt != NULL
- && htab->plt->output_section != NULL)
+ && htab->elf.splt != NULL
+ && htab->elf.splt->output_section != NULL)
{
- elf_section_type (htab->plt->output_section) = SHT_PROGBITS;
- elf_section_flags (htab->plt->output_section) = SHF_ALLOC + SHF_WRITE;
+ elf_section_type (htab->elf.splt->output_section) = SHT_PROGBITS;
+ elf_section_flags (htab->elf.splt->output_section) = SHF_ALLOC + SHF_WRITE;
}
return _bfd_elf_tls_setup (obfd, info);
/* Taking a function's address in a read/write section
doesn't require us to define the function symbol in the
executable on a plt call stub. A dynamic reloc can
- be used instead. */
- if (h->pointer_equality_needed
- && h->type != STT_GNU_IFUNC
+ be used instead, giving better runtime performance.
+ (Calls via that function pointer don't need to bounce
+ through the plt call stub.) Similarly, use a dynamic
+ reloc for a weak reference when possible, allowing the
+ resolution of the symbol to be set at load time rather
+ than link time. */
+ if ((h->pointer_equality_needed
+ || (!h->ref_regular_nonweak && h->non_got_ref))
&& !htab->is_vxworks
&& !ppc_elf_hash_entry (h)->has_sda_refs
&& !readonly_dynrelocs (h))
{
h->pointer_equality_needed = 0;
+ /* After adjust_dynamic_symbol, non_got_ref set in the
+ non-pic case means that dyn_relocs for this symbol
+ should be discarded. */
h->non_got_ref = 0;
}
-
- /* After adjust_dynamic_symbol, non_got_ref set in the
- non-shared case means that we have allocated space in
- .dynbss for the symbol and thus dyn_relocs for this
- symbol should be discarded.
- If we get here we know we are making a PLT entry for this
- symbol, and in an executable we'd normally resolve
- relocations against this symbol to the PLT entry. Allow
- dynamic relocs if the reference is weak, and the dynamic
- relocs will not cause text relocation. */
- else if (!h->ref_regular_nonweak
- && h->non_got_ref
- && h->type != STT_GNU_IFUNC
- && !htab->is_vxworks
- && !ppc_elf_hash_entry (h)->has_sda_refs
- && !readonly_dynrelocs (h))
- h->non_got_ref = 0;
}
h->protected_def = 0;
return TRUE;
if (ppc_elf_hash_entry (h)->has_sda_refs)
s = htab->dynsbss;
+ else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sdynrelro;
else
- s = htab->dynbss;
+ s = htab->elf.sdynbss;
BFD_ASSERT (s != NULL);
/* We must generate a R_PPC_COPY reloc to tell the dynamic linker to
if (ppc_elf_hash_entry (h)->has_sda_refs)
srel = htab->relsbss;
+ else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ srel = htab->elf.sreldynrelro;
else
- srel = htab->relbss;
+ srel = htab->elf.srelbss;
BFD_ASSERT (srel != NULL);
srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
if (htab->plt_type == PLT_VXWORKS)
{
- where = htab->got->size;
- htab->got->size += need;
+ where = htab->elf.sgot->size;
+ htab->elf.sgot->size += need;
}
else
{
}
else
{
- if (htab->got->size + need > max_before_header
- && htab->got->size <= max_before_header)
+ if (htab->elf.sgot->size + need > max_before_header
+ && htab->elf.sgot->size <= max_before_header)
{
- htab->got_gap = max_before_header - htab->got->size;
- htab->got->size = max_before_header + htab->got_header_size;
+ htab->got_gap = max_before_header - htab->elf.sgot->size;
+ htab->elf.sgot->size = max_before_header + htab->got_header_size;
}
- where = htab->got->size;
- htab->got->size += need;
+ where = htab->elf.sgot->size;
+ htab->elf.sgot->size += need;
}
}
return where;
}
+/* If H is undefined weak, make it dynamic if that makes sense. */
+
+static bfd_boolean
+ensure_undefweak_dynamic (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
+{
+ struct elf_link_hash_table *htab = elf_hash_table (info);
+
+ if (htab->dynamic_sections_created
+ && h->root.type == bfd_link_hash_undefweak
+ && h->dynindx == -1
+ && !h->forced_local
+ && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
+ return bfd_elf_link_record_dynamic_symbol (info, h);
+ return TRUE;
+}
+
/* Allocate space in associated reloc sections for dynamic relocs. */
static bfd_boolean
struct ppc_elf_link_hash_entry *eh;
struct ppc_elf_link_hash_table *htab;
struct elf_dyn_relocs *p;
+ bfd_boolean dyn;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
htab = ppc_elf_hash_table (info);
- if (htab->elf.dynamic_sections_created
- || h->type == STT_GNU_IFUNC)
- {
- struct plt_entry *ent;
- bfd_boolean doneone = FALSE;
- bfd_vma plt_offset = 0, glink_offset = 0;
- bfd_boolean dyn;
-
- for (ent = h->plt.plist; ent != NULL; ent = ent->next)
- if (ent->plt.refcount > 0)
- {
- /* Make sure this symbol is output as a dynamic symbol. */
- if (h->dynindx == -1
- && !h->forced_local
- && !h->def_regular
- && htab->elf.dynamic_sections_created)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return FALSE;
- }
-
- dyn = htab->elf.dynamic_sections_created;
- if (bfd_link_pic (info)
- || h->type == STT_GNU_IFUNC
- || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
- {
- asection *s = htab->plt;
- if (!dyn || h->dynindx == -1)
- s = htab->iplt;
-
- if (htab->plt_type == PLT_NEW || !dyn || h->dynindx == -1)
- {
- if (!doneone)
- {
- plt_offset = s->size;
- s->size += 4;
- }
- ent->plt.offset = plt_offset;
-
- s = htab->glink;
- if (!doneone || bfd_link_pic (info))
- {
- glink_offset = s->size;
- s->size += GLINK_ENTRY_SIZE;
- if (h == htab->tls_get_addr
- && !htab->params->no_tls_get_addr_opt)
- s->size += TLS_GET_ADDR_GLINK_SIZE - GLINK_ENTRY_SIZE;
- }
- if (!doneone
- && !bfd_link_pic (info)
- && h->def_dynamic
- && !h->def_regular)
- {
- h->root.u.def.section = s;
- h->root.u.def.value = glink_offset;
- }
- ent->glink_offset = glink_offset;
-
- if (htab->params->emit_stub_syms
- && !add_stub_sym (ent, h, info))
- return FALSE;
- }
- else
- {
- if (!doneone)
- {
- /* If this is the first .plt entry, make room
- for the special first entry. */
- if (s->size == 0)
- s->size += htab->plt_initial_entry_size;
-
- /* The PowerPC PLT is actually composed of two
- parts, the first part is 2 words (for a load
- and a jump), and then there is a remaining
- word available at the end. */
- plt_offset = (htab->plt_initial_entry_size
- + (htab->plt_slot_size
- * ((s->size
- - htab->plt_initial_entry_size)
- / htab->plt_entry_size)));
-
- /* If this symbol is not defined in a regular
- file, and we are not generating a shared
- library, then set the symbol to this location
- in the .plt. This is to avoid text
- relocations, and is required to make
- function pointers compare as equal between
- the normal executable and the shared library. */
- if (! bfd_link_pic (info)
- && h->def_dynamic
- && !h->def_regular)
- {
- h->root.u.def.section = s;
- h->root.u.def.value = plt_offset;
- }
-
- /* Make room for this entry. */
- s->size += htab->plt_entry_size;
- /* After the 8192nd entry, room for two entries
- is allocated. */
- if (htab->plt_type == PLT_OLD
- && (s->size - htab->plt_initial_entry_size)
- / htab->plt_entry_size
- > PLT_NUM_SINGLE_ENTRIES)
- s->size += htab->plt_entry_size;
- }
- ent->plt.offset = plt_offset;
- }
-
- /* We also need to make an entry in the .rela.plt section. */
- if (!doneone)
- {
- if (!htab->elf.dynamic_sections_created
- || h->dynindx == -1)
- htab->reliplt->size += sizeof (Elf32_External_Rela);
- else
- {
- htab->relplt->size += sizeof (Elf32_External_Rela);
-
- if (htab->plt_type == PLT_VXWORKS)
- {
- /* Allocate space for the unloaded relocations. */
- if (!bfd_link_pic (info)
- && htab->elf.dynamic_sections_created)
- {
- if (ent->plt.offset
- == (bfd_vma) htab->plt_initial_entry_size)
- {
- htab->srelplt2->size
- += (sizeof (Elf32_External_Rela)
- * VXWORKS_PLTRESOLVE_RELOCS);
- }
-
- htab->srelplt2->size
- += (sizeof (Elf32_External_Rela)
- * VXWORKS_PLT_NON_JMP_SLOT_RELOCS);
- }
-
- /* Every PLT entry has an associated GOT entry in
- .got.plt. */
- htab->sgotplt->size += 4;
- }
- }
- doneone = TRUE;
- }
- }
- else
- ent->plt.offset = (bfd_vma) -1;
- }
- else
- ent->plt.offset = (bfd_vma) -1;
-
- if (!doneone)
- {
- h->plt.plist = NULL;
- h->needs_plt = 0;
- }
- }
- else
- {
- h->plt.plist = NULL;
- h->needs_plt = 0;
- }
-
eh = (struct ppc_elf_link_hash_entry *) h;
if (eh->elf.got.refcount > 0
|| (ELIMINATE_COPY_RELOCS
&& eh->has_addr16_lo
&& htab->params->pic_fixup > 0))
{
- bfd_boolean dyn;
unsigned int need;
- /* Make sure this symbol is output as a dynamic symbol. */
- if (eh->elf.dynindx == -1
- && !eh->elf.forced_local
- && eh->elf.type != STT_GNU_IFUNC
- && htab->elf.dynamic_sections_created)
- {
- if (!bfd_elf_link_record_dynamic_symbol (info, &eh->elf))
- return FALSE;
- }
+ /* Make sure this symbol is output as a dynamic symbol.
+ Undefined weak syms won't yet be marked as dynamic. */
+ if (!ensure_undefweak_dynamic (info, &eh->elf))
+ return FALSE;
need = 0;
if ((eh->tls_mask & TLS_TLS) != 0)
else
{
eh->elf.got.offset = allocate_got (htab, need);
- dyn = htab->elf.dynamic_sections_created;
if ((bfd_link_pic (info)
- || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf))
+ || (htab->elf.dynamic_sections_created
+ && eh->elf.dynindx != -1
+ && !SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
&& (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT
|| eh->elf.root.type != bfd_link_hash_undefweak))
{
- asection *rsec = htab->relgot;
+ asection *rsec = htab->elf.srelgot;
if (eh->elf.type == STT_GNU_IFUNC)
- rsec = htab->reliplt;
+ rsec = htab->elf.irelplt;
/* All the entries we allocated need relocs.
Except LD only needs one. */
if ((eh->tls_mask & TLS_LD) != 0
else
eh->elf.got.offset = (bfd_vma) -1;
- if (eh->dyn_relocs == NULL
- || !htab->elf.dynamic_sections_created)
- return TRUE;
+ if (!htab->elf.dynamic_sections_created
+ && h->type != STT_GNU_IFUNC)
+ eh->dyn_relocs = NULL;
+
+ if (eh->dyn_relocs == NULL)
+ ;
/* In the shared -Bsymbolic case, discard space allocated for
dynamic pc-relative relocs against symbols which turn out to be
defined in regular objects. For the normal shared case, discard
space for relocs that have become local due to symbol visibility
changes. */
-
- if (bfd_link_pic (info))
+ else if (bfd_link_pic (info))
{
/* Relocs that use pc_count are those that appear on a call insn,
or certain REL relocs (see must_be_dyn_reloc) that can be
/* Make sure undefined weak symbols are output as a dynamic
symbol in PIEs. */
- else if (h->dynindx == -1
- && !h->forced_local
- && !h->def_regular)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return FALSE;
- }
+ else if (!ensure_undefweak_dynamic (info, h))
+ return FALSE;
}
}
else if (ELIMINATE_COPY_RELOCS)
{
- /* For the non-shared case, discard space for relocs against
+ /* For the non-pic case, discard space for relocs against
symbols which turn out to need copy relocs or are not
dynamic. */
-
if (!h->non_got_ref
&& !h->def_regular
&& !(h->protected_def
{
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
- if (h->dynindx == -1
- && !h->forced_local)
- {
- if (! bfd_elf_link_record_dynamic_symbol (info, h))
- return FALSE;
- }
+ if (!ensure_undefweak_dynamic (info, h))
+ return FALSE;
- /* If that succeeded, we know we'll be keeping all the
- relocs. */
- if (h->dynindx != -1)
- goto keep;
+ if (h->dynindx == -1)
+ eh->dyn_relocs = NULL;
}
-
- eh->dyn_relocs = NULL;
-
- keep: ;
+ else
+ eh->dyn_relocs = NULL;
}
- /* Finally, allocate space. */
+ /* Allocate space. */
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
asection *sreloc = elf_section_data (p->sec)->sreloc;
if (eh->elf.type == STT_GNU_IFUNC)
- sreloc = htab->reliplt;
+ sreloc = htab->elf.irelplt;
sreloc->size += p->count * sizeof (Elf32_External_Rela);
}
+ /* Handle PLT relocs. Done last, after dynindx has settled. */
+ dyn = htab->elf.dynamic_sections_created && h->dynindx != -1;
+ if (dyn || h->type == STT_GNU_IFUNC)
+ {
+ struct plt_entry *ent;
+ bfd_boolean doneone = FALSE;
+ bfd_vma plt_offset = 0, glink_offset = 0;
+
+ for (ent = h->plt.plist; ent != NULL; ent = ent->next)
+ if (ent->plt.refcount > 0)
+ {
+ asection *s = htab->elf.splt;
+
+ if (!dyn)
+ s = htab->elf.iplt;
+
+ if (htab->plt_type == PLT_NEW || !dyn)
+ {
+ if (!doneone)
+ {
+ plt_offset = s->size;
+ s->size += 4;
+ }
+ ent->plt.offset = plt_offset;
+
+ s = htab->glink;
+ if (!doneone || bfd_link_pic (info))
+ {
+ glink_offset = s->size;
+ s->size += GLINK_ENTRY_SIZE;
+ if (h == htab->tls_get_addr
+ && !htab->params->no_tls_get_addr_opt)
+ s->size += TLS_GET_ADDR_GLINK_SIZE - GLINK_ENTRY_SIZE;
+ }
+ if (!doneone
+ && !bfd_link_pic (info)
+ && h->def_dynamic
+ && !h->def_regular)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = glink_offset;
+ }
+ ent->glink_offset = glink_offset;
+
+ if (htab->params->emit_stub_syms
+ && !add_stub_sym (ent, h, info))
+ return FALSE;
+ }
+ else
+ {
+ if (!doneone)
+ {
+ /* If this is the first .plt entry, make room
+ for the special first entry. */
+ if (s->size == 0)
+ s->size += htab->plt_initial_entry_size;
+
+ /* The PowerPC PLT is actually composed of two
+ parts, the first part is 2 words (for a load
+ and a jump), and then there is a remaining
+ word available at the end. */
+ plt_offset = (htab->plt_initial_entry_size
+ + (htab->plt_slot_size
+ * ((s->size
+ - htab->plt_initial_entry_size)
+ / htab->plt_entry_size)));
+
+ /* If this symbol is not defined in a regular
+ file, and we are not generating a shared
+ library, then set the symbol to this location
+ in the .plt. This is to avoid text
+ relocations, and is required to make
+ function pointers compare as equal between
+ the normal executable and the shared library. */
+ if (! bfd_link_pic (info)
+ && h->def_dynamic
+ && !h->def_regular)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = plt_offset;
+ }
+
+ /* Make room for this entry. */
+ s->size += htab->plt_entry_size;
+ /* After the 8192nd entry, room for two entries
+ is allocated. */
+ if (htab->plt_type == PLT_OLD
+ && (s->size - htab->plt_initial_entry_size)
+ / htab->plt_entry_size
+ > PLT_NUM_SINGLE_ENTRIES)
+ s->size += htab->plt_entry_size;
+ }
+ ent->plt.offset = plt_offset;
+ }
+
+ /* We also need to make an entry in the .rela.plt section. */
+ if (!doneone)
+ {
+ if (!dyn)
+ htab->elf.irelplt->size += sizeof (Elf32_External_Rela);
+ else
+ {
+ htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
+
+ if (htab->plt_type == PLT_VXWORKS)
+ {
+ /* Allocate space for the unloaded relocations. */
+ if (!bfd_link_pic (info)
+ && htab->elf.dynamic_sections_created)
+ {
+ if (ent->plt.offset
+ == (bfd_vma) htab->plt_initial_entry_size)
+ {
+ htab->srelplt2->size
+ += (sizeof (Elf32_External_Rela)
+ * VXWORKS_PLTRESOLVE_RELOCS);
+ }
+
+ htab->srelplt2->size
+ += (sizeof (Elf32_External_Rela)
+ * VXWORKS_PLT_NON_JMP_SLOT_RELOCS);
+ }
+
+ /* Every PLT entry has an associated GOT entry in
+ .got.plt. */
+ htab->elf.sgotplt->size += 4;
+ }
+ }
+ doneone = TRUE;
+ }
+ }
+ else
+ ent->plt.offset = (bfd_vma) -1;
+
+ if (!doneone)
+ {
+ h->plt.plist = NULL;
+ h->needs_plt = 0;
+ }
+ }
+ else
+ {
+ h->plt.plist = NULL;
+ h->needs_plt = 0;
+ }
+
return TRUE;
}
{
asection *sreloc = elf_section_data (p->sec)->sreloc;
if (p->ifunc)
- sreloc = htab->reliplt;
+ sreloc = htab->elf.irelplt;
sreloc->size += p->count * sizeof (Elf32_External_Rela);
if ((p->sec->output_section->flags
& (SEC_READONLY | SEC_ALLOC))
*local_got = allocate_got (htab, need);
if (bfd_link_pic (info))
{
- asection *srel = htab->relgot;
+ asection *srel = htab->elf.srelgot;
if ((*lgot_masks & PLT_IFUNC) != 0)
- srel = htab->reliplt;
+ srel = htab->elf.irelplt;
srel->size += need * (sizeof (Elf32_External_Rela) / 4);
}
}
for (ent = *local_plt; ent != NULL; ent = ent->next)
if (ent->plt.refcount > 0)
{
- s = htab->iplt;
+ s = htab->elf.iplt;
if (!doneone)
{
if (!doneone)
{
- htab->reliplt->size += sizeof (Elf32_External_Rela);
+ htab->elf.irelplt->size += sizeof (Elf32_External_Rela);
doneone = TRUE;
}
}
{
htab->tlsld_got.offset = allocate_got (htab, 8);
if (bfd_link_pic (info))
- htab->relgot->size += sizeof (Elf32_External_Rela);
+ htab->elf.srelgot->size += sizeof (Elf32_External_Rela);
}
else
htab->tlsld_got.offset = (bfd_vma) -1;
- if (htab->got != NULL && htab->plt_type != PLT_VXWORKS)
+ if (htab->elf.sgot != NULL && htab->plt_type != PLT_VXWORKS)
{
unsigned int g_o_t = 32768;
for old plt/got the got size will be 0 to 32764 (not allocated),
or 32780 to 65536 (header allocated). For new plt/got, the
corresponding ranges are 0 to 32768 and 32780 to 65536. */
- if (htab->got->size <= 32768)
+ if (htab->elf.sgot->size <= 32768)
{
- g_o_t = htab->got->size;
+ g_o_t = htab->elf.sgot->size;
if (htab->plt_type == PLT_OLD)
g_o_t += 4;
- htab->got->size += htab->got_header_size;
+ htab->elf.sgot->size += htab->got_header_size;
}
htab->elf.hgot->root.u.def.value = g_o_t;
if ((s->flags & SEC_LINKER_CREATED) == 0)
continue;
- if (s == htab->plt
- || s == htab->got)
+ if (s == htab->elf.splt
+ || s == htab->elf.sgot)
{
/* We'd like to strip these sections if they aren't needed, but if
we've exported dynamic symbols from them we must leave them.
/* Strip this section if we don't need it; see the
comment below. */
}
- else if (s == htab->iplt
+ else if (s == htab->elf.iplt
|| s == htab->glink
|| s == htab->glink_eh_frame
- || s == htab->sgotplt
+ || s == htab->elf.sgotplt
|| s == htab->sbss
- || s == htab->dynbss
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro
|| s == htab->dynsbss)
{
/* Strip these too. */
return FALSE;
}
- if (htab->plt != NULL && htab->plt->size != 0)
+ if (htab->elf.splt != NULL && htab->elf.splt->size != 0)
{
if (!add_dynamic_entry (DT_PLTGOT, 0)
|| !add_dynamic_entry (DT_PLTRELSZ, 0)
}
else
{
- tsec = htab->plt;
+ tsec = htab->elf.splt;
toff = ent->plt.offset;
}
}
insn_offset = 0;
}
stub_rtype = R_PPC_RELAX;
- if (tsec == htab->plt
+ if (tsec == htab->elf.splt
|| tsec == htab->glink)
{
stub_rtype = R_PPC_RELAX_PLT;
asection *got2;
bfd_vma *local_got_offsets;
bfd_boolean ret = TRUE;
- bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0);
+ bfd_vma d_offset = (bfd_big_endian (input_bfd) ? 2 : 0);
bfd_boolean is_vxworks_tls;
unsigned int picfixup_size = 0;
struct ppc_elf_relax_info *relax_info = NULL;
{
bfd_vma insn;
- insn = bfd_get_32 (output_bfd,
+ insn = bfd_get_32 (input_bfd,
contents + rel->r_offset - d_offset);
insn &= 31 << 21;
insn |= 0x3c020000; /* addis 0,2,0 */
- bfd_put_32 (output_bfd, insn,
+ bfd_put_32 (input_bfd, insn,
contents + rel->r_offset - d_offset);
r_type = R_PPC_TPREL16_HA;
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
{
bfd_vma insn;
- insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
insn = _bfd_elf_ppc_at_tls_transform (insn, 2);
if (insn == 0)
abort ();
- bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
r_type = R_PPC_TPREL16_LO;
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
else
{
rel->r_offset -= d_offset;
- bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
+ bfd_put_32 (input_bfd, NOP, contents + rel->r_offset);
r_type = R_PPC_NONE;
}
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
the destination reg. It may be something other than
the usual r3, and moved to r3 before the call by
intervening code. */
- insn1 = bfd_get_32 (output_bfd,
+ insn1 = bfd_get_32 (input_bfd,
contents + rel->r_offset - d_offset);
if ((tls_mask & tls_gd) != 0)
{
{
rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE);
insn2 = 0x7c631214; /* add 3,3,2 */
- bfd_put_32 (output_bfd, insn2, contents + offset);
+ bfd_put_32 (input_bfd, insn2, contents + offset);
}
r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3)
+ R_PPC_GOT_TPREL16);
rel[1].r_offset = offset + d_offset;
rel[1].r_addend = rel->r_addend;
insn2 = 0x38630000; /* addi 3,3,0 */
- bfd_put_32 (output_bfd, insn2, contents + offset);
+ bfd_put_32 (input_bfd, insn2, contents + offset);
}
}
- bfd_put_32 (output_bfd, insn1,
+ bfd_put_32 (input_bfd, insn1,
contents + rel->r_offset - d_offset);
if (tls_gd == 0)
{
insn2 = 0x38630000; /* addi 3,3,0 */
}
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
- bfd_put_32 (output_bfd, insn2, contents + offset);
+ bfd_put_32 (input_bfd, insn2, contents + offset);
/* Zap the reloc on the _tls_get_addr call too. */
BFD_ASSERT (offset == rel[1].r_offset);
rel[1].r_info = ELF32_R_INFO (STN_UNDEF, R_PPC_NONE);
rel->r_info = ELF32_R_INFO (r_symndx, R_PPC_TPREL16_LO);
rel->r_offset += d_offset;
insn2 = 0x38630000; /* addi 3,3,0 */
- bfd_put_32 (output_bfd, insn2,
+ bfd_put_32 (input_bfd, insn2,
contents + rel->r_offset - d_offset);
/* Zap the reloc on the _tls_get_addr call too. */
BFD_ASSERT (rel->r_offset - d_offset == rel[1].r_offset);
{
bfd_vma insn;
- insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
insn &= ~BRANCH_PREDICT_BIT;
insn |= branch_bit;
if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0)
insn ^= BRANCH_PREDICT_BIT;
- bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
break;
}
}
if (r_type == R_PPC_ADDR16_HA)
{
- insn = bfd_get_32 (output_bfd,
+ insn = bfd_get_32 (input_bfd,
contents + rel->r_offset - d_offset);
if ((insn & (0x3f << 26)) == (15u << 26)
&& (insn & (0x1f << 16)) == 0 /* lis */)
off = (p - contents) - (rel->r_offset - d_offset);
if (off > 0x1fffffc || (off & 3) != 0)
info->callbacks->einfo
- (_("%P: %H: fixup branch overflow\n"),
+ (_("%H: fixup branch overflow\n"),
input_bfd, input_section, rel->r_offset);
- bfd_put_32 (output_bfd, B | off,
+ bfd_put_32 (input_bfd, B | off,
contents + rel->r_offset - d_offset);
- got_addr = (htab->got->output_section->vma
- + htab->got->output_offset
+ got_addr = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ (h->got.offset & ~1));
wrel->r_offset = (p - contents) + d_offset;
wrel->r_info = ELF32_R_INFO (0, R_PPC_ADDR16_HA);
wrel->r_addend = got_addr;
insn &= ~0xffff;
insn |= ((unsigned int )(got_addr + 0x8000) >> 16) & 0xffff;
- bfd_put_32 (output_bfd, insn, p);
+ bfd_put_32 (input_bfd, insn, p);
/* Convert lis to lwz, loading address from GOT. */
insn &= ~0xffff;
insn ^= (32u ^ 15u) << 26;
insn |= (insn & (0x1f << 21)) >> 5;
insn |= got_addr & 0xffff;
- bfd_put_32 (output_bfd, insn, p + 4);
+ bfd_put_32 (input_bfd, insn, p + 4);
- bfd_put_32 (output_bfd, B | ((-4 - off) & 0x3ffffff), p + 8);
+ bfd_put_32 (input_bfd, B | ((-4 - off) & 0x3ffffff), p + 8);
picfixup_size += 12;
/* Use one of the spare relocs, so --emit-relocs
}
else
info->callbacks->einfo
- (_("%P: %H: error: %s with unexpected instruction %x\n"),
+ /* xgettext:c-format */
+ (_("%H: error: %s with unexpected instruction %x\n"),
input_bfd, input_section, rel->r_offset,
"R_PPC_ADDR16_HA", insn);
}
else if (r_type == R_PPC_ADDR16_LO)
{
- insn = bfd_get_32 (output_bfd,
+ insn = bfd_get_32 (input_bfd,
contents + rel->r_offset - d_offset);
if ((insn & (0x3f << 26)) == 14u << 26 /* addi */
|| (insn & (0x3f << 26)) == 32u << 26 /* lwz */
}
else
info->callbacks->einfo
- (_("%P: %H: error: %s with unexpected instruction %x\n"),
+ /* xgettext:c-format */
+ (_("%H: error: %s with unexpected instruction %x\n"),
input_bfd, input_section, rel->r_offset,
"R_PPC_ADDR16_LO", insn);
}
is pointing into a .got2 section (and how far
into .got2). */
info->callbacks->einfo
- (_("%X%P: %H: unsupported bss-plt -fPIC ifunc %s\n"),
+ /* xgettext:c-format */
+ (_("%X%H: unsupported bss-plt -fPIC ifunc %s\n"),
input_bfd, input_section, rel->r_offset, sym_name);
}
if (h == NULL && (ent->plt.offset & 1) == 0)
Elf_Internal_Rela rela;
bfd_byte *loc;
- rela.r_offset = (htab->iplt->output_section->vma
- + htab->iplt->output_offset
+ rela.r_offset = (htab->elf.iplt->output_section->vma
+ + htab->elf.iplt->output_offset
+ ent->plt.offset);
rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
rela.r_addend = relocation;
- loc = htab->reliplt->contents;
- loc += (htab->reliplt->reloc_count++
+ loc = htab->elf.irelplt->contents;
+ loc += (htab->elf.irelplt->reloc_count++
* sizeof (Elf32_External_Rela));
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
{
unsigned char *p = ((unsigned char *) htab->glink->contents
+ ent->glink_offset);
- write_glink_stub (ent, htab->iplt, p, info);
+ write_glink_stub (ent, htab->elf.iplt, p, info);
ent->glink_offset |= 1;
}
+ htab->glink->output_offset
+ (ent->glink_offset & ~1));
else
- relocation = (htab->plt->output_section->vma
- + htab->plt->output_offset
+ relocation = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ ent->plt.offset);
}
}
{
default:
info->callbacks->einfo
+ /* xgettext:c-format */
(_("%P: %B: unknown relocation type %d for symbol %s\n"),
input_bfd, (int) r_type, sym_name);
bfd_vma *offp;
unsigned long indx;
- if (htab->got == NULL)
+ if (htab->elf.sgot == NULL)
abort ();
indx = 0;
offp = &htab->tlsld_got.offset;
else if (h != NULL)
{
- bfd_boolean dyn;
- dyn = htab->elf.dynamic_sections_created;
- if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)
- || (bfd_link_pic (info)
- && SYMBOL_REFERENCES_LOCAL (info, h)))
+ if (!htab->elf.dynamic_sections_created
+ || h->dynindx == -1
+ || SYMBOL_REFERENCES_LOCAL (info, h)
+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ && h->root.type == bfd_link_hash_undefweak))
/* This is actually a static link, or it is a
-Bsymbolic link and the symbol is defined
locally, or the symbol was forced to be local
;
else
{
- BFD_ASSERT (h->dynindx != -1);
indx = h->dynindx;
unresolved_reloc = FALSE;
}
}
/* Generate relocs for the dynamic linker. */
- if ((bfd_link_pic (info) || indx != 0)
- && (offp == &htab->tlsld_got.offset
- || h == NULL
- || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
- || h->root.type != bfd_link_hash_undefweak))
+ if (indx != 0
+ || (bfd_link_pic (info)
+ && (h == NULL
+ || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || h->root.type != bfd_link_hash_undefweak
+ || offp == &htab->tlsld_got.offset)))
{
- asection *rsec = htab->relgot;
+ asection *rsec = htab->elf.srelgot;
bfd_byte * loc;
if (ifunc != NULL)
- rsec = htab->reliplt;
- outrel.r_offset = (htab->got->output_section->vma
- + htab->got->output_offset
+ rsec = htab->elf.irelplt;
+ outrel.r_offset = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ off);
outrel.r_addend = 0;
if (tls_ty & (TLS_LD | TLS_GD))
else
{
bfd_vma value = relocation;
+ int tlsopt = (htab->plt_type == PLT_NEW
+ && !htab->params->no_tls_get_addr_opt
+ && htab->tls_get_addr != NULL
+ && htab->tls_get_addr->plt.plist != NULL);
- if (tls_ty == (TLS_TLS | TLS_LD))
- value = 1;
- else if (tls_ty != 0)
+ if (tls_ty != 0)
{
if (htab->elf.tls_sec == NULL)
value = 0;
else
{
- value -= htab->elf.tls_sec->vma + DTP_OFFSET;
- if (tls_ty == (TLS_TLS | TLS_TPREL))
+ if (tls_ty & TLS_LD)
+ value = 0;
+ else
+ value -= htab->elf.tls_sec->vma + DTP_OFFSET;
+ if ((tls_ty & TLS_TPREL)
+ || (tlsopt && !(tls_ty & TLS_DTPREL)))
value += DTP_OFFSET - TP_OFFSET;
}
- if (tls_ty == (TLS_TLS | TLS_GD))
+ if (tls_ty & (TLS_LD | TLS_GD))
{
- bfd_put_32 (output_bfd, value,
- htab->got->contents + off + 4);
- value = 1;
+ bfd_put_32 (input_bfd, value,
+ htab->elf.sgot->contents + off + 4);
+ value = !tlsopt;
}
}
- bfd_put_32 (output_bfd, value,
- htab->got->contents + off);
+ bfd_put_32 (input_bfd, value,
+ htab->elf.sgot->contents + off);
}
off += 4;
if (r_type != ELF32_R_TYPE (rel->r_info))
goto copy_reloc;
- relocation = (htab->got->output_section->vma
- + htab->got->output_offset
+ relocation = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ off
- SYM_VAL (htab->elf.hgot));
got at entry m+n bears little relation to the entry m. */
if (addend != 0)
info->callbacks->einfo
- (_("%P: %H: non-zero addend on %s reloc against `%s'\n"),
+ /* xgettext:c-format */
+ (_("%H: non-zero addend on %s reloc against `%s'\n"),
input_bfd, input_section, rel->r_offset,
howto->name,
sym_name);
local won't have the +32k reloc addend trick marking
-fPIC code, so the linker won't know whether r30 is
_GLOBAL_OFFSET_TABLE_ or pointing into a .got2 section. */
- info->callbacks->einfo (_("%X%P: %H: @local call to ifunc %s\n"),
+ /* xgettext:c-format */
+ info->callbacks->einfo (_("%X%H: @local call to ifunc %s\n"),
input_bfd, input_section, rel->r_offset,
h->root.root.string);
}
code using weak externs ought to check that they are
defined before using them. */
bfd_byte *p = contents + rel->r_offset - d_offset;
- unsigned int insn = bfd_get_32 (output_bfd, p);
+ unsigned int insn = bfd_get_32 (input_bfd, p);
insn = _bfd_elf_ppc_at_tprel_transform (insn, 2);
if (insn != 0)
- bfd_put_32 (output_bfd, insn, p);
+ bfd_put_32 (input_bfd, insn, p);
break;
}
if (htab->elf.tls_sec != NULL)
time. */
sreloc = elf_section_data (input_section)->sreloc;
if (ifunc)
- sreloc = htab->reliplt;
+ sreloc = htab->elf.irelplt;
if (sreloc == NULL)
return FALSE;
So we'll segfault when trying to run the
indirection function to resolve the reloc. */
info->callbacks->einfo
- (_("%P: %H: relocation %s for indirect "
+ /* xgettext:c-format */
+ (_("%H: relocation %s for indirect "
"function %s unsupported\n"),
input_bfd, input_section, rel->r_offset,
howto->name,
if (skip == -1)
goto copy_reloc;
- /* This reloc will be computed at runtime. We clear the memory
- so that it contains predictable value. */
- if (! skip
- && ((input_section->flags & SEC_ALLOC) != 0
- || ELF32_R_TYPE (outrel.r_info) != R_PPC_RELATIVE))
+ /* This reloc will be computed at runtime. Clear the memory
+ so that it contains a predictable value for prelink. */
+ if (!skip)
{
relocation = howto->pc_relative ? outrel.r_offset : 0;
addend = 0;
break;
}
}
+ else if (r_type == R_PPC_DTPMOD32
+ && htab->plt_type == PLT_NEW
+ && !htab->params->no_tls_get_addr_opt
+ && htab->tls_get_addr != NULL
+ && htab->tls_get_addr->plt.plist != NULL)
+ {
+ /* Set up for __tls_get_addr_opt stub when this entry
+ does not have dynamic relocs. */
+ relocation = 0;
+ /* Set up the next word for local dynamic. If it turns
+ out to be global dynamic, the reloc will overwrite
+ this value. */
+ if (rel->r_offset + 8 <= input_section->size)
+ bfd_put_32 (input_bfd, DTP_OFFSET - TP_OFFSET,
+ contents + rel->r_offset + 4);
+ }
+ else if (r_type == R_PPC_DTPREL32
+ && htab->plt_type == PLT_NEW
+ && !htab->params->no_tls_get_addr_opt
+ && htab->tls_get_addr != NULL
+ && htab->tls_get_addr->plt.plist != NULL
+ && rel > relocs
+ && rel[-1].r_info == ELF32_R_INFO (r_symndx, R_PPC_DTPMOD32)
+ && rel[-1].r_offset + 4 == rel->r_offset)
+ {
+ /* __tls_get_addr_opt stub value. */
+ addend += DTP_OFFSET - TP_OFFSET;
+ }
break;
case R_PPC_RELAX_PLT:
+ htab->glink->output_offset
+ ent->glink_offset);
else
- relocation = (htab->plt->output_section->vma
- + htab->plt->output_offset
+ relocation = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ ent->plt.offset);
}
/* Fall through. */
+ input_section->output_offset
+ rel->r_offset - 4);
stub = shared_stub_entry;
- bfd_put_32 (output_bfd, stub[0], contents + insn_offset - 12);
- bfd_put_32 (output_bfd, stub[1], contents + insn_offset - 8);
- bfd_put_32 (output_bfd, stub[2], contents + insn_offset - 4);
+ bfd_put_32 (input_bfd, stub[0], contents + insn_offset - 12);
+ bfd_put_32 (input_bfd, stub[1], contents + insn_offset - 8);
+ bfd_put_32 (input_bfd, stub[2], contents + insn_offset - 4);
stub += 3;
size = ARRAY_SIZE (shared_stub_entry) - 3;
}
/* First insn is HA, second is LO. */
insn = *stub++;
insn |= ((relocation + 0x8000) >> 16) & 0xffff;
- bfd_put_32 (output_bfd, insn, contents + insn_offset);
+ bfd_put_32 (input_bfd, insn, contents + insn_offset);
insn_offset += 4;
insn = *stub++;
insn |= relocation & 0xffff;
- bfd_put_32 (output_bfd, insn, contents + insn_offset);
+ bfd_put_32 (input_bfd, insn, contents + insn_offset);
insn_offset += 4;
size -= 2;
{
insn = *stub++;
--size;
- bfd_put_32 (output_bfd, insn, contents + insn_offset);
+ bfd_put_32 (input_bfd, insn, contents + insn_offset);
insn_offset += 4;
}
ent = find_plt_ent (&h->plt.plist, got2,
bfd_link_pic (info) ? addend : 0);
if (ent == NULL
- || htab->plt == NULL)
+ || htab->elf.splt == NULL)
{
/* We didn't make a PLT entry for this symbol. This
happens when statically linking PIC code, or when
+ htab->glink->output_offset
+ ent->glink_offset);
else
- relocation = (htab->plt->output_section->vma
- + htab->plt->output_offset
+ relocation = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ ent->plt.offset);
}
}
|| strcmp (name, ".sbss") == 0))
{
info->callbacks->einfo
+ /* xgettext:c-format */
(_("%P: %B: the target (%s) of a %s relocation is "
"in the wrong output section (%s)\n"),
input_bfd,
|| strcmp (name, ".sbss2") == 0))
{
info->callbacks->einfo
+ /* xgettext:c-format */
(_("%P: %B: the target (%s) of a %s relocation is "
"in the wrong output section (%s)\n"),
input_bfd,
case R_PPC_VLE_LO16A:
relocation = relocation + addend;
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- relocation, split16a_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, relocation,
+ split16a_type, htab->params->vle_reloc_fixup);
goto copy_reloc;
case R_PPC_VLE_LO16D:
relocation = relocation + addend;
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- relocation, split16d_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, relocation,
+ split16d_type, htab->params->vle_reloc_fixup);
goto copy_reloc;
case R_PPC_VLE_HI16A:
relocation = (relocation + addend) >> 16;
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- relocation, split16a_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, relocation,
+ split16a_type, htab->params->vle_reloc_fixup);
goto copy_reloc;
case R_PPC_VLE_HI16D:
relocation = (relocation + addend) >> 16;
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- relocation, split16d_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, relocation,
+ split16d_type, htab->params->vle_reloc_fixup);
goto copy_reloc;
case R_PPC_VLE_HA16A:
relocation = (relocation + addend + 0x8000) >> 16;
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- relocation, split16a_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, relocation,
+ split16a_type, htab->params->vle_reloc_fixup);
goto copy_reloc;
case R_PPC_VLE_HA16D:
relocation = (relocation + addend + 0x8000) >> 16;
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- relocation, split16d_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, relocation,
+ split16d_type, htab->params->vle_reloc_fixup);
goto copy_reloc;
/* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */
else
{
info->callbacks->einfo
+ /* xgettext:c-format */
(_("%P: %B: the target (%s) of a %s relocation is "
"in the wrong output section (%s)\n"),
input_bfd,
addend -= SYM_VAL (sda);
}
- insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
if (reg == 0
&& (r_type == R_PPC_VLE_SDA21
|| r_type == R_PPC_VLE_SDA21_LO))
/* And the final 11 bits of the value to bits 21 to 31. */
insn |= relocation & 0x7ff;
- bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
if (r_type == R_PPC_VLE_SDA21
&& ((relocation + 0x80000) & 0xffffffff) > 0x100000)
/* Fill in register field. */
insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
}
- bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
}
break;
{
bfd_vma value;
const char *name;
- //int reg;
struct elf_link_hash_entry *sda = NULL;
if (sec == NULL || sec->output_section == NULL)
name = bfd_get_section_name (output_bfd, sec->output_section);
if (strcmp (name, ".sdata") == 0
|| strcmp (name, ".sbss") == 0)
- {
- //reg = 13;
- sda = htab->sdata[0].sym;
- }
+ sda = htab->sdata[0].sym;
else if (strcmp (name, ".sdata2") == 0
|| strcmp (name, ".sbss2") == 0)
- {
- //reg = 2;
- sda = htab->sdata[1].sym;
- }
+ sda = htab->sdata[1].sym;
else
{
_bfd_error_handler
+ /* xgettext:c-format */
(_("%B: the target (%s) of a %s relocation is "
"in the wrong output section (%s)"),
input_bfd,
goto copy_reloc;
}
- if (sda != NULL)
+ if (sda == NULL || !is_static_defined (sda))
{
- if (!is_static_defined (sda))
- {
- unresolved_reloc = TRUE;
- break;
- }
+ unresolved_reloc = TRUE;
+ break;
}
-
- value = (sda->root.u.def.section->output_section->vma
- + sda->root.u.def.section->output_offset
- + addend);
+ value = relocation + addend - SYM_VAL (sda);
if (r_type == R_PPC_VLE_SDAREL_LO16A)
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- value, split16a_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, value,
+ split16a_type,
+ htab->params->vle_reloc_fixup);
else if (r_type == R_PPC_VLE_SDAREL_LO16D)
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- value, split16d_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, value,
+ split16d_type,
+ htab->params->vle_reloc_fixup);
else if (r_type == R_PPC_VLE_SDAREL_HI16A)
{
value = value >> 16;
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- value, split16a_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, value,
+ split16a_type,
+ htab->params->vle_reloc_fixup);
}
else if (r_type == R_PPC_VLE_SDAREL_HI16D)
{
value = value >> 16;
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- value, split16d_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, value,
+ split16d_type,
+ htab->params->vle_reloc_fixup);
}
else if (r_type == R_PPC_VLE_SDAREL_HA16A)
{
value = (value + 0x8000) >> 16;
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- value, split16a_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, value,
+ split16a_type,
+ htab->params->vle_reloc_fixup);
}
else if (r_type == R_PPC_VLE_SDAREL_HA16D)
{
value = (value + 0x8000) >> 16;
- ppc_elf_vle_split16 (output_bfd, contents + rel->r_offset,
- value, split16d_type);
+ ppc_elf_vle_split16 (input_bfd, input_section, rel->r_offset,
+ contents + rel->r_offset, value,
+ split16d_type,
+ htab->params->vle_reloc_fixup);
}
}
goto copy_reloc;
case R_PPC_EMB_RELST_HA:
case R_PPC_EMB_BIT_FLD:
info->callbacks->einfo
+ /* xgettext:c-format */
(_("%P: %B: relocation %s is not yet supported for symbol %s\n"),
input_bfd,
howto->name,
that make up part of the insn opcode. */
unsigned int insn, mask, lobit;
- insn = bfd_get_32 (output_bfd,
+ insn = bfd_get_32 (input_bfd,
contents + rel->r_offset - d_offset);
mask = 0;
if (is_insn_ds_form (insn))
{
relocation ^= lobit;
info->callbacks->einfo
- (_("%P: %H: error: %s against `%s' not a multiple of %u\n"),
+ /* xgettext:c-format */
+ (_("%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);
rel->r_offset) != (bfd_vma) -1)
{
info->callbacks->einfo
- (_("%P: %H: unresolvable %s relocation against symbol `%s'\n"),
+ /* xgettext:c-format */
+ (_("%H: unresolvable %s relocation against symbol `%s'\n"),
input_bfd, input_section, rel->r_offset,
howto->name,
sym_name);
else
{
info->callbacks->einfo
- (_("%P: %H: %s reloc against `%s': error %d\n"),
+ /* xgettext:c-format */
+ (_("%H: %s reloc against `%s': error %d\n"),
input_bfd, input_section, rel->r_offset,
howto->name, sym_name, (int) r);
ret = FALSE;
{
bfd_put_32 (output_bfd,
plt_entry[0] | PPC_HA (got_offset),
- htab->plt->contents + ent->plt.offset + 0);
+ htab->elf.splt->contents + ent->plt.offset + 0);
bfd_put_32 (output_bfd,
plt_entry[1] | PPC_LO (got_offset),
- htab->plt->contents + ent->plt.offset + 4);
+ htab->elf.splt->contents + ent->plt.offset + 4);
}
else
{
bfd_put_32 (output_bfd,
plt_entry[0] | PPC_HA (got_loc),
- htab->plt->contents + ent->plt.offset + 0);
+ htab->elf.splt->contents + ent->plt.offset + 0);
bfd_put_32 (output_bfd,
plt_entry[1] | PPC_LO (got_loc),
- htab->plt->contents + ent->plt.offset + 4);
+ htab->elf.splt->contents + ent->plt.offset + 4);
}
bfd_put_32 (output_bfd, plt_entry[2],
- htab->plt->contents + ent->plt.offset + 8);
+ htab->elf.splt->contents + ent->plt.offset + 8);
bfd_put_32 (output_bfd, plt_entry[3],
- htab->plt->contents + ent->plt.offset + 12);
+ htab->elf.splt->contents + ent->plt.offset + 12);
/* This instruction is an immediate load. The value loaded is
the byte offset of the R_PPC_JMP_SLOT relocation from the
prescaled offset. */
bfd_put_32 (output_bfd,
plt_entry[4] | reloc_index,
- htab->plt->contents + ent->plt.offset + 16);
+ htab->elf.splt->contents + ent->plt.offset + 16);
/* This instruction is a PC-relative branch whose target is
the start of the PLT section. The address of this branch
instruction is 20 bytes beyond the start of this PLT entry.
bfd_put_32 (output_bfd,
(plt_entry[5]
| (-(ent->plt.offset + 20) & 0x03fffffc)),
- htab->plt->contents + ent->plt.offset + 20);
+ htab->elf.splt->contents + ent->plt.offset + 20);
bfd_put_32 (output_bfd, plt_entry[6],
- htab->plt->contents + ent->plt.offset + 24);
+ htab->elf.splt->contents + ent->plt.offset + 24);
bfd_put_32 (output_bfd, plt_entry[7],
- htab->plt->contents + ent->plt.offset + 28);
+ htab->elf.splt->contents + ent->plt.offset + 28);
/* Fill in the GOT entry corresponding to this PLT slot with
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
+ bfd_put_32 (output_bfd, (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ ent->plt.offset + 16),
- htab->sgotplt->contents + got_offset);
+ htab->elf.sgotplt->contents + got_offset);
if (!bfd_link_pic (info))
{
* sizeof (Elf32_External_Rela));
/* Provide the @ha relocation for the first instruction. */
- rela.r_offset = (htab->plt->output_section->vma
- + htab->plt->output_offset
+ rela.r_offset = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ ent->plt.offset + 2);
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
R_PPC_ADDR16_HA);
loc += sizeof (Elf32_External_Rela);
/* Provide the @l relocation for the second instruction. */
- rela.r_offset = (htab->plt->output_section->vma
- + htab->plt->output_offset
+ rela.r_offset = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ ent->plt.offset + 6);
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
R_PPC_ADDR16_LO);
/* Provide a relocation for the GOT entry corresponding to this
PLT slot. Point it at the middle of the .plt entry. */
- rela.r_offset = (htab->sgotplt->output_section->vma
- + htab->sgotplt->output_offset
+ rela.r_offset = (htab->elf.sgotplt->output_section->vma
+ + htab->elf.sgotplt->output_offset
+ got_offset);
rela.r_info = ELF32_R_INFO (htab->elf.hplt->indx,
R_PPC_ADDR32);
address of the PLT entry for this function, as specified
by the ABI. Instead, the offset is set to the address of
the GOT slot for this function. See EABI 4.4.4.1. */
- rela.r_offset = (htab->sgotplt->output_section->vma
- + htab->sgotplt->output_offset
+ rela.r_offset = (htab->elf.sgotplt->output_section->vma
+ + htab->elf.sgotplt->output_offset
+ got_offset);
}
else
{
- asection *splt = htab->plt;
+ asection *splt = htab->elf.splt;
if (!htab->elf.dynamic_sections_created
|| h->dynindx == -1)
- splt = htab->iplt;
+ splt = htab->elf.iplt;
rela.r_offset = (splt->output_section->vma
+ splt->output_offset
if (!htab->elf.dynamic_sections_created
|| h->dynindx == -1)
- loc = (htab->reliplt->contents
- + (htab->reliplt->reloc_count++
+ loc = (htab->elf.irelplt->contents
+ + (htab->elf.irelplt->reloc_count++
* sizeof (Elf32_External_Rela)));
else
- loc = (htab->relplt->contents
+ loc = (htab->elf.srelplt->contents
+ reloc_index * sizeof (Elf32_External_Rela));
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
|| h->dynindx == -1)
{
unsigned char *p;
- asection *splt = htab->plt;
+ asection *splt = htab->elf.splt;
if (!htab->elf.dynamic_sections_created
|| h->dynindx == -1)
- splt = htab->iplt;
+ splt = htab->elf.iplt;
p = (unsigned char *) htab->glink->contents + ent->glink_offset;
if (ppc_elf_hash_entry (h)->has_sda_refs)
s = htab->relsbss;
+ else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
else
- s = htab->relbss;
+ s = htab->elf.srelbss;
BFD_ASSERT (s != NULL);
rela.r_offset = SYM_VAL (h);
{
struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
- if (rel_sec == htab->reliplt)
+ if (rel_sec == htab->elf.irelplt)
return reloc_class_ifunc;
switch (ELF32_R_TYPE (rela->r_info))
struct bfd_link_info *info)
{
asection *sdyn;
- asection *splt;
struct ppc_elf_link_hash_table *htab;
bfd_vma got;
bfd *dynobj;
#endif
htab = ppc_elf_hash_table (info);
- dynobj = elf_hash_table (info)->dynobj;
+ dynobj = htab->elf.dynobj;
sdyn = bfd_get_linker_section (dynobj, ".dynamic");
- if (htab->is_vxworks)
- splt = bfd_get_linker_section (dynobj, ".plt");
- else
- splt = NULL;
got = 0;
if (htab->elf.hgot != NULL)
{
Elf32_External_Dyn *dyncon, *dynconend;
- BFD_ASSERT (htab->plt != NULL && sdyn != NULL);
+ BFD_ASSERT (htab->elf.splt != NULL && sdyn != NULL);
dyncon = (Elf32_External_Dyn *) sdyn->contents;
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
{
case DT_PLTGOT:
if (htab->is_vxworks)
- s = htab->sgotplt;
+ s = htab->elf.sgotplt;
else
- s = htab->plt;
+ s = htab->elf.splt;
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
break;
case DT_PLTRELSZ:
- dyn.d_un.d_val = htab->relplt->size;
+ dyn.d_un.d_val = htab->elf.srelplt->size;
break;
case DT_JMPREL:
- s = htab->relplt;
+ s = htab->elf.srelplt;
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
break;
dyn.d_un.d_ptr = got;
break;
- case DT_RELASZ:
- if (htab->is_vxworks)
- {
- if (htab->relplt)
- dyn.d_un.d_ptr -= htab->relplt->size;
- break;
- }
- continue;
-
default:
if (htab->is_vxworks
&& elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
}
}
- if (htab->got != NULL)
+ if (htab->elf.sgot != NULL
+ && htab->elf.sgot->output_section != bfd_abs_section_ptr)
{
- if (htab->elf.hgot->root.u.def.section == htab->got
- || htab->elf.hgot->root.u.def.section == htab->sgotplt)
+ if (htab->elf.hgot->root.u.def.section == htab->elf.sgot
+ || htab->elf.hgot->root.u.def.section == htab->elf.sgotplt)
{
unsigned char *p = htab->elf.hgot->root.u.def.section->contents;
}
else
{
+ /* xgettext:c-format */
info->callbacks->einfo (_("%P: %s not defined in linker created %s\n"),
htab->elf.hgot->root.root.string,
- (htab->sgotplt != NULL
- ? htab->sgotplt->name : htab->got->name));
+ (htab->elf.sgotplt != NULL
+ ? htab->elf.sgotplt->name
+ : htab->elf.sgot->name));
bfd_set_error (bfd_error_bad_value);
ret = FALSE;
}
- elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4;
+ elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
}
/* Fill in the first entry in the VxWorks procedure linkage table. */
- if (splt && splt->size > 0)
+ if (htab->is_vxworks
+ && htab->elf.splt != NULL
+ && htab->elf.splt->size != 0
+ && htab->elf.splt->output_section != bfd_abs_section_ptr)
{
+ asection *splt = htab->elf.splt;
/* Use the right PLT. */
const bfd_vma *plt_entry = (bfd_link_pic (info)
? ppc_elf_vxworks_pic_plt0_entry
loc = htab->srelplt2->contents;
/* Output the @ha relocation for the first instruction. */
- rela.r_offset = (htab->plt->output_section->vma
- + htab->plt->output_offset
+ rela.r_offset = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ 2);
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_HA);
rela.r_addend = 0;
loc += sizeof (Elf32_External_Rela);
/* Output the @l relocation for the second instruction. */
- rela.r_offset = (htab->plt->output_section->vma
- + htab->plt->output_offset
+ rela.r_offset = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ 6);
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_LO);
rela.r_addend = 0;
#endif
#define elf_backend_plt_not_loaded 1
+#define elf_backend_want_dynrelro 1
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
#define elf_backend_rela_normal 1
#define elf_backend_plt_readonly 1
#undef elf_backend_got_header_size
#define elf_backend_got_header_size 12
+#undef elf_backend_dtrel_excludes_plt
+#define elf_backend_dtrel_excludes_plt 1
#undef bfd_elf32_get_synthetic_symtab