[PATCH v4 02/22] gas: move code for object attribute parsing into attr.c
Matthieu Longo
matthieu.longo@arm.com
Thu Jul 3 16:27:05 GMT 2025
---
gas/Makefile.am | 2 +
gas/Makefile.in | 11 +-
gas/attr.c | 232 +++++++++++++++++++++++++++++++++++++++++++
gas/attr.h | 33 ++++++
gas/config/obj-elf.c | 210 +--------------------------------------
gas/config/obj-elf.h | 4 +-
gas/po/POTFILES.in | 2 +
7 files changed, 278 insertions(+), 216 deletions(-)
create mode 100644 gas/attr.c
create mode 100644 gas/attr.h
diff --git a/gas/Makefile.am b/gas/Makefile.am
index 5d0358ce345..1b5fba55a4b 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -68,6 +68,7 @@ GAS_CFILES = \
app.c \
as.c \
atof-generic.c \
+ attr.c \
codeview.c \
compress-debug.c \
cond.c \
@@ -107,6 +108,7 @@ CFILES = $(GAS_CFILES) itbl-ops.c cgen.c
HFILES = \
as.h \
asintl.h \
+ attr.h \
bignum.h \
bit_fix.h \
cgen.h \
diff --git a/gas/Makefile.in b/gas/Makefile.in
index 1f24d4a5bbc..9cbb5992c53 100644
--- a/gas/Makefile.in
+++ b/gas/Makefile.in
@@ -168,10 +168,10 @@ CONFIG_CLEAN_FILES = gdb.ini .gdbinit po/Makefile.in
CONFIG_CLEAN_VPATH_FILES =
PROGRAMS = $(noinst_PROGRAMS)
am__objects_1 = app.$(OBJEXT) as.$(OBJEXT) atof-generic.$(OBJEXT) \
- codeview.$(OBJEXT) compress-debug.$(OBJEXT) cond.$(OBJEXT) \
- depend.$(OBJEXT) dwarf2dbg.$(OBJEXT) dw2gencfi.$(OBJEXT) \
- ecoff.$(OBJEXT) ehopt.$(OBJEXT) expr.$(OBJEXT) \
- flonum-copy.$(OBJEXT) flonum-konst.$(OBJEXT) \
+ attr.$(OBJEXT) codeview.$(OBJEXT) compress-debug.$(OBJEXT) \
+ cond.$(OBJEXT) depend.$(OBJEXT) dwarf2dbg.$(OBJEXT) \
+ dw2gencfi.$(OBJEXT) ecoff.$(OBJEXT) ehopt.$(OBJEXT) \
+ expr.$(OBJEXT) flonum-copy.$(OBJEXT) flonum-konst.$(OBJEXT) \
flonum-mult.$(OBJEXT) frags.$(OBJEXT) gen-sframe.$(OBJEXT) \
ginsn.$(OBJEXT) hash.$(OBJEXT) input-file.$(OBJEXT) \
input-scrub.$(OBJEXT) listing.$(OBJEXT) literal.$(OBJEXT) \
@@ -568,6 +568,7 @@ GAS_CFILES = \
app.c \
as.c \
atof-generic.c \
+ attr.c \
codeview.c \
compress-debug.c \
cond.c \
@@ -606,6 +607,7 @@ CFILES = $(GAS_CFILES) itbl-ops.c cgen.c
HFILES = \
as.h \
asintl.h \
+ attr.h \
bignum.h \
bit_fix.h \
cgen.h \
@@ -1311,6 +1313,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/app.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/as.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atof-generic.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attr.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/codeview.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compress-debug.Po@am__quote@
diff --git a/gas/attr.c b/gas/attr.c
new file mode 100644
index 00000000000..220c9ae7301
--- /dev/null
+++ b/gas/attr.c
@@ -0,0 +1,232 @@
+/* Object attributes parsing.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#include "attr.h"
+#include "safe-ctype.h"
+
+
+#define skip_whitespace(str) do { if (is_whitespace (*(str))) ++(str); } while (0)
+
+static inline int
+skip_past_char (char ** str, char c)
+{
+ if (**str == c)
+ {
+ (*str)++;
+ return 0;
+ }
+ else
+ return -1;
+}
+#define skip_past_comma(str) skip_past_char (str, ',')
+
+/* 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. */
+typedef struct recorded_attribute_info {
+ struct recorded_attribute_info *next;
+ obj_attr_vendor vendor;
+ unsigned int base;
+ unsigned long mask;
+} recorded_attribute_info;
+static recorded_attribute_info *recorded_attributes;
+
+static void
+oav1_attr_info_free (recorded_attribute_info *node)
+{
+ recorded_attribute_info *next;
+ while (node != NULL)
+ {
+ next = node->next;
+ free (node);
+ node = next;
+ }
+}
+
+void
+oav1_attr_info_init ()
+{
+ recorded_attributes = NULL;
+}
+
+void
+oav1_attr_info_exit ()
+{
+ oav1_attr_info_free (recorded_attributes);
+}
+
+/* Record that we have seen an explicit specification of attribute TAG
+ for vendor VENDOR. */
+
+static void
+oav1_attr_record_seen (obj_attr_vendor vendor, obj_attr_tag_t tag)
+{
+ unsigned int base;
+ unsigned long mask;
+ recorded_attribute_info *rai;
+
+ base = tag / (8 * sizeof (rai->mask));
+ mask = 1UL << (tag % (8 * sizeof (rai->mask)));
+ for (rai = recorded_attributes; rai; rai = rai->next)
+ if (rai->vendor == vendor && rai->base == base)
+ {
+ rai->mask |= mask;
+ return;
+ }
+
+ rai = XNEW (recorded_attribute_info);
+ rai->next = recorded_attributes;
+ rai->vendor = vendor;
+ rai->base = base;
+ rai->mask = mask;
+ recorded_attributes = rai;
+}
+
+/* Return true if we have seen an explicit specification of attribute TAG
+ for vendor VENDOR. */
+
+bool
+oav1_attr_seen (obj_attr_vendor vendor, obj_attr_tag_t tag)
+{
+ unsigned int base;
+ unsigned long mask;
+ recorded_attribute_info *rai;
+
+ base = tag / (8 * sizeof (rai->mask));
+ mask = 1UL << (tag % (8 * sizeof (rai->mask)));
+ for (rai = recorded_attributes; rai; rai = rai->next)
+ if (rai->vendor == vendor && rai->base == base)
+ return (rai->mask & mask) != 0;
+ return false;
+}
+
+/* Parse an attribute directive for VENDOR.
+ Returns the attribute number read, or zero on error. */
+
+obj_attr_tag_t
+obj_attr_v1_process_attribute (obj_attr_vendor vendor)
+{
+ expressionS exp;
+ int type;
+ int tag;
+ unsigned int i = 0;
+ char *s = NULL;
+
+ /* Read the first number or name. */
+ skip_whitespace (input_line_pointer);
+ s = input_line_pointer;
+ if (ISDIGIT (*input_line_pointer))
+ {
+ expression (& exp);
+ if (exp.X_op != O_constant)
+ goto bad;
+ tag = exp.X_add_number;
+ }
+ else
+ {
+ char *name;
+
+ /* A name may contain '_', but no other punctuation. */
+ for (; ISALNUM (*input_line_pointer) || *input_line_pointer == '_';
+ ++input_line_pointer)
+ i++;
+ if (i == 0)
+ goto bad;
+
+ name = xmemdup0 (s, i);
+
+#ifndef CONVERT_SYMBOLIC_ATTRIBUTE
+#define CONVERT_SYMBOLIC_ATTRIBUTE(a) -1
+#endif
+
+ tag = CONVERT_SYMBOLIC_ATTRIBUTE (name);
+ if (tag == -1)
+ {
+ as_bad (_("Attribute name not recognised: %s"), name);
+ ignore_rest_of_line ();
+ free (name);
+ return 0;
+ }
+ free (name);
+ }
+
+ type = _bfd_elf_obj_attrs_arg_type (stdoutput, vendor, tag);
+
+ if (skip_past_comma (&input_line_pointer) == -1)
+ goto bad;
+ if (type & 1)
+ {
+ expression (& exp);
+ if (exp.X_op != O_constant)
+ {
+ as_bad (_("expected numeric constant"));
+ ignore_rest_of_line ();
+ return 0;
+ }
+ i = exp.X_add_number;
+ }
+ if ((type & 3) == 3
+ && skip_past_comma (&input_line_pointer) == -1)
+ {
+ as_bad (_("expected comma"));
+ ignore_rest_of_line ();
+ return 0;
+ }
+ if (type & 2)
+ {
+ int len;
+
+ skip_whitespace (input_line_pointer);
+ if (*input_line_pointer != '"')
+ goto bad_string;
+ s = demand_copy_C_string (&len);
+ }
+
+ oav1_attr_record_seen (vendor, tag);
+ bool ok = false;
+ switch (type & 3)
+ {
+ case 3:
+ ok = bfd_elf_add_obj_attr_int_string (stdoutput, vendor, tag, i, s);
+ break;
+ case 2:
+ ok = bfd_elf_add_obj_attr_string (stdoutput, vendor, tag, s);
+ break;
+ case 1:
+ ok = bfd_elf_add_obj_attr_int (stdoutput, vendor, tag, i);
+ break;
+ default:
+ abort ();
+ }
+ if (!ok)
+ as_fatal (_("error adding attribute: %s"),
+ bfd_errmsg (bfd_get_error ()));
+
+ demand_empty_rest_of_line ();
+ return tag;
+ bad_string:
+ as_bad (_("bad string constant"));
+ ignore_rest_of_line ();
+ return 0;
+ bad:
+ as_bad (_("expected <tag> , <value>"));
+ ignore_rest_of_line ();
+ return 0;
+}
diff --git a/gas/attr.h b/gas/attr.h
new file mode 100644
index 00000000000..b1f049f4c53
--- /dev/null
+++ b/gas/attr.h
@@ -0,0 +1,33 @@
+/* Object attributes parsing.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef _ATTR_H
+#define _ATTR_H
+
+#include "as.h"
+#include "bfd/elf-bfd.h"
+
+/* Object attributes 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);
+extern obj_attr_tag_t obj_attr_v1_process_attribute (obj_attr_vendor);
+
+#endif /* _ATTR_H */
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 1db3e0ae6ef..c4dcad7acbc 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -25,6 +25,7 @@
#include "obstack.h"
#include "dwarf2dbg.h"
#include "ginsn.h"
+#include "attr.h"
#ifndef ECOFF_DEBUGGING
#define ECOFF_DEBUGGING 0
@@ -2043,215 +2044,6 @@ obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED)
(void) obj_elf_get_vtable_entry ();
}
-#define skip_whitespace(str) do { if (is_whitespace (*(str))) ++(str); } while (0)
-
-static inline int
-skip_past_char (char ** str, char c)
-{
- if (**str == c)
- {
- (*str)++;
- return 0;
- }
- else
- return -1;
-}
-#define skip_past_comma(str) skip_past_char (str, ',')
-
-/* 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. */
-typedef struct recorded_attribute_info {
- struct recorded_attribute_info *next;
- obj_attr_vendor vendor;
- unsigned int base;
- unsigned long mask;
-} recorded_attribute_info;
-static recorded_attribute_info *recorded_attributes;
-
-static void
-oav1_attr_info_free (recorded_attribute_info *node)
-{
- recorded_attribute_info *next;
- while (node != NULL)
- {
- next = node->next;
- free (node);
- node = next;
- }
-}
-
-static void
-oav1_attr_info_init (void)
-{
- recorded_attributes = NULL;
-}
-
-static void
-oav1_attr_info_exit (void)
-{
- oav1_attr_info_free (recorded_attributes);
-}
-
-/* Record that we have seen an explicit specification of attribute TAG
- for vendor VENDOR. */
-
-static void
-oav1_attr_record_seen (obj_attr_vendor vendor, obj_attr_tag_t tag)
-{
- unsigned int base;
- unsigned long mask;
- recorded_attribute_info *rai;
-
- base = tag / (8 * sizeof (rai->mask));
- mask = 1UL << (tag % (8 * sizeof (rai->mask)));
- for (rai = recorded_attributes; rai; rai = rai->next)
- if (rai->vendor == vendor && rai->base == base)
- {
- rai->mask |= mask;
- return;
- }
-
- rai = XNEW (recorded_attribute_info);
- rai->next = recorded_attributes;
- rai->vendor = vendor;
- rai->base = base;
- rai->mask = mask;
- recorded_attributes = rai;
-}
-
-/* Return true if we have seen an explicit specification of attribute TAG
- for vendor VENDOR. */
-
-bool
-oav1_attr_seen (obj_attr_vendor vendor, obj_attr_tag_t tag)
-{
- unsigned int base;
- unsigned long mask;
- recorded_attribute_info *rai;
-
- base = tag / (8 * sizeof (rai->mask));
- mask = 1UL << (tag % (8 * sizeof (rai->mask)));
- for (rai = recorded_attributes; rai; rai = rai->next)
- if (rai->vendor == vendor && rai->base == base)
- return (rai->mask & mask) != 0;
- return false;
-}
-
-/* Parse an attribute directive for VENDOR.
- Returns the attribute number read, or zero on error. */
-
-obj_attr_tag_t
-obj_attr_v1_process_attribute (obj_attr_vendor vendor)
-{
- expressionS exp;
- int type;
- int tag;
- unsigned int i = 0;
- char *s = NULL;
-
- /* Read the first number or name. */
- skip_whitespace (input_line_pointer);
- s = input_line_pointer;
- if (ISDIGIT (*input_line_pointer))
- {
- expression (& exp);
- if (exp.X_op != O_constant)
- goto bad;
- tag = exp.X_add_number;
- }
- else
- {
- char *name;
-
- /* A name may contain '_', but no other punctuation. */
- for (; ISALNUM (*input_line_pointer) || *input_line_pointer == '_';
- ++input_line_pointer)
- i++;
- if (i == 0)
- goto bad;
-
- name = xmemdup0 (s, i);
-
-#ifndef CONVERT_SYMBOLIC_ATTRIBUTE
-#define CONVERT_SYMBOLIC_ATTRIBUTE(a) -1
-#endif
-
- tag = CONVERT_SYMBOLIC_ATTRIBUTE (name);
- if (tag == -1)
- {
- as_bad (_("Attribute name not recognised: %s"), name);
- ignore_rest_of_line ();
- free (name);
- return 0;
- }
- free (name);
- }
-
- type = _bfd_elf_obj_attrs_arg_type (stdoutput, vendor, tag);
-
- if (skip_past_comma (&input_line_pointer) == -1)
- goto bad;
- if (type & 1)
- {
- expression (& exp);
- if (exp.X_op != O_constant)
- {
- as_bad (_("expected numeric constant"));
- ignore_rest_of_line ();
- return 0;
- }
- i = exp.X_add_number;
- }
- if ((type & 3) == 3
- && skip_past_comma (&input_line_pointer) == -1)
- {
- as_bad (_("expected comma"));
- ignore_rest_of_line ();
- return 0;
- }
- if (type & 2)
- {
- int len;
-
- skip_whitespace (input_line_pointer);
- if (*input_line_pointer != '"')
- goto bad_string;
- s = demand_copy_C_string (&len);
- }
-
- oav1_attr_record_seen (vendor, tag);
- bool ok = false;
- switch (type & 3)
- {
- case 3:
- ok = bfd_elf_add_obj_attr_int_string (stdoutput, vendor, tag, i, s);
- break;
- case 2:
- ok = bfd_elf_add_obj_attr_string (stdoutput, vendor, tag, s);
- break;
- case 1:
- ok = bfd_elf_add_obj_attr_int (stdoutput, vendor, tag, i);
- break;
- default:
- abort ();
- }
- if (!ok)
- as_fatal (_("error adding attribute: %s"),
- bfd_errmsg (bfd_get_error ()));
-
- demand_empty_rest_of_line ();
- return tag;
- bad_string:
- as_bad (_("bad string constant"));
- ignore_rest_of_line ();
- return 0;
- bad:
- as_bad (_("expected <tag> , <value>"));
- ignore_rest_of_line ();
- return 0;
-}
-
/* Parse a .gnu_attribute directive. */
static void
diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h
index a064a4da2f5..98368ac23c0 100644
--- a/gas/config/obj-elf.h
+++ b/gas/config/obj-elf.h
@@ -205,9 +205,7 @@ extern void obj_elf_vtable_entry (int);
extern struct fix * obj_elf_get_vtable_inherit (void);
extern struct fix * obj_elf_get_vtable_entry (void);
-/* Object attributes v1. */
-extern bool oav1_attr_seen (obj_attr_vendor, obj_attr_tag_t);
-extern obj_attr_tag_t obj_attr_v1_process_attribute (obj_attr_vendor);
+#include "attr.h"
/* BFD wants to write the udata field, which is a no-no for the
predefined section symbols in bfd/section.c. They are read-only. */
diff --git a/gas/po/POTFILES.in b/gas/po/POTFILES.in
index c600b179e43..b4d0c6a83ce 100644
--- a/gas/po/POTFILES.in
+++ b/gas/po/POTFILES.in
@@ -3,6 +3,8 @@ as.c
as.h
asintl.h
atof-generic.c
+attr.c
+attr.h
bignum.h
bit_fix.h
cgen.c
--
2.50.0
More information about the Binutils
mailing list