diff options
author | Markus Metzger <markus.t.metzger@intel.com> | 2013-03-22 15:56:56 +0100 |
---|---|---|
committer | Markus Metzger <markus.t.metzger@intel.com> | 2014-01-16 12:45:11 +0100 |
commit | c2170eeffa616c51ca4c7ab7142523c04b762603 (patch) | |
tree | 8275515276a5b0591073db7cf182e45545f12471 /gdb/gdbarch.c | |
parent | 864089d2f64c6624aac3f52ece2c31dff6a8f59f (diff) | |
download | gdb-c2170eeffa616c51ca4c7ab7142523c04b762603.zip gdb-c2170eeffa616c51ca4c7ab7142523c04b762603.tar.gz gdb-c2170eeffa616c51ca4c7ab7142523c04b762603.tar.bz2 |
gdbarch: add instruction predicate methods
Add new methods to gdbarch for analyzing the instruction at a given address.
Implement those methods for i386 and amd64 architectures.
This is needed by "record btrace" to detect function calls in the
execution trace.
2014-01-16 Markus Metzger <markus.t.metzger@intel.com>
* amd64-tdep.c (amd64_classify_insn_at, amd64_insn_is_call)
(amd64_insn_is_ret, amd64_insn_is_jump, amd64_jmp_p): New.
(amd64_init_abi): Add insn_is_call, insn_is_ret, and insn_is_jump
to gdbarch.
* i386-tdep.c (i386_insn_is_call, i386_insn_is_ret)
(i386_insn_is_jump, i386_jmp_p): New.
(i386_gdbarch_init): Add insn_is_call, insn_is_ret, and
insn_is_jump to gdbarch.
* gdbarch.sh (insn_is_call, insn_is_ret, insn_is_jump): New.
* gdbarch.h: Regenerated.
* gdbarch.c: Regenerated.
* arch-utils.h (default_insn_is_call, default_insn_is_ret)
(default_insn_is_jump): New.
* arch-utils.c (default_insn_is_call, default_insn_is_ret)
(default_insn_is_jump): New.
Diffstat (limited to 'gdb/gdbarch.c')
-rw-r--r-- | gdb/gdbarch.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index e1766d3..ee41d50 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -317,6 +317,9 @@ struct gdbarch gdbarch_core_info_proc_ftype *core_info_proc; gdbarch_iterate_over_objfiles_in_search_order_ftype *iterate_over_objfiles_in_search_order; struct ravenscar_arch_ops * ravenscar_ops; + gdbarch_insn_is_call_ftype *insn_is_call; + gdbarch_insn_is_ret_ftype *insn_is_ret; + gdbarch_insn_is_jump_ftype *insn_is_jump; }; @@ -490,6 +493,9 @@ struct gdbarch startup_gdbarch = 0, /* core_info_proc */ default_iterate_over_objfiles_in_search_order, /* iterate_over_objfiles_in_search_order */ NULL, /* ravenscar_ops */ + default_insn_is_call, /* insn_is_call */ + default_insn_is_ret, /* insn_is_ret */ + default_insn_is_jump, /* insn_is_jump */ /* startup_gdbarch() */ }; @@ -581,6 +587,9 @@ gdbarch_alloc (const struct gdbarch_info *info, gdbarch->gen_return_address = default_gen_return_address; gdbarch->iterate_over_objfiles_in_search_order = default_iterate_over_objfiles_in_search_order; gdbarch->ravenscar_ops = NULL; + gdbarch->insn_is_call = default_insn_is_call; + gdbarch->insn_is_ret = default_insn_is_ret; + gdbarch->insn_is_jump = default_insn_is_jump; /* gdbarch_alloc() */ return gdbarch; @@ -795,6 +804,9 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of core_info_proc, has predicate. */ /* Skip verify of iterate_over_objfiles_in_search_order, invalid_p == 0 */ /* Skip verify of ravenscar_ops, invalid_p == 0 */ + /* Skip verify of insn_is_call, invalid_p == 0 */ + /* Skip verify of insn_is_ret, invalid_p == 0 */ + /* Skip verify of insn_is_jump, invalid_p == 0 */ buf = ui_file_xstrdup (log, &length); make_cleanup (xfree, buf); if (length > 0) @@ -1128,6 +1140,15 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: inner_than = <%s>\n", host_address_to_string (gdbarch->inner_than)); fprintf_unfiltered (file, + "gdbarch_dump: insn_is_call = <%s>\n", + host_address_to_string (gdbarch->insn_is_call)); + fprintf_unfiltered (file, + "gdbarch_dump: insn_is_jump = <%s>\n", + host_address_to_string (gdbarch->insn_is_jump)); + fprintf_unfiltered (file, + "gdbarch_dump: insn_is_ret = <%s>\n", + host_address_to_string (gdbarch->insn_is_ret)); + fprintf_unfiltered (file, "gdbarch_dump: int_bit = %s\n", plongest (gdbarch->int_bit)); fprintf_unfiltered (file, @@ -4451,6 +4472,57 @@ set_gdbarch_ravenscar_ops (struct gdbarch *gdbarch, gdbarch->ravenscar_ops = ravenscar_ops; } +int +gdbarch_insn_is_call (struct gdbarch *gdbarch, CORE_ADDR addr) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->insn_is_call != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_insn_is_call called\n"); + return gdbarch->insn_is_call (gdbarch, addr); +} + +void +set_gdbarch_insn_is_call (struct gdbarch *gdbarch, + gdbarch_insn_is_call_ftype insn_is_call) +{ + gdbarch->insn_is_call = insn_is_call; +} + +int +gdbarch_insn_is_ret (struct gdbarch *gdbarch, CORE_ADDR addr) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->insn_is_ret != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_insn_is_ret called\n"); + return gdbarch->insn_is_ret (gdbarch, addr); +} + +void +set_gdbarch_insn_is_ret (struct gdbarch *gdbarch, + gdbarch_insn_is_ret_ftype insn_is_ret) +{ + gdbarch->insn_is_ret = insn_is_ret; +} + +int +gdbarch_insn_is_jump (struct gdbarch *gdbarch, CORE_ADDR addr) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->insn_is_jump != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_insn_is_jump called\n"); + return gdbarch->insn_is_jump (gdbarch, addr); +} + +void +set_gdbarch_insn_is_jump (struct gdbarch *gdbarch, + gdbarch_insn_is_jump_ftype insn_is_jump) +{ + gdbarch->insn_is_jump = insn_is_jump; +} + /* Keep a registry of per-architecture data-pointers required by GDB modules. */ |