diff options
author | Palmer Dabbelt <palmer@dabbelt.com> | 2017-05-18 18:08:25 -0700 |
---|---|---|
committer | Palmer Dabbelt <palmer@dabbelt.com> | 2017-10-19 09:19:32 -0700 |
commit | ff6f4d9b2d6c25ac144bab869df6e3d6123a6f8f (patch) | |
tree | 59e6a3f173dd8987b985d830a745f06e6b881f9d /bfd | |
parent | 95e42ad4425f0ab0ebfb90035a891be576f9fca4 (diff) | |
download | gdb-ff6f4d9b2d6c25ac144bab869df6e3d6123a6f8f.zip gdb-ff6f4d9b2d6c25ac144bab869df6e3d6123a6f8f.tar.gz gdb-ff6f4d9b2d6c25ac144bab869df6e3d6123a6f8f.tar.bz2 |
RISC-V: Add R_RISCV_DELETE, which marks bytes for deletion
We currently delete bytes by shifting an entire BFD backwards to
overwrite the bytes we no longer need. The result is that relaxing a
BFD is quadratic time.
This patch adds an additional relocation that specifies a byte range
that will be deleted from the final object file, and adds a relaxation
pass (between the existing passes that delete bytes and the alignment
pass) that actually deletes the bytes. Note that deletion is still
quadratic time, and nothing uses R_RISCV_DELETE yet.
I've been meaning to go convert all the other relaxations to use
R_RISCV_DELETE and then make it faster, but this patch has been sitting
around for months so it looks like that won't happen for a bit. The
PCREL->GPREL relaxation that comes next uses this, and since we've been
using these two patches out of tree since I wrote them months ago I
figure it's better to just get them in now. I (or someone else :)) can
convert all the relocations later...
R_RISCV_DELETE will never be emitted into ELF objects, so therefor isn't
exposed to the rest of binutils. As such, we're not considering this as
part of the ABI.
bfd/ChangeLog
2017-10-19 Palmer Dabbelt <palmer@dabbelt.com>
* elfnn-riscv (R_RISCV_DELETE): New define.
(_bfd_riscv_relax_delete): New function.
(perform_relocation): Handle R_RISCV_DELETE.
(_bfd_riscv_relax_section): Likewise.
ld/ChangeLog
2017-10-19 Palmer Dabbelt <palmer@dabbelt.com>
* emultempl/riscvelf.em (riscv_elf_before_allocation): Add a
third relaxation pass.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elfnn-riscv.c | 36 |
2 files changed, 40 insertions, 3 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 959cf06..772f526 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2017-10-19 Palmer Dabbelt <palmer@dabbelt.com> + + * elfnn-riscv.c (R_RISCV_DELETE): New define. + (_bfd_riscv_relax_delete): New function. + (perform_relocation): Handle R_RISCV_DELETE. + (_bfd_riscv_relax_section): Likewise. + 2017-10-19 H.J. Lu <hongjiu.lu@intel.com> PR ld/22263 diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index d28cabd..bd88ed7 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -32,6 +32,9 @@ #include "elf/riscv.h" #include "opcode/riscv.h" +/* Internal relocations used exclusively by the relaxation pass. */ +#define R_RISCV_DELETE (R_RISCV_max + 1) + #define ARCH_SIZE NN #define MINUS_ONE ((bfd_vma)0 - 1) @@ -1483,6 +1486,9 @@ perform_relocation (const reloc_howto_type *howto, case R_RISCV_TLS_DTPREL64: break; + case R_RISCV_DELETE: + return bfd_reloc_ok; + default: return bfd_reloc_notsupported; } @@ -1805,6 +1811,7 @@ riscv_elf_relocate_section (bfd *output_bfd, case R_RISCV_SET16: case R_RISCV_SET32: case R_RISCV_32_PCREL: + case R_RISCV_DELETE: /* These require no special handling beyond perform_relocation. */ break; @@ -2947,8 +2954,28 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec, rel->r_addend - nop_bytes); } -/* Relax a section. Pass 0 shortens code sequences unless disabled. - Pass 1, which cannot be disabled, handles code alignment directives. */ +/* Relax PC-relative references to GP-relative references. */ + +static bfd_boolean +_bfd_riscv_relax_delete (bfd *abfd, + asection *sec, + asection *sym_sec ATTRIBUTE_UNUSED, + struct bfd_link_info *link_info ATTRIBUTE_UNUSED, + Elf_Internal_Rela *rel, + bfd_vma symval ATTRIBUTE_UNUSED, + bfd_vma max_alignment ATTRIBUTE_UNUSED, + bfd_vma reserve_size ATTRIBUTE_UNUSED, + bfd_boolean *again ATTRIBUTE_UNUSED) +{ + if (!riscv_relax_delete_bytes(abfd, sec, rel->r_offset, rel->r_addend)) + return FALSE; + rel->r_info = ELFNN_R_INFO(0, R_RISCV_NONE); + return TRUE; +} + +/* Relax a section. Pass 0 shortens code sequences unless disabled. Pass 1 + deletes the bytes that pass 0 made obselete. Pass 2, which cannot be + disabled, handles code alignment directives. */ static bfd_boolean _bfd_riscv_relax_section (bfd *abfd, asection *sec, @@ -3001,6 +3028,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, int type = ELFNN_R_TYPE (rel->r_info); bfd_vma symval; + relax_func = NULL; if (info->relax_pass == 0) { if (type == R_RISCV_CALL || type == R_RISCV_CALL_PLT) @@ -3026,7 +3054,9 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec, /* Skip over the R_RISCV_RELAX. */ i++; } - else if (type == R_RISCV_ALIGN) + else if (info->relax_pass == 1 && type == R_RISCV_DELETE) + relax_func = _bfd_riscv_relax_delete; + else if (info->relax_pass == 2 && type == R_RISCV_ALIGN) relax_func = _bfd_riscv_relax_align; else continue; |