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]

[PATCH] rs6000-tdep.c: Improve prologue analysis for PowerPC targets


I've just committed the patch below.

It fixes the following failures on powerpc-unknown-linux-gnu:

FAIL: gdb.base/recurse.exp: continue to recurse (a = 8)
FAIL: gdb.base/recurse.exp: continue to recurse (a = 7)
FAIL: gdb.base/recurse.exp: continue to recurse (a = 6)
FAIL: gdb.base/recurse.exp: continue to recurse (a = 5)
FAIL: gdb.base/recurse.exp: continue to second instance watchpoint, first time
FAIL: gdb.base/recurse.exp: continue to recurse (a = 4)
FAIL: gdb.base/recurse.exp: continue to recurse (a = 3)
FAIL: gdb.base/recurse.exp: continue to recurse (a = 2)
FAIL: gdb.base/recurse.exp: continue to recurse (a = 1)
FAIL: gdb.base/recurse.exp: continue to second instance watchpoint, second time

The above FAILs were related to the testing of watchpoints.  Since we
have not yet implemented hardware watchpoints for the PowerPC target,
gdb is forced to check to see if a particular watchpoint has changed
at every instruction.  (Yes, this is very slow, since we're reduced
to single-stepping the program.)

When single-stepping through a function's prologue, there are times
at which a full prologue analysis leads the rest of gdb astray.  E.g,
consider the location at which the return address is saved.  On the
PowerPC, the return address is available in the link register (lr) at
function entry.  The prologue is responsible for saving this value
on the stack.  So, if we're stopped at a point very early in the
prologue, before the link register has been saved, it is more accurate
for the prologue analysis to not indicate that the return address
exists in memory (i.e, on the stack).

The patch below merely adds a "limit" parameter to skip_prologue()
which will cause the prologue analysis to terminate early if the PC
for the frame in question is somewhere within the prologue. 
Basically, it'll scan up to the limit, but no further.  We allow the
special case where the limit is 0 to cause the prologue analysis to be
performed in its entirety.  This is used only in
rs6000_skip_prologue() which is called e.g, when setting a breakpoint
on a function to find out where the prologue ends.

I'm still seeing three recurse.exp FAILs:

FAIL: gdb.base/recurse.exp: second instance watchpoint deleted when leaving scope
FAIL: gdb.base/recurse.exp: continue to first instance watchpoint, second time
FAIL: gdb.base/recurse.exp: first instance watchpoint deleted when leaving scope

I believe these are due to the fact that there comes a point in which
execution of an epilogue instruction is causing gdb to become confused
in much the same way that it was previously confused in the prologue.
I haven't decided what to do about these.  (I don't think it's worth
it to add an epilogue analysis.)

Anyway, in addition to fixing the above FAILs, it also now causes
backtraces in the prologue to print much more sanely.  For example:

Before:
  (gdb) si
  0x100003e8 in recurse (a=10)
      at /ocotillo1/kev/sourceware/src/gdb/testsuite/gdb.base/recurse.c:12
  12      {
  1: x/i $pc  0x100003e8 <recurse+4>:     mflr    r0
  (gdb) bt
  #0  0x100003e8 in recurse (a=10)
      at /ocotillo1/kev/sourceware/src/gdb/testsuite/gdb.base/recurse.c:12
  #1  0x7ffffcd4 in ?? ()

After:
  (gdb) si
  0x100003e8 in recurse (a=2147482844)
      at /ocotillo1/kev/sourceware/src/gdb/testsuite/gdb.base/recurse.c:12
  12      {
  1: x/i $pc  0x100003e8 <recurse+4>:     mflr    r0
  (gdb) bt
  #0  0x100003e8 in recurse (a=2147482844)
      at /ocotillo1/kev/sourceware/src/gdb/testsuite/gdb.base/recurse.c:12
  #1  0x10000434 in recurse (a=10)
      at /ocotillo1/kev/sourceware/src/gdb/testsuite/gdb.base/recurse.c:19
  #2  0x10000488 in main ()
      at /ocotillo1/kev/sourceware/src/gdb/testsuite/gdb.base/recurse.c:29
  #3  0xfebe69c in __libc_start_main (argc=1, argv=0x7ffffcd4, envp=0x7ffffcdc, 
      auxvec=0x7ffffd30, rtld_fini=0x9, stinfo=0x10000568, stack_on_entry=0x0)
      at ../sysdeps/powerpc/elf/libc-start.c:106

Here's the patch...

	* rs6000-tdep.c (skip_prologue): Add new parameter lim_pc.
	Update all callers.

Index: rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.13
diff -u -p -r1.13 rs6000-tdep.c
--- rs6000-tdep.c	2000/09/24 09:58:16	1.13
+++ rs6000-tdep.c	2000/10/05 00:45:11
@@ -118,7 +118,8 @@ void (*rs6000_set_host_arch_hook) (int) 
 
 static CORE_ADDR branch_dest (int opcode, int instr, CORE_ADDR pc,
 			      CORE_ADDR safety);
-static CORE_ADDR skip_prologue (CORE_ADDR, struct rs6000_framedata *);
+static CORE_ADDR skip_prologue (CORE_ADDR, CORE_ADDR,
+                                struct rs6000_framedata *);
 static void frame_get_saved_regs (struct frame_info * fi,
 				  struct rs6000_framedata * fdatap);
 static CORE_ADDR frame_initial_stack_address (struct frame_info *);
@@ -135,7 +136,7 @@ static CORE_ADDR
 rs6000_skip_prologue (CORE_ADDR pc)
 {
   struct rs6000_framedata frame;
-  pc = skip_prologue (pc, &frame);
+  pc = skip_prologue (pc, 0, &frame);
   return pc;
 }
 
@@ -381,7 +382,7 @@ rs6000_software_single_step (unsigned in
 #define GET_SRC_REG(x) (((x) >> 21) & 0x1f)
 
 static CORE_ADDR
-skip_prologue (CORE_ADDR pc, struct rs6000_framedata *fdata)
+skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
 {
   CORE_ADDR orig_pc = pc;
   CORE_ADDR last_prologue_pc;
@@ -403,7 +404,7 @@ skip_prologue (CORE_ADDR pc, struct rs60
   fdata->nosavedpc = 1;
 
   pc -= 4;
-  for (;;)
+  while (lim_pc == 0 || pc < lim_pc - 4)
     {
       pc += 4;
 
@@ -700,7 +701,7 @@ rs6000_pop_frame (void)
      saved %pc value in the previous frame. */
 
   addr = get_pc_function_start (frame->pc);
-  (void) skip_prologue (addr, &fdata);
+  (void) skip_prologue (addr, frame->pc, &fdata);
 
   wordsize = TDEP->wordsize;
   if (fdata.frameless)
@@ -1106,7 +1107,7 @@ rs6000_frameless_function_invocation (st
 	return 0;
     }
 
-  (void) skip_prologue (func_start, &fdata);
+  (void) skip_prologue (func_start, fi->pc, &fdata);
   return fdata.frameless;
 }
 
@@ -1132,7 +1133,7 @@ rs6000_frame_saved_pc (struct frame_info
   if (!func_start)
     return 0;
 
-  (void) skip_prologue (func_start, &fdata);
+  (void) skip_prologue (func_start, fi->pc, &fdata);
 
   if (fdata.lr_offset == 0 && fi->next != NULL)
     {
@@ -1167,7 +1168,7 @@ frame_get_saved_regs (struct frame_info 
   if (fdatap == NULL)
     {
       fdatap = &work_fdata;
-      (void) skip_prologue (get_pc_function_start (fi->pc), fdatap);
+      (void) skip_prologue (get_pc_function_start (fi->pc), fi->pc, fdatap);
     }
 
   frame_saved_regs_zalloc (fi);
@@ -1243,7 +1244,7 @@ frame_initial_stack_address (struct fram
 
   /* find out if this function is using an alloca register.. */
 
-  (void) skip_prologue (get_pc_function_start (fi->pc), &fdata);
+  (void) skip_prologue (get_pc_function_start (fi->pc), fi->pc, &fdata);
 
   /* if saved registers of this frame are not known yet, read and cache them. */
 


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