elf: Handle .gnu.debuglto_.debug_* sections
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 19 Mar 2021 03:46:28 +0000 (20:46 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 19 Mar 2021 03:57:02 +0000 (20:57 -0700)
commit 994b25132814f4c2be93ce53a616a74139c4cf3c
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Sun Jan 17 20:01:16 2021 -0800

    ld/elf: Ignore section symbols when matching linkonce with comdat

ignored section symbols when comparing symbols in 2 sections.  Since all
references to debugging sections are done with section symbols, symbols
in debugging sections are ignored and we fail to match symbols in comdat
debugging sections.  Also .gnu.debuglto_.debug_* sections aren't treated
as debugging sections.

1. Treate .gnu.debuglto_.debug_ section as debugging section unless it
is marked with SHF_EXCLUDE.
2. Revert commit 994b2513281 in elf_create_symbuf.
3. Ignore section symbols only when matching non-debugging sections or
linkonce section with comdat section.

bfd/

PR ld/27590
* elf.c (_bfd_elf_make_section_from_shdr): Treate
.gnu.debuglto_.debug_ section as debugging section unless it is
marked with SHF_EXCLUDE.
* elflink.c (elf_create_symbuf): Revert commit 994b2513281.
(bfd_elf_match_symbols_in_sections): Ignore section symbols when
matching non-debugging sections or linkonce section with comdat
section.

ld/

PR ld/27590
* testsuite/ld-elf/pr27590.s: New file.
* testsuite/ld-elf/pr27590a.d: Likewise.
* testsuite/ld-elf/pr27590b.d: Likewise.
* testsuite/ld-i386/i386.exp: Also run ld/27193 test with
--reduce-memory-overheads.

bfd/ChangeLog
bfd/elf.c
bfd/elflink.c
ld/ChangeLog
ld/testsuite/ld-elf/pr27590.s [new file with mode: 0644]
ld/testsuite/ld-elf/pr27590a.d [new file with mode: 0644]
ld/testsuite/ld-elf/pr27590b.d [new file with mode: 0644]
ld/testsuite/ld-i386/i386.exp

index 94155de66eb4c20bb147b7cc381c8916213a8a1a..2e43a4d784d368f547fde24e5d332d6da7f4cd62 100644 (file)
@@ -1,3 +1,14 @@
+2021-03-18  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/27590
+       * elf.c (_bfd_elf_make_section_from_shdr): Treate
+       .gnu.debuglto_.debug_ section as debugging section unless it is
+       marked with SHF_EXCLUDE.
+       * elflink.c (elf_create_symbuf): Revert commit 994b2513281.
+       (bfd_elf_match_symbols_in_sections): Ignore section symbols when
+       matching non-debugging sections or linkonce section with comdat
+       section.
+
 2021-03-18  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/27587
index 35c31cf40bfb226a7a5d7743d51ac91122cf1b2b..7bd12dfbf37be4ca22304fa10729aa258000334f 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1085,6 +1085,10 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       if (name [0] == '.')
        {
          if (strncmp (name, ".debug", 6) == 0
+             /* NB: Treate .gnu.debuglto_.debug_ section as debugging
+                section unless it is marked with SHF_EXCLUDE.  */
+             || ((flags & SEC_EXCLUDE) == 0
+                 && strncmp (name, ".gnu.debuglto_.debug_", 21) == 0)
              || strncmp (name, ".gnu.linkonce.wi.", 17) == 0
              || strncmp (name, ".zdebug", 7) == 0)
            flags |= SEC_DEBUGGING | SEC_ELF_OCTETS;
index e1278a5d95e797543cbeb208ce0312eb27a96a00..69362670667586d8448b41bd14fe5954d135f8ee 100644 (file)
@@ -8135,12 +8135,8 @@ elf_create_symbuf (size_t symcount, Elf_Internal_Sym *isymbuf)
   if (indbuf == NULL)
     return NULL;
 
-  /* NB: When checking if 2 sections define the same set of local and
-     global symbols, ignore both undefined and section symbols in the
-     symbol table.  */
   for (ind = indbuf, i = 0; i < symcount; i++)
-    if (isymbuf[i].st_shndx != SHN_UNDEF
-       && ELF_ST_TYPE (isymbuf[i].st_info) != STT_SECTION)
+    if (isymbuf[i].st_shndx != SHN_UNDEF)
       *ind++ = &isymbuf[i];
   indbufend = ind;
 
@@ -8203,9 +8199,10 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
   struct elf_symbuf_head *ssymbuf1, *ssymbuf2;
   Elf_Internal_Sym *isym, *isymend;
   struct elf_symbol *symtable1 = NULL, *symtable2 = NULL;
-  size_t count1, count2, i;
+  size_t count1, count2, sec_count1, sec_count2, i;
   unsigned int shndx1, shndx2;
   bfd_boolean result;
+  bfd_boolean ignore_section_symbol_p;
 
   bfd1 = sec1->owner;
   bfd2 = sec2->owner;
@@ -8239,6 +8236,13 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
   ssymbuf1 = (struct elf_symbuf_head *) elf_tdata (bfd1)->symbuf;
   ssymbuf2 = (struct elf_symbuf_head *) elf_tdata (bfd2)->symbuf;
 
+  /* Ignore section symbols only when matching non-debugging sections
+     or linkonce section with comdat section.  */
+  ignore_section_symbol_p
+    = ((sec1->flags & SEC_DEBUGGING) == 0
+       || ((elf_section_flags (sec1) & SHF_GROUP)
+          != (elf_section_flags (sec2) & SHF_GROUP)));
+
   if (ssymbuf1 == NULL)
     {
       isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
@@ -8278,6 +8282,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
       hi = ssymbuf1->count;
       ssymbuf1++;
       count1 = 0;
+      sec_count1 = 0;
       while (lo < hi)
        {
          mid = (lo + hi) / 2;
@@ -8292,11 +8297,19 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
              break;
            }
        }
+      if (ignore_section_symbol_p)
+       {
+         for (i = 0; i < count1; i++)
+           if (ELF_ST_TYPE (ssymbuf1->ssym[i].st_info) == STT_SECTION)
+             sec_count1++;
+         count1 -= sec_count1;
+       }
 
       lo = 0;
       hi = ssymbuf2->count;
       ssymbuf2++;
       count2 = 0;
+      sec_count2 = 0;
       while (lo < hi)
        {
          mid = (lo + hi) / 2;
@@ -8311,6 +8324,13 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
              break;
            }
        }
+      if (ignore_section_symbol_p)
+       {
+         for (i = 0; i < count2; i++)
+           if (ELF_ST_TYPE (ssymbuf2->ssym[i].st_info) == STT_SECTION)
+             sec_count2++;
+         count2 -= sec_count2;
+       }
 
       if (count1 == 0 || count2 == 0 || count1 != count2)
        goto done;
@@ -8323,24 +8343,30 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
        goto done;
 
       symp = symtable1;
-      for (ssym = ssymbuf1->ssym, ssymend = ssym + count1;
-          ssym < ssymend; ssym++, symp++)
-       {
-         symp->u.ssym = ssym;
-         symp->name = bfd_elf_string_from_elf_section (bfd1,
-                                                       hdr1->sh_link,
-                                                       ssym->st_name);
-       }
+      for (ssym = ssymbuf1->ssym, ssymend = ssym + count1 + sec_count1;
+          ssym < ssymend; ssym++)
+       if (sec_count1 == 0
+           || ELF_ST_TYPE (ssym->st_info) != STT_SECTION)
+         {
+           symp->u.ssym = ssym;
+           symp->name = bfd_elf_string_from_elf_section (bfd1,
+                                                         hdr1->sh_link,
+                                                         ssym->st_name);
+           symp++;
+         }
 
       symp = symtable2;
-      for (ssym = ssymbuf2->ssym, ssymend = ssym + count2;
-          ssym < ssymend; ssym++, symp++)
-       {
-         symp->u.ssym = ssym;
-         symp->name = bfd_elf_string_from_elf_section (bfd2,
-                                                       hdr2->sh_link,
-                                                       ssym->st_name);
-       }
+      for (ssym = ssymbuf2->ssym, ssymend = ssym + count2 + sec_count2;
+          ssym < ssymend; ssym++)
+       if (sec_count2 == 0
+           || ELF_ST_TYPE (ssym->st_info) != STT_SECTION)
+         {
+           symp->u.ssym = ssym;
+           symp->name = bfd_elf_string_from_elf_section (bfd2,
+                                                         hdr2->sh_link,
+                                                         ssym->st_name);
+           symp++;
+         }
 
       /* Sort symbol by name.  */
       qsort (symtable1, count1, sizeof (struct elf_symbol),
@@ -8369,12 +8395,16 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
   /* Count definitions in the section.  */
   count1 = 0;
   for (isym = isymbuf1, isymend = isym + symcount1; isym < isymend; isym++)
-    if (isym->st_shndx == shndx1)
+    if (isym->st_shndx == shndx1
+       && (!ignore_section_symbol_p
+           || ELF_ST_TYPE (isym->st_info) != STT_SECTION))
       symtable1[count1++].u.isym = isym;
 
   count2 = 0;
   for (isym = isymbuf2, isymend = isym + symcount2; isym < isymend; isym++)
-    if (isym->st_shndx == shndx2)
+    if (isym->st_shndx == shndx2
+       && (!ignore_section_symbol_p
+           || ELF_ST_TYPE (isym->st_info) != STT_SECTION))
       symtable2[count2++].u.isym = isym;
 
   if (count1 == 0 || count2 == 0 || count1 != count2)
index d9b049f003ca9147c85619005c84967737c860c8..30ac9b4d4705e5768995ca7b78978929bc5d48b0 100644 (file)
@@ -1,3 +1,12 @@
+2021-03-18  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/27590
+       * testsuite/ld-elf/pr27590.s: New file.
+       * testsuite/ld-elf/pr27590a.d: Likewise.
+       * testsuite/ld-elf/pr27590b.d: Likewise.
+       * testsuite/ld-i386/i386.exp: Also run ld/27193 test with
+       --reduce-memory-overheads.
+
 2021-03-18  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/27587
diff --git a/ld/testsuite/ld-elf/pr27590.s b/ld/testsuite/ld-elf/pr27590.s
new file mode 100644 (file)
index 0000000..f7340b4
--- /dev/null
@@ -0,0 +1,6 @@
+       .section        .gnu.debuglto_.debug_macro,"",%progbits
+.Ldebug_macro0:
+       .dc.a   .Ldebug_macro2
+       .section        .gnu.debuglto_.debug_macro,"G",%progbits,wm4,comdat
+.Ldebug_macro2:
+       .long   0x4
diff --git a/ld/testsuite/ld-elf/pr27590a.d b/ld/testsuite/ld-elf/pr27590a.d
new file mode 100644 (file)
index 0000000..c24cd89
--- /dev/null
@@ -0,0 +1,10 @@
+#source: pr27590.s
+#ld: -r tmpdir/pr27590.o
+#readelf: -rW
+#xfail: [is_generic]
+
+Relocation section '\.rel.*\.gnu\.debuglto_\.debug_macro' at offset 0x[0-9a-z]+ contains 2 entries:
+[ \t]+Offset[ \t]+Info[ \t]+Type[ \t]+Sym.*
+[0-9a-f]+[ \t]+[0-9a-f]+[ \t]+R_.*[ \t]+[0]+[ \t]+\.gnu\.debuglto_\.debug_macro.*
+[0-9a-f]+[ \t]+[0-9a-f]+[ \t]+R_.*[ \t]+[0]+[ \t]+\.gnu\.debuglto_\.debug_macro.*
+#pass
diff --git a/ld/testsuite/ld-elf/pr27590b.d b/ld/testsuite/ld-elf/pr27590b.d
new file mode 100644 (file)
index 0000000..68b198b
--- /dev/null
@@ -0,0 +1,10 @@
+#source: pr27590.s
+#ld: -r tmpdir/pr27590.o --reduce-memory-overheads
+#readelf: -rW
+#xfail: [is_generic]
+
+Relocation section '\.rel.*\.gnu\.debuglto_\.debug_macro' at offset 0x[0-9a-z]+ contains 2 entries:
+[ \t]+Offset[ \t]+Info[ \t]+Type[ \t]+Sym.*
+[0-9a-f]+[ \t]+[0-9a-f]+[ \t]+R_.*[ \t]+[0]+[ \t]+\.gnu\.debuglto_\.debug_macro.*
+[0-9a-f]+[ \t]+[0-9a-f]+[ \t]+R_.*[ \t]+[0]+[ \t]+\.gnu\.debuglto_\.debug_macro.*
+#pass
index d9075bf27b56b48886f25a0289814f3c31968f69..6ad69a818f5ebed7522c1feac7ca3ee22312d23a 100644 (file)
@@ -245,11 +245,16 @@ set i386tests {
      "-melf_i386 -shared -Bsymbolic -z notext" ""
      "--32 -mx86-used-note=yes"
      { pr19827a.S }  {{readelf {-rW} pr19827.rd}} "pr19827.so"}
-    {"Build pr27193.so"
+    {"Build pr27193a.so"
      "-melf_i386 -shared" ""
      "--32"
      { pr27193a.o.bz2 pr27193b.s }
-     {{objdump {-dw} pr27193.dd}} "pr27193.so"}
+     {{objdump {-dw} pr27193.dd}} "pr27193a.so"}
+    {"Build pr27193b.so"
+     "-melf_i386 -shared --reduce-memory-overheads" ""
+     "--32"
+     { pr27193a.o.bz2 pr27193b.s }
+     {{objdump {-dw} pr27193.dd}} "pr27193b.so"}
 }
 
 proc iamcu_tests {} {