sim/rx: add some missing includes
[binutils-gdb.git] / sim / rx / trace.c
1 /* trace.c --- tracing output for the RX simulator.
2
3 Copyright (C) 2005-2021 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
5
6 This file is part of the GNU simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21
22 #include "config.h"
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <ctype.h>
30
31 #include "bfd.h"
32 #include "dis-asm.h"
33
34 #include "cpu.h"
35 #include "mem.h"
36 #include "load.h"
37 #include "trace.h"
38
39 static int
40 sim_dis_read (bfd_vma memaddr, bfd_byte * ptr, unsigned int length,
41 struct disassemble_info *info)
42 {
43 int i;
44
45 if (rx_big_endian)
46 {
47 /* See load.c for an explanation of this. */
48 for (i=0; i<length; i++)
49 ptr[i] = mem_get_qi ((memaddr + i) ^ 3);
50 }
51 else
52 mem_get_blk (memaddr, ptr, length);
53 return 0;
54 }
55
56 /* Filter out (in place) symbols that are useless for disassembly.
57 COUNT is the number of elements in SYMBOLS.
58 Return the number of useful symbols. */
59
60 static long
61 remove_useless_symbols (asymbol ** symbols, long count)
62 {
63 register asymbol **in_ptr = symbols, **out_ptr = symbols;
64
65 while (--count >= 0)
66 {
67 asymbol *sym = *in_ptr++;
68
69 if (strstr (sym->name, "gcc2_compiled"))
70 continue;
71 if (sym->name == NULL || sym->name[0] == '\0')
72 continue;
73 if (sym->flags & (BSF_DEBUGGING))
74 continue;
75 if (bfd_is_und_section (sym->section)
76 || bfd_is_com_section (sym->section))
77 continue;
78
79 *out_ptr++ = sym;
80 }
81 return out_ptr - symbols;
82 }
83
84 static int
85 compare_symbols (const PTR ap, const PTR bp)
86 {
87 const asymbol *a = *(const asymbol **) ap;
88 const asymbol *b = *(const asymbol **) bp;
89
90 if (bfd_asymbol_value (a) > bfd_asymbol_value (b))
91 return 1;
92 else if (bfd_asymbol_value (a) < bfd_asymbol_value (b))
93 return -1;
94 return 0;
95 }
96
97 static char opbuf[1000];
98
99 static int
100 op_printf (char *buf, char *fmt, ...)
101 {
102 int ret;
103 va_list ap;
104
105 va_start (ap, fmt);
106 ret = vsprintf (opbuf + strlen (opbuf), fmt, ap);
107 va_end (ap);
108 return ret;
109 }
110
111 static bfd * current_bfd = NULL;
112 static asymbol ** symtab = NULL;
113 static int symcount = 0;
114 static asection * code_section = NULL;
115 static bfd_vma code_base = 0;
116 static struct disassemble_info info;
117
118 void
119 sim_disasm_init (bfd *prog)
120 {
121 current_bfd = prog;
122 }
123
124 typedef struct Files
125 {
126 struct Files *next;
127 char *filename;
128 int nlines;
129 char **lines;
130 char *data;
131 } Files;
132 Files *files = 0;
133
134 static char *
135 load_file_and_line (const char *filename, int lineno)
136 {
137 Files *f;
138 for (f = files; f; f = f->next)
139 if (strcmp (f->filename, filename) == 0)
140 break;
141 if (!f)
142 {
143 FILE *file;
144 int i;
145 struct stat s;
146 const char *found_filename, *slash;
147
148 found_filename = filename;
149 while (1)
150 {
151 if (stat (found_filename, &s) == 0)
152 break;
153 slash = strchr (found_filename, '/');
154 if (!slash)
155 return "";
156 found_filename = slash + 1;
157 }
158
159 f = (Files *) malloc (sizeof (Files));
160 f->next = files;
161 files = f;
162 f->filename = strdup (filename);
163 f->data = (char *) malloc (s.st_size + 2);
164 file = fopen (found_filename, "rb");
165 fread (f->data, 1, s.st_size, file);
166 f->data[s.st_size] = 0;
167 fclose (file);
168
169 f->nlines = 1;
170 for (i = 0; i < s.st_size; i++)
171 if (f->data[i] == '\n')
172 f->nlines++;
173 f->lines = (char **) malloc (f->nlines * sizeof (char *));
174 f->lines[0] = f->data;
175 f->nlines = 1;
176 for (i = 0; i < s.st_size; i++)
177 if (f->data[i] == '\n')
178 {
179 f->lines[f->nlines] = f->data + i + 1;
180 while (*f->lines[f->nlines] == ' '
181 || *f->lines[f->nlines] == '\t')
182 f->lines[f->nlines]++;
183 f->nlines++;
184 f->data[i] = 0;
185 }
186 }
187 if (lineno < 1 || lineno > f->nlines)
188 return "";
189 return f->lines[lineno - 1];
190 }
191
192 int
193 sim_get_current_source_location (const char ** pfilename,
194 const char ** pfunctionname,
195 unsigned int * plineno)
196 {
197 static int initted = 0;
198 int mypc = get_reg (pc);
199
200 if (current_bfd == NULL)
201 return 0;
202
203 if (!initted)
204 {
205 int storage;
206 asection * s;
207
208 initted = 1;
209 memset (& info, 0, sizeof (info));
210 INIT_DISASSEMBLE_INFO (info, stdout, op_printf);
211 info.read_memory_func = sim_dis_read;
212 info.arch = bfd_get_arch (current_bfd);
213 info.mach = bfd_get_mach (current_bfd);
214 if (info.mach == 0)
215 info.arch = bfd_arch_rx;
216
217 disassemble_init_for_target (& info);
218
219 storage = bfd_get_symtab_upper_bound (current_bfd);
220 if (storage > 0)
221 {
222 symtab = (asymbol **) malloc (storage);
223 symcount = bfd_canonicalize_symtab (current_bfd, symtab);
224 symcount = remove_useless_symbols (symtab, symcount);
225 qsort (symtab, symcount, sizeof (asymbol *), compare_symbols);
226 }
227
228 for (s = current_bfd->sections; s; s = s->next)
229 {
230 if (s->flags & SEC_CODE || code_section == 0)
231 {
232 code_section = s;
233 code_base = bfd_section_lma (s);
234 break;
235 }
236 }
237 }
238
239 *pfilename = *pfunctionname = NULL;
240 *plineno = 0;
241
242 bfd_find_nearest_line
243 (current_bfd, code_section, symtab, mypc - code_base,
244 pfilename, pfunctionname, plineno);
245
246 return 1;
247 }
248
249 void
250 sim_disasm_one (void)
251 {
252 static int last_sym = -1;
253 static const char * prev_filename = "";
254 static int prev_lineno = 0;
255 const char * filename;
256 const char * functionname;
257 unsigned int lineno;
258 int sym, bestaddr;
259 int min, max, i;
260 int save_trace = trace;
261 int mypc = get_reg (pc);
262
263 if (! sim_get_current_source_location (& filename, & functionname, & lineno))
264 return;
265
266 trace = 0;
267
268 if (filename && functionname && lineno)
269 {
270 if (lineno != prev_lineno || strcmp (prev_filename, filename))
271 {
272 char * the_line = load_file_and_line (filename, lineno);
273 const char * slash = strrchr (filename, '/');
274
275 if (!slash)
276 slash = filename;
277 else
278 slash++;
279 printf
280 ("========================================"
281 "=====================================\n");
282 printf ("\033[37;41m %s:%d: \033[33;40m %s\033[K\033[0m\n",
283 slash, lineno, the_line);
284 }
285 prev_lineno = lineno;
286 prev_filename = filename;
287 }
288
289 min = -1;
290 max = symcount;
291 while (min < max - 1)
292 {
293 bfd_vma sa;
294
295 sym = (min + max) / 2;
296 sa = bfd_asymbol_value (symtab[sym]);
297 /*printf("checking %4d %08x %s\n",
298 sym, sa, bfd_asymbol_name (symtab[sym])); */
299 if (sa > mypc)
300 max = sym;
301 else if (sa < mypc)
302 min = sym;
303 else
304 {
305 min = sym;
306 break;
307 }
308 }
309
310 if (min != -1 && min != last_sym)
311 {
312 bestaddr = bfd_asymbol_value (symtab[min]);
313 printf ("\033[43;30m%s", bfd_asymbol_name (symtab[min]));
314 if (bestaddr != mypc)
315 printf ("+%d", mypc - bestaddr);
316 printf (":\t\t\t\033[0m\n");
317 last_sym = min;
318 #if 0
319 if (trace == 1)
320 if (strcmp (bfd_asymbol_name (symtab[min]), "abort") == 0
321 || strcmp (bfd_asymbol_name (symtab[min]), "exit") == 0)
322 trace = 0;
323 #endif
324 }
325
326 opbuf[0] = 0;
327 #ifdef CYCLE_ACCURATE
328 printf ("\033[33m %04u %06x: ", (int)(regs.cycle_count % 10000), mypc);
329 #else
330 printf ("\033[33m %06x: ", mypc);
331
332 #endif
333
334 max = print_insn_rx (mypc, & info);
335
336 for (i = 0; i < max; i++)
337 {
338 if (rx_big_endian)
339 printf ("%02x", mem_get_qi ((mypc + i) ^ 3));
340 else
341 printf ("%02x", mem_get_qi (mypc + i));
342 }
343
344 do
345 {
346 printf (" ");
347 i ++;
348 }
349 while (i < 6);
350
351 printf ("%-16s ", opbuf);
352
353 printf ("\033[0m\n");
354 trace = save_trace;
355 }