RISC-V: Add --[no-]relax-gp to ld
authorFangrui Song <i@maskray.me>
Fri, 24 Feb 2023 06:11:14 +0000 (22:11 -0800)
committerFangrui Song <i@maskray.me>
Fri, 24 Feb 2023 06:11:14 +0000 (22:11 -0800)
--relax enables all relaxations.  --no-relax-gp disables GP relaxation to
allow measuring its effect.

The option can test effectiveness of GP relaxation and support some ABI
variants that use GP for other purposes.

Link: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/298
bfd/
    * elfnn-riscv.c (struct riscv_elf_link_hash_table): Add params.
    (riscv_elfNN_set_options): New.
    (riscv_info_to_howto_rela): Check relax_gp.
    (_bfd_riscv_relax_section): Likewise.
    * elfxx-riscv.h (struct riscv_elf_params): New.
    (riscv_elf32_set_options): New.
    (riscv_elf64_set_options): New.
ld/
    * emultempl/riscvelf.em: Add option parsing.
    * testsuite/ld-riscv-elf/code-model-relax-medlow-01-norelaxgp.d: New.
    * testsuite/ld-riscv-elf/pcgp-relax-01-norelaxgp.d: New.
    * testsuite/ld-riscv-elf/pcgp-relax-02.d: Test --relax --relax-gp can be
      used together.

bfd/ChangeLog
bfd/elfnn-riscv.c
bfd/elfxx-riscv.h
ld/ChangeLog
ld/emultempl/riscvelf.em
ld/testsuite/ld-riscv-elf/code-model-relax-medlow-01-norelaxgp.d [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
ld/testsuite/ld-riscv-elf/pcgp-relax-01-norelaxgp.d [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/pcgp-relax-02.d

index b7c03c11678b09fdd2c3c74eeaab0c1783418c16..50e1e17ef4d508e6d8b31fc3aa23f6d3ff11f7c4 100644 (file)
@@ -1,3 +1,13 @@
+2023-02-23  Fangrui Song  <i@maskray.me>
+
+       * elfnn-riscv.c (struct riscv_elf_link_hash_table): Add params.
+       (riscv_elfNN_set_options): New.
+       (riscv_info_to_howto_rela): Check relax_gp.
+       (_bfd_riscv_relax_section): Likewise.
+       * elfxx-riscv.h (struct riscv_elf_params): New.
+       (riscv_elf32_set_options): New.
+       (riscv_elf64_set_options): New.
+
 2023-02-23  Nick Clifton  <nickc@redhat.com>
             Alan Modra  <amodra@gmail.com>
 
index 355ddb225660e2b89c00636932a2729ef74fe341..1200e6b11b5bf486c0558b1173ba88ae99b30800 100644 (file)
@@ -118,6 +118,9 @@ struct riscv_elf_link_hash_table
 {
   struct elf_link_hash_table elf;
 
+  /* Various options and other info passed from the linker.  */
+  struct riscv_elf_params *params;
+
   /* Short-cuts to get to dynamic linker sections.  */
   asection *sdyntdata;
 
@@ -157,6 +160,13 @@ struct riscv_elf_link_hash_table
     && elf_hash_table_id (elf_hash_table (p)) == RISCV_ELF_DATA)       \
    ? (struct riscv_elf_link_hash_table *) (p)->hash : NULL)
 
+void
+riscv_elfNN_set_options (struct bfd_link_info *link_info,
+                        struct riscv_elf_params *params)
+{
+  riscv_elf_hash_table (link_info)->params = params;
+}
+
 static bool
 riscv_info_to_howto_rela (bfd *abfd,
                          arelent *cache_ptr,
@@ -4389,7 +4399,9 @@ _bfd_riscv_relax_lui (bfd *abfd,
                      bool undefined_weak)
 {
   bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
-  bfd_vma gp = riscv_global_pointer_value (link_info);
+  bfd_vma gp = riscv_elf_hash_table (link_info)->params->relax_gp
+                  ? riscv_global_pointer_value (link_info)
+                  : 0;
   int use_rvc = elf_elfheader (abfd)->e_flags & EF_RISCV_RVC;
 
   BFD_ASSERT (rel->r_offset + 4 <= sec->size);
@@ -4834,7 +4846,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
                   || type == R_RISCV_TPREL_LO12_I
                   || type == R_RISCV_TPREL_LO12_S)
            relax_func = _bfd_riscv_relax_tls_le;
-         else if (!bfd_link_pic (info)
+         else if (!bfd_link_pic (info) && htab->params->relax_gp
                   && (type == R_RISCV_PCREL_HI20
                       || type == R_RISCV_PCREL_LO12_I
                       || type == R_RISCV_PCREL_LO12_S))
index 5e1bdae9b2a0acba0172f6fdf083a5d0037f397d..abcb409bd78df33a5f76f6bdb40f257b7812b8e3 100644 (file)
 
 #define RISCV_UNKNOWN_VERSION -1
 
+struct riscv_elf_params
+{
+  /* Whether to relax code sequences to GP-relative addressing.  */
+  bool relax_gp;
+};
+
+extern void riscv_elf32_set_options (struct bfd_link_info *,
+                                    struct riscv_elf_params *);
+extern void riscv_elf64_set_options (struct bfd_link_info *,
+                                    struct riscv_elf_params *);
+
 extern reloc_howto_type *
 riscv_reloc_name_lookup (bfd *, const char *);
 
index de9ed2753bc933d04fc40b9bb5d38e54f1b646f1..9f4ad7cbf2533a06cc6e4c768a730129c03cefdb 100644 (file)
@@ -1,3 +1,11 @@
+2023-02-23  Fangrui Song  <i@maskray.me>
+
+       * emultempl/riscvelf.em: Add option parsing.
+       * testsuite/ld-riscv-elf/code-model-relax-medlow-01-norelaxgp.d: New.
+       * testsuite/ld-riscv-elf/pcgp-relax-01-norelaxgp.d: New.
+       * testsuite/ld-riscv-elf/pcgp-relax-02.d: Test --relax --relax-gp can be
+       used together.
+
 2023-02-20  Nick Clifton  <nickc@redhat.com>
 
        PR 30004
index b12d15065c4d5ba108c8c4b1d91c26719a533193..bb6298d3e8d47b38a8ce077ae0cdb39d2465827b 100644 (file)
@@ -25,6 +25,40 @@ fragment <<EOF
 #include "elf/riscv.h"
 #include "elfxx-riscv.h"
 
+static struct riscv_elf_params params = { .relax_gp = 1 };
+EOF
+
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.  */
+PARSE_AND_LIST_PROLOGUE=${PARSE_AND_LIST_PROLOGUE}'
+enum risccv_opt
+{
+  OPTION_RELAX_GP = 321,
+  OPTION_NO_RELAX_GP,
+};
+'
+
+PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
+    { "relax-gp", no_argument, NULL, OPTION_RELAX_GP },
+    { "no-relax-gp", no_argument, NULL, OPTION_NO_RELAX_GP },
+'
+
+PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'
+  fprintf (file, _("  --relax-gp                  Perform GP relaxation\n"));
+  fprintf (file, _("  --no-relax-gp               Don'\''t perform GP relaxation\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
+    case OPTION_RELAX_GP:
+      params.relax_gp = 1;
+      break;
+
+    case OPTION_NO_RELAX_GP:
+      params.relax_gp = 0;
+      break;
+'
+
+fragment <<EOF
 static void
 riscv_elf_before_allocation (void)
 {
@@ -96,6 +130,8 @@ riscv_create_output_section_statements (void)
               " whilst linking %s binaries\n"), "RISC-V");
       return;
     }
+
+  riscv_elf${ELFSIZE}_set_options (&link_info, &params);
 }
 
 EOF
diff --git a/ld/testsuite/ld-riscv-elf/code-model-relax-medlow-01-norelaxgp.d b/ld/testsuite/ld-riscv-elf/code-model-relax-medlow-01-norelaxgp.d
new file mode 100644 (file)
index 0000000..8e40cc5
--- /dev/null
@@ -0,0 +1,4 @@
+#source: code-model.s
+#as: -march=rv64i -mabi=lp64 --defsym __medlow__=1
+#ld: -Tcode-model-01.ld -melf64lriscv --no-relax-gp --relax
+#error: .*relocation truncated to fit: R_RISCV_HI20 against `symbolL'
index 0f7ccd92ed5fc9cf850391b8e139793b77b497e8..5dd6144efd346872a7d638ec4fc21a7805355194 100644 (file)
@@ -122,6 +122,7 @@ if [istarget "riscv*-*-*"] {
     run_dump_test "align-small-region"
     run_dump_test "call-relax"
     run_dump_test "pcgp-relax-01"
+    run_dump_test "pcgp-relax-01-norelaxgp"
     run_dump_test "pcgp-relax-02"
     run_dump_test "c-lui"
     run_dump_test "c-lui-2"
@@ -141,6 +142,7 @@ if [istarget "riscv*-*-*"] {
     run_dump_test "code-model-medany-weakref-01"
     run_dump_test "code-model-medany-weakref-02"
     run_dump_test "code-model-relax-medlow-01"
+    run_dump_test "code-model-relax-medlow-01-norelaxgp"
     run_dump_test "code-model-relax-medlow-02"
     run_dump_test "code-model-relax-medlow-weakref-01"
     run_dump_test "code-model-relax-medlow-weakref-02"
diff --git a/ld/testsuite/ld-riscv-elf/pcgp-relax-01-norelaxgp.d b/ld/testsuite/ld-riscv-elf/pcgp-relax-01-norelaxgp.d
new file mode 100644 (file)
index 0000000..d134457
--- /dev/null
@@ -0,0 +1,18 @@
+#source: pcgp-relax-01.s
+#ld: --no-relax-gp --relax
+#objdump: -d -Mno-aliases
+
+.*:[   ]+file format .*
+
+
+Disassembly of section \.text:
+
+0+[0-9a-f]+ <_start>:
+.*:[   ]+[0-9a-f]+[    ]+addi[         ]+a0,a0,[0-9]+
+.*:[   ]+[0-9a-f]+[    ]+jal[          ]+ra,[0-9a-f]+ <_start>
+.*:[   ]+[0-9a-f]+[    ]+auipc[        ]+a1,0x[0-9a-f]+
+.*:[   ]+[0-9a-f]+[    ]+addi[         ]+a1,a1,[0-9]+ # [0-9a-f]+ <data_g>
+.*:[   ]+[0-9a-f]+[    ]+lui[          ]+a2,0x[0-9a-f]+
+.*:[   ]+[0-9a-f]+[    ]+addi[         ]+a2,a2,[0-9]+ # [0-9a-f]+ <data_g>
+.*:[   ]+[0-9a-f]+[    ]+addi[         ]+a3,tp,0 # 0 <data_t>
+.*:[   ]+[0-9a-f]+[    ]+auipc[        ]+a0,0x[0-9a-f]+
index 1248132ab42c4cdf8460104bd647265e878d498b..055f03e57f2b08204f03b12d615838e9eef4662b 100644 (file)
@@ -1,6 +1,6 @@
 #source: pcgp-relax-02.s
 #as:
-#ld: --relax
+#ld: --relax --relax-gp
 #objdump: -d
 
 .*:[   ]+file format .*