This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix push_arguments on x86-64


I've looked into fixing this failure:
FAIL: gdb.base/varargs.exp: print find_max_double(5,1.0,17.0,2.0,3.0,4.0)

I did a code inspection of x86_64_push_arguments and noted a number of
problems in the way we handle arguments and fixed them with the
appended patch.  I'm now setting %rax always to the number of SSE
registers.  This is only needed for functions taking variable argument
lists but does not hurt in other cases, so it's a safe thing to do.

I was surprised to see that these testcase now do not fail anymore:

FAIL: gdb.base/interrupt.exp: call function when asleep (stays asleep)
FAIL: gdb.base/interrupt.exp: call function after waking it
FAIL: gdb.base/interrupt.exp: continue
FAIL: gdb.base/interrupt.exp: send end of file
FAIL: gdb.base/signals.exp: p func1 () #1 in signals.exp
FAIL: gdb.gdb/complaints.exp: serial start
FAIL: gdb.gdb/complaints.exp: short start

With this patch and the previous one for returning/float double, the
testsuite is down to:
# of expected passes            8971
# of unexpected failures        86
# of unexpected successes       4
# of expected failures          46
# of known failures             23
# of unresolved testcases       3
# of untested testcases         6
# of unsupported tests          1
/usr/src/aj/build/gdb/gdb/testsuite/../../gdb/gdb version  2003-06-26-cvs -nx

(from 93-96 unexpected failures depending whether
gdb.threads/linux-dp.exp failed or not)

Ok to commit to both mainline and 6.0 branch?

Andreas

2003-06-26  Andreas Jaeger  <aj@suse.de>

	* x86-64-tdep.c (x86_64_push_arguments): Always set %rax to number
	of SSE registers so that varargs functions work.
	Rework handling of passing arguments on the stack.

Index: x86-64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v
retrieving revision 1.79
diff -u -p -r1.79 x86-64-tdep.c
--- x86-64-tdep.c	15 Jun 2003 11:01:46 -0000	1.79
+++ x86-64-tdep.c	26 Jun 2003 06:21:39 -0000
@@ -597,7 +597,15 @@ x86_64_push_arguments (struct regcache *
 {
   int intreg = 0;
   int ssereg = 0;
+  /* For varargs functions we have to pass the total number of SSE arguments
+     in %rax.  So, let's count this number.  */
+  int total_sse_args = 0;
+  /* Once an SSE/int argument is passed on the stack, all subsequent
+     arguments are passed there.  */
+  int sse_stack = 0;
+  int int_stack = 0;
   int i;
+  char buf[8];
   static int int_parameter_registers[INT_REGS] =
   {
     X86_64_RDI_REGNUM, 4,	/* %rdi, %rsi */
@@ -623,9 +631,7 @@ x86_64_push_arguments (struct regcache *
       int needed_sseregs;
 
       if (!n ||
-	  !examine_argument (class, n, &needed_intregs, &needed_sseregs)
-	  || intreg / 2 + needed_intregs > INT_REGS
-	  || ssereg / 2 + needed_sseregs > SSE_REGS)
+	  !examine_argument (class, n, &needed_intregs, &needed_sseregs))
 	{			/* memory class */
 	  stack_values[stack_values_count++] = i;
 	}
@@ -633,6 +639,13 @@ x86_64_push_arguments (struct regcache *
 	{
 	  int j;
 	  int offset = 0;
+
+	  if (intreg / 2 + needed_intregs > INT_REGS)
+	    int_stack = 1;
+	  if (ssereg / 2 + needed_sseregs > SSE_REGS)
+	    sse_stack = 1;
+	  total_sse_args += needed_sseregs;
+
 	  for (j = 0; j < n; j++)
 	    {
 	      switch (class[j])
@@ -640,38 +653,56 @@ x86_64_push_arguments (struct regcache *
 		case X86_64_NO_CLASS:
 		  break;
 		case X86_64_INTEGER_CLASS:
-		  regcache_cooked_write
-		    (regcache, int_parameter_registers[(intreg + 1) / 2],
-		     VALUE_CONTENTS_ALL (args[i]) + offset);
-		  offset += 8;
-		  intreg += 2;
+		  if (int_stack)
+		    stack_values[stack_values_count++] = i;
+		  else
+		    {
+		      regcache_cooked_write
+			(regcache, int_parameter_registers[(intreg + 1) / 2],
+			 VALUE_CONTENTS_ALL (args[i]) + offset);
+		      offset += 8;
+		      intreg += 2;
+		    }
 		  break;
 		case X86_64_INTEGERSI_CLASS:
-		  {
-		    LONGEST val = extract_signed_integer
-		      (VALUE_CONTENTS_ALL (args[i]) + offset, 4);
-		    regcache_cooked_write_signed
-		      (regcache, int_parameter_registers[intreg / 2], val);
-
-		    offset += 8;
-		    intreg++;
-		    break;
-		  }
+		  if (int_stack)
+		    stack_values[stack_values_count++] = i;
+		  else
+		    {
+		      LONGEST val = extract_signed_integer
+			(VALUE_CONTENTS_ALL (args[i]) + offset, 4);
+		      regcache_cooked_write_signed
+			(regcache, int_parameter_registers[intreg / 2], val);
+		      
+		      offset += 8;
+		      intreg++;
+		    }
+		  break;
 		case X86_64_SSEDF_CLASS:
 		case X86_64_SSESF_CLASS:
 		case X86_64_SSE_CLASS:
-		  regcache_cooked_write
-		    (regcache, sse_parameter_registers[(ssereg + 1) / 2],
-		     VALUE_CONTENTS_ALL (args[i]) + offset);
-		  offset += 8;
-		  ssereg += 2;
+		  if (sse_stack)
+		    stack_values[stack_values_count++] = i;
+		  else
+		    {
+		      regcache_cooked_write
+			(regcache, sse_parameter_registers[(ssereg + 1) / 2],
+			 VALUE_CONTENTS_ALL (args[i]) + offset);
+		      offset += 8;
+		      ssereg += 2;
+		    }
 		  break;
 		case X86_64_SSEUP_CLASS:
-		  regcache_cooked_write
-		    (regcache, sse_parameter_registers[ssereg / 2],
-		     VALUE_CONTENTS_ALL (args[i]) + offset);
-		  offset += 8;
-		  ssereg++;
+		  if (sse_stack)
+		    stack_values[stack_values_count++] = i;
+		  else
+		    {
+		      regcache_cooked_write
+			(regcache, sse_parameter_registers[ssereg / 2],
+			 VALUE_CONTENTS_ALL (args[i]) + offset);
+		      offset += 8;
+		      ssereg++;
+		    }
 		  break;
 		case X86_64_X87_CLASS:
 		case X86_64_MEMORY_CLASS:
@@ -699,6 +730,11 @@ x86_64_push_arguments (struct regcache *
       sp -= (len + 7) & ~7;
       write_memory (sp, VALUE_CONTENTS_ALL (arg), len);
     }
+
+  /* Write number of SSE type arguments to RAX to take care of varargs
+     functions.  */
+  store_unsigned_integer (buf, 8, total_sse_args);
+  regcache_cooked_write (regcache, X86_64_RAX_REGNUM, buf);
 
   return sp;
 }

-- 
 Andreas Jaeger, SuSE Linux AG, aj@suse.de, http://www.suse.de/~aj
  GPG fingerprint = 93A3 365E CE47 B889 DF7F  FED1 389A 563C C272 A126

Attachment: pgp00000.pgp
Description: PGP signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]