[RFC] RISC-V: Set rvc elf_flags according to mapping symbols

Nelson Chu nelson@rivosinc.com
Fri Oct 24 01:57:07 GMT 2025


According to riscv psabi mentions rvc elf_flags,
This bit is set when the binary targets the C ABI, which allows instructions
to be aligned to 16-bit boundaries (the base RV32 and RV64 ISAs only allow
32-bit instruction alignment).

There are several ways to enable/disable c/zca extension for current assembler.
The following list the setting orders,
1. --with-arch configure option
2. -march option
3. .attribute directive
4. .option arch/rvc/norvc

Once the c/zca extensions are enabled in the above four cases, the current
assembler will set rvc elf_flags, even if the code hasn't been affected by
c/zca at all.  For example,

% cat a.s
.text
.option norvc
norvc_func:
nop
% riscv64-unknown-elf-as -march=rv32ic a.s -o a.o
% riscv64-unknown-elf-objdump -d a.o
...
Disassembly of section .text:

00000000 <norvc_func>:
   0:	00000013          	nop
% riscv64-unknown-elf-readelf -hs a.o

ELF Header:
...
  Flags:                             0x1, RVC, soft-float ABI
...
Symbol table '.symtab' contains 7 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 SECTION LOCAL  DEFAULT    1 .text
     2: 00000000     0 SECTION LOCAL  DEFAULT    2 .data
     3: 00000000     0 SECTION LOCAL  DEFAULT    3 .bss
     4: 00000000     0 NOTYPE  LOCAL  DEFAULT    1 norvc_func
     5: 00000000     0 NOTYPE  LOCAL  DEFAULT    1 $xrv32i2p1
     6: 00000000     0 SECTION LOCAL  DEFAULT    4 .riscv.attributes

The above a object is actually a norvc object, which only allows 32-bit
instructions, but the rvc elf_flags was turned on by the -march option.
It also happens when we build toolchain by --with-arch with c, but -march
or later .attribute and .option directives doesn't allow c.

I think there are several ways can resolve the problem, checking the mapping
symbols to make sure if there are any c extensions may be the easier way.

Passed gcc/binutils regressions of riscv-gnu-toolchain at least.
---
 gas/config/tc-riscv.c                           | 17 ++++++++++++++---
 .../gas/riscv/elf-header-flags-norvc.d          |  8 ++++++++
 .../gas/riscv/elf-header-flags-norvc.s          |  5 +++++
 gas/testsuite/gas/riscv/elf-header-flags-rvc.d  |  8 ++++++++
 gas/testsuite/gas/riscv/elf-header-flags-rvc.s  |  5 +++++
 5 files changed, 40 insertions(+), 3 deletions(-)
 create mode 100644 gas/testsuite/gas/riscv/elf-header-flags-norvc.d
 create mode 100644 gas/testsuite/gas/riscv/elf-header-flags-norvc.s
 create mode 100644 gas/testsuite/gas/riscv/elf-header-flags-rvc.d
 create mode 100644 gas/testsuite/gas/riscv/elf-header-flags-rvc.s

diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index df60c206b82..984bd29c74a 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -288,9 +288,6 @@ static struct riscv_set_options riscv_opts =
 static void
 riscv_set_rvc (bool rvc_value)
 {
-  if (rvc_value)
-    elf_flags |= EF_RISCV_RVC;
-
   if (start_assemble && subseg_text_p (now_seg)
       && riscv_opts.rvc && !rvc_value)
     {
@@ -723,6 +720,20 @@ riscv_check_mapping_symbols (bfd *abfd ATTRIBUTE_UNUSED,
 	}
       while (next != NULL);
     }
+
+  symbolS *s = symbol_rootP;
+  for (; s != NULL; s = symbol_next (s))
+    {
+      const char *name = S_GET_NAME (s);
+      if (name != NULL
+	  && strncmp (name, "$xrv", 4) == 0
+	  && (strstr (name, "_c") != NULL
+	      || strstr (name, "_zca") != NULL))
+	{
+	  elf_flags |= EF_RISCV_RVC;
+	  break;
+	}
+    }
 }
 
 /* The default target format to use.  */
diff --git a/gas/testsuite/gas/riscv/elf-header-flags-norvc.d b/gas/testsuite/gas/riscv/elf-header-flags-norvc.d
new file mode 100644
index 00000000000..b398835b592
--- /dev/null
+++ b/gas/testsuite/gas/riscv/elf-header-flags-norvc.d
@@ -0,0 +1,8 @@
+#as: -march=rv32ic
+#readelf: -h
+#source: elf-header-flags-norvc.s
+
+ELF Header:
+#...
+[ 	]+Flags:[ 	]+0x0
+#...
diff --git a/gas/testsuite/gas/riscv/elf-header-flags-norvc.s b/gas/testsuite/gas/riscv/elf-header-flags-norvc.s
new file mode 100644
index 00000000000..00d6e01ef00
--- /dev/null
+++ b/gas/testsuite/gas/riscv/elf-header-flags-norvc.s
@@ -0,0 +1,5 @@
+	.text
+	.option norvc
+	.global _start
+_start:
+	nop
diff --git a/gas/testsuite/gas/riscv/elf-header-flags-rvc.d b/gas/testsuite/gas/riscv/elf-header-flags-rvc.d
new file mode 100644
index 00000000000..074234d1abf
--- /dev/null
+++ b/gas/testsuite/gas/riscv/elf-header-flags-rvc.d
@@ -0,0 +1,8 @@
+#as: -march=rv32i
+#readelf: -h
+#source: elf-header-flags-rvc.s
+
+ELF Header:
+#...
+[ 	]+Flags:[ 	]+0x1, RVC.*
+#...
diff --git a/gas/testsuite/gas/riscv/elf-header-flags-rvc.s b/gas/testsuite/gas/riscv/elf-header-flags-rvc.s
new file mode 100644
index 00000000000..5ca03c87448
--- /dev/null
+++ b/gas/testsuite/gas/riscv/elf-header-flags-rvc.s
@@ -0,0 +1,5 @@
+	.text
+	.option rvc
+	.global _start
+_start:
+	nop
-- 
2.39.5 (Apple Git-154)



More information about the Binutils mailing list