aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog7
-rw-r--r--gas/expr.c55
-rw-r--r--gas/testsuite/gas/elf/elf.exp1
-rw-r--r--gas/testsuite/gas/elf/startof.d10
-rw-r--r--gas/testsuite/gas/elf/startof.s6
5 files changed, 71 insertions, 8 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index a1997d2..9e61c2f 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,10 @@
+2021-06-18 Jan Beulich <jbeulich@suse.com>
+
+ * expr.c (symbol_lookup_or_make): New.
+ (operand): Use it.
+ * testsuite/gas/elf/startof.s, testsuite/gas/elf/startof.d: New.
+ * testsuite/gas/elf/elf.exp: Run new test.
+
2021-06-17 Nick Clifton <nickc@redhat.com>
PR 27904
diff --git a/gas/expr.c b/gas/expr.c
index afd065c..03caa91 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -127,6 +127,52 @@ expr_symbol_where (symbolS *sym, const char **pfile, unsigned int *pline)
return 0;
}
+
+/* Look up a previously used .startof. / .sizeof. symbol, or make a fresh
+ one. */
+
+static symbolS *
+symbol_lookup_or_make (const char *name, bool start)
+{
+ static symbolS **seen[2];
+ static unsigned int nr_seen[2];
+ char *buf = concat (start ? ".startof." : ".sizeof.", name, NULL);
+ symbolS *symbolP;
+ unsigned int i;
+
+ for (i = 0; i < nr_seen[start]; ++i)
+ {
+ symbolP = seen[start][i];
+
+ if (! symbolP)
+ break;
+
+ name = S_GET_NAME (symbolP);
+ if ((symbols_case_sensitive
+ ? strcasecmp (buf, name)
+ : strcmp (buf, name)) == 0)
+ {
+ free (buf);
+ return symbolP;
+ }
+ }
+
+ symbolP = symbol_make (buf);
+ free (buf);
+
+ if (i >= nr_seen[start])
+ {
+ unsigned int nr = (i + 1) * 2;
+
+ seen[start] = XRESIZEVEC (symbolS *, seen[start], nr);
+ nr_seen[start] = nr;
+ memset (&seen[start][i + 1], 0, (nr - i - 1) * sizeof(seen[0][0]));
+ }
+
+ seen[start][i] = symbolP;
+
+ return symbolP;
+}
/* Utilities for building expressions.
Since complex expressions are recorded as symbols for use in other
@@ -1159,8 +1205,6 @@ operand (expressionS *expressionP, enum expr_mode mode)
as_bad (_("syntax error in .startof. or .sizeof."));
else
{
- char *buf;
-
++input_line_pointer;
SKIP_WHITESPACE ();
c = get_symbol_name (& name);
@@ -1175,13 +1219,8 @@ operand (expressionS *expressionP, enum expr_mode mode)
break;
}
- buf = concat (start ? ".startof." : ".sizeof.", name,
- (char *) NULL);
- symbolP = symbol_make (buf);
- free (buf);
-
expressionP->X_op = O_symbol;
- expressionP->X_add_symbol = symbolP;
+ expressionP->X_add_symbol = symbol_lookup_or_make (name, start);
expressionP->X_add_number = 0;
*input_line_pointer = c;
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 525f47c..2380475 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -309,6 +309,7 @@ if { [is_elf_format] } then {
run_dump_test "pr27355"
run_dump_test "syms"
+ run_dump_test "startof"
run_dump_test "missing-build-notes"
diff --git a/gas/testsuite/gas/elf/startof.d b/gas/testsuite/gas/elf/startof.d
new file mode 100644
index 0000000..9cffa93
--- /dev/null
+++ b/gas/testsuite/gas/elf/startof.d
@@ -0,0 +1,10 @@
+#name: .startof. / .sizeof.
+#readelf: -s
+
+Symbol table .*
+ Num: .*
+ 0: 0+ .*
+#...
+ [1-8]: 0+ .* UND \.startof\.\.text
+ [2-9]: 0+ .* UND \.sizeof\.\.text
+#pass
diff --git a/gas/testsuite/gas/elf/startof.s b/gas/testsuite/gas/elf/startof.s
new file mode 100644
index 0000000..a90e116
--- /dev/null
+++ b/gas/testsuite/gas/elf/startof.s
@@ -0,0 +1,6 @@
+ .data
+ .dc.a .startof.(.text)
+ .dc.a .sizeof.(.text)
+ .dc.a 0
+ .dc.a .sizeof.(.text)
+ .dc.a .startof.(.text)