Linker foreign output format support for PowerPC64 ELFv2

Makes the ld srec tests pass.  Uses a horrible scan through symbols to
find ELF fields for symbol definitions, but the generic linker doesn't
offer anything better.  Might be slow.  Anyway, sane people will link
to ELF output then objcopy to convert formats.

	* elf64-ppc.c (abiversion, set_abiversion): Move earlier.
	(ppc64_elf_branch_reloc): Adjust addend for ELFv2 local offset.
	(ppc64_elf_set_toc): Set ".TOC." symbol value when using
	generic linker.
	(ppc64_elf_relocate_section): Disable ELFv2 function entry
	optimisation when --traditional-format.
This commit is contained in:
Alan Modra 2014-07-01 13:06:20 +09:30
parent f36e88862f
commit 810d4e754d
2 changed files with 61 additions and 19 deletions

View file

@ -1,3 +1,12 @@
2014-07-01 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (abiversion, set_abiversion): Move earlier.
(ppc64_elf_branch_reloc): Adjust addend for ELFv2 local offset.
(ppc64_elf_set_toc): Set ".TOC." symbol value when using
generic linker.
(ppc64_elf_relocate_section): Disable ELFv2 function entry
optimisation when --traditional-format.
2014-07-01 Barney Stratford <barney_stratford@fastmail.fm>
Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
Pitchumani Sivanupandi <pitchumani.s@atmel.com>
@ -188,7 +197,7 @@
2014-06-04 Will Newton <will.newton@linaro.org>
* elfnn-aarch64.c (tpoff_base): Make test of tls_sec
* elfnn-aarch64.c (tpoff_base): Make test of tls_sec
being non-NULL into an assert.
(elfNN_aarch64_tls_relax): Remove unused code.

View file

@ -235,6 +235,19 @@ static bfd_vma opd_entry_value
#ifndef NO_OPD_RELOCS
#define NO_OPD_RELOCS 0
#endif
static inline int
abiversion (bfd *abfd)
{
return elf_elfheader (abfd)->e_flags & EF_PPC64_ABI;
}
static inline void
set_abiversion (bfd *abfd, int ver)
{
elf_elfheader (abfd)->e_flags &= ~EF_PPC64_ABI;
elf_elfheader (abfd)->e_flags |= ver & EF_PPC64_ABI;
}
#define ONES(n) (((bfd_vma) 1 << ((n) - 1) << 1) - 1)
@ -2487,6 +2500,29 @@ ppc64_elf_branch_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
+ symbol->section->output_section->vma
+ symbol->section->output_offset);
}
else
{
elf_symbol_type *elfsym = (elf_symbol_type *) symbol;
if (symbol->section->owner != abfd
&& abiversion (symbol->section->owner) >= 2)
{
unsigned int i;
for (i = 0; i < symbol->section->owner->symcount; ++i)
{
asymbol *symdef = symbol->section->owner->outsymbols[i];
if (strcmp (symdef->name, symbol->name) == 0)
{
elfsym = (elf_symbol_type *) symdef;
break;
}
}
}
reloc_entry->addend
+= PPC64_LOCAL_ENTRY_OFFSET (elfsym->internal_elf_sym.st_other);
}
return bfd_reloc_continue;
}
@ -2975,19 +3011,6 @@ get_opd_info (asection * sec)
return &ppc64_elf_section_data (sec)->u.opd;
return NULL;
}
static inline int
abiversion (bfd *abfd)
{
return elf_elfheader (abfd)->e_flags & EF_PPC64_ABI;
}
static inline void
set_abiversion (bfd *abfd, int ver)
{
elf_elfheader (abfd)->e_flags &= ~EF_PPC64_ABI;
elf_elfheader (abfd)->e_flags |= ver & EF_PPC64_ABI;
}
/* Parameters for the qsort hook. */
static bfd_boolean synthetic_relocatable;
@ -12394,15 +12417,24 @@ ppc64_elf_set_toc (struct bfd_link_info *info, bfd *obfd)
_bfd_set_gp_value (obfd, TOCstart);
if (info != NULL && s != NULL && is_ppc64_elf (obfd))
if (info != NULL && s != NULL)
{
struct ppc_link_hash_table *htab = ppc_hash_table (info);
if (htab != NULL
&& htab->elf.hgot != NULL)
if (htab != NULL)
{
htab->elf.hgot->root.u.def.value = TOC_BASE_OFF;
htab->elf.hgot->root.u.def.section = s;
if (htab->elf.hgot != NULL)
{
htab->elf.hgot->root.u.def.value = TOC_BASE_OFF;
htab->elf.hgot->root.u.def.section = s;
}
}
else
{
struct bfd_link_hash_entry *bh = NULL;
_bfd_generic_link_add_one_symbol (info, obfd, ".TOC.", BSF_GLOBAL,
s, TOC_BASE_OFF, NULL, FALSE,
FALSE, &bh);
}
}
return TOCstart;
@ -13544,6 +13576,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
. addi 2,2,.TOC.@l
if .TOC. is in range. */
if (!info->shared
&& !info->traditional_format
&& h != NULL && &h->elf == htab->elf.hgot
&& rel + 1 < relend
&& rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_REL16_LO)