FPDebug: cache data address

git-svn-id: trunk@44239 -
This commit is contained in:
martin 2014-02-25 21:56:02 +00:00
parent 1cedbd7c7f
commit 818e37a4d3
5 changed files with 42 additions and 10 deletions

View File

@ -994,6 +994,12 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
TDbgDwarfTypeIdentifier = class(TDbgDwarfIdentifier) TDbgDwarfTypeIdentifier = class(TDbgDwarfIdentifier)
protected protected
// FCachedDataAddress is used by
// TDbgDwarfSymbolValue.GetDwarfDataAddress
// TDbgDwarfValueIdentifier.GetDataAddress
//TODO: maybe introduce a lightweight wrapper, so types can be re-used.
FCachedDataAddress: TFpDbgMemLocation;
procedure Init; override; procedure Init; override;
procedure MemberVisibilityNeeded; override; procedure MemberVisibilityNeeded; override;
procedure SizeNeeded; override; procedure SizeNeeded; override;
@ -2825,6 +2831,13 @@ function TDbgDwarfSymbolValue.GetDwarfDataAddress(out AnAddress: TFpDbgMemLocati
var var
fields: TDbgSymbolValueFieldFlags; fields: TDbgSymbolValueFieldFlags;
begin begin
// TODO: also cache none valid address
Result := IsValidLoc(ATargetType.FCachedDataAddress);
if Result then begin
AnAddress := ATargetType.FCachedDataAddress;
exit;
end;
if FValueSymbol <> nil then begin if FValueSymbol <> nil then begin
Assert(FValueSymbol is TDbgDwarfValueIdentifier, 'TDbgDwarfSymbolValue.GetDwarfDataAddress FValueSymbol'); Assert(FValueSymbol is TDbgDwarfValueIdentifier, 'TDbgDwarfSymbolValue.GetDwarfDataAddress FValueSymbol');
Assert(TypeInfo is TDbgDwarfTypeIdentifier, 'TDbgDwarfSymbolValue.GetDwarfDataAddress TypeInfo'); Assert(TypeInfo is TDbgDwarfTypeIdentifier, 'TDbgDwarfSymbolValue.GetDwarfDataAddress TypeInfo');
@ -2856,6 +2869,8 @@ begin
if IsError(FTypeCastTargetType.LastError) then if IsError(FTypeCastTargetType.LastError) then
FLastError := FTypeCastTargetType.LastError; FLastError := FTypeCastTargetType.LastError;
end; end;
ATargetType.FCachedDataAddress := AnAddress;
end; end;
procedure TDbgDwarfSymbolValue.Reset; procedure TDbgDwarfSymbolValue.Reset;
@ -5638,11 +5653,19 @@ begin
Result := TypeInfo <> nil; Result := TypeInfo <> nil;
if not Result then if not Result then
exit; exit;
// TODO: also cache none valid address
Result := IsValidLoc(ATargetType.FCachedDataAddress);
if Result then begin
AnAddress := ATargetType.FCachedDataAddress;
exit;
end;
Assert((TypeInfo is TDbgDwarfIdentifier) and (TypeInfo.SymbolType = stType), 'TDbgDwarfValueIdentifier.GetDataAddress'); Assert((TypeInfo is TDbgDwarfIdentifier) and (TypeInfo.SymbolType = stType), 'TDbgDwarfValueIdentifier.GetDataAddress');
AnAddress := Address; AnAddress := Address;
Result := IsReadableLoc(AnAddress); Result := IsReadableLoc(AnAddress);
if Result then if Result then
Result := TDbgDwarfTypeIdentifier(TypeInfo).GetDataAddress(AnAddress, ATargetType); Result := TDbgDwarfTypeIdentifier(TypeInfo).GetDataAddress(AnAddress, ATargetType);
ATargetType.FCachedDataAddress := AnAddress;
end; end;
procedure TDbgDwarfValueIdentifier.KindNeeded; procedure TDbgDwarfValueIdentifier.KindNeeded;

View File

@ -164,6 +164,7 @@ type
* TODO: allow to pre-read and cache Target mem (e.g. before reading all fields of a record * TODO: allow to pre-read and cache Target mem (e.g. before reading all fields of a record
*) *)
TFpDbgMemLocationType = ( TFpDbgMemLocationType = (
mflUninitialized := 0, // like invalid, but not known // 0 means objet fields will start wint this
mlfInvalid, mlfInvalid,
mlfTargetMem, // an address in the target (debuggee) process mlfTargetMem, // an address in the target (debuggee) process
mlfSelfMem, // an address in this(the debuggers) process memory; the data is in TARGET format (endian, ...) mlfSelfMem, // an address in this(the debuggers) process memory; the data is in TARGET format (endian, ...)
@ -314,12 +315,12 @@ end;
function IsValidLoc(ALocation: TFpDbgMemLocation): Boolean; function IsValidLoc(ALocation: TFpDbgMemLocation): Boolean;
begin begin
Result := (ALocation.MType <> mlfInvalid); Result := not(ALocation.MType in [mlfInvalid, mflUninitialized]);
end; end;
function IsReadableLoc(ALocation: TFpDbgMemLocation): Boolean; function IsReadableLoc(ALocation: TFpDbgMemLocation): Boolean;
begin begin
Result := (ALocation.MType <> mlfInvalid) and Result := (not(ALocation.MType in [mlfInvalid, mflUninitialized])) and
( (not(ALocation.MType in [mlfTargetMem, mlfSelfMem])) or ( (not(ALocation.MType in [mlfTargetMem, mlfSelfMem])) or
(ALocation.Address <> 0) (ALocation.Address <> 0)
); );
@ -492,7 +493,7 @@ begin
FLastError := NoError; FLastError := NoError;
Result := False; Result := False;
case ALocation.MType of case ALocation.MType of
mlfInvalid: mlfInvalid, mflUninitialized:
FLastError := CreateError(fpErrCanNotReadInvalidMem); FLastError := CreateError(fpErrCanNotReadInvalidMem);
mlfTargetMem, mlfSelfMem: begin mlfTargetMem, mlfSelfMem: begin
Result := TargetMemConvertor.PrepareTargetRead(AReadDataType, ALocation.Address, Result := TargetMemConvertor.PrepareTargetRead(AReadDataType, ALocation.Address,
@ -589,7 +590,7 @@ begin
FLastError := NoError; FLastError := NoError;
Result := False; Result := False;
case ALocation.MType of case ALocation.MType of
mlfInvalid: ; mlfInvalid, mflUninitialized: ;
mlfTargetMem: mlfTargetMem:
begin begin
Result := FMemReader.ReadMemory(ALocation.Address, ASize, ADest); Result := FMemReader.ReadMemory(ALocation.Address, ASize, ADest);

View File

@ -924,6 +924,7 @@ begin
tmp2 := Items[1].ResultValue; tmp2 := Items[1].ResultValue;
if not (svfOrdinal in tmp2.FieldFlags) then if not (svfOrdinal in tmp2.FieldFlags) then
exit; exit;
if tmp2.AsCardinal > high(Integer) then exit; // TODO max member range
Result := tmp.Member[tmp2.AsCardinal]; // todo negative ? Result := tmp.Member[tmp2.AsCardinal]; // todo negative ?
if Result <> nil then if Result <> nil then
Result.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(nil, 'DoGetResultValue'){$ENDIF}; Result.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(nil, 'DoGetResultValue'){$ENDIF};

View File

@ -402,7 +402,8 @@ end;
function TTestMemReader.ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; function TTestMemReader.ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal;
ADest: Pointer): Boolean; ADest: Pointer): Boolean;
begin begin
Result := True; Result := AnAddress > 1000; // avoid reading at 0x0000
if not Result then exit;
Move(Pointer(AnAddress)^, ADest^, ASize); Move(Pointer(AnAddress)^, ADest^, ASize);
end; end;

View File

@ -5,9 +5,9 @@ unit TestTypeInfo;
interface interface
uses uses
FpPascalParser, FpDbgDwarf, FpDbgInfo, FpdMemoryTools, LazLoggerBase, LazUTF8, sysutils, FpPascalParser, FpDbgDwarf, FpDbgInfo, FpdMemoryTools, FpErrorMessages, LazLoggerBase,
fpcunit, testregistry, TestHelperClasses, TestDwarfSetup1, TestDwarfSetupBasic, LazUTF8, sysutils, fpcunit, testregistry, TestHelperClasses, TestDwarfSetup1,
DbgIntfBaseTypes, TestDwarfSetupArray; TestDwarfSetupBasic, DbgIntfBaseTypes, TestDwarfSetupArray;
type type
@ -305,8 +305,14 @@ end;
procedure TTestTypeInfo.StartInvalTest(Expr: String; ExpError: String; ExtraName: String); procedure TTestTypeInfo.StartInvalTest(Expr: String; ExpError: String; ExtraName: String);
begin begin
InitTest(Expr, ExtraName); InitTest(Expr, ExtraName);
FExpression.ResultValue; if FExpression.ResultValue <> nil then begin // some value are only invalid after accessing the data
AssertTrue(FCurrentTestName + 'invalid', (not FExpression.Valid) or (FExpression.ResultValue = nil)); FExpression.ResultValue.AsInteger;
FExpression.ResultValue.AsCardinal;
end;
AssertTrue(FCurrentTestName + 'invalid',
(not FExpression.Valid) or (FExpression.ResultValue = nil) or
(IsError(FExpression.ResultValue.LastError))
);
//AssertTrue(CurrentTestName + 'invalid', (not Expression.Valid)); //AssertTrue(CurrentTestName + 'invalid', (not Expression.Valid));
//ExpError //ExpError
end; end;