ptwrite.exp revision 1.1 1 # This testcase is part of GDB, the GNU debugger.
2 #
3 # Copyright 2024 Free Software Foundation, Inc.
4 #
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 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 load_lib gdb-python.exp
19
20 require allow_btrace_ptw_tests allow_python_tests
21
22 set opts {}
23
24 if [info exists COMPILE] {
25 # make check RUNTESTFLAGS="gdb.btrace/ptwrite.exp COMPILE=1"
26 standard_testfile ptwrite.c
27 lappend opts debug additional_flags=-mptwrite
28 } elseif {[istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} {
29 if {[is_amd64_regs_target]} {
30 standard_testfile x86_64-ptwrite.S
31 } else {
32 standard_testfile i386-ptwrite.S
33 }
34 } else {
35 unsupported "target architecture not supported"
36 return -1
37 }
38
39 if [prepare_for_testing "failed to prepare" $testfile $srcfile $opts] {
40 return -1
41 }
42
43 if { ![runto_main] } {
44 untested "failed to run to main"
45 return -1
46 }
47
48 ### 1. Default testrun
49
50 # Setup recording
51 gdb_test_no_output "set record instruction-history-size unlimited"
52 gdb_test_no_output "record btrace pt"
53 gdb_test "next 2" ".*"
54
55 with_test_prefix "Default" {
56 # Test record instruction-history
57 gdb_test "record instruction-history 1" [multi_line \
58 ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
59 "\[0-9\]+\t \\\[0x42\\\]" \
60 ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
61 "\[0-9\]+\t \\\[0x43\\\].*" \
62 ]
63
64 gdb_test "record instruction-history /a 1" [multi_line \
65 ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
66 ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+.*" \
67 ]
68
69 # Test function call history
70 gdb_test "record function-call-history 1,4" [multi_line \
71 "1\tmain" \
72 "2\tptwrite1" \
73 "\t \\\[0x42\\\]" \
74 "3\tmain" \
75 "4\tptwrite2" \
76 "\t \\\[0x43\\\]" \
77 ]
78
79 gdb_test "record function-call-history /a 1,4" [multi_line \
80 "1\tmain" \
81 "2\tptwrite1" \
82 "3\tmain" \
83 "4\tptwrite2" \
84 ]
85 }
86
87 # Test payload printing during stepping
88 with_test_prefix "Stepping" {
89 gdb_test "record goto 10" "Can't go to an auxiliary instruction\."
90 gdb_test "record goto 9" ".*ptwrite.* at .*"
91 gdb_test "stepi" ".*\\\[0x42\\\].*"
92 gdb_test "reverse-stepi" ".*\\\[0x42\\\].*"
93 gdb_test "continue" [multi_line \
94 ".*\\\[0x42\\\]" \
95 "\\\[0x43\\\].*" \
96 ]
97 gdb_test "reverse-continue" [multi_line \
98 ".*\\\[0x43\\\]" \
99 "\\\[0x42\\\].*" \
100 ]
101 }
102
103 # Test auxiliary type in python
104 gdb_test_multiline "auxiliary type in python" \
105 "python" "" \
106 "h = gdb.current_recording().instruction_history" "" \
107 "for insn in h:" "" \
108 " if hasattr(insn, 'decoded'):" "" \
109 " print(insn.decoded.decode())" "" \
110 " elif hasattr(insn, 'data'):" "" \
111 " print(insn.data)" "" \
112 "end" \
113 [multi_line \
114 ".*mov -0x4\\\(%(e|r)bp\\\),%(e|r)ax" \
115 "ptwrite %eax" \
116 "0x42" \
117 "nop.*" \
118 "mov -0x4\\\(%(e|r)bp\\\),%(e|r)ax" \
119 "ptwrite %eax" \
120 "0x43" \
121 "nop.*"
122 ]
123
124
125 ### 2. Test filter registration
126 ### 2.1 Custom filter
127 with_test_prefix "Custom" {
128 gdb_test_multiline "register filter in python" \
129 "python" "" \
130 "def my_filter(payload, ip):" "" \
131 " if payload == 66:" "" \
132 " return \"payload: {0}, ip: {1:#x}\".format(payload, ip)" "" \
133 " else:" "" \
134 " return None" "" \
135 "def factory(thread): return my_filter" "" \
136 "import gdb.ptwrite" "" \
137 "gdb.ptwrite.register_filter_factory(factory)" "" \
138 "end" ""
139
140 gdb_test "record instruction-history 1" [multi_line \
141 ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
142 "\[0-9\]+\t \\\[payload: 66, ip: $hex\\\]" \
143 ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
144 "\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:.*" \
145 ]
146 }
147
148 ### 2.2 None as filter. This resets the default behavior.
149 with_test_prefix "None" {
150 gdb_test_multiline "register filter in python" \
151 "python" "" \
152 "import gdb.ptwrite" "" \
153 "gdb.ptwrite.register_filter_factory(None)" "" \
154 "end" ""
155
156 gdb_test "record instruction-history 1" [multi_line \
157 ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
158 "\[0-9\]+\t \\\[0x42\\\]" \
159 ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
160 "\[0-9\]+\t \\\[0x43\\\].*" \
161 ]
162 }
163
164 ### 2.3 Lambdas as filter
165 with_test_prefix "Lambdas" {
166 gdb_test_multiline "register filter in python" \
167 "python" "" \
168 "import gdb.ptwrite" "" \
169 "lambda_filter = lambda payload, ip: \"{}\".format(payload + 2)" "" \
170 "gdb.ptwrite.register_filter_factory(lambda thread : lambda_filter)" "" \
171 "end" ""
172
173 gdb_test "record instruction-history 1" [multi_line \
174 ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
175 "\[0-9\]+\t \\\[68\\\]" \
176 ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
177 "\[0-9\]+\t \\\[69\\\].*" \
178 ] "Lambdas: record instruction-history 1"
179 }
180
181 ### 2.4 Functors as filter
182 with_test_prefix "Functors" {
183 gdb_test_multiline "register filter in python" \
184 "python" "" \
185 "import gdb.ptwrite" "" \
186 "class foobar(object):" "" \
187 " def __init__(self):" "" \
188 " self.variable = 0" "" \
189 " def __call__(self, payload, ip):" "" \
190 " self.variable += 1" "" \
191 " return \"{}, {}\".format(self.variable, payload)" "" \
192 "gdb.ptwrite.register_filter_factory(lambda thread : foobar())" "" \
193 "end" ""
194
195 gdb_test "record instruction-history 1" [multi_line \
196 ".*\[0-9\]+\t $hex <ptwrite1\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
197 "\[0-9\]+\t \\\[1, 66\\\]" \
198 ".*\[0-9\]+\t $hex <ptwrite2\\+\[0-9\]+>:\tptwrite %\[a-z\]+" \
199 "\[0-9\]+\t \\\[2, 67\\\].*" \
200 ] "Functors: record instruction-history 1"
201 }
202