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.
This commit is contained in:
Mike Frysinger 2015-12-30 23:17:58 -05:00
parent 4eb70007f1
commit bfb2629c16
3 changed files with 119 additions and 1 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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,