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