|
|
commit ee67d69a3ff0eed25d98c5e97ed6c3ede8069edc |
|
|
Author: Alan Modra <amodra@gmail.com> |
|
|
Date: Tue Oct 29 15:06:09 2013 +1030 |
|
|
|
|
|
Add .abiversion related support for ELFv2 |
|
|
|
|
|
Defines bits in ELF e_flags to differentiate ELFv2 objects from ELFv2, |
|
|
adds .abiversion directive to explicitly choose the ABI, and code to |
|
|
check and automatically select ABI. |
|
|
|
|
|
include/elf/ |
|
|
* ppc64.h (EF_PPC64_ABI): Define. |
|
|
bfd/ |
|
|
* elf64-ppc.c (abiversion, set_abiversion): New functions. |
|
|
(ppc64_elf_get_synthetic_symtab): Handle ELFv2 objects without .opd. |
|
|
(struct ppc_link_hash_table): Add opd_abi. |
|
|
(ppc64_elf_check_relocs): Check no .opd with ELFv2. |
|
|
(ppc64_elf_merge_private_bfd_data): New function. |
|
|
(ppc64_elf_print_private_bfd_data): New function. |
|
|
(ppc64_elf_tls_setup): Set htab->opd_abi. |
|
|
(ppc64_elf_size_dynamic_sections): Don't emit OPD related dynamic |
|
|
tags for ELFv2. |
|
|
(ppc_build_one_stub): Use R_PPC64_IRELATIVE for ELFv2 ifunc. |
|
|
(ppc64_elf_finish_dynamic_symbol): Likewise |
|
|
binutils/ |
|
|
* readelf.c (get_machine_flags): Display ABI version for EM_PPC64. |
|
|
gas/ |
|
|
* config/tc-ppc.c: Include elf/ppc64.h. |
|
|
(ppc_abiversion): New variable. |
|
|
(md_pseudo_table): Add .abiversion. |
|
|
(ppc_elf_abiversion, ppc_elf_end): New functions. |
|
|
* config/tc-ppc.h (md_end): Define. |
|
|
|
|
|
Index: gdb-7.6.1/bfd/elf64-ppc.c |
|
|
=================================================================== |
|
|
--- gdb-7.6.1.orig/bfd/elf64-ppc.c |
|
|
+++ gdb-7.6.1/bfd/elf64-ppc.c |
|
|
@@ -81,7 +81,8 @@ static bfd_vma opd_entry_value |
|
|
#define bfd_elf64_mkobject ppc64_elf_mkobject |
|
|
#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_merge_private_bfd_data _bfd_generic_verify_endian_match |
|
|
+#define bfd_elf64_bfd_merge_private_bfd_data ppc64_elf_merge_private_bfd_data |
|
|
+#define bfd_elf64_bfd_print_private_bfd_data ppc64_elf_print_private_bfd_data |
|
|
#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_free ppc64_elf_link_hash_table_free |
|
|
@@ -2836,6 +2837,19 @@ 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; |
|
|
@@ -2982,15 +2996,19 @@ ppc64_elf_get_synthetic_symtab (bfd *abf |
|
|
long count; |
|
|
char *names; |
|
|
long symcount, codesecsym, codesecsymend, secsymend, opdsymend; |
|
|
- asection *opd; |
|
|
+ asection *opd = NULL; |
|
|
bfd_boolean relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0; |
|
|
asymbol **syms; |
|
|
+ int abi = abiversion (abfd); |
|
|
|
|
|
*ret = NULL; |
|
|
|
|
|
- opd = bfd_get_section_by_name (abfd, ".opd"); |
|
|
- if (opd == NULL) |
|
|
- return 0; |
|
|
+ if (abi < 2) |
|
|
+ { |
|
|
+ opd = bfd_get_section_by_name (abfd, ".opd"); |
|
|
+ if (opd == NULL && abi == 1) |
|
|
+ return 0; |
|
|
+ } |
|
|
|
|
|
symcount = static_count; |
|
|
if (!relocatable) |
|
|
@@ -3159,20 +3177,18 @@ ppc64_elf_get_synthetic_symtab (bfd *abf |
|
|
else |
|
|
{ |
|
|
bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean); |
|
|
- bfd_byte *contents; |
|
|
+ bfd_byte *contents = NULL; |
|
|
size_t size; |
|
|
long plt_count = 0; |
|
|
bfd_vma glink_vma = 0, resolv_vma = 0; |
|
|
asection *dynamic, *glink = NULL, *relplt = NULL; |
|
|
arelent *p; |
|
|
|
|
|
- if (!bfd_malloc_and_get_section (abfd, opd, &contents)) |
|
|
+ if (opd != NULL && !bfd_malloc_and_get_section (abfd, opd, &contents)) |
|
|
{ |
|
|
+ free_contents_and_exit: |
|
|
if (contents) |
|
|
- { |
|
|
- free_contents_and_exit: |
|
|
- free (contents); |
|
|
- } |
|
|
+ free (contents); |
|
|
count = -1; |
|
|
goto done; |
|
|
} |
|
|
@@ -3772,6 +3788,9 @@ struct ppc_link_hash_table |
|
|
/* Alignment of PLT call stubs. */ |
|
|
unsigned int plt_stub_align:4; |
|
|
|
|
|
+ /* Set if we're linking code with function descriptors. */ |
|
|
+ unsigned int opd_abi:1; |
|
|
+ |
|
|
/* Set if PLT call stubs should load r11. */ |
|
|
unsigned int plt_static_chain:1; |
|
|
|
|
|
@@ -4959,6 +4978,15 @@ ppc64_elf_check_relocs (bfd *abfd, struc |
|
|
information about the associated function section. */ |
|
|
bfd_size_type amt; |
|
|
|
|
|
+ if (abiversion (abfd) == 0) |
|
|
+ set_abiversion (abfd, 1); |
|
|
+ else if (abiversion (abfd) == 2) |
|
|
+ { |
|
|
+ info->callbacks->einfo (_("%P: .opd not allowed in ABI version %d\n"), |
|
|
+ abiversion (abfd)); |
|
|
+ bfd_set_error (bfd_error_bad_value); |
|
|
+ return FALSE; |
|
|
+ } |
|
|
amt = sec->size * sizeof (*opd_sym_map) / 8; |
|
|
opd_sym_map = bfd_zalloc (abfd, amt); |
|
|
if (opd_sym_map == NULL) |
|
|
@@ -5518,6 +5546,78 @@ ppc64_elf_check_relocs (bfd *abfd, struc |
|
|
return TRUE; |
|
|
} |
|
|
|
|
|
+/* 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) |
|
|
+{ |
|
|
+ unsigned long iflags, oflags; |
|
|
+ |
|
|
+ if ((ibfd->flags & BFD_LINKER_CREATED) != 0) |
|
|
+ return TRUE; |
|
|
+ |
|
|
+ if (!is_ppc64_elf (ibfd) || !is_ppc64_elf (obfd)) |
|
|
+ return TRUE; |
|
|
+ |
|
|
+ if (!_bfd_generic_verify_endian_match (ibfd, obfd)) |
|
|
+ return FALSE; |
|
|
+ |
|
|
+ iflags = elf_elfheader (ibfd)->e_flags; |
|
|
+ oflags = elf_elfheader (obfd)->e_flags; |
|
|
+ |
|
|
+ if (!elf_flags_init (obfd) || oflags == 0) |
|
|
+ { |
|
|
+ elf_flags_init (obfd) = TRUE; |
|
|
+ elf_elfheader (obfd)->e_flags = iflags; |
|
|
+ } |
|
|
+ else if (iflags == oflags || iflags == 0) |
|
|
+ ; |
|
|
+ else if (iflags & ~EF_PPC64_ABI) |
|
|
+ { |
|
|
+ (*_bfd_error_handler) |
|
|
+ (_("%B uses unknown e_flags 0x%lx"), ibfd, iflags); |
|
|
+ bfd_set_error (bfd_error_bad_value); |
|
|
+ return FALSE; |
|
|
+ } |
|
|
+ else |
|
|
+ { |
|
|
+ (*_bfd_error_handler) |
|
|
+ (_("%B: ABI version %ld is not compatible with ABI version %ld output"), |
|
|
+ ibfd, iflags, oflags); |
|
|
+ bfd_set_error (bfd_error_bad_value); |
|
|
+ return FALSE; |
|
|
+ } |
|
|
+ |
|
|
+ /* Merge Tag_compatibility attributes and any common GNU ones. */ |
|
|
+ _bfd_elf_merge_object_attributes (ibfd, obfd); |
|
|
+ |
|
|
+ return TRUE; |
|
|
+} |
|
|
+ |
|
|
+static bfd_boolean |
|
|
+ppc64_elf_print_private_bfd_data (bfd *abfd, void *ptr) |
|
|
+{ |
|
|
+ /* Print normal ELF private data. */ |
|
|
+ _bfd_elf_print_private_bfd_data (abfd, ptr); |
|
|
+ |
|
|
+ if (elf_elfheader (abfd)->e_flags != 0) |
|
|
+ { |
|
|
+ FILE *file = ptr; |
|
|
+ |
|
|
+ /* xgettext:c-format */ |
|
|
+ fprintf (file, _("private flags = 0x%lx:"), |
|
|
+ elf_elfheader (abfd)->e_flags); |
|
|
+ |
|
|
+ if ((elf_elfheader (abfd)->e_flags & EF_PPC64_ABI) != 0) |
|
|
+ fprintf (file, _(" [abiv%ld]"), |
|
|
+ elf_elfheader (abfd)->e_flags & EF_PPC64_ABI); |
|
|
+ fputc ('\n', file); |
|
|
+ } |
|
|
+ |
|
|
+ return TRUE; |
|
|
+} |
|
|
+ |
|
|
/* OFFSET in OPD_SEC specifies a function descriptor. Return the address |
|
|
of the code entry point, and its section. */ |
|
|
|
|
|
@@ -7504,6 +7604,9 @@ ppc64_elf_tls_setup (struct bfd_link_inf |
|
|
if (htab == NULL) |
|
|
return NULL; |
|
|
|
|
|
+ if (abiversion (info->output_bfd) == 1) |
|
|
+ htab->opd_abi = 1; |
|
|
+ |
|
|
if (*no_multi_toc) |
|
|
htab->do_multi_toc = 0; |
|
|
else if (!htab->do_multi_toc) |
|
|
@@ -9127,7 +9230,7 @@ readonly_dynrelocs (struct elf_link_hash |
|
|
/* Set the sizes of the dynamic sections. */ |
|
|
|
|
|
static bfd_boolean |
|
|
-ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, |
|
|
+ppc64_elf_size_dynamic_sections (bfd *output_bfd, |
|
|
struct bfd_link_info *info) |
|
|
{ |
|
|
struct ppc_link_hash_table *htab; |
|
|
@@ -9439,7 +9542,7 @@ ppc64_elf_size_dynamic_sections (bfd *ou |
|
|
return FALSE; |
|
|
} |
|
|
|
|
|
- if (NO_OPD_RELOCS) |
|
|
+ if (NO_OPD_RELOCS && abiversion (output_bfd) <= 1) |
|
|
{ |
|
|
if (!add_dynamic_entry (DT_PPC64_OPD, 0) |
|
|
|| !add_dynamic_entry (DT_PPC64_OPDSZ, 0)) |
|
|
@@ -10202,7 +10305,10 @@ ppc_build_one_stub (struct bfd_hash_entr |
|
|
bfd_byte *rl; |
|
|
|
|
|
rela.r_offset = dest; |
|
|
- rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL); |
|
|
+ if (htab->opd_abi) |
|
|
+ rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL); |
|
|
+ else |
|
|
+ rela.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE); |
|
|
rela.r_addend = (stub_entry->target_value |
|
|
+ stub_entry->target_section->output_offset |
|
|
+ stub_entry->target_section->output_section->vma); |
|
|
@@ -14012,7 +14118,10 @@ ppc64_elf_finish_dynamic_symbol (bfd *ou |
|
|
rela.r_offset = (htab->iplt->output_section->vma |
|
|
+ htab->iplt->output_offset |
|
|
+ ent->plt.offset); |
|
|
- rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL); |
|
|
+ if (htab->opd_abi) |
|
|
+ rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL); |
|
|
+ else |
|
|
+ rela.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE); |
|
|
rela.r_addend = (h->root.u.def.value |
|
|
+ h->root.u.def.section->output_offset |
|
|
+ h->root.u.def.section->output_section->vma |
|
|
--- a/include/elf/ppc64.h |
|
|
+++ b/include/elf/ppc64.h |
|
|
@@ -173,6 +173,13 @@ END_RELOC_NUMBERS (R_PPC64_max) |
|
|
(((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA) \ |
|
|
|| ((R) >= R_PPC64_TPREL16_HIGH && (R) <= R_PPC64_DTPREL16_HIGHA)) |
|
|
|
|
|
+ |
|
|
+/* e_flags bits specifying ABI. |
|
|
+ 1 for original function descriptor using ABI, |
|
|
+ 2 for revised ABI without function descriptors, |
|
|
+ 0 for unspecified or not using any features affected by the differences. */ |
|
|
+#define EF_PPC64_ABI 3 |
|
|
+ |
|
|
/* Specify the start of the .glink section. */ |
|
|
#define DT_PPC64_GLINK DT_LOPROC |
|
|
|
|
|
|