File: dlmopen.exp

package info (click to toggle)
gdb-doc 16.3-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid, trixie
  • size: 244,264 kB
  • sloc: ansic: 2,134,731; asm: 375,582; exp: 206,875; cpp: 73,639; makefile: 70,232; sh: 26,038; python: 13,697; yacc: 11,341; ada: 7,358; xml: 6,098; perl: 5,077; pascal: 3,389; tcl: 2,986; f90: 2,764; lisp: 1,984; cs: 879; lex: 738; sed: 228; awk: 181; objc: 137; fortran: 57
file content (198 lines) | stat: -rw-r--r-- 6,945 bytes parent folder | download | duplicates (6)
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
189
190
191
192
193
194
195
196
197
198
# This testcase is part of GDB, the GNU debugger.
#
# Copyright 2021-2024 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.

require allow_dlmopen_tests

# Don't use 'dlmopen.c' as the source file name, glibc also has a file
# with that name.  Within our tests, we set the source directory search
# path order to:
#
#    (1) the test source directory,
#    (2) the compilation directory, and then
#    (3) the current working directory.
#
# Because (1) is first when we try to place a breakpoint on
# 'dlmopen.c', if the test source file has that name, then GDB will
# find both the test source file, and the source file from glibc.
#
# We could work around this by making (2) first in the source
# directory list, but that only works when the glibc source is
# installed.  If it isn't then GDB will try the compilation directory,
# fail to find the source, then try the test source directory, get a
# hit, and so still confuse the two files.
#
# You might think the problem can be solved by specifying the absolute
# path to the source file.  This doesn't work because the glibc file
# has its filename recorded as just "dlmopen.c", as such GDB has to
# figure out an absolute path to the file (if possible).  The absolute
# path is figured out based on where GDB can find a matching file in
# the source directory list, and because of the confusion above, GDB
# will usually think the test 'dlmopen.c' and the glibc 'dlmopen.c'
# are actually the same file.
#
# The conclusion is that it is just easier to rename the test source
# file to avoid conflicts with glibc.

standard_testfile -main.c -lib.c -lib-dep.c

set basename_lib dlmopen-lib
set srcfile_lib $srcfile2
set binfile_lib1 [standard_output_file $basename_lib.1.so]
set binfile_lib2 [standard_output_file $basename_lib.2.so]
set srcfile_lib_dep $srcfile3
set binfile_lib_dep [standard_output_file $basename_lib-dep.so]

if { [build_executable "build shlib dep" $binfile_lib_dep $srcfile_lib_dep \
	  {debug shlib}] == -1 } {
    return
}

if { [build_executable "build shlib" $binfile_lib1 $srcfile_lib \
	  [list debug shlib_load shlib libs=$binfile_lib_dep]] == -1 } {
    return
}

if { [build_executable "build shlib" $binfile_lib2 $srcfile_lib \
	  [list debug shlib_load shlib libs=$binfile_lib_dep]] == -1 } {
    return
}

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().
require can_spawn_for_attach

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
}