1 # Copyright 2009-2024 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 # This file is part of the gdb testsuite. 17 18 # Test displaced stepping over VEX-encoded RIP-relative AVX 19 # instructions. 20 21 require is_x86_64_m64_target have_avx 22 23 standard_testfile .S 24 25 set options [list debug nopie] 26 if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} $options] } { 27 return -1 28 } 29 30 # Get things started. 31 32 gdb_test "set displaced-stepping on" "" 33 gdb_test "show displaced-stepping" ".* displaced stepping .* is on.*" 34 35 if {![runto_main]} { 36 return 0 37 } 38 39 # GDB picks a spare register from this list to hold the RIP-relative 40 # address. 41 set rip_regs { "rax" "rbx" "rcx" "rdx" "rbp" "rsi" "rdi" } 42 43 # Assign VAL to all the RIP_REGS. 44 45 proc set_regs { val } { 46 global gdb_prompt 47 global rip_regs 48 49 foreach reg ${rip_regs} { 50 gdb_test_no_output "set \$${reg} = ${val}" 51 } 52 } 53 54 # Verify all RIP_REGS print as HEX_VAL_RE in hex. 55 56 proc verify_regs { hex_val_re } { 57 global rip_regs 58 59 foreach reg ${rip_regs} { 60 gdb_test "p /x \$${reg}" " = ${hex_val_re}" "${reg} expected value" 61 } 62 } 63 64 # Set a break at FUNC, which starts with a RIP-relative instruction 65 # that we want to displaced-step over, and then continue over the 66 # breakpoint, forcing a displaced-stepping sequence. 67 68 proc disp_step_func { func } { 69 global srcfile 70 71 set test_start_label "${func}" 72 set test_end_label "${func}_end" 73 74 gdb_test "break ${test_start_label}" \ 75 "Breakpoint.*at.* file .*$srcfile, line.*" 76 gdb_test "break ${test_end_label}" \ 77 "Breakpoint.*at.* file .*$srcfile, line.*" 78 79 gdb_test "continue" \ 80 "Continuing.*Breakpoint.*, ${test_start_label} ().*" \ 81 "continue to ${test_start_label}" 82 83 # GDB picks a spare register to hold the RIP-relative address. 84 # Ensure the spare register value is restored properly (rax-rdi, 85 # sans rsp). 86 set value "0xdeadbeefd3adb33f" 87 set_regs $value 88 89 # Turn "debug displaced" on to make sure a displaced step is actually 90 # executed, not an inline step. 91 gdb_test_no_output "set debug displaced on" 92 93 gdb_test "continue" \ 94 "Continuing.*prepared successfully .*Breakpoint.*, ${test_end_label} ().*" \ 95 "continue to ${test_end_label}" 96 97 gdb_test_no_output "set debug displaced off" 98 99 verify_regs $value 100 } 101 102 # Test a VEX2-encoded RIP-relative instruction. 103 with_test_prefix "vex2" { 104 # Initialize all XMM registers to 0. 105 for {set i 0 } { $i < 16 } { incr i } { 106 gdb_test_no_output "set \$xmm${i}.uint128 = 0" \ 107 "xmm${i} set to zero" 108 } 109 110 disp_step_func "test_rip_vex2" 111 112 # Confirm the instruction's expected side effects. It should have 113 # modified xmm0. 114 gdb_test "p /x \$xmm0.uint128" " = 0x1122334455667788" \ 115 "xmm0 has expected value after" 116 117 # And all of the other XMM register should still be 0. 118 for {set i 1 } { $i < 16 } { incr i } { 119 gdb_test "p /x \$xmm${i}.uint128" " = 0x0" \ 120 "xmm${i} has expected value after" 121 } 122 } 123 124 # Test a VEX3-encoded RIP-relative instruction. 125 with_test_prefix "vex3" { 126 # This case writes to the 'var128' variable. Confirm the 127 # variable's value is what we believe it is before the AVX 128 # instruction runs. 129 gdb_test "p /x (unsigned long long \[2\]) var128" \ 130 " = \\{0xaa55aa55aa55aa55, 0x55aa55aa55aa55aa\\}" \ 131 "var128 has expected value before" 132 133 # Run the AVX instruction. 134 disp_step_func "test_rip_vex3" 135 136 # Confirm the instruction's expected side effects. It should have 137 # modifed the 'var128' variable. 138 gdb_test "p /x (unsigned long long \[2\]) var128" \ 139 " = \\{0x1122334455667788, 0x0\\}" \ 140 "var128 has expected value after" 141 } 142 143 # Done, run program to exit. 144 gdb_continue_to_end "amd64-disp-step-avx" 145