From: Matthieu Longo Date: Thu, 17 Apr 2025 17:02:38 +0000 (+0100) Subject: gnu directives: add support for .gnu_attribute and .gnu_subsection in OAv2 context X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a3a49f3eb90e4cb04196891a0634a7785cc59823;p=thirdparty%2Fbinutils-gdb.git gnu directives: add support for .gnu_attribute and .gnu_subsection in OAv2 context 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. 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). --- diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c index c012ba4956c..904e097cf97 100644 --- a/bfd/elf-attrs.c +++ b/bfd/elf-attrs.c @@ -605,8 +605,10 @@ bfd_elf_obj_attr_subsection_v2_scope (const bfd *abfd, const char *subsec_name) const char *vendor_name = get_elf_backend_data (abfd)->obj_attrs_vendor; obj_attr_subsection_scope_v2_t scope = OA_SUBSEC_PRIVATE; size_t vendor_name_len = strlen (vendor_name); - if (strncmp (subsec_name, vendor_name, vendor_name_len) == 0 - && subsec_name[vendor_name_len] == '_') + if ((strncmp (subsec_name, vendor_name, vendor_name_len) == 0 + && subsec_name[vendor_name_len] == '_') + || (strncmp (subsec_name, "gnu_", 4) == 0 + && !gnu_testing_namespace (subsec_name))) scope = OA_SUBSEC_PUBLIC; return scope; } diff --git a/binutils/readelf.c b/binutils/readelf.c index 6d0c211fb1b..cca294c968c 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -20193,8 +20193,10 @@ elf_parse_attrs_subsection_v2 (const unsigned char *cursor, bfd_elf_obj_attr_subsection_v2_scope() in bfd/elf-attrs.c. */ size_t public_name_len = strlen (public_name); bool public_subsection - = strncmp (subsec_name, public_name, public_name_len) == 0 - && subsec_name[public_name_len] == '_'; + = ((strncmp (subsec_name, public_name, public_name_len) == 0 + && subsec_name[public_name_len] == '_') + || (strncmp (subsec_name, "gnu_", 4) == 0 + && strncmp (subsec_name + 4, "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 c200d428606..1b91c11158c 100644 --- a/gas/config/obj-elf-attr.c +++ b/gas/config/obj-elf-attr.c @@ -1251,4 +1251,38 @@ obj_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED) obj_attr_process_attribute (OBJ_ATTR_GNU); } +#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. */ + +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")); + ignore_rest_of_line (); + return; + } + obj_attr_process_subsection (); +} +#endif /* TC_OBJ_ATTR_v2 */ + #endif /* TC_OBJ_ATTR */ diff --git a/gas/config/obj-elf-attr.h b/gas/config/obj-elf-attr.h index 3c968fe683a..1bda6b56999 100644 --- a/gas/config/obj-elf-attr.h +++ b/gas/config/obj-elf-attr.h @@ -50,6 +50,9 @@ extern void obj_attr_process_subsection (void); #endif /* (TC_OBJ_ATTR_v2) */ extern void obj_elf_gnu_attribute (int); +#if (TC_OBJ_ATTR_v2) +extern void obj_elf_gnu_subsection (int); +#endif /* TC_OBJ_ATTR_v2 */ #endif /* TC_OBJ_ATTR */ diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 47bf960d351..3c617bc36a3 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -117,6 +117,9 @@ static const pseudo_typeS elf_pseudo_table[] = /* A GNU extension for object attributes. */ #ifdef TC_OBJ_ATTR {"gnu_attribute", obj_elf_gnu_attribute, 0}, +#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. */ diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 29c05437679..6114a178a0d 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -4603,6 +4603,7 @@ Some machine configurations provide additional directives. * Global:: @code{.global @var{symbol}}, @code{.globl @var{symbol}} @ifset ELF * Gnu_attribute:: @code{.gnu_attribute @var{tag},@var{value}} +* Gnu_subsection:: @code{.gnu_subsection @var{name}, @var{comprehension}, @var{encoding}} * Hidden:: @code{.hidden @var{names}} @end ifset @@ -5751,7 +5752,46 @@ partial programs. You may need the HPPA-only @code{.EXPORT} directive as well. @ifset ELF @node Gnu_attribute @section @code{.gnu_attribute @var{tag},@var{value}} -Record a @sc{gnu} object attribute for this file. @xref{Object Attributes}. + +For Object Attributes v1, record a @sc{gnu} object attribute with the pair +@var{tag}, @var{value} for this file. + +For Object Attributes v2, record an object attribute with the pair @var{tag}, +@var{value} in the current subsection for this file. + +@var{tag} can either be an integer value, or a known named key. @var{value} can +either be an integer or a string. For Object Attribute v2, the expected value +type depends on the type set on the subsection. + +@xref{Object Attributes}. + +@node Gnu_subsection +@section @code{.gnu_subsection @var{name}, @var{comprehension}, @var{encoding}} +Create or switch the current object attributes subsection to @var{name} for This +file. Valid values for @var{name} are following the pattern @code{[a-zA-Z0-9_]+}. + +The subsection property @var{comprehension} determines how a program processing +the attributes handles attributes that it does not recognize (perhaps because +the object file was generated by a different version of the toolchain). A +subsection that is marked @code{optional} can be skipped if it is not +understood. A subsection marked @code{required} implies that information +conveyed by the attribute is required for correct processing of the object file; +a fatal diagnostic must be generated if a tool does not recognize either the tag +or the value associated with it. + +@var{encoding} specifies the expected encoding of the attributes recorded in the +subsection. Currently supported values are @code{ULEB128}/@code{uleb128} and +@code{NTBS}/@code{ntbs} (null-terminated byte string). + +On the first declaration of a subsection, both @var{comprehension} and +@var{encoding} are mandatory parameters. However, on subsequent declarations, +none of the parameters is required. If they are still specified, their values +will be matched against the ones from the first declaration. Any mismatch will +be reported as an error. + +This directive is only available for Object Attributes v2. + +@xref{Object Attributes}. @node Hidden @section @code{.hidden @var{names}} @@ -7958,32 +7998,61 @@ 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. +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. -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. - -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. + +The file format used by OAv2 is documented in @cite{Build Attributes for the +Arm 64-bit Architecture (AArch64)}, as AArch64 introduced it first. + @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}.