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