mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-20 12:59:29 +01:00
Debugger: refactor register
git-svn-id: trunk@44216 -
This commit is contained in:
parent
1bdd42363f
commit
ed539caf03
@ -182,14 +182,20 @@ type
|
|||||||
TDebuggerDataMonitor = class
|
TDebuggerDataMonitor = class
|
||||||
private
|
private
|
||||||
FSupplier: TDebuggerDataSupplier;
|
FSupplier: TDebuggerDataSupplier;
|
||||||
|
FUpdateCount: Integer;
|
||||||
procedure SetSupplier(const AValue: TDebuggerDataSupplier);
|
procedure SetSupplier(const AValue: TDebuggerDataSupplier);
|
||||||
protected
|
protected
|
||||||
procedure DoModified; virtual; // user-modified / xml-storable data modified
|
procedure DoModified; virtual; // user-modified / xml-storable data modified
|
||||||
procedure DoNewSupplier; virtual;
|
procedure DoNewSupplier; virtual;
|
||||||
property Supplier: TDebuggerDataSupplier read FSupplier write SetSupplier;
|
property Supplier: TDebuggerDataSupplier read FSupplier write SetSupplier;
|
||||||
procedure DoStateChange(const {%H-}AOldState, {%H-}ANewState: TDBGState); virtual;
|
procedure DoStateChange(const {%H-}AOldState, {%H-}ANewState: TDBGState); virtual;
|
||||||
|
procedure DoBeginUpdate; virtual;
|
||||||
|
procedure DoEndUpdate; virtual;
|
||||||
|
function IsUpdating: Boolean;
|
||||||
public
|
public
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
procedure BeginUpdate;
|
||||||
|
procedure EndUpdate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TDebuggerDataSupplier }
|
{ TDebuggerDataSupplier }
|
||||||
@ -216,6 +222,8 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(const ADebugger: TDebuggerIntf);
|
constructor Create(const ADebugger: TDebuggerIntf);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
procedure BeginUpdate;
|
||||||
|
procedure EndUpdate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$region Breakpoints **********************************************************}
|
{$region Breakpoints **********************************************************}
|
||||||
@ -657,8 +665,9 @@ type
|
|||||||
private
|
private
|
||||||
FName: String;
|
FName: String;
|
||||||
FValue: String;
|
FValue: String;
|
||||||
public
|
protected
|
||||||
procedure DoAssign(AnOther: TDbgEntityValue); override;
|
procedure DoAssign(AnOther: TDbgEntityValue); override;
|
||||||
|
public
|
||||||
property Name: String read FName;
|
property Name: String read FName;
|
||||||
property Value: String read FValue;
|
property Value: String read FValue;
|
||||||
end;
|
end;
|
||||||
@ -763,80 +772,106 @@ type
|
|||||||
******************************************************************************
|
******************************************************************************
|
||||||
******************************************************************************}
|
******************************************************************************}
|
||||||
|
|
||||||
TRegisterDisplayFormat =
|
TRegisterDisplayFormat = (rdDefault, rdHex, rdBinary, rdOctal, rdDecimal, rdRaw);
|
||||||
(rdDefault, rdHex, rdBinary, rdOctal, rdDecimal, rdRaw
|
TRegisterDisplayFormats = set of TRegisterDisplayFormat;
|
||||||
);
|
|
||||||
|
|
||||||
TRegistersFormat = record
|
{ TRegisterDisplayValue }
|
||||||
Name: String;
|
|
||||||
Format: TRegisterDisplayFormat;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TRegistersFormatList }
|
TRegisterDisplayValue = class // Only created if ddsValid
|
||||||
|
private
|
||||||
|
FStringValue: String; // default, rdRaw is always in FStringValue
|
||||||
|
FNumValue: QWord;
|
||||||
|
FSize: Integer; // 2, 4 or 8 bytes
|
||||||
|
FFlags: set of (rdvHasNum); // Calculate numeric values.
|
||||||
|
FSupportedDispFormats: TRegisterDisplayFormats;
|
||||||
|
function GetValue(ADispFormat: TRegisterDisplayFormat): String;
|
||||||
|
public
|
||||||
|
procedure Assign(AnOther: TRegisterDisplayValue);
|
||||||
|
procedure SetAsNum(AValue: QWord; ASize: Integer);
|
||||||
|
procedure SetAsText(AValue: String);
|
||||||
|
procedure AddFormats(AFormats: TRegisterDisplayFormats);
|
||||||
|
property SupportedDispFormats: TRegisterDisplayFormats read FSupportedDispFormats;
|
||||||
|
property Value[ADispFormat: TRegisterDisplayFormat]: String read GetValue;
|
||||||
|
end;
|
||||||
|
|
||||||
TRegistersFormatList = class
|
{ TRegisterValue }
|
||||||
|
|
||||||
|
TRegisterValue = class(TDbgEntityValue)
|
||||||
|
private
|
||||||
|
FDataValidity: TDebuggerDataState;
|
||||||
|
FDisplayFormat: TRegisterDisplayFormat;
|
||||||
|
FModified: Boolean;
|
||||||
|
FName: String;
|
||||||
|
FValues: Array of TRegisterDisplayValue;
|
||||||
|
function GetHasValue: Boolean;
|
||||||
|
function GetHasValueFormat(ADispFormat: TRegisterDisplayFormat): Boolean;
|
||||||
|
function GetValue: String;
|
||||||
|
function GetValueObj: TRegisterDisplayValue;
|
||||||
|
function GetValueObjFormat(ADispFormat: TRegisterDisplayFormat): TRegisterDisplayValue;
|
||||||
|
procedure SetDisplayFormat(AValue: TRegisterDisplayFormat);
|
||||||
|
procedure SetValue(AValue: String);
|
||||||
|
function GetValueObject(ACreateNew: Boolean = False): TRegisterDisplayValue;
|
||||||
|
function GetValueObject(ADispFormat: TRegisterDisplayFormat; ACreateNew: Boolean = False): TRegisterDisplayValue;
|
||||||
|
procedure SetDataValidity(AValidity: TDebuggerDataState);
|
||||||
|
procedure ClearDispValues;
|
||||||
|
protected
|
||||||
|
procedure DoAssign(AnOther: TDbgEntityValue); override;
|
||||||
|
procedure DoDataValidityChanged({%H-}AnOldValidity: TDebuggerDataState); virtual;
|
||||||
|
procedure DoDisplayFormatChanged({%H-}AnOldFormat: TRegisterDisplayFormat); virtual;
|
||||||
|
procedure DoValueNotEvaluated; virtual;
|
||||||
|
public
|
||||||
|
destructor Destroy; override;
|
||||||
|
property Name: String read FName;
|
||||||
|
property Value: String read GetValue write SetValue;
|
||||||
|
property DisplayFormat: TRegisterDisplayFormat read FDisplayFormat write SetDisplayFormat;
|
||||||
|
property Modified: Boolean read FModified write FModified;
|
||||||
|
property DataValidity: TDebuggerDataState read FDataValidity write SetDataValidity;
|
||||||
|
property ValueObj: TRegisterDisplayValue read GetValueObj; // Will create the object for current DispFormat. Only use for setting data.
|
||||||
|
property HasValue: Boolean read GetHasValue;
|
||||||
|
property ValueObjFormat[ADispFormat: TRegisterDisplayFormat]: TRegisterDisplayValue read GetValueObjFormat; // Will create the object for current DispFormat. Only use for setting data.
|
||||||
|
property HasValueFormat[ADispFormat: TRegisterDisplayFormat]: Boolean read GetHasValueFormat;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TRegisters }
|
||||||
|
|
||||||
|
TRegisters = class(TDbgEntityValuesList)
|
||||||
private
|
private
|
||||||
FCount: integer;
|
FDataValidity: TDebuggerDataState;
|
||||||
FFormats: array of TRegistersFormat;
|
function GetEntry(AnIndex: Integer): TRegisterValue;
|
||||||
function GetFormat(AName: String): TRegisterDisplayFormat;
|
function GetEntryByName(const AName: String): TRegisterValue;
|
||||||
procedure SetFormat(AName: String; AValue: TRegisterDisplayFormat);
|
procedure SetDataValidity(AValue: TDebuggerDataState);
|
||||||
protected
|
protected
|
||||||
function IndexOf(const AName: String): integer;
|
function CreateEntry: TDbgEntityValue; override;
|
||||||
function Add(const AName: String; AFormat: TRegisterDisplayFormat): integer;
|
procedure DoDataValidityChanged({%H-}AnOldValidity: TDebuggerDataState); virtual;
|
||||||
property Count: Integer read FCount;
|
|
||||||
public
|
public
|
||||||
constructor Create;
|
function Count: Integer; reintroduce; virtual;
|
||||||
procedure Clear;
|
property Entries[AnIndex: Integer]: TRegisterValue read GetEntry; default;
|
||||||
property Format[AName: String]: TRegisterDisplayFormat read GetFormat write SetFormat; default;
|
property EntriesByName[const AName: String]: TRegisterValue read GetEntryByName; // autocreate
|
||||||
|
property DataValidity: TDebuggerDataState read FDataValidity write SetDataValidity;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TBaseRegisters }
|
{ TRegistersList }
|
||||||
|
|
||||||
TBaseRegisters = class(TObject)
|
TRegistersList = class(TDbgEntitiesThreadStackList)
|
||||||
protected
|
|
||||||
FUpdateCount: Integer;
|
|
||||||
FFormatList: TRegistersFormatList;
|
|
||||||
function GetModified(const {%H-}AnIndex: Integer): Boolean; virtual;
|
|
||||||
function GetName(const {%H-}AnIndex: Integer): String; virtual;
|
|
||||||
function GetValue(const {%H-}AnIndex: Integer): String; virtual;
|
|
||||||
function GetFormat(const AnIndex: Integer): TRegisterDisplayFormat;
|
|
||||||
procedure SetFormat(const AnIndex: Integer; const AValue: TRegisterDisplayFormat); virtual;
|
|
||||||
procedure ChangeUpdating; virtual;
|
|
||||||
function Updating: Boolean;
|
|
||||||
public
|
|
||||||
property FormatList: TRegistersFormatList read FFormatList write FFormatList;
|
|
||||||
public
|
|
||||||
constructor Create;
|
|
||||||
function Count: Integer; virtual;
|
|
||||||
public
|
|
||||||
procedure BeginUpdate;
|
|
||||||
procedure EndUpdate;
|
|
||||||
property Modified[const AnIndex: Integer]: Boolean read GetModified;
|
|
||||||
property Names[const AnIndex: Integer]: String read GetName;
|
|
||||||
property Values[const AnIndex: Integer]: String read GetValue;
|
|
||||||
property Formats[const AnIndex: Integer]: TRegisterDisplayFormat
|
|
||||||
read GetFormat write SetFormat;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TDBGRegisters }
|
|
||||||
|
|
||||||
TDBGRegisters = class(TBaseRegisters)
|
|
||||||
private
|
private
|
||||||
FDebugger: TDebuggerIntf; // reference to our debugger
|
function GetEntry(AThreadId, AStackFrame: Integer): TRegisters;
|
||||||
FOnChange: TNotifyEvent;
|
function GetEntryByIdx(AnIndex: Integer): TRegisters;
|
||||||
FChanged: Boolean;
|
|
||||||
protected
|
protected
|
||||||
procedure Changed; virtual;
|
|
||||||
procedure DoChange;
|
|
||||||
procedure DoStateChange(const {%H-}AOldState: TDBGState); virtual;
|
|
||||||
function GetCount: Integer; virtual;
|
|
||||||
procedure ChangeUpdating; override;
|
|
||||||
property Debugger: TDebuggerIntf read FDebugger write FDebugger;
|
|
||||||
public
|
public
|
||||||
procedure FormatChanged(const {%H-}AnIndex: Integer); virtual;
|
property EntriesByIdx[AnIndex: Integer]: TRegisters read GetEntryByIdx;
|
||||||
function Count: Integer; override;
|
property Entries[AThreadId, AStackFrame: Integer]: TRegisters read GetEntry; default;
|
||||||
constructor Create(const ADebugger: TDebuggerIntf);
|
end;
|
||||||
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
|
||||||
|
{ TRegisterSupplier }
|
||||||
|
|
||||||
|
TRegisterSupplier = class(TDebuggerDataSupplier)
|
||||||
|
private
|
||||||
|
FCurrentRegistersList: TRegistersList;
|
||||||
|
protected
|
||||||
|
procedure DoNewMonitor; override;
|
||||||
|
public
|
||||||
|
procedure RequestData(ARegisters: TRegisters); virtual;
|
||||||
|
property CurrentRegistersList: TRegistersList read FCurrentRegistersList write FCurrentRegistersList;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{%endregion ^^^^^ Register ^^^^^ }
|
{%endregion ^^^^^ Register ^^^^^ }
|
||||||
@ -1393,6 +1428,8 @@ type
|
|||||||
TDebuggerPropertiesClass= class of TDebuggerProperties;
|
TDebuggerPropertiesClass= class of TDebuggerProperties;
|
||||||
|
|
||||||
|
|
||||||
|
{ TDebuggerIntf }
|
||||||
|
|
||||||
TDebuggerIntf = class
|
TDebuggerIntf = class
|
||||||
private
|
private
|
||||||
FArguments: String;
|
FArguments: String;
|
||||||
@ -1414,7 +1451,7 @@ type
|
|||||||
FOnConsoleOutput: TDBGOutputEvent;
|
FOnConsoleOutput: TDBGOutputEvent;
|
||||||
FOnFeedback: TDBGFeedbackEvent;
|
FOnFeedback: TDBGFeedbackEvent;
|
||||||
FOnIdle: TNotifyEvent;
|
FOnIdle: TNotifyEvent;
|
||||||
FRegisters: TDBGRegisters;
|
FRegisters: TRegisterSupplier;
|
||||||
FShowConsole: Boolean;
|
FShowConsole: Boolean;
|
||||||
FSignals: TDBGSignals;
|
FSignals: TDBGSignals;
|
||||||
FState: TDBGState;
|
FState: TDBGState;
|
||||||
@ -1444,7 +1481,7 @@ type
|
|||||||
function CreateBreakPoints: TDBGBreakPoints; virtual;
|
function CreateBreakPoints: TDBGBreakPoints; virtual;
|
||||||
function CreateLocals: TLocalsSupplier; virtual;
|
function CreateLocals: TLocalsSupplier; virtual;
|
||||||
function CreateLineInfo: TDBGLineInfo; virtual;
|
function CreateLineInfo: TDBGLineInfo; virtual;
|
||||||
function CreateRegisters: TDBGRegisters; virtual;
|
function CreateRegisters: TRegisterSupplier; virtual;
|
||||||
function CreateCallStack: TCallStackSupplier; virtual;
|
function CreateCallStack: TCallStackSupplier; virtual;
|
||||||
function CreateDisassembler: TDBGDisassembler; virtual;
|
function CreateDisassembler: TDBGDisassembler; virtual;
|
||||||
function CreateWatches: TWatchesSupplier; virtual;
|
function CreateWatches: TWatchesSupplier; virtual;
|
||||||
@ -1541,7 +1578,7 @@ type
|
|||||||
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: TLocalsSupplier 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: TRegisterSupplier 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
|
||||||
property ShowConsole: Boolean read FShowConsole write FShowConsole; // Indicates if the debugger should create a console for the debuggee
|
property ShowConsole: Boolean read FShowConsole write FShowConsole; // Indicates if the debugger should create a console for the debuggee
|
||||||
property State: TDBGState read FState; // The current state of the debugger
|
property State: TDBGState read FState; // The current state of the debugger
|
||||||
@ -1724,6 +1761,19 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TRegisterSupplier }
|
||||||
|
|
||||||
|
procedure TRegisterSupplier.DoNewMonitor;
|
||||||
|
begin
|
||||||
|
inherited DoNewMonitor;
|
||||||
|
FCurrentRegistersList := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterSupplier.RequestData(ARegisters: TRegisters);
|
||||||
|
begin
|
||||||
|
ARegisters.SetDataValidity(ddsInvalid);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TLocalsValue }
|
{ TLocalsValue }
|
||||||
|
|
||||||
procedure TLocalsValue.DoAssign(AnOther: TDbgEntityValue);
|
procedure TLocalsValue.DoAssign(AnOther: TDbgEntityValue);
|
||||||
@ -1783,6 +1833,272 @@ begin
|
|||||||
Result := inherited Count;
|
Result := inherited Count;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TRegisterDisplayValue }
|
||||||
|
|
||||||
|
function TRegisterDisplayValue.GetValue(ADispFormat: TRegisterDisplayFormat): String;
|
||||||
|
const Digits = '01234567';
|
||||||
|
function IntToBase(Val, Base: Integer): String;
|
||||||
|
var
|
||||||
|
M: Integer;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
case Base of
|
||||||
|
2: M := 1;
|
||||||
|
8: M := 7;
|
||||||
|
end;
|
||||||
|
while Val > 0 do begin
|
||||||
|
Result := Digits[1 + (Val and m)] + Result;
|
||||||
|
Val := Val div Base;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
Result := '';
|
||||||
|
if not(ADispFormat in FSupportedDispFormats) then exit;
|
||||||
|
if (ADispFormat in [rdDefault, rdRaw]) or not (rdvHasNum in FFlags) then begin
|
||||||
|
Result := FStringValue;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
case ADispFormat of
|
||||||
|
rdHex: Result := IntToHex(FNumValue, FSize * 2);
|
||||||
|
rdBinary: Result := IntToBase(FNumValue, 2);
|
||||||
|
rdOctal: Result := IntToBase(FNumValue, 8);
|
||||||
|
rdDecimal: Result := IntToStr(FNumValue);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterDisplayValue.Assign(AnOther: TRegisterDisplayValue);
|
||||||
|
begin
|
||||||
|
FStringValue := AnOther.FStringValue;
|
||||||
|
FNumValue := AnOther.FNumValue;
|
||||||
|
FFlags := AnOther.FFlags;
|
||||||
|
FSize := AnOther.FSize;
|
||||||
|
FSupportedDispFormats := AnOther.FSupportedDispFormats;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterDisplayValue.SetAsNum(AValue: QWord; ASize: Integer);
|
||||||
|
begin
|
||||||
|
if FNumValue = AValue then Exit;
|
||||||
|
FNumValue := AValue;
|
||||||
|
FSize := ASize;
|
||||||
|
Include(FFlags, rdvHasNum);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterDisplayValue.SetAsText(AValue: String);
|
||||||
|
begin
|
||||||
|
FStringValue := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterDisplayValue.AddFormats(AFormats: TRegisterDisplayFormats);
|
||||||
|
begin
|
||||||
|
FSupportedDispFormats := FSupportedDispFormats + AFormats;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TRegisterValue }
|
||||||
|
|
||||||
|
function TRegisterValue.GetValue: String;
|
||||||
|
var
|
||||||
|
v: TRegisterDisplayValue;
|
||||||
|
begin
|
||||||
|
v := GetValueObject();
|
||||||
|
if v <> nil then begin
|
||||||
|
Result := v.Value[FDisplayFormat];
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := '';
|
||||||
|
DoValueNotEvaluated;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRegisterValue.GetHasValue: Boolean;
|
||||||
|
begin
|
||||||
|
Result := GetValueObject <> nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRegisterValue.GetHasValueFormat(ADispFormat: TRegisterDisplayFormat): Boolean;
|
||||||
|
begin
|
||||||
|
Result := GetValueObject(ADispFormat) <> nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRegisterValue.GetValueObj: TRegisterDisplayValue;
|
||||||
|
begin
|
||||||
|
Result := GetValueObject(True);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRegisterValue.GetValueObjFormat(ADispFormat: TRegisterDisplayFormat): TRegisterDisplayValue;
|
||||||
|
begin
|
||||||
|
Result := GetValueObject(ADispFormat, True);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterValue.SetDisplayFormat(AValue: TRegisterDisplayFormat);
|
||||||
|
var
|
||||||
|
Old: TRegisterDisplayFormat;
|
||||||
|
begin
|
||||||
|
assert(not Immutable, 'TRegisterValue.SetDisplayFormat: not Immutable');
|
||||||
|
if FDisplayFormat = AValue then Exit;
|
||||||
|
Old := FDisplayFormat;
|
||||||
|
FDisplayFormat := AValue;
|
||||||
|
DoDisplayFormatChanged(Old);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterValue.SetValue(AValue: String);
|
||||||
|
var
|
||||||
|
v: TRegisterDisplayValue;
|
||||||
|
begin
|
||||||
|
assert(not Immutable, 'TRegisterValue.SetValue: not Immutable');
|
||||||
|
v := GetValueObject(True);
|
||||||
|
v.FStringValue := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRegisterValue.GetValueObject(ACreateNew: Boolean): TRegisterDisplayValue;
|
||||||
|
begin
|
||||||
|
Result := GetValueObject(FDisplayFormat, ACreateNew);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRegisterValue.GetValueObject(ADispFormat: TRegisterDisplayFormat;
|
||||||
|
ACreateNew: Boolean): TRegisterDisplayValue;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to length(FValues) - 1 do
|
||||||
|
if ADispFormat in FValues[i].SupportedDispFormats then begin
|
||||||
|
Result := FValues[i];
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not ACreateNew then begin
|
||||||
|
Result := nil;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
assert(not Immutable, 'TRegisterValue.GetValueObject: not Immutable');
|
||||||
|
Result := TRegisterDisplayValue.Create;
|
||||||
|
Result.FSupportedDispFormats := [ADispFormat];
|
||||||
|
i := length(FValues);
|
||||||
|
SetLength(FValues, i + 1);
|
||||||
|
FValues[i] := Result;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterValue.SetDataValidity(AValidity: TDebuggerDataState);
|
||||||
|
var
|
||||||
|
Old: TDebuggerDataState;
|
||||||
|
begin
|
||||||
|
assert(not Immutable, 'TRegisterValue.SetDataValidity: not Immutable');
|
||||||
|
if FDataValidity = AValidity then exit;
|
||||||
|
Old := FDataValidity;
|
||||||
|
FDataValidity := AValidity;
|
||||||
|
DoDataValidityChanged(Old);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterValue.ClearDispValues;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to Length(FValues) - 1 do
|
||||||
|
FValues[i].Free;
|
||||||
|
FValues := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterValue.DoAssign(AnOther: TDbgEntityValue);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
inherited DoAssign(AnOther);
|
||||||
|
FDataValidity := TRegisterValue(AnOther).FDataValidity;
|
||||||
|
FDisplayFormat := TRegisterValue(AnOther).FDisplayFormat;
|
||||||
|
FName := TRegisterValue(AnOther).FName;
|
||||||
|
SetLength(FValues, length(TRegisterValue(AnOther).FValues));
|
||||||
|
for i := 0 to length(TRegisterValue(AnOther).FValues) - 1 do begin
|
||||||
|
FValues[i] := TRegisterDisplayValue.Create;
|
||||||
|
FValues[i].Assign(TRegisterValue(AnOther).FValues[i]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterValue.DoDataValidityChanged(AnOldValidity: TDebuggerDataState);
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterValue.DoDisplayFormatChanged(AnOldFormat: TRegisterDisplayFormat);
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisterValue.DoValueNotEvaluated;
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TRegisterValue.Destroy;
|
||||||
|
begin
|
||||||
|
inherited Destroy;
|
||||||
|
ClearDispValues;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TRegisters }
|
||||||
|
|
||||||
|
function TRegisters.GetEntry(AnIndex: Integer): TRegisterValue;
|
||||||
|
begin
|
||||||
|
Result := TRegisterValue(inherited Entries[AnIndex]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRegisters.GetEntryByName(const AName: String): TRegisterValue;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
for i := 0 to Count - 1 do begin
|
||||||
|
Result := Entries[i];
|
||||||
|
if Result.Name = AName then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
assert(not Immutable, 'TRegisters.GetEntryByName: not Immutable');
|
||||||
|
Result := TRegisterValue(CreateEntry);
|
||||||
|
Result.FName := AName;
|
||||||
|
Add(Result);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisters.SetDataValidity(AValue: TDebuggerDataState);
|
||||||
|
var
|
||||||
|
Old: TDebuggerDataState;
|
||||||
|
begin
|
||||||
|
assert(not Immutable, 'TRegisters.SetDataValidity: not Immutable');
|
||||||
|
if FDataValidity = AValue then Exit;
|
||||||
|
Old := FDataValidity;
|
||||||
|
FDataValidity := AValue;
|
||||||
|
DoDataValidityChanged(Old);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRegisters.CreateEntry: TDbgEntityValue;
|
||||||
|
begin
|
||||||
|
assert(not Immutable, 'TRegisters.CreateEntry: not Immutable');
|
||||||
|
Result := TRegisterValue.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegisters.DoDataValidityChanged(AnOldValidity: TDebuggerDataState);
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRegisters.Count: Integer;
|
||||||
|
begin
|
||||||
|
if FDataValidity = ddsValid then
|
||||||
|
Result := inherited Count
|
||||||
|
else
|
||||||
|
Result := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TRegistersList }
|
||||||
|
|
||||||
|
function TRegistersList.GetEntry(AThreadId, AStackFrame: Integer): TRegisters;
|
||||||
|
begin
|
||||||
|
Result := TRegisters(inherited Entries[AThreadId, AStackFrame]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRegistersList.GetEntryByIdx(AnIndex: Integer): TRegisters;
|
||||||
|
begin
|
||||||
|
Result := TRegisters(inherited EntriesByIdx[AnIndex]);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TWatchesBase }
|
{ TWatchesBase }
|
||||||
|
|
||||||
function TWatchesBase.GetItemBase(const AnIndex: Integer): TWatchBase;
|
function TWatchesBase.GetItemBase(const AnIndex: Integer): TWatchBase;
|
||||||
@ -1843,12 +2159,42 @@ begin
|
|||||||
//
|
//
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDebuggerDataMonitor.DoBeginUpdate;
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDebuggerDataMonitor.DoEndUpdate;
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDebuggerDataMonitor.IsUpdating: Boolean;
|
||||||
|
begin
|
||||||
|
Result := FUpdateCount > 0;
|
||||||
|
end;
|
||||||
|
|
||||||
destructor TDebuggerDataMonitor.Destroy;
|
destructor TDebuggerDataMonitor.Destroy;
|
||||||
begin
|
begin
|
||||||
Supplier := nil;
|
Supplier := nil;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDebuggerDataMonitor.BeginUpdate;
|
||||||
|
begin
|
||||||
|
inc(FUpdateCount);
|
||||||
|
if FUpdateCount = 1 then
|
||||||
|
DoBeginUpdate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDebuggerDataMonitor.EndUpdate;
|
||||||
|
begin
|
||||||
|
assert(FUpdateCount > 0, 'TDebuggerDataMonitor.EndUpdate: FUpdateCount > 0');
|
||||||
|
dec(FUpdateCount);
|
||||||
|
if FUpdateCount = 0 then
|
||||||
|
DoEndUpdate;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TDebuggerDataSupplier }
|
{ TDebuggerDataSupplier }
|
||||||
|
|
||||||
procedure TDebuggerDataSupplier.SetMonitor(const AValue: TDebuggerDataMonitor);
|
procedure TDebuggerDataSupplier.SetMonitor(const AValue: TDebuggerDataMonitor);
|
||||||
@ -1931,6 +2277,16 @@ begin
|
|||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDebuggerDataSupplier.BeginUpdate;
|
||||||
|
begin
|
||||||
|
FMonitor.BeginUpdate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDebuggerDataSupplier.EndUpdate;
|
||||||
|
begin
|
||||||
|
FMonitor.EndUpdate;
|
||||||
|
end;
|
||||||
|
|
||||||
{ ===========================================================================
|
{ ===========================================================================
|
||||||
TBaseBreakPoint
|
TBaseBreakPoint
|
||||||
=========================================================================== }
|
=========================================================================== }
|
||||||
@ -2713,185 +3069,6 @@ begin
|
|||||||
FDebugger := ADebugger;
|
FDebugger := ADebugger;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TRegistersFormatList }
|
|
||||||
|
|
||||||
function TRegistersFormatList.GetFormat(AName: String): TRegisterDisplayFormat;
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
begin
|
|
||||||
i := IndexOf(AName);
|
|
||||||
if i < 0
|
|
||||||
then Result := rdDefault
|
|
||||||
else Result := FFormats[i].Format;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TRegistersFormatList.SetFormat(AName: String; AValue: TRegisterDisplayFormat);
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
begin
|
|
||||||
i := IndexOf(AName);
|
|
||||||
if i < 0
|
|
||||||
then Add(AName, AValue)
|
|
||||||
else FFormats[i].Format := AValue;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TRegistersFormatList.IndexOf(const AName: String): integer;
|
|
||||||
begin
|
|
||||||
Result := FCount - 1;
|
|
||||||
while Result >= 0 do begin
|
|
||||||
if FFormats[Result].Name = AName then exit;
|
|
||||||
dec(Result);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TRegistersFormatList.Add(const AName: String;
|
|
||||||
AFormat: TRegisterDisplayFormat): integer;
|
|
||||||
begin
|
|
||||||
if FCount >= length(FFormats) then SetLength(FFormats, Max(Length(FFormats)*2, 16));
|
|
||||||
FFormats[FCount].Name := AName;
|
|
||||||
FFormats[FCount].Format := AFormat;
|
|
||||||
Result := FCount;
|
|
||||||
inc(FCount);
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TRegistersFormatList.Create;
|
|
||||||
begin
|
|
||||||
FCount := 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TRegistersFormatList.Clear;
|
|
||||||
begin
|
|
||||||
FCount := 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ =========================================================================== }
|
|
||||||
{ TBaseRegisters }
|
|
||||||
{ =========================================================================== }
|
|
||||||
|
|
||||||
function TBaseRegisters.Count: Integer;
|
|
||||||
begin
|
|
||||||
Result := 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TBaseRegisters.BeginUpdate;
|
|
||||||
begin
|
|
||||||
inc(FUpdateCount);
|
|
||||||
if FUpdateCount = 1 then ChangeUpdating;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TBaseRegisters.EndUpdate;
|
|
||||||
begin
|
|
||||||
dec(FUpdateCount);
|
|
||||||
if FUpdateCount = 0 then ChangeUpdating;
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TBaseRegisters.Create;
|
|
||||||
begin
|
|
||||||
inherited Create;
|
|
||||||
FormatList := nil;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TBaseRegisters.GetFormat(const AnIndex: Integer): TRegisterDisplayFormat;
|
|
||||||
var
|
|
||||||
s: String;
|
|
||||||
begin
|
|
||||||
Result := rdDefault;
|
|
||||||
if FFormatList = nil then exit;
|
|
||||||
s := Names[AnIndex];
|
|
||||||
if s <> '' then
|
|
||||||
Result := FFormatList[s];
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TBaseRegisters.SetFormat(const AnIndex: Integer;
|
|
||||||
const AValue: TRegisterDisplayFormat);
|
|
||||||
var
|
|
||||||
s: String;
|
|
||||||
begin
|
|
||||||
if FFormatList = nil then exit;
|
|
||||||
s := Names[AnIndex];
|
|
||||||
if s <> '' then
|
|
||||||
FFormatList[s] := AValue;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TBaseRegisters.ChangeUpdating;
|
|
||||||
begin
|
|
||||||
//
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TBaseRegisters.Updating: Boolean;
|
|
||||||
begin
|
|
||||||
Result := FUpdateCount <> 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TBaseRegisters.GetModified(const AnIndex: Integer): Boolean;
|
|
||||||
begin
|
|
||||||
Result := False;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TBaseRegisters.GetName(const AnIndex: Integer): String;
|
|
||||||
begin
|
|
||||||
Result := '';
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TBaseRegisters.GetValue(const AnIndex: Integer): String;
|
|
||||||
begin
|
|
||||||
Result := '';
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ =========================================================================== }
|
|
||||||
{ TDBGRegisters }
|
|
||||||
{ =========================================================================== }
|
|
||||||
|
|
||||||
function TDBGRegisters.Count: Integer;
|
|
||||||
begin
|
|
||||||
if (FDebugger <> nil)
|
|
||||||
and (FDebugger.State in [dsPause, dsInternalPause])
|
|
||||||
then Result := GetCount
|
|
||||||
else Result := 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TDBGRegisters.Create(const ADebugger: TDebuggerIntf);
|
|
||||||
begin
|
|
||||||
FChanged := False;
|
|
||||||
inherited Create;
|
|
||||||
FDebugger := ADebugger;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TDBGRegisters.DoChange;
|
|
||||||
begin
|
|
||||||
if Updating then begin
|
|
||||||
FChanged := True;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
FChanged := False;
|
|
||||||
if Assigned(FOnChange) then FOnChange(Self);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TDBGRegisters.DoStateChange(const AOldState: TDBGState);
|
|
||||||
begin
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TDBGRegisters.FormatChanged(const AnIndex: Integer);
|
|
||||||
begin
|
|
||||||
//
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TDBGRegisters.Changed;
|
|
||||||
begin
|
|
||||||
DoChange;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TDBGRegisters.GetCount: Integer;
|
|
||||||
begin
|
|
||||||
Result := 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TDBGRegisters.ChangeUpdating;
|
|
||||||
begin
|
|
||||||
inherited ChangeUpdating;
|
|
||||||
if (not Updating) and FChanged then DoChange;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ =========================================================================== }
|
{ =========================================================================== }
|
||||||
{ TCallStackSupplier }
|
{ TCallStackSupplier }
|
||||||
{ =========================================================================== }
|
{ =========================================================================== }
|
||||||
@ -3953,9 +4130,9 @@ begin
|
|||||||
Result := TDebuggerProperties.Create;
|
Result := TDebuggerProperties.Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDebuggerIntf.CreateRegisters: TDBGRegisters;
|
function TDebuggerIntf.CreateRegisters: TRegisterSupplier;
|
||||||
begin
|
begin
|
||||||
Result := TDBGRegisters.Create(Self);
|
Result := TRegisterSupplier.Create(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDebuggerIntf.CreateSignals: TDBGSignals;
|
function TDebuggerIntf.CreateSignals: TDBGSignals;
|
||||||
|
|||||||
@ -286,8 +286,14 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDbgEntityValuesList.Clear;
|
procedure TDbgEntityValuesList.Clear;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
Assert(not Immutable, 'TDbgEntityValuesList.Clear Immutable');
|
Assert(not Immutable, 'TDbgEntityValuesList.Clear Immutable');
|
||||||
|
if FList.Count = 0 then
|
||||||
|
exit;
|
||||||
|
for i := 0 to FList.Count - 1 do
|
||||||
|
TDbgEntityValue(FList[i]).FOwner := nil;
|
||||||
FList.Clear;
|
FList.Clear;
|
||||||
DoCleared;
|
DoCleared;
|
||||||
end;
|
end;
|
||||||
@ -443,11 +449,16 @@ end;
|
|||||||
|
|
||||||
procedure TDbgEntitiesThreadStackList.Clear;
|
procedure TDbgEntitiesThreadStackList.Clear;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i, j: Integer;
|
||||||
begin
|
begin
|
||||||
Assert(not Immutable, 'TDbgEntitiesThreadStackList.Clear Immutable');
|
Assert(not Immutable, 'TDbgEntitiesThreadStackList.Clear Immutable');
|
||||||
for i := 0 to Length(FList) - 1 do
|
if Length(FList) = 0 then
|
||||||
|
exit;
|
||||||
|
for i := 0 to Length(FList) - 1 do begin
|
||||||
|
for j := 0 to FList[i].List.Count - 1 do
|
||||||
|
TDbgEntityValuesList(FList[i].List[j]).FOwner := nil;
|
||||||
FList[i].List.Free;
|
FList[i].List.Free;
|
||||||
|
end;
|
||||||
SetLength(FList, 0);
|
SetLength(FList, 0);
|
||||||
DoCleared;
|
DoCleared;
|
||||||
end;
|
end;
|
||||||
|
|||||||
@ -32,9 +32,9 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(ADebugger: TFpGDBMIDebugger);
|
constructor Create(ADebugger: TFpGDBMIDebugger);
|
||||||
function ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
function ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||||
function ReadMemoryEx(AnAddress, AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
function ReadMemoryEx({%H-}AnAddress, {%H-}AnAddressSpace:{%H-} TDbgPtr; ASize: {%H-}Cardinal; ADest: Pointer): Boolean; override;
|
||||||
function ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr): Boolean; override;
|
function ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr): Boolean; override;
|
||||||
function RegisterSize(ARegNum: Cardinal): Integer; override;
|
function RegisterSize({%H-}ARegNum: Cardinal): Integer; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TFpGDBMIAndWin32DbgMemReader }
|
{ TFpGDBMIAndWin32DbgMemReader }
|
||||||
@ -102,6 +102,8 @@ type
|
|||||||
var AResText: String;
|
var AResText: String;
|
||||||
out ATypeInfo: TDBGType;
|
out ATypeInfo: TDBGType;
|
||||||
EvalFlags: TDBGEvaluateFlags = []): Boolean;
|
EvalFlags: TDBGEvaluateFlags = []): Boolean;
|
||||||
|
property CurrentThreadId;
|
||||||
|
property CurrentStackFrame;
|
||||||
public
|
public
|
||||||
class function Caption: String; override;
|
class function Caption: String; override;
|
||||||
public
|
public
|
||||||
@ -162,7 +164,7 @@ type
|
|||||||
FRequestedSources: TStringList;
|
FRequestedSources: TStringList;
|
||||||
protected
|
protected
|
||||||
function FpDebugger: TFpGDBMIDebugger;
|
function FpDebugger: TFpGDBMIDebugger;
|
||||||
procedure DoStateChange(const AOldState: TDBGState); override;
|
procedure DoStateChange(const {%H-}AOldState: TDBGState); override;
|
||||||
procedure ClearSources;
|
procedure ClearSources;
|
||||||
public
|
public
|
||||||
constructor Create(const ADebugger: TDebuggerIntf);
|
constructor Create(const ADebugger: TDebuggerIntf);
|
||||||
@ -308,6 +310,8 @@ var
|
|||||||
rname: String;
|
rname: String;
|
||||||
v: String;
|
v: String;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
Reg: TRegisters;
|
||||||
|
RegVObj: TRegisterDisplayValue;
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
// 32 bit gdb dwarf names
|
// 32 bit gdb dwarf names
|
||||||
@ -324,10 +328,15 @@ begin
|
|||||||
else
|
else
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
for i := 0 to FDebugger.Registers.Count - 1 do
|
Reg := FDebugger.Registers.CurrentRegistersList[FDebugger.CurrentThreadId, FDebugger.CurrentStackFrame];
|
||||||
if UpperCase(FDebugger.Registers.Names[i]) = rname then
|
for i := 0 to Reg.Count - 1 do
|
||||||
|
if UpperCase(Reg[i].Name) = rname then
|
||||||
begin
|
begin
|
||||||
v := FDebugger.Registers.Values[i];
|
RegVObj := Reg[i].ValueObjFormat[rdDefault];
|
||||||
|
if RegVObj <> nil then
|
||||||
|
v := RegVObj.Value[rdDefault]
|
||||||
|
else
|
||||||
|
v := '';
|
||||||
debugln(['TFpGDBMIDbgMemReader.ReadRegister ',rname, ' ', v]);
|
debugln(['TFpGDBMIDbgMemReader.ReadRegister ',rname, ' ', v]);
|
||||||
Result := true;
|
Result := true;
|
||||||
try
|
try
|
||||||
@ -887,7 +896,7 @@ var
|
|||||||
begin
|
begin
|
||||||
if FNeedRegValues then begin
|
if FNeedRegValues then begin
|
||||||
FNeedRegValues := False;
|
FNeedRegValues := False;
|
||||||
FpDebugger.Registers.Values[0];
|
FpDebugger.Registers.CurrentRegistersList[FpDebugger.CurrentThreadId, FpDebugger.CurrentStackFrame].Count;
|
||||||
QueueCommand;
|
QueueCommand;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -940,12 +949,11 @@ begin
|
|||||||
if FEvaluationCmdObj <> nil then exit;
|
if FEvaluationCmdObj <> nil then exit;
|
||||||
|
|
||||||
FpDebugger.Threads.CurrentThreads.Count; // trigger threads, in case
|
FpDebugger.Threads.CurrentThreads.Count; // trigger threads, in case
|
||||||
if FpDebugger.Registers.Count = 0 then // trigger register, in case
|
if FpDebugger.Registers.CurrentRegistersList[FpDebugger.CurrentThreadId, FpDebugger.CurrentStackFrame].Count = 0 then // trigger register, in case
|
||||||
FNeedRegValues := True
|
FNeedRegValues := True
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
FNeedRegValues := False;
|
FNeedRegValues := False;
|
||||||
FpDebugger.Registers.Values[0];
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Join the queue, registers and threads are needed first
|
// Join the queue, registers and threads are needed first
|
||||||
@ -1534,7 +1542,7 @@ end;
|
|||||||
|
|
||||||
class function TFpGDBMIDebugger.Caption: String;
|
class function TFpGDBMIDebugger.Caption: String;
|
||||||
begin
|
begin
|
||||||
Result := 'GNU remote debugger (with fpdebug)';
|
Result := 'GNU debugger (with fpdebug)';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TFpGDBMIDebugger.Create(const AExternalDebugger: String);
|
constructor TFpGDBMIDebugger.Create(const AExternalDebugger: String);
|
||||||
|
|||||||
@ -744,7 +744,7 @@ type
|
|||||||
function CreateBreakPoints: TDBGBreakPoints; override;
|
function CreateBreakPoints: TDBGBreakPoints; override;
|
||||||
function CreateLocals: TLocalsSupplier; override;
|
function CreateLocals: TLocalsSupplier; override;
|
||||||
function CreateLineInfo: TDBGLineInfo; override;
|
function CreateLineInfo: TDBGLineInfo; override;
|
||||||
function CreateRegisters: TDBGRegisters; override;
|
function CreateRegisters: TRegisterSupplier; override;
|
||||||
function CreateCallStack: TCallStackSupplier; override;
|
function CreateCallStack: TCallStackSupplier; override;
|
||||||
function CreateDisassembler: TDBGDisassembler; override;
|
function CreateDisassembler: TDBGDisassembler; override;
|
||||||
function CreateWatches: TWatchesSupplier; override;
|
function CreateWatches: TWatchesSupplier; override;
|
||||||
@ -1121,94 +1121,36 @@ type
|
|||||||
|
|
||||||
{%region ***** Register ***** }
|
{%region ***** Register ***** }
|
||||||
|
|
||||||
{ TGDBMIDebuggerCommandRegisterNames }
|
|
||||||
TStringArray = Array of string;
|
TStringArray = Array of string;
|
||||||
TBoolArray = Array of Boolean;
|
TBoolArray = Array of Boolean;
|
||||||
|
|
||||||
TGDBMIDebuggerCommandRegisterNames = class(TGDBMIDebuggerCommand)
|
TGDBMIRegisterSupplier = class;
|
||||||
|
|
||||||
|
{ TGDBMIDebuggerCommandRegisterUpdate }
|
||||||
|
|
||||||
|
TGDBMIDebuggerCommandRegisterUpdate = class(TGDBMIDebuggerCommand)
|
||||||
private
|
private
|
||||||
FNames: Array of String;
|
FRegisters: TRegisters;
|
||||||
function GetNames(Index: Integer): string;
|
FGDBMIRegSupplier: TGDBMIRegisterSupplier;
|
||||||
protected
|
protected
|
||||||
function DoExecute: Boolean; override;
|
function DoExecute: Boolean; override;
|
||||||
|
procedure DoCancel; override;
|
||||||
public
|
public
|
||||||
|
constructor Create(AOwner: TGDBMIDebugger; AGDBMIRegSupplier: TGDBMIRegisterSupplier; ARegisters: TRegisters);
|
||||||
|
destructor Destroy; override;
|
||||||
//function DebugText: String; override;
|
//function DebugText: String; override;
|
||||||
function Count: Integer;
|
|
||||||
property Names[Index: Integer]: string read GetNames;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TGDBMIDebuggerCommandRegisterValues }
|
{ TGDBMIRegisterSupplier }
|
||||||
|
|
||||||
TGDBMIDebuggerCommandRegisterValues = class(TGDBMIDebuggerCommand)
|
TGDBMIRegisterSupplier = class(TRegisterSupplier)
|
||||||
private
|
private
|
||||||
FRegistersToUpdate: TStringArray;
|
FRegNamesCache: TStringArray;
|
||||||
FFormat: TRegisterDisplayFormat;
|
|
||||||
protected
|
protected
|
||||||
function DoExecute: Boolean; override;
|
procedure DoStateChange(const AOldState: TDBGState); override;
|
||||||
public
|
public
|
||||||
// updates the given array directly
|
procedure Changed;
|
||||||
constructor Create(AOwner: TGDBMIDebugger;
|
procedure RequestData(ARegisters: TRegisters); override;
|
||||||
RegistersToUpdate: TStringArray;
|
|
||||||
AFormat: TRegisterDisplayFormat = rdDefault
|
|
||||||
);
|
|
||||||
function DebugText: String; override;
|
|
||||||
property Format: TRegisterDisplayFormat read FFormat;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TGDBMIDebuggerCommandRegisterModified }
|
|
||||||
|
|
||||||
TGDBMIDebuggerCommandRegisterModified = class(TGDBMIDebuggerCommand)
|
|
||||||
private
|
|
||||||
FModifiedToUpdate: TBoolArray;
|
|
||||||
protected
|
|
||||||
function DoExecute: Boolean; override;
|
|
||||||
public
|
|
||||||
// updates the given array directly
|
|
||||||
constructor Create(AOwner: TGDBMIDebugger; ModifiedToUpdate: TBoolArray);
|
|
||||||
function DebugText: String; override;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TGDBMIRegisters }
|
|
||||||
|
|
||||||
TGDBMIRegisters = class(TDBGRegisters)
|
|
||||||
private
|
|
||||||
FRegNames: TStringArray;
|
|
||||||
FRegValues: Array [TRegisterDisplayFormat] of TStringArray;
|
|
||||||
FRegModified: TBoolArray;
|
|
||||||
FFormats: Array of TRegisterDisplayFormat;
|
|
||||||
|
|
||||||
FGetRegisterCmdObj: TGDBMIDebuggerCommandRegisterNames;
|
|
||||||
FRegistersReqState: TGDBMIEvaluationState;
|
|
||||||
FInRegistersNeeded: Boolean;
|
|
||||||
|
|
||||||
FGetModifiedCmd: TGDBMIDebuggerCommandRegisterModified;
|
|
||||||
FModifiedReqState: TGDBMIEvaluationState;
|
|
||||||
FInModifiedNeeded: Boolean;
|
|
||||||
|
|
||||||
FGetValuesCmdObj: Array [TRegisterDisplayFormat] of TGDBMIDebuggerCommandRegisterValues;
|
|
||||||
FValuesReqState: Array [TRegisterDisplayFormat] of TGDBMIEvaluationState;
|
|
||||||
FInValuesNeeded: Array [TRegisterDisplayFormat] of Boolean;
|
|
||||||
|
|
||||||
function GetDebugger: TGDBMIDebugger;
|
|
||||||
procedure RegistersNeeded;
|
|
||||||
procedure ValuesNeeded(AFormat: TRegisterDisplayFormat);
|
|
||||||
procedure ModifiedNeeded;
|
|
||||||
procedure DoGetRegisterNamesDestroyed(Sender: TObject);
|
|
||||||
procedure DoGetRegisterNamesFinished(Sender: TObject);
|
|
||||||
procedure DoGetRegValuesDestroyed(Sender: TObject);
|
|
||||||
procedure DoGetRegValuesFinished(Sender: TObject);
|
|
||||||
procedure DoGetRegModifiedDestroyed(Sender: TObject);
|
|
||||||
procedure DoGetRegModifiedFinished(Sender: TObject);
|
|
||||||
protected
|
|
||||||
procedure DoStateChange(const {%H-}AOldState: TDBGState); override;
|
|
||||||
procedure Invalidate;
|
|
||||||
function GetCount: Integer; override;
|
|
||||||
function GetModified(const AnIndex: Integer): Boolean; override;
|
|
||||||
function GetName(const AnIndex: Integer): String; override;
|
|
||||||
function GetValue(const AnIndex: Integer): String; override;
|
|
||||||
property Debugger: TGDBMIDebugger read GetDebugger;
|
|
||||||
public
|
|
||||||
procedure Changed; override;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{%endregion ^^^^^ Register ^^^^^ }
|
{%endregion ^^^^^ Register ^^^^^ }
|
||||||
@ -1571,6 +1513,190 @@ begin
|
|||||||
then Result := 8;
|
then Result := 8;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TGDBMIDebuggerCommandRegisterUpdate }
|
||||||
|
|
||||||
|
function TGDBMIDebuggerCommandRegisterUpdate.DoExecute: Boolean;
|
||||||
|
procedure UpdateFormat(AFormat: TRegisterDisplayFormat);
|
||||||
|
const
|
||||||
|
// rdDefault, rdHex, rdBinary, rdOctal, rdDecimal, rdRaw
|
||||||
|
FormatChar : array [TRegisterDisplayFormat] of string =
|
||||||
|
('N', 'x', 't', 'o', 'd', 'r');
|
||||||
|
var
|
||||||
|
i, idx: Integer;
|
||||||
|
Num: QWord;
|
||||||
|
List, ValList: TGDBMINameValueList;
|
||||||
|
Item: PGDBMINameValue;
|
||||||
|
RegVal: TRegisterValue;
|
||||||
|
RegValObj: TRegisterDisplayValue;
|
||||||
|
t: String;
|
||||||
|
NumErr: word;
|
||||||
|
R: TGDBMIExecResult;
|
||||||
|
begin
|
||||||
|
if (not ExecuteCommand('-data-list-register-values %s', [FormatChar[AFormat]], R)) or
|
||||||
|
(R.State = dsError)
|
||||||
|
then begin
|
||||||
|
for i := 0 to FRegisters.Count - 1 do
|
||||||
|
if FRegisters[i].DataValidity in [ddsRequested, ddsEvaluating] then
|
||||||
|
FRegisters[i].DataValidity := ddsInvalid;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
ValList := TGDBMINameValueList.Create('');
|
||||||
|
List := TGDBMINameValueList.Create(R, ['register-values']);
|
||||||
|
for i := 0 to List.Count - 1 do
|
||||||
|
begin
|
||||||
|
Item := List.Items[i];
|
||||||
|
ValList.Init(Item^.Name);
|
||||||
|
idx := StrToIntDef(Unquote(ValList.Values['number']), -1);
|
||||||
|
if (idx < 0) or (idx > High(FGDBMIRegSupplier.FRegNamesCache)) then Continue;
|
||||||
|
RegVal := FRegisters.EntriesByName[FGDBMIRegSupplier.FRegNamesCache[idx]];
|
||||||
|
if (RegVal.DataValidity = ddsValid) and (RegVal.HasValueFormat[AFormat]) then continue;
|
||||||
|
|
||||||
|
t := Unquote(ValList.Values['value']);
|
||||||
|
RegValObj := RegVal.ValueObjFormat[AFormat];
|
||||||
|
if (AFormat in [rdDefault, rdRaw]) or (RegValObj.SupportedDispFormats = [AFormat]) then
|
||||||
|
RegValObj.SetAsText(t);
|
||||||
|
Val(t, Num, NumErr);
|
||||||
|
if NumErr <> 0 then
|
||||||
|
RegValObj.SetAsText(t)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
RegValObj.SetAsNum(Num, FTheDebugger.TargetPtrSize);
|
||||||
|
RegValObj.AddFormats([rdBinary, rdDecimal, rdOctal, rdHex]);
|
||||||
|
end;
|
||||||
|
if AFormat = RegVal.DisplayFormat then
|
||||||
|
RegVal.DataValidity := ddsValid;
|
||||||
|
end;
|
||||||
|
FreeAndNil(List);
|
||||||
|
FreeAndNil(ValList);
|
||||||
|
|
||||||
|
end;
|
||||||
|
var
|
||||||
|
R: TGDBMIExecResult;
|
||||||
|
List: TGDBMINameValueList;
|
||||||
|
i, idx: Integer;
|
||||||
|
ChangedRegList: TGDBMINameValueList;
|
||||||
|
begin
|
||||||
|
Result := True;
|
||||||
|
DebugLn(['|||||||||||||| ', dbgs(FRegisters.DataValidity), ' ', FRegisters.StackFrame]);
|
||||||
|
if FRegisters.DataValidity = ddsEvaluating then // in process
|
||||||
|
exit;
|
||||||
|
|
||||||
|
FContext.ThreadContext := ccUseLocal;
|
||||||
|
FContext.StackContext := ccUseLocal;
|
||||||
|
FContext.ThreadId := FRegisters.ThreadId;
|
||||||
|
FContext.StackFrame := FRegisters.StackFrame;
|
||||||
|
|
||||||
|
FGDBMIRegSupplier.BeginUpdate;
|
||||||
|
try
|
||||||
|
if length(FGDBMIRegSupplier.FRegNamesCache) = 0 then begin
|
||||||
|
if (not ExecuteCommand('-data-list-register-names', R, [cfNoThreadContext, cfNoStackContext])) or
|
||||||
|
(R.State = dsError)
|
||||||
|
then begin
|
||||||
|
if FRegisters.DataValidity in [ddsRequested, ddsEvaluating] then
|
||||||
|
FRegisters.DataValidity := ddsInvalid;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
List := TGDBMINameValueList.Create(R, ['register-names']);
|
||||||
|
SetLength(FGDBMIRegSupplier.FRegNamesCache, List.Count);
|
||||||
|
for i := 0 to List.Count - 1 do
|
||||||
|
FGDBMIRegSupplier.FRegNamesCache[i] := UnQuote(List.GetString(i));
|
||||||
|
FreeAndNil(List);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
if FRegisters.DataValidity = ddsRequested then begin
|
||||||
|
ChangedRegList := nil;
|
||||||
|
if (FRegisters.StackFrame = 0) and // need modified, run before all others
|
||||||
|
ExecuteCommand('-data-list-changed-registers', R, [cfscIgnoreError]) and
|
||||||
|
(R.State <> dsError)
|
||||||
|
then
|
||||||
|
ChangedRegList := TGDBMINameValueList.Create(R, ['changed-registers']);
|
||||||
|
|
||||||
|
// Need all registers
|
||||||
|
FRegisters.DataValidity := ddsEvaluating;
|
||||||
|
UpdateFormat(rdDefault);
|
||||||
|
FRegisters.DataValidity := ddsValid;
|
||||||
|
|
||||||
|
if ChangedRegList <> nil then begin
|
||||||
|
for i := 0 to ChangedRegList.Count - 1 do begin
|
||||||
|
idx := StrToIntDef(Unquote(ChangedRegList.GetString(i)), -1);
|
||||||
|
if (idx < 0) or (idx > High(FGDBMIRegSupplier.FRegNamesCache)) then Continue;
|
||||||
|
FRegisters.EntriesByName[FGDBMIRegSupplier.FRegNamesCache[idx]].Modified := True;
|
||||||
|
end;
|
||||||
|
FreeAndNil(ChangedRegList);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// check for individual updates / displayformat
|
||||||
|
for i := 0 to FRegisters.Count - 1 do begin
|
||||||
|
if not FRegisters[i].HasValue then
|
||||||
|
UpdateFormat(FRegisters[i].DisplayFormat);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
FGDBMIRegSupplier.EndUpdate;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGDBMIDebuggerCommandRegisterUpdate.DoCancel;
|
||||||
|
begin
|
||||||
|
if FRegisters.DataValidity in [ddsRequested, ddsEvaluating] then
|
||||||
|
FRegisters.DataValidity := ddsInvalid;
|
||||||
|
inherited DoCancel;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TGDBMIDebuggerCommandRegisterUpdate.Create(AOwner: TGDBMIDebugger;
|
||||||
|
AGDBMIRegSupplier: TGDBMIRegisterSupplier; ARegisters: TRegisters);
|
||||||
|
begin
|
||||||
|
inherited Create(AOwner);
|
||||||
|
FGDBMIRegSupplier := AGDBMIRegSupplier;
|
||||||
|
FRegisters := ARegisters;
|
||||||
|
FRegisters.AddReference;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TGDBMIDebuggerCommandRegisterUpdate.Destroy;
|
||||||
|
begin
|
||||||
|
inherited Destroy;
|
||||||
|
FRegisters.ReleaseReference;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TGDBMIRegisterSupplier }
|
||||||
|
|
||||||
|
procedure TGDBMIRegisterSupplier.DoStateChange(const AOldState: TDBGState);
|
||||||
|
begin
|
||||||
|
if not( (AOldState in [dsPause, dsInternalPause]) and (Debugger.State in [dsPause, dsInternalPause]) )
|
||||||
|
then
|
||||||
|
SetLength(FRegNamesCache, 0);
|
||||||
|
inherited DoStateChange(AOldState);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGDBMIRegisterSupplier.Changed;
|
||||||
|
begin
|
||||||
|
if CurrentRegistersList <> nil
|
||||||
|
then CurrentRegistersList.Clear;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGDBMIRegisterSupplier.RequestData(ARegisters: TRegisters);
|
||||||
|
var
|
||||||
|
ForceQueue: Boolean;
|
||||||
|
Cmd: TGDBMIDebuggerCommandRegisterUpdate;
|
||||||
|
begin
|
||||||
|
if (Debugger = nil) or not(Debugger.State in [dsPause, dsStop]) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
Cmd := TGDBMIDebuggerCommandRegisterUpdate.Create(TGDBMIDebugger(Debugger), Self, ARegisters);
|
||||||
|
//Cmd.OnExecuted := @DoGetRegisterNamesFinished;
|
||||||
|
//Cmd.OnDestroy := @DoGetRegisterNamesDestroyed;
|
||||||
|
Cmd.Priority := GDCMD_PRIOR_LOCALS;
|
||||||
|
Cmd.Properties := [dcpCancelOnRun];
|
||||||
|
ForceQueue := (TGDBMIDebugger(Debugger).FCurrentCommand <> nil)
|
||||||
|
and (TGDBMIDebugger(Debugger).FCurrentCommand is TGDBMIDebuggerCommandExecute)
|
||||||
|
and (not TGDBMIDebuggerCommandExecute(TGDBMIDebugger(Debugger).FCurrentCommand).NextExecQueued)
|
||||||
|
and (Debugger.State <> dsInternalPause);
|
||||||
|
TGDBMIDebugger(Debugger).QueueCommand(Cmd, ForceQueue);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TGDBMIDebuggerChangeFilenameBase }
|
{ TGDBMIDebuggerChangeFilenameBase }
|
||||||
|
|
||||||
function TGDBMIDebuggerChangeFilenameBase.DoChangeFilename: Boolean;
|
function TGDBMIDebuggerChangeFilenameBase.DoChangeFilename: Boolean;
|
||||||
@ -3073,50 +3199,6 @@ begin
|
|||||||
Result := length(FThreads);
|
Result := length(FThreads);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TGDBMIDebuggerCommandRegisterModified }
|
|
||||||
|
|
||||||
function TGDBMIDebuggerCommandRegisterModified.DoExecute: Boolean;
|
|
||||||
var
|
|
||||||
R: TGDBMIExecResult;
|
|
||||||
List: TGDBMINameValueList;
|
|
||||||
n, idx: Integer;
|
|
||||||
begin
|
|
||||||
Result := True;
|
|
||||||
FContext.StackContext := ccNotRequired;
|
|
||||||
|
|
||||||
if length(FModifiedToUpdate) = 0
|
|
||||||
then exit;
|
|
||||||
|
|
||||||
for n := Low(FModifiedToUpdate) to High(FModifiedToUpdate) do
|
|
||||||
FModifiedToUpdate[n] := False;
|
|
||||||
|
|
||||||
ExecuteCommand('-data-list-changed-registers', R, [cfscIgnoreError]);
|
|
||||||
if R.State = dsError then Exit;
|
|
||||||
|
|
||||||
List := TGDBMINameValueList.Create(R, ['changed-registers']);
|
|
||||||
for n := 0 to List.Count - 1 do
|
|
||||||
begin
|
|
||||||
idx := StrToIntDef(Unquote(List.GetString(n)), -1);
|
|
||||||
if idx < Low(FModifiedToUpdate) then Continue;
|
|
||||||
if idx > High(FModifiedToUpdate) then Continue;
|
|
||||||
|
|
||||||
FModifiedToUpdate[idx] := True;
|
|
||||||
end;
|
|
||||||
FreeAndNil(List);
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TGDBMIDebuggerCommandRegisterModified.Create(AOwner: TGDBMIDebugger;
|
|
||||||
ModifiedToUpdate: TBoolArray);
|
|
||||||
begin
|
|
||||||
inherited Create(AOwner);
|
|
||||||
FModifiedToUpdate := ModifiedToUpdate;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TGDBMIDebuggerCommandRegisterModified.DebugText: String;
|
|
||||||
begin
|
|
||||||
Result := Format('%s: Reg-Cnt=%d', [ClassName, length(FModifiedToUpdate)]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TGDBMINameValueBasedList }
|
{ TGDBMINameValueBasedList }
|
||||||
|
|
||||||
constructor TGDBMINameValueBasedList.Create;
|
constructor TGDBMINameValueBasedList.Create;
|
||||||
@ -6368,92 +6450,6 @@ begin
|
|||||||
Result := Format('%s: Source=%s', [ClassName, FSource]);
|
Result := Format('%s: Source=%s', [ClassName, FSource]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TGDBMIDebuggerCommandRegisterValues }
|
|
||||||
|
|
||||||
function TGDBMIDebuggerCommandRegisterValues.DoExecute: Boolean;
|
|
||||||
const
|
|
||||||
// rdDefault, rdHex, rdBinary, rdOctal, rdDecimal, rdRaw
|
|
||||||
FormatChar : array [TRegisterDisplayFormat] of string =
|
|
||||||
('N', 'x', 't', 'o', 'd', 'r');
|
|
||||||
var
|
|
||||||
R: TGDBMIExecResult;
|
|
||||||
List, ValList: TGDBMINameValueList;
|
|
||||||
Item: PGDBMINameValue;
|
|
||||||
n, idx: Integer;
|
|
||||||
begin
|
|
||||||
Result := True;
|
|
||||||
//FContext.StackContext := ccNotRequired;
|
|
||||||
|
|
||||||
if length(FRegistersToUpdate) = 0
|
|
||||||
then exit;
|
|
||||||
|
|
||||||
for n := Low(FRegistersToUpdate) to High(FRegistersToUpdate) do
|
|
||||||
FRegistersToUpdate[n] := '';
|
|
||||||
|
|
||||||
ExecuteCommand('-data-list-register-values %s', [FormatChar[FFormat]], R);
|
|
||||||
if R.State = dsError then Exit;
|
|
||||||
|
|
||||||
|
|
||||||
ValList := TGDBMINameValueList.Create('');
|
|
||||||
List := TGDBMINameValueList.Create(R, ['register-values']);
|
|
||||||
for n := 0 to List.Count - 1 do
|
|
||||||
begin
|
|
||||||
Item := List.Items[n];
|
|
||||||
ValList.Init(Item^.Name);
|
|
||||||
idx := StrToIntDef(Unquote(ValList.Values['number']), -1);
|
|
||||||
if (idx >= Low(FRegistersToUpdate)) and
|
|
||||||
(idx <= High(FRegistersToUpdate))
|
|
||||||
then FRegistersToUpdate[idx] := Unquote(ValList.Values['value']);
|
|
||||||
end;
|
|
||||||
FreeAndNil(List);
|
|
||||||
FreeAndNil(ValList);
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TGDBMIDebuggerCommandRegisterValues.Create(AOwner: TGDBMIDebugger;
|
|
||||||
RegistersToUpdate: TStringArray; AFormat: TRegisterDisplayFormat = rdDefault);
|
|
||||||
begin
|
|
||||||
inherited Create(AOwner);
|
|
||||||
FRegistersToUpdate := RegistersToUpdate;
|
|
||||||
FFormat := AFormat;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TGDBMIDebuggerCommandRegisterValues.DebugText: String;
|
|
||||||
begin
|
|
||||||
Result := SysUtils.Format('%s: Reg-Cnt=%d', [ClassName, length(FRegistersToUpdate)]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TGDBMIDebuggerCommandRegisterNames }
|
|
||||||
|
|
||||||
function TGDBMIDebuggerCommandRegisterNames.GetNames(Index: Integer): string;
|
|
||||||
begin
|
|
||||||
Result := FNames[Index];
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TGDBMIDebuggerCommandRegisterNames.DoExecute: Boolean;
|
|
||||||
var
|
|
||||||
R: TGDBMIExecResult;
|
|
||||||
List: TGDBMINameValueList;
|
|
||||||
n: Integer;
|
|
||||||
begin
|
|
||||||
Result := True;
|
|
||||||
FContext.ThreadContext := ccNotRequired;
|
|
||||||
FContext.StackContext := ccNotRequired;
|
|
||||||
|
|
||||||
ExecuteCommand('-data-list-register-names', R);
|
|
||||||
if R.State = dsError then Exit;
|
|
||||||
|
|
||||||
List := TGDBMINameValueList.Create(R, ['register-names']);
|
|
||||||
SetLength(FNames, List.Count);
|
|
||||||
for n := 0 to List.Count - 1 do
|
|
||||||
FNames[n] := UnQuote(List.GetString(n));
|
|
||||||
FreeAndNil(List);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TGDBMIDebuggerCommandRegisterNames.Count: Integer;
|
|
||||||
begin
|
|
||||||
Result := length(FNames);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TGDBMIDebuggerCommandStackDepth }
|
{ TGDBMIDebuggerCommandStackDepth }
|
||||||
|
|
||||||
function TGDBMIDebuggerCommandStackDepth.DoExecute: Boolean;
|
function TGDBMIDebuggerCommandStackDepth.DoExecute: Boolean;
|
||||||
@ -7168,9 +7164,9 @@ begin
|
|||||||
Result := TGDBMIDebuggerProperties.Create;
|
Result := TGDBMIDebuggerProperties.Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TGDBMIDebugger.CreateRegisters: TDBGRegisters;
|
function TGDBMIDebugger.CreateRegisters: TRegisterSupplier;
|
||||||
begin
|
begin
|
||||||
Result := TGDBMIRegisters.Create(Self);
|
Result := TGDBMIRegisterSupplier.Create(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TGDBMIDebugger.CreateWatches: TWatchesSupplier;
|
function TGDBMIDebugger.CreateWatches: TWatchesSupplier;
|
||||||
@ -7381,7 +7377,8 @@ end;
|
|||||||
procedure TGDBMIDebugger.DoThreadChanged;
|
procedure TGDBMIDebugger.DoThreadChanged;
|
||||||
begin
|
begin
|
||||||
TGDBMICallstack(CallStack).DoThreadChanged;
|
TGDBMICallstack(CallStack).DoThreadChanged;
|
||||||
TGDBMIRegisters(Registers).Changed;
|
if Registers.CurrentRegistersList <> nil then
|
||||||
|
Registers.CurrentRegistersList.Clear;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TGDBMIDebugger.DoRelease;
|
procedure TGDBMIDebugger.DoRelease;
|
||||||
@ -9701,267 +9698,6 @@ end;
|
|||||||
|
|
||||||
{%endregion ^^^^^ BreakPoints ^^^^^ }
|
{%endregion ^^^^^ BreakPoints ^^^^^ }
|
||||||
|
|
||||||
{ =========================================================================== }
|
|
||||||
{ TGDBMIRegisters }
|
|
||||||
{ =========================================================================== }
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.Changed;
|
|
||||||
begin
|
|
||||||
Invalidate;
|
|
||||||
inherited Changed;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.DoStateChange(const AOldState: TDBGState);
|
|
||||||
begin
|
|
||||||
if Debugger <> nil
|
|
||||||
then begin
|
|
||||||
case Debugger.State of
|
|
||||||
dsPause: DoChange;
|
|
||||||
dsStop, dsInit:
|
|
||||||
begin
|
|
||||||
FRegistersReqState := esInvalid;
|
|
||||||
Invalidate;
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
Invalidate
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else Invalidate;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.Invalidate;
|
|
||||||
var
|
|
||||||
n: Integer;
|
|
||||||
i: TRegisterDisplayFormat;
|
|
||||||
begin
|
|
||||||
for n := Low(FRegModified) to High(FRegModified) do
|
|
||||||
FRegModified[n] := False;
|
|
||||||
for i := low(TRegisterDisplayFormat) to high(TRegisterDisplayFormat) do begin
|
|
||||||
for n := Low(FRegValues[i]) to High(FRegValues[i]) do
|
|
||||||
FRegValues[i][n] := '';
|
|
||||||
FValuesReqState[i] := esInvalid;
|
|
||||||
end;
|
|
||||||
FModifiedReqState := esInvalid;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TGDBMIRegisters.GetCount: Integer;
|
|
||||||
begin
|
|
||||||
if (Debugger <> nil)
|
|
||||||
and (Debugger.State = dsPause)
|
|
||||||
then RegistersNeeded;
|
|
||||||
|
|
||||||
Result := Length(FRegNames);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TGDBMIRegisters.GetModified(const AnIndex: Integer): Boolean;
|
|
||||||
begin
|
|
||||||
if (Debugger <> nil)
|
|
||||||
and (Debugger.State = dsPause)
|
|
||||||
and (FModifiedReqState <> esValid)
|
|
||||||
then ModifiedNeeded;
|
|
||||||
|
|
||||||
if (FModifiedReqState = esValid)
|
|
||||||
and (AnIndex >= Low(FRegModified))
|
|
||||||
and (AnIndex <= High(FRegModified))
|
|
||||||
then Result := FRegModified[AnIndex]
|
|
||||||
else Result := False;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TGDBMIRegisters.GetName(const AnIndex: Integer): String;
|
|
||||||
begin
|
|
||||||
if (Debugger <> nil)
|
|
||||||
and (Debugger.State = dsPause)
|
|
||||||
then RegistersNeeded;
|
|
||||||
|
|
||||||
if (FRegistersReqState = esValid)
|
|
||||||
and (AnIndex >= Low(FRegNames))
|
|
||||||
and (AnIndex <= High(FRegNames))
|
|
||||||
then Result := FRegNames[AnIndex]
|
|
||||||
else Result := '';
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TGDBMIRegisters.GetValue(const AnIndex: Integer): String;
|
|
||||||
begin
|
|
||||||
if (Debugger <> nil)
|
|
||||||
and (Debugger.State = dsPause)
|
|
||||||
then ValuesNeeded(Formats[AnIndex]);
|
|
||||||
|
|
||||||
if (FValuesReqState[FFormats[AnIndex]] = esValid)
|
|
||||||
and (FRegistersReqState = esValid)
|
|
||||||
and (AnIndex >= Low(FRegValues[Formats[AnIndex]]))
|
|
||||||
and (AnIndex <= High(FRegValues[Formats[AnIndex]]))
|
|
||||||
then Result := FRegValues[Formats[AnIndex]][AnIndex]
|
|
||||||
else Result := '';
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.DoGetRegisterNamesDestroyed(Sender: TObject);
|
|
||||||
begin
|
|
||||||
if FGetRegisterCmdObj = Sender
|
|
||||||
then FGetRegisterCmdObj := nil;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.DoGetRegisterNamesFinished(Sender: TObject);
|
|
||||||
var
|
|
||||||
Cmd: TGDBMIDebuggerCommandRegisterNames;
|
|
||||||
n: Integer;
|
|
||||||
f: TRegisterDisplayFormat;
|
|
||||||
begin
|
|
||||||
Cmd := TGDBMIDebuggerCommandRegisterNames(Sender);
|
|
||||||
|
|
||||||
SetLength(FRegNames, Cmd.Count);
|
|
||||||
SetLength(FRegModified, Cmd.Count);
|
|
||||||
SetLength(FFormats, Cmd.Count);
|
|
||||||
for f := low(TRegisterDisplayFormat) to high(TRegisterDisplayFormat) do begin
|
|
||||||
SetLength(FRegValues[f], Cmd.Count);
|
|
||||||
FValuesReqState[f] := esInvalid;
|
|
||||||
end;
|
|
||||||
FModifiedReqState := esInvalid;
|
|
||||||
for n := 0 to Cmd.Count - 1 do
|
|
||||||
begin
|
|
||||||
FRegNames[n] := Cmd.Names[n];
|
|
||||||
for f := low(TRegisterDisplayFormat) to high(TRegisterDisplayFormat) do
|
|
||||||
FRegValues[f][n] := '';
|
|
||||||
FRegModified[n] := False;
|
|
||||||
FFormats[n] := rdDefault;
|
|
||||||
end;
|
|
||||||
|
|
||||||
FGetRegisterCmdObj:= nil;
|
|
||||||
FRegistersReqState := esValid;
|
|
||||||
|
|
||||||
if not FInRegistersNeeded
|
|
||||||
then Changed;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.RegistersNeeded;
|
|
||||||
var
|
|
||||||
ForceQueue: Boolean;
|
|
||||||
begin
|
|
||||||
if (Debugger = nil) or (FRegistersReqState in [esRequested, esValid])
|
|
||||||
then Exit;
|
|
||||||
|
|
||||||
if (Debugger.State in [dsPause, dsStop])
|
|
||||||
then begin
|
|
||||||
FInRegistersNeeded := True;
|
|
||||||
FRegistersReqState := esRequested;
|
|
||||||
SetLength(FRegNames, 0);
|
|
||||||
|
|
||||||
FGetRegisterCmdObj := TGDBMIDebuggerCommandRegisterNames.Create(TGDBMIDebugger(Debugger));
|
|
||||||
FGetRegisterCmdObj.OnExecuted := @DoGetRegisterNamesFinished;
|
|
||||||
FGetRegisterCmdObj.OnDestroy := @DoGetRegisterNamesDestroyed;
|
|
||||||
FGetRegisterCmdObj.Priority := GDCMD_PRIOR_LOCALS;
|
|
||||||
FGetRegisterCmdObj.Properties := [dcpCancelOnRun];
|
|
||||||
ForceQueue := (TGDBMIDebugger(Debugger).FCurrentCommand <> nil)
|
|
||||||
and (TGDBMIDebugger(Debugger).FCurrentCommand is TGDBMIDebuggerCommandExecute)
|
|
||||||
and (not TGDBMIDebuggerCommandExecute(TGDBMIDebugger(Debugger).FCurrentCommand).NextExecQueued)
|
|
||||||
and (Debugger.State <> dsInternalPause);
|
|
||||||
TGDBMIDebugger(Debugger).QueueCommand(FGetRegisterCmdObj, ForceQueue);
|
|
||||||
(* DoEvaluationFinished may be called immediately at this point *)
|
|
||||||
FInRegistersNeeded := False;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TGDBMIRegisters.GetDebugger: TGDBMIDebugger;
|
|
||||||
begin
|
|
||||||
Result := TGDBMIDebugger(inherited Debugger);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.DoGetRegValuesDestroyed(Sender: TObject);
|
|
||||||
var
|
|
||||||
Cmd: TGDBMIDebuggerCommandRegisterValues;
|
|
||||||
begin
|
|
||||||
Cmd := TGDBMIDebuggerCommandRegisterValues(Sender);
|
|
||||||
if FGetValuesCmdObj[Cmd.Format] = Sender
|
|
||||||
then FGetValuesCmdObj[Cmd.Format] := nil;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.DoGetRegValuesFinished(Sender: TObject);
|
|
||||||
var
|
|
||||||
Cmd: TGDBMIDebuggerCommandRegisterValues;
|
|
||||||
begin
|
|
||||||
Cmd := TGDBMIDebuggerCommandRegisterValues(Sender);
|
|
||||||
FValuesReqState[Cmd.Format] := esValid;
|
|
||||||
FGetValuesCmdObj[Cmd.Format] := nil;
|
|
||||||
if not FInValuesNeeded[Cmd.Format]
|
|
||||||
then inherited Changed;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.ValuesNeeded(AFormat: TRegisterDisplayFormat);
|
|
||||||
var
|
|
||||||
ForceQueue: Boolean;
|
|
||||||
begin
|
|
||||||
if (Debugger <> nil) and (Debugger.State = dsPause)
|
|
||||||
then RegistersNeeded;
|
|
||||||
|
|
||||||
if (Debugger = nil)
|
|
||||||
or (not (Debugger.State in [dsPause, dsStop]))
|
|
||||||
or (FRegistersReqState <> esValid)
|
|
||||||
or (FValuesReqState[AFormat] in [esRequested, esValid])
|
|
||||||
or (Count = 0)
|
|
||||||
then Exit;
|
|
||||||
|
|
||||||
FInValuesNeeded[AFormat] := True;
|
|
||||||
FValuesReqState[AFormat] := esRequested;
|
|
||||||
|
|
||||||
FGetValuesCmdObj[AFormat] := TGDBMIDebuggerCommandRegisterValues.Create
|
|
||||||
(Debugger, FRegValues[AFormat], AFormat);
|
|
||||||
FGetValuesCmdObj[AFormat].OnExecuted := @DoGetRegValuesFinished;
|
|
||||||
FGetValuesCmdObj[AFormat].OnDestroy := @DoGetRegValuesDestroyed;
|
|
||||||
FGetValuesCmdObj[AFormat].Priority := GDCMD_PRIOR_LOCALS;
|
|
||||||
FGetValuesCmdObj[AFormat].Properties := [dcpCancelOnRun];
|
|
||||||
ForceQueue := (Debugger.FCurrentCommand <> nil)
|
|
||||||
and (Debugger.FCurrentCommand is TGDBMIDebuggerCommandExecute)
|
|
||||||
and (not TGDBMIDebuggerCommandExecute(Debugger.FCurrentCommand).NextExecQueued)
|
|
||||||
and (Debugger.State <> dsInternalPause);
|
|
||||||
Debugger.QueueCommand(FGetValuesCmdObj[AFormat], ForceQueue);
|
|
||||||
(* DoEvaluationFinished may be called immediately at this point *)
|
|
||||||
FInValuesNeeded[AFormat] := False;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.DoGetRegModifiedDestroyed(Sender: TObject);
|
|
||||||
begin
|
|
||||||
if FGetModifiedCmd = Sender
|
|
||||||
then FGetModifiedCmd := nil;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.DoGetRegModifiedFinished(Sender: TObject);
|
|
||||||
begin
|
|
||||||
FModifiedReqState := esValid;
|
|
||||||
FGetModifiedCmd := nil;
|
|
||||||
if not FInModifiedNeeded
|
|
||||||
then inherited Changed;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TGDBMIRegisters.ModifiedNeeded;
|
|
||||||
var
|
|
||||||
ForceQueue: Boolean;
|
|
||||||
begin
|
|
||||||
if (Debugger <> nil) and (Debugger.State = dsPause)
|
|
||||||
then RegistersNeeded;
|
|
||||||
|
|
||||||
if (Debugger = nil)
|
|
||||||
or (not (Debugger.State in [dsPause, dsStop]))
|
|
||||||
or (FRegistersReqState <> esValid)
|
|
||||||
or (FModifiedReqState in [esRequested, esValid])
|
|
||||||
or (Count = 0)
|
|
||||||
then Exit;
|
|
||||||
|
|
||||||
FInModifiedNeeded := True;
|
|
||||||
FModifiedReqState := esRequested;
|
|
||||||
|
|
||||||
FGetModifiedCmd := TGDBMIDebuggerCommandRegisterModified.Create(Debugger, FRegModified);
|
|
||||||
FGetModifiedCmd.OnExecuted := @DoGetRegModifiedFinished;
|
|
||||||
FGetModifiedCmd.OnDestroy := @DoGetRegModifiedDestroyed;
|
|
||||||
FGetModifiedCmd.Priority := GDCMD_PRIOR_LOCALS;
|
|
||||||
FGetModifiedCmd.Properties := [dcpCancelOnRun];
|
|
||||||
ForceQueue := (Debugger.FCurrentCommand <> nil)
|
|
||||||
and (Debugger.FCurrentCommand is TGDBMIDebuggerCommandExecute)
|
|
||||||
and (not TGDBMIDebuggerCommandExecute(Debugger.FCurrentCommand).NextExecQueued)
|
|
||||||
and (Debugger.State <> dsInternalPause);
|
|
||||||
Debugger.QueueCommand(FGetModifiedCmd, ForceQueue);
|
|
||||||
(* DoEvaluationFinished may be called immediately at this point *)
|
|
||||||
FInModifiedNeeded := False;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ =========================================================================== }
|
{ =========================================================================== }
|
||||||
{ TGDBMIWatches }
|
{ TGDBMIWatches }
|
||||||
{ =========================================================================== }
|
{ =========================================================================== }
|
||||||
@ -10204,7 +9940,6 @@ begin
|
|||||||
if TGDBMIDebugger(Debugger).FCurrentStackFrame = idx then Exit;
|
if TGDBMIDebugger(Debugger).FCurrentStackFrame = idx then Exit;
|
||||||
|
|
||||||
TGDBMIDebugger(Debugger).FCurrentStackFrame := idx;
|
TGDBMIDebugger(Debugger).FCurrentStackFrame := idx;
|
||||||
TGDBMIRegisters(Debugger.Registers).Changed;
|
|
||||||
if cs <> nil then
|
if cs <> nil then
|
||||||
cs.CurrentIndex := idx;
|
cs.CurrentIndex := idx;
|
||||||
end;
|
end;
|
||||||
|
|||||||
@ -867,8 +867,6 @@ type
|
|||||||
property OnChange;
|
property OnChange;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TLocals }
|
|
||||||
|
|
||||||
{ TIDELocals }
|
{ TIDELocals }
|
||||||
|
|
||||||
TIDELocals = class(TLocals)
|
TIDELocals = class(TLocals)
|
||||||
@ -1019,36 +1017,93 @@ type
|
|||||||
******************************************************************************
|
******************************************************************************
|
||||||
******************************************************************************}
|
******************************************************************************}
|
||||||
|
|
||||||
|
TRegistersMonitor = class;
|
||||||
|
|
||||||
|
TRegistersNotification = class(TDebuggerChangeNotification)
|
||||||
|
public
|
||||||
|
property OnChange;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TIDERegisterValue }
|
||||||
|
|
||||||
|
TIDERegisterValue = class(TRegisterValue)
|
||||||
|
protected
|
||||||
|
procedure DoDataValidityChanged(AnOldValidity: TDebuggerDataState); override;
|
||||||
|
procedure DoDisplayFormatChanged(AnOldFormat: TRegisterDisplayFormat); override;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TIDERegisters }
|
{ TIDERegisters }
|
||||||
|
|
||||||
TIDERegistersNotification = class(TDebuggerNotification)
|
TIDERegisters = class(TRegisters)
|
||||||
|
protected
|
||||||
|
function CreateEntry: TDbgEntityValue; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TCurrentIDERegisters }
|
||||||
|
|
||||||
|
TCurrentIDERegisters = class(TIDERegisters)
|
||||||
private
|
private
|
||||||
FOnChange: TNotifyEvent;
|
FMonitor: TRegistersMonitor;
|
||||||
|
procedure DoDataValidityChanged(AnOldValidity: TDebuggerDataState); override;
|
||||||
public
|
public
|
||||||
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
constructor Create(AMonitor: TRegistersMonitor; AThreadId, AStackFrame: Integer);
|
||||||
|
function Count: Integer; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
TIDERegisters = class(TBaseRegisters)
|
TIDERegistersList = class(TRegistersList)
|
||||||
private
|
private
|
||||||
FNotificationList: TList;
|
//function GetEntry(const AThreadId: Integer; const AStackFrame: Integer): TIDERegisters;
|
||||||
FMaster: TDBGRegisters;
|
//function GetEntryByIdx(const AnIndex: Integer): TIDERegisters;
|
||||||
procedure RegistersChanged(Sender: TObject);
|
|
||||||
procedure SetMaster(const AMaster: TDBGRegisters);
|
|
||||||
protected
|
protected
|
||||||
function GetModified(const AnIndex: Integer): Boolean; override;
|
//function CreateEntry(AThreadId, AStackFrame: Integer): TDbgEntityValuesList; override; // TIDERegisters
|
||||||
function GetName(const AnIndex: Integer): String; override;
|
//procedure DoAssign(AnOther: TDbgEntitiesThreadStackList); override; // Immutable
|
||||||
function GetValue(const AnIndex: Integer): String; override;
|
// XML
|
||||||
procedure SetFormat(const AnIndex: Integer; const AValue: TRegisterDisplayFormat); override;
|
public
|
||||||
|
//property EntriesByIdx[const AnIndex: Integer]: TIDERegisters read GetEntryByIdx;
|
||||||
|
//property Entries[const AThreadId: Integer; const AStackFrame: Integer]: TIDERegisters
|
||||||
|
// read GetEntry; default;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TCurrentIDERegistersList }
|
||||||
|
|
||||||
|
TCurrentIDERegistersList = class(TIDERegistersList)
|
||||||
|
private
|
||||||
|
FMonitor: TRegistersMonitor;
|
||||||
protected
|
protected
|
||||||
procedure NotifyChange;
|
procedure DoCleared; override;
|
||||||
|
function CreateEntry(AThreadId, AStackFrame: Integer): TRegisters; override; // TIDERegisters
|
||||||
|
public
|
||||||
|
constructor Create(AMonitor: TRegistersMonitor);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TRegistersMonitor }
|
||||||
|
|
||||||
|
TRegistersMonitor = class(TDebuggerDataMonitorEx)
|
||||||
|
private
|
||||||
|
FCurrentRegistersList: TCurrentIDERegistersList;
|
||||||
|
FNotificationList: TDebuggerChangeNotificationList;
|
||||||
|
FFlags: set of (rmNeedNotifyChange);
|
||||||
|
function GetSupplier: TRegisterSupplier;
|
||||||
|
procedure SetSupplier(const AValue: TRegisterSupplier);
|
||||||
|
protected
|
||||||
|
procedure DoStateEnterPause; override;
|
||||||
|
//procedure DoStateLeavePause; override;
|
||||||
|
procedure DoStateLeavePauseClean; override;
|
||||||
|
procedure DoEndUpdate; override;
|
||||||
|
procedure NotifyChange(ARegisters: TCurrentIDERegisters);
|
||||||
|
procedure DoNewSupplier; override;
|
||||||
|
procedure RequestData(ARegisters: TCurrentIDERegisters);
|
||||||
|
//function CreateSnapshot(CreateEmpty: Boolean = False): TObject; override;
|
||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure AddNotification(const ANotification: TIDERegistersNotification);
|
procedure Clear;
|
||||||
procedure RemoveNotification(const ANotification: TIDERegistersNotification);
|
procedure AddNotification(const ANotification: TRegistersNotification);
|
||||||
function Count: Integer; override;
|
procedure RemoveNotification(const ANotification: TRegistersNotification);
|
||||||
property Master: TDBGRegisters read FMaster write SetMaster;
|
property CurrentRegistersList: TCurrentIDERegistersList read FCurrentRegistersList;
|
||||||
|
//property Snapshots[AnID: Pointer]: TIDERegistersList read GetSnapshot;
|
||||||
|
property Supplier: TRegisterSupplier read GetSupplier write SetSupplier;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{%endregion ^^^^^ Register ^^^^^ }
|
{%endregion ^^^^^ Register ^^^^^ }
|
||||||
@ -3309,13 +3364,14 @@ begin
|
|||||||
inherited;
|
inherited;
|
||||||
FNotificationList := TDebuggerChangeNotificationList.Create;
|
FNotificationList := TDebuggerChangeNotificationList.Create;
|
||||||
FCurrentLocalsList := TCurrentLocalsList.Create(Self);
|
FCurrentLocalsList := TCurrentLocalsList.Create(Self);
|
||||||
|
FCurrentLocalsList.AddReference;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TLocalsMonitor.Destroy;
|
destructor TLocalsMonitor.Destroy;
|
||||||
begin
|
begin
|
||||||
FNotificationList.Clear;
|
FNotificationList.Clear;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
FreeAndNil(FCurrentLocalsList);
|
ReleaseRefAndNil(FCurrentLocalsList);
|
||||||
FreeAndNil(FNotificationList);
|
FreeAndNil(FNotificationList);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -6357,124 +6413,179 @@ end;
|
|||||||
(******************************************************************************)
|
(******************************************************************************)
|
||||||
(******************************************************************************)
|
(******************************************************************************)
|
||||||
|
|
||||||
{ =========================================================================== }
|
{ TIDERegisterValue }
|
||||||
{ TIDERegisters }
|
|
||||||
{ =========================================================================== }
|
|
||||||
|
|
||||||
procedure TIDERegisters.AddNotification(const ANotification: TIDERegistersNotification);
|
procedure TIDERegisterValue.DoDataValidityChanged(AnOldValidity: TDebuggerDataState);
|
||||||
|
begin
|
||||||
|
if (Owner <> nil) and (Owner is TCurrentIDERegisters) then
|
||||||
|
TCurrentIDERegisters(Owner).DoDataValidityChanged(AnOldValidity);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TIDERegisterValue.DoDisplayFormatChanged(AnOldFormat: TRegisterDisplayFormat);
|
||||||
|
begin
|
||||||
|
if not HasValueFormat[DisplayFormat] then begin
|
||||||
|
DataValidity := ddsRequested;
|
||||||
|
if (Owner <> nil) and (Owner is TCurrentIDERegisters) then
|
||||||
|
TCurrentIDERegisters(Owner).FMonitor.RequestData(TCurrentIDERegisters(Owner));
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if (Owner <> nil) and (Owner is TCurrentIDERegisters) then
|
||||||
|
TCurrentIDERegisters(Owner).FMonitor.NotifyChange(TCurrentIDERegisters(Owner));
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TIDERegisters }
|
||||||
|
|
||||||
|
function TIDERegisters.CreateEntry: TDbgEntityValue;
|
||||||
|
begin
|
||||||
|
Result := TIDERegisterValue.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TCurrentIDERegisters }
|
||||||
|
|
||||||
|
procedure TCurrentIDERegisters.DoDataValidityChanged(AnOldValidity: TDebuggerDataState);
|
||||||
|
begin
|
||||||
|
inherited DoDataValidityChanged(AnOldValidity);
|
||||||
|
if not( (DataValidity in [ddsRequested, ddsEvaluating]) and
|
||||||
|
(AnOldValidity in [ddsUnknown, ddsRequested, ddsEvaluating]) )
|
||||||
|
then
|
||||||
|
FMonitor.NotifyChange(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TCurrentIDERegisters.Create(AMonitor: TRegistersMonitor; AThreadId,
|
||||||
|
AStackFrame: Integer);
|
||||||
|
begin
|
||||||
|
FMonitor := AMonitor;
|
||||||
|
inherited Create(AThreadId, AStackFrame);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCurrentIDERegisters.Count: Integer;
|
||||||
|
begin
|
||||||
|
case DataValidity of
|
||||||
|
ddsUnknown: begin
|
||||||
|
AddReference;
|
||||||
|
try
|
||||||
|
Result := 0;
|
||||||
|
DataValidity := ddsRequested;
|
||||||
|
FMonitor.RequestData(Self); // Locals can be cleared, if debugger is "run" again
|
||||||
|
if DataValidity = ddsValid then Result := inherited Count();
|
||||||
|
finally
|
||||||
|
ReleaseReference;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
ddsRequested, ddsEvaluating: Result := 0;
|
||||||
|
ddsValid: Result := inherited Count;
|
||||||
|
ddsInvalid, ddsError: Result := 0;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TCurrentIDERegistersList }
|
||||||
|
|
||||||
|
procedure TCurrentIDERegistersList.DoCleared;
|
||||||
|
begin
|
||||||
|
inherited DoCleared;
|
||||||
|
FMonitor.NotifyChange(nil);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCurrentIDERegistersList.CreateEntry(AThreadId, AStackFrame: Integer): TRegisters;
|
||||||
|
begin
|
||||||
|
Result := TCurrentIDERegisters.Create(FMonitor, AThreadId, AStackFrame);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TCurrentIDERegistersList.Create(AMonitor: TRegistersMonitor);
|
||||||
|
begin
|
||||||
|
FMonitor := AMonitor;
|
||||||
|
inherited Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TRegistersMonitor }
|
||||||
|
|
||||||
|
function TRegistersMonitor.GetSupplier: TRegisterSupplier;
|
||||||
|
begin
|
||||||
|
Result := TRegisterSupplier(inherited Supplier);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegistersMonitor.SetSupplier(const AValue: TRegisterSupplier);
|
||||||
|
begin
|
||||||
|
inherited Supplier := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegistersMonitor.DoStateEnterPause;
|
||||||
|
begin
|
||||||
|
inherited DoStateEnterPause;
|
||||||
|
if CurrentRegistersList = nil then exit;
|
||||||
|
Clear;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegistersMonitor.DoStateLeavePauseClean;
|
||||||
|
begin
|
||||||
|
inherited DoStateLeavePauseClean;
|
||||||
|
if CurrentRegistersList = nil then exit;
|
||||||
|
Clear;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegistersMonitor.DoEndUpdate;
|
||||||
|
begin
|
||||||
|
inherited DoEndUpdate;
|
||||||
|
if rmNeedNotifyChange in FFlags then
|
||||||
|
NotifyChange(nil);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegistersMonitor.NotifyChange(ARegisters: TCurrentIDERegisters);
|
||||||
|
begin
|
||||||
|
if IsUpdating then begin
|
||||||
|
Include(FFlags, rmNeedNotifyChange);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
Exclude(FFlags, rmNeedNotifyChange);
|
||||||
|
FNotificationList.NotifyChange(ARegisters);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegistersMonitor.DoNewSupplier;
|
||||||
|
begin
|
||||||
|
inherited DoNewSupplier;
|
||||||
|
NotifyChange(nil);
|
||||||
|
if Supplier <> nil then
|
||||||
|
Supplier.CurrentRegistersList := FCurrentRegistersList;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegistersMonitor.RequestData(ARegisters: TCurrentIDERegisters);
|
||||||
|
begin
|
||||||
|
if Supplier <> nil
|
||||||
|
then Supplier.RequestData(ARegisters)
|
||||||
|
else ARegisters.DataValidity := ddsInvalid;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TRegistersMonitor.Create;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FNotificationList := TDebuggerChangeNotificationList.Create;
|
||||||
|
FCurrentRegistersList := TCurrentIDERegistersList.Create(Self);
|
||||||
|
FCurrentRegistersList.AddReference;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TRegistersMonitor.Destroy;
|
||||||
|
begin
|
||||||
|
FNotificationList.Clear;
|
||||||
|
inherited Destroy;
|
||||||
|
ReleaseRefAndNil(FCurrentRegistersList);
|
||||||
|
FreeAndNil(FNotificationList);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegistersMonitor.Clear;
|
||||||
|
begin
|
||||||
|
FCurrentRegistersList.Clear;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRegistersMonitor.AddNotification(const ANotification: TRegistersNotification);
|
||||||
begin
|
begin
|
||||||
FNotificationList.Add(ANotification);
|
FNotificationList.Add(ANotification);
|
||||||
ANotification.AddReference;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TIDERegisters.Create;
|
procedure TRegistersMonitor.RemoveNotification(const ANotification: TRegistersNotification);
|
||||||
begin
|
|
||||||
FNotificationList := TList.Create;
|
|
||||||
inherited Create;
|
|
||||||
FFormatList := TRegistersFormatList.Create;
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TIDERegisters.Destroy;
|
|
||||||
var
|
|
||||||
n: Integer;
|
|
||||||
begin
|
|
||||||
for n := FNotificationList.Count - 1 downto 0 do
|
|
||||||
TDebuggerNotification(FNotificationList[n]).ReleaseReference;
|
|
||||||
|
|
||||||
inherited;
|
|
||||||
|
|
||||||
FreeAndNil(FNotificationList);
|
|
||||||
FreeAndNil(FFormatList);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TIDERegisters.RegistersChanged(Sender: TObject);
|
|
||||||
begin
|
|
||||||
NotifyChange;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TIDERegisters.SetMaster(const AMaster: TDBGRegisters);
|
|
||||||
var
|
|
||||||
DoNotify: Boolean;
|
|
||||||
begin
|
|
||||||
if FMaster = AMaster then Exit;
|
|
||||||
|
|
||||||
if FMaster <> nil
|
|
||||||
then begin
|
|
||||||
FMaster.OnChange := nil;
|
|
||||||
FMaster.FormatList := nil;
|
|
||||||
DoNotify := FMaster.Count <> 0;
|
|
||||||
end
|
|
||||||
else DoNotify := False;
|
|
||||||
|
|
||||||
FMaster := AMaster;
|
|
||||||
|
|
||||||
if FMaster <> nil
|
|
||||||
then begin
|
|
||||||
FMaster.OnChange := @RegistersChanged;
|
|
||||||
FMaster.FormatList := FormatList;
|
|
||||||
DoNotify := DoNotify or (FMaster.Count <> 0);
|
|
||||||
end;
|
|
||||||
|
|
||||||
if DoNotify
|
|
||||||
then NotifyChange;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TIDERegisters.GetModified(const AnIndex: Integer): Boolean;
|
|
||||||
begin
|
|
||||||
if Master = nil
|
|
||||||
then Result := inherited GetModified(AnIndex)
|
|
||||||
else Result := Master.Modified[AnIndex];
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TIDERegisters.GetName(const AnIndex: Integer): String;
|
|
||||||
begin
|
|
||||||
if Master = nil
|
|
||||||
then Result := inherited GetName(AnIndex)
|
|
||||||
else Result := Master.Names[AnIndex];
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TIDERegisters.GetValue(const AnIndex: Integer): String;
|
|
||||||
begin
|
|
||||||
if Master = nil
|
|
||||||
then Result := inherited GetValue(AnIndex)
|
|
||||||
else Result := Master.Values[AnIndex];
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TIDERegisters.SetFormat(const AnIndex: Integer;
|
|
||||||
const AValue: TRegisterDisplayFormat);
|
|
||||||
begin
|
|
||||||
inherited SetFormat(AnIndex, AValue);
|
|
||||||
if Master <> nil
|
|
||||||
then Master.FormatChanged(AnIndex);
|
|
||||||
NotifyChange;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TIDERegisters.NotifyChange;
|
|
||||||
var
|
|
||||||
n: Integer;
|
|
||||||
Notification: TIDERegistersNotification;
|
|
||||||
begin
|
|
||||||
for n := 0 to FNotificationList.Count - 1 do
|
|
||||||
begin
|
|
||||||
Notification := TIDERegistersNotification(FNotificationList[n]);
|
|
||||||
if Assigned(Notification.FOnChange)
|
|
||||||
then Notification.FOnChange(Self);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TIDERegisters.RemoveNotification(const ANotification: TIDERegistersNotification);
|
|
||||||
begin
|
begin
|
||||||
FNotificationList.Remove(ANotification);
|
FNotificationList.Remove(ANotification);
|
||||||
ANotification.ReleaseReference;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TIDERegisters.Count: Integer;
|
|
||||||
begin
|
|
||||||
if Master = nil
|
|
||||||
then Result := 0
|
|
||||||
else Result := Master.Count;
|
|
||||||
end;
|
|
||||||
|
|
||||||
(******************************************************************************)
|
(******************************************************************************)
|
||||||
(******************************************************************************)
|
(******************************************************************************)
|
||||||
|
|||||||
@ -69,6 +69,8 @@ type
|
|||||||
FLocalsNotification: TLocalsNotification;
|
FLocalsNotification: TLocalsNotification;
|
||||||
FWatchesMonitor: TWatchesMonitor;
|
FWatchesMonitor: TWatchesMonitor;
|
||||||
FWatchesNotification: TWatchesNotification;
|
FWatchesNotification: TWatchesNotification;
|
||||||
|
FRegistersMonitor: TRegistersMonitor;
|
||||||
|
FRegistersNotification: TRegistersNotification;
|
||||||
FBreakPoints: TIDEBreakPoints;
|
FBreakPoints: TIDEBreakPoints;
|
||||||
FBreakpointsNotification: TIDEBreakPointsNotification;
|
FBreakpointsNotification: TIDEBreakPointsNotification;
|
||||||
function GetSnapshotNotification: TSnapshotNotification;
|
function GetSnapshotNotification: TSnapshotNotification;
|
||||||
@ -76,16 +78,19 @@ type
|
|||||||
function GetCallStackNotification: TCallStackNotification;
|
function GetCallStackNotification: TCallStackNotification;
|
||||||
function GetLocalsNotification: TLocalsNotification;
|
function GetLocalsNotification: TLocalsNotification;
|
||||||
function GetWatchesNotification: TWatchesNotification;
|
function GetWatchesNotification: TWatchesNotification;
|
||||||
|
function GetRegistersNotification: TRegistersNotification;
|
||||||
function GetBreakpointsNotification: TIDEBreakPointsNotification;
|
function GetBreakpointsNotification: TIDEBreakPointsNotification;
|
||||||
procedure SetSnapshotManager(const AValue: TSnapshotManager);
|
procedure SetSnapshotManager(const AValue: TSnapshotManager);
|
||||||
procedure SetThreadsMonitor(const AValue: TThreadsMonitor);
|
procedure SetThreadsMonitor(const AValue: TThreadsMonitor);
|
||||||
procedure SetCallStackMonitor(const AValue: TCallStackMonitor);
|
procedure SetCallStackMonitor(const AValue: TCallStackMonitor);
|
||||||
procedure SetLocalsMonitor(const AValue: TLocalsMonitor);
|
procedure SetLocalsMonitor(const AValue: TLocalsMonitor);
|
||||||
procedure SetWatchesMonitor(const AValue: TWatchesMonitor);
|
procedure SetWatchesMonitor(const AValue: TWatchesMonitor);
|
||||||
|
procedure SetRegistersMonitor(AValue: TRegistersMonitor);
|
||||||
procedure SetBreakPoints(const AValue: TIDEBreakPoints);
|
procedure SetBreakPoints(const AValue: TIDEBreakPoints);
|
||||||
protected
|
protected
|
||||||
procedure JumpToUnitSource(AnUnitInfo: TDebuggerUnitInfo; ALine: Integer);
|
procedure JumpToUnitSource(AnUnitInfo: TDebuggerUnitInfo; ALine: Integer);
|
||||||
procedure DoWatchesChanged; virtual; // called if the WatchesMonitor object was changed
|
procedure DoWatchesChanged; virtual; // called if the WatchesMonitor object was changed
|
||||||
|
procedure DoRegistersChanged; virtual; // called if the WatchesMonitor object was changed
|
||||||
procedure DoBreakPointsChanged; virtual; // called if the BreakPoint(Monitor) object was changed
|
procedure DoBreakPointsChanged; virtual; // called if the BreakPoint(Monitor) object was changed
|
||||||
function GetBreakPointImageIndex(ABreakPoint: TIDEBreakPoint; AIsCurLine: Boolean = False): Integer;
|
function GetBreakPointImageIndex(ABreakPoint: TIDEBreakPoint; AIsCurLine: Boolean = False): Integer;
|
||||||
property SnapshotNotification: TSnapshotNotification read GetSnapshotNotification;
|
property SnapshotNotification: TSnapshotNotification read GetSnapshotNotification;
|
||||||
@ -93,6 +98,7 @@ type
|
|||||||
property CallStackNotification: TCallStackNotification read GetCallStackNotification;
|
property CallStackNotification: TCallStackNotification read GetCallStackNotification;
|
||||||
property LocalsNotification: TLocalsNotification read GetLocalsNotification;
|
property LocalsNotification: TLocalsNotification read GetLocalsNotification;
|
||||||
property WatchesNotification: TWatchesNotification read GetWatchesNotification;
|
property WatchesNotification: TWatchesNotification read GetWatchesNotification;
|
||||||
|
property RegistersNotification: TRegistersNotification read GetRegistersNotification;
|
||||||
property BreakpointsNotification: TIDEBreakPointsNotification read GetBreakpointsNotification;
|
property BreakpointsNotification: TIDEBreakPointsNotification read GetBreakpointsNotification;
|
||||||
protected
|
protected
|
||||||
// publish as needed
|
// publish as needed
|
||||||
@ -101,6 +107,7 @@ type
|
|||||||
property CallStackMonitor: TCallStackMonitor read FCallStackMonitor write SetCallStackMonitor;
|
property CallStackMonitor: TCallStackMonitor read FCallStackMonitor write SetCallStackMonitor;
|
||||||
property LocalsMonitor: TLocalsMonitor read FLocalsMonitor write SetLocalsMonitor;
|
property LocalsMonitor: TLocalsMonitor read FLocalsMonitor write SetLocalsMonitor;
|
||||||
property WatchesMonitor: TWatchesMonitor read FWatchesMonitor write SetWatchesMonitor;
|
property WatchesMonitor: TWatchesMonitor read FWatchesMonitor write SetWatchesMonitor;
|
||||||
|
property RegistersMonitor: TRegistersMonitor read FRegistersMonitor write SetRegistersMonitor;
|
||||||
property BreakPoints: TIDEBreakPoints read FBreakPoints write SetBreakPoints;
|
property BreakPoints: TIDEBreakPoints read FBreakPoints write SetBreakPoints;
|
||||||
public
|
public
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -162,6 +169,17 @@ begin
|
|||||||
Result := FSnapshotNotification;
|
Result := FSnapshotNotification;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TDebuggerDlg.GetRegistersNotification: TRegistersNotification;
|
||||||
|
begin
|
||||||
|
If FRegistersNotification = nil then begin
|
||||||
|
FRegistersNotification := TRegistersNotification.Create;
|
||||||
|
FRegistersNotification.AddReference;
|
||||||
|
if (FRegistersMonitor <> nil)
|
||||||
|
then FRegistersMonitor.AddNotification(FRegistersNotification);
|
||||||
|
end;
|
||||||
|
Result := FRegistersNotification;
|
||||||
|
end;
|
||||||
|
|
||||||
function TDebuggerDlg.GetThreadsNotification: TThreadsNotification;
|
function TDebuggerDlg.GetThreadsNotification: TThreadsNotification;
|
||||||
begin
|
begin
|
||||||
if FThreadsNotification = nil then begin
|
if FThreadsNotification = nil then begin
|
||||||
@ -217,6 +235,22 @@ begin
|
|||||||
Result := FBreakpointsNotification;
|
Result := FBreakpointsNotification;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDebuggerDlg.SetRegistersMonitor(AValue: TRegistersMonitor);
|
||||||
|
begin
|
||||||
|
if FRegistersMonitor = AValue then exit;
|
||||||
|
BeginUpdate;
|
||||||
|
try
|
||||||
|
if (FRegistersMonitor <> nil) and (FRegistersNotification <> nil)
|
||||||
|
then FRegistersMonitor.RemoveNotification(FRegistersNotification);
|
||||||
|
FRegistersMonitor := AValue;
|
||||||
|
if (FRegistersMonitor <> nil) and (FRegistersNotification <> nil)
|
||||||
|
then FRegistersMonitor.AddNotification(FRegistersNotification);
|
||||||
|
DoRegistersChanged;
|
||||||
|
finally
|
||||||
|
EndUpdate;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDebuggerDlg.SetSnapshotManager(const AValue: TSnapshotManager);
|
procedure TDebuggerDlg.SetSnapshotManager(const AValue: TSnapshotManager);
|
||||||
begin
|
begin
|
||||||
if FSnapshotManager = AValue then exit;
|
if FSnapshotManager = AValue then exit;
|
||||||
@ -350,6 +384,11 @@ begin
|
|||||||
//
|
//
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDebuggerDlg.DoRegistersChanged;
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDebuggerDlg.DoBreakPointsChanged;
|
procedure TDebuggerDlg.DoBreakPointsChanged;
|
||||||
begin
|
begin
|
||||||
//
|
//
|
||||||
@ -438,6 +477,12 @@ begin
|
|||||||
SetWatchesMonitor(nil);
|
SetWatchesMonitor(nil);
|
||||||
ReleaseRefAndNil(FWatchesNotification);
|
ReleaseRefAndNil(FWatchesNotification);
|
||||||
|
|
||||||
|
if FRegistersNotification <> nil then begin;
|
||||||
|
FRegistersNotification.OnChange := nil;
|
||||||
|
end;
|
||||||
|
SetRegistersMonitor(nil);
|
||||||
|
ReleaseRefAndNil(FRegistersNotification);
|
||||||
|
|
||||||
if FBreakpointsNotification <> nil then begin;
|
if FBreakpointsNotification <> nil then begin;
|
||||||
FBreakpointsNotification.OnAdd := nil;
|
FBreakpointsNotification.OnAdd := nil;
|
||||||
FBreakpointsNotification.OnRemove := nil;
|
FBreakpointsNotification.OnRemove := nil;
|
||||||
|
|||||||
@ -80,14 +80,13 @@ type
|
|||||||
procedure DispDefaultClick(Sender: TObject);
|
procedure DispDefaultClick(Sender: TObject);
|
||||||
procedure lvRegistersSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
|
procedure lvRegistersSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
|
||||||
procedure ToolButtonDispTypeClick(Sender: TObject);
|
procedure ToolButtonDispTypeClick(Sender: TObject);
|
||||||
|
function GetCurrentRegisters: TRegisters;
|
||||||
private
|
private
|
||||||
FRegisters: TIDERegisters;
|
FNeedUpdateAgain: Boolean;
|
||||||
FRegistersNotification: TIDERegistersNotification;
|
|
||||||
FPowerImgIdx, FPowerImgIdxGrey: Integer;
|
FPowerImgIdx, FPowerImgIdxGrey: Integer;
|
||||||
procedure RegistersChanged(Sender: TObject);
|
procedure RegistersChanged(Sender: TObject);
|
||||||
procedure SetRegisters(const AValue: TIDERegisters);
|
|
||||||
function IndexOfName(AName: String): Integer;
|
|
||||||
protected
|
protected
|
||||||
|
procedure DoRegistersChanged; override;
|
||||||
procedure DoBeginUpdate; override;
|
procedure DoBeginUpdate; override;
|
||||||
procedure DoEndUpdate; override;
|
procedure DoEndUpdate; override;
|
||||||
function ColSizeGetter(AColId: Integer; var ASize: Integer): Boolean;
|
function ColSizeGetter(AColId: Integer; var ASize: Integer): Boolean;
|
||||||
@ -96,7 +95,10 @@ type
|
|||||||
constructor Create(AOwner: TComponent); override;
|
constructor Create(AOwner: TComponent); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
property Registers: TIDERegisters read FRegisters write SetRegisters;
|
property RegistersMonitor;
|
||||||
|
property ThreadsMonitor;
|
||||||
|
property CallStackMonitor;
|
||||||
|
//property SnapshotManager;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -132,9 +134,10 @@ var
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
inherited Create(AOwner);
|
inherited Create(AOwner);
|
||||||
FRegistersNotification := TIDERegistersNotification.Create;
|
ThreadsNotification.OnCurrent := @RegistersChanged;
|
||||||
FRegistersNotification.AddReference;
|
CallstackNotification.OnCurrent := @RegistersChanged;
|
||||||
FRegistersNotification.OnChange := @RegistersChanged;
|
RegistersNotification.OnChange := @RegistersChanged;
|
||||||
|
|
||||||
Caption:= lisRegisters;
|
Caption:= lisRegisters;
|
||||||
lvRegisters.Columns[0].Caption:= lisName;
|
lvRegisters.Columns[0].Caption:= lisName;
|
||||||
lvRegisters.Columns[1].Caption:= lisValue;
|
lvRegisters.Columns[1].Caption:= lisValue;
|
||||||
@ -190,9 +193,6 @@ end;
|
|||||||
|
|
||||||
destructor TRegistersDlg.Destroy;
|
destructor TRegistersDlg.Destroy;
|
||||||
begin
|
begin
|
||||||
SetRegisters(nil);
|
|
||||||
FRegistersNotification.OnChange := nil;
|
|
||||||
FRegistersNotification.ReleaseReference;
|
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -226,23 +226,23 @@ end;
|
|||||||
|
|
||||||
procedure TRegistersDlg.DispDefaultClick(Sender: TObject);
|
procedure TRegistersDlg.DispDefaultClick(Sender: TObject);
|
||||||
var
|
var
|
||||||
n, i: Integer;
|
n: Integer;
|
||||||
Item: TListItem;
|
Item: TListItem;
|
||||||
|
Reg: TRegisters;
|
||||||
|
RegVal: TRegisterValue;
|
||||||
begin
|
begin
|
||||||
ToolButtonPower.Down := True;
|
ToolButtonPower.Down := True;
|
||||||
FRegisters.BeginUpdate;
|
Reg := GetCurrentRegisters;
|
||||||
try
|
if Reg = nil then exit;
|
||||||
for n := 0 to lvRegisters.Items.Count -1 do
|
|
||||||
begin
|
for n := 0 to lvRegisters.Items.Count -1 do
|
||||||
Item := lvRegisters.Items[n];
|
begin
|
||||||
if Item.Selected then begin
|
Item := lvRegisters.Items[n];
|
||||||
i := IndexOfName(Item.Caption);
|
if Item.Selected then begin
|
||||||
if i >= 0
|
RegVal := Reg.EntriesByName[Item.Caption];
|
||||||
then FRegisters.Formats[i] := TRegisterDisplayFormat(TMenuItem(Sender).Tag);
|
if RegVal <> nil then
|
||||||
end;
|
RegVal.DisplayFormat := TRegisterDisplayFormat(TMenuItem(Sender).Tag);
|
||||||
end;
|
end;
|
||||||
finally
|
|
||||||
FRegisters.EndUpdate;
|
|
||||||
end;
|
end;
|
||||||
lvRegistersSelectItem(nil, nil, True);
|
lvRegistersSelectItem(nil, nil, True);
|
||||||
end;
|
end;
|
||||||
@ -250,23 +250,28 @@ end;
|
|||||||
procedure TRegistersDlg.lvRegistersSelectItem(Sender: TObject; Item: TListItem;
|
procedure TRegistersDlg.lvRegistersSelectItem(Sender: TObject; Item: TListItem;
|
||||||
Selected: Boolean);
|
Selected: Boolean);
|
||||||
var
|
var
|
||||||
n, i, j: Integer;
|
n, j: Integer;
|
||||||
SelFormat: TRegisterDisplayFormat;
|
SelFormat: TRegisterDisplayFormat;
|
||||||
MultiFormat: Boolean;
|
MultiFormat: Boolean;
|
||||||
|
Reg: TRegisters;
|
||||||
|
RegVal: TRegisterValue;
|
||||||
begin
|
begin
|
||||||
j := 0;
|
j := 0;
|
||||||
MultiFormat := False;
|
MultiFormat := False;
|
||||||
SelFormat := rdDefault;
|
SelFormat := rdDefault;
|
||||||
|
Reg := GetCurrentRegisters;
|
||||||
|
if Reg = nil then exit;
|
||||||
|
|
||||||
for n := 0 to lvRegisters.Items.Count -1 do
|
for n := 0 to lvRegisters.Items.Count -1 do
|
||||||
begin
|
begin
|
||||||
Item := lvRegisters.Items[n];
|
Item := lvRegisters.Items[n];
|
||||||
if Item.Selected then begin
|
if Item.Selected then begin
|
||||||
i := IndexOfName(Item.Caption);
|
RegVal := Reg.EntriesByName[Item.Caption];
|
||||||
if i >= 0 then begin
|
if RegVal <> nil then begin
|
||||||
if j = 0
|
if j = 0
|
||||||
then SelFormat := FRegisters.Formats[i];
|
then SelFormat := RegVal.DisplayFormat;
|
||||||
inc(j);
|
inc(j);
|
||||||
if SelFormat <> FRegisters.Formats[i] then begin
|
if SelFormat <> RegVal.DisplayFormat then begin
|
||||||
MultiFormat := True;
|
MultiFormat := True;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
@ -321,25 +326,53 @@ begin
|
|||||||
ToolButtonDispType.CheckMenuDropdown;
|
ToolButtonDispType.CheckMenuDropdown;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TRegistersDlg.GetCurrentRegisters: TRegisters;
|
||||||
|
var
|
||||||
|
CurThreadId, CurStackFrame: Integer;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
if (ThreadsMonitor = nil) or
|
||||||
|
(ThreadsMonitor.CurrentThreads = nil) or
|
||||||
|
(CallStackMonitor = nil) or
|
||||||
|
(CallStackMonitor.CurrentCallStackList = nil) or
|
||||||
|
(RegistersMonitor = nil)
|
||||||
|
then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
CurThreadId := ThreadsMonitor.CurrentThreads.CurrentThreadId;
|
||||||
|
if (CallStackMonitor.CurrentCallStackList.EntriesForThreads[CurThreadId] = nil) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
CurStackFrame := CallStackMonitor.CurrentCallStackList.EntriesForThreads[CurThreadId].CurrentIndex;
|
||||||
|
Result := RegistersMonitor.CurrentRegistersList[CurThreadId, CurStackFrame];
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TRegistersDlg.RegistersChanged(Sender: TObject);
|
procedure TRegistersDlg.RegistersChanged(Sender: TObject);
|
||||||
var
|
var
|
||||||
n, idx: Integer;
|
n, idx, Cnt: Integer;
|
||||||
List: TStringList;
|
List: TStringList;
|
||||||
Item: TListItem;
|
Item: TListItem;
|
||||||
S: String;
|
S: String;
|
||||||
|
Reg: TRegisters;
|
||||||
begin
|
begin
|
||||||
if (not ToolButtonPower.Down) then exit;
|
if (not ToolButtonPower.Down) then exit;
|
||||||
|
|
||||||
|
if IsUpdating then begin
|
||||||
|
FNeedUpdateAgain := True;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
FNeedUpdateAgain := False;
|
||||||
|
|
||||||
|
Reg := GetCurrentRegisters;
|
||||||
|
if Reg = nil then begin
|
||||||
|
lvRegisters.Items.Clear;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
List := TStringList.Create;
|
List := TStringList.Create;
|
||||||
try
|
try
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
try
|
try
|
||||||
if FRegisters = nil
|
|
||||||
then begin
|
|
||||||
lvRegisters.Items.Clear;
|
|
||||||
Exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
//Get existing items
|
//Get existing items
|
||||||
for n := 0 to lvRegisters.Items.Count - 1 do
|
for n := 0 to lvRegisters.Items.Count - 1 do
|
||||||
begin
|
begin
|
||||||
@ -350,23 +383,26 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// add/update entries
|
// add/update entries
|
||||||
for n := 0 to FRegisters.Count - 1 do
|
Cnt := Reg.Count; // Count may trigger changes
|
||||||
|
FNeedUpdateAgain := False; // changes after this point, and we must update again
|
||||||
|
|
||||||
|
for n := 0 to Cnt - 1 do
|
||||||
begin
|
begin
|
||||||
idx := List.IndexOf(Uppercase(FRegisters.Names[n]));
|
idx := List.IndexOf(Uppercase(Reg[n].Name));
|
||||||
if idx = -1
|
if idx = -1
|
||||||
then begin
|
then begin
|
||||||
// New entry
|
// New entry
|
||||||
Item := lvRegisters.Items.Add;
|
Item := lvRegisters.Items.Add;
|
||||||
Item.Caption := FRegisters.Names[n];
|
Item.Caption := Reg[n].Name;
|
||||||
Item.SubItems.Add(FRegisters.Values[n]);
|
Item.SubItems.Add(Reg[n].Value);
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
// Existing entry
|
// Existing entry
|
||||||
Item := TListItem(List.Objects[idx]);
|
Item := TListItem(List.Objects[idx]);
|
||||||
Item.SubItems[0] := FRegisters.Values[n];
|
Item.SubItems[0] := Reg[n].Value;
|
||||||
List.Delete(idx);
|
List.Delete(idx);
|
||||||
end;
|
end;
|
||||||
if FRegisters.Modified[n]
|
if Reg[n].Modified
|
||||||
then Item.ImageIndex := 0
|
then Item.ImageIndex := 0
|
||||||
else Item.ImageIndex := -1;
|
else Item.ImageIndex := -1;
|
||||||
end;
|
end;
|
||||||
@ -381,37 +417,13 @@ begin
|
|||||||
finally
|
finally
|
||||||
List.Free;
|
List.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
lvRegistersSelectItem(nil, nil, True);
|
lvRegistersSelectItem(nil, nil, True);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TRegistersDlg.SetRegisters(const AValue: TIDERegisters);
|
procedure TRegistersDlg.DoRegistersChanged;
|
||||||
begin
|
begin
|
||||||
if FRegisters = AValue then Exit;
|
RegistersChanged(nil);
|
||||||
|
|
||||||
BeginUpdate;
|
|
||||||
try
|
|
||||||
if FRegisters <> nil
|
|
||||||
then begin
|
|
||||||
FRegisters.RemoveNotification(FRegistersNotification);
|
|
||||||
end;
|
|
||||||
|
|
||||||
FRegisters := AValue;
|
|
||||||
|
|
||||||
if FRegisters <> nil
|
|
||||||
then begin
|
|
||||||
FRegisters.AddNotification(FRegistersNotification);
|
|
||||||
end;
|
|
||||||
|
|
||||||
RegistersChanged(FRegisters);
|
|
||||||
finally
|
|
||||||
EndUpdate;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TRegistersDlg.IndexOfName(AName: String): Integer;
|
|
||||||
begin
|
|
||||||
Result := FRegisters.Count - 1;
|
|
||||||
while (Result >= 0) and (FRegisters.Names[Result] <> AName) do dec(Result);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TRegistersDlg.DoBeginUpdate;
|
procedure TRegistersDlg.DoBeginUpdate;
|
||||||
@ -422,6 +434,7 @@ end;
|
|||||||
procedure TRegistersDlg.DoEndUpdate;
|
procedure TRegistersDlg.DoEndUpdate;
|
||||||
begin
|
begin
|
||||||
lvRegisters.EndUpdate;
|
lvRegisters.EndUpdate;
|
||||||
|
if FNeedUpdateAgain then RegistersChanged(nil);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TRegistersDlg.ColSizeGetter(AColId: Integer; var ASize: Integer): Boolean;
|
function TRegistersDlg.ColSizeGetter(AColId: Integer; var ASize: Integer): Boolean;
|
||||||
|
|||||||
@ -117,7 +117,7 @@ type
|
|||||||
FLineInfo: TIDELineInfo;
|
FLineInfo: TIDELineInfo;
|
||||||
FWatches: TWatchesMonitor;
|
FWatches: TWatchesMonitor;
|
||||||
FThreads: TThreadsMonitor;
|
FThreads: TThreadsMonitor;
|
||||||
FRegisters: TIDERegisters;
|
FRegisters: TRegistersMonitor;
|
||||||
FSnapshots: TSnapshotManager;
|
FSnapshots: TSnapshotManager;
|
||||||
FManagerStates: TDebugManagerStates;
|
FManagerStates: TDebugManagerStates;
|
||||||
function GetState: TDBGState; virtual; abstract;
|
function GetState: TDBGState; virtual; abstract;
|
||||||
@ -220,7 +220,7 @@ type
|
|||||||
property Disassembler: TIDEDisassembler read FDisassembler;
|
property Disassembler: TIDEDisassembler read FDisassembler;
|
||||||
property Locals: TLocalsMonitor read FLocals;
|
property Locals: TLocalsMonitor read FLocals;
|
||||||
property LineInfo: TIDELineInfo read FLineInfo;
|
property LineInfo: TIDELineInfo read FLineInfo;
|
||||||
property Registers: TIDERegisters read FRegisters;
|
property Registers: TRegistersMonitor 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
|
||||||
property Watches: TWatchesMonitor read FWatches;
|
property Watches: TWatchesMonitor read FWatches;
|
||||||
property Threads: TThreadsMonitor read FThreads;
|
property Threads: TThreadsMonitor read FThreads;
|
||||||
|
|||||||
@ -1583,7 +1583,9 @@ var
|
|||||||
TheDialog: TRegistersDlg;
|
TheDialog: TRegistersDlg;
|
||||||
begin
|
begin
|
||||||
TheDialog := TRegistersDlg(FDialogs[ddtRegisters]);
|
TheDialog := TRegistersDlg(FDialogs[ddtRegisters]);
|
||||||
TheDialog.Registers := FRegisters;
|
TheDialog.ThreadsMonitor := FThreads;
|
||||||
|
TheDialog.CallStackMonitor := FCallStack;
|
||||||
|
TheDialog.RegistersMonitor := FRegisters;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDebugManager.InitAssemblerDlg;
|
procedure TDebugManager.InitAssemblerDlg;
|
||||||
@ -1663,7 +1665,7 @@ begin
|
|||||||
FLineInfo := TIDELineInfo.Create;
|
FLineInfo := TIDELineInfo.Create;
|
||||||
FCallStack := TCallStackMonitor.Create;
|
FCallStack := TCallStackMonitor.Create;
|
||||||
FDisassembler := TIDEDisassembler.Create;
|
FDisassembler := TIDEDisassembler.Create;
|
||||||
FRegisters := TIDERegisters.Create;
|
FRegisters := TRegistersMonitor.Create;
|
||||||
|
|
||||||
FSnapshots := TSnapshotManager.Create;
|
FSnapshots := TSnapshotManager.Create;
|
||||||
FSnapshots.Threads := FThreads;
|
FSnapshots.Threads := FThreads;
|
||||||
@ -2955,7 +2957,7 @@ begin
|
|||||||
FCallStack.Supplier := nil;
|
FCallStack.Supplier := nil;
|
||||||
FDisassembler.Master := nil;
|
FDisassembler.Master := nil;
|
||||||
FSignals.Master := nil;
|
FSignals.Master := nil;
|
||||||
FRegisters.Master := nil;
|
FRegisters.Supplier := nil;
|
||||||
FSnapshots.Debugger := nil;
|
FSnapshots.Debugger := nil;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
@ -2969,7 +2971,7 @@ begin
|
|||||||
FCallStack.UnitInfoProvider := FUnitInfoProvider;
|
FCallStack.UnitInfoProvider := FUnitInfoProvider;
|
||||||
FDisassembler.Master := FDebugger.Disassembler;
|
FDisassembler.Master := FDebugger.Disassembler;
|
||||||
FSignals.Master := FDebugger.Signals;
|
FSignals.Master := FDebugger.Signals;
|
||||||
FRegisters.Master := FDebugger.Registers;
|
FRegisters.Supplier := FDebugger.Registers;
|
||||||
FSnapshots.Debugger := FDebugger;
|
FSnapshots.Debugger := FDebugger;
|
||||||
|
|
||||||
FDebugger.Exceptions := FExceptions;
|
FDebugger.Exceptions := FExceptions;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user