[PATCH v4 21/22] gas: disable code related to object attributes (OAs) on non-OA targets
Matthieu Longo
matthieu.longo@arm.com
Thu Jul 3 16:27:24 GMT 2025
Gas, contrarilly to others binutils tools, is compiled for a specific
target. Some targets don't support Object Attributes (OAs).
For those cases, only the directives are disabled today, but not the
code to handle the parsing, which constitutes dead code.
This patch aims at removing this code from Gas when the target does not
support the OAs. It also pushes the disabling of code further to support
the following configurations for OAs:
- enable both OAv1 and OAv2 parsing. This is currently used by no
target, but is useful for migration from OAv1 to OAv2.
- enable OAv1 parsing only. This is used by all targets supporting OAs
except for AArch64.
- enable OAv2 parsing only. This is only used by AArch64.
Adding/removing the OA feature from Gas for a specific target can easilly
be done from gas/attr.h by using the TC_<arch> define (see existing
examples in the header).
---
gas/attr.c | 84 ++++++++++++++++++++++++++++++++++++++------
gas/attr.h | 17 +++++++--
gas/config/obj-elf.c | 15 ++++++++
3 files changed, 103 insertions(+), 13 deletions(-)
diff --git a/gas/attr.c b/gas/attr.c
index 9e129a258bc..866e1c320d9 100644
--- a/gas/attr.c
+++ b/gas/attr.c
@@ -19,6 +19,9 @@
02110-1301, USA. */
#include "attr.h"
+
+#ifdef HAVE_OBJ_ATTR
+
#include "obstack.h"
#include "safe-ctype.h"
@@ -38,6 +41,8 @@ skip_past_char (char ** str, char c)
}
#define skip_past_comma(str) skip_past_char (str, ',')
+#if (HAVE_OBJ_ATTR_v1)
+
/* A list of attributes that have been explicitly set by the assembly code.
VENDOR is the vendor id, BASE is the tag shifted right by the number
of bits in MASK, and bit N of MASK is set if tag BASE+N has been set. */
@@ -118,6 +123,8 @@ oav1_attr_seen (obj_attr_vendor vendor, obj_attr_tag_t tag)
return false;
}
+#endif /* HAVE_OBJ_ATTR_v1 */
+
/* Expected argument tokens for object attribute directives. */
typedef enum {
/* Base types. */
@@ -237,6 +244,7 @@ extract_identifier (bool (*char_predicate) (char), arg_t *arg_out)
return true;
}
+#if (HAVE_OBJ_ATTR_v2)
/* Resolve the identifier if it matches the given symbol. */
static bool
resolve_if_matching (const char *identifier,
@@ -281,7 +289,9 @@ resolve_if_matching (const char *identifier,
return true;
}
+#endif /* HAVE_OBJ_ATTR_v2 */
+#if (HAVE_OBJ_ATTR_v1)
/* Look up attribute keys defined in the backend (object attribute v1). */
static bool
obj_attr_v1_lookup_known_attr_key_symbol (const char *identifier,
@@ -302,7 +312,9 @@ obj_attr_v1_lookup_known_attr_key_symbol (const char *identifier,
val_out->vtype = VALUE_UNSIGNED_INTEGER;
return true;
}
+#endif /* HAVE_OBJ_ATTR_v1 */
+#if (HAVE_OBJ_ATTR_v2)
/* Look up attribute keys defined in the backend (object attribute v2). */
static bool
obj_attr_v2_lookup_known_attr_key_symbol (const char *identifier,
@@ -339,6 +351,7 @@ obj_attr_v2_lookup_known_attr_key_symbol (const char *identifier,
return resolved;
}
+#endif /* HAVE_OBJ_ATTR_v2 */
/* Look up known symbols, and try to resolve the given identifier. */
static bool
@@ -354,6 +367,7 @@ lookup_known_symbols (const char *identifier,
arg_token_t high_ttype = (token_type & HT_MASK);
+#if (HAVE_OBJ_ATTR_v2)
static const gas_symbol_t known_identifiers_subsection_optional[] = {
{ "optional", .value = { .val.b = true, .vtype = VALUE_BOOL } },
{ "required", .value = { .val.b = false, .vtype = VALUE_BOOL } },
@@ -381,9 +395,11 @@ lookup_known_symbols (const char *identifier,
}
},
};
+#endif /* HAVE_OBJ_ATTR_v2 */
bool resolved = false;
+#if (HAVE_OBJ_ATTR_v2)
if (high_ttype == SUBSECTION_OPTION_1 || high_ttype == SUBSECTION_OPTION_2)
{
const gas_symbol_t *known_identifiers
@@ -400,15 +416,24 @@ lookup_known_symbols (const char *identifier,
&known_identifiers[i],
val_out);
}
- else if (high_ttype == ATTRIBUTE_KEY)
+ else
+#endif
+ if (high_ttype == ATTRIBUTE_KEY)
{
obj_attr_version_t version = elf_obj_attr_version (stdoutput);
+#if (HAVE_OBJ_ATTR_v1)
if (version == OBJ_ATTR_V1)
resolved = obj_attr_v1_lookup_known_attr_key_symbol (identifier,
token_type, val_out);
- else if (version == OBJ_ATTR_V2)
+#endif
+#if (HAVE_OBJ_ATTR_v2)
+ #if (HAVE_OBJ_ATTR_v1)
+ else
+ #endif
+ if (version == OBJ_ATTR_V2)
resolved = obj_attr_v2_lookup_known_attr_key_symbol (identifier,
token_type, val_out);
+#endif
else
abort ();
}
@@ -600,6 +625,7 @@ obj_attr_parse_args (arg_token_t expected_ttype,
return false;
}
+#if (HAVE_OBJ_ATTR_v2)
static bool
is_valid_boolean (uint64_t value)
{
@@ -616,19 +642,21 @@ is_valid_encoding (uint64_t value)
}
static bool
-match_symbol (char c)
+match_subsection_identifier (char c)
{
- return ISALNUM (c) || c == '_';
+ return ISALNUM (c) || c == '_' || c == '-';
}
-
-#define match_tag_identifier match_symbol
+#endif /* HAVE_OBJ_ATTR_v2 */
static bool
-match_subsection_identifier (char c)
+match_symbol (char c)
{
- return ISALNUM (c) || c == '_' || c == '-';
+ return ISALNUM (c) || c == '_';
}
+#define match_tag_identifier match_symbol
+
+#if (HAVE_OBJ_ATTR_v1)
/* Determine the expected argument type based on the tag ID. */
static arg_token_t
obj_attr_v1_get_arg_type (bfd *abfd, obj_attr_vendor vendor, obj_attr_tag_t tag)
@@ -646,7 +674,9 @@ obj_attr_v1_get_arg_type (bfd *abfd, obj_attr_vendor vendor, obj_attr_tag_t tag)
arg_type = UNSIGNED_INTEGER;
return arg_type;
}
+#endif
+#if (HAVE_OBJ_ATTR_v2)
/* Determine the expected argument type based on the subsection encoding. */
static arg_token_t
obj_attr_v2_get_arg_type (obj_attr_encoding_v2 subsec_encoding)
@@ -666,11 +696,21 @@ obj_attr_v2_get_arg_type (obj_attr_encoding_v2 subsec_encoding)
}
return arg_type;
}
+#endif
/* Parse the arguments of [vendor]_attribute directive. */
static arg_t *
-vendor_attribute_parse_args (obj_attr_vendor vendor,
+vendor_attribute_parse_args (
+#if (HAVE_OBJ_ATTR_v1 && HAVE_OBJ_ATTR_v2)
+ obj_attr_vendor vendor,
+ const obj_attr_subsection_v2 *subsec,
+#elif (HAVE_OBJ_ATTR_v1)
+ obj_attr_vendor vendor,
+ const obj_attr_subsection_v2 *subsec ATTRIBUTE_UNUSED,
+#else /* HAVE_OBJ_ATTR_v2 */
+ obj_attr_vendor vendor ATTRIBUTE_UNUSED,
const obj_attr_subsection_v2 *subsec,
+#endif
unsigned int nargs, ...)
{
va_list args;
@@ -694,10 +734,17 @@ vendor_attribute_parse_args (obj_attr_vendor vendor,
if (high_ttype == ATTRIBUTE_VALUE)
{
arg_token_t type_attr_value
+#if (HAVE_OBJ_ATTR_v1 && HAVE_OBJ_ATTR_v2)
= (subsec != NULL)
? obj_attr_v2_get_arg_type (subsec->encoding)
: obj_attr_v1_get_arg_type (stdoutput, vendor,
args_out[n-1].val.u32);
+#elif (HAVE_OBJ_ATTR_v1)
+ = obj_attr_v1_get_arg_type (stdoutput, vendor,
+ args_out[n-1].val.u32);
+#else
+ = obj_attr_v2_get_arg_type (subsec->encoding);
+#endif
expected_ttype |= type_attr_value;
}
@@ -728,6 +775,7 @@ bad:
return NULL;
}
+#if (HAVE_OBJ_ATTR_v1)
/* Record an attribute (object attribute v1 only). */
static obj_attribute *
obj_attr_v1_record (bfd *abfd,
@@ -763,7 +811,9 @@ obj_attr_v1_record (bfd *abfd,
}
return attr;
}
+#endif
+#if (HAVE_OBJ_ATTR_v2)
/* Parse the arguments of [vendor]_subsection directive (v2 only). */
static arg_t *
vendor_subsection_parse_args (unsigned int nargs, ...)
@@ -927,6 +977,7 @@ obj_attr_v2_subsection_record (const char *name,
&elf_obj_attr_subsections (stdoutput), new_subsection);
}
}
+#endif
/* Parse an attribute directive (supports both v1 & v2). */
obj_attr_tag_t
@@ -935,6 +986,7 @@ obj_attr_process_attribute (obj_attr_vendor vendor)
obj_attr_version_t version = elf_obj_attr_version (stdoutput);
obj_attr_subsection_v2 *subsec = NULL;
+#if (HAVE_OBJ_ATTR_v2)
if (version == OBJ_ATTR_V2)
{
subsec = elf_obj_attr_subsections (stdoutput).last_;
@@ -946,6 +998,7 @@ obj_attr_process_attribute (obj_attr_vendor vendor)
return 0;
}
}
+#endif /* HAVE_OBJ_ATTR_v2 */
const size_t N_ARGS = 2;
arg_t *args = vendor_attribute_parse_args (
@@ -957,13 +1010,20 @@ obj_attr_process_attribute (obj_attr_vendor vendor)
return 0;
obj_attr_tag_t tag = args[0].val.u64;
+#if (HAVE_OBJ_ATTR_v1)
if (version == OBJ_ATTR_V1)
{
oav1_attr_record_seen (vendor, tag);
obj_attr_v1_record (stdoutput, vendor, tag, &args[1]);
}
- else if (version == OBJ_ATTR_V2)
+#endif /* HAVE_OBJ_ATTR_v1 */
+#if (HAVE_OBJ_ATTR_v2)
+ #if (HAVE_OBJ_ATTR_v1)
+ else
+ #endif
+ if (version == OBJ_ATTR_V2)
obj_attr_v2_record (tag, &args[1]);
+#endif /* HAVE_OBJ_ATTR_v2 */
else
abort ();
@@ -972,6 +1032,7 @@ obj_attr_process_attribute (obj_attr_vendor vendor)
return tag;
}
+#if (HAVE_OBJ_ATTR_v2)
/* Parse an object attribute v2's subsection directive. */
void
obj_attr_process_subsection ()
@@ -995,3 +1056,6 @@ obj_attr_process_subsection ()
args_list_free (args, N_ARGS);
}
+#endif /* HAVE_OBJ_ATTR_v2 */
+
+#endif /* HAVE_OBJ_ATTR */
diff --git a/gas/attr.h b/gas/attr.h
index 04f19dc589d..62f0bbf2f6c 100644
--- a/gas/attr.h
+++ b/gas/attr.h
@@ -48,16 +48,27 @@
#define HAVE_OBJ_ATTR_v2 0
#endif
-/* Object attributes v1. */
+#if (HAVE_OBJ_ATTR_v1 || HAVE_OBJ_ATTR_v2)
+ #define HAVE_OBJ_ATTR 1
+#endif
+
+#ifdef HAVE_OBJ_ATTR
+
+#if (HAVE_OBJ_ATTR_v1)
extern void oav1_attr_info_init (void);
extern void oav1_attr_info_exit (void);
extern bool oav1_attr_seen (obj_attr_vendor, obj_attr_tag_t);
+#endif
/* Object attributes parsers. */
-/* Object attributes v1 & v2. */
+#if (HAVE_OBJ_ATTR_v1 || HAVE_OBJ_ATTR_v2)
extern obj_attr_tag_t obj_attr_process_attribute (obj_attr_vendor);
-/* Object attributes v2 only. */
+#endif
+#if (HAVE_OBJ_ATTR_v2)
extern void obj_attr_process_subsection (void);
+#endif
+
+#endif /* HAVE_OBJ_ATTR */
#endif /* _ATTR_H */
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 6e59c335d23..27f1eb323d1 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -72,12 +72,14 @@ static void obj_elf_visibility (int);
static void obj_elf_symver (int);
static void obj_elf_subsection (int);
static void obj_elf_popsection (int);
+#ifdef HAVE_OBJ_ATTR
#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
+#endif /* HAVE_OBJ_ATTR */
static void obj_elf_tls_common (int);
static void obj_elf_lcomm (int);
static void obj_elf_struct (int);
@@ -122,12 +124,14 @@ static const pseudo_typeS elf_pseudo_table[] =
{"vtable_entry", obj_elf_vtable_entry, 0},
/* A GNU extension for object attributes. */
+#ifdef HAVE_OBJ_ATTR
#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
+#endif /* HAVE_OBJ_ATTR */
/* These are used for dwarf2. */
{ "file", dwarf2_directive_file, 0 },
@@ -2054,6 +2058,8 @@ obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED)
(void) obj_elf_get_vtable_entry ();
}
+#ifdef HAVE_OBJ_ATTR
+
/* Parse a .gnu_attribute directive. */
#if (HAVE_OBJ_ATTR_v1 || HAVE_OBJ_ATTR_v2)
static void
@@ -2080,6 +2086,8 @@ obj_elf_gnu_subsection (int ignored ATTRIBUTE_UNUSED)
}
#endif
+#endif /* HAVE_OBJ_ATTR */
+
void
elf_obj_read_begin_hook (void)
{
@@ -3011,12 +3019,16 @@ elf_begin (void)
comment_section = NULL;
memset (&groups, 0, sizeof (groups));
+#ifdef HAVE_OBJ_ATTR
/* Set the object attribute version for the output object to the recommended
value by the backend. */
elf_obj_attr_version (stdoutput)
= get_elf_backend_data (stdoutput)->default_obj_attr_version;
+#if HAVE_OBJ_ATTR_v1
oav1_attr_info_init ();
+#endif /* HAVE_OBJ_ATTR_v1 */
+#endif /* HAVE_OBJ_ATTR */
}
void
@@ -3033,7 +3045,10 @@ elf_end (void)
htab_delete (groups.indexes);
free (groups.head);
}
+
+#if HAVE_OBJ_ATTR_v1
oav1_attr_info_exit ();
+#endif /* HAVE_OBJ_ATTR_v1 */
}
#ifdef USE_EMULATIONS
--
2.50.0
More information about the Binutils
mailing list