diff options
author | Andrey Ponomarenko <aponomarenko@rosalab.ru> | 2015-10-13 00:13:47 +0300 |
---|---|---|
committer | Andrey Ponomarenko <aponomarenko@rosalab.ru> | 2015-10-13 00:13:47 +0300 |
commit | 6cca24c59e1f2f7a71453455c305d20497766aa2 (patch) | |
tree | de40eadf52ee8839a2dc8231bd2d70343c71512f | |
parent | 841155c67f12e4127b373ce978bf50bb9743808e (diff) | |
download | abi-dumper-6cca24c59e1f2f7a71453455c305d20497766aa2.tar.gz |
Added -public-headers option to filter out private symbols from the ABI dump. Added -ignore-tags option to help ctags tool to read symbols in header files. Support for gnu_debuglink in the object. Print warnings to stderr. Added warning on incompatible build options of the input object. Removed private -header-symbols option. Fixed Makefile.
-rw-r--r-- | INSTALL | 4 | ||||
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r--[-rwxr-xr-x] | Makefile.pl | 0 | ||||
-rw-r--r-- | abi-dumper.pl | 254 |
4 files changed, 221 insertions, 38 deletions
@@ -6,8 +6,8 @@ All rights reserved. RELEASE INFORMATION Project: ABI Dumper -Version: 0.99.10 -Date: 2015-09-08 +Version: 0.99.11 +Date: 2015-10-12 This file explains how to install and setup environment @@ -1,5 +1,6 @@ prefix ?= /usr +.PHONY: install install: perl Makefile.pl -install -prefix "$(prefix)" diff --git a/Makefile.pl b/Makefile.pl index 806e8ca..806e8ca 100755..100644 --- a/Makefile.pl +++ b/Makefile.pl diff --git a/abi-dumper.pl b/abi-dumper.pl index d74caf6..982bbbd 100644 --- a/abi-dumper.pl +++ b/abi-dumper.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl ########################################################################### -# ABI Dumper 0.99.10 +# ABI Dumper 0.99.11 # Dump ABI of an ELF object containing DWARF debug info # # Copyright (C) 2013-2015 Andrey Ponomarenko's ABI Laboratory @@ -17,6 +17,10 @@ # Elfutils (eu-readelf) # Vtable-Dumper (1.1 or newer) # +# SUGGESTS +# ======== +# Ctags (5.8 or newer) +# # COMPATIBILITY # ============= # ABI Compliance Checker >= 1.99.8 @@ -43,7 +47,7 @@ use Cwd qw(abs_path cwd realpath); use Storable qw(dclone); use Data::Dumper; -my $TOOL_VERSION = "0.99.10"; +my $TOOL_VERSION = "0.99.11"; my $ABI_DUMP_VERSION = "3.2"; my $ORIG_DIR = cwd(); my $TMP_DIR = tempdir(CLEANUP=>1); @@ -54,11 +58,13 @@ my $VTABLE_DUMPER_VERSION = "1.0"; my $LOCALE = "LANG=C.UTF-8"; my $EU_READELF = "eu-readelf"; my $EU_READELF_L = $LOCALE." ".$EU_READELF; +my $CTAGS = "ctags"; my ($Help, $ShowVersion, $DumpVersion, $OutputDump, $SortDump, $StdOut, $TargetVersion, $ExtraInfo, $FullDump, $AllTypes, $AllSymbols, $BinOnly, $SkipCxx, $Loud, $AddrToName, $DumpStatic, $Compare, $AltDebugInfo, -$AddDirs, $VTDumperPath, $HeaderSymbolsPath, $SymbolsListPath); +$AddDirs, $VTDumperPath, $SymbolsListPath, $PublicHeadersPath, +$IgnoreTagsPath); my $CmdName = getFilename($0); @@ -103,7 +109,7 @@ GetOptions("h|help!" => \$Help, "sort!" => \$SortDump, "stdout!" => \$StdOut, "loud!" => \$Loud, - "lver|lv=s" => \$TargetVersion, + "vnum|lver|lv=s" => \$TargetVersion, "extra-info=s" => \$ExtraInfo, "bin-only!" => \$BinOnly, "all-types!" => \$AllTypes, @@ -114,11 +120,12 @@ GetOptions("h|help!" => \$Help, "dump-static!" => \$DumpStatic, "compare!" => \$Compare, "alt=s" => \$AltDebugInfo, - "dir!" =>\$AddDirs, - "vt-dumper=s" =>\$VTDumperPath, + "dir!" => \$AddDirs, + "vt-dumper=s" => \$VTDumperPath, + "public-headers=s" => \$PublicHeadersPath, + "ignore-tags=s" => \$IgnoreTagsPath, # internal options - "addr2name!" => \$AddrToName, - "header-symbols=s" =>\$HeaderSymbolsPath + "addr2name!" => \$AddrToName ) or ERR_MESSAGE(); sub ERR_MESSAGE() @@ -173,7 +180,7 @@ GENERAL OPTIONS: -loud Print all warnings. - -lv|-lver NUM + -vnum NUM Set version of the library to NUM. -extra-info DIR @@ -215,6 +222,15 @@ GENERAL OPTIONS: -vt-dumper PATH Path to the vtable-dumper executable if it is installed to non-default location (not in PATH). + + -public-headers PATH + Path to directory with public header files or to file with + the list of header files. This option allows to filter out + private symbols from the ABI dump. + + -ignore-tags PATH + Path to ignore.tags file to help ctags tool to read + symbols in header files. "; sub HELP_MESSAGE() { @@ -330,12 +346,15 @@ my $SYS_WORD; my $SYS_GCCV; my $SYS_COMP; my $LIB_LANG; +my $OBJ_LANG; # Errors my $InvalidDebugLoc; -# Input +# Public Headers my %SymbolToHeader; +my %PublicHeader; +my $PublicSymbols_Detected; # Filter my %SymbolsList; @@ -349,7 +368,8 @@ sub printMsg($$) if($Type!~/_C\Z/) { $Msg .= "\n"; } - if($Type eq "ERROR") { + if($Type eq "ERROR" + or $Type eq "WARNING") { print STDERR $Msg; } else { @@ -594,6 +614,17 @@ sub read_Symbols($) $Symbol_Value{$Symbol} = $Value; $Value_Symbol{$Value}{$Symbol} = 1; + + if(defined $PublicHeadersPath) + { + if(not defined $OBJ_LANG) + { + if(index($Symbol, "_Z")==0) + { + $OBJ_LANG = "C++"; + } + } + } } foreach ($SectionInfo{$Ndx}, "") @@ -614,6 +645,10 @@ sub read_Symbols($) } close(LIB); + if(not defined $Library_Symbol{$TargetName}) { + return; + } + my %Found = (); foreach my $Symbol (keys(%{$Library_Symbol{$TargetName}})) { @@ -660,6 +695,14 @@ sub read_Symbols($) $Found{$Symbol} = 1; } } + + if(defined $PublicHeadersPath) + { + if(not defined $OBJ_LANG) + { + $OBJ_LANG = "C"; + } + } } sub read_Alt_Info($) @@ -807,6 +850,19 @@ sub read_DWARF_Info($) if($Sect!~/\.z?debug_info/) { # No DWARF info + if(my $DebugFile = getDebugFile($Path, "gnu_debuglink")) + { + my $DPath = $DebugFile; + + if(my $DDir = getDirname($Path)) + { + $DPath = $DDir."/".$DPath; + } + + printMsg("INFO", "Reading $DPath (gnu_debuglink)"); + + return read_DWARF_Info($DPath); + } return 0; } @@ -1317,6 +1373,10 @@ sub read_DWARF_Dump($$) { # 4.6.1 20110627 (Mandriva) $SYS_GCCV = $1.$2; } + + if($Val=~/(\A| )(\-O[0-3])( |\Z)/) { + printMsg("WARNING", "incompatible build option detected: $2"); + } } else { $SYS_COMP = $Val; @@ -2190,6 +2250,12 @@ sub complete_ABI() foreach my $ID (sort {int($a) <=> int($b)} keys(%SymbolInfo)) { + my $Symbol = $SymbolInfo{$ID}{"MnglName"}; + + if(not $Symbol) { + $Symbol = $SymbolInfo{$ID}{"ShortName"}; + } + if($LIB_LANG eq "C++") { if(not $SymbolInfo{$ID}{"MnglName"}) @@ -2259,6 +2325,26 @@ sub complete_ABI() delete($SymbolInfo{$ID}); next; } + elsif(defined $PublicHeadersPath) + { + if(not defined $SymbolInfo{$ID}{"Header"} + or not defined $PublicHeader{getFilename($SymbolInfo{$ID}{"Header"})}) + { + if($OBJ_LANG eq "C") + { + if(not defined $SymbolToHeader{$Symbol}) + { + delete($SymbolInfo{$ID}); + next; + } + } + else + { + delete($SymbolInfo{$ID}); + next; + } + } + } $SelectedSymbols{$ID} = $S; @@ -4628,6 +4714,101 @@ sub dump_sorting($) } } +sub getDebugFile($$) +{ + my ($Obj, $Header) = @_; + + my $Str = `$EU_READELF_L --strings=.$Header \"$Obj\" 2>\"$TMP_DIR/error\"`; + if($Str=~/0\]\s*(.+)/) { + return $1; + } + + return undef; +} + +sub findFiles(@) +{ + my ($Path, $Type) = @_; + my $Cmd = "find \"$Path\""; + + if($Type) { + $Cmd .= " -type ".$Type; + } + + my @Res = split(/\n/, `$Cmd`); + return @Res; +} + +sub isHeader($) +{ + my $Path = $_[0]; + return ($Path=~/\.(h|hh|hp|hxx|hpp|h\+\+|tcc)\Z/i); +} + +sub detectPublicSymbols($) +{ + my $Path = $_[0]; + + if(not -e $Path) { + exitStatus("Access_Error", "can't access \'$Path\'"); + } + + printMsg("INFO", "Detect public symbols"); + + if(not check_Cmd($CTAGS)) + { + printMsg("ERROR", "can't find \"$CTAGS\""); + return; + } + + my @Files = (); + my @Headers = (); + + if(-f $Path) + { # list of headers + @Headers = split(/\n/, readFile($Path)); + } + elsif(-d $Path) + { # directory + @Files = findFiles($Path, "f"); + + foreach my $File (@Files) + { + if(isHeader($File)) { + push(@Headers, $File); + } + } + } + + foreach my $File (@Headers) + { + $PublicHeader{getFilename($File)} = 1; + } + + if(defined $OBJ_LANG and $OBJ_LANG eq "C") + { + foreach my $File (@Headers) + { + my $HName = getFilename($File); + my $IgnoreTags = ""; + + if(defined $IgnoreTagsPath) { + $IgnoreTags = "-I \@".$IgnoreTagsPath; + } + + my $List_S = `$CTAGS -x --c-kinds=pfxv $IgnoreTags \"$File\"`; + foreach my $Line (split(/\n/, $List_S)) + { + if($Line=~/\A(\w+)/) { + $SymbolToHeader{$1} = $HName; + } + } + } + } + + $PublicSymbols_Detected = 1; +} + sub scenario() { if($Help) @@ -4637,7 +4818,11 @@ sub scenario() } if($ShowVersion) { - printMsg("INFO", "ABI Dumper $TOOL_VERSION\nCopyright (C) 2015 Andrey Ponomarenko's ABI Laboratory\nLicense: LGPL or GPL <http://www.gnu.org/licenses/>\nThis program is free software: you can redistribute it and/or modify it.\n\nWritten by Andrey Ponomarenko."); + printMsg("INFO", "ABI Dumper $TOOL_VERSION"); + printMsg("INFO", "Copyright (C) 2015 Andrey Ponomarenko's ABI Laboratory"); + printMsg("INFO", "License: LGPL or GPL <http://www.gnu.org/licenses/>"); + printMsg("INFO", "This program is free software: you can redistribute it and/or modify it.\n"); + printMsg("INFO", "Written by Andrey Ponomarenko."); exit(0); } if($DumpVersion) @@ -4773,15 +4958,13 @@ sub scenario() { if($Sect=~/\.gnu_debugaltlink/) { - my $Str = `$EU_READELF_L --strings=.gnu_debugaltlink \"$Obj\" 2>\"$TMP_DIR/error\"`; - - if($Str=~/0\]\s*(.+)/) + if(my $AltDebugFile = getDebugFile($Obj, "gnu_debugaltlink")) { - my $AltObj_R = getDirname($Obj)."/".$1; + my $AltObj_R = getDirname($Obj)."/".$AltDebugFile; my $AltObj = $AltObj_R; - while($AltObj=~s/\/[^\/]+\/\.\.\//\//){}; + while($AltObj=~s&/[^/]+/\.\./&/&){}; if(-e $AltObj) { @@ -4799,25 +4982,6 @@ sub scenario() } } - if(defined $HeaderSymbolsPath) - { - if(not -f $HeaderSymbolsPath) - { - exitStatus("Access_Error", "can't access \'$HeaderSymbolsPath\'"); - } - - if(my $HeaderSymbols = eval(readFile($HeaderSymbolsPath))) - { - foreach my $P (sort keys(%{$HeaderSymbols})) - { - foreach my $S (sort keys(%{$HeaderSymbols->{$P}})) - { - $SymbolToHeader{$S} = getFilename($P); - } - } - } - } - if($AltDebugInfo) { read_Alt_Info($AltDebugInfo); } @@ -4842,6 +5006,14 @@ sub scenario() } read_Symbols($Obj); + + if(not defined $PublicSymbols_Detected) + { + if(defined $PublicHeadersPath) { + detectPublicSymbols($PublicHeadersPath); + } + } + $Res += read_DWARF_Info($Obj); %DWARF_Info = (); @@ -4876,6 +5048,16 @@ sub scenario() %TName_Tids = (); %SymbolTable = (); + if(defined $PublicHeadersPath) + { + foreach my $H (keys(%HeadersInfo)) + { + if(not defined $PublicHeader{getFilename($H)}) { + delete($HeadersInfo{$H}); + } + } + } + dump_ABI(); exit(0); |