* frame.h (frame_unwind_arch): New.
authorUlrich Weigand <uweigand@de.ibm.com>
Thu, 2 Jul 2009 17:09:28 +0000 (17:09 +0000)
committerUlrich Weigand <uweigand@de.ibm.com>
Thu, 2 Jul 2009 17:09:28 +0000 (17:09 +0000)
(frame_unwind_caller_arch): Likewise.
* frame-unwind.h (frame_prev_arch_ftype): New type.
(struct frame_unwind): New member prev_arch.
* frame.c (struct frame_info): New member prev_arch.
(frame_unwind_arch): New function.
(frame_unwind_caller_arch): Likewise..
(get_frame_arch): Reimplement in terms of frame_unwind_arch.
* sentinel-frame.c (sentinel_frame_prev_arch): New function.
(sentinel_frame_unwinder): Install it.

* frame.c (frame_pc_unwind): Use frame_unwind_arch instead
of get_frame_arch.
(frame_unwind_register_value): Likewise.
(frame_unwind_register_signed): Likewise.
(frame_unwind_register_unsigned): Likewise.
* frame-unwind.c (frame_unwind_got_optimized): Likewise.
(frame_unwind_got_register): Likewise.
(frame_unwind_got_constant): Likewise.
(frame_unwind_got_bytes): Likewise.
(frame_unwind_got_address): Likewise.

* frame.h (enum frame_type): New value ARCH_FRAME.
* frame.c (fprint_frame_type): Handle ARCH_FRAME.
* stack.c (print_frame_info): Likewise.

gdb/ChangeLog
gdb/frame-unwind.c
gdb/frame-unwind.h
gdb/frame.c
gdb/frame.h
gdb/sentinel-frame.c
gdb/stack.c

index 3a1936975decde0746271bb57cca00079ac71003..496fb24bf71998ac962c9ba1e30401034ac5e890 100644 (file)
@@ -1,3 +1,31 @@
+2009-07-02  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * frame.h (frame_unwind_arch): New.
+       (frame_unwind_caller_arch): Likewise.
+       * frame-unwind.h (frame_prev_arch_ftype): New type.
+       (struct frame_unwind): New member prev_arch.
+       * frame.c (struct frame_info): New member prev_arch.
+       (frame_unwind_arch): New function.
+       (frame_unwind_caller_arch): Likewise..
+       (get_frame_arch): Reimplement in terms of frame_unwind_arch.
+       * sentinel-frame.c (sentinel_frame_prev_arch): New function.
+       (sentinel_frame_unwinder): Install it.
+
+       * frame.c (frame_pc_unwind): Use frame_unwind_arch instead
+       of get_frame_arch.
+       (frame_unwind_register_value): Likewise.
+       (frame_unwind_register_signed): Likewise.
+       (frame_unwind_register_unsigned): Likewise.
+       * frame-unwind.c (frame_unwind_got_optimized): Likewise.
+       (frame_unwind_got_register): Likewise.
+       (frame_unwind_got_constant): Likewise.
+       (frame_unwind_got_bytes): Likewise.
+       (frame_unwind_got_address): Likewise.
+
+       * frame.h (enum frame_type): New value ARCH_FRAME.
+       * frame.c (fprint_frame_type): Handle ARCH_FRAME.
+       * stack.c (print_frame_info): Likewise.
+
 2009-07-02  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * target.h (struct target_ops): New member to_thread_architecture.
index d3e102a2245329391ab6f5dd6bfcdc20bd51a90e..cdfd045d02f9beed3d3986b3e1b3904a5ba6d753 100644 (file)
@@ -129,7 +129,7 @@ default_frame_sniffer (const struct frame_unwind *self,
 struct value *
 frame_unwind_got_optimized (struct frame_info *frame, int regnum)
 {
-  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct gdbarch *gdbarch = frame_unwind_arch (frame);
   struct value *reg_val;
 
   reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
@@ -152,7 +152,7 @@ frame_unwind_got_register (struct frame_info *frame, int regnum, int new_regnum)
 struct value *
 frame_unwind_got_memory (struct frame_info *frame, int regnum, CORE_ADDR addr)
 {
-  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct gdbarch *gdbarch = frame_unwind_arch (frame);
 
   return value_at_lazy (register_type (gdbarch, regnum), addr);
 }
@@ -164,7 +164,7 @@ struct value *
 frame_unwind_got_constant (struct frame_info *frame, int regnum,
                           ULONGEST val)
 {
-  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct gdbarch *gdbarch = frame_unwind_arch (frame);
   struct value *reg_val;
 
   reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
@@ -176,7 +176,7 @@ frame_unwind_got_constant (struct frame_info *frame, int regnum,
 struct value *
 frame_unwind_got_bytes (struct frame_info *frame, int regnum, gdb_byte *buf)
 {
-  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct gdbarch *gdbarch = frame_unwind_arch (frame);
   struct value *reg_val;
 
   reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
@@ -192,7 +192,7 @@ struct value *
 frame_unwind_got_address (struct frame_info *frame, int regnum,
                          CORE_ADDR addr)
 {
-  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct gdbarch *gdbarch = frame_unwind_arch (frame);
   struct value *reg_val;
 
   reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
index 35eeebf56cc96351ee0ab113648166822497170a..c4518b558e189c7b9d9b309eb7e24e654965e8f2 100644 (file)
@@ -121,6 +121,13 @@ typedef struct value * (frame_prev_register_ftype)
 typedef void (frame_dealloc_cache_ftype) (struct frame_info *self,
                                          void *this_cache);
 
+/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
+   use THIS frame, and implicitly the NEXT frame's register unwind
+   method, return PREV frame's architecture.  */
+
+typedef struct gdbarch *(frame_prev_arch_ftype) (struct frame_info *this_frame,
+                                                void **this_prologue_cache);
+
 struct frame_unwind
 {
   /* The frame's type.  Should this instead be a collection of
@@ -133,6 +140,7 @@ struct frame_unwind
   const struct frame_data *unwind_data;
   frame_sniffer_ftype *sniffer;
   frame_dealloc_cache_ftype *dealloc_cache;
+  frame_prev_arch_ftype *prev_arch;
 };
 
 /* Register a frame unwinder, _prepending_ it to the front of the
index 68c41463e9e9383a54af93295291dff745bff67d..9a06959479e03ec24f249007131f0c19300b2114 100644 (file)
@@ -78,6 +78,13 @@ struct frame_info
   void *prologue_cache;
   const struct frame_unwind *unwind;
 
+  /* Cached copy of the previous frame's architecture.  */
+  struct
+  {
+    int p;
+    struct gdbarch *arch;
+  } prev_arch;
+
   /* Cached copy of the previous frame's resume address.  */
   struct {
     int p;
@@ -201,6 +208,9 @@ fprint_frame_type (struct ui_file *file, enum frame_type type)
     case SIGTRAMP_FRAME:
       fprintf_unfiltered (file, "SIGTRAMP_FRAME");
       return;
+    case ARCH_FRAME:
+      fprintf_unfiltered (file, "ARCH_FRAME");
+      return;
     default:
       fprintf_unfiltered (file, "<unknown type>");
       return;
@@ -535,7 +545,7 @@ frame_unwind_pc (struct frame_info *this_frame)
   if (!this_frame->prev_pc.p)
     {
       CORE_ADDR pc;
-      if (gdbarch_unwind_pc_p (get_frame_arch (this_frame)))
+      if (gdbarch_unwind_pc_p (frame_unwind_arch (this_frame)))
        {
          /* The right way.  The `pure' way.  The one true way.  This
             method depends solely on the register-unwind code to
@@ -553,7 +563,7 @@ frame_unwind_pc (struct frame_info *this_frame)
             frame.  This is all in stark contrast to the old
             FRAME_SAVED_PC which would try to directly handle all the
             different ways that a PC could be unwound.  */
-         pc = gdbarch_unwind_pc (get_frame_arch (this_frame), this_frame);
+         pc = gdbarch_unwind_pc (frame_unwind_arch (this_frame), this_frame);
        }
       else
        internal_error (__FILE__, __LINE__, _("No unwind_pc method"));
@@ -732,17 +742,18 @@ get_frame_register (struct frame_info *frame,
 struct value *
 frame_unwind_register_value (struct frame_info *frame, int regnum)
 {
+  struct gdbarch *gdbarch;
   struct value *value;
 
   gdb_assert (frame != NULL);
+  gdbarch = frame_unwind_arch (frame);
 
   if (frame_debug)
     {
       fprintf_unfiltered (gdb_stdlog, "\
 { frame_unwind_register_value (frame=%d,regnum=%d(%s),...) ",
                          frame->level, regnum,
-                         user_reg_map_regnum_to_name
-                           (get_frame_arch (frame), regnum));
+                         user_reg_map_regnum_to_name (gdbarch, regnum));
     }
 
   /* Find the unwinder.  */
@@ -777,7 +788,7 @@ frame_unwind_register_value (struct frame_info *frame, int regnum)
 
              fprintf_unfiltered (gdb_stdlog, " bytes=");
              fprintf_unfiltered (gdb_stdlog, "[");
-             for (i = 0; i < register_size (get_frame_arch (frame), regnum); i++)
+             for (i = 0; i < register_size (gdbarch, regnum); i++)
                fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
              fprintf_unfiltered (gdb_stdlog, "]");
            }
@@ -800,7 +811,7 @@ frame_unwind_register_signed (struct frame_info *frame, int regnum)
 {
   gdb_byte buf[MAX_REGISTER_SIZE];
   frame_unwind_register (frame, regnum, buf);
-  return extract_signed_integer (buf, register_size (get_frame_arch (frame),
+  return extract_signed_integer (buf, register_size (frame_unwind_arch (frame),
                                                     regnum));
 }
 
@@ -815,7 +826,7 @@ frame_unwind_register_unsigned (struct frame_info *frame, int regnum)
 {
   gdb_byte buf[MAX_REGISTER_SIZE];
   frame_unwind_register (frame, regnum, buf);
-  return extract_unsigned_integer (buf, register_size (get_frame_arch (frame),
+  return extract_unsigned_integer (buf, register_size (frame_unwind_arch (frame),
                                                       regnum));
 }
 
@@ -1880,17 +1891,48 @@ safe_frame_unwind_memory (struct frame_info *this_frame,
   return !target_read_memory (addr, buf, len);
 }
 
-/* Architecture method.  */
+/* Architecture methods.  */
 
 struct gdbarch *
 get_frame_arch (struct frame_info *this_frame)
 {
-  /* In the future, this function will return a per-frame
-     architecture instead of current_gdbarch.  Calling the
-     routine with a NULL value of this_frame is a bug!  */
-  gdb_assert (this_frame);
+  return frame_unwind_arch (this_frame->next);
+}
+
+struct gdbarch *
+frame_unwind_arch (struct frame_info *next_frame)
+{
+  if (!next_frame->prev_arch.p)
+    {
+      struct gdbarch *arch;
 
-  return current_gdbarch;
+      if (next_frame->unwind == NULL)
+       next_frame->unwind
+         = frame_unwind_find_by_frame (next_frame,
+                                       &next_frame->prologue_cache);
+
+      if (next_frame->unwind->prev_arch != NULL)
+       arch = next_frame->unwind->prev_arch (next_frame,
+                                             &next_frame->prologue_cache);
+      else
+       arch = get_frame_arch (next_frame);
+
+      next_frame->prev_arch.arch = arch;
+      next_frame->prev_arch.p = 1;
+      if (frame_debug)
+       fprintf_unfiltered (gdb_stdlog,
+                           "{ frame_unwind_arch (next_frame=%d) -> %s }\n",
+                           next_frame->level,
+                           gdbarch_bfd_arch_info (arch)->printable_name);
+    }
+
+  return next_frame->prev_arch.arch;
+}
+
+struct gdbarch *
+frame_unwind_caller_arch (struct frame_info *next_frame)
+{
+  return frame_unwind_arch (skip_inlined_frames (next_frame));
 }
 
 /* Stack pointer methods.  */
index 261c329b68b1287edfcbabde472ff85518e15485..febef5c04f783706342dc0c8c76325639f6c86f4 100644 (file)
@@ -203,6 +203,8 @@ enum frame_type
   /* In a signal handler, various OSs handle this in various ways.
      The main thing is that the frame may be far from normal.  */
   SIGTRAMP_FRAME,
+  /* Fake frame representing a cross-architecture call.  */
+  ARCH_FRAME,
   /* Sentinel or registers frame.  This frame obtains register values
      direct from the inferior's registers.  */
   SENTINEL_FRAME
@@ -545,9 +547,14 @@ extern int safe_frame_unwind_memory (struct frame_info *this_frame,
                                     CORE_ADDR addr, gdb_byte *buf, int len);
 
 /* Return this frame's architecture.  */
-
 extern struct gdbarch *get_frame_arch (struct frame_info *this_frame);
 
+/* Return the previous frame's architecture.  */
+extern struct gdbarch *frame_unwind_arch (struct frame_info *frame);
+
+/* Return the previous frame's architecture, skipping inline functions.  */
+extern struct gdbarch *frame_unwind_caller_arch (struct frame_info *frame);
+
 
 /* Values for the source flag to be used in print_frame_info_base().  */
 enum print_what
index d20c42666c34782fd514cb424f50b344be8df3f8..e01d19827917a7ab08efb45a06bb162f9b8d6e19 100644 (file)
@@ -76,11 +76,23 @@ sentinel_frame_this_id (struct frame_info *this_frame,
   internal_error (__FILE__, __LINE__, _("sentinel_frame_this_id called"));
 }
 
+static struct gdbarch *
+sentinel_frame_prev_arch (struct frame_info *this_frame,
+                         void **this_prologue_cache)
+{
+  struct frame_unwind_cache *cache = *this_prologue_cache;
+  return get_regcache_arch (cache->regcache);
+}
+
 const struct frame_unwind sentinel_frame_unwinder =
 {
   SENTINEL_FRAME,
   sentinel_frame_this_id,
-  sentinel_frame_prev_register
+  sentinel_frame_prev_register,
+  NULL,
+  NULL,
+  NULL,
+  sentinel_frame_prev_arch,
 };
 
 const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder;
index 0f5b42638b584ca8dee8a7a62b59cec9580e982d..7117f278cd8f51ca43562c8f82553301b6a4cb8b 100644 (file)
@@ -522,7 +522,8 @@ print_frame_info (struct frame_info *frame, int print_level,
   int location_print;
 
   if (get_frame_type (frame) == DUMMY_FRAME
-      || get_frame_type (frame) == SIGTRAMP_FRAME)
+      || get_frame_type (frame) == SIGTRAMP_FRAME
+      || get_frame_type (frame) == ARCH_FRAME)
     {
       struct cleanup *uiout_cleanup
        = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
@@ -555,6 +556,10 @@ print_frame_info (struct frame_info *frame, int print_level,
          annotate_signal_handler_caller ();
           ui_out_field_string (uiout, "func", "<signal handler called>");
         }
+      else if (get_frame_type (frame) == ARCH_FRAME)
+        {
+          ui_out_field_string (uiout, "func", "<cross-architecture call>");
+       }
       ui_out_text (uiout, "\n");
       annotate_frame_end ();