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";
}
}