aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.base/solib-search.exp
blob: eaabe508bf06b01ce784164740694fa6800d1dc8 (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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# Copyright 2013-2022 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 solib-search-path, and in the case of solib-svr4.c whether l_addr_p
# is properly reset when the path is changed.

if {[is_remote target] || [skip_shlib_tests]} {
    untested "skipping remote target and shared library tests"
    return -1
}

# This is required by gdb_compile_shlib.
if {[get_compiler_info]} {
    warning "Could not get compiler info"
    untested "no compiler info"
    return 1
}

# Build "wrong" and "right" versions of the libraries in separate directories.
set wrong_lib_subdir "solib-search-wrong"
set right_lib_subdir "solib-search-right"

# First library file.
set libname1 "solib-search-lib1"
set srcfile1_lib ${srcdir}/${subdir}/${libname1}.c
set wrong_binfile1_lib \
    [standard_output_file ${wrong_lib_subdir}/${libname1}.so]
set right_binfile1_lib \
    [standard_output_file ${right_lib_subdir}/${libname1}.so]
# Second library file.
set libname2 "solib-search-lib2"
set srcfile2_lib ${srcdir}/${subdir}/${libname2}.c
set wrong_binfile2_lib \
    [standard_output_file ${wrong_lib_subdir}/${libname2}.so]
set right_binfile2_lib \
    [standard_output_file ${right_lib_subdir}/${libname2}.so]
# Link with the library that lives here.
# This is so that we can replace what gdb sees with the wrong copy,
# and then tell gdb to use the right copy that lives someplace else.
set binfile1_lib [standard_output_file ${libname1}.so]
set binfile2_lib [standard_output_file ${libname2}.so]

set lib_flags [list debug ldflags=-Wl,-Bsymbolic]
set wrong_lib_flags "$lib_flags additional_flags=-DARRAY_SIZE=1"
set right_lib_flags "$lib_flags additional_flags=-DARRAY_SIZE=8192 -DRIGHT"

# Binary file.
standard_testfile .c
set bin_flags [list debug shlib=${binfile1_lib} shlib=${binfile2_lib}]

remote_exec build "rm -rf [standard_output_file ${wrong_lib_subdir}]"
remote_exec build "rm -rf [standard_output_file ${right_lib_subdir}]"
remote_exec build "mkdir [standard_output_file ${wrong_lib_subdir}]"
remote_exec build "mkdir [standard_output_file ${right_lib_subdir}]"

if { [gdb_compile_shlib ${srcfile1_lib} ${wrong_binfile1_lib} $wrong_lib_flags] != ""
     || [gdb_compile_shlib ${srcfile2_lib} ${wrong_binfile2_lib} $wrong_lib_flags] != ""
     || [gdb_compile_shlib ${srcfile1_lib} ${right_binfile1_lib} $right_lib_flags] != ""
     || [gdb_compile_shlib ${srcfile2_lib} ${right_binfile2_lib} $right_lib_flags] != "" } {
    untested "failed to compile shared library"
    return -1
}

# Build the test binary using the right copies of the libraries.
remote_exec build "ln -sf ${right_lib_subdir}/${libname1}.so ${binfile1_lib}"
remote_exec build "ln -sf ${right_lib_subdir}/${libname2}.so ${binfile2_lib}"
if { [gdb_compile $srcdir/$subdir/${srcfile} ${binfile} \
	  executable $bin_flags] != "" } {
    untested "failed to compile"
    return -1
}

clean_restart $testfile

if { ![runto_main] } {
    return
}

gdb_breakpoint "break_here"
gdb_continue "break_here"

set corefile [standard_output_file solib-search.core]
set core_supported [gdb_gcore_cmd "$corefile" "save a corefile"]

if {!$core_supported} {
  return -1
}

# Before we restart gdb, replace the libs with the "wrong" ones.
remote_exec build "ln -sf ${wrong_lib_subdir}/${libname1}.so ${binfile1_lib}"
remote_exec build "ln -sf ${wrong_lib_subdir}/${libname2}.so ${binfile2_lib}"

clean_restart $testfile

set core_loaded [gdb_core_cmd $corefile "re-load generated corefile"]
if { $core_loaded == -1 } {
    # No use proceeding from here.
    return
}

proc test_backtrace { expect_fail } {
    global gdb_prompt

    set count 0
    set total_expected 5

    if { $expect_fail } {
	set testname "backtrace (with wrong libs)"
    } else {
	set testname "backtrace (with right libs)"
    }
    # N.B. The order of the tests here is important.
    # We need to count each function in the backtrace, and expect matches
    # the first one it finds.
    gdb_test_multiple "backtrace" $testname {
	-re "\[^\r\n\]* in lib2_func4 \[^\r\n\]*" {
	    incr count
	    exp_continue
	}
	-re "\[^\r\n\]* in lib1_func3 \[^\r\n\]*" {
	    incr count
	    exp_continue
	}
	-re "\[^\r\n\]* in lib2_func2 \[^\r\n\]*" {
	    incr count
	    exp_continue
	}
	-re "\[^\r\n\]* in lib1_func1 \[^\r\n\]*" {
	    incr count
	    exp_continue
	}
	-re "\[^\r\n\]* in main \[^\r\n\]*" {
	    incr count
	    exp_continue
	}
	-re "\[\r\n\]$gdb_prompt $" {
	    pass "$testname (data collection)"
	}
    }

    set fail 0
    if { $expect_fail } {
	# If the backtrace output is correct the test isn't sufficiently
	# testing what it should.
	if { $count == $total_expected } {
	    set fail 1
	}
    } else {
	if { $count != $total_expected } {
	    set fail 1
	}
    }
    if { $fail } {
	fail $testname
    } else {
	pass $testname
    }
}

# Verify the backtrace is messed up.
test_backtrace 1

# Remove the copies gdb currently sees: the absolute path is encoded in
# the core file and we want gdb to find the right copies elsewhere.
remote_exec build "rm -f ${binfile1_lib}"
remote_exec build "rm -f ${binfile2_lib}"
# Set solib-search-path to use the correct copies of libraries.
gdb_test "set solib-search-path [standard_output_file ${right_lib_subdir}]" \
    "" \
    "set solib-search-path"

# Verify gdb has properly updated the location of the libraries.
test_backtrace 0
gdb_test "p lib1_size" " = 8192"
gdb_test "p lib2_size" " = 8192"