1 /* Branch trace support for GDB, the GNU debugger.
3 Copyright (C) 2013-2014 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 /* Return the function name of a recorded function segment for printing.
49 This function never returns NULL. */
52 ftrace_print_function_name (const struct btrace_function *bfun)
54 struct minimal_symbol *msym;
61 return SYMBOL_PRINT_NAME (sym);
64 return SYMBOL_PRINT_NAME (msym);
69 /* Return the file name of a recorded function segment for printing.
70 This function never returns NULL. */
73 ftrace_print_filename (const struct btrace_function *bfun)
81 filename = symtab_to_filename_for_display (sym->symtab);
83 filename = "<unknown>";
88 /* Return a string representation of the address of an instruction.
89 This function never returns NULL. */
92 ftrace_print_insn_addr (const struct btrace_insn *insn)
97 return core_addr_to_string_nz (insn->pc);
100 /* Print an ftrace debug status message. */
103 ftrace_debug (const struct btrace_function *bfun, const char *prefix)
105 const char *fun, *file;
106 unsigned int ibegin, iend;
107 int lbegin, lend, level;
109 fun = ftrace_print_function_name (bfun);
110 file = ftrace_print_filename (bfun);
113 lbegin = bfun->lbegin;
116 ibegin = bfun->insn_offset;
117 iend = ibegin + VEC_length (btrace_insn_s, bfun->insn);
119 DEBUG_FTRACE ("%s: fun = %s, file = %s, level = %d, lines = [%d; %d], "
120 "insn = [%u; %u)", prefix, fun, file, level, lbegin, lend,
124 /* Return non-zero if BFUN does not match MFUN and FUN,
125 return zero otherwise. */
128 ftrace_function_switched (const struct btrace_function *bfun,
129 const struct minimal_symbol *mfun,
130 const struct symbol *fun)
132 struct minimal_symbol *msym;
138 /* If the minimal symbol changed, we certainly switched functions. */
139 if (mfun != NULL && msym != NULL
140 && strcmp (SYMBOL_LINKAGE_NAME (mfun), SYMBOL_LINKAGE_NAME (msym)) != 0)
143 /* If the symbol changed, we certainly switched functions. */
144 if (fun != NULL && sym != NULL)
146 const char *bfname, *fname;
148 /* Check the function name. */
149 if (strcmp (SYMBOL_LINKAGE_NAME (fun), SYMBOL_LINKAGE_NAME (sym)) != 0)
152 /* Check the location of those functions, as well. */
153 bfname = symtab_to_fullname (sym->symtab);
154 fname = symtab_to_fullname (fun->symtab);
155 if (filename_cmp (fname, bfname) != 0)
159 /* If we lost symbol information, we switched functions. */
160 if (!(msym == NULL && sym == NULL) && mfun == NULL && fun == NULL)
163 /* If we gained symbol information, we switched functions. */
164 if (msym == NULL && sym == NULL && !(mfun == NULL && fun == NULL))
170 /* Return non-zero if we should skip this file when generating the function
171 call history, zero otherwise.
172 We would want to do that if, say, a macro that is defined in another file
173 is expanded in this function. */
176 ftrace_skip_file (const struct btrace_function *bfun, const char *fullname)
185 bfile = symtab_to_fullname (sym->symtab);
187 return (filename_cmp (bfile, fullname) != 0);
190 /* Allocate and initialize a new branch trace function segment.
191 PREV is the chronologically preceding function segment.
192 MFUN and FUN are the symbol information we have for this function. */
194 static struct btrace_function *
195 ftrace_new_function (struct btrace_function *prev,
196 struct minimal_symbol *mfun,
199 struct btrace_function *bfun;
201 bfun = xzalloc (sizeof (*bfun));
205 bfun->flow.prev = prev;
207 /* We start with the identities of min and max, respectively. */
208 bfun->lbegin = INT_MAX;
209 bfun->lend = INT_MIN;
213 gdb_assert (prev->flow.next == NULL);
214 prev->flow.next = bfun;
216 bfun->number = prev->number + 1;
217 bfun->insn_offset = (prev->insn_offset
218 + VEC_length (btrace_insn_s, prev->insn));
224 /* Update the UP field of a function segment. */
227 ftrace_update_caller (struct btrace_function *bfun,
228 struct btrace_function *caller,
229 enum btrace_function_flag flags)
231 if (bfun->up != NULL)
232 ftrace_debug (bfun, "updating caller");
237 ftrace_debug (bfun, "set caller");
240 /* Fix up the caller for all segments of a function. */
243 ftrace_fixup_caller (struct btrace_function *bfun,
244 struct btrace_function *caller,
245 enum btrace_function_flag flags)
247 struct btrace_function *prev, *next;
249 ftrace_update_caller (bfun, caller, flags);
251 /* Update all function segments belonging to the same function. */
252 for (prev = bfun->segment.prev; prev != NULL; prev = prev->segment.prev)
253 ftrace_update_caller (prev, caller, flags);
255 for (next = bfun->segment.next; next != NULL; next = next->segment.next)
256 ftrace_update_caller (next, caller, flags);
259 /* Add a new function segment for a call.
260 CALLER is the chronologically preceding function segment.
261 MFUN and FUN are the symbol information we have for this function. */
263 static struct btrace_function *
264 ftrace_new_call (struct btrace_function *caller,
265 struct minimal_symbol *mfun,
268 struct btrace_function *bfun;
270 bfun = ftrace_new_function (caller, mfun, fun);
272 bfun->level = caller->level + 1;
274 ftrace_debug (bfun, "new call");
279 /* Add a new function segment for a tail call.
280 CALLER is the chronologically preceding function segment.
281 MFUN and FUN are the symbol information we have for this function. */
283 static struct btrace_function *
284 ftrace_new_tailcall (struct btrace_function *caller,
285 struct minimal_symbol *mfun,
288 struct btrace_function *bfun;
290 bfun = ftrace_new_function (caller, mfun, fun);
292 bfun->level = caller->level + 1;
293 bfun->flags |= BFUN_UP_LINKS_TO_TAILCALL;
295 ftrace_debug (bfun, "new tail call");
300 /* Find the innermost caller in the back trace of BFUN with MFUN/FUN
301 symbol information. */
303 static struct btrace_function *
304 ftrace_find_caller (struct btrace_function *bfun,
305 struct minimal_symbol *mfun,
308 for (; bfun != NULL; bfun = bfun->up)
310 /* Skip functions with incompatible symbol information. */
311 if (ftrace_function_switched (bfun, mfun, fun))
314 /* This is the function segment we're looking for. */
321 /* Find the innermost caller in the back trace of BFUN, skipping all
322 function segments that do not end with a call instruction (e.g.
323 tail calls ending with a jump). */
325 static struct btrace_function *
326 ftrace_find_call (struct gdbarch *gdbarch, struct btrace_function *bfun)
328 for (; bfun != NULL; bfun = bfun->up)
330 struct btrace_insn *last;
333 /* We do not allow empty function segments. */
334 gdb_assert (!VEC_empty (btrace_insn_s, bfun->insn));
336 last = VEC_last (btrace_insn_s, bfun->insn);
339 if (gdbarch_insn_is_call (gdbarch, pc))
346 /* Add a continuation segment for a function into which we return.
347 PREV is the chronologically preceding function segment.
348 MFUN and FUN are the symbol information we have for this function. */
350 static struct btrace_function *
351 ftrace_new_return (struct gdbarch *gdbarch,
352 struct btrace_function *prev,
353 struct minimal_symbol *mfun,
356 struct btrace_function *bfun, *caller;
358 bfun = ftrace_new_function (prev, mfun, fun);
360 /* It is important to start at PREV's caller. Otherwise, we might find
361 PREV itself, if PREV is a recursive function. */
362 caller = ftrace_find_caller (prev->up, mfun, fun);
365 /* The caller of PREV is the preceding btrace function segment in this
366 function instance. */
367 gdb_assert (caller->segment.next == NULL);
369 caller->segment.next = bfun;
370 bfun->segment.prev = caller;
372 /* Maintain the function level. */
373 bfun->level = caller->level;
375 /* Maintain the call stack. */
376 bfun->up = caller->up;
377 bfun->flags = caller->flags;
379 ftrace_debug (bfun, "new return");
383 /* We did not find a caller. This could mean that something went
384 wrong or that the call is simply not included in the trace. */
386 /* Let's search for some actual call. */
387 caller = ftrace_find_call (gdbarch, prev->up);
390 /* There is no call in PREV's back trace. We assume that the
391 branch trace did not include it. */
393 /* Let's find the topmost call function - this skips tail calls. */
394 while (prev->up != NULL)
397 /* We maintain levels for a series of returns for which we have
399 We start at the preceding function's level in case this has
400 already been a return for which we have not seen the call.
401 We start at level 0 otherwise, to handle tail calls correctly. */
402 bfun->level = min (0, prev->level) - 1;
404 /* Fix up the call stack for PREV. */
405 ftrace_fixup_caller (prev, bfun, BFUN_UP_LINKS_TO_RET);
407 ftrace_debug (bfun, "new return - no caller");
411 /* There is a call in PREV's back trace to which we should have
412 returned. Let's remain at this level. */
413 bfun->level = prev->level;
415 ftrace_debug (bfun, "new return - unknown caller");
422 /* Add a new function segment for a function switch.
423 PREV is the chronologically preceding function segment.
424 MFUN and FUN are the symbol information we have for this function. */
426 static struct btrace_function *
427 ftrace_new_switch (struct btrace_function *prev,
428 struct minimal_symbol *mfun,
431 struct btrace_function *bfun;
433 /* This is an unexplained function switch. The call stack will likely
434 be wrong at this point. */
435 bfun = ftrace_new_function (prev, mfun, fun);
437 /* We keep the function level. */
438 bfun->level = prev->level;
440 ftrace_debug (bfun, "new switch");
445 /* Update BFUN with respect to the instruction at PC. This may create new
447 Return the chronologically latest function segment, never NULL. */
449 static struct btrace_function *
450 ftrace_update_function (struct gdbarch *gdbarch,
451 struct btrace_function *bfun, CORE_ADDR pc)
453 struct bound_minimal_symbol bmfun;
454 struct minimal_symbol *mfun;
456 struct btrace_insn *last;
458 /* Try to determine the function we're in. We use both types of symbols
459 to avoid surprises when we sometimes get a full symbol and sometimes
460 only a minimal symbol. */
461 fun = find_pc_function (pc);
462 bmfun = lookup_minimal_symbol_by_pc (pc);
465 if (fun == NULL && mfun == NULL)
466 DEBUG_FTRACE ("no symbol at %s", core_addr_to_string_nz (pc));
468 /* If we didn't have a function before, we create one. */
470 return ftrace_new_function (bfun, mfun, fun);
472 /* Check the last instruction, if we have one.
473 We do this check first, since it allows us to fill in the call stack
474 links in addition to the normal flow links. */
476 if (!VEC_empty (btrace_insn_s, bfun->insn))
477 last = VEC_last (btrace_insn_s, bfun->insn);
485 /* Check for returns. */
486 if (gdbarch_insn_is_ret (gdbarch, lpc))
487 return ftrace_new_return (gdbarch, bfun, mfun, fun);
489 /* Check for calls. */
490 if (gdbarch_insn_is_call (gdbarch, lpc))
494 size = gdb_insn_length (gdbarch, lpc);
496 /* Ignore calls to the next instruction. They are used for PIC. */
497 if (lpc + size != pc)
498 return ftrace_new_call (bfun, mfun, fun);
502 /* Check if we're switching functions for some other reason. */
503 if (ftrace_function_switched (bfun, mfun, fun))
505 DEBUG_FTRACE ("switching from %s in %s at %s",
506 ftrace_print_insn_addr (last),
507 ftrace_print_function_name (bfun),
508 ftrace_print_filename (bfun));
512 CORE_ADDR start, lpc;
514 start = get_pc_function_start (pc);
516 /* If we can't determine the function for PC, we treat a jump at
517 the end of the block as tail call. */
523 /* Jumps indicate optimized tail calls. */
524 if (start == pc && gdbarch_insn_is_jump (gdbarch, lpc))
525 return ftrace_new_tailcall (bfun, mfun, fun);
528 return ftrace_new_switch (bfun, mfun, fun);
534 /* Update BFUN's source range with respect to the instruction at PC. */
537 ftrace_update_lines (struct btrace_function *bfun, CORE_ADDR pc)
539 struct symtab_and_line sal;
540 const char *fullname;
542 sal = find_pc_line (pc, 0);
543 if (sal.symtab == NULL || sal.line == 0)
545 DEBUG_FTRACE ("no lines at %s", core_addr_to_string_nz (pc));
549 /* Check if we switched files. This could happen if, say, a macro that
550 is defined in another file is expanded here. */
551 fullname = symtab_to_fullname (sal.symtab);
552 if (ftrace_skip_file (bfun, fullname))
554 DEBUG_FTRACE ("ignoring file at %s, file=%s",
555 core_addr_to_string_nz (pc), fullname);
559 /* Update the line range. */
560 bfun->lbegin = min (bfun->lbegin, sal.line);
561 bfun->lend = max (bfun->lend, sal.line);
563 if (record_debug > 1)
564 ftrace_debug (bfun, "update lines");
567 /* Add the instruction at PC to BFUN's instructions. */
570 ftrace_update_insns (struct btrace_function *bfun, CORE_ADDR pc)
572 struct btrace_insn *insn;
574 insn = VEC_safe_push (btrace_insn_s, bfun->insn, NULL);
577 if (record_debug > 1)
578 ftrace_debug (bfun, "update insn");
581 /* Compute the function branch trace from a block branch trace BTRACE for
582 a thread given by BTINFO. */
585 btrace_compute_ftrace (struct btrace_thread_info *btinfo,
586 VEC (btrace_block_s) *btrace)
588 struct btrace_function *begin, *end;
589 struct gdbarch *gdbarch;
593 DEBUG ("compute ftrace");
595 gdbarch = target_gdbarch ();
599 blk = VEC_length (btrace_block_s, btrace);
603 btrace_block_s *block;
608 block = VEC_index (btrace_block_s, btrace, blk);
615 /* We should hit the end of the block. Warn if we went too far. */
618 warning (_("Recorded trace may be corrupted around %s."),
619 core_addr_to_string_nz (pc));
623 end = ftrace_update_function (gdbarch, end, pc);
627 /* Maintain the function level offset. */
628 level = min (level, end->level);
630 ftrace_update_insns (end, pc);
631 ftrace_update_lines (end, pc);
633 /* We're done once we pushed the instruction at the end. */
634 if (block->end == pc)
637 size = gdb_insn_length (gdbarch, pc);
639 /* Make sure we terminate if we fail to compute the size. */
642 warning (_("Recorded trace may be incomplete around %s."),
643 core_addr_to_string_nz (pc));
651 btinfo->begin = begin;
654 /* LEVEL is the minimal function level of all btrace function segments.
655 Define the global level offset to -LEVEL so all function levels are
656 normalized to start at zero. */
657 btinfo->level = -level;
663 btrace_enable (struct thread_info *tp)
665 if (tp->btrace.target != NULL)
668 if (!target_supports_btrace ())
669 error (_("Target does not support branch tracing."));
671 DEBUG ("enable thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
673 tp->btrace.target = target_enable_btrace (tp->ptid);
679 btrace_disable (struct thread_info *tp)
681 struct btrace_thread_info *btp = &tp->btrace;
684 if (btp->target == NULL)
687 DEBUG ("disable thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
689 target_disable_btrace (btp->target);
698 btrace_teardown (struct thread_info *tp)
700 struct btrace_thread_info *btp = &tp->btrace;
703 if (btp->target == NULL)
706 DEBUG ("teardown thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
708 target_teardown_btrace (btp->target);
717 btrace_fetch (struct thread_info *tp)
719 struct btrace_thread_info *btinfo;
720 VEC (btrace_block_s) *btrace;
721 struct cleanup *cleanup;
723 DEBUG ("fetch thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
725 btinfo = &tp->btrace;
726 if (btinfo->target == NULL)
729 btrace = target_read_btrace (btinfo->target, BTRACE_READ_NEW);
730 cleanup = make_cleanup (VEC_cleanup (btrace_block_s), &btrace);
732 if (!VEC_empty (btrace_block_s, btrace))
735 btrace_compute_ftrace (btinfo, btrace);
738 do_cleanups (cleanup);
744 btrace_clear (struct thread_info *tp)
746 struct btrace_thread_info *btinfo;
747 struct btrace_function *it, *trash;
749 DEBUG ("clear thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
751 btinfo = &tp->btrace;
762 btinfo->begin = NULL;
765 xfree (btinfo->insn_history);
766 xfree (btinfo->call_history);
768 btinfo->insn_history = NULL;
769 btinfo->call_history = NULL;
775 btrace_free_objfile (struct objfile *objfile)
777 struct thread_info *tp;
779 DEBUG ("free objfile");
785 #if defined (HAVE_LIBEXPAT)
787 /* Check the btrace document version. */
790 check_xml_btrace_version (struct gdb_xml_parser *parser,
791 const struct gdb_xml_element *element,
792 void *user_data, VEC (gdb_xml_value_s) *attributes)
794 const char *version = xml_find_attribute (attributes, "version")->value;
796 if (strcmp (version, "1.0") != 0)
797 gdb_xml_error (parser, _("Unsupported btrace version: \"%s\""), version);
800 /* Parse a btrace "block" xml record. */
803 parse_xml_btrace_block (struct gdb_xml_parser *parser,
804 const struct gdb_xml_element *element,
805 void *user_data, VEC (gdb_xml_value_s) *attributes)
807 VEC (btrace_block_s) **btrace;
808 struct btrace_block *block;
809 ULONGEST *begin, *end;
812 block = VEC_safe_push (btrace_block_s, *btrace, NULL);
814 begin = xml_find_attribute (attributes, "begin")->value;
815 end = xml_find_attribute (attributes, "end")->value;
817 block->begin = *begin;
821 static const struct gdb_xml_attribute block_attributes[] = {
822 { "begin", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
823 { "end", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
824 { NULL, GDB_XML_AF_NONE, NULL, NULL }
827 static const struct gdb_xml_attribute btrace_attributes[] = {
828 { "version", GDB_XML_AF_NONE, NULL, NULL },
829 { NULL, GDB_XML_AF_NONE, NULL, NULL }
832 static const struct gdb_xml_element btrace_children[] = {
833 { "block", block_attributes, NULL,
834 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, parse_xml_btrace_block, NULL },
835 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
838 static const struct gdb_xml_element btrace_elements[] = {
839 { "btrace", btrace_attributes, btrace_children, GDB_XML_EF_NONE,
840 check_xml_btrace_version, NULL },
841 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
844 #endif /* defined (HAVE_LIBEXPAT) */
848 VEC (btrace_block_s) *
849 parse_xml_btrace (const char *buffer)
851 VEC (btrace_block_s) *btrace = NULL;
852 struct cleanup *cleanup;
855 #if defined (HAVE_LIBEXPAT)
857 cleanup = make_cleanup (VEC_cleanup (btrace_block_s), &btrace);
858 errcode = gdb_xml_parse_quick (_("btrace"), "btrace.dtd", btrace_elements,
862 do_cleanups (cleanup);
866 /* Keep parse results. */
867 discard_cleanups (cleanup);
869 #else /* !defined (HAVE_LIBEXPAT) */
871 error (_("Cannot process branch trace. XML parsing is not supported."));
873 #endif /* !defined (HAVE_LIBEXPAT) */
880 const struct btrace_insn *
881 btrace_insn_get (const struct btrace_insn_iterator *it)
883 const struct btrace_function *bfun;
884 unsigned int index, end;
889 /* The index is within the bounds of this function's instruction vector. */
890 end = VEC_length (btrace_insn_s, bfun->insn);
891 gdb_assert (0 < end);
892 gdb_assert (index < end);
894 return VEC_index (btrace_insn_s, bfun->insn, index);
900 btrace_insn_number (const struct btrace_insn_iterator *it)
902 const struct btrace_function *bfun;
905 return bfun->insn_offset + it->index;
911 btrace_insn_begin (struct btrace_insn_iterator *it,
912 const struct btrace_thread_info *btinfo)
914 const struct btrace_function *bfun;
916 bfun = btinfo->begin;
918 error (_("No trace."));
927 btrace_insn_end (struct btrace_insn_iterator *it,
928 const struct btrace_thread_info *btinfo)
930 const struct btrace_function *bfun;
935 error (_("No trace."));
937 /* The last instruction in the last function is the current instruction.
938 We point to it - it is one past the end of the execution trace. */
939 length = VEC_length (btrace_insn_s, bfun->insn);
942 it->index = length - 1;
948 btrace_insn_next (struct btrace_insn_iterator *it, unsigned int stride)
950 const struct btrace_function *bfun;
951 unsigned int index, steps;
959 unsigned int end, space, adv;
961 end = VEC_length (btrace_insn_s, bfun->insn);
963 gdb_assert (0 < end);
964 gdb_assert (index < end);
966 /* Compute the number of instructions remaining in this segment. */
969 /* Advance the iterator as far as possible within this segment. */
970 adv = min (space, stride);
975 /* Move to the next function if we're at the end of this one. */
978 const struct btrace_function *next;
980 next = bfun->flow.next;
983 /* We stepped past the last function.
985 Let's adjust the index to point to the last instruction in
986 the previous function. */
992 /* We now point to the first instruction in the new function. */
997 /* We did make progress. */
998 gdb_assert (adv > 0);
1001 /* Update the iterator. */
1002 it->function = bfun;
1011 btrace_insn_prev (struct btrace_insn_iterator *it, unsigned int stride)
1013 const struct btrace_function *bfun;
1014 unsigned int index, steps;
1016 bfun = it->function;
1024 /* Move to the previous function if we're at the start of this one. */
1027 const struct btrace_function *prev;
1029 prev = bfun->flow.prev;
1033 /* We point to one after the last instruction in the new function. */
1035 index = VEC_length (btrace_insn_s, bfun->insn);
1037 /* There is at least one instruction in this function segment. */
1038 gdb_assert (index > 0);
1041 /* Advance the iterator as far as possible within this segment. */
1042 adv = min (index, stride);
1047 /* We did make progress. */
1048 gdb_assert (adv > 0);
1051 /* Update the iterator. */
1052 it->function = bfun;
1061 btrace_insn_cmp (const struct btrace_insn_iterator *lhs,
1062 const struct btrace_insn_iterator *rhs)
1064 unsigned int lnum, rnum;
1066 lnum = btrace_insn_number (lhs);
1067 rnum = btrace_insn_number (rhs);
1069 return (int) (lnum - rnum);
1075 btrace_find_insn_by_number (struct btrace_insn_iterator *it,
1076 const struct btrace_thread_info *btinfo,
1077 unsigned int number)
1079 const struct btrace_function *bfun;
1082 for (bfun = btinfo->end; bfun != NULL; bfun = bfun->flow.prev)
1083 if (bfun->insn_offset <= number)
1089 end = bfun->insn_offset + VEC_length (btrace_insn_s, bfun->insn);
1093 it->function = bfun;
1094 it->index = number - bfun->insn_offset;
1101 const struct btrace_function *
1102 btrace_call_get (const struct btrace_call_iterator *it)
1104 return it->function;
1110 btrace_call_number (const struct btrace_call_iterator *it)
1112 const struct btrace_thread_info *btinfo;
1113 const struct btrace_function *bfun;
1116 btinfo = it->btinfo;
1117 bfun = it->function;
1119 return bfun->number;
1121 /* For the end iterator, i.e. bfun == NULL, we return one more than the
1122 number of the last function. */
1124 insns = VEC_length (btrace_insn_s, bfun->insn);
1126 /* If the function contains only a single instruction (i.e. the current
1127 instruction), it will be skipped and its number is already the number
1130 return bfun->number;
1132 /* Otherwise, return one more than the number of the last function. */
1133 return bfun->number + 1;
1139 btrace_call_begin (struct btrace_call_iterator *it,
1140 const struct btrace_thread_info *btinfo)
1142 const struct btrace_function *bfun;
1144 bfun = btinfo->begin;
1146 error (_("No trace."));
1148 it->btinfo = btinfo;
1149 it->function = bfun;
1155 btrace_call_end (struct btrace_call_iterator *it,
1156 const struct btrace_thread_info *btinfo)
1158 const struct btrace_function *bfun;
1162 error (_("No trace."));
1164 it->btinfo = btinfo;
1165 it->function = NULL;
1171 btrace_call_next (struct btrace_call_iterator *it, unsigned int stride)
1173 const struct btrace_function *bfun;
1176 bfun = it->function;
1178 while (bfun != NULL)
1180 const struct btrace_function *next;
1183 next = bfun->flow.next;
1186 /* Ignore the last function if it only contains a single
1187 (i.e. the current) instruction. */
1188 insns = VEC_length (btrace_insn_s, bfun->insn);
1193 if (stride == steps)
1200 it->function = bfun;
1207 btrace_call_prev (struct btrace_call_iterator *it, unsigned int stride)
1209 const struct btrace_thread_info *btinfo;
1210 const struct btrace_function *bfun;
1213 bfun = it->function;
1220 btinfo = it->btinfo;
1225 /* Ignore the last function if it only contains a single
1226 (i.e. the current) instruction. */
1227 insns = VEC_length (btrace_insn_s, bfun->insn);
1229 bfun = bfun->flow.prev;
1237 while (steps < stride)
1239 const struct btrace_function *prev;
1241 prev = bfun->flow.prev;
1249 it->function = bfun;
1256 btrace_call_cmp (const struct btrace_call_iterator *lhs,
1257 const struct btrace_call_iterator *rhs)
1259 unsigned int lnum, rnum;
1261 lnum = btrace_call_number (lhs);
1262 rnum = btrace_call_number (rhs);
1264 return (int) (lnum - rnum);
1270 btrace_find_call_by_number (struct btrace_call_iterator *it,
1271 const struct btrace_thread_info *btinfo,
1272 unsigned int number)
1274 const struct btrace_function *bfun;
1276 for (bfun = btinfo->end; bfun != NULL; bfun = bfun->flow.prev)
1280 bnum = bfun->number;
1283 it->btinfo = btinfo;
1284 it->function = bfun;
1288 /* Functions are ordered and numbered consecutively. We could bail out
1289 earlier. On the other hand, it is very unlikely that we search for
1290 a nonexistent function. */
1299 btrace_set_insn_history (struct btrace_thread_info *btinfo,
1300 const struct btrace_insn_iterator *begin,
1301 const struct btrace_insn_iterator *end)
1303 if (btinfo->insn_history == NULL)
1304 btinfo->insn_history = xzalloc (sizeof (*btinfo->insn_history));
1306 btinfo->insn_history->begin = *begin;
1307 btinfo->insn_history->end = *end;
1313 btrace_set_call_history (struct btrace_thread_info *btinfo,
1314 const struct btrace_call_iterator *begin,
1315 const struct btrace_call_iterator *end)
1317 gdb_assert (begin->btinfo == end->btinfo);
1319 if (btinfo->call_history == NULL)
1320 btinfo->call_history = xzalloc (sizeof (*btinfo->call_history));
1322 btinfo->call_history->begin = *begin;
1323 btinfo->call_history->end = *end;