summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog28
-rw-r--r--gdb/frame-unwind.c10
-rw-r--r--gdb/frame-unwind.h8
-rw-r--r--gdb/frame.c68
-rw-r--r--gdb/frame.h9
-rw-r--r--gdb/sentinel-frame.c14
-rw-r--r--gdb/stack.c7
7 files changed, 123 insertions, 21 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3a1936975de..496fb24bf71 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,33 @@
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.
(target_thread_architecture): New macro.
* target.c (update_current_target): Inherit to_thread_architecture.
diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c
index d3e102a2245..cdfd045d02f 100644
--- a/gdb/frame-unwind.c
+++ b/gdb/frame-unwind.c
@@ -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);
diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h
index 35eeebf56cc..c4518b558e1 100644
--- a/gdb/frame-unwind.h
+++ b/gdb/frame-unwind.h
@@ -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
diff --git a/gdb/frame.c b/gdb/frame.c
index 68c41463e9e..9a06959479e 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -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. */
diff --git a/gdb/frame.h b/gdb/frame.h
index 261c329b68b..febef5c04f7 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -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
diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c
index d20c42666c3..e01d1982791 100644
--- a/gdb/sentinel-frame.c
+++ b/gdb/sentinel-frame.c
@@ -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;
diff --git a/gdb/stack.c b/gdb/stack.c
index 0f5b42638b5..7117f278cd8 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -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 ();