FPDebug: parser for pascal expressions / class members

git-svn-id: trunk@43224 -
This commit is contained in:
martin 2013-10-12 23:35:42 +00:00
parent 129d4f8771
commit e0939b1610
2 changed files with 273 additions and 46 deletions

View File

@ -261,11 +261,16 @@ type
function GetScopeIndex: Integer;
procedure SetAbbrev(AValue: TDwarfAbbrev);
procedure SetScopeIndex(AValue: Integer);
protected
function GoNamedChild(AName: String): Boolean;
public
constructor Create(ACompUnit: TDwarfCompilationUnit; AnInformationEntry: Pointer);
constructor Create(ACompUnit: TDwarfCompilationUnit; AScope: TDwarfScopeInfo);
property CompUnit: TDwarfCompilationUnit read FCompUnit;
function FindNamedChild(AName: String): TDwarfInformationEntry;
function FindChildByTag(ATag: Cardinal): TDwarfInformationEntry;
property Abbrev: TDwarfAbbrev read GetAbbrev write SetAbbrev;
property AbbrevData: PDwarfAbbrevEntry read FAbbrevData; // only valid if Abbrev is available
function HasAttrib(AnAttrib: Cardinal): boolean;
@ -541,6 +546,7 @@ type
end;
{ TDbgDwarfTypeIdentifier }
TDbgDwarfIdentifierStructure = class;
(* Types and allowed tags in dwarf 2
@ -588,13 +594,18 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
protected
function GetIsBaseType: Boolean; virtual;
function GetIsPointerType: Boolean; virtual;
function GetIsStructType: Boolean; virtual;
function GetPointedToType: TDbgDwarfTypeIdentifier; virtual;
function GetStructTypeInfo: TDbgDwarfIdentifierStructure; virtual;
public
class function CreateTybeSubClass(AName: String; AnInformationEntry: TDwarfInformationEntry): TDbgDwarfTypeIdentifier;
property TypeInfo;
property IsBaseType: Boolean read GetIsBaseType;
property IsPointerType: Boolean read GetIsPointerType;
property IsStructType: Boolean read GetIsStructType;
property PointedToType: TDbgDwarfTypeIdentifier read GetPointedToType;
property StructTypeInfo: TDbgDwarfIdentifierStructure read GetStructTypeInfo;
end;
{ TDbgDwarfBaseTypeIdentifier }
@ -611,6 +622,8 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
function GetIsBaseType: Boolean; override;
function GetIsPointerType: Boolean; override;
function GetPointedToType: TDbgDwarfTypeIdentifier; override;
function GetIsStructType: Boolean; override;
function GetStructTypeInfo: TDbgDwarfIdentifierStructure; override;
end;
{ TDbgDwarfTypeIdentifierDeclaration }
@ -625,6 +638,25 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
protected
function GetIsPointerType: Boolean; override;
function GetPointedToType: TDbgDwarfTypeIdentifier; override;
// fpc encodes classes as pointer, not ref (so Obj1 = obj2 compares the pointers)
function GetIsStructType: Boolean; override;
function GetStructTypeInfo: TDbgDwarfIdentifierStructure; override;
end;
TDbgDwarfIdentifierMember = class(TDbgDwarfValueIdentifier)
end;
{ TDbgDwarfIdentifierStructure }
TDbgDwarfIdentifierStructure = class(TDbgDwarfTypeIdentifier)
// record or class
private
function GetMemberByName(AName: String): TDbgDwarfIdentifierMember;
protected
function GetIsStructType: Boolean; override;
function GetStructTypeInfo: TDbgDwarfIdentifierStructure; override;
public
property MemberByName[AName: String]: TDbgDwarfIdentifierMember read GetMemberByName;
end;
{ TDbgDwarfProcSymbol }
@ -1157,6 +1189,53 @@ begin
end;
end;
{ TDbgDwarfIdentifierStructure }
function TDbgDwarfIdentifierStructure.GetMemberByName(AName: String): TDbgDwarfIdentifierMember;
var
Info, NewInfo, Ident: TDwarfInformationEntry;
FwdInfoPtr: Pointer;
FwdCompUint: TDwarfCompilationUnit;
r: TDbgDwarfIdentifier;
begin
Result := nil;
r := nil;
Info := FInformationEntry;
Info.AddReference;
while Info <> nil do begin
Ident := Info.FindNamedChild(AName);
if Ident <> nil then
r := TDbgDwarfTypeIdentifier.CreateSubClass('', Ident);
ReleaseRefAndNil(Ident);
if (R <> nil) and (r is TDbgDwarfIdentifierMember) then begin
ReleaseRefAndNil(Info);
Result := TDbgDwarfIdentifierMember(r);
break;
end;
NewInfo := Info.FindChildByTag(DW_TAG_inheritance);
ReleaseRefAndNil(Info);
if NewInfo <> nil then begin
if NewInfo.ReadReference(DW_AT_type, FwdInfoPtr, FwdCompUint) then begin
Info := TDwarfInformationEntry.Create(FwdCompUint, FwdInfoPtr);
Info.SearchScope;
DebugLn(['!!!! PARENT !!! ', dbgs(Info.FScope, FwdCompUint) ]);
end;
ReleaseRefAndNil(NewInfo);
end;
end;
end;
function TDbgDwarfIdentifierStructure.GetIsStructType: Boolean;
begin
Result := True;
end;
function TDbgDwarfIdentifierStructure.GetStructTypeInfo: TDbgDwarfIdentifierStructure;
begin
Result := Self;
end;
{ TDbgDwarfTypeIdentifierModifier }
function TDbgDwarfTypeIdentifierModifier.GetIsBaseType: Boolean;
@ -1186,6 +1265,25 @@ begin
Result := Result.PointedToType;
end;
function TDbgDwarfTypeIdentifierModifier.GetIsStructType: Boolean;
var
ti: TDbgDwarfTypeIdentifier;
begin
ti := TypeInfo;
if ti <> nil
then Result := ti.IsStructType
else Result := False;
end;
function TDbgDwarfTypeIdentifierModifier.GetStructTypeInfo: TDbgDwarfIdentifierStructure;
var
ti: TDbgDwarfTypeIdentifier;
begin
ti := TypeInfo;
if ti <> nil then
Result := ti.StructTypeInfo;
end;
{ TDbgDwarfTypeIdentifierPointer }
function TDbgDwarfTypeIdentifierPointer.GetIsPointerType: Boolean;
@ -1198,6 +1296,32 @@ begin
Result := TypeInfo;
end;
function TDbgDwarfTypeIdentifierPointer.GetIsStructType: Boolean;
var
ti: TDbgDwarfTypeIdentifier;
begin
Result := False;
ti := TypeInfo;
// fpc encodes classes as pointer, not ref (so Obj1 = obj2 compares the pointers)
if (ti <> nil) and (ti is TDbgDwarfIdentifierStructure) and
(ti.InformationEntry.Abbrev.tag = DW_TAG_class_type)
then
Result := True;
end;
function TDbgDwarfTypeIdentifierPointer.GetStructTypeInfo: TDbgDwarfIdentifierStructure;
var
ti: TDbgDwarfTypeIdentifier;
begin
Result := nil;
ti := TypeInfo;
// fpc encodes classes as pointer, not ref (so Obj1 = obj2 compares the pointers)
if (ti <> nil) and (ti is TDbgDwarfIdentifierStructure) and
(ti.InformationEntry.Abbrev.tag = DW_TAG_class_type)
then
Result := TDbgDwarfIdentifierStructure(ti);
end;
{ TDbgDwarfBaseTypeIdentifier }
function TDbgDwarfBaseIdentifierBase.GetIsBaseType: Boolean;
@ -1212,6 +1336,11 @@ begin
Result := nil;
end;
function TDbgDwarfTypeIdentifier.GetStructTypeInfo: TDbgDwarfIdentifierStructure;
begin
Result := nil;
end;
function TDbgDwarfTypeIdentifier.GetIsBaseType: Boolean;
begin
Result := False;
@ -1222,6 +1351,11 @@ begin
Result := False;
end;
function TDbgDwarfTypeIdentifier.GetIsStructType: Boolean;
begin
Result := False;
end;
class function TDbgDwarfTypeIdentifier.CreateTybeSubClass(AName: String;
AnInformationEntry: TDwarfInformationEntry): TDbgDwarfTypeIdentifier;
var
@ -1328,6 +1462,29 @@ begin
ScopeChanged;
end;
function TDwarfInformationEntry.GoNamedChild(AName: String): Boolean;
var
EntryName: String;
begin
Result := False;
GoChild;
while HasValidScope do begin
if not ReadValue(DW_AT_name, EntryName) then begin
GoNext;
Continue;
end;
if UpperCase(EntryName) = UpperCase(AName) then begin
// TODO: check DW_AT_start_scope;
DebugLn(['!!!! FOUND !!! ', dbgs(FScope, FCompUnit), DbgSName(Self)]);
Result := True;
exit;
end;
GoNext;
end;
end;
constructor TDwarfInformationEntry.Create(ACompUnit: TDwarfCompilationUnit;
AnInformationEntry: Pointer);
begin
@ -1346,6 +1503,47 @@ begin
ScopeChanged;
end;
function TDwarfInformationEntry.FindNamedChild(AName: String): TDwarfInformationEntry;
var
ScopeEntryName: String;
begin
Result := nil;
if (not FScope.IsValid) and (FInformationEntry <> nil) then
if not SearchScope then
exit;
Result := TDwarfInformationEntry.Create(FCompUnit, FScope);
// TODO: parent
if Result.GoNamedChild(AName) then
exit;
ReleaseRefAndNil(Result);
end;
function TDwarfInformationEntry.FindChildByTag(ATag: Cardinal): TDwarfInformationEntry;
var
Scope: TDwarfScopeInfo;
EntryName: String;
AbbrList: TDwarfAbbrevList;
Abbr: TDwarfAbbrev;
begin
Result := nil;
if (not FScope.IsValid) and (FInformationEntry <> nil) then
if not SearchScope then
exit;
Scope := FScope.Child;
while Scope.IsValid do begin
AbbrList := FCompUnit.FAbbrevList;
if AbbrList.FindLe128bFromPointer(Scope.Entry, Abbr) <> nil then begin
if Abbr.tag = ATag then begin
Result := TDwarfInformationEntry.Create(FCompUnit, Scope);
exit;
end;
end;
Scope.GoNext;
end;
end;
function TDwarfInformationEntry.HasAttrib(AnAttrib: Cardinal): boolean;
var
i: Integer;
@ -1523,9 +1721,9 @@ end;
class function TDbgDwarfIdentifier.GetSubClass(ATag: Cardinal): TDbgDwarfIdentifierClass;
begin
case ATag of
DW_TAG_variable, DW_TAG_formal_parameter, DW_TAG_constant, DW_TAG_member:
DW_TAG_variable, DW_TAG_formal_parameter, DW_TAG_constant:
Result := TDbgDwarfValueIdentifier;
DW_TAG_member: Result := TDbgDwarfIdentifierMember;
DW_TAG_base_type: Result := TDbgDwarfBaseIdentifierBase;
DW_TAG_typedef: Result := TDbgDwarfTypeIdentifierDeclaration;
DW_TAG_pointer_type: Result := TDbgDwarfTypeIdentifierPointer;
@ -1533,12 +1731,13 @@ begin
DW_TAG_const_type,
DW_TAG_volatile_type: Result := TDbgDwarfTypeIdentifierModifier;
DW_TAG_reference_type,
DW_TAG_string_type, DW_TAG_array_type, DW_TAG_class_type,
DW_TAG_string_type, DW_TAG_array_type,
DW_TAG_enumeration_type, DW_TAG_subroutine_type,
DW_TAG_union_type, DW_TAG_ptr_to_member_type,
DW_TAG_set_type, DW_TAG_subrange_type, DW_TAG_file_type,
DW_TAG_thrown_type: Result := TDbgDwarfTypeIdentifier;
DW_TAG_structure_type,
DW_TAG_enumeration_type, DW_TAG_subroutine_type, DW_TAG_union_type,
DW_TAG_ptr_to_member_type, DW_TAG_set_type, DW_TAG_subrange_type, DW_TAG_file_type,
DW_TAG_thrown_type:
Result := TDbgDwarfTypeIdentifier;
DW_TAG_class_type: Result := TDbgDwarfIdentifierStructure;
else
Result := TDbgDwarfIdentifier;
@ -2585,26 +2784,13 @@ begin
while InfoEntry.HasValidScope do begin
debugln(['TDbgDwarf.FindIdentifier Searching ', dbgs(InfoEntry.FScope, CU)]);
StartScopeIdx := InfoEntry.ScopeIndex;
InfoEntry.GoChild;
while InfoEntry.HasValidScope do begin
if not InfoEntry.ReadValue(DW_AT_name, EntryName) then begin
InfoEntry.GoNext;
Continue;
end;
if UpperCase(EntryName) = UpperCase(AName) then begin
// TODO: check DW_AT_start_scope;
Result := TDbgDwarfIdentifier.CreateSubClass(AName, InfoEntry);
//DebugLn(['!!!! FOUND !!! ', dbgs(InfoEntry.FScope, CU), DbgsDump(InfoEntry.FScope, CU) ]);
DebugLn(['!!!! FOUND !!! ', dbgs(InfoEntry.FScope, CU), DbgSName(Result)]);
break;
end;
InfoEntry.GoNext;
end;
if Result <> nil then
if InfoEntry.GoNamedChild(AName) then begin
Result := TDbgDwarfIdentifier.CreateSubClass(AName, InfoEntry);
//DebugLn(['!!!! FOUND !!! ', dbgs(InfoEntry.FScope, CU), DbgsDump(InfoEntry.FScope, CU) ]);
DebugLn(['!!!! FOUND !!! ', dbgs(InfoEntry.FScope, CU), DbgSName(Result)]);
break;
end;
// Search parent(s)
InfoEntry.ScopeIndex := StartScopeIdx;

View File

@ -105,6 +105,7 @@ type
protected
procedure Init; virtual;
procedure DoGetResultType(var AResultType: TFpPasExprType); virtual;
procedure InitResultTypeFromDbgInfo(var AResultType: TFpPasExprType; ADbgInfo: TDbgSymbol);
Procedure ReplaceInParent(AReplacement: TFpPascalExpressionPart);
procedure DoHandleEndOfExpression; virtual;
@ -238,6 +239,7 @@ type
TFpPascalExpressionPartOperatorMakeRef = class(TFpPascalExpressionPartUnaryOperator) // ^TTYpe
protected
procedure Init; override;
function IsValidNextPart(APart: TFpPascalExpressionPart): Boolean; override;
procedure DoGetResultType(var AResultType: TFpPasExprType); override;
end;
@ -283,6 +285,8 @@ type
TFpPascalExpressionPartOperatorMemberOf = class(TFpPascalExpressionPartBinaryOperator) // struct.member
protected
procedure Init; override;
function IsValidNextPart(APart: TFpPascalExpressionPart): Boolean; override;
procedure DoGetResultType(var AResultType: TFpPasExprType); override;
end;
implementation
@ -303,28 +307,8 @@ end;
procedure TFpPascalExpressionPartIdentifer.DoGetResultType(var AResultType: TFpPasExprType);
begin
FResultType.Kind := ptkInvalid;
FDbgType := FExpression.GetDbgTyeForIdentifier(GetText);
if (FDbgType = nil) then
exit;
if (FDbgType is TDbgDwarfTypeIdentifier) then begin
AResultType.DbgType := TDbgDwarfTypeIdentifier(FDbgType);
AResultType.DbgType.AddReference;
FResultType.Kind := ptkTypeDbgType;
exit;
end;
if FDbgType is TDbgDwarfValueIdentifier then begin
AResultType.DbgType := TDbgDwarfValueIdentifier(FDbgType).TypeInfo;
AResultType.DbgType.AddReference;
if AResultType.DbgType <> nil then
FResultType.Kind := ptkValueDbgType;
exit;
end;
debugln(['TFpPascalExpressionPartIdentifer.DoGetResultType UNKNOWN: ', DbgSName(FDbgType)]);
InitResultTypeFromDbgInfo(AResultType, FDbgType);
end;
destructor TFpPascalExpressionPartIdentifer.Destroy;
@ -602,6 +586,32 @@ begin
FResultType.Kind := ptkInvalid;
end;
procedure TFpPascalExpressionPart.InitResultTypeFromDbgInfo(var AResultType: TFpPasExprType;
ADbgInfo: TDbgSymbol);
begin
AResultType.Kind := ptkInvalid;
if (ADbgInfo = nil) then
exit;
if (ADbgInfo is TDbgDwarfTypeIdentifier) then begin
AResultType.DbgType := TDbgDwarfTypeIdentifier(ADbgInfo);
AResultType.DbgType.AddReference;
AResultType.Kind := ptkTypeDbgType;
exit;
end;
if ADbgInfo is TDbgDwarfValueIdentifier then begin
AResultType.DbgType := TDbgDwarfValueIdentifier(ADbgInfo).TypeInfo;
AResultType.DbgType.AddReference;
if AResultType.DbgType <> nil then
AResultType.Kind := ptkValueDbgType;
exit;
end;
debugln(['TFpPascalExpressionPartIdentifer.DoGetResultType UNKNOWN: ', DbgSName(ADbgInfo)]);
end;
procedure TFpPascalExpressionPart.ReplaceInParent(AReplacement: TFpPascalExpressionPart);
var
i: Integer;
@ -977,6 +987,12 @@ begin
inherited Init;
end;
function TFpPascalExpressionPartOperatorMakeRef.IsValidNextPart(APart: TFpPascalExpressionPart): Boolean;
begin
Result := (inherited IsValidNextPart(APart)) and
(APart is TFpPascalExpressionPartIdentifer);
end;
procedure TFpPascalExpressionPartOperatorMakeRef.DoGetResultType(var AResultType: TFpPasExprType);
begin
AResultType.Kind := ptkInvalid;
@ -1076,5 +1092,30 @@ begin
inherited Init;
end;
function TFpPascalExpressionPartOperatorMemberOf.IsValidNextPart(APart: TFpPascalExpressionPart): Boolean;
begin
Result := (inherited IsValidNextPart(APart)) and
(APart is TFpPascalExpressionPartIdentifer);
end;
procedure TFpPascalExpressionPartOperatorMemberOf.DoGetResultType(var AResultType: TFpPasExprType);
var
tmp: TFpPasExprType;
struct: TDbgDwarfIdentifierStructure;
member: TDbgDwarfIdentifierMember;
begin
AResultType.Kind := ptkInvalid;
if Count <> 2 then exit;
tmp := Items[0].ResultType;
// Todo unit
if (tmp.Kind = ptkValueDbgType) and (tmp.DbgType.IsStructType) then begin
struct := tmp.DbgType.StructTypeInfo;
member := struct.MemberByName[Items[1].GetText];
InitResultTypeFromDbgInfo(AResultType, member);
ReleaseRefAndNil(member);
end;
end;
end.