📄 sim-trace.c
字号:
/* Simulator tracing/debugging support. Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc. Contributed by Cygnus Support.This file is part of GDB, the GNU debugger.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "sim-main.h"#include "sim-io.h"#include "sim-options.h"#include "sim-fpu.h"#include "bfd.h"#include "libiberty.h"#include "sim-assert.h"#ifdef HAVE_STRING_H#include <string.h>#else#ifdef HAVE_STRINGS_H#include <strings.h>#endif#endif#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifndef SIZE_PHASE#define SIZE_PHASE 8#endif#ifndef SIZE_LOCATION#define SIZE_LOCATION 20#endif#ifndef SIZE_PC#define SIZE_PC 6#endif#ifndef SIZE_LINE_NUMBER#define SIZE_LINE_NUMBER 4#endifstatic MODULE_INIT_FN trace_init;static MODULE_UNINSTALL_FN trace_uninstall;static DECLARE_OPTION_HANDLER (trace_option_handler);enum { OPTION_TRACE_INSN = OPTION_START, OPTION_TRACE_DECODE, OPTION_TRACE_EXTRACT, OPTION_TRACE_LINENUM, OPTION_TRACE_MEMORY, OPTION_TRACE_MODEL, OPTION_TRACE_ALU, OPTION_TRACE_CORE, OPTION_TRACE_EVENTS, OPTION_TRACE_FPU, OPTION_TRACE_BRANCH, OPTION_TRACE_SEMANTICS, OPTION_TRACE_RANGE, OPTION_TRACE_FUNCTION, OPTION_TRACE_DEBUG, OPTION_TRACE_FILE, OPTION_TRACE_VPU};static const OPTION trace_options[] ={ /* This table is organized to group related instructions together. */ { {"trace", optional_argument, NULL, 't'}, 't', "on|off", "Trace useful things", trace_option_handler }, { {"trace-insn", optional_argument, NULL, OPTION_TRACE_INSN}, '\0', "on|off", "Perform instruction tracing", trace_option_handler }, { {"trace-decode", optional_argument, NULL, OPTION_TRACE_DECODE}, '\0', "on|off", "Trace instruction decoding", trace_option_handler }, { {"trace-extract", optional_argument, NULL, OPTION_TRACE_EXTRACT}, '\0', "on|off", "Trace instruction extraction", trace_option_handler }, { {"trace-linenum", optional_argument, NULL, OPTION_TRACE_LINENUM}, '\0', "on|off", "Perform line number tracing (implies --trace-insn)", trace_option_handler }, { {"trace-memory", optional_argument, NULL, OPTION_TRACE_MEMORY}, '\0', "on|off", "Trace memory operations", trace_option_handler }, { {"trace-alu", optional_argument, NULL, OPTION_TRACE_ALU}, '\0', "on|off", "Trace ALU operations", trace_option_handler }, { {"trace-fpu", optional_argument, NULL, OPTION_TRACE_FPU}, '\0', "on|off", "Trace FPU operations", trace_option_handler }, { {"trace-vpu", optional_argument, NULL, OPTION_TRACE_VPU}, '\0', "on|off", "Trace VPU operations", trace_option_handler }, { {"trace-branch", optional_argument, NULL, OPTION_TRACE_BRANCH}, '\0', "on|off", "Trace branching", trace_option_handler }, { {"trace-semantics", optional_argument, NULL, OPTION_TRACE_SEMANTICS}, '\0', "on|off", "Perform ALU, FPU, MEMORY, and BRANCH tracing", trace_option_handler }, { {"trace-model", optional_argument, NULL, OPTION_TRACE_MODEL}, '\0', "on|off", "Include model performance data", trace_option_handler }, { {"trace-core", optional_argument, NULL, OPTION_TRACE_CORE}, '\0', "on|off", "Trace core operations", trace_option_handler }, { {"trace-events", optional_argument, NULL, OPTION_TRACE_EVENTS}, '\0', "on|off", "Trace events", trace_option_handler },#ifdef SIM_HAVE_ADDR_RANGE { {"trace-range", required_argument, NULL, OPTION_TRACE_RANGE}, '\0', "START,END", "Specify range of addresses for instruction tracing", trace_option_handler },#if 0 /*wip*/ { {"trace-function", required_argument, NULL, OPTION_TRACE_FUNCTION}, '\0', "FUNCTION", "Specify function to trace", trace_option_handler },#endif#endif { {"trace-debug", optional_argument, NULL, OPTION_TRACE_DEBUG}, '\0', "on|off", "Add information useful for debugging the simulator to the tracing output", trace_option_handler }, { {"trace-file", required_argument, NULL, OPTION_TRACE_FILE}, '\0', "FILE NAME", "Specify tracing output file", trace_option_handler }, { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }};/* Set/reset the trace options indicated in MASK. */static SIM_RCset_trace_option_mask (sd, name, mask, arg) SIM_DESC sd; const char *name; int mask; const char *arg;{ int trace_nr; int cpu_nr; int trace_val = 1; if (arg != NULL) { if (strcmp (arg, "yes") == 0 || strcmp (arg, "on") == 0 || strcmp (arg, "1") == 0) trace_val = 1; else if (strcmp (arg, "no") == 0 || strcmp (arg, "off") == 0 || strcmp (arg, "0") == 0) trace_val = 0; else { sim_io_eprintf (sd, "Argument `%s' for `--trace%s' invalid, one of `on', `off', `yes', `no' expected\n", arg, name); return SIM_RC_FAIL; } } /* update applicable trace bits */ for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr) { if ((mask & (1 << trace_nr)) == 0) continue; /* Set non-cpu specific values. */ switch (trace_nr) { case TRACE_EVENTS_IDX: STATE_EVENTS (sd)->trace = trace_val; break; case TRACE_DEBUG_IDX: STATE_TRACE_FLAGS (sd)[trace_nr] = trace_val; break; } /* Set cpu values. */ for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) { CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr] = trace_val; } } /* Re-compute the cpu trace summary. */ if (trace_val) { for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1; } else { for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) { CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 0; for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr) { if (CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr]) { CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1; break; } } } } return SIM_RC_OK;}/* Set one trace option based on its IDX value. */static SIM_RCset_trace_option (sd, name, idx, arg) SIM_DESC sd; const char *name; int idx; const char *arg;{ return set_trace_option_mask (sd, name, 1 << idx, arg);}static SIM_RCtrace_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, char *arg, int is_command){ int n; int cpu_nr; switch (opt) { case 't' : if (! WITH_TRACE) sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n"); else return set_trace_option_mask (sd, "trace", TRACE_USEFUL_MASK, arg); break; case OPTION_TRACE_INSN : if (WITH_TRACE_INSN_P) return set_trace_option (sd, "-insn", TRACE_INSN_IDX, arg); else sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n"); break; case OPTION_TRACE_DECODE : if (WITH_TRACE_DECODE_P) return set_trace_option (sd, "-decode", TRACE_DECODE_IDX, arg); else sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n"); break; case OPTION_TRACE_EXTRACT : if (WITH_TRACE_EXTRACT_P) return set_trace_option (sd, "-extract", TRACE_EXTRACT_IDX, arg); else sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n"); break; case OPTION_TRACE_LINENUM : if (WITH_TRACE_LINENUM_P && WITH_TRACE_INSN_P) { if (set_trace_option (sd, "-linenum", TRACE_LINENUM_IDX, arg) != SIM_RC_OK || set_trace_option (sd, "-linenum", TRACE_INSN_IDX, arg) != SIM_RC_OK) return SIM_RC_FAIL; } else sim_io_eprintf (sd, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n"); break; case OPTION_TRACE_MEMORY : if (WITH_TRACE_MEMORY_P) return set_trace_option (sd, "-memory", TRACE_MEMORY_IDX, arg); else sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n"); break; case OPTION_TRACE_MODEL : if (WITH_TRACE_MODEL_P) return set_trace_option (sd, "-model", TRACE_MODEL_IDX, arg); else sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n"); break; case OPTION_TRACE_ALU : if (WITH_TRACE_ALU_P) return set_trace_option (sd, "-alu", TRACE_ALU_IDX, arg); else sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n"); break; case OPTION_TRACE_CORE : if (WITH_TRACE_CORE_P) return set_trace_option (sd, "-core", TRACE_CORE_IDX, arg); else sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n"); break; case OPTION_TRACE_EVENTS : if (WITH_TRACE_EVENTS_P) return set_trace_option (sd, "-events", TRACE_EVENTS_IDX, arg); else sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n"); break; case OPTION_TRACE_FPU : if (WITH_TRACE_FPU_P) return set_trace_option (sd, "-fpu", TRACE_FPU_IDX, arg); else sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n"); break; case OPTION_TRACE_VPU : if (WITH_TRACE_VPU_P) return set_trace_option (sd, "-vpu", TRACE_VPU_IDX, arg); else sim_io_eprintf (sd, "VPU tracing not compiled in, `--trace-vpu' ignored\n"); break; case OPTION_TRACE_BRANCH : if (WITH_TRACE_BRANCH_P) return set_trace_option (sd, "-branch", TRACE_BRANCH_IDX, arg); else sim_io_eprintf (sd, "Branch tracing not compiled in, `--trace-branch' ignored\n"); break; case OPTION_TRACE_SEMANTICS : if (WITH_TRACE_ALU_P && WITH_TRACE_FPU_P && WITH_TRACE_MEMORY_P && WITH_TRACE_BRANCH_P) { if (set_trace_option (sd, "-semantics", TRACE_ALU_IDX, arg) != SIM_RC_OK || set_trace_option (sd, "-semantics", TRACE_FPU_IDX, arg) != SIM_RC_OK || set_trace_option (sd, "-semantics", TRACE_VPU_IDX, arg) != SIM_RC_OK || set_trace_option (sd, "-semantics", TRACE_MEMORY_IDX, arg) != SIM_RC_OK || set_trace_option (sd, "-semantics", TRACE_BRANCH_IDX, arg) != SIM_RC_OK) return SIM_RC_FAIL; } else sim_io_eprintf (sd, "Alu, fpu, memory, and/or branch tracing not compiled in, `--trace-semantics' ignored\n"); break;#ifdef SIM_HAVE_ADDR_RANGE case OPTION_TRACE_RANGE : if (WITH_TRACE) { char *chp = arg; unsigned long start,end; start = strtoul (chp, &chp, 0); if (*chp != ',') { sim_io_eprintf (sd, "--trace-range missing END argument\n"); return SIM_RC_FAIL; } end = strtoul (chp + 1, NULL, 0); /* FIXME: Argument validation. */ if (cpu != NULL) sim_addr_range_add (TRACE_RANGE (CPU_PROFILE_DATA (cpu)), start, end); else for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) sim_addr_range_add (TRACE_RANGE (CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))), start, end); } else sim_io_eprintf (sd, "Tracing not compiled in, `--trace-range' ignored\n"); break; case OPTION_TRACE_FUNCTION : if (WITH_TRACE) { /*wip: need to compute function range given name*/ } else sim_io_eprintf (sd, "Tracing not compiled in, `--trace-function' ignored\n"); break;#endif /* SIM_HAVE_ADDR_RANGE */ case OPTION_TRACE_DEBUG : if (WITH_TRACE_DEBUG_P) return set_trace_option (sd, "-debug", TRACE_DEBUG_IDX, arg); else sim_io_eprintf (sd, "Tracing debug support not compiled in, `--trace-debug' ignored\n"); break; case OPTION_TRACE_FILE : if (! WITH_TRACE) sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n"); else { FILE *f = fopen (arg, "w"); if (f == NULL) { sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg); return SIM_RC_FAIL; } for (n = 0; n < MAX_NR_PROCESSORS; ++n) TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f; TRACE_FILE (STATE_TRACE_DATA (sd)) = f; } break; } return SIM_RC_OK;}/* Install tracing support. */SIM_RCtrace_install (SIM_DESC sd){ int i; SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); sim_add_option_table (sd, NULL, trace_options); memset (STATE_TRACE_DATA (sd), 0, sizeof (* STATE_TRACE_DATA (sd))); for (i = 0; i < MAX_NR_PROCESSORS; ++i) memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0, sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i)))); sim_module_add_init_fn (sd, trace_init); sim_module_add_uninstall_fn (sd, trace_uninstall); return SIM_RC_OK;}static SIM_RCtrace_init (SIM_DESC sd){#ifdef SIM_HAVE_ADDR_RANGE /* Check if a range has been specified without specifying what to collect. */ { int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -