This is the mail archive of the gdb-patches@sourceware.org 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]

[PATCH] Improve detection of end-of-prologue with no debug info on ppc


This patch improves the accuracy of skip_prologue, which is used to skip the prologue of a function if no debug info is provided. The problem is with code like this:

10000478 <f>:
void f(int a, int b, int c, int d, int e, int f, int g, int h)
{
10000478:       94 21 ff c0     stwu    r1,-64(r1)
1000047c:       93 e1 00 3c     stw     r31,60(r1)
10000480:       7c 3f 0b 78     mr      r31,r1
10000484:       90 7f 00 18     stw     r3,24(r31)
10000488:       90 9f 00 1c     stw     r4,28(r31)
1000048c:       90 bf 00 20     stw     r5,32(r31)
10000490:       90 df 00 24     stw     r6,36(r31)
10000494:       90 ff 00 28     stw     r7,40(r31)
10000498:       91 1f 00 2c     stw     r8,44(r31)
1000049c:       91 3f 00 30     stw     r9,48(r31)
100004a0:       91 5f 00 34     stw     r10,52(r31)
   int x = 1;
100004a4:       39 20 00 01     li      r9,1
100004a8:       91 3f 00 08     stw     r9,8(r31)
}
100004ac:       39 7f 00 40     addi    r11,r31,64
100004b0:       83 eb ff fc     lwz     r31,-4(r11)
100004b4:       7d 61 5b 78     mr      r1,r11
100004b8:       4e 80 00 20     blr

'break f' sets the breakpoint at 0x100004ac because skip_prologue recognises the 'stw r9,9(r31)' as a prologue instruction that saves a register containing an incoming argument on the frame stack, when in fact it is actually writing back a local variable.

This patch improves on this by noting that the prologue will not save the same argument register twice. store_param_on_stack_p is modified to keep track of the registers that have been saved on the stack frame so far, and will return 0 if an instruction that saves an already saved register is given. In doing this I have tidied up the code by regrouping the checks so that all the integer and floating-point stores are grouped together.

I also noticed and fixed what appear to be some bugs here. According to the System V ABI and EABI, f1 is also used during parameter passing, in addition to f2-f8 which are currently accounted for. Also, the code that checked for saves of r3-r10 also checked 'stfd' using the range for integer registers (i.e. f3-f10 instead of f1-f8).

Is this code also called for PPC64? If so, the 64-bit ABI states that f1-f13 are used for parameter passing, and the range will need to be modified accordingly.

Kwok

gdb/ChangeLog:

	gdb/
	* rs6000-tdep.c (store_param_on_stack_p): Track register assigned
	to r0.  Track saved registers.  Return false if a register has
	already been saved.  Fix range used for parameters passed in
	floating-point registers.
	(skip_prologue): Add variables used to keep track of saved
	registers and pass to store_param_on_stack_p.
diff -rup src.old/gdb/rs6000-tdep.c src/gdb/rs6000-tdep.c
--- src.old/gdb/rs6000-tdep.c	2013-05-15 15:31:07.732018965 +0100
+++ src/gdb/rs6000-tdep.c	2013-05-15 17:33:17.379026892 +0100
@@ -1177,10 +1177,14 @@ static int max_skip_non_prologue_insns =
 /* Return nonzero if the given instruction OP can be part of the prologue
    of a function and saves a parameter on the stack.  FRAMEP should be
    set if one of the previous instructions in the function has set the
-   Frame Pointer.  */
+   Frame Pointer.  If the parameter has already been saved on the stack by
+   a previous prologue instruction, then OP is not considered to be part
+   of the prologue.  */
 
 static int
-store_param_on_stack_p (unsigned long op, int framep, int *r0_contains_arg)
+store_param_on_stack_p (unsigned long op, int framep, int *r0_contains_arg,
+                        unsigned int *saved_gp_params,
+                        unsigned int *saved_fp_params)
 {
   /* Move parameters from argument registers to temporary register.  */
   if ((op & 0xfc0007fe) == 0x7c000378)         /* mr(.)  Rx,Ry */
@@ -1192,7 +1196,7 @@ store_param_on_stack_p (unsigned long op
 
       if (rx_regno == 0 && ry_regno >= 3 && ry_regno <= 10)
         {
-          *r0_contains_arg = 1;
+          *r0_contains_arg = ry_regno;
           return 1;
         }
       else
@@ -1200,45 +1204,45 @@ store_param_on_stack_p (unsigned long op
     }
 
   /* Save a General Purpose Register on stack.  */
+  if ((op & 0xfc1f0003) == 0xf8010000 ||                /* std Rx,NUM(r1) */
+      (framep && (op & 0xfc1f0000) == 0x901f0000) ||    /* stw Rx,NUM(r31) */
+      (framep && (op & 0xfc1f0000) == 0x981f0000))      /* stb Rx,NUM(r31) */
 
-  if ((op & 0xfc1f0003) == 0xf8010000 ||       /* std  Rx,NUM(r1) */
-      (op & 0xfc1f0000) == 0xd8010000)         /* stfd Rx,NUM(r1) */
-    {
-      /* Rx: Only r3 - r10 are used for parameter passing.  */
-      const int rx_regno = GET_SRC_REG (op);
-
-      return (rx_regno >= 3 && rx_regno <= 10);
-    }
-           
-  /* Save a General Purpose Register on stack via the Frame Pointer.  */
-
-  if (framep &&
-      ((op & 0xfc1f0000) == 0x901f0000 ||     /* st rx,NUM(r31) */
-       (op & 0xfc1f0000) == 0x981f0000 ||     /* stb Rx,NUM(r31) */
-       (op & 0xfc1f0000) == 0xd81f0000))      /* stfd Rx,NUM(r31) */
     {
       /* Rx: Usually, only r3 - r10 are used for parameter passing.
          However, the compiler sometimes uses r0 to hold an argument.  */
-      const int rx_regno = GET_SRC_REG (op);
+      int rx_regno = GET_SRC_REG (op);
 
-      return ((rx_regno >= 3 && rx_regno <= 10)
-              || (rx_regno == 0 && *r0_contains_arg));
-    }
+      if (rx_regno == 0 && *r0_contains_arg)
+        rx_regno = *r0_contains_arg;
 
-  if ((op & 0xfc1f0000) == 0xfc010000)         /* frsp, fp?,NUM(r1) */
-    {
-      /* Only f2 - f8 are used for parameter passing.  */
-      const int src_regno = GET_SRC_REG (op);
-
-      return (src_regno >= 2 && src_regno <= 8);
+      if (rx_regno >= 3 && rx_regno <= 10 &&
+          !(*saved_gp_params & (1 << rx_regno)))
+        {
+          *saved_gp_params |= 1 << rx_regno;
+          return 1;
+        }
+      else
+        return 0;
     }
 
-  if (framep && ((op & 0xfc1f0000) == 0xfc1f0000))  /* frsp, fp?,NUM(r31) */
+  /* Save a Floating Point Register on stack.  */
+  if ((op & 0xfc1f0000) == 0xd8010000 ||              /* stfd Fx,NUM(r1) */
+      (op & 0xfc1f0000) == 0xfc010000 ||              /* frsp Fx,NUM(r1) */
+      (framep && (op & 0xfc1f0000) == 0xd81f0000) ||  /* stfd Fx,NUM(r31) */
+      (framep && (op & 0xfc1f0000) == 0xfc1f0000))    /* frsp Fx,NUM(r31) */
     {
-      /* Only f2 - f8 are used for parameter passing.  */
+      /* Only f1 - f8 are used for parameter passing.  */
       const int src_regno = GET_SRC_REG (op);
 
-      return (src_regno >= 2 && src_regno <= 8);
+      if (src_regno >= 1 && src_regno <= 8 &&
+          !(*saved_fp_params & (1 << src_regno)))
+        {
+          *saved_fp_params |= 1 << src_regno;
+          return 1;
+        }
+      else
+        return 0;
     }
 
   /* Not an insn that saves a parameter on stack.  */
@@ -1513,6 +1517,8 @@ skip_prologue (struct gdbarch *gdbarch,
   int prev_insn_was_prologue_insn = 1;
   int num_skip_non_prologue_insns = 0;
   int r0_contains_arg = 0;
+  unsigned int saved_gp_params = 0;
+  unsigned int saved_fp_params = 0;
   const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
@@ -1820,7 +1826,9 @@ skip_prologue (struct gdbarch *gdbarch,
 	  /* store parameters in stack */
 	}
       /* Move parameters from argument registers to temporary register.  */
-      else if (store_param_on_stack_p (op, framep, &r0_contains_arg))
+      else if (store_param_on_stack_p (op, framep, &r0_contains_arg,
+                                       &saved_gp_params,
+                                       &saved_fp_params))
         {
 	  continue;
 

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