Debuggers (FpLLDB, FpGDBMI): add some safety checks. Do not free dwarf, in the middle of watch eval

git-svn-id: trunk@63786 -
This commit is contained in:
martin 2020-08-18 23:12:49 +00:00
parent d8007187b8
commit 35d829c943
2 changed files with 85 additions and 28 deletions

View File

@ -76,6 +76,8 @@ type
FMemManager: TFpDbgMemManager; FMemManager: TFpDbgMemManager;
// cache last context // cache last context
FLastContext: array [0..MAX_CTX_CACHE-1] of TFpDbgSymbolScope; FLastContext: array [0..MAX_CTX_CACHE-1] of TFpDbgSymbolScope;
FLockUnLoadDwarf: integer;
FUnLoadDwarfNeeded: Boolean;
protected protected
function CreateCommandStartDebugging(AContinueCommand: TGDBMIDebuggerCommand): TGDBMIDebuggerCommandStartDebugging; override; function CreateCommandStartDebugging(AContinueCommand: TGDBMIDebuggerCommand): TGDBMIDebuggerCommandStartDebugging; override;
function CreateLineInfo: TDBGLineInfo; override; function CreateLineInfo: TDBGLineInfo; override;
@ -85,6 +87,8 @@ type
function HasDwarf: Boolean; function HasDwarf: Boolean;
procedure LoadDwarf; procedure LoadDwarf;
procedure UnLoadDwarf; procedure UnLoadDwarf;
procedure LockUnLoadDwarf;
procedure UnLockUnLoadDwarf;
function RequestCommand(const ACommand: TDBGCommand; function RequestCommand(const ACommand: TDBGCommand;
const AParams: array of const; const AParams: array of const;
const ACallback: TMethod): Boolean; override; const ACallback: TMethod): Boolean; override;
@ -276,36 +280,41 @@ var
m: TFpValue; m: TFpValue;
n, v: String; n, v: String;
begin begin
Ctx := FpDebugger.GetInfoContextForContext(ALocals.ThreadId, ALocals.StackFrame); FpDebugger.LockUnLoadDwarf;
if (Ctx = nil) or (Ctx.SymbolAtAddress = nil) then begin try
ALocals.SetDataValidity(ddsInvalid); Ctx := FpDebugger.GetInfoContextForContext(ALocals.ThreadId, ALocals.StackFrame);
exit; if (Ctx = nil) or (Ctx.SymbolAtAddress = nil) then begin
end; ALocals.SetDataValidity(ddsInvalid);
exit;
ProcVal := Ctx.ProcedureAtAddress;
if (ProcVal = nil) then begin
ALocals.SetDataValidity(ddsInvalid);
exit;
end;
FpDebugger.FPrettyPrinter.AddressSize := ctx.SizeOfAddress;
FpDebugger.FPrettyPrinter.MemManager := ctx.MemManager;
ALocals.Clear;
for i := 0 to ProcVal.MemberCount - 1 do begin
m := ProcVal.Member[i];
if m <> nil then begin
if m.DbgSymbol <> nil then
n := m.DbgSymbol.Name
else
n := '';
FpDebugger.FPrettyPrinter.PrintValue(v, m);
m.ReleaseReference;
ALocals.Add(n, v);
end; end;
ProcVal := Ctx.ProcedureAtAddress;
if (ProcVal = nil) then begin
ALocals.SetDataValidity(ddsInvalid);
exit;
end;
FpDebugger.FPrettyPrinter.AddressSize := ctx.SizeOfAddress;
FpDebugger.FPrettyPrinter.MemManager := ctx.MemManager;
ALocals.Clear;
for i := 0 to ProcVal.MemberCount - 1 do begin
m := ProcVal.Member[i];
if m <> nil then begin
if m.DbgSymbol <> nil then
n := m.DbgSymbol.Name
else
n := '';
FpDebugger.FPrettyPrinter.PrintValue(v, m);
m.ReleaseReference;
ALocals.Add(n, v);
end;
end;
ProcVal.ReleaseReference;
ALocals.SetDataValidity(ddsValid);
finally
FpDebugger.UnLockUnLoadDwarf;
end; end;
ProcVal.ReleaseReference;
ALocals.SetDataValidity(ddsValid);
end; end;
function TFPGDBMILocals.FpDebugger: TFpGDBMIDebugger; function TFPGDBMILocals.FpDebugger: TFpGDBMIDebugger;
@ -569,6 +578,7 @@ begin
if FWatchEvalLock > 0 then if FWatchEvalLock > 0 then
exit; exit;
inc(FWatchEvalLock); inc(FWatchEvalLock);
FpDebugger.LockUnLoadDwarf;
try // TODO: if the stack/thread is changed, registers will be wrong try // TODO: if the stack/thread is changed, registers will be wrong
while (FpDebugger.FWatchEvalList.Count > 0) and (FEvaluationCmdObj = nil) do begin while (FpDebugger.FWatchEvalList.Count > 0) and (FEvaluationCmdObj = nil) do begin
try try
@ -598,6 +608,7 @@ begin
end; end;
finally finally
dec(FWatchEvalLock); dec(FWatchEvalLock);
FpDebugger.UnLockUnLoadDwarf;
end; end;
end; end;
@ -777,6 +788,11 @@ end;
procedure TFpGDBMIDebugger.UnLoadDwarf; procedure TFpGDBMIDebugger.UnLoadDwarf;
begin begin
if FLockUnLoadDwarf > 0 then begin
FUnLoadDwarfNeeded := True;
exit;
end;
FUnLoadDwarfNeeded := False;
debugln(DBG_VERBOSE, ['TFpGDBMIDebugger.UnLoadDwarf ']); debugln(DBG_VERBOSE, ['TFpGDBMIDebugger.UnLoadDwarf ']);
FreeAndNil(FDwarfInfo); FreeAndNil(FDwarfInfo);
FreeAndNil(FImageLoaderList); FreeAndNil(FImageLoaderList);
@ -787,6 +803,18 @@ begin
FreeAndNil(FPrettyPrinter); FreeAndNil(FPrettyPrinter);
end; end;
procedure TFpGDBMIDebugger.LockUnLoadDwarf;
begin
inc(FLockUnLoadDwarf);
end;
procedure TFpGDBMIDebugger.UnLockUnLoadDwarf;
begin
dec(FLockUnLoadDwarf);
if (FLockUnLoadDwarf <= 0) and FUnLoadDwarfNeeded then
UnLoadDwarf;
end;
function TFpGDBMIDebugger.RequestCommand(const ACommand: TDBGCommand; function TFpGDBMIDebugger.RequestCommand(const ACommand: TDBGCommand;
const AParams: array of const; const ACallback: TMethod): Boolean; const AParams: array of const; const ACallback: TMethod): Boolean;
var var
@ -1030,6 +1058,7 @@ begin
FPrettyPrinter.AddressSize := ctx.SizeOfAddress; FPrettyPrinter.AddressSize := ctx.SizeOfAddress;
FPrettyPrinter.MemManager := ctx.MemManager; FPrettyPrinter.MemManager := ctx.MemManager;
LockUnLoadDwarf;
PasExpr := TFpPascalExpression.Create(AExpression, Ctx); PasExpr := TFpPascalExpression.Create(AExpression, Ctx);
try try
if not IsWatchValueAlive then exit; if not IsWatchValueAlive then exit;
@ -1130,6 +1159,7 @@ DebugLn(DBG_VERBOSE, [ErrorHandler.ErrorAsString(PasExpr.Error)]);
finally finally
PasExpr.Free; PasExpr.Free;
FMemManager.DefaultContext := nil; FMemManager.DefaultContext := nil;
UnLockUnLoadDwarf;
end; end;
end; end;

View File

@ -131,6 +131,8 @@ type
FDwarfLoaderThread: TDwarfLoaderThread; FDwarfLoaderThread: TDwarfLoaderThread;
// cache last context // cache last context
FLastContext: array [0..MAX_CTX_CACHE-1] of TFpDbgSymbolScope; FLastContext: array [0..MAX_CTX_CACHE-1] of TFpDbgSymbolScope;
FLockUnLoadDwarf: integer;
FUnLoadDwarfNeeded: Boolean;
procedure DoBeginReceivingLines(Sender: TObject); procedure DoBeginReceivingLines(Sender: TObject);
procedure DoEndReceivingLines(Sender: TObject); procedure DoEndReceivingLines(Sender: TObject);
protected protected
@ -144,6 +146,8 @@ type
function HasDwarf: Boolean; function HasDwarf: Boolean;
function LoadDwarf: String; function LoadDwarf: String;
procedure UnLoadDwarf; procedure UnLoadDwarf;
procedure LockUnLoadDwarf;
procedure UnLockUnLoadDwarf;
function RequestCommand(const ACommand: TDBGCommand; function RequestCommand(const ACommand: TDBGCommand;
const AParams: array of const; const AParams: array of const;
const ACallback: TMethod): Boolean; override; const ACallback: TMethod): Boolean; override;
@ -412,6 +416,7 @@ begin
exit; exit;
end; end;
FpDebugger.LockUnLoadDwarf;
Ctx := FpDebugger.GetInfoContextForContext(ALocals.ThreadId, ALocals.StackFrame); Ctx := FpDebugger.GetInfoContextForContext(ALocals.ThreadId, ALocals.StackFrame);
try try
if (Ctx = nil) or (Ctx.SymbolAtAddress = nil) then begin if (Ctx = nil) or (Ctx.SymbolAtAddress = nil) then begin
@ -449,6 +454,7 @@ begin
finally finally
Ctx.ReleaseReference; Ctx.ReleaseReference;
ProcVal.ReleaseReference; ProcVal.ReleaseReference;
FpDebugger.UnLockUnLoadDwarf;
end; end;
end; end;
@ -799,6 +805,7 @@ begin
debugln(['ProcessEvalList ']); debugln(['ProcessEvalList ']);
inc(FWatchEvalLock); inc(FWatchEvalLock);
FpDebugger.LockUnLoadDwarf;
try // TODO: if the stack/thread is changed, registers will be wrong try // TODO: if the stack/thread is changed, registers will be wrong
while (FpDebugger.FWatchEvalList.Count > 0) and (FEvaluationCmdObj = nil) and (not FWatchEvalCancel) while (FpDebugger.FWatchEvalList.Count > 0) and (FEvaluationCmdObj = nil) and (not FWatchEvalCancel)
do begin do begin
@ -828,6 +835,7 @@ debugln(['ProcessEvalList ']);
end; end;
finally finally
dec(FWatchEvalLock); dec(FWatchEvalLock);
FpDebugger.UnLockUnLoadDwarf;
end; end;
end; end;
@ -1208,6 +1216,11 @@ end;
procedure TFpLldbDebugger.UnLoadDwarf; procedure TFpLldbDebugger.UnLoadDwarf;
begin begin
if FLockUnLoadDwarf > 0 then begin
FUnLoadDwarfNeeded := True;
exit;
end;
FUnLoadDwarfNeeded := False;
debugln(DBG_VERBOSE, ['TFpLldbDebugger.UnLoadDwarf ']); debugln(DBG_VERBOSE, ['TFpLldbDebugger.UnLoadDwarf ']);
FreeAndNil(FDwarfInfo); FreeAndNil(FDwarfInfo);
FreeAndNil(FImageLoaderList); FreeAndNil(FImageLoaderList);
@ -1226,6 +1239,18 @@ begin
end; end;
end; end;
procedure TFpLldbDebugger.LockUnLoadDwarf;
begin
inc(FLockUnLoadDwarf);
end;
procedure TFpLldbDebugger.UnLockUnLoadDwarf;
begin
dec(FLockUnLoadDwarf);
if (FLockUnLoadDwarf <= 0) and FUnLoadDwarfNeeded then
UnLoadDwarf;
end;
function TFpLldbDebugger.RequestCommand(const ACommand: TDBGCommand; function TFpLldbDebugger.RequestCommand(const ACommand: TDBGCommand;
const AParams: array of const; const ACallback: TMethod): Boolean; const AParams: array of const; const ACallback: TMethod): Boolean;
var var
@ -1473,6 +1498,7 @@ begin
FPrettyPrinter.AddressSize := ctx.SizeOfAddress; FPrettyPrinter.AddressSize := ctx.SizeOfAddress;
FPrettyPrinter.MemManager := ctx.MemManager; FPrettyPrinter.MemManager := ctx.MemManager;
LockUnLoadDwarf;
PasExpr := TFpPascalExpression.Create(AExpression, Ctx); PasExpr := TFpPascalExpression.Create(AExpression, Ctx);
try try
if not IsWatchValueAlive then exit; if not IsWatchValueAlive then exit;
@ -1591,6 +1617,7 @@ DebugLn(DBG_VERBOSE, [ErrorHandler.ErrorAsString(PasExpr.Error)]);
PasExpr.Free; PasExpr.Free;
FMemManager.DefaultContext := nil; FMemManager.DefaultContext := nil;
Ctx.ReleaseReference; Ctx.ReleaseReference;
UnLockUnLoadDwarf;
end; end;
end; end;