]>
Commit | Line | Data |
---|---|---|
9c317b71 YQ |
1 | # This testcase is part of GDB, the GNU debugger. |
2 | ||
618f726f | 3 | # Copyright 2011-2016 Free Software Foundation, Inc. |
9c317b71 YQ |
4 | |
5 | # This program is free software; you can redistribute it and/or modify | |
6 | # it under the terms of the GNU General Public License as published by | |
7 | # the Free Software Foundation; either version 3 of the License, or | |
8 | # (at your option) any later version. | |
9 | # | |
10 | # This program is distributed in the hope that it will be useful, | |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | # GNU General Public License for more details. | |
14 | # | |
15 | # You should have received a copy of the GNU General Public License | |
16 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | ||
18 | if { ![support_displaced_stepping] } { | |
19 | unsupported "displaced stepping" | |
20 | return -1 | |
21 | } | |
22 | ||
23 | set syscall_insn "" | |
24 | ||
25 | # Define the syscall instruction for each target. | |
26 | ||
27 | if { [istarget "i\[34567\]86-*-linux*"] || [istarget "x86_64-*-linux*"] } { | |
9a7f938f | 28 | set syscall_insn "\[ \t\](int|syscall|sysenter)\[ \t\]" |
99fd02d9 | 29 | } elseif { [istarget "aarch64*-*-linux*"] || [istarget "arm*-*-linux*"] } { |
5d0a3b53 | 30 | set syscall_insn "\[ \t\](swi|svc)\[ \t\]" |
9c317b71 YQ |
31 | } else { |
32 | return -1 | |
33 | } | |
34 | ||
0a251e08 YQ |
35 | proc disp_step_cross_syscall { syscall } { |
36 | with_test_prefix "$syscall" { | |
37 | global syscall_insn | |
38 | global gdb_prompt | |
9c317b71 | 39 | |
0a251e08 | 40 | set testfile "disp-step-$syscall" |
9c317b71 | 41 | |
0a251e08 YQ |
42 | if [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c {debug}] { |
43 | untested ${testfile}.exp | |
44 | return -1 | |
45 | } | |
9c317b71 | 46 | |
0a251e08 YQ |
47 | if { ![runto main] } then { |
48 | fail "run to main ($syscall)" | |
49 | return | |
50 | } | |
9c317b71 | 51 | |
32d2e5d6 PA |
52 | set is_target_remote [gdb_is_target_remote] |
53 | ||
0a251e08 YQ |
54 | # Delete the breakpoint on main. |
55 | gdb_test_no_output "delete break 1" | |
9c317b71 | 56 | |
0a251e08 YQ |
57 | gdb_test "break marker" "Breakpoint.*at.* file .*${testfile}.c, line.*" |
58 | gdb_test_no_output "set displaced-stepping off" | |
9c317b71 | 59 | |
0a251e08 YQ |
60 | set syscall_bp 0 |
61 | gdb_test_multiple "break $syscall" "break $syscall" { | |
62 | -re "Breakpoint (\[0-9\]*) at .*$gdb_prompt $" { | |
63 | set syscall_bp $expect_out(1,string) | |
64 | pass "break $syscall" | |
65 | } | |
9c317b71 | 66 | } |
9c317b71 | 67 | |
0a251e08 YQ |
68 | gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, (.* in |__libc_|)$syscall \\(\\).*" \ |
69 | "continue to $syscall (1st time)" | |
70 | # Hit the breakpoint on $syscall for the first time. In this time, we will let PLT | |
71 | # resolution done, and the number single steps we will do later will be | |
72 | # reduced. | |
9c317b71 | 73 | |
0a251e08 YQ |
74 | gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, (.* in |__libc_|)$syscall \\(\\).*" \ |
75 | "continue to $syscall (2nd time)" | |
76 | # Hit the breakpoint on $syscall for the second time. In this time, the address | |
77 | # of syscall insn and next insn of syscall are recorded. | |
9c317b71 | 78 | |
0a251e08 | 79 | gdb_test "display/i \$pc" ".*" |
9c317b71 YQ |
80 | |
81 | ||
32d2e5d6 PA |
82 | # Single step until we see a syscall insn or we reach the |
83 | # upper bound of loop iterations. | |
84 | set msg "find syscall insn in $syscall" | |
85 | set steps 0 | |
86 | set max_steps 1000 | |
87 | gdb_test_multiple "stepi" $msg { | |
88 | -re ".*$syscall_insn.*$gdb_prompt $" { | |
89 | pass $msg | |
90 | } | |
91 | -re "x/i .*=>.*\r\n$gdb_prompt $" { | |
92 | incr steps | |
93 | if {$steps == $max_steps} { | |
94 | fail $msg | |
95 | } else { | |
96 | send_gdb "stepi\n" | |
97 | exp_continue | |
0a251e08 | 98 | } |
9c317b71 | 99 | } |
9c317b71 | 100 | } |
9c317b71 | 101 | |
32d2e5d6 | 102 | if {$steps == $max_steps} { |
0a251e08 YQ |
103 | return -1 |
104 | } | |
9c317b71 | 105 | |
0a251e08 | 106 | set syscall_insn_addr [get_hexadecimal_valueof "\$pc" "0"] |
32d2e5d6 PA |
107 | if {[gdb_test "stepi" "x/i .*=>.*" "stepi $syscall insn"] != 0} { |
108 | return -1 | |
109 | } | |
0a251e08 | 110 | set syscall_insn_next_addr [get_hexadecimal_valueof "\$pc" "0"] |
9c317b71 | 111 | |
0a251e08 YQ |
112 | gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, (.* in |__libc_|)$syscall \\(\\).*" \ |
113 | "continue to $syscall (3rd time)" | |
9c317b71 | 114 | |
0a251e08 YQ |
115 | # Hit the breakpoint on $syscall for the third time. In this time, we'll set |
116 | # breakpoint on the syscall insn we recorded previously, and single step over it. | |
9c317b71 | 117 | |
0a251e08 YQ |
118 | set syscall_insn_bp 0 |
119 | gdb_test_multiple "break \*$syscall_insn_addr" "break on syscall insn" { | |
120 | -re "Breakpoint (\[0-9\]*) at .*$gdb_prompt $" { | |
121 | set syscall_insn_bp $expect_out(1,string) | |
122 | pass "break on syscall insns" | |
123 | } | |
9c317b71 | 124 | } |
0a251e08 | 125 | gdb_test_no_output "delete $syscall_bp" "delete break $syscall" |
9c317b71 | 126 | |
0a251e08 YQ |
127 | gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, .*" \ |
128 | "continue to syscall insn $syscall" | |
9c317b71 | 129 | |
0a251e08 | 130 | gdb_test_no_output "set displaced-stepping on" |
9c317b71 | 131 | |
0a251e08 | 132 | # Check the address of next instruction of syscall. |
32d2e5d6 | 133 | if {$syscall == "vfork" && $is_target_remote} { |
0a251e08 | 134 | setup_kfail server/13796 "*-*-*" |
dfe2ac14 | 135 | } |
32d2e5d6 PA |
136 | |
137 | if {[gdb_test "stepi" "x/i .*=>.*" "single step over $syscall"] != 0} { | |
138 | return -1 | |
69dc1c4d | 139 | } |
0a251e08 YQ |
140 | |
141 | set syscall_insn_next_addr_found [get_hexadecimal_valueof "\$pc" "0"] | |
142 | ||
143 | set test "single step over $syscall final pc" | |
144 | if {$syscall_insn_next_addr != 0 | |
145 | && $syscall_insn_next_addr == $syscall_insn_next_addr_found} { | |
dfe2ac14 | 146 | pass $test |
0a251e08 YQ |
147 | } else { |
148 | fail $test | |
dfe2ac14 | 149 | } |
dfe2ac14 | 150 | |
0a251e08 YQ |
151 | # Delete breakpoint syscall insns to avoid interference to other syscalls. |
152 | gdb_test_no_output "delete $syscall_insn_bp" "delete break $syscall insn" | |
9a7f938f | 153 | |
0a251e08 YQ |
154 | gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+, marker \\(\\) at.*" \ |
155 | "continue to marker ($syscall)" | |
9a7f938f | 156 | } |
0a251e08 | 157 | } |
9c317b71 YQ |
158 | |
159 | disp_step_cross_syscall "fork" | |
160 | disp_step_cross_syscall "vfork" |