1 /* Simulator tracing/debugging support.
2 Copyright (C) 1997 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
5 This file is part of GDB, the GNU debugger.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 #include "sim-options.h"
26 #include "sim-assert.h"
41 #define SIZE_LOCATION 20
48 #ifndef SIZE_LINE_NUMBER
49 #define SIZE_LINE_NUMBER 4
52 static MODULE_UNINSTALL_FN trace_uninstall
;
54 static DECLARE_OPTION_HANDLER (trace_option_handler
);
57 OPTION_TRACE_INSN
= OPTION_START
,
68 OPTION_TRACE_SEMANTICS
,
73 static const OPTION trace_options
[] =
75 { {"trace", optional_argument
, NULL
, 't'},
76 't', "on|off", "Perform tracing",
77 trace_option_handler
},
78 { {"trace-insn", optional_argument
, NULL
, OPTION_TRACE_INSN
},
79 '\0', "on|off", "Perform instruction tracing",
80 trace_option_handler
},
81 { {"trace-decode", optional_argument
, NULL
, OPTION_TRACE_DECODE
},
82 '\0', "on|off", "Perform instruction decoding tracing",
83 trace_option_handler
},
84 { {"trace-extract", optional_argument
, NULL
, OPTION_TRACE_EXTRACT
},
85 '\0', "on|off", "Perform instruction extraction tracing",
86 trace_option_handler
},
87 { {"trace-linenum", optional_argument
, NULL
, OPTION_TRACE_LINENUM
},
88 '\0', "on|off", "Perform line number tracing (implies --trace-insn)",
89 trace_option_handler
},
90 { {"trace-memory", optional_argument
, NULL
, OPTION_TRACE_MEMORY
},
91 '\0', "on|off", "Perform memory tracing",
92 trace_option_handler
},
93 { {"trace-model", optional_argument
, NULL
, OPTION_TRACE_MODEL
},
94 '\0', "on|off", "Perform model tracing",
95 trace_option_handler
},
96 { {"trace-alu", optional_argument
, NULL
, OPTION_TRACE_ALU
},
97 '\0', "on|off", "Perform ALU tracing",
98 trace_option_handler
},
99 { {"trace-core", optional_argument
, NULL
, OPTION_TRACE_CORE
},
100 '\0', "on|off", "Perform CORE tracing",
101 trace_option_handler
},
102 { {"trace-events", optional_argument
, NULL
, OPTION_TRACE_EVENTS
},
103 '\0', "on|off", "Perform EVENTS tracing",
104 trace_option_handler
},
105 { {"trace-fpu", optional_argument
, NULL
, OPTION_TRACE_FPU
},
106 '\0', "on|off", "Perform FPU tracing",
107 trace_option_handler
},
108 { {"trace-branch", optional_argument
, NULL
, OPTION_TRACE_BRANCH
},
109 '\0', "on|off", "Perform branch tracing",
110 trace_option_handler
},
111 { {"trace-semantics", optional_argument
, NULL
, OPTION_TRACE_SEMANTICS
},
112 '\0', "on|off", "Perform ALU, FPU, MEMORY, and BRANCH tracing",
113 trace_option_handler
},
114 { {"trace-debug", optional_argument
, NULL
, OPTION_TRACE_DEBUG
},
115 '\0', "on|off", "Add information useful for debugging the simulator to the tracing output",
116 trace_option_handler
},
117 { {"trace-file", required_argument
, NULL
, OPTION_TRACE_FILE
},
118 '\0', "FILE NAME", "Specify tracing output file",
119 trace_option_handler
},
120 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
124 /* Set FIRST_TRACE .. LAST_TRACE according to arg. At least
125 FIRST_TRACE is always set */
128 set_trace_options (sd
, name
, first_trace
, last_trace
, arg
)
141 if (strcmp (arg
, "yes") == 0
142 || strcmp (arg
, "on") == 0
143 || strcmp (arg
, "1") == 0)
145 else if (strcmp (arg
, "no") == 0
146 || strcmp (arg
, "off") == 0
147 || strcmp (arg
, "0") == 0)
151 sim_io_eprintf (sd
, "Argument `%s' for `--trace%s' invalid, one of `on', `off', `yes', `no' expected\n", arg
, name
);
156 trace_nr
= first_trace
;
159 /* Set non-cpu specific values. */
162 case TRACE_EVENTS_IDX
:
163 STATE_EVENTS (sd
)->trace
= trace_val
;
165 case TRACE_DEBUG_IDX
:
166 STATE_TRACE_FLAGS (sd
)[trace_nr
] = trace_val
;
170 /* Set cpu values. */
171 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++)
173 CPU_TRACE_FLAGS (STATE_CPU (sd
, cpu_nr
))[trace_nr
] = trace_val
;
176 while (++trace_nr
< last_trace
);
183 trace_option_handler (sd
, opt
, arg
, is_command
)
195 sim_io_eprintf (sd
, "Tracing not compiled in, `-t' ignored\n");
197 return set_trace_options (sd
, "trace", 0, MAX_TRACE_VALUES
, arg
);
200 case OPTION_TRACE_INSN
:
201 if (WITH_TRACE_INSN_P
)
202 return set_trace_options (sd
, "-insn", TRACE_INSN_IDX
, -1, arg
);
204 sim_io_eprintf (sd
, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
207 case OPTION_TRACE_DECODE
:
208 if (WITH_TRACE_DECODE_P
)
209 return set_trace_options (sd
, "-decode", TRACE_DECODE_IDX
, -1, arg
);
211 sim_io_eprintf (sd
, "Decode tracing not compiled in, `--trace-decode' ignored\n");
214 case OPTION_TRACE_EXTRACT
:
215 if (WITH_TRACE_EXTRACT_P
)
216 return set_trace_options (sd
, "-extract", TRACE_EXTRACT_IDX
, -1, arg
);
218 sim_io_eprintf (sd
, "Extract tracing not compiled in, `--trace-extract' ignored\n");
221 case OPTION_TRACE_LINENUM
:
222 if (WITH_TRACE_LINENUM_P
&& WITH_TRACE_INSN_P
)
224 if (set_trace_options (sd
, "-linenum", TRACE_LINENUM_IDX
, -1, arg
) != SIM_RC_OK
225 || set_trace_options (sd
, "-linenum", TRACE_INSN_IDX
, -1, arg
) != SIM_RC_OK
)
229 sim_io_eprintf (sd
, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n");
232 case OPTION_TRACE_MEMORY
:
233 if (WITH_TRACE_MEMORY_P
)
234 return set_trace_options (sd
, "-memory", TRACE_MEMORY_IDX
, -1, arg
);
236 sim_io_eprintf (sd
, "Memory tracing not compiled in, `--trace-memory' ignored\n");
239 case OPTION_TRACE_MODEL
:
240 if (WITH_TRACE_MODEL_P
)
241 return set_trace_options (sd
, "-model", TRACE_MODEL_IDX
, -1, arg
);
243 sim_io_eprintf (sd
, "Model tracing not compiled in, `--trace-model' ignored\n");
246 case OPTION_TRACE_ALU
:
247 if (WITH_TRACE_ALU_P
)
248 return set_trace_options (sd
, "-alu", TRACE_ALU_IDX
, -1, arg
);
250 sim_io_eprintf (sd
, "ALU tracing not compiled in, `--trace-alu' ignored\n");
253 case OPTION_TRACE_CORE
:
254 if (WITH_TRACE_CORE_P
)
255 return set_trace_options (sd
, "-core", TRACE_CORE_IDX
, -1, arg
);
257 sim_io_eprintf (sd
, "CORE tracing not compiled in, `--trace-core' ignored\n");
260 case OPTION_TRACE_EVENTS
:
261 if (WITH_TRACE_EVENTS_P
)
262 return set_trace_options (sd
, "-events", TRACE_EVENTS_IDX
, -1, arg
);
264 sim_io_eprintf (sd
, "EVENTS tracing not compiled in, `--trace-events' ignored\n");
267 case OPTION_TRACE_FPU
:
268 if (WITH_TRACE_FPU_P
)
269 return set_trace_options (sd
, "-fpu", TRACE_FPU_IDX
, -1, arg
);
271 sim_io_eprintf (sd
, "FPU tracing not compiled in, `--trace-fpu' ignored\n");
274 case OPTION_TRACE_BRANCH
:
275 if (WITH_TRACE_BRANCH_P
)
276 return set_trace_options (sd
, "-branch", TRACE_BRANCH_IDX
, -1, arg
);
278 sim_io_eprintf (sd
, "Branch tracing not compiled in, `--trace-branch' ignored\n");
281 case OPTION_TRACE_SEMANTICS
:
284 && WITH_TRACE_MEMORY_P
285 && WITH_TRACE_BRANCH_P
)
287 if (set_trace_options (sd
, "-semantics", TRACE_ALU_IDX
, -1, arg
) != SIM_RC_OK
288 || set_trace_options (sd
, "-semantics", TRACE_FPU_IDX
, -1, arg
) != SIM_RC_OK
289 || set_trace_options (sd
, "-semantics", TRACE_MEMORY_IDX
, -1, arg
) != SIM_RC_OK
290 || set_trace_options (sd
, "-semantics", TRACE_BRANCH_IDX
, -1, arg
) != SIM_RC_OK
)
294 sim_io_eprintf (sd
, "Alu, fpu, memory, and/or branch tracing not compiled in, `--trace-semantics' ignored\n");
297 case OPTION_TRACE_DEBUG
:
298 if (WITH_TRACE_DEBUG_P
)
299 return set_trace_options (sd
, "-debug", TRACE_DEBUG_IDX
, -1, arg
);
301 sim_io_eprintf (sd
, "Tracing debug support not compiled in, `--trace-debug' ignored\n");
304 case OPTION_TRACE_FILE
:
306 sim_io_eprintf (sd
, "Tracing not compiled in, `--trace-file' ignored\n");
309 FILE *f
= fopen (arg
, "w");
313 sim_io_eprintf (sd
, "Unable to open trace output file `%s'\n", arg
);
316 for (n
= 0; n
< MAX_NR_PROCESSORS
; ++n
)
317 TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd
, n
))) = f
;
318 TRACE_FILE (STATE_TRACE_DATA (sd
)) = f
;
326 /* Install tracing support. */
329 trace_install (SIM_DESC sd
)
333 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
335 sim_add_option_table (sd
, trace_options
);
336 memset (STATE_TRACE_DATA (sd
), 0, sizeof (* STATE_TRACE_DATA (sd
)));
337 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
338 memset (CPU_TRACE_DATA (STATE_CPU (sd
, i
)), 0,
339 sizeof (* CPU_TRACE_DATA (STATE_CPU (sd
, i
))));
340 sim_module_add_uninstall_fn (sd
, trace_uninstall
);
345 trace_uninstall (SIM_DESC sd
)
348 FILE *sfile
= TRACE_FILE (STATE_TRACE_DATA (sd
));
353 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
355 FILE *cfile
= TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd
, i
)));
356 if (cfile
!= NULL
&& cfile
!= sfile
)
358 /* If output from different cpus is going to the same file,
359 avoid closing the file twice. */
360 for (j
= 0; j
< i
; ++j
)
361 if (TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd
, j
))) == cfile
)
370 trace_one_insn (SIM_DESC sd
, sim_cpu
*cpu
, address_word pc
,
371 int line_p
, const char *filename
, int linenum
,
372 const char *phase_wo_colon
, const char *fmt
,
376 char phase
[SIZE_PHASE
+2];
378 strncpy (phase
, phase_wo_colon
, SIZE_PHASE
);
383 trace_printf (sd
, cpu
, "%-*s %s:%-*d 0x%.*lx ",
386 SIZE_LINE_NUMBER
, linenum
,
389 trace_vprintf (sd
, cpu
, fmt
, ap
);
391 trace_printf (sd
, cpu
, "\n");
398 if (STATE_TEXT_SECTION (CPU_STATE (cpu
))
399 && pc
>= STATE_TEXT_START (CPU_STATE (cpu
))
400 && pc
< STATE_TEXT_END (CPU_STATE (cpu
)))
402 const char *pc_filename
= (const char *)0;
403 const char *pc_function
= (const char *)0;
404 unsigned int pc_linenum
= 0;
406 if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu
)),
407 STATE_TEXT_SECTION (CPU_STATE (cpu
)),
408 (struct symbol_cache_entry
**) 0,
409 pc
- STATE_TEXT_START (CPU_STATE (cpu
)),
410 &pc_filename
, &pc_function
, &pc_linenum
))
415 sprintf (p
, "#%-*d ", SIZE_LINE_NUMBER
, pc_linenum
);
420 sprintf (p
, "%-*s ", SIZE_LINE_NUMBER
+1, "---");
421 p
+= SIZE_LINE_NUMBER
+2;
426 sprintf (p
, "%s ", pc_function
);
429 else if (pc_filename
)
431 char *q
= (char *) strrchr (pc_filename
, '/');
432 sprintf (p
, "%s ", (q
) ? q
+1 : pc_filename
);
441 trace_printf (sd
, cpu
, "%-*s 0x%.*x %-*.*s ",
443 SIZE_PC
, (unsigned) pc
,
444 SIZE_LOCATION
, SIZE_LOCATION
, buf
);
446 trace_vprintf (sd
, cpu
, fmt
, ap
);
448 trace_printf (sd
, cpu
, "\n");
453 trace_vprintf (SIM_DESC sd
, sim_cpu
*cpu
, const char *fmt
, va_list ap
)
457 if (TRACE_FILE (CPU_TRACE_DATA (cpu
)) != NULL
)
458 vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu
)), fmt
, ap
);
460 sim_io_evprintf (sd
, fmt
, ap
);
464 if (TRACE_FILE (STATE_TRACE_DATA (sd
)) != NULL
)
465 vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd
)), fmt
, ap
);
467 sim_io_evprintf (sd
, fmt
, ap
);
472 trace_printf
VPARAMS ((SIM_DESC sd
, sim_cpu
*cpu
, const char *fmt
, ...))
474 #if !defined __STDC__ && !defined ALMOST_STDC
482 #if !defined __STDC__ && !defined ALMOST_STDC
483 sd
= va_arg (ap
, SIM_DESC
);
484 cpu
= va_arg (ap
, sim_cpu
*);
485 fmt
= va_arg (ap
, const char *);
488 trace_vprintf (sd
, cpu
, fmt
, ap
);
494 debug_printf
VPARAMS ((sim_cpu
*cpu
, const char *fmt
, ...))
496 #if !defined __STDC__ && !defined ALMOST_STDC
503 #if !defined __STDC__ && !defined ALMOST_STDC
504 cpu
= va_arg (ap
, sim_cpu
*);
505 fmt
= va_arg (ap
, const char *);
508 if (CPU_DEBUG_FILE (cpu
) == NULL
)
509 (* STATE_CALLBACK (CPU_STATE (cpu
))->evprintf_filtered
)
510 (STATE_CALLBACK (CPU_STATE (cpu
)), fmt
, ap
);
512 vfprintf (CPU_DEBUG_FILE (cpu
), fmt
, ap
);