ltrace.exp revision c13bd96c15af83fa5818862a1f785a2d49094bee
1# This file was written by Yao Qi. (qiyao@cn.ibm.com) 2 3# Generic ltrace test subroutines that should work for any target. If these 4# need to be modified for any target, it can be done with a variable 5# or by passing arguments. 6 7source $objdir/env.exp 8 9global LTRACE 10if [info exists TOOL_EXECUTABLE] { 11 set LTRACE $TOOL_EXECUTABLE 12} else { 13 set LTRACE $objdir/../ltrace 14} 15 16global LTRACE_OPTIONS 17set LTRACE_OPTIONS ""; 18global LTRACE_ARGS 19set LTRACE_ARGS ""; 20 21# ltrace_compile SOURCE DEST TYPE OPTIONS 22# 23# Compile PUT(program under test) by native compiler. ltrace_compile runs 24# the right compiler, and TCL captures the output, and I evaluate the output. 25# 26# SOURCE is the name of program under test, with full directory. 27# DEST is the name of output of compilation, with full directory. 28# TYPE is an enum-like variable to affect the format or result of compiler 29# output. Values: 30# executable if output is an executable. 31# object if output is an object. 32# OPTIONS is option to compiler in this compilation. 33proc ltrace_compile {source dest type options} { 34 global LTRACE_TESTCASE_OPTIONS; 35 36 # Add platform-specific options if a shared library was specified using 37 # "shlib=librarypath" in OPTIONS. 38 set new_options "" 39 set shlib_found 0 40 41 foreach opt $options { 42 if [regexp {^shlib=(.*)} $opt dummy_var shlib_name] { 43 if [test_compiler_info "xlc*"] { 44 # IBM xlc compiler doesn't accept shared library named other 45 # than .so: use "-Wl," to bypass this 46 lappend source "-Wl,$shlib_name" 47 } else { 48 lappend source $shlib_name 49 } 50 51 if {$shlib_found == 0} { 52 set shlib_found 1 53 54 if { ([test_compiler_info "gcc-*"]&& ([istarget "powerpc*-*-aix*"]|| [istarget "rs6000*-*-aix*"] ))} { 55 lappend options "additional_flags=-L${objdir}/${subdir}" 56 } elseif { [istarget "mips-sgi-irix*"] } { 57 lappend options "additional_flags=-rpath ${objdir}/${subdir}" 58 } 59 } 60 61 } else { 62 lappend new_options $opt 63 } 64 } 65 #end of for loop 66 set options $new_options 67 # dump some information for debug purpose. 68 verbose "options are $options" 69 verbose "source is $source $dest $type $options" 70 71 # Wipe the DEST file, so that we don't end up running an obsolete 72 # version of the binary. 73 exec rm -f $dest 74 75 set result [target_compile $source $dest $type $options]; 76 verbose "result is $result" 77 regsub "\[\r\n\]*$" "$result" "" result; 78 regsub "^\[\r\n\]*" "$result" "" result; 79 if { $result != "" && [lsearch $options quiet] == -1} { 80 clone_output "compile failed for ltrace test, $result" 81 } 82 return $result; 83} 84 85proc get_compiler_info {binfile args} { 86 # For compiler.c and compiler.cc 87 global srcdir 88 89 # I am going to play with the log to keep noise out. 90 global outdir 91 global tool 92 93 # These come from compiler.c or compiler.cc 94 global compiler_info 95 96 # Legacy global data symbols. 97 #global gcc_compiled 98 99 # Choose which file to preprocess. 100 set ifile "${srcdir}/lib/compiler.c" 101 if { [llength $args] > 0 && [lindex $args 0] == "c++" } { 102 set ifile "${srcdir}/lib/compiler.cc" 103 } 104 105 # Run $ifile through the right preprocessor. 106 # Toggle ltrace.log to keep the compiler output out of the log. 107 #log_file 108 set cppout [ ltrace_compile "${ifile}" "" preprocess [list "$args" quiet] ] 109 #log_file -a "$outdir/$tool.log" 110 111 # Eval the output. 112 set unknown 0 113 foreach cppline [ split "$cppout" "\n" ] { 114 if { [ regexp "^#" "$cppline" ] } { 115 # line marker 116 } elseif { [ regexp "^\[\n\r\t \]*$" "$cppline" ] } { 117 # blank line 118 } elseif { [ regexp "^\[\n\r\t \]*set\[\n\r\t \]" "$cppline" ] } { 119 # eval this line 120 verbose "get_compiler_info: $cppline" 2 121 eval "$cppline" 122 } else { 123 # unknown line 124 verbose "get_compiler_info: $cppline" 125 set unknown 1 126 } 127 } 128 129 # Reset to unknown compiler if any diagnostics happened. 130 if { $unknown } { 131 set compiler_info "unknown" 132 } 133 return 0 134} 135 136proc test_compiler_info { {compiler ""} } { 137 global compiler_info 138 verbose "compiler_info=$compiler_info" 139 # if no arg, return the compiler_info string 140 141 if [string match "" $compiler] { 142 if [info exists compiler_info] { 143 return $compiler_info 144 } else { 145 perror "No compiler info found." 146 } 147 } 148 149 return [string match $compiler $compiler_info] 150} 151 152proc ltrace_compile_shlib {sources dest options} { 153 set obj_options $options 154 verbose "+++++++ [test_compiler_info]" 155 switch -glob [test_compiler_info] { 156 "xlc-*" { 157 lappend obj_options "additional_flags=-qpic" 158 } 159 "gcc-*" { 160 if { !([istarget "powerpc*-*-aix*"] 161 || [istarget "rs6000*-*-aix*"]) } { 162 lappend obj_options "additional_flags=-fpic" 163 } 164 } 165 "xlc++-*" { 166 lappend obj_options "additional_flags=-qpic" 167 } 168 169 default { 170 fail "Bad compiler!" 171 } 172 } 173 174 set outdir [file dirname $dest] 175 set objects "" 176 foreach source $sources { 177 set sourcebase [file tail $source] 178 if {[ltrace_compile $source "${outdir}/${sourcebase}.o" object $obj_options] != ""} { 179 return -1 180 } 181 lappend objects ${outdir}/${sourcebase}.o 182 } 183 184 set link_options $options 185 if { [test_compiler_info "xlc-*"] || [test_compiler_info "xlc++-*"]} { 186 lappend link_options "additional_flags=-qmkshrobj" 187 } else { 188 lappend link_options "additional_flags=-shared" 189 } 190 if {[ltrace_compile "${objects}" "${dest}" executable $link_options] != ""} { 191 return -1 192 } 193} 194 195# 196# ltrace_options OPTIONS_LIST 197# Pass ltrace commandline options. 198# 199proc ltrace_options { args } { 200 201 global LTRACE_OPTIONS 202 set LTRACE_OPTIONS $args 203} 204 205# 206# ltrace_args ARGS_LIST 207# Pass ltrace'd program its own commandline options. 208# 209proc ltrace_args { args } { 210 211 global LTRACE_ARGS 212 set LTRACE_ARGS $args 213} 214 215# 216# handle run-time library paths 217# 218proc ld_library_path { args } { 219 220 set ALL_LIBRARY_PATHS { } 221 if [info exists LD_LIBRARY_PATH] { 222 lappend ALL_LIBRARY_PATHS $LD_LIBRARY_PATH 223 } 224 global libelf_LD_LIBRARY_PATH 225 if {[string length $libelf_LD_LIBRARY_PATH] > 0} { 226 lappend ALL_LIBRARY_PATHS $libelf_LD_LIBRARY_PATH 227 } 228 global libunwind_LD_LIBRARY_PATH 229 if {[string length $libunwind_LD_LIBRARY_PATH] > 0} { 230 lappend ALL_LIBRARY_PATHS $libunwind_LD_LIBRARY_PATH 231 } 232 lappend ALL_LIBRARY_PATHS $args 233 join $ALL_LIBRARY_PATHS ":" 234} 235 236# 237# ltrace_runtest LD_LIBRARY_PATH BIN FILE 238# Trace the execution of BIN and return result. 239# 240# BIN is program-under-test. 241# LD_LIBRARY_PATH is the env for program-under-test to run. 242# FILE is to save the output from ltrace with default name $BIN.ltrace. 243# Retrun output from ltrace. 244# 245proc ltrace_runtest { args } { 246 247 global LTRACE 248 global LTRACE_OPTIONS 249 global LTRACE_ARGS 250 251 verbose "LTRACE = $LTRACE" 252 253 set LD_LIBRARY_PATH_ [ld_library_path [lindex $args 0]] 254 set BIN [lindex $args 1] 255 256 # specify the output file, the default one is $BIN.ltrace 257 if [llength $args]==3 then { 258 set file [lindex $args 2] 259 } else { 260 set file $BIN.ltrace 261 } 262 263 # Remove the file first. If ltrace fails to overwrite it, we 264 # would be comparing output to an obsolete run. 265 exec rm -f $file 266 267 # append this option to LTRACE_OPTIONS. 268 lappend LTRACE_OPTIONS "-o" 269 lappend LTRACE_OPTIONS "$file" 270 verbose "LTRACE_OPTIONS = $LTRACE_OPTIONS" 271 #ltrace the PUT. 272 catch "exec sh -c {export LD_LIBRARY_PATH=$LD_LIBRARY_PATH_; $LTRACE $LTRACE_OPTIONS $BIN $LTRACE_ARGS;exit}" output 273 274 # return output from ltrace. 275 return $output 276} 277 278# 279# ltrace_saveoutput OUTPUT FILE 280# Save OUTPUT from ltrace to file FILE. 281# OUTPUT is output from ltrace or return value of ltrace_runtest. 282# FILE is file save output. 283# 284proc ltrace_saveoutput { args } { 285 286 set output [lindex $args 0] 287 set file [lindex $args 1] 288 289 set fd [open $file w] 290 puts $fd $output 291 close $fd 292} 293 294 295# 296# ltrace_verify_output FILE_TO_SEARCH PATTERN MAX_LINE 297# Verify the ltrace output by comparing the number of PATTERN in 298# FILE_TO_SEARCH with INSTANCE_NO. Do not specify INSTANCE_NO if 299# instance number is ignored in this test. 300# Reutrn: 301# 0 = number of PATTERN in FILE_TO_SEARCH inqual to INSTANCE_NO. 302# 1 = number of PATTERN in FILE_TO_SEARCH qual to INSTANCE_NO. 303# 304proc ltrace_verify_output { file_to_search pattern {instance_no 0} {grep_command "grep"}} { 305 306 # compute the number of PATTERN in FILE_TO_SEARCH by grep and wc. 307 catch "exec sh -c {$grep_command \"$pattern\" $file_to_search | wc -l ;exit}" output 308 verbose "output = $output" 309 310 if [ regexp "syntax error" $output ] then { 311 fail "Invalid regular expression $pattern" 312 } elseif { $instance_no == 0 } then { 313 if { $output == 0 } then { 314 fail "Fail to find $pattern in $file_to_search" 315 } else { 316 pass "$pattern in $file_to_search" 317 } 318 } elseif { $output >= $instance_no } then { 319 pass "$pattern in $file_to_search for $output times" 320 } else { 321 fail "$pattern in $file_to_search for $output times, should be $instance_no" 322 } 323} 324