mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-09 04:41:44 +01:00
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:
parent
d8007187b8
commit
35d829c943
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user