trace.c 8.3 KB

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