summaryrefslogtreecommitdiff
path: root/bfd/elfxx-riscv.c
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2016-12-18 22:53:48 -0800
committerAlan Modra <amodra@gmail.com>2016-12-20 12:26:33 +1030
commit45f764234a71431b581340957a3c8338e0593fdb (patch)
tree15fdb770f8d357dde9e570452a2afed2ba0772d0 /bfd/elfxx-riscv.c
parent1d65abb5e2cb1624b358dda27a53a070bec685cc (diff)
Rework RISC-V relocations
Before this commit we didn't cleanly support CFI directives because the internal offsets used to get relaxed which broke them. This patch significantly reworks how we handle linker relaxations: * DWARF is now properly supported * There is a ".option norelax" to disable relaxations, for when users write assembly that can't be relaxed (if it's to be later patched up, for example). * There is an additional _RELAX relocation that specifies when previous relocations can be relaxed. We're in the process of documenting the RISC-V ELF ABI, which will include documentation of our relocations https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md but we expect that this relocation set will remain ABI compatible in the future (ie, it's safe to release). Thanks to Kuan-Lin Chen for figuring out how to correctly relax the debug info! include/ * elf/riscv.h: Add R_RISCV_TPREL_I through R_RISCV_SET32. bfd/ * reloc.c (BFD_RELOC_RISCV_TPREL_I): New relocation. (BFD_RELOC_RISCV_TPREL_S): Likewise. (BFD_RELOC_RISCV_RELAX): Likewise. (BFD_RELOC_RISCV_CFA): Likewise. (BFD_RELOC_RISCV_SUB6): Likewise. (BFD_RELOC_RISCV_SET8): Likewise. (BFD_RELOC_RISCV_SET8): Likewise. (BFD_RELOC_RISCV_SET16): Likewise. (BFD_RELOC_RISCV_SET32): Likewise. * elfnn-riscv.c (perform_relocation): Handle the new relocations. (_bfd_riscv_relax_tls_le): Likewise. (_bfd_riscv_relax_align): Likewise. (_bfd_riscv_relax_section): Likewise. (howto_table): Likewise. (riscv_reloc_map): Likewise. (relax_func_t): New type. (_bfd_riscv_relax_call): Add reserve_size argument, which controls the maximal offset pessimism. Correct type of max_alignment. (_bfd_riscv_relax_lui): Likewise. (_bfd_riscv_relax_tls_le): Likewise. (_bfd_riscv_relax_align): Likewise. (_bfd_riscv_relax_section): Compute the required reserve size when relocating and use it to when calling relax_func. * bfd-in2.h: Regenerate. * libbfd.h: Likewise. gas/ * config/tc-riscv.c (riscv_set_options): Add relax. (riscv_opts): Likewise. (s_riscv_option): Add relax and norelax. (riscv_apply_const_reloc): New function. (append_insn): Move constant relocation handling to riscv_apply_const_reloc. (md_pcrel_from): Likewise. (parse_relocation): Skip BFD_RELOC_UNUSED. (md_pcrel_from): Handle BFD_RELOC_RISCV_SUB6, BFD_RELOC_RISCV_RELAX, BFD_RELOC_RISCV_CFA. (md_apply_fix): Likewise. (riscv_pre_output_hook): New function. * config/tc-riscv.h (md_pre_output_hook): Define. (riscv_pre_output_hook): Declare. (DWARF_CIE_DATA_ALIGNMENT): Always -4.
Diffstat (limited to 'bfd/elfxx-riscv.c')
-rw-r--r--bfd/elfxx-riscv.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 0fb250d0f5..3d935cfb6d 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -713,6 +713,126 @@ static reloc_howto_type howto_table[] =
0, /* src_mask */
ENCODE_STYPE_IMM (-1U), /* dst_mask */
FALSE), /* pcrel_offset */
+
+ /* TP-relative TLS LE load. */
+ HOWTO (R_RISCV_TPREL_I, /* 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_TPREL_I", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ ENCODE_ITYPE_IMM (-1U), /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* TP-relative TLS LE store. */
+ HOWTO (R_RISCV_TPREL_S, /* 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_TPREL_S", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ ENCODE_STYPE_IMM (-1U), /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The paired relocation may be relaxed. */
+ HOWTO (R_RISCV_RELAX, /* type */
+ 0, /* rightshift */
+ 3, /* size */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_RISCV_RELAX", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* 6-bit in-place addition, for local label subtraction. */
+ HOWTO (R_RISCV_SUB6, /* type */
+ 0, /* rightshift */
+ 0, /* size */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_RISCV_SUB6", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x3f, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* 6-bit in-place setting, for local label subtraction. */
+ HOWTO (R_RISCV_SET6, /* type */
+ 0, /* rightshift */
+ 0, /* size */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_RISCV_SET6", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x3f, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* 8-bit in-place setting, for local label subtraction. */
+ HOWTO (R_RISCV_SET8, /* type */
+ 0, /* rightshift */
+ 0, /* size */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_RISCV_SET8", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* 16-bit in-place setting, for local label subtraction. */
+ HOWTO (R_RISCV_SET16, /* type */
+ 0, /* rightshift */
+ 1, /* size */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_RISCV_SET16", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* 32-bit in-place setting, for local label subtraction. */
+ HOWTO (R_RISCV_SET32, /* 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_SET32", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ FALSE), /* pcrel_offset */
};
/* A mapping from BFD reloc types to RISC-V ELF reloc types. */
@@ -766,6 +886,14 @@ static const struct elf_reloc_map riscv_reloc_map[] =
{ BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
{ BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
{ BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
+ { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
+ { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
+ { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
+ { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
+ { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
+ { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
+ { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
+ { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
};
/* Given a BFD reloc type, return a howto structure. */