1#! perl 2################################################################################ 3# Copyright (C) 2001-2003, Parrot Foundation. 4################################################################################ 5 6=head1 NAME 7 8tools/dev/lib_deps.pl - List libc dependencies 9 10=head1 SYNOPSIS 11 12 % perl tools/dev/lib_deps.pl [object | source] file1 [file2 ...] 13 14=head1 DESCRIPTION 15 16This script is intended to give us an idea of what C<libc> functions 17this build depends upon. 18 19=head2 Options 20 21=over 4 22 23=item C<object> 24 25In C<object> mode, it expects a list of all parrot's object files. It 26runs C<nm> on each and determines what external functions are being 27called. Note that it assumes a gnu-ish C<nm>. 28 29=item C<source> 30 31In C<source> mode, it uses a the C<cxref> program 32(L<http://www.gedanken.demon.co.uk/cxref/>) to extract information from 33the program source about what functions are being called, what includes 34are used, etc. This mode is potentially more thorough, but a bit more 35magical and therefore less conclusive. 36 37=back 38 39=cut 40 41################################################################################ 42 43use strict; 44use warnings; 45use File::Find; 46use File::Spec; 47 48my %defined_in; 49my %referenced_in; 50my %ansi_c89_symbol; 51my %ansi_c89_header; 52 53my ( $mode, @files ) = @ARGV; 54 55if ( $mode !~ /^(source|object)$/ || !@files ) { 56 die "Usage: $0 object <object files..>\n" . " $0 source <source files..>\n"; 57} 58 59while (<DATA>) { 60 next if /^\s*#/; 61 chomp; 62 next unless $_; 63 my ( $symbol, $file ) = /(\S+)\s+(\S+)/; 64 $ansi_c89_symbol{$symbol} = $file unless ( $symbol eq "UNDEF" ); 65 push @{ $ansi_c89_header{$file} }, $symbol; 66} 67 68if ( $mode eq "object" ) { 69 do_object(); 70} 71else { 72 do_source(); 73} 74 75exit(0); 76 77############################################################################## 78 79sub do_source { 80 81 if ( $files[0] eq "all_source" ) { 82 83 # do a little "find" action for now. 84 85 @files = (); 86 File::Find::find( 87 { 88 wanted => sub { 89 /^.*\.[ch]\z/s 90 && push @files, $File::Find::name; 91 } 92 }, 93 '.' 94 ); 95 } 96 97 # note: need to run this a second time so the database is built. 98 # should just use the build process to do it the first time. 99 my $devnull = File::Spec->devnull; 100 my $cmd = "cxref -raw -Iinclude -Iinclude/pmc -xref @files"; 101 print "Running cxref (pass 1)\n"; 102 system("$cmd > $devnull 2>$devnull"); 103 print "Running cxref (pass 2)\n"; 104 open( my $F, '-|', "$cmd 2>$devnull|" ) 105 || die "Can't run $cmd.\n"; 106 107 my %external_calls; 108 my %internal_calls; 109 my %variable_visible; 110 my %system_include; 111 my ( $file, $function, $variable ); 112 while (<$F>) { 113 114 if (/----------------------------------------/) { 115 undef $file if defined($file); 116 next; 117 } 118 119 if (/^INCLUDES : '(.*)' \[System file\]/) { 120 next if ( $1 =~ /^include\// ); 121 $system_include{$1}{$file}++; 122 next; 123 } 124 125 if ( !$file && /^FILE : '(.*)'$/ ) { 126 $file = $1; 127 next; 128 } 129 130 # skip anything between files. 131 next unless $file; 132 133 # beginning of function block 134 if (/FUNCTION : (.*) \[(.*)\]/) { 135 $function = $1; 136 my $function_scope = $2; 137 138 next; 139 } 140 141 # end of function block 142 if ( $function && /^\s*$/ ) { 143 undef $function; 144 next; 145 } 146 147 # beginning of variable block 148 if (/VARIABLE : (.*) \[(.*)\]/) { 149 $variable = $1; 150 my $variable_scope = $2; 151 if ( $variable_scope eq "Local" ) { 152 $variable_visible{$file}{$1}++; 153 } 154 else { 155 $variable_visible{"ALL"}{$1}++; 156 } 157 158 next; 159 } 160 161 # end of variable block 162 if ( $variable && /^\s*$/ ) { 163 undef $variable; 164 next; 165 } 166 167 if ($function) { 168 if (/Calls (.*) : (.*)/) { 169 170 # calling another function within parrot. 171 $internal_calls{$1}{"$file:$function"}++ 172 unless ( $variable_visible{$file}{$1} 173 || $variable_visible{ALL}{$1} ); 174 } 175 elsif (/Calls (.*)/) { 176 177 # calling a function outside of parrot! 178 $external_calls{$1}{"$file:$function"}++ 179 unless ( $variable_visible{$file}{$1} 180 || $variable_visible{ALL}{$1} ); 181 } 182 } 183 } 184 185 close($F); 186 187 # filter out things that start with _. Probably internal libc stuff. 188 my @external_calls = grep { !/^_/ } sort keys %external_calls; 189 my @internal_calls = grep { !/^_/ } sort keys %internal_calls; 190 my @non_ansi_external_calls = grep { !exists( $ansi_c89_symbol{$_} ) } @external_calls; 191 192 printf( 193 "Found %d functions which are defined and called within the %d supplied source files.\n", 194 scalar(@internal_calls), scalar(@files) ); 195 printf( "Found %d external functions which were called.\n", scalar(@external_calls) ); 196 printf( "Of these, %d are not defined by ANSI C89:\n", scalar(@non_ansi_external_calls) ); 197 198 foreach (@non_ansi_external_calls) { 199 print " $_:\n"; 200 foreach ( sort keys %{ $external_calls{$_} } ) { 201 print " $_\n"; 202 } 203 } 204 205 print "\nThe following non-ansi system includes are used:\n"; 206 foreach my $include ( sort keys %system_include ) { 207 if ( !exists( $ansi_c89_header{$include} ) ) { 208 print " $include, included by:\n"; 209 foreach my $file ( sort keys %{ $system_include{$include} } ) { 210 print " $file\n"; 211 } 212 } 213 } 214} 215 216sub do_object { 217 foreach my $obj (@files) { 218 open( my $F, '-|', "nm -a $obj" ) || die "Can't run nm -a $obj\n"; 219 220 while (<$F>) { 221 chomp; 222 223 my ( $type, $symbol ) = /^.+ (\S) (.*)/; 224 225 if ( $type eq 'U' ) { 226 $defined_in{$symbol} ||= undef; 227 push @{ $referenced_in{$symbol} }, $obj; 228 } 229 else { 230 $defined_in{$symbol} .= "$obj "; 231 } 232 } 233 234 close($F); 235 } 236 237 # omit symbols which begin with _. These are likely to be internal 238 # variables used by libc macros. 239 my @symbols = grep { !/^_/ } sort keys %defined_in; 240 241 my @external_symbols = sort grep { !defined( $defined_in{$_} ) } @symbols; 242 my @internal_symbols = sort grep { defined( $defined_in{$_} ) } @symbols; 243 my @non_ansi_external_symbols = grep { !exists( $ansi_c89_symbol{$_} ) } @external_symbols; 244 245 printf( 246 "Found %d symbols defined within the %d supplied object files.\n", 247 scalar(@internal_symbols), 248 scalar(@files) 249 ); 250 printf( "Found %d external symbols\n", scalar(@external_symbols) ); 251 printf( "Of these, %d are not defined by ANSI C89:\n", scalar(@non_ansi_external_symbols) ); 252 253 print " $_ (in " . ( join ',', @{ $referenced_in{$_} } ) . ")\n" 254 foreach (@non_ansi_external_symbols); 255} 256 257__END__ 258# The following symbols are available in a C89 Hosted Implementation 259# (not sure if I got this right- it came from a C99 reference, so some 99isms 260# might have slipped in) 261abort stdlib.h 262abs stdlib.h 263acos math.h 264acosf math.h 265acosh math.h 266acoshf math.h 267acoshl math.h 268acosl math.h 269arg complex.h 270asctime time.h 271asin math.h 272asinf math.h 273asinh math.h 274asinhf math.h 275asinhl math.h 276asinl math.h 277atan math.h 278atan2 math.h 279atan2f math.h 280atan2l math.h 281atanf math.h 282atanh math.h 283atanhf math.h 284atanhl math.h 285atanl math.h 286atexit stdlib.h 287atof stdlib.h 288atoi stdlib.h 289atol stdlib.h 290atoll stdlib.h 291bsearch stdlib.h 292cabs complex.h 293cabsf complex.h 294cabsl complex.h 295cacos complex.h 296cacosf complex.h 297cacosh complex.h 298cacoshf complex.h 299cacoshl complex.h 300cacosl complex.h 301calloc stdlib.h 302carg complex.h 303cargf complex.h 304cargl complex.h 305casin complex.h 306casinf complex.h 307casinh complex.h 308casinhf complex.h 309casinhl complex.h 310casinl complex.h 311catan complex.h 312catanf complex.h 313catanh complex.h 314catanhf complex.h 315catanhl complex.h 316catanl complex.h 317cbrt math.h 318cbrtf math.h 319cbrtl math.h 320ccos complex.h 321ccosf complex.h 322ccosh complex.h 323ccoshf complex.h 324ccoshl complex.h 325ccosl complex.h 326ceil math.h 327ceilf math.h 328ceill math.h 329cexp complex.h 330cexpf complex.h 331cexpl complex.h 332cimag complex.h 333cimagf complex.h 334cimagl complex.h 335clearerr stdio.h 336clock time.h 337clog complex.h 338clogf complex.h 339clogl complex.h 340conj complex.h 341conjf complex.h 342conjl complex.h 343copysign math.h 344copysignf math.h 345copysignl math.h 346cos math.h 347cosf math.h 348cosh math.h 349coshf math.h 350coshl math.h 351cosl math.h 352cpow complex.h 353cpowf complex.h 354cpowl complex.h 355cproj complex.h 356cprojf complex.h 357cprojl complex.h 358creal complex.h 359crealf complex.h 360creall complex.h 361csin complex.h 362csinf complex.h 363csinh complex.h 364csinhf complex.h 365csinhl complex.h 366csinl complex.h 367csqrt complex.h 368csqrtf complex.h 369csqrtl complex.h 370ctan complex.h 371ctanf complex.h 372ctanh complex.h 373ctanhf complex.h 374ctanhl complex.h 375ctanl complex.h 376ctime time.h 377difftime time.h 378div stdlib.h 379erf math.h 380erfc math.h 381erfcf math.h 382erfcl math.h 383erff math.h 384erfl math.h 385errno errno.h 386exit stdlib.h 387exp math.h 388exp2 math.h 389exp2f math.h 390exp2l math.h 391expf math.h 392expl math.h 393expm1 math.h 394expm1f math.h 395expm1l math.h 396fabs math.h 397fabsf math.h 398fabsl math.h 399fclose stdio.h 400fdim math.h 401fdimf math.h 402fdiml math.h 403feof stdio.h 404ferror stdio.h 405fflush stdio.h 406fgetc stdio.h 407fgetpos stdio.h 408fgets stdio.h 409floor math.h 410floorf math.h 411floorl math.h 412fma math.h 413fmaf math.h 414fmal math.h 415fmax math.h 416fmaxf math.h 417fmaxl math.h 418fmin math.h 419fminf math.h 420fminl math.h 421fmod math.h 422fmodf math.h 423fmodl math.h 424fopen stdio.h 425fpclassify math.h 426fprintf stdio.h 427fputc stdio.h 428fputs stdio.h 429fread stdio.h 430free stdlib.h 431freopen stdio.h 432frexp math.h 433frexpf math.h 434frexpl math.h 435fscanf stdio.h 436fseek stdio.h 437fsetpos stdio.h 438ftell stdio.h 439fwrite stdio.h 440getc stdio.h 441getchar stdio.h 442getenv stdlib.h 443gets stdio.h 444gmtime time.h 445hypot math.h 446hypotf math.h 447hypotl math.h 448ilogb math.h 449ilogbf math.h 450ilogbl math.h 451imag complex.h 452isalnum ctype.h 453isalpha ctype.h 454isblank ctype.h 455iscntrl ctype.h 456isdigit ctype.h 457isfinite math.h 458isgraph ctype.h 459isgreater math.h 460isgreatereq math.h 461isinf math.h 462isless math.h 463islessequal math.h 464islessgreat math.h 465islower ctype.h 466isnan math.h 467isnormal math.h 468isprint ctype.h 469ispunct ctype.h 470isspace ctype.h 471isunordered math.h 472isupper ctype.h 473isxdigit ctype.h 474labs stdlib.h 475ldexp math.h 476ldexpf math.h 477ldexpl math.h 478ldiv stdlib.h 479lgamma math.h 480lgammaf math.h 481lgammal math.h 482llabs stdlib.h 483llrint math.h 484llrintf math.h 485llrintl math.h 486llround math.h 487llroundf math.h 488llroundl math.h 489localeconv locale.h 490localtime time.h 491log math.h 492log10 math.h 493log10f math.h 494log10l math.h 495log1p math.h 496log1pf math.h 497log1pl math.h 498log2 math.h 499log2f math.h 500log2l math.h 501logb math.h 502logbf math.h 503logbl math.h 504logf math.h 505logl math.h 506longjmp setjmp.h 507lrint math.h 508lrintf math.h 509lrintl math.h 510lround math.h 511lroundf math.h 512lroundl math.h 513malloc stdlib.h 514mblen stdlib.h 515mbstowcs stdlib.h 516mbtowc stdlib.h 517memchr string.h 518memcmp string.h 519memcpy string.h 520memmove string.h 521memset string.h 522mktime time.h 523modf math.h 524modff math.h 525modfl math.h 526nan math.h 527nanf math.h 528nanl math.h 529nearbyint math.h 530nearbyintf math.h 531nearbyintl math.h 532nextafter math.h 533nextafterf math.h 534nextafterl math.h 535nexttoward math.h 536nexttowardf math.h 537nexttowardl math.h 538perror stdio.h 539pow math.h 540printf stdio.h 541putc stdio.h 542putchar stdio.h 543puts stdio.h 544qsort stdlib.h 545raise signal.h 546rand stdlib.h 547real complex.h 548realloc stdlib.h 549remainder math.h 550remainderf math.h 551remainderl math.h 552remove stdio.h 553remquo math.h 554remquof math.h 555remquol math.h 556rename stdio.h 557rewind stdio.h 558rint math.h 559rintf math.h 560rintl math.h 561round math.h 562roundf math.h 563roundl math.h 564scalbln math.h 565scalblnf math.h 566scalblnl math.h 567scalbn math.h 568scalbnf math.h 569scalbnl math.h 570scanf stdio.h 571setbuf stdio.h 572setlocale locale.h 573setvbuf stdio.h 574signal signal.h 575signbit math.h 576sin math.h 577sinf math.h 578sinh math.h 579sinhf math.h 580sinhl math.h 581sinl math.h 582sprintf stdio.h 583sqrt math.h 584sqrtf math.h 585sqrtl math.h 586srand stdlib.h 587sscanf stdio.h 588stderr stdio.h 589stdin stdio.h 590stdout stdio.h 591strcat string.h 592strchr string.h 593strcmp string.h 594strcoll string.h 595strcpy string.h 596strcspn string.h 597strerror string.h 598strftime time.h 599strlen string.h 600strncat string.h 601strncmp string.h 602strncpy string.h 603strpbrk string.h 604strrchr string.h 605strspn string.h 606strstr string.h 607strtod stdlib.h 608strtof stdlib.h 609strtok string.h 610strtol stdlib.h 611strtold stdlib.h 612strtoll stdlib.h 613strtoul stdlib.h 614strtoull stdlib.h 615strxfrm string.h 616system stdlib.h 617tan math.h 618tanf math.h 619tanh math.h 620tanhf math.h 621tanhl math.h 622tanl math.h 623tgamma math.h 624tgammaf math.h 625tgammal math.h 626time time.h 627tmpfile stdio.h 628tmpnam stdio.h 629tolower ctype.h 630toupper ctype.h 631trunc math.h 632truncf math.h 633truncl math.h 634ungetc stdio.h 635vfprintf stdio.h 636vfscanf stdio.h 637vprintf stdio.h 638vscanf stdio.h 639vsprintf stdio.h 640vsscanf stdio.h 641UNDEF assert.h 642UNDEF stdarg.h 643 644# Local Variables: 645# mode: cperl 646# cperl-indent-level: 4 647# fill-column: 100 648# End: 649# vim: expandtab shiftwidth=4: 650