Line 32... |
Line 32... |
#include "bfdlink.h"
|
#include "bfdlink.h"
|
#include "libbfd.h"
|
#include "libbfd.h"
|
#include "elf-bfd.h"
|
#include "elf-bfd.h"
|
#include "elf/ppc64.h"
|
#include "elf/ppc64.h"
|
#include "elf64-ppc.h"
|
#include "elf64-ppc.h"
|
|
#include "dwarf2.h"
|
|
|
static bfd_reloc_status_type ppc64_elf_ha_reloc
|
static bfd_reloc_status_type ppc64_elf_ha_reloc
|
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
static bfd_reloc_status_type ppc64_elf_branch_reloc
|
static bfd_reloc_status_type ppc64_elf_branch_reloc
|
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
|
Line 78... |
Line 79... |
#define elf_backend_default_execstack 0
|
#define elf_backend_default_execstack 0
|
|
|
#define bfd_elf64_mkobject ppc64_elf_mkobject
|
#define bfd_elf64_mkobject ppc64_elf_mkobject
|
#define bfd_elf64_bfd_reloc_type_lookup ppc64_elf_reloc_type_lookup
|
#define bfd_elf64_bfd_reloc_type_lookup ppc64_elf_reloc_type_lookup
|
#define bfd_elf64_bfd_reloc_name_lookup ppc64_elf_reloc_name_lookup
|
#define bfd_elf64_bfd_reloc_name_lookup ppc64_elf_reloc_name_lookup
|
#define bfd_elf64_bfd_merge_private_bfd_data ppc64_elf_merge_private_bfd_data
|
#define bfd_elf64_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
|
#define bfd_elf64_new_section_hook ppc64_elf_new_section_hook
|
#define bfd_elf64_new_section_hook ppc64_elf_new_section_hook
|
#define bfd_elf64_bfd_link_hash_table_create ppc64_elf_link_hash_table_create
|
#define bfd_elf64_bfd_link_hash_table_create ppc64_elf_link_hash_table_create
|
#define bfd_elf64_bfd_link_hash_table_free ppc64_elf_link_hash_table_free
|
#define bfd_elf64_bfd_link_hash_table_free ppc64_elf_link_hash_table_free
|
#define bfd_elf64_get_synthetic_symtab ppc64_elf_get_synthetic_symtab
|
#define bfd_elf64_get_synthetic_symtab ppc64_elf_get_synthetic_symtab
|
#define bfd_elf64_bfd_link_just_syms ppc64_elf_link_just_syms
|
#define bfd_elf64_bfd_link_just_syms ppc64_elf_link_just_syms
|
Line 2725... |
Line 2726... |
"CORE", note_type, data, sizeof (data));
|
"CORE", note_type, data, sizeof (data));
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
/* Merge backend specific data from an object file to the output
|
|
object file when linking. */
|
|
|
|
static bfd_boolean
|
|
ppc64_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
|
|
{
|
|
/* Check if we have the same endianness. */
|
|
if (ibfd->xvec->byteorder != obfd->xvec->byteorder
|
|
&& ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
|
|
&& obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
|
|
{
|
|
const char *msg;
|
|
|
|
if (bfd_big_endian (ibfd))
|
|
msg = _("%B: compiled for a big endian system "
|
|
"and target is little endian");
|
|
else
|
|
msg = _("%B: compiled for a little endian system "
|
|
"and target is big endian");
|
|
|
|
(*_bfd_error_handler) (msg, ibfd);
|
|
|
|
bfd_set_error (bfd_error_wrong_format);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Add extra PPC sections. */
|
/* Add extra PPC sections. */
|
|
|
static const struct bfd_elf_special_section ppc64_elf_special_sections[]=
|
static const struct bfd_elf_special_section ppc64_elf_special_sections[]=
|
{
|
{
|
{ STRING_COMMA_LEN (".plt"), 0, SHT_NOBITS, 0 },
|
{ STRING_COMMA_LEN (".plt"), 0, SHT_NOBITS, 0 },
|
Line 3747... |
Line 3719... |
asection *relbss;
|
asection *relbss;
|
asection *glink;
|
asection *glink;
|
asection *sfpr;
|
asection *sfpr;
|
asection *brlt;
|
asection *brlt;
|
asection *relbrlt;
|
asection *relbrlt;
|
|
asection *glink_eh_frame;
|
|
|
/* Shortcut to .__tls_get_addr and __tls_get_addr. */
|
/* Shortcut to .__tls_get_addr and __tls_get_addr. */
|
struct ppc_link_hash_entry *tls_get_addr;
|
struct ppc_link_hash_entry *tls_get_addr;
|
struct ppc_link_hash_entry *tls_get_addr_fd;
|
struct ppc_link_hash_entry *tls_get_addr_fd;
|
|
|
Line 3761... |
Line 3734... |
unsigned long stub_count[ppc_stub_plt_call];
|
unsigned long stub_count[ppc_stub_plt_call];
|
|
|
/* Number of stubs against global syms. */
|
/* Number of stubs against global syms. */
|
unsigned long stub_globals;
|
unsigned long stub_globals;
|
|
|
|
/* Set if PLT call stubs should load r11. */
|
|
unsigned int plt_static_chain:1;
|
|
|
/* Set if we should emit symbols for stubs. */
|
/* Set if we should emit symbols for stubs. */
|
unsigned int emit_stub_syms:1;
|
unsigned int emit_stub_syms:1;
|
|
|
/* Set if __tls_get_addr optimization should not be done. */
|
/* Set if __tls_get_addr optimization should not be done. */
|
unsigned int no_tls_get_addr_opt:1;
|
unsigned int no_tls_get_addr_opt:1;
|
Line 4155... |
Line 4131... |
/* Enter this entry into the linker stub hash table. */
|
/* Enter this entry into the linker stub hash table. */
|
stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, stub_name,
|
stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table, stub_name,
|
TRUE, FALSE);
|
TRUE, FALSE);
|
if (stub_entry == NULL)
|
if (stub_entry == NULL)
|
{
|
{
|
info->callbacks->einfo (_("%B: cannot create stub entry %s\n"),
|
info->callbacks->einfo (_("%P: %B: cannot create stub entry %s\n"),
|
section->owner, stub_name);
|
section->owner, stub_name);
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
stub_entry->stub_sec = stub_sec;
|
stub_entry->stub_sec = stub_sec;
|
Line 4194... |
Line 4170... |
flags);
|
flags);
|
if (htab->glink == NULL
|
if (htab->glink == NULL
|
|| ! bfd_set_section_alignment (dynobj, htab->glink, 3))
|
|| ! bfd_set_section_alignment (dynobj, htab->glink, 3))
|
return FALSE;
|
return FALSE;
|
|
|
|
if (!info->no_ld_generated_unwind_info)
|
|
{
|
|
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
|
|
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
|
|
htab->glink_eh_frame = bfd_make_section_anyway_with_flags (dynobj,
|
|
".eh_frame",
|
|
flags);
|
|
if (htab->glink_eh_frame == NULL
|
|
|| !bfd_set_section_alignment (abfd, htab->glink_eh_frame, 2))
|
|
return FALSE;
|
|
}
|
|
|
flags = SEC_ALLOC | SEC_LINKER_CREATED;
|
flags = SEC_ALLOC | SEC_LINKER_CREATED;
|
htab->iplt = bfd_make_section_anyway_with_flags (dynobj, ".iplt", flags);
|
htab->iplt = bfd_make_section_anyway_with_flags (dynobj, ".iplt", flags);
|
if (htab->iplt == NULL
|
if (htab->iplt == NULL
|
|| ! bfd_set_section_alignment (dynobj, htab->iplt, 3))
|
|| ! bfd_set_section_alignment (dynobj, htab->iplt, 3))
|
return FALSE;
|
return FALSE;
|
Line 4376... |
Line 4364... |
struct ppc_link_hash_entry *edir, *eind;
|
struct ppc_link_hash_entry *edir, *eind;
|
|
|
edir = (struct ppc_link_hash_entry *) dir;
|
edir = (struct ppc_link_hash_entry *) dir;
|
eind = (struct ppc_link_hash_entry *) ind;
|
eind = (struct ppc_link_hash_entry *) ind;
|
|
|
|
edir->is_func |= eind->is_func;
|
|
edir->is_func_descriptor |= eind->is_func_descriptor;
|
|
edir->tls_mask |= eind->tls_mask;
|
|
if (eind->oh != NULL)
|
|
edir->oh = ppc_follow_link (eind->oh);
|
|
|
|
/* If called to transfer flags for a weakdef during processing
|
|
of elf_adjust_dynamic_symbol, don't copy NON_GOT_REF.
|
|
We clear it ourselves for ELIMINATE_COPY_RELOCS. */
|
|
if (!(ELIMINATE_COPY_RELOCS
|
|
&& eind->elf.root.type != bfd_link_hash_indirect
|
|
&& edir->elf.dynamic_adjusted))
|
|
edir->elf.non_got_ref |= eind->elf.non_got_ref;
|
|
|
|
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;
|
|
|
|
/* If we were called to copy over info for a weak sym, that's all. */
|
|
if (eind->elf.root.type != bfd_link_hash_indirect)
|
|
return;
|
|
|
/* Copy over any dynamic relocs we may have on the indirect sym. */
|
/* Copy over any dynamic relocs we may have on the indirect sym. */
|
if (eind->dyn_relocs != NULL)
|
if (eind->dyn_relocs != NULL)
|
{
|
{
|
if (edir->dyn_relocs != NULL)
|
if (edir->dyn_relocs != NULL)
|
{
|
{
|
Line 4408... |
Line 4419... |
|
|
edir->dyn_relocs = eind->dyn_relocs;
|
edir->dyn_relocs = eind->dyn_relocs;
|
eind->dyn_relocs = NULL;
|
eind->dyn_relocs = NULL;
|
}
|
}
|
|
|
edir->is_func |= eind->is_func;
|
|
edir->is_func_descriptor |= eind->is_func_descriptor;
|
|
edir->tls_mask |= eind->tls_mask;
|
|
if (eind->oh != NULL)
|
|
edir->oh = ppc_follow_link (eind->oh);
|
|
|
|
/* If called to transfer flags for a weakdef during processing
|
|
of elf_adjust_dynamic_symbol, don't copy NON_GOT_REF.
|
|
We clear it ourselves for ELIMINATE_COPY_RELOCS. */
|
|
if (!(ELIMINATE_COPY_RELOCS
|
|
&& eind->elf.root.type != bfd_link_hash_indirect
|
|
&& edir->elf.dynamic_adjusted))
|
|
edir->elf.non_got_ref |= eind->elf.non_got_ref;
|
|
|
|
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;
|
|
|
|
/* If we were called to copy over info for a weak sym, that's all. */
|
|
if (eind->elf.root.type != bfd_link_hash_indirect)
|
|
return;
|
|
|
|
/* Copy over got entries that we may have already seen to the
|
/* Copy over got entries that we may have already seen to the
|
symbol which just became indirect. */
|
symbol which just became indirect. */
|
if (eind->elf.got.glist != NULL)
|
if (eind->elf.got.glist != NULL)
|
{
|
{
|
if (edir->elf.got.glist != NULL)
|
if (edir->elf.got.glist != NULL)
|
Line 6473... |
Line 6461... |
of gcc out there that improperly (for this ABI) put initialized
|
of gcc out there that improperly (for this ABI) put initialized
|
function pointers, vtable refs and suchlike in read-only
|
function pointers, vtable refs and suchlike in read-only
|
sections. Allow them to proceed, but warn that this might
|
sections. Allow them to proceed, but warn that this might
|
break at runtime. */
|
break at runtime. */
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(_("copy reloc against `%s' requires lazy plt linking; "
|
(_("%P: copy reloc against `%s' requires lazy plt linking; "
|
"avoid setting LD_BIND_NOW=1 or upgrade gcc\n"),
|
"avoid setting LD_BIND_NOW=1 or upgrade gcc\n"),
|
h->root.root.string);
|
h->root.root.string);
|
}
|
}
|
|
|
/* This is a reference to a symbol defined by a dynamic object which
|
/* This is a reference to a symbol defined by a dynamic object which
|
is not a function. */
|
is not a function. */
|
|
|
if (h->size == 0)
|
if (h->size == 0)
|
{
|
{
|
info->callbacks->einfo (_("dynamic variable `%s' is zero size\n"),
|
info->callbacks->einfo (_("%P: dynamic variable `%s' is zero size\n"),
|
h->root.root.string);
|
h->root.root.string);
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
/* We must allocate the symbol in our .dynbss section, which will
|
/* We must allocate the symbol in our .dynbss section, which will
|
Line 6898... |
Line 6886... |
return TRUE;
|
return TRUE;
|
}
|
}
|
pp = &p->next;
|
pp = &p->next;
|
}
|
}
|
|
|
info->callbacks->einfo (_("dynreloc miscount for %B, section %A\n"),
|
info->callbacks->einfo (_("%P: dynreloc miscount for %B, section %A\n"),
|
sec->owner, sec);
|
sec->owner, sec);
|
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
Line 8277... |
Line 8265... |
*drop &= ~ref_from_discarded;
|
*drop &= ~ref_from_discarded;
|
if ((*drop & can_optimize) != 0)
|
if ((*drop & can_optimize) != 0)
|
some_unused = 1;
|
some_unused = 1;
|
last = 0;
|
last = 0;
|
}
|
}
|
else if (*drop)
|
else if (*drop & ref_from_discarded)
|
{
|
{
|
some_unused = 1;
|
some_unused = 1;
|
last = ref_from_discarded;
|
last = ref_from_discarded;
|
}
|
}
|
else
|
else
|
Line 9049... |
Line 9037... |
|| s == htab->dynbss)
|
|| s == htab->dynbss)
|
{
|
{
|
/* Strip this section if we don't need it; see the
|
/* Strip this section if we don't need it; see the
|
comment below. */
|
comment below. */
|
}
|
}
|
|
else if (s == htab->glink_eh_frame)
|
|
{
|
|
if (!bfd_is_abs_section (s->output_section))
|
|
/* Not sized yet. */
|
|
continue;
|
|
}
|
else if (CONST_STRNEQ (s->name, ".rela"))
|
else if (CONST_STRNEQ (s->name, ".rela"))
|
{
|
{
|
if (s->size != 0)
|
if (s->size != 0)
|
{
|
{
|
if (s != htab->relplt)
|
if (s != htab->relplt)
|
Line 9280... |
Line 9274... |
}
|
}
|
|
|
/* Build a .plt call stub. */
|
/* Build a .plt call stub. */
|
|
|
static inline bfd_byte *
|
static inline bfd_byte *
|
build_plt_stub (bfd *obfd, bfd_byte *p, int offset, Elf_Internal_Rela *r)
|
build_plt_stub (bfd *obfd, bfd_byte *p, int offset, Elf_Internal_Rela *r,
|
|
bfd_boolean plt_static_chain)
|
{
|
{
|
#define PPC_LO(v) ((v) & 0xffff)
|
#define PPC_LO(v) ((v) & 0xffff)
|
#define PPC_HI(v) (((v) >> 16) & 0xffff)
|
#define PPC_HI(v) (((v) >> 16) & 0xffff)
|
#define PPC_HA(v) PPC_HI ((v) + 0x8000)
|
#define PPC_HA(v) PPC_HI ((v) + 0x8000)
|
|
|
Line 9294... |
Line 9289... |
{
|
{
|
r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_HA);
|
r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_HA);
|
r[1].r_offset = r[0].r_offset + 8;
|
r[1].r_offset = r[0].r_offset + 8;
|
r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
r[1].r_addend = r[0].r_addend;
|
r[1].r_addend = r[0].r_addend;
|
if (PPC_HA (offset + 16) != PPC_HA (offset))
|
if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
{
|
{
|
r[2].r_offset = r[1].r_offset + 4;
|
r[2].r_offset = r[1].r_offset + 4;
|
r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO);
|
r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO);
|
r[2].r_addend = r[0].r_addend;
|
r[2].r_addend = r[0].r_addend;
|
}
|
}
|
else
|
else
|
{
|
{
|
r[2].r_offset = r[1].r_offset + 8;
|
r[2].r_offset = r[1].r_offset + 8;
|
r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
r[2].r_addend = r[0].r_addend + 8;
|
r[2].r_addend = r[0].r_addend + 8;
|
|
if (plt_static_chain)
|
|
{
|
r[3].r_offset = r[2].r_offset + 4;
|
r[3].r_offset = r[2].r_offset + 4;
|
r[3].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
r[3].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
r[3].r_addend = r[0].r_addend + 16;
|
r[3].r_addend = r[0].r_addend + 16;
|
}
|
}
|
}
|
}
|
|
}
|
bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p), p += 4;
|
bfd_put_32 (obfd, ADDIS_R12_R2 | PPC_HA (offset), p), p += 4;
|
bfd_put_32 (obfd, STD_R2_40R1, p), p += 4;
|
bfd_put_32 (obfd, STD_R2_40R1, p), p += 4;
|
bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p), p += 4;
|
bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset), p), p += 4;
|
if (PPC_HA (offset + 16) != PPC_HA (offset))
|
if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
{
|
{
|
bfd_put_32 (obfd, ADDI_R12_R12 | PPC_LO (offset), p), p += 4;
|
bfd_put_32 (obfd, ADDI_R12_R12 | PPC_LO (offset), p), p += 4;
|
offset = 0;
|
offset = 0;
|
}
|
}
|
bfd_put_32 (obfd, MTCTR_R11, p), p += 4;
|
bfd_put_32 (obfd, MTCTR_R11, p), p += 4;
|
bfd_put_32 (obfd, LD_R2_0R12 | PPC_LO (offset + 8), p), p += 4;
|
bfd_put_32 (obfd, LD_R2_0R12 | PPC_LO (offset + 8), p), p += 4;
|
|
if (plt_static_chain)
|
bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset + 16), p), p += 4;
|
bfd_put_32 (obfd, LD_R11_0R12 | PPC_LO (offset + 16), p), p += 4;
|
bfd_put_32 (obfd, BCTR, p), p += 4;
|
bfd_put_32 (obfd, BCTR, p), p += 4;
|
}
|
}
|
else
|
else
|
{
|
{
|
if (r != NULL)
|
if (r != NULL)
|
{
|
{
|
r[0].r_offset += 4;
|
r[0].r_offset += 4;
|
r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
if (PPC_HA (offset + 16) != PPC_HA (offset))
|
if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
{
|
{
|
r[1].r_offset = r[0].r_offset + 4;
|
r[1].r_offset = r[0].r_offset + 4;
|
r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16);
|
r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16);
|
r[1].r_addend = r[0].r_addend;
|
r[1].r_addend = r[0].r_addend;
|
}
|
}
|
else
|
else
|
{
|
{
|
r[1].r_offset = r[0].r_offset + 8;
|
r[1].r_offset = r[0].r_offset + 8;
|
r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
r[1].r_addend = r[0].r_addend + 16;
|
r[1].r_addend = r[0].r_addend + 8 + 8 * plt_static_chain;
|
|
if (plt_static_chain)
|
|
{
|
r[2].r_offset = r[1].r_offset + 4;
|
r[2].r_offset = r[1].r_offset + 4;
|
r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
r[2].r_addend = r[0].r_addend + 8;
|
r[2].r_addend = r[0].r_addend + 8;
|
}
|
}
|
}
|
}
|
|
}
|
bfd_put_32 (obfd, STD_R2_40R1, p), p += 4;
|
bfd_put_32 (obfd, STD_R2_40R1, p), p += 4;
|
bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset), p), p += 4;
|
bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset), p), p += 4;
|
if (PPC_HA (offset + 16) != PPC_HA (offset))
|
if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
{
|
{
|
bfd_put_32 (obfd, ADDI_R2_R2 | PPC_LO (offset), p), p += 4;
|
bfd_put_32 (obfd, ADDI_R2_R2 | PPC_LO (offset), p), p += 4;
|
offset = 0;
|
offset = 0;
|
}
|
}
|
bfd_put_32 (obfd, MTCTR_R11, p), p += 4;
|
bfd_put_32 (obfd, MTCTR_R11, p), p += 4;
|
|
if (plt_static_chain)
|
bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset + 16), p), p += 4;
|
bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset + 16), p), p += 4;
|
bfd_put_32 (obfd, LD_R2_0R2 | PPC_LO (offset + 8), p), p += 4;
|
bfd_put_32 (obfd, LD_R2_0R2 | PPC_LO (offset + 8), p), p += 4;
|
bfd_put_32 (obfd, BCTR, p), p += 4;
|
bfd_put_32 (obfd, BCTR, p), p += 4;
|
}
|
}
|
return p;
|
return p;
|
Line 9378... |
Line 9381... |
#define LD_R2_0R1 0xe8410000
|
#define LD_R2_0R1 0xe8410000
|
#define MTLR_R11 0x7d6803a6
|
#define MTLR_R11 0x7d6803a6
|
|
|
static inline bfd_byte *
|
static inline bfd_byte *
|
build_tls_get_addr_stub (bfd *obfd, bfd_byte *p, int offset,
|
build_tls_get_addr_stub (bfd *obfd, bfd_byte *p, int offset,
|
Elf_Internal_Rela *r)
|
Elf_Internal_Rela *r, bfd_boolean plt_static_chain)
|
{
|
{
|
bfd_put_32 (obfd, LD_R11_0R3 + 0, p), p += 4;
|
bfd_put_32 (obfd, LD_R11_0R3 + 0, p), p += 4;
|
bfd_put_32 (obfd, LD_R12_0R3 + 8, p), p += 4;
|
bfd_put_32 (obfd, LD_R12_0R3 + 8, p), p += 4;
|
bfd_put_32 (obfd, MR_R0_R3, p), p += 4;
|
bfd_put_32 (obfd, MR_R0_R3, p), p += 4;
|
bfd_put_32 (obfd, CMPDI_R11_0, p), p += 4;
|
bfd_put_32 (obfd, CMPDI_R11_0, p), p += 4;
|
Line 9392... |
Line 9395... |
bfd_put_32 (obfd, MFLR_R11, p), p += 4;
|
bfd_put_32 (obfd, MFLR_R11, p), p += 4;
|
bfd_put_32 (obfd, STD_R11_0R1 + 32, p), p += 4;
|
bfd_put_32 (obfd, STD_R11_0R1 + 32, p), p += 4;
|
|
|
if (r != NULL)
|
if (r != NULL)
|
r[0].r_offset += 9 * 4;
|
r[0].r_offset += 9 * 4;
|
p = build_plt_stub (obfd, p, offset, r);
|
p = build_plt_stub (obfd, p, offset, r, plt_static_chain);
|
bfd_put_32 (obfd, BCTRL, p - 4);
|
bfd_put_32 (obfd, BCTRL, p - 4);
|
|
|
bfd_put_32 (obfd, LD_R11_0R1 + 32, p), p += 4;
|
bfd_put_32 (obfd, LD_R11_0R1 + 32, p), p += 4;
|
bfd_put_32 (obfd, LD_R2_0R1 + 40, p), p += 4;
|
bfd_put_32 (obfd, LD_R2_0R1 + 40, p), p += 4;
|
bfd_put_32 (obfd, MTLR_R11, p), p += 4;
|
bfd_put_32 (obfd, MTLR_R11, p), p += 4;
|
Line 9451... |
Line 9454... |
bfd_vma opd_off = stub_entry->h->elf.root.u.def.value;
|
bfd_vma opd_off = stub_entry->h->elf.root.u.def.value;
|
|
|
if (strcmp (opd->name, ".opd") != 0
|
if (strcmp (opd->name, ".opd") != 0
|
|| opd->reloc_count != 0)
|
|| opd->reloc_count != 0)
|
{
|
{
|
info->callbacks->einfo (_("cannot find opd entry toc for %s\n"),
|
info->callbacks->einfo (_("%P: cannot find opd entry toc for %s\n"),
|
stub_entry->h->elf.root.root.string);
|
stub_entry->h->elf.root.root.string);
|
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
return 0;
|
return 0;
|
}
|
}
|
if (!bfd_get_section_contents (opd->owner, opd, buf, opd_off + 8, 8))
|
if (!bfd_get_section_contents (opd->owner, opd, buf, opd_off + 8, 8))
|
Line 9533... |
Line 9536... |
}
|
}
|
bfd_put_32 (htab->stub_bfd, B_DOT | (off & 0x3fffffc), loc);
|
bfd_put_32 (htab->stub_bfd, B_DOT | (off & 0x3fffffc), loc);
|
|
|
if (off + (1 << 25) >= (bfd_vma) (1 << 26))
|
if (off + (1 << 25) >= (bfd_vma) (1 << 26))
|
{
|
{
|
info->callbacks->einfo (_("long branch stub `%s' offset overflow\n"),
|
info->callbacks->einfo (_("%P: long branch stub `%s' offset overflow\n"),
|
stub_entry->root.string);
|
stub_entry->root.string);
|
htab->stub_error = TRUE;
|
htab->stub_error = TRUE;
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
Line 9592... |
Line 9595... |
br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table,
|
br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table,
|
stub_entry->root.string + 9,
|
stub_entry->root.string + 9,
|
FALSE, FALSE);
|
FALSE, FALSE);
|
if (br_entry == NULL)
|
if (br_entry == NULL)
|
{
|
{
|
info->callbacks->einfo (_("can't find branch stub `%s'\n"),
|
info->callbacks->einfo (_("%P: can't find branch stub `%s'\n"),
|
stub_entry->root.string);
|
stub_entry->root.string);
|
htab->stub_error = TRUE;
|
htab->stub_error = TRUE;
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
Line 9654... |
Line 9657... |
- htab->stub_group[stub_entry->id_sec->id].toc_off);
|
- htab->stub_group[stub_entry->id_sec->id].toc_off);
|
|
|
if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
|
if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
|
{
|
{
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(_("linkage table error against `%s'\n"),
|
(_("%P: linkage table error against `%s'\n"),
|
stub_entry->root.string);
|
stub_entry->root.string);
|
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
htab->stub_error = TRUE;
|
htab->stub_error = TRUE;
|
return FALSE;
|
return FALSE;
|
}
|
}
|
Line 9796... |
Line 9799... |
- htab->stub_group[stub_entry->id_sec->id].toc_off);
|
- htab->stub_group[stub_entry->id_sec->id].toc_off);
|
|
|
if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
|
if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
|
{
|
{
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(_("linkage table error against `%s'\n"),
|
(_("%P: linkage table error against `%s'\n"),
|
stub_entry->h != NULL
|
stub_entry->h != NULL
|
? stub_entry->h->elf.root.root.string
|
? stub_entry->h->elf.root.root.string
|
: "<local sym>");
|
: "<local sym>");
|
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
htab->stub_error = TRUE;
|
htab->stub_error = TRUE;
|
Line 9809... |
Line 9812... |
|
|
r = NULL;
|
r = NULL;
|
if (info->emitrelocations)
|
if (info->emitrelocations)
|
{
|
{
|
r = get_relocs (stub_entry->stub_sec,
|
r = get_relocs (stub_entry->stub_sec,
|
(2 + (PPC_HA (off) != 0)
|
(2
|
+ (PPC_HA (off + 16) == PPC_HA (off))));
|
+ (PPC_HA (off) != 0)
|
|
+ (htab->plt_static_chain
|
|
&& PPC_HA (off + 16) == PPC_HA (off))));
|
if (r == NULL)
|
if (r == NULL)
|
return FALSE;
|
return FALSE;
|
r[0].r_offset = loc - stub_entry->stub_sec->contents;
|
r[0].r_offset = loc - stub_entry->stub_sec->contents;
|
if (bfd_big_endian (info->output_bfd))
|
if (bfd_big_endian (info->output_bfd))
|
r[0].r_offset += 2;
|
r[0].r_offset += 2;
|
Line 9822... |
Line 9827... |
}
|
}
|
if (stub_entry->h != NULL
|
if (stub_entry->h != NULL
|
&& (stub_entry->h == htab->tls_get_addr_fd
|
&& (stub_entry->h == htab->tls_get_addr_fd
|
|| stub_entry->h == htab->tls_get_addr)
|
|| stub_entry->h == htab->tls_get_addr)
|
&& !htab->no_tls_get_addr_opt)
|
&& !htab->no_tls_get_addr_opt)
|
p = build_tls_get_addr_stub (htab->stub_bfd, loc, off, r);
|
p = build_tls_get_addr_stub (htab->stub_bfd, loc, off, r,
|
|
htab->plt_static_chain);
|
else
|
else
|
p = build_plt_stub (htab->stub_bfd, loc, off, r);
|
p = build_plt_stub (htab->stub_bfd, loc, off, r,
|
|
htab->plt_static_chain);
|
size = p - loc;
|
size = p - loc;
|
break;
|
break;
|
|
|
default:
|
default:
|
BFD_FAIL ();
|
BFD_FAIL ();
|
Line 9911... |
Line 9918... |
+ plt->output_section->vma
|
+ plt->output_section->vma
|
- elf_gp (plt->output_section->owner)
|
- elf_gp (plt->output_section->owner)
|
- htab->stub_group[stub_entry->id_sec->id].toc_off);
|
- htab->stub_group[stub_entry->id_sec->id].toc_off);
|
|
|
size = PLT_CALL_STUB_SIZE;
|
size = PLT_CALL_STUB_SIZE;
|
|
if (!htab->plt_static_chain)
|
|
size -= 4;
|
if (PPC_HA (off) == 0)
|
if (PPC_HA (off) == 0)
|
size -= 4;
|
size -= 4;
|
if (PPC_HA (off + 16) != PPC_HA (off))
|
if (PPC_HA (off + 8 + 8 * htab->plt_static_chain) != PPC_HA (off))
|
size += 4;
|
size += 4;
|
if (stub_entry->h != NULL
|
if (stub_entry->h != NULL
|
&& (stub_entry->h == htab->tls_get_addr_fd
|
&& (stub_entry->h == htab->tls_get_addr_fd
|
|| stub_entry->h == htab->tls_get_addr)
|
|| stub_entry->h == htab->tls_get_addr)
|
&& !htab->no_tls_get_addr_opt)
|
&& !htab->no_tls_get_addr_opt)
|
size += 13 * 4;
|
size += 13 * 4;
|
if (info->emitrelocations)
|
if (info->emitrelocations)
|
{
|
{
|
stub_entry->stub_sec->reloc_count
|
stub_entry->stub_sec->reloc_count
|
+= 2 + (PPC_HA (off) != 0) + (PPC_HA (off + 16) == PPC_HA (off));
|
+= (2
|
|
+ (PPC_HA (off) != 0)
|
|
+ (htab->plt_static_chain
|
|
&& PPC_HA (off + 16) == PPC_HA (off)));
|
stub_entry->stub_sec->flags |= SEC_RELOC;
|
stub_entry->stub_sec->flags |= SEC_RELOC;
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
Line 9970... |
Line 9982... |
br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table,
|
br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table,
|
stub_entry->root.string + 9,
|
stub_entry->root.string + 9,
|
TRUE, FALSE);
|
TRUE, FALSE);
|
if (br_entry == NULL)
|
if (br_entry == NULL)
|
{
|
{
|
info->callbacks->einfo (_("can't build branch stub `%s'\n"),
|
info->callbacks->einfo (_("%P: can't build branch stub `%s'\n"),
|
stub_entry->root.string);
|
stub_entry->root.string);
|
htab->stub_error = TRUE;
|
htab->stub_error = TRUE;
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
Line 10843... |
Line 10855... |
while (list-- != htab->input_list);
|
while (list-- != htab->input_list);
|
free (htab->input_list);
|
free (htab->input_list);
|
#undef PREV_SEC
|
#undef PREV_SEC
|
}
|
}
|
|
|
|
static const unsigned char glink_eh_frame_cie[] =
|
|
{
|
|
0, 0, 0, 16, /* length. */
|
|
0, 0, 0, 0, /* id. */
|
|
1, /* CIE version. */
|
|
'z', 'R', 0, /* Augmentation string. */
|
|
4, /* Code alignment. */
|
|
0x78, /* Data alignment. */
|
|
65, /* RA reg. */
|
|
1, /* Augmentation size. */
|
|
DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding. */
|
|
DW_CFA_def_cfa, 1, 0 /* def_cfa: r1 offset 0. */
|
|
};
|
|
|
|
/* Stripping output sections is normally done before dynamic section
|
|
symbols have been allocated. This function is called later, and
|
|
handles cases like htab->brlt which is mapped to its own output
|
|
section. */
|
|
|
|
static void
|
|
maybe_strip_output (struct bfd_link_info *info, asection *isec)
|
|
{
|
|
if (isec->size == 0
|
|
&& isec->output_section->size == 0
|
|
&& !bfd_section_removed_from_list (info->output_bfd,
|
|
isec->output_section)
|
|
&& elf_section_data (isec->output_section)->dynindx == 0)
|
|
{
|
|
isec->output_section->flags |= SEC_EXCLUDE;
|
|
bfd_section_list_remove (info->output_bfd, isec->output_section);
|
|
info->output_bfd->section_count--;
|
|
}
|
|
}
|
|
|
/* Determine and set the size of the stub section for a final link.
|
/* Determine and set the size of the stub section for a final link.
|
|
|
The basic idea here is to examine all the relocations looking for
|
The basic idea here is to examine all the relocations looking for
|
PC-relative calls to a target that is unreachable with a "bl"
|
PC-relative calls to a target that is unreachable with a "bl"
|
instruction. */
|
instruction. */
|
|
|
bfd_boolean
|
bfd_boolean
|
ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size)
|
ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
|
|
bfd_boolean plt_static_chain)
|
{
|
{
|
bfd_size_type stub_group_size;
|
bfd_size_type stub_group_size;
|
bfd_boolean stubs_always_before_branch;
|
bfd_boolean stubs_always_before_branch;
|
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
|
|
if (htab == NULL)
|
if (htab == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
|
htab->plt_static_chain = plt_static_chain;
|
stubs_always_before_branch = group_size < 0;
|
stubs_always_before_branch = group_size < 0;
|
if (group_size < 0)
|
if (group_size < 0)
|
stub_group_size = -group_size;
|
stub_group_size = -group_size;
|
else
|
else
|
stub_group_size = group_size;
|
stub_group_size = group_size;
|
Line 11184... |
Line 11232... |
{
|
{
|
htab->glink->reloc_count = 1;
|
htab->glink->reloc_count = 1;
|
htab->glink->flags |= SEC_RELOC;
|
htab->glink->flags |= SEC_RELOC;
|
}
|
}
|
|
|
|
if (htab->glink_eh_frame != NULL
|
|
&& !bfd_is_abs_section (htab->glink_eh_frame->output_section)
|
|
&& (htab->glink_eh_frame->flags & SEC_EXCLUDE) == 0)
|
|
{
|
|
bfd_size_type size = 0;
|
|
|
|
for (stub_sec = htab->stub_bfd->sections;
|
|
stub_sec != NULL;
|
|
stub_sec = stub_sec->next)
|
|
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
|
size += 20;
|
|
if (htab->glink != NULL && htab->glink->size != 0)
|
|
size += 24;
|
|
if (size != 0)
|
|
size += sizeof (glink_eh_frame_cie);
|
|
htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size;
|
|
htab->glink_eh_frame->size = size;
|
|
}
|
|
|
for (stub_sec = htab->stub_bfd->sections;
|
for (stub_sec = htab->stub_bfd->sections;
|
stub_sec != NULL;
|
stub_sec != NULL;
|
stub_sec = stub_sec->next)
|
stub_sec = stub_sec->next)
|
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
|
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0
|
&& stub_sec->rawsize != stub_sec->size)
|
&& stub_sec->rawsize != stub_sec->size)
|
break;
|
break;
|
|
|
/* Exit from this loop when no stubs have been added, and no stubs
|
/* Exit from this loop when no stubs have been added, and no stubs
|
have changed size. */
|
have changed size. */
|
if (stub_sec == NULL)
|
if (stub_sec == NULL
|
|
&& (htab->glink_eh_frame == NULL
|
|
|| htab->glink_eh_frame->rawsize == htab->glink_eh_frame->size))
|
break;
|
break;
|
|
|
/* Ask the linker to do its stuff. */
|
/* Ask the linker to do its stuff. */
|
(*htab->layout_sections_again) ();
|
(*htab->layout_sections_again) ();
|
}
|
}
|
|
|
/* It would be nice to strip htab->brlt from the output if the
|
maybe_strip_output (info, htab->brlt);
|
section is empty, but it's too late. If we strip sections here,
|
if (htab->glink_eh_frame != NULL)
|
the dynamic symbol table is corrupted since the section symbol
|
maybe_strip_output (info, htab->glink_eh_frame);
|
for the stripped section isn't written. */
|
|
|
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
/* Called after we have determined section placement. If sections
|
/* Called after we have determined section placement. If sections
|
Line 11408... |
Line 11476... |
htab->relbrlt->size);
|
htab->relbrlt->size);
|
if (htab->relbrlt->contents == NULL)
|
if (htab->relbrlt->contents == NULL)
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
|
if (htab->glink_eh_frame != NULL
|
|
&& htab->glink_eh_frame->size != 0)
|
|
{
|
|
bfd_vma val;
|
|
|
|
p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
|
|
if (p == NULL)
|
|
return FALSE;
|
|
htab->glink_eh_frame->contents = p;
|
|
|
|
htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size;
|
|
|
|
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);
|
|
|
|
for (stub_sec = htab->stub_bfd->sections;
|
|
stub_sec != NULL;
|
|
stub_sec = stub_sec->next)
|
|
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
|
{
|
|
/* FDE length. */
|
|
bfd_put_32 (htab->elf.dynobj, 16, p);
|
|
p += 4;
|
|
/* CIE pointer. */
|
|
val = p - htab->glink_eh_frame->contents;
|
|
bfd_put_32 (htab->elf.dynobj, val, p);
|
|
p += 4;
|
|
/* Offset to stub section. */
|
|
val = (stub_sec->output_section->vma
|
|
+ stub_sec->output_offset);
|
|
val -= (htab->glink_eh_frame->output_section->vma
|
|
+ htab->glink_eh_frame->output_offset);
|
|
val -= p - htab->glink_eh_frame->contents;
|
|
if (val + 0x80000000 > 0xffffffff)
|
|
{
|
|
info->callbacks->einfo
|
|
(_("%P: %s offset too large for .eh_frame sdata4 encoding"),
|
|
stub_sec->name);
|
|
return FALSE;
|
|
}
|
|
bfd_put_32 (htab->elf.dynobj, val, p);
|
|
p += 4;
|
|
/* stub section size. */
|
|
bfd_put_32 (htab->elf.dynobj, stub_sec->rawsize, p);
|
|
p += 4;
|
|
/* Augmentation. */
|
|
p += 1;
|
|
/* Pad. */
|
|
p += 3;
|
|
}
|
|
if (htab->glink != NULL && htab->glink->size != 0)
|
|
{
|
|
/* FDE length. */
|
|
bfd_put_32 (htab->elf.dynobj, 20, 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->output_offset
|
|
+ 8);
|
|
val -= (htab->glink_eh_frame->output_section->vma
|
|
+ htab->glink_eh_frame->output_offset);
|
|
val -= p - htab->glink_eh_frame->contents;
|
|
if (val + 0x80000000 > 0xffffffff)
|
|
{
|
|
info->callbacks->einfo
|
|
(_("%P: %s offset too large for .eh_frame sdata4 encoding"),
|
|
htab->glink->name);
|
|
return FALSE;
|
|
}
|
|
bfd_put_32 (htab->elf.dynobj, val, p);
|
|
p += 4;
|
|
/* .glink size. */
|
|
bfd_put_32 (htab->elf.dynobj, htab->glink->rawsize - 8, p);
|
|
p += 4;
|
|
/* Augmentation. */
|
|
p += 1;
|
|
|
|
*p++ = DW_CFA_advance_loc + 1;
|
|
*p++ = DW_CFA_register;
|
|
*p++ = 65;
|
|
*p++ = 12;
|
|
*p++ = DW_CFA_advance_loc + 4;
|
|
*p++ = DW_CFA_restore_extended;
|
|
*p++ = 65;
|
|
}
|
|
htab->glink_eh_frame->size = p - htab->glink_eh_frame->contents;
|
|
}
|
|
|
/* Build the stubs as directed by the stub hash table. */
|
/* Build the stubs as directed by the stub hash table. */
|
bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
|
bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
|
|
|
if (htab->relbrlt != NULL)
|
if (htab->relbrlt != NULL)
|
htab->relbrlt->reloc_count = 0;
|
htab->relbrlt->reloc_count = 0;
|
Line 11425... |
Line 11587... |
if (stub_sec->rawsize != stub_sec->size)
|
if (stub_sec->rawsize != stub_sec->size)
|
break;
|
break;
|
}
|
}
|
|
|
if (stub_sec != NULL
|
if (stub_sec != NULL
|
|| htab->glink->rawsize != htab->glink->size)
|
|| htab->glink->rawsize != htab->glink->size
|
|
|| (htab->glink_eh_frame != NULL
|
|
&& htab->glink_eh_frame->rawsize != htab->glink_eh_frame->size))
|
{
|
{
|
htab->stub_error = TRUE;
|
htab->stub_error = TRUE;
|
info->callbacks->einfo (_("stubs don't match calculated size\n"));
|
info->callbacks->einfo (_("%P: stubs don't match calculated size\n"));
|
}
|
}
|
|
|
if (htab->stub_error)
|
if (htab->stub_error)
|
return FALSE;
|
return FALSE;
|
|
|
Line 11787... |
Line 11951... |
/* R_PPC64_TLS is OK against a symbol in the TOC. */
|
/* R_PPC64_TLS is OK against a symbol in the TOC. */
|
;
|
;
|
else
|
else
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(!IS_PPC64_TLS_RELOC (r_type)
|
(!IS_PPC64_TLS_RELOC (r_type)
|
? _("%H: %s used with TLS symbol %s\n")
|
? _("%P: %H: %s used with TLS symbol %s\n")
|
: _("%H: %s used with non-TLS symbol %s\n"),
|
: _("%P: %H: %s used with non-TLS symbol %s\n"),
|
input_bfd, input_section, rel->r_offset,
|
input_bfd, input_section, rel->r_offset,
|
ppc64_elf_howto_table[r_type]->name,
|
ppc64_elf_howto_table[r_type]->name,
|
sym_name);
|
sym_name);
|
}
|
}
|
|
|
Line 12286... |
Line 12450... |
if (strcmp (input_section->output_section->name,
|
if (strcmp (input_section->output_section->name,
|
".init") == 0
|
".init") == 0
|
|| strcmp (input_section->output_section->name,
|
|| strcmp (input_section->output_section->name,
|
".fini") == 0)
|
".fini") == 0)
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(_("%H: automatic multiple TOCs "
|
(_("%P: %H: automatic multiple TOCs "
|
"not supported using your crt files; "
|
"not supported using your crt files; "
|
"recompile with -mminimal-toc or upgrade gcc\n"),
|
"recompile with -mminimal-toc or upgrade gcc\n"),
|
input_bfd, input_section, rel->r_offset);
|
input_bfd, input_section, rel->r_offset);
|
else
|
else
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(_("%H: sibling call optimization to `%s' "
|
(_("%P: %H: sibling call optimization to `%s' "
|
"does not allow automatic multiple TOCs; "
|
"does not allow automatic multiple TOCs; "
|
"recompile with -mminimal-toc or "
|
"recompile with -mminimal-toc or "
|
"-fno-optimize-sibling-calls, "
|
"-fno-optimize-sibling-calls, "
|
"or make `%s' extern\n"),
|
"or make `%s' extern\n"),
|
input_bfd, input_section, rel->r_offset,
|
input_bfd, input_section, rel->r_offset,
|
Line 12399... |
Line 12563... |
tls_type = 0;
|
tls_type = 0;
|
switch (r_type)
|
switch (r_type)
|
{
|
{
|
default:
|
default:
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(_("%B: unknown relocation type %d for symbol %s\n"),
|
(_("%P: %B: unknown relocation type %d for symbol %s\n"),
|
input_bfd, (int) r_type, sym_name);
|
input_bfd, (int) r_type, sym_name);
|
|
|
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
ret = FALSE;
|
ret = FALSE;
|
continue;
|
continue;
|
Line 12904... |
Line 13068... |
if (h != NULL
|
if (h != NULL
|
? h->elf.type == STT_GNU_IFUNC
|
? h->elf.type == STT_GNU_IFUNC
|
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
|
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
|
{
|
{
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(_("%H: relocation %s for indirect "
|
(_("%P: %H: relocation %s for indirect "
|
"function %s unsupported\n"),
|
"function %s unsupported\n"),
|
input_bfd, input_section, rel->r_offset,
|
input_bfd, input_section, rel->r_offset,
|
ppc64_elf_howto_table[r_type]->name,
|
ppc64_elf_howto_table[r_type]->name,
|
sym_name);
|
sym_name);
|
ret = FALSE;
|
ret = FALSE;
|
Line 13009... |
Line 13173... |
case R_PPC64_PLTREL32:
|
case R_PPC64_PLTREL32:
|
case R_PPC64_PLTREL64:
|
case R_PPC64_PLTREL64:
|
/* These ones haven't been implemented yet. */
|
/* These ones haven't been implemented yet. */
|
|
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(_("%B: relocation %s is not supported for symbol %s\n"),
|
(_("%P: %B: relocation %s is not supported for symbol %s\n"),
|
input_bfd,
|
input_bfd,
|
ppc64_elf_howto_table[r_type]->name, sym_name);
|
ppc64_elf_howto_table[r_type]->name, sym_name);
|
|
|
bfd_set_error (bfd_error_invalid_operation);
|
bfd_set_error (bfd_error_invalid_operation);
|
ret = FALSE;
|
ret = FALSE;
|
Line 13186... |
Line 13350... |
if ((insn & (0x3f << 26)) == (56u << 26))
|
if ((insn & (0x3f << 26)) == (56u << 26))
|
mask = 15;
|
mask = 15;
|
if (((relocation + addend) & mask) != 0)
|
if (((relocation + addend) & mask) != 0)
|
{
|
{
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(_("%H: error: %s not a multiple of %u\n"),
|
(_("%P: %H: error: %s not a multiple of %u\n"),
|
input_bfd, input_section, rel->r_offset,
|
input_bfd, input_section, rel->r_offset,
|
ppc64_elf_howto_table[r_type]->name,
|
ppc64_elf_howto_table[r_type]->name,
|
mask + 1);
|
mask + 1);
|
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
ret = FALSE;
|
ret = FALSE;
|
Line 13205... |
Line 13369... |
if (unresolved_reloc
|
if (unresolved_reloc
|
&& !((input_section->flags & SEC_DEBUGGING) != 0
|
&& !((input_section->flags & SEC_DEBUGGING) != 0
|
&& h->elf.def_dynamic))
|
&& h->elf.def_dynamic))
|
{
|
{
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(_("%H: unresolvable %s relocation against symbol `%s'\n"),
|
(_("%P: %H: unresolvable %s relocation against symbol `%s'\n"),
|
input_bfd, input_section, rel->r_offset,
|
input_bfd, input_section, rel->r_offset,
|
ppc64_elf_howto_table[(int) r_type]->name,
|
ppc64_elf_howto_table[(int) r_type]->name,
|
h->elf.root.root.string);
|
h->elf.root.root.string);
|
ret = FALSE;
|
ret = FALSE;
|
}
|
}
|
Line 13250... |
Line 13414... |
return FALSE;
|
return FALSE;
|
}
|
}
|
else
|
else
|
{
|
{
|
info->callbacks->einfo
|
info->callbacks->einfo
|
(_("%H: %s reloc against `%s': error %d\n"),
|
(_("%P: %H: %s reloc against `%s': error %d\n"),
|
input_bfd, input_section, rel->r_offset,
|
input_bfd, input_section, rel->r_offset,
|
ppc64_elf_howto_table[r_type]->name,
|
ppc64_elf_howto_table[r_type]->name,
|
sym_name,
|
sym_name,
|
(int) r);
|
(int) r);
|
ret = FALSE;
|
ret = FALSE;
|
Line 13574... |
Line 13738... |
elf_section_data (htab->glink)->rela.hdr,
|
elf_section_data (htab->glink)->rela.hdr,
|
elf_section_data (htab->glink)->relocs,
|
elf_section_data (htab->glink)->relocs,
|
NULL))
|
NULL))
|
return FALSE;
|
return FALSE;
|
|
|
|
|
|
if (htab->glink_eh_frame != NULL
|
|
&& htab->glink_eh_frame->sec_info_type == ELF_INFO_TYPE_EH_FRAME
|
|
&& !_bfd_elf_write_section_eh_frame (output_bfd, info,
|
|
htab->glink_eh_frame,
|
|
htab->glink_eh_frame->contents))
|
|
return FALSE;
|
|
|
/* We need to handle writing out multiple GOT sections ourselves,
|
/* We need to handle writing out multiple GOT sections ourselves,
|
since we didn't add them to DYNOBJ. We know dynobj is the first
|
since we didn't add them to DYNOBJ. We know dynobj is the first
|
bfd. */
|
bfd. */
|
while ((dynobj = dynobj->link_next) != NULL)
|
while ((dynobj = dynobj->link_next) != NULL)
|
{
|
{
|