nuke lseek
[deliverable/binutils-gdb.git] / sim / common / sim-trace.c
CommitLineData
e9b2f579
DE
1/* Simulator tracing/debugging support.
2 Copyright (C) 1997 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License along
18with this program; if not, write to the Free Software Foundation, Inc.,
1959 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "sim-main.h"
22#include "sim-io.h"
3971886a 23#include "sim-options.h"
a7724171 24#include "bfd.h"
e9b2f579 25
50a2a691
AC
26#include "sim-assert.h"
27
3971886a
AC
28#ifdef HAVE_STRING_H
29#include <string.h>
30#else
31#ifdef HAVE_STRINGS_H
32#include <strings.h>
33#endif
34#endif
35
7b167b09
MM
36#ifndef SIZE_PHASE
37#define SIZE_PHASE 8
38#endif
39
a7724171
MM
40#ifndef SIZE_LOCATION
41#define SIZE_LOCATION 20
42#endif
43
44#ifndef SIZE_PC
45#define SIZE_PC 6
46#endif
47
48#ifndef SIZE_LINE_NUMBER
49#define SIZE_LINE_NUMBER 4
50#endif
51
3971886a
AC
52static MODULE_UNINSTALL_FN trace_uninstall;
53
54static DECLARE_OPTION_HANDLER (trace_option_handler);
55
7b167b09
MM
56enum {
57 OPTION_TRACE_INSN = OPTION_START,
58 OPTION_TRACE_DECODE,
59 OPTION_TRACE_EXTRACT,
60 OPTION_TRACE_LINENUM,
61 OPTION_TRACE_MEMORY,
62 OPTION_TRACE_MODEL,
63 OPTION_TRACE_ALU,
64 OPTION_TRACE_CORE,
65 OPTION_TRACE_EVENTS,
66 OPTION_TRACE_FPU,
67 OPTION_TRACE_BRANCH,
68 OPTION_TRACE_SEMANTICS,
091521c4 69 OPTION_TRACE_DEBUG,
7b167b09
MM
70 OPTION_TRACE_FILE
71};
3971886a
AC
72
73static const OPTION trace_options[] =
74{
50a2a691
AC
75 { {"trace", optional_argument, NULL, 't'},
76 't', "on|off", "Perform tracing",
3971886a 77 trace_option_handler },
50a2a691
AC
78 { {"trace-insn", optional_argument, NULL, OPTION_TRACE_INSN},
79 '\0', "on|off", "Perform instruction tracing",
3971886a 80 trace_option_handler },
50a2a691
AC
81 { {"trace-decode", optional_argument, NULL, OPTION_TRACE_DECODE},
82 '\0', "on|off", "Perform instruction decoding tracing",
3971886a 83 trace_option_handler },
50a2a691
AC
84 { {"trace-extract", optional_argument, NULL, OPTION_TRACE_EXTRACT},
85 '\0', "on|off", "Perform instruction extraction tracing",
3971886a 86 trace_option_handler },
50a2a691
AC
87 { {"trace-linenum", optional_argument, NULL, OPTION_TRACE_LINENUM},
88 '\0', "on|off", "Perform line number tracing (implies --trace-insn)",
3971886a 89 trace_option_handler },
50a2a691
AC
90 { {"trace-memory", optional_argument, NULL, OPTION_TRACE_MEMORY},
91 '\0', "on|off", "Perform memory tracing",
3971886a 92 trace_option_handler },
50a2a691
AC
93 { {"trace-model", optional_argument, NULL, OPTION_TRACE_MODEL},
94 '\0', "on|off", "Perform model tracing",
3971886a 95 trace_option_handler },
50a2a691
AC
96 { {"trace-alu", optional_argument, NULL, OPTION_TRACE_ALU},
97 '\0', "on|off", "Perform ALU tracing",
3971886a 98 trace_option_handler },
50a2a691
AC
99 { {"trace-core", optional_argument, NULL, OPTION_TRACE_CORE},
100 '\0', "on|off", "Perform CORE tracing",
3971886a 101 trace_option_handler },
50a2a691
AC
102 { {"trace-events", optional_argument, NULL, OPTION_TRACE_EVENTS},
103 '\0', "on|off", "Perform EVENTS tracing",
3971886a 104 trace_option_handler },
50a2a691
AC
105 { {"trace-fpu", optional_argument, NULL, OPTION_TRACE_FPU},
106 '\0', "on|off", "Perform FPU tracing",
3971886a 107 trace_option_handler },
50a2a691
AC
108 { {"trace-branch", optional_argument, NULL, OPTION_TRACE_BRANCH},
109 '\0', "on|off", "Perform branch tracing",
7b167b09 110 trace_option_handler },
50a2a691
AC
111 { {"trace-semantics", optional_argument, NULL, OPTION_TRACE_SEMANTICS},
112 '\0', "on|off", "Perform ALU, FPU, MEMORY, and BRANCH tracing",
7b167b09 113 trace_option_handler },
091521c4
DE
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 },
3971886a
AC
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 }
121};
122
50a2a691
AC
123
124/* Set FIRST_TRACE .. LAST_TRACE according to arg. At least
125 FIRST_TRACE is always set */
126
3971886a 127static SIM_RC
50a2a691
AC
128set_trace_options (sd, name, first_trace, last_trace, arg)
129 SIM_DESC sd;
130 const char *name;
131 int first_trace;
132 int last_trace;
133 const char *arg;
134{
135 int trace_nr;
136 int cpu_nr;
137 int trace_val = 1;
091521c4 138
50a2a691
AC
139 if (arg != NULL)
140 {
141 if (strcmp (arg, "yes") == 0
142 || strcmp (arg, "on") == 0
143 || strcmp (arg, "1") == 0)
144 trace_val = 1;
145 else if (strcmp (arg, "no") == 0
146 || strcmp (arg, "off") == 0
147 || strcmp (arg, "0") == 0)
148 trace_val = 0;
149 else
150 {
151 sim_io_eprintf (sd, "Argument `%s' for `--trace%s' invalid, one of `on', `off', `yes', `no' expected\n", arg, name);
152 return SIM_RC_FAIL;
153 }
154 }
091521c4 155
50a2a691
AC
156 trace_nr = first_trace;
157 do
158 {
091521c4 159 /* Set non-cpu specific values. */
50a2a691
AC
160 switch (trace_nr)
161 {
50a2a691 162 case TRACE_EVENTS_IDX:
091521c4
DE
163 STATE_EVENTS (sd)->trace = trace_val;
164 break;
165 case TRACE_DEBUG_IDX:
166 STATE_TRACE_FLAGS (sd)[trace_nr] = trace_val;
50a2a691
AC
167 break;
168 }
091521c4
DE
169
170 /* Set cpu values. */
50a2a691
AC
171 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
172 {
173 CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr] = trace_val;
174 }
175 }
176 while (++trace_nr < last_trace);
091521c4 177
50a2a691
AC
178 return SIM_RC_OK;
179}
180
181
182static SIM_RC
183trace_option_handler (sd, opt, arg, is_command)
3971886a
AC
184 SIM_DESC sd;
185 int opt;
186 char *arg;
50a2a691 187 int is_command;
3971886a 188{
50a2a691 189 int n;
3971886a
AC
190
191 switch (opt)
192 {
193 case 't' :
194 if (! WITH_TRACE)
195 sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n");
196 else
50a2a691 197 return set_trace_options (sd, "trace", 0, MAX_TRACE_VALUES, arg);
3971886a
AC
198 break;
199
200 case OPTION_TRACE_INSN :
201 if (WITH_TRACE_INSN_P)
50a2a691 202 return set_trace_options (sd, "-insn", TRACE_INSN_IDX, -1, arg);
3971886a
AC
203 else
204 sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
205 break;
206
207 case OPTION_TRACE_DECODE :
208 if (WITH_TRACE_DECODE_P)
50a2a691 209 return set_trace_options (sd, "-decode", TRACE_DECODE_IDX, -1, arg);
3971886a
AC
210 else
211 sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n");
212 break;
213
214 case OPTION_TRACE_EXTRACT :
215 if (WITH_TRACE_EXTRACT_P)
50a2a691 216 return set_trace_options (sd, "-extract", TRACE_EXTRACT_IDX, -1, arg);
3971886a
AC
217 else
218 sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n");
219 break;
220
221 case OPTION_TRACE_LINENUM :
a7724171 222 if (WITH_TRACE_LINENUM_P && WITH_TRACE_INSN_P)
50a2a691
AC
223 {
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)
226 return SIM_RC_FAIL;
227 }
3971886a 228 else
a7724171 229 sim_io_eprintf (sd, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n");
3971886a
AC
230 break;
231
232 case OPTION_TRACE_MEMORY :
233 if (WITH_TRACE_MEMORY_P)
50a2a691 234 return set_trace_options (sd, "-memory", TRACE_MEMORY_IDX, -1, arg);
3971886a
AC
235 else
236 sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n");
237 break;
238
239 case OPTION_TRACE_MODEL :
240 if (WITH_TRACE_MODEL_P)
50a2a691 241 return set_trace_options (sd, "-model", TRACE_MODEL_IDX, -1, arg);
3971886a
AC
242 else
243 sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n");
244 break;
245
246 case OPTION_TRACE_ALU :
247 if (WITH_TRACE_ALU_P)
50a2a691 248 return set_trace_options (sd, "-alu", TRACE_ALU_IDX, -1, arg);
3971886a
AC
249 else
250 sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n");
251 break;
252
253 case OPTION_TRACE_CORE :
254 if (WITH_TRACE_CORE_P)
50a2a691 255 return set_trace_options (sd, "-core", TRACE_CORE_IDX, -1, arg);
3971886a
AC
256 else
257 sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n");
258 break;
259
260 case OPTION_TRACE_EVENTS :
261 if (WITH_TRACE_EVENTS_P)
50a2a691 262 return set_trace_options (sd, "-events", TRACE_EVENTS_IDX, -1, arg);
3971886a
AC
263 else
264 sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n");
265 break;
266
267 case OPTION_TRACE_FPU :
268 if (WITH_TRACE_FPU_P)
50a2a691 269 return set_trace_options (sd, "-fpu", TRACE_FPU_IDX, -1, arg);
3971886a
AC
270 else
271 sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n");
272 break;
273
7b167b09
MM
274 case OPTION_TRACE_BRANCH :
275 if (WITH_TRACE_BRANCH_P)
50a2a691 276 return set_trace_options (sd, "-branch", TRACE_BRANCH_IDX, -1, arg);
7b167b09
MM
277 else
278 sim_io_eprintf (sd, "Branch tracing not compiled in, `--trace-branch' ignored\n");
279 break;
280
281 case OPTION_TRACE_SEMANTICS :
50a2a691
AC
282 if (WITH_TRACE_ALU_P
283 && WITH_TRACE_FPU_P
284 && WITH_TRACE_MEMORY_P
285 && WITH_TRACE_BRANCH_P)
286 {
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)
291 return SIM_RC_FAIL;
292 }
7b167b09 293 else
50a2a691 294 sim_io_eprintf (sd, "Alu, fpu, memory, and/or branch tracing not compiled in, `--trace-semantics' ignored\n");
7b167b09
MM
295 break;
296
091521c4
DE
297 case OPTION_TRACE_DEBUG :
298 if (WITH_TRACE_DEBUG_P)
299 return set_trace_options (sd, "-debug", TRACE_DEBUG_IDX, -1, arg);
300 else
301 sim_io_eprintf (sd, "Tracing debug support not compiled in, `--trace-debug' ignored\n");
302 break;
303
3971886a
AC
304 case OPTION_TRACE_FILE :
305 if (! WITH_TRACE)
306 sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n");
307 else
308 {
309 FILE *f = fopen (arg, "w");
310
311 if (f == NULL)
312 {
313 sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg);
314 return SIM_RC_FAIL;
315 }
316 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
317 TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f;
091521c4 318 TRACE_FILE (STATE_TRACE_DATA (sd)) = f;
3971886a
AC
319 }
320 break;
321 }
322
323 return SIM_RC_OK;
324}
325\f
326/* Install tracing support. */
327
328SIM_RC
329trace_install (SIM_DESC sd)
330{
331 int i;
332
50a2a691
AC
333 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
334
3971886a 335 sim_add_option_table (sd, trace_options);
091521c4 336 memset (STATE_TRACE_DATA (sd), 0, sizeof (* STATE_TRACE_DATA (sd)));
3971886a
AC
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);
341 return SIM_RC_OK;
342}
343
344static void
345trace_uninstall (SIM_DESC sd)
346{
ea4e4493 347 int i,j;
091521c4
DE
348 FILE *sfile = TRACE_FILE (STATE_TRACE_DATA (sd));
349
350 if (sfile != NULL)
351 fclose (sfile);
3971886a
AC
352
353 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
354 {
091521c4
DE
355 FILE *cfile = TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, i)));
356 if (cfile != NULL && cfile != sfile)
ea4e4493
DE
357 {
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)
091521c4 361 if (TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, j))) == cfile)
ea4e4493
DE
362 break;
363 if (i == j)
091521c4 364 fclose (cfile);
ea4e4493 365 }
3971886a
AC
366 }
367}
368\f
e9b2f579 369void
d0adfefd 370trace_one_insn (SIM_DESC sd, sim_cpu *cpu, address_word pc,
7b167b09 371 int line_p, const char *filename, int linenum,
381f42ef
AC
372 const char *phase_wo_colon, const char *fmt,
373 ...)
a7724171 374{
381f42ef 375 va_list ap;
7b167b09
MM
376 char phase[SIZE_PHASE+2];
377
378 strncpy (phase, phase_wo_colon, SIZE_PHASE);
379 strcat (phase, ":");
380
d0adfefd 381 if (!line_p)
381f42ef
AC
382 {
383 trace_printf (sd, cpu, "%-*s %s:%-*d 0x%.*lx ",
384 SIZE_PHASE+1, phase,
385 filename,
386 SIZE_LINE_NUMBER, linenum,
387 SIZE_PC, (long)pc);
388 va_start (ap, fmt);
389 trace_vprintf (sd, cpu, fmt, ap);
390 va_end (ap);
391 trace_printf (sd, cpu, "\n");
392 }
a7724171
MM
393 else
394 {
395 char buf[256];
396
397 buf[0] = 0;
398 if (STATE_TEXT_SECTION (CPU_STATE (cpu))
399 && pc >= STATE_TEXT_START (CPU_STATE (cpu))
400 && pc < STATE_TEXT_END (CPU_STATE (cpu)))
401 {
402 const char *pc_filename = (const char *)0;
403 const char *pc_function = (const char *)0;
404 unsigned int pc_linenum = 0;
405
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))
411 {
412 char *p = buf;
413 if (pc_linenum)
414 {
415 sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
416 p += strlen (p);
417 }
418 else
419 {
420 sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
421 p += SIZE_LINE_NUMBER+2;
422 }
423
424 if (pc_function)
425 {
426 sprintf (p, "%s ", pc_function);
427 p += strlen (p);
428 }
d0adfefd 429 else if (pc_filename)
a7724171 430 {
d0adfefd
MM
431 char *q = (char *) strrchr (pc_filename, '/');
432 sprintf (p, "%s ", (q) ? q+1 : pc_filename);
a7724171
MM
433 p += strlen (p);
434 }
435
436 if (*p == ' ')
437 *p = '\0';
438 }
439 }
440
381f42ef 441 trace_printf (sd, cpu, "%-*s 0x%.*x %-*.*s ",
7b167b09 442 SIZE_PHASE+1, phase,
a7724171 443 SIZE_PC, (unsigned) pc,
381f42ef
AC
444 SIZE_LOCATION, SIZE_LOCATION, buf);
445 va_start (ap, fmt);
446 trace_vprintf (sd, cpu, fmt, ap);
447 va_end (ap);
448 trace_printf (sd, cpu, "\n");
a7724171
MM
449 }
450}
451\f
381f42ef
AC
452void
453trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap)
454{
091521c4
DE
455 if (cpu != NULL)
456 {
457 if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
458 vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
459 else
460 sim_io_evprintf (sd, fmt, ap);
461 }
381f42ef 462 else
091521c4
DE
463 {
464 if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL)
465 vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap);
466 else
467 sim_io_evprintf (sd, fmt, ap);
468 }
381f42ef
AC
469}
470
a7724171 471void
3971886a 472trace_printf VPARAMS ((SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...))
e9b2f579 473{
091521c4 474#if !defined __STDC__ && !defined ALMOST_STDC
3971886a 475 SIM_DESC sd;
e9b2f579
DE
476 sim_cpu *cpu;
477 const char *fmt;
478#endif
479 va_list ap;
480
481 VA_START (ap, fmt);
091521c4 482#if !defined __STDC__ && !defined ALMOST_STDC
3971886a 483 sd = va_arg (ap, SIM_DESC);
e9b2f579
DE
484 cpu = va_arg (ap, sim_cpu *);
485 fmt = va_arg (ap, const char *);
486#endif
487
381f42ef 488 trace_vprintf (sd, cpu, fmt, ap);
e9b2f579
DE
489
490 va_end (ap);
491}
492
493void
494debug_printf VPARAMS ((sim_cpu *cpu, const char *fmt, ...))
495{
091521c4 496#if !defined __STDC__ && !defined ALMOST_STDC
e9b2f579
DE
497 sim_cpu *cpu;
498 const char *fmt;
499#endif
500 va_list ap;
501
502 VA_START (ap, fmt);
091521c4 503#if !defined __STDC__ && !defined ALMOST_STDC
e9b2f579
DE
504 cpu = va_arg (ap, sim_cpu *);
505 fmt = va_arg (ap, const char *);
506#endif
507
508 if (CPU_DEBUG_FILE (cpu) == NULL)
509 (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
510 (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap);
511 else
512 vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap);
513
514 va_end (ap);
515}
This page took 0.062147 seconds and 4 git commands to generate.