\n$BSummary\n".get_Report_Added("Binary").get_Report_Removed("Binary").get_Report_Problems("High", "Binary").get_Report_Problems("Medium", "Binary").get_Report_Problems("Low", "Binary").get_Report_Problems("Safe", "Binary").get_SourceInfo()."
";
- $Report .= "\n$SSummary\n".get_Report_Added("Source").get_Report_Removed("Source").get_Report_Problems("High", "Source").get_Report_Problems("Medium", "Source").get_Report_Problems("Low", "Source").get_Report_Problems("Safe", "Source").get_SourceInfo()."
";
+ $Report .= "\n";
- $Report .= get_Report_Title($Level)."\n".$Summary."\n";
- $Report .= get_Report_Added($Level).get_Report_Removed($Level);
- $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
- $Report .= get_SourceInfo();
+ my $Report = "\n".composeHTML_Head($Title, $Keywords, $Des, $CssStyles, $JScripts, $AnyChanged)."\n\n
\n";
+ $Report .= getReportTitle($Level)."\n".$Summary."\n";
+ $Report .= getReportProblems_All($Level);
+ $Report .= getSourceInfo();
$Report .= "
\n
\n";
$Report .= getReportFooter();
$Report .= "\n\n";
@@ -17558,36 +8460,39 @@
}
}
-sub getLegend()
+sub getReportProblems_All($)
{
- return "
-
-
- added |
- compatible |
-
-
- warning |
- incompatible |
-
\n";
+ my $Level = $_[0];
+
+ my $Report = getReportAdded($Level).getReportRemoved($Level);
+ $Report .= getReportProblems("High", $Level);
+ $Report .= getReportProblems("Medium", $Level);
+ $Report .= getReportProblems("Low", $Level);
+ $Report .= getReportProblems("Safe", $Level);
+
+ # clean memory
+ delete($TypeProblemsIndex{$Level});
+ delete($TypeChanges{$Level});
+ delete($CompatProblems{$Level});
+
+ return $Report;
}
sub createReport()
{
- if($JoinReport)
- { # --stdout
+ if($In::Opt{"JoinReport"}) {
writeReport("Join", getReport("Join"));
}
- elsif($DoubleReport)
+ elsif($In::Opt{"DoubleReport"})
{ # default
writeReport("Binary", getReport("Binary"));
writeReport("Source", getReport("Source"));
}
- elsif($BinaryOnly)
+ elsif($In::Opt{"BinOnly"})
{ # --binary
writeReport("Binary", getReport("Binary"));
}
- elsif($SourceOnly)
+ elsif($In::Opt{"SrcOnly"})
{ # --source
writeReport("Source", getReport("Source"));
}
@@ -17597,33 +8502,33 @@
{
my $Footer = "";
- $Footer .= "
";
- $Footer .= "";
+ $Footer .= "
\n";
+ $Footer .= "\n";
$Footer .= "
\n";
return $Footer;
}
-sub get_Report_Problems($$)
+sub getReportProblems($$)
{
my ($Severity, $Level) = @_;
- my $Report = get_Report_TypeProblems($Severity, $Level);
- if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
+ my $Report = getReportTypeProblems($Severity, $Level);
+ if(my $SProblems = getReportSymbolProblems($Severity, $Level)) {
$Report .= $SProblems;
}
if($Severity eq "Low" or $Severity eq "Safe") {
- $Report .= get_Report_ChangedConstants($Severity, $Level);
+ $Report .= getReportChangedConstants($Severity, $Level);
}
- if($ReportFormat eq "html")
+ if($In::Opt{"ReportFormat"} eq "html")
{
if($Report)
{ # add anchor
- if($JoinReport)
+ if($In::Opt{"JoinReport"})
{
if($Severity eq "Safe") {
$Report = "
".$Report;
@@ -17646,27 +8551,28 @@
return $Report;
}
-sub composeHTML_Head($$$$$)
+sub composeHTML_Head($$$$$$)
{
- my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
- return "
-
-
-
-
-
-
- $Title
-
-
-
- ";
+ my ($Title, $Keywords, $Des, $Styles, $Scripts, $AnyChanged) = @_;
+
+ my $Head = "\n";
+ $Head .= "\n";
+ $Head .= "\n";
+ $Head .= "
\n";
+ $Head .= "
\n";
+ $Head .= "
\n";
+ $Head .= "
\n";
+
+ if(not $AnyChanged) {
+ $Head .= "
\n";
+ }
+
+ $Head .= "
$Title\n";
+ $Head .= "\n";
+ $Head .= "\n";
+ $Head .= "\n";
+
+ return $Head;
}
sub insertIDs($)
@@ -17684,132 +8590,25 @@
return $Text;
}
-sub checkPreprocessedUnit($)
-{
- my $Path = $_[0];
- my ($CurHeader, $CurHeaderName) = ("", "");
- my $CurClass = ""; # extra info
- open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
-
- while(my $Line =
)
- { # detecting public and private constants
- if(substr($Line, 0, 1) eq "#")
- {
- chomp($Line);
- if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
- {
- $CurHeader = path_format($1, $OSgroup);
- $CurHeaderName = get_filename($CurHeader);
- $CurClass = "";
-
- if(index($CurHeader, $TMP_DIR)==0) {
- next;
- }
-
- if(substr($CurHeaderName, 0, 1) eq "<")
- { # , , etc.
- $CurHeaderName = "";
- $CurHeader = "";
- }
-
- if($ExtraInfo)
- {
- if($CurHeaderName) {
- $PreprocessedHeaders{$Version}{$CurHeader} = 1;
- }
- }
- }
- if(not $ExtraDump)
- {
- if($CurHeaderName)
- {
- if(not $Include_Neighbors{$Version}{$CurHeaderName}
- and not $Registered_Headers{$Version}{$CurHeader})
- { # not a target
- next;
- }
- if(not is_target_header($CurHeaderName, 1)
- and not is_target_header($CurHeaderName, 2))
- { # user-defined header
- next;
- }
- }
- }
-
- if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
- {
- my ($Name, $Value) = ($1, $2);
- if(not $Constants{$Version}{$Name}{"Access"})
- {
- $Constants{$Version}{$Name}{"Access"} = "public";
- $Constants{$Version}{$Name}{"Value"} = $Value;
- if($CurHeaderName) {
- $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
- }
- }
- }
- elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
- $Constants{$Version}{$1}{"Access"} = "private";
- }
- }
- else
- {
- if(defined $ExtraDump)
- {
- if($Line=~/(\w+)\s*\(/)
- { # functions
- $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
- }
- #elsif($Line=~/(\w+)\s*;/)
- #{ # data
- # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
- #}
- elsif($Line=~/(\A|\s)class\s+(\w+)/) {
- $CurClass = $2;
- }
- }
- }
- }
- close(PREPROC);
- foreach my $Constant (keys(%{$Constants{$Version}}))
- {
- if($Constants{$Version}{$Constant}{"Access"} eq "private")
- {
- delete($Constants{$Version}{$Constant});
- next;
- }
- if(not $ExtraDump and ($Constant=~/_h\Z/i
- or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
- { # skip
- delete($Constants{$Version}{$Constant});
- }
- else {
- delete($Constants{$Version}{$Constant}{"Access"});
- }
- }
- if($Debug)
- {
- mkpath($DEBUG_PATH{$Version});
- copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
- }
-}
-
sub uncoverConstant($$)
{
- my ($LibVersion, $Constant) = @_;
- return "" if(not $LibVersion or not $Constant);
- return $Constant if(isCyclical(\@RecurConstant, $Constant));
- if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
- return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
+ my ($LVer, $Constant) = @_;
+
+ if(isCyclical(\@RecurConstant, $Constant)) {
+ return $Constant;
+ }
+
+ if(defined $Cache{"uncoverConstant"}{$LVer}{$Constant}) {
+ return $Cache{"uncoverConstant"}{$LVer}{$Constant};
}
- if(defined $Constants{$LibVersion}{$Constant})
+ if(defined $Constants{$LVer}{$Constant})
{
- my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
- if(defined $Constants{$LibVersion}{$Value})
+ my $Value = $Constants{$LVer}{$Constant}{"Value"};
+ if(defined $Constants{$LVer}{$Value})
{
push(@RecurConstant, $Constant);
- my $Uncovered = uncoverConstant($LibVersion, $Value);
+ my $Uncovered = uncoverConstant($LVer, $Value);
if($Uncovered ne "") {
$Value = $Uncovered;
}
@@ -17818,14 +8617,14 @@
# FIXME: uncover $Value using all the enum constants
# USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
- return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
+ return ($Cache{"uncoverConstant"}{$LVer}{$Constant} = $Value);
}
- return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
+ return ($Cache{"uncoverConstant"}{$LVer}{$Constant} = "");
}
sub simpleConstant($$)
{
- my ($LibVersion, $Value) = @_;
+ my ($LVer, $Value) = @_;
if($Value=~/\W/)
{
my $Value_Copy = $Value;
@@ -17834,7 +8633,7 @@
my $Word = $1;
if($Value!~/$Word\s*\(/)
{
- my $Val = uncoverConstant($LibVersion, $Word);
+ my $Val = uncoverConstant($LVer, $Word);
if($Val ne "")
{
$Value=~s/\b$Word\b/$Val/g;
@@ -17860,7 +8659,7 @@
return $Value;
}
-my %IgnoreConstant = map {$_=>1} (
+my $IgnoreConstant = join("|",
"VERSION",
"VERSIONCODE",
"VERNUM",
@@ -17919,21 +8718,16 @@
{ # __malloc_ptr_t
return 1;
}
- foreach (keys(%IgnoreConstant))
- {
- if($Name=~/(\A|_)$_(_|\Z)/)
- { # version
- return 1;
- }
- if(/\A[A-Z].*[a-z]\Z/)
- {
- if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
- { # version
- return 1;
- }
- }
+ if($Name=~/(\A|_)($IgnoreConstant)(_|\Z)/)
+ { # version
+ return 1;
}
- if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
+ if($Name=~/(\A|[a-z])(Release|Version)([A-Z]|\Z)/)
+ { # version
+ return 1;
+ }
+ my $LShort = $In::Opt{"TargetLibShort"};
+ if($Name=~/(\A|_)(lib|open|)$LShort(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
{ # version
return 1;
}
@@ -17971,18 +8765,24 @@
sub mergeConstants($)
{
my $Level = $_[0];
- foreach my $Constant (keys(%{$Constants{1}}))
+ foreach my $Constant (sort keys(%{$Constants{1}}))
{
- if($SkipConstants{1}{$Constant})
+ if($In::Desc{1}{"SkipConstants"}{$Constant})
{ # skipped by the user
next;
}
if(my $Header = $Constants{1}{$Constant}{"Header"})
{
- if(not is_target_header($Header, 1)
- and not is_target_header($Header, 2))
- { # user-defined header
+ if(not isTargetHeader($Header, 1)
+ and not isTargetHeader($Header, 2)) {
+ next;
+ }
+ }
+ elsif(my $Source = $Constants{1}{$Constant}{"Source"})
+ {
+ if(not isTargetSource($Source, 1)
+ and not isTargetSource($Source, 2)) {
next;
}
}
@@ -17999,9 +8799,12 @@
if(not defined $Constants{2}{$Constant}{"Value"})
{ # removed
- %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
- "Target"=>$Constant,
- "Old_Value"=>$Old_Value );
+ if(not defined $In::Opt{"SkipRemovedConstants"})
+ {
+ %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
+ "Target"=>$Constant,
+ "Old_Value"=>$Old_Value );
+ }
next;
}
@@ -18033,7 +8836,7 @@
{ # expressions
next;
}
- if(convert_integer($Old_Value) eq convert_integer($New_Value))
+ if(convertInteger($Old_Value) eq convertInteger($New_Value))
{ # 0x0001 and 0x1, 0x1 and 1 equal constants
next;
}
@@ -18052,19 +8855,31 @@
}
}
+ if(defined $In::Opt{"SkipAddedConstants"}) {
+ return;
+ }
+
foreach my $Constant (keys(%{$Constants{2}}))
{
if(not defined $Constants{1}{$Constant}{"Value"})
{
- if($SkipConstants{2}{$Constant})
+ if($In::Desc{2}{"SkipConstants"}{$Constant})
{ # skipped by the user
next;
}
if(my $Header = $Constants{2}{$Constant}{"Header"})
{
- if(not is_target_header($Header, 1)
- and not is_target_header($Header, 2))
+ if(not isTargetHeader($Header, 1)
+ and not isTargetHeader($Header, 2))
+ { # user-defined header
+ next;
+ }
+ }
+ elsif(my $Source = $Constants{2}{$Constant}{"Source"})
+ {
+ if(not isTargetSource($Source, 1)
+ and not isTargetSource($Source, 2))
{ # user-defined header
next;
}
@@ -18090,7 +8905,7 @@
}
}
-sub convert_integer($)
+sub convertInteger($)
{
my $Value = $_[0];
if($Value=~/\A0x[a-f0-9]+\Z/)
@@ -18110,1703 +8925,626 @@
}
}
-sub readSymbols($)
-{
- my $LibVersion = $_[0];
- my @LibPaths = getSOPaths($LibVersion);
- if($#LibPaths==-1 and not $CheckHeadersOnly)
- {
- if($LibVersion==1)
- {
- printMsg("WARNING", "checking headers only");
- $CheckHeadersOnly = 1;
- }
- else {
- exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
- }
- }
-
- foreach my $LibPath (@LibPaths) {
- readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
- }
-
- if($CheckUndefined)
- {
- my %UndefinedLibs = ();
-
- my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
-
- foreach my $LibName (sort @Libs)
- {
- if(defined $UndefinedSymbols{$LibVersion}{$LibName})
- {
- foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
- {
- if($Symbol_Library{$LibVersion}{$Symbol}
- or $DepSymbol_Library{$LibVersion}{$Symbol})
- { # exported by target library
- next;
- }
- if(index($Symbol, '@')!=-1)
- { # exported default symbol version (@@)
- $Symbol=~s/\@/\@\@/;
- if($Symbol_Library{$LibVersion}{$Symbol}
- or $DepSymbol_Library{$LibVersion}{$Symbol}) {
- next;
- }
- }
- foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
- $UndefinedLibs{$Path} = 1;
- }
- }
- }
- }
- if($ExtraInfo)
- { # extra information for other tools
- if(my @Paths = sort keys(%UndefinedLibs))
- {
- my $LibString = "";
- my %Dirs = ();
- foreach (@Paths)
- {
- $KnownLibs{$_} = 1;
- my ($Dir, $Name) = separate_path($_);
-
- if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
- $Dirs{esc($Dir)} = 1;
- }
-
- $Name = parse_libname($Name, "name", $OStarget);
- $Name=~s/\Alib//;
-
- $LibString .= " -l$Name";
- }
-
- foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
- {
- $LibString = " -L".esc($Dir).$LibString;
- }
-
- writeFile($ExtraInfo."/libs-string", $LibString);
- }
- }
- }
-
- if($ExtraInfo) {
- writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
- }
+sub getSymbolSize($$)
+{ # size from the shared library
+ my ($Symbol, $LVer) = @_;
- if(not $CheckHeadersOnly)
+ if(defined $In::ABI{$LVer}{"SymLib"}{$Symbol}
+ and my $LibName = $In::ABI{$LVer}{"SymLib"}{$Symbol})
{
- if($#LibPaths!=-1)
+ if(defined $In::ABI{$LVer}{"Symbols"}{$LibName}{$Symbol}
+ and my $Size = $In::ABI{$LVer}{"Symbols"}{$LibName}{$Symbol})
{
- if(not keys(%{$Symbol_Library{$LibVersion}}))
- {
- printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
- printMsg("WARNING", "checking headers only");
- $CheckHeadersOnly = 1;
+ if($Size<0) {
+ return -$Size;
}
}
}
-
- # clean memory
- %SystemObjects = ();
+ return 0;
}
-my %Prefix_Lib_Map=(
- # symbols for autodetecting library dependencies (by prefix)
- "pthread_" => ["libpthread"],
- "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
- "cairo_" => ["libcairo"],
- "gtk_" => ["libgtk-x11-2.0"],
- "atk_" => ["libatk-1.0"],
- "gdk_" => ["libgdk-x11-2.0"],
- "gl" => ["libGL"],
- "glu" => ["libGLU"],
- "popt" => ["libpopt"],
- "Py" => ["libpython"],
- "jpeg_" => ["libjpeg"],
- "BZ2_" => ["libbz2"],
- "Fc" => ["libfontconfig"],
- "Xft" => ["libXft"],
- "SSL_" => ["libssl"],
- "sem_" => ["libpthread"],
- "snd_" => ["libasound"],
- "art_" => ["libart_lgpl_2"],
- "dbus_g" => ["libdbus-glib-1"],
- "GOMP_" => ["libgomp"],
- "omp_" => ["libgomp"],
- "cms" => ["liblcms"]
-);
-
-my %Pattern_Lib_Map=(
- "SL[a-z]" => ["libslang"]
-);
-
-my %Symbol_Lib_Map=(
- # symbols for autodetecting library dependencies (by name)
- "pow" => "libm",
- "fmod" => "libm",
- "sin" => "libm",
- "floor" => "libm",
- "cos" => "libm",
- "dlopen" => "libdl",
- "deflate" => "libz",
- "inflate" => "libz",
- "move_panel" => "libpanel",
- "XOpenDisplay" => "libX11",
- "resize_term" => "libncurses",
- "clock_gettime" => "librt",
- "crypt" => "libcrypt"
-);
-
-sub find_SymbolLibs($$)
+sub createSymbolsList($$$$$)
{
- my ($LibVersion, $Symbol) = @_;
+ my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
- if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
- { # debug symbols
- return ();
- }
+ $In::ABI{1} = readABIDump(1, $DPath);
+ initAliases(1);
- my %Paths = ();
+ prepareSymbols(1);
- if(my $LibName = $Symbol_Lib_Map{$Symbol})
+ my %SymbolHeaderLib = ();
+ my $Total = 0;
+
+ # Get List
+ foreach my $Symbol (sort keys(%{$CompSign{1}}))
{
- if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
- $Paths{$Path} = 1;
+ if(not linkSymbol($Symbol, 1, "-Deps"))
+ { # skip src only and all external functions
+ next;
}
+ if(not symbolFilter($Symbol, $CompSign{1}{$Symbol}, "Public", "Binary", 1))
+ { # skip other symbols
+ next;
+ }
+ my $HeaderName = $CompSign{1}{$Symbol}{"Header"};
+ if(not $HeaderName)
+ { # skip src only and all external functions
+ next;
+ }
+ my $DyLib = $In::ABI{1}{"SymLib"}{$Symbol};
+ if(not $DyLib)
+ { # skip src only and all external functions
+ next;
+ }
+ $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
+ $Total += 1;
}
-
- if(my $SymbolPrefix = getPrefix($Symbol))
+ # Draw List
+ my $SYMBOLS_LIST = "Public symbols in $LName ($LVersion)";
+ $SYMBOLS_LIST .= " on ".showArch($ArchName)."
Total: $Total
";
+ foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
{
- if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
- return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
- }
-
- if(not keys(%Paths))
+ foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
{
- if(defined $Prefix_Lib_Map{$SymbolPrefix})
- {
- foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
- {
- if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
- $Paths{$Path} = 1;
- }
- }
+ my %NS_Symbol = ();
+ foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
+ $NS_Symbol{selectSymbolNs($Symbol, 1)}{$Symbol} = 1;
}
- }
-
- if(not keys(%Paths))
- {
- foreach my $Prefix (sort keys(%Pattern_Lib_Map))
+ foreach my $NameSpace (sort keys(%NS_Symbol))
{
- if($Symbol=~/\A$Prefix/)
+ $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
+ my @SortedInterfaces = sort {lc($CompSign{1}{$a}{"Unmangled"}) cmp lc($CompSign{1}{$b}{"Unmangled"})} sort {lc($a) cmp lc($b)} keys(%{$NS_Symbol{$NameSpace}});
+ foreach my $Symbol (@SortedInterfaces)
{
- foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
- {
- if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
- $Paths{$Path} = 1;
- }
+ my $SubReport = "";
+ my $Signature = highLight_ItalicColor($Symbol, 1);
+ if($NameSpace) {
+ $Signature = cutNs($Signature, $NameSpace);
}
- }
- }
- }
-
- if(not keys(%Paths))
- {
- if($SymbolPrefix)
- { # try to find a library by symbol prefix
- if($SymbolPrefix eq "inotify" and
- index($Symbol, "\@GLIBC")!=-1)
- {
- if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
- $Paths{$Path} = 1;
+ if($Symbol=~/\A(_Z|\?)/) {
+ $SubReport = insertIDs($ContentSpanStart.$Signature.$ContentSpanEnd."
\n".$ContentDivStart."$Symbol
".$ContentDivEnd."\n");
}
- }
- else
- {
- if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
- $Paths{$Path} = 1;
+ else {
+ $SubReport = "".$Signature."
\n";
}
+ $SYMBOLS_LIST .= $SubReport;
}
}
- }
-
- if(my @Paths = keys(%Paths)) {
- $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
+ $SYMBOLS_LIST .= "
\n";
}
}
- return keys(%Paths);
-}
-
-sub get_LibPath_Prefix($$)
-{
- my ($LibVersion, $Prefix) = @_;
+ # clear info
+ (%CompSign, %ClassMethods, %AllocableClass, %ClassNames, %In::ABI) = ();
- $Prefix = lc($Prefix);
- $Prefix=~s/[_]+\Z//g;
+ ($Content_Counter, $ContentID) = (0, 0);
- foreach ("-2", "2", "-1", "1", "")
- { # libgnome-2.so
- # libxml2.so
- # libdbus-1.so
- if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
- return $Path;
- }
- }
- return "";
+ my $CssStyles = readModule("Styles", "SymbolsList.css");
+ my $JScripts = readModule("Scripts", "Sections.js");
+ $SYMBOLS_LIST = "".$SYMBOLS_LIST.$TOP_REF."
\n";
+ my $Title = "$LName: public symbols";
+ my $Keywords = "$LName, API, symbols";
+ my $Des = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
+ $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Des, $CssStyles, $JScripts, 1)."
+ \n$SYMBOLS_LIST
+
\n".getReportFooter()."
+ ";
+ writeFile($SaveTo, $SYMBOLS_LIST);
}
-sub getPrefix($)
+sub dumpSorting($)
{
- my $Str = $_[0];
- if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
- { # XmuValidArea: Xmu
- return $1;
- }
- elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
- { # snfReadFont: snf
- return $1;
- }
- elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
- { # XRRTimes: XRR
- return $1;
- }
- elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
- { # H5HF_delete: H5
- return $1;
- }
- elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
- { # alarm_event_add: alarm_
- return $1;
- }
- elsif($Str=~/\A(([a-z])\2{1,})/i)
- { # ffopen
- return $1;
- }
- return "";
-}
-
-sub getSymbolSize($$)
-{ # size from the shared library
- my ($Symbol, $LibVersion) = @_;
- return 0 if(not $Symbol);
- if(defined $Symbol_Library{$LibVersion}{$Symbol}
- and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
- {
- if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
- and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
- {
- if($Size<0) {
- return -$Size;
- }
- }
+ my $Hash = $_[0];
+ if(not $Hash) {
+ return [];
}
- return 0;
-}
-
-sub canonifyName($$)
-{ # make TIFFStreamOpen(char const*, std::basic_ostream >*)
- # to be TIFFStreamOpen(char const*, std::basic_ostream*)
- my ($Name, $Type) = @_;
- # single
- while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
- {
- my $P = $1;
- $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
+ my @Keys = keys(%{$Hash});
+ if($#Keys<0) {
+ return [];
}
- # double
- if($Name=~/$DEFAULT_STD_PARMS/)
- {
- if($Type eq "S")
- {
- my ($ShortName, $FuncParams) = split_Signature($Name);
-
- foreach my $FParam (separate_Params($FuncParams, 0, 0))
- {
- if(index($FParam, "<")!=-1)
- {
- $FParam=~s/>([^<>]+)\Z/>/; # remove quals
- my $FParam_N = canonifyName($FParam, "T");
- if($FParam_N ne $FParam) {
- $Name=~s/\Q$FParam\E/$FParam_N/g;
- }
- }
- }
- }
- elsif($Type eq "T")
- {
- my ($ShortTmpl, $TmplParams) = template_Base($Name);
-
- my @TParams = separate_Params($TmplParams, 0, 0);
- if($#TParams>=1)
- {
- my $FParam = $TParams[0];
- foreach my $Pos (1 .. $#TParams)
- {
- my $TParam = $TParams[$Pos];
- if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
- $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
- }
- }
- }
- }
+ if($Keys[0]=~/\A\d+\Z/)
+ { # numbers
+ return [sort {$a<=>$b} @Keys];
}
- if($Type eq "S") {
- return formatName($Name, "S");
+ else
+ { # strings
+ return [sort {$a cmp $b} @Keys];
}
- return $Name;
}
-sub translateSymbols(@)
-{
- my $LibVersion = pop(@_);
- my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
- foreach my $Symbol (sort @_)
- {
- if(index($Symbol, "_Z")==0)
- {
- next if($tr_name{$Symbol});
- $Symbol=~s/[\@\$]+(.*)\Z//;
- push(@MnglNames1, $Symbol);
- }
- elsif(index($Symbol, "?")==0)
- {
- next if($tr_name{$Symbol});
- push(@MnglNames2, $Symbol);
- }
- else
- { # not mangled
- $tr_name{$Symbol} = $Symbol;
- $mangled_name_gcc{$Symbol} = $Symbol;
- $mangled_name{$LibVersion}{$Symbol} = $Symbol;
- }
+sub exitReport()
+{ # the tool has run without any errors
+ printReport();
+ if($In::Opt{"CompileError"})
+ { # errors in headers may add false positives/negatives
+ exit(getErrorCode("Compile_Error"));
}
- if($#MnglNames1 > -1)
- { # GCC names
- @UnmangledNames = reverse(unmangleArray(@MnglNames1));
- foreach my $MnglName (@MnglNames1)
- {
- if(my $Unmangled = pop(@UnmangledNames))
- {
- $tr_name{$MnglName} = canonifyName($Unmangled, "S");
- if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
- $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
- }
- if(index($MnglName, "_ZTV")==0
- and $tr_name{$MnglName}=~/vtable for (.+)/)
- { # bind class name and v-table symbol
- my $ClassName = $1;
- $ClassVTable{$ClassName} = $MnglName;
- $VTableClass{$MnglName} = $ClassName;
- }
- }
- }
+ if($In::Opt{"BinOnly"} and $RESULT{"Binary"}{"Problems"})
+ { # --binary
+ exit(getErrorCode("Incompatible"));
}
- if($#MnglNames2 > -1)
- { # MSVC names
- @UnmangledNames = reverse(unmangleArray(@MnglNames2));
- foreach my $MnglName (@MnglNames2)
- {
- if(my $Unmangled = pop(@UnmangledNames))
- {
- $tr_name{$MnglName} = formatName($Unmangled, "S");
- $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
- }
- }
+ elsif($In::Opt{"SrcOnly"}
+ and $RESULT{"Source"}{"Problems"})
+ { # --source
+ exit(getErrorCode("Incompatible"));
}
- return \%tr_name;
-}
-
-sub link_symbol($$$)
-{
- my ($Symbol, $RunWith, $Deps) = @_;
- if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
- return 1;
+ elsif($RESULT{"Source"}{"Problems"}
+ or $RESULT{"Binary"}{"Problems"})
+ { # default
+ exit(getErrorCode("Incompatible"));
}
- if($Deps eq "+Deps")
- { # check the dependencies
- if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
- return 1;
- }
+ else {
+ exit(getErrorCode("Compatible"));
}
- return 0;
}
-sub link_symbol_internal($$$)
+sub readRules($)
{
- my ($Symbol, $RunWith, $Where) = @_;
- return 0 if(not $Where or not $Symbol);
- if($Where->{$RunWith}{$Symbol})
- { # the exact match by symbol name
- return 1;
- }
- if(my $VSym = $SymVer{$RunWith}{$Symbol})
- { # indirect symbol version, i.e.
- # foo_old and its symlink foo@v (or foo@@v)
- # foo_old may be in symtab table
- if($Where->{$RunWith}{$VSym}) {
- return 1;
- }
+ my $Kind = $_[0];
+ if(not -f $RULES_PATH{$Kind}) {
+ exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
}
- my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
- if($Sym and $Ver)
- { # search for the symbol with the same version
- # or without version
- if($Where->{$RunWith}{$Sym})
- { # old: foo@v|foo@@v
- # new: foo
- return 1;
+ my $Content = readFile($RULES_PATH{$Kind});
+ while(my $Rule = parseTag(\$Content, "rule"))
+ {
+ my $RId = parseTag(\$Rule, "id");
+ my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
+ foreach my $Prop (@Properties) {
+ if(my $Value = parseTag(\$Rule, lc($Prop)))
+ {
+ $Value=~s/\n[ ]*//;
+ $CompatRules{$Kind}{$RId}{$Prop} = $Value;
+ }
}
- if($Where->{$RunWith}{$Sym."\@".$Ver})
- { # old: foo|foo@@v
- # new: foo@v
- return 1;
+ if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
+ $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
}
- if($Where->{$RunWith}{$Sym."\@\@".$Ver})
- { # old: foo|foo@v
- # new: foo@@v
- return 1;
+ else {
+ $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
}
}
- return 0;
}
-sub readSymbols_App($)
+sub getReportPath($)
{
- my $Path = $_[0];
- return () if(not $Path);
- my @Imported = ();
- if($OStarget eq "macos")
+ my $Level = $_[0];
+ my $Dir = "compat_reports/".$In::Opt{"TargetLib"}."/".$In::Desc{1}{"Version"}."_to_".$In::Desc{2}{"Version"};
+ if($Level eq "Binary")
{
- my $NM = get_CmdPath("nm");
- if(not $NM) {
- exitStatus("Not_Found", "can't find \"nm\"");
+ if($In::Opt{"BinReportPath"})
+ { # --bin-report-path
+ return $In::Opt{"BinReportPath"};
}
- open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
- while()
- {
- if(/ U _([\w\$]+)\s*\Z/) {
- push(@Imported, $1);
- }
+ elsif($In::Opt{"OutputReportPath"})
+ { # --report-path
+ return $In::Opt{"OutputReportPath"};
+ }
+ else
+ { # default
+ return $Dir."/abi_compat_report.".$In::Opt{"ReportFormat"};
}
- close(APP);
}
- elsif($OStarget eq "windows")
+ elsif($Level eq "Source")
{
- my $DumpBinCmd = get_CmdPath("dumpbin");
- if(not $DumpBinCmd) {
- exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
+ if($In::Opt{"SrcReportPath"})
+ { # --src-report-path
+ return $In::Opt{"SrcReportPath"};
}
- open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
- while()
- {
- if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
- push(@Imported, $1);
- }
+ elsif($In::Opt{"OutputReportPath"})
+ { # --report-path
+ return $In::Opt{"OutputReportPath"};
+ }
+ else
+ { # default
+ return $Dir."/src_compat_report.".$In::Opt{"ReportFormat"};
}
- close(APP);
}
else
{
- my $ReadelfCmd = get_CmdPath("readelf");
- if(not $ReadelfCmd) {
- exitStatus("Not_Found", "can't find \"readelf\"");
- }
- open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
- my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
- while()
- {
- if(defined $symtab)
- { # do nothing with symtab
- if(index($_, "'.dynsym'")!=-1)
- { # dynamic table
- $symtab = undef;
- }
- }
- elsif(index($_, "'.symtab'")!=-1)
- { # symbol table
- $symtab = 1;
- }
- elsif(my @Info = readline_ELF($_))
- {
- my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
- if($Ndx eq "UND")
- { # only imported symbols
- push(@Imported, $Symbol);
- }
- }
- }
- close(APP);
- }
- return @Imported;
-}
-
-my %ELF_BIND = map {$_=>1} (
- "WEAK",
- "GLOBAL"
-);
-
-my %ELF_TYPE = map {$_=>1} (
- "FUNC",
- "IFUNC",
- "OBJECT",
- "COMMON"
-);
-
-my %ELF_VIS = map {$_=>1} (
- "DEFAULT",
- "PROTECTED"
-);
-
-sub readline_ELF($)
-{ # read the line of 'readelf' output corresponding to the symbol
- my @Info = split(/\s+/, $_[0]);
- # Num: Value Size Type Bind Vis Ndx Name
- # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
- # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
- shift(@Info); # spaces
- shift(@Info); # num
-
- if($#Info==7)
- { # UND SYMBOL (N)
- if($Info[7]=~/\(\d+\)/) {
- pop(@Info);
+ if($In::Opt{"OutputReportPath"})
+ { # --report-path
+ return $In::Opt{"OutputReportPath"};
}
- }
-
- if($#Info!=6)
- { # other lines
- return ();
- }
- return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
- return () if(not defined $ELF_BIND{$Info[3]});
- return () if(not defined $ELF_VIS{$Info[4]});
- if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
- { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
- return ();
- }
- if($OStarget eq "symbian")
- { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
- if(index($Info[6], "_._.absent_export_")!=-1)
- { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
- return ();
+ else
+ { # default
+ return $Dir."/compat_report.".$In::Opt{"ReportFormat"};
}
- $Info[6]=~s/\@.+//g; # remove version
- }
- if(index($Info[2], "0x") == 0)
- { # size == 0x3d158
- $Info[2] = hex($Info[2]);
}
- return @Info;
}
-sub get_LibPath($$)
+sub printStatMsg($)
{
- my ($LibVersion, $Name) = @_;
- return "" if(not $LibVersion or not $Name);
- if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
- return $Cache{"get_LibPath"}{$LibVersion}{$Name};
- }
- return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
+ my $Level = $_[0];
+ printMsg("INFO", "Total ".lc($Level)." compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
}
-sub get_LibPath_I($$)
+sub listAffected($)
{
- my ($LibVersion, $Name) = @_;
- if(is_abs($Name))
+ my $Level = $_[0];
+ my $List = "";
+ foreach (keys(%{$TotalAffected{$Level}}))
{
- if(-f $Name)
- { # absolute path
- return $Name;
- }
- else
- { # broken
- return "";
- }
- }
- if(defined $RegisteredObjects{$LibVersion}{$Name})
- { # registered paths
- return $RegisteredObjects{$LibVersion}{$Name};
- }
- if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
- { # registered paths
- return $RegisteredSONAMEs{$LibVersion}{$Name};
- }
- if(my $DefaultPath = $DyLib_DefaultPath{$Name})
- { # ldconfig default paths
- return $DefaultPath;
- }
- foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
- { # search in default linker directories
- # and then in all system paths
- if(-f $Dir."/".$Name) {
- return join_P($Dir,$Name);
+ if($In::Opt{"StrictCompat"} and $TotalAffected{$Level}{$_} eq "Low")
+ { # skip "Low"-severity problems
+ next;
}
+ $List .= "$_\n";
}
- if(not defined $Cache{"checkSystemFiles"}) {
- checkSystemFiles();
- }
- if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
- return $AllObjects[0];
+ my $Dir = getDirname(getReportPath($Level));
+ if($Level eq "Binary") {
+ writeFile($Dir."/abi_affected.txt", $List);
}
- if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
- {
- if($ShortName ne $Name)
- { # FIXME: check this case
- if(my $Path = get_LibPath($LibVersion, $ShortName)) {
- return $Path;
- }
- }
+ elsif($Level eq "Source") {
+ writeFile($Dir."/src_affected.txt", $List);
}
- # can't find
- return "";
}
-sub readSymbols_Lib($$$$$$)
+sub printReport()
{
- my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
- return () if(not $LibVersion or not $Lib_Path);
-
- my $Real_Path = realpath($Lib_Path);
-
- if(not $Real_Path)
- { # broken link
- return ();
- }
+ printMsg("INFO", "Creating compatibility report ...");
- my $Lib_Name = get_filename($Real_Path);
-
- if($ExtraInfo)
- {
- $KnownLibs{$Real_Path} = 1;
- $KnownLibs{$Lib_Path} = 1; # links
- }
+ createReport();
- if($IsNeededLib)
+ if($In::Opt{"JoinReport"} or $In::Opt{"DoubleReport"})
{
- if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
- return ();
- }
- }
- return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
- $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
-
- push(@RecurLib, $Lib_Name);
- my (%Value_Interface, %Interface_Value, %NeededLib) = ();
- my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
-
- if(not $IsNeededLib)
- { # special cases: libstdc++ and libc
- if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
- {
- if($ShortName eq "libstdc++")
- { # libstdc++.so.6
- $STDCXX_TESTING = 1;
- }
- elsif($ShortName eq "libc")
- { # libc-2.11.3.so
- $GLIBC_TESTING = 1;
- }
- }
- }
- my $DebugPath = "";
- if($Debug and not $DumpSystem)
- { # debug mode
- $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
- mkpath(get_dirname($DebugPath));
- }
- if($OStarget eq "macos")
- { # Mac OS X: *.dylib, *.a
- my $NM = get_CmdPath("nm");
- if(not $NM) {
- exitStatus("Not_Found", "can't find \"nm\"");
- }
- $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
- if($DebugPath)
- { # debug mode
- # write to file
- system($NM." >\"$DebugPath\"");
- open(LIB, $DebugPath);
- }
- else
- { # write to pipe
- open(LIB, $NM." |");
- }
- while()
- {
- if($CheckUndefined)
- {
- if(not $IsNeededLib)
- {
- if(/ U _([\w\$]+)\s*\Z/)
- {
- $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
- next;
- }
- }
- }
-
- if(/ [STD] _([\w\$]+)\s*\Z/)
- {
- my $Symbol = $1;
- if($IsNeededLib)
- {
- if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
- {
- $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
- $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
- }
- }
- else
- {
- $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
- $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
- if($COMMON_LANGUAGE{$LibVersion} ne "C++")
- {
- if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
- setLanguage($LibVersion, "C++");
- }
- }
- }
- }
- }
- close(LIB);
-
- if($Deps)
- {
- if($LIB_TYPE eq "dynamic")
- { # dependencies
-
- my $OtoolCmd = get_CmdPath("otool");
- if(not $OtoolCmd) {
- exitStatus("Not_Found", "can't find \"otool\"");
- }
-
- open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
- while()
- {
- if(/\s*([\/\\].+\.$LIB_EXT)\s*/
- and $1 ne $Lib_Path) {
- $NeededLib{$1} = 1;
- }
- }
- close(LIB);
- }
- }
- }
- elsif($OStarget eq "windows")
- { # Windows *.dll, *.lib
- my $DumpBinCmd = get_CmdPath("dumpbin");
- if(not $DumpBinCmd) {
- exitStatus("Not_Found", "can't find \"dumpbin\"");
- }
- $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
- if($DebugPath)
- { # debug mode
- # write to file
- system($DumpBinCmd." >\"$DebugPath\"");
- open(LIB, $DebugPath);
- }
- else
- { # write to pipe
- open(LIB, $DumpBinCmd." |");
- }
- while()
- { # 1197 4AC 0000A620 SetThreadStackGuarantee
- # 1198 4AD SetThreadToken (forwarded to ...)
- # 3368 _o2i_ECPublicKey
- # 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/)
- { # dynamic, static and forwarded symbols
- my $realname = $1;
- if($IsNeededLib)
- {
- if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
- {
- $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
- $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
- }
- }
- else
- {
- $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
- $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
- if($COMMON_LANGUAGE{$LibVersion} ne "C++")
- {
- if(index($realname, "_Z")==0 or index($realname, "?")==0) {
- setLanguage($LibVersion, "C++");
- }
- }
- }
- }
- }
- close(LIB);
-
- if($Deps)
+ if($RESULT{"Binary"}{"Problems"}
+ or $RESULT{"Source"}{"Problems"})
{
- if($LIB_TYPE eq "dynamic")
- { # dependencies
- open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
- while()
- {
- if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
- and $1 ne $Lib_Path) {
- $NeededLib{path_format($1, $OSgroup)} = 1;
- }
- }
- close(LIB);
- }
- }
- }
- else
- { # Unix; *.so, *.a
- # Symbian: *.dso, *.lib
- my $ReadelfCmd = get_CmdPath("readelf");
- if(not $ReadelfCmd) {
- exitStatus("Not_Found", "can't find \"readelf\"");
- }
- my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
- if($DebugPath)
- { # debug mode
- # write to file
- system($Cmd." >\"$DebugPath\"");
- open(LIB, $DebugPath);
+ printMsg("INFO", "Binary compatibility: ".(100-$RESULT{"Binary"}{"Affected"})."\%");
+ printMsg("INFO", "Source compatibility: ".(100-$RESULT{"Source"}{"Affected"})."\%");
}
else
- { # write to pipe
- open(LIB, $Cmd." |");
- }
- my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
- while()
{
- if($LIB_TYPE eq "dynamic")
- { # dynamic library specifics
- if(defined $symtab)
- {
- if(index($_, "'.dynsym'")!=-1)
- { # dynamic table
- $symtab = undef;
- }
- # do nothing with symtab
- next;
- }
- elsif(index($_, "'.symtab'")!=-1)
- { # symbol table
- $symtab = 1;
- next;
- }
- }
- if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
- { # read ELF entry
- if($Ndx eq "UND")
- { # ignore interfaces that are imported from somewhere else
- if($CheckUndefined)
- {
- if(not $IsNeededLib) {
- $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
- }
- }
- next;
- }
- if($Bind eq "WEAK")
- {
- $WeakSymbols{$LibVersion}{$Symbol} = 1;
- if($Weak eq "-Weak")
- { # skip WEAK symbols
- next;
- }
- }
- my $Short = $Symbol;
- $Short=~s/\@.+//g;
- if($Type eq "OBJECT")
- { # global data
- $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
- $GlobalDataObject{$LibVersion}{$Short} = $Size;
- }
- if($IsNeededLib)
- {
- if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
- {
- $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
- $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
- }
- }
- else
- {
- $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
- $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
- if($Vers)
- {
- if($LIB_EXT eq "so")
- { # value
- $Interface_Value{$LibVersion}{$Symbol} = $Value;
- $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
- }
- }
- if($COMMON_LANGUAGE{$LibVersion} ne "C++")
- {
- if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
- setLanguage($LibVersion, "C++");
- }
- }
- }
- }
+ printMsg("INFO", "Binary compatibility: 100\%");
+ printMsg("INFO", "Source compatibility: 100\%");
}
- close(LIB);
+ printStatMsg("Binary");
+ printStatMsg("Source");
- if($Deps and $LIB_TYPE eq "dynamic")
- { # dynamic library specifics
- $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
- open(LIB, $Cmd." |");
-
- while()
- {
- if(/NEEDED.+\[([^\[\]]+)\]/)
- { # dependencies:
- # 0x00000001 (NEEDED) Shared library: [libc.so.6]
- $NeededLib{$1} = 1;
- }
- }
-
- close(LIB);
+ if($In::Opt{"ListAffected"})
+ { # --list-affected
+ listAffected("Binary");
+ listAffected("Source");
}
}
- if($Vers)
+ elsif($In::Opt{"BinOnly"})
{
- if(not $IsNeededLib and $LIB_EXT eq "so")
- { # get symbol versions
- my %Found = ();
-
- # by value
- foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
- {
- next if(index($Symbol,"\@")==-1);
- if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
- {
- foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
- {
- if($Symbol_SameValue ne $Symbol
- and index($Symbol_SameValue,"\@")==-1)
- {
- $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
- $Found{$Symbol} = 1;
- last;
- }
- }
- }
- }
-
- # default
- foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
- {
- next if(defined $Found{$Symbol});
- next if(index($Symbol,"\@\@")==-1);
-
- if($Symbol=~/\A([^\@]*)\@\@/
- and not $SymVer{$LibVersion}{$1})
- {
- $SymVer{$LibVersion}{$1} = $Symbol;
- $Found{$Symbol} = 1;
- }
- }
-
- # non-default
- foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
- {
- next if(defined $Found{$Symbol});
- next if(index($Symbol,"\@")==-1);
-
- if($Symbol=~/\A([^\@]*)\@([^\@]*)/
- and not $SymVer{$LibVersion}{$1})
- {
- $SymVer{$LibVersion}{$1} = $Symbol;
- $Found{$Symbol} = 1;
- }
- }
+ if($RESULT{"Binary"}{"Problems"}) {
+ printMsg("INFO", "Binary compatibility: ".(100-$RESULT{"Binary"}{"Affected"})."\%");
}
- }
- if($Deps)
- {
- foreach my $DyLib (sort keys(%NeededLib))
- {
- $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
-
- if(my $DepPath = get_LibPath($LibVersion, $DyLib))
- {
- if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
- readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
- }
- }
+ else {
+ printMsg("INFO", "Binary compatibility: 100\%");
}
- }
- pop(@RecurLib);
- return $Library_Symbol{$LibVersion};
-}
-
-sub get_prefixes($)
-{
- my %Prefixes = ();
- get_prefixes_I([$_[0]], \%Prefixes);
- return keys(%Prefixes);
-}
-
-sub get_prefixes_I($$)
-{
- foreach my $P (@{$_[0]})
- {
- my @Parts = reverse(split(/[\/\\]+/, $P));
- my $Name = $Parts[0];
- foreach (1 .. $#Parts)
- {
- $_[1]->{$Name}{$P} = 1;
- last if($_>4 or $Parts[$_] eq "include");
- $Name = $Parts[$_].$SLASH.$Name;
+ printStatMsg("Binary");
+
+ if($In::Opt{"ListAffected"})
+ { # --list-affected
+ listAffected("Binary");
}
}
-}
-
-sub checkSystemFiles()
-{
- $Cache{"checkSystemFiles"} = 1;
-
- my @SysHeaders = ();
-
- foreach my $DevelPath (@{$SystemPaths{"lib"}})
+ elsif($In::Opt{"SrcOnly"})
{
- next if(not -d $DevelPath);
-
- my @Files = cmd_find($DevelPath,"f");
- foreach my $Link (cmd_find($DevelPath,"l"))
- { # add symbolic links
- if(-f $Link) {
- push(@Files, $Link);
- }
+ if($RESULT{"Source"}{"Problems"}) {
+ printMsg("INFO", "Source compatibility: ".(100-$RESULT{"Source"}{"Affected"})."\%");
}
+ else {
+ printMsg("INFO", "Source compatibility: 100\%");
+ }
+ printStatMsg("Source");
- # search for headers in /usr/lib
- my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
- @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
- push(@SysHeaders, @Headers);
-
- # search for libraries in /usr/lib (including symbolic links)
- my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
- foreach my $Path (@Libs)
- {
- my $N = get_filename($Path);
- $SystemObjects{$N}{$Path} = 1;
- $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
+ if($In::Opt{"ListAffected"})
+ { # --list-affected
+ listAffected("Source");
}
}
- foreach my $DevelPath (@{$SystemPaths{"include"}})
- {
- next if(not -d $DevelPath);
- # search for all header files in the /usr/include
- # with or without extension (ncurses.h, QtCore, ...)
- push(@SysHeaders, cmd_find($DevelPath,"f"));
- foreach my $Link (cmd_find($DevelPath,"l"))
- { # add symbolic links
- if(-f $Link) {
- push(@SysHeaders, $Link);
- }
- }
- }
- get_prefixes_I(\@SysHeaders, \%SystemHeaders);
-}
-
-sub getSOPaths($)
-{
- my $LibVersion = $_[0];
- my @Paths = ();
- foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
+ if($In::Opt{"StdOut"})
{
- if(not -e $Dest) {
- exitStatus("Access_Error", "can't access \'$Dest\'");
+ if($In::Opt{"JoinReport"} or not $In::Opt{"DoubleReport"})
+ { # --binary or --source
+ printMsg("INFO", "Compatibility report has been generated to stdout");
}
- $Dest = get_abs_path($Dest);
- my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
- foreach (@SoPaths_Dest) {
- push(@Paths, $_);
+ else
+ { # default
+ printMsg("INFO", "Compatibility reports have been generated to stdout");
}
}
- return sort @Paths;
-}
-
-sub skipLib($$)
-{
- my ($Path, $LibVersion) = @_;
- return 1 if(not $Path or not $LibVersion);
- my $Name = get_filename($Path);
- if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
- return 1;
- }
- my $ShortName = parse_libname($Name, "name+ext", $OStarget);
- if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
- return 1;
- }
- foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
+ else
{
- if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
- return 1;
+ if($In::Opt{"JoinReport"})
+ { # default
+ printMsg("INFO", "Report: ".pathFmt(getReportPath("Join")));
}
- }
- foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
- {
- if($Name=~/$P/) {
- return 1;
+ elsif($In::Opt{"DoubleReport"})
+ {
+ printMsg("INFO", "Report (BC): ".pathFmt(getReportPath("Binary")));
+ printMsg("INFO", "Report (SC): ".pathFmt(getReportPath("Source")));
}
- if($P=~/[\/\\]/ and $Path=~/$P/) {
- return 1;
+ elsif($In::Opt{"BinOnly"})
+ { # --binary
+ printMsg("INFO", "Report: ".pathFmt(getReportPath("Binary")));
+ }
+ elsif($In::Opt{"SrcOnly"})
+ { # --source
+ printMsg("INFO", "Report: ".pathFmt(getReportPath("Source")));
}
}
- return 0;
}
-sub specificHeader($$)
+sub unpackDump($)
{
- my ($Header, $Spec) = @_;
- my $Name = get_filename($Header);
+ my $Path = $_[0];
- if($Spec eq "windows")
- {# MS Windows
- return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
- return 1 if($Name=~/([._-]w|win)(32|64)/i);
- return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
- return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
- my @Dirs = (
- "win32",
- "win64",
- "win",
- "windows",
- "msvcrt"
- ); # /gsf-win32/
- if(my $DIRs = join("|", @Dirs)) {
- return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
- }
- }
- elsif($Spec eq "macos")
- { # Mac OS
- return 1 if($Name=~/(\A|[_-])mac[._-]/i);
- }
+ $Path = getAbsPath($Path);
+ my ($Dir, $FileName) = sepPath($Path);
- return 0;
-}
-
-sub skipAlienHeader($)
-{
- my $Path = $_[0];
- my $Name = get_filename($Path);
- my $Dir = get_dirname($Path);
+ my $TmpDir = $In::Opt{"Tmp"};
+ my $UnpackDir = $TmpDir."/unpack";
+ rmtree($UnpackDir);
+ mkpath($UnpackDir);
- if($Tolerance=~/2/)
- { # 2 - skip internal headers
- my @Terms = (
- "p",
- "priv",
- "int",
- "impl",
- "implementation",
- "internal",
- "private",
- "old",
- "compat",
- "debug",
- "test",
- "gen"
- );
-
- my @Dirs = (
- "private",
- "priv",
- "port",
- "impl",
- "internal",
- "detail",
- "details",
- "old",
- "compat",
- "debug",
- "config",
- "compiler",
- "platform",
- "test"
- );
-
- if(my $TERMs = join("|", @Terms)) {
- return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
+ if($FileName=~s/\Q.zip\E\Z//g)
+ { # *.zip
+ my $UnzipCmd = getCmdPath("unzip");
+ if(not $UnzipCmd) {
+ exitStatus("Not_Found", "can't find \"unzip\" command");
}
- if(my $DIRs = join("|", @Dirs)) {
- return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
+ chdir($UnpackDir);
+ system("$UnzipCmd \"$Path\" >\"$TmpDir/null\"");
+ if($?) {
+ exitStatus("Error", "can't extract \'$Path\' ($?): $!");
}
-
- return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
+ chdir($In::Opt{"OrigDir"});
+ my @Contents = cmdFind($UnpackDir, "f");
+ if(not @Contents) {
+ exitStatus("Error", "can't extract \'$Path\'");
+ }
+ return $Contents[0];
}
-
- if($Tolerance=~/1/)
- { # 1 - skip non-Linux headers
- if($OSgroup ne "windows")
- {
- if(specificHeader($Path, "windows")) {
- return 1;
+ elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
+ { # *.tar.gz
+ # *.tar.gz.amd64 (dh & cdbs)
+ if($In::Opt{"OS"} eq "windows")
+ { # -xvzf option is not implemented in tar.exe (2003)
+ # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
+ my $TarCmd = getCmdPath("tar");
+ if(not $TarCmd) {
+ exitStatus("Not_Found", "can't find \"tar\" command");
+ }
+ my $GzipCmd = getCmdPath("gzip");
+ if(not $GzipCmd) {
+ exitStatus("Not_Found", "can't find \"gzip\" command");
+ }
+ chdir($UnpackDir);
+ system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
+ if($?) {
+ exitStatus("Error", "can't extract \'$Path\'");
}
+ system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TmpDir/null\"");
+ if($?) {
+ exitStatus("Error", "can't extract \'$Path\' ($?): $!");
+ }
+ chdir($In::Opt{"OrigDir"});
+ unlink($Dir."/".$FileName.".tar");
+ my @Contents = cmdFind($UnpackDir, "f");
+ if(not @Contents) {
+ exitStatus("Error", "can't extract \'$Path\'");
+ }
+ return $Contents[0];
}
- if($OSgroup ne "macos")
- {
- if(specificHeader($Path, "macos")) {
- return 1;
+ else
+ { # Unix, Mac
+ my $TarCmd = getCmdPath("tar");
+ if(not $TarCmd) {
+ exitStatus("Not_Found", "can't find \"tar\" command");
+ }
+ chdir($UnpackDir);
+ system("$TarCmd -xvzf \"$Path\" >\"$TmpDir/null\"");
+ if($?) {
+ exitStatus("Error", "can't extract \'$Path\' ($?): $!");
+ }
+ chdir($In::Opt{"OrigDir"});
+ my @Contents = cmdFind($UnpackDir, "f");
+ if(not @Contents) {
+ exitStatus("Error", "can't extract \'$Path\'");
}
+ return $Contents[0];
}
}
-
- # valid
- return 0;
}
-sub skipHeader($$)
+sub createArchive($$)
{
- my ($Path, $LibVersion) = @_;
- return 1 if(not $Path or not $LibVersion);
- if(defined $Cache{"skipHeader"}{$Path}) {
- return $Cache{"skipHeader"}{$Path};
+ my ($Path, $To) = @_;
+ if(not $To) {
+ $To = ".";
}
- if(defined $Tolerance and $Tolerance=~/1|2/)
- { # --tolerant
- if(skipAlienHeader($Path)) {
- return ($Cache{"skipHeader"}{$Path} = 1);
+
+ my ($From, $Name) = sepPath($Path);
+ if($In::Opt{"OS"} eq "windows")
+ { # *.zip
+ my $ZipCmd = getCmdPath("zip");
+ if(not $ZipCmd) {
+ exitStatus("Not_Found", "can't find \"zip\"");
}
- }
- if(not keys(%{$SkipHeaders{$LibVersion}})) {
- return 0;
- }
- return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
-}
-
-sub skipHeader_I($$)
-{ # returns:
- # 1 - if header should NOT be included and checked
- # 2 - if header should NOT be included, but should be checked
- my ($Path, $LibVersion) = @_;
- my $Name = get_filename($Path);
- if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
- return $Kind;
- }
- foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
- keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
- {
- if(index($Path, $D)!=-1)
- {
- if($Path=~/\Q$D\E([\/\\]|\Z)/) {
- return $SkipHeaders{$LibVersion}{"Path"}{$D};
- }
+ my $Pkg = $To."/".$Name.".zip";
+ unlink($Pkg);
+ chdir($To);
+ system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"".$In::Opt{"Tmp"}."/null\"");
+ if($?)
+ { # cannot allocate memory (or other problems with "zip")
+ chdir($In::Opt{"OrigDir"});
+ exitStatus("Error", "can't pack the ABI dump: ".$!);
}
+ chdir($In::Opt{"OrigDir"});
+ unlink($Path);
+ return $Pkg;
}
- foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
- keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
- {
- if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
- {
- if($Name=~/$P/) {
- return $Kind;
- }
- if($P=~/[\/\\]/ and $Path=~/$P/) {
- return $Kind;
- }
+ else
+ { # *.tar.gz
+ my $TarCmd = getCmdPath("tar");
+ if(not $TarCmd) {
+ exitStatus("Not_Found", "can't find \"tar\"");
}
+ my $GzipCmd = getCmdPath("gzip");
+ if(not $GzipCmd) {
+ exitStatus("Not_Found", "can't find \"gzip\"");
+ }
+ my $Pkg = abs_path($To)."/".$Name.".tar.gz";
+ if(-e $Pkg) {
+ unlink($Pkg);
+ }
+ system($TarCmd, "-C", $From, "-czf", $Pkg, $Name);
+ if($?)
+ { # cannot allocate memory (or other problems with "tar")
+ exitStatus("Error", "can't pack the ABI dump: ".$!);
+ }
+ unlink($Path);
+ return $To."/".$Name.".tar.gz";
}
-
- return 0;
}
-sub registerObject_Dir($$)
+sub defaultDumpPath($$)
{
- my ($Dir, $LibVersion) = @_;
- if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
- { # system directory
- return;
- }
- if($RegisteredObject_Dirs{$LibVersion}{$Dir})
- { # already registered
- return;
- }
- foreach my $Path (find_libs($Dir,"",1))
- {
- next if(ignore_path($Path));
- next if(skipLib($Path, $LibVersion));
- registerObject($Path, $LibVersion);
- }
- $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
+ my ($N, $V) = @_;
+ return "abi_dumps/".$N."/".$V."/ABI.dump";
}
-sub registerObject($$)
+sub createABIFile($$)
{
- my ($Path, $LibVersion) = @_;
-
- my $Name = get_filename($Path);
- $RegisteredObjects{$LibVersion}{$Name} = $Path;
- if($OStarget=~/linux|bsd/i)
- {
- if(my $SONAME = getSONAME($Path)) {
- $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
- }
- }
- if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
- $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
- }
+ my ($LVer, $DescPath) = @_;
- if(not $CheckedArch{$LibVersion} and -f $Path)
- {
- if(my $ObjArch = getArch_Object($Path))
- {
- if($ObjArch ne getArch_GCC($LibVersion))
- { # translation unit dump generated by the GCC compiler should correspond to the input objects
- $CheckedArch{$LibVersion} = 1;
- printMsg("WARNING", "the architectures of input objects and the used GCC compiler are not equal, please change the compiler by --gcc-path=PATH option.");
- }
- }
+ if(not -e $DescPath) {
+ exitStatus("Access_Error", "can't access \'$DescPath\'");
}
-}
-
-sub getArch_Object($)
-{
- my $Path = $_[0];
- my %MachineType = (
- "14C" => "x86",
- "8664" => "x86_64",
- "1C0" => "arm",
- "200" => "ia64"
- );
+ detectDefaultPaths(undef, undef, "bin", undef);
- my %ArchName = (
- "s390:31-bit" => "s390",
- "s390:64-bit" => "s390x",
- "powerpc:common" => "ppc32",
- "powerpc:common64" => "ppc64",
- "i386:x86-64" => "x86_64",
- "mips:3000" => "mips",
- "sparc:v8plus" => "sparcv9"
- );
-
- if($OStarget eq "windows")
+ if(isDump($DescPath))
{
- my $DumpbinCmd = get_CmdPath("dumpbin");
- if(not $DumpbinCmd) {
- exitStatus("Not_Found", "can't find \"dumpbin\"");
- }
-
- my $Cmd = $DumpbinCmd." /headers \"$Path\"";
- my $Out = `$Cmd`;
+ $In::ABI{$LVer} = readABIDump($LVer, $DescPath);
+ initAliases($LVer);
- if($Out=~/(\w+)\smachine/)
- {
- if(my $Type = $MachineType{uc($1)})
- {
- return $Type;
- }
+ if(my $V = $In::Desc{$LVer}{"TargetVersion"}) {
+ $In::Desc{$LVer}{"Version"} = $V;
+ }
+ else {
+ $In::Desc{$LVer}{"Version"} = $In::ABI{$LVer}{"LibraryVersion"};
}
}
- elsif($OStarget=~/linux|bsd/)
+ else
{
- my $ObjdumpCmd = get_CmdPath("objdump");
- if(not $ObjdumpCmd) {
- exitStatus("Not_Found", "can't find \"objdump\"");
- }
+ loadModule("ABIDump");
+ readDesc(createDesc($DescPath, $LVer), $LVer);
- my $Cmd = $ObjdumpCmd." -f \"$Path\"";
+ initLogging($LVer);
- if($OSgroup eq "windows") {
- $Cmd = "set LANG=$LOCALE & ".$Cmd;
- }
- else {
- $Cmd = "LANG=$LOCALE ".$Cmd;
- }
- my $Out = `$Cmd`;
-
- if($Out=~/architecture:\s+([\w\-\:]+)/)
+ if($In::Opt{"Debug"})
{
- my $Arch = $1;
- if($Arch=~s/\:(.+)//)
- {
- my $Suffix = $1;
-
- if(my $Name = $ArchName{$Arch.":".$Suffix})
- {
- $Arch = $Name;
- }
- }
-
- if($Arch=~/i[3-6]86/) {
- $Arch = "x86";
- }
-
- if($Arch eq "x86-64") {
- $Arch = "x86_64";
- }
-
- if($Arch eq "ia64-elf64") {
- $Arch = "ia64";
+ if(not $In::Opt{"ExtraInfo"}) {
+ $In::Opt{"ExtraInfo"} = getExtraDir($LVer);
}
-
- return $Arch;
}
- }
- else
- { # macos, etc.
- # TODO
+
+ detectDefaultPaths("inc", "lib", undef, "gcc");
+ createABIDump($LVer);
}
- return undef;
-}
-
-sub getSONAME($)
-{
- my $Path = $_[0];
- return if(not $Path);
- if(defined $Cache{"getSONAME"}{$Path}) {
- return $Cache{"getSONAME"}{$Path};
- }
- my $ObjdumpCmd = get_CmdPath("objdump");
- if(not $ObjdumpCmd) {
- exitStatus("Not_Found", "can't find \"objdump\"");
- }
- my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
- if($OSgroup eq "windows") {
- $SonameCmd .= " | find \"SONAME\"";
- }
- else {
- $SonameCmd .= " | grep SONAME";
- }
- if(my $SonameInfo = `$SonameCmd`)
- {
- if($SonameInfo=~/SONAME\s+([^\s]+)/) {
- return ($Cache{"getSONAME"}{$Path} = $1);
- }
- }
- return ($Cache{"getSONAME"}{$Path}="");
-}
-
-sub getSOPaths_Dest($$)
-{
- my ($Dest, $LibVersion) = @_;
- if(skipLib($Dest, $LibVersion)) {
- return ();
- }
- if(-f $Dest)
- {
- if(not parse_libname($Dest, "name", $OStarget)) {
- exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
- }
- registerObject($Dest, $LibVersion);
- registerObject_Dir(get_dirname($Dest), $LibVersion);
- return ($Dest);
- }
- elsif(-d $Dest)
- {
- $Dest=~s/[\/\\]+\Z//g;
- my %Libs = ();
- if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
- { # you have specified /usr/lib as the search directory () in the XML descriptor
- # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
- foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
- { # all files and symlinks that match the name of a library
- if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
- {
- registerObject($Path, $LibVersion);
- $Libs{realpath($Path)}=1;
- }
- }
- }
- else
- { # search for all files and symlinks
- foreach my $Path (find_libs($Dest,"",""))
- {
- next if(ignore_path($Path));
- next if(skipLib($Path, $LibVersion));
- registerObject($Path, $LibVersion);
- $Libs{realpath($Path)}=1;
- }
- if($OSgroup eq "macos")
- { # shared libraries on MacOS X may have no extension
- foreach my $Path (cmd_find($Dest,"f"))
- {
- next if(ignore_path($Path));
- next if(skipLib($Path, $LibVersion));
- if(get_filename($Path)!~/\./
- and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
- {
- registerObject($Path, $LibVersion);
- $Libs{realpath($Path)}=1;
- }
- }
- }
- }
- return keys(%Libs);
- }
- else {
- return ();
- }
-}
-
-sub isCyclical($$)
-{
- my ($Stack, $Value) = @_;
- return (grep {$_ eq $Value} @{$Stack});
-}
-
-sub getGCC_Opts($)
-{ # to use in module
- my $LibVersion = $_[0];
+ clearSysFilesCache($LVer);
- my @Opts = ();
+ printMsg("INFO", "Creating library ABI dump ...");
- if($CompilerOptions{$LibVersion})
- { # user-defined options
- push(@Opts, $CompilerOptions{$LibVersion});
- }
- if($GccOptions)
- { # additional
- push(@Opts, $GccOptions);
- }
+ $In::ABI{$LVer}{"ABI_DUMP_VERSION"} = $ABI_DUMP_VERSION;
+ $In::ABI{$LVer}{"ABI_COMPLIANCE_CHECKER_VERSION"} = $TOOL_VERSION;
- if(@Opts) {
- return join(" ", @Opts);
+ if($In::Opt{"UseXML"}) {
+ $In::ABI{$LVer}{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
}
- return undef;
-}
-
-sub getArch_GCC($)
-{
- my $LibVersion = $_[0];
+ $In::ABI{$LVer}{"TargetHeaders"} = $In::Desc{$LVer}{"TargetHeader"};
- if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
- return $Cache{"getArch_GCC"}{$LibVersion};
+ foreach ("SymLib", "DepSymLib", "TName_Tid", "TypeTypedef",
+ "TypedefBase", "Class_SubClasses", "ClassVTable") {
+ delete($In::ABI{$LVer}{$_});
}
- my $Arch = undef;
-
- if($GCC_PATH)
- {
- writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
-
- my $Cmd = $GCC_PATH." test.c -o test";
- if(my $Opts = getGCC_Opts($LibVersion))
- { # user-defined options
- $Cmd .= " ".$Opts;
- }
-
- chdir($TMP_DIR);
- system($Cmd);
- chdir($ORIG_DIR);
-
- $Arch = getArch_Object("$TMP_DIR/test");
-
- unlink("$TMP_DIR/test.c");
- unlink("$TMP_DIR/test");
- }
-
- if(not $Arch) {
- exitStatus("Error", "can't check ARCH type");
+ my $DumpPath = defaultDumpPath($In::Opt{"TargetLib"}, $In::Desc{1}{"Version"});
+ if($In::Opt{"OutputDumpPath"})
+ { # user defined path
+ $DumpPath = $In::Opt{"OutputDumpPath"};
}
- return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
-}
-
-sub detectWordSize($)
-{
- my $LibVersion = $_[0];
-
- my $Size = undef;
+ my $ArExt = $In::Opt{"Ar"};
+ my $Archive = ($DumpPath=~s/\Q.$ArExt\E\Z//g);
- # speed up detection
- if(my $Arch = getArch($LibVersion))
- {
- if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
- $Size = "8";
+ if($Archive and not $In::Opt{"StdOut"})
+ { # check archive utilities
+ if($In::Opt{"OS"} eq "windows")
+ { # using zip
+ my $ZipCmd = getCmdPath("zip");
+ if(not $ZipCmd) {
+ exitStatus("Not_Found", "can't find \"zip\"");
+ }
}
- elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
- $Size = "4";
+ else
+ { # using tar and gzip
+ my $TarCmd = getCmdPath("tar");
+ if(not $TarCmd) {
+ exitStatus("Not_Found", "can't find \"tar\"");
+ }
+ my $GzipCmd = getCmdPath("gzip");
+ if(not $GzipCmd) {
+ exitStatus("Not_Found", "can't find \"gzip\"");
+ }
}
}
- if($GCC_PATH)
+ my $ABI_DUMP = "";
+ if($In::Opt{"UseXML"})
{
- writeFile("$TMP_DIR/empty.h", "");
-
- my $Cmd = $GCC_PATH." -E -dD empty.h";
- if(my $Opts = getGCC_Opts($LibVersion))
- { # user-defined options
- $Cmd .= " ".$Opts;
+ loadModule("XmlDump");
+ $ABI_DUMP = createXmlDump($LVer);
+ }
+ else
+ { # default
+ $ABI_DUMP = Dumper($In::ABI{$LVer});
+ }
+ if($In::Opt{"StdOut"})
+ {
+ print STDOUT $ABI_DUMP;
+ printMsg("INFO", "ABI dump has been generated to stdout");
+ return;
+ }
+ else
+ { # to file
+ my ($DDir, $DName) = sepPath($DumpPath);
+ my $DPath = $In::Opt{"Tmp"}."/".$DName;
+ if(not $Archive) {
+ $DPath = $DumpPath;
}
- chdir($TMP_DIR);
- my $Defines = `$Cmd`;
- chdir($ORIG_DIR);
+ mkpath($DDir);
- unlink("$TMP_DIR/empty.h");
+ open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
+ print DUMP $ABI_DUMP;
+ close(DUMP);
- if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
- { # GCC 4
- $Size = $1;
+ if(not -s $DPath) {
+ exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
}
- elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
- { # GCC 3
- my $PTRDIFF = $1;
- if($PTRDIFF=~/long/) {
- $Size = "8";
- }
- else {
- $Size = "4";
- }
+ if($Archive) {
+ $DumpPath = createArchive($DPath, $DDir);
}
+
+ printMsg("INFO", "Dump path: ".pathFmt($DumpPath));
}
-
- if(not $Size) {
- exitStatus("Error", "can't check WORD size");
- }
-
- return $Size;
-}
-
-sub getWordSize($)
-{ # to use in module
- return $WORD_SIZE{$_[0]};
-}
-
-sub majorVersion($)
-{
- my $V = $_[0];
- return 0 if(not $V);
- my @VParts = split(/\./, $V);
- return $VParts[0];
-}
-
-sub cmpVersions($$)
-{ # compare two versions in dotted-numeric format
- my ($V1, $V2) = @_;
- return 0 if($V1 eq $V2);
- my @V1Parts = split(/\./, $V1);
- my @V2Parts = split(/\./, $V2);
- for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
- {
- return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
- return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
- }
- return -1 if($#V1Parts < $#V2Parts);
- return 1 if($#V1Parts > $#V2Parts);
- return 0;
}
-sub read_ABI_Dump($$)
+sub readABIDump($$)
{
- my ($LibVersion, $Path) = @_;
- return if(not $LibVersion or not -e $Path);
+ my ($LVer, $Path) = @_;
+
my $FilePath = "";
if(isDump_U($Path))
{ # input *.abi
@@ -19820,13 +9558,13 @@
}
}
- my $ABI = {};
+ my $ABIRef = {};
my $Line = readLineNum($FilePath, 0);
if($Line=~/xml/)
{ # XML format
loadModule("XmlDump");
- $ABI = readXmlDump($FilePath);
+ $ABIRef = readXmlDump($FilePath);
}
else
{ # Perl Data::Dumper format (default)
@@ -19835,2433 +9573,496 @@
my $Content = ;
close(DUMP);
- if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
+ if(getDirname($FilePath) eq $In::Opt{"Tmp"}."/unpack")
{ # remove temp file
unlink($FilePath);
}
if($Content!~/};\s*\Z/) {
exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
}
- $ABI = eval($Content);
- if(not $ABI) {
+ $ABIRef = eval($Content);
+ if(not $ABIRef) {
exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
}
}
- # new dumps (>=1.22) have a personal versioning
- my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
- my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
- if(not $DVersion)
- { # old dumps (<=1.21.6) have been marked by the tool version
- $DVersion = $ToolVersion;
- }
- $UsedDump{$LibVersion}{"V"} = $DVersion;
- $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
- if($ABI->{"PublicABI"}) {
- $UsedDump{$LibVersion}{"Public"} = 1;
- }
+ my $ABIVer = $ABIRef->{"ABI_DUMP_VERSION"};
- if($ABI->{"ABI_DUMP_VERSION"})
+ if($ABIVer)
{
- if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
- { # Don't know how to parse future dump formats
- exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
- }
- }
- else
- { # support for old ABI dumps
- if(cmpVersions($DVersion, $TOOL_VERSION)>0)
- { # Don't know how to parse future dump formats
- exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
+ if(cmpVersions($ABIVer, $ABI_DUMP_VERSION)>0)
+ { # future formats
+ exitStatus("Dump_Version", "the versions of the ABI dump is newer than version of the tool");
}
}
- if(majorVersion($DVersion)<2)
- {
- exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)");
+ if(cmpVersions($ABIVer, $ABI_DUMP_VERSION_MIN)<0) {
+ exitStatus("Dump_Version", "the version of the ABI dump is too old and unsupported anymore, please regenerate it");
}
- if(defined $ABI->{"ABI_DUMPER_VERSION"})
+ if(defined $ABIRef->{"ABI_DUMPER_VERSION"})
{ # DWARF ABI Dump
- $UseConv_Real{$LibVersion}{"P"} = 1;
- $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
+ $UseConv_Real{$LVer}{"P"} = 1;
+ $UseConv_Real{$LVer}{"R"} = 0; # not implemented yet
- $UsedDump{$LibVersion}{"DWARF"} = 1;
+ $UsedDump{$LVer}{"DWARF"} = 1;
- if(not $TargetComponent_Opt)
- {
- if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
- $TargetComponent = "module";
- }
- else {
- $TargetComponent = "object";
- }
+ if($ABIRef->{"LibraryName"}=~/\.ko(\.|\Z)/) {
+ $In::Opt{"TargetComponent"} = "module";
+ }
+ else {
+ $In::Opt{"TargetComponent"} = "object";
}
}
- if(not checkDump($LibVersion, "2.11"))
- { # old ABI dumps
- $UsedDump{$LibVersion}{"BinOnly"} = 1;
+ if(index($ABIRef->{"LibraryName"}, "libstdc++")==0
+ or index($ABIRef->{"LibraryName"}, "libc++")==0) {
+ $In::Opt{"StdcxxTesting"} = 1;
}
- elsif($ABI->{"BinOnly"})
+
+ if($ABIRef->{"BinOnly"})
{ # ABI dump created with --binary option
- $UsedDump{$LibVersion}{"BinOnly"} = 1;
+ $UsedDump{$LVer}{"BinOnly"} = 1;
}
else
{ # default
- $UsedDump{$LibVersion}{"SrcBin"} = 1;
+ $UsedDump{$LVer}{"SrcBin"} = 1;
}
- if(defined $ABI->{"Mode"}
- and $ABI->{"Mode"} eq "Extended")
+ if(defined $ABIRef->{"Mode"}
+ and $ABIRef->{"Mode"} eq "Extended")
{ # --ext option
- $ExtendedCheck = 1;
- }
- if($ABI->{"Extra"}) {
- $ExtraDump = 1;
+ $In::Opt{"ExtendedCheck"} = 1;
}
- if(my $Lang = $ABI->{"Language"})
- {
- $UsedDump{$LibVersion}{"L"} = $Lang;
- setLanguage($LibVersion, $Lang);
- }
- if(checkDump($LibVersion, "2.15")) {
- $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
- }
- else
- { # support for old ABI dumps
- my $TInfo = $ABI->{"TypeInfo"};
- if(not $TInfo)
- { # support for older ABI dumps
- $TInfo = $ABI->{"TypeDescr"};
- }
- my %Tid_TDid = ();
- foreach my $TDid (keys(%{$TInfo}))
- {
- foreach my $Tid (keys(%{$TInfo->{$TDid}}))
- {
- $MAX_ID = $Tid if($Tid>$MAX_ID);
- $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
- $Tid_TDid{$Tid}{$TDid} = 1;
- }
- }
- my %NewID = ();
- foreach my $Tid (keys(%Tid_TDid))
- {
- my @TDids = keys(%{$Tid_TDid{$Tid}});
- if($#TDids>=1)
- {
- foreach my $TDid (@TDids)
- {
- if($TDid) {
- %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
- }
- else
- {
- my $ID = ++$MAX_ID;
-
- $NewID{$TDid}{$Tid} = $ID;
- %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
- $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
- }
- }
- }
- else
- {
- my $TDid = $TDids[0];
- %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
- }
- }
- foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
- {
- my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
- if(defined $Info{"BaseType"})
- {
- my $Bid = $Info{"BaseType"}{"Tid"};
- my $BDid = $Info{"BaseType"}{"TDid"};
- $BDid="" if(not defined $BDid);
- delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
- if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
- $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
- }
- }
- delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
- }
- }
- read_Machine_DumpInfo($ABI, $LibVersion);
- $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
- if(not $SymbolInfo{$LibVersion})
- { # support for old dumps
- $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
+ if($ABIRef->{"Extra"}) {
+ $In::Opt{"ExtraDump"} = 1;
}
- if(not keys(%{$SymbolInfo{$LibVersion}}))
+
+ if(not keys(%{$ABIRef->{"SymbolInfo"}}))
{ # validation of old-version dumps
- if(not $ExtendedCheck) {
- exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
- }
- }
- if(checkDump($LibVersion, "2.15")) {
- $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
- }
- else
- { # support for old ABI dumps
- my $DepSymbols = $ABI->{"DepSymbols"};
- if(not $DepSymbols) {
- $DepSymbols = $ABI->{"DepInterfaces"};
- }
- if(not $DepSymbols)
- { # Cannot reconstruct DepSymbols. This may result in false
- # positives if the old dump is for library 2. Not a problem if
- # old dumps are only from old libraries.
- $DepSymbols = {};
- }
- foreach my $Symbol (keys(%{$DepSymbols})) {
- $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
+ if(not $In::Opt{"ExtendedCheck"}) {
+ exitStatus("Invalid_Dump", "no symbols info in the ABI dump");
}
}
- $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
- if(my $V = $TargetVersion{$LibVersion}) {
- $Descriptor{$LibVersion}{"Version"} = $V;
- }
- else {
- $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
- }
-
- if(not $SkipTypes{$LibVersion})
- { # if not defined by -skip-types option
- if(defined $ABI->{"SkipTypes"})
- {
- foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
- {
- $SkipTypes{$LibVersion}{$TName} = 1;
- }
- }
- if(defined $ABI->{"OpaqueTypes"})
- { # support for old dumps
- foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
- {
- $SkipTypes{$LibVersion}{$TName} = 1;
- }
+ if(defined $ABIRef->{"GccConstants"})
+ { # support for 3.0
+ foreach my $Name (keys(%{$ABIRef->{"GccConstants"}})) {
+ $ABIRef->{"Constants"}{$Name}{"Value"} = $ABIRef->{"GccConstants"}{$Name};
}
}
-
- if(not $SkipSymbols{$LibVersion})
- { # if not defined by -skip-symbols option
- $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
- if(not $SkipSymbols{$LibVersion})
- { # support for old dumps
- $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
- }
- if(not $SkipSymbols{$LibVersion})
- { # support for old dumps
- $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
+ elsif(defined $ABIRef->{"CompilerConstants"})
+ {
+ foreach my $Name (keys(%{$ABIRef->{"CompilerConstants"}})) {
+ $ABIRef->{"Constants"}{$Name}{"Value"} = $ABIRef->{"CompilerConstants"}{$Name};
}
}
- $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
-
- if(not $TargetHeaders{$LibVersion})
- { # if not defined by -headers-list option
- $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
- }
- foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
- {
- $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
- my ($CPath, $Type) = classifyPath($Path);
- $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
+ if(not $ABIRef->{"SymbolVersion"}) {
+ $ABIRef->{"SymbolVersion"} = $ABIRef->{"SymVer"};
}
- read_Source_DumpInfo($ABI, $LibVersion);
- read_Libs_DumpInfo($ABI, $LibVersion);
-
- if(not checkDump($LibVersion, "2.10.1")
- or not $TargetHeaders{$LibVersion})
- { # support for old ABI dumps: added target headers
- foreach (keys(%{$Registered_Headers{$LibVersion}})) {
- $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
- }
-
- if(not $ABI->{"PublicABI"})
- {
- foreach (keys(%{$Registered_Sources{$LibVersion}})) {
- $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
- }
- }
- }
- $Constants{$LibVersion} = $ABI->{"Constants"};
- if(defined $ABI->{"GccConstants"})
- { # 3.0
- foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
- $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
- }
+ if(defined $ABIRef->{"TargetHeaders"}) {
+ $In::Desc{$LVer}{"TargetHeader"} = $ABIRef->{"TargetHeaders"};
}
- $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
- if(not $NestedNameSpaces{$LibVersion})
- { # support for old dumps
- # Cannot reconstruct NameSpaces. This may affect design
- # of the compatibility report.
- $NestedNameSpaces{$LibVersion} = {};
- }
- # target system type
- # needed to adopt HTML report
- if(not $DumpSystem)
- { # to use in createSymbolsList(...)
- $OStarget = $ABI->{"Target"};
- }
- # recreate environment
- foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
+ foreach my $LName (keys(%{$ABIRef->{"Symbols"}}))
{
- foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
- {
- $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
- if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
- { # data marked as -size in the dump
- $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
- }
- if($COMMON_LANGUAGE{$LibVersion} ne "C++")
- {
- if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
- setLanguage($LibVersion, "C++");
- }
- }
- }
- }
- foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
- {
- foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
- $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
+ foreach my $Symbol (keys(%{$ABIRef->{"Symbols"}{$LName}})) {
+ $ABIRef->{"SymLib"}{$Symbol} = $LName;
}
}
- my @VFunc = ();
- foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
+ foreach my $LName (keys(%{$ABIRef->{"DepSymbols"}}))
{
- if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
- {
- if(not $Symbol_Library{$LibVersion}{$MnglName}
- and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
- push(@VFunc, $MnglName);
- }
+ foreach my $Symbol (keys(%{$ABIRef->{"DepSymbols"}{$LName}})) {
+ $ABIRef->{"DepSymLib"}{$Symbol} = $LName;
}
}
- translateSymbols(@VFunc, $LibVersion);
- translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
- translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
- if(not checkDump($LibVersion, "3.0"))
- { # support for old ABI dumps
- foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
- {
- if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
- {
- if(ref($BaseType) eq "HASH") {
- $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
- }
- }
- }
- }
+ $In::Opt{"Target"} = $ABIRef->{"Target"};
+ $In::Desc{$LVer}{"Dump"} = 1;
- if(not checkDump($LibVersion, "3.2"))
- { # support for old ABI dumps
- foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
- {
- if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
- {
- foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
- $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
- }
- }
- }
-
- # repair target headers list
- delete($TargetHeaders{$LibVersion});
- foreach (keys(%{$Registered_Headers{$LibVersion}})) {
- $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
- }
- foreach (keys(%{$Registered_Sources{$LibVersion}})) {
- $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
- }
-
- # non-target constants from anon enums
- foreach my $Name (keys(%{$Constants{$LibVersion}}))
- {
- if(not $ExtraDump
- and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
- {
- delete($Constants{$LibVersion}{$Name});
- }
- }
- }
+ return $ABIRef;
+}
+
+sub prepareCompare($)
+{
+ my $LVer = $_[0];
- if(not checkDump($LibVersion, "2.20"))
- { # support for old ABI dumps
- foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
+ foreach my $Lib_Name (keys(%{$In::ABI{$LVer}{"Symbols"}}))
+ {
+ foreach my $Symbol (keys(%{$In::ABI{$LVer}{"Symbols"}{$Lib_Name}}))
{
- my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
-
- if($TType=~/Struct|Union|Enum|Typedef/)
- { # repair complex types first
- next;
- }
-
- if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
- {
- my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
- if($BType=~/Struct|Union|Enum/i)
- {
- my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
- $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
+ if($In::ABI{$LVer}{"Symbols"}{$Lib_Name}{$Symbol}<0)
+ { # data marked as -size in the dump
+ $GlobalDataObject{$LVer}{$Symbol} = -$In::ABI{$LVer}{"Symbols"}{$Lib_Name}{$Symbol};
+
+ if($Symbol=~/\A(.+?)\@.+/) {
+ $GlobalDataObject{$LVer}{$1} = $GlobalDataObject{$LVer}{$Symbol};
}
}
}
- foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
- {
- my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
- my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
- if($TType=~/Struct|Union|Enum/) {
- $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
- }
- }
}
- 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"}}))
- {
- if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
- {
- if($Access ne "public") {
- $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
- }
- }
- $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
- }
- delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
- }
- if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
- { # support for old ABI dumps
- $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
- }
- elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
- { # DWARF ABI Dumps
- $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
- }
- if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
- $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
- }
- my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
- if(defined $TInfo{"Base"})
- {
- foreach (keys(%{$TInfo{"Base"}})) {
- $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
- }
+ foreach my $TypeId (sort {$a<=>$b} keys(%{$TypeInfo{$LVer}}))
+ { # NOTE: order is important
+ if(not defined $TypeInfo{$LVer}{$TypeId}{"Tid"}) {
+ $TypeInfo{$LVer}{$TypeId}{"Tid"} = $TypeId;
}
- if($TInfo{"Type"} eq "MethodPtr")
+
+ my $TInfo = $TypeInfo{$LVer}{$TypeId};
+ if(defined $TInfo->{"Base"})
{
- if(defined $TInfo{"Param"})
- { # support for old ABI dumps <= 1.17
- if(not defined $TInfo{"Param"}{"0"})
- {
- my $Max = keys(%{$TInfo{"Param"}});
- foreach my $Pos (1 .. $Max) {
- $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
- }
- delete($TInfo{"Param"}{$Max});
- %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
+ foreach my $SubId (keys(%{$TInfo->{"Base"}}))
+ {
+ if($SubId eq $TypeId)
+ { # Fix erroneus ABI dump
+ delete($TypeInfo{$LVer}{$TypeId}{"Base"}{$SubId});
+ next;
}
+
+ $In::ABI{$LVer}{"Class_SubClasses"}{$SubId}{$TypeId} = 1;
}
}
- if($TInfo{"BaseType"} eq $TypeId)
+
+ if($TInfo->{"BaseType"} eq $TypeId)
{ # fix ABI dump
- delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
+ delete($TypeInfo{$LVer}{$TypeId}{"BaseType"});
}
- if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
+
+ if($TInfo->{"Type"} eq "Typedef" and not $TInfo->{"Artificial"})
{
- if(my $BTid = $TInfo{"BaseType"})
+ if(my $BTid = $TInfo->{"BaseType"})
{
- my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
+ my $BName = $TypeInfo{$LVer}{$BTid}{"Name"};
if(not $BName)
{ # broken type
next;
}
- if($TInfo{"Name"} eq $BName)
+ if($TInfo->{"Name"} eq $BName)
{ # typedef to "class Class"
# should not be registered in TName_Tid
next;
}
- if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
- $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
+ if(not $In::ABI{$LVer}{"TypedefBase"}{$TInfo->{"Name"}}) {
+ $In::ABI{$LVer}{"TypedefBase"}{$TInfo->{"Name"}} = $BName;
}
}
}
- if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
+ if(not $TName_Tid{$LVer}{$TInfo->{"Name"}})
{ # classes: class (id1), typedef (artificial, id2 > id1)
- $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
- }
- }
-
- if(not checkDump($LibVersion, "2.15"))
- { # support for old ABI dumps
- my %Dups = ();
- foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
- {
- if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
- {
- if(not defined $TypeInfo{$LibVersion}{$ClassId})
- { # remove template decls
- delete($SymbolInfo{$LibVersion}{$InfoId});
- next;
- }
- }
- my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
- if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
- { # templates
- delete($SymbolInfo{$LibVersion}{$InfoId});
- }
+ $TName_Tid{$LVer}{$TInfo->{"Name"}} = $TypeId;
}
}
-
- foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
- {
- if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
- and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
- and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
- { # support for old ABI dumps (< 3.1)
- if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
- or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
- { # add "this" first parameter
- my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
- my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
-
- if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
- {
- my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
- foreach my $Pos (reverse(0 .. $#Pos)) {
- %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
- }
- }
- $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
- }
- }
-
- if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
- { # ABI dumps have no mangled names for C-functions
- $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
- }
- if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
- { # support for old ABI dumps
- $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
- }
- elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
- { # DWARF ABI Dumps
- $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
- }
- }
-
- $Descriptor{$LibVersion}{"Dump"} = 1;
}
-sub read_Machine_DumpInfo($$)
+sub compareABIDumps($$)
{
- my ($ABI, $LibVersion) = @_;
- if($ABI->{"Arch"}) {
- $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
- }
- if($ABI->{"WordSize"}) {
- $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
- }
- else
- { # support for old dumps
- $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
- }
- if(not $WORD_SIZE{$LibVersion})
- { # support for old dumps (<1.23)
- if(my $Tid = getTypeIdByName("char*", $LibVersion))
- { # size of char*
- $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
- }
- else
- {
- my $PSize = 0;
- foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
- {
- if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
- { # any "pointer"-type
- $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
- last;
- }
- }
- if($PSize)
- { # a pointer type size
- $WORD_SIZE{$LibVersion} = $PSize;
- }
- else {
- printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
- }
- }
- }
- if($ABI->{"GccVersion"}) {
- $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
- }
-}
-
-sub read_Libs_DumpInfo($$)
-{
- my ($ABI, $LibVersion) = @_;
- $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
- if(not $Library_Symbol{$LibVersion})
- { # support for old dumps
- $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
- }
- if(keys(%{$Library_Symbol{$LibVersion}})
- and not $DumpAPI) {
- $Descriptor{$LibVersion}{"Libs"} = "OK";
- }
-}
-
-sub read_Source_DumpInfo($$)
-{
- my ($ABI, $LibVersion) = @_;
+ my ($V1, $V2) = @_;
+ my $DumpPath1 = defaultDumpPath($In::Opt{"TargetLib"}, $V1);
+ my $DumpPath2 = defaultDumpPath($In::Opt{"TargetLib"}, $V2);
- if(keys(%{$ABI->{"Headers"}})
- and not $DumpAPI) {
- $Descriptor{$LibVersion}{"Headers"} = "OK";
- }
- foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
- {
- $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
- $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
- }
+ unlink($DumpPath1);
+ unlink($DumpPath2);
- if(keys(%{$ABI->{"Sources"}})
- and not $DumpAPI) {
- $Descriptor{$LibVersion}{"Sources"} = "OK";
- }
- foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
- {
- $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
- $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
- }
-}
-
-sub find_libs($$$)
-{
- my ($Path, $Type, $MaxDepth) = @_;
- # FIXME: correct the search pattern
- return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
-}
-
-sub createDescriptor($$)
-{
- my ($LibVersion, $Path) = @_;
- if(not $LibVersion or not $Path
- or not -e $Path) {
- return "";
- }
- if(-d $Path)
- { # directory with headers files and shared objects
- return "
-
- ".$TargetVersion{$LibVersion}."
-
-
-
- $Path
-
-
-
- $Path
- ";
- }
- else
- { # files
- if($Path=~/\.(xml|desc)\Z/i)
- { # standard XML-descriptor
- return readFile($Path);
- }
- elsif(is_header($Path, 2, $LibVersion))
- { # header file
- $CheckHeadersOnly = 1;
-
- if($LibVersion==1) {
- $TargetVersion{$LibVersion} = "X";
- }
-
- if($LibVersion==2) {
- $TargetVersion{$LibVersion} = "Y";
- }
-
- return "
-
- ".$TargetVersion{$LibVersion}."
-
-
-
- $Path
-
-
-
- none
- ";
- }
- else
- { # standard XML-descriptor
- return readFile($Path);
+ my $Pid = fork();
+ if($Pid)
+ { # dump on two CPU cores
+ my @PARAMS = ("-dump", $In::Desc{1}{"Path"}, "-l", $In::Opt{"TargetLib"});
+ @PARAMS = (@PARAMS, "-vnum", $V1);
+
+ if($In::Desc{1}{"RelativeDirectory"}) {
+ @PARAMS = (@PARAMS, "-relpath", $In::Desc{1}{"RelativeDirectory"});
}
- }
-}
-
-sub detect_lib_default_paths()
-{
- my %LPaths = ();
- if($OSgroup eq "bsd")
- {
- if(my $LdConfig = get_CmdPath("ldconfig"))
- {
- foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
- {
- if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
- {
- my $Name = "lib".$1;
- if(not defined $LPaths{$Name}) {
- $LPaths{$Name} = $2;
- }
- }
- }
+ if($In::Desc{1}{"OutputLogPath"}) {
+ @PARAMS = (@PARAMS, "-log-path", $In::Desc{1}{"OutputLogPath"});
}
- else {
- printMsg("WARNING", "can't find ldconfig");
+ if($In::Opt{"CrossGcc"}) {
+ @PARAMS = (@PARAMS, "-cross-gcc", $In::Opt{"CrossGcc"});
}
- }
- else
- {
- if(my $LdConfig = get_CmdPath("ldconfig"))
+ if($In::Opt{"Quiet"})
{
- if($SystemRoot and $OSgroup eq "linux")
- { # use host (x86) ldconfig with the target (arm) ld.so.conf
- if(-e $SystemRoot."/etc/ld.so.conf") {
- $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
- }
- }
- foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
- {
- if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
- {
- my ($Name, $Path) = ($1, $2);
- $Path=~s/[\/]{2,}/\//;
- if(not defined $LPaths{$Name})
- { # get first element from the list of available paths
-
- # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
- # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
- # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
-
- $LPaths{$Name} = $Path;
- }
- }
- }
+ @PARAMS = (@PARAMS, "-quiet");
+ @PARAMS = (@PARAMS, "-logging-mode", "a");
}
- elsif($OSgroup eq "linux") {
- printMsg("WARNING", "can't find ldconfig");
+ elsif($In::Opt{"LogMode"} and $In::Opt{"LogMode"} ne "w")
+ { # "w" is default
+ @PARAMS = (@PARAMS, "-logging-mode", $In::Opt{"LogMode"});
}
- }
- return \%LPaths;
-}
-
-sub detect_bin_default_paths()
-{
- my $EnvPaths = $ENV{"PATH"};
- if($OSgroup eq "beos") {
- $EnvPaths.=":".$ENV{"BETOOLS"};
- }
- my $Sep = ($OSgroup eq "windows")?";":":|;";
- foreach my $Path (split(/$Sep/, $EnvPaths))
- {
- $Path = path_format($Path, $OSgroup);
- next if(not $Path);
- if($SystemRoot
- and $Path=~/\A\Q$SystemRoot\E\//)
- { # do NOT use binaries from target system
- next;
+ if($In::Opt{"ExtendedCheck"}) {
+ @PARAMS = (@PARAMS, "-extended");
}
- push_U(\@DefaultBinPaths, $Path);
- }
-}
-
-sub detect_inc_default_paths()
-{
- my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
- writeFile("$TMP_DIR/empty.h", "");
- foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
- { # detecting GCC default include paths
- next if(index($Line, "/cc1plus ")!=-1);
-
- if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
- {
- my $Path = realpath($1);
- $Path = path_format($Path, $OSgroup);
- if(index($Path, "c++")!=-1
- or index($Path, "/g++/")!=-1)
- {
- push_U($DPaths{"Cpp"}, $Path);
- if(not defined $MAIN_CPP_DIR
- or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
- $MAIN_CPP_DIR = $Path;
- }
- }
- elsif(index($Path, "gcc")!=-1) {
- push_U($DPaths{"Gcc"}, $Path);
- }
- else
- {
- if($Path=~/local[\/\\]+include/)
- { # local paths
- next;
- }
- if($SystemRoot
- and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
- { # The GCC include path for user headers is not a part of the system root
- # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
- # or it is the internal cross-GCC path like arm-linux-gnueabi/include
- next;
- }
- push_U($DPaths{"Inc"}, $Path);
- }
+ if($In::Opt{"UserLang"}) {
+ @PARAMS = (@PARAMS, "-lang", $In::Opt{"UserLang"});
}
- }
- unlink("$TMP_DIR/empty.h");
- return %DPaths;
-}
-
-sub detect_default_paths($)
-{
- my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
- my $Search = $_[0];
- if($Search!~/inc/) {
- $HSearch = 0;
- }
- if($Search!~/lib/) {
- $LSearch = 0;
- }
- if($Search!~/bin/) {
- $BSearch = 0;
- }
- if($Search!~/gcc/) {
- $GSearch = 0;
- }
- if(@{$SystemPaths{"include"}})
- { # section of the XML descriptor
- # do NOT search for systems headers
- $HSearch = 0;
- }
- if(@{$SystemPaths{"lib"}})
- { # section of the XML descriptor
- # do NOT search for systems libraries
- $LSearch = 0;
- }
- foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
- { # additional search paths
- next if($Type eq "include" and not $HSearch);
- next if($Type eq "lib" and not $LSearch);
- next if($Type eq "bin" and not $BSearch);
- push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
- }
- if($OSgroup ne "windows")
- { # unix-like
- foreach my $Type ("include", "lib", "bin")
- { # automatic detection of system "devel" directories
- next if($Type eq "include" and not $HSearch);
- next if($Type eq "lib" and not $LSearch);
- next if($Type eq "bin" and not $BSearch);
- my ($UsrDir, $RootDir) = ("/usr", "/");
- if($SystemRoot and $Type ne "bin")
- { # 1. search for target headers and libraries
- # 2. use host commands: ldconfig, readelf, etc.
- ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
- }
- push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
- if(-d $RootDir."/".$Type)
- { # if "/lib" is symbolic link
- if($RootDir eq "/") {
- push_U($SystemPaths{$Type}, "/".$Type);
- }
- else {
- push_U($SystemPaths{$Type}, $RootDir."/".$Type);
- }
- }
- if(-d $UsrDir)
- {
- push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
- if(-d $UsrDir."/".$Type)
- { # if "/usr/lib" is symbolic link
- push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
- }
- }
- }
- }
- if($BSearch)
- {
- detect_bin_default_paths();
- push_U($SystemPaths{"bin"}, @DefaultBinPaths);
- }
- # check environment variables
- if($OSgroup eq "beos")
- {
- foreach (my @Paths = @{$SystemPaths{"bin"}})
- {
- if($_ eq ".") {
- next;
- }
- # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
- if(my @Dirs = sort cmd_find($_, "d", "bin")) {
- push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
- }
- }
- if($HSearch)
- {
- push_U(\@DefaultIncPaths, grep { is_abs($_) } (
- split(/:|;/, $ENV{"BEINCLUDES"})
- ));
- }
- if($LSearch)
- {
- push_U(\@DefaultLibPaths, grep { is_abs($_) } (
- split(/:|;/, $ENV{"BELIBRARIES"}),
- split(/:|;/, $ENV{"LIBRARY_PATH"})
- ));
+ if($In::Opt{"BinOnly"}) {
+ @PARAMS = (@PARAMS, "-binary");
}
- }
- if($LSearch)
- { # using linker to get system paths
- if(my $LPaths = detect_lib_default_paths())
- { # unix-like
- my %Dirs = ();
- foreach my $Name (keys(%{$LPaths}))
- {
- if($SystemRoot
- and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
- { # wrong ldconfig configuration
- # check your /etc/ld.so.conf
- next;
- }
- $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
- if(my $Dir = get_dirname($LPaths->{$Name})) {
- $Dirs{$Dir} = 1;
- }
- }
- push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
+ if($In::Opt{"SrcOnly"}) {
+ @PARAMS = (@PARAMS, "-source");
}
- push_U($SystemPaths{"lib"}, @DefaultLibPaths);
- }
- if($BSearch)
- {
- if($CrossGcc)
- { # --cross-gcc=arm-linux-gcc
- if(-e $CrossGcc)
- { # absolute or relative path
- $GCC_PATH = get_abs_path($CrossGcc);
- }
- elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
- { # command name
- $GCC_PATH = $CrossGcc;
- }
- else {
- exitStatus("Access_Error", "can't access \'$CrossGcc\'");
- }
- if($GCC_PATH=~/\s/) {
- $GCC_PATH = "\"".$GCC_PATH."\"";
- }
+ if($In::Opt{"SortDump"}) {
+ @PARAMS = (@PARAMS, "-sort");
}
- }
- if($GSearch)
- { # GCC path and default include dirs
- if(not $CrossGcc)
- { # try default gcc
- $GCC_PATH = get_CmdPath("gcc");
+ if($In::Opt{"DumpFormat"} and $In::Opt{"DumpFormat"} ne "perl") {
+ @PARAMS = (@PARAMS, "-dump-format", $In::Opt{"DumpFormat"});
}
- if(not $GCC_PATH)
- { # try to find gcc-X.Y
- foreach my $Path (@{$SystemPaths{"bin"}})
- {
- if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
- { # select the latest version
- @GCCs = sort {$b cmp $a} @GCCs;
- if(check_gcc($GCCs[0], "3"))
- {
- $GCC_PATH = $GCCs[0];
- last;
- }
- }
- }
+ if($In::Opt{"CheckHeadersOnly"}) {
+ @PARAMS = (@PARAMS, "-headers-only");
}
- if(not $GCC_PATH) {
- exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
+ if($In::Opt{"CxxIncompat"}) {
+ @PARAMS = (@PARAMS, "-cxx-incompatible");
}
-
- if(my $GCC_Ver = get_dumpversion($GCC_PATH))
+ if($In::Opt{"Debug"})
{
- my $GccTarget = get_dumpmachine($GCC_PATH);
-
- if($GccTarget=~/linux/)
- {
- $OStarget = "linux";
- $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
- }
- elsif($GccTarget=~/symbian/)
- {
- $OStarget = "symbian";
- $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
- }
-
- printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
-
- # 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.");
- $EMERGENCY_MODE_48 = 1;
- }
+ @PARAMS = (@PARAMS, "-debug");
+ printMsg("INFO", "Executing perl $0 @PARAMS");
}
- else {
- exitStatus("Error", "something is going wrong with the GCC compiler");
+ system("perl", $0, @PARAMS);
+ if(not -f $DumpPath1) {
+ exit(1);
}
}
- if($HSearch)
- {
- # GCC standard paths
- if($GCC_PATH and not $NoStdInc)
- {
- my %DPaths = detect_inc_default_paths();
- @DefaultCppPaths = @{$DPaths{"Cpp"}};
- @DefaultGccPaths = @{$DPaths{"Gcc"}};
- @DefaultIncPaths = @{$DPaths{"Inc"}};
- push_U($SystemPaths{"include"}, @DefaultIncPaths);
- }
+ else
+ { # child
+ my @PARAMS = ("-dump", $In::Desc{2}{"Path"}, "-l", $In::Opt{"TargetLib"});
+ @PARAMS = (@PARAMS, "-vnum", $V2);
- # users include paths
- my $IncPath = "/usr/include";
- if($SystemRoot) {
- $IncPath = $SystemRoot.$IncPath;
- }
- if(-d $IncPath) {
- push_U(\@UsersIncPath, $IncPath);
+ if($In::Desc{2}{"RelativeDirectory"}) {
+ @PARAMS = (@PARAMS, "-relpath", $In::Desc{2}{"RelativeDirectory"});
}
- }
-
- if($ExtraInfo)
- {
- writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
- writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
- }
-}
-
-sub getLIB_EXT($)
-{
- my $Target = $_[0];
- if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
- return $Ext;
- }
- return $OS_LibExt{$LIB_TYPE}{"default"};
-}
-
-sub getAR_EXT($)
-{
- my $Target = $_[0];
- if(my $Ext = $OS_Archive{$Target}) {
- return $Ext;
- }
- return $OS_Archive{"default"};
-}
-
-sub get_dumpversion($)
-{
- my $Cmd = $_[0];
- return "" if(not $Cmd);
- if($Cache{"get_dumpversion"}{$Cmd}) {
- return $Cache{"get_dumpversion"}{$Cmd};
- }
- my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
- chomp($V);
- return ($Cache{"get_dumpversion"}{$Cmd} = $V);
-}
-
-sub get_dumpmachine($)
-{
- my $Cmd = $_[0];
- return "" if(not $Cmd);
- if($Cache{"get_dumpmachine"}{$Cmd}) {
- return $Cache{"get_dumpmachine"}{$Cmd};
- }
- my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
- chomp($Machine);
- return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
-}
-
-sub checkCmd($)
-{
- my $Cmd = $_[0];
- return "" if(not $Cmd);
- my @Options = (
- "--version",
- "-help"
- );
- foreach my $Opt (@Options)
- {
- my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
- if($Info) {
- return 1;
+ if($In::Desc{2}{"OutputLogPath"}) {
+ @PARAMS = (@PARAMS, "-log-path", $In::Desc{2}{"OutputLogPath"});
}
- }
- return 0;
-}
-
-sub check_gcc($$)
-{
- my ($Cmd, $ReqVer) = @_;
- return 0 if(not $Cmd or not $ReqVer);
- if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
- return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
- }
- if(my $GccVer = get_dumpversion($Cmd))
- {
- $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
- if(cmpVersions($GccVer, $ReqVer)>=0) {
- return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
+ if($In::Opt{"CrossGcc"}) {
+ @PARAMS = (@PARAMS, "-cross-gcc", $In::Opt{"CrossGcc"});
}
- }
- return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
-}
-
-sub get_depth($)
-{
- if(defined $Cache{"get_depth"}{$_[0]}) {
- return $Cache{"get_depth"}{$_[0]};
- }
- return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
-}
-
-sub registerGccHeaders()
-{
- return if($Cache{"registerGccHeaders"}); # this function should be called once
-
- foreach my $Path (@DefaultGccPaths)
- {
- my @Headers = cmd_find($Path,"f");
- @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
- foreach my $HPath (@Headers)
+ if($In::Opt{"Quiet"})
{
- my $FileName = get_filename($HPath);
- if(not defined $DefaultGccHeader{$FileName})
- { # skip duplicated
- $DefaultGccHeader{$FileName} = $HPath;
- }
+ @PARAMS = (@PARAMS, "-quiet");
+ @PARAMS = (@PARAMS, "-logging-mode", "a");
}
- }
- $Cache{"registerGccHeaders"} = 1;
-}
-
-sub registerCppHeaders()
-{
- return if($Cache{"registerCppHeaders"}); # this function should be called once
-
- foreach my $CppDir (@DefaultCppPaths)
- {
- my @Headers = cmd_find($CppDir,"f");
- @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
- foreach my $Path (@Headers)
- {
- my $FileName = get_filename($Path);
- if(not defined $DefaultCppHeader{$FileName})
- { # skip duplicated
- $DefaultCppHeader{$FileName} = $Path;
- }
+ elsif($In::Opt{"LogMode"} and $In::Opt{"LogMode"} ne "w")
+ { # "w" is default
+ @PARAMS = (@PARAMS, "-logging-mode", $In::Opt{"LogMode"});
}
- }
- $Cache{"registerCppHeaders"} = 1;
-}
-
-sub parse_libname($$$)
-{
- return "" if(not $_[0]);
- if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
- return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
- }
- return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
-}
-
-sub parse_libname_I($$$)
-{
- my ($Name, $Type, $Target) = @_;
-
- if($Target eq "symbian") {
- return parse_libname_symbian($Name, $Type);
- }
- elsif($Target eq "windows") {
- return parse_libname_windows($Name, $Type);
- }
-
- # unix
- my $Ext = getLIB_EXT($Target);
- if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
- { # libSDL-1.2.so.0.7.1
- # libwbxml2.so.0.0.18
- # libopcodes-2.21.53-system.20110810.so
- if($Type eq "name")
- { # libSDL-1.2
- # libwbxml2
- return $2;
+ if($In::Opt{"ExtendedCheck"}) {
+ @PARAMS = (@PARAMS, "-extended");
}
- elsif($Type eq "name+ext")
- { # libSDL-1.2.so
- # libwbxml2.so
- return $1;
+ if($In::Opt{"UserLang"}) {
+ @PARAMS = (@PARAMS, "-lang", $In::Opt{"UserLang"});
}
- elsif($Type eq "version")
- {
- if(defined $7
- and $7 ne "")
- { # 0.7.1
- return $7;
- }
- else
- { # libc-2.5.so (=>2.5 version)
- my $MV = $5;
- $MV=~s/\A[\-\_]+//g;
- return $MV;
- }
- }
- elsif($Type eq "short")
- { # libSDL
- # libwbxml2
- return $3;
- }
- elsif($Type eq "shortest")
- { # SDL
- # wbxml
- return shortest_name($3);
- }
- }
- return "";# error
-}
-
-sub parse_libname_symbian($$)
-{
- my ($Name, $Type) = @_;
- my $Ext = getLIB_EXT("symbian");
- if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
- { # libpthread{00010001}.dso
- if($Type eq "name")
- { # libpthread{00010001}
- return $2;
- }
- elsif($Type eq "name+ext")
- { # libpthread{00010001}.dso
- return $1;
- }
- elsif($Type eq "version")
- { # 00010001
- my $V = $4;
- $V=~s/\{(.+)\}/$1/;
- return $V;
- }
- elsif($Type eq "short")
- { # libpthread
- return $3;
+ if($In::Opt{"BinOnly"}) {
+ @PARAMS = (@PARAMS, "-binary");
}
- elsif($Type eq "shortest")
- { # pthread
- return shortest_name($3);
+ if($In::Opt{"SrcOnly"}) {
+ @PARAMS = (@PARAMS, "-source");
}
- }
- return "";# error
-}
-
-sub parse_libname_windows($$)
-{
- my ($Name, $Type) = @_;
- my $Ext = getLIB_EXT("windows");
- if($Name=~/((.+?)\.$Ext)\Z/)
- { # netapi32.dll
- if($Type eq "name")
- { # netapi32
- return $2;
- }
- elsif($Type eq "name+ext")
- { # netapi32.dll
- return $1;
- }
- elsif($Type eq "version")
- { # DLL version embedded
- # at binary-level
- return "";
- }
- elsif($Type eq "short")
- { # netapi32
- return $2;
- }
- elsif($Type eq "shortest")
- { # netapi
- return shortest_name($2);
- }
- }
- return "";# error
-}
-
-sub shortest_name($)
-{
- my $Name = $_[0];
- # remove prefix
- $Name=~s/\A(lib|open)//;
- # remove suffix
- $Name=~s/[\W\d_]+\Z//i;
- $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
- return $Name;
-}
-
-sub createSymbolsList($$$$$)
-{
- my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
-
- read_ABI_Dump(1, $DPath);
- prepareSymbols(1);
-
- my %SymbolHeaderLib = ();
- my $Total = 0;
-
- # Get List
- foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
- {
- if(not link_symbol($Symbol, 1, "-Deps"))
- { # skip src only and all external functions
- next;
+ if($In::Opt{"SortDump"}) {
+ @PARAMS = (@PARAMS, "-sort");
}
- if(not symbolFilter($Symbol, 1, "Public", "Binary"))
- { # skip other symbols
- next;
+ if($In::Opt{"DumpFormat"} and $In::Opt{"DumpFormat"} ne "perl") {
+ @PARAMS = (@PARAMS, "-dump-format", $In::Opt{"DumpFormat"});
}
- my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
- if(not $HeaderName)
- { # skip src only and all external functions
- next;
+ if($In::Opt{"CheckHeadersOnly"}) {
+ @PARAMS = (@PARAMS, "-headers-only");
}
- my $DyLib = $Symbol_Library{1}{$Symbol};
- if(not $DyLib)
- { # skip src only and all external functions
- next;
+ if($In::Opt{"CxxIncompat"}) {
+ @PARAMS = (@PARAMS, "-cxx-incompatible");
}
- $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
- $Total+=1;
- }
- # Draw List
- my $SYMBOLS_LIST = "Public symbols in $LName ($LVersion)";
- $SYMBOLS_LIST .= " on ".showArch($ArchName)."
Total: $Total
";
- foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
- {
- foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
+ if($In::Opt{"Debug"})
{
- my %NS_Symbol = ();
- foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
- $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
- }
- foreach my $NameSpace (sort keys(%NS_Symbol))
- {
- $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
- my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
- foreach my $Symbol (@SortedInterfaces)
- {
- my $SubReport = "";
- my $Signature = get_Signature($Symbol, 1);
- if($NameSpace) {
- $Signature=~s/\b\Q$NameSpace\E::\b//g;
- }
- if($Symbol=~/\A(_Z|\?)/)
- {
- if($Signature) {
- $SubReport = insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."
\n".$ContentDivStart."[symbol: $Symbol]
".$ContentDivEnd."\n");
- }
- else {
- $SubReport = "".$Symbol."
\n";
- }
- }
- else
- {
- if($Signature) {
- $SubReport = "".highLight_Signature_Italic_Color($Signature)."
\n";
- }
- else {
- $SubReport = "".$Symbol."
\n";
- }
- }
- $SYMBOLS_LIST .= $SubReport;
- }
- }
- $SYMBOLS_LIST .= "
\n";
- }
- }
- # clear info
- (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
- %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
- %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
- %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
- ($Content_Counter, $ContentID) = (0, 0);
- # print report
- my $CssStyles = readModule("Styles", "SymbolsList.css");
- my $JScripts = readModule("Scripts", "Sections.js");
- $SYMBOLS_LIST = "".$SYMBOLS_LIST.$TOP_REF."
\n";
- my $Title = "$LName: public symbols";
- my $Keywords = "$LName, API, symbols";
- my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
- $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
- \n$SYMBOLS_LIST
-
\n".getReportFooter()."
- ";
- writeFile($SaveTo, $SYMBOLS_LIST);
-}
-
-sub add_target_libs($)
-{
- foreach (@{$_[0]}) {
- $TargetLibs{$_} = 1;
- }
-}
-
-sub is_target_lib($)
-{
- my $LName = $_[0];
- if(not $LName) {
- return 0;
- }
- if($TargetLibraryName
- and $LName!~/\Q$TargetLibraryName\E/) {
- return 0;
- }
- if(keys(%TargetLibs)
- and not $TargetLibs{$LName}
- and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
- return 0;
- }
- return 1;
-}
-
-sub is_target_header($$)
-{ # --header, --headers-list
- my ($H, $V) = @_;
- if(keys(%{$TargetHeaders{$V}}))
- {
- if($TargetHeaders{$V}{$H}) {
- return 1;
+ @PARAMS = (@PARAMS, "-debug");
+ printMsg("INFO", "Executing perl $0 @PARAMS");
}
- }
- return 0;
-}
-
-sub readLibs($)
-{
- my $LibVersion = $_[0];
- if($OStarget eq "windows")
- { # dumpbin.exe will crash
- # without VS Environment
- check_win32_env();
- }
- readSymbols($LibVersion);
- translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
- translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
-}
-
-sub dump_sorting($)
-{
- my $Hash = $_[0];
- return [] if(not $Hash);
- my @Keys = keys(%{$Hash});
- return [] if($#Keys<0);
- if($Keys[0]=~/\A\d+\Z/)
- { # numbers
- return [sort {int($a)<=>int($b)} @Keys];
- }
- else
- { # strings
- return [sort {$a cmp $b} @Keys];
- }
-}
-
-sub printMsg($$)
-{
- my ($Type, $Msg) = @_;
- if($Type!~/\AINFO/) {
- $Msg = $Type.": ".$Msg;
- }
- if($Type!~/_C\Z/) {
- $Msg .= "\n";
- }
- if($Quiet)
- { # --quiet option
- appendFile($COMMON_LOG_PATH, $Msg);
- }
- else
- {
- if($Type eq "ERROR") {
- print STDERR $Msg;
+ system("perl", $0, @PARAMS);
+ if(not -f $DumpPath2) {
+ exit(1);
}
else {
- print $Msg;
+ exit(0);
}
}
-}
-
-sub exitStatus($$)
-{
- my ($Code, $Msg) = @_;
- printMsg("ERROR", $Msg);
- exit($ERROR_CODE{$Code});
-}
-
-sub exitReport()
-{ # the tool has run without any errors
- printReport();
- if($COMPILE_ERRORS)
- { # errors in headers may add false positives/negatives
- exit($ERROR_CODE{"Compile_Error"});
+ waitpid($Pid, 0);
+
+ my @CMP_PARAMS = ("-l", $In::Opt{"TargetLib"});
+ @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
+ @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
+ if($In::Opt{"TargetTitle"} ne $In::Opt{"TargetLib"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-title", $In::Opt{"TargetTitle"});
}
- if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
- { # --binary
- exit($ERROR_CODE{"Incompatible"});
+ if($In::Opt{"ShowRetVal"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
}
- elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
- { # --source
- exit($ERROR_CODE{"Incompatible"});
+ if($In::Opt{"CrossGcc"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $In::Opt{"CrossGcc"});
}
- elsif($RESULT{"Source"}{"Problems"}
- or $RESULT{"Binary"}{"Problems"})
- { # default
- exit($ERROR_CODE{"Incompatible"});
+ @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
+ if($In::Opt{"Quiet"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
}
- else {
- exit($ERROR_CODE{"Compatible"});
+ if($In::Opt{"ReportFormat"}
+ and $In::Opt{"ReportFormat"} ne "html")
+ { # HTML is default format
+ @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $In::Opt{"ReportFormat"});
}
-}
-
-sub readRules($)
-{
- my $Kind = $_[0];
- if(not -f $RULES_PATH{$Kind}) {
- exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
+ if($In::Opt{"OutputReportPath"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $In::Opt{"OutputReportPath"});
}
- my $Content = readFile($RULES_PATH{$Kind});
- while(my $Rule = parseTag(\$Content, "rule"))
- {
- my $RId = parseTag(\$Rule, "id");
- my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
- foreach my $Prop (@Properties) {
- if(my $Value = parseTag(\$Rule, lc($Prop)))
- {
- $Value=~s/\n[ ]*//;
- $CompatRules{$Kind}{$RId}{$Prop} = $Value;
- }
- }
- if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
- $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
- }
- else {
- $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
- }
+ if($In::Opt{"BinReportPath"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $In::Opt{"BinReportPath"});
}
-}
-
-sub getReportPath($)
-{
- my $Level = $_[0];
- my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
- if($Level eq "Binary")
- {
- if($BinaryReportPath)
- { # --bin-report-path
- return $BinaryReportPath;
- }
- elsif($OutputReportPath)
- { # --report-path
- return $OutputReportPath;
- }
- else
- { # default
- return $Dir."/abi_compat_report.$ReportFormat";
- }
+ if($In::Opt{"SrcReportPath"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $In::Opt{"SrcReportPath"});
}
- elsif($Level eq "Source")
- {
- if($SourceReportPath)
- { # --src-report-path
- return $SourceReportPath;
- }
- elsif($OutputReportPath)
- { # --report-path
- return $OutputReportPath;
- }
- else
- { # default
- return $Dir."/src_compat_report.$ReportFormat";
- }
+ if($In::Opt{"LoggingPath"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $In::Opt{"LoggingPath"});
}
- else
- {
- if($OutputReportPath)
- { # --report-path
- return $OutputReportPath;
- }
- else
- { # default
- return $Dir."/compat_report.$ReportFormat";
- }
+ if($In::Opt{"CheckHeadersOnly"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
}
-}
-
-sub printStatMsg($)
-{
- my $Level = $_[0];
- printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
-}
-
-sub listAffected($)
-{
- my $Level = $_[0];
- my $List = "";
- foreach (keys(%{$TotalAffected{$Level}}))
- {
- if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
- { # skip "Low"-severity problems
- next;
- }
- $List .= "$_\n";
- }
- my $Dir = get_dirname(getReportPath($Level));
- if($Level eq "Binary") {
- writeFile($Dir."/abi_affected.txt", $List);
- }
- elsif($Level eq "Source") {
- writeFile($Dir."/src_affected.txt", $List);
+ if($In::Opt{"BinOnly"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-binary");
}
-}
-
-sub printReport()
-{
- printMsg("INFO", "creating compatibility report ...");
- createReport();
- if($JoinReport or $DoubleReport)
- {
- if($RESULT{"Binary"}{"Problems"}
- or $RESULT{"Source"}{"Problems"}) {
- printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
- }
- else {
- printMsg("INFO", "result: COMPATIBLE");
- }
- printStatMsg("Binary");
- printStatMsg("Source");
- if($ListAffected)
- { # --list-affected
- listAffected("Binary");
- listAffected("Source");
- }
+ if($In::Opt{"SrcOnly"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-source");
}
- elsif($BinaryOnly)
- {
- if($RESULT{"Binary"}{"Problems"}) {
- printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
- }
- else {
- printMsg("INFO", "result: COMPATIBLE");
- }
- printStatMsg("Binary");
- if($ListAffected)
- { # --list-affected
- listAffected("Binary");
- }
+ if($In::Opt{"FilterPath"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-filter", $In::Opt{"FilterPath"});
}
- elsif($SourceOnly)
- {
- if($RESULT{"Source"}{"Problems"}) {
- printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
- }
- else {
- printMsg("INFO", "result: COMPATIBLE");
- }
- printStatMsg("Source");
- if($ListAffected)
- { # --list-affected
- listAffected("Source");
- }
+ if($In::Opt{"SkipInternalSymbols"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-skip-internal-symbols", $In::Opt{"SkipInternalSymbols"});
}
- if($StdOut)
- {
- if($JoinReport or not $DoubleReport)
- { # --binary or --source
- printMsg("INFO", "compatibility report has been generated to stdout");
- }
- else
- { # default
- printMsg("INFO", "compatibility reports have been generated to stdout");
- }
+ if($In::Opt{"SkipInternalTypes"}) {
+ @CMP_PARAMS = (@CMP_PARAMS, "-skip-internal-types", $In::Opt{"SkipInternalTypes"});
}
- else
+ if($In::Opt{"Debug"})
{
- if($JoinReport)
- {
- printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
- }
- elsif($DoubleReport)
- { # default
- printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
- }
- elsif($BinaryOnly)
- { # --binary
- printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
- }
- elsif($SourceOnly)
- { # --source
- printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
- }
- }
-}
-
-sub check_win32_env()
-{
- if(not $ENV{"DevEnvDir"}
- or not $ENV{"LIB"}) {
- exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
+ @CMP_PARAMS = (@CMP_PARAMS, "-debug");
+ printMsg("INFO", "Executing perl $0 @CMP_PARAMS");
}
+ system("perl", $0, @CMP_PARAMS);
+ exit($?>>8);
}
-sub diffSets($$)
+sub compareInit()
{
- my ($S1, $S2) = @_;
- my @SK1 = keys(%{$S1});
- my @SK2 = keys(%{$S2});
- if($#SK1!=$#SK2) {
- return 1;
- }
- foreach my $K1 (@SK1)
- {
- if(not defined $S2->{$K1}) {
- return 1;
- }
+ # read input XML descriptors or ABI dumps
+ if(not $In::Desc{1}{"Path"}) {
+ exitStatus("Error", "-old option is not specified");
}
- return 0;
-}
-
-sub defaultDumpPath($$)
-{
- my ($N, $V) = @_;
- return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
-}
-
-sub create_ABI_Dump()
-{
- if(not -e $DumpAPI) {
- exitStatus("Access_Error", "can't access \'$DumpAPI\'");
+ if(not -e $In::Desc{1}{"Path"}) {
+ exitStatus("Access_Error", "can't access \'".$In::Desc{1}{"Path"}."\'");
}
- if(isDump($DumpAPI)) {
- read_ABI_Dump(1, $DumpAPI);
- }
- else {
- readDescriptor(1, createDescriptor(1, $DumpAPI));
+ if(not $In::Desc{2}{"Path"}) {
+ exitStatus("Error", "-new option is not specified");
}
-
- if(not $Descriptor{1}{"Version"})
- { # set to default: N
- $Descriptor{1}{"Version"} = "N";
+ if(not -e $In::Desc{2}{"Path"}) {
+ exitStatus("Access_Error", "can't access \'".$In::Desc{2}{"Path"}."\'");
}
- initLogging(1);
- detect_default_paths("inc|lib|bin|gcc"); # complete analysis
+ detectDefaultPaths(undef, undef, "bin", undef); # to extract dumps
- my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
- if($OutputDumpPath)
- { # user defined path
- $DumpPath = $OutputDumpPath;
- }
- my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
+ printMsg("INFO", "Preparing, please wait ...");
- if(not $Archive and not $StdOut)
- { # check archive utilities
- if($OSgroup eq "windows")
- { # using zip
- my $ZipCmd = get_CmdPath("zip");
- if(not $ZipCmd) {
- exitStatus("Not_Found", "can't find \"zip\"");
- }
- }
- else
- { # using tar and gzip
- my $TarCmd = get_CmdPath("tar");
- if(not $TarCmd) {
- exitStatus("Not_Found", "can't find \"tar\"");
- }
- my $GzipCmd = get_CmdPath("gzip");
- if(not $GzipCmd) {
- exitStatus("Not_Found", "can't find \"gzip\"");
- }
+ if($In::Opt{"UseDumps"})
+ { # --use-dumps
+ # parallel processing
+ if(isDump($In::Desc{1}{"Path"})
+ or isDump($In::Desc{2}{"Path"})) {
+ exitStatus("Error", "please specify input XML descriptors instead of ABI dumps to use with -use-dumps option.");
}
+
+ readDesc(createDesc($In::Desc{1}{"Path"}, 1), 1);
+ readDesc(createDesc($In::Desc{2}{"Path"}, 2), 2);
+
+ compareABIDumps($In::Desc{1}{"Version"}, $In::Desc{2}{"Version"});
}
- if(not $Descriptor{1}{"Dump"})
+ if(isDump($In::Desc{1}{"Path"}))
{
- if(not $CheckHeadersOnly) {
- readLibs(1);
- }
- if($CheckHeadersOnly) {
- setLanguage(1, "C++");
- }
- searchForHeaders(1);
- $WORD_SIZE{1} = detectWordSize(1);
- }
- if(not $Descriptor{1}{"Dump"})
- {
- if($Descriptor{1}{"Headers"}) {
- readHeaders(1);
- }
- }
- cleanDump(1);
- if(not keys(%{$SymbolInfo{1}}))
- { # check if created dump is valid
- if(not $ExtendedCheck)
- {
- if($CheckHeadersOnly) {
- exitStatus("Empty_Set", "the set of public symbols is empty");
- }
- else {
- exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
- }
+ $In::ABI{1} = readABIDump(1, $In::Desc{1}{"Path"});
+ initAliases(1);
+
+ if(my $V = $In::Desc{1}{"TargetVersion"}) {
+ $In::Desc{1}{"Version"} = $V;
}
- }
- my %HeadersInfo = ();
- foreach my $HPath (keys(%{$Registered_Headers{1}})) {
- $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
- }
- if($ExtraDump)
- { # add unmangled names to the ABI dump
- my @Names = ();
- foreach my $InfoId (keys(%{$SymbolInfo{1}}))
- {
- if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
- push(@Names, $MnglName);
- }
+ else {
+ $In::Desc{1}{"Version"} = $In::ABI{1}{"LibraryVersion"};
}
- translateSymbols(@Names, 1);
- foreach my $InfoId (keys(%{$SymbolInfo{1}}))
- {
- if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
- {
- if(my $Unmangled = $tr_name{$MnglName})
- {
- if($MnglName ne $Unmangled) {
- $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
- }
- }
- }
+
+ if(not defined $In::Desc{1}{"Version"}) {
+ $In::Desc{1}{"Version"} = "X";
}
}
-
- my %GccConstants = (); # built-in GCC constants
- foreach my $Name (keys(%{$Constants{1}}))
+ else
{
- if(not defined $Constants{1}{$Name}{"Header"})
- {
- $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
- delete($Constants{1}{$Name});
- }
- }
-
- printMsg("INFO", "creating library ABI dump ...");
- my %ABI = (
- "TypeInfo" => $TypeInfo{1},
- "SymbolInfo" => $SymbolInfo{1},
- "Symbols" => $Library_Symbol{1},
- "DepSymbols" => $DepLibrary_Symbol{1},
- "SymbolVersion" => $SymVer{1},
- "LibraryVersion" => $Descriptor{1}{"Version"},
- "LibraryName" => $TargetLibraryName,
- "Language" => $COMMON_LANGUAGE{1},
- "SkipTypes" => $SkipTypes{1},
- "SkipSymbols" => $SkipSymbols{1},
- "SkipNameSpaces" => $SkipNameSpaces{1},
- "SkipHeaders" => $SkipHeadersList{1},
- "Headers" => \%HeadersInfo,
- "Constants" => $Constants{1},
- "GccConstants" => \%GccConstants,
- "NameSpaces" => $NestedNameSpaces{1},
- "Target" => $OStarget,
- "Arch" => getArch(1),
- "WordSize" => $WORD_SIZE{1},
- "GccVersion" => get_dumpversion($GCC_PATH),
- "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
- "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
- );
- if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
- $ABI{"TargetHeaders"} = $TargetHeaders{1};
- }
- if($UseXML) {
- $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
- }
- if($ExtendedCheck)
- { # --ext option
- $ABI{"Mode"} = "Extended";
- }
- if($BinaryOnly)
- { # --binary
- $ABI{"BinOnly"} = 1;
- }
- if($ExtraDump)
- { # --extra-dump
- $ABI{"Extra"} = 1;
- $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
- $ABI{"Needed"} = $Library_Needed{1};
+ loadModule("ABIDump");
+ readDesc(createDesc($In::Desc{1}{"Path"}, 1), 1);
+
+ initLogging(1);
+ detectDefaultPaths("inc", "lib", undef, "gcc");
+ createABIDump(1);
}
- my $ABI_DUMP = "";
- if($UseXML)
+ if(isDump($In::Desc{2}{"Path"}))
{
- loadModule("XmlDump");
- $ABI_DUMP = createXmlDump(\%ABI);
- }
- else
- { # default
- $ABI_DUMP = Dumper(\%ABI);
- }
- if($StdOut)
- { # --stdout option
- print STDOUT $ABI_DUMP;
- printMsg("INFO", "ABI dump has been generated to stdout");
- return;
- }
- else
- { # write to gzipped file
- my ($DDir, $DName) = separate_path($DumpPath);
- my $DPath = $TMP_DIR."/".$DName;
- if(not $Archive) {
- $DPath = $DumpPath;
- }
-
- mkpath($DDir);
-
- open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
- print DUMP $ABI_DUMP;
- close(DUMP);
-
- if(not -s $DPath) {
- exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
- }
- if($Archive) {
- $DumpPath = createArchive($DPath, $DDir);
- }
+ $In::ABI{2} = readABIDump(2, $In::Desc{2}{"Path"});
+ initAliases(2);
- if($OutputDumpPath) {
- printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
+ if(my $V = $In::Desc{2}{"TargetVersion"}) {
+ $In::Desc{2}{"Version"} = $V;
}
else {
- printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
- }
- printMsg("INFO", "you can transfer this dump everywhere and use instead of the ".$Descriptor{1}{"Version"}." version descriptor");
- }
-}
-
-sub quickEmptyReports()
-{ # Quick "empty" reports
- # 4 times faster than merging equal dumps
- # NOTE: the dump contains the "LibraryVersion" attribute
- # if you change the version, then your dump will be different
- # OVERCOME: use -v1 and v2 options for comparing dumps
- # and don't change version in the XML descriptor (and dumps)
- # OVERCOME 2: separate meta info from the dumps in ACC 2.0
- if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
- {
- my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
- my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
- if($FilePath1 and $FilePath2)
- {
- my $Line = readLineNum($FilePath1, 0);
- if($Line=~/xml/)
- { # XML format
- # is not supported yet
- return;
- }
-
- local $/ = undef;
-
- open(DUMP1, $FilePath1);
- my $Content1 = ;
- close(DUMP1);
-
- open(DUMP2, $FilePath2);
- my $Content2 = ;
- close(DUMP2);
-
- if($Content1 eq $Content2)
- {
- # clean memory
- undef $Content2;
-
- # read a number of headers, libs, symbols and types
- my $ABIdump = eval($Content1);
-
- # clean memory
- undef $Content1;
-
- if(not $ABIdump) {
- exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
- }
- if(not $ABIdump->{"TypeInfo"})
- { # support for old dumps
- $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
- }
- if(not $ABIdump->{"SymbolInfo"})
- { # support for old dumps
- $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
- }
- read_Source_DumpInfo($ABIdump, 1);
- read_Libs_DumpInfo($ABIdump, 1);
- read_Machine_DumpInfo($ABIdump, 1);
- read_Machine_DumpInfo($ABIdump, 2);
-
- %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
- %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
-
- %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
- %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
-
- $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
- $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
- exitReport();
- }
+ $In::Desc{2}{"Version"} = $In::ABI{2}{"LibraryVersion"};
}
- }
-}
-
-sub initLogging($)
-{
- my $LibVersion = $_[0];
- # create log directory
- my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
- if($OutputLogPath{$LibVersion})
- { # user-defined by -log-path option
- ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
- }
- if($LogMode ne "n") {
- mkpath($LOG_DIR);
- }
- $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
- if($Debug)
- { # debug directory
- $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
- if(not $ExtraInfo)
- { # enable --extra-info
- $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
- }
- }
- resetLogging($LibVersion);
-}
-
-sub writeLog($$)
-{
- my ($LibVersion, $Msg) = @_;
- if($LogMode ne "n") {
- appendFile($LOG_PATH{$LibVersion}, $Msg);
- }
-}
-
-sub resetLogging($)
-{
- my $LibVersion = $_[0];
- if($LogMode!~/a|n/)
- { # remove old log
- unlink($LOG_PATH{$LibVersion});
- if($Debug) {
- rmtree($DEBUG_PATH{$LibVersion});
+ if(not defined $In::Desc{2}{"Version"}) {
+ $In::Desc{2}{"Version"} = "Y";
}
}
-}
-
-sub printErrorLog($)
-{
- my $LibVersion = $_[0];
- if($LogMode ne "n") {
- printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
- }
-}
-
-sub isDump($)
-{
- if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
- { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
- return $1;
- }
- return 0;
-}
-
-sub isDump_U($)
-{
- if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
- return $1;
- }
- return 0;
-}
-
-sub compareInit()
-{
- # read input XML descriptors or ABI dumps
- if(not $Descriptor{1}{"Path"}) {
- exitStatus("Error", "-old option is not specified");
- }
- if(not -e $Descriptor{1}{"Path"}) {
- exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
- }
-
- if(not $Descriptor{2}{"Path"}) {
- exitStatus("Error", "-new option is not specified");
- }
- if(not -e $Descriptor{2}{"Path"}) {
- exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
- }
-
- detect_default_paths("bin"); # to extract dumps
- if(isDump($Descriptor{1}{"Path"})
- and isDump($Descriptor{2}{"Path"}))
- { # optimization: equal ABI dumps
- quickEmptyReports();
- }
-
- printMsg("INFO", "preparation, please wait ...");
-
- if(isDump($Descriptor{1}{"Path"})) {
- read_ABI_Dump(1, $Descriptor{1}{"Path"});
- }
- else {
- readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
- }
-
- if(isDump($Descriptor{2}{"Path"})) {
- read_ABI_Dump(2, $Descriptor{2}{"Path"});
- }
- else {
- readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
- }
-
- if(not $Descriptor{1}{"Version"})
- { # set to default: X
- $Descriptor{1}{"Version"} = "X";
- print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
- }
-
- if(not $Descriptor{2}{"Version"})
- { # set to default: Y
- $Descriptor{2}{"Version"} = "Y";
- print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
- }
-
- if(not $UsedDump{1}{"V"}) {
- initLogging(1);
- }
-
- if(not $UsedDump{2}{"V"}) {
+ else
+ {
+ loadModule("ABIDump");
+ readDesc(createDesc($In::Desc{2}{"Path"}, 2), 2);
+
initLogging(2);
+ detectDefaultPaths("inc", "lib", undef, "gcc");
+ createABIDump(2);
}
- # check input data
- if(not $Descriptor{1}{"Headers"}) {
- exitStatus("Error", "can't find header files info in descriptor d1");
- }
- if(not $Descriptor{2}{"Headers"}) {
- exitStatus("Error", "can't find header files info in descriptor d2");
- }
+ clearSysFilesCache(1);
+ clearSysFilesCache(2);
- if(not $CheckHeadersOnly)
+ if(my $FPath = $In::Opt{"FilterPath"})
{
- if(not $Descriptor{1}{"Libs"}) {
- exitStatus("Error", "can't find libraries info in descriptor d1");
- }
- if(not $Descriptor{2}{"Libs"}) {
- exitStatus("Error", "can't find libraries info in descriptor d2");
- }
- }
-
- if($UseDumps)
- { # --use-dumps
- # parallel processing
- my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
- my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
-
- unlink($DumpPath1);
- unlink($DumpPath2);
-
- my $pid = fork();
- if($pid)
- { # dump on two CPU cores
- my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
- if($RelativeDirectory{1}) {
- @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
- }
- if($OutputLogPath{1}) {
- @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
- }
- if($CrossGcc) {
- @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
- }
- if($Quiet)
- {
- @PARAMS = (@PARAMS, "-quiet");
- @PARAMS = (@PARAMS, "-logging-mode", "a");
- }
- elsif($LogMode and $LogMode ne "w")
- { # "w" is default
- @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
- }
- if($ExtendedCheck) {
- @PARAMS = (@PARAMS, "-extended");
- }
- if($UserLang) {
- @PARAMS = (@PARAMS, "-lang", $UserLang);
- }
- if($TargetVersion{1}) {
- @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
- }
- if($BinaryOnly) {
- @PARAMS = (@PARAMS, "-binary");
- }
- if($SourceOnly) {
- @PARAMS = (@PARAMS, "-source");
- }
- if($SortDump) {
- @PARAMS = (@PARAMS, "-sort");
- }
- if($DumpFormat and $DumpFormat ne "perl") {
- @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
- }
- if($CheckHeadersOnly) {
- @PARAMS = (@PARAMS, "-headers-only");
- }
- if($Debug)
- {
- @PARAMS = (@PARAMS, "-debug");
- printMsg("INFO", "running perl $0 @PARAMS");
- }
- system("perl", $0, @PARAMS);
- if(not -f $DumpPath1) {
- exit(1);
- }
- }
- else
- { # child
- my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
- if($RelativeDirectory{2}) {
- @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
- }
- if($OutputLogPath{2}) {
- @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
- }
- if($CrossGcc) {
- @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
- }
- if($Quiet)
- {
- @PARAMS = (@PARAMS, "-quiet");
- @PARAMS = (@PARAMS, "-logging-mode", "a");
- }
- elsif($LogMode and $LogMode ne "w")
- { # "w" is default
- @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
- }
- if($ExtendedCheck) {
- @PARAMS = (@PARAMS, "-extended");
- }
- if($UserLang) {
- @PARAMS = (@PARAMS, "-lang", $UserLang);
- }
- if($TargetVersion{2}) {
- @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
- }
- if($BinaryOnly) {
- @PARAMS = (@PARAMS, "-binary");
- }
- if($SourceOnly) {
- @PARAMS = (@PARAMS, "-source");
- }
- if($SortDump) {
- @PARAMS = (@PARAMS, "-sort");
- }
- if($DumpFormat and $DumpFormat ne "perl") {
- @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
- }
- if($CheckHeadersOnly) {
- @PARAMS = (@PARAMS, "-headers-only");
- }
- if($Debug)
- {
- @PARAMS = (@PARAMS, "-debug");
- printMsg("INFO", "running perl $0 @PARAMS");
- }
- system("perl", $0, @PARAMS);
- if(not -f $DumpPath2) {
- exit(1);
- }
- else {
- exit(0);
- }
+ if(not -f $FPath) {
+ exitStatus("Access_Error", "can't access \'".$FPath."\'");
}
- waitpid($pid, 0);
- my @CMP_PARAMS = ("-l", $TargetLibraryName);
- @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
- @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
- if($TargetTitle ne $TargetLibraryName) {
- @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
- }
- if($ShowRetVal) {
- @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
- }
- if($CrossGcc) {
- @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
- }
- @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
- if($Quiet) {
- @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
- }
- if($ReportFormat and $ReportFormat ne "html")
- { # HTML is default format
- @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
- }
- if($OutputReportPath) {
- @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
- }
- if($BinaryReportPath) {
- @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
- }
- if($SourceReportPath) {
- @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
- }
- if($LoggingPath) {
- @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
- }
- if($CheckHeadersOnly) {
- @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
- }
- if($BinaryOnly) {
- @CMP_PARAMS = (@CMP_PARAMS, "-binary");
- }
- if($SourceOnly) {
- @CMP_PARAMS = (@CMP_PARAMS, "-source");
- }
- if($Debug)
- {
- @CMP_PARAMS = (@CMP_PARAMS, "-debug");
- printMsg("INFO", "running perl $0 @CMP_PARAMS");
- }
- system("perl", $0, @CMP_PARAMS);
- exit($?>>8);
- }
- if(not $Descriptor{1}{"Dump"}
- or not $Descriptor{2}{"Dump"})
- { # need GCC toolchain to analyze
- # header files and libraries
- detect_default_paths("inc|lib|gcc");
- }
- if(not $Descriptor{1}{"Dump"})
- {
- if(not $CheckHeadersOnly) {
- readLibs(1);
- }
- if($CheckHeadersOnly) {
- setLanguage(1, "C++");
- }
- searchForHeaders(1);
- $WORD_SIZE{1} = detectWordSize(1);
- }
- if(not $Descriptor{2}{"Dump"})
- {
- if(not $CheckHeadersOnly) {
- readLibs(2);
- }
- if($CheckHeadersOnly) {
- setLanguage(2, "C++");
- }
- searchForHeaders(2);
- $WORD_SIZE{2} = detectWordSize(2);
- }
- if($WORD_SIZE{1} ne $WORD_SIZE{2})
- { # support for old ABI dumps
- # try to synch different WORD sizes
- if(not checkDump(1, "2.1"))
- {
- $WORD_SIZE{1} = $WORD_SIZE{2};
- printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
- }
- elsif(not checkDump(2, "2.1"))
+ if(my $Filt = readFile($FPath))
{
- $WORD_SIZE{2} = $WORD_SIZE{1};
- printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
+ readFilter($Filt, 1);
+ readFilter($Filt, 2);
}
}
- elsif(not $WORD_SIZE{1}
- and not $WORD_SIZE{2})
- { # support for old ABI dumps
- $WORD_SIZE{1} = "4";
- $WORD_SIZE{2} = "4";
- }
- if($Descriptor{1}{"Dump"})
- { # support for old ABI dumps
- prepareTypes(1);
- }
- if($Descriptor{2}{"Dump"})
- { # support for old ABI dumps
- prepareTypes(2);
- }
- if($AppPath and not keys(%{$Symbol_Library{1}})) {
- printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
- }
- # process input data
- if($Descriptor{1}{"Headers"}
- and not $Descriptor{1}{"Dump"}) {
- readHeaders(1);
- }
- if($Descriptor{2}{"Headers"}
- and not $Descriptor{2}{"Dump"}) {
- readHeaders(2);
- }
- # clean memory
- %SystemHeaders = ();
- %mangled_name_gcc = ();
+ prepareCompare(1);
+ prepareCompare(2);
+
+ if($In::Opt{"AppPath"} and not keys(%{$In::ABI{1}{"SymLib"}})) {
+ printMsg("WARNING", "the application ".getFilename($In::Opt{"AppPath"})." has no symbols imported from libraries");
+ }
prepareSymbols(1);
prepareSymbols(2);
- # clean memory
- %SymbolInfo = ();
-
# Virtual Tables
registerVTable(1);
registerVTable(2);
-
- if(not checkDump(1, "1.22")
- and checkDump(2, "1.22"))
- { # support for old ABI dumps
- foreach my $ClassName (keys(%{$VirtualTable{2}}))
- {
- if($ClassName=~/)
- { # templates
- if(not defined $VirtualTable{1}{$ClassName})
- { # synchronize
- delete($VirtualTable{2}{$ClassName});
- }
- }
- }
- }
registerOverriding(1);
registerOverriding(2);
@@ -22284,13 +10085,13 @@
loadModule("CallConv");
if($Level eq "Binary") {
- printMsg("INFO", "comparing ABIs ...");
+ printMsg("INFO", "Comparing ABIs ...");
}
else {
- printMsg("INFO", "comparing APIs ...");
+ printMsg("INFO", "Comparing APIs ...");
}
- if($CheckHeadersOnly
+ if($In::Opt{"CheckHeadersOnly"}
or $Level eq "Source")
{ # added/removed in headers
detectAdded_H($Level);
@@ -22303,13 +10104,17 @@
}
mergeSymbols($Level);
- if(keys(%{$CheckedSymbols{$Level}})) {
- mergeConstants($Level);
+
+ if(not defined $In::Opt{"DisableConstantsCheck"})
+ {
+ if(keys(%{$CheckedSymbols{$Level}})) {
+ mergeConstants($Level);
+ }
}
$Cache{"mergeTypes"} = (); # free memory
- if($CheckHeadersOnly
+ if($In::Opt{"CheckHeadersOnly"}
or $Level eq "Source")
{ # added/removed in headers
mergeHeaders($Level);
@@ -22320,271 +10125,310 @@
}
}
-sub getSysOpts()
+sub initAliases($)
{
- my %Opts = (
- "OStarget"=>$OStarget,
- "Debug"=>$Debug,
- "Quiet"=>$Quiet,
- "LogMode"=>$LogMode,
- "CheckHeadersOnly"=>$CheckHeadersOnly,
-
- "SystemRoot"=>$SystemRoot,
- "GCC_PATH"=>$GCC_PATH,
- "TargetSysInfo"=>$TargetSysInfo,
- "CrossPrefix"=>$CrossPrefix,
- "TargetLibraryName"=>$TargetLibraryName,
- "CrossGcc"=>$CrossGcc,
- "UseStaticLibs"=>$UseStaticLibs,
- "NoStdInc"=>$NoStdInc,
+ my $LVer = $_[0];
- "BinaryOnly" => $BinaryOnly,
- "SourceOnly" => $SourceOnly
- );
- return \%Opts;
-}
-
-sub get_CodeError($)
-{
- my %CODE_ERROR = reverse(%ERROR_CODE);
- return $CODE_ERROR{$_[0]};
+ initABI($LVer);
+
+ $SymbolInfo{$LVer} = $In::ABI{$LVer}{"SymbolInfo"};
+ $TypeInfo{$LVer} = $In::ABI{$LVer}{"TypeInfo"};
+ $TName_Tid{$LVer} = $In::ABI{$LVer}{"TName_Tid"};
+ $Constants{$LVer} = $In::ABI{$LVer}{"Constants"};
+
+ initAliases_TypeAttr($LVer);
}
sub scenario()
{
- if($StdOut)
+ setTarget("default");
+
+ initAliases(1);
+ initAliases(2);
+
+ $In::Opt{"Locale"} = "C.UTF-8";
+ $In::Opt{"OrigDir"} = cwd();
+ $In::Opt{"Tmp"} = tempdir(CLEANUP=>1);
+ $In::Opt{"TargetLibShort"} = libPart($In::Opt{"TargetLib"}, "shortest");
+
+ $In::Opt{"DoubleReport"} = 0;
+ $In::Opt{"JoinReport"} = 1;
+
+ $In::Opt{"SysPaths"}{"include"} = [];
+ $In::Opt{"SysPaths"}{"lib"} = [];
+ $In::Opt{"SysPaths"}{"bin"} = [];
+
+ $In::Opt{"CompileError"} = 0;
+
+ if($In::Opt{"TargetComponent"}) {
+ $In::Opt{"TargetComponent"} = lc($In::Opt{"TargetComponent"});
+ }
+ else
+ { # default: library
+ $In::Opt{"TargetComponent"} = "library";
+ }
+
+ foreach (keys(%{$In::Desc{0}}))
+ { # common options
+ $In::Desc{1}{$_} = $In::Desc{0}{$_};
+ $In::Desc{2}{$_} = $In::Desc{0}{$_};
+ }
+
+ $In::Opt{"AddTemplateInstances"} = 1;
+ $In::Opt{"GccMissedMangling"} = 0;
+
+ if($In::Opt{"StdOut"})
{ # enable quiet mode
- $Quiet = 1;
- $JoinReport = 1;
+ $In::Opt{"Quiet"} = 1;
+ $In::Opt{"JoinReport"} = 1;
}
- if(not $LogMode)
+ if(not $In::Opt{"LogMode"})
{ # default
- $LogMode = "w";
+ $In::Opt{"LogMode"} = "w";
}
- if($UserLang)
- { # --lang=C++
- $UserLang = uc($UserLang);
- $COMMON_LANGUAGE{1}=$UserLang;
- $COMMON_LANGUAGE{2}=$UserLang;
+
+ if($In::Opt{"UserLang"}) {
+ $In::Opt{"UserLang"} = uc($In::Opt{"UserLang"});
}
- if($LoggingPath)
+
+ if(my $LoggingPath = $In::Opt{"LoggingPath"})
{
- $OutputLogPath{1} = $LoggingPath;
- $OutputLogPath{2} = $LoggingPath;
- if($Quiet) {
- $COMMON_LOG_PATH = $LoggingPath;
+ $In::Desc{1}{"OutputLogPath"} = $LoggingPath;
+ $In::Desc{2}{"OutputLogPath"} = $LoggingPath;
+ if($In::Opt{"Quiet"}) {
+ $In::Opt{"DefaultLog"} = $LoggingPath;
}
}
- if($SkipInternalSymbols) {
- $SkipInternalSymbols=~s/\*/.*/g;
- }
-
- if($SkipInternalTypes) {
- $SkipInternalTypes=~s/\*/.*/g;
+ if($In::Opt{"Force"}) {
+ $In::Opt{"GccMissedMangling"} = 1;
}
- if($Quick) {
- $ADD_TMPL_INSTANCES = 0;
+ if($In::Opt{"Quick"}) {
+ $In::Opt{"AddTemplateInstances"} = 0;
}
- if($OutputDumpPath)
+ if(my $DP = $In::Opt{"OutputDumpPath"})
{ # validate
- if(not isDump($OutputDumpPath)) {
- exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
+ if(not isDump($DP)) {
+ exitStatus("Error", "the dump path should be a path to *.dump or *.dump.".$In::Opt{"Ar"}." file");
}
}
- if($BinaryOnly and $SourceOnly)
+ if($In::Opt{"BinOnly"}
+ and $In::Opt{"SrcOnly"})
{ # both --binary and --source
# is the default mode
- if(not $CmpSystems)
+ if(not $In::Opt{"CmpSystems"})
{
- $BinaryOnly = 0;
- $SourceOnly = 0;
+ $In::Opt{"BinOnly"} = 0;
+ $In::Opt{"SrcOnly"} = 0;
}
- $DoubleReport = 1;
- $JoinReport = 0;
+ $In::Opt{"DoubleReport"} = 1;
+ $In::Opt{"JoinReport"} = 0;
- if($OutputReportPath)
+ if($In::Opt{"OutputReportPath"})
{ # --report-path
- $DoubleReport = 0;
- $JoinReport = 1;
+ $In::Opt{"DoubleReport"} = 0;
+ $In::Opt{"JoinReport"} = 1;
}
}
- elsif($BinaryOnly or $SourceOnly)
+ elsif($In::Opt{"BinOnly"}
+ or $In::Opt{"SrcOnly"})
{ # --binary or --source
- $DoubleReport = 0;
- $JoinReport = 0;
+ $In::Opt{"DoubleReport"} = 0;
+ $In::Opt{"JoinReport"} = 0;
}
- if($UseXML)
+ if($In::Opt{"UseXML"})
{ # --xml option
- $ReportFormat = "xml";
- $DumpFormat = "xml";
+ $In::Opt{"ReportFormat"} = "xml";
+ $In::Opt{"DumpFormat"} = "xml";
}
- if($ReportFormat)
+ if($In::Opt{"ReportFormat"})
{ # validate
- $ReportFormat = lc($ReportFormat);
- if($ReportFormat!~/\A(xml|html|htm)\Z/) {
- exitStatus("Error", "unknown report format \'$ReportFormat\'");
+ $In::Opt{"ReportFormat"} = lc($In::Opt{"ReportFormat"});
+ if($In::Opt{"ReportFormat"}!~/\A(xml|html|htm)\Z/) {
+ exitStatus("Error", "unknown report format \'".$In::Opt{"ReportFormat"}."\'");
}
- if($ReportFormat eq "htm")
+ if($In::Opt{"ReportFormat"} eq "htm")
{ # HTM == HTML
- $ReportFormat = "html";
+ $In::Opt{"ReportFormat"} = "html";
}
- elsif($ReportFormat eq "xml")
+ elsif($In::Opt{"ReportFormat"} eq "xml")
{ # --report-format=XML equal to --xml
- $UseXML = 1;
+ $In::Opt{"UseXML"} = 1;
}
}
else
{ # default: HTML
- $ReportFormat = "html";
+ $In::Opt{"ReportFormat"} = "html";
}
- if($DumpFormat)
+ if($In::Opt{"DumpFormat"})
{ # validate
- $DumpFormat = lc($DumpFormat);
- if($DumpFormat!~/\A(xml|perl)\Z/) {
- exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
+ $In::Opt{"DumpFormat"} = lc($In::Opt{"DumpFormat"});
+ if($In::Opt{"DumpFormat"}!~/\A(xml|perl)\Z/) {
+ exitStatus("Error", "unknown ABI dump format \'".$In::Opt{"DumpFormat"}."\'");
}
- if($DumpFormat eq "xml")
+ if($In::Opt{"DumpFormat"} eq "xml")
{ # --dump-format=XML equal to --xml
- $UseXML = 1;
+ $In::Opt{"UseXML"} = 1;
}
}
else
{ # default: Perl Data::Dumper
- $DumpFormat = "perl";
+ $In::Opt{"DumpFormat"} = "perl";
}
- if($Quiet and $LogMode!~/a|n/)
+ if($In::Opt{"Quiet"} and $In::Opt{"LogMode"}!~/a|n/)
{ # --quiet log
- if(-f $COMMON_LOG_PATH) {
- unlink($COMMON_LOG_PATH);
+ if(-f $In::Opt{"DefaultLog"}) {
+ unlink($In::Opt{"DefaultLog"});
}
}
- if($ExtraInfo) {
- $CheckUndefined = 1;
+ if($In::Opt{"ExtraInfo"}) {
+ $In::Opt{"CheckUndefined"} = 1;
}
- if($TestTool and $UseDumps)
+
+ if($In::Opt{"TestTool"} and $In::Opt{"UseDumps"})
{ # --test && --use-dumps == --test-dump
- $TestDump = 1;
+ $In::Opt{"TestDump"} = 1;
}
- if($Tolerant)
+ if($In::Opt{"Tolerant"})
{ # enable all
- $Tolerance = 1234;
+ $In::Opt{"Tolerance"} = 1234;
}
- if($Help)
+ if($In::Opt{"Help"})
{
- HELP_MESSAGE();
+ helpMsg();
exit(0);
}
- if($InfoMsg)
+ if($In::Opt{"InfoMsg"})
{
- INFO_MESSAGE();
+ infoMsg();
exit(0);
}
- if($ShowVersion)
+ if($In::Opt{"ShowVersion"})
{
- printMsg("INFO", "ABI Compliance Checker (ABICC) $TOOL_VERSION\nCopyright (C) 2015 Andrey Ponomarenko's ABI Laboratory\nLicense: LGPL or GPL \nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko.");
+ printMsg("INFO", "ABI Compliance Checker (ABICC) $TOOL_VERSION\nCopyright (C) 2018 Andrey Ponomarenko's ABI Laboratory\nLicense: GNU LGPL 2.1 \nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko.");
exit(0);
}
- if($DumpVersion)
+ if($In::Opt{"DumpVersion"})
{
printMsg("INFO", $TOOL_VERSION);
exit(0);
}
- if($ExtendedCheck) {
- $CheckHeadersOnly = 1;
+ if($In::Opt{"ExtendedCheck"}) {
+ $In::Opt{"CheckHeadersOnly"} = 1;
}
- if($SystemRoot_Opt)
+ if($In::Opt{"SystemRoot"})
{ # user defined root
- if(not -e $SystemRoot_Opt) {
- exitStatus("Access_Error", "can't access \'$SystemRoot\'");
+ if(not -e $In::Opt{"SystemRoot"}) {
+ exitStatus("Access_Error", "can't access \'".$In::Opt{"SystemRoot"}."\'");
}
- $SystemRoot = $SystemRoot_Opt;
- $SystemRoot=~s/[\/]+\Z//g;
- if($SystemRoot) {
- $SystemRoot = get_abs_path($SystemRoot);
+ $In::Opt{"SystemRoot"}=~s/[\/]+\Z//g;
+ if($In::Opt{"SystemRoot"}) {
+ $In::Opt{"SystemRoot"} = getAbsPath($In::Opt{"SystemRoot"});
}
}
$Data::Dumper::Sortkeys = 1;
- if($SortDump)
+ if($In::Opt{"SortDump"})
{
$Data::Dumper::Useperl = 1;
$Data::Dumper::Sortkeys = \&dump_sorting;
}
- if($TargetLibsPath)
+ if(my $TargetLibsPath = $In::Opt{"TargetLibsPath"})
{
if(not -f $TargetLibsPath) {
exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
}
- foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
- $TargetLibs{$Lib} = 1;
+ foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath)))
+ {
+ if($In::Opt{"OS"} eq "windows") {
+ $In::Opt{"TargetLibs"}{lc($Lib)} = 1;
+ }
+ else {
+ $In::Opt{"TargetLibs"}{$Lib} = 1;
+ }
}
}
- if($TargetHeadersPath)
+ if(my $TPath = $In::Opt{"TargetHeadersPath"})
{ # --headers-list
- if(not -f $TargetHeadersPath) {
- exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
+ if(not -f $TPath) {
+ exitStatus("Access_Error", "can't access file \'$TPath\'");
}
- foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
+
+ $In::Desc{1}{"TargetHeader"} = {};
+ $In::Desc{2}{"TargetHeader"} = {};
+
+ foreach my $Header (split(/\s*\n\s*/, readFile($TPath)))
{
- $TargetHeaders{1}{get_filename($Header)} = 1;
- $TargetHeaders{2}{get_filename($Header)} = 1;
+ my $Name = getFilename($Header);
+ $In::Desc{1}{"TargetHeader"}{$Name} = 1;
+ $In::Desc{2}{"TargetHeader"}{$Name} = 1;
}
}
- if($TargetHeader)
+ if($In::Opt{"TargetHeader"})
{ # --header
- $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
- $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
+ $In::Desc{1}{"TargetHeader"} = {};
+ $In::Desc{2}{"TargetHeader"} = {};
+
+ my $Name = getFilename($In::Opt{"TargetHeader"});
+ $In::Desc{1}{"TargetHeader"}{$Name} = 1;
+ $In::Desc{2}{"TargetHeader"}{$Name} = 1;
}
- if($TestTool
- or $TestDump)
+ if($In::Opt{"TestABIDumper"})
+ {
+ if($In::Opt{"OS"} ne "linux") {
+ exitStatus("Error", "-test-abi-dumper option is available on Linux only");
+ }
+ }
+ if($In::Opt{"TestTool"}
+ or $In::Opt{"TestDump"}
+ or $In::Opt{"TestABIDumper"})
{ # --test, --test-dump
- detect_default_paths("bin|gcc"); # to compile libs
+ detectDefaultPaths(undef, undef, "bin", "gcc"); # to compile libs
loadModule("RegTests");
- testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
- $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
+ testTool();
exit(0);
}
- if($DumpSystem)
+ if($In::Opt{"DumpSystem"})
{ # --dump-system
+ if(not $In::Opt{"TargetSysInfo"})
+ {
+ if(-d $MODULES_DIR."/Targets/"
+ and -d $MODULES_DIR."/Targets/".$In::Opt{"Target"}) {
+ $In::Opt{"TargetSysInfo"} = $MODULES_DIR."/Targets/".$In::Opt{"Target"};
+ }
+ }
- if(not $TargetSysInfo) {
+ if(not $In::Opt{"TargetSysInfo"}) {
exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
}
- if(not -d $TargetSysInfo) {
- exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
+ if(not -d $In::Opt{"TargetSysInfo"}) {
+ exitStatus("Access_Error", "can't access \'".$In::Opt{"TargetSysInfo"}."\'");
}
loadModule("SysCheck");
- if($DumpSystem=~/\.(xml|desc)\Z/)
+ if($In::Opt{"DumpSystem"}=~/\.(xml|desc)\Z/)
{ # system XML descriptor
- if(not -f $DumpSystem) {
- exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
+ if(not -f $In::Opt{"DumpSystem"}) {
+ exitStatus("Access_Error", "can't access file \'".$In::Opt{"DumpSystem"}."\'");
}
- my $SDesc = readFile($DumpSystem);
- if(my $RelDir = $RelativeDirectory{1}) {
- $SDesc =~ s/{RELPATH}/$RelDir/g;
+ my $SDesc = readFile($In::Opt{"DumpSystem"});
+ if(my $RelDir = $In::Desc{1}{"RelativeDirectory"}) {
+ $SDesc=~s/\{RELPATH\}/$RelDir/g;
}
- my $Ret = readSystemDescriptor($SDesc);
- foreach (@{$Ret->{"Tools"}})
- {
- push_U($SystemPaths{"bin"}, $_);
- $TargetTools{$_} = 1;
- }
- if($Ret->{"CrossPrefix"}) {
- $CrossPrefix = $Ret->{"CrossPrefix"};
- }
+ readSysDesc($SDesc);
}
- elsif($SystemRoot_Opt)
+ elsif(defined $In::Opt{"SystemRoot"})
{ # -sysroot "/" option
# default target: /usr/lib, /usr/include
# search libs: /usr/lib and /lib
+ my $SystemRoot = $In::Opt{"SystemRoot"};
+
if(not -e $SystemRoot."/usr/lib") {
exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
}
@@ -22594,9 +10438,9 @@
if(not -e $SystemRoot."/usr/include") {
exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
}
- readSystemDescriptor("
+ readSysDesc("
- $DumpSystem
+ ".$In::Opt{"DumpSystem"}."
$SystemRoot/usr/include
@@ -22611,90 +10455,105 @@
else {
exitStatus("Error", "-sysroot option should be specified, usually it's \"/\"");
}
- detect_default_paths("bin|gcc"); # to check symbols
- if($OStarget eq "windows")
+ detectDefaultPaths(undef, undef, "bin", "gcc"); # to check symbols
+ if($In::Opt{"Target"} eq "windows")
{ # to run dumpbin.exe
# and undname.exe
- check_win32_env();
+ checkWin32Env();
}
- dumpSystem(getSysOpts());
+ dumpSystem();
exit(0);
}
- if($CmpSystems)
+
+ if($In::Opt{"CmpSystems"})
{ # --cmp-systems
- detect_default_paths("bin"); # to extract dumps
+ detectDefaultPaths(undef, undef, "bin", undef); # to extract dumps
loadModule("SysCheck");
- cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
+
+ if(not $In::Opt{"BinOnly"}
+ and not $In::Opt{"SrcOnly"})
+ { # default
+ $In::Opt{"BinOnly"} = 1;
+ }
+
+ cmpSystems($In::Desc{1}{"Path"}, $In::Desc{2}{"Path"});
exit(0);
}
- if(not $TargetLibraryName) {
- exitStatus("Error", "library name is not selected (-l option)");
- }
- else
- { # validate library name
- if($TargetLibraryName=~/[\*\/\\]/) {
- exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
+
+ if(not $In::Opt{"CountSymbols"})
+ {
+ if(not $In::Opt{"TargetLib"}) {
+ exitStatus("Error", "library name is not selected (-l option)");
+ }
+ else
+ { # validate library name
+ if($In::Opt{"TargetLib"}=~/[\*\/\\]/) {
+ exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
+ }
}
}
- if(not $TargetTitle) {
- $TargetTitle = $TargetLibraryName;
+
+ if(not $In::Opt{"TargetTitle"}) {
+ $In::Opt{"TargetTitle"} = $In::Opt{"TargetLib"};
}
- if($SymbolsListPath)
+ if(my $SymbolsListPath = $In::Opt{"SymbolsListPath"})
{
if(not -f $SymbolsListPath) {
exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
}
- foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
- $SymbolsList{$Interface} = 1;
+ foreach my $S (split(/\s*\n\s*/, readFile($SymbolsListPath)))
+ {
+ $In::Desc{1}{"SymbolsList"}{$S} = 1;
+ $In::Desc{2}{"SymbolsList"}{$S} = 1;
}
}
- if($TypesListPath)
+ if(my $TypesListPath = $In::Opt{"TypesListPath"})
{
if(not -f $TypesListPath) {
exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
}
- foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
- $TypesList{$Type} = 1;
+ foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath)))
+ {
+ $In::Desc{1}{"TypesList"}{$Type} = 1;
+ $In::Desc{2}{"TypesList"}{$Type} = 1;
}
}
- if($SkipSymbolsListPath)
+ if(my $SymbolsListPath = $In::Opt{"SkipSymbolsListPath"})
{
- if(not -f $SkipSymbolsListPath) {
- exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
+ if(not -f $SymbolsListPath) {
+ exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
}
- foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
+ foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath)))
{
- $SkipSymbols{1}{$Interface} = 1;
- $SkipSymbols{2}{$Interface} = 1;
+ $In::Desc{1}{"SkipSymbols"}{$Interface} = 1;
+ $In::Desc{2}{"SkipSymbols"}{$Interface} = 1;
}
}
- if($SkipTypesListPath)
+ if(my $TypesListPath = $In::Opt{"SkipTypesListPath"})
{
- if(not -f $SkipTypesListPath) {
- exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
+ if(not -f $TypesListPath) {
+ exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
}
- foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
+ foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath)))
{
- $SkipTypes{1}{$Type} = 1;
- $SkipTypes{2}{$Type} = 1;
+ $In::Desc{1}{"SkipTypes"}{$Type} = 1;
+ $In::Desc{2}{"SkipTypes"}{$Type} = 1;
}
}
- if($SkipHeadersPath)
+ if(my $HeadersList = $In::Opt{"SkipHeadersPath"})
{
- if(not -f $SkipHeadersPath) {
- exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
+ if(not -f $HeadersList) {
+ exitStatus("Access_Error", "can't access file \'$HeadersList\'");
}
- foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
- { # register for both versions
- $SkipHeadersList{1}{$Path} = 1;
- $SkipHeadersList{2}{$Path} = 1;
+ foreach my $Path (split(/\s*\n\s*/, readFile($HeadersList)))
+ {
my ($CPath, $Type) = classifyPath($Path);
- $SkipHeaders{1}{$Type}{$CPath} = 1;
- $SkipHeaders{2}{$Type}{$CPath} = 1;
+ $In::Desc{1}{"SkipHeaders"}{$Type}{$CPath} = 1;
+ $In::Desc{2}{"SkipHeaders"}{$Type}{$CPath} = 1;
}
}
- if($ParamNamesPath)
+ if(my $ParamNamesPath = $In::Opt{"ParamNamesPath"})
{
if(not -f $ParamNamesPath) {
exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
@@ -22707,49 +10566,104 @@
if($Line=~/;(\d+);/)
{
while($Line=~s/(\d+);(\w+)//) {
- $AddIntParams{$Interface}{$1}=$2;
+ $AddSymbolParams{$Interface}{$1}=$2;
}
}
else
{
my $Num = 0;
foreach my $Name (split(/;/, $Line)) {
- $AddIntParams{$Interface}{$Num++}=$Name;
+ $AddSymbolParams{$Interface}{$Num++}=$Name;
}
}
}
}
}
- if($AppPath)
+
+ if(my $AppPath = $In::Opt{"AppPath"})
{
if(not -f $AppPath) {
exitStatus("Access_Error", "can't access file \'$AppPath\'");
}
- detect_default_paths("bin|gcc");
- foreach my $Interface (readSymbols_App($AppPath)) {
- $SymbolsList_App{$Interface} = 1;
+ detectDefaultPaths(undef, undef, "bin", "gcc");
+ foreach my $Symbol (readSymbols_App($AppPath)) {
+ $In::Opt{"SymbolsList_App"}{$Symbol} = 1;
+ }
+ }
+
+ if(my $Path = $In::Opt{"CountSymbols"})
+ {
+ if(not -e $Path) {
+ exitStatus("Access_Error", "can't access \'$Path\'");
+ }
+
+ $In::ABI{1} = readABIDump(1, $Path);
+ initAliases(1);
+
+ foreach my $Id (keys(%{$SymbolInfo{1}}))
+ {
+ my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
+ if(not $MnglName) {
+ $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
+ }
+
+ if(my $SV = $In::ABI{1}{"SymbolVersion"}{$MnglName}) {
+ $CompSign{1}{$SV} = $SymbolInfo{1}{$Id};
+ }
+ else {
+ $CompSign{1}{$MnglName} = $SymbolInfo{1}{$Id};
+ }
+
+ if(my $Alias = $CompSign{1}{$MnglName}{"Alias"}) {
+ $CompSign{1}{$Alias} = $SymbolInfo{1}{$Id};
+ }
+ }
+
+ my $Count = 0;
+ foreach my $Symbol (sort keys(%{$CompSign{1}}))
+ {
+ if($CompSign{1}{$Symbol}{"PureVirt"}) {
+ next;
+ }
+
+ if(not $CompSign{1}{$Symbol}{"Header"})
+ {
+ if(index($CompSign{1}{$Symbol}{"Source"}, ".f")==-1)
+ { # Fortran
+ next;
+ }
+ }
+
+ $Count += symbolFilter($Symbol, $CompSign{1}{$Symbol}, "Affected + InlineVirt", "Binary", 1);
}
+
+ printMsg("INFO", $Count);
+ exit(0);
}
- if($DumpAPI)
- { # --dump-abi
- # make an API dump
- create_ABI_Dump();
- exit($COMPILE_ERRORS);
+
+ if($In::Opt{"DumpABI"})
+ {
+ createABIFile(1, $In::Opt{"DumpABI"});
+
+ if($In::Opt{"CompileError"}) {
+ exit(getErrorCode("Compile_Error"));
+ }
+
+ exit(0);
}
+
# default: compare APIs
- # -d1
- # -d2
compareInit();
- if($JoinReport or $DoubleReport)
+ if($In::Opt{"JoinReport"} or $In::Opt{"DoubleReport"})
{
compareAPIs("Binary");
compareAPIs("Source");
}
- elsif($BinaryOnly) {
+ elsif($In::Opt{"BinOnly"}) {
compareAPIs("Binary");
}
- elsif($SourceOnly) {
+ elsif($In::Opt{"SrcOnly"}) {
compareAPIs("Source");
}
exitReport();
diff -Nru abi-compliance-checker-1.99.14/debian/changelog abi-compliance-checker-2.3/debian/changelog
--- abi-compliance-checker-1.99.14/debian/changelog 2015-11-06 20:42:31.000000000 +0000
+++ abi-compliance-checker-2.3/debian/changelog 2024-03-19 00:45:44.000000000 +0000
@@ -1,3 +1,119 @@
+abi-compliance-checker (2.3-2~16.04.sav0) xenial; urgency=medium
+
+ * Backport to Xenial
+
+ -- Rob Savoury Mon, 18 Mar 2024 17:45:44 -0700
+
+abi-compliance-checker (2.3-2) unstable; urgency=medium
+
+ [ Mathieu Malaterre ]
+ * d/control: Point to actual correct homepage
+
+ [ Steve Langasek ]
+ * d/patches: Fix Invalid use of Perl "next". Closes: #951076
+ * d/patches: uses inconsitent flags to GCC for C code. Closes: #1030540
+
+ [ Mathieu Malaterre ]
+ * d/s/lintian-overrides: remove warning about doc/index.html
+ * d/control: Bump Std-Vers to 4.6.2 no changes needed
+
+ -- Mathieu Malaterre Thu, 23 Feb 2023 08:27:46 +0100
+
+abi-compliance-checker (2.3-1) unstable; urgency=medium
+
+ * d/patches: statx and statx_timestamp need to be skipped. Closes: #916294
+ * d/control: Update location of source code
+ * d/control: Update new Vcs locations
+ * d/compat: Move to compat 10
+ * d/control: Bumpt Std-Vers to 4.6.0 no changes needed
+
+ -- Mathieu Malaterre Thu, 09 Dec 2021 07:55:56 +0100
+
+abi-compliance-checker (2.3-0.2) unstable; urgency=medium
+
+ * Non-maintainer upload
+
+ [ Steve Langasek ]
+ * debian/patches/fpic-for-arm64.patch: require -fPIC on arm64 in
+ addition to x86_64 and arm (Closes: #907604).
+ * debian/patches/oom-exec-helper.patch: Run packing commands in a
+ subprocess (Closes: #907602).
+
+ -- Gianfranco Costamagna Tue, 04 Sep 2018 10:28:14 +0200
+
+abi-compliance-checker (2.3-0.1) unstable; urgency=medium
+
+ * Non-maintainer upload
+ * New upstream release (Closes: #904126)
+ * Update copyright and licenses
+
+ -- Gianfranco Costamagna Thu, 19 Jul 2018 20:57:41 +0200
+
+abi-compliance-checker (2.2-2) unstable; urgency=medium
+
+ * Update Std-Vers to 4.1.0, no changes needed
+ * Fix lintian warning: privacy-breach-logo
+
+ -- Mathieu Malaterre Wed, 20 Sep 2017 14:24:17 +0200
+
+abi-compliance-checker (2.2-1) unstable; urgency=medium
+
+ * New upstream release: 2.2. Remove patches:
+ - d/p/emergency-mode.patch
+ - d/p/fix-test-compilation.patch
+ - d/p/remove-gcc-check.patch
+ * Remove Ryan Niebur from Uploaders. Closes: #856362.
+ Thanks for your work !
+
+ -- Mathieu Malaterre Fri, 15 Sep 2017 21:44:01 +0200
+
+abi-compliance-checker (1.99.22-1.1) unstable; urgency=high
+
+ [ Dmitry Shachnev ]
+ * Add a patch to fix tests compilation with new GCC.
+ * Add a patch to not rely on GCC for symbols mangling, it is not working
+ with GCC 6 and GCC 7 because of PR c++/78040.
+
+ [ Gianfranco Costamagna ]
+ * Non-maintainer upload
+ * Fix autopkgtests, due to bad doit call (Closes: #868473)
+
+ -- Gianfranco Costamagna Fri, 01 Sep 2017 07:51:53 +0200
+
+abi-compliance-checker (1.99.22-1) unstable; urgency=medium
+
+ * New upstream release
+
+ -- Mathieu Malaterre Sat, 16 Jul 2016 21:24:11 +0200
+
+abi-compliance-checker (1.99.20-3) unstable; urgency=medium
+
+ * Fix copyright file missing. Closes: #825556
+
+ -- Mathieu Malaterre Wed, 01 Jun 2016 17:47:57 +0200
+
+abi-compliance-checker (1.99.20-2) unstable; urgency=medium
+
+ * Make sure to build manpage during indep build.
+
+ -- Mathieu Malaterre Mon, 23 May 2016 09:55:55 +0200
+
+abi-compliance-checker (1.99.20-1) unstable; urgency=medium
+
+ * New release. Closes: #825053. Remove patches applied upstream:
+ - d/p/bug798470.patch
+ - d/p/bug805441.patch
+ * Bump Std-Vers to 3.9.8, no changes needed
+
+ -- Mathieu Malaterre Mon, 23 May 2016 09:09:59 +0200
+
+abi-compliance-checker (1.99.14-1.1) unstable; urgency=medium
+
+ * Non-maintainer upload.
+ * Restore support for GNU/Hurd - backport from upstream (Closes: #805441)
+
+ -- Mattias Ellert Sun, 08 May 2016 06:34:53 +0200
+
abi-compliance-checker (1.99.14-1) unstable; urgency=medium
* New release. Refresh patches.
diff -Nru abi-compliance-checker-1.99.14/debian/compat abi-compliance-checker-2.3/debian/compat
--- abi-compliance-checker-1.99.14/debian/compat 2013-04-19 13:08:55.000000000 +0000
+++ abi-compliance-checker-2.3/debian/compat 2021-12-09 06:55:26.000000000 +0000
@@ -1 +1 @@
-9
+10
diff -Nru abi-compliance-checker-1.99.14/debian/control abi-compliance-checker-2.3/debian/control
--- abi-compliance-checker-1.99.14/debian/control 2015-09-16 19:54:01.000000000 +0000
+++ abi-compliance-checker-2.3/debian/control 2023-02-23 07:27:22.000000000 +0000
@@ -1,14 +1,13 @@
Source: abi-compliance-checker
Section: devel
Priority: optional
-Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), help2man
-Maintainer: Ryan Niebur
-Uploaders: Mathieu Malaterre
-Standards-Version: 3.9.6
-Homepage: http://ispras.linux-foundation.org/index.php/ABI_compliance_checker
-Vcs-Svn: svn://anonscm.debian.org/collab-maint/deb-maint/abi-compliance-checker/trunk
-Vcs-Browser: http://anonscm.debian.org/viewvc/collab-maint/deb-maint/abi-compliance-checker/trunk/
+Build-Depends: debhelper (>= 10), dpkg-dev (>= 1.16.1~), help2man
+Maintainer: Mathieu Malaterre
+Standards-Version: 4.6.2
+Homepage: https://lvc.github.io/abi-compliance-checker/
XS-Testsuite: autopkgtest
+Vcs-Browser: https://salsa.debian.org/debian/abi-compliance-checker
+Vcs-Git: https://salsa.debian.org/debian/abi-compliance-checker.git
Package: abi-compliance-checker
Architecture: all
diff -Nru abi-compliance-checker-1.99.14/debian/copyright abi-compliance-checker-2.3/debian/copyright
--- abi-compliance-checker-1.99.14/debian/copyright 2015-09-16 19:54:01.000000000 +0000
+++ abi-compliance-checker-2.3/debian/copyright 2021-12-09 06:53:37.000000000 +0000
@@ -1,11 +1,12 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Source: http://ispras.linux-foundation.org/index.php/ABI_compliance_checker_Downloads
+Upstream-Source: https://github.com/lvc/abi-compliance-checker/
Upstream-Name: ABI compliance checker
Files: *
Copyright: Copyright 2009, The Linux Foundation
Copyright 2009, Institute for System Programming, Russian Academy of Sciences
-License: GPL-3+
+ Copyright: 2015-2018 Andrey Ponomarenko's ABI Laboratory
+License: LGPL-2.1+
Files: debian/*
Copyright: 2009, Ryan Niebur
@@ -15,6 +16,24 @@
Copyright: 2009, Paul Sladen
License: GPL-3+
+License: LGPL-2.1+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, or (at your option)
+ any later version.
+ .
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+ .
+ You should have received a copy of the GNU Lesser General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ .
+ On Debian systems, the complete text of the GNU Lesser General Public
+ License version 2.1 can be found in ‘/usr/share/common-licenses/LGPL-2.1’.
+
License: GPL-3+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff -Nru abi-compliance-checker-1.99.14/debian/dh/dh_acc abi-compliance-checker-2.3/debian/dh/dh_acc
--- abi-compliance-checker-1.99.14/debian/dh/dh_acc 2013-04-19 13:08:55.000000000 +0000
+++ abi-compliance-checker-2.3/debian/dh/dh_acc 2021-12-09 06:49:16.000000000 +0000
@@ -56,11 +56,11 @@
if ($definition) {
# TODO if next command fails, should output debug/log info?
- doit("abi-compliance-checker -q -l $package -v1 $version -dump $definition -dump-path $abidump");
+ doit('abi-compliance-checker', '-q', '-l', $package, '-v1', $version, '-dump', $definition, '-dump-path', $abidump);
}
if ($base) {
- doit("abi-compliance-checker -l $package -d1 $base -d2 $abidump -report-path ${path}_report.html");
- doit("abi-compliance-checker -q -l $package -d1 $base -d2 $abidump -xml -report-path ${path}_report.xml");
+ doit('abi-compliance-checker', '-l', $package, '-d1', $base, '-d2', $abidump, '-report-path', ${path}.'_report.html');
+ doit('abi-compliance-checker', '-q', '-l', $package, '-d1', $base, '-d2', $abidump, '-xml', '-report-path', ${path}.'_report.xml');
}
# TODO clean up temp files & logs
}
diff -Nru abi-compliance-checker-1.99.14/debian/patches/0659b3b0a23e3535f41c6fd8dee5255ad8e29f7e.patch abi-compliance-checker-2.3/debian/patches/0659b3b0a23e3535f41c6fd8dee5255ad8e29f7e.patch
--- abi-compliance-checker-1.99.14/debian/patches/0659b3b0a23e3535f41c6fd8dee5255ad8e29f7e.patch 1970-01-01 00:00:00.000000000 +0000
+++ abi-compliance-checker-2.3/debian/patches/0659b3b0a23e3535f41c6fd8dee5255ad8e29f7e.patch 2021-12-09 06:53:37.000000000 +0000
@@ -0,0 +1,49 @@
+From 0659b3b0a23e3535f41c6fd8dee5255ad8e29f7e Mon Sep 17 00:00:00 2001
+From: Kier Davis
+Date: Mon, 13 Sep 2021 08:41:05 -0500
+Subject: [PATCH] add statx to list of ignored functions
+
+statx (like stat, wait, flock, sysinfo) is both the name of a function:
+
+ /usr/include/bits/statx-generic.h:int statx (int __dirfd, const char *__restrict __path, int __flags,
+ /usr/include/bits/statx-generic.h: unsigned int __mask, struct statx *__restrict __buf)
+
+and a struct:
+
+ /usr/include/linux/stat.h:struct statx {
+ ...
+ /usr/include/linux/stat.h:};
+
+Typically `statx` always denotes the function and `struct statx` denotes the struct.
+
+When usage of the struct is encountered in C++ code, abi-compliance-checker generates this line in dump1.h:
+
+ statx* tmp_add_class_66;
+
+which fails to compile:
+
+ /tmp/qktDQcucCm/dump1.h:103:3: error: 'statx' does not name a type
+ statx* tmp_add_class_66;
+ ^~~~~
+
+Ideally abi-compliance-checker should instead generate this in dump1.h:
+
+ struct statx* tmp_add_class_66;
+
+but determining when the `struct` qualifier should/shouldn't be used seems non-trivial, so lets take the same approach as we do for other similarly overloaded names.
+---
+ modules/Internals/TUDump.pm | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/modules/Internals/TUDump.pm b/modules/Internals/TUDump.pm
+index 1bc72f3..4eb7d35 100644
+--- a/modules/Internals/TUDump.pm
++++ b/modules/Internals/TUDump.pm
+@@ -45,6 +45,7 @@ my %C_Structure = map {$_=>1} (
+ "stat64",
+ "_stat64",
+ "_stati64",
++ "statx",
+ "if_nameindex",
+ "usb_device",
+ "sigaltstack",
diff -Nru abi-compliance-checker-1.99.14/debian/patches/bug798470.patch abi-compliance-checker-2.3/debian/patches/bug798470.patch
--- abi-compliance-checker-1.99.14/debian/patches/bug798470.patch 2015-11-06 20:42:09.000000000 +0000
+++ abi-compliance-checker-2.3/debian/patches/bug798470.patch 1970-01-01 00:00:00.000000000 +0000
@@ -1,19 +0,0 @@
-Description: drop timestamp from generated HTML reports
-Forwarded: not-needed
-Bug-Debian: http://bugs.debian.org/798470
-Author: Chris Lamb
-Reviewed-by: Mathieu Malaterre
-
-Index: abi-compliance-checker-1.99.14/abi-compliance-checker.pl
-===================================================================
---- abi-compliance-checker-1.99.14.orig/abi-compliance-checker.pl
-+++ abi-compliance-checker-1.99.14/abi-compliance-checker.pl
-@@ -17598,7 +17598,7 @@ sub getReportFooter()
- my $Footer = "";
-
- $Footer .= "
";
-- $Footer .= "