]>
Commit | Line | Data |
---|---|---|
8acc9f48 | 1 | # Copyright (C) 2010-2013 Free Software Foundation, Inc. |
5e3b36f8 JK |
2 | |
3 | # This program is free software; you can redistribute it and/or modify | |
4 | # it under the terms of the GNU General Public License as published by | |
5 | # the Free Software Foundation; either version 3 of the License, or | |
6 | # (at your option) any later version. | |
7 | # | |
8 | # This program is distributed in the hope that it will be useful, | |
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | # GNU General Public License for more details. | |
12 | # | |
13 | # You should have received a copy of the GNU General Public License | |
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | ||
16 | # Return nul-terminated string read from section SECTION of EXEC. Return "" | |
17 | # if no such section or nul-terminated string was found. Function is useful | |
18 | # for sections ".interp" or ".gnu_debuglink". | |
19 | ||
20 | proc section_get {exec section} { | |
21 | global objdir | |
22 | global subdir | |
23 | set tmp "${objdir}/${subdir}/section_get.tmp" | |
24 | set objcopy_program [transform objcopy] | |
25 | ||
26 | set command "exec $objcopy_program -O binary --set-section-flags $section=A --change-section-address $section=0 -j $section $exec $tmp" | |
27 | verbose -log "command is $command" | |
28 | set result [catch $command output] | |
29 | verbose -log "result is $result" | |
30 | verbose -log "output is $output" | |
31 | if {$result == 1} { | |
32 | return "" | |
33 | } | |
34 | set fi [open $tmp] | |
35 | fconfigure $fi -translation binary | |
36 | set data [read $fi] | |
37 | close $fi | |
38 | file delete $tmp | |
39 | # .interp has size $len + 1 but .gnu_debuglink contains garbage after \000. | |
40 | set len [string first \000 $data] | |
41 | if {$len < 0} { | |
42 | verbose -log "section $section not found" | |
43 | return "" | |
44 | } | |
45 | set retval [string range $data 0 [expr $len - 1]] | |
46 | verbose -log "section $section is <$retval>" | |
47 | return $retval | |
48 | } | |
49 | ||
50 | # Resolve symlinks. | |
51 | ||
52 | proc symlink_resolve {file} { | |
53 | set loop 0 | |
54 | while {[file type $file] == "link"} { | |
55 | set target [file readlink $file] | |
56 | if {[file pathtype $target] == "relative"} { | |
57 | set src2 [file dirname $file]/$target | |
58 | } else { | |
59 | set src2 $target | |
60 | } | |
61 | verbose -log "Resolved symlink $file targetting $target as $src2" | |
62 | set file $src2 | |
63 | ||
64 | set loop [expr $loop + 1] | |
65 | if {$loop > 30} { | |
66 | fail "Looping symlink resolution for $file" | |
67 | return "" | |
68 | } | |
69 | } | |
70 | return $file | |
71 | } | |
72 | ||
73 | # Copy SRC to DEST, resolving any symlinks in SRC. Return nonzero iff | |
74 | # the copy was succesful. | |
75 | # | |
76 | # This function is guaranteed to never raise any exception, even when the copy | |
77 | # fails. | |
78 | ||
79 | proc file_copy {src dest} { | |
80 | set src [symlink_resolve $src] | |
81 | # Test name would contain unstable directory name for symlink-unresolved | |
82 | # $src. | |
83 | set test "copy [file tail $src] to [file tail $dest]" | |
84 | set command "file copy -force -- $src $dest" | |
85 | verbose -log "command is $command" | |
86 | if [catch $command] { | |
87 | fail $test | |
88 | return 0 | |
89 | } else { | |
90 | pass $test | |
91 | return 1 | |
92 | } | |
93 | } | |
94 | ||
95 | # Wrap function build_executable so that the resulting executable is fully | |
96 | # self-sufficient (without dependencies on system libraries). Parameter | |
97 | # INTERP may be used to specify a loader (ld.so) to be used that is | |
98 | # different from the default system one. Libraries on which the executable | |
99 | # depends are copied into directory DIR. Default DIR value to | |
100 | # `${objdir}/${subdir}/${EXECUTABLE}.d'. | |
101 | # | |
102 | # In case of success, return a string containing the arguments to be used | |
103 | # in order to perform a prelink of the executable obtained. Return the | |
104 | # empty string in case of failure. | |
105 | # | |
106 | # This can be useful when trying to prelink an executable which might | |
107 | # depend on system libraries. To properly prelink an executable, all | |
108 | # of its dynamically linked libraries must be prelinked as well. If | |
109 | # the executable depends on some system libraries, we may not have | |
110 | # sufficient write priviledges on these files to perform the prelink. | |
111 | # This is why we make a copy of these shared libraries, and link the | |
112 | # executable against these copies instead. | |
113 | # | |
114 | # Function recognizes only libraries listed by `ldd' after | |
115 | # its ` => ' separator. That means $INTERP and any libraries not being linked | |
116 | # with -Wl,-soname,NAME.so are not copied. | |
117 | ||
118 | proc build_executable_own_libs {testname executable sources options {interp ""} {dir ""}} { | |
119 | global objdir subdir | |
120 | ||
121 | if {[build_executable $testname $executable $sources $options] == -1} { | |
122 | return "" | |
123 | } | |
124 | set binfile ${objdir}/${subdir}/${executable} | |
125 | ||
126 | set command "ldd $binfile" | |
127 | set test "ldd $executable" | |
128 | set result [catch "exec $command" output] | |
129 | verbose -log "result of $command is $result" | |
130 | verbose -log "output of $command is $output" | |
131 | if {$result != 0 || $output == ""} { | |
132 | fail $test | |
133 | } else { | |
134 | pass $test | |
135 | } | |
136 | ||
137 | # gdb testsuite will put there also needless -lm. | |
138 | set test "$test output contains libs" | |
139 | set libs [regexp -all -inline -line {^.* => (/[^ ]+).*$} $output] | |
140 | if {[llength $libs] == 0} { | |
141 | fail $test | |
142 | } else { | |
143 | pass $test | |
144 | } | |
145 | ||
146 | if {$dir == ""} { | |
147 | set dir ${binfile}.d | |
148 | } | |
149 | file delete -force -- $dir | |
150 | file mkdir $dir | |
151 | ||
152 | if {$interp == ""} { | |
153 | set interp_system [section_get $binfile .interp] | |
154 | set interp ${dir}/[file tail $interp_system] | |
155 | file_copy $interp_system $interp | |
156 | } | |
157 | ||
158 | set dests {} | |
159 | foreach {trash abspath} $libs { | |
160 | set dest "$dir/[file tail $abspath]" | |
161 | file_copy $abspath $dest | |
162 | lappend dests $dest | |
163 | } | |
164 | ||
165 | # Do not lappend it so that "-rpath $dir" overrides any possible "-rpath"s | |
166 | # specified by the caller to be able to link it for ldd" above. | |
d8b34041 | 167 | set options [linsert $options 0 "ldflags=-Wl,--dynamic-linker,$interp,-rpath,$dir"] |
5e3b36f8 JK |
168 | |
169 | if {[build_executable $testname $executable $sources $options] == -1} { | |
170 | return "" | |
171 | } | |
172 | ||
173 | set prelink_args "--dynamic-linker=$interp --ld-library-path=$dir $binfile $interp [concat $dests]" | |
174 | return $prelink_args | |
175 | } | |
176 | ||
177 | # Unprelink ARG. Reported test name can be specified by NAME. Return non-zero | |
178 | # on success, zero on failure. | |
179 | ||
180 | proc prelink_no {arg {name {}}} { | |
181 | if {$name == ""} { | |
182 | set name [file tail $arg] | |
183 | } | |
184 | set test "unprelink $name" | |
185 | set command "exec /usr/sbin/prelink -uN $arg" | |
186 | verbose -log "command is $command" | |
187 | set result [catch $command output] | |
188 | verbose -log "result is $result" | |
189 | verbose -log "output is $output" | |
1a219cc7 JK |
190 | if {$result == 1 && [regexp {^(couldn't execute "/usr/sbin/prelink[^\r\n]*": no such file or directory\n?)*$} $output]} { |
191 | # Without prelink, at least verify that all the binaries do not | |
192 | # contain the ".gnu.prelink_undo" section (which would mean that they | |
193 | # have already been prelinked). | |
194 | set test "$test (missing /usr/sbin/prelink)" | |
195 | foreach bin [split $arg] { | |
196 | if [string match "-*" $bin] { | |
197 | # Skip prelink options. | |
198 | continue | |
199 | } | |
200 | set readelf_program [transform readelf] | |
201 | set command "exec $readelf_program -WS $bin" | |
202 | verbose -log "command is $command" | |
203 | set result [catch $command output] | |
204 | verbose -log "result is $result" | |
205 | verbose -log "output is $output" | |
206 | if {$result != 0 || [string match {* .gnu.prelink_undo *} $output]} { | |
207 | fail "$test ($bin is already prelinked)" | |
208 | return 0 | |
209 | } | |
210 | } | |
211 | pass $test | |
212 | return 1 | |
213 | } | |
5e3b36f8 JK |
214 | if {$result == 0 && $output == ""} { |
215 | verbose -log "$name has been now unprelinked" | |
216 | set command "exec /usr/sbin/prelink -uN $arg" | |
217 | verbose -log "command is $command" | |
218 | set result [catch $command output] | |
219 | verbose -log "result is $result" | |
220 | verbose -log "output is $output" | |
221 | } | |
222 | # Last line does miss the trailing \n. There can be multiple such messages | |
223 | # as ARG may list multiple files. | |
224 | if {$result == 1 && [regexp {^(/usr/sbin/prelink[^\r\n]*: [^ ]* does not have .gnu.prelink_undo section\n?)*$} $output]} { | |
225 | pass $test | |
226 | return 1 | |
227 | } else { | |
228 | fail $test | |
229 | return 0 | |
230 | } | |
231 | } | |
232 | ||
233 | # Prelink ARG. Reported test name can be specified by NAME. Return non-zero | |
234 | # on success, zero on failure. | |
235 | ||
236 | proc prelink_yes {arg {name ""}} { | |
237 | if {$name == ""} { | |
238 | set name [file tail $arg] | |
239 | } | |
240 | ||
241 | # Try to unprelink it first so that, if it has been already prelinked | |
242 | # before, we get a different address now, making the new result unaffected | |
243 | # by any previous prelinking. | |
1a219cc7 JK |
244 | if ![prelink_no $arg "$name pre-unprelink"] { |
245 | return 0 | |
246 | } | |
5e3b36f8 JK |
247 | |
248 | set test "prelink $name" | |
249 | ||
250 | # `--no-exec-shield' is for i386, where prelink in the exec-shield mode is | |
251 | # forced to push all the libraries tight together, in order to fit into | |
252 | # the first two memory areas (either the ASCII Shield area or at least | |
253 | # below the executable). If the prelink was performed in exec-shield | |
254 | # mode, prelink could have no choice on how to randomize the single new | |
255 | # unprelinked library address without wasting space in the first one/two | |
256 | # memory areas. In such case prelink could place $ARG repeatedly at the | |
257 | # same place and we could have false prelink results on | |
258 | # gdb.base/prelink.exp and others. To prevent this from happening, we use | |
259 | # the --no-exec-shield switch. This may have some consequences in terms | |
260 | # of security, but we do not care in our case. | |
261 | ||
262 | set command "exec /usr/sbin/prelink -qNR --no-exec-shield $arg" | |
263 | ||
264 | verbose -log "command is $command" | |
265 | set result [catch $command output] | |
266 | verbose -log "result is $result" | |
267 | verbose -log "output is $output" | |
1a219cc7 JK |
268 | if {$result == 1 && [regexp {^(couldn't execute "/usr/sbin/prelink[^\r\n]*": no such file or directory\n?)*$} $output]} { |
269 | set test "$test (missing /usr/sbin/prelink)" | |
270 | ||
271 | # We could not find prelink. We could check whether $args is already | |
272 | # prelinked but we don't, because: | |
273 | # - It is unlikely that someone uninstalls prelink after having | |
274 | # prelinked the system ld.so; | |
275 | # - We still cannot change its prelinked address. | |
276 | # Therefore, we just skip the test. | |
277 | ||
278 | xfail $test | |
279 | return 0 | |
280 | } | |
5e3b36f8 JK |
281 | if {$result == 0 && $output == ""} { |
282 | pass $test | |
283 | return 1 | |
284 | } elseif {$result == 1 \ | |
285 | && [string match -nocase "*: Not enough room to add .dynamic entry" $output]} { | |
286 | # Linker should have reserved some entries for prelink. | |
287 | xfail $test | |
288 | return 0 | |
289 | } else { | |
290 | fail $test | |
291 | return 0 | |
292 | } | |
293 | } |