diff options
author | Andrew Waterman <andrew@sifive.com> | 2016-12-18 22:53:48 -0800 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2016-12-20 12:26:33 +1030 |
commit | 45f764234a71431b581340957a3c8338e0593fdb (patch) | |
tree | 15fdb770f8d357dde9e570452a2afed2ba0772d0 /bfd/elfxx-riscv.c | |
parent | 1d65abb5e2cb1624b358dda27a53a070bec685cc (diff) | |
download | gdb-45f764234a71431b581340957a3c8338e0593fdb.zip gdb-45f764234a71431b581340957a3c8338e0593fdb.tar.gz gdb-45f764234a71431b581340957a3c8338e0593fdb.tar.bz2 |
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.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 0fb250d..3d935cf 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. */ |