xref: /dragonfly/contrib/gdb-7/gdb/btrace.c (revision 0db87cb7)
1 /* Branch trace support for GDB, the GNU debugger.
2 
3    Copyright (C) 2013 Free Software Foundation, Inc.
4 
5    Contributed by Intel Corp. <markus.t.metzger@intel.com>
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 #include "btrace.h"
23 #include "gdbthread.h"
24 #include "exceptions.h"
25 #include "inferior.h"
26 #include "target.h"
27 #include "record.h"
28 #include "symtab.h"
29 #include "disasm.h"
30 #include "source.h"
31 #include "filenames.h"
32 #include "xml-support.h"
33 
34 /* Print a record debug message.  Use do ... while (0) to avoid ambiguities
35    when used in if statements.  */
36 
37 #define DEBUG(msg, args...)						\
38   do									\
39     {									\
40       if (record_debug != 0)						\
41         fprintf_unfiltered (gdb_stdlog,					\
42 			    "[btrace] " msg "\n", ##args);		\
43     }									\
44   while (0)
45 
46 #define DEBUG_FTRACE(msg, args...) DEBUG ("[ftrace] " msg, ##args)
47 
48 /* Initialize the instruction iterator.  */
49 
50 static void
51 btrace_init_insn_iterator (struct btrace_thread_info *btinfo)
52 {
53   DEBUG ("init insn iterator");
54 
55   btinfo->insn_iterator.begin = 1;
56   btinfo->insn_iterator.end = 0;
57 }
58 
59 /* Initialize the function iterator.  */
60 
61 static void
62 btrace_init_func_iterator (struct btrace_thread_info *btinfo)
63 {
64   DEBUG ("init func iterator");
65 
66   btinfo->func_iterator.begin = 1;
67   btinfo->func_iterator.end = 0;
68 }
69 
70 /* Compute the instruction trace from the block trace.  */
71 
72 static VEC (btrace_inst_s) *
73 compute_itrace (VEC (btrace_block_s) *btrace)
74 {
75   VEC (btrace_inst_s) *itrace;
76   struct gdbarch *gdbarch;
77   unsigned int b;
78 
79   DEBUG ("compute itrace");
80 
81   itrace = NULL;
82   gdbarch = target_gdbarch ();
83   b = VEC_length (btrace_block_s, btrace);
84 
85   while (b-- != 0)
86     {
87       btrace_block_s *block;
88       CORE_ADDR pc;
89 
90       block = VEC_index (btrace_block_s, btrace, b);
91       pc = block->begin;
92 
93       /* Add instructions for this block.  */
94       for (;;)
95 	{
96 	  btrace_inst_s *inst;
97 	  int size;
98 
99 	  /* We should hit the end of the block.  Warn if we went too far.  */
100 	  if (block->end < pc)
101 	    {
102 	      warning (_("Recorded trace may be corrupted."));
103 	      break;
104 	    }
105 
106 	  inst = VEC_safe_push (btrace_inst_s, itrace, NULL);
107 	  inst->pc = pc;
108 
109 	  /* We're done once we pushed the instruction at the end.  */
110 	  if (block->end == pc)
111 	    break;
112 
113 	  size = gdb_insn_length (gdbarch, pc);
114 
115 	  /* Make sure we terminate if we fail to compute the size.  */
116 	  if (size <= 0)
117 	    {
118 	      warning (_("Recorded trace may be incomplete."));
119 	      break;
120 	    }
121 
122 	  pc += size;
123 	}
124     }
125 
126   return itrace;
127 }
128 
129 /* Return the function name of a recorded function segment for printing.
130    This function never returns NULL.  */
131 
132 static const char *
133 ftrace_print_function_name (struct btrace_func *bfun)
134 {
135   struct minimal_symbol *msym;
136   struct symbol *sym;
137 
138   msym = bfun->msym;
139   sym = bfun->sym;
140 
141   if (sym != NULL)
142     return SYMBOL_PRINT_NAME (sym);
143 
144   if (msym != NULL)
145     return SYMBOL_PRINT_NAME (msym);
146 
147   return "<unknown>";
148 }
149 
150 /* Return the file name of a recorded function segment for printing.
151    This function never returns NULL.  */
152 
153 static const char *
154 ftrace_print_filename (struct btrace_func *bfun)
155 {
156   struct symbol *sym;
157   const char *filename;
158 
159   sym = bfun->sym;
160 
161   if (sym != NULL)
162     filename = symtab_to_filename_for_display (sym->symtab);
163   else
164     filename = "<unknown>";
165 
166   return filename;
167 }
168 
169 /* Print an ftrace debug status message.  */
170 
171 static void
172 ftrace_debug (struct btrace_func *bfun, const char *prefix)
173 {
174   DEBUG_FTRACE ("%s: fun = %s, file = %s, lines = [%d; %d], insn = [%u; %u]",
175 		prefix, ftrace_print_function_name (bfun),
176 		ftrace_print_filename (bfun), bfun->lbegin, bfun->lend,
177 		bfun->ibegin, bfun->iend);
178 }
179 
180 /* Initialize a recorded function segment.  */
181 
182 static void
183 ftrace_init_func (struct btrace_func *bfun, struct minimal_symbol *mfun,
184 		  struct symbol *fun, unsigned int idx)
185 {
186   bfun->msym = mfun;
187   bfun->sym = fun;
188   bfun->lbegin = INT_MAX;
189   bfun->lend = 0;
190   bfun->ibegin = idx;
191   bfun->iend = idx;
192 }
193 
194 /* Check whether the function has changed.  */
195 
196 static int
197 ftrace_function_switched (struct btrace_func *bfun,
198 			  struct minimal_symbol *mfun, struct symbol *fun)
199 {
200   struct minimal_symbol *msym;
201   struct symbol *sym;
202 
203   /* The function changed if we did not have one before.  */
204   if (bfun == NULL)
205     return 1;
206 
207   msym = bfun->msym;
208   sym = bfun->sym;
209 
210   /* If the minimal symbol changed, we certainly switched functions.  */
211   if (mfun != NULL && msym != NULL
212       && strcmp (SYMBOL_LINKAGE_NAME (mfun), SYMBOL_LINKAGE_NAME (msym)) != 0)
213     return 1;
214 
215   /* If the symbol changed, we certainly switched functions.  */
216   if (fun != NULL && sym != NULL)
217     {
218       const char *bfname, *fname;
219 
220       /* Check the function name.  */
221       if (strcmp (SYMBOL_LINKAGE_NAME (fun), SYMBOL_LINKAGE_NAME (sym)) != 0)
222 	return 1;
223 
224       /* Check the location of those functions, as well.  */
225       bfname = symtab_to_fullname (sym->symtab);
226       fname = symtab_to_fullname (fun->symtab);
227       if (filename_cmp (fname, bfname) != 0)
228 	return 1;
229     }
230 
231   return 0;
232 }
233 
234 /* Check if we should skip this file when generating the function call
235    history.  We would want to do that if, say, a macro that is defined
236    in another file is expanded in this function.  */
237 
238 static int
239 ftrace_skip_file (struct btrace_func *bfun, const char *filename)
240 {
241   struct symbol *sym;
242   const char *bfile;
243 
244   sym = bfun->sym;
245 
246   if (sym != NULL)
247     bfile = symtab_to_fullname (sym->symtab);
248   else
249     bfile = "";
250 
251   if (filename == NULL)
252     filename = "";
253 
254   return (filename_cmp (bfile, filename) != 0);
255 }
256 
257 /* Compute the function trace from the instruction trace.  */
258 
259 static VEC (btrace_func_s) *
260 compute_ftrace (VEC (btrace_inst_s) *itrace)
261 {
262   VEC (btrace_func_s) *ftrace;
263   struct btrace_inst *binst;
264   struct btrace_func *bfun;
265   unsigned int idx;
266 
267   DEBUG ("compute ftrace");
268 
269   ftrace = NULL;
270   bfun = NULL;
271 
272   for (idx = 0; VEC_iterate (btrace_inst_s, itrace, idx, binst); ++idx)
273     {
274       struct symtab_and_line sal;
275       struct minimal_symbol *mfun;
276       struct symbol *fun;
277       const char *filename;
278       CORE_ADDR pc;
279 
280       pc = binst->pc;
281 
282       /* Try to determine the function we're in.  We use both types of symbols
283 	 to avoid surprises when we sometimes get a full symbol and sometimes
284 	 only a minimal symbol.  */
285       fun = find_pc_function (pc);
286       mfun = lookup_minimal_symbol_by_pc (pc);
287 
288       if (fun == NULL && mfun == NULL)
289 	{
290 	  DEBUG_FTRACE ("no symbol at %u, pc=%s", idx,
291 			core_addr_to_string_nz (pc));
292 	  continue;
293 	}
294 
295       /* If we're switching functions, we start over.  */
296       if (ftrace_function_switched (bfun, mfun, fun))
297 	{
298 	  bfun = VEC_safe_push (btrace_func_s, ftrace, NULL);
299 
300 	  ftrace_init_func (bfun, mfun, fun, idx);
301 	  ftrace_debug (bfun, "init");
302 	}
303 
304       /* Update the instruction range.  */
305       bfun->iend = idx;
306       ftrace_debug (bfun, "update insns");
307 
308       /* Let's see if we have source correlation, as well.  */
309       sal = find_pc_line (pc, 0);
310       if (sal.symtab == NULL || sal.line == 0)
311 	{
312 	  DEBUG_FTRACE ("no lines at %u, pc=%s", idx,
313 			core_addr_to_string_nz (pc));
314 	  continue;
315 	}
316 
317       /* Check if we switched files.  This could happen if, say, a macro that
318 	 is defined in another file is expanded here.  */
319       filename = symtab_to_fullname (sal.symtab);
320       if (ftrace_skip_file (bfun, filename))
321 	{
322 	  DEBUG_FTRACE ("ignoring file at %u, pc=%s, file=%s", idx,
323 			core_addr_to_string_nz (pc), filename);
324 	  continue;
325 	}
326 
327       /* Update the line range.  */
328       bfun->lbegin = min (bfun->lbegin, sal.line);
329       bfun->lend = max (bfun->lend, sal.line);
330       ftrace_debug (bfun, "update lines");
331     }
332 
333   return ftrace;
334 }
335 
336 /* See btrace.h.  */
337 
338 void
339 btrace_enable (struct thread_info *tp)
340 {
341   if (tp->btrace.target != NULL)
342     return;
343 
344   if (!target_supports_btrace ())
345     error (_("Target does not support branch tracing."));
346 
347   DEBUG ("enable thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
348 
349   tp->btrace.target = target_enable_btrace (tp->ptid);
350 }
351 
352 /* See btrace.h.  */
353 
354 void
355 btrace_disable (struct thread_info *tp)
356 {
357   struct btrace_thread_info *btp = &tp->btrace;
358   int errcode = 0;
359 
360   if (btp->target == NULL)
361     return;
362 
363   DEBUG ("disable thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
364 
365   target_disable_btrace (btp->target);
366   btp->target = NULL;
367 
368   btrace_clear (tp);
369 }
370 
371 /* See btrace.h.  */
372 
373 void
374 btrace_teardown (struct thread_info *tp)
375 {
376   struct btrace_thread_info *btp = &tp->btrace;
377   int errcode = 0;
378 
379   if (btp->target == NULL)
380     return;
381 
382   DEBUG ("teardown thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
383 
384   target_teardown_btrace (btp->target);
385   btp->target = NULL;
386 
387   btrace_clear (tp);
388 }
389 
390 /* See btrace.h.  */
391 
392 void
393 btrace_fetch (struct thread_info *tp)
394 {
395   struct btrace_thread_info *btinfo;
396   VEC (btrace_block_s) *btrace;
397 
398   DEBUG ("fetch thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
399 
400   btinfo = &tp->btrace;
401   if (btinfo->target == NULL)
402     return;
403 
404   btrace = target_read_btrace (btinfo->target, btrace_read_new);
405   if (VEC_empty (btrace_block_s, btrace))
406     return;
407 
408   btrace_clear (tp);
409 
410   btinfo->btrace = btrace;
411   btinfo->itrace = compute_itrace (btinfo->btrace);
412   btinfo->ftrace = compute_ftrace (btinfo->itrace);
413 
414   /* Initialize branch trace iterators.  */
415   btrace_init_insn_iterator (btinfo);
416   btrace_init_func_iterator (btinfo);
417 }
418 
419 /* See btrace.h.  */
420 
421 void
422 btrace_clear (struct thread_info *tp)
423 {
424   struct btrace_thread_info *btinfo;
425 
426   DEBUG ("clear thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
427 
428   btinfo = &tp->btrace;
429 
430   VEC_free (btrace_block_s, btinfo->btrace);
431   VEC_free (btrace_inst_s, btinfo->itrace);
432   VEC_free (btrace_func_s, btinfo->ftrace);
433 
434   btinfo->btrace = NULL;
435   btinfo->itrace = NULL;
436   btinfo->ftrace = NULL;
437 }
438 
439 /* See btrace.h.  */
440 
441 void
442 btrace_free_objfile (struct objfile *objfile)
443 {
444   struct thread_info *tp;
445 
446   DEBUG ("free objfile");
447 
448   ALL_THREADS (tp)
449     btrace_clear (tp);
450 }
451 
452 #if defined (HAVE_LIBEXPAT)
453 
454 /* Check the btrace document version.  */
455 
456 static void
457 check_xml_btrace_version (struct gdb_xml_parser *parser,
458 			  const struct gdb_xml_element *element,
459 			  void *user_data, VEC (gdb_xml_value_s) *attributes)
460 {
461   const char *version = xml_find_attribute (attributes, "version")->value;
462 
463   if (strcmp (version, "1.0") != 0)
464     gdb_xml_error (parser, _("Unsupported btrace version: \"%s\""), version);
465 }
466 
467 /* Parse a btrace "block" xml record.  */
468 
469 static void
470 parse_xml_btrace_block (struct gdb_xml_parser *parser,
471 			const struct gdb_xml_element *element,
472 			void *user_data, VEC (gdb_xml_value_s) *attributes)
473 {
474   VEC (btrace_block_s) **btrace;
475   struct btrace_block *block;
476   ULONGEST *begin, *end;
477 
478   btrace = user_data;
479   block = VEC_safe_push (btrace_block_s, *btrace, NULL);
480 
481   begin = xml_find_attribute (attributes, "begin")->value;
482   end = xml_find_attribute (attributes, "end")->value;
483 
484   block->begin = *begin;
485   block->end = *end;
486 }
487 
488 static const struct gdb_xml_attribute block_attributes[] = {
489   { "begin", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
490   { "end", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
491   { NULL, GDB_XML_AF_NONE, NULL, NULL }
492 };
493 
494 static const struct gdb_xml_attribute btrace_attributes[] = {
495   { "version", GDB_XML_AF_NONE, NULL, NULL },
496   { NULL, GDB_XML_AF_NONE, NULL, NULL }
497 };
498 
499 static const struct gdb_xml_element btrace_children[] = {
500   { "block", block_attributes, NULL,
501     GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, parse_xml_btrace_block, NULL },
502   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
503 };
504 
505 static const struct gdb_xml_element btrace_elements[] = {
506   { "btrace", btrace_attributes, btrace_children, GDB_XML_EF_NONE,
507     check_xml_btrace_version, NULL },
508   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
509 };
510 
511 #endif /* defined (HAVE_LIBEXPAT) */
512 
513 /* See btrace.h.  */
514 
515 VEC (btrace_block_s) *
516 parse_xml_btrace (const char *buffer)
517 {
518   VEC (btrace_block_s) *btrace = NULL;
519   struct cleanup *cleanup;
520   int errcode;
521 
522 #if defined (HAVE_LIBEXPAT)
523 
524   cleanup = make_cleanup (VEC_cleanup (btrace_block_s), &btrace);
525   errcode = gdb_xml_parse_quick (_("btrace"), "btrace.dtd", btrace_elements,
526 				 buffer, &btrace);
527   if (errcode != 0)
528     {
529       do_cleanups (cleanup);
530       return NULL;
531     }
532 
533   /* Keep parse results.  */
534   discard_cleanups (cleanup);
535 
536 #else  /* !defined (HAVE_LIBEXPAT) */
537 
538   error (_("Cannot process branch trace.  XML parsing is not supported."));
539 
540 #endif  /* !defined (HAVE_LIBEXPAT) */
541 
542   return btrace;
543 }
544