148596154Schristos /* trace.c --- tracing output for the RL78 simulator.
248596154Schristos
3*1424dfb3Schristos Copyright (C) 2005-2020 Free Software Foundation, Inc.
448596154Schristos Contributed by Red Hat, Inc.
548596154Schristos
648596154Schristos This file is part of the GNU simulators.
748596154Schristos
848596154Schristos This program is free software; you can redistribute it and/or modify
948596154Schristos it under the terms of the GNU General Public License as published by
1048596154Schristos the Free Software Foundation; either version 3 of the License, or
1148596154Schristos (at your option) any later version.
1248596154Schristos
1348596154Schristos This program is distributed in the hope that it will be useful,
1448596154Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1548596154Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1648596154Schristos GNU General Public License for more details.
1748596154Schristos
1848596154Schristos You should have received a copy of the GNU General Public License
1948596154Schristos along with this program. If not, see <http://www.gnu.org/licenses/>.
2048596154Schristos */
2148596154Schristos
2248596154Schristos
2348596154Schristos #include "config.h"
2448596154Schristos #include <stdio.h>
2548596154Schristos #include <stdarg.h>
2648596154Schristos #include <string.h>
2748596154Schristos #include <stdlib.h>
2848596154Schristos #include <sys/types.h>
2948596154Schristos #include <sys/stat.h>
3048596154Schristos #include <ctype.h>
3148596154Schristos
3248596154Schristos #include "libiberty.h"
3348596154Schristos #include "bfd.h"
3448596154Schristos #include "dis-asm.h"
3548596154Schristos
3648596154Schristos #include "cpu.h"
3748596154Schristos #include "mem.h"
3848596154Schristos #include "load.h"
3948596154Schristos
40ed6a76a9Schristos static disassembler_ftype rl78_disasm_fn = NULL;
41ed6a76a9Schristos
4248596154Schristos static int
sim_dis_read(bfd_vma memaddr,bfd_byte * ptr,unsigned int length,struct disassemble_info * info)4348596154Schristos sim_dis_read (bfd_vma memaddr, bfd_byte * ptr, unsigned int length,
4448596154Schristos struct disassemble_info *info)
4548596154Schristos {
4648596154Schristos mem_get_blk (memaddr, ptr, length);
4748596154Schristos return 0;
4848596154Schristos }
4948596154Schristos
5048596154Schristos /* Filter out (in place) symbols that are useless for disassembly.
5148596154Schristos COUNT is the number of elements in SYMBOLS.
5248596154Schristos Return the number of useful symbols. */
5348596154Schristos
5448596154Schristos static long
remove_useless_symbols(asymbol ** symbols,long count)5548596154Schristos remove_useless_symbols (asymbol ** symbols, long count)
5648596154Schristos {
5748596154Schristos register asymbol **in_ptr = symbols, **out_ptr = symbols;
5848596154Schristos
5948596154Schristos while (-- count >= 0)
6048596154Schristos {
6148596154Schristos asymbol *sym = *in_ptr ++;
6248596154Schristos
6348596154Schristos if (strstr (sym->name, "gcc2_compiled"))
6448596154Schristos continue;
6548596154Schristos if (sym->name == NULL || sym->name[0] == '\0')
6648596154Schristos continue;
6748596154Schristos if (sym->flags & (BSF_DEBUGGING))
6848596154Schristos continue;
6948596154Schristos if (bfd_is_und_section (sym->section)
7048596154Schristos || bfd_is_com_section (sym->section))
7148596154Schristos continue;
7248596154Schristos
7348596154Schristos *out_ptr++ = sym;
7448596154Schristos }
7548596154Schristos return out_ptr - symbols;
7648596154Schristos }
7748596154Schristos
7848596154Schristos static int
compare_symbols(const PTR ap,const PTR bp)7948596154Schristos compare_symbols (const PTR ap, const PTR bp)
8048596154Schristos {
8148596154Schristos const asymbol *a = *(const asymbol **) ap;
8248596154Schristos const asymbol *b = *(const asymbol **) bp;
8348596154Schristos
8448596154Schristos if (bfd_asymbol_value (a) > bfd_asymbol_value (b))
8548596154Schristos return 1;
8648596154Schristos else if (bfd_asymbol_value (a) < bfd_asymbol_value (b))
8748596154Schristos return -1;
8848596154Schristos return 0;
8948596154Schristos }
9048596154Schristos
9148596154Schristos static char opbuf[1000];
9248596154Schristos
9348596154Schristos static int
op_printf(char * buf,char * fmt,...)9448596154Schristos op_printf (char *buf, char *fmt, ...)
9548596154Schristos {
9648596154Schristos int ret;
9748596154Schristos va_list ap;
9848596154Schristos
9948596154Schristos va_start (ap, fmt);
10048596154Schristos ret = vsprintf (opbuf + strlen (opbuf), fmt, ap);
10148596154Schristos va_end (ap);
10248596154Schristos return ret;
10348596154Schristos }
10448596154Schristos
10548596154Schristos static bfd * current_bfd = NULL;
10648596154Schristos static asymbol ** symtab = NULL;
10748596154Schristos static int symcount = 0;
10848596154Schristos static asection * code_section = NULL;
10948596154Schristos static bfd_vma code_base = 0;
11048596154Schristos static struct disassemble_info info;
11148596154Schristos
11248596154Schristos void
sim_disasm_init(bfd * prog)11348596154Schristos sim_disasm_init (bfd *prog)
11448596154Schristos {
11548596154Schristos current_bfd = prog;
116ed6a76a9Schristos rl78_disasm_fn = NULL;
11748596154Schristos }
11848596154Schristos
11948596154Schristos typedef struct Files
12048596154Schristos {
12148596154Schristos struct Files *next;
12248596154Schristos char *filename;
12348596154Schristos int nlines;
12448596154Schristos char **lines;
12548596154Schristos char *data;
12648596154Schristos } Files;
12748596154Schristos Files *files = 0;
12848596154Schristos
12948596154Schristos static char *
load_file_and_line(const char * filename,int lineno)13048596154Schristos load_file_and_line (const char *filename, int lineno)
13148596154Schristos {
13248596154Schristos Files *f;
13348596154Schristos for (f = files; f; f = f->next)
13448596154Schristos if (strcmp (f->filename, filename) == 0)
13548596154Schristos break;
13648596154Schristos if (!f)
13748596154Schristos {
13848596154Schristos int i;
13948596154Schristos struct stat s;
14048596154Schristos const char *found_filename, *slash;
14148596154Schristos
14248596154Schristos found_filename = filename;
14348596154Schristos while (1)
14448596154Schristos {
14548596154Schristos if (stat (found_filename, &s) == 0)
14648596154Schristos break;
14748596154Schristos slash = strchr (found_filename, '/');
14848596154Schristos if (!slash)
14948596154Schristos return "";
15048596154Schristos found_filename = slash + 1;
15148596154Schristos }
15248596154Schristos
15348596154Schristos f = (Files *) xmalloc (sizeof (Files));
15448596154Schristos f->next = files;
15548596154Schristos files = f;
15648596154Schristos f->filename = xstrdup (filename);
15748596154Schristos f->data = (char *) xmalloc (s.st_size + 2);
15848596154Schristos FILE *file = fopen (found_filename, "rb");
15948596154Schristos fread (f->data, 1, s.st_size, file);
16048596154Schristos f->data[s.st_size] = 0;
16148596154Schristos fclose (file);
16248596154Schristos
16348596154Schristos f->nlines = 1;
16448596154Schristos for (i = 0; i < s.st_size; i ++)
16548596154Schristos if (f->data[i] == '\n')
16648596154Schristos f->nlines ++;
16748596154Schristos f->lines = (char **) xmalloc (f->nlines * sizeof (char *));
16848596154Schristos f->lines[0] = f->data;
16948596154Schristos f->nlines = 1;
17048596154Schristos for (i = 0; i < s.st_size; i ++)
17148596154Schristos if (f->data[i] == '\n')
17248596154Schristos {
17348596154Schristos f->lines[f->nlines] = f->data + i + 1;
17448596154Schristos while (*f->lines[f->nlines] == ' '
17548596154Schristos || *f->lines[f->nlines] == '\t')
17648596154Schristos f->lines[f->nlines] ++;
17748596154Schristos f->nlines ++;
17848596154Schristos f->data[i] = 0;
17948596154Schristos }
18048596154Schristos }
18148596154Schristos if (lineno < 1 || lineno > f->nlines)
18248596154Schristos return "";
18348596154Schristos return f->lines[lineno - 1];
18448596154Schristos }
18548596154Schristos
18648596154Schristos int
sim_get_current_source_location(const char ** pfilename,const char ** pfunctionname,unsigned int * plineno)18748596154Schristos sim_get_current_source_location (const char ** pfilename,
18848596154Schristos const char ** pfunctionname,
18948596154Schristos unsigned int * plineno)
19048596154Schristos {
19148596154Schristos static int initted = 0;
19248596154Schristos int mypc = pc;
19348596154Schristos
19448596154Schristos if (current_bfd == NULL)
19548596154Schristos return 0;
19648596154Schristos
19748596154Schristos if (!initted)
19848596154Schristos {
19948596154Schristos int storage;
20048596154Schristos asection * s;
20148596154Schristos
20248596154Schristos initted = 1;
20348596154Schristos memset (& info, 0, sizeof (info));
20448596154Schristos INIT_DISASSEMBLE_INFO (info, stdout, op_printf);
20548596154Schristos info.read_memory_func = sim_dis_read;
20648596154Schristos info.arch = bfd_get_arch (current_bfd);
20748596154Schristos info.mach = bfd_get_mach (current_bfd);
20848596154Schristos if (info.mach == 0)
20948596154Schristos info.arch = bfd_arch_rl78;
21048596154Schristos
21148596154Schristos disassemble_init_for_target (& info);
21248596154Schristos
21348596154Schristos storage = bfd_get_symtab_upper_bound (current_bfd);
21448596154Schristos if (storage > 0)
21548596154Schristos {
21648596154Schristos symtab = (asymbol **) xmalloc (storage);
21748596154Schristos symcount = bfd_canonicalize_symtab (current_bfd, symtab);
21848596154Schristos symcount = remove_useless_symbols (symtab, symcount);
21948596154Schristos qsort (symtab, symcount, sizeof (asymbol *), compare_symbols);
22048596154Schristos }
22148596154Schristos
22248596154Schristos for (s = current_bfd->sections; s; s = s->next)
22348596154Schristos {
22448596154Schristos if (s->flags & SEC_CODE || code_section == 0)
22548596154Schristos {
22648596154Schristos code_section = s;
227*1424dfb3Schristos code_base = bfd_section_lma (s);
22848596154Schristos break;
22948596154Schristos }
23048596154Schristos }
23148596154Schristos }
23248596154Schristos
23348596154Schristos *pfilename = *pfunctionname = NULL;
23448596154Schristos *plineno = 0;
23548596154Schristos
23648596154Schristos bfd_find_nearest_line
23748596154Schristos (current_bfd, code_section, symtab, mypc - code_base,
23848596154Schristos pfilename, pfunctionname, plineno);
23948596154Schristos
24048596154Schristos return 1;
24148596154Schristos }
24248596154Schristos
24348596154Schristos void
sim_disasm_one(void)24448596154Schristos sim_disasm_one (void)
24548596154Schristos {
24648596154Schristos static int last_sym = -1;
24748596154Schristos static const char * prev_filename = "";
24848596154Schristos static int prev_lineno = 0;
24948596154Schristos const char * filename;
25048596154Schristos const char * functionname;
25148596154Schristos unsigned int lineno;
25248596154Schristos int sym, bestaddr;
25348596154Schristos int min, max, i;
25448596154Schristos int save_trace = trace;
25548596154Schristos int mypc = pc;
25648596154Schristos
25748596154Schristos if (! sim_get_current_source_location (& filename, & functionname, & lineno))
25848596154Schristos return;
25948596154Schristos
26048596154Schristos trace = 0;
26148596154Schristos
262ed6a76a9Schristos if (!rl78_disasm_fn)
263ed6a76a9Schristos {
264ed6a76a9Schristos if (rl78_g10_mode)
265ed6a76a9Schristos rl78_disasm_fn = print_insn_rl78_g10;
266ed6a76a9Schristos else if (g14_multiply)
267ed6a76a9Schristos rl78_disasm_fn = print_insn_rl78_g14;
268ed6a76a9Schristos else if (g13_multiply)
269ed6a76a9Schristos rl78_disasm_fn = print_insn_rl78_g13;
270ed6a76a9Schristos else
271ed6a76a9Schristos rl78_disasm_fn = print_insn_rl78;
272ed6a76a9Schristos }
273ed6a76a9Schristos
27448596154Schristos if (filename && functionname && lineno)
27548596154Schristos {
27648596154Schristos if (lineno != prev_lineno || strcmp (prev_filename, filename))
27748596154Schristos {
27848596154Schristos char * the_line = load_file_and_line (filename, lineno);
27948596154Schristos const char * slash = strrchr (filename, '/');
28048596154Schristos
28148596154Schristos if (!slash)
28248596154Schristos slash = filename;
28348596154Schristos else
28448596154Schristos slash ++;
28548596154Schristos printf
28648596154Schristos ("========================================"
28748596154Schristos "=====================================\n");
28848596154Schristos printf ("\033[37;41m %s:%d: \033[33;40m %s\033[K\033[0m\n",
28948596154Schristos slash, lineno, the_line);
29048596154Schristos }
29148596154Schristos prev_lineno = lineno;
29248596154Schristos prev_filename = filename;
29348596154Schristos }
29448596154Schristos
29548596154Schristos min = -1;
29648596154Schristos max = symcount;
29748596154Schristos while (min < max - 1)
29848596154Schristos {
29948596154Schristos bfd_vma sa;
30048596154Schristos
30148596154Schristos sym = (min + max) / 2;
30248596154Schristos sa = bfd_asymbol_value (symtab[sym]);
30348596154Schristos /*printf ("checking %4d %08x %s\n",
30448596154Schristos sym, sa, bfd_asymbol_name (symtab[sym])); */
30548596154Schristos if (sa > mypc)
30648596154Schristos max = sym;
30748596154Schristos else if (sa < mypc)
30848596154Schristos min = sym;
30948596154Schristos else
31048596154Schristos {
31148596154Schristos min = sym;
31248596154Schristos break;
31348596154Schristos }
31448596154Schristos }
31548596154Schristos
31648596154Schristos if (min != -1 && min != last_sym)
31748596154Schristos {
31848596154Schristos bestaddr = bfd_asymbol_value (symtab[min]);
31948596154Schristos printf ("\033[43;30m%s", bfd_asymbol_name (symtab[min]));
32048596154Schristos if (bestaddr != mypc)
32148596154Schristos printf ("+%d", mypc - bestaddr);
32248596154Schristos printf (":\t\t\t\033[0m\n");
32348596154Schristos last_sym = min;
32448596154Schristos #if 0
32548596154Schristos if (trace == 1)
32648596154Schristos if (strcmp (bfd_asymbol_name (symtab[min]), "abort") == 0
32748596154Schristos || strcmp (bfd_asymbol_name (symtab[min]), "exit") == 0)
32848596154Schristos trace = 0;
32948596154Schristos #endif
33048596154Schristos }
33148596154Schristos
33248596154Schristos #define TCR0 0xf0180
33348596154Schristos
33448596154Schristos opbuf[0] = 0;
33548596154Schristos #ifdef CYCLE_ACCURATE
33648596154Schristos printf ("\033[33m %04u %06x: ", (int)(regs.cycle_count % 10000), mypc);
33748596154Schristos #else
33848596154Schristos printf ("\033[33m %08llx %06x: ", total_clocks, mypc);
33948596154Schristos #endif
34048596154Schristos
341ed6a76a9Schristos max = rl78_disasm_fn (mypc, & info);
34248596154Schristos
34348596154Schristos for (i = 0; i < max; i ++)
34448596154Schristos printf ("%02x", mem_get_qi (mypc + i));
34548596154Schristos
34648596154Schristos do
34748596154Schristos {
34848596154Schristos printf (" ");
34948596154Schristos i ++;
35048596154Schristos }
35148596154Schristos while (i < 6);
35248596154Schristos
35348596154Schristos printf ("%-16s ", opbuf);
35448596154Schristos
35548596154Schristos printf ("\033[0m\n");
35648596154Schristos trace = save_trace;
35748596154Schristos }
358