in src/main/abi-symbols/abi-dumper.pl [3709:4255]
sub getTypeInfo($)
{
my $ID = $_[0];
if(not defined $DWARF_Info{$ID}) {
return;
}
if(not keys(%{$DWARF_Info{$ID}}))
{
delete($DWARF_Info{$ID});
return;
}
my $Kind = $DWARF_Info{$ID}{"kind"};
if(defined $Cache{"getTypeInfo"}{$ID}) {
return;
}
if(my $N = $NameSpace{$ID})
{
if($DWARF_Info{$N}{"kind"} eq "prog")
{ # local code
# template instances are declared in the subprogram (constructor)
my $Tmpl = 0;
if(my $ObjP = $DWARF_Info{$N}{"objptr"})
{
while($DWARF_Info{$ObjP}{"type"}) {
$ObjP = $DWARF_Info{$ObjP}{"type"};
}
my $CName = $DWARF_Info{$ObjP}{"name"};
$CName=~s/<.*//g;
if($CName eq $DWARF_Info{$N}{"name"}) {
$Tmpl = 1;
}
}
if(not $Tmpl)
{ # local types
$LocalType{$ID} = 1;
}
}
elsif($DWARF_Info{$N}{"kind"} eq "lexical_block")
{ # local code
return;
}
}
$Cache{"getTypeInfo"}{$ID} = 1;
my %TInfo = ();
$TInfo{"Type"} = $TypeType{$Kind};
if(not $TInfo{"Type"})
{
if($DWARF_Info{$ID}{"kind"} eq "subroutine_type") {
$TInfo{"Type"} = "Func";
}
}
if($DWARF_Info{$ID}{"name"} eq "__unknown__")
{ # size of such type may vary
delete($DWARF_Info{$ID}{"size"});
}
if(defined $SYS_CLANGV
and $TInfo{"Type"} eq "FieldPtr")
{ # support for Clang
if(my $T = $DWARF_Info{$ID}{"type"})
{
if($DWARF_Info{$T}{"kind"} eq "subroutine_type")
{
$TInfo{"Type"} = "MethodPtr";
$DWARF_Info{$ID}{"pfn"} = $T;
$DWARF_Info{$T}{"objptr"} = $DWARF_Info{$ID}{"container"};
}
}
}
my $RealType = $TInfo{"Type"};
if(defined $ClassMethods{$ID})
{
if($TInfo{"Type"} eq "Struct") {
$RealType = "Class";
}
}
if($TInfo{"Type"} ne "Enum"
and my $BaseType = $DWARF_Info{$ID}{"type"})
{
$TInfo{"BaseType"} = "$BaseType";
if(defined $TypeType{$DWARF_Info{$BaseType}{"kind"}})
{
getTypeInfo($TInfo{"BaseType"});
if(not defined $TypeInfo{$TInfo{"BaseType"}}
or not $TypeInfo{$TInfo{"BaseType"}}{"Name"})
{ # local code
delete($TypeInfo{$ID});
return;
}
}
}
if($RealType eq "Class") {
$TInfo{"Copied"} = 1; # will be changed in getSymbolInfo()
}
if(defined $TypeMember{$ID})
{
my $Unnamed = 0;
foreach my $Pos (sort {$a<=>$b} keys(%{$TypeMember{$ID}}))
{
my $MemId = $TypeMember{$ID}{$Pos};
my $MInfo = $DWARF_Info{$MemId};
if(my $Name = $MInfo->{"name"})
{
if(index($Name, "_vptr.")==0)
{ # v-table pointer
$Name="_vptr";
}
$TInfo{"Memb"}{$Pos}{"name"} = $Name;
}
else
{
$TInfo{"Memb"}{$Pos}{"name"} = "unnamed".$Unnamed;
$Unnamed += 1;
}
if($TInfo{"Type"} eq "Enum") {
$TInfo{"Memb"}{$Pos}{"value"} = $MInfo->{"cval"};
}
else
{
$TInfo{"Memb"}{$Pos}{"type"} = $MInfo->{"type"};
if(my $Access = $MInfo->{"access"})
{
if($Access ne "public")
{ # NOTE: default access of members in the ABI dump is "public"
$TInfo{"Memb"}{$Pos}{"access"} = $Access;
}
}
else
{
if($DWARF_Info{$ID}{"kind"} eq "class_type")
{ # NOTE: default access of class members in the debug info is "private"
$TInfo{"Memb"}{$Pos}{"access"} = "private";
}
else
{
# NOTE: default access of struct members in the debug info is "public"
}
}
if($TInfo{"Type"} eq "Union") {
$TInfo{"Memb"}{$Pos}{"offset"} = "0";
}
elsif(defined $MInfo->{"mloc"}) {
$TInfo{"Memb"}{$Pos}{"offset"} = $MInfo->{"mloc"};
}
}
if((my $BitSize = $MInfo->{"bit_size"}) ne "") {
$TInfo{"Memb"}{$Pos}{"bitfield"} = $BitSize;
}
}
}
my $NS = $NameSpace{$ID};
if(not $NS)
{
if(my $Sp = $DWARF_Info{$ID}{"spec"}) {
$NS = $NameSpace{$Sp};
}
}
if($NS and $DWARF_Info{$NS}{"kind"}=~/\A(class_type|structure_type)\Z/)
{ # member class
if(my $Access = $DWARF_Info{$ID}{"access"})
{
if($Access ne "public")
{ # NOTE: default access of member classes in the ABI dump is "public"
$TInfo{ucfirst($Access)} = 1;
}
}
else
{
if($DWARF_Info{$NS}{"kind"} eq "class_type")
{
# NOTE: default access of member classes in the debug info is "private"
$TInfo{"Private"} = 1;
}
else
{
# NOTE: default access to struct member classes in the debug info is "public"
}
}
}
else
{
if(my $Access = $DWARF_Info{$ID}{"access"})
{
if($Access ne "public")
{ # NOTE: default access of classes in the ABI dump is "public"
$TInfo{ucfirst($Access)} = 1;
}
}
}
my $Size = $DWARF_Info{$ID}{"size"};
if($Size ne "") {
$TInfo{"Size"} = $Size;
}
setSource(\%TInfo, $ID);
if(not $DWARF_Info{$ID}{"name"}
and my $Spec = $DWARF_Info{$ID}{"spec"}) {
$DWARF_Info{$ID}{"name"} = $DWARF_Info{$Spec}{"name"};
}
if($NS)
{
if($DWARF_Info{$NS}{"kind"} eq "namespace")
{
if(my $NS_F = completeNS($ID))
{
$TInfo{"NameSpace"} = $NS_F;
}
}
elsif($DWARF_Info{$NS}{"kind"} eq "class_type"
or $DWARF_Info{$NS}{"kind"} eq "structure_type")
{ # class
getTypeInfo($NS);
if(my $Sp = $SpecElem{$NS}) {
getTypeInfo($Sp);
}
if($TypeInfo{$NS}{"Name"})
{
$TInfo{"NameSpace"} = $TypeInfo{$NS}{"Name"};
$TInfo{"NameSpace"}=~s/\Astruct //;
}
}
}
if(my $Name = $DWARF_Info{$ID}{"name"})
{
$TInfo{"Name"} = $Name;
if($TInfo{"NameSpace"}) {
$TInfo{"Name"} = $TInfo{"NameSpace"}."::".$TInfo{"Name"};
}
if($TInfo{"Type"}=~/\A(Struct|Enum|Union)\Z/) {
$TInfo{"Name"} = lc($TInfo{"Type"})." ".$TInfo{"Name"};
}
}
if($TInfo{"Type"} eq "Struct")
{
if(not $TInfo{"Name"})
{
if(defined $TInfo{"Memb"}
and $TInfo{"Memb"}{0}{"name"} eq "__pfn")
{ # __pfn and __delta
my $Pfn = $TInfo{"Memb"}{0}{"type"};
if(my $Pfn_B = $DWARF_Info{$Pfn}{"type"})
{
if($DWARF_Info{$Pfn_B}{"kind"} eq "subroutine_type")
{
$TInfo{"Type"} = "MethodPtr";
}
}
}
}
}
if($TInfo{"Type"}=~/Pointer|Ptr|Ref/)
{
if(not $TInfo{"Size"}) {
$TInfo{"Size"} = $SYS_WORD;
}
}
if($TInfo{"Type"} eq "Pointer")
{
if($DWARF_Info{$TInfo{"BaseType"}}{"kind"} eq "subroutine_type")
{
initFuncType(\%TInfo, $TInfo{"BaseType"}, "FuncPtr");
}
}
elsif($TInfo{"Type"}=~/Typedef|Const|Volatile/)
{
if($DWARF_Info{$TInfo{"BaseType"}}{"kind"} eq "subroutine_type")
{
getTypeInfo($TInfo{"BaseType"});
}
}
elsif($TInfo{"Type"} eq "Func")
{
initFuncType(\%TInfo, $ID, "Func");
}
elsif($TInfo{"Type"} eq "MethodPtr")
{
my $Pfn_B = undef;
if(defined $TInfo{"Memb"}
and $TInfo{"Memb"}{0}{"name"} eq "__pfn")
{
if(my $Pfn = $TInfo{"Memb"}{0}{"type"}) {
$Pfn_B = $DWARF_Info{$Pfn}{"type"};
}
}
else
{ # support for Clang
$Pfn_B = $DWARF_Info{$ID}{"pfn"};
}
if($Pfn_B)
{
my @Prms = ();
my $PPos = 0;
foreach my $Pos (sort {$a<=>$b} keys(%{$FuncParam{$Pfn_B}}))
{
my $ParamId = $FuncParam{$Pfn_B}{$Pos};
my %PInfo = %{$DWARF_Info{$ParamId}};
if(defined $PInfo{"art"})
{ # this
next;
}
if(my $PTypeId = $PInfo{"type"})
{
$TInfo{"Param"}{$PPos}{"type"} = $PTypeId;
getTypeInfo($PTypeId);
push(@Prms, $TypeInfo{$PTypeId}{"Name"});
}
$PPos += 1;
}
if(my $ClassId = $DWARF_Info{$Pfn_B}{"objptr"})
{
while($DWARF_Info{$ClassId}{"type"}) {
$ClassId = $DWARF_Info{$ClassId}{"type"};
}
$TInfo{"Class"} = $ClassId;
getTypeInfo($TInfo{"Class"});
}
if($TInfo{"Return"} = $DWARF_Info{$Pfn_B}{"type"}) {
getTypeInfo($TInfo{"Return"});
}
else
{ # void
$TInfo{"Return"} = "1";
}
$TInfo{"Name"} = createMethodPtrName(\%TInfo);
delete($TInfo{"BaseType"});
}
}
elsif($TInfo{"Type"} eq "FieldPtr")
{
$TInfo{"Return"} = $TInfo{"BaseType"};
delete($TInfo{"BaseType"});
if(my $Class = $DWARF_Info{$ID}{"container"})
{
$TInfo{"Class"} = $Class;
getTypeInfo($TInfo{"Class"});
$TInfo{"Name"} = createFieldPtrName(\%TInfo);
}
$TInfo{"Size"} = $SYS_WORD;
}
elsif($TInfo{"Type"} eq "String")
{
$TInfo{"Type"} = "Pointer";
$TInfo{"Name"} = "char*";
$TInfo{"BaseType"} = $TName_Tid{"Intrinsic"}{"char"};
}
if(defined $Inheritance{$ID})
{
foreach my $Pos (sort {$a<=>$b} keys(%{$Inheritance{$ID}}))
{
if(my $BaseId = $Inheritance{$ID}{$Pos}{"id"})
{
if(my $E = $SpecElem{$BaseId}) {
$BaseId = $E;
}
$TInfo{"Base"}{$BaseId}{"pos"} = "$Pos";
if(my $Access = $Inheritance{$ID}{$Pos}{"access"}) {
$TInfo{"Base"}{$BaseId}{"access"} = $Access;
}
if($Inheritance{$ID}{$Pos}{"virtual"}) {
$TInfo{"Base"}{$BaseId}{"virtual"} = 1;
}
$ClassChild{$BaseId}{$ID} = 1;
}
}
}
if(not $TInfo{"BaseType"})
{
if($TInfo{"Type"} eq "Pointer")
{
$TInfo{"Name"} = "void*";
$TInfo{"BaseType"} = "1";
}
elsif($TInfo{"Type"} eq "Const")
{
$TInfo{"Name"} = "const void";
$TInfo{"BaseType"} = "1";
}
elsif($TInfo{"Type"} eq "Volatile")
{
$TInfo{"Name"} = "volatile void";
$TInfo{"BaseType"} = "1";
}
elsif($TInfo{"Type"} eq "Typedef")
{
$TInfo{"BaseType"} = "1";
}
}
if(not $TInfo{"Name"}
and $TInfo{"Type"} ne "Enum")
{
my $ID_ = $ID;
my $BaseID = undef;
my $Name = "";
while($BaseID = $DWARF_Info{$ID_}{"type"})
{
my $Kind = $DWARF_Info{$ID_}{"kind"};
if(my $Q = $Qual{$TypeType{$Kind}})
{
$Name = $Q.$Name;
if($Q=~/\A\w/) {
$Name = " ".$Name;
}
}
if(defined $TypeInfo{$BaseID}
and $TypeInfo{$BaseID}{"Name"})
{
$Name = $TypeInfo{$BaseID}{"Name"}.$Name;
last;
}
elsif(defined $DWARF_Info{$BaseID}
and $DWARF_Info{$BaseID}{"name"})
{
$Name = $DWARF_Info{$BaseID}{"name"}.$Name;
$ID_ = $BaseID;
}
elsif(defined $Compressed
and not defined $AllUnits)
{
$Name = "T#".$BaseID.$Name;
last;
}
else
{ # error
last;
}
}
if($Name) {
$TInfo{"Name"} = $Name;
}
if($TInfo{"Type"} eq "Array")
{
if(my $Count = $ArrayCount{$ID})
{
$TInfo{"Name"} .= "[".$Count."]";
if(my $BType = $TInfo{"BaseType"})
{
if(my $BSize = $TypeInfo{$BType}{"Size"})
{
if(my $Size = $Count*$BSize)
{
$TInfo{"Size"} = "$Size";
}
}
}
}
else
{
$TInfo{"Name"} .= "[]";
$TInfo{"Size"} = $SYS_WORD;
}
}
elsif($TInfo{"Type"} eq "Pointer")
{
if(my $BType = $TInfo{"BaseType"})
{
if($TypeInfo{$BType}{"Type"}=~/MethodPtr|FuncPtr/)
{ # void(GTestSuite::**)()
# int(**)(...)
if($TInfo{"Name"}=~s/\*\Z//) {
$TInfo{"Name"}=~s/\*(\))/\*\*$1/;
}
}
}
}
}
if(my $Bid = $TInfo{"BaseType"})
{
if(not $TInfo{"Size"}
and $TypeInfo{$Bid}{"Size"}) {
$TInfo{"Size"} = $TypeInfo{$Bid}{"Size"};
}
}
if($TInfo{"Name"}) {
$TInfo{"Name"} = formatName($TInfo{"Name"}, "T");
}
if($TInfo{"Name"}=~/>\Z/)
{
my ($Short, $TParams) = getTParams($ID, $TInfo{"Name"});
if($TParams)
{
delete($TInfo{"TParam"});
foreach my $Pos (0 .. $#{$TParams}) {
$TInfo{"TParam"}{$Pos} = $TParams->[$Pos];
}
my @TKeys = getTKeys($TParams);
@TKeys = shortTParams($Short, \@TKeys);
$TInfo{"Name"} = formatName($Short."<".join(", ", @TKeys).">", "T");
}
}