aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Ponomarenko <andrewponomarenko@yandex.ru>2016-08-11 19:27:31 +0300
committerAndrey Ponomarenko <andrewponomarenko@yandex.ru>2016-08-11 19:27:31 +0300
commit0f715a644ce0651ad507936d43f9a8f4165fde16 (patch)
tree10715b059bad865f6581975576fcbc7c093a3023
parentfef4a9a033d243d5f9e44d3b28612b4f54c27ee2 (diff)
downloadabi-dumper-0f715a644ce0651ad507936d43f9a8f4165fde16.tar.gz
Added -search-debuginfo option. Do not dump registers usage and stack offsets if object is built with incompatible options. Fixed resolving of gnu_debuglink and gnu_debugaltlink. Fixed detection of incompatible build options. Print error message if input debug-info is corrupted. Fixed reading of v-tables. Fixed aliases of functions.
-rw-r--r--abi-dumper.pl199
1 files changed, 138 insertions, 61 deletions
diff --git a/abi-dumper.pl b/abi-dumper.pl
index 4447613..5201b90 100644
--- a/abi-dumper.pl
+++ b/abi-dumper.pl
@@ -1,6 +1,6 @@
#!/usr/bin/perl
###########################################################################
-# ABI Dumper 0.99.16
+# ABI Dumper 0.99.17
# Dump ABI of an ELF object containing DWARF debug info
#
# Copyright (C) 2013-2016 Andrey Ponomarenko's ABI Laboratory
@@ -46,7 +46,7 @@ use Cwd qw(abs_path cwd realpath);
use Storable qw(dclone);
use Data::Dumper;
-my $TOOL_VERSION = "0.99.16";
+my $TOOL_VERSION = "0.99.17";
my $ABI_DUMP_VERSION = "3.2";
my $ORIG_DIR = cwd();
my $TMP_DIR = tempdir(CLEANUP=>1);
@@ -66,7 +66,8 @@ $TargetVersion, $ExtraInfo, $FullDump, $AllTypes, $AllSymbols, $BinOnly,
$SkipCxx, $Loud, $AddrToName, $DumpStatic, $Compare, $AltDebugInfo,
$AddDirs, $VTDumperPath, $SymbolsListPath, $PublicHeadersPath,
$IgnoreTagsPath, $KernelExport, $UseTU, $ReimplementStd,
-$IncludePreamble, $IncludePaths, $CacheHeaders, $MixedHeaders, $Debug);
+$IncludePreamble, $IncludePaths, $CacheHeaders, $MixedHeaders, $Debug,
+$SearchDirDebuginfo);
my $CmdName = getFilename($0);
@@ -129,6 +130,7 @@ GetOptions("h|help!" => \$Help,
"reimplement-std!" => \$ReimplementStd,
"mixed-headers!" => \$MixedHeaders,
"kernel-export!" => \$KernelExport,
+ "search-debuginfo=s" => \$SearchDirDebuginfo,
"debug!" => \$Debug,
# extra options
"use-tu-dump!" => \$UseTU,
@@ -258,6 +260,10 @@ GENERAL OPTIONS:
symbols declared in the ksymtab section of the object and
system calls.
+ -search-debuginfo DIR
+ Search for debug-info files referenced from gnu_debuglink
+ section of the object in DIR.
+
-debug
Enable debug messages.
@@ -399,6 +405,8 @@ my $SYS_COMP;
my $LIB_LANG;
my $OBJ_LANG;
+my $IncompatibleOpt = undef;
+
# Errors
my $InvalidDebugLoc;
@@ -719,14 +727,11 @@ sub read_Symbols($)
$Symbol_Value{$Symbol} = $Value;
$Value_Symbol{$Value}{$Symbol} = 1;
- if(defined $PublicHeadersPath)
+ if(not defined $OBJ_LANG)
{
- if(not defined $OBJ_LANG)
+ if(index($Symbol, "_Z")==0)
{
- if(index($Symbol, "_Z")==0)
- {
- $OBJ_LANG = "C++";
- }
+ $OBJ_LANG = "C++";
}
}
}
@@ -808,12 +813,9 @@ sub read_Symbols($)
}
}
- if(defined $PublicHeadersPath)
+ if(not defined $OBJ_LANG)
{
- if(not defined $OBJ_LANG)
- {
- $OBJ_LANG = "C";
- }
+ $OBJ_LANG = "C";
}
}
@@ -965,18 +967,62 @@ sub read_DWARF_Info($)
if(my $DebugFile = getDebugFile($Path, "gnu_debuglink"))
{
my $DPath = $DebugFile;
+ my $DName = getFilename($DPath);
if(my $DDir = getDirname($Path))
{
$DPath = $DDir."/".$DPath;
}
- printMsg("INFO", "Reading $DPath (gnu_debuglink)");
+ my $Found = undef;
+ if(defined $SearchDirDebuginfo)
+ {
+ my @Files = findFiles($SearchDirDebuginfo, "f");
+
+ foreach my $F (@Files)
+ {
+ if(getFilename($F) eq $DName)
+ {
+ $Found = $F;
+ last;
+ }
+ }
+ }
+
+ if($Found)
+ {
+ $DPath = $Found;
+ printMsg("INFO", "Found debuginfo $DName (gnu_debuglink)");
+ }
- return read_DWARF_Info($DPath);
+ if($DPath ne $Path)
+ {
+ if(-e $DPath)
+ {
+ printMsg("INFO", "Reading debuginfo $DName (gnu_debuglink)");
+ return read_DWARF_Info($DPath);
+ }
+ else {
+ printMsg("WARNING", "Missed debuginfo $DName (gnu_debuglink)");
+ }
+ }
+ else {
+ return 0;
+ }
}
return 0;
}
+ else
+ {
+ if($Sect=~/\.gnu_debugaltlink/)
+ {
+ if(my $AltObj = getDebugAltLink($Path))
+ {
+ $AltDebugInfo = $AltObj;
+ read_Alt_Info($AltObj);
+ }
+ }
+ }
printMsg("INFO", "Reading debug-info");
@@ -1486,8 +1532,23 @@ sub read_DWARF_Dump($$)
$SYS_GCCV = $1.$2;
}
- if($Val=~/(\A| )(\-O[0-3])( |\Z)/) {
- printMsg("WARNING", "incompatible build option detected: $2");
+ my %Opts = ();
+ while($Val=~s/(\A| )(\-O([0-3]|g))( |\Z)/ /) {
+ $Opts{keys(%Opts)} = $2;
+ }
+
+ if(keys(%Opts))
+ {
+ if($Opts{keys(%Opts)-1} ne "-Og")
+ {
+ printMsg("WARNING", "incompatible build option detected: ".$Opts{keys(%Opts)-1}." (required -Og for better analysis)");
+ $IncompatibleOpt = 1;
+ }
+ }
+ else
+ {
+ printMsg("WARNING", "the object should be compiled with -Og option for better analysis");
+ $IncompatibleOpt = 1;
}
}
else {
@@ -1674,6 +1735,10 @@ sub read_DWARF_Dump($$)
}
}
+ if(not defined $ID) {
+ printMsg("ERROR", "the debuginfo looks empty or corrupted");
+ }
+
# read the last compile unit
# or all units if debug_info is compressed
complete_Dump($Primary);
@@ -1688,7 +1753,8 @@ sub read_Vtables($)
my $Dir = getDirname($Path);
- if(index($LIB_LANG, "C++")!=-1)
+ if(index($LIB_LANG, "C++")!=-1
+ or $OBJ_LANG eq "C++")
{
printMsg("INFO", "Reading v-tables");
@@ -1790,6 +1856,12 @@ sub dump_ABI()
$ABI{"PublicABI"} = "1";
}
+ if(defined $IncompatibleOpt)
+ {
+ $ABI{"MissedOffsets"} = "1";
+ $ABI{"MissedRegs"} = "1";
+ }
+
my $ABI_DUMP = Dumper(\%ABI);
if($StdOut)
@@ -3862,7 +3934,9 @@ sub getSymbolInfo($)
{
if($SInfo{"ShortName"})
{
- $SInfo{"Alias"} = $SInfo{"ShortName"};
+ if(index($SInfo{"ShortName"}, ".")==-1) {
+ $SInfo{"Alias"} = $SInfo{"ShortName"};
+ }
$SInfo{"ShortName"} = $SInfo{"MnglName"};
}
@@ -4211,7 +4285,8 @@ sub getSymbolInfo($)
my %PInfo = %{$DWARF_Info{$ParamId}};
- if(defined $Offset) {
+ if(defined $Offset
+ and not defined $IncompatibleOpt) {
$SInfo{"Param"}{$Pos}{"offset"} = $Offset;
}
@@ -4235,7 +4310,8 @@ sub getSymbolInfo($)
$SInfo{"Param"}{$Pos}{"name"} = "p".($PPos+1);
}
- if(defined $Reg)
+ if(defined $Reg
+ and not defined $IncompatibleOpt)
{
$SInfo{"Reg"}{$Pos} = $Reg;
}
@@ -5353,6 +5429,39 @@ sub detectPublicSymbols($)
}
}
+sub getDebugAltLink($)
+{
+ my $Obj = $_[0];
+
+ my $AltDebugFile = getDebugFile($Obj, "gnu_debugaltlink");
+
+ if(not $AltDebugFile) {
+ return undef;
+ }
+
+ my $Dir = getDirname($Obj);
+
+ my $AltObj_R = $AltDebugFile;
+ if($Dir and $Dir ne ".") {
+ $AltObj_R = $Dir."/".$AltObj_R;
+ }
+
+ my $AltObj = $AltObj_R;
+
+ while($AltObj=~s&/[^/]+/\.\./&/&){};
+
+ if(-e $AltObj)
+ {
+ printMsg("INFO", "Set alternate debug-info file to \'$AltObj\' (use -alt option to change it)");
+ return $AltObj;
+ }
+ else {
+ printMsg("WARNING", "can't access \'$AltObj_R\'");
+ }
+
+ return undef;
+}
+
sub scenario()
{
if($Help)
@@ -5381,6 +5490,13 @@ sub scenario()
$Data::Dumper::Sortkeys = \&dump_sorting;
}
+ if($SearchDirDebuginfo)
+ {
+ if(not -d $SearchDirDebuginfo) {
+ exitStatus("Access_Error", "can't access directory \'$SearchDirDebuginfo\'");
+ }
+ }
+
if($PublicHeadersPath)
{
if(not -e $PublicHeadersPath) {
@@ -5506,45 +5622,6 @@ sub scenario()
if(not -e $AltDebugInfo) {
exitStatus("Access_Error", "can't access \'$AltDebugInfo\'");
}
- }
- else
- {
- if(not check_Cmd($EU_READELF)) {
- exitStatus("Not_Found", "can't find \"$EU_READELF\" command");
- }
- foreach my $Obj (@ARGV)
- {
- my $Sect = `$EU_READELF_L -S \"$Obj\" 2>\"$TMP_DIR/error\"`;
-
- if($Sect=~/\.z?debug_info/)
- {
- if($Sect=~/\.gnu_debugaltlink/)
- {
- if(my $AltDebugFile = getDebugFile($Obj, "gnu_debugaltlink"))
- {
- my $AltObj_R = getDirname($Obj)."/".$AltDebugFile;
-
- my $AltObj = $AltObj_R;
-
- while($AltObj=~s&/[^/]+/\.\./&/&){};
-
- if(-e $AltObj)
- {
- printMsg("INFO", "Set alternate debug-info file to \'$AltObj\' (use -alt option to change it)");
- $AltDebugInfo = $AltObj;
- }
- else
- {
- printMsg("WARNING", "can't access \'$AltObj_R\'");
- }
- }
- }
- last;
- }
- }
- }
-
- if($AltDebugInfo) {
read_Alt_Info($AltDebugInfo);
}