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