DBG: Refactor Master/Slave class structure (locals)

git-svn-id: trunk@30721 -
This commit is contained in:
martin 2011-05-13 14:00:35 +00:00
parent 4f1223747b
commit 99624b9b9a
7 changed files with 481 additions and 350 deletions

View File

@ -217,7 +217,9 @@ type
TWatch = class; TWatch = class;
TWatchesMonitor = class; TWatchesMonitor = class;
TWatchesSupplier = class; TWatchesSupplier = class;
TIDELocals = class; TLocalsMonitor = class;
TLocalsSupplier = class;
TCurrentLocals = class;
TIDELineInfo = class; TIDELineInfo = class;
TCallStack = class; TCallStack = class;
TCallStackMonitor = class; TCallStackMonitor = class;
@ -1008,69 +1010,112 @@ type
****************************************************************************** ******************************************************************************
******************************************************************************} ******************************************************************************}
{ TBaseLocals } TLocalsNotification = class(TDebuggerChangeNotification)
public
property OnChange;
end;
TBaseLocals = class(TObject) { TLocals }
TLocals = class(TObject)
private private
function GetName(const AnIndex: Integer): String;
function GetValue(const AnIndex: Integer): String;
protected protected
function GetName(const AnIndex: Integer): String; virtual; FLocals: TStringList;
function GetValue(const AnIndex: Integer): String; virtual; FStackFrame: Integer;
FThreadId: Integer;
public public
constructor Create; constructor Create;
destructor Destroy; override;
function Count: Integer; virtual; function Count: Integer; virtual;
public public
property Names[const AnIndex: Integer]: String read GetName; property Names[const AnIndex: Integer]: String read GetName;
property Values[const AnIndex: Integer]: String read GetValue; property Values[const AnIndex: Integer]: String read GetValue;
property ThreadId: Integer read FThreadId;
property StackFrame: Integer read FStackFrame;
end; end;
{ TIDELocals } { TLocalsList }
{ TIDELocalsNotification } TLocalsList = class
TDBGLocals = class;
TIDELocalsNotification = class(TDebuggerNotification)
private private
FOnChange: TNotifyEvent; FList: TList;
public function GetEntry(const AThreadId: Integer; const AStackFrame: Integer): TLocals;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
TIDELocals = class(TBaseLocals)
private
FNotificationList: TList;
FMaster: TDBGLocals;
procedure LocalsChanged(Sender: TObject);
procedure SetMaster(const AMaster: TDBGLocals);
protected protected
procedure NotifyChange; function CreateEntry(const AThreadId: Integer; const AStackFrame: Integer): TLocals; virtual;
function GetName(const AnIndex: Integer): String; override; public
function GetValue(const AnIndex: Integer): String; override; //procedure Assign(AnOther: TWatchValueList);
constructor Create;
destructor Destroy; override;
procedure Clear;
property Entries[const AThreadId: Integer; const AStackFrame: Integer]: TLocals
read GetEntry; default;
end;
{ TCurrentLocals }
TCurrentLocals = class(TLocals)
private
FMonitor: TLocalsMonitor;
FDataValidity: TDebuggerDataState;
public
constructor Create(AMonitor: TLocalsMonitor; AThreadId, AStackFrame: Integer);
function Count: Integer; override;
procedure Clear;
procedure Add(const AName, AValue: String);
procedure SetDataValidity(AValidity: TDebuggerDataState);
end;
{ TCurrentLocalsList }
TCurrentLocalsList = class(TLocalsList)
private
FMonitor: TLocalsMonitor;
protected
function CreateEntry(const AThreadId: Integer; const AStackFrame: Integer): TLocals;
override;
public
constructor Create(AMonitor: TLocalsMonitor);
end;
{ TLocalsMonitor }
TLocalsMonitor = class(TDebuggerDataMonitor)
private
FCurrentLocalsList: TCurrentLocalsList;
FNotificationList: TDebuggerChangeNotificationList;
function GetSupplier: TLocalsSupplier;
procedure SetSupplier(const AValue: TLocalsSupplier);
protected
procedure NotifyChange(ALocals: TCurrentLocals);
procedure DoNewSupplier; override;
procedure RequestData(ALocals: TCurrentLocals);
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
procedure AddNotification(const ANotification: TIDELocalsNotification); procedure Clear;
procedure RemoveNotification(const ANotification: TIDELocalsNotification); procedure AddNotification(const ANotification: TLocalsNotification);
function Count: Integer; override; procedure RemoveNotification(const ANotification: TLocalsNotification);
property Master: TDBGLocals read FMaster write SetMaster; property CurrentLocalsList: TCurrentLocalsList read FCurrentLocalsList;
property Supplier: TLocalsSupplier read GetSupplier write SetSupplier;
end; end;
{ TDBGLocals } { TLocalsSupplier }
TDBGLocals = class(TBaseLocals) TLocalsSupplier = class(TDebuggerDataSupplier)
private private
FDebugger: TDebugger; // reference to our debugger function GetCurrentLocalsList: TCurrentLocalsList;
FOnChange: TNotifyEvent; function GetMonitor: TLocalsMonitor;
procedure SetMonitor(const AValue: TLocalsMonitor);
protected protected
procedure Changed; virtual; procedure RequestData(ALocals: TCurrentLocals); virtual;
procedure DoChange;
procedure DoStateChange(const AOldState: TDBGState); virtual;
function GetCount: Integer; virtual;
property Debugger: TDebugger read FDebugger;
public public
function Count: Integer; override; procedure DoStateChange(const AOldState: TDBGState); virtual;
constructor Create(const ADebugger: TDebugger); property CurrentLocalsList: TCurrentLocalsList read GetCurrentLocalsList;
property OnChange: TNotifyEvent read FOnChange write FOnChange; property Monitor: TLocalsMonitor read GetMonitor write SetMonitor;
end; end;
{%endregion ^^^^^ Locals ^^^^^ } {%endregion ^^^^^ Locals ^^^^^ }
@ -2068,7 +2113,7 @@ type
FExternalDebugger: String; FExternalDebugger: String;
//FExceptions: TDBGExceptions; //FExceptions: TDBGExceptions;
FFileName: String; FFileName: String;
FLocals: TDBGLocals; FLocals: TLocalsSupplier;
FLineInfo: TDBGLineInfo; FLineInfo: TDBGLineInfo;
FOnConsoleOutput: TDBGOutputEvent; FOnConsoleOutput: TDBGOutputEvent;
FOnFeedback: TDBGFeedbackEvent; FOnFeedback: TDBGFeedbackEvent;
@ -2098,7 +2143,7 @@ type
procedure SetFileName(const AValue: String); procedure SetFileName(const AValue: String);
protected protected
function CreateBreakPoints: TDBGBreakPoints; virtual; function CreateBreakPoints: TDBGBreakPoints; virtual;
function CreateLocals: TDBGLocals; virtual; function CreateLocals: TLocalsSupplier; virtual;
function CreateLineInfo: TDBGLineInfo; virtual; function CreateLineInfo: TDBGLineInfo; virtual;
function CreateRegisters: TDBGRegisters; virtual; function CreateRegisters: TDBGRegisters; virtual;
function CreateCallStack: TCallStackSupplier; virtual; function CreateCallStack: TCallStackSupplier; virtual;
@ -2177,7 +2222,7 @@ type
property ExitCode: Integer read FExitCode; property ExitCode: Integer read FExitCode;
property ExternalDebugger: String read FExternalDebugger; // The name of the debugger executable property ExternalDebugger: String read FExternalDebugger; // The name of the debugger executable
property FileName: String read FFileName write SetFileName; // The name of the exe to be debugged property FileName: String read FFileName write SetFileName; // The name of the exe to be debugged
property Locals: TDBGLocals read FLocals; // list of all localvars etc property Locals: TLocalsSupplier read FLocals; // list of all localvars etc
property LineInfo: TDBGLineInfo read FLineInfo; // list of all source LineInfo property LineInfo: TDBGLineInfo read FLineInfo; // list of all source LineInfo
property Registers: TDBGRegisters read FRegisters; // list of all registers property Registers: TDBGRegisters read FRegisters; // list of all registers
property Signals: TDBGSignals read FSignals; // A list of actions for signals we know property Signals: TDBGSignals read FSignals; // A list of actions for signals we know
@ -2331,6 +2376,168 @@ begin
Result:=bpaStop; Result:=bpaStop;
end; end;
{ TCurrentLocalsList }
function TCurrentLocalsList.CreateEntry(const AThreadId: Integer;
const AStackFrame: Integer): TLocals;
begin
Result := TCurrentLocals.Create(FMonitor, AThreadId, AStackFrame);
end;
constructor TCurrentLocalsList.Create(AMonitor: TLocalsMonitor);
begin
FMonitor := AMonitor;
inherited Create;
end;
{ TLocalsList }
function TLocalsList.GetEntry(const AThreadId: Integer; const AStackFrame: Integer): TLocals;
var
i: Integer;
begin
i := FList.Count - 1;
while i >= 0 do begin
Result := TLocals(FList[i]);
if (Result.ThreadId = AThreadId) and (Result.StackFrame = AStackFrame)
then exit;
dec(i);
end;
Result := CreateEntry(AThreadId, AStackFrame);
if Result = nil then exit;
FList.Add(Result);
end;
function TLocalsList.CreateEntry(const AThreadId: Integer;
const AStackFrame: Integer): TLocals;
begin
Result := nil;
end;
constructor TLocalsList.Create;
begin
FList := TList.Create;
inherited Create;
end;
destructor TLocalsList.Destroy;
begin
Clear;
inherited Destroy;
FList.Free;
end;
procedure TLocalsList.Clear;
begin
while FList.Count > 0 do begin
TObject(FList[0]).Free;
FList.Delete(0);
end;
end;
{ TLocalsSupplier }
function TLocalsSupplier.GetCurrentLocalsList: TCurrentLocalsList;
begin
if Monitor <> nil
then Result := Monitor.CurrentLocalsList
else Result := nil;
end;
function TLocalsSupplier.GetMonitor: TLocalsMonitor;
begin
Result := TLocalsMonitor(inherited Monitor);
end;
procedure TLocalsSupplier.SetMonitor(const AValue: TLocalsMonitor);
begin
inherited Monitor := AValue;
end;
procedure TLocalsSupplier.RequestData(ALocals: TCurrentLocals);
begin
ALocals.SetDataValidity(ddsInvalid)
end;
procedure TLocalsSupplier.DoStateChange(const AOldState: TDBGState);
begin
if FDebugger.State = dsPause
then begin
if Monitor<> nil
then Monitor.Clear;
end
else begin
if (AOldState = dsPause) or (AOldState = dsNone) { Force clear on initialisation }
then begin
if Monitor<> nil
then Monitor.Clear;
end;
end;
end;
{ TLocalsMonitor }
function TLocalsMonitor.GetSupplier: TLocalsSupplier;
begin
Result := TLocalsSupplier(inherited Supplier);
end;
procedure TLocalsMonitor.SetSupplier(const AValue: TLocalsSupplier);
begin
inherited Supplier := AValue;
end;
procedure TLocalsMonitor.NotifyChange(ALocals: TCurrentLocals);
begin
FNotificationList.NotifyChange(ALocals);
end;
procedure TLocalsMonitor.DoNewSupplier;
begin
inherited DoNewSupplier;
NotifyChange(nil);
end;
procedure TLocalsMonitor.RequestData(ALocals: TCurrentLocals);
begin
if Supplier <> nil
then Supplier.RequestData(ALocals)
else ALocals.SetDataValidity(ddsInvalid);
end;
constructor TLocalsMonitor.Create;
begin
inherited;
FNotificationList := TDebuggerChangeNotificationList.Create;
FCurrentLocalsList := TCurrentLocalsList.Create(Self);
end;
destructor TLocalsMonitor.Destroy;
begin
FNotificationList.Clear;
inherited Destroy;
FreeAndNil(FCurrentLocalsList);
FreeAndNil(FNotificationList);
end;
procedure TLocalsMonitor.Clear;
begin
FCurrentLocalsList.Clear;
NotifyChange(nil);
end;
procedure TLocalsMonitor.AddNotification(const ANotification: TLocalsNotification);
begin
FNotificationList.Add(ANotification);
end;
procedure TLocalsMonitor.RemoveNotification(const ANotification: TLocalsNotification);
begin
FNotificationList.Remove(ANotification);
end;
{ TCurrentWatchValue }
procedure TCurrentWatchValue.SetTypeInfo(const AValue: TDBGType); procedure TCurrentWatchValue.SetTypeInfo(const AValue: TDBGType);
begin begin
if FTypeInfo<> nil then if FTypeInfo<> nil then
@ -2379,6 +2586,7 @@ begin
dec(i); dec(i);
end; end;
Result := CreateEntry(AThreadId, AStackFrame, ADisplayFormat); Result := CreateEntry(AThreadId, AStackFrame, ADisplayFormat);
if Result = nil then exit;
FList.Add(Result); FList.Add(Result);
Result.RequestData; Result.RequestData;
end; end;
@ -3320,9 +3528,9 @@ begin
Result := TDBGExceptions.Create(Self, TDBGException); Result := TDBGExceptions.Create(Self, TDBGException);
end; end;
function TDebugger.CreateLocals: TDBGLocals; function TDebugger.CreateLocals: TLocalsSupplier;
begin begin
Result := TDBGLocals.Create(Self); Result := TLocalsSupplier.Create(Self);
end; end;
function TDebugger.CreateLineInfo: TDBGLineInfo; function TDebugger.CreateLineInfo: TDBGLineInfo;
@ -5529,162 +5737,80 @@ end;
(******************************************************************************) (******************************************************************************)
{ =========================================================================== } { =========================================================================== }
{ TBaseLocals } { TLocals }
{ =========================================================================== } { =========================================================================== }
function TBaseLocals.Count: Integer; function TLocals.Count: Integer;
begin begin
Result := 0; Result := FLocals.Count;
end; end;
constructor TBaseLocals.Create; constructor TLocals.Create;
begin begin
FLocals := TStringList.Create;
inherited Create; inherited Create;
end; end;
function TBaseLocals.GetName(const AnIndex: Integer): String; destructor TLocals.Destroy;
begin begin
Result := ''; inherited Destroy;
FreeAndNil(FLocals);
end; end;
function TBaseLocals.GetValue(const AnIndex: Integer): String; function TLocals.GetName(const AnIndex: Integer): String;
begin begin
Result := ''; Result := FLocals.Names[AnIndex];
end;
function TLocals.GetValue(const AnIndex: Integer): String;
begin
Result := FLocals[AnIndex];
Result := GetPart('=', '', Result);
end; end;
{ =========================================================================== } { =========================================================================== }
{ TIDELocals } { TCurrentLocals }
{ =========================================================================== } { =========================================================================== }
procedure TIDELocals.AddNotification(const ANotification: TIDELocalsNotification); constructor TCurrentLocals.Create(AMonitor: TLocalsMonitor; AThreadId, AStackFrame: Integer);
begin begin
FNotificationList.Add(ANotification); FMonitor := AMonitor;
ANotification.AddReference; FDataValidity := ddsUnknown;
end; FThreadId := AThreadId;
FStackFrame := AStackFrame;
constructor TIDELocals.Create;
begin
FNotificationList := TList.Create;
inherited Create; inherited Create;
end; end;
destructor TIDELocals.Destroy; function TCurrentLocals.Count: Integer;
var
n: Integer;
begin begin
for n := FNotificationList.Count - 1 downto 0 do case FDataValidity of
TDebuggerNotification(FNotificationList[n]).ReleaseReference; ddsUnknown: begin
Result := 0;
inherited; FDataValidity := ddsRequested;
FMonitor.RequestData(Self);
FreeAndNil(FNotificationList); if FDataValidity = ddsValid then Result := inherited Count;
end; end;
ddsRequested, ddsEvaluating: Result := 0;
procedure TIDELocals.LocalsChanged(Sender: TObject); ddsValid: Result := inherited Count;
begin ddsInvalid, ddsError: Result := 0;
NotifyChange;
end;
procedure TIDELocals.SetMaster(const AMaster: TDBGLocals);
var
DoNotify: Boolean;
begin
if FMaster = AMaster then Exit;
if FMaster <> nil
then begin
FMaster.OnChange := nil;
DoNotify := FMaster.Count <> 0;
end
else DoNotify := False;
FMaster := AMaster;
if FMaster <> nil
then begin
FMaster.OnChange := @LocalsChanged;
DoNotify := DoNotify or (FMaster.Count <> 0);
end;
if DoNotify
then NotifyChange;
end;
procedure TIDELocals.NotifyChange;
var
n: Integer;
Notification: TIDELocalsNotification;
begin
for n := 0 to FNotificationList.Count - 1 do
begin
Notification := TIDELocalsNotification(FNotificationList[n]);
if Assigned(Notification.FOnChange)
then Notification.FOnChange(Self);
end; end;
end; end;
function TIDELocals.GetName(const AnIndex: Integer): String; procedure TCurrentLocals.Clear;
begin begin
if Master = nil FLocals.Clear;
then Result := inherited GetName(AnIndex)
else Result := Master.Names[AnIndex];
end; end;
function TIDELocals.GetValue(const AnIndex: Integer): String; procedure TCurrentLocals.Add(const AName, AValue: String);
begin begin
if Master = nil FLocals.Add(AName + '=' + AValue);
then Result := inherited GetValue(AnIndex)
else Result := Master.Values[AnIndex];
end; end;
procedure TIDELocals.RemoveNotification(const ANotification: TIDELocalsNotification); procedure TCurrentLocals.SetDataValidity(AValidity: TDebuggerDataState);
begin begin
FNotificationList.Remove(ANotification); if FDataValidity = AValidity then exit;
ANotification.ReleaseReference; FDataValidity := AValidity;
end; FMonitor.NotifyChange(Self);
function TIDELocals.Count: Integer;
begin
if Master = nil
then Result := 0
else Result := Master.Count;
end;
{ =========================================================================== }
{ TDBGLocals }
{ =========================================================================== }
function TDBGLocals.Count: Integer;
begin
if (FDebugger <> nil)
and (FDebugger.State = dsPause)
then Result := GetCount
else Result := 0;
end;
constructor TDBGLocals.Create(const ADebugger: TDebugger);
begin
inherited Create;
FDebugger := ADebugger;
end;
procedure TDBGLocals.DoChange;
begin
if Assigned(FOnChange) then FOnChange(Self);
end;
procedure TDBGLocals.DoStateChange(const AOldState: TDBGState);
begin
end;
procedure TDBGLocals.Changed;
begin
DoChange;
end;
function TDBGLocals.GetCount: Integer;
begin
Result := 0;
end; end;
(******************************************************************************) (******************************************************************************)

View File

@ -373,7 +373,7 @@ type
function ChangeFileName: Boolean; override; function ChangeFileName: Boolean; override;
function CreateBreakPoints: TDBGBreakPoints; override; function CreateBreakPoints: TDBGBreakPoints; override;
function CreateLocals: TDBGLocals; override; function CreateLocals: TLocalsSupplier; override;
function CreateLineInfo: TDBGLineInfo; override; function CreateLineInfo: TDBGLineInfo; override;
function CreateRegisters: TDBGRegisters; override; function CreateRegisters: TDBGRegisters; override;
function CreateCallStack: TCallStackSupplier; override; function CreateCallStack: TCallStackSupplier; override;
@ -388,7 +388,6 @@ type
procedure ClearCommandQueue; procedure ClearCommandQueue;
procedure DoState(const OldState: TDBGState); override; procedure DoState(const OldState: TDBGState); override;
procedure DoThreadChanged; procedure DoThreadChanged;
procedure DoCallStackChanged;
property TargetPID: Integer read FTargetInfo.TargetPID; property TargetPID: Integer read FTargetInfo.TargetPID;
property TargetPtrSize: Byte read FTargetInfo.TargetPtrSize; property TargetPtrSize: Byte read FTargetInfo.TargetPtrSize;
property TargetFlags: TGDBMITargetFlags read FTargetInfo.TargetFlags write FTargetInfo.TargetFlags; property TargetFlags: TGDBMITargetFlags read FTargetInfo.TargetFlags write FTargetInfo.TargetFlags;
@ -580,36 +579,26 @@ type
TGDBMIDebuggerCommandLocals = class(TGDBMIDebuggerCommand) TGDBMIDebuggerCommandLocals = class(TGDBMIDebuggerCommand)
private private
FResult: TStringList; FLocals: TCurrentLocals;
protected protected
function DoExecute: Boolean; override; function DoExecute: Boolean; override;
public public
constructor Create(AOwner: TGDBMIDebugger); constructor Create(AOwner: TGDBMIDebugger; ALocals: TCurrentLocals);
destructor Destroy; override;
function DebugText: String; override; function DebugText: String; override;
property Result: TStringList read FResult;
end; end;
{ TGDBMILocals } { TGDBMILocals }
TGDBMILocals = class(TDBGLocals) TGDBMILocals = class(TLocalsSupplier)
private private
FEvaluatedState: TGDBMIEvaluationState; FCommandList: TList;
FEvaluationCmdObj: TGDBMIDebuggerCommandLocals; procedure CancelEvaluation; deprecated;
FInLocalsNeeded: Boolean;
FLocals: TStringList;
procedure LocalsNeeded;
procedure CancelEvaluation;
procedure DoEvaluationDestroyed(Sender: TObject); procedure DoEvaluationDestroyed(Sender: TObject);
procedure DoEvaluationFinished(Sender: TObject);
protected protected
procedure DoStateChange(const AOldState: TDBGState); override; procedure CancelAllCommands;
procedure Invalidate; procedure RequestData(ALocals: TCurrentLocals); override;
function GetCount: Integer; override;
function GetName(const AnIndex: Integer): String; override;
function GetValue(const AnIndex: Integer): String; override;
public public
procedure Changed; override; procedure Changed;
constructor Create(const ADebugger: TDebugger); constructor Create(const ADebugger: TDebugger);
destructor Destroy; override; destructor Destroy; override;
end; end;
@ -1160,7 +1149,7 @@ type
{%endregion ^^^^^ Disassembler ^^^^^ } {%endregion ^^^^^ Disassembler ^^^^^ }
{%region ***** Register ***** } {%region ***** Threads ***** }
{ TGDBMIDebuggerCommandThreads } { TGDBMIDebuggerCommandThreads }
@ -1221,7 +1210,7 @@ type
procedure DoStateChange(const AOldState: TDBGState); override; procedure DoStateChange(const AOldState: TDBGState); override;
end; end;
{%endregion ^^^^^ Register ^^^^^ } {%endregion ^^^^^ Threads ^^^^^ }
{%region ***** TGDBMIExpression ***** } {%region ***** TGDBMIExpression ***** }
@ -5271,7 +5260,7 @@ begin
Result := TGDBMIDisassembler.Create(Self); Result := TGDBMIDisassembler.Create(Self);
end; end;
function TGDBMIDebugger.CreateLocals: TDBGLocals; function TGDBMIDebugger.CreateLocals: TLocalsSupplier;
begin begin
Result := TGDBMILocals.Create(Self); Result := TGDBMILocals.Create(Self);
end; end;
@ -5397,15 +5386,9 @@ end;
procedure TGDBMIDebugger.DoThreadChanged; procedure TGDBMIDebugger.DoThreadChanged;
begin begin
TGDBMICallstack(CallStack).DoThreadChanged; TGDBMICallstack(CallStack).DoThreadChanged;
TGDBMILocals(Locals).Changed;
TGDBMIRegisters(Registers).Changed; TGDBMIRegisters(Registers).Changed;
end; end;
procedure TGDBMIDebugger.DoCallStackChanged;
begin
TGDBMILocals(Locals).Changed;
end;
procedure TGDBMIDebugger.DoRelease; procedure TGDBMIDebugger.DoRelease;
begin begin
SetState(dsDestroying); SetState(dsDestroying);
@ -7197,7 +7180,7 @@ function TGDBMIDebuggerCommandLocals.DoExecute: Boolean;
else Value := '''' + GetText(addr) + ''''; else Value := '''' + GetText(addr) + '''';
end; end;
FResult.Add(Name + '=' + Value); FLocals.Add(Name, Value);
end; end;
FreeAndNil(List); FreeAndNil(List);
FreeAndNil(LocList); FreeAndNil(LocList);
@ -7208,6 +7191,7 @@ var
List: TGDBMINameValueList; List: TGDBMINameValueList;
begin begin
Result := True; Result := True;
FLocals.Clear;
// args // args
ExecuteCommand('-stack-list-arguments 1 %0:d %0:d', ExecuteCommand('-stack-list-arguments 1 %0:d %0:d',
[FTheDebugger.FCurrentStackFrame], R); [FTheDebugger.FCurrentStackFrame], R);
@ -7226,18 +7210,13 @@ begin
AddLocals(List.Values['locals']); AddLocals(List.Values['locals']);
FreeAndNil(List); FreeAndNil(List);
end; end;
FLocals.SetDataValidity(ddsValid);
end; end;
constructor TGDBMIDebuggerCommandLocals.Create(AOwner: TGDBMIDebugger); constructor TGDBMIDebuggerCommandLocals.Create(AOwner: TGDBMIDebugger; ALocals: TCurrentLocals);
begin begin
inherited Create(AOwner); inherited Create(AOwner);
FResult := TStringList.Create; FLocals := ALocals;
end;
destructor TGDBMIDebuggerCommandLocals.Destroy;
begin
inherited Destroy;
FreeAndNil(FResult);
end; end;
function TGDBMIDebuggerCommandLocals.DebugText: String; function TGDBMIDebuggerCommandLocals.DebugText: String;
@ -7251,134 +7230,62 @@ end;
procedure TGDBMILocals.Changed; procedure TGDBMILocals.Changed;
begin begin
Invalidate; if Monitor <> nil
inherited Changed; then Monitor.Clear;
end; end;
constructor TGDBMILocals.Create(const ADebugger: TDebugger); constructor TGDBMILocals.Create(const ADebugger: TDebugger);
begin begin
FLocals := TStringList.Create; FCommandList := TList.Create;
FLocals.Sorted := True;
FEvaluatedState := esInvalid;
FEvaluationCmdObj := nil;
inherited; inherited;
end; end;
destructor TGDBMILocals.Destroy; destructor TGDBMILocals.Destroy;
begin begin
CancelEvaluation; CancelAllCommands;
inherited; inherited;
FreeAndNil(FLocals); FreeAndNil(FCommandList);
end; end;
procedure TGDBMILocals.DoStateChange(const AOldState: TDBGState); procedure TGDBMILocals.CancelAllCommands;
var
i: Integer;
begin begin
if (Debugger <> nil) for i := 0 to FCommandList.Count-1 do
and (Debugger.State = dsPause) with TGDBMIDebuggerCommandStack(FCommandList[i]) do begin
then begin OnExecuted := nil;
DoChange; OnDestroy := nil;
end Cancel;
else begin end;
Invalidate; FCommandList.Clear;
end;
end; end;
procedure TGDBMILocals.Invalidate; procedure TGDBMILocals.RequestData(ALocals: TCurrentLocals);
var
ForceQueue: Boolean;
EvaluationCmdObj: TGDBMIDebuggerCommandLocals;
begin begin
FEvaluatedState := esInvalid; if (Debugger = nil) or (Debugger.State <> dsPause) then Exit;
CancelEvaluation;
FLocals.Clear;
end;
function TGDBMILocals.GetCount: Integer; EvaluationCmdObj := TGDBMIDebuggerCommandLocals.Create(TGDBMIDebugger(Debugger), ALocals);
begin EvaluationCmdObj.OnDestroy := @DoEvaluationDestroyed;
if (Debugger <> nil) EvaluationCmdObj.Priority := GDCMD_PRIOR_LOCALS;
and (Debugger.State = dsPause) EvaluationCmdObj.Properties := [dcpCancelOnRun];
then begin ForceQueue := (TGDBMIDebugger(Debugger).FCurrentCommand <> nil)
LocalsNeeded; and (TGDBMIDebugger(Debugger).FCurrentCommand is TGDBMIDebuggerCommandExecute)
if FEvaluatedState = esValid and (not TGDBMIDebuggerCommandExecute(TGDBMIDebugger(Debugger).FCurrentCommand).NextExecQueued);
then Result := FLocals.Count FCommandList.add(EvaluationCmdObj);
else Result := 0; TGDBMIDebugger(Debugger).QueueCommand(EvaluationCmdObj, ForceQueue);
end (* DoEvaluationFinished may be called immediately at this point *)
else Result := 0;
end;
function TGDBMILocals.GetName(const AnIndex: Integer): String;
begin
if (Debugger <> nil)
and (Debugger.State = dsPause)
then begin
LocalsNeeded;
Result := FLocals.Names[AnIndex];
end
else Result := '';
end;
function TGDBMILocals.GetValue(const AnIndex: Integer): String;
begin
if (Debugger <> nil)
and (Debugger.State = dsPause)
then begin
LocalsNeeded;
Result := FLocals[AnIndex];
Result := GetPart('=', '', Result);
end
else Result := '';
end; end;
procedure TGDBMILocals.DoEvaluationDestroyed(Sender: TObject); procedure TGDBMILocals.DoEvaluationDestroyed(Sender: TObject);
begin begin
if FEvaluationCmdObj = Sender FCommandList.Remove(Sender);
then FEvaluationCmdObj := nil;
end;
procedure TGDBMILocals.DoEvaluationFinished(Sender: TObject);
var
Cmd: TGDBMIDebuggerCommandLocals;
begin
FLocals.Clear;
FEvaluatedState := esValid;
FEvaluationCmdObj := nil;
Cmd := TGDBMIDebuggerCommandLocals(Sender);
FLocals.Assign(Cmd.Result);
// Do not recursively call, whoever is requesting the locals
if not FInLocalsNeeded
then inherited Changed;
end;
procedure TGDBMILocals.LocalsNeeded;
var
ForceQueue: Boolean;
begin
if Debugger = nil then Exit;
if FEvaluatedState in [esRequested, esValid] then Exit;
FLocals.Clear;
FInLocalsNeeded := True;
FEvaluatedState := esRequested;
FEvaluationCmdObj := TGDBMIDebuggerCommandLocals.Create(TGDBMIDebugger(Debugger));
FEvaluationCmdObj.OnExecuted := @DoEvaluationFinished;
FEvaluationCmdObj.OnDestroy := @DoEvaluationDestroyed;
FEvaluationCmdObj.Priority := GDCMD_PRIOR_LOCALS;
FEvaluationCmdObj.Properties := [dcpCancelOnRun];
ForceQueue := (TGDBMIDebugger(Debugger).FCurrentCommand <> nil)
and (TGDBMIDebugger(Debugger).FCurrentCommand is TGDBMIDebuggerCommandExecute)
and (not TGDBMIDebuggerCommandExecute(TGDBMIDebugger(Debugger).FCurrentCommand).NextExecQueued);
TGDBMIDebugger(Debugger).QueueCommand(FEvaluationCmdObj, ForceQueue);
(* DoEvaluationFinished may be called immediately at this point *)
FInLocalsNeeded := False;
end; end;
procedure TGDBMILocals.CancelEvaluation; procedure TGDBMILocals.CancelEvaluation;
begin begin
FEvaluatedState := esInvalid;
if FEvaluationCmdObj <> nil
then begin
FEvaluationCmdObj.OnExecuted := nil;;
FEvaluationCmdObj.OnDestroy := nil;;
FEvaluationCmdObj.Cancel;
end;
FEvaluationCmdObj := nil;
end; end;
{%endregion ^^^^^ BreakPoints ^^^^^ } {%endregion ^^^^^ BreakPoints ^^^^^ }
@ -7839,7 +7746,6 @@ end;
procedure TGDBMICallStack.DoSetIndexCommandExecuted(Sender: TObject); procedure TGDBMICallStack.DoSetIndexCommandExecuted(Sender: TObject);
begin begin
TGDBMIDebugger(Debugger).FCurrentStackFrame := TGDBMIDebuggerCommandStackSetCurrent(Sender).NewCurrent; TGDBMIDebugger(Debugger).FCurrentStackFrame := TGDBMIDebuggerCommandStackSetCurrent(Sender).NewCurrent;
TGDBMIDebugger(Debugger).DoCallStackChanged;
TGDBMIDebuggerCommandStackSetCurrent(Sender).Callstack.CurrentIndex := TGDBMIDebuggerCommandStackSetCurrent(Sender).NewCurrent; TGDBMIDebuggerCommandStackSetCurrent(Sender).Callstack.CurrentIndex := TGDBMIDebuggerCommandStackSetCurrent(Sender).NewCurrent;
end; end;

View File

@ -40,13 +40,25 @@ uses
ComCtrls, Debugger, DebuggerDlg; ComCtrls, Debugger, DebuggerDlg;
type type
{ TLocalsDlg }
TLocalsDlg = class(TDebuggerDlg) TLocalsDlg = class(TDebuggerDlg)
lvLocals: TListView; lvLocals: TListView;
private private
FLocals: TIDELocals; FCallStackMonitor: TCallStackMonitor;
FLocalsNotification: TIDELocalsNotification; FLocalsMonitor: TLocalsMonitor;
FLocalsNotification: TLocalsNotification;
FThreadsMonitor: TThreadsMonitor;
FThreadsNotification: TThreadsNotification;
FCallstackNotification: TCallStackNotification;
procedure ContextChanged(Sender: TObject);
procedure LocalsChanged(Sender: TObject); procedure LocalsChanged(Sender: TObject);
procedure SetLocals(const AValue: TIDELocals); procedure SetCallStackMonitor(const AValue: TCallStackMonitor);
procedure SetLocals(const AValue: TLocalsMonitor);
procedure SetThreadsMonitor(const AValue: TThreadsMonitor);
function GetThreadId: Integer;
function GetStackframe: Integer;
protected protected
procedure DoBeginUpdate; override; procedure DoBeginUpdate; override;
procedure DoEndUpdate; override; procedure DoEndUpdate; override;
@ -54,7 +66,9 @@ type
constructor Create(AOwner: TComponent); override; constructor Create(AOwner: TComponent); override;
destructor Destroy; override; destructor Destroy; override;
property Locals: TIDELocals read FLocals write SetLocals; property LocalsMonitor: TLocalsMonitor read FLocalsMonitor write SetLocals;
property ThreadsMonitor: TThreadsMonitor read FThreadsMonitor write SetThreadsMonitor;
property CallStackMonitor: TCallStackMonitor read FCallStackMonitor write SetCallStackMonitor;
end; end;
@ -70,9 +84,18 @@ uses
constructor TLocalsDlg.Create(AOwner: TComponent); constructor TLocalsDlg.Create(AOwner: TComponent);
begin begin
inherited Create(AOwner); inherited Create(AOwner);
FLocalsNotification := TIDELocalsNotification.Create; FLocalsNotification := TLocalsNotification.Create;
FLocalsNotification.AddReference; FLocalsNotification.AddReference;
FLocalsNotification.OnChange := @LocalsChanged; FLocalsNotification.OnChange := @LocalsChanged;
FThreadsNotification := TThreadsNotification.Create;
FThreadsNotification.AddReference;
FThreadsNotification.OnCurrent := @ContextChanged;
FCallstackNotification := TCallStackNotification.Create;
FCallstackNotification.AddReference;
FCallstackNotification.OnCurrent := @ContextChanged;
Caption:= lisLocals; Caption:= lisLocals;
lvLocals.Columns[0].Caption:= lisLocalsDlgName; lvLocals.Columns[0].Caption:= lisLocalsDlgName;
lvLocals.Columns[1].Caption:= lisLocalsDlgValue; lvLocals.Columns[1].Caption:= lisLocalsDlgValue;
@ -83,26 +106,48 @@ begin
SetLocals(nil); SetLocals(nil);
FLocalsNotification.OnChange := nil; FLocalsNotification.OnChange := nil;
FLocalsNotification.ReleaseReference; FLocalsNotification.ReleaseReference;
FThreadsNotification.OnCurrent := nil;
FThreadsNotification.ReleaseReference;
FCallstackNotification.OnCurrent := nil;
FCallstackNotification.ReleaseReference;
inherited Destroy; inherited Destroy;
end; end;
procedure TLocalsDlg.ContextChanged(Sender: TObject);
begin
LocalsChanged(nil);
end;
procedure TLocalsDlg.LocalsChanged(Sender: TObject); procedure TLocalsDlg.LocalsChanged(Sender: TObject);
var var
n, idx: Integer; n, idx: Integer;
List: TStringList; List: TStringList;
Item: TListItem; Item: TListItem;
S: String; S: String;
Locals: TLocals;
begin begin
if (FThreadsMonitor = nil) or (FCallStackMonitor = nil) then begin
lvLocals.Items.Clear;
exit;
end;
if GetStackframe < 0 then begin // TODO need dedicated validity property
lvLocals.Items.Clear;
exit;
end;
List := TStringList.Create; List := TStringList.Create;
try try
BeginUpdate; BeginUpdate;
try try
if FLocals = nil if FLocalsMonitor <> nil
then Locals := LocalsMonitor.CurrentLocalsList[GetThreadId, GetStackframe]
else Locals := nil;
if Locals = nil
then begin then begin
lvLocals.Items.Clear; lvLocals.Items.Clear;
Exit; Exit;
end; end;
//Get existing items //Get existing items
for n := 0 to lvLocals.Items.Count - 1 do for n := 0 to lvLocals.Items.Count - 1 do
begin begin
@ -113,20 +158,20 @@ begin
end; end;
// add/update entries // add/update entries
for n := 0 to FLocals.Count - 1 do for n := 0 to Locals.Count - 1 do
begin begin
idx := List.IndexOf(Uppercase(FLocals.Names[n])); idx := List.IndexOf(Uppercase(Locals.Names[n]));
if idx = -1 if idx = -1
then begin then begin
// New entry // New entry
Item := lvLocals.Items.Add; Item := lvLocals.Items.Add;
Item.Caption := FLocals.Names[n]; Item.Caption := Locals.Names[n];
Item.SubItems.Add(FLocals.Values[n]); Item.SubItems.Add(Locals.Values[n]);
end end
else begin else begin
// Existing entry // Existing entry
Item := TListItem(List.Objects[idx]); Item := TListItem(List.Objects[idx]);
Item.SubItems[0] := FLocals.Values[n]; Item.SubItems[0] := Locals.Values[n];
List.Delete(idx); List.Delete(idx);
end; end;
end; end;
@ -143,30 +188,82 @@ begin
end; end;
end; end;
procedure TLocalsDlg.SetLocals(const AValue: TIDELocals); procedure TLocalsDlg.SetCallStackMonitor(const AValue: TCallStackMonitor);
begin begin
if FLocals = AValue then Exit; if FCallStackMonitor = AValue then exit;
BeginUpdate; BeginUpdate;
try try
if FLocals <> nil if FCallStackMonitor <> nil
then begin then FCallStackMonitor.RemoveNotification(FCallstackNotification);
FLocals.RemoveNotification(FLocalsNotification);
end;
FLocals := AValue; FCallStackMonitor := AValue;
if FLocals <> nil if FCallStackMonitor <> nil
then begin then FCallStackMonitor.AddNotification(FCallstackNotification);
FLocals.AddNotification(FLocalsNotification);
end; LocalsChanged(nil);
LocalsChanged(FLocals);
finally finally
EndUpdate; EndUpdate;
end; end;
end; end;
procedure TLocalsDlg.SetLocals(const AValue: TLocalsMonitor);
begin
if FLocalsMonitor = AValue then Exit;
BeginUpdate;
try
if FLocalsMonitor <> nil
then begin
FLocalsMonitor.RemoveNotification(FLocalsNotification);
end;
FLocalsMonitor := AValue;
if FLocalsMonitor <> nil
then begin
FLocalsMonitor.AddNotification(FLocalsNotification);
end;
LocalsChanged(FLocalsMonitor);
finally
EndUpdate;
end;
end;
procedure TLocalsDlg.SetThreadsMonitor(const AValue: TThreadsMonitor);
begin
if FThreadsMonitor = AValue then exit;
BeginUpdate;
try
if FThreadsMonitor <> nil
then FThreadsMonitor.RemoveNotification(FThreadsNotification);
FThreadsMonitor := AValue;
if FThreadsMonitor <> nil
then FThreadsMonitor.AddNotification(FThreadsNotification);
LocalsChanged(nil);
finally
EndUpdate;
end;
end;
function TLocalsDlg.GetThreadId: Integer;
begin
Result := -1;
if (FThreadsMonitor = nil) then exit;
Result := FThreadsMonitor.CurrentThreads.CurrentThreadId;
end;
function TLocalsDlg.GetStackframe: Integer;
begin
Result := -1;
if (FCallStackMonitor = nil) then exit;
Result := FCallStackMonitor.CurrentCallStackList.EntriesForThreads[GetThreadId].CurrentIndex;
end;
procedure TLocalsDlg.DoBeginUpdate; procedure TLocalsDlg.DoBeginUpdate;
begin begin
lvLocals.BeginUpdate; lvLocals.BeginUpdate;

View File

@ -177,7 +177,7 @@ type
FSignals: TIDESignals; FSignals: TIDESignals;
//FBreakPoints: TIDEBreakPoints; //FBreakPoints: TIDEBreakPoints;
//FBreakPointGroups: TIDEBreakPointGroups; //FBreakPointGroups: TIDEBreakPointGroups;
FLocals: TIDELocals; FLocals: TLocalsMonitor;
FLineInfo: TIDELineInfo; FLineInfo: TIDELineInfo;
FWatches: TWatchesMonitor; FWatches: TWatchesMonitor;
FThreads: TThreadsMonitor; FThreads: TThreadsMonitor;
@ -223,7 +223,7 @@ type
property Exceptions: TIDEExceptions read FExceptions; // A list of exceptions we should ignore property Exceptions: TIDEExceptions read FExceptions; // A list of exceptions we should ignore
property CallStack: TCallStackMonitor read FCallStack; property CallStack: TCallStackMonitor read FCallStack;
property Disassembler: TIDEDisassembler read FDisassembler; property Disassembler: TIDEDisassembler read FDisassembler;
property Locals: TIDELocals read FLocals; property Locals: TLocalsMonitor read FLocals;
property LineInfo: TIDELineInfo read FLineInfo; property LineInfo: TIDELineInfo read FLineInfo;
property Registers: TIDERegisters read FRegisters; property Registers: TIDERegisters read FRegisters;
property Signals: TIDESignals read FSignals; // A list of actions for signals we know of property Signals: TIDESignals read FSignals; // A list of actions for signals we know of
@ -377,7 +377,7 @@ begin
FThreads := TThreadsMonitor.Create; FThreads := TThreadsMonitor.Create;
FExceptions := TIDEExceptions.Create; FExceptions := TIDEExceptions.Create;
FSignals := TIDESignals.Create; FSignals := TIDESignals.Create;
FLocals := TIDELocals.Create; FLocals := TLocalsMonitor.Create;
FLineInfo := TIDELineInfo.Create; FLineInfo := TIDELineInfo.Create;
FCallStack := TCallStackMonitor.Create; FCallStack := TCallStackMonitor.Create;
FDisassembler := TIDEDisassembler.Create; FDisassembler := TIDEDisassembler.Create;
@ -388,7 +388,7 @@ begin
//TManagedBreakpoints(FBreakpoints).Master := FDebugger.BreakPoints; //TManagedBreakpoints(FBreakpoints).Master := FDebugger.BreakPoints;
FWatches.Supplier := Result.Watches; FWatches.Supplier := Result.Watches;
FThreads.Supplier := Result.Threads; FThreads.Supplier := Result.Threads;
FLocals.Master := Result.Locals; FLocals.Supplier := Result.Locals;
FLineInfo.Master := Result.LineInfo; FLineInfo.Master := Result.LineInfo;
FCallStack.Supplier := Result.CallStack; FCallStack.Supplier := Result.CallStack;
FDisassembler.Master := Result.Disassembler; FDisassembler.Master := Result.Disassembler;
@ -412,7 +412,7 @@ begin
//TManagedBreakpoints(FBreakpoints).Master := nil; //TManagedBreakpoints(FBreakpoints).Master := nil;
FWatches.Supplier := nil; FWatches.Supplier := nil;
FThreads.Supplier := nil; FThreads.Supplier := nil;
FLocals.Master := nil; FLocals.Supplier := nil;
FLineInfo.Master := nil; FLineInfo.Master := nil;
FCallStack.Supplier := nil; FCallStack.Supplier := nil;
FDisassembler.Master := nil; FDisassembler.Master := nil;

View File

@ -47,7 +47,7 @@ type
FSignals: TIDESignals; FSignals: TIDESignals;
//FBreakPoints: TIDEBreakPoints; //FBreakPoints: TIDEBreakPoints;
//FBreakPointGroups: TIDEBreakPointGroups; //FBreakPointGroups: TIDEBreakPointGroups;
FLocals: TIDELocals; FLocals: TLocalsMonitor;
FLineInfo: TIDELineInfo; FLineInfo: TIDELineInfo;
FWatches: TWatchesMonitor; FWatches: TWatchesMonitor;
FThreads: TThreadsMonitor; FThreads: TThreadsMonitor;
@ -339,7 +339,7 @@ var
FThreads := TThreadsMonitor.Create; FThreads := TThreadsMonitor.Create;
FExceptions := TIDEExceptions.Create; FExceptions := TIDEExceptions.Create;
FSignals := TIDESignals.Create; FSignals := TIDESignals.Create;
FLocals := TIDELocals.Create; FLocals := TLocalsMonitor.Create;
FLineInfo := TIDELineInfo.Create; FLineInfo := TIDELineInfo.Create;
FCallStack := TCallStackMonitor.Create; FCallStack := TCallStackMonitor.Create;
FRegisters := TIDERegisters.Create; FRegisters := TIDERegisters.Create;
@ -347,7 +347,7 @@ var
//TManagedBreakpoints(FBreakpoints).Master := FDebugger.BreakPoints; //TManagedBreakpoints(FBreakpoints).Master := FDebugger.BreakPoints;
FWatches.Supplier := Gdb.Watches; FWatches.Supplier := Gdb.Watches;
FThreads.Supplier := Gdb.Threads; FThreads.Supplier := Gdb.Threads;
FLocals.Master := Gdb.Locals; FLocals.Supplier := Gdb.Locals;
FLineInfo.Master := Gdb.LineInfo; FLineInfo.Master := Gdb.LineInfo;
FCallStack.Supplier := Gdb.CallStack; FCallStack.Supplier := Gdb.CallStack;
FExceptions.Master := Gdb.Exceptions; FExceptions.Master := Gdb.Exceptions;

View File

@ -89,7 +89,7 @@ type
FSignals: TIDESignals; FSignals: TIDESignals;
FBreakPoints: TIDEBreakPoints; FBreakPoints: TIDEBreakPoints;
FBreakPointGroups: TIDEBreakPointGroups; FBreakPointGroups: TIDEBreakPointGroups;
FLocals: TIDELocals; FLocals: TLocalsMonitor;
FLineInfo: TIDELineInfo; FLineInfo: TIDELineInfo;
FWatches: TWatchesMonitor; FWatches: TWatchesMonitor;
FThreads: TThreadsMonitor; FThreads: TThreadsMonitor;
@ -173,7 +173,7 @@ type
property Exceptions: TIDEExceptions read FExceptions; // A list of exceptions we should ignore property Exceptions: TIDEExceptions read FExceptions; // A list of exceptions we should ignore
property CallStack: TCallStackMonitor read FCallStack; property CallStack: TCallStackMonitor read FCallStack;
property Disassembler: TIDEDisassembler read FDisassembler; property Disassembler: TIDEDisassembler read FDisassembler;
property Locals: TIDELocals read FLocals; property Locals: TLocalsMonitor read FLocals;
property LineInfo: TIDELineInfo read FLineInfo; property LineInfo: TIDELineInfo read FLineInfo;
property Registers: TIDERegisters read FRegisters; property Registers: TIDERegisters read FRegisters;
property Signals: TIDESignals read FSignals; // A list of actions for signals we know of property Signals: TIDESignals read FSignals; // A list of actions for signals we know of

View File

@ -1199,7 +1199,9 @@ var
TheDialog: TLocalsDlg; TheDialog: TLocalsDlg;
begin begin
TheDialog := TLocalsDlg(FDialogs[ddtLocals]); TheDialog := TLocalsDlg(FDialogs[ddtLocals]);
TheDialog.Locals := FLocals; TheDialog.LocalsMonitor := FLocals;
TheDialog.ThreadsMonitor := FThreads;
TheDialog.CallStackMonitor := FCallStack;
end; end;
procedure TDebugManager.InitRegistersDlg; procedure TDebugManager.InitRegistersDlg;
@ -1270,7 +1272,7 @@ begin
FThreads := TThreadsMonitor.Create; FThreads := TThreadsMonitor.Create;
FExceptions := TProjectExceptions.Create; FExceptions := TProjectExceptions.Create;
FSignals := TIDESignals.Create; FSignals := TIDESignals.Create;
FLocals := TIDELocals.Create; FLocals := TLocalsMonitor.Create;
FLineInfo := TIDELineInfo.Create; FLineInfo := TIDELineInfo.Create;
FCallStack := TCallStackMonitor.Create; FCallStack := TCallStackMonitor.Create;
FDisassembler := TIDEDisassembler.Create; FDisassembler := TIDEDisassembler.Create;
@ -2281,7 +2283,7 @@ begin
TManagedBreakpoints(FBreakpoints).Master := nil; TManagedBreakpoints(FBreakpoints).Master := nil;
FWatches.Supplier := nil; FWatches.Supplier := nil;
FThreads.Supplier := nil; FThreads.Supplier := nil;
FLocals.Master := nil; FLocals.Supplier := nil;
FLineInfo.Master := nil; FLineInfo.Master := nil;
FCallStack.Supplier := nil; FCallStack.Supplier := nil;
FDisassembler.Master := nil; FDisassembler.Master := nil;
@ -2293,7 +2295,7 @@ begin
TManagedBreakpoints(FBreakpoints).Master := FDebugger.BreakPoints; TManagedBreakpoints(FBreakpoints).Master := FDebugger.BreakPoints;
FWatches.Supplier := FDebugger.Watches; FWatches.Supplier := FDebugger.Watches;
FThreads.Supplier := FDebugger.Threads; FThreads.Supplier := FDebugger.Threads;
FLocals.Master := FDebugger.Locals; FLocals.Supplier := FDebugger.Locals;
FLineInfo.Master := FDebugger.LineInfo; FLineInfo.Master := FDebugger.LineInfo;
FCallStack.Supplier := FDebugger.CallStack; FCallStack.Supplier := FDebugger.CallStack;
FDisassembler.Master := FDebugger.Disassembler; FDisassembler.Master := FDebugger.Disassembler;