[WIP][PATCH] RISC-V: Implement relocations for GP-relative addressing
Maciej W. Rozycki
macro@wdc.com
Mon Aug 31 14:08:37 GMT 2020
Implement R_RISCV_GPREL_HI20, R_RISCV_GPREL_LO12_I, and
R_RISCV_GPREL_LO12_S relocations and the associated GAS relocations
operators.
bfd/
* elfnn-riscv.c (perform_relocation): Handle R_RISCV_GPREL_HI20,
R_RISCV_GPREL_LO12_I, and R_RISCV_GPREL_LO12_S relocations.
(riscv_elf_relocate_section): Likewise.
* elfxx-riscv.c (howto_table, riscv_reloc_map): Likewise.
* reloc.c (BFD_RELOC_RISCV_GPREL_HI20)
(BFD_RELOC_RISCV_GPREL_LO12_I, BFD_RELOC_RISCV_GPREL_LO12_S):
New relocations.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-riscv.c (append_insn): Handle
BFD_RELOC_RISCV_GPREL_HI20.
(percent_op_utype): Add `%gprel_hi' operator.
(percent_op_itype, percent_op_stype): Add `%gprel_lo' operator.
(md_apply_fix): Handle BFD_RELOC_RISCV_GPREL_HI20,
BFD_RELOC_RISCV_GPREL_LO12_S, and BFD_RELOC_RISCV_GPREL_LO12_I
relocations.
include/
* elf/riscv.h (elf_riscv_reloc_type): Add R_RISCV_GPREL_HI20,
R_RISCV_GPREL_LO12_I, and R_RISCV_GPREL_LO12_S relocations.
---
Hi,
This is very early stage really, just implementing basic GP-relative
relocation support, in preparation for FDPIC support discussed here:
<https://groups.google.com/a/groups.riscv.org/g/sw-dev/c/ZjYUJswknQ4>
I planned adding support to GAS macros such as LA next, but I won't be
able to continue with this effort now as I am leaving Western Digital
today, so I am posting this in case someone finds it useful or wishes to
continue the effort.
No regressions in `riscv64-linux-gnu' testing.
A corresponding GCC change has also been posted.
Maciej
---
bfd/bfd-in2.h | 3 ++
bfd/elfnn-riscv.c | 9 ++++++++
bfd/elfxx-riscv.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
bfd/libbfd.h | 3 ++
bfd/reloc.c | 6 +++++
gas/config/tc-riscv.c | 9 +++++++-
include/elf/riscv.h | 3 ++
7 files changed, 83 insertions(+), 1 deletion(-)
binutils-riscv-gprel.diff
Index: binutils-gdb/bfd/bfd-in2.h
===================================================================
--- binutils-gdb.orig/bfd/bfd-in2.h
+++ binutils-gdb/bfd/bfd-in2.h
@@ -4408,6 +4408,9 @@ number for the SBIC, SBIS, SBI and CBI i
BFD_RELOC_RISCV_SET16,
BFD_RELOC_RISCV_SET32,
BFD_RELOC_RISCV_32_PCREL,
+ BFD_RELOC_RISCV_GPREL_HI20,
+ BFD_RELOC_RISCV_GPREL_LO12_I,
+ BFD_RELOC_RISCV_GPREL_LO12_S,
/* Renesas RL78 Relocations. */
BFD_RELOC_RL78_NEG8,
Index: binutils-gdb/bfd/elfnn-riscv.c
===================================================================
--- binutils-gdb.orig/bfd/elfnn-riscv.c
+++ binutils-gdb/bfd/elfnn-riscv.c
@@ -1325,6 +1325,7 @@ perform_relocation (const reloc_howto_ty
case R_RISCV_GOT_HI20:
case R_RISCV_TLS_GOT_HI20:
case R_RISCV_TLS_GD_HI20:
+ case R_RISCV_GPREL_HI20:
if (ARCH_SIZE > 32 && !VALID_UTYPE_IMM (RISCV_CONST_HIGH_PART (value)))
return bfd_reloc_overflow;
value = ENCODE_UTYPE_IMM (RISCV_CONST_HIGH_PART (value));
@@ -1335,6 +1336,7 @@ perform_relocation (const reloc_howto_ty
case R_RISCV_TPREL_LO12_I:
case R_RISCV_TPREL_I:
case R_RISCV_PCREL_LO12_I:
+ case R_RISCV_GPREL_LO12_I:
value = ENCODE_ITYPE_IMM (value);
break;
@@ -1343,6 +1345,7 @@ perform_relocation (const reloc_howto_ty
case R_RISCV_TPREL_LO12_S:
case R_RISCV_TPREL_S:
case R_RISCV_PCREL_LO12_S:
+ case R_RISCV_GPREL_LO12_S:
value = ENCODE_STYPE_IMM (value);
break;
@@ -1923,6 +1926,12 @@ riscv_elf_relocate_section (bfd *output_
r = bfd_reloc_overflow;
break;
+ case R_RISCV_GPREL_HI20:
+ case R_RISCV_GPREL_LO12_I:
+ case R_RISCV_GPREL_LO12_S:
+ relocation -= riscv_global_pointer_value (info);
+ break;
+
case R_RISCV_GPREL_I:
case R_RISCV_GPREL_S:
{
Index: binutils-gdb/bfd/elfxx-riscv.c
===================================================================
--- binutils-gdb.orig/bfd/elfxx-riscv.c
+++ binutils-gdb/bfd/elfxx-riscv.c
@@ -854,6 +854,54 @@ static reloc_howto_type howto_table[] =
0, /* src_mask */
MINUS_ONE, /* dst_mask */
FALSE), /* pcrel_offset */
+
+ /* R_RISCV_IRELATIVE */
+ EMPTY_HOWTO (58),
+
+ /* High 20 bits of a 32-bit GP-relative reference. */
+ HOWTO (R_RISCV_GPREL_HI20, /* type */
+ 0, /* rightshift */
+ 2, /* size */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_RISCV_GPREL_HI20", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ ENCODE_UTYPE_IMM (-1U), /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Low 12 bits of a 32-bit GP-relative load or add. */
+ HOWTO (R_RISCV_GPREL_LO12_I, /* type */
+ 0, /* rightshift */
+ 2, /* size */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_RISCV_GPREL_LO12_I", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ ENCODE_ITYPE_IMM (-1U), /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Low 12 bits of a 32-bit GP-relative store. */
+ HOWTO (R_RISCV_GPREL_LO12_S, /* type */
+ 0, /* rightshift */
+ 2, /* size */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_RISCV_GPREL_LO12_S", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ ENCODE_STYPE_IMM (-1U), /* dst_mask */
+ FALSE), /* pcrel_offset */
};
/* A mapping from BFD reloc types to RISC-V ELF reloc types. */
@@ -916,6 +964,9 @@ static const struct elf_reloc_map riscv_
{ BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
{ BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
{ BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL },
+ { BFD_RELOC_RISCV_GPREL_HI20, R_RISCV_GPREL_HI20 },
+ { BFD_RELOC_RISCV_GPREL_LO12_S, R_RISCV_GPREL_LO12_S },
+ { BFD_RELOC_RISCV_GPREL_LO12_I, R_RISCV_GPREL_LO12_I },
};
/* Given a BFD reloc type, return a howto structure. */
Index: binutils-gdb/bfd/libbfd.h
===================================================================
--- binutils-gdb.orig/bfd/libbfd.h
+++ binutils-gdb/bfd/libbfd.h
@@ -2378,6 +2378,9 @@ static const char *const bfd_reloc_code_
"BFD_RELOC_RISCV_SET16",
"BFD_RELOC_RISCV_SET32",
"BFD_RELOC_RISCV_32_PCREL",
+ "BFD_RELOC_RISCV_GPREL_HI20",
+ "BFD_RELOC_RISCV_GPREL_LO12_I",
+ "BFD_RELOC_RISCV_GPREL_LO12_S",
"BFD_RELOC_RL78_NEG8",
"BFD_RELOC_RL78_NEG16",
"BFD_RELOC_RL78_NEG24",
Index: binutils-gdb/bfd/reloc.c
===================================================================
--- binutils-gdb.orig/bfd/reloc.c
+++ binutils-gdb/bfd/reloc.c
@@ -5215,6 +5215,12 @@ ENUMX
BFD_RELOC_RISCV_SET32
ENUMX
BFD_RELOC_RISCV_32_PCREL
+ENUMX
+ BFD_RELOC_RISCV_GPREL_HI20
+ENUMX
+ BFD_RELOC_RISCV_GPREL_LO12_I
+ENUMX
+ BFD_RELOC_RISCV_GPREL_LO12_S
ENUMDOC
RISC-V relocations.
Index: binutils-gdb/gas/config/tc-riscv.c
===================================================================
--- binutils-gdb.orig/gas/config/tc-riscv.c
+++ binutils-gdb/gas/config/tc-riscv.c
@@ -1138,7 +1138,8 @@ append_insn (struct riscv_cl_insn *ip, e
|| reloc_type == BFD_RELOC_RISCV_HI20
|| reloc_type == BFD_RELOC_RISCV_PCREL_HI20
|| reloc_type == BFD_RELOC_RISCV_TPREL_HI20
- || reloc_type == BFD_RELOC_RISCV_TPREL_ADD)
+ || reloc_type == BFD_RELOC_RISCV_TPREL_ADD
+ || reloc_type == BFD_RELOC_RISCV_GPREL_HI20)
{
frag_wane (frag_now);
frag_new (0);
@@ -1501,6 +1502,7 @@ static const struct percent_op_match per
{"%tls_ie_pcrel_hi", BFD_RELOC_RISCV_TLS_GOT_HI20},
{"%tls_gd_pcrel_hi", BFD_RELOC_RISCV_TLS_GD_HI20},
{"%hi", BFD_RELOC_RISCV_HI20},
+ {"%gprel_hi", BFD_RELOC_RISCV_GPREL_HI20},
{0, 0}
};
@@ -1509,6 +1511,7 @@ static const struct percent_op_match per
{"%lo", BFD_RELOC_RISCV_LO12_I},
{"%tprel_lo", BFD_RELOC_RISCV_TPREL_LO12_I},
{"%pcrel_lo", BFD_RELOC_RISCV_PCREL_LO12_I},
+ {"%gprel_lo", BFD_RELOC_RISCV_GPREL_LO12_I},
{0, 0}
};
@@ -1517,6 +1520,7 @@ static const struct percent_op_match per
{"%lo", BFD_RELOC_RISCV_LO12_S},
{"%tprel_lo", BFD_RELOC_RISCV_TPREL_LO12_S},
{"%pcrel_lo", BFD_RELOC_RISCV_PCREL_LO12_S},
+ {"%gprel_lo", BFD_RELOC_RISCV_GPREL_LO12_S},
{0, 0}
};
@@ -3009,6 +3013,9 @@ md_apply_fix (fixS *fixP, valueT *valP,
case BFD_RELOC_RISCV_PCREL_HI20:
case BFD_RELOC_RISCV_PCREL_LO12_S:
case BFD_RELOC_RISCV_PCREL_LO12_I:
+ case BFD_RELOC_RISCV_GPREL_HI20:
+ case BFD_RELOC_RISCV_GPREL_LO12_S:
+ case BFD_RELOC_RISCV_GPREL_LO12_I:
relaxable = riscv_opts.relax;
break;
Index: binutils-gdb/include/elf/riscv.h
===================================================================
--- binutils-gdb.orig/include/elf/riscv.h
+++ binutils-gdb/include/elf/riscv.h
@@ -88,6 +88,9 @@ START_RELOC_NUMBERS (elf_riscv_reloc_typ
RELOC_NUMBER (R_RISCV_SET16, 55)
RELOC_NUMBER (R_RISCV_SET32, 56)
RELOC_NUMBER (R_RISCV_32_PCREL, 57)
+ RELOC_NUMBER (R_RISCV_GPREL_HI20, 59)
+ RELOC_NUMBER (R_RISCV_GPREL_LO12_I, 60)
+ RELOC_NUMBER (R_RISCV_GPREL_LO12_S, 61)
END_RELOC_NUMBERS (R_RISCV_max)
/* Processor specific flags for the ELF header e_flags field. */
More information about the Binutils
mailing list