aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.mi/mi-exec-run.exp
blob: 7e1758f5255dc84424b901ac8a785a607626051f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# Copyright 2016-2018 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/>.

# Test that -exec-run works as expected.  Exercises various testing
# axes:
#
# - MI running on main UI vs separate UI.
#
# - inferior tty set to main tty vs separate tty.
#
# - forking the child failing and sending output to the right inferior
#   terminal, vs the child not failing to start.

load_lib mi-support.exp
set MIFLAGS "-i=mi"

# The purpose of this testcase is to test the -exec-run command. If we
# cannot use it, then there is no point in running this testcase.
if [target_info exists use_gdb_stub] {
     untested "cannot use -exec-run command"
     return -1
}

standard_testfile mi-start.c

if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
     untested "could not build mi-exec-run"
     return -1
}

# The test proper.  INFTTY_MODE determines whether "set inferior-tty"
# is in effect.  MI_MODE determines whether MI is run on the main UI,
# or as a separate UI.  FORCE_FAIL is true when we want -exec-run to
# fail and cause inferior output be sent to the inferior tty.

proc test {inftty_mode mi_mode force_fail} {
    global srcdir subdir binfile srcfile
    global gdb_spawn_id gdb_main_spawn_id mi_spawn_id inferior_spawn_id
    global decimal

    mi_gdb_exit

    set start_ops {}
    if {$inftty_mode == "separate"} {
	lappend start_ops "separate-inferior-tty"
    }
    if {$mi_mode == "separate"} {
	lappend start_ops "separate-mi-tty"
    }

    if [eval mi_gdb_start $start_ops] {
	return
    }

    if {$force_fail} {
	# Disable the shell so that its the first exec that fails,
	# instead of the shell starting and then failing with some
	# unspecified output.
	mi_gdb_test "-gdb-set startup-with-shell off" ".*"
	set bin $binfile.nox
    } else {
	set bin $binfile
    }

    mi_delete_breakpoints
    mi_gdb_reinitialize_dir $srcdir/$subdir
    mi_gdb_reinitialize_dir $srcdir/$subdir
    mi_gdb_load ${bin}

    # Useful for debugging:
    verbose -log "Channels:"
    verbose -log " inferior_spawn_id=$inferior_spawn_id"
    verbose -log " gdb_spawn_id=$gdb_spawn_id"
    verbose -log " gdb_main_spawn_id=$gdb_main_spawn_id"
    verbose -log " mi_spawn_id=$mi_spawn_id"

    if {$force_fail} {
	set saw_perm_error 0
	set saw_mi_error 0
	set test "run failure detected"
	send_gdb "-exec-run --start\n"

	while {1} {
	    gdb_expect {
		-i "$inferior_spawn_id"
		-re ".*Cannot exec.*Permission denied" {
		    set saw_perm_error 1
		    verbose -log "saw mi error"
		}
		-i "$gdb_spawn_id"
		-re "\\^error,msg=\"During startup program exited with code 127" {
		    set saw_mi_error 1
		    verbose -log "saw mi error"
		}
		timeout {
		    fail "$test (timeout)"
		    break
		}
		-i "$gdb_main_spawn_id"
		eof {
		    fail "$test (eof)"
		    break
		}
	    }

	    if {$saw_perm_error && $saw_mi_error} {
		pass $test
		break
	    }
	}
    } else {
	mi_run_cmd "--start"
	mi_expect_stop "breakpoint-hit" "main" "" ".*$srcfile" "$decimal" \
	    { "" "disp=\"del\"" } "breakpoint hit reported on mi"

	if {$mi_mode == "separate"} {
	    # Check that the breakpoint hit is reported on the main
	    # UI/CLI.  Note no prompt is expected.
	    switch_gdb_spawn_id $gdb_main_spawn_id

	    set test "breakpoint hit reported on console"
	    gdb_test_multiple "" $test {
		-re "Temporary breakpoint .*, main \\(\\) at .*$srcfile:$decimal.*return 0;" {
		    pass $test
		}
	    }

	    # Switch back to the MI UI.
	    global mi_spawn_id
	    switch_gdb_spawn_id $mi_spawn_id
	}
    }
}

# Create a not-executable copy of the program, in order to exercise
# vfork->exec failing.
gdb_remote_download host $binfile $binfile.nox
remote_spawn target "chmod \"a-x\" $binfile.nox"

foreach_with_prefix inferior-tty {"main" "separate"} {
    foreach_with_prefix mi {"main" "separate"} {
	foreach_with_prefix force-fail {0 1} {
	    test ${inferior-tty} ${mi} ${force-fail}
	}
    }
}