aboutsummaryrefslogtreecommitdiff
blob: ce5c324d6d1462d0a22689633e6cf923a1c04f29 (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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# Copyright (C) 2003, 2005, 2007, 2008, 2009, 2010
# 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/>.
#

# Tests for shared object file relocation. If two shared objects have
# the same load address (actually, overlapping load spaces), one of
# them gets relocated at load-time. Check that gdb gets the right
# values for the debugging and minimal symbols.

if {[skip_shlib_tests]} {
    return 0
}

if $tracelevel then {
    strace $tracelevel
}

#
# This file uses shreloc.c, shreloc1.c and shreloc2.c
#


set workdir ${objdir}/${subdir}
set testfile "shreloc"
set libfile1 "shreloc1"
set libfile2 "shreloc2"
set srcfile $srcdir/$subdir/$testfile.c
set lib1src $srcdir/$subdir/$libfile1.c
set lib2src $srcdir/$subdir/$libfile2.c
set binfile $objdir/$subdir/$testfile
set lib1_sl $objdir/$subdir/$libfile1.sl
set lib2_sl $objdir/$subdir/$libfile2.sl

if [get_compiler_info ${binfile}] {
    return -1
}

set lib_opts "debug"
set exec_opts [list debug shlib=$lib1_sl shlib=$lib2_sl]

if {([istarget "*pc-cygwin"] || [istarget "*pc-mingw32"]) } {
    lappend lib_opts "ldflags=-Wl,--image-base,0x04000000"
}

if [test_compiler_info "xlc-*"] {

    # IBM's xlc compiler does not add static variables to the ELF symbol 
    # table by default.  We need this option to make the variables show 
    # up in "maint print msymbols". 

    lappend lib_opts "additional_flags=-qstatsym"

}

if { [gdb_compile_shlib $lib1src $lib1_sl $lib_opts] != ""} {
    untested "Could not build $lib1_sl."
    return -1
} elseif { [gdb_compile_shlib $lib2src $lib2_sl $lib_opts] != ""} {
    untested "Could not build $lib1_s2."
    return -1
} elseif { [gdb_compile $srcfile $binfile executable $exec_opts] != ""} {
    untested "Could not build $binfile."
    return -1
}

# Start with a fresh gdb.

gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${workdir}/shreloc
gdb_load_shlibs $lib1_sl $lib2_sl

# Load up the shared objects
if ![runto_main] then {
    fail "Can't run to main"
    return 0
}

proc get_var_address { var } {
    global gdb_prompt hex

    # Match output like:
    # $1 = (int *) 0x0
    # $5 = (int (*)()) 0
    # $6 = (int (*)()) 0x24 <function_bar>

    gdb_test_multiple "print &${var}" "get address of ${var}" {
	-re "\\\$\[0-9\]+ = \\(.*\\) (0|$hex)( <${var}>)?\[\r\n\]+${gdb_prompt} $"
	{
	    pass "get address of ${var}"
	    if { $expect_out(1,string) == "0" } {
		return "0x0"
	    } else {
		return $expect_out(1,string)
	    }
	}
    }
    return ""
}

#
# Check debugging symbol relocations
#

# Check extern function for relocation
set fn_1_addr [get_var_address fn_1]
set fn_2_addr [get_var_address fn_2]

if { "${fn_1_addr}" == "${fn_2_addr}" } {
  fail "relocated extern functions have different addresses"
} else {
  pass "relocated extern functions have different addresses"
}

# Check extern var for relocation
set extern_var_1_addr [get_var_address extern_var_1]
set extern_var_2_addr [get_var_address extern_var_2]

if { "${extern_var_1_addr}" == "${extern_var_2_addr}" } {
  fail "relocated extern variables have different addresses"
} else {
  pass "relocated extern variables have different addresses"
}

# Check static var for relocation
set static_var_1_addr [get_var_address static_var_1]
set static_var_2_addr [get_var_address static_var_2]

if { "${static_var_1_addr}" == "${static_var_2_addr}" } {
  fail "relocated static variables have different addresses"
} else {
  pass "relocated static variables have different addresses"
}

#
# Check minimal symbol relocations
#

proc send_gdb_discard { command } {
    # Send a command to gdb and discard output up to the next prompt

    global gdb_prompt

    # Discard output
    gdb_test_multiple "${command}" "${command}" {
	-re ".*\[\r\n]+${gdb_prompt} $" {
	    return 1
	}
	timeout {
	    fail "{$command} (timeout)"
	    return 0
	}
    }
}

proc get_msym_addrs { var msymfile } {
    # Extract the list of values for symbols matching var in the
    # minimal symbol output file

    global gdb_prompt hex
    set result ""

    send_gdb "shell grep -E \" ${var}(\[ \t\]+.*)?\$\" ${msymfile}\n"

    while 1 {
	gdb_expect {
	    -re "\[\[\]\[ 0-9\]+\] . (${hex}) ${var}(\[ \t\]+\[^\r\n\]*)?\[\r\n\]+" {
		set result [concat $result $expect_out(1,string)]
	    }

	    -re "$gdb_prompt $" {
		pass "get_msym_addrs ${var}"
		return "${result}"
	    }

	    -re "\[^\r\n\]*\[\r\n\]+" {
		# Skip
	    }

	    timeout {
		fail "get_msym_addrs ${var} (timeout)"
		return -1
	    }
	}
    }
}

proc check_same {var msymfile} {
    # Check that the minimal symbol values matching var are the same

    set len [llength [lsort -unique [get_msym_addrs "${var}" "${msymfile}"]]]

    if { $len == 1 } {
	return 1
    } else {
	return 0
    }
}

proc check_different {var msymfile} {
    # Check that the minimal symbol values matching var are different

    set addr_list [lsort [get_msym_addrs "${var}" "${msymfile}"]]
    set prev ""

    if { [llength ${addr_list}] < 2 } {
	return 0
    }

    foreach addr ${addr_list} {
	if { ${prev} == ${addr} } {
	  return 0
	}
	set prev ${addr}
    }

    return 1
}

set msymfile "${workdir}/shreloc.txt"

if [send_gdb_discard "maint print msymbols ${msymfile}"] {
    if {[check_different "static_var_\[12\]" "${msymfile}"]} {
	pass "(msymbol) relocated static vars have different addresses"
    } else {
	fail "(msymbol) relocated static vars have different addresses"
    }

    if {[check_different "extern_var_\[12\]" "${msymfile}"]} {
	pass "(msymbol) relocated extern vars have different addresses"
    } else {
	fail "(msymbol) relocated extern vars have different addresses"
    }

    if {[check_different "fn_\[12\]" "${msymfile}"]} {
	pass "(msymbol) relocated functions have different addresses"
    } else {
	fail "(msymbol) relocated functions have different addresses"
    }
}

if {([istarget "*pc-cygwin"] || [istarget "*pc-mingw32"]) } {
    #
    # We know the names of some absolute symbols included in the
    # portable-executable (DLL) format. Check that they didn't get
    # relocated.
    #
    # A better approach would be include absolute symbols via the assembler.
    #
    if {[check_same "_minor_os_version__" "${msymfile}"]} {
	pass "Absolute symbols not relocated"
    } else {
	fail "Absolute symbols not relocated"
    }
}