mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-14 16:59:21 +02:00
LazDebuggerFp: Add cache for common function addresses (used in watch-eval function calling), e.g. FPC_ANSISTR_DECR_REF
This commit is contained in:
parent
3c322a009f
commit
a571e61d9c
@ -5,12 +5,17 @@ unit FpDebugDebuggerBase;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, FPDbgController, FpdMemoryTools, FpDbgClasses, FpDbgUtil,
|
Classes, SysUtils, fgl, FPDbgController, FpdMemoryTools, FpDbgClasses,
|
||||||
DbgIntfDebuggerBase, FpDebugDebuggerUtils;
|
FpDbgUtil, FpDbgInfo, DbgIntfDebuggerBase, LazLoggerBase,
|
||||||
|
FpDebugDebuggerUtils, LazDebuggerIntfBaseTypes;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
{ TFpDebugDebuggerBase }
|
||||||
|
|
||||||
TFpDebugDebuggerBase = class(TDebuggerIntf)
|
TFpDebugDebuggerBase = class(TDebuggerIntf)
|
||||||
|
private type
|
||||||
|
TCachedDbgPtrMap = specialize TFPGMap<Pointer, TDbgPtr>;
|
||||||
protected
|
protected
|
||||||
FDbgController: TDbgController;
|
FDbgController: TDbgController;
|
||||||
FMemManager: TFpDbgMemManager;
|
FMemManager: TFpDbgMemManager;
|
||||||
@ -18,7 +23,21 @@ type
|
|||||||
FMemConverter: TFpDbgMemConvertorLittleEndian;
|
FMemConverter: TFpDbgMemConvertorLittleEndian;
|
||||||
FLockList: TFpDbgLockList;
|
FLockList: TFpDbgLockList;
|
||||||
FWorkQueue: TFpThreadPriorityWorkerQueue;
|
FWorkQueue: TFpThreadPriorityWorkerQueue;
|
||||||
|
|
||||||
|
FCached_FPC_ANSISTR_DECR_REF: TDbgPtr;
|
||||||
|
FCached_FPC_WIDESTR_DECR_REF: TDbgPtr;
|
||||||
|
FCached_Data: TCachedDbgPtrMap;
|
||||||
public
|
public
|
||||||
|
destructor Destroy; override;
|
||||||
|
|
||||||
|
// All caches must only be accessed it the debug-thread
|
||||||
|
function GetCached_FPC_ANSISTR_DECR_REF: TDBGPtr;
|
||||||
|
function GetCached_FPC_WIDESTR_DECR_REF: TDBGPtr;
|
||||||
|
procedure SetCachedData(AKey: Pointer; AValue: TDBGPtr);
|
||||||
|
function GetCachedData(AKey: Pointer): TDBGPtr;
|
||||||
|
procedure ClearCachedData;
|
||||||
|
|
||||||
|
|
||||||
property DbgController: TDbgController read FDbgController;
|
property DbgController: TDbgController read FDbgController;
|
||||||
property MemManager: TFpDbgMemManager read FMemManager;
|
property MemManager: TFpDbgMemManager read FMemManager;
|
||||||
property MemReader: TDbgMemReader read FMemReader;
|
property MemReader: TDbgMemReader read FMemReader;
|
||||||
@ -30,5 +49,74 @@ type
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
{ TFpDebugDebuggerBase }
|
||||||
|
|
||||||
|
destructor TFpDebugDebuggerBase.Destroy;
|
||||||
|
begin
|
||||||
|
inherited Destroy;
|
||||||
|
FreeAndNil(FCached_Data);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFpDebugDebuggerBase.GetCached_FPC_ANSISTR_DECR_REF: TDBGPtr;
|
||||||
|
var
|
||||||
|
StringDecRefSymbol: TFpSymbol;
|
||||||
|
begin
|
||||||
|
Result := FCached_FPC_ANSISTR_DECR_REF;
|
||||||
|
if Result <> 0 then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
StringDecRefSymbol := DbgController.CurrentProcess.FindProcSymbol('FPC_ANSISTR_DECR_REF');
|
||||||
|
|
||||||
|
if (StringDecRefSymbol <> nil) and (IsTargetNotNil(StringDecRefSymbol.Address)) then
|
||||||
|
FCached_FPC_ANSISTR_DECR_REF := StringDecRefSymbol.Address.Address;
|
||||||
|
|
||||||
|
StringDecRefSymbol.ReleaseReference;
|
||||||
|
Result := FCached_FPC_ANSISTR_DECR_REF;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFpDebugDebuggerBase.GetCached_FPC_WIDESTR_DECR_REF: TDBGPtr;
|
||||||
|
var
|
||||||
|
StringDecRefSymbol: TFpSymbol;
|
||||||
|
begin
|
||||||
|
Result := FCached_FPC_WIDESTR_DECR_REF;
|
||||||
|
if Result <> 0 then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
StringDecRefSymbol := DbgController.CurrentProcess.FindProcSymbol('FPC_WIDESTR_DECR_REF');
|
||||||
|
|
||||||
|
if (StringDecRefSymbol <> nil) and (IsTargetNotNil(StringDecRefSymbol.Address)) then
|
||||||
|
FCached_FPC_WIDESTR_DECR_REF := StringDecRefSymbol.Address.Address;
|
||||||
|
|
||||||
|
StringDecRefSymbol.ReleaseReference;
|
||||||
|
Result := FCached_FPC_WIDESTR_DECR_REF;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFpDebugDebuggerBase.SetCachedData(AKey: Pointer; AValue: TDBGPtr);
|
||||||
|
begin
|
||||||
|
if FCached_Data = nil then
|
||||||
|
FCached_Data := TCachedDbgPtrMap.Create;
|
||||||
|
FCached_Data[AKey] := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFpDebugDebuggerBase.GetCachedData(AKey: Pointer): TDBGPtr;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
if FCached_Data <> nil then begin
|
||||||
|
i := FCached_Data.IndexOf(AKey);
|
||||||
|
if i >= 0 then
|
||||||
|
Result := FCached_Data.Data[i];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFpDebugDebuggerBase.ClearCachedData;
|
||||||
|
begin
|
||||||
|
FCached_FPC_ANSISTR_DECR_REF := 0;
|
||||||
|
FCached_FPC_WIDESTR_DECR_REF := 0;
|
||||||
|
if FCached_Data <> nil then
|
||||||
|
FCached_Data.Clear;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -486,6 +486,7 @@ end;
|
|||||||
|
|
||||||
procedure TFpThreadWorkerRunLoop.DoExecute;
|
procedure TFpThreadWorkerRunLoop.DoExecute;
|
||||||
begin
|
begin
|
||||||
|
FDebugger.ClearCachedData;
|
||||||
FDebugger.DbgController.ProcessLoop;
|
FDebugger.DbgController.ProcessLoop;
|
||||||
Queue(@LoopFinished_DecRef);
|
Queue(@LoopFinished_DecRef);
|
||||||
end;
|
end;
|
||||||
@ -783,7 +784,7 @@ function TFpThreadWorkerEvaluate.DoWatchFunctionCall(
|
|||||||
AResult: TFpValue; var AnError: TFpError): boolean;
|
AResult: TFpValue; var AnError: TFpError): boolean;
|
||||||
var
|
var
|
||||||
FunctionSymbolData, FunctionSymbolType, FunctionResultSymbolType,
|
FunctionSymbolData, FunctionSymbolType, FunctionResultSymbolType,
|
||||||
TempSymbol, StringDecRefSymbol, StringSymbol: TFpSymbol;
|
TempSymbol, StringSymbol: TFpSymbol;
|
||||||
ExprParamVal: TFpValue;
|
ExprParamVal: TFpValue;
|
||||||
ProcAddress: TFpDbgMemLocation;
|
ProcAddress: TFpDbgMemLocation;
|
||||||
FunctionResultDataSize: TFpDbgValueSize;
|
FunctionResultDataSize: TFpDbgValueSize;
|
||||||
@ -791,7 +792,7 @@ var
|
|||||||
CallContext: TFpDbgInfoCallContext;
|
CallContext: TFpDbgInfoCallContext;
|
||||||
PCnt, i, FoundIdx, ItemsOffs: Integer;
|
PCnt, i, FoundIdx, ItemsOffs: Integer;
|
||||||
rk: TDbgSymbolKind;
|
rk: TDbgSymbolKind;
|
||||||
StringAddr: TDBGPtr;
|
StringAddr, StringDecRefAddress: TDBGPtr;
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
if FExpressionScope = nil then
|
if FExpressionScope = nil then
|
||||||
@ -829,16 +830,19 @@ begin
|
|||||||
|
|
||||||
try
|
try
|
||||||
ParameterSymbolArr := nil;
|
ParameterSymbolArr := nil;
|
||||||
StringDecRefSymbol := nil;
|
StringDecRefAddress := 0;
|
||||||
StringAddr := 0;
|
StringAddr := 0;
|
||||||
|
|
||||||
if (FunctionResultSymbolType.Kind in [skString, skAnsiString, skWideString])
|
if (FunctionResultSymbolType.Kind in [skString, skAnsiString, skWideString])
|
||||||
then begin
|
then begin
|
||||||
|
// FCached_FPC_ANSISTR_DECR_REF TFpThreadWorkerRunLoop.DoExecute
|
||||||
|
|
||||||
if (FunctionResultSymbolType.Kind = skWideString) then
|
if (FunctionResultSymbolType.Kind = skWideString) then
|
||||||
StringDecRefSymbol := FDebugger.DbgController.CurrentProcess.FindProcSymbol('FPC_WIDESTR_DECR_REF')
|
StringDecRefAddress := FDebugger.GetCached_FPC_WIDESTR_DECR_REF
|
||||||
else
|
else
|
||||||
StringDecRefSymbol := FDebugger.DbgController.CurrentProcess.FindProcSymbol('FPC_ANSISTR_DECR_REF');
|
StringDecRefAddress := FDebugger.GetCached_FPC_ANSISTR_DECR_REF;
|
||||||
if (StringDecRefSymbol = nil) or (not IsTargetNotNil(StringDecRefSymbol.Address)) then begin
|
|
||||||
|
if (StringDecRefAddress = 0) then begin
|
||||||
DebugLn(['Error result kind ', dbgs(FunctionSymbolType.Kind)]);
|
DebugLn(['Error result kind ', dbgs(FunctionSymbolType.Kind)]);
|
||||||
AnError := CreateError(fpErrAnyError, ['Result type of function not supported']);
|
AnError := CreateError(fpErrAnyError, ['Result type of function not supported']);
|
||||||
exit;
|
exit;
|
||||||
@ -940,7 +944,7 @@ begin
|
|||||||
FDebugger.MemReader, FDebugger.MemConverter);
|
FDebugger.MemReader, FDebugger.MemConverter);
|
||||||
|
|
||||||
try
|
try
|
||||||
if (ASelfValue = nil) and (StringDecRefSymbol <> nil) then begin
|
if (ASelfValue = nil) and (StringDecRefAddress <> 0) then begin
|
||||||
if not CallContext.AddStringResult then begin
|
if not CallContext.AddStringResult then begin
|
||||||
DebugLn('Internal error for string result');
|
DebugLn('Internal error for string result');
|
||||||
AnError := CallContext.LastError;
|
AnError := CallContext.LastError;
|
||||||
@ -963,7 +967,7 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (ASelfValue <> nil) and (StringDecRefSymbol <> nil) and (i = 0) then begin
|
if (ASelfValue <> nil) and (StringDecRefAddress <> 0) and (i = 0) then begin
|
||||||
if not CallContext.AddStringResult then begin
|
if not CallContext.AddStringResult then begin
|
||||||
DebugLn('Internal error for string result');
|
DebugLn('Internal error for string result');
|
||||||
AnError := CallContext.LastError;
|
AnError := CallContext.LastError;
|
||||||
@ -1017,7 +1021,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
if (FunctionResultSymbolType.Kind in [skString, skAnsiString, skWideString]) and (StringAddr <> 0) then begin
|
if (FunctionResultSymbolType.Kind in [skString, skAnsiString, skWideString]) and (StringAddr <> 0) then begin
|
||||||
CallContext := FDebugger.DbgController.Call(StringDecRefSymbol.Address, FExpressionScope.LocationContext,
|
CallContext := FDebugger.DbgController.Call(TargetLoc(StringDecRefAddress), FExpressionScope.LocationContext,
|
||||||
FDebugger.MemReader, FDebugger.MemConverter);
|
FDebugger.MemReader, FDebugger.MemConverter);
|
||||||
try
|
try
|
||||||
CallContext.AddOrdinalViaRefAsParam(StringAddr);
|
CallContext.AddOrdinalViaRefAsParam(StringAddr);
|
||||||
@ -1034,7 +1038,6 @@ begin
|
|||||||
for i := 0 to High(ParameterSymbolArr) do
|
for i := 0 to High(ParameterSymbolArr) do
|
||||||
if ParameterSymbolArr[i] <> nil then
|
if ParameterSymbolArr[i] <> nil then
|
||||||
ParameterSymbolArr[i].ReleaseReference;
|
ParameterSymbolArr[i].ReleaseReference;
|
||||||
ReleaseRefAndNil(StringDecRefSymbol);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
@ -302,9 +302,9 @@ function TFpDbgValueConverterVariantToLStr.ConvertValue(ASourceValue: TFpValue;
|
|||||||
): TFpValue;
|
): TFpValue;
|
||||||
var
|
var
|
||||||
NewResult, ProcVal, m: TFpValue;
|
NewResult, ProcVal, m: TFpValue;
|
||||||
ProcSym, StringDecRefSymbol: TFpSymbol;
|
ProcSym: TFpSymbol;
|
||||||
CallContext: TFpDbgInfoCallContext;
|
CallContext: TFpDbgInfoCallContext;
|
||||||
StringAddr, ProcAddr: TDbgPtr;
|
StringAddr, ProcAddr, StringDecRefAddress: TDbgPtr;
|
||||||
ProcLoc: TFpDbgMemLocation;
|
ProcLoc: TFpDbgMemLocation;
|
||||||
r: Boolean;
|
r: Boolean;
|
||||||
begin
|
begin
|
||||||
@ -330,7 +330,6 @@ begin
|
|||||||
|
|
||||||
ProcVal := nil;
|
ProcVal := nil;
|
||||||
ProcSym := nil;
|
ProcSym := nil;
|
||||||
StringDecRefSymbol := nil;
|
|
||||||
try
|
try
|
||||||
(*
|
(*
|
||||||
//VARIANTS_$$_SYSVARTOLSTR$ANSISTRING$VARIANT
|
//VARIANTS_$$_SYSVARTOLSTR$ANSISTRING$VARIANT
|
||||||
@ -359,15 +358,19 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ProcAddr := GetProcAddrFromMgr(AnFpDebugger, AnExpressionScope);
|
ProcAddr := AnFpDebugger.GetCachedData(pointer(TFpDbgValueConverterVariantToLStr));
|
||||||
if ProcAddr = 0 then begin
|
if ProcAddr = 0 then begin
|
||||||
SetError(CreateError(fpErrAnyError, ['SysVarToLStr not found']));
|
ProcAddr := GetProcAddrFromMgr(AnFpDebugger, AnExpressionScope);
|
||||||
exit;
|
if ProcAddr = 0 then begin
|
||||||
|
SetError(CreateError(fpErrAnyError, ['SysVarToLStr not found']));
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
AnFpDebugger.SetCachedData(pointer(TFpDbgValueConverterVariantToLStr), ProcAddr);
|
||||||
end;
|
end;
|
||||||
ProcLoc := TargetLoc(ProcAddr);
|
ProcLoc := TargetLoc(ProcAddr);
|
||||||
|
|
||||||
StringDecRefSymbol := AnFpDebugger.DbgController.CurrentProcess.FindProcSymbol('FPC_ANSISTR_DECR_REF');
|
StringDecRefAddress := AnFpDebugger.GetCached_FPC_ANSISTR_DECR_REF;
|
||||||
if (StringDecRefSymbol = nil) or (not IsTargetAddr(StringDecRefSymbol.Address)) then begin
|
if (StringDecRefAddress = 0) then begin
|
||||||
SetError(CreateError(fpErrAnyError, ['STRING_DEC_REF not found']));
|
SetError(CreateError(fpErrAnyError, ['STRING_DEC_REF not found']));
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -405,7 +408,7 @@ begin
|
|||||||
AnFpDebugger.DbgController.AbortCurrentCommand;
|
AnFpDebugger.DbgController.AbortCurrentCommand;
|
||||||
CallContext.ReleaseReference;
|
CallContext.ReleaseReference;
|
||||||
|
|
||||||
CallContext := AnFpDebugger.DbgController.Call(StringDecRefSymbol.Address, AnExpressionScope.LocationContext,
|
CallContext := AnFpDebugger.DbgController.Call(TargetLoc(StringDecRefAddress), AnExpressionScope.LocationContext,
|
||||||
AnFpDebugger.MemReader, AnFpDebugger.MemConverter);
|
AnFpDebugger.MemReader, AnFpDebugger.MemConverter);
|
||||||
try
|
try
|
||||||
CallContext.AddOrdinalViaRefAsParam(StringAddr);
|
CallContext.AddOrdinalViaRefAsParam(StringAddr);
|
||||||
@ -419,7 +422,6 @@ begin
|
|||||||
finally
|
finally
|
||||||
ProcVal.ReleaseReference;
|
ProcVal.ReleaseReference;
|
||||||
ProcSym.ReleaseReference;
|
ProcSym.ReleaseReference;
|
||||||
StringDecRefSymbol.ReleaseReference;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user