aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorClément Chigot <clement.chigot@atos.net>2021-03-11 11:08:19 +0100
committerAlan Modra <amodra@gmail.com>2021-03-12 22:47:23 +1030
commit4a403be0c1b4540e22c8c608ea0bfecbf0f85e51 (patch)
tree3908b8d38af9e56e3fd960da596c4d600f5915c5 /bfd
parent2c1bef53dee85aede31e6de6fa8276d6869f6512 (diff)
downloadbinutils-4a403be0c1b4540e22c8c608ea0bfecbf0f85e51.zip
binutils-4a403be0c1b4540e22c8c608ea0bfecbf0f85e51.tar.gz
binutils-4a403be0c1b4540e22c8c608ea0bfecbf0f85e51.tar.bz2
aix: implement R_TOCU and R_TOCL relocations
Implement support for largetoc on XCOFF. R_TOCU and R_TOCL are referenced by the new BFD defines: BFD_RELOC_PPC_TOC16_HI and BFD_RELOC_PPC_TOC16_LO. A new toc storage class is added XMC_TE. In order to correctly handle R_TOCU, the logic behind xcoff_reloc_type_toc is changed to compute the whole TOC offset instead of just the difference between the "link" offset and the "assembly" offset. In gas, add a function to transform addis format used by AIX "addis RT, D(RA)" into the ELF format "addis RT, RA, SI". bfd/ * reloc.c (BFD_RELOC_PPC_TOC16_HI, BFD_RELOC_PPC_TOC16_LO): New relocations. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. * coff-rs6000.c (xcoff_calculate_relocation): Call xcoff_reloc_type_toc for R_TOCU and R_TOCL. (xcoff_howto_table): Remove src_mask for TOC relocations. Add R_TOCU and R_TOCL howtos. (_bfd_xcoff_reloc_type_lookup): Add cases for BFD_RELOC_PPC_TOC16_HI and BFD_RELOC_PPC_TOC16_LO. (xcoff_reloc_type_toc): Compute the whole offset. Implement R_TOCU and R_TOCL. * coff64-rs6000.c (xcoff64_calculate_relocation): Likewise. (xcoff64_howto_table): Likewise. (xcoff64_reloc_type_lookup): Likewise. gas/ * config/tc-ppc.c (ppc_xcoff_suffix): New function. (MAP, MAP32, MAP64): New macros for XCOFF. (ppc_xcoff_fixup_addis): New function. (ppc_is_toc_sym): Handle XMC_TE. (fixup_size): Add cases for BFD_RELOC_PPC_TOC16_HI and BFD_RELOC_PPC_TOC16_LO. (md_assemble): Call ppc_xcoff_fixup_addis for XCOFF. (ppc_change_csect): Handle XMC_TE. (ppc_tc): Enable .tc symbols to have only a XMC_TC or XMC_TE storage class. (ppc_symbol_new_hook): Handle XMC_TE. (ppc_frob_symbol): Likewise. (ppc_fix_adjustable): Likewise. (md_apply_fix): Handle BFD_RELOC_PPC_TOC16_HI and BFD_RELOC_PPC_TOC16_LO. ld/ * scripttempl/aix.sc: Add .te to .data section. * testsuite/ld-powerpc/aix52.exp: Add test structure for AIX7+. Add aix-largetoc-1 test. * testsuite/ld-powerpc/aix-largetoc-1-32.d: New test. * testsuite/ld-powerpc/aix-largetoc-1-64.d: New test. * testsuite/ld-powerpc/aix-largetoc-1.ex: New test. * testsuite/ld-powerpc/aix-largetoc-1.s: New test.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog19
-rw-r--r--bfd/bfd-in2.h2
-rw-r--r--bfd/coff-rs6000.c70
-rw-r--r--bfd/coff64-rs6000.c45
-rw-r--r--bfd/libbfd.h2
-rw-r--r--bfd/reloc.c4
6 files changed, 119 insertions, 23 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 6c359ac..d955f78 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,24 @@
2021-03-12 Clément Chigot <clement.chigot@atos.net>
+ * reloc.c (BFD_RELOC_PPC_TOC16_HI, BFD_RELOC_PPC_TOC16_LO):
+ New relocations.
+ * bfd-in2.h: Regenerate.
+ * libbfd.h: Regenerate.
+ * coff-rs6000.c (xcoff_calculate_relocation): Call
+ xcoff_reloc_type_toc for R_TOCU and R_TOCL.
+ (xcoff_howto_table): Remove src_mask for TOC relocations.
+ Add R_TOCU and R_TOCL howtos.
+ (_bfd_xcoff_reloc_type_lookup): Add cases for
+ BFD_RELOC_PPC_TOC16_HI and BFD_RELOC_PPC_TOC16_LO.
+ (xcoff_reloc_type_toc): Compute the whole offset.
+ Implement R_TOCU and R_TOCL.
+ * coff64-rs6000.c (xcoff64_calculate_relocation):
+ Likewise.
+ (xcoff64_howto_table): Likewise.
+ (xcoff64_reloc_type_lookup): Likewise.
+
+2021-03-12 Clément Chigot <clement.chigot@atos.net>
+
* coff-rs6000.c (xcoff_calculate_relocation): Correct and
add new relocations.
(xcoff_howto_table): Likewise.
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index d142bb5..9bd61b1 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2899,6 +2899,8 @@ instruction. */
BFD_RELOC_PPC_B26,
BFD_RELOC_PPC_BA26,
BFD_RELOC_PPC_TOC16,
+ BFD_RELOC_PPC_TOC16_LO,
+ BFD_RELOC_PPC_TOC16_HI,
BFD_RELOC_PPC_B16,
BFD_RELOC_PPC_B16_BRTAKEN,
BFD_RELOC_PPC_B16_BRNTAKEN,
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index 2cae299..b77ff0c 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -206,8 +206,8 @@ xcoff_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION] =
xcoff_reloc_type_fail, /* (0x2d) */
xcoff_reloc_type_fail, /* (0x2e) */
xcoff_reloc_type_fail, /* (0x2f) */
- xcoff_reloc_type_fail, /* R_TOCU (0x30) */
- xcoff_reloc_type_fail, /* R_TOCL (0x31) */
+ xcoff_reloc_type_toc, /* R_TOCU (0x30) */
+ xcoff_reloc_type_toc, /* R_TOCL (0x31) */
};
xcoff_complain_function *const
@@ -745,7 +745,7 @@ reloc_howto_type xcoff_howto_table[] =
0, /* special_function */
"R_TOC", /* name */
TRUE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
@@ -760,7 +760,7 @@ reloc_howto_type xcoff_howto_table[] =
0, /* special_function */
"R_TRL", /* name */
TRUE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
@@ -775,7 +775,7 @@ reloc_howto_type xcoff_howto_table[] =
0, /* special_function */
"R_GL", /* name */
TRUE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
@@ -790,7 +790,7 @@ reloc_howto_type xcoff_howto_table[] =
0, /* special_function */
"R_TCL", /* name */
TRUE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
@@ -892,7 +892,7 @@ reloc_howto_type xcoff_howto_table[] =
0, /* special_function */
"R_TRLA", /* name */
TRUE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
@@ -1093,10 +1093,34 @@ reloc_howto_type xcoff_howto_table[] =
EMPTY_HOWTO(0x2f),
/* 0x30: High-order 16 bit TOC relative relocation. */
- EMPTY_HOWTO (R_TOCU),
+ HOWTO (R_TOCU, /* type */
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TOCU", /* name */
+ TRUE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
/* 0x31: Low-order 16 bit TOC relative relocation. */
- EMPTY_HOWTO (R_TOCL),
+ HOWTO (R_TOCL, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TOCL", /* name */
+ TRUE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
};
@@ -1145,6 +1169,10 @@ _bfd_xcoff_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
return &xcoff_howto_table[8];
case BFD_RELOC_PPC_TOC16:
return &xcoff_howto_table[3];
+ case BFD_RELOC_PPC_TOC16_HI:
+ return &xcoff_howto_table[0x30];
+ case BFD_RELOC_PPC_TOC16_LO:
+ return &xcoff_howto_table[0x31];
case BFD_RELOC_PPC_B16:
return &xcoff_howto_table[0x1d];
case BFD_RELOC_32:
@@ -2904,7 +2932,7 @@ xcoff_reloc_type_toc (bfd *input_bfd,
asection *input_section ATTRIBUTE_UNUSED,
bfd *output_bfd,
struct internal_reloc *rel,
- struct internal_syment *sym,
+ struct internal_syment *sym ATTRIBUTE_UNUSED,
struct reloc_howto_struct *howto ATTRIBUTE_UNUSED,
bfd_vma val,
bfd_vma addend ATTRIBUTE_UNUSED,
@@ -2935,8 +2963,16 @@ xcoff_reloc_type_toc (bfd *input_bfd,
+ h->toc_section->output_offset);
}
- *relocation = ((val - xcoff_data (output_bfd)->toc)
- - (sym->n_value - xcoff_data (input_bfd)->toc));
+ /* We can't use the preexisting value written down by the
+ assembly, as R_TOCU needs to be adjusted when the final
+ R_TOCL value is signed. */
+ *relocation = val - xcoff_data (output_bfd)->toc;
+
+ if (rel->r_type == R_TOCU)
+ *relocation = ((*relocation + 0x8000) >> 16) & 0xffff;
+ if (rel->r_type == R_TOCL)
+ *relocation = *relocation & 0x0000ffff;
+
return TRUE;
}
@@ -3299,8 +3335,6 @@ xcoff_complain_overflow_unsigned_func (bfd *input_bfd,
quite figure out when this is useful. These relocs are
not defined by the PowerOpen ABI.
- R_TOCU
- R_TOCL
R_TLS
R_TLS_IE
R_TLS_LD
@@ -3402,6 +3436,14 @@ xcoff_complain_overflow_unsigned_func (bfd *input_bfd,
The PowerPC ABI defines this as an absolute branch to a
fixed address which may be modified to a relative branch.
The PowerOpen ABI does not define this relocation type.
+
+ R_TOCU:
+ Upper TOC relative relocation. The value is the
+ high-order 16 bit of a TOC relative relocation.
+
+ R_TOCL:
+ Lower TOC relative relocation. The value is the
+ low-order 16 bit of a TOC relative relocation.
*/
bfd_boolean
diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c
index 0cb7e8b..55a6821 100644
--- a/bfd/coff64-rs6000.c
+++ b/bfd/coff64-rs6000.c
@@ -228,8 +228,8 @@ xcoff64_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION] =
xcoff_reloc_type_fail, /* (0x2d) */
xcoff_reloc_type_fail, /* (0x2e) */
xcoff_reloc_type_fail, /* (0x2f) */
- xcoff_reloc_type_fail, /* R_TOCU (0x30) */
- xcoff_reloc_type_fail, /* R_TOCL (0x31) */
+ xcoff_reloc_type_toc, /* R_TOCU (0x30) */
+ xcoff_reloc_type_toc, /* R_TOCL (0x31) */
};
/* coffcode.h needs these to be defined. */
@@ -899,7 +899,7 @@ reloc_howto_type xcoff64_howto_table[] =
0, /* special_function */
"R_TOC", /* name */
TRUE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
@@ -914,7 +914,7 @@ reloc_howto_type xcoff64_howto_table[] =
0, /* special_function */
"R_TRL", /* name */
TRUE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
@@ -929,7 +929,7 @@ reloc_howto_type xcoff64_howto_table[] =
0, /* special_function */
"R_GL", /* name */
TRUE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
@@ -944,7 +944,7 @@ reloc_howto_type xcoff64_howto_table[] =
0, /* special_function */
"R_TCL", /* name */
TRUE, /* partial_inplace */
- 0xffff, /* src_mask */
+ 0, /* src_mask */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
@@ -1260,11 +1260,34 @@ reloc_howto_type xcoff64_howto_table[] =
EMPTY_HOWTO(0x2e),
EMPTY_HOWTO(0x2f),
- /* 0x30: High-order 16 bit TOC relative relocation. */
- EMPTY_HOWTO (R_TOCU),
+ HOWTO (R_TOCU, /* type */
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TOCU", /* name */
+ TRUE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
/* 0x31: Low-order 16 bit TOC relative relocation. */
- EMPTY_HOWTO (R_TOCL),
+ HOWTO (R_TOCL, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TOCL", /* name */
+ TRUE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
};
@@ -1319,6 +1342,10 @@ xcoff64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
return &xcoff64_howto_table[8];
case BFD_RELOC_PPC_TOC16:
return &xcoff64_howto_table[3];
+ case BFD_RELOC_PPC_TOC16_HI:
+ return &xcoff64_howto_table[0x30];
+ case BFD_RELOC_PPC_TOC16_LO:
+ return &xcoff64_howto_table[0x31];
case BFD_RELOC_PPC_B16:
return &xcoff64_howto_table[0x1e];
case BFD_RELOC_32:
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 3a481ea..62b6bf8 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1462,6 +1462,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_PPC_B26",
"BFD_RELOC_PPC_BA26",
"BFD_RELOC_PPC_TOC16",
+ "BFD_RELOC_PPC_TOC16_LO",
+ "BFD_RELOC_PPC_TOC16_HI",
"BFD_RELOC_PPC_B16",
"BFD_RELOC_PPC_B16_BRTAKEN",
"BFD_RELOC_PPC_B16_BRNTAKEN",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 5ed7bb8..6864521 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2737,6 +2737,10 @@ ENUMX
ENUMX
BFD_RELOC_PPC_TOC16
ENUMX
+ BFD_RELOC_PPC_TOC16_LO
+ENUMX
+ BFD_RELOC_PPC_TOC16_HI
+ENUMX
BFD_RELOC_PPC_B16
ENUMX
BFD_RELOC_PPC_B16_BRTAKEN