1# Copyright 2012-2023 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16# Optionally test a Python API here as well. 17load_lib gdb-python.exp 18 19standard_testfile jit-reader-host.c 20 21if { (![istarget x86_64-*-*] && ![istarget i?86-*-*]) || ![is_lp64_target] } { 22 return -1; 23} 24 25if {[skip_shlib_tests]} { 26 return -1 27} 28 29if { ![isnative] } { 30 return -1 31} 32 33# Increase this to see more detail. 34set test_verbose 0 35 36set jit_host_src $srcfile 37set jit_host_bin $binfile 38 39# We inject the complete path to jit-reader.h into the source file 40# lest we end up (incorrectly) building against a system-installed 41# version. 42set jit_reader_header [standard_output_file "../../../../../gdb/jit-reader.h"] 43set jit_reader_flag "-DJIT_READER_H=\"$jit_reader_header\"" 44 45if { [gdb_compile "${srcdir}/${subdir}/${jit_host_src}" "${jit_host_bin}" \ 46 executable [list debug additional_flags=$jit_reader_flag]] != "" } { 47 untested "failed to compile" 48 return -1 49} 50 51set jit_reader jit-reader 52set jit_reader_src ${jit_reader}.c 53set jit_reader_bin [standard_output_file ${jit_reader}.so] 54 55if { [gdb_compile_shlib "${srcdir}/${subdir}/${jit_reader_src}" "${jit_reader_bin}" \ 56 [list debug additional_flags=$jit_reader_flag]] != "" } { 57 untested "failed to compile" 58 return -1 59} 60 61# Test "info registers" in the current frame, expecting RSP's value to 62# be SP. 63 64proc info_registers_current_frame {sp} { 65 global hex decimal 66 67 set any "\[^\r\n\]*" 68 69 set neg_decimal "-?$decimal" 70 71 set expected \ 72 [multi_line \ 73 "rax $hex +$neg_decimal" \ 74 "rbx $hex +$neg_decimal" \ 75 "rcx $hex +$neg_decimal" \ 76 "rdx $hex +$neg_decimal" \ 77 "rsi $hex +$neg_decimal" \ 78 "rdi $hex +$neg_decimal" \ 79 "rbp $hex +$hex" \ 80 "rsp $sp +$sp" \ 81 "r8 $hex +$neg_decimal" \ 82 "r9 $hex +$neg_decimal" \ 83 "r10 $hex +$neg_decimal" \ 84 "r11 $hex +$neg_decimal" \ 85 "r12 $hex +$neg_decimal" \ 86 "r13 $hex +$neg_decimal" \ 87 "r14 $hex +$neg_decimal" \ 88 "r15 $hex +$neg_decimal" \ 89 "rip $hex +$hex$any" \ 90 "eflags $hex +\\\[$any\\\]" \ 91 "cs $hex +$neg_decimal" \ 92 "ss $hex +$neg_decimal" \ 93 "ds $hex +$neg_decimal" \ 94 "es $hex +$neg_decimal" \ 95 "fs $hex +$neg_decimal" \ 96 "gs $hex +$neg_decimal" \ 97 ] 98 99 # There may be more registers. 100 append expected ".*" 101 102 gdb_test "info registers" $expected 103} 104 105proc jit_reader_test {} { 106 global jit_host_bin 107 global jit_reader_bin 108 global test_verbose 109 global hex decimal 110 111 set any "\[^\r\n\]*" 112 113 clean_restart $jit_host_bin 114 gdb_load_shlib $jit_reader_bin 115 116 if {$test_verbose > 0} { 117 gdb_test_no_output "set debug jit 1" 118 } 119 120 gdb_test_no_output "jit-reader-load ${jit_reader_bin}" "jit-reader-load" 121 gdb_run_cmd 122 gdb_test "" "Program received signal SIGTRAP, .*" "expect SIGTRAP" 123 124 # Test the JIT reader unwinder. 125 with_test_prefix "with jit-reader" { 126 127 with_test_prefix "before mangling" { 128 gdb_test "bt" \ 129 [multi_line \ 130 "#0 ${any} in jit_function_stack_mangle ${any}" \ 131 "#1 ${any} in main ${any}" \ 132 ] \ 133 "bt works" 134 135 set sp_before_mangling \ 136 [get_hexadecimal_valueof "\$sp" 0 "get sp"] 137 138 gdb_test "up" "#1 $any in main $any\r\n$any function_stack_mangle $any" \ 139 "move up to caller" 140 141 set caller_sp \ 142 [get_hexadecimal_valueof "\$sp" 0 "get caller sp"] 143 } 144 145 # Step over the instruction that mangles the stack pointer. 146 # While that confuses GDB's built-in unwinder, the JIT 147 # reader's unwinder understands the mangling and should thus 148 # be able to unwind at that location. 149 with_test_prefix "after mangling" { 150 gdb_test "si" "in jit_function_stack_mangle .*" "step over stack mangling" 151 152 set sp_after_mangling \ 153 [get_hexadecimal_valueof "\$sp" 0 "get sp"] 154 155 gdb_assert {$sp_before_mangling != $sp_after_mangling} \ 156 "sp is mangled" 157 158 # Check that the jit unwinder manages to backtrace through 159 # the mangled stack pointer. 160 gdb_test "bt" \ 161 [multi_line \ 162 "#0 ${any} in jit_function_stack_mangle ${any}" \ 163 "#1 ${any} in main ${any}" \ 164 ] \ 165 "bt works" 166 167 with_test_prefix "current frame" { 168 info_registers_current_frame $sp_after_mangling 169 170 gdb_test "info frame" \ 171 "Stack level 0, frame at $sp_before_mangling.*in jit_function_stack_mangle.*" 172 } 173 174 with_test_prefix "caller frame" { 175 gdb_test "up" "#1 $any in main $any\r\n$any function_stack_mangle $any" \ 176 "up to caller" 177 178 # Since the JIT unwinder only provides RIP/RSP/RBP, 179 # all other registers should show as "<not saved>". 180 181 set expected \ 182 [multi_line \ 183 "rax <not saved>" \ 184 "rbx <not saved>" \ 185 "rcx <not saved>" \ 186 "rdx <not saved>" \ 187 "rsi <not saved>" \ 188 "rdi <not saved>" \ 189 "rbp $hex +$hex" \ 190 "rsp $caller_sp +$caller_sp" \ 191 "r8 <not saved>" \ 192 "r9 <not saved>" \ 193 "r10 <not saved>" \ 194 "r11 <not saved>" \ 195 "r12 <not saved>" \ 196 "r13 <not saved>" \ 197 "r14 <not saved>" \ 198 "r15 <not saved>" \ 199 "rip $hex +$hex $any" \ 200 "eflags <not saved>" \ 201 "cs <not saved>" \ 202 "ss <not saved>" \ 203 "ds <not saved>" \ 204 "es <not saved>" \ 205 "fs <not saved>" \ 206 "gs <not saved>" \ 207 ] 208 209 # There may be more registers. 210 append expected ".*" 211 212 gdb_test "info registers" $expected 213 214 # Make sure that "info frame" doesn't crash. 215 gdb_test "info frame" "Stack level 1, .*in main.*" 216 217 # ... and that neither does printing a pseudo 218 # register. 219 gdb_test "print /x \$ebp" " = $hex" "print pseudo register" 220 221 # There's no way for the JIT reader API to support 222 # modifyiable values. 223 gdb_test "print \$rbp = -1" \ 224 "Attempt to assign to an unmodifiable value\." \ 225 "cannot assign to register" 226 } 227 228 if { ![skip_python_tests] } { 229 gdb_test "python print(gdb.objfiles())" \ 230 "$any<gdb.Objfile filename=<< JIT compiled code at $hex >>>$any" \ 231 "python gdb.Objfile.__repr__ ()" 232 233 gdb_test "python print(list(map(lambda objf : objf.filename, gdb.objfiles())))" \ 234 "$any'<< JIT compiled code at $hex >>'$any" \ 235 "python gdb.Objfile.filename" 236 } 237 } 238 } 239 240 # Now unload the jit reader, and ensure that backtracing really 241 # doesn't work without it. 242 with_test_prefix "without jit-reader" { 243 gdb_test_no_output "jit-reader-unload ${jit_reader_bin}" \ 244 "jit-reader-unload" 245 246 # Check that we're no longer using the JIT unwinder, and that 247 # the built-in unwinder cannot backtrace through the mangled 248 # stack pointer. 249 gdb_test "bt" \ 250 "Backtrace stopped: Cannot access memory at address $sp_after_mangling" \ 251 "bt shows error" 252 253 gdb_test "info frame" "Cannot access memory at address.*" \ 254 "info frame shows error" 255 info_registers_current_frame $sp_after_mangling 256 gdb_test "up" "Initial frame selected; you cannot go up\\." \ 257 "cannot go up" 258 } 259 260 with_test_prefix "with jit-reader again" { 261 gdb_test_no_output "jit-reader-load ${jit_reader_bin}" "jit-reader-load" 262 263 # Check that the jit unwinder manages to backtrace through 264 # the mangled stack pointer. 265 gdb_test "bt" \ 266 [multi_line \ 267 "#0 ${any} in jit_function_stack_mangle ${any}" \ 268 "#1 ${any} in main ${any}" \ 269 ] 270 } 271 272 if {![skip_python_tests]} { 273 gdb_test "python print(any(\[not x.is_file for x in gdb.objfiles()\]))" \ 274 "True" \ 275 "at least one non-file objfile" 276 gdb_test "python print(any(\[x.is_file for x in gdb.objfiles()\]))" \ 277 "True" \ 278 "at least one file-based objfile" 279 } 280 281 with_test_prefix "test dwarf unwinder" { 282 # Check that the DWARF unwinder does not crash in presence of 283 # JIT objfiles. 284 gdb_test "up" 285 gdb_breakpoint "*function_add" temporary 286 gdb_test "cont" ".*Temporary breakpoint ${any} in jit_function_add .*" 287 gdb_test "bt" \ 288 [multi_line \ 289 "#0 ${any} in jit_function_add ${any}" \ 290 "#1 ${any} in main ${any}" \ 291 ] 292 } 293} 294 295jit_reader_test 296