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