This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix for bug 21700


Hi all,

First attempt at producing a patch for this project for XCOFF support
for AIX. I can't seem to find a contribution guide that explains the
exact procedure for raising a PR so apologies if this is not the right
thing to do...!

See https://sourceware.org/bugzilla/show_bug.cgi?id=21700 for details
and discussion.

Bug summary:

When creating a Linux / AIX cross-compiler I hit the following error:

 
/tmp/ccLI9PmP.s:2660: Error: can't resolve `_ehpersonality.rw_[RW]' {.data section} - `__gcc_unwind_dbase' {*UND* section}

This is caused by this line:

  .vbyte  4,LDFCM..0-__gcc_unwind_dbase

The attached file "exceptions.cpp" when compiled with gcc 6.3.0 on an AIX 6.1
machine will produce "exceptions.s" that contains this line:

  g++ -S exceptions.cpp -o exceptions.s
  g++ -v
  Using built-in specs.
  COLLECT_GCC=g++
  COLLECT_LTO_WRAPPER=/opt/freeware/libexec/gcc/powerpc-ibm-
aix6.1.1.0/6.3.0/lto-wrapper
  Target: powerpc-ibm-aix6.1.1.0
  Configured with: ../gcc-6.3.0/configure --with-as=/usr/bin/as
  --with-ld=/usr/bin/ld --enable-languages=c,c++,fortran
  --prefix=/opt/freeware --mandir=/opt/freeware/man
  --infodir=/opt/freeware/info --enable-version-specific-runtime-libs
  --disable-nls --enable-decimal-float=dpd --with-cloog=no
  --with-ppl=no --disable-libstdcxx-pch --enable__cxa_atexit
  --enable-bootstrap --host=powerpc-ibm-aix6.1.1.0
  Thread model: aix
  gcc version 6.3.0 (GCC)

The IBM as is able to compile this file to create relocations as:

  103: R_POS	_exceptions.rw_-0x150
  103: R_NEG	__gcc_unwind_dbase

Additionally the IBM as creates relocations for .__cxa_throw (bl
.__cxa_throw) and similar as:

  00000040 R_RBR_26          .__cxa_throw

whereas gas creates:

  00000040 R_BR              .__cxa_throw

Lastly, the IBM as will correctly compile ".vbyte  4,LFB..0-$" to the
correct section boundary.


Changelog:

2018-02-19  James Reynolds  <james.reynolds@cristie.com>

* bfd/bfd-in2.h: Add new BFD_RELOC_PPC_NEG type
* bfd/coff-rs6000.c: Fix relocation type RBR_26 and add PPC_NEG type
* bfd/coff64-rs6000.c: Add PPC_NEG type
* bfd/libbfd.h: Add PPC_NEG type
* bfd/reloc.c: Add size calculations for PPC_NEG type
* gas/config/tc-ppc.c: Allow creation of negative relocations and adjust for section boundaries
* gas/config/tc-ppc.h: Allow negative relocations in TC_VALIDATE_FIX_SUB


This was tested by compiling exceptions.s to produce matching
relocations to the IBM as. This corrects bug 21700 but c++ exceptions
are not correctly caught at present, further investigation and a new
patch will be submitted to correct this.

Thanks all,
James

----- patch -----

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 9742c1ac7f..e81d6810c2 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3442,6 +3442,7 @@ instruction.  */
   BFD_RELOC_PPC64_ADDR16_HIGHA,
   BFD_RELOC_PPC64_ADDR64_LOCAL,
   BFD_RELOC_PPC64_ENTRY,
+  BFD_RELOC_PPC_NEG,
 
 /* PowerPC and PowerPC64 thread-local storage relocations.  */
   BFD_RELOC_PPC_TLS,
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index d8db1f3894..db61628990 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -981,7 +981,7 @@ reloc_howto_type xcoff_howto_table[] =
 	 0,			/* rightshift */
 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
 	 26,			/* bitsize */
-	 FALSE,			/* pc_relative */
+	 TRUE,			/* pc_relative */
 	 0,			/* bitpos */
 	 complain_overflow_signed, /* complain_on_overflow */
 	 0,			/* special_function */
@@ -1090,7 +1090,7 @@ _bfd_xcoff_reloc_type_lookup (bfd *abfd
ATTRIBUTE_UNUSED,
   switch (code)
     {
     case BFD_RELOC_PPC_B26:
-      return &xcoff_howto_table[0xa];
+      return &xcoff_howto_table[0x1a];
     case BFD_RELOC_PPC_BA16:
       return &xcoff_howto_table[0x1c];
     case BFD_RELOC_PPC_BA26:
@@ -1107,6 +1107,8 @@ _bfd_xcoff_reloc_type_lookup (bfd *abfd
ATTRIBUTE_UNUSED,
       return &xcoff_howto_table[0];
     case BFD_RELOC_NONE:
       return &xcoff_howto_table[0xf];
+    case BFD_RELOC_PPC_NEG:
+      return &xcoff_howto_table[0x1];
     default:
       return NULL;
     }
diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c
index 78f14a09f4..c395aaee07 100644
--- a/bfd/coff64-rs6000.c
+++ b/bfd/coff64-rs6000.c
@@ -1831,6 +1831,8 @@ xcoff64_reloc_type_lookup (bfd *abfd
ATTRIBUTE_UNUSED,
       return &xcoff64_howto_table[0];
     case BFD_RELOC_NONE:
       return &xcoff64_howto_table[0xf];
+    case BFD_RELOC_PPC_NEG:
+      return &xcoff64_howto_table[0x1];
     default:
       return NULL;
     }
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 0fba5bea3e..dbfb58c46b 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1425,6 +1425,7 @@ static const char *const
bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_PPC64_ADDR16_HIGHA",
   "BFD_RELOC_PPC64_ADDR64_LOCAL",
   "BFD_RELOC_PPC64_ENTRY",
+  "BFD_RELOC_PPC_NEG",
   "BFD_RELOC_PPC_TLS",
   "BFD_RELOC_PPC_TLSGD",
   "BFD_RELOC_PPC_TLSLD",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 42e35b91ed..bc197e67a4 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -441,6 +441,7 @@ bfd_get_reloc_size (reloc_howto_type *howto)
     case 8: return 16;
     case -1: return 2;
     case -2: return 4;
+    case -4: return 8;
     default: abort ();
     }
 }
@@ -1351,6 +1352,14 @@ space consuming.  For each target:
 	bfd_put_64 (abfd, x, data);
       }
       break;
+    case -4:
+      {
+	bfd_vma x = bfd_get_64 (abfd, data);
+	relocation = -relocation;
+	DOIT (x);
+	bfd_put_64 (abfd, (bfd_vma) x, data);
+      }
+      break;
     default:
       return bfd_reloc_other;
     }
@@ -3009,6 +3018,8 @@ ENUMX
   BFD_RELOC_PPC64_ADDR64_LOCAL
 ENUMX
   BFD_RELOC_PPC64_ENTRY
+ENUMX
+  BFD_RELOC_PPC_NEG
 ENUMDOC
   Power(rs6000) and PowerPC relocations.
 
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index ff76221dc0..0107a28400 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -6279,6 +6279,40 @@ md_pcrel_from_section (fixS *fixp, segT sec
ATTRIBUTE_UNUSED)
 
 #ifdef OBJ_XCOFF
 
+/* Possibly adjust the reloc to be against the csect.  */
+symbolS *
+ppc_can_adjust_to_csect(symbolS *sym);
+symbolS *
+ppc_can_adjust_to_csect(symbolS *sym)
+{
+  segT symseg = sym ? S_GET_SEGMENT (sym) : 0;
+  TC_SYMFIELD_TYPE *tc = sym ? symbol_get_tc (sym) : NULL;
+  valueT val = sym ? resolve_symbol_value (sym) : 0;
+  if (sym 
+      && tc->subseg == 0
+      && tc->symbol_class != XMC_TC0
+      && tc->symbol_class != XMC_TC
+      && symseg != bss_section
+      /* Don't adjust if this is a reloc in the toc section.  */
+      && (symseg != data_section
+	  || ppc_toc_csect == NULL
+	  || val < ppc_toc_frag->fr_address
+	  || (ppc_after_toc_frag != NULL
+	      && val >= ppc_after_toc_frag->fr_address)))
+    {
+      symbolS *csect = symbol_get_tc (sym)->within;
+
+      /* If the symbol was not declared by a label (eg: a section
symbol),
+         use the section instead of the csect.  This doesn't happen in
+         normal AIX assembly code.  */
+      if (csect == NULL)
+        csect = seg_info (S_GET_SEGMENT (sym))->sym;
+
+      return csect;
+    }
+  return NULL;
+}
+
 /* This is called to see whether a fixup should be adjusted to use a
    section symbol.  We take the opportunity to change a fixup against
    a symbol in the TOC subsegment into a reloc against the
@@ -6289,7 +6323,7 @@ ppc_fix_adjustable (fixS *fix)
 {
   valueT val = resolve_symbol_value (fix->fx_addsy);
   segT symseg = S_GET_SEGMENT (fix->fx_addsy);
-  TC_SYMFIELD_TYPE *tc;
+  symbolS *csect;
 
   if (symseg == absolute_section)
     return 0;
@@ -6330,30 +6364,17 @@ ppc_fix_adjustable (fixS *fix)
     }
 
   /* Possibly adjust the reloc to be against the csect.  */
-  tc = symbol_get_tc (fix->fx_addsy);
-  if (tc->subseg == 0
-      && tc->symbol_class != XMC_TC0
-      && tc->symbol_class != XMC_TC
-      && symseg != bss_section
-      /* Don't adjust if this is a reloc in the toc section.  */
-      && (symseg != data_section
-	  || ppc_toc_csect == NULL
-	  || val < ppc_toc_frag->fr_address
-	  || (ppc_after_toc_frag != NULL
-	      && val >= ppc_after_toc_frag->fr_address)))
+  if ((csect = ppc_can_adjust_to_csect(fix->fx_addsy)) != NULL)
     {
-      symbolS *csect = tc->within;
-
-      /* If the symbol was not declared by a label (eg: a section
symbol),
-         use the section instead of the csect.  This doesn't happen in
-         normal AIX assembly code.  */
-      if (csect == NULL)
-        csect = seg_info (symseg)->sym;
-
       fix->fx_offset += val - symbol_get_frag (csect)->fr_address;
       fix->fx_addsy = csect;
+    }
 
-      return 0;
+  /* Possibly adjust the reloc to be against the csect.  */
+  if ((csect = ppc_can_adjust_to_csect(fix->fx_subsy)) != NULL)
+    {
+      fix->fx_offset += symbol_get_frag (csect)->fr_address - val;
+      fix->fx_subsy = csect;
     }
 
   /* Adjust a reloc against a .lcomm symbol to be against the base
@@ -6585,6 +6606,20 @@ ppc_handle_align (struct frag *fragP)
     }
 }
 
+/*
+ * If the resulting fix would be negative then force a relocation.
+ */
+int
+ppc_force_relocation_sub_same(fixS *fixP, segT seg)
+{
+  if (!fixP->fx_addsy || !fixP->fx_subsy) return !SEG_NORMAL(seg);
+  if (S_GET_VALUE (fixP->fx_addsy) < S_GET_VALUE (fixP->fx_subsy))
+    {
+      return TRUE;
+    }
+  return !SEG_NORMAL(seg);
+}
+
 /* Apply a fixup to the object code.  This is called for all the
    fixups we generated by the calls to fix_new_exp, above.  */
 
@@ -7224,27 +7259,71 @@ md_apply_fix (fixS *fixP, valueT *valP, segT
seg)
 
 /* Generate a reloc for a fixup.  */
 
-arelent *
+arelent **
 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
 {
   arelent *reloc;
+  static arelent *relocs[3];
 
-  reloc = XNEW (arelent);
+  relocs[0] = reloc = XNEW (arelent);
+  relocs[1] = NULL;
 
   reloc->sym_ptr_ptr = XNEW (asymbol *);
   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+  
   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
   if (reloc->howto == (reloc_howto_type *) NULL)
     {
       as_bad_where (fixp->fx_file, fixp->fx_line,
 		    _("reloc %d not supported by object file format"),
 		    (int) fixp->fx_r_type);
-      return NULL;
+      relocs[0] = NULL;
+      return relocs;
     }
   reloc->addend = fixp->fx_addnumber;
 
-  return reloc;
+  /* We expand a subtraction into an R_POS and R_NEG */
+  if (fixp->fx_subsy && fixp->fx_addsy)
+    {
+      if (ppc_obj64)
+        {
+          reloc->howto = bfd_reloc_type_lookup (stdoutput,
BFD_RELOC_64);
+        }
+
+      /* If this is negative then we should put the relocs the other
way around */
+      if (S_GET_VALUE (fixp->fx_addsy) < S_GET_VALUE (fixp->fx_subsy))
+        {
+          relocs[1] = reloc;
+          relocs[0] = reloc = XNEW (arelent);
+          relocs[2] = NULL;
+        }
+      else
+        {
+          relocs[1] = reloc = XNEW (arelent);
+          relocs[2] = NULL;
+        }
+
+      bfd_reloc_code_real_type code = BFD_RELOC_PPC_NEG;
+      
+      reloc->sym_ptr_ptr = XNEW (asymbol *);
+      *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
+      reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+      
+      reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
+      reloc->addend = fixp->fx_addnumber;
+     
+      if (reloc->howto == (reloc_howto_type *) NULL)
+        {
+          as_bad_where (fixp->fx_file, fixp->fx_line,
+            _("reloc %d not supported by object file format"),
+            code);
+          relocs[0] = NULL;
+          return relocs;
+        }
+    }
+
+  return relocs;
 }
 
 void
diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h
index cf627dec26..9c6b2af413 100644
--- a/gas/config/tc-ppc.h
+++ b/gas/config/tc-ppc.h
@@ -260,6 +260,11 @@ extern void ppc_elf_end (void);
 extern int ppc_force_relocation (struct fix *);
 #endif
 
+#if defined (OBJ_XCOFF)
+#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG)
ppc_force_relocation_sub_same(FIX, SEG)
+extern int ppc_force_relocation_sub_same(struct fix *, segT);
+#endif
+
 #ifdef OBJ_ELF
 /* Don't allow the generic code to convert fixups involving the
    subtraction of a label in the current section to pc-relative if we
@@ -274,7 +279,9 @@ extern int ppc_force_relocation (struct fix *);
      || (FIX)->fx_r_type == BFD_RELOC_PPC_16DX_HA))
 #endif
 
-#define TC_VALIDATE_FIX_SUB(FIX, SEG) 0
+#define RELOC_EXPANSION_POSSIBLE
+#define MAX_RELOC_EXPANSION 2
+#define UNDEFINED_DIFFERENCE_OK
 
 /* call md_pcrel_from_section, not md_pcrel_from */
 #define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX,
SEC)

Attachment: testcase.tar.bz2
Description: testcase.tar.bz2


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]