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