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