]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
BFD: Fix the bug of R_LARCH_AGLIN caused by discard section
authormengqinggang <mengqinggang@loongson.cn>
Wed, 24 Jan 2024 06:34:26 +0000 (14:34 +0800)
committerliuzhensong <liuzhensong@loongson.cn>
Sun, 31 Mar 2024 06:21:00 +0000 (14:21 +0800)
To represent the first and third expression of .align, R_LARCH_ALIGN need to
associate with a symbol. We define a local symbol for R_LARCH_AGLIN.
But if the section of the local symbol is discarded, it may result in
a undefined symbol error.

Instead, we use the section name symbols, and this does not need to
add extra symbols.

During partial linking (ld -r), if the symbol associated with a relocation is
STT_SECTION type, the addend of relocation needs to add the section output
offset. We prevent it for R_LARCH_ALIGN.

The elf_backend_data.rela_normal only can set all relocations of a target to
rela_normal. Add a new function is_rela_normal to elf_backend_data, it can
set part of relocations to rela_normal.

bfd/elf-bfd.h
bfd/elflink.c
bfd/elfnn-loongarch.c
bfd/elfxx-target.h
gas/config/tc-loongarch.c
gas/testsuite/gas/loongarch/relax_align.d
ld/testsuite/ld-loongarch-elf/relax-align-discard.lds [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/relax-align-discard.s [new file with mode: 0644]
ld/testsuite/ld-loongarch-elf/relax.exp

index c5d325435b60a310844c9adc72bda9c66b64b4af..af507b93df58ecdf18b780ee516849401af66b13 100644 (file)
@@ -1721,6 +1721,10 @@ struct elf_backend_data
      backend relocate_section routine for relocatable linking.  */
   unsigned rela_normal : 1;
 
+  /* Whether a relocation is rela_normal. Compared with rela_normal,
+     is_rela_normal can set part of relocations to rela_normal.  */
+  bool (*is_rela_normal) (Elf_Internal_Rela *);
+
   /* Set if DT_REL/DT_RELA/DT_RELSZ/DT_RELASZ should not include PLT
      relocations.  */
   unsigned dtrel_excludes_plt : 1;
index 24eb30d19468b3a45eded4eae9f278bd0edac469..5d9b4092e48f4b952b53856dc2ea179c786cae1f 100644 (file)
@@ -11692,7 +11692,10 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                    {
                      rel_hash = PTR_ADD (esdo->rela.hashes, esdo->rela.count);
                      rela_hash_list = rel_hash;
-                     rela_normal = bed->rela_normal;
+                     if (bed->is_rela_normal != NULL)
+                       rela_normal = bed->is_rela_normal (irela);
+                     else
+                       rela_normal = bed->rela_normal;
                    }
 
                  irela->r_offset = _bfd_elf_section_offset (output_bfd,
index c42052f93212159e3d597728c3363b5f44dffc0a..1679aa5da7d9eed9ec4816cdf36790f9ae568752 100644 (file)
@@ -5454,6 +5454,21 @@ elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h)
   return _bfd_elf_hash_symbol (h);
 }
 
+/* If a relocation is rela_normal and the symbol associated with the
+   relocation is STT_SECTION type, the addend of the relocation would add
+   sec->output_offset when partial linking (ld -r).
+   See elf_backend_data.rela_normal and elf_link_input_bfd().
+   The addend of R_LARCH_ALIGN is used to represent the first and third
+   expression of .align, it should be a constant when linking.  */
+
+static bool
+loongarch_elf_is_rela_normal (Elf_Internal_Rela *rel)
+{
+  if (R_LARCH_ALIGN == ELFNN_R_TYPE (rel->r_info))
+    return false;
+  return true;
+}
+
 #define TARGET_LITTLE_SYM loongarch_elfNN_vec
 #define TARGET_LITTLE_NAME "elfNN-loongarch"
 #define ELF_ARCH bfd_arch_loongarch
@@ -5489,6 +5504,7 @@ elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h)
 #define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
 #define elf_backend_hash_symbol elf_loongarch64_hash_symbol
 #define bfd_elfNN_bfd_relax_section loongarch_elf_relax_section
+#define elf_backend_is_rela_normal loongarch_elf_is_rela_normal
 
 #define elf_backend_dtrel_excludes_plt 1
 
index 1e6992b579304f24f8aaa658442bf28a49bb2b34..6e2d948b69b2bc66c166f012e09842e6957f8e19 100644 (file)
 #define elf_backend_rela_normal 0
 #endif
 
+#ifndef elf_backend_is_rela_normal
+#define elf_backend_is_rela_normal NULL
+#endif
+
 #ifndef elf_backend_dtrel_excludes_plt
 #define elf_backend_dtrel_excludes_plt 0
 #endif
@@ -955,6 +959,7 @@ static const struct elf_backend_data elfNN_bed =
   elf_backend_default_use_rela_p,
   elf_backend_rela_plts_and_copies_p,
   elf_backend_rela_normal,
+  elf_backend_is_rela_normal,
   elf_backend_dtrel_excludes_plt,
   elf_backend_sign_extend_vma,
   elf_backend_want_got_plt,
index 30aefce36fd44941086e2611b4062e2ba6604ff7..6b1a89738efeb455cff9fc5d1930e987b939c552 100644 (file)
@@ -1791,10 +1791,7 @@ loongarch_frag_align_code (int n, int max)
      if (fragP->fr_subtype != 0 && offset > fragP->fr_subtype).  */
   if (max > 0 && (bfd_vma) max < worst_case_bytes)
     {
-      s = symbol_find (".Lla-relax-align");
-      if (s == NULL)
-       s = (symbolS *)local_symbol_make (".Lla-relax-align", now_seg,
-                                         &zero_address_frag, 0);
+      s = symbol_find (now_seg->name);
       ex.X_add_symbol = s;
       ex.X_op = O_symbol;
       ex.X_add_number = (max << 8) | n;
index fc1fd032611503122db18c0e166118e94d5dd1fd..acd215a4abcacf319a79148f4f2286062a27f1d1 100644 (file)
@@ -7,7 +7,7 @@
 
 Disassembly of section .text:
 
-[      ]*0000000000000000 <.Lla-relax-align>:
+[      ]*0000000000000000 <.text>:
 [      ]+0:[   ]+4c000020[     ]+ret
 [      ]+4:[   ]+03400000[     ]+nop
 [      ]+4: R_LARCH_ALIGN[     ]+\*ABS\*\+0xc
@@ -20,12 +20,12 @@ Disassembly of section .text:
 [      ]+1c:[  ]+03400000[     ]+nop
 [      ]+20:[  ]+4c000020[     ]+ret
 [      ]+24:[  ]+03400000[     ]+nop
-[      ]+24: R_LARCH_ALIGN[    ]+.Lla-relax-align\+0x104
+[      ]+24: R_LARCH_ALIGN[    ]+.text\+0x104
 [      ]+28:[  ]+03400000[     ]+nop
 [      ]+2c:[  ]+03400000[     ]+nop
 [      ]+30:[  ]+4c000020[     ]+ret
 [      ]+34:[  ]+03400000[     ]+nop
-[      ]+34: R_LARCH_ALIGN[    ]+.Lla-relax-align\+0xb04
+[      ]+34: R_LARCH_ALIGN[    ]+.text\+0xb04
 [      ]+38:[  ]+03400000[     ]+nop
 [      ]+3c:[  ]+03400000[     ]+nop
 [      ]+40:[  ]+4c000020[     ]+ret
diff --git a/ld/testsuite/ld-loongarch-elf/relax-align-discard.lds b/ld/testsuite/ld-loongarch-elf/relax-align-discard.lds
new file mode 100644 (file)
index 0000000..4a81323
--- /dev/null
@@ -0,0 +1,4 @@
+SECTIONS
+{
+  /DISCARD/ : { *(.another.*) }
+}
diff --git a/ld/testsuite/ld-loongarch-elf/relax-align-discard.s b/ld/testsuite/ld-loongarch-elf/relax-align-discard.s
new file mode 100644 (file)
index 0000000..b65d63f
--- /dev/null
@@ -0,0 +1,17 @@
+# Use the section name symbol for R_LARCH_ALIGN to avoid discard section problem
+.section ".another.text", "ax"
+.cfi_startproc
+break 0
+.cfi_def_cfa_offset 16
+.p2align 5
+break 1
+.cfi_endproc
+
+.text
+.cfi_startproc
+break 0
+.cfi_def_cfa_offset 16
+.p2align 5
+break 1
+.cfi_endproc
+
index 7d95a9ca41dac51b1a9c46faf7563e957fd1be0e..ed71fb45b46141c06040f4f5a87280d26c5c89ed 100644 (file)
@@ -295,6 +295,18 @@ if [istarget loongarch64-*-*] {
                "relax-align" \
            ] \
        ]
+
+    run_ld_link_tests \
+      [list \
+       [list \
+         "loongarch relax align discard" \
+         "-e 0x0 -T relax-align-discard.lds -r" "" \
+         "" \
+         {relax-align-discard.s} \
+         {} \
+         "relax-align-discard" \
+       ] \
+      ]
   }
 
   set objdump_flags "-s -j .data"