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