summaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.base/dlmopen.exp
blob: 31f74008f10cc371863cd6355861a9800aed44f1 (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
# This testcase is part of GDB, the GNU debugger.
#
# Copyright 2021-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 shared libraries loaded into different namespaces with dlmopen().
#
# We test that GDB shows the correct number of instances of the libraries
# the test loaded while unloading them one-by-one.

if { [skip_dlmopen_tests] } {
    unsupported "target does not support dlmopen debugging"
    return -1
}

standard_testfile

set basename_lib dlmopen-lib
set srcfile_lib $srcdir/$subdir/$basename_lib.c
set binfile_lib1 [standard_output_file $basename_lib.1.so]
set binfile_lib2 [standard_output_file $basename_lib.2.so]
set srcfile_lib_dep $srcdir/$subdir/$basename_lib-dep.c
set binfile_lib_dep [standard_output_file $basename_lib-dep.so]

if { [gdb_compile_shlib $srcfile_lib_dep $binfile_lib_dep {debug}] != "" } {
    untested "failed to prepare shlib"
    return -1
}

if { [gdb_compile_shlib $srcfile_lib $binfile_lib1 \
	  [list debug shlib_load libs=$binfile_lib_dep]] != "" } {
    untested "failed to prepare shlib"
    return -1
}

if { [gdb_compile_shlib $srcfile_lib $binfile_lib2 \
	  [list debug shlib_load libs=$binfile_lib_dep]] != "" } {
    untested "failed to prepare shlib"
    return -1
}

if { [prepare_for_testing "failed to prepare" $testfile $srcfile \
	  [list additional_flags=-DDSO1_NAME=\"$binfile_lib1\" \
	       additional_flags=-DDSO2_NAME=\"$binfile_lib2\" \
	       shlib_load debug]] } {
    return -1
}

if { ![runto_main] } {
    return -1
}

# Check that 'info shared' show NUM occurrences of DSO.
proc check_dso_count { dso num } {
    global gdb_prompt hex

    set count 0
    gdb_test_multiple "info shared" "info shared" {
	-re "$hex  $hex  Yes \[^\r\n\]*$dso\r\n" {
	    # use longer form so debug remote does not interfere
	    set count [expr $count + 1]
	    exp_continue
	}
	-re "$gdb_prompt " {
	    verbose -log "library: $dso, expected: $num, found: $count"
	    gdb_assert {$count == $num} "$gdb_test_name"
	}
    }
}

# The DSO part of the test.  We run it once per DSO call.
proc test_dlmopen_one { ndso1 ndso2 exp_glob } {
    global srcfile_lib srcfile_lib basename_lib bp_inc

    # Try to reach the breakpoint in the dynamically loaded library.
    gdb_continue_to_breakpoint "cont to bp.inc" \
	".*$srcfile_lib:$bp_inc\r\n.*"

    # We opened all DSOs initially and close them one by one.
    with_test_prefix "dso 1" { check_dso_count $basename_lib.1.so $ndso1 }
    with_test_prefix "dso 2" { check_dso_count $basename_lib.2.so $ndso2 }

    # This might help debugging.
    gdb_test "info breakpoints" ".*"
    gdb_test "print \$pc" ".*"

    # We expect different instances of GDB_DLMOPEN_GLOB per DSO.
    gdb_test "print amount" "= $exp_glob"
    gdb_test "print gdb_dlmopen_glob" "= $exp_glob"

    # Modify that DSO's instance, which should leave the others intact.
    gdb_test "print &gdb_dlmopen_glob" "= .*"
    gdb_test "print gdb_dlmopen_glob = -1" "= -1"
}

# The actual test.  We run it twice.
proc test_dlmopen {} {
    global srcfile basename_lib bp_main

    # Note that when loading dlmopen-lib.1.so and dlmopen-lib.2.so into
    # the same namespace, dlmopen-lib-dep.so is loaded only once, so in
    # this case, the changes to gdb_dlmopen_glob inside test_dlmopen_one
    # will actually be visible.
    #
    # Hence, we supply the expected value of this variable as argument to
    # test_dlmopen_one.
    with_test_prefix "dlmopen 1" { test_dlmopen_one 3 1 1 }
    with_test_prefix "dlmopen 2" { test_dlmopen_one 2 1 1 }
    with_test_prefix "dlmopen 3" { test_dlmopen_one 1 1 1 }
    with_test_prefix "dlmopen 4" { test_dlmopen_one 0 1 -1 }

    with_test_prefix "main" {
	# Try to reach the breakpoint in the dynamically loaded library.
	gdb_continue_to_breakpoint "cont to bp.main" \
	    ".*$srcfile:$bp_main\r\n.*"

	# The library should not be listed.
	with_test_prefix "dso 1" { check_dso_count $basename_lib.1.so 0 }
	with_test_prefix "dso 2" { check_dso_count $basename_lib.2.so 0 }
    }
}

# Remove the pause.  We only need it for the attach test.
gdb_test "print wait_for_gdb = 0" "\\\$1 = 0"

# Break in the to-be-loaded library and at the end of main.
set bp_inc [gdb_get_line_number "bp.inc" $srcfile_lib]
set bp_main [gdb_get_line_number "bp.main" $srcfile]

delete_breakpoints
gdb_breakpoint $srcfile_lib:$bp_inc allow-pending
gdb_breakpoint $srcfile:$bp_main

test_dlmopen

# Try the same again when attaching after dlmopen().
if { ![can_spawn_for_attach] } {
    unsupported "target does not support attach"
    return -1
}

clean_restart $binfile

# Start the test program.
set test_spawn_id [spawn_wait_for_attach $binfile]
set testpid [spawn_id_get_pid $test_spawn_id]

# Attach.
if { ![gdb_attach $testpid] } {
    return
}

with_test_prefix "attach" {
    # Remove the pause.  We no longer need it.
    gdb_test "print wait_for_gdb = 0" "\\\$1 = 0"

    # Set the same breakpoints again.  This time, however, we do not allow the
    # breakpoint to be pending since the library has already been loaded.
    gdb_breakpoint $srcfile_lib:$bp_inc
    gdb_breakpoint $srcfile:$bp_main

    test_dlmopen
}