[PATCH] Fix for bug 21700
James Reynolds
james.reynolds@cristie.com
Mon Mar 19 16:42:00 GMT 2018
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)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: testcase.tar.bz2
Type: application/x-bzip-compressed-tar
Size: 1801 bytes
Desc: testcase.tar.bz2
URL: <https://sourceware.org/pipermail/binutils/attachments/20180319/a2e77a7f/attachment.bin>
More information about the Binutils
mailing list