[PATCH v7 16/19] gnu directives: add support for gnu_attribute and gnu_subsection in OAv2 context
Matthieu Longo
matthieu.longo@arm.com
Mon Jul 14 16:58:46 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 TC_OBJ_ATTR_v1 and TC_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/config/obj-elf-attr.c | 9 ++---
gas/config/obj-elf.c | 41 +++++++++++++++++++++++
gas/doc/as.texi | 69 +++++++++++++++++++++++++++++----------
5 files changed, 106 insertions(+), 26 deletions(-)
diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c
index c089fae94d8..68219958776 100644
--- a/bfd/elf-attrs.c
+++ b/bfd/elf-attrs.c
@@ -2614,10 +2614,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
+ && !gnu_testing_namespace (subsection_name)))
+ scope = OA_SUBSEC_PUBLIC;
obj_attr_subsection_v2 *subsec
= _bfd_elf_obj_attr_subsection_v2_init (subsection_name, scope,
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 14fa445489d..9baf6834f0b 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -19626,7 +19626,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/config/obj-elf-attr.c b/gas/config/obj-elf-attr.c
index 223c2512480..798913b7a45 100644
--- a/gas/config/obj-elf-attr.c
+++ b/gas/config/obj-elf-attr.c
@@ -975,10 +975,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/config/obj-elf.c b/gas/config/obj-elf.c
index afde2122351..07a8bda262e 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -75,6 +75,9 @@ static void obj_elf_popsection (int);
#if (TC_OBJ_ATTR_v1 || TC_OBJ_ATTR_v2)
static void obj_elf_gnu_attribute (int);
#endif /* (TC_OBJ_ATTR_v1 || TC_OBJ_ATTR_v2) */
+#if (TC_OBJ_ATTR_v2)
+static void obj_elf_gnu_subsection (int);
+#endif /* TC_OBJ_ATTR_v2 */
#endif /* TC_OBJ_ATTR */
static void obj_elf_tls_common (int);
static void obj_elf_lcomm (int);
@@ -124,6 +127,9 @@ static const pseudo_typeS elf_pseudo_table[] =
#if (TC_OBJ_ATTR_v1 || TC_OBJ_ATTR_v2)
{"gnu_attribute", obj_elf_gnu_attribute, 0},
#endif /* (TC_OBJ_ATTR_v1 || TC_OBJ_ATTR_v2) */
+#if (TC_OBJ_ATTR_v2)
+ {"gnu_subsection", obj_elf_gnu_subsection, 0},
+#endif /* TC_OBJ_ATTR_v2 */
#endif /* TC_OBJ_ATTR */
/* These are used for dwarf2. */
@@ -2070,6 +2076,41 @@ obj_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
}
#endif /* (TC_OBJ_ATTR_v1 || TC_OBJ_ATTR_v2) */
+#if (TC_OBJ_ATTR_v2)
+/* Return True if the VERSION of object attributes supports subsections, False
+ otherwise. */
+
+static inline bool
+attr_fmt_has_subsections (obj_attr_version_t version)
+{
+ switch (version)
+ {
+ case OBJ_ATTR_V1:
+ return false;
+ case OBJ_ATTR_V2:
+ return true;
+ default:
+ abort (); /* Unsupported format. */
+ }
+}
+
+/* Parse a .gnu_subsection directive. */
+
+static void
+obj_elf_gnu_subsection (int ignored ATTRIBUTE_UNUSED)
+{
+ obj_attr_version_t version = elf_obj_attr_version (stdoutput);
+ if (! attr_fmt_has_subsections (version))
+ {
+ 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 /* TC_OBJ_ATTR_v2 */
+
#endif /* TC_OBJ_ATTR */
void
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index c2e33b26398..363baa0b008 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -4593,6 +4593,7 @@ Some machine configurations provide additional directives.
* Func:: @code{.func}
* Global:: @code{.global @var{symbol}}, @code{.globl @var{symbol}}
@ifset ELF
+* Gnu_subsection:: @code{.gnu_subsection @var{name}, @var{comprehension}, @var{encoding}}
* Gnu_attribute:: @code{.gnu_attribute @var{tag},@var{value}}
* Hidden:: @code{.hidden @var{names}}
@end ifset
@@ -5740,6 +5741,10 @@ partial programs. You may need the HPPA-only @code{.EXPORT} directive as well.
@end ifset
@ifset ELF
+@node Gnu_subsection
+@section @code{.gnu_subsection @var{name}, @var{comprehension}, @var{encoding}}
+Record a @sc{gnu} object attribute subsection for this file. @xref{Object Attributes}
+
@node Gnu_attribute
@section @code{.gnu_attribute @var{tag},@var{value}}
Record a @sc{gnu} object attribute for this file. @xref{Object Attributes}.
@@ -7947,32 +7952,62 @@ Many architectures support incompatible variations. For instance, floating
point arguments might be passed in floating point registers if the object file
requires hardware floating point support---or floating point arguments might be
passed in integer registers if the object file supports processors with no
-hardware floating point unit. Or, if two objects are built for different
-generations of the same architecture, the combination may require the
-newer generation at run-time.
-
-This information is useful during and after linking. At link time,
-@command{@value{LD}} can warn about incompatible object files. After link
-time, tools like @command{gdb} can use it to process the linked file
-correctly.
+hardware floating point unit. Another example might be when two object files
+make use of different architectural extensions: the final image will require
+both features to be supported at runtime; or if the features are mutually
+exclusive, the linker can issue a diagnostic.
-Compatibility information is recorded as a series of object attributes. Each
-attribute has a @dfn{vendor}, @dfn{tag}, and @dfn{value}. The vendor is a
-string, and indicates who sets the meaning of the tag. The tag is an integer,
-and indicates what property the attribute describes. The value may be a string
-or an integer, and indicates how the property affects this object. Missing
-attributes are the same as attributes with a zero value or empty string value.
+@command{@value{AS}} currently supports two versions of object attributes:
+@itemize @bullet{}
+@item
+Object Attributes version 1 (OAv1) used by: ARC, ARM, C-SKY, MIPS, MSP430, M68K,
+PowerPC, RISC-V, SPARC, s390, and TIC6X.
+@item
+Object Attributes version 2 (OAv2) used by: AArch64.
+@end itemize
-Object attributes were developed as part of the ABI for the ARM Architecture.
-The file format is documented in @cite{ELF for the ARM Architecture}.
+Object attributes are only supported when generating ELF format.
@menu
+* Object Attributes v1:: Object Attributes v1
+* Object Attributes v2:: Object Attributes v2
* GNU Object Attributes:: @sc{gnu} Object Attributes
* Defining New Object Attributes:: Defining New Object Attributes
@end menu
+@node Object Attributes v1
+@section Object Attributes v1
+
+In Object Attributes v1 (OAv1) Compatibility information is recorded as a series
+of object attributes. Each attribute has a @dfn{vendor}, @dfn{tag}, and
+@dfn{value}. The @dfn{vendor} is a string, and indicates who sets the meaning
+of the tag. The @dfn{tag} is an integer, and indicates what property the
+attribute describes. The @dfn{value} may be a string or an integer, and
+indicates how the property affects this object. Integer tags generally default
+to 0, while string tags default to the empty string. Tags are only recorded in
+the file if they have a non-default value.
+
+OAv1 were developed as part of the ABI for the ARM Architecture. The file
+format is documented in @cite{Addenda to, and Errata in, the ABI for the Arm
+Architecture}.
+
+@node Object Attributes v2
+@section Object Attributes v2
+
+Object Attributes v2 (OAv2) share common concepts of @dfn{vendor}, @dfn{tag}
+and @dfn{value} with OAv1, but also introduce the new ones like @dfn{subsection}
+and @dfn{scope}. Attributes with common properties are grouped into subsections.
+All the attributes in a subsection share the same encoding, comprehension, and
+scope. A subsection starting with the vendor name is considered public. The
+value of an attribute may be a string or an integer depending on the encoding
+set on its subsection.
+
+OAv2 is only used by AArch64. Directives are documented in @ref{AArch64
+Directives}. The file format is documented in @cite{Build Attributes for the
+Arm 64-bit Architecture (AArch64)}.
+
@node GNU Object Attributes
-@section @sc{gnu} Object Attributes
+@section @sc{gnu} Object Attributes (OAv1 only)
The @code{.gnu_attribute} directive records an object attribute
with vendor @samp{gnu}.
--
2.50.1
More information about the Binutils
mailing list