From: Matthieu Longo Date: Fri, 30 Jan 2026 11:20:02 +0000 (+0000) Subject: Object Attributes v2: clean up attributes data when freeing BFDs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf0a637f4d5f73b5242241bcec5a447a7531d5d2;p=thirdparty%2Fbinutils-gdb.git Object Attributes v2: clean up attributes data when freeing BFDs Once attributes merge is complete, object attributes from input files are no longer needed and can be safely released. The same applies to object attributes associated to the output object. Ideally, a single clean-up mechanism should handle both inputs and output cases. GNU ld already provides such a mechanism via _bfd_elf_free_cached_info(). The previous patch series that introduced support for Object Attributes v2 did not free any OAv2 data, resulting in leaks of all OAv2-related resources. This patch adds a new helper, _bfd_elf_cleanup_object_attributes, to the OAv2 API to deallocate all OAv2 resources associated with a BFD. The helper is invoked from _bfd_elf_free_cached_info(). The patch also fixes a logical error after the attributes merge, where object attributes were copied from the accumulator into output_bfd. A simple pointer copy is insufficient because ownership of the wrapper must be fully swapped between the two BFDs to ensure resources are deallocated correctly. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33858 Co-authored-by: Alan Modra --- diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c index 7160bd4d284..6c3cfc09677 100644 --- a/bfd/elf-attrs.c +++ b/bfd/elf-attrs.c @@ -2194,10 +2194,11 @@ _bfd_elf_link_setup_object_attributes (struct bfd_link_info *info) return NULL; BFD_ASSERT (elf_obj_attr_subsections (res.pbfd).size > 0); - - /* Shallow-copy the object attributes into output_bfd. */ - elf_obj_attr_subsections (info->output_bfd) - = elf_obj_attr_subsections (res.pbfd); + /* Swap the old object attributes stored in output_bfd (i.e. the frozen + config) with the final merge result. */ + LINKED_LIST_SWAP_LISTS (obj_attr_subsection_list_t) + (&elf_obj_attr_subsections (info->output_bfd), + &elf_obj_attr_subsections (res.pbfd)); /* Note: the object attributes section in the output object is copied from the input object which was used for the merge (res.pbfd). No need to @@ -2953,6 +2954,16 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr) free (data); } +/* Clean-up all the object attributes in a file. */ +void +_bfd_elf_cleanup_object_attributes (bfd *abfd) +{ + obj_attr_subsection_list_t *plist = &elf_obj_attr_subsections (abfd); + obj_attr_subsection_v2_t *subsec = plist->first; + while (subsec != NULL) + subsec = oav2_subsec_delete (plist, subsec); +} + /* Merge common object attributes from IBFD into OBFD. Raise an error if there are conflicting attributes. Any processor-specific attributes have already been merged. This must be called from the diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index dbf53756200..837fbefa6a2 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -3207,6 +3207,8 @@ extern int bfd_elf_obj_attrs_arg_type (bfd *, obj_attr_vendor_t, obj_attr_tag_t); extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *) ATTRIBUTE_HIDDEN; +extern void _bfd_elf_cleanup_object_attributes + (bfd *) ATTRIBUTE_HIDDEN; extern bfd *_bfd_elf_link_setup_object_attributes (struct bfd_link_info *) ATTRIBUTE_HIDDEN; extern bool _bfd_elf_merge_object_attributes diff --git a/bfd/elf.c b/bfd/elf.c index 75a2e0b9358..f7437f11fbd 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -10207,6 +10207,7 @@ _bfd_elf_free_cached_info (bfd *abfd) _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info); _bfd_dwarf1_cleanup_debug_info (abfd, &tdata->dwarf1_find_line_info); _bfd_stab_cleanup (abfd, &tdata->line_info); + _bfd_elf_cleanup_object_attributes (abfd); for (asection *sec = abfd->sections; sec != NULL; sec = sec->next) { _bfd_elf_munmap_section_contents (sec, sec->contents);