[binutils-gdb] COFF: function auxiliary symbols

Jan Beulich jbeulich@sourceware.org
Fri May 2 08:11:18 GMT 2025


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

commit ea9c4d157496d68a489f1d9e3a623d1dd9788192
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri May 2 10:07:53 2025 +0200

    COFF: function auxiliary symbols
    
    For one at least x86 gcc emits .def/.endef for functions, but no 2nd
    pair to designate their ends (sizes). While we can't recover the sizes,
    we can at least properly establish the chain of function symbols, which
    of course requires to emit auxiliary symbols for every function symbol
    even when there's no C_EFCN: We simply shouldn't be making their
    insertion conditional upon there not being a function processing of
    which is "in progress".
    
    In fact it was wrong to assign dual purpose to {,next_}set_end:
    Functions don't have "ends" set, but links to the next one. The same
    symbol table entry can serve both as an end marker and be a part of the
    chain of (defined) functions; this can't be expressed by a single static
    variable. Use what (again) becomes last_functionP for this purpose,
    along with tracking what symbol C_EFCN should apply to.
    
    This then allows to undo exposing of the respective (supposedly static)
    tracking variable, which PPC's XCOFF handling had introduced. Also
    rename it back to what it was before its exposure.
    
    For now the new testcases are XFAIL for Arm64 since there, unlike for
    Arm32, mapping symbols are emitted for COFF, too.

Diff:
---
 gas/config/obj-coff.c           | 21 ++++++++++++---------
 gas/config/obj-coff.h           |  1 -
 gas/config/tc-ppc.c             |  7 -------
 gas/testsuite/gas/coff/coff.exp |  8 ++++++++
 gas/testsuite/gas/coff/func1.d  | 16 ++++++++++++++++
 gas/testsuite/gas/coff/func1.s  | 22 ++++++++++++++++++++++
 gas/testsuite/gas/coff/func2.d  | 16 ++++++++++++++++
 gas/testsuite/gas/coff/func2.s  | 34 ++++++++++++++++++++++++++++++++++
 gas/testsuite/gas/coff/func3.d  | 16 ++++++++++++++++
 gas/testsuite/gas/coff/func3.s  | 33 +++++++++++++++++++++++++++++++++
 gas/testsuite/gas/coff/func4.d  | 18 ++++++++++++++++++
 gas/testsuite/gas/coff/func4.s  | 41 +++++++++++++++++++++++++++++++++++++++++
 12 files changed, 216 insertions(+), 17 deletions(-)

diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c
index 53e923197d3..445f2ac764d 100644
--- a/gas/config/obj-coff.c
+++ b/gas/config/obj-coff.c
@@ -1187,7 +1187,6 @@ coff_assign_symbol (symbolS *symp ATTRIBUTE_UNUSED)
 #endif
 }
 
-symbolS *coff_last_function;
 #ifndef OBJ_XCOFF
 static symbolS *coff_last_bf;
 #endif
@@ -1195,6 +1194,7 @@ static symbolS *coff_last_bf;
 void
 coff_frob_symbol (symbolS *symp, int *punt)
 {
+  static symbolS *last_functionP;
   static symbolS *last_tagP;
   static stack *block_stack;
   static symbolS *set_end;
@@ -1338,12 +1338,10 @@ coff_frob_symbol (symbolS *symp, int *punt)
 		}
 	    }
 
-	  if (coff_last_function == 0 && SF_GET_FUNCTION (symp)
-	      && S_IS_DEFINED (symp))
+	  if (SF_GET_FUNCTION (symp) && S_IS_DEFINED (symp))
 	    {
 	      union internal_auxent *auxp;
 
-	      coff_last_function = symp;
 	      if (S_GET_NUMBER_AUXILIARY (symp) < 1)
 		S_SET_NUMBER_AUXILIARY (symp, 1);
 	      auxp = SYM_AUXENT (symp);
@@ -1354,14 +1352,12 @@ coff_frob_symbol (symbolS *symp, int *punt)
 	  if (S_GET_STORAGE_CLASS (symp) == C_EFCN
 	      && S_IS_DEFINED (symp))
 	    {
-	      if (coff_last_function == 0)
+	      if (!last_functionP)
 		as_fatal (_("C_EFCN symbol for %s out of scope"),
 			  S_GET_NAME (symp));
-	      SA_SET_SYM_FSIZE (coff_last_function,
+	      SA_SET_SYM_FSIZE (last_functionP,
 				(long) (S_GET_VALUE (symp)
-					- S_GET_VALUE (coff_last_function)));
-	      next_set_end = coff_last_function;
-	      coff_last_function = 0;
+					- S_GET_VALUE (last_functionP)));
 	    }
 	}
 
@@ -1415,6 +1411,13 @@ coff_frob_symbol (symbolS *symp, int *punt)
       set_end = next_set_end;
     }
 
+  if (SF_GET_FUNCTION (symp) && S_IS_DEFINED (symp) && !*punt)
+    {
+      if (last_functionP)
+	SA_SET_SYM_ENDNDX (last_functionP, symp);
+      last_functionP = symp;
+    }
+
 #ifndef OBJ_XCOFF
   if (! *punt
       && S_GET_STORAGE_CLASS (symp) == C_FCN
diff --git a/gas/config/obj-coff.h b/gas/config/obj-coff.h
index 1d191ee2eee..51dfd56e447 100644
--- a/gas/config/obj-coff.h
+++ b/gas/config/obj-coff.h
@@ -242,7 +242,6 @@
 extern int text_lineno_number;
 extern int coff_line_base;
 extern int coff_n_line_nos;
-extern symbolS *coff_last_function;
 
 #define obj_emit_lineno(WHERE, LINE, FILE_START)	abort ()
 #define obj_app_file(name)           c_dot_file_symbol (name)
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index 33f3a4c840a..0de27140d6a 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -6140,9 +6140,6 @@ ppc_frob_symbol (symbolS *sym)
 
   if (SF_GET_FUNCTION (sym))
     {
-      /* Make sure coff_last_function is reset. Otherwise, we won't create
-         the auxent for the next function.  */
-      coff_last_function = 0;
       ppc_last_function = sym;
       if (symbol_get_tc (sym)->u.size != (symbolS *) NULL)
 	{
@@ -6170,10 +6167,6 @@ ppc_frob_symbol (symbolS *sym)
 	{
 	  set_end = ppc_last_function;
 	  ppc_last_function = NULL;
-
-	  /* We don't have a C_EFCN symbol, but we need to force the
-	     COFF backend to believe that it has seen one.  */
-	  coff_last_function = NULL;
 	}
     }
 
diff --git a/gas/testsuite/gas/coff/coff.exp b/gas/testsuite/gas/coff/coff.exp
index 0ef804490fe..b5e7d240689 100644
--- a/gas/testsuite/gas/coff/coff.exp
+++ b/gas/testsuite/gas/coff/coff.exp
@@ -30,3 +30,11 @@ if {    ![istarget arm*-*-*]
      && ![istarget *c54x*-*-*] } {
     run_dump_test tag
 }
+
+# Omit c4x and c54x, since .def means something different there.
+if { ![istarget *c4x*-*-*] && ![istarget *c54x*-*-*] } {
+    run_dump_test func1
+    run_dump_test func2
+    run_dump_test func3
+    run_dump_test func4
+}
diff --git a/gas/testsuite/gas/coff/func1.d b/gas/testsuite/gas/coff/func1.d
new file mode 100644
index 00000000000..c0bfa831d66
--- /dev/null
+++ b/gas/testsuite/gas/coff/func1.d
@@ -0,0 +1,16 @@
+#xfail: aarch64-*-*
+#objdump: -t
+#name: functions w/o C_EFCN
+
+.*:     file format .*
+
+SYMBOL TABLE:
+\[  0\]\(sec -2\)\(fl 0x00\)\(ty    0\)\(scl 103\) \(nx 1\) 0x0+0000 func1.c
+File *
+\[  2\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   3\) \(nx 1\) 0x0+0000 inner
+AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 4
+\[  4\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   3\) \(nx 1\) 0x0+000. outer
+AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 6
+\[  6\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   2\) \(nx 1\) 0x0+000. test
+AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
+#pass
diff --git a/gas/testsuite/gas/coff/func1.s b/gas/testsuite/gas/coff/func1.s
new file mode 100644
index 00000000000..28300e709df
--- /dev/null
+++ b/gas/testsuite/gas/coff/func1.s
@@ -0,0 +1,22 @@
+	.file	"func1.c"
+	.text
+	.macro fcn, name
+	.def	\name
+	.scl	3		/* C_STAT */
+	.type	32		/* DT_FUNC */
+	.endef
+\name:
+	.endm
+
+	fcn inner
+	.nop
+
+	fcn outer
+	.nop
+	.nop
+
+	.global	test
+	fcn test
+	.nop
+	.nop
+	.nop
diff --git a/gas/testsuite/gas/coff/func2.d b/gas/testsuite/gas/coff/func2.d
new file mode 100644
index 00000000000..55a3a25c6e5
--- /dev/null
+++ b/gas/testsuite/gas/coff/func2.d
@@ -0,0 +1,16 @@
+#xfail: aarch64-*-*
+#objdump: -t
+#name: functions w/ C_EFCN
+
+.*:     file format .*
+
+SYMBOL TABLE:
+\[  0\]\(sec -2\)\(fl 0x00\)\(ty    0\)\(scl 103\) \(nx 1\) 0x0+0000 func2.c
+File *
+\[  2\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   3\) \(nx 1\) 0x0+0000 inner
+AUX tagndx 0 ttlsiz 0x[124] lnnos 0 next 4
+\[  4\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   3\) \(nx 1\) 0x0+000. outer
+AUX tagndx 0 ttlsiz 0x[248] lnnos 0 next 6
+\[  6\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   2\) \(nx 1\) 0x0+000. test
+AUX tagndx 0 ttlsiz 0x[36c] lnnos 0 next 0
+#pass
diff --git a/gas/testsuite/gas/coff/func2.s b/gas/testsuite/gas/coff/func2.s
new file mode 100644
index 00000000000..75f2069d919
--- /dev/null
+++ b/gas/testsuite/gas/coff/func2.s
@@ -0,0 +1,34 @@
+	.file	"func2.c"
+
+	.macro fcn, name
+	.def	\name
+	.scl	3		/* C_STAT */
+	.type	32		/* DT_FUNC */
+	.endef
+\name:
+	.endm
+
+	.macro efcn, name
+	.def	.\name
+	.scl	255		/* C_EFCN */
+	.val	.
+	.endef
+	.endm
+
+	.text
+
+	fcn inner
+	.nop
+	efcn inner
+
+	fcn outer
+	.nop
+	.nop
+	efcn outer
+
+	.global	test
+	fcn test
+	.nop
+	.nop
+	.nop
+	efcn test
diff --git a/gas/testsuite/gas/coff/func3.d b/gas/testsuite/gas/coff/func3.d
new file mode 100644
index 00000000000..06b37f81e4c
--- /dev/null
+++ b/gas/testsuite/gas/coff/func3.d
@@ -0,0 +1,16 @@
+#xfail: aarch64-*-*
+#objdump: -t
+#name: functions mixed C_EFCN
+
+.*:     file format .*
+
+SYMBOL TABLE:
+\[  0\]\(sec -2\)\(fl 0x00\)\(ty    0\)\(scl 103\) \(nx 1\) 0x0+0000 func3.c
+File *
+\[  2\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   3\) \(nx 1\) 0x0+0000 inner
+AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 4
+\[  4\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   3\) \(nx 1\) 0x0+000. outer
+AUX tagndx 0 ttlsiz 0x[248] lnnos 0 next 6
+\[  6\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   2\) \(nx 1\) 0x0+000. test
+AUX tagndx 0 ttlsiz 0x[36c] lnnos 0 next 0
+#pass
diff --git a/gas/testsuite/gas/coff/func3.s b/gas/testsuite/gas/coff/func3.s
new file mode 100644
index 00000000000..5d411712039
--- /dev/null
+++ b/gas/testsuite/gas/coff/func3.s
@@ -0,0 +1,33 @@
+	.file	"func3.c"
+
+	.macro fcn, name
+	.def	\name
+	.scl	3		/* C_STAT */
+	.type	32		/* DT_FUNC */
+	.endef
+\name:
+	.endm
+
+	.macro efcn, name
+	.def	.\name
+	.scl	255		/* C_EFCN */
+	.val	.
+	.endef
+	.endm
+
+	.text
+
+	fcn inner
+	.nop
+
+	fcn outer
+	.nop
+	.nop
+	efcn outer
+
+	.global	test
+	fcn test
+	.nop
+	.nop
+	.nop
+	efcn test
diff --git a/gas/testsuite/gas/coff/func4.d b/gas/testsuite/gas/coff/func4.d
new file mode 100644
index 00000000000..e7cd4445a7f
--- /dev/null
+++ b/gas/testsuite/gas/coff/func4.d
@@ -0,0 +1,18 @@
+#xfail: aarch64-*-*
+#objdump: -t
+#name: functions interleaved with data
+
+.*:     file format .*
+
+SYMBOL TABLE:
+\[  0\]\(sec -2\)\(fl 0x00\)\(ty    0\)\(scl 103\) \(nx 1\) 0x0+0000 func4.c
+File *
+\[  2\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   3\) \(nx 1\) 0x0+0000 inner
+AUX tagndx 0 ttlsiz 0x[124] lnnos 0 next 5
+\[  4\]\(sec  2\)\(fl 0x00\)\(ty    0\)\(scl   3\) \(nx 0\) 0x0+0000 item1
+\[  5\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   3\) \(nx 1\) 0x0+000. outer
+AUX tagndx 0 ttlsiz 0x[248] lnnos 0 next 8
+\[  7\]\(sec  2\)\(fl 0x00\)\(ty    0\)\(scl   3\) \(nx 0\) 0x0+000. item2
+\[  8\]\(sec  1\)\(fl 0x00\)\(ty   20\)\(scl   2\) \(nx 1\) 0x0+000. test
+AUX tagndx 0 ttlsiz 0x[36c] lnnos 0 next 0
+#pass
diff --git a/gas/testsuite/gas/coff/func4.s b/gas/testsuite/gas/coff/func4.s
new file mode 100644
index 00000000000..e9c75f4f15f
--- /dev/null
+++ b/gas/testsuite/gas/coff/func4.s
@@ -0,0 +1,41 @@
+	.file	"func4.c"
+
+	.macro fcn, name
+	.def	\name
+	.scl	3		/* C_STAT */
+	.type	32		/* DT_FUNC */
+	.endef
+\name:
+	.endm
+
+	.macro efcn, name
+	.def	.\name
+	.scl	255		/* C_EFCN */
+	.val	.
+	.endef
+	.endm
+
+	.text
+	fcn inner
+	.nop
+	efcn inner
+
+	.data
+item1:	.long -1
+
+	.text
+	fcn outer
+	.nop
+	.nop
+	efcn outer
+
+	.data
+item2:	.long -2
+
+	.text
+	.global	test
+	fcn test
+	.nop
+	.nop
+	.nop
+	efcn test


More information about the Binutils-cvs mailing list