Fixed missed IDs in the ABI dump (Fedora)
diff --git a/INSTALL b/INSTALL
index b8195d0..351f6f2 100644
--- a/INSTALL
+++ b/INSTALL
@@ -6,8 +6,8 @@
 RELEASE INFORMATION
 
 Project:           ABI Dumper
-Version:           0.99.3
-Date:              2013-08-05
+Version:           0.99.4
+Date:              2013-08-06
 
 
 This file explains how to install and setup environment
diff --git a/README b/README
index e0c564d..8be2ee2 100644
--- a/README
+++ b/README
@@ -29,7 +29,7 @@
   abi-compliance-checker -l libTest -old ABIv0.dump -new ABIv1.dump
   
 COMPATIBILITY:
-  ABI Compliance Checker >= 1.99.7 (https://github.com/lvc/abi-compliance-checker)
+  ABI Compliance Checker >= 1.99.8 (https://github.com/lvc/abi-compliance-checker)
 
 ADV. USAGE:
   For advanced usage, see output of --help option.
\ No newline at end of file
diff --git a/abi-dumper.pl b/abi-dumper.pl
index a43d613..8998348 100755
--- a/abi-dumper.pl
+++ b/abi-dumper.pl
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 ###########################################################################
-# ABI Dumper 0.99.3
+# ABI Dumper 0.99.4
 # Dump ABI of an ELF object containing DWARF debug info
 #
 # Copyright (C) 2013 ROSA Laboratory
@@ -43,7 +43,7 @@
 use Storable qw(dclone);
 use Data::Dumper;
 
-my $TOOL_VERSION = "0.99.3";
+my $TOOL_VERSION = "0.99.4";
 my $ABI_DUMP_VERSION = "3.2";
 my $ORIG_DIR = cwd();
 my $TMP_DIR = tempdir(CLEANUP=>1);
@@ -204,6 +204,7 @@
 
 # Alternate
 my %ImportedUnit;
+my %ImportedDecl;
 
 # Output
 my %SymbolInfo;
@@ -224,6 +225,7 @@
 my %LocalType;
 
 my %SourceFile;
+my %SourceFile_Alt;
 my %DebugLoc;
 my %TName_Tid;
 my %TName_Tids;
@@ -272,6 +274,7 @@
 
 # ELF
 my %Library_Symbol;
+my %Library_LocalSymbol;
 my %Library_UndefSymbol;
 my %Library_Needed;
 my %SymbolTable;
@@ -531,7 +534,12 @@
                     next;
                 }
                 
-                $Library_Symbol{$TargetName}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
+                if($Bind eq "LOCAL") {
+                    $Library_LocalSymbol{$TargetName}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
+                }
+                else {
+                    $Library_Symbol{$TargetName}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
+                }
                 
                 $Symbol_Value{$Symbol} = $Value;
                 $Value_Symbol{$Value}{$Symbol} = 1;
@@ -617,6 +625,40 @@
     
     my $ExtraPath = undef;
     
+    # lines info
+    
+    if($ExtraInfo)
+    {
+        $ExtraPath = $ExtraInfo."/".$Name;
+        mkpath($ExtraPath);
+        $ExtraPath .= "/debug_line";
+    }
+    
+    if($ExtraPath)
+    {
+        system("$Readelf -N --debug-dump=line \"$Path\" 2>\"$TMP_DIR/error\" >\"$ExtraPath\"");
+        open(SRC, $ExtraPath);
+    }
+    else {
+        open(SRC, "$Readelf -N --debug-dump=line \"$Path\" 2>\"$TMP_DIR/error\" |");
+    }
+    
+    my $Offset = undef;
+    
+    while(<SRC>)
+    {
+        if( /(\d+)\s+\d+\s+\d+\s+\d+\s+([^ ]+)/)
+        {
+            my ($Num, $File) = ($1, $2);
+            chomp($File);
+            
+            $SourceFile_Alt{0}{$Num} = $File;
+        }
+    }
+    close(SRC);
+    
+    # debug info
+    
     if($ExtraInfo)
     {
         $ExtraPath = $ExtraInfo."/".$Name;
@@ -639,17 +681,23 @@
     while(<INFO>)
     {
         
-        if(/\[\s*(\w+?)\]  (\w+)/)
+        if(/\A \[\s*(\w+?)\](\s+)(\w+)/)
         {
-            if($2 eq "partial_unit")
+            if($3 eq "partial_unit")
             {
                 $ID = $1;
                 $Num = 0;
                 $ImportedUnit{$ID}{0} = $_;
             }
-            else {
+            elsif(length($2)==2)
+            {
                 $ID = undef;
             }
+            elsif(defined $ID)
+            {
+                $ImportedDecl{$1} = $ID;
+                $ImportedUnit{$ID}{$Num++} = $_;
+            }
         }
         elsif(defined $ID)
         {
@@ -761,13 +809,6 @@
             chomp($File);
             
             $SourceFile{$Offset}{$Num} = $File;
-            
-            if($File=~/\.($HEADER_EXT)\Z/) {
-                $HeadersInfo{$File} = 1;
-            }
-            elsif($File ne "<built-in>") {
-                $SourcesInfo{$File} = 1;
-            }
         }
     }
     close(SRC);
@@ -805,6 +846,8 @@
         $ExtraPath .= "/debug_info";
     }
     
+    my $INFO_fh;
+    
     if($Dir)
     { # to find ".dwz" directory (Fedora)
         chdir($Dir);
@@ -812,13 +855,31 @@
     if($ExtraPath)
     {
         system("$Readelf $AddOpt --debug-dump=info \"$Name\" 2>\"$TMP_DIR/error\" >\"$ExtraPath\"");
-        open(INFO, $ExtraPath);
+        open($INFO_fh, $ExtraPath);
     }
     else {
-        open(INFO, "$Readelf $AddOpt --debug-dump=info \"$Name\" 2>\"$TMP_DIR/error\" |");
+        open($INFO_fh, "$Readelf $AddOpt --debug-dump=info \"$Name\" 2>\"$TMP_DIR/error\" |");
     }
     chdir($ORIG_DIR);
     
+    read_DWARF_Dump($INFO_fh, 1);
+    
+    close($INFO_fh);
+    
+    if(my $Err = readFile("$TMP_DIR/error"))
+    { # eu-readelf: cannot get next DIE: invalid DWARF
+        if($Err=~/invalid DWARF/i) {
+            exitStatus("Invalid_DWARF", "invalid DWARF info");
+        }
+    }
+    
+    return 1;
+}
+
+sub read_DWARF_Dump($$)
+{
+    my ($FH, $Primary) = @_;
+    
     my %TypeUnit = ();
     my %Post_Change = ();
     my $TypeUnit_Sign = undef;
@@ -853,7 +914,10 @@
     my $Import = undef;
     my $Import_Num = 0;
     
-    while(($Import and $Line = $ImportedUnit{$Import}{$Import_Num}) or $Line = <INFO>)
+    my %UsedUnit;
+    my %UsedDecl;
+    
+    while(($Import and $Line = $ImportedUnit{$Import}{$Import_Num}) or $Line = <$FH>)
     {
         if(not defined $ImportedUnit{$Import}{$Import_Num})
         {
@@ -879,6 +943,7 @@
                         {
                             $Import = $1;
                             $Import_Num = 0;
+                            $UsedUnit{$Import} = 1;
                         }
                     }
                 }
@@ -910,6 +975,7 @@
                 if($1 eq "GNU_ref_alt")
                 {
                     $Val = -$Val;
+                    $UsedDecl{$2} = 1;
                 }
             }
             elsif($Attr eq "name")
@@ -925,7 +991,7 @@
             {
                 if($Val=~/\)\s*\Z/)
                 { # value on the next line
-                    $Val .= <INFO>;
+                    $Val .= <$FH>;
                 }
                 
                 if($Val=~/\A\(\w+\)\s*(-?)(\w+)\Z/)
@@ -989,7 +1055,7 @@
                 $DWARF_Info{$ID}{"rID"} = $ID-$ID_Shift;
             }
             
-            if($Import)
+            if($Import or not $Primary)
             {
                 if(defined $Shift{$Attr})
                 {
@@ -1017,7 +1083,7 @@
                 }
             }
             
-            if($Kind eq "partial_unit")
+            if($Kind eq "partial_unit" and not $Import)
             { # support for dwz
                 if($Attr eq "stmt_list") {
                     $CUnit = $Val;
@@ -1030,7 +1096,7 @@
             $NS = $2;
             $Kind = $3;
             
-            if($Import)
+            if($Import or not $Primary)
             {
                 $ID = -$ID;
             }
@@ -1086,14 +1152,6 @@
             $SYS_WORD = $1;
         }
     }
-    close(INFO);
-    
-    if(my $Err = readFile("$TMP_DIR/error"))
-    { # eu-readelf: cannot get next DIE: invalid DWARF
-        if($Err=~/invalid DWARF/i) {
-            exitStatus("Invalid_DWARF", "invalid DWARF info");
-        }
-    }
     
     foreach my $ID (keys(%Post_Change))
     {
@@ -1114,38 +1172,83 @@
     %TypeUnit = ();
     %Post_Change = ();
     
-    if(defined $CUnit_F)
+    if($Primary)
     {
-        if(my $Compiler= $DWARF_Info{$CUnit_F}{"producer"})
+        if(defined $CUnit_F)
         {
-            $Compiler=~s/\A\"//;
-            $Compiler=~s/\"\Z//;
-            
-            if($Compiler=~/GNU\s+(C|C\+\+)\s+(.+)\Z/)
+            if(my $Compiler= $DWARF_Info{$CUnit_F}{"producer"})
             {
-                $SYS_GCCV = $2;
-                $SYS_GCCV=~s/\d+\s+\(.+\).*//; # 4.6.1 20110627 (Mandriva)
+                $Compiler=~s/\A\"//;
+                $Compiler=~s/\"\Z//;
+                
+                if($Compiler=~/GNU\s+(C|C\+\+)\s+(.+)\Z/)
+                {
+                    $SYS_GCCV = $2;
+                    $SYS_GCCV=~s/\d+\s+\(.+\).*//; # 4.6.1 20110627 (Mandriva)
+                }
+                else {
+                    $SYS_COMP = $Compiler;
+                }
             }
-            else {
-                $SYS_COMP = $Compiler;
+            if(my $Lang = $DWARF_Info{$CUnit_F}{"language"})
+            {
+                $Lang=~s/\s*\(.+?\)\Z//;
+                if($Lang=~/C\d/i) {
+                    $LIB_LANG = "C";
+                }
+                elsif($Lang=~/C\+\+/i) {
+                    $LIB_LANG = "C++";
+                }
+                else {
+                    $LIB_LANG = $Lang;
+                }
             }
         }
-        if(my $Lang = $DWARF_Info{$CUnit_F}{"language"})
+        
+        my %AddUnits = ();
+        
+        foreach my $ID (keys(%UsedDecl))
         {
-            $Lang=~s/\s*\(.+?\)\Z//;
-            if($Lang=~/C\d/i) {
-                $LIB_LANG = "C";
-            }
-            elsif($Lang=~/C\+\+/i) {
-                $LIB_LANG = "C++";
-            }
-            else {
-                $LIB_LANG = $Lang;
+            if(my $U_ID = $ImportedDecl{$ID})
+            {
+                if(not $UsedUnit{$U_ID})
+                {
+                    $AddUnits{$U_ID} = 1;
+                }
             }
         }
+        
+        if(keys(%AddUnits))
+        {
+            my $ADD_DUMP = "";
+            
+            foreach my $U_ID (sort {hex($a)<=>hex($b)} keys(%AddUnits))
+            {
+                foreach my $N (sort {int($a)<=>int($b)} keys(%{$ImportedUnit{$U_ID}}))
+                {
+                    $ADD_DUMP .= $ImportedUnit{$U_ID}{$N};
+                }
+            }
+            
+            my $AddUnit_F = $TMP_DIR."/add_unit.dump";
+            
+            writeFile($AddUnit_F, $ADD_DUMP);
+            
+            my $FH_add;
+            open($FH_add, $AddUnit_F);
+            read_DWARF_Dump($FH_add, 0);
+            close($FH_add);
+            
+            unlink($AddUnit_F);
+        }
+        
     }
     
-    return 1;
+    # clean memory
+    %ImportedUnit = ();
+    %ImportedDecl = ();
+    %UsedUnit = ();
+    %UsedDecl = ();
 }
 
 sub read_Vtables($)
@@ -1213,6 +1316,7 @@
         "TypeInfo" => \%TypeInfo,
         "SymbolInfo" => \%SymbolInfo,
         "Symbols" => \%Library_Symbol,
+        "LocalSymbols" => \%Library_LocalSymbol,
         "UndefinedSymbols" => \%Library_UndefSymbol,
         "Needed" => \%Library_Needed,
         "SymbolVersion" => \%SymVer,
@@ -1562,6 +1666,11 @@
     
     foreach my $ID (sort {int($a) <=> int($b)} keys(%DWARF_Info))
     {
+        if($ID<0)
+        { # imported
+            next;
+        }
+        
         if($DWARF_Info{$ID}{"Kind"} eq "subprogram"
         or $DWARF_Info{$ID}{"Kind"} eq "variable")
         {
@@ -1759,7 +1868,8 @@
             { # defined in source files
                 return 0;
             }
-            else {
+            else
+            {
                 return 2;
             }
         }
@@ -2352,7 +2462,7 @@
     
     if(not $TInfo{"Name"})
     {
-        if($TInfo{"Type"}=~/\A(Struct|Enum|Union)\Z/)
+        if($TInfo{"Type"}=~/\A(Class|Struct|Enum|Union)\Z/)
         {
             if($TInfo{"Header"}) {
                 $TInfo{"Name"} = "anon-".lc($TInfo{"Type"})."-".$TInfo{"Header"}."-".$TInfo{"Line"};
@@ -2411,16 +2521,26 @@
     
     if(defined $File)
     {
-        if($SourceFile{$Unit}{$File}=~/\.($HEADER_EXT)\Z/)
+        my $Name = undef;
+        
+        if($ID>=0) {
+            $Name = $SourceFile{$Unit}{$File};
+        }
+        else
+        { # imported
+            $Name = $SourceFile_Alt{0}{$File};
+        }
+        
+        if($Name=~/\.($HEADER_EXT)\Z/)
         {
-            $R->{"Header"} = $SourceFile{$Unit}{$File};
+            $R->{"Header"} = $Name;
             if(defined $Line) {
                 $R->{"Line"} = $Line;
             }
         }
-        elsif($SourceFile{$Unit}{$File} ne "<built-in>")
+        elsif($Name ne "<built-in>")
         {
-            $R->{"Source"} = $SourceFile{$Unit}{$File};
+            $R->{"Source"} = $Name;
             if(defined $Line) {
                 $R->{"SourceLine"} = $Line;
             }
@@ -3826,7 +3946,9 @@
                     
                     if($Str=~/0\]\s*(.+)/)
                     {
-                        my $AltObj = get_dirname($Obj)."/".$1;
+                        my $AltObj_R = get_dirname($Obj)."/".$1;
+                        
+                        my $AltObj = $AltObj_R;
                         
                         while($AltObj=~s/\/[^\/]+\/..\//\//g){};
                         
@@ -3837,7 +3959,7 @@
                         }
                         else
                         {
-                            printMsg("WARNING", "can't access \'$AltObj\'");
+                            printMsg("WARNING", "can't access \'$AltObj_R\'");
                         }
                     }
                 }
@@ -3879,10 +4001,28 @@
     init_Registers();
     read_ABI();
     
+    # clean memory
     %DWARF_Info = ();
     
     remove_Unused();
     
+    # clean memory
+    %SourceFile = ();
+    %SourceFile_Alt = ();
+    %DebugLoc = ();
+    %TName_Tid = ();
+    %TName_Tids = ();
+    
+    %TypeMember = ();
+    %ArrayCount = ();
+    %FuncParam = ();
+    %Inheritance = ();
+    %NameSpace = ();
+    %SpecElem = ();
+    %ClassMethods = ();
+    %TypeSpec = ();
+    %ClassChild = ();
+    
     dump_ABI();
     
     exit(0);