ABI Compliance Checker 1.98.3
diff --git a/abi-compliance-checker.pl b/abi-compliance-checker.pl
index 15637e2..a7f1801 100755
--- a/abi-compliance-checker.pl
+++ b/abi-compliance-checker.pl
@@ -1,6 +1,6 @@
#!/usr/bin/perl
###########################################################################
-# ABI Compliance Checker (ACC) 1.98.2
+# ABI Compliance Checker (ACC) 1.98.3
# A tool for checking backward compatibility of a C/C++ library API
#
# Copyright (C) 2009-2010 The Linux Foundation
@@ -20,9 +20,11 @@
# - G++ (3.0-4.7, recommended 4.5 or newer)
# - GNU Binutils (readelf, c++filt, objdump)
# - Perl 5 (5.8 or newer)
+# - Ctags (5.8 or newer)
#
# Mac OS X
# - Xcode (gcc, otool, c++filt)
+# - Ctags (5.8 or newer)
#
# MS Windows
# - MinGW (3.0-4.7, recommended 4.5 or newer)
@@ -30,6 +32,7 @@
# - Active Perl 5 (5.8 or newer)
# - Sigcheck v1.71 or newer
# - Info-ZIP 3.0 (zip, unzip)
+# - Ctags (5.8 or newer)
# - Add gcc.exe path (C:\MinGW\bin\) to your system PATH variable
# - Run vsvars32.bat (C:\Microsoft Visual Studio 9.0\Common7\Tools\)
#
@@ -55,11 +58,11 @@
use Data::Dumper;
use Config;
-my $TOOL_VERSION = "1.98.2";
-my $ABI_DUMP_VERSION = "2.18";
+my $TOOL_VERSION = "1.98.3";
+my $ABI_DUMP_VERSION = "2.19";
my $OLDEST_SUPPORTED_VERSION = "1.18";
my $XML_REPORT_VERSION = "1.0";
-my $XML_ABI_DUMP_VERSION = "1.1";
+my $XML_ABI_DUMP_VERSION = "1.2";
my $OSgroup = get_OSgroup();
my $ORIG_DIR = cwd();
my $TMP_DIR = tempdir(CLEANUP=>1);
@@ -1387,6 +1390,7 @@
my %SkipLibs;
my %Include_Order;
my %TUnit_NameSpaces;
+my %TUnit_Classes;
my %C99Mode = (
"1"=>0,
@@ -1439,6 +1443,11 @@
my %SourceAlternative_B;
my %SourceReplacement;
+# Calling Conventions
+my %UseConv_Real = (
+ "1"=>0,
+ "2"=>0 );
+
# OS Compliance
my %TargetLibs;
my %TargetHeaders;
@@ -2163,9 +2172,26 @@
{
foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
{
- my @Translations = keys(%{$Typedef_Tr{$Version}{$Base}});
- if($#Translations==0 and length($Translations[0])<=length($Base)) {
- $Typedef_Eq{$Version}{$Base} = $Translations[0];
+ if($Typedef_Eq{$Version}{$Base}) {
+ next;
+ }
+ my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
+ if($#Translations==0)
+ {
+ if(length($Translations[0])<=length($Base)) {
+ $Typedef_Eq{$Version}{$Base} = $Translations[0];
+ }
+ }
+ else
+ { # select most appropriate
+ foreach my $Tr (@Translations)
+ {
+ if($Base=~/\A\Q$Tr\E/)
+ {
+ $Typedef_Eq{$Version}{$Base} = $Tr;
+ last;
+ }
+ }
}
}
foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
@@ -2178,23 +2204,28 @@
if($TypeName=~/>(::\w+)+\Z/)
{ # skip unused types
next;
- };
+ }
foreach my $Base (sort {length($b)<=>length($a)}
sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
{
next if(not $Base);
next if(index($TypeName,$Base)==-1);
next if(length($TypeName) - length($Base) <= 3);
- my $Typedef = $Typedef_Eq{$Version}{$Base};
- $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
- $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
- if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
+ if(my $Typedef = $Typedef_Eq{$Version}{$Base})
{
- foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
+ $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
+ $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
+ if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
{
- my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"};
- $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
- $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName);
+ foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
+ {
+ if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
+ {
+ $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
+ $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
+ $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName);
+ }
+ }
}
}
}
@@ -2557,6 +2588,9 @@
if(not $BTid) {
return ();
}
+ if(my $Algn = getAlgn($TypeId)) {
+ $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
+ }
$TypeAttr{"BaseType"}{"Tid"} = $BTid;
if(my %BTAttr = getTypeAttr($BTid))
{
@@ -2723,6 +2757,9 @@
$TypeAttr{"Size"} = $BTAttr{"Size"};
}
}
+ if(my $Algn = getAlgn($TypeId)) {
+ $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
+ }
$TypeAttr{"Name"} = formatName($TypeAttr{"Name"});
if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
$TypeAttr{"Header"} = $BTAttr{"Header"};
@@ -2822,15 +2859,17 @@
# one typedefs to the same type
return $Covers[0];
}
- my $TypeName_Covered = $TypeName;
+ my $Covered = $TypeName;
while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
{
- my $Cover = $Covers[0];
- $TypeName_Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
- $TypeName_Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
+ if(my $Cover = $Covers[0])
+ {
+ $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
+ $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
+ }
}
- return formatName($TypeName_Covered);
+ return formatName($Covered);
}
sub getNodeIntCst($)
@@ -2904,6 +2943,9 @@
$TypeAttr{"Size"} = "$Size";
}
}
+ if(my $Algn = getAlgn($TypeId)) {
+ $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
+ }
# Return
if($Type eq "FieldPtr")
{
@@ -3297,7 +3339,14 @@
return;
}
$SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
- $SymbolInfo{$Version}{$InfoId}{"MnglName"} = getTreeStr(getTreeAttr_Mngl($InfoId));
+ if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
+ {
+ if($OSgroup eq "windows")
+ { # cut the offset
+ $MnglName=~s/\@\d+\Z//g;
+ }
+ $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
+ }
if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
and $SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A_Z/)
{ # validate mangled name
@@ -3415,7 +3464,7 @@
my ($TypeId, $LibVersion) = @_;
my %Base = get_Type($TypeId, $LibVersion);
while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
- %Base = get_OneStep_BaseType($Base{"Tid"}, $LibVersion);
+ %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
}
return ($Base{"Type"} eq "Const");
}
@@ -3548,6 +3597,9 @@
return ();
}
}
+ if(my $Algn = getAlgn($TypeId)) {
+ $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
+ }
setSpec($TypeId, \%TypeAttr);
setTypeMemb($TypeId, \%TypeAttr);
$TypeAttr{"Tid"} = $TypeId;
@@ -3671,7 +3723,7 @@
foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
{ # checking parameters
my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
- my %PType = get_PureType($PId, $Version);
+ my %PType = get_PureType($PId, $TypeInfo{$Version});
my $PTName = unmangledFormat($PType{"Name"}, $Version);
$PTName=~s/\b(restrict|register)\b//g;
if($Compiler eq "MSVC") {
@@ -3724,7 +3776,7 @@
{ # mangled names for template function specializations include return value
if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
{
- my %RType = get_PureType($ReturnId, $Version);
+ my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
$PureSignature = $ReturnName." ".$PureSignature;
}
@@ -4524,10 +4576,18 @@
{ # support for GCC 3.4
$SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
}
- $SymbolInfo{$Version}{$InfoId}{"MnglName"} = getTreeStr(getTreeAttr_Mngl($InfoId));
- # NOTE: mangling of some symbols may change depending on GCC version
- # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
- # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
+ if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
+ {
+ if($OSgroup eq "windows")
+ { # cut the offset
+ $MnglName=~s/\@\d+\Z//g;
+ }
+ $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
+
+ # NOTE: mangling of some symbols may change depending on GCC version
+ # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
+ # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
+ }
if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
and $SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A_Z/)
@@ -4787,16 +4847,18 @@
{ # mutable fields
$TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
}
- if(my $BFSize = getStructMembBitFieldSize($TypeMembInfoId)) {
+ if(my $Algn = getAlgn($TypeMembInfoId)) {
+ $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
+ }
+ if(my $BFSize = getBitField($TypeMembInfoId))
+ { # in bits
$TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
}
else
- { # set alignment for non-bit fields
- # alignment for bitfields is always equal to 1 bit
- if(my $Algn = getAlgn($TypeMembInfoId)) {
- $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
- }
+ { # in bytes
+ $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
}
+
$TypeMembInfoId = getNextElem($TypeMembInfoId);
$Pos += 1;
}
@@ -5313,7 +5375,7 @@
return "";
}
-sub getStructMembBitFieldSize($)
+sub getBitField($)
{
if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
{
@@ -6740,7 +6802,7 @@
}
}
}
- return ""
+ return "";
}
sub getFuncTypeId($)
@@ -6769,24 +6831,24 @@
return $Cache{"formatName"}{$_[0]};
}
- $_ = $_[0];
+ my $N = $_[0];
- s/\A[ ]+|[ ]+\Z//g;
- s/[ ]{2,}/ /g;
- s/[ ]*(\W)[ ]*/$1/g;
+ $N=~s/\A[ ]+|[ ]+\Z//g;
+ $N=~s/[ ]{2,}/ /g;
+ $N=~s/[ ]*(\W)[ ]*/$1/g;
- s/\bvolatile const\b/const volatile/g;
+ $N=~s/\bvolatile const\b/const volatile/g;
- s/\b(long long|short|long) unsigned\b/unsigned $1/g;
- s/\b(short|long) int\b/$1/g;
+ $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
+ $N=~s/\b(short|long) int\b/$1/g;
- s/([\)\]])(const|volatile)\b/$1 $2/g;
+ $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
- while(s/>>/> >/g) {};
+ while($N=~s/>>/> >/g) {};
- s/\b(operator[ ]*)> >/$1>>/;
+ $N=~s/\b(operator[ ]*)> >/$1>>/;
- return ($Cache{"formatName"}{$_[0]}=$_);
+ return ($Cache{"formatName"}{$_[0]}=$N);
}
sub get_HeaderDeps($$)
@@ -7183,6 +7245,42 @@
return ();
}
+sub checkCTags($)
+{
+ my $Path = $_[0];
+ if(not $Path) {
+ return;
+ }
+ my $CTags = get_CmdPath("ctags");
+ if(not $CTags) {
+ return;
+ }
+ my $Out = $TMP_DIR."/ctags.txt";
+ if($Debug) {
+ $Out = $DEBUG_PATH{$Version}."/ctags.txt";
+ }
+ system("$CTags -f \"$Out\" \"$Path\"");
+ open(CTAGS, "<", $Out);
+ while(my $Line = <CTAGS>)
+ {
+ chomp($Line);
+ my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
+ if($Type eq "n")
+ {
+ if($Scpe=~/\Aclass:/) {
+ next;
+ }
+ if($Scpe)
+ {
+ $Scpe=~s/\Anamespace://;
+ $Name = $Scpe."::".$Name;
+ }
+ $TUnit_NameSpaces{$Version}{$Name}=1;
+ }
+ }
+ close(CTAGS);
+}
+
sub getDump()
{
if(not $GCC_PATH) {
@@ -7235,11 +7333,16 @@
delete($Cache{"selectSystemHeader"});
# preprocessing stage
- checkPreprocessedUnit(callPreprocessor($TmpHeaderPath, $IncludeString, $Version));
+ my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
+ checkPreprocessedUnit($Pre);
# clean memory
delete($Include_Neighbors{$Version});
+ if($COMMON_LANGUAGE{$Version} eq "C++") {
+ checkCTags($Pre);
+ }
+
my $MContent = "";
my $PreprocessCmd = getCompileCmd($TmpHeaderPath, "-E", $IncludeString);
if($OStarget eq "windows"
@@ -7361,7 +7464,6 @@
chdir($ORIG_DIR);
if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
{
- my %AddClasses = ();
my $Content = readFile($ClassDump);
foreach my $ClassInfo (split(/\n\n/, $Content))
{
@@ -7372,7 +7474,7 @@
$TUnit_NameSpaces{$Version}{$CName} = -1;
if($CName=~/\A[\w:]+\Z/)
{ # classes
- $AddClasses{$CName} = 1;
+ $TUnit_Classes{$Version}{$CName} = 1;
}
if($CName=~/(\w[\w:]*)::/)
{ # namespaces
@@ -7398,24 +7500,28 @@
copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
}
unlink($ClassDump);
- if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
- { # GCC on all supported platforms does not include namespaces to the dump by default
- appendFile($MHeaderPath, "\n // add namespaces\n".$NS_Add);
+ }
+
+ # add namespaces and classes
+ if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
+ { # GCC on all supported platforms does not include namespaces to the dump by default
+ appendFile($MHeaderPath, "\n // add namespaces\n".$NS_Add);
+ }
+ # some GCC versions don't include class methods to the TU dump by default
+ my ($AddClass, $ClassNum) = ("", 0);
+ foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
+ {
+ next if($C_Structure{$CName});
+ next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
+ next if(($CName=~tr![:]!!)>2);
+ next if($SkipTypes{$Version}{$CName});
+ if($CName=~/\A(.+)::[^:]+\Z/)
+ { # will be added by name space
+ next;
}
- # some GCC versions don't include class methods to the TU dump by default
- my ($AddClass, $ClassNum) = ("", 0);
- foreach my $CName (sort keys(%AddClasses))
- {
- next if($C_Structure{$CName});
- next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
- next if(($CName=~tr![:]!!)>2);
- next if($SkipTypes{$Version}{$CName});
- if($CName=~/\A(.+)::[^:]+\Z/
- and $AddClasses{$1}) {
- next;
- }
- $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
- }
+ $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
+ }
+ if($AddClass) {
appendFile($MHeaderPath, "\n // add classes\n".$AddClass);
}
}
@@ -7493,7 +7599,8 @@
writeLog($Version, "\n");# new line
}
chdir($ORIG_DIR);
- unlink($TmpHeaderPath, $MHeaderPath);
+ unlink($TmpHeaderPath);
+ unlink($MHeaderPath);
return (cmd_find($TMP_DIR,"f","*.tu",1))[0];
}
@@ -7569,7 +7676,7 @@
$IncludeString = getIncString(getIncPaths($Path), "GCC");
}
my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
- my $Out = $TMP_DIR."/preprocessed";
+ my $Out = $TMP_DIR."/preprocessed.h";
system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
return $Out;
}
@@ -7930,12 +8037,12 @@
# V >= 2.5: array size in bytes
foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
{
- my %Type = get_PureType($TypeId, $LibVersion);
+ my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
if($Type{"Type"} eq "Array")
{
if(my $Size = $Type{"Size"})
{ # array[N]
- my %Base = get_OneStep_BaseType($Type{"Tid"}, $LibVersion);
+ my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
$Size *= $Base{"Size"};
$TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
}
@@ -7952,7 +8059,7 @@
# size of "method ptr" corrected in 2.7
foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
{
- my %PureType = get_PureType($TypeId, $LibVersion);
+ my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
if($PureType{"Type"} eq "MethodPtr")
{
my %Type = get_Type($TypeId, $LibVersion);
@@ -8558,7 +8665,7 @@
my %Type = get_Type($TypeId, $LibVersion);
if($Type{"Type"} eq "Typedef")
{
- my %Base = get_OneStep_BaseType($TypeId, $LibVersion);
+ my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
if($Base{"Type"}=~/Class|Struct/)
{
if($Type{"Name"} eq $Base{"Name"}) {
@@ -8895,204 +9002,6 @@
return 0;
}
-sub getAlignment($$$)
-{
- my ($Pos, $TypePtr, $LibVersion) = @_;
- my $Tid = $TypePtr->{"Memb"}{$Pos}{"type"};
- my %Type = get_PureType($Tid, $LibVersion);
- my $TSize = $Type{"Size"}*$BYTE_SIZE;
- my $MSize = $Type{"Size"}*$BYTE_SIZE;
- if(my $BSize = $TypePtr->{"Memb"}{$Pos}{"bitfield"})
- { # bitfields
- ($TSize, $MSize) = ($WORD_SIZE{$LibVersion}*$BYTE_SIZE, $BSize);
- }
- elsif($Type{"Type"} eq "Array")
- { # in the context of function parameter
- # it's passed through the pointer
- }
- # alignment
- my $Alignment = $WORD_SIZE{$LibVersion}*$BYTE_SIZE; # default
- if(my $Computed = $TypePtr->{"Memb"}{$Pos}{"algn"})
- { # computed by GCC
- $Alignment = $Computed*$BYTE_SIZE;
- }
- elsif($TypePtr->{"Memb"}{$Pos}{"bitfield"})
- { # bitfields are 1 bit aligned
- $Alignment = 1;
- }
- elsif($TSize and $TSize<$WORD_SIZE{$LibVersion}*$BYTE_SIZE)
- { # model
- $Alignment = $TSize;
- }
- return ($Alignment, $MSize);
-}
-
-sub getOffset($$$)
-{ # offset of the field including padding
- my ($FieldPos, $TypePtr, $LibVersion) = @_;
- my $Offset = 0;
- foreach my $Pos (0 .. keys(%{$TypePtr->{"Memb"}})-1)
- {
- my ($Alignment, $MSize) = getAlignment($Pos, $TypePtr, $LibVersion);
- # padding
- my $Padding = 0;
- if($Offset % $Alignment!=0)
- { # not aligned, add padding
- $Padding = $Alignment - $Offset % $Alignment;
- }
- $Offset += $Padding;
- if($Pos==$FieldPos)
- { # after the padding
- # before the field
- return $Offset;
- }
- $Offset += $MSize;
- }
- return $FieldPos;# if something is going wrong
-}
-
-sub isMemPadded($$$$$)
-{ # check if the target field can be added/removed/changed
- # without shifting other fields because of padding bits
- my ($FieldPos, $Size, $TypePtr, $Skip, $LibVersion) = @_;
- return 0 if($FieldPos==0);
- if(defined $TypePtr->{"Memb"}{""})
- {
- delete($TypePtr->{"Memb"}{""});
- if($Debug) {
- printMsg("WARNING", "internal error detected");
- }
- }
- my $Offset = 0;
- my (%Alignment, %MSize) = ();
- my $MaxAlgn = 0;
- my $End = keys(%{$TypePtr->{"Memb"}})-1;
- my $NextField = $FieldPos+1;
- foreach my $Pos (0 .. $End)
- {
- if($Skip and $Skip->{$Pos})
- { # skip removed/added fields
- if($Pos > $FieldPos)
- { # after the target
- $NextField += 1;
- next;
- }
- }
- ($Alignment{$Pos}, $MSize{$Pos}) = getAlignment($Pos, $TypePtr, $LibVersion);
- if($Alignment{$Pos}>$MaxAlgn) {
- $MaxAlgn = $Alignment{$Pos};
- }
- if($Pos==$FieldPos)
- {
- if($Size==-1)
- { # added/removed fields
- if($Pos!=$End)
- { # skip target field and see
- # if enough padding will be
- # created on the next step
- # to include this field
- next;
- }
- }
- }
- # padding
- my $Padding = 0;
- if($Offset % $Alignment{$Pos}!=0)
- { # not aligned, add padding
- $Padding = $Alignment{$Pos} - $Offset % $Alignment{$Pos};
- }
- if($Pos==$NextField)
- { # try to place target field in the padding
- if($Size==-1)
- { # added/removed fields
- my $TPadding = 0;
- if($Offset % $Alignment{$FieldPos}!=0)
- {# padding of the target field
- $TPadding = $Alignment{$FieldPos} - $Offset % $Alignment{$FieldPos};
- }
- if($TPadding+$MSize{$FieldPos}<=$Padding)
- { # enough padding to place target field
- return 1;
- }
- else {
- return 0;
- }
- }
- else
- { # changed fields
- my $Delta = $Size-$MSize{$FieldPos};
- if($Delta>=0)
- { # increased
- if($Size-$MSize{$FieldPos}<=$Padding)
- { # enough padding to change target field
- return 1;
- }
- else {
- return 0;
- }
- }
- else
- { # decreased
- $Delta = abs($Delta);
- if($Delta+$Padding>=$MSize{$Pos})
- { # try to place the next field
- if(($Offset-$Delta) % $Alignment{$Pos} != 0)
- { # padding of the next field in new place
- my $NPadding = $Alignment{$Pos} - ($Offset-$Delta) % $Alignment{$Pos};
- if($NPadding+$MSize{$Pos}<=$Delta+$Padding)
- { # enough delta+padding to store next field
- return 0;
- }
- }
- else
- {
- return 0;
- }
- }
- return 1;
- }
- }
- }
- elsif($Pos==$End)
- { # target field is the last field
- if($Size==-1)
- { # added/removed fields
- if($Offset % $MaxAlgn!=0)
- { # tail padding
- my $TailPadding = $MaxAlgn - $Offset % $MaxAlgn;
- if($Padding+$MSize{$Pos}<=$TailPadding)
- { # enough tail padding to place the last field
- return 1;
- }
- }
- return 0;
- }
- else
- { # changed fields
- # scenario #1
- my $Offset1 = $Offset+$Padding+$MSize{$Pos};
- if($Offset1 % $MaxAlgn != 0)
- { # tail padding
- $Offset1 += $MaxAlgn - $Offset1 % $MaxAlgn;
- }
- # scenario #2
- my $Offset2 = $Offset+$Padding+$Size;
- if($Offset2 % $MaxAlgn != 0)
- { # tail padding
- $Offset2 += $MaxAlgn - $Offset2 % $MaxAlgn;
- }
- if($Offset1!=$Offset2)
- { # different sizes of structure
- return 0;
- }
- return 1;
- }
- }
- $Offset += $Padding+$MSize{$Pos};
- }
- return 0;
-}
-
sub isReserved($)
{ # reserved fields == private
my $MName = $_[0];
@@ -9373,7 +9282,7 @@
}
if($Level eq "Source")
{
- %Class_New = get_PureType($ClassId_New, 2);
+ %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
if($Class_New{"Type"}!~/Class|Struct/) {
next;
}
@@ -9382,23 +9291,27 @@
}
my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
my @Bases_New = sort {$Class_New{"Base"}{$a}{"pos"}<=>$Class_New{"Base"}{$b}{"pos"}} keys(%{$Class_New{"Base"}});
+
+ my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
+ my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
+
my ($BNum1, $BNum2) = (1, 1);
- my %BasePos_Old = map {$TypeInfo{1}{$_}{"Name"} => $BNum1++} @Bases_Old;
- my %BasePos_New = map {$TypeInfo{2}{$_}{"Name"} => $BNum2++} @Bases_New;
+ my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
+ my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
my %ShortBase_Old = map {get_ShortType($_, 1) => 1} @Bases_Old;
my %ShortBase_New = map {get_ShortType($_, 2) => 1} @Bases_New;
my $Shift_Old = getShift($ClassId_Old, 1);
my $Shift_New = getShift($ClassId_New, 2);
- my %BaseId_New = map {$TypeInfo{2}{$_}{"Name"} => $_} @Bases_New;
+ my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
my ($Added, $Removed) = (0, 0);
my @StableBases_Old = ();
foreach my $BaseId (@Bases_Old)
{
my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
- if($BasePos_New{$BaseName}) {
+ if($BasePos_New{$Tr_Old{$BaseName}}) {
push(@StableBases_Old, $BaseId);
}
- elsif(not $ShortBase_New{$BaseName}
+ elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
and not $ShortBase_New{get_ShortType($BaseId, 1)})
{ # removed base
# excluding namespace::SomeClass to SomeClass renaming
@@ -9424,10 +9337,12 @@
my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
{
- my $SubName = $TypeInfo{1}{$SubId}{"Name"};
- push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
- if($ProblemKind=~/VTable/) {
- $VTableChanged_M{$SubName}=1;
+ if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
+ {
+ push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
+ if($ProblemKind=~/VTable/) {
+ $VTableChanged_M{$SubName}=1;
+ }
}
}
foreach my $Interface (@Affected)
@@ -9447,10 +9362,10 @@
foreach my $BaseId (@Bases_New)
{
my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
- if($BasePos_Old{$BaseName}) {
+ if($BasePos_Old{$Tr_New{$BaseName}}) {
push(@StableBases_New, $BaseId);
}
- elsif(not $ShortBase_Old{$BaseName}
+ elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
and not $ShortBase_Old{get_ShortType($BaseId, 2)})
{ # added base
# excluding namespace::SomeClass to SomeClass renaming
@@ -9476,10 +9391,12 @@
my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
{
- my $SubName = $TypeInfo{1}{$SubId}{"Name"};
- push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
- if($ProblemKind=~/VTable/) {
- $VTableChanged_M{$SubName}=1;
+ if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
+ {
+ push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
+ if($ProblemKind=~/VTable/) {
+ $VTableChanged_M{$SubName}=1;
+ }
}
}
foreach my $Interface (@Affected)
@@ -9498,15 +9415,15 @@
if($Level eq "Binary")
{ # Binary-level
($BNum1, $BNum2) = (1, 1);
- my %BaseRelPos_Old = map {$TypeInfo{1}{$_}{"Name"} => $BNum1++} @StableBases_Old;
- my %BaseRelPos_New = map {$TypeInfo{2}{$_}{"Name"} => $BNum2++} @StableBases_New;
+ my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
+ my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
foreach my $BaseId (@Bases_Old)
{
my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
- if(my $NewPos = $BaseRelPos_New{$BaseName})
+ if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
{
- my $BaseNewId = $BaseId_New{$BaseName};
- my $OldPos = $BaseRelPos_Old{$BaseName};
+ my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
+ my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
if($NewPos!=$OldPos)
{ # changed position of the base class
foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
@@ -9550,7 +9467,7 @@
{ # search for changed base
my %BaseType = get_Type($BaseId, 1);
my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
- my $Size_New = $TypeInfo{2}{$BaseId_New{$BaseType{"Name"}}}{"Size"};
+ my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
if($Size_Old ne $Size_New
and $Size_Old and $Size_New)
{
@@ -9586,9 +9503,9 @@
}
}
}
- if(defined $VirtualTable{1}{$ClassName}
+ if(defined $VirtualTable_Model{1}{$ClassName}
and cmpVTables_Real($ClassName, 1)==1
- and my @VFunctions = keys(%{$VirtualTable{1}{$ClassName}}))
+ and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
{ # compare virtual tables size in base classes
my $VShift_Old = getVShift($ClassId_Old, 1);
my $VShift_New = getVShift($ClassId_New, 2);
@@ -9597,11 +9514,11 @@
my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
($BNum1, $BNum2) = (1, 1);
- my %StableBase = map {$TypeInfo{2}{$_}{"Name"} => $_} @AllBases_New;
+ my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
foreach my $BaseId (@AllBases_Old)
{
my %BaseType = get_Type($BaseId, 1);
- if(not $StableBase{$BaseType{"Name"}})
+ if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
{ # lost base
next;
}
@@ -9610,8 +9527,8 @@
if($VSize_Old!=$VSize_New)
{
foreach my $Symbol (@VFunctions)
- {
- if(not defined $VirtualTable{2}{$ClassName}{$Symbol})
+ { # TODO: affected non-virtual methods?
+ if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
{ # Removed_Virtual_Method, will be registered in mergeVirtualTables()
next;
}
@@ -10023,12 +9940,12 @@
my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
- my %MemberType_Pure = get_PureType($MemberType_Id, $LVersion1);
+ my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
if(not defined $Type2->{"Memb"}{$MemPos}) {
return "";
}
my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
- my %PairType_Pure = get_PureType($PairType_Id, $LVersion2);
+ my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
@@ -10129,8 +10046,8 @@
return ();
}
$CheckedTypes{$Level}{$Type1{"Name"}}=1;
- my %Type1_Pure = get_PureType($Type1_Id, 1);
- my %Type2_Pure = get_PureType($Type2_Id, 2);
+ my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
+ my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
$CheckedTypes{$Level}{$Type1_Pure{"Name"}}=1;
if(not $Type1_Pure{"Size"} or not $Type2_Pure{"Size"})
{ # including a case when "class Class { ... };" changed to "class Class;"
@@ -10150,8 +10067,8 @@
and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
{
- my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, 1);
- my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, 2);
+ my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
+ my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
if($Base_1{"Name"} ne $Base_2{"Name"})
{
if(differentDumps("G")
@@ -10450,11 +10367,11 @@
$ProblemType = "Removed_Private_Field";
}
if($Level eq "Binary"
- and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, 1))
+ and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, $WORD_SIZE{1}))
{
if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
{ # affected fields
- if(getOffset($MNum-1, \%Type1_Pure, 1)!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, 2))
+ if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, $WORD_SIZE{2}))
{ # changed offset
$ProblemType .= "_And_Layout";
}
@@ -10552,11 +10469,11 @@
# example: "abidata" members in GStreamer types
$ProblemType = "Private_".$ProblemType;
}
- if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, 1))
+ if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, $WORD_SIZE{1}))
{ # check an effect
if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
{ # public fields after the current
- if(getOffset($MNum-1, \%Type1_Pure, 1)!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, 2))
+ if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, $WORD_SIZE{2}))
{ # changed offset
$ProblemType .= "_And_Layout";
}
@@ -10668,11 +10585,11 @@
or isUnnamed($Member_Name)) {
$ProblemType = "Private_".$ProblemType;
}
- if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, 1))
+ if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, $WORD_SIZE{1}))
{ # check an effect
if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
{ # public fields after the current
- if(getOffset($MNum-1, \%Type1_Pure, 1)!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, 2))
+ if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, $WORD_SIZE{2}))
{ # changed offset
$ProblemType .= "_And_Layout";
}
@@ -10745,11 +10662,11 @@
$ProblemType = "Added_Private_Field";
}
if($Level eq "Binary"
- and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, 2))
+ and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, $WORD_SIZE{2}))
{
if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
{ # public fields after the current
- if(getOffset($MNum-1, \%Type2_Pure, 2)!=getOffset($RelatedField_Rev{$MNum-1}, \%Type1_Pure, 1))
+ if(getOffset($MNum-1, \%Type2_Pure, $TypeInfo{2}, $WORD_SIZE{2})!=getOffset($RelatedField_Rev{$MNum-1}, \%Type1_Pure, $TypeInfo{1}, $WORD_SIZE{1}))
{ # changed offset
$ProblemType .= "_And_Layout";
}
@@ -10809,7 +10726,7 @@
sub get_ShortType($$)
{
my ($TypeId, $LibVersion) = @_;
- my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
+ my $TypeName = uncover_typedefs($TypeInfo{$LibVersion}{$TypeId}{"Name"}, $LibVersion);
if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
$TypeName=~s/\A$NameSpace\:\://g;
}
@@ -10846,19 +10763,21 @@
sub get_PureType($$)
{
- my ($TypeId, $LibVersion) = @_;
- return () if(not $TypeId);
- if(defined $Cache{"get_PureType"}{$TypeId}{$LibVersion}) {
- return %{$Cache{"get_PureType"}{$TypeId}{$LibVersion}};
+ my ($TypeId, $Info) = @_;
+ if(not $TypeId or not $Info
+ or not $Info->{$TypeId}) {
+ return ();
}
- return () if(not $TypeInfo{$LibVersion}{$TypeId});
- my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
+ if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
+ return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
+ }
+ my %Type = %{$Info->{$TypeId}};
return %Type if(not defined $Type{"BaseType"});
return %Type if(not $Type{"BaseType"}{"Tid"});
if($TypeSpecAttributes{$Type{"Type"}}) {
- %Type = get_PureType($Type{"BaseType"}{"Tid"}, $LibVersion);
+ %Type = get_PureType($Type{"BaseType"}{"Tid"}, $Info);
}
- $Cache{"get_PureType"}{$TypeId}{$LibVersion} = \%Type;
+ $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
return %Type;
}
@@ -10928,13 +10847,25 @@
sub get_OneStep_BaseType($$)
{
- my ($TypeId, $LibVersion) = @_;
- return () if(not $TypeId);
- return () if(not $TypeInfo{$LibVersion}{$TypeId});
- my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
+ my ($TypeId, $Info) = @_;
+ if(not $TypeId or not $Info
+ or not $Info->{$TypeId}) {
+ return ();
+ }
+ my %Type = %{$Info->{$TypeId}};
return %Type if(not defined $Type{"BaseType"});
- return %Type if(not $Type{"BaseType"}{"Tid"});
- return get_Type($Type{"BaseType"}{"Tid"}, $LibVersion);
+ if(my $BTid = $Type{"BaseType"}{"Tid"})
+ {
+ if($Info->{$BTid}) {
+ return %{$Info->{$BTid}};
+ }
+ else { # something is going wrong
+ return ();
+ }
+ }
+ else {
+ return %Type;
+ }
}
sub get_Type($$)
@@ -12108,9 +12039,9 @@
}
else
{
- my %ParamType_Pure = get_PureType($PType2_Id, 2);
+ my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
- my %PairType_Pure = get_PureType($PairType_Id, 1);
+ my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
{
@@ -12190,9 +12121,9 @@
}
elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
{
- my %ParamType_Pure = get_PureType($PType1_Id, 1);
+ my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
- my %PairType_Pure = get_PureType($PairType_Id, 2);
+ my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
and find_ParamPair_Pos_byName($Parameter_NewName, $Symbol, 1) eq "lost")
{
@@ -12232,24 +12163,8 @@
my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
my $NewProblemType = $SubProblemType;
- if($Level eq "Binary" and $SubProblemType eq "Return_Type_Became_Void"
- and keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
- { # parameters stack has been affected
- $NewProblemType = "Return_Type_Became_Void_And_Stack_Layout";
- }
- elsif($Level eq "Binary"
- and $SubProblemType eq "Return_Type_From_Void")
- { # parameters stack has been affected
- if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})) {
- $NewProblemType = "Return_Type_From_Void_And_Stack_Layout";
- }
- else
- { # safe
- delete($SubProblems{$SubProblemType});
- next;
- }
- }
- elsif($SubProblemType eq "Return_Type_And_Size"
+
+ if($SubProblemType eq "Return_Type_And_Size"
and $CompleteSignature{1}{$Symbol}{"Data"}) {
$NewProblemType = "Global_Data_Type_And_Size";
}
@@ -12282,6 +12197,85 @@
$NewProblemType = "Global_Data_Type_Format";
}
}
+ if($Level eq "Binary"
+ and not $CompleteSignature{1}{$Symbol}{"Data"})
+ {
+ my ($Arch1, $Arch2) = (getArch(1), getArch(2));
+ if($Arch1 eq "unknown" or $Arch2 eq "unknown")
+ { # if one of the architectures is unknown
+ # then set other arhitecture to unknown too
+ ($Arch1, $Arch2) = ("unknown", "unknown");
+ }
+ my (%Conv1, %Conv2) = ();
+ if($UseConv_Real{1} and $UseConv_Real{1})
+ {
+ %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
+ %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
+ }
+ else
+ {
+ %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
+ %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
+ }
+
+ if($SubProblemType eq "Return_Type_Became_Void")
+ {
+ if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
+ { # parameters stack has been affected
+ if($Conv1{"Method"} eq "stack") {
+ $NewProblemType = "Return_Type_Became_Void_And_Stack_Layout";
+ }
+ elsif($Conv1{"Hidden"}) {
+ $NewProblemType = "Return_Type_Became_Void_And_Register";
+ }
+ }
+ }
+ elsif($SubProblemType eq "Return_Type_From_Void")
+ {
+ if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
+ { # parameters stack has been affected
+ if($Conv2{"Method"} eq "stack") {
+ $NewProblemType = "Return_Type_From_Void_And_Stack_Layout";
+ }
+ elsif($Conv2{"Hidden"}) {
+ $NewProblemType = "Return_Type_From_Void_And_Register";
+ }
+ }
+ }
+ elsif($SubProblemType eq "Return_Type"
+ or $SubProblemType eq "Return_Type_And_Size"
+ or $SubProblemType eq "Return_Type_Format")
+ {
+ if($Conv1{"Method"} ne $Conv2{"Method"})
+ {
+ if($Conv1{"Method"} eq "stack")
+ { # returns in a register instead of a hidden first parameter
+ $NewProblemType = "Return_Type_From_Stack_To_Register";
+ }
+ else {
+ $NewProblemType = "Return_Type_From_Register_To_Stack";
+ }
+ }
+ else
+ {
+ if($Conv1{"Method"} eq "reg")
+ {
+ if($Conv1{"Registers"} ne $Conv2{"Registers"})
+ {
+ if($Conv1{"Hidden"}) {
+ $NewProblemType = "Return_Type_And_Register_Was_Hidden_Parameter";
+ }
+ elsif($Conv2{"Hidden"}) {
+ $NewProblemType = "Return_Type_And_Register_Became_Hidden_Parameter";
+ }
+ else {
+ $NewProblemType = "Return_Type_And_Register";
+ }
+ }
+ }
+ }
+ }
+ }
@{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
}
if($ReturnType1_Id and $ReturnType2_Id)
@@ -12456,7 +12450,7 @@
sub showVal($$$)
{
my ($Value, $TypeId, $LibVersion) = @_;
- my %PureType = get_PureType($TypeId, $LibVersion);
+ my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
if(substr($Value, 0, 2) eq "_Z")
{
@@ -12627,6 +12621,8 @@
{ # modify/register problems
my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
+ my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
+ my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
my $NewProblemType = $SubProblemType;
if($Old_Value eq "..." and $New_Value ne "...")
{ # change from "..." to "int"
@@ -12650,36 +12646,52 @@
$NewProblemType = "Parameter_Became_Non_Const";
}
elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
- or $SubProblemType eq "Parameter_Type"))
+ or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
{
my ($Arch1, $Arch2) = (getArch(1), getArch(2));
- if($Arch1 eq "unknown" or $Arch2 eq "unknown")
+ if($Arch1 eq "unknown"
+ or $Arch2 eq "unknown")
{ # if one of the architectures is unknown
- # then set other arhitecture to unknown too
+ # then set other arhitecture to unknown too
($Arch1, $Arch2) = ("unknown", "unknown");
}
- my ($Method1, $Passed1, $SizeOnStack1, $RegName1) = callingConvention($Symbol, $ParamPos1, 1, $Arch1);
- my ($Method2, $Passed2, $SizeOnStack2, $RegName2) = callingConvention($Symbol, $ParamPos2, 2, $Arch2);
- if($Method1 eq $Method2)
+ my (%Conv1, %Conv2) = ();
+ if($UseConv_Real{1} and $UseConv_Real{1})
+ { # real
+ %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
+ %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
+ }
+ else
+ { # model
+ %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
+ %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
+ }
+ if($Conv1{"Method"} eq $Conv2{"Method"})
{
- if($Method1 eq "stack" and $SizeOnStack1 ne $SizeOnStack2) {
- $NewProblemType = "Parameter_Type_And_Stack";
+ if($Conv1{"Method"} eq "stack")
+ {
+ if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
+ $NewProblemType = "Parameter_Type_And_Stack";
+ }
}
- elsif($Method1 eq "register" and $RegName1 ne $RegName2) {
- $NewProblemType = "Parameter_Type_And_Register";
+ elsif($Conv1{"Method"} eq "reg")
+ {
+ if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
+ $NewProblemType = "Parameter_Type_And_Register";
+ }
}
}
else
{
- if($Method1 eq "stack") {
- $NewProblemType = "Parameter_Type_And_Pass_Through_Register";
+ if($Conv1{"Method"} eq "stack") {
+ $NewProblemType = "Parameter_Type_From_Stack_To_Register";
}
- elsif($Method1 eq "register") {
- $NewProblemType = "Parameter_Type_And_Pass_Through_Stack";
+ elsif($Conv1{"Method"} eq "register") {
+ $NewProblemType = "Parameter_Type_From_Register_To_Stack";
}
}
- $SubProblems{$SubProblemType}{"Old_Reg"} = $RegName1;
- $SubProblems{$SubProblemType}{"New_Reg"} = $RegName2;
+ $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
+ $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
}
%{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
"Target"=>$PName1,
@@ -12716,114 +12728,6 @@
}
}
-sub callingConvention($$$$)
-{ # calling conventions for different compilers and operating systems
- my ($Symbol, $ParamPos, $LibVersion, $Arch) = @_;
- my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
- my %Type = get_PureType($ParamTypeId, $LibVersion);
- my ($Method, $Alignment, $Passed, $Register) = ("", 0, "", "");
- if($OSgroup=~/\A(linux|macos|freebsd)\Z/)
- { # GCC
- if($Arch eq "x86")
- { # System V ABI Intel386 ("Function Calling Sequence")
- # The stack is word aligned. Although the architecture does not require any
- # alignment of the stack, software convention and the operating system
- # requires that the stack be aligned on a word boundary.
-
- # Argument words are pushed onto the stack in reverse order (that is, the
- # rightmost argument in C call syntax has the highest address), preserving the
- # stack’s word alignment. All incoming arguments appear on the stack, residing
- # in the stack frame of the caller.
-
- # An argument’s size is increased, if necessary, to make it a multiple of words.
- # This may require tail padding, depending on the size of the argument.
-
- # Other areas depend on the compiler and the code being compiled. The stan-
- # dard calling sequence does not define a maximum stack frame size, nor does
- # it restrict how a language system uses the ‘‘unspecified’’ area of the stan-
- # dard stack frame.
- ($Method, $Alignment) = ("stack", 4);
- }
- elsif($Arch eq "x86_64")
- { # System V AMD64 ABI ("Function Calling Sequence")
- ($Method, $Alignment) = ("stack", 8);# eightbyte aligned
- }
- elsif($Arch eq "arm")
- { # Procedure Call Standard for the ARM Architecture
- # The stack must be double-word aligned
- ($Method, $Alignment) = ("stack", 8);# double-word
- }
- }
- elsif($OSgroup eq "windows")
- { # MS C++ Compiler
- if($Arch eq "x86")
- {
- if($ParamPos==0) {
- ($Method, $Register, $Passed) = ("register", "ecx", "value");
- }
- elsif($ParamPos==1) {
- ($Method, $Register, $Passed) = ("register", "edx", "value");
- }
- else {
- ($Method, $Alignment) = ("stack", 4);
- }
- }
- elsif($Arch eq "x86_64")
- {
- if($ParamPos<=3)
- {
- if($Type{"Name"}=~/\A(float|double|long double)\Z/) {
- ($Method, $Passed) = ("xmm".$ParamPos, "value");
- }
- elsif(isScalar($Type{"Name"})
- or $Type{"Type"}=~/\A(Struct|Union|Enum|Array)\Z/
- or $Type{"Name"}=~/\A(__m64|__m128)\Z/)
- {
- if($ParamPos==0) {
- ($Method, $Register, $Passed) = ("register", "rcx", "value");
- }
- elsif($ParamPos==1) {
- ($Method, $Register, $Passed) = ("register", "rdx", "value");
- }
- elsif($ParamPos==2) {
- ($Method, $Register, $Passed) = ("register", "r8", "value");
- }
- elsif($ParamPos==3) {
- ($Method, $Register, $Passed) = ("register", "r9", "value");
- }
- if($Type{"Size"}>64
- or $Type{"Type"} eq "Array") {
- $Passed = "pointer";
- }
- }
- }
- else {
- ($Method, $Alignment) = ("stack", 8);# word alignment
- }
- }
- }
- if($Method eq "register") {
- return ("register", $Passed, "", $Register);
- }
- else
- { # on the stack
- if(not $Alignment)
- { # default convention
- $Alignment = $WORD_SIZE{$LibVersion};
- }
- if(not $Passed)
- { # default convention
- $Passed = "value";
- }
- my $SizeOnStack = $Type{"Size"};
- # FIXME: improve stack alignment
- if($SizeOnStack!=$Alignment) {
- $SizeOnStack = int(($Type{"Size"}+$Alignment)/$Alignment)*$Alignment;
- }
- return ("stack", $Passed, $SizeOnStack, "");
- }
-}
-
sub find_ParamPair_Pos_byName($$$)
{
my ($Name, $Symbol, $LibVersion) = @_;
@@ -12864,8 +12768,8 @@
sub checkFormatChange($$$)
{
my ($Type1_Id, $Type2_Id, $Level) = @_;
- my %Type1_Pure = get_PureType($Type1_Id, 1);
- my %Type2_Pure = get_PureType($Type2_Id, 2);
+ my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
+ my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
{ # equal types
return 0;
@@ -12958,14 +12862,6 @@
return 0;
}
-sub isScalar($) {
- return ($_[0]=~/\A(unsigned |)(short|int|long|long long)\Z/);
-}
-
-sub isFloat($) {
- return ($_[0]=~/\A(float|double|long double)\Z/);
-}
-
sub detectTypeChange($$$$)
{
my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
@@ -12975,10 +12871,10 @@
my %LocalProblems = ();
my %Type1 = get_Type($Type1_Id, 1);
my %Type2 = get_Type($Type2_Id, 2);
- my %Type1_Pure = get_PureType($Type1_Id, 1);
- my %Type2_Pure = get_PureType($Type2_Id, 2);
- my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, 1):get_BaseType($Type1_Id, 1);
- my %Type2_Base = ($Type2_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type2_Pure{"Tid"}, 2):get_BaseType($Type2_Id, 2);
+ my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
+ my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
+ my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
+ my %Type2_Base = ($Type2_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type2_Pure{"Tid"}, $TypeInfo{2}):get_BaseType($Type2_Id, 2);
my $Type1_PLevel = get_PLevel($Type1_Id, 1);
my $Type2_PLevel = get_PLevel($Type2_Id, 2);
return () if(not $Type1{"Name"} or not $Type2{"Name"});
@@ -13013,6 +12909,8 @@
%{$LocalProblems{$Prefix."_BaseType_Format"}}=(
"Old_Value"=>$Type1_Base{"Name"},
"New_Value"=>$Type2_Base{"Name"},
+ "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
+ "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
"InitialType_Type"=>$Type1_Pure{"Type"});
}
elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
@@ -13020,6 +12918,8 @@
%{$LocalProblems{$Prefix."_BaseType"}}=(
"Old_Value"=>$Type1_Base{"Name"},
"New_Value"=>$Type2_Base{"Name"},
+ "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
+ "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
"InitialType_Type"=>$Type1_Pure{"Type"});
}
}
@@ -13029,12 +12929,7 @@
{ # type change
if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
{
- if($Prefix eq "Return" and $Type1{"Name"} eq "void"
- and $Type2_Pure{"Type"}=~/Intrinsic|Enum/) {
- # safe change
- }
- elsif($Level eq "Binary"
- and $Prefix eq "Return"
+ if($Prefix eq "Return"
and $Type1_Pure{"Name"} eq "void")
{
%{$LocalProblems{"Return_Type_From_Void"}}=(
@@ -13042,29 +12937,6 @@
"New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
"InitialType_Type"=>$Type1_Pure{"Type"});
}
- elsif($Level eq "Binary"
- and $Prefix eq "Return" and $Type1_Pure{"Type"}=~/Intrinsic|Enum/
- and $Type2_Pure{"Type"}=~/Struct|Class|Union/)
- { # returns into hidden first parameter instead of a register
-
- # System V ABI Intel386 ("Function Calling Sequence")
- # A function that returns an integral or pointer value places its result in register %eax.
-
- # A floating-point return value appears on the top of the Intel387 register stack. The
- # caller then must remove the value from the Intel387 stack, even if it doesn’t use the
- # value.
-
- # If a function returns a structure or union, then the caller provides space for the
- # return value and places its address on the stack as argument word zero. In effect,
- # this address becomes a ‘‘hidden’’ first argument.
-
- %{$LocalProblems{"Return_Type_From_Register_To_Stack"}}=(
- "Old_Value"=>$Type1{"Name"},
- "New_Value"=>$Type2{"Name"},
- "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
- "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
- "InitialType_Type"=>$Type1_Pure{"Type"});
- }
elsif($Prefix eq "Return"
and $Type2_Pure{"Name"} eq "void")
{
@@ -13073,28 +12945,6 @@
"Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
"InitialType_Type"=>$Type1_Pure{"Type"});
}
- elsif($Level eq "Binary" and $Prefix eq "Return"
- and ((isScalar($Type1_Pure{"Name"}) and isFloat($Type2_Pure{"Name"}))
- or (isScalar($Type2_Pure{"Name"}) and isFloat($Type1_Pure{"Name"}))))
- { # The scalar and floating-point values are passed in different registers
- %{$LocalProblems{"Return_Type_And_Register"}}=(
- "Old_Value"=>$Type1{"Name"},
- "New_Value"=>$Type2{"Name"},
- "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
- "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
- "InitialType_Type"=>$Type1_Pure{"Type"});
- }
- elsif($Level eq "Binary"
- and $Prefix eq "Return" and $Type2_Pure{"Type"}=~/Intrinsic|Enum/
- and $Type1_Pure{"Type"}=~/Struct|Class|Union/)
- { # returns in a register instead of a hidden first parameter
- %{$LocalProblems{"Return_Type_From_Stack_To_Register"}}=(
- "Old_Value"=>$Type1{"Name"},
- "New_Value"=>$Type2{"Name"},
- "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
- "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
- "InitialType_Type"=>$Type1_Pure{"Type"});
- }
else
{
if($Level eq "Binary"
@@ -13115,6 +12965,8 @@
%{$LocalProblems{$Prefix."_Type_Format"}}=(
"Old_Value"=>$Type1{"Name"},
"New_Value"=>$Type2{"Name"},
+ "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
+ "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
"InitialType_Type"=>$Type1_Pure{"Type"});
}
elsif(tNameLock($Type1_Id, $Type2_Id))
@@ -13122,6 +12974,8 @@
%{$LocalProblems{$Prefix."_Type"}}=(
"Old_Value"=>$Type1{"Name"},
"New_Value"=>$Type2{"Name"},
+ "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
+ "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
"InitialType_Type"=>$Type1_Pure{"Type"});
}
}
@@ -13202,11 +13056,11 @@
my %Base1 = get_Type($Tid1, 1);
while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
- %Base1 = get_OneStep_BaseType($Base1{"Tid"}, 1);
+ %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
}
my %Base2 = get_Type($Tid2, 2);
while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
- %Base2 = get_OneStep_BaseType($Base2{"Tid"}, 2);
+ %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
}
my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
@@ -13631,24 +13485,24 @@
sub get_OSgroup()
{
- $_ = $Config{"osname"};
- if(/macos|darwin|rhapsody/i) {
+ my $N = $Config{"osname"};
+ if($N=~/macos|darwin|rhapsody/i) {
return "macos";
}
- elsif(/freebsd|openbsd|netbsd/i) {
+ elsif($N=~/freebsd|openbsd|netbsd/i) {
return "bsd";
}
- elsif(/haiku|beos/i) {
+ elsif($N=~/haiku|beos/i) {
return "beos";
}
- elsif(/symbian|epoc/i) {
+ elsif($N=~/symbian|epoc/i) {
return "symbian";
}
- elsif(/win/i) {
+ elsif($N=~/win/i) {
return "windows";
}
else {
- return $_;
+ return $N;
}
}
@@ -15604,10 +15458,10 @@
if(not $Cmd)
{ # default browser
if($OSgroup eq "macos") {
- system("open \"$Path\"");
+ $Cmd = "open \"$Path\"";
}
elsif($OSgroup eq "windows") {
- system("start \"$Path\"");
+ $Cmd = "start ".path_format($Path, $OSgroup);
}
else
{ # linux, freebsd, solaris
@@ -15635,8 +15489,12 @@
if($Debug) {
printMsg("INFO", "running $Cmd");
}
- if($Cmd!~/lynx|links/) {
- $Cmd .= " >\"$TMP_DIR/null\" 2>&1 &";
+ if($OSgroup ne "windows"
+ and $OSgroup ne "macos")
+ {
+ if($Cmd!~/lynx|links/) {
+ $Cmd .= " >\"$TMP_DIR/null\" 2>&1 &";
+ }
}
system($Cmd);
}
@@ -17045,6 +16903,10 @@
return ($Cache{"detectWordSize"} = $WSize);
}
+sub getWordSize($) {
+ return $WORD_SIZE{$_[0]};
+}
+
sub majorVersion($)
{
my $V = $_[0];
@@ -17340,25 +17202,20 @@
my @VFunc = ();
foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
{
- my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
- if($MnglName)
+ if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
{
if(not $Symbol_Library{$LibVersion}{$MnglName}
and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
push(@VFunc, $MnglName);
}
}
- else
- { # ABI dumps have no mangled names for C-functions
- $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
- }
}
translateSymbols(@VFunc, $LibVersion);
translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
- {
+ { # order is important
if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
{ # support for old ABI dumps < 2.0 (ACC 1.22)
foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
@@ -17444,6 +17301,14 @@
}
}
+ foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
+ {
+ if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
+ { # ABI dumps have no mangled names for C-functions
+ $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
+ }
+ }
+
$Descriptor{$LibVersion}{"Dump"} = 1;
}
@@ -19157,6 +19022,12 @@
if($DumpFormat and $DumpFormat ne "perl") {
@PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
}
+ if($CheckHeadersOnly) {
+ @PARAMS = (@PARAMS, "-headers-only");
+ }
+ if($CheckObjectsOnly) {
+ @PARAMS = (@PARAMS, "-objects-only");
+ }
if($Debug)
{
@PARAMS = (@PARAMS, "-debug");
@@ -19209,6 +19080,12 @@
if($DumpFormat and $DumpFormat ne "perl") {
@PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
}
+ if($CheckHeadersOnly) {
+ @PARAMS = (@PARAMS, "-headers-only");
+ }
+ if($CheckObjectsOnly) {
+ @PARAMS = (@PARAMS, "-objects-only");
+ }
if($Debug)
{
@PARAMS = (@PARAMS, "-debug");
@@ -19255,6 +19132,18 @@
if($LoggingPath) {
@CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
}
+ if($CheckHeadersOnly) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
+ }
+ if($CheckObjectsOnly) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
+ }
+ if($BinaryOnly) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-binary");
+ }
+ if($SourceOnly) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-source");
+ }
if($Browse) {
@CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
}
@@ -19391,6 +19280,7 @@
{
my $Level = $_[0];
readRules($Level);
+ loadModule("CallConv");
if($Level eq "Binary") {
printMsg("INFO", "comparing ABIs ...");
}
@@ -19624,8 +19514,8 @@
{ # --test, --test-dump
detect_default_paths("bin|gcc"); # to compile libs
loadModule("RegTests");
- testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode,
- $ReportFormat, $DumpFormat, $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump);
+ testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
+ $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
exit(0);
}
if($DumpSystem)