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
|
# Test that the linker reports undefined symbol errors correctly.
# By Ian Lance Taylor, Cygnus Support
#
# Copyright (C) 1995-2021 Free Software Foundation, Inc.
#
# This file is part of the GNU Binutils.
#
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
# MA 02110-1301, USA.
set testund "undefined"
set testfn "undefined function"
set testline "undefined line"
if { ![check_compiler_available] } {
verbose "Could not find C compiler!" 1
untested $testund
untested $testfn
untested $testline
} elseif { ![ld_compile "$CC -g $NOLTO_CFLAGS" $srcdir/$subdir/undefined.c tmpdir/undefined.o] } {
verbose "Unable to compile test file!" 1
unresolved $testund
unresolved $testfn
unresolved $testline
} else {
remote_file host delete "tmpdir/undefined"
set flags [big_or_little_endian]
# Using -e start prevents the SunOS linker from trying to build a
# shared library. But don't use an entry point in BPF targets.
switch -glob $target_triplet {
bpf-*-* { set entry "" }
* { set entry "-e start" }
}
send_log "$ld $entry $flags -o tmpdir/undefined tmpdir/undefined.o\n"
set exec_output [run_host_cmd "$ld" "$entry $flags -o tmpdir/undefined tmpdir/undefined.o"]
send_log "$exec_output\n"
verbose "$exec_output"
proc checkund { string testname } {
global exec_output
if [string match "*$string*" $exec_output] {
pass $testname
} else {
fail $testname
}
}
set mu "undefined reference to `*this_function_is_not_defined'"
checkund $mu $testund
# ARM PE defaults to using stabs debugging, which we can't handle
# for a COFF file.
#setup_xfail "arm*-*-pe*"
# For Xtensa on GNU Linux systems (or any other system where PIC
# code is always used), the address of the undefined function is
# in a literal pool outside the function, so that both the
# "undefined function" and "undefined line" tests fail.
setup_xfail xtensa*-*-linux*
set mf "tmpdir/undefined.o* in function `function':"
checkund $mf $testfn
if ![is_elf_format] {
# COFF SH gets this test wrong--it reports line 10, because
# although the jump is at line 9, the function address, and
# the reloc, is stored at the end of the function.
setup_xfail "sh-*-*"
# ARM PE defaults to using stabs debugging, which we can't
# handle for a COFF file.
#setup_xfail "arm*-*-pe*"
}
set ml "undefined.c:9: undefined reference to `*this_function_is_not_defined'"
# With targets that use elf/dwarf2, such as the arm-elf toolchain,
# the code in bfd/elf.c:_bfd_elf_find_nearest_line() is called in
# order to locate the file name/line number where the undefined
# reference occurs. Unfortunately this tries to use the dwarf2
# debug information held in the .debug_info section. This section
# contains a series of comp_unit structures, each of which has a
# low/high address range representing the span of memory locations
# covered by that structure. The structures also index into other
# structures held in the .debug_line section and together they can
# translate memory locations back into file/function/line number
# addresses in the source code. Since the information about the
# memory region covered by a comp_unit is only determined at link
# time, the low/high addresses in the .debug_info section and the
# line addresses in the .debug_line section are computed by
# generating relocs against known symbols in the object code.
#
# When the undefined reference is detected, the relocs in the
# dwarf2 debug sections have not yet been resolved, so the
# low/high addresses and the line number address are all set at
# zero. Thus when _bfd_elf_find_nearest_line() calls
# _bfd_dwarf2_find_nearest_line() no comp_unit can be found which
# actually covers the address where the reference occurred, and so
# _bfd_elf_find_nearest_line() fails.
#
# The upshot of all of this, is that the error message reported by
# the linker, instead of having a source file name & line number
# as in:
#
# undefined.c:9: undefined reference to `this_function_is_not_defined'
#
# has an object file & section address instead:
#
# undefined.0(.text+0xc): undefined reference to `this_function_is_not_defined'
#
# hence the xfails below.
setup_xfail mcore-*-elf
setup_xfail mep-*-*
setup_xfail mips-sgi-irix6*
# Fails for the MSP430 because it uses SYM_DIFF relocs but it does
# not provide a special_function for handling them. If
# optimization is enabled then this test passes because
# function()'s prologue is eliminated.
setup_xfail "msp430-*-*"
# The undefined test fails on 31 bit s/390 because the address of
# the function `this_function_is_not_defined' is stored in the
# literal pool of the function. Therefore the line number in the
# error message is 8 instead of 9. On 64 bit s/390 this works
# because of the new brasl instruction that doesn't need a literal
# pool entry.
setup_xfail s390-*-*
# See comments above for Xtensa.
setup_xfail xtensa*-*-linux*
setup_xfail hppa*64*-*-*
# eBPF doesn't support dwarf yet.
setup_xfail bpf-*-*
checkund $ml $testline
}
# Undefined symbols should become dynamic when linking a shared lib.
set testname "undefined symbols in shared lib"
set asflags ""
switch -glob $target_triplet {
aarch64* -
arm* -
powerpc64* { set asflags "--defsym BL=1" }
powerpc* { set asflags "--defsym BLPLT=1" }
hppa* { set asflags "--defsym HPPA=1" }
i\[3-7\]86* -
x86_64* { set asflags "--defsym CALLPLT=1" }
}
if { ![is_elf_format] || ![check_shared_lib_support]} then {
unsupported $testname
} elseif {![ld_assemble $as "$asflags $srcdir/$subdir/fundef.s" \
tmpdir/fundef.o]} then {
fail $testname
} elseif {![ld_link $ld tmpdir/fundef.so \
"-shared --allow-shlib-undefined tmpdir/fundef.o"]} then {
setup_xfail tic6x-*-*
fail $testname
} else {
if {![is_remote host] && [which $nm] == 0} then {
unresolved "$testname (dyn sym)"
} else {
set exec_output [run_host_cmd "$nm" "-D tmpdir/fundef.so"]
set exec_output [prune_warnings $exec_output]
if { ($asflags == ""
|| ([regexp ".* undef_fun_typed.*" $exec_output]
&& [regexp ".* undef_fun_notype.*" $exec_output]))
&& [regexp ".* undef_data.*" $exec_output]
&& [regexp ".* undef_pfun.*" $exec_output]
&& [regexp ".* undef_notype.*" $exec_output]} then {
pass "$testname (dyn sym)"
} else {
fail "$testname (dyn sym)"
}
}
global READELF
if {![is_remote host] && [which $READELF] == 0} then {
unresolved "$testname (dyn reloc)"
} else {
set exec_output [run_host_cmd "$READELF" "-r tmpdir/fundef.so"]
set exec_output [prune_warnings $exec_output]
# We ought to get two .rel{a}.plt and three .rel{a}.dyn relocs,
# except for MIPS targets whose psABI mandates an extra
# R_MIPS_NONE relocation, also used to pad n64 relocation
# triplets, and S+core targets using an extra R_SCORE_NONE
# relocation, so adjust for that.
switch -glob $target_triplet {
"mips64*-*-openbsd*" {
set none_count 6
set reloc_count 4
}
"mips*" -
"score*" {
set none_count 1
set reloc_count 4
}
"*" {
set none_count 0
set reloc_count 3
}
}
if { ($asflags == "" || [regexp ".* contains 2 .*" $exec_output])
&& [regexp ".* contains $reloc_count .*" $exec_output]
&& [regexp -all "_NONE" $exec_output] == $none_count } then {
pass "$testname (dyn reloc)"
} else {
fail "$testname (dyn reloc)"
}
}
}
|