public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Nelson Chu <nelson@rivosinc.com>
To: binutils@sourceware.org
Cc: i@maskray.me, nelson.rivosinc.com@NelsondeMBP.localdomain,
	Nelson Chu <nelson@rivosinc.com>
Subject: [PATCH] RISC-V: Don't emit internal relax relocations when --emit-relocs.
Date: Tue,  7 May 2024 18:07:49 +0800	[thread overview]
Message-ID: <20240507100749.44181-1-nelson@rivosinc.com> (raw)

Although PR27180 still has the bug, and there may be no conclusion yet about
PR30844, at least I think we cannot just emit the internal relocations when
--emit-relocs.  The internal relocation means it isn't defined in the riscv
psabi, it is just used in the GNU linker.  All of them are used for relaxation
so far.

For relax lui,
1. Emit R_RISCV_HI20 for R_RISCV_RVC_LUI.
2. R_RISCV_LUI_GPREL_I/S, which is same as R_RISCV_GPREL_I/S before, but it
   implies the relocation type before relaxing.  Emit R_RISCV_LO12_I/S for it,
   and may emit R_RISCV_GPREL_LO12_I/S for it in the future.

For relax auipc,
1. R_RISCV_AUIPC_GPREL_I/S is similar as R_RISCV_LUI_GPREL_I/S.  Emit
   R_RISCV_PCREL_LO12_I/S for it.  It is hard to find back the corresponding
   R_RISCV_PCREL_HI20 since deleted, so we still store the target symbol
   rather than it's pcrel instruction address.  I think it's fine since the
   symbol + addend field in the readelf/objdump is still shown as symbol - gp.
   Likewise, we may emit R_RISCV_GPREL_LO12_I/S for it in the future.

For relax tprel,
1. Emit R_RISCV_TPREL_LO12_I/S for R_RISCV_TPREL_I/S.

bfd/
	* elfnn-riscv.c (perform_relocation): Updated since R_RISCV_GPREL_I/S
	are seperated to R_RISCV_LUI_GPREL_I/S and R_RISCV_AUIPC_GPREL_I/S.
	(_bfd_riscv_relax_lui): Likewise.
	(_bfd_riscv_relax_pc): Likewise.
	(riscv_elf_relocate_section): Shouldn't emit internal relocation when
	--emit-relocs.
	* elfxx-riscv.c (howto_table_internal): Seperated R_RISCV_GPREL_I/S
	to R_RISCV_LUI_GPREL_I/S and R_RISCV_AUIPC_GPREL_I/S.
	(elf_internal_reloc_map, riscv_internal_reloc_map):
	Map the internal relax relocation to the one which we should emit when
	--emit-relocs.
	(riscv_emit_internal_reloc_type_lookup): New function.
	(elfxx-riscv.h): extern riscv_emit_internal_reloc_type_lookup.
include/
	* elf/riscv.h: Updated since R_RISCV_GPREL_I/S are seperated to
	R_RISCV_LUI_GPREL_I/S and R_RISCV_AUIPC_GPREL_I/S.
ld/
	* testsuite/ld-riscv-elf/c-lui-2-emitrelocs.d: New testcase.
	* testsuite/ld-riscv-elf/pcgp-relax-01-emitrelocs.d: Likewise.
	* testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated.
---
 bfd/elfnn-riscv.c                             | 28 +++++--
 bfd/elfxx-riscv.c                             | 84 +++++++++++++++++--
 bfd/elfxx-riscv.h                             |  3 +
 include/elf/riscv.h                           | 10 ++-
 .../ld-riscv-elf/c-lui-2-emitrelocs.d         | 23 +++++
 ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp    |  2 +
 .../ld-riscv-elf/pcgp-relax-01-emitrelocs.d   | 38 +++++++++
 7 files changed, 167 insertions(+), 21 deletions(-)
 create mode 100644 ld/testsuite/ld-riscv-elf/c-lui-2-emitrelocs.d
 create mode 100644 ld/testsuite/ld-riscv-elf/pcgp-relax-01-emitrelocs.d

diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 604f6de4511..dbf7380986d 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -1804,7 +1804,8 @@ perform_relocation (const reloc_howto_type *howto,
       break;
 
     case R_RISCV_LO12_I:
-    case R_RISCV_GPREL_I:
+    case R_RISCV_LUI_GPREL_I:
+    case R_RISCV_AUIPC_GPREL_I:
     case R_RISCV_TPREL_LO12_I:
     case R_RISCV_TPREL_I:
     case R_RISCV_PCREL_LO12_I:
@@ -1814,7 +1815,8 @@ perform_relocation (const reloc_howto_type *howto,
       break;
 
     case R_RISCV_LO12_S:
-    case R_RISCV_GPREL_S:
+    case R_RISCV_LUI_GPREL_S:
+    case R_RISCV_AUIPC_GPREL_S:
     case R_RISCV_TPREL_LO12_S:
     case R_RISCV_TPREL_S:
     case R_RISCV_PCREL_LO12_S:
@@ -2816,8 +2818,10 @@ riscv_elf_relocate_section (bfd *output_bfd,
 	    r = bfd_reloc_overflow;
 	  break;
 
-	case R_RISCV_GPREL_I:
-	case R_RISCV_GPREL_S:
+	case R_RISCV_LUI_GPREL_I:
+	case R_RISCV_LUI_GPREL_S:
+	case R_RISCV_AUIPC_GPREL_I:
+	case R_RISCV_AUIPC_GPREL_S:
 	  {
 	    bfd_vma gp = riscv_global_pointer_value (info);
 	    bool x0_base = VALID_ITYPE_IMM (relocation + rel->r_addend);
@@ -3136,6 +3140,14 @@ riscv_elf_relocate_section (bfd *output_bfd,
       switch (r)
 	{
 	case bfd_reloc_ok:
+	  {
+	    /* Shouldn't emit internal relocs.  */
+	    reloc_howto_type *emit_howto =
+		riscv_emit_internal_reloc_type_lookup (input_bfd, r_type);
+	    if (emit_howto)
+	      rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info),
+					  emit_howto->type);
+	  }
 	  continue;
 
 	case bfd_reloc_overflow:
@@ -4772,11 +4784,11 @@ _bfd_riscv_relax_lui (bfd *abfd,
       switch (ELFNN_R_TYPE (rel->r_info))
 	{
 	case R_RISCV_LO12_I:
-	  rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_I);
+	  rel->r_info = ELFNN_R_INFO (sym, R_RISCV_LUI_GPREL_I);
 	  return true;
 
 	case R_RISCV_LO12_S:
-	  rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_S);
+	  rel->r_info = ELFNN_R_INFO (sym, R_RISCV_LUI_GPREL_S);
 	  return true;
 
 	case R_RISCV_HI20:
@@ -5036,12 +5048,12 @@ _bfd_riscv_relax_pc (bfd *abfd ATTRIBUTE_UNUSED,
       switch (ELFNN_R_TYPE (rel->r_info))
 	{
 	case R_RISCV_PCREL_LO12_I:
-	  rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_I);
+	  rel->r_info = ELFNN_R_INFO (sym, R_RISCV_AUIPC_GPREL_I);
 	  rel->r_addend += hi_reloc.hi_addend;
 	  return true;
 
 	case R_RISCV_PCREL_LO12_S:
-	  rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_S);
+	  rel->r_info = ELFNN_R_INFO (sym, R_RISCV_AUIPC_GPREL_S);
 	  rel->r_addend += hi_reloc.hi_addend;
 	  return true;
 
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index b08e44577b8..39a36a71958 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -884,7 +884,7 @@ static reloc_howto_type howto_table_internal[] =
   /* R_RISCV_DELETE.  */
   EMPTY_HOWTO (0),
 
-  /* High 6 bits of 18-bit absolute address.  */
+  /* For lui relaxation, high 6 bits of 18-bit absolute address.  */
   HOWTO (R_RISCV_RVC_LUI,		/* type */
 	 0,				/* rightshift */
 	 2,				/* size */
@@ -899,8 +899,8 @@ static reloc_howto_type howto_table_internal[] =
 	 ENCODE_CITYPE_IMM (-1U),	/* dst_mask */
 	 false),			/* pcrel_offset */
 
-  /* GP-relative load.  */
-  HOWTO (R_RISCV_GPREL_I,		/* type */
+  /* For lui relaxation, GP-relative load.  */
+  HOWTO (R_RISCV_LUI_GPREL_I,		/* type */
 	 0,				/* rightshift */
 	 4,				/* size */
 	 32,				/* bitsize */
@@ -908,14 +908,14 @@ static reloc_howto_type howto_table_internal[] =
 	 0,				/* bitpos */
 	 complain_overflow_dont,	/* complain_on_overflow */
 	 bfd_elf_generic_reloc,		/* special_function */
-	 "R_RISCV_GPREL_I",		/* name */
+	 "R_RISCV_LUI_GPREL_I",		/* name */
 	 false,				/* partial_inplace */
 	 0,				/* src_mask */
 	 ENCODE_ITYPE_IMM (-1U),	/* dst_mask */
 	 false),			/* pcrel_offset */
 
-  /* GP-relative store.  */
-  HOWTO (R_RISCV_GPREL_S,		/* type */
+  /* For lui relaxation, GP-relative store.  */
+  HOWTO (R_RISCV_LUI_GPREL_S,		/* type */
 	 0,				/* rightshift */
 	 4,				/* size */
 	 32,				/* bitsize */
@@ -923,13 +923,43 @@ static reloc_howto_type howto_table_internal[] =
 	 0,				/* bitpos */
 	 complain_overflow_dont,	/* complain_on_overflow */
 	 bfd_elf_generic_reloc,		/* special_function */
-	 "R_RISCV_GPREL_S",		/* name */
+	 "R_RISCV_LUI_GPREL_S",		/* name */
 	 false,				/* partial_inplace */
 	 0,				/* src_mask */
 	 ENCODE_STYPE_IMM (-1U),	/* dst_mask */
 	 false),			/* pcrel_offset */
 
-  /* TP-relative TLS LE load.  */
+  /* For auipc relaxation, GP-relative load.  */
+  HOWTO (R_RISCV_AUIPC_GPREL_I,		/* type */
+	 0,				/* rightshift */
+	 4,				/* size */
+	 32,				/* bitsize */
+	 false,				/* pc_relative */
+	 0,				/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,		/* special_function */
+	 "R_RISCV_AUIPC_GPREL_I",	/* name */
+	 false,				/* partial_inplace */
+	 0,				/* src_mask */
+	 ENCODE_ITYPE_IMM (-1U),	/* dst_mask */
+	 false),			/* pcrel_offset */
+
+  /* For auipc relaxation, GP-relative store.  */
+  HOWTO (R_RISCV_AUIPC_GPREL_S,		/* type */
+	 0,				/* rightshift */
+	 4,				/* size */
+	 32,				/* bitsize */
+	 false,				/* pc_relative */
+	 0,				/* bitpos */
+	 complain_overflow_dont,	/* complain_on_overflow */
+	 bfd_elf_generic_reloc,		/* special_function */
+	 "R_RISCV_AUIPC_GPREL_S",	/* name */
+	 false,				/* partial_inplace */
+	 0,				/* src_mask */
+	 ENCODE_STYPE_IMM (-1U),	/* dst_mask */
+	 false),			/* pcrel_offset */
+
+  /* For tprel relaxation, TP-relative TLS LE load.  */
   HOWTO (R_RISCV_TPREL_I,		/* type */
 	 0,				/* rightshift */
 	 4,				/* size */
@@ -944,7 +974,7 @@ static reloc_howto_type howto_table_internal[] =
 	 ENCODE_ITYPE_IMM (-1U),	/* dst_mask */
 	 false),			/* pcrel_offset */
 
-  /* TP-relative TLS LE store.  */
+  /* For tprel relaxation, TP-relative TLS LE store.  */
   HOWTO (R_RISCV_TPREL_S,		/* type */
 	 0,				/* rightshift */
 	 4,				/* size */
@@ -1038,6 +1068,42 @@ riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return NULL;
 }
 
+/* A mapping from RISC-V internal reloc types to standard reloc types.  */
+struct elf_internal_reloc_map
+{ 
+  enum elf_riscv_reloc_type internal;
+  enum elf_riscv_reloc_type standard;
+};
+
+static const struct elf_internal_reloc_map riscv_internal_reloc_map[] =
+{
+  { R_RISCV_DELETE, R_RISCV_NONE },
+  { R_RISCV_RVC_LUI, R_RISCV_HI20 },
+  { R_RISCV_LUI_GPREL_I, R_RISCV_LO12_I},
+  { R_RISCV_LUI_GPREL_S, R_RISCV_LO12_S},
+  { R_RISCV_AUIPC_GPREL_I, R_RISCV_PCREL_LO12_I},
+  { R_RISCV_AUIPC_GPREL_S, R_RISCV_PCREL_LO12_S},
+  { R_RISCV_TPREL_I, R_RISCV_TPREL_LO12_I },
+  { R_RISCV_TPREL_S, R_RISCV_TPREL_LO12_S },
+};
+
+reloc_howto_type *
+riscv_emit_internal_reloc_type_lookup (bfd *abfd, unsigned int r_type)
+{
+  if (r_type < ARRAY_SIZE (howto_table))
+    return NULL;
+
+  unsigned int i;
+  for (i = 0; i < ARRAY_SIZE (riscv_internal_reloc_map); i++)
+    if (riscv_internal_reloc_map[i].internal == r_type)
+      return &howto_table[riscv_internal_reloc_map[i].standard];
+
+  (*_bfd_error_handler)
+	(_("%pB: warning: mismatched internal relocation type %#x"),
+	 abfd, r_type);
+  return NULL;
+}
+
 reloc_howto_type *
 riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
 {
diff --git a/bfd/elfxx-riscv.h b/bfd/elfxx-riscv.h
index 49be71746b9..9c747fdd540 100644
--- a/bfd/elfxx-riscv.h
+++ b/bfd/elfxx-riscv.h
@@ -46,6 +46,9 @@ riscv_reloc_name_lookup (bfd *, const char *);
 extern reloc_howto_type *
 riscv_reloc_type_lookup (bfd *, bfd_reloc_code_real_type);
 
+extern reloc_howto_type *
+riscv_emit_internal_reloc_type_lookup (bfd *, unsigned int r_type);
+
 extern reloc_howto_type *
 riscv_elf_rtype_to_howto (bfd *, unsigned int r_type);
 
diff --git a/include/elf/riscv.h b/include/elf/riscv.h
index c1e73f7f5c0..3da04ef4806 100644
--- a/include/elf/riscv.h
+++ b/include/elf/riscv.h
@@ -100,10 +100,12 @@ END_RELOC_NUMBERS (R_RISCV_max)
 /* Internal relocations used exclusively by the relaxation pass.  */
 #define R_RISCV_DELETE  (R_RISCV_max)
 #define R_RISCV_RVC_LUI (R_RISCV_max + 1)
-#define R_RISCV_GPREL_I (R_RISCV_max + 2)
-#define R_RISCV_GPREL_S (R_RISCV_max + 3)
-#define R_RISCV_TPREL_I (R_RISCV_max + 4)
-#define R_RISCV_TPREL_S (R_RISCV_max + 5)
+#define R_RISCV_LUI_GPREL_I (R_RISCV_max + 2)
+#define R_RISCV_LUI_GPREL_S (R_RISCV_max + 3)
+#define R_RISCV_AUIPC_GPREL_I (R_RISCV_max + 4)
+#define R_RISCV_AUIPC_GPREL_S (R_RISCV_max + 5)
+#define R_RISCV_TPREL_I (R_RISCV_max + 6)
+#define R_RISCV_TPREL_S (R_RISCV_max + 7)
 
 /* Processor specific flags for the ELF header e_flags field.  */
 
diff --git a/ld/testsuite/ld-riscv-elf/c-lui-2-emitrelocs.d b/ld/testsuite/ld-riscv-elf/c-lui-2-emitrelocs.d
new file mode 100644
index 00000000000..f5658732239
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/c-lui-2-emitrelocs.d
@@ -0,0 +1,23 @@
+#name: c.lui to c.li relaxation
+#source: c-lui-2.s
+#as: -march=rv32ic
+#ld: -m[riscv_choose_ilp32_emul] -Tc-lui-2.ld --emit-relocs
+#objdump: -dr -M no-aliases,numeric
+
+.*:     file format .*
+
+
+Disassembly of section \.text:
+
+.* <_start>:
+.*:	4501                	c.li	x10,0
+.*:[ 	]+R_RISCV_HI20[ 	]+foo
+.*:	7fe00513          	addi	x10,x0,2046
+.*:[ 	]+R_RISCV_NONE[ 	]+\*ABS\*\+0x2
+.*:[ 	]+R_RISCV_LO12_I[ 	]+foo
+.*:[ 	]+R_RISCV_RELAX[ 	]+\*ABS\*
+	...
+
+.* <foo>:
+.*:	8082                	c.jr	x1
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
index a1dd0e5e37e..de70dba628d 100644
--- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
+++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
@@ -123,9 +123,11 @@ if [istarget "riscv*-*-*"] {
     run_dump_test "call-relax"
     run_dump_test "pcgp-relax-01"
     run_dump_test "pcgp-relax-01-norelaxgp"
+    run_dump_test "pcgp-relax-01-emitrelocs"
     run_dump_test "pcgp-relax-02"
     run_dump_test "c-lui"
     run_dump_test "c-lui-2"
+    run_dump_test "c-lui-2-emitrelocs"
     run_dump_test "disas-jalr"
     run_dump_test "pcrel-lo-addend"
     run_dump_test "pcrel-lo-addend-2a"
diff --git a/ld/testsuite/ld-riscv-elf/pcgp-relax-01-emitrelocs.d b/ld/testsuite/ld-riscv-elf/pcgp-relax-01-emitrelocs.d
new file mode 100644
index 00000000000..9aa05d5be6a
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/pcgp-relax-01-emitrelocs.d
@@ -0,0 +1,38 @@
+#source: pcgp-relax-01.s
+#ld: --relax --emit-relocs
+#objdump: -dr -Mno-aliases
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+[0-9a-f]+ <_start>:
+[ 	]+[0-9a-f]+:[ 	]+[0-9a-f]+[ 	]+addi[ 	]+a0,a0,[0-9]+
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_PCREL_LO12_I[ 	]+.L2
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_RELAX[ 	]+\*ABS\*
+[ 	]+[0-9a-f]+:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+ra,[0-9a-f]+ <_start>
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_JAL[ 	]+_start
+[ 	]+[0-9a-f]+:[ 	]+[0-9a-f]+[ 	]+addi[ 	]+a1,gp,\-[0-9]+ # [0-9a-f]+ <data_g>
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_NONE[ 	]+\*ABS\*\+0x4
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_NONE[ 	]+\*ABS\*\+0x4
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_RELAX[ 	]+\*ABS\*
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_PCREL_LO12_I[ 	]+data_g\-0x[0-9a-f]+
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_RELAX[ 	]+\*ABS\*
+[ 	]+[0-9a-f]+:[ 	]+[0-9a-f]+[ 	]+addi[ 	]+a2,gp,\-[0-9]+ # [0-9a-f]+ <data_g>
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_NONE[ 	]+\*ABS\*\+0x4
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_RELAX[ 	]+\*ABS\*
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_LO12_I[ 	]+data_g\-0x[0-9a-f]+
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_RELAX[ 	]+\*ABS\*
+[ 	]+[0-9a-f]+:[ 	]+[0-9a-f]+[ 	]+addi[ 	]+a3,tp,0 # 0 <data_t>
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_NONE[ 	]+\*ABS\*\+0x4
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_RELAX[ 	]+\*ABS\*
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_NONE[ 	]+\*ABS\*\+0x4
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_RELAX[ 	]+\*ABS\*
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_TPREL_LO12_I[ 	]+data_t
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_RELAX[ 	]+\*ABS\*
+
+0+[0-9a-f]+ <.L2>:
+[ 	]+[0-9a-f]+:[ 	]+[0-9a-f]+[ 	]+auipc[ 	]+a0,0x[0-9a-f]+
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_PCREL_HI20[ 	]+data_g
+[ 	]+[0-9a-f]+:[ 	]+R_RISCV_RELAX[ 	]+\*ABS\*
-- 
2.39.3 (Apple Git-146)


                 reply	other threads:[~2024-05-07 10:07 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240507100749.44181-1-nelson@rivosinc.com \
    --to=nelson@rivosinc.com \
    --cc=binutils@sourceware.org \
    --cc=i@maskray.me \
    --cc=nelson.rivosinc.com@NelsondeMBP.localdomain \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).