Check if the cpu architecture of the input objects is equal to architecture of the used GCC compiler; Added -arch option
diff --git a/abi-compliance-checker.pl b/abi-compliance-checker.pl
index bd08cdd..6ac2bf2 100755
--- a/abi-compliance-checker.pl
+++ b/abi-compliance-checker.pl
@@ -93,7 +93,8 @@
$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
$SourceReportPath, $UseXML, $Browse, $OpenReport, $SortDump, $DumpFormat,
$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
-$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat, $SkipInternal);
+$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat, $SkipInternal,
+$TargetArch);
my $CmdName = get_filename($0);
my %OS_LibExt = (
@@ -244,6 +245,7 @@
"dump-format=s" => \$DumpFormat,
"xml!" => \$UseXML,
"lang=s" => \$UserLang,
+ "arch=s" => \$TargetArch,
"binary|bin|abi!" => \$BinaryOnly,
"source|src|api!" => \$SourceOnly,
"limit-affected|affected-limit=s" => \$AffectLimit,
@@ -631,6 +633,11 @@
Set library language (C or C++). You can use this option if the tool
cannot auto-detect a language. This option may be useful for checking
C-library headers (--lang=C) in --headers-only or --extended modes.
+
+ -arch ARCH
+ Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
+ ect.). The option is useful if the tool cannot detect correct architecture
+ of the input objects.
-binary|-bin|-abi
Show \"Binary\" compatibility problems only.
@@ -15560,6 +15567,11 @@
sub getArch($)
{
my $LibVersion = $_[0];
+
+ if($TargetArch) {
+ return $TargetArch;
+ }
+
if($CPU_ARCH{$LibVersion})
{ # dump version
return $CPU_ARCH{$LibVersion};
@@ -15568,8 +15580,14 @@
{ # old-version dumps
return "unknown";
}
- if(defined $Cache{"getArch"}{$LibVersion}) {
- return $Cache{"getArch"}{$LibVersion};
+
+ return getArch_GCC();
+}
+
+sub getArch_GCC()
+{
+ if(defined $Cache{"getArch_GCC"}) {
+ return $Cache{"getArch_GCC"};
}
my $Arch = get_dumpmachine($GCC_PATH); # host version
if(not $Arch) {
@@ -15585,8 +15603,7 @@
$Arch = "x86" if($Arch=~/win32|mingw32/i);
$Arch = "x86_64" if($Arch=~/win64|mingw64/i);
}
- $Cache{"getArch"}{$LibVersion} = $Arch;
- return $Arch;
+ return ($Cache{"getArch_GCC"} = $Arch);
}
sub get_Report_Header($)
@@ -19265,9 +19282,10 @@
{ # 1197 4AC 0000A620 SetThreadStackGuarantee
# 1198 4AD SetThreadToken (forwarded to ...)
# 3368 _o2i_ECPublicKey
- if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
+ # 1 0 00005B30 ??0?N = ... (with pdb)
+ if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
- or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
+ or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
{ # dynamic, static and forwarded symbols
my $realname = $1;
if($IsNeededLib)
@@ -19805,6 +19823,7 @@
sub registerObject($$)
{
my ($Path, $LibVersion) = @_;
+
my $Name = get_filename($Path);
$RegisteredObjects{$LibVersion}{$Name} = $Path;
if($OSgroup=~/linux|bsd/i)
@@ -19816,6 +19835,108 @@
if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
$RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
}
+
+ if(not $CPU_ARCH{$LibVersion})
+ {
+ $CPU_ARCH{$LibVersion} = getArch_Object($Path);
+
+ if($CPU_ARCH{$LibVersion})
+ {
+ if(my $GccArch = getArch_GCC())
+ {
+ if($CPU_ARCH{$LibVersion} ne $GccArch)
+ { # translation unit dump generated by the GCC compiler should correspond to the input objects
+ printMsg("WARNING", "the architectures of input objects and the used GCC compiler are not equal, please change the compiler by --gcc-path=PATH option.");
+ $CPU_ARCH{$LibVersion} = $GccArch;
+ }
+ }
+ }
+ }
+}
+
+sub getArch_Object($)
+{
+ my $Path = $_[0];
+
+ my %MachineType = (
+ "14C" => "x86",
+ "8664" => "x86_64",
+ "1C0" => "arm",
+ "200" => "ia64"
+ );
+
+ if($OSgroup eq "windows")
+ {
+ my $DumpbinCmd = get_CmdPath("dumpbin");
+ if(not $DumpbinCmd) {
+ exitStatus("Not_Found", "can't find \"dumpbin\"");
+ }
+
+ my $Cmd = $DumpbinCmd." /headers \"$Path\"";
+ my $Out = `$Cmd`;
+
+ if($Out=~/(\w+)\smachine/)
+ {
+ if(my $Type = $MachineType{uc($1)})
+ {
+ return $Type;
+ }
+ }
+ }
+ elsif($OSgroup=~/linux|bsd/)
+ {
+ my $ObjdumpCmd = get_CmdPath("objdump");
+ if(not $ObjdumpCmd) {
+ exitStatus("Not_Found", "can't find \"objdump\"");
+ }
+
+ my $Cmd = $ObjdumpCmd." -f \"$Path\"";
+ my $Out = `$Cmd`;
+
+ if($Out=~/architecture:\s+([\w\-\:]+)/)
+ {
+ my $Arch = $1;
+ if($Arch=~s/\:(.+)//)
+ {
+ my $Suffix = $1;
+
+ if($Suffix eq "x86-64") {
+ $Arch = $Suffix;
+ }
+
+ if($Arch eq "powerpc")
+ {
+ if($Suffix eq "common64")
+ {
+ $Arch = "ppc64";
+ }
+ elsif($Suffix eq "common")
+ {
+ $Arch = "ppc32";
+ }
+ }
+ }
+
+ if($Arch=~/i[3-7]86/) {
+ $Arch = "x86";
+ }
+
+ if($Arch eq "x86-64") {
+ $Arch = "x86_64";
+ }
+
+ if($Arch=~/\A(x86|x86_64|arm|ia64)\Z/)
+ {
+ return $Arch;
+ }
+ }
+ }
+ else
+ { # macos, etc.
+ # TODO
+ }
+
+ return undef;
}
sub getSONAME($)
@@ -19836,7 +19957,8 @@
else {
$SonameCmd .= " | grep SONAME";
}
- if(my $SonameInfo = `$SonameCmd`) {
+ if(my $SonameInfo = `$SonameCmd`)
+ {
if($SonameInfo=~/SONAME\s+([^\s]+)/) {
return ($Cache{"getSONAME"}{$Path} = $1);
}
@@ -19912,34 +20034,50 @@
return (grep {$_ eq $Value} @{$Stack});
}
-sub detectWordSize()
+sub detectWordSize($)
{
- return "" if(not $GCC_PATH);
- if($Cache{"detectWordSize"}) {
- return $Cache{"detectWordSize"};
- }
- writeFile("$TMP_DIR/empty.h", "");
- my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
- unlink("$TMP_DIR/empty.h");
- my $WSize = 0;
- if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
- { # GCC 4
- $WSize = $1;
- }
- elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
- { # GCC 3
- my $PTRDIFF = $1;
- if($PTRDIFF=~/long/) {
- $WSize = "8";
+ my $LibVersion = $_[0];
+
+ if(my $Arch = getArch($LibVersion))
+ {
+ if($Arch=~/64|390x/)
+ { # x86_64, ppc64, s390x, ia64, etc.
+ return "8";
}
- else {
- $WSize = "4";
+ else
+ { # x86, ppc, s390, etc.
+ return "4";
}
}
- if(not $WSize) {
- exitStatus("Error", "can't check WORD size");
+ elsif($GCC_PATH)
+ {
+ writeFile("$TMP_DIR/empty.h", "");
+ my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
+ unlink("$TMP_DIR/empty.h");
+
+ my $WSize = 0;
+ if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
+ { # GCC 4
+ $WSize = $1;
+ }
+ elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
+ { # GCC 3
+ my $PTRDIFF = $1;
+ if($PTRDIFF=~/long/) {
+ $WSize = "8";
+ }
+ else {
+ $WSize = "4";
+ }
+ }
+ if(not $WSize) {
+ exitStatus("Error", "can't check WORD size");
+ }
+ return $WSize;
}
- return ($Cache{"detectWordSize"} = $WSize);
+
+ # error
+ return undef;
}
sub getWordSize($) {
@@ -21767,6 +21905,7 @@
if(not -e $DumpAPI) {
exitStatus("Access_Error", "can't access \'$DumpAPI\'");
}
+
my @DParts = split(/\s*,\s*/, $DumpAPI);
foreach my $Part (@DParts)
{
@@ -21834,7 +21973,7 @@
if(not $CheckObjectsOnly) {
searchForHeaders(1);
}
- $WORD_SIZE{1} = detectWordSize();
+ $WORD_SIZE{1} = detectWordSize(1);
}
if(not $Descriptor{1}{"Dump"})
{
@@ -22456,7 +22595,7 @@
if(not $CheckObjectsOnly) {
searchForHeaders(1);
}
- $WORD_SIZE{1} = detectWordSize();
+ $WORD_SIZE{1} = detectWordSize(1);
}
if(not $Descriptor{2}{"Dump"})
{
@@ -22469,7 +22608,7 @@
if(not $CheckObjectsOnly) {
searchForHeaders(2);
}
- $WORD_SIZE{2} = detectWordSize();
+ $WORD_SIZE{2} = detectWordSize(2);
}
if($WORD_SIZE{1} ne $WORD_SIZE{2})
{ # support for old ABI dumps