]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
elf: Fix a memory leak in _bfd_elf_add_dynamic_entry
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 10 Apr 2024 01:41:59 +0000 (18:41 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 11 Apr 2024 02:50:01 +0000 (19:50 -0700)
Normally, the section contents is allocated by bfd_alloc which is freed
when the object is closed.  But the .dynamic section contents is allocated
by bfd_realloc, which should be freed by calling free.  Add a dynamic
field to elf_link_hash_table for the .dynamic section and free its
contents in _bfd_elf_link_hash_table_free.

* elf-bfd.h (elf_link_hash_table): Add dynamic.
* elflink.c (_bfd_elf_link_create_dynamic_sections): Set the
dynamic field in elf_link_hash_table.
(_bfd_elf_add_dynamic_entry): Use hash_table->dynamic.
(_bfd_elf_strip_zero_sized_dynamic_sections): Likewise.
(bfd_elf_add_dt_needed_tag): Likewise.
(elf_finalize_dynstr): Likewise.
(_bfd_elf_link_hash_table_free): Free htab->dynamic->contents.
(bfd_elf_final_link): Use htab->dynamic.
* elfxx-x86.c (_bfd_x86_elf_finish_dynamic_sections): Use
htab->elf.dynamic.

bfd/elf-bfd.h
bfd/elflink.c
bfd/elfxx-x86.c

index 85e66488955c53b9207b13df6c64294e4c90feaf..ef5dcb55e72827a95252890fae29aa6d46c61a2e 100644 (file)
@@ -757,6 +757,7 @@ struct elf_link_hash_table
   asection *irelifunc;
   asection *dynsym;
   asection *srelrdyn;
+  asection *dynamic;
 };
 
 /* Returns TRUE if the hash table is a struct elf_link_hash_table.  */
index c73470276cdd4a274ae4792ca5cb1114a6391e5f..22fddb8f56bf77bcdffc5dd10962ac0598323434 100644 (file)
@@ -355,6 +355,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   if (s == NULL
       || !bfd_set_section_alignment (s, bed->s->log_file_align))
     return false;
+  elf_hash_table (info)->dynamic = s;
 
   /* The special symbol _DYNAMIC is always set to the start of the
      .dynamic section.  We could set _DYNAMIC in a linker script, but we
@@ -3729,7 +3730,7 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
     hash_table->dynamic_relocs = true;
 
   bed = get_elf_backend_data (hash_table->dynobj);
-  s = bfd_get_linker_section (hash_table->dynobj, ".dynamic");
+  s = hash_table->dynamic;
   BFD_ASSERT (s != NULL);
 
   newsize = s->size + bed->s->sizeof_dyn;
@@ -3772,7 +3773,7 @@ _bfd_elf_strip_zero_sized_dynamic_sections (struct bfd_link_info *info)
   if (!hash_table->dynobj)
     return true;
 
-  sdynamic= bfd_get_linker_section (hash_table->dynobj, ".dynamic");
+  sdynamic= hash_table->dynamic;
   if (!sdynamic)
     return true;
 
@@ -3872,7 +3873,7 @@ bfd_elf_add_dt_needed_tag (bfd *abfd, struct bfd_link_info *info)
       bfd_byte *extdyn;
 
       bed = get_elf_backend_data (hash_table->dynobj);
-      sdyn = bfd_get_linker_section (hash_table->dynobj, ".dynamic");
+      sdyn = hash_table->dynamic;
       if (sdyn != NULL && sdyn->size != 0)
        for (extdyn = sdyn->contents;
             extdyn < sdyn->contents + sdyn->size;
@@ -4017,7 +4018,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
     info->callbacks->examine_strtab (dynstr);
 
   bed = get_elf_backend_data (dynobj);
-  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
+  sdyn = hash_table->dynamic;
   BFD_ASSERT (sdyn != NULL);
 
   /* Update all .dynamic entries referencing .dynstr strings.  */
@@ -8352,6 +8353,9 @@ _bfd_elf_link_hash_table_free (bfd *obfd)
   if (htab->dynstr != NULL)
     _bfd_elf_strtab_free (htab->dynstr);
   _bfd_merge_sections_free (htab->merge_info);
+  /* NB: htab->dynamic->contents is always allocated by bfd_realloc.  */
+  if (htab->dynamic != NULL)
+    free (htab->dynamic->contents);
   if (htab->first_hash != NULL)
     {
       bfd_hash_table_free (htab->first_hash);
@@ -13420,7 +13424,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       bfd_byte *dyncon, *dynconend;
 
       /* Fix up .dynamic entries.  */
-      o = bfd_get_linker_section (dynobj, ".dynamic");
+      o = htab->dynamic;
       BFD_ASSERT (o != NULL);
 
       dyncon = o->contents;
@@ -13654,7 +13658,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
       /* Check for DT_TEXTREL (late, in case the backend removes it).  */
       if (bfd_link_textrel_check (info)
-         && (o = bfd_get_linker_section (dynobj, ".dynamic")) != NULL
+         && (o = htab->dynamic) != NULL
          && o->size != 0)
        {
          bfd_byte *dyncon, *dynconend;
index 7d189bc66d15238c9caa0a4c49aa9f19f9e4dc46..725884e78c136d89c2482743b99cf01a9a3bf7d7 100644 (file)
@@ -2715,7 +2715,7 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
     return htab;
 
   dynobj = htab->elf.dynobj;
-  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
+  sdyn = htab->elf.dynamic;
 
   /* GOT is always created in setup_gnu_properties.  But it may not be
      needed.  .got.plt section may be needed for static IFUNC.  */