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
,
72 static const OPTION trace_options
[] =
74 { {"trace", optional_argument
, NULL
, 't'},
75 't', "on|off", "Perform tracing",
76 trace_option_handler
},
77 { {"trace-insn", optional_argument
, NULL
, OPTION_TRACE_INSN
},
78 '\0', "on|off", "Perform instruction tracing",
79 trace_option_handler
},
80 { {"trace-decode", optional_argument
, NULL
, OPTION_TRACE_DECODE
},
81 '\0', "on|off", "Perform instruction decoding tracing",
82 trace_option_handler
},
83 { {"trace-extract", optional_argument
, NULL
, OPTION_TRACE_EXTRACT
},
84 '\0', "on|off", "Perform instruction extraction tracing",
85 trace_option_handler
},
86 { {"trace-linenum", optional_argument
, NULL
, OPTION_TRACE_LINENUM
},
87 '\0', "on|off", "Perform line number tracing (implies --trace-insn)",
88 trace_option_handler
},
89 { {"trace-memory", optional_argument
, NULL
, OPTION_TRACE_MEMORY
},
90 '\0', "on|off", "Perform memory tracing",
91 trace_option_handler
},
92 { {"trace-model", optional_argument
, NULL
, OPTION_TRACE_MODEL
},
93 '\0', "on|off", "Perform model tracing",
94 trace_option_handler
},
95 { {"trace-alu", optional_argument
, NULL
, OPTION_TRACE_ALU
},
96 '\0', "on|off", "Perform ALU tracing",
97 trace_option_handler
},
99 { {"trace-core", optional_argument
, NULL
, OPTION_TRACE_CORE
},
100 '\0', "on|off", "Perform CORE tracing",
101 trace_option_handler
},
103 { {"trace-events", optional_argument
, NULL
, OPTION_TRACE_EVENTS
},
104 '\0', "on|off", "Perform EVENTS tracing",
105 trace_option_handler
},
106 { {"trace-fpu", optional_argument
, NULL
, OPTION_TRACE_FPU
},
107 '\0', "on|off", "Perform FPU tracing",
108 trace_option_handler
},
109 { {"trace-branch", optional_argument
, NULL
, OPTION_TRACE_BRANCH
},
110 '\0', "on|off", "Perform branch tracing",
111 trace_option_handler
},
112 { {"trace-semantics", optional_argument
, NULL
, OPTION_TRACE_SEMANTICS
},
113 '\0', "on|off", "Perform ALU, FPU, MEMORY, and BRANCH tracing",
114 trace_option_handler
},
115 { {"trace-file", required_argument
, NULL
, OPTION_TRACE_FILE
},
116 '\0', "FILE NAME", "Specify tracing output file",
117 trace_option_handler
},
118 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
122 /* Set FIRST_TRACE .. LAST_TRACE according to arg. At least
123 FIRST_TRACE is always set */
126 set_trace_options (sd
, name
, first_trace
, last_trace
, arg
)
138 if (strcmp (arg
, "yes") == 0
139 || strcmp (arg
, "on") == 0
140 || strcmp (arg
, "1") == 0)
142 else if (strcmp (arg
, "no") == 0
143 || strcmp (arg
, "off") == 0
144 || strcmp (arg
, "0") == 0)
148 sim_io_eprintf (sd
, "Argument `%s' for `--trace%s' invalid, one of `on', `off', `yes', `no' expected\n", arg
, name
);
152 trace_nr
= first_trace
;
159 STATE_CORE(sd
)->trace
= trace_val
;
162 case TRACE_EVENTS_IDX
:
163 STATE_EVENTS(sd
)->trace
= trace_val
;
166 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++)
168 CPU_TRACE_FLAGS (STATE_CPU (sd
, cpu_nr
))[trace_nr
] = trace_val
;
171 while (++trace_nr
< last_trace
);
177 trace_option_handler (sd
, opt
, arg
, is_command
)
189 sim_io_eprintf (sd
, "Tracing not compiled in, `-t' ignored\n");
191 return set_trace_options (sd
, "trace", 0, MAX_TRACE_VALUES
, arg
);
194 case OPTION_TRACE_INSN
:
195 if (WITH_TRACE_INSN_P
)
196 return set_trace_options (sd
, "-insn", TRACE_INSN_IDX
, -1, arg
);
198 sim_io_eprintf (sd
, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
201 case OPTION_TRACE_DECODE
:
202 if (WITH_TRACE_DECODE_P
)
203 return set_trace_options (sd
, "-decode", TRACE_DECODE_IDX
, -1, arg
);
205 sim_io_eprintf (sd
, "Decode tracing not compiled in, `--trace-decode' ignored\n");
208 case OPTION_TRACE_EXTRACT
:
209 if (WITH_TRACE_EXTRACT_P
)
210 return set_trace_options (sd
, "-extract", TRACE_EXTRACT_IDX
, -1, arg
);
212 sim_io_eprintf (sd
, "Extract tracing not compiled in, `--trace-extract' ignored\n");
215 case OPTION_TRACE_LINENUM
:
216 if (WITH_TRACE_LINENUM_P
&& WITH_TRACE_INSN_P
)
218 if (set_trace_options (sd
, "-linenum", TRACE_LINENUM_IDX
, -1, arg
) != SIM_RC_OK
219 || set_trace_options (sd
, "-linenum", TRACE_INSN_IDX
, -1, arg
) != SIM_RC_OK
)
223 sim_io_eprintf (sd
, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n");
226 case OPTION_TRACE_MEMORY
:
227 if (WITH_TRACE_MEMORY_P
)
228 return set_trace_options (sd
, "-memory", TRACE_MEMORY_IDX
, -1, arg
);
230 sim_io_eprintf (sd
, "Memory tracing not compiled in, `--trace-memory' ignored\n");
233 case OPTION_TRACE_MODEL
:
234 if (WITH_TRACE_MODEL_P
)
235 return set_trace_options (sd
, "-model", TRACE_MODEL_IDX
, -1, arg
);
237 sim_io_eprintf (sd
, "Model tracing not compiled in, `--trace-model' ignored\n");
240 case OPTION_TRACE_ALU
:
241 if (WITH_TRACE_ALU_P
)
242 return set_trace_options (sd
, "-alu", TRACE_ALU_IDX
, -1, arg
);
244 sim_io_eprintf (sd
, "ALU tracing not compiled in, `--trace-alu' ignored\n");
247 case OPTION_TRACE_CORE
:
248 if (WITH_TRACE_CORE_P
)
249 return set_trace_options (sd
, "-core", TRACE_CORE_IDX
, -1, arg
);
251 sim_io_eprintf (sd
, "CORE tracing not compiled in, `--trace-core' ignored\n");
254 case OPTION_TRACE_EVENTS
:
255 if (WITH_TRACE_EVENTS_P
)
256 return set_trace_options (sd
, "-events", TRACE_EVENTS_IDX
, -1, arg
);
258 sim_io_eprintf (sd
, "EVENTS tracing not compiled in, `--trace-events' ignored\n");
261 case OPTION_TRACE_FPU
:
262 if (WITH_TRACE_FPU_P
)
263 return set_trace_options (sd
, "-fpu", TRACE_FPU_IDX
, -1, arg
);
265 sim_io_eprintf (sd
, "FPU tracing not compiled in, `--trace-fpu' ignored\n");
268 case OPTION_TRACE_BRANCH
:
269 if (WITH_TRACE_BRANCH_P
)
270 return set_trace_options (sd
, "-branch", TRACE_BRANCH_IDX
, -1, arg
);
272 sim_io_eprintf (sd
, "Branch tracing not compiled in, `--trace-branch' ignored\n");
275 case OPTION_TRACE_SEMANTICS
:
278 && WITH_TRACE_MEMORY_P
279 && WITH_TRACE_BRANCH_P
)
281 if (set_trace_options (sd
, "-semantics", TRACE_ALU_IDX
, -1, arg
) != SIM_RC_OK
282 || set_trace_options (sd
, "-semantics", TRACE_FPU_IDX
, -1, arg
) != SIM_RC_OK
283 || set_trace_options (sd
, "-semantics", TRACE_MEMORY_IDX
, -1, arg
) != SIM_RC_OK
284 || set_trace_options (sd
, "-semantics", TRACE_BRANCH_IDX
, -1, arg
) != SIM_RC_OK
)
288 sim_io_eprintf (sd
, "Alu, fpu, memory, and/or branch tracing not compiled in, `--trace-semantics' ignored\n");
291 case OPTION_TRACE_FILE
:
293 sim_io_eprintf (sd
, "Tracing not compiled in, `--trace-file' ignored\n");
296 FILE *f
= fopen (arg
, "w");
300 sim_io_eprintf (sd
, "Unable to open trace output file `%s'\n", arg
);
303 for (n
= 0; n
< MAX_NR_PROCESSORS
; ++n
)
304 TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd
, n
))) = f
;
312 /* Install tracing support. */
315 trace_install (SIM_DESC sd
)
319 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
321 sim_add_option_table (sd
, trace_options
);
322 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
323 memset (CPU_TRACE_DATA (STATE_CPU (sd
, i
)), 0,
324 sizeof (* CPU_TRACE_DATA (STATE_CPU (sd
, i
))));
325 sim_module_add_uninstall_fn (sd
, trace_uninstall
);
330 trace_uninstall (SIM_DESC sd
)
334 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
336 TRACE_DATA
*data
= CPU_TRACE_DATA (STATE_CPU (sd
, i
));
337 if (TRACE_FILE (data
) != NULL
)
339 /* If output from different cpus is going to the same file,
340 avoid closing the file twice. */
341 for (j
= 0; j
< i
; ++j
)
342 if (TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd
, j
)))
343 == TRACE_FILE (data
))
346 fclose (TRACE_FILE (data
));
352 trace_one_insn (SIM_DESC sd
, sim_cpu
*cpu
, address_word pc
,
353 int line_p
, const char *filename
, int linenum
,
354 const char *phase_wo_colon
, const char *fmt
,
358 char phase
[SIZE_PHASE
+2];
360 strncpy (phase
, phase_wo_colon
, SIZE_PHASE
);
365 trace_printf (sd
, cpu
, "%-*s %s:%-*d 0x%.*lx ",
368 SIZE_LINE_NUMBER
, linenum
,
371 trace_vprintf (sd
, cpu
, fmt
, ap
);
373 trace_printf (sd
, cpu
, "\n");
380 if (STATE_TEXT_SECTION (CPU_STATE (cpu
))
381 && pc
>= STATE_TEXT_START (CPU_STATE (cpu
))
382 && pc
< STATE_TEXT_END (CPU_STATE (cpu
)))
384 const char *pc_filename
= (const char *)0;
385 const char *pc_function
= (const char *)0;
386 unsigned int pc_linenum
= 0;
388 if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu
)),
389 STATE_TEXT_SECTION (CPU_STATE (cpu
)),
390 (struct symbol_cache_entry
**) 0,
391 pc
- STATE_TEXT_START (CPU_STATE (cpu
)),
392 &pc_filename
, &pc_function
, &pc_linenum
))
397 sprintf (p
, "#%-*d ", SIZE_LINE_NUMBER
, pc_linenum
);
402 sprintf (p
, "%-*s ", SIZE_LINE_NUMBER
+1, "---");
403 p
+= SIZE_LINE_NUMBER
+2;
408 sprintf (p
, "%s ", pc_function
);
411 else if (pc_filename
)
413 char *q
= (char *) strrchr (pc_filename
, '/');
414 sprintf (p
, "%s ", (q
) ? q
+1 : pc_filename
);
423 trace_printf (sd
, cpu
, "%-*s 0x%.*x %-*.*s ",
425 SIZE_PC
, (unsigned) pc
,
426 SIZE_LOCATION
, SIZE_LOCATION
, buf
);
428 trace_vprintf (sd
, cpu
, fmt
, ap
);
430 trace_printf (sd
, cpu
, "\n");
435 trace_vprintf (SIM_DESC sd
, sim_cpu
*cpu
, const char *fmt
, va_list ap
)
437 if (cpu
!= NULL
&& TRACE_FILE (CPU_TRACE_DATA (cpu
)) != NULL
)
438 vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu
)), fmt
, ap
);
440 sim_io_evprintf (sd
, fmt
, ap
);
444 trace_printf
VPARAMS ((SIM_DESC sd
, sim_cpu
*cpu
, const char *fmt
, ...))
455 sd
= va_arg (ap
, SIM_DESC
);
456 cpu
= va_arg (ap
, sim_cpu
*);
457 fmt
= va_arg (ap
, const char *);
460 trace_vprintf (sd
, cpu
, fmt
, ap
);
466 debug_printf
VPARAMS ((sim_cpu
*cpu
, const char *fmt
, ...))
476 cpu
= va_arg (ap
, sim_cpu
*);
477 fmt
= va_arg (ap
, const char *);
480 if (CPU_DEBUG_FILE (cpu
) == NULL
)
481 (* STATE_CALLBACK (CPU_STATE (cpu
))->evprintf_filtered
)
482 (STATE_CALLBACK (CPU_STATE (cpu
)), fmt
, ap
);
484 vfprintf (CPU_DEBUG_FILE (cpu
), fmt
, ap
);