* 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.
This commit is contained in:
parent
848f574829
commit
36f15f554f
7 changed files with 123 additions and 21 deletions
|
@ -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>
|
2009-07-02 Ulrich Weigand <uweigand@de.ibm.com>
|
||||||
|
|
||||||
* target.h (struct target_ops): New member to_thread_architecture.
|
* target.h (struct target_ops): New member to_thread_architecture.
|
||||||
|
|
|
@ -129,7 +129,7 @@ default_frame_sniffer (const struct frame_unwind *self,
|
||||||
struct value *
|
struct value *
|
||||||
frame_unwind_got_optimized (struct frame_info *frame, int regnum)
|
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;
|
struct value *reg_val;
|
||||||
|
|
||||||
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
|
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 *
|
struct value *
|
||||||
frame_unwind_got_memory (struct frame_info *frame, int regnum, CORE_ADDR addr)
|
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);
|
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,
|
frame_unwind_got_constant (struct frame_info *frame, int regnum,
|
||||||
ULONGEST val)
|
ULONGEST val)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_frame_arch (frame);
|
struct gdbarch *gdbarch = frame_unwind_arch (frame);
|
||||||
struct value *reg_val;
|
struct value *reg_val;
|
||||||
|
|
||||||
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
|
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 *
|
struct value *
|
||||||
frame_unwind_got_bytes (struct frame_info *frame, int regnum, gdb_byte *buf)
|
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;
|
struct value *reg_val;
|
||||||
|
|
||||||
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
|
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,
|
frame_unwind_got_address (struct frame_info *frame, int regnum,
|
||||||
CORE_ADDR addr)
|
CORE_ADDR addr)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_frame_arch (frame);
|
struct gdbarch *gdbarch = frame_unwind_arch (frame);
|
||||||
struct value *reg_val;
|
struct value *reg_val;
|
||||||
|
|
||||||
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
|
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
|
||||||
|
|
|
@ -121,6 +121,13 @@ typedef struct value * (frame_prev_register_ftype)
|
||||||
typedef void (frame_dealloc_cache_ftype) (struct frame_info *self,
|
typedef void (frame_dealloc_cache_ftype) (struct frame_info *self,
|
||||||
void *this_cache);
|
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
|
struct frame_unwind
|
||||||
{
|
{
|
||||||
/* The frame's type. Should this instead be a collection of
|
/* The frame's type. Should this instead be a collection of
|
||||||
|
@ -133,6 +140,7 @@ struct frame_unwind
|
||||||
const struct frame_data *unwind_data;
|
const struct frame_data *unwind_data;
|
||||||
frame_sniffer_ftype *sniffer;
|
frame_sniffer_ftype *sniffer;
|
||||||
frame_dealloc_cache_ftype *dealloc_cache;
|
frame_dealloc_cache_ftype *dealloc_cache;
|
||||||
|
frame_prev_arch_ftype *prev_arch;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Register a frame unwinder, _prepending_ it to the front of the
|
/* Register a frame unwinder, _prepending_ it to the front of the
|
||||||
|
|
68
gdb/frame.c
68
gdb/frame.c
|
@ -78,6 +78,13 @@ struct frame_info
|
||||||
void *prologue_cache;
|
void *prologue_cache;
|
||||||
const struct frame_unwind *unwind;
|
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. */
|
/* Cached copy of the previous frame's resume address. */
|
||||||
struct {
|
struct {
|
||||||
int p;
|
int p;
|
||||||
|
@ -201,6 +208,9 @@ fprint_frame_type (struct ui_file *file, enum frame_type type)
|
||||||
case SIGTRAMP_FRAME:
|
case SIGTRAMP_FRAME:
|
||||||
fprintf_unfiltered (file, "SIGTRAMP_FRAME");
|
fprintf_unfiltered (file, "SIGTRAMP_FRAME");
|
||||||
return;
|
return;
|
||||||
|
case ARCH_FRAME:
|
||||||
|
fprintf_unfiltered (file, "ARCH_FRAME");
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
fprintf_unfiltered (file, "<unknown type>");
|
fprintf_unfiltered (file, "<unknown type>");
|
||||||
return;
|
return;
|
||||||
|
@ -535,7 +545,7 @@ frame_unwind_pc (struct frame_info *this_frame)
|
||||||
if (!this_frame->prev_pc.p)
|
if (!this_frame->prev_pc.p)
|
||||||
{
|
{
|
||||||
CORE_ADDR pc;
|
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
|
/* The right way. The `pure' way. The one true way. This
|
||||||
method depends solely on the register-unwind code to
|
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. This is all in stark contrast to the old
|
||||||
FRAME_SAVED_PC which would try to directly handle all the
|
FRAME_SAVED_PC which would try to directly handle all the
|
||||||
different ways that a PC could be unwound. */
|
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
|
else
|
||||||
internal_error (__FILE__, __LINE__, _("No unwind_pc method"));
|
internal_error (__FILE__, __LINE__, _("No unwind_pc method"));
|
||||||
|
@ -732,17 +742,18 @@ get_frame_register (struct frame_info *frame,
|
||||||
struct value *
|
struct value *
|
||||||
frame_unwind_register_value (struct frame_info *frame, int regnum)
|
frame_unwind_register_value (struct frame_info *frame, int regnum)
|
||||||
{
|
{
|
||||||
|
struct gdbarch *gdbarch;
|
||||||
struct value *value;
|
struct value *value;
|
||||||
|
|
||||||
gdb_assert (frame != NULL);
|
gdb_assert (frame != NULL);
|
||||||
|
gdbarch = frame_unwind_arch (frame);
|
||||||
|
|
||||||
if (frame_debug)
|
if (frame_debug)
|
||||||
{
|
{
|
||||||
fprintf_unfiltered (gdb_stdlog, "\
|
fprintf_unfiltered (gdb_stdlog, "\
|
||||||
{ frame_unwind_register_value (frame=%d,regnum=%d(%s),...) ",
|
{ frame_unwind_register_value (frame=%d,regnum=%d(%s),...) ",
|
||||||
frame->level, regnum,
|
frame->level, regnum,
|
||||||
user_reg_map_regnum_to_name
|
user_reg_map_regnum_to_name (gdbarch, regnum));
|
||||||
(get_frame_arch (frame), regnum));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the unwinder. */
|
/* 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, " bytes=");
|
||||||
fprintf_unfiltered (gdb_stdlog, "[");
|
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, "%02x", buf[i]);
|
||||||
fprintf_unfiltered (gdb_stdlog, "]");
|
fprintf_unfiltered (gdb_stdlog, "]");
|
||||||
}
|
}
|
||||||
|
@ -800,7 +811,7 @@ frame_unwind_register_signed (struct frame_info *frame, int regnum)
|
||||||
{
|
{
|
||||||
gdb_byte buf[MAX_REGISTER_SIZE];
|
gdb_byte buf[MAX_REGISTER_SIZE];
|
||||||
frame_unwind_register (frame, regnum, buf);
|
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));
|
regnum));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,7 +826,7 @@ frame_unwind_register_unsigned (struct frame_info *frame, int regnum)
|
||||||
{
|
{
|
||||||
gdb_byte buf[MAX_REGISTER_SIZE];
|
gdb_byte buf[MAX_REGISTER_SIZE];
|
||||||
frame_unwind_register (frame, regnum, buf);
|
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));
|
regnum));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1880,17 +1891,48 @@ safe_frame_unwind_memory (struct frame_info *this_frame,
|
||||||
return !target_read_memory (addr, buf, len);
|
return !target_read_memory (addr, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Architecture method. */
|
/* Architecture methods. */
|
||||||
|
|
||||||
struct gdbarch *
|
struct gdbarch *
|
||||||
get_frame_arch (struct frame_info *this_frame)
|
get_frame_arch (struct frame_info *this_frame)
|
||||||
{
|
{
|
||||||
/* In the future, this function will return a per-frame
|
return frame_unwind_arch (this_frame->next);
|
||||||
architecture instead of current_gdbarch. Calling the
|
}
|
||||||
routine with a NULL value of this_frame is a bug! */
|
|
||||||
gdb_assert (this_frame);
|
|
||||||
|
|
||||||
return current_gdbarch;
|
struct gdbarch *
|
||||||
|
frame_unwind_arch (struct frame_info *next_frame)
|
||||||
|
{
|
||||||
|
if (!next_frame->prev_arch.p)
|
||||||
|
{
|
||||||
|
struct gdbarch *arch;
|
||||||
|
|
||||||
|
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. */
|
/* Stack pointer methods. */
|
||||||
|
|
|
@ -203,6 +203,8 @@ enum frame_type
|
||||||
/* In a signal handler, various OSs handle this in various ways.
|
/* In a signal handler, various OSs handle this in various ways.
|
||||||
The main thing is that the frame may be far from normal. */
|
The main thing is that the frame may be far from normal. */
|
||||||
SIGTRAMP_FRAME,
|
SIGTRAMP_FRAME,
|
||||||
|
/* Fake frame representing a cross-architecture call. */
|
||||||
|
ARCH_FRAME,
|
||||||
/* Sentinel or registers frame. This frame obtains register values
|
/* Sentinel or registers frame. This frame obtains register values
|
||||||
direct from the inferior's registers. */
|
direct from the inferior's registers. */
|
||||||
SENTINEL_FRAME
|
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);
|
CORE_ADDR addr, gdb_byte *buf, int len);
|
||||||
|
|
||||||
/* Return this frame's architecture. */
|
/* Return this frame's architecture. */
|
||||||
|
|
||||||
extern struct gdbarch *get_frame_arch (struct frame_info *this_frame);
|
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(). */
|
/* Values for the source flag to be used in print_frame_info_base(). */
|
||||||
enum print_what
|
enum print_what
|
||||||
|
|
|
@ -76,11 +76,23 @@ sentinel_frame_this_id (struct frame_info *this_frame,
|
||||||
internal_error (__FILE__, __LINE__, _("sentinel_frame_this_id called"));
|
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 =
|
const struct frame_unwind sentinel_frame_unwinder =
|
||||||
{
|
{
|
||||||
SENTINEL_FRAME,
|
SENTINEL_FRAME,
|
||||||
sentinel_frame_this_id,
|
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;
|
const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder;
|
||||||
|
|
|
@ -522,7 +522,8 @@ print_frame_info (struct frame_info *frame, int print_level,
|
||||||
int location_print;
|
int location_print;
|
||||||
|
|
||||||
if (get_frame_type (frame) == DUMMY_FRAME
|
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
|
struct cleanup *uiout_cleanup
|
||||||
= make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
|
= 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 ();
|
annotate_signal_handler_caller ();
|
||||||
ui_out_field_string (uiout, "func", "<signal handler called>");
|
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");
|
ui_out_text (uiout, "\n");
|
||||||
annotate_frame_end ();
|
annotate_frame_end ();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue