[PATCH v10 15/28] OAv2 merge: find first input containing an object attributes section

Matthieu Longo matthieu.longo@arm.com
Thu Nov 20 17:59:06 GMT 2025


During the merge process, the linker first scans the list of input files
to identify ELF object files that contain object attributes. If no such
object file is found, the merge process terminates. Otherwise, the first
matching file is used as the placeholder for the global merge result.

This patch implements a linear search to locate the first input BFD
containing an Object Attributes section, while recording a good candidate
otherwise.

It is worth noting that the position of the object file in the list, as
well as whether it contains object attributes or not, or whether it
contains an object attributes section or not, are not significant. Any
input ELF object files could serve this placeholder purpose if the merge
process was performed in parallel.
---
 bfd/elf-attrs.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 67 insertions(+), 3 deletions(-)

diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c
index 239f75f4416..c34d4b21daf 100644
--- a/bfd/elf-attrs.c
+++ b/bfd/elf-attrs.c
@@ -713,6 +713,26 @@ oav2_encoding_to_string (obj_attr_encoding_v2_t encoding)
   return (encoding == OA_ENC_ULEB128) ? "ULEB128" : "NTBS";
 }
 
+/* Returns True if the given BFD is an ELF object with the target backend
+   machine code, non-dynamic (i.e. not a shared library), non-executable, and
+   has sections.  False otherwise.
+   Note: this function is a convenient encapsulation of the predicate used to
+   search for objects containing object attributes in the list of BFDs.  */
+static bool
+elf_may_contain_obj_attrs (const struct bfd_link_info *info,
+			   const bfd *const abfd)
+{
+  const struct elf_backend_data *output_bed
+    = get_elf_backend_data (info->output_bfd);
+  unsigned int elfclass = output_bed->s->elfclass;
+  int elf_machine_code = output_bed->elf_machine_code;
+  return (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+	  && abfd->section_count != 0
+	  && (abfd->flags & (DYNAMIC | EXEC_P)) == 0
+	  && elf_machine_code == get_elf_backend_data (abfd)->elf_machine_code
+	  && elfclass == get_elf_backend_data (abfd)->s->elfclass);
+}
+
 /* Structure storing the result of a search in the list of input BFDs.  */
 typedef struct
 {
@@ -729,6 +749,41 @@ typedef struct
   asection *sec;
 } bfd_search_result_t;
 
+/* Checks whether a BFD contains object attributes, and if so search for the
+   relevant section storing them.  The name and type of the section have to
+   match with what the backend expects, i.e. elf_backend_obj_attrs_section and
+   elf_backend_obj_attrs_section_type, otherwise the object attributes section
+   won't be recognized as such, and will be skipped.
+   Return True if an object attribute section is found, False otherwise.  */
+static bool
+bfd_has_object_attributes (const struct bfd_link_info *info,
+			   bfd *abfd,
+			   bfd_search_result_t *res)
+{
+  /* The file may contain object attributes.  Save this candidate.  */
+  res->pbfd = abfd;
+
+  if (elf_obj_attr_subsections (abfd).size == 0)
+    return false;
+
+  res->has_object_attributes = true;
+
+  uint32_t sec_type = get_elf_backend_data (abfd)->obj_attrs_section_type;
+  const char *sec_name = get_elf_backend_data (abfd)->obj_attrs_section;
+  res->sec = bfd_get_section_by_name (abfd, sec_name);
+  if (res->sec != NULL)
+    {
+      if (elf_section_type (res->sec) != sec_type)
+	{
+	  info->callbacks->minfo
+	    (_("%X%pB: warning: ignoring section '%s' with unexpected type 0x%x\n"),
+	     abfd, elf_section_type (res->sec), sec_name);
+	  res->sec = NULL;
+	}
+    }
+  return (res->sec != NULL);
+}
+
 /* Search for the first input object file containing object attributes.
    If no such object is found, PBFD points to the last object file that
    could have contained object attributes.  HAS_OBJECT_ATTRIBUTES allows
@@ -737,9 +792,18 @@ typedef struct
 static bfd_search_result_t
 bfd_linear_find_first_with_obj_attrs (const struct bfd_link_info *info)
 {
-  (void) info;
-  /* TO IMPLEMENT */
-  bfd_search_result_t res = {NULL, false, NULL};
+  bfd_search_result_t res = {
+    .pbfd = NULL,
+    .has_object_attributes = false,
+    .sec = NULL,
+  };
+
+  for (bfd *abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
+    {
+      if (elf_may_contain_obj_attrs (info, abfd)
+	  && bfd_has_object_attributes (info, abfd, &res))
+	break;
+    }
   return res;
 }
 
-- 
2.52.0



More information about the Binutils mailing list