📄 sim-trace.c
字号:
for (i = 0; i < MAX_NR_PROCESSORS; ++i) { sim_cpu *cpu = STATE_CPU (sd, i); if (ADDR_RANGE_RANGES (TRACE_RANGE (CPU_TRACE_DATA (cpu))) && ! TRACE_INSN_P (cpu)) { sim_io_eprintf_cpu (cpu, "Tracing address range specified without --trace-insn.\n"); sim_io_eprintf_cpu (cpu, "Address range ignored.\n"); sim_addr_range_delete (TRACE_RANGE (CPU_TRACE_DATA (cpu)), 0, ~ (address_word) 0); } } }#endif return SIM_RC_OK;}static voidtrace_uninstall (SIM_DESC sd){ int i,j; FILE *sfile = TRACE_FILE (STATE_TRACE_DATA (sd)); if (sfile != NULL) fclose (sfile); for (i = 0; i < MAX_NR_PROCESSORS; ++i) { FILE *cfile = TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, i))); if (cfile != NULL && cfile != sfile) { /* If output from different cpus is going to the same file, avoid closing the file twice. */ for (j = 0; j < i; ++j) if (TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, j))) == cfile) break; if (i == j) fclose (cfile); } }}typedef enum { trace_fmt_invalid, trace_fmt_word, trace_fmt_fp, trace_fmt_fpu, trace_fmt_string, trace_fmt_bool, trace_fmt_addr, trace_fmt_instruction_incomplete,} data_fmt;/* compute the nr of trace data units consumed by data */static intsave_data_size (TRACE_DATA *data, long size){ return ((size + sizeof (TRACE_INPUT_DATA (data) [0]) - 1) / sizeof (TRACE_INPUT_DATA (data) [0]));}/* Archive DATA into the trace buffer */static voidsave_data (SIM_DESC sd, TRACE_DATA *data, data_fmt fmt, long size, void *buf){ int i = TRACE_INPUT_IDX (data); if (i == sizeof (TRACE_INPUT_FMT (data))) sim_io_error (sd, "trace buffer overflow"); TRACE_INPUT_FMT (data) [i] = fmt; TRACE_INPUT_SIZE (data) [i] = size; memcpy (&TRACE_INPUT_DATA (data) [i], buf, size); i += save_data_size (data, size); TRACE_INPUT_IDX (data) = i;}static voidprint_data (SIM_DESC sd, sim_cpu *cpu, data_fmt fmt, long size, void *data){ switch (fmt) { case trace_fmt_instruction_incomplete: trace_printf (sd, cpu, " (instruction incomplete)"); break; case trace_fmt_word: case trace_fmt_addr: { switch (size) { case sizeof (unsigned32): trace_printf (sd, cpu, " 0x%08lx", (long) * (unsigned32*) data); break; case sizeof (unsigned64): trace_printf (sd, cpu, " 0x%08lx%08lx", (long) ((* (unsigned64*) data) >> 32), (long) * (unsigned64*) data); break; default: abort (); } break; } case trace_fmt_bool: { SIM_ASSERT (size == sizeof (int)); trace_printf (sd, cpu, " %-8s", (* (int*) data) ? "true" : "false"); break; } case trace_fmt_fp: { sim_fpu fp; switch (size) { /* FIXME: Assumes sizeof float == 4; sizeof double == 8 */ case 4: sim_fpu_32to (&fp, *(unsigned32*)data); break; case 8: sim_fpu_64to (&fp, *(unsigned64*)data); break; default: abort (); } trace_printf (sd, cpu, " %8g", sim_fpu_2d (&fp)); switch (size) { case 4: trace_printf (sd, cpu, " (0x%08lx)", (long) *(unsigned32*)data); break; case 8: trace_printf (sd, cpu, " (0x%08lx%08lx)", (long) (*(unsigned64*)data >> 32), (long) (*(unsigned64*)data)); break; default: abort (); } break; } case trace_fmt_fpu: /* FIXME: At present sim_fpu data is stored as a double */ trace_printf (sd, cpu, " %8g", * (double*) data); break; case trace_fmt_string: trace_printf (sd, cpu, " %-8s", (char*) data); break; default: abort (); }} static const char *trace_idx_to_str (int trace_idx){ static char num[8]; switch (trace_idx) { case TRACE_ALU_IDX: return "alu: "; case TRACE_INSN_IDX: return "insn: "; case TRACE_DECODE_IDX: return "decode: "; case TRACE_EXTRACT_IDX: return "extract: "; case TRACE_MEMORY_IDX: return "memory: "; case TRACE_CORE_IDX: return "core: "; case TRACE_EVENTS_IDX: return "events: "; case TRACE_FPU_IDX: return "fpu: "; case TRACE_BRANCH_IDX: return "branch: "; case TRACE_VPU_IDX: return "vpu: "; default: sprintf (num, "?%d?", trace_idx); return num; }}static voidtrace_results (SIM_DESC sd, sim_cpu *cpu, int trace_idx, int last_input){ TRACE_DATA *data = CPU_TRACE_DATA (cpu); int nr_out; int i; /* cross check trace_idx against TRACE_IDX (data)? */ /* prefix */ trace_printf (sd, cpu, "%s %s", trace_idx_to_str (TRACE_IDX (data)), TRACE_PREFIX (data)); TRACE_IDX (data) = 0; for (i = 0, nr_out = 0; i < TRACE_INPUT_IDX (data); i += save_data_size (data, TRACE_INPUT_SIZE (data) [i]), nr_out++) { if (i == last_input) { int pad = (strlen (" 0x") + sizeof (unsigned_word) * 2); int padding = pad * (3 - nr_out); if (padding < 0) padding = 0; padding += strlen (" ::"); trace_printf (sd, cpu, "%*s", padding, " ::"); } print_data (sd, cpu, TRACE_INPUT_FMT (data) [i], TRACE_INPUT_SIZE (data) [i], &TRACE_INPUT_DATA (data) [i]); } trace_printf (sd, cpu, "\n");}voidtrace_prefix (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, address_word pc, int line_p, const char *filename, int linenum, const char *fmt, ...){ TRACE_DATA *data = CPU_TRACE_DATA (cpu); va_list ap; char *prefix = TRACE_PREFIX (data); char *chp; /* FIXME: The TRACE_PREFIX_WIDTH should be determined at build time using known information about the disassembled instructions. */#ifndef TRACE_PREFIX_WIDTH#define TRACE_PREFIX_WIDTH 48#endif int width = TRACE_PREFIX_WIDTH; /* if the previous trace data wasn't flushed, flush it now with a note indicating that the trace was incomplete. */ if (TRACE_IDX (data) != 0) { int last_input = TRACE_INPUT_IDX (data); save_data (sd, data, trace_fmt_instruction_incomplete, 1, ""); trace_results (sd, cpu, TRACE_IDX (data), last_input); } TRACE_IDX (data) = 0; TRACE_INPUT_IDX (data) = 0; /* Create the text prefix for this new instruction: */ if (!line_p) { if (filename) { sprintf (prefix, "%s:%-*d 0x%.*lx ", filename, SIZE_LINE_NUMBER, linenum, SIZE_PC, (long) pc); } else { sprintf (prefix, "0x%.*lx ", SIZE_PC, (long) pc); /* Shrink the width by the amount that we didn't print. */ width -= SIZE_LINE_NUMBER + SIZE_PC + 8; } chp = strchr (prefix, '\0'); va_start (ap, fmt); vsprintf (chp, fmt, ap); va_end (ap); } else { char buf[256]; buf[0] = 0; if (STATE_TEXT_SECTION (CPU_STATE (cpu)) && pc >= STATE_TEXT_START (CPU_STATE (cpu)) && pc < STATE_TEXT_END (CPU_STATE (cpu))) { const char *pc_filename = (const char *)0; const char *pc_function = (const char *)0; unsigned int pc_linenum = 0; bfd *abfd; asymbol **asymbols; abfd = STATE_PROG_BFD (CPU_STATE (cpu)); asymbols = STATE_PROG_SYMS (CPU_STATE (cpu)); if (asymbols == NULL) { long symsize; long symbol_count; symsize = bfd_get_symtab_upper_bound (abfd); if (symsize < 0) { sim_engine_abort (sd, cpu, cia, "could not read symbols"); } asymbols = (asymbol **) xmalloc (symsize); symbol_count = bfd_canonicalize_symtab (abfd, asymbols); if (symbol_count < 0) { sim_engine_abort (sd, cpu, cia, "could not canonicalize symbols"); } STATE_PROG_SYMS (CPU_STATE (cpu)) = asymbols; } if (bfd_find_nearest_line (abfd, STATE_TEXT_SECTION (CPU_STATE (cpu)), asymbols, pc - STATE_TEXT_START (CPU_STATE (cpu)), &pc_filename, &pc_function, &pc_linenum)) { char *p = buf; if (pc_linenum) { sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum); p += strlen (p); } else { sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---"); p += SIZE_LINE_NUMBER+2; } if (pc_function) { sprintf (p, "%s ", pc_function); p += strlen (p); } else if (pc_filename) { char *q = (char *) strrchr (pc_filename, '/'); sprintf (p, "%s ", (q) ? q+1 : pc_filename); p += strlen (p); } if (*p == ' ') *p = '\0'; } } sprintf (prefix, "0x%.*x %-*.*s ", SIZE_PC, (unsigned) pc, SIZE_LOCATION, SIZE_LOCATION, buf); chp = strchr (prefix, '\0'); va_start (ap, fmt); vsprintf (chp, fmt, ap); va_end (ap); } /* Pad it out to TRACE_PREFIX_WIDTH. */ chp = strchr (prefix, '\0'); if (chp - prefix < width) { memset (chp, ' ', width - (chp - prefix)); chp = &prefix [width]; *chp = '\0'; } strcpy (chp, " -"); /* check that we've not over flowed the prefix buffer */ if (strlen (prefix) >= sizeof (TRACE_PREFIX (data))) abort ();}voidtrace_generic (SIM_DESC sd, sim_cpu *cpu, int trace_idx, const char *fmt, ...){ va_list ap; trace_printf (sd, cpu, "%s %s", trace_idx_to_str (trace_idx), TRACE_PREFIX (CPU_TRACE_DATA (cpu))); va_start (ap, fmt); trace_vprintf (sd, cpu, fmt, ap); va_end (ap); trace_printf (sd, cpu, "\n");}voidtrace_input0 (SIM_DESC sd, sim_cpu *cpu, int trace_idx){ TRACE_DATA *data = CPU_TRACE_DATA (cpu); TRACE_IDX (data) = trace_idx;}voidtrace_input_word1 (SIM_DESC sd, sim_cpu *cpu, int trace_idx, unsigned_word d0){ TRACE_DATA *data = CPU_TRACE_DATA (cpu); TRACE_IDX (data) = trace_idx; save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0);}voidtrace_input_word2 (SIM_DESC sd, sim_cpu *cpu, int trace_idx, unsigned_word d0, unsigned_word d1){ TRACE_DATA *data = CPU_TRACE_DATA (cpu); TRACE_IDX (data) = trace_idx; save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0); save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1);}voidtrace_input_word3 (SIM_DESC sd, sim_cpu *cpu, int trace_idx, unsigned_word d0, unsigned_word d1, unsigned_word d2){ TRACE_DATA *data = CPU_TRACE_DATA (cpu); TRACE_IDX (data) = trace_idx; save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0); save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1); save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d2);}voidtrace_input_word4 (SIM_DESC sd, sim_cpu *cpu, int trace_idx, unsigned_word d0, unsigned_word d1, unsigned_word d2, unsigned_word d3){ TRACE_DATA *data = CPU_TRACE_DATA (cpu); TRACE_IDX (data) = trace_idx; save_data (sd, data, trace_fmt_word, sizeof (d0), &d0); save_data (sd, data, trace_fmt_word, sizeof (d1), &d1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -