diff options
author | Andrey Ponomarenko <andrewponomarenko@yandex.ru> | 2016-08-19 19:06:58 +0300 |
---|---|---|
committer | Andrey Ponomarenko <andrewponomarenko@yandex.ru> | 2016-08-19 19:06:58 +0300 |
commit | 7e580d0580b78074a3c93117c01582fe89db33b4 (patch) | |
tree | 88df68e3d2e26ebccf94da55bd2df8110b7ce015 | |
parent | 3df9fba720617c105c7c20b87338ce888483f5dc (diff) | |
download | abi-dumper-7e580d0580b78074a3c93117c01582fe89db33b4.tar.gz |
Fixed detection of a symbol/type header. Fixed resolving of gnu_debuglink and gnu_debugaltlink. Fixed -public-headers option. Show warning if no exported symbols found in objects. Added -keep-registers-and-offsets option.
-rw-r--r-- | abi-dumper.pl | 274 |
1 files changed, 146 insertions, 128 deletions
diff --git a/abi-dumper.pl b/abi-dumper.pl index 4b92d7a..b213037 100644 --- a/abi-dumper.pl +++ b/abi-dumper.pl @@ -67,7 +67,7 @@ $SkipCxx, $Loud, $AddrToName, $DumpStatic, $Compare, $AltDebugInfoOpt, $AddDirs, $VTDumperPath, $SymbolsListPath, $PublicHeadersPath, $IgnoreTagsPath, $KernelExport, $UseTU, $ReimplementStd, $IncludePreamble, $IncludePaths, $CacheHeaders, $MixedHeaders, $Debug, -$SearchDirDebuginfo); +$SearchDirDebuginfo, $KeepRegsAndOffsets); my $CmdName = getFilename($0); @@ -130,6 +130,7 @@ GetOptions("h|help!" => \$Help, "mixed-headers!" => \$MixedHeaders, "kernel-export!" => \$KernelExport, "search-debuginfo=s" => \$SearchDirDebuginfo, + "keep-registers-and-offsets!" => \$KeepRegsAndOffsets, "debug!" => \$Debug, # extra options "use-tu-dump!" => \$UseTU, @@ -263,6 +264,10 @@ GENERAL OPTIONS: Search for debug-info files referenced from gnu_debuglink section of the object in DIR. + -keep-registers-and-offsets + Dump used registers and stack offsets even if incompatible + build options detected. + -debug Enable debug messages. @@ -301,6 +306,7 @@ my %DWARF_Info; # Alternate my %ImportedUnit; my %ImportedDecl; +my $AltDebugInfo = undef; # Dump my %TypeUnit; @@ -381,7 +387,7 @@ my $SRC_EXT = "c|cpp|cxx|c\\+\\+"; # Other my %NestedNameSpaces; -my $TargetName; +my $TargetName = undef; my %HeadersInfo; my %SourcesInfo; my %SymVer; @@ -1534,24 +1540,27 @@ sub read_DWARF_Dump($$) $SYS_GCCV = $1.$2; } - my %Opts = (); - while($Val=~s/(\A| )(\-O([0-3]|g))( |\Z)/ /) { - $Opts{keys(%Opts)} = $2; - } - - if(keys(%Opts)) + if(not defined $KeepRegsAndOffsets) { - if($Opts{keys(%Opts)-1} ne "-Og") + 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", "incompatible build option detected: ".$Opts{keys(%Opts)-1}." (required -Og for better analysis)"); + printMsg("WARNING", "the object should be compiled with -Og option for better analysis"); $IncompatibleOpt = 1; } } - else - { - printMsg("WARNING", "the object should be compiled with -Og option for better analysis"); - $IncompatibleOpt = 1; - } } else { $SYS_COMP = $Val; @@ -2612,9 +2621,6 @@ sub selectPublicType($) if(not defined $TypeToHeader{$TName}) { return 0; } - elsif($Header ne $TypeToHeader{$TName}) { - return 0; - } } elsif($MixedHeaders) { @@ -2625,13 +2631,6 @@ sub selectPublicType($) } return 0; } - elsif($Header ne $TypeToHeader{$TName}) - { - if(defined $Debug) { - warnPrivateType($TypeInfo{$Tid}{"Name"}, "OTHER_HEADER"); - } - return 0; - } } } else @@ -2665,10 +2664,6 @@ sub selectPublic($$) if(not defined $SymbolToHeader{$Symbol}) { return 0; } - elsif($Header ne $SymbolToHeader{$Symbol} - and not defined $SymbolInfo{$ID}{"Alias"}) { - return 0; - } } elsif($MixedHeaders) { @@ -2679,14 +2674,6 @@ sub selectPublic($$) } return 0; } - elsif($Header ne $SymbolToHeader{$Symbol} - and not defined $SymbolInfo{$ID}{"Alias"}) - { - if(defined $Debug) { - warnPrivateSymbol($Symbol, "OTHER_HEADER"); - } - return 0; - } } } else @@ -4214,23 +4201,22 @@ sub getSymbolInfo($) } } - if(not $SInfo{"Header"} or $SInfo{"External"}) + if(not $SInfo{"Header"} + or ($SInfo{"External"} and not defined $PublicHeader{$SInfo{"Header"}})) { - if(defined $SymbolToHeader{$MnglName}) { - $SInfo{"Header"} = $SymbolToHeader{$MnglName}; + if($SInfo{"MnglName"} and defined $SymbolToHeader{$SInfo{"MnglName"}}) { + $SInfo{"Header"} = chooseHeader($SInfo{"MnglName"}, $SInfo{"Source"}); } elsif(not $SInfo{"Class"} and defined $SymbolToHeader{$SInfo{"ShortName"}}) { - $SInfo{"Header"} = $SymbolToHeader{$SInfo{"ShortName"}}; + $SInfo{"Header"} = chooseHeader($SInfo{"ShortName"}, $SInfo{"Source"}); } } if($SInfo{"Alias"}) { - if(defined $SymbolToHeader{$SInfo{"Alias"}} - and $SymbolToHeader{$SInfo{"Alias"}} ne $SInfo{"Header"}) - { # TODO: review this case - $SInfo{"Header"} = $SymbolToHeader{$SInfo{"Alias"}}; + if(defined $SymbolToHeader{$SInfo{"Alias"}}) { + $SInfo{"Header"} = chooseHeader($SInfo{"Alias"}, $SInfo{"Source"}); } } @@ -4384,6 +4370,29 @@ sub getSymbolInfo($) } } +sub chooseHeader($$) +{ + my ($Symbol, $Source) = @_; + + my @Headers = keys(%{$SymbolToHeader{$Symbol}}); + + if($#Headers==0) { + return $Headers[0]; + } + + $Source=~s/\.\w+\Z//g; + foreach my $Header (@Headers) + { + if($Header=~/\A\Q$Source\E(|\.[\w\+]+)\Z/) { + return $Header; + } + } + + @Headers = sort {length($a)<=>length($b)} sort {lc($a) cmp lc($b)} @Headers; + + return $Headers[0]; +} + sub getTypeIdByName($$) { my ($Type, $Name) = @_; @@ -5098,8 +5107,8 @@ sub getDebugFile($$) my ($Obj, $Header) = @_; my $Str = `$EU_READELF_L --strings=.$Header \"$Obj\" 2>\"$TMP_DIR/error\"`; - if($Str=~/0\]\s*(.+)/) { - return $1; + if($Str=~/(\s|\[)0\]\s*(.+)/) { + return $2; } return undef; @@ -5209,7 +5218,7 @@ sub detectPublicSymbols($) my $Is_C = ($OBJ_LANG eq "C"); - foreach my $File (sort {lc($a) cmp lc($b)} @Headers) + foreach my $File (sort {length($b)<=>length($a)} sort {lc($b) cmp lc($a)} @Headers) { my $HName = getFilename($File); @@ -5221,6 +5230,7 @@ sub detectPublicSymbols($) } my $File_A = abs_path($File); + my $IncDir = getDirname($File_A); my $IncDir_O = getDirname($IncDir); @@ -5271,85 +5281,78 @@ sub detectPublicSymbols($) my $TuDump = $TmpDir."/tmp-inc.h.001t.tu"; - if(not -e $TuDump) { + if(not -e $TuDump) + { printMsg("ERROR", "failed to list symbols in the header \'$HName\'"); + next; } elsif($?) { printMsg("ERROR", "some errors occured when compiling header \'$HName\'"); } - else + + my (%Fdecl, %Tdecl, %Tname, %Ident, %NotDecl) = (); + my $Content = readFile($TuDump); + $Content=~s/\n[ ]+/ /g; + + my @Lines = split(/\n/, $Content); + foreach my $N (0 .. $#Lines) { - my (%Fdecl, %Tdecl, %Tname, %Ident, %NotDecl) = (); - my $Content = readFile($TuDump); - $Content=~s/\n[ ]+/ /g; - - my @Lines = split(/\n/, $Content); - foreach my $N (0 .. $#Lines) + my $Line = $Lines[$N]; + if(index($Line, "function_decl")!=-1 + or index($Line, "var_decl")!=-1) { - my $Line = $Lines[$N]; - if(index($Line, "function_decl")!=-1 - or index($Line, "var_decl")!=-1) + if($Line=~/name: \@(\d+)/) { - if($Line=~/name: \@(\d+)/) + my $Id = $1; + + if($Line=~/srcp: ([^:]+)\:\d/) { - my $Id = $1; - - if($Line=~/srcp: ([^:]+)\:\d/) - { - if(defined $PublicHeader{$1}) { - $Fdecl{$Id} = $1; - } + if(defined $PublicHeader{$1}) { + $Fdecl{$Id} = $1; } } } - elsif($Line=~/\@(\d+)\s+identifier_node\s+strg:\s+(\w+)/) - { - $Ident{$1} = $2; - } - elsif($Is_C) + } + elsif($Line=~/\@(\d+)\s+identifier_node\s+strg:\s+(\w+)/) + { + $Ident{$1} = $2; + } + elsif($Is_C) + { + if(index($Line, "type_decl")!=-1) { - if(index($Line, "type_decl")!=-1) + if($Line=~/\A\@(\d+)/) { - if($Line=~/\A\@(\d+)/) + my $Id = $1; + if($Line=~/name: \@(\d+)/) { - my $Id = $1; - if($Line=~/name: \@(\d+)/) + my $NId = $1; + + if($Line=~/srcp: ([^:]+)\:\d/) { - my $NId = $1; - - if($Line=~/srcp: ([^:]+)\:\d/) + if(defined $PublicHeader{$1}) { - if(defined $PublicHeader{$1}) - { - $Tdecl{$Id} = $1; - $Tname{$Id} = $NId; - } + $Tdecl{$Id} = $1; + $Tname{$Id} = $NId; } } } } - elsif(index($Line, "record_type")!=-1 - or index($Line, "union_type")!=-1) - { - if($Line!~/ flds:/) - { - if($Line=~/name: \@(\d+)/) - { - $NotDecl{$1} = 1; - } - } - } - elsif(index($Line, "enumeral_type")!=-1) + } + elsif(index($Line, "record_type")!=-1 + or index($Line, "union_type")!=-1) + { + if($Line!~/ flds:/) { - if($Line!~/ csts:/) + if($Line=~/name: \@(\d+)/) { - if($Line=~/name: \@(\d+)/) - { - $NotDecl{$1} = 1; - } + $NotDecl{$1} = 1; } } - elsif(index($Line, "integer_type")!=-1) + } + elsif(index($Line, "enumeral_type")!=-1) + { + if($Line!~/ csts:/) { if($Line=~/name: \@(\d+)/) { @@ -5357,31 +5360,38 @@ sub detectPublicSymbols($) } } } - } - - foreach my $Id (keys(%Fdecl)) - { - if(my $Name = $Ident{$Id}) { - $SymbolToHeader{$Name} = $Fdecl{$Id}; + elsif(index($Line, "integer_type")!=-1) + { + if($Line=~/name: \@(\d+)/) + { + $NotDecl{$1} = 1; + } } } - - if($Is_C) + } + + foreach my $Id (keys(%Fdecl)) + { + if(my $Name = $Ident{$Id}) { + $SymbolToHeader{$Name}{$Fdecl{$Id}} = 1; + } + } + + if($Is_C) + { + foreach my $Id (keys(%Tdecl)) { - foreach my $Id (keys(%Tdecl)) - { - if(defined $NotDecl{$Id}) { - next; - } - - if(my $Name = $Ident{$Tname{$Id}}) { - $TypeToHeader{$Name} = $Tdecl{$Id}; - } + if(defined $NotDecl{$Id}) { + next; + } + + if(my $Name = $Ident{$Tname{$Id}}) { + $TypeToHeader{$Name} = $Tdecl{$Id}; } } - - unlink($TuDump); } + + unlink($TuDump); } else { # using Ctags @@ -5395,7 +5405,7 @@ sub detectPublicSymbols($) foreach my $Line (split(/\n/, $List_S)) { if($Line=~/\A(\w+)/) { - $SymbolToHeader{$1} = $HName; + $SymbolToHeader{$1}{$HName} = 1; } } @@ -5635,11 +5645,14 @@ sub scenario() foreach my $Obj (@ARGV) { - $TargetName = getFilename(realpath($Obj)); - $TargetName=~s/\.debug\Z//; # nouveau.ko.debug - - if(index($TargetName, "libstdc++.so")==0) { - $STDCXX_TARGET = 1; + if(not $TargetName) + { + $TargetName = getFilename(realpath($Obj)); + $TargetName=~s/\.debug\Z//; # nouveau.ko.debug + + if(index($TargetName, "libstdc++.so")==0) { + $STDCXX_TARGET = 1; + } } read_Symbols($Obj); @@ -5660,6 +5673,10 @@ sub scenario() read_Vtables($Obj); } + if(not defined $Library_Symbol{$TargetName}) { + exitStatus("Error", "can't find exported symbols in object(s), please add a shared object on command line"); + } + if(not $Res) { exitStatus("No_DWARF", "can't find debug info in object(s)"); } @@ -5673,7 +5690,8 @@ sub scenario() { foreach my $Tid (sort {lc($TypeInfo{$a}{"Name"}) cmp lc($TypeInfo{$b}{"Name"})} keys(%TypeInfo)) { - if(not $TypeInfo{$Tid}{"Header"}) + if(not $TypeInfo{$Tid}{"Header"} + or not defined $PublicHeader{$TypeInfo{$Tid}{"Header"}}) { if($TypeInfo{$Tid}{"Type"}=~/Struct|Union|Enum|Typedef/) { |