nmcheck
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:9k
源码类别:

OpenGL

开发平台:

Visual C++

  1. #!/usr/bin/perl -w
  2. # Check namespace cleanness of a library.
  3. # Allowed symbols are passed as arguments.
  4. # They may have trailing * = wildcard.
  5. # Wildcards may be also specified as *::* (e.g. K*::* for all KDE classes)
  6. # Symbols are listed as full function unmangled names without arguments,
  7. # e.g. 'foo bar* nspace::*' allows foo(), foo(int), bar(), barbar()
  8. # and all symbols in namespace/class nspace.
  9. # If an argument has comma in it, it's a filename of a file containing
  10. # allowed symbols, one per line.
  11. $thisProg   = "$0";     # This programs name
  12. $library = "";
  13. $allowed_symbols = "";
  14. $debug = 0;
  15. $allowed_weak = "";
  16. $weak_specified = 0;
  17. while( defined( $ARGV[ 0 ] ))
  18. {
  19.     $_ = shift;
  20.     if( /^--verbose$|^-v$/ )
  21.     {
  22. $debug = 1;
  23.     }
  24.     elsif( /^--help$|^-h$/ )
  25.     {
  26.         print STDOUT "Usage $thisProg [OPTION] ... library [allowed symbols] ...n",
  27.                 "n",
  28. "Check if the given library has only allowed public symbols.n",
  29.                 "n",
  30. "  --allowweak=[symbol] allow only these weak symbolsn",
  31.                 "  -v, --verbose        verbosely list files processedn",
  32.                 "  -h, --help           print this help, then exitn";
  33.         exit 0;
  34.     }
  35.     elsif( /^--allowweak=(.*)$/ )
  36.     {
  37. $allowed_weak .= " " . $1;
  38. $weak_specified = 1;
  39.     }
  40.     elsif( /^--allowweak$/ ) # simply list all weak
  41.     {
  42. $allowed_weak .= " ";
  43. $weak_specified = 1;
  44.     }
  45.     elsif( /^--*/ )
  46.     {
  47. die "Invalid argument!n";
  48.     }
  49.     else
  50.     {
  51. if( ! $library )
  52. {
  53.     $library = $_;
  54. }
  55. else
  56. {
  57.     $allowed_symbols .= " " . $_;
  58. }
  59.     }
  60. }
  61. if( ! $weak_specified )
  62. {
  63.     $allowed_weak = "*"; 
  64.     # allow all weak symbols by default
  65.     # instances of templates and similar stuff - unfortunately includes also things from other libraries,
  66.     # so it cannot be on by default
  67. }
  68. print STDERR "library:" . $library . "n" if $debug;
  69. print STDERR "allowed_symbols:" . $allowed_symbols . "n" if $debug;
  70. print STDERR "allowed_weak:" . $allowed_weak . "n" if $debug;
  71. $default_symbols = "_fini _init";  # system symbols
  72. # on my system, every .so has :
  73. # A _DYNAMIC
  74. # A _GLOBAL_OFFSET_TABLE_
  75. # A __bss_start
  76. # A _edata
  77. # A _end
  78. # T _fini
  79. # T _init
  80. # no need to list A symbols in $default_symbols
  81. print STDERR "default_symbols: " . $default_symbols . "n" if $debug;
  82. print STDOUT "Namespace cleanness check for " . $library . " :n";
  83. $lib_file = "";
  84. if( $library =~ /.la$/ )
  85. {
  86.     # get the real library file from .la
  87.     open( FILEIN, $library ) || die "Couldn't open $! !n";
  88.     while( $line = <FILEIN> )
  89.     {
  90. if( $line =~ /library_names='([^ ]*).*/o )
  91. {
  92.     $lib_file = $1;
  93. }
  94.     }
  95.     close( FILEIN );
  96.     if( ! $lib_file )
  97.     {
  98. print STDERR "Library file not found in .la file!n";
  99. exit 1;
  100.     }
  101.     my $libpath = $library;
  102.     $libpath =~ s%[^/]*$%%;
  103.     if(  -e $libpath . ".libs/" . $lib_file )
  104.     {
  105. $lib_file = $libpath . ".libs/" . $lib_file;
  106.     }
  107.     else
  108.     {
  109. $lib_file = $libpath . $lib_file;
  110.     }
  111. }
  112. else
  113. {
  114.     $lib_file = $library;
  115. }
  116. print STDERR "libfile: ". $lib_file . "n" if $debug;
  117. $allowed_symbols .= " " . $default_symbols;
  118. sub process_symbols($@%@);
  119. @wildcards = ();
  120. %exacts = ();
  121. @regwildcards = ();
  122. process_symbols( $allowed_symbols, @wildcards, %exacts, @regwildcards );
  123. @weak_wildcards = ();
  124. %weak_exacts = ();
  125. @weak_regwildcards = ();
  126. process_symbols( $allowed_weak, @weak_wildcards, %weak_exacts, @weak_regwildcards );
  127. # grep is for stripping not exported symbols, which don't have address (=first column)
  128. $nm_command = "nm -BDCg " . $lib_file . " | grep -v '^ ' |";
  129. # TODO how portable is this nmcheck stuff?
  130. print STDERR "nm command:" . $nm_command . "n" if $debug;
  131. open( FILEIN, $nm_command ) || die "nm command failedn";
  132. my $exit_code = 0;
  133. while( $line = <FILEIN> )
  134. {
  135.     my $type;
  136.     my $symbol;
  137.     if( $line =~ /^[^ ]* (.) (.*)$/o )
  138.     {
  139. $type = $1;
  140. $symbol = $2;
  141.     }
  142.     else
  143.     {
  144. die "Invalid line: " . $line . "n";
  145.     }
  146.     
  147.     print STDERR "Type: " . $type . " , symbol: " . $symbol . "n" if $debug;
  148.     if( $type eq "A" )
  149.     { # these should be system symbols, so ignore them
  150. next;
  151.     }
  152.     my $orig_symbol = $symbol;
  153.     if( $symbol =~ /(anonymous namespace)/o )
  154.     { # TODO tell to prefer named namespaces? (shorter symbols)
  155. next;
  156.     }
  157.     # strip prefixes
  158.     # the :: appending is to make "CLASS::*" work also for "vtable for CLASS"
  159.     $symbol =~ s/^typeinfo for (.*)$/$1::/o;
  160.     $symbol =~ s/^typeinfo fn for (.*)$/$1::/o;
  161.     $symbol =~ s/^typeinfo name for (.*)$/$1::/o;
  162.     $symbol =~ s/^vtable for (.*)$/$1::/o;
  163.     $symbol =~ s/^guard variable for (.*)$/$1::/o;
  164.     $symbol =~ s/^reference temporary for (.*)$/$1::/o;
  165.     $symbol =~ s/^VTT for (.*)$/$1::/o;
  166.     $symbol =~ s/^virtual thunk [[^]]*] to (.*)$/$1::/o;
  167.     $symbol =~ s/^non-virtual thunk [[^]]*] to (.*)$/$1::/o;
  168.     $symbol =~ s/^covariant return thunk [[^]]*] to (.*)$/$1::/o;
  169.     $symbol =~ s/^construction vtable thunk for (.*)$/$1::/o;
  170.     $symbol =~ s/^construction vtable for .*-in-(.*) [0-9]*$/$1::/o;
  171.     # templates seem to have also return types mangled in their name, and nm prints it too
  172.     # they have also template arguments in the symbol
  173.     # get rid of both of those
  174.     while( $symbol =~ /<.*>/o )
  175.     {
  176.         $symbol =~ s/<[^<>]*>//o; # strip innermost <>
  177.     }
  178.     if( $symbol !~ /operator()/o )
  179.     {
  180. $symbol =~ s/ ?(.*).*$//o;  # strip () and all after it
  181.     }
  182.     else
  183.     {
  184. $symbol =~ s/(^|:| )operator() ?(.*).*$//o;  # strip () and all after it
  185.     }
  186.     $symbol =~ s/[.*] *$//o;   # strip [in-charge] etc.
  187.     if( $symbol =~ /(^|:| )operator /o )
  188.     {
  189. $symbol =~ s/.* ([^s]*)operator /$1/o; # strip everything before 'X::operator blah'
  190.     }
  191.     else
  192.     {
  193. $symbol =~ s/.* ([^s]+) *$/$1/o;  # get last word (strip return type)
  194.     }
  195.     # print STDERR "Processed symbol: " . $symbol . "n" if $debug;
  196.     
  197.     my $found = 0;
  198.     if( $exacts{ $symbol } )
  199.     {
  200. $found = 1;
  201.     }
  202.     if( ! $found )
  203.     {
  204. for my $wild ( @wildcards )
  205. {
  206.     if( index( $symbol, $wild ) == 0 )
  207.     {
  208. $found = 1;
  209. last;
  210.     }
  211. }
  212.     }
  213.     if( ! $found )
  214.     {
  215. for my $wild ( @regwildcards )
  216. {
  217.     if( $symbol =~ /^$wild$/ )
  218.     {
  219. $found = 1;
  220. last;
  221.     }
  222. }
  223.     }
  224.     if( ( ! $found ) && ( $type eq "W" || $type eq "V" ))
  225.     {
  226. if( $weak_exacts{ $symbol } )
  227. {
  228.     $found = 1;
  229. }
  230. if( ! $found )
  231. {
  232.     for my $wild ( @weak_wildcards )
  233.     {
  234.         if( index( $symbol, $wild ) == 0 )
  235.         {
  236.          $found = 1;
  237.     last;
  238. }
  239.     }
  240. }
  241. if( ! $found )
  242. {
  243.     for my $wild ( @weak_regwildcards )
  244.     {
  245.         if( $symbol =~ /^$wild$/ )
  246.         {
  247.     $found = 1;
  248.     last;
  249.         }
  250.     }
  251. }
  252.     }
  253.     if( ! $found )
  254.     {
  255. print STDERR "Public symbol " . $orig_symbol . " is not allowed!n";
  256. $exit_code = 1;
  257.     }
  258. }
  259. close( FILEIN );
  260. print STDOUT $exit_code == 0 ? "OKn" : "FAILEDn";
  261. exit $exit_code;
  262. sub process_symbols($@%@)
  263. {
  264.     my $allowed_symbols = $_[ 0 ];
  265.     my $wildcards_ref = $_[ 1 ];
  266.     my $exacts_ref = $_[ 2 ];
  267.     my $regwildcards_ref = $_[ 3 ];
  268.     
  269.     $allowed_symbols =~ s/^ *//o;  # strip whitespace
  270.     $allowed_symbols =~ s/ *$//o;
  271.     if( $allowed_symbols eq "NONE" )
  272.     {
  273. $allowed_symbols = "";
  274.     }
  275.     my @symbols1 = split( ' ', $allowed_symbols );
  276.     my $i = 0;
  277.     my @symbols2 = ();
  278.     while( defined( $symbols1[ $i ] ))
  279.     {
  280. my $symbol = $symbols1[ $i ];
  281. if( $symbol =~ /./ )  # dot in name -> file
  282. {
  283.     open( SYMIN, $symbol ) || die ( "Cannot open file " . $symbol . "!" );
  284.     while( $line = <SYMIN> )
  285.     {
  286. $line =~ s/^s*//o;  # strip whitespace
  287. $line =~ s/s*$//o;
  288. if( $line !~ /^$/o  # empty line
  289.     &&  $line !~ /^s*#/ ) # comment line starting with #
  290. {
  291.     $symbols2[ $#symbols2 + 1 ] = $line;
  292. }
  293.     }
  294.     close( SYMIN );
  295. }
  296. else
  297. {
  298.     $symbols2[ $#symbols2 + 1 ] = $symbol;
  299. }
  300. $i++;
  301.     }
  302.     $i = 0;
  303.     while( defined( $symbols2[ $i ] ))
  304.     {
  305. my $symbol = $symbols2[ $i ];
  306. if( $symbol =~ /__/
  307.     || $symbol =~ /^_[A-Z]/ )
  308. { # ISO C++ 2.10.2
  309.     die "Symbols containing a double underscore or beginning with an underscore and an upper-case letter are reserved!n";
  310. }
  311. elsif( $symbol eq "main"
  312.     || $symbol eq "main*" )
  313. {
  314.     die "Symbol main is not allowed!n";
  315. }
  316. if( $symbol =~ /^([^*]*)*$/o   # trailing * without any * before it
  317.     && $symbol !~ /operator*$/o )
  318.         {
  319.     print STDERR "wildcard:" . $symbol . "n" if $debug;
  320.          $wildcards_ref->[ $#{$wildcards_ref} + 1 ] = $1;
  321. }
  322. elsif( $symbol =~ /*$/o
  323.     && ( $symbol =~ /*::/o || $symbol =~ /::*/o )
  324.     && $symbol !~ /^*/o
  325.     && $symbol !~ /operator*$/o )
  326. {
  327.     print STDERR "regwildcard:" . $symbol . "n" if $debug;
  328.     $symbol =~ s/*/.*/go;  # change * to .* (regexp)
  329.     $regwildcards_ref->[ $#{$regwildcards_ref} + 1 ] = $symbol;
  330. }
  331. else
  332. {
  333.     print STDERR "exact:" . $symbol . "n" if $debug;
  334.     $exacts_ref->{ $symbol } = 1;
  335. }
  336. $i++;
  337.     }
  338. }