[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