[PATCH v4 17/22] gnu directives: add support for gnu_attribute and gnu_subsection in OAv2 context

Matthieu Longo matthieu.longo@arm.com
Thu Jul 3 16:27:20 GMT 2025


This patch adds support for the GNU directives .gnu_attribute and
.gnu_subsection, used respectively for OAv1 and OAv2, and for OAv2 only.
These directives behave like their AEABI counterparts, as they are aliases
intended for use by any backends supporting OAv1 and/or OAv2. Their
availability is controlled by the HAVE_OBJ_ATTR_v1 and HAVE_OBJ_ATTR_v2
macros, which are defined via TC_<target>.

Previously, the "gnu" subsection namespace was used only for
"gnu-testing" and defaulted to a private scope. This patch updates the
scope recognition to correctly distinguish between private usage (e.g.,
testing) and public usage (e.g., actual GNU subsections storing public
information).
---
 bfd/elf-attrs.c      |  9 +++++----
 binutils/readelf.c   |  4 +++-
 gas/attr.c           |  9 +++++----
 gas/attr.h           | 24 ++++++++++++++++++++++++
 gas/config/obj-elf.c | 30 +++++++++++++++++++++++++++++-
 5 files changed, 66 insertions(+), 10 deletions(-)

diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c
index 98f54891750..cd585016f9c 100644
--- a/bfd/elf-attrs.c
+++ b/bfd/elf-attrs.c
@@ -2600,10 +2600,11 @@ oav2_parse_subsection (bfd *abfd,
     }
 
   const char *vendor_name = get_elf_backend_data (abfd)->obj_attrs_vendor;
-  obj_attr_subsection_scope_v2 scope =
-    (strncmp (subsection_name, vendor_name, strlen (vendor_name)) == 0)
-    ? OA_SUBSEC_PUBLIC
-    : OA_SUBSEC_PRIVATE;
+  obj_attr_subsection_scope_v2 scope = OA_SUBSEC_PRIVATE;
+  if (strncmp (subsection_name, vendor_name, strlen (vendor_name)) == 0
+      || (strncmp (subsection_name, "gnu", 3) == 0
+	  && strncmp (subsection_name + 3, "-testing", 8) != 0))
+    scope = OA_SUBSEC_PUBLIC;
 
   obj_attr_subsection_v2 *subsec =
     _bfd_elf_obj_attr_subsection_v2_init (subsection_name, scope, optional_raw,
diff --git a/binutils/readelf.c b/binutils/readelf.c
index babbd91c67e..a6f128b296a 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -19649,7 +19649,9 @@ elf_parse_attrs_subsection_v2 (unsigned char *cursor,
       const char *subsec_name = (const char *) cursor;
       printf (_(" - Name:	  %s\n"), subsec_name);
       bool public_subsection =
-	strncmp (subsec_name, public_name, strlen (public_name)) == 0;
+	strncmp (subsec_name, public_name, strlen (public_name)) == 0
+	|| (strncmp (subsec_name, "gnu", 3) == 0
+	    && strncmp (subsec_name + 3, "-testing", 8) != 0);
       cursor += subsection_name_len;
       op.read += subsection_name_len;
 
diff --git a/gas/attr.c b/gas/attr.c
index e4738c274ce..9e129a258bc 100644
--- a/gas/attr.c
+++ b/gas/attr.c
@@ -915,10 +915,11 @@ obj_attr_v2_subsection_record (const char *name,
     {
       const char *vendor_name =
 	get_elf_backend_data (stdoutput)->obj_attrs_vendor;
-      obj_attr_subsection_scope_v2 scope =
-	(strncmp (name, vendor_name, strlen (vendor_name)) == 0)
-	? OA_SUBSEC_PUBLIC
-	: OA_SUBSEC_PRIVATE;
+      obj_attr_subsection_scope_v2 scope = OA_SUBSEC_PRIVATE;
+      if (strncmp (name, vendor_name, strlen (vendor_name)) == 0
+	  || (strncmp (name, "gnu", 3) == 0
+	      && strncmp (name + 3, "-testing", 8) != 0))
+	scope = OA_SUBSEC_PUBLIC;
 
       obj_attr_subsection_v2 *new_subsection =
 	_bfd_elf_obj_attr_subsection_v2_init (name, scope, optional, encoding);
diff --git a/gas/attr.h b/gas/attr.h
index f629cca63af..04f19dc589d 100644
--- a/gas/attr.h
+++ b/gas/attr.h
@@ -24,6 +24,30 @@
 #include "as.h"
 #include "bfd/elf-bfd.h"
 
+/* The target supports Object Attributes v1.  */
+#if (defined(TC_ARC) \
+ || defined(TC_ARM) \
+ || defined(TC_CSKY) \
+ || defined(TC_M68K) \
+ || defined(TC_MIPS) \
+ || defined(TC_MSP430) \
+ || defined(TC_PPC) \
+ || defined(TC_RISCV) \
+ || defined(TC_S390) \
+ || defined(TC_SPARC) \
+ || defined(TC_TIC6X))
+#define HAVE_OBJ_ATTR_v1 1
+#else
+#define HAVE_OBJ_ATTR_v1 0
+#endif
+
+/* The target supports Object Attributes v2.  */
+#if defined(TC_AARCH64)
+#define HAVE_OBJ_ATTR_v2 1
+#else
+#define HAVE_OBJ_ATTR_v2 0
+#endif
+
 /* Object attributes v1.  */
 extern void oav1_attr_info_init (void);
 extern void oav1_attr_info_exit (void);
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index c05ec4859ea..6e59c335d23 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -72,7 +72,12 @@ static void obj_elf_visibility (int);
 static void obj_elf_symver (int);
 static void obj_elf_subsection (int);
 static void obj_elf_popsection (int);
+#if (HAVE_OBJ_ATTR_v1 || HAVE_OBJ_ATTR_v2)
 static void obj_elf_gnu_attribute (int);
+#endif
+#if HAVE_OBJ_ATTR_v2
+static void obj_elf_gnu_subsection (int);
+#endif
 static void obj_elf_tls_common (int);
 static void obj_elf_lcomm (int);
 static void obj_elf_struct (int);
@@ -117,7 +122,12 @@ static const pseudo_typeS elf_pseudo_table[] =
   {"vtable_entry", obj_elf_vtable_entry, 0},
 
   /* A GNU extension for object attributes.  */
+#if (HAVE_OBJ_ATTR_v1 || HAVE_OBJ_ATTR_v2)
   {"gnu_attribute", obj_elf_gnu_attribute, 0},
+#endif
+#if (HAVE_OBJ_ATTR_v2)
+  {"gnu_subsection", obj_elf_gnu_subsection, 0},
+#endif
 
   /* These are used for dwarf2.  */
   { "file", dwarf2_directive_file, 0 },
@@ -2045,12 +2055,30 @@ obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED)
 }
 
 /* Parse a .gnu_attribute directive.  */
-
+#if (HAVE_OBJ_ATTR_v1 || HAVE_OBJ_ATTR_v2)
 static void
 obj_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
 {
   obj_attr_process_attribute (OBJ_ATTR_GNU);
 }
+#endif
+
+/* Parse a .gnu_subsection directive.  */
+#if (HAVE_OBJ_ATTR_v2)
+static void
+obj_elf_gnu_subsection (int ignored ATTRIBUTE_UNUSED)
+{
+  obj_attr_version_t version = elf_obj_attr_version (stdoutput);
+  if (version < OBJ_ATTR_V2)
+    {
+      as_bad (_(".gnu_subsection is only available with object attributes v2,"
+		" and the current target only supports object attributes v1"));
+      ignore_rest_of_line ();
+      return;
+    }
+  obj_attr_process_subsection ();
+}
+#endif
 
 void
 elf_obj_read_begin_hook (void)
-- 
2.50.0



More information about the Binutils mailing list