FpDebug: Refactor GetDataAddress

git-svn-id: trunk@61799 -
This commit is contained in:
martin 2019-09-02 00:44:41 +00:00
parent e436e9b9dd
commit 767d2014d8
2 changed files with 114 additions and 58 deletions

View File

@ -497,9 +497,10 @@ type
): Boolean; ): Boolean;
// GetDataAddress: data of a class, or string // GetDataAddress: data of a class, or string
function GetDataAddress(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; function GetDataAddress(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation;
ATargetType: TFpSymbolDwarfType): Boolean; ATargetType: TFpSymbolDwarfType = nil): Boolean;
function GetNextTypeInfoForDataAddress(ATargetType: TFpSymbolDwarfType): TFpSymbolDwarfType; virtual;
function GetDataAddressNext(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; function GetDataAddressNext(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation;
ATargetType: TFpSymbolDwarfType): Boolean; virtual; out ADoneWork: Boolean; ATargetType: TFpSymbolDwarfType): Boolean; virtual;
function HasAddress: Boolean; virtual; function HasAddress: Boolean; virtual;
procedure Init; override; procedure Init; override;
@ -641,6 +642,7 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
protected protected
procedure TypeInfoNeeded; override; procedure TypeInfoNeeded; override;
procedure ForwardToSymbolNeeded; override; procedure ForwardToSymbolNeeded; override;
function GetNextTypeInfoForDataAddress(ATargetType: TFpSymbolDwarfType): TFpSymbolDwarfType; override;
public public
function GetTypedValueObject(ATypeCast: Boolean): TFpValueDwarf; override; function GetTypedValueObject(ATypeCast: Boolean): TFpValueDwarf; override;
end; end;
@ -651,7 +653,7 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
protected protected
function GetFlags: TDbgSymbolFlags; override; function GetFlags: TDbgSymbolFlags; override;
function GetDataAddressNext(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; function GetDataAddressNext(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation;
ATargetType: TFpSymbolDwarfType): Boolean; override; out ADoneWork: Boolean; ATargetType: TFpSymbolDwarfType): Boolean; override;
end; end;
{ TFpSymbolDwarfTypeDeclaration } { TFpSymbolDwarfTypeDeclaration }
@ -664,6 +666,7 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
TFpSymbolDwarfTypeSubRange = class(TFpSymbolDwarfTypeModifier) TFpSymbolDwarfTypeSubRange = class(TFpSymbolDwarfTypeModifier)
// TODO not a modifier, maybe have a forwarder base class // TODO not a modifier, maybe have a forwarder base class
// GetNextTypeInfoForDataAddress => wrong behaviour, but basetypes should not change addr anyway.
private private
FLowBoundConst: Int64; FLowBoundConst: Int64;
FLowBoundValue: TFpValue; FLowBoundValue: TFpValue;
@ -727,8 +730,8 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
function GetNestedSymbolCount: Integer; override; function GetNestedSymbolCount: Integer; override;
// TODO: deal with DW_TAG_pointer_type // TODO: deal with DW_TAG_pointer_type
function GetDataAddressNext(AValueObj: TFpValueDwarf; function GetDataAddressNext(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation;
var AnAddress: TFpDbgMemLocation; ATargetType: TFpSymbolDwarfType): Boolean; override; out ADoneWork: Boolean; ATargetType: TFpSymbolDwarfType): Boolean; override;
procedure KindNeeded; override; procedure KindNeeded; override;
public public
destructor Destroy; override; destructor Destroy; override;
@ -841,7 +844,7 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
function GetNestedSymbolCount: Integer; override; function GetNestedSymbolCount: Integer; override;
function GetDataAddressNext(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; function GetDataAddressNext(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation;
ATargetType: TFpSymbolDwarfType): Boolean; override; out ADoneWork: Boolean; ATargetType: TFpSymbolDwarfType): Boolean; override;
public public
destructor Destroy; override; destructor Destroy; override;
function GetTypedValueObject(ATypeCast: Boolean): TFpValueDwarf; override; function GetTypedValueObject(ATypeCast: Boolean): TFpValueDwarf; override;
@ -1482,13 +1485,12 @@ begin
if HasTypeCastInfo and (svfOrdinal in FTypeCastSourceValue.FieldFlags) then if HasTypeCastInfo and (svfOrdinal in FTypeCastSourceValue.FieldFlags) then
Result := ConstLoc(FTypeCastSourceValue.AsCardinal) Result := ConstLoc(FTypeCastSourceValue.AsCardinal)
else else
GetDwarfDataAddress(Result, FOwner); GetDwarfDataAddress(Result);
end; end;
function TFpValueDwarf.GetDataAddress: TFpDbgMemLocation; function TFpValueDwarf.GetDataAddress: TFpDbgMemLocation;
begin begin
if not GetDwarfDataAddress(Result) then GetDwarfDataAddress(Result);
Result := InvalidLoc;
end; end;
function TFpValueDwarf.GetDwarfDataAddress(out AnAddress: TFpDbgMemLocation; function TFpValueDwarf.GetDwarfDataAddress(out AnAddress: TFpDbgMemLocation;
@ -1513,7 +1515,7 @@ begin
Result := ti <> nil; Result := ti <> nil;
if not Result then if not Result then
exit; exit;
Assert((ti is TFpSymbolDwarf) and (ti.SymbolType = stType), 'TDbgDwarfSymbolValue.GetDwarfDataAddress TypeInfo = stType'); Assert((ti is TFpSymbolDwarfType) and (ti.SymbolType = stType), 'TDbgDwarfSymbolValue.GetDwarfDataAddress TypeInfo = stType');
AnAddress := Address; AnAddress := Address;
Result := IsReadableLoc(AnAddress); Result := IsReadableLoc(AnAddress);
@ -1529,11 +1531,11 @@ begin
begin begin
// TODO: cache own address // TODO: cache own address
// try typecast // try typecast
AnAddress := InvalidLoc;
Result := HasTypeCastInfo; Result := HasTypeCastInfo;
if not Result then if not Result then
exit; exit;
fields := FTypeCastSourceValue.FieldFlags; fields := FTypeCastSourceValue.FieldFlags;
AnAddress := InvalidLoc;
if svfOrdinal in fields then if svfOrdinal in fields then
AnAddress := ConstLoc(FTypeCastSourceValue.AsCardinal) AnAddress := ConstLoc(FTypeCastSourceValue.AsCardinal)
else else
@ -1541,16 +1543,16 @@ begin
AnAddress := FTypeCastSourceValue.Address; AnAddress := FTypeCastSourceValue.Address;
Result := IsReadableLoc(AnAddress); Result := IsReadableLoc(AnAddress);
if not Result then if Result then begin
exit; Result := FTypeCastTargetType.GetDataAddress(Self, AnAddress, ATargetType);
if IsError(FTypeCastTargetType.LastError) then
Result := FTypeCastTargetType.GetDataAddress(Self, AnAddress, ATargetType); FLastError := FTypeCastTargetType.LastError;
if IsError(FTypeCastTargetType.LastError) then end;
FLastError := FTypeCastTargetType.LastError;
end; end;
if Result then if not Result then
FCachedDataAddress := AnAddress; AnAddress := InvalidLoc;
FCachedDataAddress := AnAddress;
end; end;
function TFpValueDwarf.GetStructureDwarfDataAddress(out AnAddress: TFpDbgMemLocation; function TFpValueDwarf.GetStructureDwarfDataAddress(out AnAddress: TFpDbgMemLocation;
@ -2024,8 +2026,7 @@ begin
if (FSize <= 0) then if (FSize <= 0) then
Result := InvalidLoc Result := InvalidLoc
else else
if not GetDwarfDataAddress(Result, Owner) then Result := inherited;
Result := InvalidLoc
end; end;
function TFpValueDwarfPointer.GetAsString: AnsiString; function TFpValueDwarfPointer.GetAsString: AnsiString;
@ -2256,7 +2257,7 @@ begin
t := t.TypeInfo; t := t.TypeInfo;
if t = nil then exit; if t = nil then exit;
GetDwarfDataAddress(DAddr, FOwner); GetDwarfDataAddress(DAddr);
if not MemManager.ReadSet(DAddr, FSize, FMem) then begin if not MemManager.ReadSet(DAddr, FSize, FMem) then begin
FLastError := MemManager.LastError; FLastError := MemManager.LastError;
exit; // TODO: error exit; // TODO: error
@ -3146,10 +3147,11 @@ function TFpSymbolDwarf.GetDataAddress(AValueObj: TFpValueDwarf;
var AnAddress: TFpDbgMemLocation; ATargetType: TFpSymbolDwarfType): Boolean; var AnAddress: TFpDbgMemLocation; ATargetType: TFpSymbolDwarfType): Boolean;
var var
ti: TFpSymbolDwarfType; ti: TFpSymbolDwarfType;
InitLocParserData: TInitLocParserData;
AttrData: TDwarfAttribData; AttrData: TDwarfAttribData;
t: TDBGPtr; t: TDBGPtr;
dummy: Boolean;
begin begin
Assert(self is TFpSymbolDwarfType);
Result := False; Result := False;
if InformationEntry.GetAttribData(DW_AT_allocated, AttrData) then begin if InformationEntry.GetAttribData(DW_AT_allocated, AttrData) then begin
if not ConstRefOrExprFromAttrData(AttrData, AValueObj, t) then begin if not ConstRefOrExprFromAttrData(AttrData, AValueObj, t) then begin
@ -3173,32 +3175,42 @@ begin
end; end;
end; end;
InitLocParserData.ObjectDataAddress := AnAddress; Result := GetDataAddressNext(AValueObj, AnAddress, dummy, ATargetType);
InitLocParserData.ObjectDataAddrPush := False;
Result := LocationFromTag(DW_AT_data_location, AValueObj, AnAddress, @InitLocParserData, True);
if not Result then if not Result then
exit; exit;
if ATargetType = Self then begin ti := GetNextTypeInfoForDataAddress(ATargetType);
Result := True; if ti = nil then
exit;
end;
Result := GetDataAddressNext(AValueObj, AnAddress, ATargetType);
if not Result then
exit; exit;
ti := NestedTypeInfo; Result := ti.GetDataAddress(AValueObj, AnAddress, ATargetType);
if ti <> nil then end;
Result := ti.GetDataAddress(AValueObj, AnAddress, ATargetType)
function TFpSymbolDwarf.GetNextTypeInfoForDataAddress(
ATargetType: TFpSymbolDwarfType): TFpSymbolDwarfType;
begin
if (ATargetType = nil) or (ATargetType = self) then
Result := nil
else else
Result := ATargetType = nil; // end of type chain Result := NestedTypeInfo;
end; end;
function TFpSymbolDwarf.GetDataAddressNext(AValueObj: TFpValueDwarf; function TFpSymbolDwarf.GetDataAddressNext(AValueObj: TFpValueDwarf;
var AnAddress: TFpDbgMemLocation; ATargetType: TFpSymbolDwarfType): Boolean; var AnAddress: TFpDbgMemLocation; out ADoneWork: Boolean;
ATargetType: TFpSymbolDwarfType): Boolean;
var
AttrData: TDwarfAttribData;
InitLocParserData: TInitLocParserData;
begin begin
Result := True; Result := True;
ADoneWork := False;
if InformationEntry.GetAttribData(DW_AT_data_location, AttrData) then begin
ADoneWork := True;
InitLocParserData.ObjectDataAddress := AnAddress;
InitLocParserData.ObjectDataAddrPush := False;
Result := LocationFromAttrData(AttrData, AValueObj, AnAddress, @InitLocParserData);
end;
end; end;
function TFpSymbolDwarf.HasAddress: Boolean; function TFpSymbolDwarf.HasAddress: Boolean;
@ -3564,6 +3576,15 @@ begin
SetForwardToSymbol(NestedTypeInfo) SetForwardToSymbol(NestedTypeInfo)
end; end;
function TFpSymbolDwarfTypeModifier.GetNextTypeInfoForDataAddress(
ATargetType: TFpSymbolDwarfType): TFpSymbolDwarfType;
begin
if (ATargetType = self) then
Result := nil
else
Result := NestedTypeInfo;
end;
function TFpSymbolDwarfTypeModifier.GetTypedValueObject(ATypeCast: Boolean): TFpValueDwarf; function TFpSymbolDwarfTypeModifier.GetTypedValueObject(ATypeCast: Boolean): TFpValueDwarf;
var var
ti: TFpSymbolDwarfType; ti: TFpSymbolDwarfType;
@ -3583,18 +3604,22 @@ begin
end; end;
function TFpSymbolDwarfTypeRef.GetDataAddressNext(AValueObj: TFpValueDwarf; function TFpSymbolDwarfTypeRef.GetDataAddressNext(AValueObj: TFpValueDwarf;
var AnAddress: TFpDbgMemLocation; ATargetType: TFpSymbolDwarfType): Boolean; var AnAddress: TFpDbgMemLocation; out ADoneWork: Boolean;
ATargetType: TFpSymbolDwarfType): Boolean;
begin begin
Result := inherited GetDataAddressNext(AValueObj, AnAddress, ADoneWork, ATargetType);
if (not Result) or ADoneWork then
exit;
Result := AValueObj.MemManager <> nil; Result := AValueObj.MemManager <> nil;
if not Result then if not Result then
exit; exit;
AnAddress := AValueObj.MemManager.ReadAddress(AnAddress, CompilationUnit.AddressSize); AnAddress := AValueObj.MemManager.ReadAddress(AnAddress, CompilationUnit.AddressSize);
Result := IsValidLoc(AnAddress); Result := IsValidLoc(AnAddress);
if Result then if (not Result) and
Result := inherited GetDataAddressNext(AValueObj, AnAddress, ATargetType) IsError(AValueObj.MemManager.LastError)
else then
if IsError(AValueObj.MemManager.LastError) then
SetLastError(AValueObj.MemManager.LastError); SetLastError(AValueObj.MemManager.LastError);
// Todo: other error // Todo: other error
end; end;
@ -3947,9 +3972,13 @@ begin
end; end;
function TFpSymbolDwarfTypeSubroutine.GetDataAddressNext( function TFpSymbolDwarfTypeSubroutine.GetDataAddressNext(
AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; out
ATargetType: TFpSymbolDwarfType): Boolean; ADoneWork: Boolean; ATargetType: TFpSymbolDwarfType): Boolean;
begin begin
Result := inherited GetDataAddressNext(AValueObj, AnAddress, ADoneWork, ATargetType);
if (not Result) or ADoneWork then
exit;
Result := AValueObj.MemManager <> nil; Result := AValueObj.MemManager <> nil;
if not Result then if not Result then
exit; exit;
@ -4250,9 +4279,25 @@ begin
end; end;
function TFpSymbolDwarfTypeStructure.GetDataAddressNext( function TFpSymbolDwarfTypeStructure.GetDataAddressNext(
AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; out
ATargetType: TFpSymbolDwarfType): Boolean; ADoneWork: Boolean; ATargetType: TFpSymbolDwarfType): Boolean;
begin begin
Result := inherited GetDataAddressNext(AValueObj, AnAddress, ADoneWork, ATargetType);
(* We have the DataAddress for this class => stop here, unless ATargetType
indicates that we want a parent-class DataAddress
Adding the InheritanceInfo's DW_AT_data_member_location would normally
have to be done by the parent class. But then we would need to make it
available there.
// TODO: Could not determine from the Dwarf Spec, if the parent class
should skip its DW_AT_data_location, if it was reached via
DW_AT_data_member_location
The spec says "handled the same as for members" => might indicate it should
*)
if (ATargetType = nil) or (ATargetType = self) then
exit;
Result := IsReadableMem(AnAddress); Result := IsReadableMem(AnAddress);
if not Result then if not Result then
exit; exit;
@ -4265,8 +4310,6 @@ begin
Result := ComputeDataMemberAddress(FInheritanceInfo, AValueObj, AnAddress); Result := ComputeDataMemberAddress(FInheritanceInfo, AValueObj, AnAddress);
if not Result then if not Result then
exit; exit;
Result := inherited GetDataAddressNext(AValueObj, AnAddress, ATargetType);
end; end;
function TFpSymbolDwarfTypeStructure.GetNestedSymbol(AIndex: Int64): TFpSymbol; function TFpSymbolDwarfTypeStructure.GetNestedSymbol(AIndex: Int64): TFpSymbol;

View File

@ -113,8 +113,9 @@ type
procedure TypeInfoNeeded; override; procedure TypeInfoNeeded; override;
procedure KindNeeded; override; procedure KindNeeded; override;
procedure ForwardToSymbolNeeded; override; procedure ForwardToSymbolNeeded; override;
function GetNextTypeInfoForDataAddress(ATargetType: TFpSymbolDwarfType): TFpSymbolDwarfType; override;
function GetDataAddressNext(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; function GetDataAddressNext(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation;
ATargetType: TFpSymbolDwarfType): Boolean; override; out ADoneWork: Boolean; ATargetType: TFpSymbolDwarfType): Boolean; override;
function GetTypedValueObject(ATypeCast: Boolean): TFpValueDwarf; override; function GetTypedValueObject(ATypeCast: Boolean): TFpValueDwarf; override;
function DataSize: Integer; override; function DataSize: Integer; override;
public public
@ -644,11 +645,24 @@ begin
SetForwardToSymbol(nil); // inherited ForwardToSymbolNeeded; SetForwardToSymbol(nil); // inherited ForwardToSymbolNeeded;
end; end;
function TFpSymbolDwarfFreePascalTypePointer.GetDataAddressNext( function TFpSymbolDwarfFreePascalTypePointer.GetNextTypeInfoForDataAddress(
AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; ATargetType: TFpSymbolDwarfType): TFpSymbolDwarfType;
ATargetType: TFpSymbolDwarfType): Boolean;
begin begin
if not IsInternalPointer then exit(True); if IsInternalPointer then
Result := NestedTypeInfo
else
Result := inherited;
end;
function TFpSymbolDwarfFreePascalTypePointer.GetDataAddressNext(
AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; out
ADoneWork: Boolean; ATargetType: TFpSymbolDwarfType): Boolean;
begin
if (not IsInternalPointer) and (ATargetType = nil) then exit(True);
Result := inherited GetDataAddressNext(AValueObj, AnAddress, ADoneWork, ATargetType);
if (not Result) or ADoneWork then
exit;
Result := AValueObj.MemManager <> nil; Result := AValueObj.MemManager <> nil;
if not Result then if not Result then
@ -656,10 +670,9 @@ begin
AnAddress := AValueObj.MemManager.ReadAddress(AnAddress, CompilationUnit.AddressSize); AnAddress := AValueObj.MemManager.ReadAddress(AnAddress, CompilationUnit.AddressSize);
Result := IsValidLoc(AnAddress); Result := IsValidLoc(AnAddress);
if Result then if (not Result) and
Result := inherited GetDataAddressNext(AValueObj, AnAddress, ATargetType) IsError(AValueObj.MemManager.LastError)
else then
if IsError(AValueObj.MemManager.LastError) then
SetLastError(AValueObj.MemManager.LastError); SetLastError(AValueObj.MemManager.LastError);
// Todo: other error // Todo: other error
end; end;