diff options
-rw-r--r-- | gas/ChangeLog | 7 | ||||
-rw-r--r-- | gas/expr.c | 55 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/elf.exp | 1 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/startof.d | 10 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/startof.s | 6 |
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 @@ -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) |