]> sourceware.org Git - systemtap.git/blame - testsuite/lib/systemtap.exp
lib/systemtap.exp: rename hw_breakpoint_p to hwbkpt_probes_p
[systemtap.git] / testsuite / lib / systemtap.exp
CommitLineData
814bc89d 1load_lib site.exp
744884cd 2load_lib "compile_flags.exp"
814bc89d
FCE
3
4proc installtest_p {} {
5 global TOOL_OPTIONS
23361495 6 if {[info exists TOOL_OPTIONS] && [string match "*install*" $TOOL_OPTIONS]} {
814bc89d
FCE
7 return 1
8 } else { return 0 }
9}
10
23361495 11
c3e70cc8
JS
12proc grep_kallsyms { pattern } {
13 if {! [catch {exec grep -q "$pattern" "/proc/kallsyms"} dummy]} {
75ebbc0d
FCE
14 return 1
15 }
16 return 0
17}
18
19
c3e70cc8
JS
20# Test for kernel built-in utrace (CONFIG_UTRACE).
21# Only original rhel5/6-era utrace need apply.
22proc utrace_orig_p {} {
23 # We want utrace_attach (rhel5) or utrace_attach_task (rhel6), but don't
24 # get confused by the private module version of any active stap module.
25 return [grep_kallsyms "T utrace_attach"]
26}
55352180 27
55352180 28
c3e70cc8
JS
29# Test for tracepoint-based utrace, or rather the in-kernel
30# facilities which enable our emulation of utrace.
31proc utrace_emu_p {} {
32 # Check for the set of 5 tracepoints we need and task_work_add()
33 # (see runtime/autoconf-utrace-via-tracepoints.c for details).
34 return [expr [grep_kallsyms task_work_add] \
35 && [grep_kallsyms tracepoint_sched_process_fork] \
36 && [grep_kallsyms tracepoint_sched_process_exec] \
37 && [grep_kallsyms tracepoint_sched_process_exit] \
38 && [grep_kallsyms tracepoint_sys_enter] \
39 && [grep_kallsyms tracepoint_sys_exit] \
40 ]
83ff01c2 41}
f249edcd
JS
42
43
c3e70cc8
JS
44# Test for utrace - any flavor will do...
45proc utrace_p {} {
46 return [expr [utrace_orig_p] || [utrace_emu_p] ]
47}
48
49
50proc classic_uprobes_p {} {
7d26ee02
JS
51 # If this is a utrace kernel, then we can use our version of uprobes.
52 # No need to build it now, stap will handle that itself.
55352180 53 #
c3e70cc8
JS
54 # Although ia64 has classical utrace, uprobes hasn't been
55 # ported there (PR7081).
56 return [expr [utrace_orig_p] && ! [istarget ia64-*-*] ]
57}
fdb3f242 58
c3e70cc8
JS
59proc inode_uprobes_p {} {
60 # inode-uprobes (or unlikely compiled-in classical uprobes?)
fdb3f242
DS
61 #
62 # Note we're looking for " uprobe_register" to avoid finding
63 # 'kallsyms_uprobe_register' from a loaded systemtap module.
53ce8435
JL
64 return [expr ([grep_kallsyms register_uprobe] \
65 || [grep_kallsyms " uprobe_register"]) \
66 && ! [classic_uprobes_p] \
c3e70cc8 67 ]
f249edcd 68}
dd466726
DS
69
70
c3e70cc8
JS
71proc uprobes_p {} {
72 return [expr [classic_uprobes_p] || [inode_uprobes_p] ]
73}
dd466726 74
c3e70cc8
JS
75
76proc classic_uretprobes_p {} {
77 # Classic uprobes always has uretprobes
78 return [classic_uprobes_p]
dd466726 79}
83ff01c2 80
c3e70cc8
JS
81proc inode_uretprobes_p {} {
82 # inode-uprobes, now with return probes! Looking for any mention of
83 # uretprobe, notably arch_uretprobe_hijack_return_addr
84 return [expr [inode_uprobes_p] && [grep_kallsyms uretprobe] ]
85}
83ff01c2 86
9c41fd2c 87proc uretprobes_p {} {
c3e70cc8 88 return [expr [classic_uretprobes_p] || [inode_uretprobes_p] ]
9c41fd2c
FCE
89}
90
1cd0bda2
DS
91proc plt_probes_p {} {
92 # .plt probes need uprobes and a supported arch (x86 and arm)
93 return [expr [uprobes_p] \
94 && [regexp "^(x86_64|i.86|arm.*)$" $::tcl_platform(machine)] ]
95}
9c41fd2c 96
20810599
DS
97proc perf_probes_p {} {
98 # perf probes need and exported perf_event_create_kernel_counter
99 return [grep_kallsyms perf_event_create_kernel_counter]
100}
101
c1dfb8be
JL
102proc hwbkpt_probes_p {} {
103 global have_hw_breakpoint_p
104 return $have_hw_breakpoint_p
105}
106
8c94efa7 107proc dyninst_p {} {
cd3a2693
FCE
108 global systemtap_dyninst_p
109 return $systemtap_dyninst_p
110}
8c94efa7 111
cd3a2693
FCE
112proc nss_p {} {
113 global systemtap_nss_p
114 return $systemtap_nss_p
8c94efa7
DS
115}
116
ca49ae2c
DS
117proc java_p {} {
118 global systemtap_java_p
119 return $systemtap_java_p
120}
121
8c94efa7
DS
122proc get_runtime_list {} {
123 # Always return the default runtime.
124 set runtime_list [list ""]
125
126 if {[dyninst_p]} {
127 lappend runtime_list "dyninst"
128 }
129 return $runtime_list
130}
131
132
814bc89d
FCE
133proc print_systemtap_version {} {
134 set version [exec /bin/uname -r]
135 set location "/boot/vmlinux-$version"
136 if {! [file exists $location]} {
137 # try the debuginfo location
138 set location "/usr/lib/debug/lib/modules/$version/vmlinux"
139 if {! [file exists $location]} { set location "" }
140 }
141
142 print "kernel location: $location"
143 print "kernel version: $version"
144
145 set location [exec /usr/bin/which stap]
146 regexp {version [^)]*} [exec stap -V 2>@ stdout] version
147
148 print "systemtap location: $location"
149 print "systemtap version: $version"
47561106
MW
150
151 set location [exec /usr/bin/which gcc]
152 set version [exec gcc --version | head -1]
153
154 print "gcc location: $location"
155 print "gcc version: $version"
814bc89d
FCE
156}
157
158
159proc setup_systemtap_environment {} {
ca49ae2c
DS
160 global srcdir env server_pid logfile systemtap_dyninst_p
161 global systemtap_nss_p systemtap_java_p
0939a9fe 162 global have_hw_breakpoint_p
0b872dd0 163 global kill_needs_doubledash
814bc89d
FCE
164
165 # need an absolute SRCDIR for the top-level src/ tree
5ba96b90 166 # XXX: or, we could change nearby uses of ${SRCDIR}/testsuite to ${SRCDIR}
99e1fb7a 167 set env(SRCDIR) [fullpath $srcdir/..]
814bc89d 168
b8f96d36
JL
169 # pretend to be a dumb terminal so that coloring is always turned off
170 # otherwise, we will have problems with expect
171 set env(TERM) dumb
172
0fbf54d6
MW
173 # Use a local systemtap directory and cache. Add user name so
174 # make check and sudo make check don't clobber each other.
574cf27a 175 set env(SYSTEMTAP_DIR) [pwd]/.systemtap-[exec whoami]
75bde6fe 176 exec mkdir -p $env(SYSTEMTAP_DIR)
5ba96b90 177
aae091fc
DB
178 # Start with fresh server certificates
179 exec rm -fr $env(SYSTEMTAP_DIR)/ssl
180
f1d4f431
FCE
181 # Remove the rc file
182 exec rm -f $env(SYSTEMTAP_DIR)/rc
183
184 # All hail the prophet lockdep
185 set chan [open $env(SYSTEMTAP_DIR)/rc w]
38f1dea2 186 puts $chan "--rlimit-cpu=300"
f1d4f431
FCE
187 close $chan
188
aae091fc 189 # Erase the old server log file.
574cf27a 190 set logfile "[pwd]/server.log"
aae091fc
DB
191 if {[file exists $logfile]} then {
192 exec rm -f $logfile;
d5658775 193 }
aae091fc
DB
194 # Create a new one and make sure it's world writable.
195 exec touch $logfile
196 exec chmod 666 $logfile
197
7288f08e
FCE
198 # Zap any previous uprobes, if any
199 catch { exec /sbin/rmmod uprobes }
200
8501d45c 201 # No compile-server started yet.
7d54db1a 202 set server_pid 0
d5658775 203
2e230f8a
DS
204 # If the environment variable ARCH exists, this can throw off our
205 # custom module building (when set to the wrong value). To be
206 # safe, remove it.
207 if [info exists env(ARCH)] {
208 verbose -log "clearing env ARCH (was $env(ARCH))"
209 unset env(ARCH)
210 }
211
5ba96b90
FCE
212 # PATH, SYSTEMTAP_TAPSET, SYSTEMTAP_RUNTIME, LD_LIBRARY_PATH are already set.
213 foreach var {PATH STAP SRCDIR SYSTEMTAP_TAPSET SYSTEMTAP_RUNTIME SYSTEMTAP_DIR LD_LIBRARY_PATH} {
214 if [info exists env($var)] {
215 verbose -log "env $var = $env($var)"
216 }
217 }
e26df1cb 218
752fd1e5 219 # Remember if this very version of systemtap compiled with dyninst support
8c94efa7 220 if {! [catch {exec sh -c "stap -V 2>&1 | grep -q DYNINST"} dummy]} {
cd3a2693
FCE
221 set systemtap_dyninst_p 1
222 } else {
223 set systemtap_dyninst_p 0
224 }
225
752fd1e5 226 # Remember if this selfsame version of systemtap compiled with nss support
cd3a2693
FCE
227 if {! [catch {exec sh -c "stap -V 2>&1 | grep -q NSS"} dummy]} {
228 set systemtap_nss_p 1
229 } else {
230 set systemtap_nss_p 0
8c94efa7 231 }
cd3a2693 232
ca49ae2c
DS
233 # Remember if this selfsame version of systemtap compiled with java support
234 if {! [catch {exec sh -c "stap -V 2>&1 | grep -q JAVA"} dummy]} {
235 set systemtap_java_p 1
236 } else {
237 set systemtap_java_p 0
238 }
0b872dd0 239
0939a9fe
JL
240 # Remember if this selfsame version of systemtap supports HW breakpoints
241 if {! [catch {exec stap -l {kernel.data(0x123).rw}}]} {
242 set have_hw_breakpoint_p 1
243 } else {
244 set have_hw_breakpoint_p 0
245 }
246
0b872dd0
JL
247 # There are some kill executables that had issues with -SIG -PID, thinking
248 # that the -PID was an option (procps-ng v3.3.2 and v3.3.3) and thus require
249 # a -- before -PID. So check for those, otherwise, just assume that no -- is
250 # needed.
251 if {![catch {exec kill --version 2>@1} killver]} {
252 if {[string match "*procps-ng 3.3.\[23\]" $killver]} {
253 set kill_needs_doubledash 1
254 } else {
255 # any other procps versions support the standard convention
256 # and anything not procps (e.g. util-linux) supports both
257 set kill_needs_doubledash 0
258 }
259 } else {
260 # kill doesn't support --version (e.g. busybox), just assume standard
261 # convention
262 set kill_needs_doubledash 0
263 }
264
e26df1cb 265 return 1
814bc89d
FCE
266}
267
72629a44
DB
268# Set up the environment so that tests will be performed using the systemtap
269# client and server.
fc3d2b46 270proc setup_server { args } {
0bdc958c 271 global srcdir env installed_stap logfile use_server server_spec avahi_ok_p
72629a44 272
250fb71a 273 # Start the server
fc3d2b46 274 if {! [start_server $args]} then {
250fb71a
DB
275 return 0
276 }
277
51c1bb7a 278 # Make sure that stap can find the server.
7f4595d7 279 exec sleep 1
51c1bb7a 280 set use_server --use-server
2be2e486
DB
281 set res [catch { exec stap --list-servers=online,trusted,compatible >& stap-list-servers.out } looksee]
282 verbose -log "stap --list-servers returned: res==$res"
283 verbose -log $looksee[exec cat stap-list-servers.out]
0bdc958c 284 set listRes [catch { exec grep "^ host" stap-list-servers.out } looksee]
a7dbd06e 285 verbose -log "grep for servers returned: res==$res\n$looksee"
2be2e486 286
0bdc958c
DB
287 # Try to discover the port the server is listening on from the server log.
288 # We're matching a line of the form:
289 # "Thu Jul 25 11:58:11 2013: Using network address <addr>:37804"
290 set res [catch { exec /bin/cat $logfile | awk "/Using network address/ {print \$9}" } server_address]
291 send_log "server_address=='$server_address'\n"
51c1bb7a 292 if {$res != 0} then {
0bdc958c
DB
293 verbose -log "Unable to discover the address used by the systemtap server"
294 shutdown_server
295 return 0
296 }
297 set res [regsub ".*:(\[0-9\]\[0-9\]*)\$" $server_address {\1} server_port]
298 send_log "server_port=='$server_port'\n"
299 if {$res != 1} then {
300 verbose -log "Unable to discover the port used by the systemtap server"
301 shutdown_server
302 return 0
303 }
304 set server_spec [info hostname]:$server_port
305 send_log "server_spec=='$server_spec'\n"
306
307 set avahi_ok_p 1
308 if {$listRes != 0} then {
2be2e486 309 verbose -log "Unable to automatically find the systemtap server -- check firewall settings for mDNS"
2d69ca83 310 set avahi_ok_p 0
a7dbd06e 311 verbose -log "Client/Server tests will be run by contacting the server directly as $server_spec"
51c1bb7a
DB
312
313 # Make sure stap can contact the server directly
314 set use_server --use-server=$server_spec
315 set res [catch {exec stap $use_server -p2 -e {probe begin {exit()}}} looksee]
316 if {$res != 0} then {
a7dbd06e
DB
317 verbose -log "Unable to contact the server at $server_spec directly"
318 shutdown_server
51c1bb7a
DB
319 return 0
320 }
321 }
322
250fb71a
DB
323 return 1
324}
325
fc3d2b46 326proc start_server { options } {
aae091fc 327 global srcdir env server_pid installed_stap logfile
250fb71a 328
cd3a2693
FCE
329 if {! [nss_p]} { return 0 }
330
72629a44
DB
331 # Server management scripts and data are installed if this is an
332 # install test, otherwise there is some setup to do.
edecda6c 333 # Make sure the server management scripts and tools are on the $PATH.
72629a44 334 if {! [installtest_p]} then {
574cf27a
SC
335 set env(PATH) "$srcdir/..:[pwd]/..:$env(PATH)"
336 set installed_stap "[pwd]/../stap"
67c7a9ac 337 set env(SYSTEMTAP_SERVER_SCRIPTS) "$srcdir/.."
edecda6c
DB
338 } else {
339 set env(PATH) "$env(PKGLIBDIR):$env(PATH)"
ff86dcd5 340 set installed_stap "$env(SYSTEMTAP_PATH)/stap"
2bdb7139 341 set env(SYSTEMTAP_SERVER_SCRIPTS) $env(PKGLIBDIR)
72629a44
DB
342 }
343
51c1bb7a 344 # Try to start the server.
78cd5654 345 set status 0
fc3d2b46 346 if {[catch {eval {exec env STAP_PR11197_OVERRIDE=1 \
78cd5654 347 env SYSTEMTAP_STAP=[exec which stap] stap-start-server \
fc3d2b46 348 --log=$logfile} $options} server_pid]} {
c26c10cb
DS
349 if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
350 set status [lindex $::errorCode 2]
78cd5654
DS
351 }
352 }
353 verbose -log "output: $server_pid"
354 if { "$server_pid" == "" || $status != 0 } then {
a7dbd06e 355 verbose -log "Cannot start a systemtap server"
72629a44 356 set server_pid 0
e26df1cb 357 return 0
72629a44 358 } else {
543bcb4c 359 verbose -log "Started a systemtap server as PID==$server_pid"
72629a44
DB
360 }
361
e26df1cb 362 return 1
72629a44
DB
363}
364
365proc shutdown_server {} {
8501d45c 366 global server_pid
72629a44 367 if { $server_pid != 0 } then {
543bcb4c 368 verbose -log "Stopping the systemtap server with PID==$server_pid"
3793a797 369 catch {exec stap-stop-server $server_pid}
7d54db1a 370 set server_pid 0
72629a44
DB
371 }
372
574cf27a 373 foreach module [glob -nocomplain [pwd]/stap_*.ko] {
b2ca731b
DB
374 exec /bin/rm -f $module
375 }
574cf27a 376 foreach sig [glob -nocomplain [pwd]/stap_*.ko.sgn] {
250fb71a
DB
377 exec /bin/rm -f $sig
378 }
72629a44
DB
379}
380
cd3a2693 381
aa238e24
WC
382proc normalize_arch { arch } {
383 if {$arch == "ppc64"} then {return "powerpc"}
384 if {$arch == "s390x"} then {return "s390"}
385 if {$arch == "i686"} then {return "i386"}
386 if {$arch == "armv5tel"} then {return "arm"}
387 if {$arch == "armv7l"} then {return "arm"}
388 if {$arch == "armv7lh"} then {return "arm"}
d8faa2f7 389 if {$arch == "aarch64"} then {return "arm64"}
aa238e24
WC
390 return $arch
391}
392
99e1fb7a
JS
393proc fullpath { path } {
394 if {[string index $path 0] != "/"} then {
395 # relative paths are anchored to the current directory
396 return [pwd]/$path
397 } else {
398 return $path
399 }
400}
401
9446a6d6 402proc get_system_info {} {
22a05791 403 global Host Snapshot Distro GCC_Version GCC_FullVersion ELF_Version env SElinux
bf4ac953
RM
404
405 set Host [exec /bin/uname -a]
05de43cb
FCE
406 if [file exists ../SNAPSHOT] {
407 set Snapshot [exec /bin/cat ../SNAPSHOT]
408 } elseif [file exists $env(SRCDIR)/../SNAPSHOT] {
9446a6d6
WH
409 set Snapshot [exec /bin/cat $env(SRCDIR)/../SNAPSHOT]
410 } else {
48a00e93 411 regexp {version [^)]*} [exec stap -V 2>@ stdout] version
172d72b3 412 set Snapshot $version
48a00e93 413 }
9446a6d6 414 set Distro "Linux"
172d72b3
FCE
415 if [file exists /usr/bin/lsb_release] {
416 # this produces one line of this format:
417 # Distribution:\tSTRING
418 set Distro [lrange [exec /usr/bin/lsb_release -d] 1 end]
419 } else {
420 foreach f {/etc/fedora-release /etc/enterprise-release /etc/redhat-release /etc/suse-release /etc/debian_version} {
421 if [file exists $f] then {set Distro [exec /bin/cat $f]; break }
422 }
23d89280 423 }
47561106
MW
424 # Easily parsable version first major minor patch level
425 set n [exec echo "__GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__" | cpp -P]
426 set n [string map {" " "."} $n]
8e02c673 427 set n [string map {"\n" ""} $n]
22a05791
JL
428 set GCC_Version "$n"
429 # Plus full version between square brackets for GCC_FullVersion
47561106 430 set full [exec gcc --version | head -1]
22a05791
JL
431 set GCC_FullVersion "$n \[$full\]"
432 # Parse elfutils version stap was compiled with
433 regexp {version [^/]*/([^,]*)} [exec stap -V 2>@ stdout] all ELF_Version
528296dc
FCE
434 # selinux status
435 if [file exists /usr/sbin/getenforce] {
436 set SElinux [exec /usr/sbin/getenforce]
437 } else {
438 set SElinux "unknown"
439 }
9446a6d6 440}
814bc89d 441
e26df1cb 442if {! [setup_systemtap_environment]} then {
51c1bb7a
DB
443 cleanup
444 exit 1
e26df1cb
DB
445}
446
814bc89d 447print_systemtap_version
9446a6d6 448get_system_info
814bc89d 449
03712201 450# PR11798: die if kernel-devel is not sufficient to build any modules
d153cbf8 451if {[catch {exec stap -p4 -e {probe begin {exit()}}} result]} {
03712201
FCE
452 puts "\n\n\n**** failed systemtap kernel-devel smoke test:\n"
453 puts $result
454# puts "****\n"
455# puts $options
456 puts "\n**** aborting testing.\n"
250fb71a 457 cleanup
03712201
FCE
458 exit 1
459}
460
461# PR11798: die also if kernel-debuginfo is not available
462# NB: if one introduced a [kernel_debuginfo_p] proc like the
463# ones for uprobes/utrace above, and sprinkled it throughout,
464# then this wouldn't have to be a failing condition.
31766229
MW
465# Note the --skip-badvars -w, we just care there is some debuginfo,
466# it is allowed have bad var location descriptors (which will cause
9ff46a11
MW
467# some tests to fail of course). Just test -p2, kernel-devel smoke
468# test above does a full module build, we don't need another one.
469if {[catch {exec stap --skip-badvars -w -p2 -e {probe syscall.open {println (argstr)}}} result]} {
03712201
FCE
470 puts "\n\n\n**** failed systemtap kernel-debuginfo smoke test:\n"
471 puts $result
472# puts "****\n"
473# puts $options
474 puts "\n**** aborting testing.\n"
250fb71a 475 cleanup
03712201
FCE
476 exit 1
477}
478
48eb228d 479# Make more likely that all development packages for the supported ABIs (-m64 -m32/-m31)
744884cd
MW
480# are installed by building a quick hello.c and hello.cxx program with both.
481set source "hello.c"
482set hello_file [open $source "w"]
483puts $hello_file "#include <stdio.h>"
484puts $hello_file "int main () { printf(\"Hello World!\"); return 0; }"
485close $hello_file
486for {set i 0} {$i < [arch_compile_flags]} {incr i} {
487 set flags "additional_flags=-g compiler=gcc [arch_compile_flag $i]"
488 set exe "hello-[arch_compile_flag_name $i]"
489 set result [target_compile $source $exe executable $flags]
490 if { $result != "" } {
491 puts "\n\n\n**** failed gcc [arch_compile_flag_name $i] smoke test:\n"
492 puts $result
493 puts "Please install libgcc and glibc development packages for [arch_compile_flag_name $i]\n"
744884cd
MW
494 }
495}
496set source "hello.cxx"
497set hello_file [open $source "w"]
498puts $hello_file "#include <iostream>"
499puts $hello_file "using namespace std;"
500puts $hello_file "int main () { cout << \"Hello World!\" << endl; return 0; }"
501close $hello_file
502for {set i 0} {$i < [arch_compile_flags]} {incr i} {
503 set flags "additional_flags=-g compiler=g++ [arch_compile_flag $i]"
504 set exe "hello-[arch_compile_flag_name $i]"
505 set result [target_compile $source $exe executable $flags]
506 if { $result != "" } {
507 puts "\n\n\n**** failed g++ [arch_compile_flag_name $i] smoke test:\n"
508 puts $result
509 puts "Please install libstdc++-devel package for [arch_compile_flag_name $i]\n"
744884cd
MW
510 }
511}
68547587 512catch { eval [list exec rm -f] [glob "hello.c*" "hello-*"] }
03712201 513
814bc89d
FCE
514proc systemtap_init {args} {}
515proc systemtap_version {} {}
d5658775 516
7d54db1a 517proc cleanup {} {
d5658775 518 # Stop the stap server, if we started it.
7d54db1a 519 shutdown_server
d5658775 520}
814bc89d 521
0ecbca4c 522
8c94efa7
DS
523proc stap_run_batch {filename args} {
524 verbose -log "starting $filename $args"
5ba96b90
FCE
525
526 # Many of our test cases use "#! stap ...". Since these lack
527 # /full/paths, they are not really executable. (We can't have
528 # /full/paths because the choice of systemtap interpreter is set
529 # at "make check" time.)
530
531 # So we cheat. If the file begins with "#! stap", we will spawn
532 # stap manually here (relying on $PATH). Otherwise, we presume
533 # the file properly executable.
534
8c94efa7 535 set file [open $filename r]
5ba96b90
FCE
536 set firstbits [gets $file]
537 close $file
538 if [regexp -line {\#! stap (.*)} $firstbits -> stap_args] {
8c94efa7 539 verbose -log "spawn1 stap $stap_args $filename $args"
353cb874
MW
540 # Make sure we don't accidentially add an extra empty argument.
541 if {$args == ""} {
542 spawn stap $stap_args $filename
543 } else {
544 spawn stap $stap_args $filename $args
545 }
5ba96b90 546 } else {
8c94efa7 547 verbose -log "spawn2 $filename $args"
353cb874
MW
548 # Make sure we don't accidentially add an extra empty argument.
549 if {$args == ""} {
550 spawn $filename
551 } else {
552 spawn $filename $args
553 }
5ba96b90
FCE
554 }
555
bf4ac953 556 expect {
59cbc061 557 -timeout -1
bf4ac953 558 -re {[^\r]*\r} { verbose -log $expect_out(0,string); exp_continue }
bbbce017 559 eof { }
bbbce017 560 }
0ecbca4c
FCE
561 set results [wait]
562 verbose -log "wait results: $results"
c2d92a15
MH
563 if {[llength $results] >= 5} {
564 # Unexpected output. stap must have crashed
565 return -1
566 } else {
567 return [lindex $results 3]
568 }
68e7e59b 569}
14b31996
WC
570
571proc as_root { command } {
2b70fd78 572 set effective_uid [exec /usr/bin/id -u]
14b31996 573
2b70fd78
DS
574 if {$effective_uid != 0} {
575 set command "sudo $command"
576 }
577 verbose -log "as_root $command"
578 set res [catch {eval exec $command} value]
579 verbose -log "OUT $value"
580 verbose -log "RC $res"
581 return $res
582}
bf4ac953 583
005f34a8 584proc as_non_root { command } {
2b70fd78
DS
585 set effective_uid [exec /usr/bin/id -u]
586
587 if {$effective_uid == 0} {
edb7542e
DS
588 # If logname fails (which it can if we're not in a login
589 # shell) or if we're root, use user 'nobody'.
2b70fd78
DS
590 #
591 # Note that user 'nobody' can't use systemtap to load kernel
592 # modules, since he isn't a member of the stapusr/stapdev
593 # groups. But, 'nobody' can use systemtap to compile a kernel
594 # module.
edb7542e
DS
595 set logname "root"
596 if {[catch {exec /usr/bin/logname} logname] || $logname == "root"} {
2b70fd78
DS
597 set logname "nobody"
598 }
41029fd7
DS
599
600 # User 'nobody' doesn't have a home directory, which means we
601 # can't create ~nobody/.systemtap. So, temporarily override
602 # SYSTEMTAP_DIR.
603 if {$logname == "nobody"} {
604 set stap_dir "/tmp/.systemtap-nobody"
605 set command "su -s /bin/sh $logname -c \"SYSTEMTAP_DIR=$stap_dir $command\""
606 } else {
607 set command "su -s /bin/sh $logname -c \"$command\""
608 }
2b70fd78
DS
609 }
610 verbose -log "as_non_root $command"
611 set res [catch {eval exec $command} value]
41029fd7
DS
612 if {$effective_uid == 0 && $logname == "nobody"} {
613 # If we created a SYSTEMTAP_DIR for user 'nobody' above, we
614 # can now remove it.
615 catch {exec rm -rf $stap_dir}
616 }
2b70fd78
DS
617 verbose -log "OUT $value"
618 verbose -log "RC $res"
619 return $res
005f34a8
CM
620}
621
bf4ac953 622proc sdt_includes {} {
6b51ee12 623 global srcdir env
bf4ac953
RM
624
625 # The wrapper sys/sdt.h for testing STAP_SDT_V[12] is here.
626 set dirs [list $srcdir]
627
628 if {[installtest_p]} {
629 # Use the installed <sys/sdt.h>.
630 lappend dirs $env(SYSTEMTAP_INCLUDES)
631 } else {
632 # Find <sys/sdt.h> in the source tree.
633 lappend dirs $srcdir/../includes
634 # The uninstalled, configured sdt-config.h has to be found here.
831b13d6 635 lappend dirs ../includes/sys
bf4ac953
RM
636 }
637
638 set flags ""
639 foreach dir $dirs {
831b13d6 640 set flags "$flags additional_flags=-isystem${dir}"
bf4ac953
RM
641 }
642
643 return $flags
644}
d9151131
DS
645
646proc stripped_p { EXE } {
647 if { [catch {eval exec "file $EXE | grep -q \"not stripped\""} dummy] } {
648 return 1
649 }
650 return 0
651}
ff579492
JS
652
653proc prelink_p {} {
654 global prelink_bin
655 set prelink_bin "/usr/sbin/prelink"
656 return [file exists "$prelink_bin"]
657}
658
659# Run prelink via a temp file, so it can succeed even when running from an nfs
660# $HOME, for instance. Otherwise, prelink complains that it can't restore context.
661proc prelink { FILE ADDR } {
662 global prelink_bin
663 if {![prelink_p]} {
664 verbose -log "Prelink is not found on this system"
665 return 0
666 }
667 if {[catch {exec mktemp -t staptestXXXXXX} tmpfile]} {
668 verbose -log "Failed to create prelink temporary file: $tmpfile"
669 return 0
670 }
671 if {[catch {exec cp -a "$FILE" "$tmpfile"} result]} {
672 verbose -log "Failed to copy file for prelink: $result"
673 catch {exec rm -rf "$tmpfile"}
674 return 0
675 }
676 set prelink_cmd [concat "$prelink_bin" -vfNR -r "$ADDR" "$tmpfile"]
677 send_log "Executing: $prelink_cmd\n"
678 if {[catch {eval exec $prelink_cmd} result]} {
679 verbose -log "Prelink failed: $result"
680 catch {exec rm -rf "$tmpfile"}
681 return 0
682 }
683 if {[catch {exec mv "$tmpfile" "$FILE"} result]} {
684 verbose -log "Failed to move prelinked file back: $result"
685 catch {exec rm -rf "$tmpfile"}
686 return 0
687 }
688 return 1
689}
0b872dd0
JL
690
691# Send signal SIG to PID. If KILL_TIMEOUT > 0, waits KILL_TIMEOUT seconds before
692# also sending a SIGKILL signal to PID. SIG can be with or without leading '-'.
693proc kill { SIG PID {KILL_TIMEOUT 0} } {
694 global kill_needs_doubledash
695
696 if {$kill_needs_doubledash} {
697 set PID "-- $PID"
698 }
699 if {![string match -* $SIG]} {
700 set SIG "-$SIG"
701 }
702
703 verbose -log "Executing: kill $SIG $PID"
704 catch {eval exec kill $SIG $PID}
705
3f11227f
JL
706 if {$KILL_TIMEOUT > 0} {
707 while {$KILL_TIMEOUT > 0} {
708 if {![file isdirectory /proc/$PID]} {
709 return
710 }
711 sleep 1
712 incr KILL_TIMEOUT -1
713 }
0b872dd0
JL
714 verbose -log "Executing: kill -KILL $PID"
715 catch {eval exec kill -KILL $PID}
716 }
717}
6bcbab76
JL
718
719# Compares vers1 to vers2. Returns an integer less than, equal to, or greater
720# than zero if vers1 is before, equal, or after vers2. Similar to the GNU
721# extension strverscmp(3), but restricted to simple M.N... version numbers.
722proc strverscmp { vers1 vers2 } {
723
724 # Check that both versions are valid M.N... format
725 if {![regexp {^[0-9]+(\.[0-9]+)*$} $vers1]} {
726 error "$vers1 is not a valid version number"
727 }
728 if {![regexp {^[0-9]+(\.[0-9]+)*$} $vers2]} {
729 error "$vers2 is not a valid version number"
730 }
731
732 while {1} {
733
734 # Get the next M for each as well as following N...
735 regexp {^([0-9]+)(\.(.*))?} $vers1 dummy subvers1 dummy nextvers1
736 regexp {^([0-9]+)(\.(.*))?} $vers2 dummy subvers2 dummy nextvers2
737
738 # Compare M
739 if {$subvers1 < $subvers2} { return -1 }
740 if {$subvers1 > $subvers2} { return 1 }
741 # The M parts are equal
742
743 # Check if one (or both) of them don't have a next subversion
744 if {![string length $nextvers1] \
745 && ![string length $nextvers2]} { return 0 }
746 if {![string length $nextvers1] \
747 && [string length $nextvers2]} { return -1 }
748 if {[string length $nextvers1] \
749 && ![string length $nextvers2]} { return 1 }
750
751 # They both have a subversion following, let's re-iterate
752
753 # Sanity check that we're making progress and not looping forever
754 if {[string length $nextvers1] >= [string length $vers1]} \
755 { error "$vers1 not converging" }
756 if {[string length $nextvers2] >= [string length $vers2]} \
757 { error "$vers2 not converging" }
758
759 set vers1 $nextvers1
760 set vers2 $nextvers2
761 }
762}
This page took 0.267151 seconds and 5 git commands to generate.