Enable --trace-linenum support
[binutils-gdb.git] / sim / common / sim-trace.c
1 /* Simulator tracing/debugging support.
2 Copyright (C) 1997 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
4
5 This file is part of GDB, the GNU debugger.
6
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)
10 any later version.
11
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.
16
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. */
20
21 #include "sim-main.h"
22 #include "sim-io.h"
23 #include "sim-options.h"
24 #include "bfd.h"
25
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #else
29 #ifdef HAVE_STRINGS_H
30 #include <strings.h>
31 #endif
32 #endif
33
34 #ifndef SIZE_LOCATION
35 #define SIZE_LOCATION 20
36 #endif
37
38 #ifndef SIZE_PC
39 #define SIZE_PC 6
40 #endif
41
42 #ifndef SIZE_LINE_NUMBER
43 #define SIZE_LINE_NUMBER 4
44 #endif
45
46 static MODULE_UNINSTALL_FN trace_uninstall;
47
48 static DECLARE_OPTION_HANDLER (trace_option_handler);
49
50 #define OPTION_TRACE_INSN (OPTION_START + 0)
51 #define OPTION_TRACE_DECODE (OPTION_START + 1)
52 #define OPTION_TRACE_EXTRACT (OPTION_START + 2)
53 #define OPTION_TRACE_LINENUM (OPTION_START + 3)
54 #define OPTION_TRACE_MEMORY (OPTION_START + 4)
55 #define OPTION_TRACE_MODEL (OPTION_START + 5)
56 #define OPTION_TRACE_ALU (OPTION_START + 6)
57 #define OPTION_TRACE_CORE (OPTION_START + 7)
58 #define OPTION_TRACE_EVENTS (OPTION_START + 8)
59 #define OPTION_TRACE_FPU (OPTION_START + 9)
60 #define OPTION_TRACE_FILE (OPTION_START + 10)
61
62 static const OPTION trace_options[] =
63 {
64 { {"trace", no_argument, NULL, 't'},
65 't', NULL, "Perform tracing",
66 trace_option_handler },
67 { {"trace-insn", no_argument, NULL, OPTION_TRACE_INSN},
68 '\0', NULL, "Perform instruction tracing",
69 trace_option_handler },
70 { {"trace-decode", no_argument, NULL, OPTION_TRACE_DECODE},
71 '\0', NULL, "Perform instruction decoding tracing",
72 trace_option_handler },
73 { {"trace-extract", no_argument, NULL, OPTION_TRACE_EXTRACT},
74 '\0', NULL, "Perform instruction extraction tracing",
75 trace_option_handler },
76 { {"trace-linenum", no_argument, NULL, OPTION_TRACE_LINENUM},
77 '\0', NULL, "Perform line number tracing (implies --trace-insn)",
78 trace_option_handler },
79 { {"trace-memory", no_argument, NULL, OPTION_TRACE_MEMORY},
80 '\0', NULL, "Perform memory tracing",
81 trace_option_handler },
82 { {"trace-model", no_argument, NULL, OPTION_TRACE_MODEL},
83 '\0', NULL, "Perform model tracing",
84 trace_option_handler },
85 { {"trace-alu", no_argument, NULL, OPTION_TRACE_ALU},
86 '\0', NULL, "Perform ALU tracing",
87 trace_option_handler },
88 { {"trace-core", no_argument, NULL, OPTION_TRACE_CORE},
89 '\0', NULL, "Perform CORE tracing",
90 trace_option_handler },
91 { {"trace-events", no_argument, NULL, OPTION_TRACE_EVENTS},
92 '\0', NULL, "Perform EVENTS tracing",
93 trace_option_handler },
94 { {"trace-fpu", no_argument, NULL, OPTION_TRACE_FPU},
95 '\0', NULL, "Perform FPU tracing",
96 trace_option_handler },
97 { {"trace-file", required_argument, NULL, OPTION_TRACE_FILE},
98 '\0', "FILE NAME", "Specify tracing output file",
99 trace_option_handler },
100 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
101 };
102
103 static SIM_RC
104 trace_option_handler (sd, opt, arg)
105 SIM_DESC sd;
106 int opt;
107 char *arg;
108 {
109 int i,n;
110
111 switch (opt)
112 {
113 case 't' :
114 if (! WITH_TRACE)
115 sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n");
116 else
117 {
118 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
119 for (i = 0; i < MAX_TRACE_VALUES; ++i)
120 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[i] = 1;
121 STATE_CORE(sd)->trace = 1;
122 STATE_EVENTS(sd)->trace = 1;
123 }
124 break;
125
126 case OPTION_TRACE_INSN :
127 if (WITH_TRACE_INSN_P)
128 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
129 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_INSN_IDX] = 1;
130 else
131 sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n");
132 break;
133
134 case OPTION_TRACE_DECODE :
135 if (WITH_TRACE_DECODE_P)
136 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
137 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_DECODE_IDX] = 1;
138 else
139 sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n");
140 break;
141
142 case OPTION_TRACE_EXTRACT :
143 if (WITH_TRACE_EXTRACT_P)
144 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
145 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EXTRACT_IDX] = 1;
146 else
147 sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n");
148 break;
149
150 case OPTION_TRACE_LINENUM :
151 if (WITH_TRACE_LINENUM_P && WITH_TRACE_INSN_P)
152 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
153 {
154 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_LINENUM_IDX] = 1;
155 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_INSN_IDX] = 1;
156 }
157 else
158 sim_io_eprintf (sd, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n");
159 break;
160
161 case OPTION_TRACE_MEMORY :
162 if (WITH_TRACE_MEMORY_P)
163 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
164 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MEMORY_IDX] = 1;
165 else
166 sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n");
167 break;
168
169 case OPTION_TRACE_MODEL :
170 if (WITH_TRACE_MODEL_P)
171 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
172 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_MODEL_IDX] = 1;
173 else
174 sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n");
175 break;
176
177 case OPTION_TRACE_ALU :
178 if (WITH_TRACE_ALU_P)
179 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
180 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_ALU_IDX] = 1;
181 else
182 sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n");
183 break;
184
185 case OPTION_TRACE_CORE :
186 if (WITH_TRACE_CORE_P)
187 {
188 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
189 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_CORE_IDX] = 1;
190 STATE_CORE(sd)->trace = 1;
191 }
192 else
193 sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n");
194 break;
195
196 case OPTION_TRACE_EVENTS :
197 if (WITH_TRACE_EVENTS_P)
198 {
199 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
200 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_EVENTS_IDX] = 1;
201 STATE_EVENTS(sd)->trace = 1;
202 }
203 else
204 sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n");
205 break;
206
207 case OPTION_TRACE_FPU :
208 if (WITH_TRACE_FPU_P)
209 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
210 CPU_TRACE_FLAGS (STATE_CPU (sd, n))[TRACE_FPU_IDX] = 1;
211 else
212 sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n");
213 break;
214
215 case OPTION_TRACE_FILE :
216 if (! WITH_TRACE)
217 sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n");
218 else
219 {
220 FILE *f = fopen (arg, "w");
221
222 if (f == NULL)
223 {
224 sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg);
225 return SIM_RC_FAIL;
226 }
227 for (n = 0; n < MAX_NR_PROCESSORS; ++n)
228 TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f;
229 }
230 break;
231 }
232
233 return SIM_RC_OK;
234 }
235 \f
236 /* Install tracing support. */
237
238 SIM_RC
239 trace_install (SIM_DESC sd)
240 {
241 int i;
242
243 sim_add_option_table (sd, trace_options);
244 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
245 memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0,
246 sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i))));
247 sim_module_add_uninstall_fn (sd, trace_uninstall);
248 return SIM_RC_OK;
249 }
250
251 static void
252 trace_uninstall (SIM_DESC sd)
253 {
254 int i;
255
256 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
257 {
258 TRACE_DATA *data = CPU_TRACE_DATA (STATE_CPU (sd, i));
259 if (TRACE_FILE (data) != NULL)
260 fclose (TRACE_FILE (data));
261 }
262 }
263 \f
264 void
265 trace_one_insn (SIM_DESC sd, sim_cpu *cpu, const char *filename,
266 int linenum, int idecode, address_word pc, const char *name)
267 {
268 if (idecode)
269 trace_printf(sd, cpu, "%s:%-*d 0x%.*lx (decode) %s\n",
270 filename,
271 SIZE_LINE_NUMBER, linenum,
272 SIZE_PC, (long)pc,
273 name);
274
275 else if (!TRACE_LINENUM_P (cpu))
276 trace_printf(sd, cpu, "%s:%-*d 0x%.*lx %s\n",
277 filename,
278 SIZE_LINE_NUMBER, linenum,
279 SIZE_PC, (long)pc,
280 name);
281
282 else
283 {
284 char buf[256];
285
286 buf[0] = 0;
287 if (STATE_TEXT_SECTION (CPU_STATE (cpu))
288 && pc >= STATE_TEXT_START (CPU_STATE (cpu))
289 && pc < STATE_TEXT_END (CPU_STATE (cpu)))
290 {
291 const char *pc_filename = (const char *)0;
292 const char *pc_function = (const char *)0;
293 unsigned int pc_linenum = 0;
294
295 if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu)),
296 STATE_TEXT_SECTION (CPU_STATE (cpu)),
297 (struct symbol_cache_entry **) 0,
298 pc - STATE_TEXT_START (CPU_STATE (cpu)),
299 &pc_filename, &pc_function, &pc_linenum))
300 {
301 char *p = buf;
302 if (pc_linenum)
303 {
304 sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum);
305 p += strlen (p);
306 }
307 else
308 {
309 sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---");
310 p += SIZE_LINE_NUMBER+2;
311 }
312
313 if (pc_function)
314 {
315 sprintf (p, "%s ", pc_function);
316 p += strlen (p);
317 }
318 else if (filename)
319 {
320 char *q = (char *) strrchr (filename, '/');
321 sprintf (p, "%s ", (q) ? q+1 : filename);
322 p += strlen (p);
323 }
324
325 if (*p == ' ')
326 *p = '\0';
327 }
328 }
329
330 trace_printf (sd, cpu, "0x%.*x %-*.*s %s\n",
331 SIZE_PC, (unsigned) pc,
332 SIZE_LOCATION, SIZE_LOCATION, buf,
333 name);
334 }
335 }
336 \f
337 void
338 trace_printf VPARAMS ((SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...))
339 {
340 #ifndef __STDC__
341 SIM_DESC sd;
342 sim_cpu *cpu;
343 const char *fmt;
344 #endif
345 va_list ap;
346
347 VA_START (ap, fmt);
348 #ifndef __STDC__
349 sd = va_arg (ap, SIM_DESC);
350 cpu = va_arg (ap, sim_cpu *);
351 fmt = va_arg (ap, const char *);
352 #endif
353
354 if (cpu != NULL && TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL)
355 vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap);
356 else
357 sim_io_evprintf (sd, fmt, ap);
358
359 va_end (ap);
360 }
361
362 void
363 debug_printf VPARAMS ((sim_cpu *cpu, const char *fmt, ...))
364 {
365 #ifndef __STDC__
366 sim_cpu *cpu;
367 const char *fmt;
368 #endif
369 va_list ap;
370
371 VA_START (ap, fmt);
372 #ifndef __STDC__
373 cpu = va_arg (ap, sim_cpu *);
374 fmt = va_arg (ap, const char *);
375 #endif
376
377 if (CPU_DEBUG_FILE (cpu) == NULL)
378 (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered)
379 (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap);
380 else
381 vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap);
382
383 va_end (ap);
384 }