1808
1971
foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1810
$Path = clean_path($Path);
1811
1973
if(not -d $Path) {
1812
1974
exitStatus("Access_Error", "can't access directory \'$Path\'");
1976
$Path = get_abs_path($Path);
1814
1977
$Path = path_format($Path, $OSgroup);
1815
$SystemPaths{"include"}{$Path}=1;
1978
push_U($SystemPaths{"include"}, $Path);
1817
1980
foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1819
$Path = clean_path($Path);
1820
1982
if(not -d $Path) {
1821
1983
exitStatus("Access_Error", "can't access directory \'$Path\'");
1985
$Path = get_abs_path($Path);
1823
1986
$Path = path_format($Path, $OSgroup);
1824
$SystemPaths{"lib"}{$Path}=1;
1987
push_U($SystemPaths{"lib"}, $Path);
1826
1989
foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1828
$Path=clean_path($Path);
1829
1991
if(not -d $Path) {
1830
1992
exitStatus("Access_Error", "can't access directory \'$Path\'");
1994
$Path = get_abs_path($Path);
1832
1995
$Path = path_format($Path, $OSgroup);
1833
$SystemPaths{"bin"}{$Path}=1;
1996
push_U($SystemPaths{"bin"}, $Path);
1834
1997
$TargetTools{$Path}=1;
1836
1999
if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1837
2000
$CrossPrefix = $Prefix;
2002
$Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
1839
2003
foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1841
$Path=clean_path($Path);
1842
2005
if(not -d $Path) {
1843
2006
exitStatus("Access_Error", "can't access directory \'$Path\'");
2008
$Path = get_abs_path($Path);
1845
2009
$Path = path_format($Path, $OSgroup);
1846
$Descriptor{$LibVersion}{"IncludePaths"}{$Path} = 1;
2010
push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
2012
$Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
1848
2013
foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1850
$Path=clean_path($Path);
1851
2015
if(not -d $Path) {
1852
2016
exitStatus("Access_Error", "can't access directory \'$Path\'");
2018
$Path = get_abs_path($Path);
1854
2019
$Path = path_format($Path, $OSgroup);
1855
$Descriptor{$LibVersion}{"AddIncludePaths"}{$Path} = 1;
2020
push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
1857
2022
foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
1859
# skip some auto-generated include paths
1860
$Skip_Include_Paths{$LibVersion}{path_format($Path)}=1;
2023
{ # skip some auto-generated include paths
2024
if(not is_abs($Path))
2026
if(my $P = abs_path($Path)) {
2030
$Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
1862
2032
foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
1864
# skip direct including of some headers
1865
$SkipHeadersList{$LibVersion}{$Path} = 2;
2033
{ # skip direct including of some headers
1866
2034
my ($CPath, $Type) = classifyPath($Path);
1867
2035
$SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
1869
2037
$Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
1870
foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"})) {
1871
$CompilerOptions{$LibVersion} .= " ".$Option;
2038
foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
2040
if($Option!~/\A\-(Wl|l|L)/)
2041
{ # skip linker options
2042
$CompilerOptions{$LibVersion} .= " ".$Option;
1873
2045
$Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1874
2046
foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
6980
7632
return $GccCall;
7635
sub detectPreamble($$)
6986
exitStatus("Error", "internal error - GCC path is not set");
7637
my ($Content, $LibVersion) = @_;
6988
7638
my %HeaderElems = (
6990
7640
"stdio.h" => ["FILE", "va_list"],
6991
7641
"stddef.h" => ["NULL", "ptrdiff_t"],
6992
"stdint.h" => ["uint32_t", "int32_t", "uint64_t"],
7642
"stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
7643
"int8_t", "int16_t", "int32_t", "int64_t"],
6993
7644
"time.h" => ["time_t"],
6994
7645
"sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
6995
"u_int", "off_t", "u_quad_t", "u_long", "size_t", "mode_t"],
6996
"unistd.h" => ["gid_t", "uid_t"],
7646
"u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
7647
"unistd.h" => ["gid_t", "uid_t", "socklen_t"],
6997
7648
"stdbool.h" => ["_Bool"],
6998
7649
"rpc/xdr.h" => ["bool_t"],
6999
7650
"in_systm.h" => ["n_long", "n_short"],
7001
7652
"arpa/inet.h" => ["fw_src", "ip_src"],
7003
"stdlib.h" => ["free", "malloc"],
7654
"stdlib.h" => ["free", "malloc", "size_t"],
7004
7655
"string.h" => ["memmove", "strcmp"]
7006
7657
my %AutoPreamble = ();
7007
7658
foreach (keys(%HeaderElems))
7009
7660
foreach my $Elem (@{$HeaderElems{$_}}) {
7010
$AutoPreamble{$Elem}=$_;
7013
my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
7014
my $MHeaderPath = $TmpHeaderPath;
7015
open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
7016
if(my $AddDefines = $Descriptor{$Version}{"Defines"})
7018
$AddDefines=~s/\n\s+/\n /g;
7019
print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
7021
print TMP_HEADER "\n // add includes\n";
7022
my @PreambleHeaders = keys(%{$Include_Preamble{$Version}});
7023
@PreambleHeaders = sort {int($Include_Preamble{$Version}{$a}{"Position"})<=>int($Include_Preamble{$Version}{$b}{"Position"})} @PreambleHeaders;
7024
foreach my $Header_Path (@PreambleHeaders) {
7025
print TMP_HEADER " #include \"".path_format($Header_Path, "unix")."\"\n";
7027
my @Headers = keys(%{$Registered_Headers{$Version}});
7028
@Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
7029
foreach my $Header_Path (@Headers)
7031
next if($Include_Preamble{$Version}{$Header_Path});
7032
print TMP_HEADER " #include \"".path_format($Header_Path, "unix")."\"\n";
7035
my $IncludeString = getIncString(getIncPaths(@PreambleHeaders, @Headers), "GCC");
7038
writeFile($DEBUG_PATH{$Version}."/headers/direct-includes.txt", Dumper($Header_Includes{$Version}));
7039
writeFile($DEBUG_PATH{$Version}."/headers/recursive-includes.txt", Dumper($RecursiveIncludes{$Version}));
7040
writeFile($DEBUG_PATH{$Version}."/headers/include-paths.txt", Dumper($Cache{"get_HeaderDeps"}{$Version}));
7041
writeFile($DEBUG_PATH{$Version}."/headers/default-paths.txt", Dumper(\%DefaultIncPaths));
7045
addTargetHeaders($Version);
7048
%RecursiveIncludes = ();
7049
%Header_Include_Prefix = ();
7050
%Header_Includes = ();
7053
delete($Cache{"identifyHeader"});
7054
delete($Cache{"detect_header_includes"});
7055
delete($Cache{"selectSystemHeader"});
7057
# preprocessing stage
7058
checkPreprocessedUnit(callPreprocessor($TmpHeaderPath, $IncludeString, $Version));
7061
delete($Include_Neighbors{$Version});
7064
my $PreprocessCmd = getCompileCmd($TmpHeaderPath, "-E", $IncludeString);
7661
$AutoPreamble{$Elem} = $_;
7665
while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
7666
{ # error: 'FILE' has not been declared
7671
my %AddHeaders = ();
7672
foreach my $Type (keys(%Types))
7674
if(my $Header = $AutoPreamble{$Type})
7676
if(my $Path = identifyHeader($Header, $LibVersion))
7678
if(skipHeader($Path, $LibVersion)) {
7681
$Path = path_format($Path, $OSgroup);
7682
$AddHeaders{$Path}{"Type"} = $Type;
7683
$AddHeaders{$Path}{"Header"} = $Header;
7687
if(keys(%AddHeaders)) {
7688
return \%AddHeaders;
7702
if($OSgroup eq "bsd")
7703
{ # use ectags on BSD
7704
$CTags = get_CmdPath("ectags");
7706
printMsg("WARNING", "can't find \'ectags\' program");
7710
$CTags = get_CmdPath("ctags");
7714
printMsg("WARNING", "can't find \'ctags\' program");
7718
if($OSgroup ne "linux")
7719
{ # macos, freebsd, etc.
7720
my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
7721
if($Info!~/exuberant/i)
7723
printMsg("WARNING", "incompatible version of \'ctags\' program");
7728
my $Out = $TMP_DIR."/ctags.txt";
7729
system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
7731
copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
7733
open(CTAGS, "<", $Out);
7734
while(my $Line = <CTAGS>)
7737
my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
7738
if(defined $Intrinsic_Keywords{$Name})
7744
if(index($Scpe, "class:")==0) {
7747
if(index($Scpe, "struct:")==0) {
7750
if(index($Scpe, "namespace:")==0)
7752
if($Scpe=~s/\Anamespace://) {
7753
$Name = $Scpe."::".$Name;
7756
$TUnit_NameSpaces{$Version}{$Name} = 1;
7760
if(not $Scpe or index($Scpe, "namespace:")==0) {
7761
$TUnit_Funcs{$Version}{$Name} = 1;
7766
if(not $Scpe or index($Scpe, "namespace:")==0) {
7767
$TUnit_Vars{$Version}{$Name} = 1;
7776
my ($HeaderPath, $IncStr) = @_;
7778
my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
7779
my $Content = undef;
7065
7781
if($OStarget eq "windows"
7066
7782
and get_dumpmachine($GCC_PATH)=~/mingw/i
7067
7783
and $MinGWMode{$Version}!=-1)
7068
7784
{ # modify headers to compile by MinGW
7070
7786
{ # preprocessing
7071
$MContent = `$PreprocessCmd 2>$TMP_DIR/null`;
7787
$Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
7073
if($MContent=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
7789
if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
7074
7790
{ # __asm { ... }
7075
7791
$MinGWMode{$Version}=1;
7077
if($MContent=~s/\s+(\/ \/.*?)\n/\n/g)
7793
if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
7078
7794
{ # comments after preprocessing
7079
7795
$MinGWMode{$Version}=1;
7081
if($MContent=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
7797
if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
7083
7799
$MinGWMode{$Version}=1;
7085
if($MinGWMode{$Version})
7802
if($MinGWMode{$Version}) {
7087
7803
printMsg("INFO", "Using MinGW compatibility mode");
7088
$MHeaderPath = $TMP_DIR."/dump$Version.i";
7091
7807
if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
7092
and $C99Mode{$Version}!=-1 and not $Cpp2003)
7808
and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
7093
7809
{ # rename C++ keywords in C code
7810
# disable this code by -cpp-compatible option
7095
7812
{ # preprocessing
7096
$MContent = `$PreprocessCmd 2>$TMP_DIR/null`;
7813
$Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
7098
7815
my $RegExp_C = join("|", keys(%CppKeywords_C));
7099
7816
my $RegExp_F = join("|", keys(%CppKeywords_F));
7100
7817
my $RegExp_O = join("|", keys(%CppKeywords_O));
7101
while($MContent=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
7819
my $Detected = undef;
7821
while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
7103
7823
# int foo(int new, int class, int (*new)(int));
7104
7824
# unsigned private: 8;
7105
7825
# DO NOT MATCH:
7106
7826
# #pragma GCC visibility push(default)
7107
$C99Mode{$Version} = 1;
7827
$CppMode{$Version} = 1;
7828
$Detected = "$1$2$3$4" if(not defined $Detected);
7109
if($MContent=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
7830
if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
7111
7832
# int delete(...);
7112
7833
# int explicit(...);
7113
7834
# DO NOT MATCH:
7114
7835
# void operator delete(...)
7115
$C99Mode{$Version} = 1;
7836
$CppMode{$Version} = 1;
7837
$Detected = "$1$2$3" if(not defined $Detected);
7117
if($MContent=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
7839
if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
7120
7842
# DO NOT MATCH:
7122
7844
# return *this;
7124
$C99Mode{$Version} = 1;
7846
$CppMode{$Version} = 1;
7847
$Detected = "$1$2$3" if(not defined $Detected);
7126
if($MContent=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
7849
if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
7128
7851
# int operator(...);
7129
7852
# DO NOT MATCH:
7130
7853
# int operator()(...);
7131
$C99Mode{$Version} = 1;
7854
$CppMode{$Version} = 1;
7855
$Detected = "$1$2$3" if(not defined $Detected);
7133
if($MContent=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
7857
if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
7135
7859
# int foo(int operator);
7136
7860
# int foo(int operator, int other);
7137
7861
# DO NOT MATCH:
7138
7862
# int operator,(...);
7139
$C99Mode{$Version} = 1;
7863
$CppMode{$Version} = 1;
7864
$Detected = "$1$2$3" if(not defined $Detected);
7141
if($MContent=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
7866
if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
7143
7868
# int foo(gboolean *bool);
7144
7869
# DO NOT MATCH:
7145
7870
# void setTabEnabled(int index, bool);
7146
$C99Mode{$Version} = 1;
7871
$CppMode{$Version} = 1;
7872
$Detected = "$1$2$3" if(not defined $Detected);
7148
if($MContent=~s/(\w)([^\w\(\,\s]\s*|\s+)(this)(\s*(\,|\)))/$1$2c99_$3$4/g)
7874
if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
7150
7876
# int foo(int* this);
7151
7877
# int bar(int this);
7878
# int baz(int throw);
7152
7879
# DO NOT MATCH:
7154
$C99Mode{$Version} = 1;
7156
if($C99Mode{$Version}==1)
7157
{ # try to change C++ "keyword" to "c99_keyword"
7158
printMsg("INFO", "Using C99 compatibility mode");
7159
$MHeaderPath = $TMP_DIR."/dump$Version.i";
7881
$CppMode{$Version} = 1;
7882
$Detected = "$1$2$3$4" if(not defined $Detected);
7884
if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
7886
# struct template {...};
7887
# extern template foo(...);
7888
$CppMode{$Version} = 1;
7889
$Detected = "$1$2" if(not defined $Detected);
7892
if($CppMode{$Version} == 1)
7896
$Detected=~s/\A\s+//g;
7897
printMsg("INFO", "Detected code: \"$Detected\"");
7901
# remove typedef enum NAME NAME;
7902
my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
7904
while($N<=$#FwdTypedefs-1)
7906
my $S = $FwdTypedefs[$N];
7907
if($S eq $FwdTypedefs[$N+1])
7909
$Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
7910
$CppMode{$Version} = 1;
7913
printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
7919
if($CppMode{$Version}==1) {
7920
printMsg("INFO", "Using C++ compatibility mode");
7162
if($C99Mode{$Version}==1
7924
if($CppMode{$Version}==1
7163
7925
or $MinGWMode{$Version}==1)
7164
{ # compile the corrected preprocessor output
7165
writeFile($MHeaderPath, $MContent);
7927
my $IPath = $TMP_DIR."/dump$Version.i";
7928
writeFile($IPath, $Content);
7938
exitStatus("Error", "internal error - GCC path is not set");
7941
my @Headers = keys(%{$Registered_Headers{$Version}});
7942
@Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
7944
my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
7946
my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
7947
my $HeaderPath = $TmpHeaderPath;
7950
open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
7951
if(my $AddDefines = $Descriptor{$Version}{"Defines"})
7953
$AddDefines=~s/\n\s+/\n /g;
7954
print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
7956
print TMP_HEADER "\n // add includes\n";
7957
foreach my $HPath (@{$Include_Preamble{$Version}}) {
7958
print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
7960
foreach my $HPath (@Headers)
7962
if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
7963
print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
7969
{ # extra information for other tools
7970
if($IncludeString) {
7971
writeFile($ExtraInfo."/include-string", $IncludeString);
7973
writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
7974
writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
7976
if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
7979
foreach my $P1 (sort @Redirects) {
7980
$REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
7982
writeFile($ExtraInfo."/include-redirect", $REDIR);
7986
if(not keys(%{$TargetHeaders{$Version}}))
7988
addTargetHeaders($Version);
7992
%RecursiveIncludes = ();
7993
%Header_Include_Prefix = ();
7994
%Header_Includes = ();
7997
delete($Cache{"identifyHeader"});
7998
delete($Cache{"detect_header_includes"});
7999
delete($Cache{"selectSystemHeader"});
8001
# preprocessing stage
8002
my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8003
checkPreprocessedUnit($Pre);
8006
{ # extra information for other tools
8007
writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8011
delete($Include_Neighbors{$Version});
8012
delete($PreprocessedHeaders{$Version});
8014
if($COMMON_LANGUAGE{$Version} eq "C++") {
8018
if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8019
{ # try to correct the preprocessor output
8020
$HeaderPath = $PrePath;
7171
8023
if($COMMON_LANGUAGE{$Version} eq "C++")
7172
8024
{ # add classes and namespaces to the dump
7173
8025
my $CHdump = "-fdump-class-hierarchy -c";
7174
if($C99Mode{$Version}==1
8026
if($CppMode{$Version}==1
7175
8027
or $MinGWMode{$Version}==1) {
7176
8028
$CHdump .= " -fpreprocessed";
7178
my $ClassHierarchyCmd = getCompileCmd($MHeaderPath, $CHdump, $IncludeString);
8030
my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
7179
8031
chdir($TMP_DIR);
7180
8032
system($ClassHierarchyCmd." >null 2>&1");
7181
8033
chdir($ORIG_DIR);
7182
8034
if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
7184
my %AddClasses = ();
7185
8036
my $Content = readFile($ClassDump);
7186
8037
foreach my $ClassInfo (split(/\n\n/, $Content))
7208
8059
$ClassVTable_Content{$Version}{$CName} = $VTable;
8062
foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8063
{ # add user-defined namespaces
8064
$TUnit_NameSpaces{$Version}{$NS} = 1;
7213
8068
mkpath($DEBUG_PATH{$Version});
7214
8069
copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
7216
8071
unlink($ClassDump);
7217
if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
7218
{ # GCC on all supported platforms does not include namespaces to the dump by default
7219
appendFile($MHeaderPath, "\n // add namespaces\n".$NS_Add);
8074
# add namespaces and classes
8075
if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8076
{ # GCC on all supported platforms does not include namespaces to the dump by default
8077
appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
8079
# some GCC versions don't include class methods to the TU dump by default
8080
my ($AddClass, $ClassNum) = ("", 0);
8081
my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
8082
foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8084
next if($C_Structure{$CName});
8085
next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
8086
next if($SkipTypes{$Version}{$CName});
8087
if(not $Force and $GCC_44
8088
and $OSgroup eq "linux")
8089
{ # optimization for linux with GCC >= 4.4
8090
# disable this code by -force option
8091
if(index($CName, "::")!=-1)
8092
{ # should be added by name space
7221
# some GCC versions don't include class methods to the TU dump by default
7222
my ($AddClass, $ClassNum) = ("", 0);
7223
foreach my $CName (sort keys(%AddClasses))
7225
next if($C_Structure{$CName});
7226
next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
7227
next if(($CName=~tr![:]!!)>2);
7228
next if($SkipTypes{$Version}{$CName});
7229
8098
if($CName=~/\A(.+)::[^:]+\Z/
7230
and $AddClasses{$1}) {
8099
and $TUnit_Classes{$Version}{$1})
8100
{ # classes inside other classes
7233
$AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
7235
appendFile($MHeaderPath, "\n // add classes\n".$AddClass);
8104
if(defined $TUnit_Funcs{$Version}{$CName})
8105
{ # the same name for a function and type
8108
if(defined $TUnit_Vars{$Version}{$CName})
8109
{ # the same name for a variable and type
8112
$AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8115
appendFile($HeaderPath, "\n // add classes\n".$AddClass);
7238
8118
writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
7239
8119
# create TU dump
7240
8120
my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
7241
if($C99Mode{$Version}==1
8121
if($CppMode{$Version}==1
7242
8122
or $MinGWMode{$Version}==1) {
7243
8123
$TUdump .= " -fpreprocessed";
7245
my $SyntaxTreeCmd = getCompileCmd($MHeaderPath, $TUdump, $IncludeString);
8125
my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
7246
8126
writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
7247
8127
chdir($TMP_DIR);
7248
system($SyntaxTreeCmd." >$TMP_DIR/tu_errors 2>&1");
8128
system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
7250
8131
{ # failed to compile, but the TU dump still can be created
7251
my $Errors = readFile($TMP_DIR."/tu_errors");
7253
{ # disable c99 mode
7254
$C99Mode{$Version}=-1;
7255
printMsg("INFO", "Disabling C99 compatibility mode");
7256
resetLogging($Version);
7257
$TMP_DIR = tempdir(CLEANUP=>1);
7260
elsif($AutoPreambleMode{$Version}!=-1
7261
and my $TErrors = $Errors)
7264
while($TErrors=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
7265
{ # error: 'FILE' has not been declared
7268
my %AddHeaders = ();
7269
foreach my $Type (keys(%Types))
7271
if(my $Header = $AutoPreamble{$Type}) {
7272
$AddHeaders{path_format($Header, $OSgroup)}=$Type;
7275
if(my @Headers = sort {$b cmp $a} keys(%AddHeaders))
7276
{ # sys/types.h should be the first
8132
if($Errors = readFile($TMP_DIR."/tu_errors"))
8133
{ # try to recompile
8134
# FIXME: handle other errors and try to recompile
8135
if($CppMode{$Version}==1
8136
and index($Errors, "c99_")!=-1)
8137
{ # disable c99 mode and try again
8138
$CppMode{$Version}=-1;
8139
printMsg("INFO", "Disabling C++ compatibility mode");
8140
resetLogging($Version);
8141
$TMP_DIR = tempdir(CLEANUP=>1);
8144
elsif($AutoPreambleMode{$Version}!=-1
8145
and my $AddHeaders = detectPreamble($Errors, $Version))
8146
{ # add auto preamble headers and try again
8147
$AutoPreambleMode{$Version}=-1;
8148
my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
7277
8149
foreach my $Num (0 .. $#Headers)
7279
my $Name = $Headers[$Num];
7280
if(my $Path = identifyHeader($Name, $Version))
7281
{ # add automatic preamble headers
7282
if(defined $Include_Preamble{$Version}{$Path})
7286
$Include_Preamble{$Version}{$Path}{"Position"} = keys(%{$Include_Preamble{$Version}});
7287
my $Type = $AddHeaders{$Name};
7288
printMsg("INFO", "Add \'$Name\' preamble header for \'$Type\'");
8151
my $Path = $Headers[$Num];
8152
if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8154
push_U($Include_Preamble{$Version}, $Path);
8155
printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
7291
$AutoPreambleMode{$Version}=-1;
7292
resetLogging($Version);
7293
$TMP_DIR = tempdir(CLEANUP=>1);
7297
elsif($MinGWMode{$Version}!=-1)
7299
$MinGWMode{$Version}=-1;
7300
resetLogging($Version);
7301
$TMP_DIR = tempdir(CLEANUP=>1);
7304
# FIXME: handle other errors and try to recompile
7305
writeLog($Version, $Errors);
8158
resetLogging($Version);
8159
$TMP_DIR = tempdir(CLEANUP=>1);
8162
elsif($Cpp0xMode{$Version}!=-1
8163
and ($Errors=~/\Q-std=c++0x\E/
8164
or $Errors=~/is not a class or namespace/))
8165
{ # c++0x: enum class
8166
if(check_gcc($GCC_PATH, "4.6"))
8168
$Cpp0xMode{$Version}=-1;
8169
printMsg("INFO", "Enabling c++0x mode");
8170
resetLogging($Version);
8171
$TMP_DIR = tempdir(CLEANUP=>1);
8172
$CompilerOptions{$Version} .= " -std=c++0x";
8176
printMsg("WARNING", "Probably c++0x construction detected");
8180
elsif($MinGWMode{$Version}==1)
8181
{ # disable MinGW mode and try again
8182
$MinGWMode{$Version}=-1;
8183
resetLogging($Version);
8184
$TMP_DIR = tempdir(CLEANUP=>1);
8187
writeLog($Version, $Errors);
8190
writeLog($Version, "$!: $?\n");
7306
8192
printMsg("ERROR", "some errors occurred when compiling headers");
7307
8193
printErrorLog($Version);
7308
8194
$COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
7309
writeLog($Version, "\n");# new line
8195
writeLog($Version, "\n"); # new line
7311
8197
chdir($ORIG_DIR);
7312
unlink($TmpHeaderPath, $MHeaderPath);
7313
return (cmd_find($TMP_DIR,"f","*.tu",1))[0];
8198
unlink($TmpHeaderPath);
8199
unlink($HeaderPath);
8201
if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8206
my $Msg = "can't compile header(s)";
8207
if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8208
$Msg .= "\nDid you install G++?";
8210
exitStatus("Cannot_Compile", $Msg);
7316
8214
sub cmd_file($)
8669
sub getAlignment($$$)
8671
my ($Pos, $TypePtr, $LibVersion) = @_;
8672
my $Tid = $TypePtr->{"Memb"}{$Pos}{"type"};
8673
my %Type = get_PureType($Tid, $LibVersion);
8674
my $TSize = $Type{"Size"}*$BYTE_SIZE;
8675
my $MSize = $Type{"Size"}*$BYTE_SIZE;
8676
if(my $BSize = $TypePtr->{"Memb"}{$Pos}{"bitfield"})
8678
($TSize, $MSize) = ($WORD_SIZE{$LibVersion}*$BYTE_SIZE, $BSize);
8680
elsif($Type{"Type"} eq "Array")
8681
{ # in the context of function parameter
8682
# it's passed through the pointer
8685
my $Alignment = $WORD_SIZE{$LibVersion}*$BYTE_SIZE; # default
8686
if(my $Computed = $TypePtr->{"Memb"}{$Pos}{"algn"})
8688
$Alignment = $Computed*$BYTE_SIZE;
8690
elsif($TypePtr->{"Memb"}{$Pos}{"bitfield"})
8691
{ # bitfields are 1 bit aligned
8694
elsif($TSize and $TSize<$WORD_SIZE{$LibVersion}*$BYTE_SIZE)
8696
$Alignment = $TSize;
8698
return ($Alignment, $MSize);
8702
{ # offset of the field including padding
8703
my ($FieldPos, $TypePtr, $LibVersion) = @_;
8705
foreach my $Pos (0 .. keys(%{$TypePtr->{"Memb"}})-1)
8707
my ($Alignment, $MSize) = getAlignment($Pos, $TypePtr, $LibVersion);
8710
if($Offset % $Alignment!=0)
8711
{ # not aligned, add padding
8712
$Padding = $Alignment - $Offset % $Alignment;
8714
$Offset += $Padding;
8716
{ # after the padding
8722
return $FieldPos;# if something is going wrong
8725
sub isMemPadded($$$$$)
8726
{ # check if the target field can be added/removed/changed
8727
# without shifting other fields because of padding bits
8728
my ($FieldPos, $Size, $TypePtr, $Skip, $LibVersion) = @_;
8729
return 0 if($FieldPos==0);
8730
if(defined $TypePtr->{"Memb"}{""})
8732
delete($TypePtr->{"Memb"}{""});
8734
printMsg("WARNING", "internal error detected");
8738
my (%Alignment, %MSize) = ();
8740
my $End = keys(%{$TypePtr->{"Memb"}})-1;
8741
my $NextField = $FieldPos+1;
8742
foreach my $Pos (0 .. $End)
8744
if($Skip and $Skip->{$Pos})
8745
{ # skip removed/added fields
8746
if($Pos > $FieldPos)
8747
{ # after the target
8752
($Alignment{$Pos}, $MSize{$Pos}) = getAlignment($Pos, $TypePtr, $LibVersion);
8753
if($Alignment{$Pos}>$MaxAlgn) {
8754
$MaxAlgn = $Alignment{$Pos};
8759
{ # added/removed fields
8761
{ # skip target field and see
8762
# if enough padding will be
8763
# created on the next step
8764
# to include this field
8771
if($Offset % $Alignment{$Pos}!=0)
8772
{ # not aligned, add padding
8773
$Padding = $Alignment{$Pos} - $Offset % $Alignment{$Pos};
8775
if($Pos==$NextField)
8776
{ # try to place target field in the padding
8778
{ # added/removed fields
8780
if($Offset % $Alignment{$FieldPos}!=0)
8781
{# padding of the target field
8782
$TPadding = $Alignment{$FieldPos} - $Offset % $Alignment{$FieldPos};
8784
if($TPadding+$MSize{$FieldPos}<=$Padding)
8785
{ # enough padding to place target field
8794
my $Delta = $Size-$MSize{$FieldPos};
8797
if($Size-$MSize{$FieldPos}<=$Padding)
8798
{ # enough padding to change target field
8807
$Delta = abs($Delta);
8808
if($Delta+$Padding>=$MSize{$Pos})
8809
{ # try to place the next field
8810
if(($Offset-$Delta) % $Alignment{$Pos} != 0)
8811
{ # padding of the next field in new place
8812
my $NPadding = $Alignment{$Pos} - ($Offset-$Delta) % $Alignment{$Pos};
8813
if($NPadding+$MSize{$Pos}<=$Delta+$Padding)
8814
{ # enough delta+padding to store next field
8828
{ # target field is the last field
8830
{ # added/removed fields
8831
if($Offset % $MaxAlgn!=0)
8833
my $TailPadding = $MaxAlgn - $Offset % $MaxAlgn;
8834
if($Padding+$MSize{$Pos}<=$TailPadding)
8835
{ # enough tail padding to place the last field
8844
my $Offset1 = $Offset+$Padding+$MSize{$Pos};
8845
if($Offset1 % $MaxAlgn != 0)
8847
$Offset1 += $MaxAlgn - $Offset1 % $MaxAlgn;
8850
my $Offset2 = $Offset+$Padding+$Size;
8851
if($Offset2 % $MaxAlgn != 0)
8853
$Offset2 += $MaxAlgn - $Offset2 % $MaxAlgn;
8855
if($Offset1!=$Offset2)
8856
{ # different sizes of structure
8862
$Offset += $Padding+$MSize{$Pos};
8867
9695
sub isReserved($)
8868
9696
{ # reserved fields == private
8869
9697
my $MName = $_[0];
8870
9698
if($MName=~/reserved|padding|f_spare/i) {
8873
if($MName=~/\A[_]*(spare|pad|unused)[_]*\Z/i) {
9701
if($MName=~/\A[_]*(spare|pad|unused)[_\d]*\Z/i) {
8876
9704
if($MName=~/(pad\d+)/i) {
9946
10869
%{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
9947
10870
"Target"=>$Typedef_1{"Name"},
9948
10871
"Type_Name"=>$Typedef_1{"Name"},
9949
"Type_Type"=>"Typedef",
9950
10872
"Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
9951
10873
"New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
9953
%{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
9954
"Target"=>$Typedef_1{"Name"},
9955
"Type_Name"=>$Typedef_1{"Name"},
9956
"Type_Type"=>"Typedef",
9957
"Old_Value"=>$Base_1{"Name"},
9958
"New_Value"=>$Base_2{"Name"} );
10875
my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
10876
my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
10877
if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
10879
if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
10881
%{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
10882
"Target"=>$Typedef_1{"Name"},
10883
"Type_Name"=>$Typedef_1{"Name"},
10884
"Old_Value"=>$Base_1{"Name"},
10885
"New_Value"=>$Base_2{"Name"} );
10889
%{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
10890
"Target"=>$Typedef_1{"Name"},
10891
"Type_Name"=>$Typedef_1{"Name"},
10892
"Old_Value"=>$Base_1{"Name"},
10893
"New_Value"=>$Base_2{"Name"} );
9961
10898
if(nonComparable(\%Type1_Pure, \%Type2_Pure))
9962
10899
{ # different types (reported in detectTypeChange(...))
9963
if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
9964
and $Type1_Pure{"Type"} ne $Type2_Pure{"Type"}
9965
and $Type1_Pure{"Type"}!~/Intrinsic|Pointer|Ref|Typedef/)
10900
my $TT1 = $Type1_Pure{"Type"};
10901
my $TT2 = $Type2_Pure{"Type"};
10904
and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
9966
10905
{ # different type of the type
9967
%{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
9968
"Target"=>$Type1_Pure{"Name"},
9969
"Type_Name"=>$Type1_Pure{"Name"},
9970
"Type_Type"=>$Type1_Pure{"Type"},
9971
"Old_Value"=>lc($Type1_Pure{"Type"}),
9972
"New_Value"=>lc($Type2_Pure{"Type"}) );
10906
my $Short1 = $Type1_Pure{"Name"};
10907
my $Short2 = $Type2_Pure{"Name"};
10909
$Short1=~s/\A\Q$TT1\E //ig;
10910
$Short2=~s/\A\Q$TT2\E //ig;
10912
if($Short1 eq $Short2)
10914
%{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
10915
"Target"=>$Type1_Pure{"Name"},
10916
"Type_Name"=>$Type1_Pure{"Name"},
10917
"Old_Value"=>lc($Type1_Pure{"Type"}),
10918
"New_Value"=>lc($Type2_Pure{"Type"}) );
9974
10921
%{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
9975
10922
return %SubProblems;
9977
pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"});
10924
pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
9978
10925
if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
9979
10926
or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
9980
10927
and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11991
13005
my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
11992
13006
my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
11993
13007
%SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
11994
13009
foreach my $SubProblemType (keys(%SubProblems))
11996
13011
my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
11997
13012
my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
11998
my $NewProblemType = $SubProblemType;
11999
if($Level eq "Binary" and $SubProblemType eq "Return_Type_Became_Void"
12000
and keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
12001
{ # parameters stack has been affected
12002
$NewProblemType = "Return_Type_Became_Void_And_Stack_Layout";
12004
elsif($Level eq "Binary"
12005
and $SubProblemType eq "Return_Type_From_Void")
12006
{ # parameters stack has been affected
12007
if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})) {
12008
$NewProblemType = "Return_Type_From_Void_And_Stack_Layout";
12012
delete($SubProblems{$SubProblemType});
12016
elsif($SubProblemType eq "Return_Type_And_Size"
12017
and $CompleteSignature{1}{$Symbol}{"Data"}) {
12018
$NewProblemType = "Global_Data_Type_And_Size";
12020
elsif($SubProblemType eq "Return_Type")
12022
if($CompleteSignature{1}{$Symbol}{"Data"})
12024
if(removedQual($Old_Value, $New_Value, "const"))
12025
{ # const -> non-const global data
12026
$NewProblemType = "Global_Data_Became_Non_Const";
12028
elsif(addedQual($Old_Value, $New_Value, "const"))
12029
{ # non-const -> const global data
12030
$NewProblemType = "Global_Data_Became_Const";
12033
$NewProblemType = "Global_Data_Type";
12038
if(addedQual($Old_Value, $New_Value, "const")) {
12039
$NewProblemType = "Return_Type_Became_Const";
12043
elsif($SubProblemType eq "Return_Type_Format")
12045
if($CompleteSignature{1}{$Symbol}{"Data"}) {
12046
$NewProblemType = "Global_Data_Type_Format";
12049
@{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
13013
my %ProblemTypes = ();
13015
if($CompleteSignature{1}{$Symbol}{"Data"})
13017
if($SubProblemType eq "Return_Type_And_Size") {
13018
$ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13020
elsif($SubProblemType eq "Return_Type_Format") {
13021
$ProblemTypes{"Global_Data_Type_Format"} = 1;
13024
$ProblemTypes{"Global_Data_Type"} = 1;
13028
if($SubProblemType eq "Return_Type"
13029
or $SubProblemType eq "Return_Type_And_Size"
13030
or $SubProblemType eq "Return_Type_Format")
13032
if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13033
{ # const to non-const
13035
$ProblemTypes{"Global_Data_Removed_Const"} = 1;
13038
$ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13040
$ProblemTypes{"Global_Data_Type"} = 1;
13042
elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13043
{ # non-const to const
13045
$ProblemTypes{"Global_Data_Added_Const"} = 1;
13048
$ProblemTypes{"Global_Data_Became_Const"} = 1;
13050
$ProblemTypes{"Global_Data_Type"} = 1;
13057
if($SubProblemType eq "Return_Type"
13058
or $SubProblemType eq "Return_Type_And_Size"
13059
or $SubProblemType eq "Return_Type_Format")
13061
if(checkDump(1, "2.6") and checkDump(2, "2.6"))
13063
if(addedQual($Old_Value, $New_Value, "volatile"))
13065
$ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13066
if($Level ne "Source"
13067
or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13068
$ProblemTypes{"Return_Type"} = 1;
13072
if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13075
$ProblemTypes{"Return_Type_Added_Const"} = 1;
13078
$ProblemTypes{"Return_Type_Became_Const"} = 1;
13080
if($Level ne "Source"
13081
or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13082
$ProblemTypes{"Return_Type"} = 1;
13087
if($Level eq "Binary"
13088
and not $CompleteSignature{1}{$Symbol}{"Data"})
13090
my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13091
if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13092
{ # if one of the architectures is unknown
13093
# then set other arhitecture to unknown too
13094
($Arch1, $Arch2) = ("unknown", "unknown");
13096
my (%Conv1, %Conv2) = ();
13097
if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
13099
%Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13100
%Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13104
%Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13105
%Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13108
if($SubProblemType eq "Return_Type_Became_Void")
13110
if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13111
{ # parameters stack has been affected
13112
if($Conv1{"Method"} eq "stack") {
13113
$ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
13115
elsif($Conv1{"Hidden"}) {
13116
$ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
13120
elsif($SubProblemType eq "Return_Type_From_Void")
13122
if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13123
{ # parameters stack has been affected
13124
if($Conv2{"Method"} eq "stack") {
13125
$ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
13127
elsif($Conv2{"Hidden"}) {
13128
$ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
13132
elsif($SubProblemType eq "Return_Type"
13133
or $SubProblemType eq "Return_Type_And_Size"
13134
or $SubProblemType eq "Return_Type_Format")
13136
if($Conv1{"Method"} ne $Conv2{"Method"})
13138
if($Conv1{"Method"} eq "stack")
13139
{ # returns in a register instead of a hidden first parameter
13140
$ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
13143
$ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
13148
if($Conv1{"Method"} eq "reg")
13150
if($Conv1{"Registers"} ne $Conv2{"Registers"})
13152
if($Conv1{"Hidden"}) {
13153
$ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
13155
elsif($Conv2{"Hidden"}) {
13156
$ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
13159
$ProblemTypes{"Return_Type_And_Register"} = 1;
13167
if(not keys(%ProblemTypes))
13169
$ProblemTypes{$SubProblemType} = 1;
13172
foreach my $ProblemType (keys(%ProblemTypes))
13174
@{$CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
12051
13177
if($ReturnType1_Id and $ReturnType2_Id)
12053
13179
@RecurTypes = ();
12054
13180
%SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
12055
foreach my $SubProblemType (keys(%SubProblems))
12056
{ # add "Global_Data_Size" problem
12057
my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
12058
my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
12059
if($SubProblemType eq "DataType_Size"
12060
and $CompleteSignature{1}{$Symbol}{"Data"}
12061
and get_PLevel($ReturnType1_Id, 1)==0)
12062
{ # add a new problem
12063
%{$SubProblems{"Global_Data_Size"}} = %{$SubProblems{$SubProblemType}};
13182
if($CompleteSignature{1}{$Symbol}{"Data"})
13184
if($Level eq "Binary")
13186
if(get_PLevel($ReturnType1_Id, 1)==0)
13188
foreach my $SubProblemType (keys(%SubProblems))
13189
{ # add "Global_Data_Size" problem
13190
my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13191
my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
13192
if($SubProblemType eq "DataType_Size")
13193
{ # add a new problem
13194
%{$SubProblems{"Global_Data_Size"}} = %{$SubProblems{$SubProblemType}};
13198
if(not defined $SubProblems{"Global_Data_Size"})
13200
if(defined $GlobalDataObject{1}{$Symbol}
13201
and defined $GlobalDataObject{2}{$Symbol})
13203
my $Old_Size = $GlobalDataObject{1}{$Symbol};
13204
my $New_Size = $GlobalDataObject{2}{$Symbol};
13205
if($Old_Size!=$New_Size)
13207
%{$SubProblems{"Global_Data_Size"}{"retval"}} = (
13208
"Old_Size"=>$Old_Size*$BYTE_SIZE,
13209
"New_Size"=>$New_Size*$BYTE_SIZE );
12066
13215
foreach my $SubProblemType (keys(%SubProblems))
12321
13575
"New_Value"=>$Value_New );
12324
if($PName1 and $PName2 and $PName1 ne $PName2
12325
and $PType1_Id!=-1 and $PType2_Id!=-1
12326
and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
12327
{ # except unnamed "..." value list (Id=-1)
12328
%{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
12330
"Param_Pos"=>$ParamPos1,
12331
"Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
12332
"Old_Value"=>$PName1,
12333
"New_Value"=>$PName2,
12334
"New_Signature"=>get_Signature($Symbol, 2) );
13581
if($PName1 and $PName2 and $PName1 ne $PName2
13582
and $PType1_Id!=-1 and $PType2_Id!=-1
13583
and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
13584
{ # except unnamed "..." value list (Id=-1)
13585
%{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
13587
"Param_Pos"=>$ParamPos1,
13588
"Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
13589
"Old_Value"=>$PName1,
13590
"New_Value"=>$PName2,
13591
"New_Signature"=>get_Signature($Symbol, 2) );
12336
13595
# checking type change (replace)
12337
13596
my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
12338
13597
foreach my $SubProblemType (keys(%SubProblems))
12339
13598
{ # add new problems, remove false alarms
12340
13599
my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
12341
13600
my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
12342
if($SubProblemType eq "Parameter_Type")
13603
if($SubProblemType eq "Parameter_Type"
13604
or $SubProblemType eq "Parameter_Type_And_Size"
13605
or $SubProblemType eq "Parameter_Type_Format")
12344
13607
if(checkDump(1, "2.6") and checkDump(2, "2.6"))
12346
if(my $RA = addedQual($Old_Value, $New_Value, "restrict"))
13609
if(addedQual($Old_Value, $New_Value, "restrict")) {
12348
13610
%{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
12349
if($Level eq "Source"
12350
and cmpBTypes($Old_Value, $New_Value, 1, 2)) {
12351
delete($SubProblems{$SubProblemType});
12354
elsif(my $RR = removedQual($Old_Value, $New_Value, "restrict"))
12356
%{$SubProblems{"Parameter_Became_NonRestrict"}} = %{$SubProblems{$SubProblemType}};
12357
if($Level eq "Source"
12358
and cmpBTypes($Old_Value, $New_Value, 1, 2)) {
12359
delete($SubProblems{$SubProblemType});
13612
elsif(removedQual($Old_Value, $New_Value, "restrict")) {
13613
%{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
13616
if(checkDump(1, "2.6") and checkDump(2, "2.6"))
13618
if(removedQual($Old_Value, $New_Value, "volatile")) {
13619
%{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
12363
13622
if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
12394
13682
$NewProblemType = "Parameter_Became_VaList";
12396
elsif($SubProblemType eq "Parameter_Type"
12397
and removedQual($Old_Value, $New_Value, "const"))
12398
{ # parameter: "const" to non-"const"
12399
$NewProblemType = "Parameter_Became_Non_Const";
12401
13684
elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
12402
or $SubProblemType eq "Parameter_Type"))
13685
or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
12404
13687
my ($Arch1, $Arch2) = (getArch(1), getArch(2));
12405
if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13688
if($Arch1 eq "unknown"
13689
or $Arch2 eq "unknown")
12406
13690
{ # if one of the architectures is unknown
12407
# then set other arhitecture to unknown too
13691
# then set other arhitecture to unknown too
12408
13692
($Arch1, $Arch2) = ("unknown", "unknown");
12410
my ($Method1, $Passed1, $SizeOnStack1, $RegName1) = callingConvention($Symbol, $ParamPos1, 1, $Arch1);
12411
my ($Method2, $Passed2, $SizeOnStack2, $RegName2) = callingConvention($Symbol, $ParamPos2, 2, $Arch2);
12412
if($Method1 eq $Method2)
12414
if($Method1 eq "stack" and $SizeOnStack1 ne $SizeOnStack2) {
12415
$NewProblemType = "Parameter_Type_And_Stack";
12417
elsif($Method1 eq "register" and $RegName1 ne $RegName2) {
12418
$NewProblemType = "Parameter_Type_And_Register";
12423
if($Method1 eq "stack") {
12424
$NewProblemType = "Parameter_Type_And_Pass_Through_Register";
12426
elsif($Method1 eq "register") {
12427
$NewProblemType = "Parameter_Type_And_Pass_Through_Stack";
12430
$SubProblems{$SubProblemType}{"Old_Reg"} = $RegName1;
12431
$SubProblems{$SubProblemType}{"New_Reg"} = $RegName2;
13694
my (%Conv1, %Conv2) = ();
13695
if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
13697
%Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
13698
%Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
13702
%Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13703
%Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13705
if($Conv1{"Method"} eq $Conv2{"Method"})
13707
if($Conv1{"Method"} eq "stack")
13709
if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
13710
$NewProblemType = "Parameter_Type_And_Stack";
13713
elsif($Conv1{"Method"} eq "reg")
13715
if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
13716
$NewProblemType = "Parameter_Type_And_Register";
13722
if($Conv1{"Method"} eq "stack") {
13723
$NewProblemType = "Parameter_Type_From_Stack_To_Register";
13725
elsif($Conv1{"Method"} eq "register") {
13726
$NewProblemType = "Parameter_Type_From_Register_To_Stack";
13729
$SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
13730
$SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
12433
13732
%{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
12434
13733
"Target"=>$PName1,
12468
sub callingConvention($$$$)
12469
{ # calling conventions for different compilers and operating systems
12470
my ($Symbol, $ParamPos, $LibVersion, $Arch) = @_;
12471
my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
12472
my %Type = get_PureType($ParamTypeId, $LibVersion);
12473
my ($Method, $Alignment, $Passed, $Register) = ("", 0, "", "");
12474
if($OSgroup=~/\A(linux|macos|freebsd)\Z/)
12477
{ # System V ABI Intel386 ("Function Calling Sequence")
12478
# The stack is word aligned. Although the architecture does not require any
12479
# alignment of the stack, software convention and the operating system
12480
# requires that the stack be aligned on a word boundary.
12482
# Argument words are pushed onto the stack in reverse order (that is, the
12483
# rightmost argument in C call syntax has the highest address), preserving the
12484
# stackās word alignment. All incoming arguments appear on the stack, residing
12485
# in the stack frame of the caller.
12487
# An argumentās size is increased, if necessary, to make it a multiple of words.
12488
# This may require tail padding, depending on the size of the argument.
12490
# Other areas depend on the compiler and the code being compiled. The stan-
12491
# dard calling sequence does not define a maximum stack frame size, nor does
12492
# it restrict how a language system uses the āāunspecifiedāā area of the stan-
12493
# dard stack frame.
12494
($Method, $Alignment) = ("stack", 4);
12496
elsif($Arch eq "x86_64")
12497
{ # System V AMD64 ABI ("Function Calling Sequence")
12498
($Method, $Alignment) = ("stack", 8);# eightbyte aligned
12500
elsif($Arch eq "arm")
12501
{ # Procedure Call Standard for the ARM Architecture
12502
# The stack must be double-word aligned
12503
($Method, $Alignment) = ("stack", 8);# double-word
12506
elsif($OSgroup eq "windows")
12507
{ # MS C++ Compiler
12511
($Method, $Register, $Passed) = ("register", "ecx", "value");
12513
elsif($ParamPos==1) {
12514
($Method, $Register, $Passed) = ("register", "edx", "value");
12517
($Method, $Alignment) = ("stack", 4);
12520
elsif($Arch eq "x86_64")
12524
if($Type{"Name"}=~/\A(float|double|long double)\Z/) {
12525
($Method, $Passed) = ("xmm".$ParamPos, "value");
12527
elsif(isScalar($Type{"Name"})
12528
or $Type{"Type"}=~/\A(Struct|Union|Enum|Array)\Z/
12529
or $Type{"Name"}=~/\A(__m64|__m128)\Z/)
12532
($Method, $Register, $Passed) = ("register", "rcx", "value");
12534
elsif($ParamPos==1) {
12535
($Method, $Register, $Passed) = ("register", "rdx", "value");
12537
elsif($ParamPos==2) {
12538
($Method, $Register, $Passed) = ("register", "r8", "value");
12540
elsif($ParamPos==3) {
12541
($Method, $Register, $Passed) = ("register", "r9", "value");
12543
if($Type{"Size"}>64
12544
or $Type{"Type"} eq "Array") {
12545
$Passed = "pointer";
12550
($Method, $Alignment) = ("stack", 8);# word alignment
12554
if($Method eq "register") {
12555
return ("register", $Passed, "", $Register);
12560
{ # default convention
12561
$Alignment = $WORD_SIZE{$LibVersion};
12564
{ # default convention
12567
my $SizeOnStack = $Type{"Size"};
12568
# FIXME: improve stack alignment
12569
if($SizeOnStack!=$Alignment) {
12570
$SizeOnStack = int(($Type{"Size"}+$Alignment)/$Alignment)*$Alignment;
12572
return ("stack", $Passed, $SizeOnStack, "");
12576
13767
sub find_ParamPair_Pos_byName($$$)
12578
13769
my ($Name, $Symbol, $LibVersion) = @_;
15568
16994
sub checkPreprocessedUnit($)
15570
16996
my $Path = $_[0];
15571
my $CurHeader = "";
16997
my ($CurHeader, $CurHeaderName) = ("", "");
16998
my $CurClass = ""; # extra info
15572
16999
open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
17001
while(my $Line = <PREPROC>)
15574
17002
{ # detecting public and private constants
15575
next if(not /\A#/);
15577
if(/#[ \t]+\d+[ \t]+\"(.+)\"/) {
15578
$CurHeader=path_format($1, $OSgroup);
15580
if(not $Include_Neighbors{$Version}{get_filename($CurHeader)}
15581
and not $Registered_Headers{$Version}{$CurHeader})
15585
my $HName = get_filename($CurHeader);
15586
if(not is_target_header($HName, 1)
15587
and not is_target_header($HName, 2))
15588
{ # user-defined header
15591
if(/\#[ \t]*define[ \t]+([_A-Z0-9]+)[ \t]+(.+)[ \t]*\Z/)
15593
my ($Name, $Value) = ($1, $2);
15594
if(not $Constants{$Version}{$Name}{"Access"})
15596
$Constants{$Version}{$Name}{"Access"} = "public";
15597
$Constants{$Version}{$Name}{"Value"} = $Value;
15598
$Constants{$Version}{$Name}{"Header"} = get_filename($CurHeader);
15601
elsif(/\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
15602
$Constants{$Version}{$1}{"Access"} = "private";
17003
if(substr($Line, 0, 1) eq "#")
17006
if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
17008
$CurHeader = path_format($1, $OSgroup);
17009
$CurHeaderName = get_filename($CurHeader);
17012
if(index($CurHeader, $TMP_DIR)==0) {
17016
if(substr($CurHeaderName, 0, 1) eq "<")
17017
{ # <built-in>, <command-line>, etc.
17018
$CurHeaderName = "";
17024
if($CurHeaderName) {
17025
$PreprocessedHeaders{$Version}{$CurHeader} = 1;
17033
if(not $Include_Neighbors{$Version}{$CurHeaderName}
17034
and not $Registered_Headers{$Version}{$CurHeader})
17038
if(not is_target_header($CurHeaderName, 1)
17039
and not is_target_header($CurHeaderName, 2))
17040
{ # user-defined header
17046
if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
17048
my ($Name, $Value) = ($1, $2);
17049
if(not $Constants{$Version}{$Name}{"Access"})
17051
$Constants{$Version}{$Name}{"Access"} = "public";
17052
$Constants{$Version}{$Name}{"Value"} = $Value;
17053
if($CurHeaderName) {
17054
$Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17058
elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17059
$Constants{$Version}{$1}{"Access"} = "private";
17064
if(defined $ExtraDump)
17066
if($Line=~/(\w+)\s*\(/)
17068
$SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17070
#elsif($Line=~/(\w+)\s*;/)
17072
# $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17074
elsif($Line=~/(\A|\s)class\s+(\w+)/) {
15605
17080
close(PREPROC);
15606
17081
foreach my $Constant (keys(%{$Constants{$Version}}))
15608
if($Constants{$Version}{$Constant}{"Access"} eq "private" or $Constant=~/_h\Z/i
15609
or isBuiltIn($Constants{$Version}{$Constant}{"Header"}))
15610
{ # skip private constants
17083
if($Constants{$Version}{$Constant}{"Access"} eq "private")
17085
delete($Constants{$Version}{$Constant});
17088
if(not $ExtraDump and ($Constant=~/_h\Z/i or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
15611
17090
delete($Constants{$Version}{$Constant});
15614
17093
delete($Constants{$Version}{$Constant}{"Access"});
17098
mkpath($DEBUG_PATH{$Version});
17099
copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
15619
17103
sub uncoverConstant($$)
15699
17283
{ # skipped by the user
15702
if(not defined $Constants{2}{$Constant}{"Value"}
15703
or $Constants{2}{$Constant}{"Value"} eq "")
17287
if(my $Header = $Constants{1}{$Constant}{"Header"})
17289
if(not is_target_header($Header, 1)
17290
and not is_target_header($Header, 2))
17291
{ # user-defined header
17299
my $Old_Value = uncoverConstant(1, $Constant);
17301
if(constantFilter($Constant, $Old_Value, $Level))
17302
{ # separate binary and source problems
17306
if(not defined $Constants{2}{$Constant}{"Value"})
17308
%{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
17309
"Target"=>$Constant,
17310
"Old_Value"=>$Old_Value );
17314
if($Constants{2}{$Constant}{"Value"} eq "")
15704
17315
{ # empty value
15707
my $Header = $Constants{1}{$Constant}{"Header"};
15708
if(not is_target_header($Header, 1)
15709
and not is_target_header($Header, 2))
15710
{ # user-defined header
15713
my ($Old_Value, $New_Value, $Old_Value_Pure, $New_Value_Pure);
15714
$Old_Value = $Old_Value_Pure = uncoverConstant(1, $Constant);
15715
$New_Value = $New_Value_Pure = uncoverConstant(2, $Constant);
17316
# TODO: implement a rule
17320
my $New_Value = uncoverConstant(2, $Constant);
17322
my $Old_Value_Pure = $Old_Value;
17323
my $New_Value_Pure = $New_Value;
15716
17325
$Old_Value_Pure=~s/(\W)\s+/$1/g;
15717
17326
$Old_Value_Pure=~s/\s+(\W)/$1/g;
15718
17327
$New_Value_Pure=~s/(\W)\s+/$1/g;
15719
17328
$New_Value_Pure=~s/\s+(\W)/$1/g;
15720
17330
next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
15721
17332
if($New_Value_Pure ne $Old_Value_Pure)
15722
17333
{ # different values
15723
if($Level eq "Binary")
15725
if(grep {$Constant=~/(\A|_)$_(_|\Z)/} keys(%IgnoreConstant))
15726
{ # ignore library version
15729
if($Constant=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
15730
{ # ignore library version
15733
if($Old_Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Old_Value=~/[\/\\]\w+[\/\\]\w+/)
15734
{ # ignoring path defines:
15735
# /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
15738
if($Old_Value=~/\A\(*[a-z_]+(\s+|\|)/i)
15739
{ # ignore source defines:
15740
# static int gcry_pth_init ( void) { return ...
15741
# (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
15744
if($Old_Value=~/\(/i and $Old_Value!~/[\"\']/i)
15745
{ # ignore source defines:
17334
if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
17338
if(computeValue($Old_Value) eq computeValue($New_Value))
15750
17342
if(convert_integer($Old_Value) eq convert_integer($New_Value))
15751
17343
{ # 0x0001 and 0x1, 0x1 and 1 equal constants
15823
17519
%SystemObjects = ();
17522
my %Prefix_Lib_Map=(
17523
# symbols for autodetecting library dependencies (by prefix)
17524
"pthread_" => ["libpthread"],
17525
"g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
17526
"cairo_" => ["libcairo"],
17527
"gtk_" => ["libgtk-x11-2.0"],
17528
"atk_" => ["libatk-1.0"],
17529
"gdk_" => ["libgdk-x11-2.0"],
17531
"glu" => ["libGLU"],
17532
"popt" => ["libpopt"],
17533
"Py" => ["libpython"],
17534
"jpeg_" => ["libjpeg"],
17535
"BZ2_" => ["libbz2"],
17536
"Fc" => ["libfontconfig"],
17537
"Xft" => ["libXft"],
17538
"SSL_" => ["libssl"],
17539
"sem_" => ["libpthread"],
17540
"snd_" => ["libasound"],
17541
"art_" => ["libart_lgpl_2"],
17542
"dbus_g" => ["libdbus-glib-1"],
17543
"GOMP_" => ["libgomp"],
17544
"omp_" => ["libgomp"],
17545
"cms" => ["liblcms"]
17548
my %Pattern_Lib_Map=(
17549
"SL[a-z]" => ["libslang"]
17552
my %Symbol_Lib_Map=(
17553
# symbols for autodetecting library dependencies (by name)
17559
"dlopen" => "libdl",
17560
"deflate" => "libz",
17561
"inflate" => "libz",
17562
"move_panel" => "libpanel",
17563
"XOpenDisplay" => "libX11",
17564
"resize_term" => "libncurses",
17565
"clock_gettime" => "librt",
17566
"crypt" => "libcrypt"
17569
sub find_SymbolLibs($$)
17571
my ($LibVersion, $Symbol) = @_;
17573
if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
17580
if(my $LibName = $Symbol_Lib_Map{$Symbol})
17582
if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17587
if(my $SymbolPrefix = getPrefix($Symbol))
17589
if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
17590
return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
17593
if(not keys(%Paths))
17595
if(defined $Prefix_Lib_Map{$SymbolPrefix})
17597
foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
17599
if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17606
if(not keys(%Paths))
17608
foreach my $Prefix (sort keys(%Pattern_Lib_Map))
17610
if($Symbol=~/\A$Prefix/)
17612
foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
17614
if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17622
if(not keys(%Paths))
17625
{ # try to find a library by symbol prefix
17626
if($SymbolPrefix eq "inotify" and
17627
index($Symbol, "\@GLIBC")!=-1)
17629
if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
17635
if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
17642
if(my @Paths = keys(%Paths)) {
17643
$Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
17646
return keys(%Paths);
17649
sub get_LibPath_Prefix($$)
17651
my ($LibVersion, $Prefix) = @_;
17653
$Prefix = lc($Prefix);
17654
$Prefix=~s/[_]+\Z//g;
17656
foreach ("-2", "2", "-1", "1", "")
17660
if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
17670
if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
17671
{ # XmuValidArea: Xmu
17674
elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
17675
{ # snfReadFont: snf
17678
elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
17682
elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
17683
{ # H5HF_delete: H5
17686
elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
17687
{ # alarm_event_add: alarm_
17690
elsif($Str=~/\A(([a-z])\2{1,})/i)
15826
17697
sub getSymbolSize($$)
15827
17698
{ # size from the shared library
15828
17699
my ($Symbol, $LibVersion) = @_;
16032
17951
return @Imported;
17954
my %ELF_BIND = map {$_=>1} (
17959
my %ELF_TYPE = map {$_=>1} (
17966
my %ELF_VIS = map {$_=>1} (
16035
17971
sub readline_ELF($)
16037
if($_[0]=~/\s*\d+:\s+(\w*)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s([^\s]+)/)
16038
{ # the line of 'readelf' output corresponding to the interface
16039
# symbian-style: _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
16040
my ($value, $size, $type, $bind,
16041
$vis, $Ndx, $fullname)=($1, $2, $3, $4, $5, $6, $7);
16042
if($bind!~/\A(WEAK|GLOBAL)\Z/) {
16045
if($type!~/\A(FUNC|IFUNC|OBJECT|COMMON)\Z/) {
16048
if($vis!~/\A(DEFAULT|PROTECTED)\Z/) {
16051
if($Ndx eq "ABS" and $value!~/\D|1|2|3|4|5|6|7|8|9/) {
16054
if($OStarget eq "symbian")
16056
if($fullname=~/_\._\.absent_export_\d+/)
16057
{ # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
16060
my @Elems = separate_symbol($fullname);
16061
$fullname = $Elems[0]; # remove internal version, {00020001}[10011235].dll
16063
return ($fullname, $value, $Ndx, $type, $size, $bind);
16068
sub read_symlink($)
16071
return "" if(not $Path);
16072
return "" if(not -f $Path and not -l $Path);
16073
if(defined $Cache{"read_symlink"}{$Path}) {
16074
return $Cache{"read_symlink"}{$Path};
16076
if(my $Res = readlink($Path)) {
16077
return ($Cache{"read_symlink"}{$Path} = $Res);
16079
elsif(my $ReadlinkCmd = get_CmdPath("readlink")) {
16080
return ($Cache{"read_symlink"}{$Path} = `$ReadlinkCmd -n $Path`);
16082
elsif(my $FileCmd = get_CmdPath("file"))
16084
my $Info = `$FileCmd $Path`;
16085
if($Info=~/symbolic\s+link\s+to\s+['`"]*([\w\d\.\-\/\\]+)['`"]*/i) {
16086
return ($Cache{"read_symlink"}{$Path} = $1);
16089
return ($Cache{"read_symlink"}{$Path} = "");
16092
sub resolve_symlink($)
16095
return "" if(not $Path);
16096
return "" if(not -f $Path and not -l $Path);
16097
if(defined $Cache{"resolve_symlink"}{$Path}) {
16098
return $Cache{"resolve_symlink"}{$Path};
16100
return $Path if(isCyclical(\@RecurSymlink, $Path));
16101
push(@RecurSymlink, $Path);
16102
if(-l $Path and my $Redirect=read_symlink($Path))
16104
if(is_abs($Redirect))
17972
{ # read the line of 'readelf' output corresponding to the symbol
17973
my @Info = split(/\s+/, $_[0]);
17974
# Num: Value Size Type Bind Vis Ndx Name
17975
# 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
17976
# 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
17977
shift(@Info); # spaces
17978
shift(@Info); # num
17982
if($Info[7]=~/\(\d+\)/) {
17991
return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
17992
return () if(not defined $ELF_BIND{$Info[3]});
17993
return () if(not defined $ELF_VIS{$Info[4]});
17994
if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
17995
{ # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
17998
if($OStarget eq "symbian")
17999
{ # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18000
if(index($Info[6], "_._.absent_export_")!=-1)
18001
{ # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18004
$Info[6]=~s/\@.+//g; # remove version
18006
if(index($Info[2], "0x") == 0)
18007
{ # size == 0x3d158
18008
$Info[2] = hex($Info[2]);
18013
sub get_LibPath($$)
18015
my ($LibVersion, $Name) = @_;
18016
return "" if(not $LibVersion or not $Name);
18017
if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18018
return $Cache{"get_LibPath"}{$LibVersion}{$Name};
18020
return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18023
sub get_LibPath_I($$)
18025
my ($LibVersion, $Name) = @_;
16105
18029
{ # absolute path
16106
if($SystemRoot and $SystemRoot ne "/"
16107
and $Path=~/\A\Q$SystemRoot\E\//
16108
and (-f $SystemRoot.$Redirect or -l $SystemRoot.$Redirect))
16109
{ # symbolic links from the sysroot
16110
# should be corrected to point to
16111
# the files inside sysroot
16112
$Redirect = $SystemRoot.$Redirect;
16114
my $Res = resolve_symlink($Redirect);
16115
pop(@RecurSymlink);
16116
return ($Cache{"resolve_symlink"}{$Path} = $Res);
16118
elsif($Redirect=~/\.\.[\/\\]/)
16120
$Redirect = joinPath(get_dirname($Path), $Redirect);
16121
while($Redirect=~s&(/|\\)[^\/\\]+(\/|\\)\.\.(\/|\\)&$1&){};
16122
my $Res = resolve_symlink($Redirect);
16123
pop(@RecurSymlink);
16124
return ($Cache{"resolve_symlink"}{$Path} = $Res);
16126
elsif(-f get_dirname($Path)."/".$Redirect)
16127
{ # file name in the same directory
16128
my $Res = resolve_symlink(joinPath(get_dirname($Path), $Redirect));
16129
pop(@RecurSymlink);
16130
return ($Cache{"resolve_symlink"}{$Path} = $Res);
16134
pop(@RecurSymlink);
16135
return ($Cache{"resolve_symlink"}{$Path} = "");
16138
pop(@RecurSymlink);
16139
return ($Cache{"resolve_symlink"}{$Path} = $Path);
16142
sub find_lib_path($$)
16144
my ($LibVersion, $DyLib) = @_;
16145
return "" if(not $DyLib or not $LibVersion);
16146
return $DyLib if(is_abs($DyLib));
16147
if(defined $Cache{"find_lib_path"}{$LibVersion}{$DyLib}) {
16148
return $Cache{"find_lib_path"}{$LibVersion}{$DyLib};
16150
if(my @Paths = sort keys(%{$InputObject_Paths{$LibVersion}{$DyLib}})) {
16151
return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = $Paths[0]);
16153
elsif(my $DefaultPath = $DyLib_DefaultPath{$DyLib}) {
16154
return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = $DefaultPath);
18037
if(defined $RegisteredObjects{$LibVersion}{$Name})
18038
{ # registered paths
18039
return $RegisteredObjects{$LibVersion}{$Name};
18041
if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
18042
{ # registered paths
18043
return $RegisteredSONAMEs{$LibVersion}{$Name};
18045
if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18046
{ # ldconfig default paths
18047
return $DefaultPath;
18049
foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
18050
{ # search in default linker directories
18051
# and then in all system paths
18052
if(-f $Dir."/".$Name) {
18053
return join_P($Dir,$Name);
18056
detectSystemObjects() if(not keys(%SystemObjects));
18057
if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18058
return $AllObjects[0];
18060
if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
16158
foreach my $Dir (sort keys(%DefaultLibPaths), sort keys(%{$SystemPaths{"lib"}}))
16159
{ # search in default linker paths and then in all system paths
16160
if(-f $Dir."/".$DyLib) {
16161
return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = joinPath($Dir,$DyLib));
16164
detectSystemObjects() if(not keys(%SystemObjects));
16165
if(my @AllObjects = keys(%{$SystemObjects{$DyLib}})) {
16166
return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = $AllObjects[0]);
16168
my $ShortName = parse_libname($DyLib, "name+ext", $OStarget);
16169
if($ShortName ne $DyLib
16170
and my $Path = find_lib_path($ShortName))
18062
if($ShortName ne $Name)
16171
18063
{ # FIXME: check this case
16172
return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = $Path);
18064
if(my $Path = get_LibPath($LibVersion, $ShortName)) {
16174
return ($Cache{"find_lib_path"}{$LibVersion}{$DyLib} = "");
16178
sub readSymbols_Lib($$$$$)
18073
sub readSymbols_Lib($$$$$$)
16180
my ($LibVersion, $Lib_Path, $IsNeededLib, $GroupNames, $Weak) = @_;
16181
return if(not $Lib_Path or not -f $Lib_Path);
16182
my ($Lib_Dir, $Lib_Name) = separate_path(resolve_symlink($Lib_Path));
16183
return if($CheckedDyLib{$LibVersion}{$Lib_Name} and $IsNeededLib);
16184
return if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
18075
my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18076
return () if(not $LibVersion or not $Lib_Path);
18078
my $Real_Path = realpath($Lib_Path);
18085
my $Lib_Name = get_filename($Real_Path);
18089
$KnownLibs{$Real_Path} = 1;
18090
$KnownLibs{$Lib_Path} = 1; # links
18095
if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18099
return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
16185
18100
$CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
16186
my $Lib_SName = parse_libname($Lib_Name, "name+ext", $OStarget);
16188
if($CheckImpl and not $IsNeededLib) {
16189
getImplementations($LibVersion, $Lib_Path);
18104
if(not $IsNeededLib) {
18105
getImplementations($LibVersion, $Lib_Path);
16192
18109
push(@RecurLib, $Lib_Name);
16193
18110
my (%Value_Interface, %Interface_Value, %NeededLib) = ();
18111
my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
16194
18113
if(not $IsNeededLib)
16195
{ # libstdc++ and libc are always used by other libs
16196
# if you test one of these libs then you not need
16197
# to find them in the system for reusing
16198
if(parse_libname($Lib_Name, "short", $OStarget) eq "libstdc++")
16200
$STDCXX_TESTING = 1;
16202
if(parse_libname($Lib_Name, "short", $OStarget) eq "libc")
16204
$GLIBC_TESTING = 1;
18114
{ # special cases: libstdc++ and libc
18115
if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18117
if($ShortName eq "libstdc++")
18119
$STDCXX_TESTING = 1;
18121
elsif($ShortName eq "libc")
18123
$GLIBC_TESTING = 1;
16207
18127
my $DebugPath = "";
18128
if($Debug and not $DumpSystem)
16209
18129
{ # debug mode
16210
18130
$DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
16211
18131
mkpath(get_dirname($DebugPath));
16213
18133
if($OStarget eq "macos")
16214
18134
{ # Mac OS X: *.dylib, *.a
16215
my $OtoolCmd = get_CmdPath("otool");
16216
if(not $OtoolCmd) {
16217
exitStatus("Not_Found", "can't find \"otool\"");
18135
my $NM = get_CmdPath("nm");
18137
exitStatus("Not_Found", "can't find \"nm\"");
16219
$OtoolCmd .= " -TV \"".$Lib_Path."\" 2>$TMP_DIR/null";
18139
$NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
16221
18141
{ # debug mode
16222
18142
# write to file
16223
system($OtoolCmd." >".$DebugPath);
18143
system($NM." >\"$DebugPath\"");
16224
18144
open(LIB, $DebugPath);
16227
18147
{ # write to pipe
16228
open(LIB, $OtoolCmd." |");
18148
open(LIB, $NM." |");
16232
if(/[^_]+\s+_([\w\$]+)\s*\Z/)
18152
if($CheckUndefined)
18154
if(not $IsNeededLib)
18156
if(/ U _([\w\$]+)\s*\Z/)
18158
$UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
18164
if(/ [STD] _([\w\$]+)\s*\Z/)
16235
18167
if($IsNeededLib)
16237
if(not $GroupNames->{$Lib_SName})
18169
if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
16239
$DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
16240
$DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18171
$DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18172
$DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
16245
$Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
16246
$Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
16247
if($COMMON_LANGUAGE{$LibVersion} ne "C++"
16248
and $realname=~/\A(_Z|\?)/) {
16249
setLanguage($LibVersion, "C++");
18177
$Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18178
$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
18179
if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18181
if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
18182
setLanguage($LibVersion, "C++");
16251
18185
if($CheckObjectsOnly
16252
18186
and $LibVersion==1) {
16253
$CheckedSymbols{"Binary"}{$realname} = 1;
18187
$CheckedSymbols{"Binary"}{$Symbol} = 1;
16259
if($LIB_TYPE eq "dynamic")
16261
open(LIB, "$OtoolCmd -L \"".$Lib_Path."\" 2>$TMP_DIR/null |");
16264
if(/\s*([\/\\].+\.$LIB_EXT)\s*/
16265
and $1 ne $Lib_Path) {
16266
$NeededLib{$1} = 1;
18196
if($LIB_TYPE eq "dynamic")
18199
my $OtoolCmd = get_CmdPath("otool");
18200
if(not $OtoolCmd) {
18201
exitStatus("Not_Found", "can't find \"otool\"");
18204
open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18207
if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18208
and $1 ne $Lib_Path) {
18209
$NeededLib{$1} = 1;
16272
18216
elsif($OStarget eq "windows")
16339
18288
if(not $ReadelfCmd) {
16340
18289
exitStatus("Not_Found", "can't find \"readelf\"");
16342
$ReadelfCmd .= " -WhlSsdA \"".$Lib_Path."\" 2>$TMP_DIR/null";
18291
$ReadelfCmd .= " -WhlSsdA \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
16344
18293
{ # debug mode
16345
18294
# write to file
16346
system($ReadelfCmd." >".$DebugPath);
18295
system($ReadelfCmd." >\"$DebugPath\"");
16347
18296
open(LIB, $DebugPath);
16350
18299
{ # write to pipe
16351
18300
open(LIB, $ReadelfCmd." |");
16353
my $symtab=0; # indicates that we are processing 'symtab' section of 'readelf' output
18302
my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
16356
18305
if($LIB_TYPE eq "dynamic")
16357
18306
{ # dynamic library specifics
18307
if(defined $symtab)
18309
if(index($_, "'.dynsym'")!=-1)
16361
18310
{ # dynamic table
16366
{ # do nothing with symtab
18313
# do nothing with symtab
16370
elsif(/'\.symtab'/)
18316
elsif(index($_, "'.symtab'")!=-1)
16371
18317
{ # symbol table
16376
if(my ($fullname, $idx, $Ndx, $type, $size, $bind) = readline_ELF($_))
18322
if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
16377
18323
{ # read ELF entry
16378
if( $Ndx eq "UND" )
16379
18325
{ # ignore interfaces that are imported from somewhere else
16383
and $Weak eq "-Weak")
16384
{ # skip WEAK symbols
16387
my ($realname, $version_spec, $version) = separate_symbol($fullname);
16388
if($type eq "OBJECT")
18326
if($CheckUndefined)
18328
if(not $IsNeededLib) {
18329
$UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
18334
if($Bind eq "WEAK")
18336
$WeakSymbols{$LibVersion}{$Symbol} = 1;
18337
if($Weak eq "-Weak")
18338
{ # skip WEAK symbols
18342
my $Short = $Symbol;
18344
if($Type eq "OBJECT")
16389
18345
{ # global data
16390
$GlobalDataObject{$LibVersion}{$fullname} = 1;
16391
$GlobalDataObject{$LibVersion}{$realname} = 1;
18346
$GlobalDataObject{$LibVersion}{$Symbol} = $Size;
18347
$GlobalDataObject{$LibVersion}{$Short} = $Size;
16393
18349
if($IsNeededLib)
16395
if(not $GroupNames->{$Lib_SName})
18351
if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
16397
$DepSymbol_Library{$LibVersion}{$fullname} = $Lib_Name;
16398
$DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$fullname} = ($type eq "OBJECT")?-$size:1;
18353
$DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18354
$DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
16403
$Symbol_Library{$LibVersion}{$fullname} = $Lib_Name;
16404
$Library_Symbol{$LibVersion}{$Lib_Name}{$fullname} = ($type eq "OBJECT")?-$size:1;
16405
if($LIB_EXT eq "so")
16407
$Interface_Value{$LibVersion}{$fullname} = $idx;
16408
$Value_Interface{$LibVersion}{$idx}{$fullname} = 1;
18359
$Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18360
$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
18363
if($LIB_EXT eq "so")
18365
$Interface_Value{$LibVersion}{$Symbol} = $Value;
18366
$Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
16410
if($COMMON_LANGUAGE{$LibVersion} ne "C++"
16411
and $realname=~/\A(_Z|\?)/) {
16412
setLanguage($LibVersion, "C++");
18369
if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18371
if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
18372
setLanguage($LibVersion, "C++");
16414
18375
if($CheckObjectsOnly
16415
18376
and $LibVersion==1) {
16416
$CheckedSymbols{"Binary"}{$fullname} = 1;
18377
$CheckedSymbols{"Binary"}{$Symbol} = 1;
16420
18381
elsif($LIB_TYPE eq "dynamic")
16421
18382
{ # dynamic library specifics
16422
if(/NEEDED.+\[([^\[\]]+)\]/)
16424
# 0x00000001 (NEEDED) Shared library: [libc.so.6]
16425
$NeededLib{$1} = 1;
18385
if(/NEEDED.+\[([^\[\]]+)\]/)
18387
# 0x00000001 (NEEDED) Shared library: [libc.so.6]
18388
$NeededLib{$1} = 1;
16431
if(not $IsNeededLib and $LIB_EXT eq "so")
16432
{ # get symbol versions
16433
foreach my $Symbol (keys(%{$Symbol_Library{$LibVersion}}))
18397
if(not $IsNeededLib and $LIB_EXT eq "so")
18398
{ # get symbol versions
18402
foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
18404
next if(index($Symbol,"\@")==-1);
18405
if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
18407
foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
18409
if($Symbol_SameValue ne $Symbol
18410
and index($Symbol_SameValue,"\@")==-1)
18412
$SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
18413
$Found{$Symbol} = 1;
18421
foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
18423
next if(defined $Found{$Symbol});
18424
next if(index($Symbol,"\@\@")==-1);
18426
if($Symbol=~/\A([^\@]*)\@\@/
18427
and not $SymVer{$LibVersion}{$1})
18429
$SymVer{$LibVersion}{$1} = $Symbol;
18430
$Found{$Symbol} = 1;
18435
foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
18437
next if(defined $Found{$Symbol});
18438
next if(index($Symbol,"\@")==-1);
18440
if($Symbol=~/\A([^\@]*)\@([^\@]*)/
18441
and not $SymVer{$LibVersion}{$1})
18443
$SymVer{$LibVersion}{$1} = $Symbol;
18444
$Found{$Symbol} = 1;
18451
foreach my $DyLib (sort keys(%NeededLib))
16435
next if(index($Symbol,"\@")==-1);
16436
my $Interface_SymName = "";
16437
foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Interface_Value{$LibVersion}{$Symbol}}}))
16439
if($Symbol_SameValue ne $Symbol
16440
and index($Symbol_SameValue,"\@")==-1)
16442
$SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
16443
$Interface_SymName = $Symbol_SameValue;
16447
if(not $Interface_SymName)
16449
if($Symbol=~/\A([^\@\$\?]*)[\@\$]+([^\@\$]*)\Z/
16450
and not $SymVer{$LibVersion}{$1}) {
16451
$SymVer{$LibVersion}{$1} = $Symbol;
16456
foreach my $DyLib (sort keys(%NeededLib))
16458
my $DepPath = find_lib_path($LibVersion, $DyLib);
16459
if($DepPath and -f $DepPath) {
16460
readSymbols_Lib($LibVersion, $DepPath, 1, $GroupNames, "+Weak");
18453
$Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
18455
if(my $DepPath = get_LibPath($LibVersion, $DyLib))
18457
if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
18458
readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
16463
18463
pop(@RecurLib);
16464
18464
return $Library_Symbol{$LibVersion};
16467
sub get_path_prefixes($)
18467
sub get_prefixes($)
16470
my ($Dir, $Name) = separate_path($Path);
16471
18469
my %Prefixes = ();
16472
foreach my $Prefix (reverse(split(/[\/\\]+/, $Dir)))
16474
$Prefixes{$Name} = 1;
16475
$Name = joinPath($Prefix, $Name);
16476
last if(keys(%Prefixes)>5 or $Prefix eq "include");
18470
get_prefixes_I([$_[0]], \%Prefixes);
16478
18471
return keys(%Prefixes);
18474
sub get_prefixes_I($$)
18476
foreach my $P (@{$_[0]})
18478
my @Parts = reverse(split(/[\/\\]+/, $P));
18479
my $Name = $Parts[0];
18480
foreach (1 .. $#Parts)
18482
$_[1]->{$Name}{$P} = 1;
18483
last if($_>4 or $Parts[$_] eq "include");
18484
$Name = $Parts[$_].$SLASH.$Name;
16481
18489
sub detectSystemHeaders()
16483
18491
my @SysHeaders = ();
16484
foreach my $DevelPath (keys(%{$SystemPaths{"include"}}))
18492
foreach my $DevelPath (@{$SystemPaths{"include"}})
16486
18494
next if(not -d $DevelPath);
16487
18495
# search for all header files in the /usr/include
16488
18496
# with or without extension (ncurses.h, QtCore, ...)
16489
@SysHeaders = (@SysHeaders, cmd_find($DevelPath,"f","",""));
16490
foreach my $Link (cmd_find($DevelPath,"l","",""))
18497
push(@SysHeaders, cmd_find($DevelPath,"f"));
18498
foreach my $Link (cmd_find($DevelPath,"l"))
16491
18499
{ # add symbolic links
16492
18500
if(-f $Link) {
16493
18501
push(@SysHeaders, $Link);
16497
foreach my $DevelPath (keys(%{$SystemPaths{"lib"}}))
18505
foreach my $DevelPath (@{$SystemPaths{"lib"}})
18506
{ # search for config headers in the /usr/lib
16499
18507
next if(not -d $DevelPath);
16500
# search for config headers in the /usr/lib
16501
@SysHeaders = (@SysHeaders, cmd_find($DevelPath,"f","*.h",""));
16502
foreach my $Dir (cmd_find($DevelPath,"d","include",""))
16503
{ # search for all include directories
16504
# this is for headers that are installed to /usr/lib
16505
# Example: Qt4 headers in Mandriva (/usr/lib/qt4/include/)
16506
if($Dir=~/\/(gcc|jvm|syslinux|kdb)\//) {
18508
foreach (cmd_find($DevelPath,"f",'\.h(pp|xx)?\Z|\/include\/',"",1))
18510
if(/\/(gcc|jvm|syslinux|kbd|parrot|xemacs)/)
18511
{ # skip useless headers
16509
@SysHeaders = (@SysHeaders, cmd_find($Dir,"f","",""));
16512
foreach my $Path (@SysHeaders)
16514
foreach my $Part (get_path_prefixes($Path)) {
16515
$SystemHeaders{$Part}{$Path}=1;
18514
push(@SysHeaders, $_);
18517
get_prefixes_I(\@SysHeaders, \%SystemHeaders);
16520
18520
sub detectSystemObjects()
16522
foreach my $DevelPath (keys(%{$SystemPaths{"lib"}}))
18522
foreach my $DevelPath (@{$SystemPaths{"lib"}})
16524
18524
next if(not -d $DevelPath);
16525
18525
foreach my $Path (find_libs($DevelPath,"",""))
16771
18923
my ($LibVersion, $Path) = @_;
16772
18924
return if(not $LibVersion or not -e $Path);
16773
18925
my $FilePath = "";
16774
if($Path=~/\.abi\Z/)
18926
if(isDump_U($Path))
16775
18927
{ # input *.abi
16776
18928
$FilePath = $Path;
16779
18931
{ # input *.abi.tar.gz
16780
18932
$FilePath = unpackDump($Path);
16782
if($FilePath!~/\.abi\Z/) {
16783
exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
16786
open(DUMP, $FilePath);
16788
my $Content = <DUMP>;
16791
if($Path!~/\.abi\Z/)
16792
{ # remove temp file
16795
if($Content!~/};\s*\Z/) {
16796
exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
16798
my $LibraryABI = eval($Content);
16799
if(not $LibraryABI) {
16800
exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
18933
if(not isDump_U($FilePath)) {
18934
exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
18940
my $Line = readLineNum($FilePath, 0);
18943
loadModule("XmlDump");
18944
$ABI = readXmlDump($FilePath);
18947
{ # Perl Data::Dumper format (default)
18948
open(DUMP, $FilePath);
18950
my $Content = <DUMP>;
18953
if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
18954
{ # remove temp file
18957
if($Content!~/};\s*\Z/) {
18958
exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
18960
$ABI = eval($Content);
18962
exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
16802
18965
# new dumps (>=1.22) have a personal versioning
16803
my $DumpVersion = $LibraryABI->{"ABI_DUMP_VERSION"};
16804
my $ToolVersion = $LibraryABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
16805
if(not $DumpVersion)
18966
my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
18967
my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
16806
18969
{ # old dumps (<=1.21.6) have been marked by the tool version
16807
$DumpVersion = $ToolVersion;
16809
$UsedDump{$LibVersion}{"V"} = $DumpVersion;
16810
if(majorVersion($DumpVersion) ne majorVersion($ABI_DUMP_VERSION))
16811
{ # should be compatible with dumps of the same major version
16812
if(cmpVersions($DumpVersion, $ABI_DUMP_VERSION)>0)
16813
{ # Don't know how to parse future dump formats
16814
exitStatus("Dump_Version", "incompatible version $DumpVersion of specified ABI dump (newer than $ABI_DUMP_VERSION)");
16816
elsif(cmpVersions($DumpVersion, $TOOL_VERSION)>0 and not $LibraryABI->{"ABI_DUMP_VERSION"})
16817
{ # Don't know how to parse future dump formats
16818
exitStatus("Dump_Version", "incompatible version $DumpVersion of specified ABI dump (newer than $TOOL_VERSION)");
18970
$DVersion = $ToolVersion;
18972
$UsedDump{$LibVersion}{"V"} = $DVersion;
18974
if($ABI->{"ABI_DUMP_VERSION"})
18976
if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
18977
{ # Don't know how to parse future dump formats
18978
exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
18982
{ # support for old ABI dumps
18983
if(cmpVersions($DVersion, $TOOL_VERSION)>0)
18984
{ # Don't know how to parse future dump formats
18985
exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
18988
if(majorVersion($DVersion)<2)
18989
{ # support for old ABI dumps
16820
18990
if($UseOldDumps)
16822
if(cmpVersions($DumpVersion, $OLDEST_SUPPORTED_VERSION)<0) {
16823
exitStatus("Dump_Version", "incompatible version $DumpVersion of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
18992
if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
18993
exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
16828
my $Msg = "incompatible version $DumpVersion of specified ABI dump (allowed only ".majorVersion($ABI_DUMP_VERSION).".0<=V<=$ABI_DUMP_VERSION)";
16829
if(cmpVersions($DumpVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
16830
$Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<".majorVersion($ABI_DUMP_VERSION).".0)";
18998
my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
18999
if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
19000
$Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
16832
19002
exitStatus("Dump_Version", $Msg);
16835
if($LibraryABI->{"SrcBin"})
19006
if(defined $ABI->{"ABI_DUMPER_VERSION"})
19008
$UseConv_Real{$LibVersion}{"P"} = 1;
19009
$UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19011
$UsedDump{$LibVersion}{"DWARF"} = 1;
19013
$TargetComponent = "module";
19016
if(not checkDump($LibVersion, "2.11"))
19018
$UsedDump{$LibVersion}{"BinOnly"} = 1;
19020
elsif($ABI->{"BinOnly"})
19021
{ # ABI dump created with --binary option
19022
$UsedDump{$LibVersion}{"BinOnly"} = 1;
16837
19026
$UsedDump{$LibVersion}{"SrcBin"} = 1;
16839
elsif($LibraryABI->{"BinOnly"})
16840
{ # ABI dump created with --binary option
16841
$UsedDump{$LibVersion}{"BinOnly"} = 1;
16843
if(defined $LibraryABI->{"Mode"}
16844
and $LibraryABI->{"Mode"} eq "Extended")
19029
if(defined $ABI->{"Mode"}
19030
and $ABI->{"Mode"} eq "Extended")
16845
19031
{ # --ext option
16846
19032
$ExtendedCheck = 1;
16848
if(my $Lang = $LibraryABI->{"Language"})
19034
if($ABI->{"Extra"}) {
19038
if(my $Lang = $ABI->{"Language"})
16850
19040
$UsedDump{$LibVersion}{"L"} = $Lang;
16851
19041
setLanguage($LibVersion, $Lang);
16853
19043
if(checkDump($LibVersion, "2.15")) {
16854
$TypeInfo{$LibVersion} = $LibraryABI->{"TypeInfo"};
19044
$TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
16857
19047
{ # support for old ABI dumps
16858
my $TInfo = $LibraryABI->{"TypeInfo"};
19048
my $TInfo = $ABI->{"TypeInfo"};
16859
19049
if(not $TInfo)
16860
19050
{ # support for older ABI dumps
16861
$TInfo = $LibraryABI->{"TypeDescr"};
19051
$TInfo = $ABI->{"TypeDescr"};
16863
19053
my %Tid_TDid = ();
16864
19054
foreach my $TDid (keys(%{$TInfo}))
16950
19135
$DepSymbol_Library{$LibVersion}{$Symbol} = 1;
16953
$SymVer{$LibVersion} = $LibraryABI->{"SymbolVersion"};
16954
$Descriptor{$LibVersion}{"Version"} = $LibraryABI->{"LibraryVersion"};
16955
$SkipTypes{$LibVersion} = $LibraryABI->{"SkipTypes"};
19138
$SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
19139
$Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
19140
$SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
16956
19141
if(not $SkipTypes{$LibVersion})
16957
19142
{ # support for old dumps
16958
$SkipTypes{$LibVersion} = $LibraryABI->{"OpaqueTypes"};
16960
$SkipSymbols{$LibVersion} = $LibraryABI->{"SkipSymbols"};
16961
if(not $SkipSymbols{$LibVersion})
16962
{ # support for old dumps
16963
$SkipSymbols{$LibVersion} = $LibraryABI->{"SkipInterfaces"};
16965
if(not $SkipSymbols{$LibVersion})
16966
{ # support for old dumps
16967
$SkipSymbols{$LibVersion} = $LibraryABI->{"InternalInterfaces"};
16969
$SkipNameSpaces{$LibVersion} = $LibraryABI->{"SkipNameSpaces"};
16970
$TargetHeaders{$LibVersion} = $LibraryABI->{"TargetHeaders"};
16971
foreach my $Path (keys(%{$LibraryABI->{"SkipHeaders"}}))
19143
$SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
19145
$SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
19146
if(not $SkipSymbols{$LibVersion})
19147
{ # support for old dumps
19148
$SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
19150
if(not $SkipSymbols{$LibVersion})
19151
{ # support for old dumps
19152
$SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
19154
$SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
19155
$TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
19156
foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
16973
$SkipHeadersList{$LibVersion}{$Path} = $LibraryABI->{"SkipHeaders"}{$Path};
19158
$SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
16974
19159
my ($CPath, $Type) = classifyPath($Path);
16975
$SkipHeaders{$LibVersion}{$Type}{$CPath} = $LibraryABI->{"SkipHeaders"}{$Path};
19160
$SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
16977
read_Headers_DumpInfo($LibraryABI, $LibVersion);
16978
read_Libs_DumpInfo($LibraryABI, $LibVersion);
16979
if(not checkDump($LibVersion, "2.10.1"))
19162
read_Source_DumpInfo($ABI, $LibVersion);
19163
read_Libs_DumpInfo($ABI, $LibVersion);
19164
if(not checkDump($LibVersion, "2.10.1")
19165
or not $TargetHeaders{$LibVersion})
16980
19166
{ # support for old ABI dumps: added target headers
16981
19167
foreach (keys(%{$Registered_Headers{$LibVersion}})) {
16982
19168
$TargetHeaders{$LibVersion}{get_filename($_)}=1;
16985
$Constants{$LibVersion} = $LibraryABI->{"Constants"};
16986
$NestedNameSpaces{$LibVersion} = $LibraryABI->{"NameSpaces"};
19170
foreach (keys(%{$Registered_Sources{$LibVersion}})) {
19171
$TargetHeaders{$LibVersion}{get_filename($_)}=1;
19174
$Constants{$LibVersion} = $ABI->{"Constants"};
19175
if(defined $ABI->{"GccConstants"})
19177
foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
19178
$Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
19182
$NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
16987
19183
if(not $NestedNameSpaces{$LibVersion})
16988
19184
{ # support for old dumps
16989
19185
# Cannot reconstruct NameSpaces. This may affect design
17633
19988
sub get_depth($)
17635
19990
if(defined $Cache{"get_depth"}{$_[0]}) {
17636
return $Cache{"get_depth"}{$_[0]}
19991
return $Cache{"get_depth"}{$_[0]};
17638
19993
return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
17641
sub find_gcc_cxx_headers($)
19996
sub registerGccHeaders()
17643
my $LibVersion = $_[0];
17644
return if($Cache{"find_gcc_cxx_headers"});# this function should be called once
17645
# detecting system header paths
17646
foreach my $Path (sort {get_depth($b) <=> get_depth($a)} keys(%DefaultGccPaths))
19998
return if($Cache{"registerGccHeaders"}); # this function should be called once
20000
foreach my $Path (@DefaultGccPaths)
17648
foreach my $HeaderPath (sort {get_depth($a) <=> get_depth($b)} cmd_find($Path,"f","",""))
20002
my @Headers = cmd_find($Path,"f");
20003
@Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20004
foreach my $HPath (@Headers)
17650
my $FileName = get_filename($HeaderPath);
17651
next if($DefaultGccHeader{$FileName});
17652
$DefaultGccHeader{$FileName} = $HeaderPath;
20006
my $FileName = get_filename($HPath);
20007
if(not defined $DefaultGccHeader{$FileName})
20008
{ # skip duplicated
20009
$DefaultGccHeader{$FileName} = $HPath;
17655
if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
20013
$Cache{"registerGccHeaders"} = 1;
20016
sub registerCppHeaders()
20018
return if($Cache{"registerCppHeaders"}); # this function should be called once
20020
foreach my $CppDir (@DefaultCppPaths)
17657
foreach my $CppDir (sort {get_depth($b)<=>get_depth($a)} keys(%DefaultCppPaths))
20022
my @Headers = cmd_find($CppDir,"f");
20023
@Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20024
foreach my $Path (@Headers)
17659
my @AllCppHeaders = cmd_find($CppDir,"f","","");
17660
foreach my $Path (sort {get_depth($a)<=>get_depth($b)} @AllCppHeaders)
17662
my $FileName = get_filename($Path);
17663
next if($DefaultCppHeader{$FileName});
20026
my $FileName = get_filename($Path);
20027
if(not defined $DefaultCppHeader{$FileName})
20028
{ # skip duplicated
17664
20029
$DefaultCppHeader{$FileName} = $Path;
17668
$Cache{"find_gcc_cxx_headers"} = 1;
20033
$Cache{"registerCppHeaders"} = 1;
17671
20036
sub parse_libname($$$)
20038
return "" if(not $_[0]);
20039
if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20040
return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
20042
return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20045
sub parse_libname_I($$$)
17673
20047
my ($Name, $Type, $Target) = @_;
17677
20049
if($Target eq "symbian") {
17678
20050
return parse_libname_symbian($Name, $Type);
17680
20052
elsif($Target eq "windows") {
17681
20053
return parse_libname_windows($Name, $Type);
17683
20057
my $Ext = getLIB_EXT($Target);
17684
if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+|))\.$Ext)(\.(.+)|)\Z/)
20058
if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
17685
20059
{ # libSDL-1.2.so.0.7.1
17686
20060
# libwbxml2.so.0.0.18
20061
# libopcodes-2.21.53-system.20110810.so
17687
20062
if($Type eq "name")
17688
20063
{ # libSDL-1.2