diff options
author | Alan Modra <amodra@gmail.com> | 2020-09-17 07:44:53 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2020-09-21 09:41:05 +0930 |
commit | b1b11e922b3de18b7e226da6fe6d87fa17564bde (patch) | |
tree | 9b536f098bf4f10f69e2c860088804d4baf456b1 /gas/config | |
parent | 4f94229e83d28b00d415a932ff467ee7a621081c (diff) | |
download | gdb-b1b11e922b3de18b7e226da6fe6d87fa17564bde.zip gdb-b1b11e922b3de18b7e226da6fe6d87fa17564bde.tar.gz gdb-b1b11e922b3de18b7e226da6fe6d87fa17564bde.tar.bz2 |
PR26569, R_RISCV_RVC_JUMP results in buffer overflow
This patch corrects "size" and "bitsize" in R_RISCV_RVC_* reloc howtos
so that elfnn-riscv.c:perform_relocation doesn't access past the end
of a section. I've also corrected "size" in the R_RISCV_CALL* reloc
howtos since these relocs apply to two consecutive instructions. That
caused fallout in the assembler with complaints about "fixup not
contained within frag" due to tc-riscv.c:append_insn finishing off a
frag after the auipc insn making up a "call" macro. Which is a little
rude since the CALL reloc also relocates the following jalr. Fixed by
changing the frag handling a little.
I've also changed R_RISCV_ALIGN and R_RISCV_TPREL_ADD marker reloc
howtos to look like R_RISCV_NONE, and corrected dst_mask for numerous
relocs, not that it matters very much.
bfd/
PR 26569
* elfxx-riscv.c (howto_table): Correct size and bitsize of
R_RISCV_RVC_BRANCH, R_RISCV_RVC_JUMP, and R_RISCV_RVC_LUI.
Correct size for R_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPREL32,
R_RISCV_CALL, and R_RISCV_CALL_PLT. Make R_RISCV_TPREL_ADD and
R_RISCV_ALIGN like R_RISCV_NONE. Correct dst_mask many relocs.
gas/
* config/tc-riscv.c (append_insn): Don't tie off frags at CALL
relocs.
(riscv_call): Tie them off after the jalr.
(md_apply_fix): Zero fx_size of RELAX fixup.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-riscv.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index 9df6d3f..eb31e42 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -1133,9 +1133,7 @@ append_insn (struct riscv_cl_insn *ip, expressionS *address_expr, optimized away or compressed by the linker during relaxation, to prevent the assembler from computing static offsets across such an instruction. This is necessary to get correct EH info. */ - if (reloc_type == BFD_RELOC_RISCV_CALL - || reloc_type == BFD_RELOC_RISCV_CALL_PLT - || reloc_type == BFD_RELOC_RISCV_HI20 + if (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) @@ -1311,8 +1309,13 @@ static void riscv_call (int destreg, int tempreg, expressionS *ep, bfd_reloc_code_real_type reloc) { + /* Ensure the jalr is emitted to the same frag as the auipc. */ + frag_grow (8); macro_build (ep, "auipc", "d,u", tempreg, reloc); macro_build (NULL, "jalr", "d,s", destreg, tempreg); + /* See comment at end of append_insn. */ + frag_wane (frag_now); + frag_new (0); } /* Load an integer constant into a register. */ @@ -3031,6 +3034,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP)); fixP->fx_next->fx_addsy = fixP->fx_next->fx_subsy = NULL; fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_RELAX; + fixP->fx_next->fx_size = 0; } } |