sub readSymbols()

in src/main/abi-symbols/abi-dumper.pl [655:914]


sub readSymbols($)
{
    my $Lib_Path = $_[0];
    my $Lib_Name = getFilename($Lib_Path);
    
    my $Dynamic = ($Lib_Name=~/\.so(\.|\Z)/);
    my $Dbg = ($Lib_Name=~/\.debug\Z/);
    
    if(not checkCmd($EU_READELF)) {
        exitStatus("Not_Found", "can't find \"eu-readelf\" from Elfutils");
    }
    
    my %SectionInfo;
    my %KSect;
    
    my $Cmd = $EU_READELF_L." -S \"$Lib_Path\" 2>\"$TMP_DIR/error\"";
    foreach (split(/\n/, `$Cmd`))
    {
        if(/\[\s*(\d+)\]\s+([\w\.]+)/)
        {
            my ($Num, $Name) = ($1, $2);
            
            $SectionInfo{$Num} = $Name;
            
            if(defined $KernelExport)
            {
                if($Name=~/\A(__ksymtab|__ksymtab_gpl)\Z/) {
                    $KSect{$1} = 1;
                }
            }
        }
    }
    
    if(defined $KernelExport)
    {
        if(not keys(%KSect))
        {
            printMsg("ERROR", "can't find __ksymtab or __ksymtab_gpl sections in the object");
            exit(1);
        }
        
        foreach my $Name (sort keys(%KSect))
        {
            $Cmd = $OBJDUMP." --section=$Name -d \"$Lib_Path\" 2>\"$TMP_DIR/error\"";
            
            foreach my $Line (split(/\n/, qx/$Cmd/))
            {
                if($Line=~/<__ksymtab_(.+?)>/)
                {
                    $KSymTab{$1} = 1;
                }
            }
        }
    }
    
    if($Dynamic)
    { # dynamic library specifics
        $Cmd = $EU_READELF_L." -d \"$Lib_Path\" 2>\"$TMP_DIR/error\"";
        foreach (split(/\n/, `$Cmd`))
        {
            if(/NEEDED.+\[([^\[\]]+)\]/)
            { # dependencies:
              # 0x00000001 (NEEDED) Shared library: [libc.so.6]
                $Library_Needed{$1} = 1;
            }
        }
    }
    
    my $ExtraPath = undef;
    
    if($ExtraInfo)
    {
        mkpath($ExtraInfo);
        $ExtraPath = $ExtraInfo."/elf-info";
    }
    
    $Cmd = $EU_READELF_L." -s \"$Lib_Path\" 2>\"$TMP_DIR/error\"";
    
    if($ExtraPath)
    { # debug mode
        # write to file
        system($Cmd." >\"$ExtraPath\"");
        open(LIB, $ExtraPath);
    }
    else
    { # write to pipe
        open(LIB, $Cmd." |");
    }
    
    my (%Symbol_Value, %Value_Symbol) = ();
    
    my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
    while(<LIB>)
    {
        if($Dynamic and not $Dbg)
        { # dynamic library specifics
            if(defined $symtab)
            {
                if(index($_, "'.dynsym'")!=-1)
                { # dynamic table
                    $symtab = undef;
                }
                if(not $AllSymbols)
                { # do nothing with symtab
                    # next;
                }
            }
            elsif(index($_, "'.symtab'")!=-1)
            { # symbol table
                $symtab = 1;
            }
        }
        if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
        { # read ELF entry
            $Symbol_Bind{$Symbol} = $Bind;
            if(index($Symbol, '@')!=-1)
            {
                if($Symbol=~/\A(.+?)\@/) {
                    $Symbol_Bind{$1} = $Bind;
                }
            }
            
            if(not $symtab)
            { # dynsym
                if(skipSymbol($Symbol)) {
                    next;
                }
                
                if($Ndx eq "UNDEF")
                { # ignore interfaces that are imported from somewhere else
                    $Library_UndefSymbol{$TargetName}{$Symbol} = 0;
                    next;
                }
                
                if(defined $KernelExport)
                {
                    if($Bind ne "LOCAL")
                    {
                        if(index($Symbol, "sys_")==0
                        or index($Symbol, "SyS_")==0) {
                            $KSymTab{$Symbol} = 1;
                        }
                    }
                    
                    if(not defined $KSymTab{$Symbol}) {
                        next;
                    }
                }
                
                if($Bind ne "LOCAL") {
                    $Library_Symbol{$TargetName}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
                }
                
                if(not defined $OBJ_LANG)
                {
                    if(index($Symbol, "_Z")==0)
                    {
                        $OBJ_LANG = "C++";
                    }
                }
            }
            
            if($Ndx ne "UNDEF" and $Value!~/\A0+\Z/)
            {
                $Symbol_Value{$Symbol} = $Value;
                $Value_Symbol{$Value}{$Symbol} = 1;

                if(defined $ExtraDump)
                {
                    $SymbolAttribute{$Symbol} = {
                        "Val" => $Value,
                        "Size" => $Size,
                        "Kind" => $Type,
                        "Bind" => $Bind,
                        "Vis" => $Vis,
                        "Ndx" => $Ndx
                    };
                }
            }
            
            if(not $symtab)
            {
                foreach ($SectionInfo{$Ndx}, "")
                {
                    my $Val = $Value;
                    
                    $SymbolTable{$_}{$Val}{$Symbol} = 1;
                    
                    if($Val=~s/\A[0]+//)
                    {
                        if($Val eq "") {
                            $Val = "0";
                        }
                        $SymbolTable{$_}{$Val}{$Symbol} = 1;
                    }
                }
            }
        }
    }
    close(LIB);
    
    if(not defined $Library_Symbol{$TargetName}) {
        return;
    }
    
    my %Found = ();
    foreach my $Symbol (sort keys(%Symbol_Value))
    {
        next if(index($Symbol, '@')==-1);
        if(my $Value = $Symbol_Value{$Symbol})
        {
            foreach my $Symbol_SameValue (sort keys(%{$Value_Symbol{$Value}}))
            {
                if($Symbol_SameValue ne $Symbol
                and index($Symbol_SameValue, '@')==-1)
                {
                    $SymVer{$Symbol_SameValue} = $Symbol;
                    $Found{$Symbol} = 1;
                    
                    if(index($Symbol, '@@')==-1) {
                        last;
                    }
                }
            }
        }
    }
    
    # default
    foreach my $Symbol (sort keys(%Symbol_Value))
    {
        next if(defined $Found{$Symbol});
        next if(index($Symbol, '@@')==-1);
        
        if($Symbol=~/\A([^\@]*)\@\@/
        and not $SymVer{$1})
        {
            $SymVer{$1} = $Symbol;
            $Found{$Symbol} = 1;
        }
    }
    
    # non-default
    foreach my $Symbol (sort keys(%Symbol_Value))
    {
        next if(defined $Found{$Symbol});
        next if(index($Symbol, '@')==-1);
        
        if($Symbol=~/\A([^\@]*)\@([^\@]*)/
        and not $SymVer{$1})
        {
            $SymVer{$1} = $Symbol;
            $Found{$Symbol} = 1;
        }
    }
    
    if(not defined $OBJ_LANG)
    {
        $OBJ_LANG = "C";
    }
}