Home | History | Annotate | Line # | Download | only in rx
trace.c revision 1.1
      1  1.1  christos /* trace.c --- tracing output for the RX simulator.
      2  1.1  christos 
      3  1.1  christos Copyright (C) 2005-2014 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.1  christos 	      code_base = bfd_section_lma (current_bfd, 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