Fix seg-fault when generating an empty DLL with LTO enabled.
authorNick Clifton <nickc@redhat.com>
Tue, 24 Jan 2023 09:47:43 +0000 (09:47 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 24 Jan 2023 09:47:43 +0000 (09:47 +0000)
ld   PR 29998
     * pe-dll.c (generate_reloc): Handle sections
     with no assigned output section.
     Terminate early of there are no relocs to put
     in the .reloc section.
     (pe_exe_fill_sections): Do not emit an empty
     .reloc section.

bfd  * cofflink.c (_bfd_coff_generic_relocate_section):
     Add an assertion that the output section is set
     for defined, global symbols.

bfd/ChangeLog
bfd/cofflink.c
ld/ChangeLog
ld/pe-dll.c

index 75a2c4901e2711dadc46e0044c728b5913619b70..08cc18353f2f1ed98b8790e28f3c8bb4d4cd6693 100644 (file)
@@ -1,3 +1,10 @@
+2023-01-24  Nick Clifton  <nickc@redhat.com>
+
+       PR 29998
+       * cofflink.c (_bfd_coff_generic_relocate_section): Add an
+       assertion that the output section is set for defined, global
+       symbols.
+
 2023-01-17  Xianmiao Qu  <cooper.qu@linux.alibaba.com>
 
        * elf32-csky.c (elf32_csky_merge_attributes): Don't save
index 07226882e0d1d97448c858e2aef93d83df8e35b3..3174bd3aff1a72d8c633e6df3e469b0c9e7a549e 100644 (file)
@@ -2977,10 +2977,11 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
       else
        {
          if (h->root.type == bfd_link_hash_defined
+             /* Defined weak symbols are a GNU extension.  */
              || h->root.type == bfd_link_hash_defweak)
            {
-             /* Defined weak symbols are a GNU extension. */
              sec = h->root.u.def.section;
+             BFD_ASSERT (sec->output_section != NULL);
              val = (h->root.u.def.value
                     + sec->output_section->vma
                     + sec->output_offset);
@@ -3087,7 +3088,6 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
          return false;
        case bfd_reloc_overflow:
          {
-
            /* Ignore any weak undef symbols that may have overflowed.  Due to
               PR ld/19011 the base address is now in the upper 64-bit address
               range.  This means that when _bfd_final_link_relocate calculates
@@ -3123,5 +3123,6 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
          }
        }
     }
+
   return true;
 }
index f02520432d30ee0263c69167bbf971f2fa1d0b1f..502da5e59433730c57dd2d201b96b32cebb8d114 100644 (file)
@@ -1,3 +1,11 @@
+2023-01-24  Nick Clifton  <nickc@redhat.com>
+
+       PR 29998
+       * pe-dll.c (generate_reloc): Handle sections with no assigned
+       output section.  Terminate early of there are no relocs to put in
+       the .reloc section.
+       (pe_exe_fill_sections): Do not emit an empty .reloc section.
+
 2023-01-06  Nick Clifton  <nickc@redhat.com>
 
        * po/bg.po: Updated Bulgarian translation.
index 0248f4b2cf9e602c54985feb47682e9b4d9eae27..7b883edc3eb987345ba7c63122828a65348347a3 100644 (file)
@@ -168,7 +168,8 @@ static bfd_vma image_base;
 static bfd *filler_bfd;
 static struct bfd_section *edata_s, *reloc_s;
 static unsigned char *edata_d, *reloc_d;
-static size_t edata_sz, reloc_sz;
+static unsigned char *reloc_d = NULL;
+static size_t edata_sz, reloc_sz = 0;
 static int runtime_pseudo_relocs_created = 0;
 static bool runtime_pseudp_reloc_v2_init = false;
 
@@ -1033,9 +1034,10 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *
 /* Build the bfd that will contain .edata and .reloc sections.  */
 
 static void
-build_filler_bfd (int include_edata)
+build_filler_bfd (bool include_edata)
 {
   lang_input_statement_type *filler_file;
+
   filler_file = lang_add_input_file ("dll stuff",
                                     lang_input_file_is_fake_enum,
                                     NULL);
@@ -1526,6 +1528,8 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
 
   if (reloc_s == NULL || reloc_s->output_section == bfd_abs_section_ptr)
     return;
+
+  /* Set an upper bound for the total number of relocations we will have to generate.  */
   total_relocs = 0;
   for (b = info->input_bfds; b; b = b->link.next)
     for (s = b->sections; s; s = s->next)
@@ -1541,28 +1545,34 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
 
       for (s = b->sections; s; s = s->next)
        {
-         bfd_vma sec_vma = s->output_section->vma + s->output_offset;
+         bfd_vma sec_vma;
          asymbol **symbols;
 
-         /* If it's not loaded, we don't need to relocate it this way.  */
-         if (!(s->output_section->flags & SEC_LOAD))
-           continue;
+         /* If the section is not going to be output, then ignore it.  */
+         if (s->output_section == NULL)
+           {
+             /* PR 29998: LTO processing can elminate whole code sections,
+                but it sets the output section to NULL rather than *ABS*.
+                Fix that here, then ignore the section.  */
+             s->output_section = bfd_abs_section_ptr;
+             continue;
+           }
 
          /* I don't know why there would be a reloc for these, but I've
             seen it happen - DJ  */
          if (s->output_section == bfd_abs_section_ptr)
            continue;
 
+         /* If it's not loaded, we don't need to relocate it this way.  */
+         if (!(s->output_section->flags & SEC_LOAD))
+           continue;
+
+         /* This happens when linking with --just-symbols=<file>
+            so do not generate an error.  */
          if (s->output_section->vma == 0)
-           {
-             /* Huh?  Shouldn't happen, but punt if it does.  */
-#if 0 /* This happens when linking with --just-symbols=<file>, so do not generate an error.  */
-             einfo (_("%P: zero vma section reloc detected: `%s' #%d f=%d\n"),
-                    s->output_section->name, s->output_section->index,
-                    s->output_section->flags);
-#endif
-             continue;
-           }
+           continue;
+
+         sec_vma = s->output_section->vma + s->output_offset;
 
          if (!bfd_generic_link_read_symbols (b))
            {
@@ -1696,12 +1706,17 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
                    }
                }
            }
+
          free (relocs);
          /* Warning: the allocated symbols are remembered in BFD and
             reused later, so don't free them!  */
        }
     }
 
+  /* This can happen for example when LTO has eliminated all code.  */
+  if (total_relocs == 0)
+    return;
+  
   /* At this point, we have total_relocs relocation addresses in
      reloc_addresses, which are all suitable for the .reloc section.
      We must now create the new sections.  */
@@ -1726,9 +1741,9 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
 
   reloc_sz = (reloc_sz + 3) & ~3;      /* 4-byte align.  */
   reloc_d = xmalloc (reloc_sz);
-  sec_page = (bfd_vma) -1;
+
+  page_ptr = sec_page = (bfd_vma) -1;
   reloc_sz = 0;
-  page_ptr = (bfd_vma) -1;
 
   for (i = 0; i < total_relocs; i++)
     {
@@ -1758,7 +1773,6 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info)
          bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);
          reloc_sz += 2;
        }
-
     }
 
   while (reloc_sz & 3)
@@ -3649,14 +3663,14 @@ pe_dll_build_sections (bfd *abfd, struct bfd_link_info *info)
     {
       if (pe_dll_enable_reloc_section)
        {
-         build_filler_bfd (0);
+         build_filler_bfd (false /* edata not needed.  */);
          pe_output_file_set_long_section_names (filler_bfd);
        }
       return;
     }
 
   generate_edata ();
-  build_filler_bfd (1);
+  build_filler_bfd (true /* edata is needed.  */);
   pe_output_file_set_long_section_names (filler_bfd);
 }
 
@@ -3692,6 +3706,7 @@ pe_exe_fill_sections (bfd *abfd, struct bfd_link_info *info)
   image_base = pe_data (abfd)->pe_opthdr.ImageBase;
 
   generate_reloc (abfd, info);
+
   if (reloc_sz > 0)
     {
       bfd_set_section_size (reloc_s, reloc_sz);
@@ -3705,9 +3720,15 @@ pe_exe_fill_sections (bfd *abfd, struct bfd_link_info *info)
 
       /* Do the assignments again.  */
       lang_do_assignments (lang_final_phase_enum);
+
+      reloc_s->contents = reloc_d;
+    }
+  else if (reloc_s)
+    {
+      /* Do not emit an empty reloc section.  */
+      bfd_set_section_flags (reloc_s, SEC_IN_MEMORY | SEC_EXCLUDE);
+      reloc_s->output_section = bfd_abs_section_ptr;
     }
-  if (reloc_s)
-    reloc_s->contents = reloc_d;
 }
 
 bool