1#!/usr/bin/perl -w 2# 3# $Id: gcov_filter.pl,v 1.4 2005-11-02 17:23:57 kz Exp $ 4# 5# ************************************************************* 6# 7# Licensed to the Apache Software Foundation (ASF) under one 8# or more contributor license agreements. See the NOTICE file 9# distributed with this work for additional information 10# regarding copyright ownership. The ASF licenses this file 11# to you under the Apache License, Version 2.0 (the 12# "License"); you may not use this file except in compliance 13# with the License. You may obtain a copy of the License at 14# 15# http://www.apache.org/licenses/LICENSE-2.0 16# 17# Unless required by applicable law or agreed to in writing, 18# software distributed under the License is distributed on an 19# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 20# KIND, either express or implied. See the License for the 21# specific language governing permissions and limitations 22# under the License. 23# 24# ************************************************************* 25 26# GCOV_FILTER 27# 28# Helper to filter the gcov output. 29# Handle a compare between the hole gcov output and a given select list of exported functions. 30# 31# Q: Why perl? 32# A: regexp ;-) 33# 34 35 36use strict; 37use File::Basename; 38use Getopt::Long; 39 40# Global constants 41our $version_info = 'gcov helper $Revision: 1.4 $ '; 42our $help; # Help option flag 43our $version; # Version option flag 44our $cwd = `pwd`; # current working directory 45chomp($cwd); 46# our $tool_dir = dirname($0); 47# our $tool_file = basename($0); 48 49# our $output_filename; 50our $input_allfunc; 51# our $input_filename; 52 53our $allfuncinfo; # allfuncinfo option flag 54our $showallfunc; # showallfunc option flag 55our $no_percentage; # no_percentage option flag 56our $donotfilter; # donotfilter option flag 57our $objectdir; 58 59# Prototypes 60sub print_usage(*); 61sub read_gcov_function_file($); 62sub get_PRJ_from_makefile_mk(); 63# sub read_ExportedFunctionList(); 64sub read_List($); 65 66# if (! ($tool_dir =~ /^\/(.*)$/)) 67# { 68# $tool_dir = "$cwd/$tool_dir"; 69# } 70 71# Parse command line options 72if (!GetOptions( "input-allfunc=s" => \$input_allfunc, 73 "allfuncinfo" => \$allfuncinfo, 74 "showallfunc" => \$showallfunc, 75 "no-percentage" => \$no_percentage, 76 "do-not-filter" => \$donotfilter, 77 "objectdir=s" => \$objectdir, 78 "help" => \$help, 79 "version" => \$version 80 )) 81{ 82 print_usage(*STDERR); 83 exit(1); 84} 85 86# Check for help option 87if ($help) 88{ 89 print_usage(*STDOUT); 90 exit(0); 91} 92 93# Check for version option 94if ($version) 95{ 96 print("$version_info\n"); 97 exit(0); 98} 99 100# check if enough parameters 101if ($#ARGV < 0) 102{ 103 print("No input filename specified\n"); 104 print_usage(*STDERR); 105 exit(1); 106} 107 108# special case: 109# the filename contains a . or '/' at the beginning 110my $startdir = $ARGV[0]; 111if ( ($startdir =~ /^\.\./) || 112 ($startdir =~ /^\//) ) 113{ 114 $startdir = dirname($startdir); 115 # print("start directory is $startdir\n"); 116 # chdir $startdir; 117} 118else 119{ 120 $startdir = ""; 121} 122 123# check for sal.map 124if ( ! $input_allfunc ) 125{ 126 # this is a try, to get the project directory form a found makefile.mk 127 # may work, but fails due to some disunderstandings may be problems in perl :-( 128 my $sDir = get_PRJ_from_makefile_mk(); 129 # chomp($sDir); 130 # HDW: print("PRJ is $dir\n"); 131 132 # $sDir2 = "../.."; 133 my $sMapFile = "$sDir" . "/util/sal.map"; 134 # $sMapFile = "$sDir2" . "/util/sal.map"; 135 136 if ( -e $sMapFile) 137 { 138 $input_allfunc = $sMapFile; 139 } 140 else 141 { 142 print("No input-allfunc filename specified\n"); 143 print_usage(*STDERR); 144 exit(1); 145 } 146} 147our @aDeprecatedList; 148our @aExportedFunctionList; 149# read_ExportedFunctionList(); 150@aExportedFunctionList = read_List($input_allfunc); 151@aDeprecatedList = read_List("deprecated.txt"); 152 153if ($allfuncinfo) 154{ 155 print("Count of all functions: $#aExportedFunctionList\n"); 156 exit(0); 157} 158 159if ($showallfunc) 160{ 161 my $func; 162 foreach $func (@aExportedFunctionList) 163 { 164 print("$func\n"); 165 } 166 exit(0); 167} 168 169# back to current directory 170# this chdir was for a before chdir (in $startdir creation) but due to the fact, 171# that the get_PRJ_from_makefile_mk works but the after concat of strings not, this 172# chdir is also remarked. 173# chdir $cwd; 174 175# HWD: print "count of param: \n"; 176# $input_filename = $ARGV[0]; 177 178my $nCount = $#ARGV + 1; 179my $nIdx; 180 181for ($nIdx = 0; $nIdx < $nCount ; ++$nIdx) 182{ 183 my $file = $ARGV[$nIdx]; 184 # print("processing: $file\n"); 185 186 # change directory, to the current file, due to the fact, that we may be need to call gcov 187 # and gcov will create some extra files, like *.gcov near the current file. 188 # if ( $startdir ne "" ) 189 # { 190 # chdir $startdir; 191 # $file = basename($file); 192 # } 193 194 my $OBJECTS=""; 195 if ($objectdir) 196 { 197 $OBJECTS = "-o " . $objectdir; 198 } 199 200 if (! ($file =~ /\.f$/ )) 201 { 202 my $filef = "$file.f"; 203 # if (! -e $filef ) 204 # { 205 # print "gcov $OBJECTS -l -f $file >$filef\n"; 206 my $blah = `gcov $OBJECTS -n -f $file >$filef`; 207 # } 208 $file = $filef; 209 } 210 read_gcov_function_file($file); 211 212 # go back to old directory, because it's possible to change relative to an other directory. 213 if ( $startdir ne "" ) 214 { 215 chdir $cwd; 216 } 217} 218 219# print "$tool_dir\n"; 220# print "all is right\n"; 221exit(0); 222 223 224# -------------------------------------------------------------------------------- 225# Read the map file, which should contain all exported functions. 226sub read_List($) 227{ 228 local *INPUT_HANDLE; 229 my $filename = $_[0]; 230 my @list; 231 my $line = ""; 232 open(INPUT_HANDLE, $filename); 233 # or die("ERROR: cannot open $filename!\n"); 234 235 while ($line = <INPUT_HANDLE>) 236 { 237 chomp($line); 238 # reg exp: [spaces]functionname[semicolon][line end] 239 if ($line =~ /^\s+(\w*);$/) 240 { 241 # print("$1\n"); 242 push(@list, $1); 243 } 244 } 245 close(INPUT_HANDLE); 246 return @list; 247} 248 249# -------------------------------------------------------------------------------- 250# Helper function, test is a given value is found in the global exported function list. 251# the given value format could be a simple function name 252# or a prototype 253# e.g. 254# osl_getSystemPathFromFileURL 255# or 256# void getSystemPathFromFileURL( const char* rtl_...) 257# 258sub contain_in_List($$) 259{ 260 my $func; 261 my $value = $_[0]; 262 my $list = $_[1]; 263 264 if ($donotfilter) 265 { 266 return $value; 267 } 268 269 foreach $func (@$list) # (@aExportedFunctionList) 270 { 271 # first try, direct check 272 if ($value eq $func) 273 { 274 # HWD: print("$value eq $func\n"); 275 return $value; 276 } 277 278 # value not found, second try, may be we found it if we search word wise. 279 # helper, to insert a space after the word, before '(' 280 $value =~ s/\(/ \(/g; 281 # may be here we should replace all white spaces by ' ' 282 283 # split by 'space' 284 my @list = split(' ', $value); 285 for(@list) 286 { 287 # HWD: print "$list[$n]\n"; 288 if ($_ eq $func) 289 { 290 # HWD: print ("found $func in $value\n"); 291 return $_; 292 } 293 } 294 } 295 # not found 296 return ""; 297} 298# -------------------------------------------------------------------------------- 299# Read the gcov function (gcov -f) file 300# and compare line by line with the export function list 301# so we get a list of functions, which are only exported, and not all stuff. 302# sample of output 303# new gcov gcc 3.4 format 304sub read_gcov_function_file($) 305{ 306 local *INPUT_HANDLE; 307 my $file = $_[0]; 308 my $line = ""; 309 open(INPUT_HANDLE, $file) 310 or die("ERROR: cannot open $file!\n"); 311 312 while ($line = <INPUT_HANDLE>) 313 { 314 chomp($line); 315 # sample line (for reg exp:) 316 # 100.00% of 3 source lines executed in function osl_thread_init_Impl 317 if ($line =~ /^Function \`(.*)\'$/ ) 318 { 319 my $sFunctionName = $1; 320 my $sPercentage; 321 $line = <INPUT_HANDLE>; 322 if ($line =~ /^Lines executed:(.*)% of/ ) 323 { 324 $sPercentage = $1; 325 } 326 my $value = contain_in_List( $sFunctionName, \@aExportedFunctionList ); 327 if ($value) 328 { 329 my $isDeprecated = contain_in_List( $sFunctionName, \@aDeprecatedList ); 330 if ($isDeprecated) 331 { 332 # Function is deprecated, do not export it. 333 } 334 else 335 { 336 if ($no_percentage) 337 { 338 print("$value\n"); 339 } 340 else 341 { 342 print("$sPercentage $value\n"); 343 } 344 } 345 } 346 # push(@aExportedFunctionList, $1); 347 } 348 } 349 close(INPUT_HANDLE); 350} 351 352# gcov format since gcc 3.3.6 353# 100.00% von 3 Zeilen in function helloworld ausgef�hrt 354# 100.00% von 5 Zeilen in function main ausgef�hrt 355# 100.00% von 8 Zeilen in file tmp.c ausgef�hrt 356sub read_gcov_function_file_old_gcc_3($) 357{ 358 local *INPUT_HANDLE; 359 my $file = $_[0]; 360 my $line = ""; 361 open(INPUT_HANDLE, $file) 362 or die("ERROR: cannot open $file!\n"); 363 364 while ($line = <INPUT_HANDLE>) 365 { 366 chomp($line); 367 # sample line (for reg exp:) 368 # 100.00% of 3 source lines executed in function osl_thread_init_Impl 369 if ($line =~ /^(.*)% of \d+ source lines executed in function (.*)$/ ) 370 { 371 my $value = contain_in_List( $2, \@aExportedFunctionList ); 372 if ($value) 373 { 374 my $isDeprecated = contain_in_List( $2, \@aDeprecatedList ); 375 if ($isDeprecated) 376 { 377 # Function is deprecated, do not export it. 378 } 379 else 380 { 381 if ($no_percentage) 382 { 383 print("$value\n"); 384 } 385 else 386 { 387 print("$1 $value\n"); 388 } 389 } 390 } 391 # push(@aExportedFunctionList, $1); 392 } 393 } 394 close(INPUT_HANDLE); 395} 396 397# ------------------------------------------------------------------------------ 398# helper, to read the PRJ value out of a makefile.mk file 399sub get_PRJ_from_makefile_mk() 400{ 401 local *INPUT_HANDLE; 402 # my $startdir = @_[0]; 403 my $line = ""; 404 my $value = ""; 405 open(INPUT_HANDLE, "makefile.mk") 406 or die("ERROR: cannot open makefile.mk\n"); 407 408 while ($line = <INPUT_HANDLE>) 409 { 410 chomp($line); 411 # sample line 412 # PRJ= 413 # HWD: print("$line\n"); 414 if ($line =~ /^PRJ\s*=(.*)\s*$/) 415 { 416 # HWD: print("FOUND #####\n"); 417 $value = $1; 418 chomp($value); 419 $value =~ s/\$\//\//g; 420 } 421 } 422 close(INPUT_HANDLE); 423 return $value; 424} 425 426# ---------------------------------------------------------------------------- 427sub print_usage(*) 428{ 429 local *HANDLE = $_[0]; 430 my $tool_name = basename($0); 431 432 print(HANDLE <<END_OF_USAGE); 433 434Usage: $tool_name [OPTIONS] INPUTFILE 435 436 -h, --help Print this help, then exit 437 -v, --version Print version number, then exit 438 -i, --input-allfunc FILENAME Map file, which contain all exported functions 439 -s, --showallfunc Shows all exported functions then exit 440 -a, --allfuncinfo Shows the count of all exported functions then quit 441 -n, --no-percentage Suppress the output of the percent value for tested functions 442 -d, --do-not-filter Show all functions, which gcov -f produce 443 444END_OF_USAGE 445 ; 446} 447 448