Skip to content

Commit

Permalink
RISC-V: Refer mapping symbol to R_RISCV_RELAX for rvc relaxations.
Browse files Browse the repository at this point in the history
RISC-V Psabi pr116,
riscv-non-isa/riscv-elf-psabi-doc#116

bfd/
    * elfnn-riscv.c (_bfd_riscv_enable_rvc): New function to check the
    mapping symbol with architecture string in the R_RISCV_RELAX, to see
    if rvc is enabled or not.  If we don't find any mapping symbols, then
    just check the elf header flag as usual.
    (_bfd_riscv_relax_call): Updated since above change.
    (_bfd_riscv_relax_lui): Likewise.
gas/
    * config/tc-riscv.c (append_insn): Store $x+arch in tc_fix_data if exsit.
    (md_apply_fix): Refer the $x+arch from tc_fix_data into R_RISCV_RELAX,
    these only for the relocations used to do rvc relaxation.  Besides, set
    addend of R_RISCV_RELAX (fx_offset) to zero.
    * config/tc-riscv.h (TC_FIX_TYPE): Defined to store $x+arch in each fixup
    only for risc-v target.
    (struct riscv_fixup_type): Likewise.
    (TC_INIT_FIX_DATA): Likewise.
    * testsuite/gas/riscv/mapping-relax.d: New testcase.
    * testsuite/gas/riscv/mapping-relax.s: Likewise.
ld/
    * testsuite/ld-riscv-elf/c-relax.d: New testcase for specific rvc relaxation.
    * testsuite/ld-riscv-elf/c-relax.s: Likewise.
    * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated.
  • Loading branch information
Nelson Chu authored and ouuleilei-bot committed Sep 30, 2022
1 parent 50f6417 commit 5491579
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 5 deletions.
31 changes: 28 additions & 3 deletions bfd/elfnn-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -4168,6 +4168,31 @@ typedef bool (*relax_func_t) (bfd *, asection *, asection *,
riscv_pcgp_relocs *,
bool undefined_weak);

/* Check the mapping symbol with architecture string in the R_RISCV_RELAX,
to see if rvc is enabled or not. If we don't find any mapping symbols,
then just check the elf header flag as usual. */

static int
_bfd_riscv_enable_rvc (bfd *abfd, Elf_Internal_Rela *rel)
{
Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
int rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC;
if (ELFNN_R_SYM (rel->r_info) < symtab_hdr->sh_info)
{
Elf_Internal_Sym *isym = ((Elf_Internal_Sym *) symtab_hdr->contents
+ ELFNN_R_SYM (rel->r_info));

if (isym->st_shndx == SHN_UNDEF
|| isym->st_shndx >= elf_numsections (abfd))
return rvc;

const char *name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
rvc = (name && strncmp (name, "$xrv", 4) == 0
&& strstr (name, "_c") != NULL) ? 1 : 0;
}
return rvc;
}

/* Relax AUIPC + JALR into JAL. */

static bool
Expand All @@ -4185,7 +4210,8 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
bfd_vma foff = symval - (sec_addr (sec) + rel->r_offset);
bool near_zero = (symval + RISCV_IMM_REACH / 2) < RISCV_IMM_REACH;
bfd_vma auipc, jalr;
int rd, r_type, len = 4, rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC;
int rd, r_type, len = 4;
int rvc = _bfd_riscv_enable_rvc (abfd, rel + 1);

/* If the call crosses section boundaries, an alignment directive could
cause the PC-relative offset to later increase, so we need to add in the
Expand Down Expand Up @@ -4279,7 +4305,6 @@ _bfd_riscv_relax_lui (bfd *abfd,
{
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
bfd_vma gp = riscv_global_pointer_value (link_info);
int use_rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC;

BFD_ASSERT (rel->r_offset + 4 <= sec->size);

Expand Down Expand Up @@ -4347,7 +4372,7 @@ _bfd_riscv_relax_lui (bfd *abfd,
account for this assuming page alignment at worst. In the presence of
RELRO segment the linker aligns it by one page size, therefore sections
after the segment can be moved more than one page. */

int use_rvc = _bfd_riscv_enable_rvc (abfd, rel + 1);
if (use_rvc
&& ELFNN_R_TYPE (rel->r_info) == R_RISCV_HI20
&& VALID_CITYPE_LUI_IMM (RISCV_CONST_HIGH_PART (symval))
Expand Down
15 changes: 13 additions & 2 deletions gas/config/tc-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,8 @@ make_mapping_symbol (enum riscv_seg_mstate state,
symbol_get_bfdsym (symbol)->flags |= (BSF_NO_FLAGS | BSF_LOCAL);
if (reset_seg_arch_str)
{
/* Store current $x+arch into tc_segment_info. */
/* Store current $x+arch into tc_segment_info, so that we can
refer to the correct $x+arch for each R_RISCV_RELAX. */
seg_info (now_seg)->tc_segment_info_data.arch_map_symbol = symbol;
xfree ((void *) buff);
}
Expand Down Expand Up @@ -1558,6 +1559,8 @@ append_insn (struct riscv_cl_insn *ip, expressionS *address_expr,
address_expr, false, reloc_type);

ip->fixp->fx_tcbit = riscv_opts.relax;
ip->fixp->tc_fix_data.arch_map_symbol =
seg_info (now_seg)->tc_segment_info_data.arch_map_symbol;
}
}

Expand Down Expand Up @@ -3731,6 +3734,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
unsigned int subtype;
bfd_byte *buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
bool relaxable = false;
bool rvc_relaxable = false;
offsetT loc;
segT sub_segment;

Expand All @@ -3747,6 +3751,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
if (fixP->fx_addsy == NULL)
fixP->fx_done = true;
relaxable = true;
rvc_relaxable = true;
break;

case BFD_RELOC_RISCV_GOT_HI20:
Expand Down Expand Up @@ -3940,6 +3945,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
case BFD_RELOC_RISCV_CALL:
case BFD_RELOC_RISCV_CALL_PLT:
relaxable = true;
rvc_relaxable = true;
break;

case BFD_RELOC_RISCV_PCREL_HI20:
Expand All @@ -3964,9 +3970,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
if (relaxable && fixP->fx_tcbit && fixP->fx_addsy != NULL)
{
fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
fixP->fx_next->fx_addsy = fixP->fx_next->fx_subsy = NULL;
/* Currently only rvc relaxations need $x+arch. */
fixP->fx_next->fx_addsy = (need_arch_map_symbol && rvc_relaxable)
? fixP->tc_fix_data.arch_map_symbol : NULL;
fixP->fx_next->fx_subsy = NULL;
fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_RELAX;
fixP->fx_next->fx_size = 0;
/* Set addend to zero. */
fixP->fx_next->fx_offset = 0;
}
}

Expand Down
7 changes: 7 additions & 0 deletions gas/config/tc-riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ struct riscv_frag_type
#define TC_FRAG_INIT(fragp, max_bytes) riscv_init_frag (fragp, max_bytes)
extern void riscv_init_frag (struct frag *, int);

#define TC_FIX_TYPE struct riscv_fixup_type
struct riscv_fixup_type
{
symbolS *arch_map_symbol;
};
#define TC_INIT_FIX_DATA(FIX) ((FIX)->tc_fix_data.arch_map_symbol = NULL)

#define obj_adjust_symtab() riscv_adjust_symtab ()
extern void riscv_adjust_symtab (void);

Expand Down
23 changes: 23 additions & 0 deletions gas/testsuite/gas/riscv/mapping-relax.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#name:
#source: mapping-relax.s
#as:
#readelf: -rW

Relocation section '.rela.text' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_HI20[ ]+[0-9a-f]+[ ]+foo \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_RELAX[ ]+[0-9a-f]+[ ]+\$xrv32i2p1 \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_LO12_I[ ]+[0-9a-f]+[ ]+foo \+ 4
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_RELAX[ ]+[0-9a-f]+[ ]+\$xrv32i2p1 \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_TPREL_HI20[ ]+[0-9a-f]+[ ]+i \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_RELAX[ ]+0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_TPREL_ADD[ ]+[0-9a-f]+[ ]+i \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_RELAX[ ]+0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_TPREL_LO12_I[ ]+[0-9a-f]+[ ]+i \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_RELAX[ ]+0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_PCREL_HI20[ ]+[0-9a-f]+[ ]+foo \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_RELAX[ ]+0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_PCREL_LO12_I[ ]+[0-9a-f]+[ ]+L1 \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_RELAX[ ]+0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_CALL_PLT[ ]+[0-9a-f]+[ ]+foo \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_RELAX[ ]+[0-9a-f]+[ ]+\$xrv32i2p1_c2p0 \+ 0
21 changes: 21 additions & 0 deletions gas/testsuite/gas/riscv/mapping-relax.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.attribute arch, "rv32i"
.option relax
foo:
.align 2
lui a0, %hi (foo)
addi a0, a0, %lo (foo + 4)
.option arch, +a
lui a0, %tprel_hi (i)
add a0, a0, tp, %tprel_add (i)
lw a1, %tprel_lo (i) (a0)
.option arch, -a, +c
L1: auipc a0, %pcrel_hi (foo)
addi a0, a0, %pcrel_lo (L1)
call foo

.globl i
.section .tbss, "awT", @nobits
.type i, @object
.size i, 4
i:
.zero 4
16 changes: 16 additions & 0 deletions ld/testsuite/ld-riscv-elf/c-relax.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#source: c-relax.s
#ld: --relax
#objdump: -d -Mno-aliases

.*:[ ]+file format .*


Disassembly of section .text:

0+[0-9a-f]+ <_start>:
.*:[ ]+[0-9a-f]+[ ]+lui[ ]+.*
.*:[ ]+[0-9a-f]+[ ]+addi[ ]+.*
.*:[ ]+[0-9a-f]+[ ]+c\.lui[ ]+.*
.*:[ ]+[0-9a-f]+[ ]+addi[ ]+.*
.*:[ ]+[0-9a-f]+[ ]+c\.j[ ]+.*
.*:[ ]+[0-9a-f]+[ ]+jal[ ]+.*
12 changes: 12 additions & 0 deletions ld/testsuite/ld-riscv-elf/c-relax.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.option relax
.option arch, -c
.globl _start
_start:
lui a0, %hi (_start)
addi a0, a0, %lo (_start)
.option arch, +c
lui a0, %hi (_start)
addi a0, a0, %lo (_start)
call zero, _start
.option arch, -c
call zero, _start
1 change: 1 addition & 0 deletions ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ if [istarget "riscv*-*-*"] {
run_dump_test "pcgp-relax-02"
run_dump_test "c-lui"
run_dump_test "c-lui-2"
run_dump_test "c-relax"
run_dump_test "disas-jalr"
run_dump_test "pcrel-lo-addend"
run_dump_test "pcrel-lo-addend-2a"
Expand Down

0 comments on commit 5491579

Please sign in to comment.