diff options
author | Doug Evans <dje@google.com> | 2009-01-29 00:29:57 +0000 |
---|---|---|
committer | Doug Evans <dje@google.com> | 2009-01-29 00:29:57 +0000 |
commit | 35669430c88d5bcf7a346d47818c3eef0bf57d96 (patch) | |
tree | 12edeb51967522ebb031fe5b5a7506e8ed021217 /gdb/testsuite/gdb.arch | |
parent | 2211be76e9b95052a9c9403eaf032bd71d52c04c (diff) | |
download | gdb-35669430c88d5bcf7a346d47818c3eef0bf57d96.zip gdb-35669430c88d5bcf7a346d47818c3eef0bf57d96.tar.gz gdb-35669430c88d5bcf7a346d47818c3eef0bf57d96.tar.bz2 |
* opcode/i386.h: Add multiple inclusion protection.
(EAX_REG_NUM,ECX_REG_NUM,EDX_REGNUM,EBX_REG_NUM,ESI_REG_NUM)
(EDI_REG_NUM): New macros.
(MODRM_MOD_FIELD,MODRM_REG_FIELD,MODRM_RM_FIELD): New macros.
(SIB_SCALE_FIELD,SIB_INDEX_FIELD,SIB_BASE_FIELD): New macros.
(REG_PREFIX_P): New macro.
* amd64-tdep.h (amd64_displaced_step_copy_insn): Declare.
(amd64_displaced_step_fixup): Declare.
* amd64-tdep.c: #include opcode/i386.h, dis-asm.h.
(amd64_arch_regmap): Move out of amd64_analyze_stack_align
and make static global.
(amd64_arch_regmap_len): New static global.
(amd64_arch_reg_to_regnum): New function.
(struct amd64_insn): New struct.
(struct displaced_step_closure): New struct.
(onebyte_has_modrm,twobyte_has_modrm): New static globals.
(rex_prefix_p,skip_prefixes)
(amd64_insn_length_fprintf,amd64_insn_length_init_dis)
(amd64_insn_length,amd64_get_unused_input_int_reg)
(amd64_get_insn_details,fixup_riprel,fixup_displaced_copy)
(amd64_displaced_step_copy_insn)
(amd64_absolute_jmp_p,amd64_absolute_call_p,amd64_ret_p)
(amd64_call_p,amd64_breakpoint_p,amd64_syscall_p)
(amd64_displaced_step_fixup): New functions.
* amd64-linux-tdep.c: #include arch-utils.h.
(amd64_linux_init_abi): Install displaced stepping support.
* gdb.arch/amd64-disp-step.S: New file.
* gdb.arch/amd64-disp-step.exp: New file.
* gdb.arch/i386-disp-step.S: New file.
* gdb.arch/i386-disp-step.exp: New file.
Diffstat (limited to 'gdb/testsuite/gdb.arch')
-rw-r--r-- | gdb/testsuite/gdb.arch/amd64-disp-step.S | 153 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/amd64-disp-step.exp | 219 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/i386-disp-step.S | 64 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/i386-disp-step.exp | 112 |
4 files changed, 548 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.arch/amd64-disp-step.S b/gdb/testsuite/gdb.arch/amd64-disp-step.S new file mode 100644 index 0000000..45eeb9b --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-disp-step.S @@ -0,0 +1,153 @@ +/* Copyright 2009 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. + It tests displaced stepping over various insns that require special + handling. */ + + .text + + .global main +main: + nop + +/* test call/ret */ + + .global test_call +test_call: + call test_call_subr + nop + .global test_ret_end +test_ret_end: + nop + +/* test abs-jmp/rep-ret */ + +test_abs_jmp_setup: + mov $test_abs_jmp_return,%rdx + push %rdx + mov $test_abs_jmp_subr,%rdx + .global test_abs_jmp +test_abs_jmp: + jmp *%rdx +test_abs_jmp_return: + nop + .global test_rep_ret_end +test_rep_ret_end: + nop + +/* test syscall */ + + .global test_syscall + mov $0x27,%eax /* getpid */ +test_syscall: + syscall + nop +test_syscall_end: + nop + +/* test rip-relative + GDB picks a spare register to hold the rip-relative address. + Exercise all the possibilities (rax-rdi, sans rsp). */ + + .global test_rip_rax +test_rip_rax: + add answer(%rip),%rax + .global test_rip_rax_end +test_rip_rax_end: + nop + + .global test_rip_rbx +test_rip_rbx: + add answer(%rip),%rbx + .global test_rip_rbx_end +test_rip_rbx_end: + nop + + .global test_rip_rcx +test_rip_rcx: + add answer(%rip),%rcx + .global test_rip_rcx_end +test_rip_rcx_end: + nop + + .global test_rip_rdx +test_rip_rdx: + add answer(%rip),%rdx + .global test_rip_rdx_end +test_rip_rdx_end: + nop + + .global test_rip_rbp +test_rip_rbp: + add answer(%rip),%rbp + .global test_rip_rbp_end +test_rip_rbp_end: + nop + + .global test_rip_rsi +test_rip_rsi: + add answer(%rip),%rsi + .global test_rip_rsi_end +test_rip_rsi_end: + nop + + .global test_rip_rdi +test_rip_rdi: + add answer(%rip),%rdi + .global test_rip_rdi_end +test_rip_rdi_end: + nop + + /* skip over test data */ + jmp done + +/* test rip-relative data */ + +answer: .8byte 42 + +/* all done */ + +done: + mov $0,%rdi + call exit + hlt + +/***********************************************/ + +/* subroutine to help test call/ret */ + +test_call_subr: + nop + .global test_call_end +test_call_end: + nop + + .global test_ret +test_ret: + ret + +/* subroutine to help test abs-jmp/rep-ret */ + +test_abs_jmp_subr: + nop + .global test_abs_jmp_end +test_abs_jmp_end: + nop + + .global test_rep_ret +test_rep_ret: + repz + ret diff --git a/gdb/testsuite/gdb.arch/amd64-disp-step.exp b/gdb/testsuite/gdb.arch/amd64-disp-step.exp new file mode 100644 index 0000000..26ebe59 --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-disp-step.exp @@ -0,0 +1,219 @@ +# Copyright 2009 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 +} + +set prms_id 0 +set bug_id 0 + +if ![istarget "x86_64-*-linux*"] then { + 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" + +########################################## + +# 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" diff --git a/gdb/testsuite/gdb.arch/i386-disp-step.S b/gdb/testsuite/gdb.arch/i386-disp-step.S new file mode 100644 index 0000000..a56ff1c --- /dev/null +++ b/gdb/testsuite/gdb.arch/i386-disp-step.S @@ -0,0 +1,64 @@ +/* Copyright 2009 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. + It tests displaced stepping over various insns that require special + handling. */ + + .text + + .global main +main: + nop + +/* test call/ret */ + + .global test_call +test_call: + call test_call_subr + nop + .global test_ret_end +test_ret_end: + nop + +/* test syscall */ + + .global test_syscall + mov $0x14,%eax /* getpid */ +test_syscall: + int $0x80 + nop +test_syscall_end: + nop + +/* all done */ + + pushl $0 + call exit + hlt + +/***********************************************/ + +/* subroutine to help test call/ret */ + +test_call_subr: + nop + .global test_call_end +test_call_end: + nop + + .global test_ret +test_ret: + ret diff --git a/gdb/testsuite/gdb.arch/i386-disp-step.exp b/gdb/testsuite/gdb.arch/i386-disp-step.exp new file mode 100644 index 0000000..06c5fb2 --- /dev/null +++ b/gdb/testsuite/gdb.arch/i386-disp-step.exp @@ -0,0 +1,112 @@ +# Copyright 2009 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 i386 displaced stepping. + +if $tracelevel { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +if ![istarget "i?86-*-linux*"] then { + verbose "Skipping x86 displaced stepping tests." + return +} + +set testfile "i386-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 i386-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 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" + +########################################## + +# Done, run program to exit. + +gdb_continue_to_end "i386-disp-step" |