aboutsummaryrefslogtreecommitdiff
path: root/abi-compliance-checker.pl
diff options
context:
space:
mode:
Diffstat (limited to 'abi-compliance-checker.pl')
-rw-r--r--abi-compliance-checker.pl152
1 files changed, 128 insertions, 24 deletions
diff --git a/abi-compliance-checker.pl b/abi-compliance-checker.pl
index 6f14454..650f3a1 100644
--- a/abi-compliance-checker.pl
+++ b/abi-compliance-checker.pl
@@ -1,6 +1,6 @@
#!/usr/bin/perl
###########################################################################
-# ABI Compliance Checker (ABICC) 1.99.16
+# ABI Compliance Checker (ABICC) 1.99.17
# A tool for checking backward compatibility of a C/C++ library API
#
# Copyright (C) 2009-2011 Institute for System Programming, RAS
@@ -21,7 +21,7 @@
# - GNU Binutils (readelf, c++filt, objdump)
# - Perl 5 (5.8 or newer)
# - Ctags (5.8 or newer)
-# - ABI Dumper (0.99.14 or newer)
+# - ABI Dumper (0.99.15 or newer)
#
# Mac OS X
# - Xcode (g++, c++filt, otool, nm)
@@ -60,7 +60,7 @@ use Storable qw(dclone);
use Data::Dumper;
use Config;
-my $TOOL_VERSION = "1.99.16";
+my $TOOL_VERSION = "1.99.17";
my $ABI_DUMP_VERSION = "3.2";
my $XML_REPORT_VERSION = "1.2";
my $XML_ABI_DUMP_VERSION = "1.2";
@@ -4931,7 +4931,7 @@ sub linkSymbol($)
or $EMERGENCY_MODE_48)
{ # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
# GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
- # GCC 4.8 doesn't mangle anything
+ # GCC 4.8.[012] doesn't mangle anything
if(not $CheckHeadersOnly)
{
if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
@@ -7452,12 +7452,18 @@ sub get_Signature($$)
my ($Signature, @Param_Types_FromUnmangledName) = ();
my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
+
if($Symbol=~/\A(_Z|\?)/)
{
if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
{
my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
$ClassName=~s/\bstruct //g;
+
+ if(index($Symbol, "_ZTV")==0) {
+ return "vtable for $ClassName [data]";
+ }
+
$Signature .= $ClassName."::";
if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
$Signature .= "~";
@@ -7480,9 +7486,15 @@ sub get_Signature($$)
my @ParamArray = ();
foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
{
- next if($Pos eq "");
+ if($Pos eq "") {
+ next;
+ }
+
my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
- next if(not $ParamTypeId);
+ if(not $ParamTypeId) {
+ next;
+ }
+
my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
if(not $ParamTypeName) {
$ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
@@ -9277,6 +9289,19 @@ sub prepareSymbols($)
if(not $MnglName) {
next;
}
+
+ # NOTE: duplicated entries in the ABI Dump
+ if(defined $CompleteSignature{$LibVersion}{$MnglName})
+ {
+ if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
+ {
+ if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
+ {
+ next;
+ }
+ }
+ }
+
if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
{ # NOTE: global data may enter here twice
%{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
@@ -9297,6 +9322,7 @@ sub prepareSymbols($)
if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
{
%{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
+
if($SymVer{$LibVersion}{$Alias}) {
%{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
}
@@ -9789,14 +9815,26 @@ sub isTargetType($$)
}
if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
- {
+ { # NOTE: header is defined to source if undefined (DWARF dumps)
if(not is_target_header($THeader, $LibVersion))
{ # from target headers
return 0;
}
}
- else {
- return 0;
+ else
+ { # NOTE: if type is defined in source
+ if($UsedDump{$LibVersion}{"Public"})
+ {
+ if(isPrivateABI($Tid, $LibVersion)) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+ }
+ else {
+ return 0;
+ }
}
if($SkipInternalTypes)
@@ -10472,7 +10510,7 @@ sub cmpVTables_Real($$)
$Entry1 = simpleVEntry($Entry1);
$Entry2 = simpleVEntry($Entry2);
- if($Entry1=~/ 0x/ and $Entry2=~/ 0x/)
+ if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
{ # NOTE: problem with vtable-dumper
next;
}
@@ -12277,6 +12315,47 @@ sub mergeTypes($$$)
}
}
+ if($Type1_Pure{"Type"} eq "FuncPtr")
+ {
+ foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
+ {
+ if(not defined $Type2_Pure{"Param"}{$PPos}) {
+ next;
+ }
+
+ my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
+ my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
+
+ my $PName = "p".$PPos;
+
+ my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
+ my %DupProblems = ();
+
+ foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
+ {
+ foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
+ {
+ if(not defined $AllAffected)
+ {
+ if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
+ next;
+ }
+ }
+
+ my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
+ $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
+
+ if(not defined $AllAffected)
+ {
+ $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
+ }
+ }
+ }
+
+ %DupProblems = ();
+ }
+ }
+
pop(@RecurTypes);
return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
}
@@ -12712,6 +12791,11 @@ sub mergeLibs($)
next;
}
}
+
+ if($SkipSymbols{1}{$Symbol})
+ { # user defined symbols to ignore
+ next;
+ }
}
else {
next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
@@ -15545,7 +15629,7 @@ sub get_SourceInfo()
$CheckedLibs .= "<div class='lib_list'>\n";
foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
{
- $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
+ # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
$CheckedLibs .= $Library."<br/>\n";
}
$CheckedLibs .= "</div>\n";
@@ -15860,7 +15944,7 @@ sub get_Summary($)
$TestResults .= " <libs>\n";
foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
{
- $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
+ # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
$TestResults .= " <name>$Library</name>\n";
}
$TestResults .= " </libs>\n";
@@ -16264,9 +16348,11 @@ sub getTitle($$$)
{
my ($Header, $Library, $NameSpace) = @_;
my $Title = "";
- if($Library and $Library!~/\.\w+\Z/) {
- $Library .= " (.$LIB_EXT)";
- }
+
+ # if($Library and $Library!~/\.\w+\Z/) {
+ # $Library .= " (.$LIB_EXT)";
+ # }
+
if($Header and $Library)
{
$Title .= "<span class='h_name'>$Header</span>";
@@ -17039,7 +17125,13 @@ sub showVTables($)
foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
{
my ($Color1, $Color2) = ("", "");
- if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
+
+ my $E1 = $Entries{$Index}{"E1"};
+ my $E2 = $Entries{$Index}{"E2"};
+
+ if($E1 ne $E2
+ and $E1!~/ 0x/
+ and $E2!~/ 0x/)
{
if($Entries{$Index}{"E1"})
{
@@ -17668,10 +17760,10 @@ sub getReportFooter()
{
my $Footer = "";
- $Footer .= "<hr/>";
- $Footer .= "<div class='footer' align='right'><i>Generated on ".localtime(time);
- $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
- $Footer .= "</i></div>";
+ $Footer .= "<hr/>\n";
+ $Footer .= "<div class='footer' align='right'>";
+ $Footer .= "<i>Generated by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
+ $Footer .= "</div>\n";
$Footer .= "<br/>\n";
return $Footer;
@@ -20886,7 +20978,19 @@ sub detect_default_paths($)
exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
}
- if(my $GCC_Ver = get_dumpversion($GCC_PATH))
+ my $GCC_Ver = get_dumpversion($GCC_PATH);
+ if($GCC_Ver eq "4.8")
+ { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
+ my $Info = `$GCC_PATH --version`;
+
+ if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
+ { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
+ # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
+ $GCC_Ver = $2;
+ }
+ }
+
+ if($GCC_Ver)
{
my $GccTarget = get_dumpmachine($GCC_PATH);
@@ -20906,9 +21010,9 @@ sub detect_default_paths($)
# check GCC version
if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
{ # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
- # introduced in 4.8
- # fixed in 4.8.3
- printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
+ # introduced in 4.8 and fixed in 4.8.3
+ printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update GCC to 4.8.3 or downgrade it to 4.7. You can use a local GCC installation by --gcc-path=PATH option.");
+
$EMERGENCY_MODE_48 = 1;
}
}