1 /* Branch trace support for GDB, the GNU debugger.
3 Copyright (C) 2013 Free Software Foundation, Inc.
5 Contributed by Intel Corp. <markus.t.metzger@intel.com>
7 This file is part of GDB.
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.
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.
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/>. */
23 #include "gdbthread.h"
24 #include "exceptions.h"
31 #include "filenames.h"
32 #include "xml-support.h"
34 /* Print a record debug message. Use do ... while (0) to avoid ambiguities
35 when used in if statements. */
37 #define DEBUG(msg, args...) \
40 if (record_debug != 0) \
41 fprintf_unfiltered (gdb_stdlog, \
42 "[btrace] " msg "\n", ##args); \
46 #define DEBUG_FTRACE(msg, args...) DEBUG ("[ftrace] " msg, ##args)
48 /* Initialize the instruction iterator. */
51 btrace_init_insn_iterator (struct btrace_thread_info
*btinfo
)
53 DEBUG ("init insn iterator");
55 btinfo
->insn_iterator
.begin
= 1;
56 btinfo
->insn_iterator
.end
= 0;
59 /* Initialize the function iterator. */
62 btrace_init_func_iterator (struct btrace_thread_info
*btinfo
)
64 DEBUG ("init func iterator");
66 btinfo
->func_iterator
.begin
= 1;
67 btinfo
->func_iterator
.end
= 0;
70 /* Compute the instruction trace from the block trace. */
72 static VEC (btrace_inst_s
) *
73 compute_itrace (VEC (btrace_block_s
) *btrace
)
75 VEC (btrace_inst_s
) *itrace
;
76 struct gdbarch
*gdbarch
;
79 DEBUG ("compute itrace");
82 gdbarch
= target_gdbarch ();
83 b
= VEC_length (btrace_block_s
, btrace
);
87 btrace_block_s
*block
;
90 block
= VEC_index (btrace_block_s
, btrace
, b
);
93 /* Add instructions for this block. */
99 /* We should hit the end of the block. Warn if we went too far. */
102 warning (_("Recorded trace may be corrupted."));
106 inst
= VEC_safe_push (btrace_inst_s
, itrace
, NULL
);
109 /* We're done once we pushed the instruction at the end. */
110 if (block
->end
== pc
)
113 size
= gdb_insn_length (gdbarch
, pc
);
115 /* Make sure we terminate if we fail to compute the size. */
118 warning (_("Recorded trace may be incomplete."));
129 /* Return the function name of a recorded function segment for printing.
130 This function never returns NULL. */
133 ftrace_print_function_name (struct btrace_func
*bfun
)
135 struct minimal_symbol
*msym
;
142 return SYMBOL_PRINT_NAME (sym
);
145 return SYMBOL_PRINT_NAME (msym
);
150 /* Return the file name of a recorded function segment for printing.
151 This function never returns NULL. */
154 ftrace_print_filename (struct btrace_func
*bfun
)
157 const char *filename
;
162 filename
= symtab_to_filename_for_display (sym
->symtab
);
164 filename
= "<unknown>";
169 /* Print an ftrace debug status message. */
172 ftrace_debug (struct btrace_func
*bfun
, const char *prefix
)
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
);
180 /* Initialize a recorded function segment. */
183 ftrace_init_func (struct btrace_func
*bfun
, struct minimal_symbol
*mfun
,
184 struct symbol
*fun
, unsigned int idx
)
188 bfun
->lbegin
= INT_MAX
;
194 /* Check whether the function has changed. */
197 ftrace_function_switched (struct btrace_func
*bfun
,
198 struct minimal_symbol
*mfun
, struct symbol
*fun
)
200 struct minimal_symbol
*msym
;
203 /* The function changed if we did not have one before. */
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)
215 /* If the symbol changed, we certainly switched functions. */
216 if (fun
!= NULL
&& sym
!= NULL
)
218 const char *bfname
, *fname
;
220 /* Check the function name. */
221 if (strcmp (SYMBOL_LINKAGE_NAME (fun
), SYMBOL_LINKAGE_NAME (sym
)) != 0)
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)
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. */
239 ftrace_skip_file (struct btrace_func
*bfun
, const char *filename
)
247 bfile
= symtab_to_fullname (sym
->symtab
);
251 if (filename
== NULL
)
254 return (filename_cmp (bfile
, filename
) != 0);
257 /* Compute the function trace from the instruction trace. */
259 static VEC (btrace_func_s
) *
260 compute_ftrace (VEC (btrace_inst_s
) *itrace
)
262 VEC (btrace_func_s
) *ftrace
;
263 struct btrace_inst
*binst
;
264 struct btrace_func
*bfun
;
267 DEBUG ("compute ftrace");
272 for (idx
= 0; VEC_iterate (btrace_inst_s
, itrace
, idx
, binst
); ++idx
)
274 struct symtab_and_line sal
;
275 struct bound_minimal_symbol mfun
;
277 const char *filename
;
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
);
288 if (fun
== NULL
&& mfun
.minsym
== NULL
)
290 DEBUG_FTRACE ("no symbol at %u, pc=%s", idx
,
291 core_addr_to_string_nz (pc
));
295 /* If we're switching functions, we start over. */
296 if (ftrace_function_switched (bfun
, mfun
.minsym
, fun
))
298 bfun
= VEC_safe_push (btrace_func_s
, ftrace
, NULL
);
300 ftrace_init_func (bfun
, mfun
.minsym
, fun
, idx
);
301 ftrace_debug (bfun
, "init");
304 /* Update the instruction range. */
306 ftrace_debug (bfun
, "update insns");
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)
312 DEBUG_FTRACE ("no lines at %u, pc=%s", idx
,
313 core_addr_to_string_nz (pc
));
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
))
322 DEBUG_FTRACE ("ignoring file at %u, pc=%s, file=%s", idx
,
323 core_addr_to_string_nz (pc
), filename
);
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");
339 btrace_enable (struct thread_info
*tp
)
341 if (tp
->btrace
.target
!= NULL
)
344 if (!target_supports_btrace ())
345 error (_("Target does not support branch tracing."));
347 DEBUG ("enable thread %d (%s)", tp
->num
, target_pid_to_str (tp
->ptid
));
349 tp
->btrace
.target
= target_enable_btrace (tp
->ptid
);
355 btrace_disable (struct thread_info
*tp
)
357 struct btrace_thread_info
*btp
= &tp
->btrace
;
360 if (btp
->target
== NULL
)
363 DEBUG ("disable thread %d (%s)", tp
->num
, target_pid_to_str (tp
->ptid
));
365 target_disable_btrace (btp
->target
);
374 btrace_teardown (struct thread_info
*tp
)
376 struct btrace_thread_info
*btp
= &tp
->btrace
;
379 if (btp
->target
== NULL
)
382 DEBUG ("teardown thread %d (%s)", tp
->num
, target_pid_to_str (tp
->ptid
));
384 target_teardown_btrace (btp
->target
);
393 btrace_fetch (struct thread_info
*tp
)
395 struct btrace_thread_info
*btinfo
;
396 VEC (btrace_block_s
) *btrace
;
398 DEBUG ("fetch thread %d (%s)", tp
->num
, target_pid_to_str (tp
->ptid
));
400 btinfo
= &tp
->btrace
;
401 if (btinfo
->target
== NULL
)
404 btrace
= target_read_btrace (btinfo
->target
, btrace_read_new
);
405 if (VEC_empty (btrace_block_s
, btrace
))
410 btinfo
->btrace
= btrace
;
411 btinfo
->itrace
= compute_itrace (btinfo
->btrace
);
412 btinfo
->ftrace
= compute_ftrace (btinfo
->itrace
);
414 /* Initialize branch trace iterators. */
415 btrace_init_insn_iterator (btinfo
);
416 btrace_init_func_iterator (btinfo
);
422 btrace_clear (struct thread_info
*tp
)
424 struct btrace_thread_info
*btinfo
;
426 DEBUG ("clear thread %d (%s)", tp
->num
, target_pid_to_str (tp
->ptid
));
428 btinfo
= &tp
->btrace
;
430 VEC_free (btrace_block_s
, btinfo
->btrace
);
431 VEC_free (btrace_inst_s
, btinfo
->itrace
);
432 VEC_free (btrace_func_s
, btinfo
->ftrace
);
434 btinfo
->btrace
= NULL
;
435 btinfo
->itrace
= NULL
;
436 btinfo
->ftrace
= NULL
;
442 btrace_free_objfile (struct objfile
*objfile
)
444 struct thread_info
*tp
;
446 DEBUG ("free objfile");
452 #if defined (HAVE_LIBEXPAT)
454 /* Check the btrace document version. */
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
)
461 const char *version
= xml_find_attribute (attributes
, "version")->value
;
463 if (strcmp (version
, "1.0") != 0)
464 gdb_xml_error (parser
, _("Unsupported btrace version: \"%s\""), version
);
467 /* Parse a btrace "block" xml record. */
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
)
474 VEC (btrace_block_s
) **btrace
;
475 struct btrace_block
*block
;
476 ULONGEST
*begin
, *end
;
479 block
= VEC_safe_push (btrace_block_s
, *btrace
, NULL
);
481 begin
= xml_find_attribute (attributes
, "begin")->value
;
482 end
= xml_find_attribute (attributes
, "end")->value
;
484 block
->begin
= *begin
;
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
}
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
}
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
}
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
}
511 #endif /* defined (HAVE_LIBEXPAT) */
515 VEC (btrace_block_s
) *
516 parse_xml_btrace (const char *buffer
)
518 VEC (btrace_block_s
) *btrace
= NULL
;
519 struct cleanup
*cleanup
;
522 #if defined (HAVE_LIBEXPAT)
524 cleanup
= make_cleanup (VEC_cleanup (btrace_block_s
), &btrace
);
525 errcode
= gdb_xml_parse_quick (_("btrace"), "btrace.dtd", btrace_elements
,
529 do_cleanups (cleanup
);
533 /* Keep parse results. */
534 discard_cleanups (cleanup
);
536 #else /* !defined (HAVE_LIBEXPAT) */
538 error (_("Cannot process branch trace. XML parsing is not supported."));
540 #endif /* !defined (HAVE_LIBEXPAT) */