# Copyright 2009-2019 Free Software Foundation, Inc. # 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 . # This file is part of the gdb testsuite. # Test amd64 displaced stepping. if { ![istarget x86_64-*-* ] || ![is_lp64_target] } { verbose "Skipping x86_64 displaced stepping tests." return } set newline "\[\r\n\]*" set opts {debug nopie} standard_testfile .S if { [prepare_for_testing "failed to prepare" $testfile $srcfile $opts] } { return -1 } gdb_test "set displaced-stepping on" "" gdb_test "show displaced-stepping" ".* displaced stepping .* is on.*" if ![runto_main] then { fail "can't run to main" return 0 } ########################################## # Test call/ret. gdb_test "break test_call" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_call" gdb_test "break test_call_end" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_call_end" gdb_test "break test_ret" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_ret" gdb_test "break test_ret_end" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_ret_end" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_call ().*" \ "continue to test_call" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_call_end ().*" \ "continue to test_call_end" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_ret ().*" \ "continue to test_ret" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_ret_end ().*" \ "continue to test_ret_end" ########################################## # Test abs-jmp/rep-ret. gdb_test "break test_abs_jmp" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_abs_jmp" gdb_test "break test_abs_jmp_end" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_abs_jmp_end" gdb_test "break test_rep_ret" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_rep_ret" gdb_test "break test_rep_ret_end" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_rep_ret_end" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_abs_jmp ().*" \ "continue to test_abs_jmp" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_abs_jmp_end ().*" \ "continue to test_abs_jmp_end" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_rep_ret ().*" \ "continue to test_rep_ret" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_rep_ret_end ().*" \ "continue to test_rep_ret_end" ########################################## # Test syscall. gdb_test "break test_syscall" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_syscall" gdb_test "break test_syscall_end" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_syscall_end" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_syscall ().*" \ "continue to test_syscall" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_syscall_end ().*" \ "continue to test_syscall_end" ########################################## # int3 (with prefixes) # These don't occur in normal code, but gdb should still DTRT. gdb_test "break test_int3" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_int3" gdb_test "break test_int3_end" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break test_int3_end" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_int3 ().*" \ "continue to test_int3" gdb_test "continue" \ "Continuing.*Breakpoint.*, test_int3_end ().*" \ "continue to test_int3_end" ########################################## # Test rip-relative. # GDB picks a spare register to hold the rip-relative address. # Exercise all the possibilities (rax-rdi, sans rsp). # The order must much the order in srcfile. set rip_regs { "rax" "rbx" "rcx" "rdx" "rbp" "rsi" "rdi" } # Assign val to all specified regs. proc set_regs { regs val } { global gdb_prompt foreach reg ${regs} { # Use send_gdb/gdb_expect so that these aren't logged as pass/fail. send_gdb "set \$${reg} = ${val}\n" gdb_expect 10 { -re "$gdb_prompt $" { verbose "Setting ${reg} to ${val}." 2 } timeout { warning "Couldn't set ${reg} to ${val}." } } } } # Verify all REGS equal VAL, except REG which equals REG_VAL. proc verify_regs { test_name regs val except_reg except_reg_val } { global newline foreach reg ${regs} { set expected ${val} if { "${reg}" == "${except_reg}" } { set expected ${except_reg_val} } # The cast to (int) is because RBP is printed as a pointer. gdb_test "p (int) \$${reg}" " = ${expected}${newline}" "${test_name} ${reg} expected value" } } proc rip_test { reg } { global srcfile rip_regs set test_start_label "test_rip_${reg}" set test_end_label "test_rip_${reg}_end" gdb_test "break ${test_start_label}" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break ${test_start_label}" gdb_test "break ${test_end_label}" \ "Breakpoint.*at.* file .*$srcfile, line.*" \ "break ${test_end_label}" gdb_test "continue" \ "Continuing.*Breakpoint.*, ${test_start_label} ().*" \ "continue to ${test_start_label}" set_regs ${rip_regs} 0 gdb_test "continue" \ "Continuing.*Breakpoint.*, ${test_end_label} ().*" \ "continue to ${test_end_label}" verify_regs "test rip w/${reg}" ${rip_regs} 0 ${reg} 42 } foreach reg ${rip_regs} { rip_test $reg } ########################################## # Done, run program to exit. gdb_continue_to_end "amd64-disp-step"