[binutils-gdb] gas: fold symbol table entries generated for .startof.() / .sizeof.()

Jan Beulich jbeulich@sourceware.org
Fri Jun 18 11:52:01 GMT 2021


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=162c6aef1f3a96923e75f0b4ef430822d273465c

commit 162c6aef1f3a96923e75f0b4ef430822d273465c
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri Jun 18 13:51:52 2021 +0200

    gas: fold symbol table entries generated for .startof.() / .sizeof.()
    
    When the same such construct is used multiple times in a source file,
    there's still no need to emit a separate symbol each time. Under the
    assumption that there won't be many of these, use a simple array
    lookup method to record previously used symbols.

Diff:
---
 gas/ChangeLog                   |  7 ++++++
 gas/expr.c                      | 55 +++++++++++++++++++++++++++++++++++------
 gas/testsuite/gas/elf/elf.exp   |  1 +
 gas/testsuite/gas/elf/startof.d | 10 ++++++++
 gas/testsuite/gas/elf/startof.s |  6 +++++
 5 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index a1997d2c028..9e61c2f3a5e 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 afd065c23be..03caa91f4d1 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 525f47c0023..23804758c5a 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 00000000000..9cffa93e22b
--- /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 00000000000..a90e1160dd8
--- /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)


More information about the Binutils-cvs mailing list