]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/rx/trace.c
bfd: add stdlib.h when using abort
[thirdparty/binutils-gdb.git] / sim / rx / trace.c
CommitLineData
4f8d4a38
DD
1/* trace.c --- tracing output for the RX simulator.
2
3666a048 3Copyright (C) 2005-2021 Free Software Foundation, Inc.
4f8d4a38
DD
4Contributed by Red Hat, Inc.
5
6This file is part of the GNU simulators.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21
93378652 22#include "config.h"
4f8d4a38
DD
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"
fab2b376 37#include "trace.h"
4f8d4a38
DD
38
39static int
40sim_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
60static long
61remove_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
84static int
85compare_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
97static char opbuf[1000];
98
99static int
100op_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
111static bfd * current_bfd = NULL;
112static asymbol ** symtab = NULL;
113static int symcount = 0;
114static asection * code_section = NULL;
115static bfd_vma code_base = 0;
116static struct disassemble_info info;
117
118void
119sim_disasm_init (bfd *prog)
120{
121 current_bfd = prog;
122}
123
124typedef struct Files
125{
126 struct Files *next;
127 char *filename;
128 int nlines;
129 char **lines;
130 char *data;
131} Files;
132Files *files = 0;
133
134static char *
135load_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 {
783a7b12 143 FILE *file;
4f8d4a38
DD
144 int i;
145 struct stat s;
9ee45557 146 size_t ret;
4f8d4a38
DD
147 const char *found_filename, *slash;
148
149 found_filename = filename;
150 while (1)
151 {
152 if (stat (found_filename, &s) == 0)
153 break;
154 slash = strchr (found_filename, '/');
155 if (!slash)
156 return "";
157 found_filename = slash + 1;
158 }
159
160 f = (Files *) malloc (sizeof (Files));
161 f->next = files;
162 files = f;
163 f->filename = strdup (filename);
164 f->data = (char *) malloc (s.st_size + 2);
783a7b12 165 file = fopen (found_filename, "rb");
9ee45557
MF
166 ret = fread (f->data, 1, s.st_size, file);
167 f->data[ret] = 0;
4f8d4a38
DD
168 fclose (file);
169
170 f->nlines = 1;
171 for (i = 0; i < s.st_size; i++)
172 if (f->data[i] == '\n')
173 f->nlines++;
174 f->lines = (char **) malloc (f->nlines * sizeof (char *));
175 f->lines[0] = f->data;
176 f->nlines = 1;
177 for (i = 0; i < s.st_size; i++)
178 if (f->data[i] == '\n')
179 {
180 f->lines[f->nlines] = f->data + i + 1;
181 while (*f->lines[f->nlines] == ' '
182 || *f->lines[f->nlines] == '\t')
183 f->lines[f->nlines]++;
184 f->nlines++;
185 f->data[i] = 0;
186 }
187 }
188 if (lineno < 1 || lineno > f->nlines)
189 return "";
190 return f->lines[lineno - 1];
191}
192
193int
194sim_get_current_source_location (const char ** pfilename,
195 const char ** pfunctionname,
196 unsigned int * plineno)
197{
198 static int initted = 0;
199 int mypc = get_reg (pc);
200
201 if (current_bfd == NULL)
202 return 0;
203
204 if (!initted)
205 {
206 int storage;
207 asection * s;
208
209 initted = 1;
210 memset (& info, 0, sizeof (info));
211 INIT_DISASSEMBLE_INFO (info, stdout, op_printf);
212 info.read_memory_func = sim_dis_read;
213 info.arch = bfd_get_arch (current_bfd);
214 info.mach = bfd_get_mach (current_bfd);
215 if (info.mach == 0)
216 info.arch = bfd_arch_rx;
217
218 disassemble_init_for_target (& info);
219
220 storage = bfd_get_symtab_upper_bound (current_bfd);
221 if (storage > 0)
222 {
223 symtab = (asymbol **) malloc (storage);
224 symcount = bfd_canonicalize_symtab (current_bfd, symtab);
225 symcount = remove_useless_symbols (symtab, symcount);
226 qsort (symtab, symcount, sizeof (asymbol *), compare_symbols);
227 }
228
229 for (s = current_bfd->sections; s; s = s->next)
230 {
231 if (s->flags & SEC_CODE || code_section == 0)
232 {
233 code_section = s;
fd361982 234 code_base = bfd_section_lma (s);
4f8d4a38
DD
235 break;
236 }
237 }
238 }
239
240 *pfilename = *pfunctionname = NULL;
241 *plineno = 0;
242
243 bfd_find_nearest_line
244 (current_bfd, code_section, symtab, mypc - code_base,
245 pfilename, pfunctionname, plineno);
246
247 return 1;
248}
249
250void
251sim_disasm_one (void)
252{
253 static int last_sym = -1;
254 static const char * prev_filename = "";
255 static int prev_lineno = 0;
256 const char * filename;
257 const char * functionname;
258 unsigned int lineno;
259 int sym, bestaddr;
260 int min, max, i;
261 int save_trace = trace;
262 int mypc = get_reg (pc);
263
264 if (! sim_get_current_source_location (& filename, & functionname, & lineno))
265 return;
266
267 trace = 0;
268
269 if (filename && functionname && lineno)
270 {
271 if (lineno != prev_lineno || strcmp (prev_filename, filename))
272 {
273 char * the_line = load_file_and_line (filename, lineno);
274 const char * slash = strrchr (filename, '/');
275
276 if (!slash)
277 slash = filename;
278 else
279 slash++;
280 printf
281 ("========================================"
282 "=====================================\n");
283 printf ("\033[37;41m %s:%d: \033[33;40m %s\033[K\033[0m\n",
284 slash, lineno, the_line);
285 }
286 prev_lineno = lineno;
287 prev_filename = filename;
288 }
289
290 min = -1;
291 max = symcount;
292 while (min < max - 1)
293 {
294 bfd_vma sa;
295
296 sym = (min + max) / 2;
297 sa = bfd_asymbol_value (symtab[sym]);
298 /*printf("checking %4d %08x %s\n",
299 sym, sa, bfd_asymbol_name (symtab[sym])); */
300 if (sa > mypc)
301 max = sym;
302 else if (sa < mypc)
303 min = sym;
304 else
305 {
306 min = sym;
307 break;
308 }
309 }
310
311 if (min != -1 && min != last_sym)
312 {
313 bestaddr = bfd_asymbol_value (symtab[min]);
314 printf ("\033[43;30m%s", bfd_asymbol_name (symtab[min]));
315 if (bestaddr != mypc)
316 printf ("+%d", mypc - bestaddr);
317 printf (":\t\t\t\033[0m\n");
318 last_sym = min;
319#if 0
320 if (trace == 1)
321 if (strcmp (bfd_asymbol_name (symtab[min]), "abort") == 0
322 || strcmp (bfd_asymbol_name (symtab[min]), "exit") == 0)
323 trace = 0;
324#endif
325 }
326
327 opbuf[0] = 0;
93378652
DD
328#ifdef CYCLE_ACCURATE
329 printf ("\033[33m %04u %06x: ", (int)(regs.cycle_count % 10000), mypc);
330#else
331 printf ("\033[33m %06x: ", mypc);
332
333#endif
334
4f8d4a38
DD
335 max = print_insn_rx (mypc, & info);
336
337 for (i = 0; i < max; i++)
338 {
339 if (rx_big_endian)
340 printf ("%02x", mem_get_qi ((mypc + i) ^ 3));
341 else
342 printf ("%02x", mem_get_qi (mypc + i));
343 }
344
345 do
346 {
347 printf (" ");
348 i ++;
349 }
350 while (i < 6);
351
352 printf ("%-16s ", opbuf);
353
354 printf ("\033[0m\n");
355 trace = save_trace;
356}