+2014-01-16 Markus Metzger <markus.t.metzger@intel.com>
+
+ * btrace.c: Include regcache.h.
+ (btrace_add_pc): New.
+ (btrace_enable): Call btrace_add_pc.
+ (btrace_is_empty): New.
+ * btrace.h (btrace_is_empty): New.
+ * record-btrace.c (require_btrace, record_btrace_info): Call
+ btrace_is_empty.
+
2014-01-16 Markus Metzger <markus.t.metzger@intel.com>
* common/linux-btrace.c (perf_event_read_bts, linux_read_btrace):
#include "source.h"
#include "filenames.h"
#include "xml-support.h"
+#include "regcache.h"
/* Print a record debug message. Use do ... while (0) to avoid ambiguities
when used in if statements. */
btinfo->level = -level;
}
+/* Add an entry for the current PC. */
+
+static void
+btrace_add_pc (struct thread_info *tp)
+{
+ VEC (btrace_block_s) *btrace;
+ struct btrace_block *block;
+ struct regcache *regcache;
+ struct cleanup *cleanup;
+ CORE_ADDR pc;
+
+ regcache = get_thread_regcache (tp->ptid);
+ pc = regcache_read_pc (regcache);
+
+ btrace = NULL;
+ cleanup = make_cleanup (VEC_cleanup (btrace_block_s), &btrace);
+
+ block = VEC_safe_push (btrace_block_s, btrace, NULL);
+ block->begin = pc;
+ block->end = pc;
+
+ btrace_compute_ftrace (&tp->btrace, btrace);
+
+ do_cleanups (cleanup);
+}
+
/* See btrace.h. */
void
DEBUG ("enable thread %d (%s)", tp->num, target_pid_to_str (tp->ptid));
tp->btrace.target = target_enable_btrace (tp->ptid);
+
+ /* Add an entry for the current PC so we start tracing from where we
+ enabled it. */
+ if (tp->btrace.target != NULL)
+ btrace_add_pc (tp);
}
/* See btrace.h. */
{
return tp->btrace.replay != NULL;
}
+
+/* See btrace.h. */
+
+int
+btrace_is_empty (struct thread_info *tp)
+{
+ struct btrace_insn_iterator begin, end;
+ struct btrace_thread_info *btinfo;
+
+ btinfo = &tp->btrace;
+
+ if (btinfo->begin == NULL)
+ return 1;
+
+ btrace_insn_begin (&begin, btinfo);
+ btrace_insn_end (&end, btinfo);
+
+ return btrace_insn_cmp (&begin, &end) == 0;
+}
/* Determine if branch tracing is currently replaying TP. */
extern int btrace_is_replaying (struct thread_info *tp);
+/* Return non-zero if the branch trace for TP is empty; zero otherwise. */
+extern int btrace_is_empty (struct thread_info *tp);
+
+
#endif /* BTRACE_H */
require_btrace_thread (void)
{
struct thread_info *tp;
- struct btrace_thread_info *btinfo;
DEBUG ("require");
btrace_fetch (tp);
- btinfo = &tp->btrace;
-
- if (btinfo->begin == NULL)
+ if (btrace_is_empty (tp))
error (_("No trace."));
return tp;
calls = 0;
btinfo = &tp->btrace;
- if (btinfo->begin != NULL)
+
+ if (!btrace_is_empty (tp))
{
struct btrace_call_iterator call;
struct btrace_insn_iterator insn;
+2014-01-16 Markus Metzger <markus.t.metzger@intel.com>
+
+ * gdb.btrace/Makefile.in (EXECUTABLES): Add delta.
+ * gdb.btrace/exception.exp: Update.
+ * gdb.btrace/instruction_history.exp: Update.
+ * gdb.btrace/record_goto.exp: Update.
+ * gdb.btrace/tailcall.exp: Update.
+ * gdb.btrace/unknown_functions.exp: Update.
+ * gdb.btrace/delta.exp: New.
+
2014-01-16 Markus Metzger <markus.t.metzger@intel.com>
* gdb.btrace/record_goto.exp: Add backtrace test.
srcdir = @srcdir@
EXECUTABLES = enable function_call_history instruction_history tailcall \
- exception unknown_functions record_goto
+ exception unknown_functions record_goto delta
MISCELLANEOUS =
--- /dev/null
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2013 Free Software Foundation, Inc.
+#
+# Contributed by Intel Corp. <markus.t.metzger@intel.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# start inferior
+standard_testfile x86-record_goto.S
+if [prepare_for_testing delta.exp $testfile $srcfile] {
+ return -1
+}
+if ![runto_main] {
+ return -1
+}
+
+# proceed to some sequential code
+gdb_test "next"
+
+# start tracing
+gdb_test_no_output "record btrace"
+
+# we start without trace
+with_test_prefix "no trace" {
+ gdb_test "info record" [join [list \
+ "Active record target: record-btrace" \
+ "Recorded 0 instructions in 0 functions for .*" \
+ ] "\r\n"]
+ gdb_test "record instruction-history" "No trace\."
+ gdb_test "record function-call-history" "No trace\."
+}
+
+# we record each single-step, even if we have not seen a branch, yet.
+gdb_test "stepi"
+
+proc check_trace {} {
+ gdb_test "info record" [join [list \
+ "Active record target: record-btrace" \
+ "Recorded 1 instructions in 1 functions for .*" \
+ ] "\r\n"]
+ gdb_test "record instruction-history /f 1" \
+ "1\t 0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tmov *\\\$0x0,%eax\r"
+ gdb_test "record function-call-history /c 1" "1\tmain"
+}
+
+# make sure we don't extend the trace when we ask twice.
+with_test_prefix "once" {
+ check_trace
+}
+
+with_test_prefix "twice" {
+ check_trace
+}
send_gdb "record function-call-history 1\n"
gdb_expect_list "flat" "\r\n$gdb_prompt $" [list \
[join [list \
- "1\ttest\\(\\)" \
- "2\tfoo\\(\\)" \
- "3\tbar\\(\\)" \
- "4\tbad\\(\\)" \
+ "1\tmain\\(\\)" \
+ "2\ttest\\(\\)" \
+ "3\tfoo\\(\\)" \
+ "4\tbar\\(\\)" \
+ "5\tbad\\(\\)\r" \
] "\r\n"] \
"" \
"\[0-9\]*\ttest\\(\\)"]
send_gdb "record function-call-history /c 1\n"
gdb_expect_list "indented" "\r\n$gdb_prompt $" [list \
[join [list \
- "1\ttest\\(\\)" \
- "2\t foo\\(\\)" \
- "3\t bar\\(\\)" \
- "4\t bad\\(\\)\r" \
- ] "\r\n"] \
+ "1\tmain\\(\\)" \
+ "2\t test\\(\\)" \
+ "3\t foo\\(\\)" \
+ "4\t bar\\(\\)" \
+ "5\t bad\\(\\)\r" \
+ ] "\r\n"] \
"" \
- "\[0-9\]*\ttest\\(\\)"]
+ "\[0-9\]*\t test\\(\\)"]
}
}
-# we have exactly 6 instructions here
-set message "exactly 6 instructions"
-if { $traced != 6 } {
+# we have exactly 11 instructions here
+set message "exactly 11 instructions"
+if { $traced != 11 } {
fail $message
} else {
pass $message
}
# test that we see the expected instructions
-gdb_test "record instruction-history 2,6" [join [list \
- "2\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
- "3\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tdec %eax" \
- "4\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tjmp 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
- "5\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tcmp \\\$0x0,%eax" \
- "6\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
+gdb_test "record instruction-history 3,7" [join [list \
+ "3\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
+ "4\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tdec %eax" \
+ "5\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tjmp 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
+ "6\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tcmp \\\$0x0,%eax" \
+ "7\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
] "\r\n"]
-gdb_test "record instruction-history /f 2,+5" [join [list \
- "2\t 0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
- "3\t 0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tdec %eax" \
- "4\t 0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tjmp 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
- "5\t 0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tcmp \\\$0x0,%eax" \
- "6\t 0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
+gdb_test "record instruction-history /f 3,+5" [join [list \
+ "3\t 0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
+ "4\t 0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tdec %eax" \
+ "5\t 0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tjmp 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
+ "6\t 0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tcmp \\\$0x0,%eax" \
+ "7\t 0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
] "\r\n"]
-gdb_test "record instruction-history /p 6,-5" [join [list \
- "2\t0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
- "3\t0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tdec %eax" \
- "4\t0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tjmp 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
- "5\t0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tcmp \\\$0x0,%eax" \
- "6\t0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
+gdb_test "record instruction-history /p 7,-5" [join [list \
+ "3\t0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
+ "4\t0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tdec %eax" \
+ "5\t0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tjmp 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
+ "6\t0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tcmp \\\$0x0,%eax" \
+ "7\t0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
] "\r\n"]
-gdb_test "record instruction-history /pf 2,6" [join [list \
- "2\t0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
- "3\t0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tdec %eax" \
- "4\t0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tjmp 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
- "5\t0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tcmp \\\$0x0,%eax" \
- "6\t0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
+gdb_test "record instruction-history /pf 3,7" [join [list \
+ "3\t0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
+ "4\t0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tdec %eax" \
+ "5\t0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tjmp 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
+ "6\t0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tcmp \\\$0x0,%eax" \
+ "7\t0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
] "\r\n"]
-gdb_test "record instruction-history 2,2" "2\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r"
+gdb_test "record instruction-history 3,3" "3\t 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje 0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r"
# the following tests are checking the iterators
# to avoid lots of regexps, we just check the number of lines that
}
# test that the iterator works
-set history_size 3
+set history_size 4
gdb_test_no_output "set record instruction-history-size $history_size"
set message "browse history forward start"
set lines [test_lines_length "record instruction-history 1" $message]
pass $message
}
-set history_size 2
-gdb_test_no_output "set record instruction-history-size $history_size"
set message "browse history forward middle"
set lines [test_lines_length "record instruction-history +" $message]
if { $lines != $history_size } {
set message "browse history forward last"
set lines [test_lines_length "record instruction-history +" $message]
-if { $lines != 1 } {
+if { $lines != 3 } {
fail $message
} else {
pass $message
# make sure we cannot move further
gdb_test "record instruction-history" "At the end of the branch trace record\\." "browse history forward beyond 2"
-set history_size 3
-gdb_test_no_output "set record instruction-history-size $history_size"
set message "browse history backward last"
set lines [test_lines_length "record instruction-history -" $message]
if { $lines != $history_size } {
pass $message
}
-set history_size 2
-gdb_test_no_output "set record instruction-history-size $history_size"
set message "browse history backward middle"
set lines [test_lines_length "record instruction-history -" $message]
if { $lines != $history_size } {
set message "browse history backward first"
set lines [test_lines_length "record instruction-history -" $message]
-if { $lines != 1 } {
+if { $lines != 3 } {
fail $message
} else {
pass $message
# start by listing all functions
gdb_test "record function-call-history /ci 1, +20" [join [list \
- "1\tfun4\tinst 1,3" \
- "2\t fun1\tinst 4,7" \
- "3\tfun4\tinst 8,8" \
- "4\t fun2\tinst 9,11" \
- "5\t fun1\tinst 12,15" \
- "6\t fun2\tinst 16,17" \
- "7\tfun4\tinst 18,18" \
- "8\t fun3\tinst 19,21" \
- "9\t fun1\tinst 22,25" \
- "10\t fun3\tinst 26,26" \
- "11\t fun2\tinst 27,29" \
- "12\t fun1\tinst 30,33" \
- "13\t fun2\tinst 34,35" \
- "14\t fun3\tinst 36,37" \
- "15\tfun4\tinst 38,39" \
+ "1\tmain\tinst 1,1" \
+ "2\t fun4\tinst 2,4" \
+ "3\t fun1\tinst 5,8" \
+ "4\t fun4\tinst 9,9" \
+ "5\t fun2\tinst 10,12" \
+ "6\t fun1\tinst 13,16" \
+ "7\t fun2\tinst 17,18" \
+ "8\t fun4\tinst 19,19" \
+ "9\t fun3\tinst 20,22" \
+ "10\t fun1\tinst 23,26" \
+ "11\t fun3\tinst 27,27" \
+ "12\t fun2\tinst 28,30" \
+ "13\t fun1\tinst 31,34" \
+ "14\t fun2\tinst 35,36" \
+ "15\t fun3\tinst 37,38" \
+ "16\t fun4\tinst 39,40" \
] "\r\n"]
# let's see if we can go back in history
-gdb_test "record goto 18" ".*fun4 \\(\\) at record_goto.c:43.*"
+gdb_test "record goto 19" ".*fun4 \\(\\) at record_goto.c:43.*"
# the function call history should start at the new location
gdb_test "record function-call-history /ci" [join [list \
- "7\tfun4\tinst 18,18" \
- "8\t fun3\tinst 19,21" \
- "9\t fun1\tinst 22,25" \
- ] "\r\n"] "function-call-history from 18 forwards"
+ "8\t fun4\tinst 19,19" \
+ "9\t fun3\tinst 20,22" \
+ "10\t fun1\tinst 23,26" \
+ ] "\r\n"] "function-call-history from 19 forwards"
# the instruction history should start at the new location
gdb_test "record instruction-history" [join [list \
- "18.*" \
"19.*" \
"20.*" \
- ] "\r\n"] "instruction-history from 18 forwards"
+ "21.*" \
+ ] "\r\n"] "instruction-history from 19 forwards"
# let's go to another place in the history
-gdb_test "record goto 26" ".*fun3 \\(\\) at record_goto.c:35.*"
+gdb_test "record goto 27" ".*fun3 \\(\\) at record_goto.c:35.*"
# check the back trace at that location
gdb_test "backtrace" [join [list \
# the function call history should start at the new location
gdb_test "record function-call-history /ci -" [join [list \
- "8\t fun3\tinst 19,21" \
- "9\t fun1\tinst 22,25" \
- "10\t fun3\tinst 26,26\r" \
- ] "\r\n"] "function-call-history from 26 backwards"
+ "9\t fun3\tinst 20,22" \
+ "10\t fun1\tinst 23,26" \
+ "11\t fun3\tinst 27,27" \
+ ] "\r\n"] "function-call-history from 27 backwards"
# the instruction history should start at the new location
gdb_test "record instruction-history -" [join [list \
- "24.*" \
"25.*" \
- "26.*\r" \
- ] "\r\n"] "instruction-history from 26 backwards"
+ "26.*" \
+ "27.*" \
+ ] "\r\n"] "instruction-history from 27 backwards"
# test that we can go to the begin of the trace
-gdb_test "record goto begin" ".*fun4 \\(\\) at record_goto.c:40.*"
+gdb_test "record goto begin" ".*main \\(\\) at record_goto.c:49.*"
# check that we're filling up the context correctly
gdb_test "record function-call-history /ci -" [join [list \
- "1\tfun4\tinst 1,3" \
- "2\t fun1\tinst 4,7" \
- "3\tfun4\tinst 8,8" \
+ "1\tmain\tinst 1,1" \
+ "2\t fun4\tinst 2,4" \
+ "3\t fun1\tinst 5,8" \
] "\r\n"] "function-call-history from begin backwards"
# check that we're filling up the context correctly
# check that we're filling up the context correctly
gdb_test "record function-call-history /ci -" [join [list \
- "1\tfun4\tinst 1,3" \
- "2\t fun1\tinst 4,7" \
- "3\tfun4\tinst 8,8" \
+ "1\tmain\tinst 1,1" \
+ "2\t fun4\tinst 2,4" \
+ "3\t fun1\tinst 5,8\r" \
] "\r\n"] "function-call-history from 2 backwards"
# check that we're filling up the context correctly
# check that we're filling up the context correctly
gdb_test "record function-call-history /ci" [join [list \
- "13\t fun2\tinst 34,35" \
- "14\t fun3\tinst 36,37" \
- "15\tfun4\tinst 38,39" \
+ "14\t fun2\tinst 35,36" \
+ "15\t fun3\tinst 37,38" \
+ "16\t fun4\tinst 39,40" \
] "\r\n"] "function-call-history from end forwards"
# check that we're filling up the context correctly
gdb_test "record instruction-history" [join [list \
- "37.*" \
"38.*" \
"39.*" \
+ "40.*\r" \
] "\r\n"] "instruction-history from end forwards"
# we should get the exact same history from the second to last instruction
-gdb_test "record goto 38" ".*fun4 \\(\\) at record_goto.c:44.*"
+gdb_test "record goto 39" ".*fun4 \\(\\) at record_goto.c:44.*"
# check that we're filling up the context correctly
gdb_test "record function-call-history /ci" [join [list \
- "13\t fun2\tinst 34,35" \
- "14\t fun3\tinst 36,37" \
- "15\tfun4\tinst 38,39" \
- ] "\r\n"] "function-call-history from 38 forwards"
+ "14\t fun2\tinst 35,36" \
+ "15\t fun3\tinst 37,38" \
+ "16\t fun4\tinst 39,40\r" \
+ ] "\r\n"] "function-call-history from 39 forwards"
# check that we're filling up the context correctly
gdb_test "record instruction-history" [join [list \
- "37.*" \
"38.*" \
"39.*" \
- ] "\r\n"] "instruction-history from 38 forwards"
+ "40.*\r" \
+ ] "\r\n"] "instruction-history from 39 forwards"
# show the flat branch trace
gdb_test "record function-call-history 1" [join [list \
- "1\tfoo" \
- "2\tbar" \
- "3\tmain" \
+ "1\tmain" \
+ "2\tfoo" \
+ "3\tbar" \
+ "4\tmain" \
] "\r\n"] "flat"
# show the branch trace with calls indented
gdb_test "record function-call-history /c 1" [join [list \
- "1\t foo" \
- "2\t bar" \
- "3\tmain" \
+ "1\tmain" \
+ "2\t foo" \
+ "3\t bar" \
+ "4\tmain" \
] "\r\n"] "indented"
# go into bar
-gdb_test "record goto 3" ".*bar \\(\\) at .*x86-tailcall.c:24\r\n.*"
+gdb_test "record goto 4" ".*bar \\(\\) at .*x86-tailcall.c:24\r\n.*"
# check the backtrace
gdb_test "backtrace" [join [list \
# show the flat branch trace
gdb_test "record function-call-history 1" [join [list \
- "1\t\\\?\\\?" \
+ "1\ttest" \
"2\t\\\?\\\?" \
"3\t\\\?\\\?" \
- "4\ttest" \
- "5\tmain" \
- "6\ttest" \
+ "4\t\\\?\\\?" \
+ "5\ttest" \
+ "6\tmain" \
+ "7\ttest" \
] "\r\n"] "flat"
# show the branch trace with calls indented
gdb_test "record function-call-history /c 1" [join [list \
- "1\t \\\?\\\?" \
- "2\t \\\?\\\?" \
- "3\t \\\?\\\?" \
- "4\t test" \
- "5\tmain" \
- "6\t test" \
+ "1\t test" \
+ "2\t \\\?\\\?" \
+ "3\t \\\?\\\?" \
+ "4\t \\\?\\\?" \
+ "5\t test" \
+ "6\tmain" \
+ "7\t test" \
] "\r\n"] "indented"