[binutils-gdb] Object Attributes v2: clean up attributes data when freeing BFDs
Matthieu Longo
mlongo@sourceware.org
Fri Feb 6 10:42:15 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=bf0a637f4d5f73b5242241bcec5a447a7531d5d2
commit bf0a637f4d5f73b5242241bcec5a447a7531d5d2
Author: Matthieu Longo <matthieu.longo@arm.com>
Date: Fri Jan 30 11:20:02 2026 +0000
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 <amodra@gmail.com>
Diff:
---
bfd/elf-attrs.c | 19 +++++++++++++++----
bfd/elf-bfd.h | 2 ++
bfd/elf.c | 1 +
3 files changed, 18 insertions(+), 4 deletions(-)
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);
More information about the Binutils-cvs
mailing list