summaryrefslogtreecommitdiff
path: root/sim/common
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2015-12-30 23:17:58 -0500
committerMike Frysinger <vapier@gentoo.org>2016-01-05 14:28:37 -0500
commitbfb2629c162c05dac30fc16180953efb671c4227 (patch)
tree2071f7a69d507899e7dfe518fd36dad1416233a8 /sim/common
parent4eb70007f1a750b5bdf4e2a08eef96cf7c666c0a (diff)
downloadbinutils-gdb-bfb2629c162c05dac30fc16180953efb671c4227.tar.gz
sim: trace: add support for disassembling
Some targets have started to add support for calling the disassembler automatically when executing code. Add support for that directly into the trace core.
Diffstat (limited to 'sim/common')
-rw-r--r--sim/common/ChangeLog20
-rw-r--r--sim/common/sim-trace.c62
-rw-r--r--sim/common/sim-trace.h38
3 files changed, 119 insertions, 1 deletions
diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog
index 8ad6a417351..6dc76f5de3f 100644
--- a/sim/common/ChangeLog
+++ b/sim/common/ChangeLog
@@ -1,3 +1,23 @@
+2016-01-05 Mike Frysinger <vapier@gentoo.org>
+
+ * sim-trace.c: Include dis-asm.h.
+ (OPTION_TRACE_DISASM): New enum.
+ (trace_options): Add trace-disasm flag.
+ (trace_option_handler): Handle OPTION_TRACE_DISASM.
+ (trace_idx_to_str): Handle TRACE_DISASM_IDX.
+ (dis_read, dis_printf, trace_disasm): New functions.
+ * sim-trace.h: Include dis-asm.h.
+ (TRACE_INSN_IDX): Clarify comment.
+ (TRACE_DISASM_IDX): New enum.
+ (TRACE_disasm): New define.
+ (WITH_TRACE_DISASM_P): New define.
+ (struct _trace_data): Add dis_bfd, disassembler, and dis_info.
+ (STRACE_DISASM_P): New define.
+ (TRACE_DISASM_P): Likewise.
+ (TRACE_DISASM_P): Likewise.
+ (TRACE_DISASM): Likewise.
+ (trace_disasm): New function.
+
2016-01-04 Mike Frysinger <vapier@gentoo.org>
* sim-utils.c (sim_state_free): Change to STATE_MAGIC.
diff --git a/sim/common/sim-trace.c b/sim/common/sim-trace.c
index 6c01e15e106..e299cf857d0 100644
--- a/sim/common/sim-trace.c
+++ b/sim/common/sim-trace.c
@@ -25,6 +25,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "bfd.h"
#include "libiberty.h"
+#include "dis-asm.h"
+
#include "sim-assert.h"
#ifdef HAVE_STRING_H
@@ -61,6 +63,7 @@ static DECLARE_OPTION_HANDLER (trace_option_handler);
enum {
OPTION_TRACE_INSN = OPTION_START,
+ OPTION_TRACE_DISASM,
OPTION_TRACE_DECODE,
OPTION_TRACE_EXTRACT,
OPTION_TRACE_LINENUM,
@@ -90,6 +93,9 @@ static const OPTION trace_options[] =
{ {"trace-insn", optional_argument, NULL, OPTION_TRACE_INSN},
'\0', "on|off", "Perform instruction tracing",
trace_option_handler, NULL },
+ { {"trace-disasm", optional_argument, NULL, OPTION_TRACE_DISASM},
+ '\0', "on|off", "Disassemble instructions (slower, but more accurate)",
+ trace_option_handler, NULL },
{ {"trace-decode", optional_argument, NULL, OPTION_TRACE_DECODE},
'\0', "on|off", "Trace instruction decoding",
trace_option_handler, NULL },
@@ -249,6 +255,13 @@ trace_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
break;
+ case OPTION_TRACE_DISASM :
+ if (WITH_TRACE_DISASM_P)
+ return set_trace_option (sd, "-disasm", TRACE_DISASM_IDX, arg);
+ else
+ sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-disasm' ignored\n");
+ break;
+
case OPTION_TRACE_DECODE :
if (WITH_TRACE_DECODE_P)
return set_trace_option (sd, "-decode", TRACE_DECODE_IDX, arg);
@@ -616,6 +629,7 @@ trace_idx_to_str (int trace_idx)
{
case TRACE_ALU_IDX: return "alu: ";
case TRACE_INSN_IDX: return "insn: ";
+ case TRACE_DISASM_IDX: return "disasm: ";
case TRACE_DECODE_IDX: return "decode: ";
case TRACE_EXTRACT_IDX: return "extract: ";
case TRACE_MEMORY_IDX: return "memory: ";
@@ -837,6 +851,54 @@ trace_generic (SIM_DESC sd,
trace_printf (sd, cpu, "\n");
}
+static int
+dis_read (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length,
+ struct disassemble_info *dinfo)
+{
+ SIM_CPU *cpu = dinfo->application_data;
+ sim_core_read_buffer (CPU_STATE (cpu), cpu, NULL_CIA, myaddr, memaddr, length);
+ return 0;
+}
+
+static int
+dis_printf (SIM_CPU *cpu, const char *fmt, ...)
+{
+ SIM_DESC sd = CPU_STATE (cpu);
+ va_list ap;
+ va_start (ap, fmt);
+ trace_vprintf (sd, cpu, fmt, ap);
+ va_end (ap);
+ return 0;
+}
+
+void
+trace_disasm (SIM_DESC sd, sim_cpu *cpu, address_word addr)
+{
+ struct bfd *bfd = STATE_PROG_BFD (sd);
+ TRACE_DATA *trace_data = CPU_TRACE_DATA (cpu);
+ disassemble_info *info = &trace_data->dis_info;
+
+ /* See if we need to set up the disassembly func. */
+ if (trace_data->dis_bfd != bfd)
+ {
+ trace_data->dis_bfd = bfd;
+ trace_data->disassembler = disassembler (trace_data->dis_bfd);
+ INIT_DISASSEMBLE_INFO (*info, cpu, dis_printf);
+ info->read_memory_func = dis_read;
+ info->arch = bfd_get_arch (bfd);
+ info->mach = bfd_get_mach (bfd);
+ disassemble_init_for_target (info);
+ }
+
+ info->application_data = cpu;
+
+ trace_printf (sd, cpu, "%s %s",
+ trace_idx_to_str (TRACE_DISASM_IDX),
+ TRACE_PREFIX (trace_data));
+ trace_data->disassembler (addr, info);
+ trace_printf (sd, cpu, "\n");
+}
+
void
trace_input0 (SIM_DESC sd,
sim_cpu *cpu,
diff --git a/sim/common/sim-trace.h b/sim/common/sim-trace.h
index 6d62c5ab0a7..40de5bf5a21 100644
--- a/sim/common/sim-trace.h
+++ b/sim/common/sim-trace.h
@@ -22,12 +22,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef SIM_TRACE_H
#define SIM_TRACE_H
+#include "dis-asm.h"
+
/* Standard traceable entities. */
enum {
- /* Trace insn execution. */
+ /* Trace insn execution. The port itself is responsible for displaying what
+ it thinks it is decoding. */
TRACE_INSN_IDX = 1,
+ /* Disassemble code addresses. Like insn tracing, but relies on the opcode
+ framework for displaying code. Can be slower, more accurate as to what
+ the binary code actually is, but not how the sim is decoding it. */
+ TRACE_DISASM_IDX,
+
/* Trace insn decoding.
??? This is more of a simulator debugging operation and might best be
moved to --debug-decode. */
@@ -97,6 +105,7 @@ enum {
The case choice here is on purpose. The lowercase parts are args to
--with-trace. */
#define TRACE_insn (1 << TRACE_INSN_IDX)
+#define TRACE_disasm (1 << TRACE_DISASM_IDX)
#define TRACE_decode (1 << TRACE_DECODE_IDX)
#define TRACE_extract (1 << TRACE_EXTRACT_IDX)
#define TRACE_linenum (1 << TRACE_LINENUM_IDX)
@@ -118,6 +127,7 @@ enum {
/* Preprocessor macros to simplify tests of WITH_TRACE. */
#define WITH_TRACE_ANY_P (WITH_TRACE)
#define WITH_TRACE_INSN_P WITH_TRACE_P (TRACE_INSN_IDX)
+#define WITH_TRACE_DISASM_P WITH_TRACE_P (TRACE_DISASM_IDX)
#define WITH_TRACE_DECODE_P WITH_TRACE_P (TRACE_DECODE_IDX)
#define WITH_TRACE_EXTRACT_P WITH_TRACE_P (TRACE_EXTRACT_IDX)
#define WITH_TRACE_LINENUM_P WITH_TRACE_P (TRACE_LINENUM_IDX)
@@ -190,6 +200,19 @@ typedef struct _trace_data {
??? Not all cpu's support this. */
ADDR_RANGE range;
#define TRACE_RANGE(t) (& (t)->range)
+
+ /* The bfd used to disassemble code. Should compare against STATE_PROG_BFD
+ before using the disassembler helper.
+ Meant for use by the internal trace module only. */
+ struct bfd *dis_bfd;
+
+ /* The function used to actually disassemble code.
+ Meant for use by the internal trace module only. */
+ disassembler_ftype disassembler;
+
+ /* State used with the disassemble function.
+ Meant for use by the internal trace module only. */
+ disassemble_info dis_info;
} TRACE_DATA;
/* System tracing support. */
@@ -204,6 +227,7 @@ typedef struct _trace_data {
/* Non-zero if --trace-<xxxx> was specified for SD. */
#define STRACE_ANY_P(sd) (WITH_TRACE_ANY_P && (STATE_TRACE_DATA (sd)->trace_any_p))
#define STRACE_INSN_P(sd) STRACE_P (sd, TRACE_INSN_IDX)
+#define STRACE_DISASM_P(sd) STRACE_P (sd, TRACE_DISASM_IDX)
#define STRACE_DECODE_P(sd) STRACE_P (sd, TRACE_DECODE_IDX)
#define STRACE_EXTRACT_P(sd) STRACE_P (sd, TRACE_EXTRACT_IDX)
#define STRACE_LINENUM_P(sd) STRACE_P (sd, TRACE_LINENUM_IDX)
@@ -226,6 +250,7 @@ typedef struct _trace_data {
trace_generic (sd, NULL, idx, fmt, ## args); \
} while (0)
#define STRACE_INSN(sd, fmt, args...) STRACE (sd, TRACE_INSN_IDX, fmt, ## args)
+#define STRACE_DISASM(sd, fmt, args...) STRACE (sd, TRACE_DISASM_IDX, fmt, ## args)
#define STRACE_DECODE(sd, fmt, args...) STRACE (sd, TRACE_DECODE_IDX, fmt, ## args)
#define STRACE_EXTRACT(sd, fmt, args...) STRACE (sd, TRACE_EXTRACT_IDX, fmt, ## args)
#define STRACE_LINENUM(sd, fmt, args...) STRACE (sd, TRACE_LINENUM_IDX, fmt, ## args)
@@ -252,6 +277,7 @@ typedef struct _trace_data {
/* Non-zero if --trace-<xxxx> was specified for CPU. */
#define TRACE_ANY_P(cpu) (WITH_TRACE_ANY_P && (CPU_TRACE_DATA (cpu)->trace_any_p))
#define TRACE_INSN_P(cpu) TRACE_P (cpu, TRACE_INSN_IDX)
+#define TRACE_DISASM_P(cpu) TRACE_P (cpu, TRACE_DISASM_IDX)
#define TRACE_DECODE_P(cpu) TRACE_P (cpu, TRACE_DECODE_IDX)
#define TRACE_EXTRACT_P(cpu) TRACE_P (cpu, TRACE_EXTRACT_IDX)
#define TRACE_LINENUM_P(cpu) TRACE_P (cpu, TRACE_LINENUM_IDX)
@@ -266,6 +292,7 @@ typedef struct _trace_data {
#define TRACE_SYSCALL_P(cpu) TRACE_P (cpu, TRACE_SYSCALL_IDX)
#define TRACE_REGISTER_P(cpu) TRACE_P (cpu, TRACE_REGISTER_IDX)
#define TRACE_DEBUG_P(cpu) TRACE_P (cpu, TRACE_DEBUG_IDX)
+#define TRACE_DISASM_P(cpu) TRACE_P (cpu, TRACE_DISASM_IDX)
/* Helper functions for printing messages. */
#define TRACE(cpu, idx, fmt, args...) \
@@ -288,6 +315,11 @@ typedef struct _trace_data {
#define TRACE_SYSCALL(cpu, fmt, args...) TRACE (cpu, TRACE_SYSCALL_IDX, fmt, ## args)
#define TRACE_REGISTER(cpu, fmt, args...) TRACE (cpu, TRACE_REGISTER_IDX, fmt, ## args)
#define TRACE_DEBUG(cpu, fmt, args...) TRACE (cpu, TRACE_DEBUG_IDX, fmt, ## args)
+#define TRACE_DISASM(cpu, addr) \
+ do { \
+ if (TRACE_DISASM_P (cpu)) \
+ trace_disasm (CPU_STATE (cpu), cpu, addr); \
+ } while (0)
/* Tracing functions. */
@@ -313,6 +345,10 @@ extern void trace_generic (SIM_DESC sd,
...)
__attribute__((format (printf, 4, 5)));
+/* Disassemble the specified address. */
+
+extern void trace_disasm (SIM_DESC sd, sim_cpu *cpu, address_word addr);
+
typedef enum {
trace_fmt_invalid,
trace_fmt_word,