Blame SOURCES/gdb-rhbz1125820-ppc64le-enablement-08of37.patch

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