Blame SOURCES/gdb-rhbz1218710-reverse-debugging-ppc-2of7.patch

01917d
  NOTE: The testcase part of this patch has been removed.
01917d
01917d
commit 5ce0145de764dc9c6e92daf2f843fa6e496c49d0
01917d
Author: Pedro Alves <palves@redhat.com>
01917d
Date:   Tue Dec 17 20:47:36 2013 +0000
01917d
01917d
    "tfind" across unavailable-stack frames.
01917d
    
01917d
    Like when stepping, the current stack frame location is expected to be
01917d
    printed as result of tfind command, if that results in moving to a
01917d
    different function.  In tfind_1 we see:
01917d
    
01917d
      if (from_tty
01917d
          && (has_stack_frames () || traceframe_number >= 0))
01917d
        {
01917d
          enum print_what print_what;
01917d
    
01917d
          /* NOTE: in imitation of the step command, try to determine
01917d
             whether we have made a transition from one function to
01917d
             another.  If so, we'll print the "stack frame" (ie. the new
01917d
             function and it's arguments) -- otherwise we'll just show the
01917d
             new source line.  */
01917d
    
01917d
          if (frame_id_eq (old_frame_id,
01917d
                           get_frame_id (get_current_frame ())))
01917d
            print_what = SRC_LINE;
01917d
          else
01917d
            print_what = SRC_AND_LOC;
01917d
    
01917d
          print_stack_frame (get_selected_frame (NULL), 1, print_what, 1);
01917d
          do_displays ();
01917d
        }
01917d
    
01917d
    However, when we haven't collected any registers in the tracepoint
01917d
    (collect $regs), that doesn't actually work:
01917d
    
01917d
     (gdb) tstart
01917d
     (gdb) info tracepoints
01917d
     Num     Type           Disp Enb Address    What
01917d
     1       tracepoint     keep y   0x080483b7 in func0
01917d
                                                at ../.././../git/gdb/testsuite/gdb.trace/circ.c:28
01917d
             collect testload
01917d
         installed on target
01917d
     2       tracepoint     keep y   0x080483bc in func1
01917d
                                                at ../.././../git/gdb/testsuite/gdb.trace/circ.c:32
01917d
             collect testload
01917d
         installed on target
01917d
     (gdb) c
01917d
     Continuing.
01917d
    
01917d
     Breakpoint 3, end () at ../.././../git/gdb/testsuite/gdb.trace/circ.c:72
01917d
     72    }
01917d
     (gdb) tstop
01917d
     (gdb) tfind start
01917d
     Found trace frame 0, tracepoint 1
01917d
     #0  func0 () at ../.././../git/gdb/testsuite/gdb.trace/circ.c:28
01917d
     28    }
01917d
     (gdb) tfind
01917d
     Found trace frame 1, tracepoint 2
01917d
     32    }
01917d
     (gdb)
01917d
    
01917d
    When we don't have info about the stack available
01917d
    (UNWIND_UNAVAILABLE), frames end up with outer_frame_id as frame ID.
01917d
    And in the scenario above, the issue is that both frames before and
01917d
    after the second tfind (the frames for func0 an func1) have the same
01917d
    id (outer_frame_id), so the frame_id_eq check returns false, even
01917d
    though the frames were of different functions.  GDB knows that,
01917d
    because the PC is inferred from the tracepoint's address, even if no
01917d
    registers were collected.
01917d
    
01917d
    To fix this, this patch adds support for frame ids with a valid code
01917d
    address, but <unavailable> stack address, and then makes the unwinders
01917d
    use that instead of the catch-all outer_frame_id for such frames.  The
01917d
    frame_id_eq check in tfind_1 then automatically does the right thing
01917d
    as expected.
01917d
    
01917d
    I tested with --directory=gdb.trace/ , before/after the patch, and
01917d
    compared the resulting gdb.logs, then adjusted the tests to expect the
01917d
    extra output that came out.  Turns out that was only circ.exp, the
01917d
    original test that actually brought this issue to light.
01917d
    
01917d
    Tested on x86_64 Fedora 17, native and gdbserver.
01917d
    
01917d
    gdb/
01917d
    2013-12-17  Pedro Alves  <palves@redhat.com>
01917d
    
01917d
    	* frame.h (enum frame_id_stack_status): New enum.
01917d
    	(struct frame_id) <stack_addr>: Adjust comment.
01917d
    	<stack_addr_p>: Delete field, replaced with ...
01917d
    	<stack_status>: ... this new field.
01917d
    	(frame_id_build_unavailable_stack): Declare.
01917d
    	* frame.c (frame_addr_hash, fprint_field, outer_frame_id)
01917d
    	(frame_id_build_special): Adjust.
01917d
    	(frame_id_build_unavailable_stack): New function.
01917d
    	(frame_id_build, frame_id_build_wild): Adjust.
01917d
    	(frame_id_p, frame_id_eq, frame_id_inner): Adjust to take into
01917d
    	account frames with unavailable stack.
01917d
    
01917d
    	* amd64-tdep.c (amd64_frame_this_id)
01917d
    	(amd64_sigtramp_frame_this_id, amd64_epilogue_frame_this_id): Use
01917d
    	frame_id_build_unavailable_stack.
01917d
    	* dwarf2-frame.c (dwarf2_frame_this_id): Likewise.
01917d
    	* i386-tdep.c (i386_frame_this_id, i386_epilogue_frame_this_id)
01917d
    	(i386_sigtramp_frame_this_id):  Likewise.
01917d
    
01917d
    gdb/testsuite/
01917d
    2013-12-17  Pedro Alves  <palves@redhat.com>
01917d
    
01917d
    	* gdb.trace/circ.exp: Expect frame info to be printed when
01917d
    	switching between frames with unavailable stack, but different
01917d
    	functions.
01917d
01917d
Index: gdb-7.6.1/gdb/amd64-tdep.c
01917d
===================================================================
01917d
--- gdb-7.6.1.orig/gdb/amd64-tdep.c
01917d
+++ gdb-7.6.1/gdb/amd64-tdep.c
01917d
@@ -2403,15 +2403,16 @@ amd64_frame_this_id (struct frame_info *
01917d
   struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
01917d
 
01917d
   if (!cache->base_p)
01917d
-    return;
01917d
-
01917d
-  /* This marks the outermost frame.  */
01917d
-  if (cache->base == 0)
01917d
-    return;
01917d
-
01917d
-  /* Detect OS dependent outermost frames; such as `clone'.  */
01917d
-  if (tdep->outermost_frame_p && tdep->outermost_frame_p (this_frame))
01917d
-    return;
01917d
+    (*this_id) = frame_id_build_unavailable_stack (cache->pc);
01917d
+  else if (cache->base == 0)
01917d
+    {
01917d
+      /* This marks the outermost frame.  */
01917d
+      return;
01917d
+    }
01917d
+  else
01917d
+    /* Detect OS dependent outermost frames; such as `clone'.  */
01917d
+    if (tdep->outermost_frame_p && tdep->outermost_frame_p (this_frame))
01917d
+      return;
01917d
 
01917d
   (*this_id) = frame_id_build (cache->base + 16, cache->pc);
01917d
 }
01917d
@@ -2528,9 +2529,14 @@ amd64_sigtramp_frame_this_id (struct fra
01917d
     amd64_sigtramp_frame_cache (this_frame, this_cache);
01917d
 
01917d
   if (!cache->base_p)
01917d
-    return;
01917d
-
01917d
-  (*this_id) = frame_id_build (cache->base + 16, get_frame_pc (this_frame));
01917d
+    (*this_id) = frame_id_build_unavailable_stack (get_frame_pc (this_frame));
01917d
+  else if (cache->base == 0)
01917d
+    {
01917d
+      /* This marks the outermost frame.  */
01917d
+      return;
01917d
+    }
01917d
+  else
01917d
+    (*this_id) = frame_id_build (cache->base + 16, get_frame_pc (this_frame));
01917d
 }
01917d
 
01917d
 static struct value *
01917d
@@ -2699,9 +2705,9 @@ amd64_epilogue_frame_this_id (struct fra
01917d
 							       this_cache);
01917d
 
01917d
   if (!cache->base_p)
01917d
-    return;
01917d
-
01917d
-  (*this_id) = frame_id_build (cache->base + 8, cache->pc);
01917d
+    (*this_id) = frame_id_build_unavailable_stack (cache->pc);
01917d
+  else
01917d
+    (*this_id) = frame_id_build (cache->base + 8, cache->pc);
01917d
 }
01917d
 
01917d
 static const struct frame_unwind amd64_epilogue_frame_unwind =
01917d
Index: gdb-7.6.1/gdb/dwarf2-frame.c
01917d
===================================================================
01917d
--- gdb-7.6.1.orig/gdb/dwarf2-frame.c
01917d
+++ gdb-7.6.1/gdb/dwarf2-frame.c
01917d
@@ -1265,12 +1265,11 @@ dwarf2_frame_this_id (struct frame_info
01917d
     dwarf2_frame_cache (this_frame, this_cache);
01917d
 
01917d
   if (cache->unavailable_retaddr)
01917d
+    (*this_id) = frame_id_build_unavailable_stack (get_frame_func (this_frame));
01917d
+  else if (cache->undefined_retaddr)
01917d
     return;
01917d
-
01917d
-  if (cache->undefined_retaddr)
01917d
-    return;
01917d
-
01917d
-  (*this_id) = frame_id_build (cache->cfa, get_frame_func (this_frame));
01917d
+  else
01917d
+    (*this_id) = frame_id_build (cache->cfa, get_frame_func (this_frame));
01917d
 }
01917d
 
01917d
 static struct value *
01917d
Index: gdb-7.6.1/gdb/frame.c
01917d
===================================================================
01917d
--- gdb-7.6.1.orig/gdb/frame.c
01917d
+++ gdb-7.6.1/gdb/frame.c
01917d
@@ -147,10 +147,11 @@ frame_addr_hash (const void *ap)
01917d
   const struct frame_id f_id = frame->this_id.value;
01917d
   hashval_t hash = 0;
01917d
 
01917d
-  gdb_assert (f_id.stack_addr_p || f_id.code_addr_p
01917d
+  gdb_assert (f_id.stack_status != FID_STACK_INVALID
01917d
+	      || f_id.code_addr_p
01917d
 	      || f_id.special_addr_p);
01917d
 
01917d
-  if (f_id.stack_addr_p)
01917d
+  if (f_id.stack_status == FID_STACK_VALID)
01917d
     hash = iterative_hash (&f_id.stack_addr,
01917d
 			   sizeof (f_id.stack_addr), hash);
01917d
   if (f_id.code_addr_p)
01917d
@@ -290,13 +291,23 @@ void
01917d
 fprint_frame_id (struct ui_file *file, struct frame_id id)
01917d
 {
01917d
   fprintf_unfiltered (file, "{");
01917d
-  fprint_field (file, "stack", id.stack_addr_p, id.stack_addr);
01917d
+
01917d
+  if (id.stack_status == FID_STACK_INVALID)
01917d
+    fprintf_unfiltered (file, "!stack");
01917d
+  else if (id.stack_status == FID_STACK_UNAVAILABLE)
01917d
+    fprintf_unfiltered (file, "stack=<unavailable>");
01917d
+  else
01917d
+    fprintf_unfiltered (file, "stack=%s", hex_string (id.stack_addr));
01917d
   fprintf_unfiltered (file, ",");
01917d
+
01917d
   fprint_field (file, "code", id.code_addr_p, id.code_addr);
01917d
   fprintf_unfiltered (file, ",");
01917d
+
01917d
   fprint_field (file, "special", id.special_addr_p, id.special_addr);
01917d
+
01917d
   if (id.artificial_depth)
01917d
     fprintf_unfiltered (file, ",artificial=%d", id.artificial_depth);
01917d
+
01917d
   fprintf_unfiltered (file, "}");
01917d
 }
01917d
 
01917d
@@ -446,7 +457,7 @@ frame_unwind_caller_id (struct frame_inf
01917d
 }
01917d
 
01917d
 const struct frame_id null_frame_id; /* All zeros.  */
01917d
-const struct frame_id outer_frame_id = { 0, 0, 0, 0, 0, 1, 0 };
01917d
+const struct frame_id outer_frame_id = { 0, 0, 0, FID_STACK_INVALID, 0, 1, 0 };
01917d
 
01917d
 struct frame_id
01917d
 frame_id_build_special (CORE_ADDR stack_addr, CORE_ADDR code_addr,
01917d
@@ -455,7 +466,7 @@ frame_id_build_special (CORE_ADDR stack_
01917d
   struct frame_id id = null_frame_id;
01917d
 
01917d
   id.stack_addr = stack_addr;
01917d
-  id.stack_addr_p = 1;
01917d
+  id.stack_status = FID_STACK_VALID;
01917d
   id.code_addr = code_addr;
01917d
   id.code_addr_p = 1;
01917d
   id.special_addr = special_addr;
01917d
@@ -463,13 +474,26 @@ frame_id_build_special (CORE_ADDR stack_
01917d
   return id;
01917d
 }
01917d
 
01917d
+/* See frame.h.  */
01917d
+
01917d
+struct frame_id
01917d
+frame_id_build_unavailable_stack (CORE_ADDR code_addr)
01917d
+{
01917d
+  struct frame_id id = null_frame_id;
01917d
+
01917d
+  id.stack_status = FID_STACK_UNAVAILABLE;
01917d
+  id.code_addr = code_addr;
01917d
+  id.code_addr_p = 1;
01917d
+  return id;
01917d
+}
01917d
+
01917d
 struct frame_id
01917d
 frame_id_build (CORE_ADDR stack_addr, CORE_ADDR code_addr)
01917d
 {
01917d
   struct frame_id id = null_frame_id;
01917d
 
01917d
   id.stack_addr = stack_addr;
01917d
-  id.stack_addr_p = 1;
01917d
+  id.stack_status = FID_STACK_VALID;
01917d
   id.code_addr = code_addr;
01917d
   id.code_addr_p = 1;
01917d
   return id;
01917d
@@ -481,7 +505,7 @@ frame_id_build_wild (CORE_ADDR stack_add
01917d
   struct frame_id id = null_frame_id;
01917d
 
01917d
   id.stack_addr = stack_addr;
01917d
-  id.stack_addr_p = 1;
01917d
+  id.stack_status = FID_STACK_VALID;
01917d
   return id;
01917d
 }
01917d
 
01917d
@@ -491,7 +515,7 @@ frame_id_p (struct frame_id l)
01917d
   int p;
01917d
 
01917d
   /* The frame is valid iff it has a valid stack address.  */
01917d
-  p = l.stack_addr_p;
01917d
+  p = l.stack_status != FID_STACK_INVALID;
01917d
   /* outer_frame_id is also valid.  */
01917d
   if (!p && memcmp (&l, &outer_frame_id, sizeof (l)) == 0)
01917d
     p = 1;
01917d
@@ -518,19 +542,20 @@ frame_id_eq (struct frame_id l, struct f
01917d
 {
01917d
   int eq;
01917d
 
01917d
-  if (!l.stack_addr_p && l.special_addr_p
01917d
-      && !r.stack_addr_p && r.special_addr_p)
01917d
+  if (l.stack_status == FID_STACK_INVALID && l.special_addr_p
01917d
+      && r.stack_status == FID_STACK_INVALID && r.special_addr_p)
01917d
     /* The outermost frame marker is equal to itself.  This is the
01917d
        dodgy thing about outer_frame_id, since between execution steps
01917d
        we might step into another function - from which we can't
01917d
        unwind either.  More thought required to get rid of
01917d
        outer_frame_id.  */
01917d
     eq = 1;
01917d
-  else if (!l.stack_addr_p || !r.stack_addr_p)
01917d
+  else if (l.stack_status == FID_STACK_INVALID
01917d
+	   || r.stack_status == FID_STACK_INVALID)
01917d
     /* Like a NaN, if either ID is invalid, the result is false.
01917d
        Note that a frame ID is invalid iff it is the null frame ID.  */
01917d
     eq = 0;
01917d
-  else if (l.stack_addr != r.stack_addr)
01917d
+  else if (l.stack_status != r.stack_status || l.stack_addr != r.stack_addr)
01917d
     /* If .stack addresses are different, the frames are different.  */
01917d
     eq = 0;
01917d
   else if (l.code_addr_p && r.code_addr_p && l.code_addr != r.code_addr)
01917d
@@ -597,8 +622,9 @@ frame_id_inner (struct gdbarch *gdbarch,
01917d
 {
01917d
   int inner;
01917d
 
01917d
-  if (!l.stack_addr_p || !r.stack_addr_p)
01917d
-    /* Like NaN, any operation involving an invalid ID always fails.  */
01917d
+  if (l.stack_status != FID_STACK_VALID || r.stack_status != FID_STACK_VALID)
01917d
+    /* Like NaN, any operation involving an invalid ID always fails.
01917d
+       Likewise if either ID has an unavailable stack address.  */
01917d
     inner = 0;
01917d
   else if (l.artificial_depth > r.artificial_depth
01917d
 	   && l.stack_addr == r.stack_addr
01917d
Index: gdb-7.6.1/gdb/frame.h
01917d
===================================================================
01917d
--- gdb-7.6.1.orig/gdb/frame.h
01917d
+++ gdb-7.6.1/gdb/frame.h
01917d
@@ -76,6 +76,23 @@ struct block;
01917d
 struct gdbarch;
01917d
 struct ui_file;
01917d
 
01917d
+/* Status of a given frame's stack.  */
01917d
+
01917d
+enum frame_id_stack_status
01917d
+{
01917d
+  /* Stack address is invalid.  E.g., this frame is the outermost
01917d
+     (i.e., _start), and the stack hasn't been setup yet.  */
01917d
+  FID_STACK_INVALID = 0,
01917d
+
01917d
+  /* Stack address is valid, and is found in the stack_addr field.  */
01917d
+  FID_STACK_VALID = 1,
01917d
+
01917d
+  /* Stack address is unavailable.  I.e., there's a valid stack, but
01917d
+     we don't know where it is (because memory or registers we'd
01917d
+     compute it from were not collected).  */
01917d
+  FID_STACK_UNAVAILABLE = -1
01917d
+};
01917d
+
01917d
 /* The frame object.  */
01917d
 
01917d
 struct frame_info;
01917d
@@ -97,8 +114,9 @@ struct frame_id
01917d
      function pointer register or stack pointer register.  They are
01917d
      wrong.
01917d
 
01917d
-     This field is valid only if stack_addr_p is true.  Otherwise, this
01917d
-     frame represents the null frame.  */
01917d
+     This field is valid only if frame_id.stack_status is
01917d
+     FID_STACK_VALID.  It will be 0 for other
01917d
+     FID_STACK_... statuses.  */
01917d
   CORE_ADDR stack_addr;
01917d
 
01917d
   /* The frame's code address.  This shall be constant through out the
01917d
@@ -129,7 +147,7 @@ struct frame_id
01917d
   CORE_ADDR special_addr;
01917d
 
01917d
   /* Flags to indicate the above fields have valid contents.  */
01917d
-  unsigned int stack_addr_p : 1;
01917d
+  ENUM_BITFIELD(frame_id_stack_status) stack_status : 2;
01917d
   unsigned int code_addr_p : 1;
01917d
   unsigned int special_addr_p : 1;
01917d
 
01917d
@@ -169,6 +187,12 @@ extern struct frame_id frame_id_build_sp
01917d
 					       CORE_ADDR code_addr,
01917d
 					       CORE_ADDR special_addr);
01917d
 
01917d
+/* Construct a frame ID representing a frame where the stack address
01917d
+   exists, but is unavailable.  CODE_ADDR is the frame's constant code
01917d
+   address (typically the entry point).  The special identifier
01917d
+   address is set to indicate a wild card.  */
01917d
+extern struct frame_id frame_id_build_unavailable_stack (CORE_ADDR code_addr);
01917d
+
01917d
 /* Construct a wild card frame ID.  The parameter is the frame's constant
01917d
    stack address (typically the outer-bound).  The code address as well
01917d
    as the special identifier address are set to indicate wild cards.  */
01917d
Index: gdb-7.6.1/gdb/i386-tdep.c
01917d
===================================================================
01917d
--- gdb-7.6.1.orig/gdb/i386-tdep.c
01917d
+++ gdb-7.6.1/gdb/i386-tdep.c
01917d
@@ -1846,12 +1846,17 @@ i386_frame_this_id (struct frame_info *t
01917d
 {
01917d
   struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache);
01917d
 
01917d
-  /* This marks the outermost frame.  */
01917d
-  if (cache->base == 0)
01917d
-    return;
01917d
-
01917d
-  /* See the end of i386_push_dummy_call.  */
01917d
-  (*this_id) = frame_id_build (cache->base + 8, cache->pc);
01917d
+  if (!cache->base_p)
01917d
+    (*this_id) = frame_id_build_unavailable_stack (cache->pc);
01917d
+  else if (cache->base == 0)
01917d
+    {
01917d
+      /* This marks the outermost frame.  */
01917d
+    }
01917d
+  else
01917d
+    {
01917d
+      /* See the end of i386_push_dummy_call.  */
01917d
+      (*this_id) = frame_id_build (cache->base + 8, cache->pc);
01917d
+    }
01917d
 }
01917d
 
01917d
 static enum unwind_stop_reason
01917d
@@ -2032,9 +2037,9 @@ i386_epilogue_frame_this_id (struct fram
01917d
     i386_epilogue_frame_cache (this_frame, this_cache);
01917d
 
01917d
   if (!cache->base_p)
01917d
-    return;
01917d
-
01917d
-  (*this_id) = frame_id_build (cache->base + 8, cache->pc);
01917d
+    (*this_id) = frame_id_build_unavailable_stack (cache->pc);
01917d
+  else
01917d
+    (*this_id) = frame_id_build (cache->base + 8, cache->pc);
01917d
 }
01917d
 
01917d
 static struct value *
01917d
@@ -2226,10 +2231,12 @@ i386_sigtramp_frame_this_id (struct fram
01917d
     i386_sigtramp_frame_cache (this_frame, this_cache);
01917d
 
01917d
   if (!cache->base_p)
01917d
-    return;
01917d
-
01917d
-  /* See the end of i386_push_dummy_call.  */
01917d
-  (*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame));
01917d
+    (*this_id) = frame_id_build_unavailable_stack (get_frame_pc (this_frame));
01917d
+  else
01917d
+    {
01917d
+      /* See the end of i386_push_dummy_call.  */
01917d
+      (*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame));
01917d
+    }
01917d
 }
01917d
 
01917d
 static struct value *