mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-22 15:29:35 +01:00
FPDebug: cache data address
git-svn-id: trunk@44239 -
This commit is contained in:
parent
1cedbd7c7f
commit
818e37a4d3
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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};
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user