From 36f15f554fcea7aedfdcdabcdd19e927b623d615 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 2 Jul 2009 17:09:28 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 28 ++++++++++++++++++ gdb/frame-unwind.c | 10 +++---- gdb/frame-unwind.h | 8 ++++++ gdb/frame.c | 68 +++++++++++++++++++++++++++++++++++--------- gdb/frame.h | 9 +++++- gdb/sentinel-frame.c | 14 ++++++++- gdb/stack.c | 7 ++++- 7 files changed, 123 insertions(+), 21 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3a1936975d..496fb24bf7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,31 @@ +2009-07-02 Ulrich Weigand + + * 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 * target.h (struct target_ops): New member to_thread_architecture. diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c index d3e102a224..cdfd045d02 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 35eeebf56c..c4518b558e 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 68c41463e9..9a06959479 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, ""); 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 261c329b68..febef5c04f 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 d20c42666c..e01d198279 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 0f5b42638b..7117f278cd 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", ""); } + else if (get_frame_type (frame) == ARCH_FRAME) + { + ui_out_field_string (uiout, "func", ""); + } ui_out_text (uiout, "\n"); annotate_frame_end (); -- 2.34.1