| # Copyright 2009, 2010 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 <http://www.gnu.org/licenses/>. |
| |
| # This file is part of the gdb testsuite. |
| |
| # Test amd64 displaced stepping. |
| |
| if $tracelevel { |
| strace $tracelevel |
| } |
| |
| |
| if { ![istarget x86_64-*-* ] || ![is_lp64_target] } { |
| verbose "Skipping x86_64 displaced stepping tests." |
| return |
| } |
| |
| set newline "\[\r\n\]*" |
| |
| set testfile "amd64-disp-step" |
| set srcfile ${testfile}.S |
| set binfile ${objdir}/${subdir}/${testfile} |
| |
| set additional_flags "-Wa,-g" |
| |
| if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug $additional_flags]] != "" } { |
| untested amd64-disp-step.exp |
| return -1 |
| } |
| |
| # Get things started. |
| |
| gdb_exit |
| gdb_start |
| gdb_reinitialize_dir $srcdir/$subdir |
| gdb_load ${binfile} |
| |
| 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" |