[PATCH 3/4] COFF: function auxiliary symbols

Jan Beulich jbeulich@suse.com
Fri Apr 25 13:00:43 GMT 2025


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.
---
The condition around the first SA_SET_SYM_ENDNDX() is now getting yet
more questionable: Why would the current symbol being a function matter?
Or the symbol being non-external? The concept behind BSF_NOT_AT_END also
continues to escape me.

I fear that with the little bit of XCOFF testing that there is in the
PPC testsuite, there's still a fair risk of me overlooking some crucial
aspect here.

--- a/gas/config/obj-coff.c
+++ b/gas/config/obj-coff.c
@@ -1187,7 +1187,6 @@ coff_assign_symbol (symbolS *symp ATTRIB
 #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 *pu
 		}
 	    }
 
-	  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 *pu
 	  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 *pu
       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
--- 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)
--- 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;
 	}
     }
 
--- 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
+}
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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 mailing list