mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-22 12:39:23 +02:00
FpDebugServer: Added locals command
git-svn-id: trunk@49370 -
This commit is contained in:
parent
8d3d8a4032
commit
6d32f521e9
@ -137,8 +137,8 @@ function TJSonInOutputProcessor.EventToText(AnEvent: TFpDebugEvent): string;
|
|||||||
var
|
var
|
||||||
JSonEvent: TJSONObject;
|
JSonEvent: TJSONObject;
|
||||||
JSonLocationRec: TJSONObject;
|
JSonLocationRec: TJSONObject;
|
||||||
JSonStackArray: TJSONArray;
|
JSonArray: TJSONArray;
|
||||||
JSonStackEntry: TJSONObject;
|
JSonArrayEntry: TJSONObject;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
JSonEvent := TJSONObject.Create;
|
JSonEvent := TJSONObject.Create;
|
||||||
@ -192,41 +192,53 @@ begin
|
|||||||
JSonEvent.Add('message',AnEvent.Message);
|
JSonEvent.Add('message',AnEvent.Message);
|
||||||
if length(AnEvent.StackEntryArray)>0 then
|
if length(AnEvent.StackEntryArray)>0 then
|
||||||
begin
|
begin
|
||||||
JSonStackArray := TJSONArray.Create;
|
JSonArray := TJSONArray.Create;
|
||||||
for i := 0 to high(AnEvent.StackEntryArray) do
|
for i := 0 to high(AnEvent.StackEntryArray) do
|
||||||
begin
|
begin
|
||||||
JSonStackEntry := TJSONObject.Create;
|
JSonArrayEntry := TJSONObject.Create;
|
||||||
JSonStackEntry.Add('address', FormatAddress(AnEvent.StackEntryArray[i].AnAddress));
|
JSonArrayEntry.Add('address', FormatAddress(AnEvent.StackEntryArray[i].AnAddress));
|
||||||
JSonStackEntry.Add('frameaddress', FormatAddress(AnEvent.StackEntryArray[i].FrameAdress));
|
JSonArrayEntry.Add('frameaddress', FormatAddress(AnEvent.StackEntryArray[i].FrameAdress));
|
||||||
JSonStackEntry.Add('sourcefile', AnEvent.StackEntryArray[i].SourceFile);
|
JSonArrayEntry.Add('sourcefile', AnEvent.StackEntryArray[i].SourceFile);
|
||||||
JSonStackEntry.Add('line', AnEvent.StackEntryArray[i].Line);
|
JSonArrayEntry.Add('line', AnEvent.StackEntryArray[i].Line);
|
||||||
JSonStackEntry.Add('functionname', AnEvent.StackEntryArray[i].FunctionName);
|
JSonArrayEntry.Add('functionname', AnEvent.StackEntryArray[i].FunctionName);
|
||||||
JSonStackArray.Add(JSonStackEntry);
|
JSonArray.Add(JSonArrayEntry);
|
||||||
end;
|
end;
|
||||||
JSonEvent.Add('callstack', JSonStackArray);
|
JSonEvent.Add('callstack', JSonArray);
|
||||||
end;
|
end;
|
||||||
if length(AnEvent.DisassemblerEntryArray)>0 then
|
if length(AnEvent.DisassemblerEntryArray)>0 then
|
||||||
begin
|
begin
|
||||||
JSonStackArray := TJSONArray.Create;
|
JSonArray := TJSONArray.Create;
|
||||||
for i := 0 to high(AnEvent.DisassemblerEntryArray) do
|
for i := 0 to high(AnEvent.DisassemblerEntryArray) do
|
||||||
begin
|
begin
|
||||||
JSonStackEntry := TJSONObject.Create;
|
JSonArrayEntry := TJSONObject.Create;
|
||||||
JSonStackEntry.Add('address', FormatAddress(AnEvent.DisassemblerEntryArray[i].Addr));
|
JSonArrayEntry.Add('address', FormatAddress(AnEvent.DisassemblerEntryArray[i].Addr));
|
||||||
JSonStackEntry.Add('dump', AnEvent.DisassemblerEntryArray[i].Dump);
|
JSonArrayEntry.Add('dump', AnEvent.DisassemblerEntryArray[i].Dump);
|
||||||
JSonStackEntry.Add('statement', AnEvent.DisassemblerEntryArray[i].Statement);
|
JSonArrayEntry.Add('statement', AnEvent.DisassemblerEntryArray[i].Statement);
|
||||||
JSonStackEntry.Add('srcfilename', AnEvent.DisassemblerEntryArray[i].SrcFileName);
|
JSonArrayEntry.Add('srcfilename', AnEvent.DisassemblerEntryArray[i].SrcFileName);
|
||||||
JSonStackEntry.Add('srcfileline', AnEvent.DisassemblerEntryArray[i].SrcFileLine);
|
JSonArrayEntry.Add('srcfileline', AnEvent.DisassemblerEntryArray[i].SrcFileLine);
|
||||||
JSonStackEntry.Add('srcstatementindex', AnEvent.DisassemblerEntryArray[i].SrcStatementIndex);
|
JSonArrayEntry.Add('srcstatementindex', AnEvent.DisassemblerEntryArray[i].SrcStatementIndex);
|
||||||
JSonStackEntry.Add('srcstatementcount', AnEvent.DisassemblerEntryArray[i].SrcStatementCount);
|
JSonArrayEntry.Add('srcstatementcount', AnEvent.DisassemblerEntryArray[i].SrcStatementCount);
|
||||||
JSonStackEntry.Add('functionname', AnEvent.DisassemblerEntryArray[i].FuncName);
|
JSonArrayEntry.Add('functionname', AnEvent.DisassemblerEntryArray[i].FuncName);
|
||||||
JSonStackEntry.Add('offset', AnEvent.DisassemblerEntryArray[i].Offset);
|
JSonArrayEntry.Add('offset', AnEvent.DisassemblerEntryArray[i].Offset);
|
||||||
JSonStackArray.Add(JSonStackEntry);
|
JSonArray.Add(JSonArrayEntry);
|
||||||
end;
|
end;
|
||||||
JSonEvent.Add('disassembly', JSonStackArray);
|
JSonEvent.Add('disassembly', JSonArray);
|
||||||
JSonEvent.Add('startaddress', FormatAddress(AnEvent.Addr1));
|
JSonEvent.Add('startaddress', FormatAddress(AnEvent.Addr1));
|
||||||
JSonEvent.Add('endaddress', FormatAddress(AnEvent.Addr2));
|
JSonEvent.Add('endaddress', FormatAddress(AnEvent.Addr2));
|
||||||
JSonEvent.Add('lastentryendaddress', FormatAddress(AnEvent.Addr3));
|
JSonEvent.Add('lastentryendaddress', FormatAddress(AnEvent.Addr3));
|
||||||
end;
|
end;
|
||||||
|
if length(AnEvent.WatchEntryArray)>0 then
|
||||||
|
begin
|
||||||
|
JSonArray := TJSONArray.Create;
|
||||||
|
for i := 0 to high(AnEvent.WatchEntryArray) do
|
||||||
|
begin
|
||||||
|
JSonArrayEntry := TJSONObject.Create;
|
||||||
|
JSonArrayEntry.Add('name', AnEvent.WatchEntryArray[i].Expression);
|
||||||
|
JSonArrayEntry.Add('value', AnEvent.WatchEntryArray[i].TextValue);
|
||||||
|
JSonArray.Add(JSonArrayEntry);
|
||||||
|
end;
|
||||||
|
JSonEvent.Add('variables', JSonArray);
|
||||||
|
end;
|
||||||
result := JSonEvent.AsJSON;
|
result := JSonEvent.AsJSON;
|
||||||
finally
|
finally
|
||||||
JSonEvent.Free;
|
JSonEvent.Free;
|
||||||
|
@ -48,8 +48,14 @@ type
|
|||||||
FunctionName: string;
|
FunctionName: string;
|
||||||
Line: integer;
|
Line: integer;
|
||||||
end;
|
end;
|
||||||
|
TFpDebugEventWatchEntry = record
|
||||||
|
TextValue: string;
|
||||||
|
Expression: string;
|
||||||
|
end;
|
||||||
|
|
||||||
TFpDebugEventCallStackEntryArray = array of TFpDebugEventCallStackEntry;
|
TFpDebugEventCallStackEntryArray = array of TFpDebugEventCallStackEntry;
|
||||||
TFpDebugEventDisassemblerEntryArray = array of TDisassemblerEntry;
|
TFpDebugEventDisassemblerEntryArray = array of TDisassemblerEntry;
|
||||||
|
TFpDebugEventWatchEntryArray = array of TFpDebugEventWatchEntry;
|
||||||
|
|
||||||
// This record is used to pass debugging-events. Not every field is applicable for each type of event.
|
// This record is used to pass debugging-events. Not every field is applicable for each type of event.
|
||||||
TFpDebugEvent = record
|
TFpDebugEvent = record
|
||||||
@ -69,6 +75,7 @@ type
|
|||||||
Addr3: TDBGPtr;
|
Addr3: TDBGPtr;
|
||||||
StackEntryArray: TFpDebugEventCallStackEntryArray;
|
StackEntryArray: TFpDebugEventCallStackEntryArray;
|
||||||
DisassemblerEntryArray: TFpDebugEventDisassemblerEntryArray;
|
DisassemblerEntryArray: TFpDebugEventDisassemblerEntryArray;
|
||||||
|
WatchEntryArray: TFpDebugEventWatchEntryArray;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Each listener should implement this interface.
|
// Each listener should implement this interface.
|
||||||
@ -323,6 +330,7 @@ begin
|
|||||||
AnEvent.Validity:=ddsUnknown;
|
AnEvent.Validity:=ddsUnknown;
|
||||||
SetLength(AnEvent.StackEntryArray,0);
|
SetLength(AnEvent.StackEntryArray,0);
|
||||||
SetLength(AnEvent.DisassemblerEntryArray,0);
|
SetLength(AnEvent.DisassemblerEntryArray,0);
|
||||||
|
SetLength(AnEvent.WatchEntryArray,0);
|
||||||
AnEvent.Addr1:=0;
|
AnEvent.Addr1:=0;
|
||||||
AnEvent.Addr2:=0;
|
AnEvent.Addr2:=0;
|
||||||
AnEvent.Addr3:=0;
|
AnEvent.Addr3:=0;
|
||||||
|
@ -225,11 +225,90 @@ type
|
|||||||
property LinesBefore: integer read FLinesBefore write FLinesBefore;
|
property LinesBefore: integer read FLinesBefore write FLinesBefore;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TFpDebugLocalsCommand }
|
||||||
|
|
||||||
|
TFpDebugLocalsCommand = class(TFpDebugThreadCommand)
|
||||||
|
private
|
||||||
|
FWatchEntryArray: TFpDebugEventWatchEntryArray;
|
||||||
|
public
|
||||||
|
function Execute(AController: TDbgController; out DoProcessLoop: boolean): boolean; override;
|
||||||
|
class function TextName: string; override;
|
||||||
|
procedure ComposeSuccessEvent(var AnEvent: TFpDebugEvent); override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
FpDbgDisasX86;
|
FpDbgDisasX86;
|
||||||
|
|
||||||
|
{ TFpDebugLocalsCommand }
|
||||||
|
|
||||||
|
function TFpDebugLocalsCommand.Execute(AController: TDbgController; out DoProcessLoop: boolean): boolean;
|
||||||
|
var
|
||||||
|
AContext: TFpDbgInfoContext;
|
||||||
|
ProcVal: TFpDbgValue;
|
||||||
|
i: Integer;
|
||||||
|
m: TFpDbgValue;
|
||||||
|
n, v: String;
|
||||||
|
Reg: TDBGPtr;
|
||||||
|
PrettyPrinter: TFpPascalPrettyPrinter;
|
||||||
|
begin
|
||||||
|
result := false;
|
||||||
|
if (AController = nil) or (AController.CurrentProcess = nil) or
|
||||||
|
(AController.CurrentProcess.DbgInfo = nil) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
Reg := AController.CurrentProcess.GetInstructionPointerRegisterValue;
|
||||||
|
AContext := AController.CurrentProcess.DbgInfo.FindContext(AController.CurrentThread.ID, 0, Reg);
|
||||||
|
|
||||||
|
if (AContext = nil) or (AContext.SymbolAtAddress = nil) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
ProcVal := AContext.ProcedureAtAddress;
|
||||||
|
|
||||||
|
if (ProcVal = nil) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
PrettyPrinter := TFpPascalPrettyPrinter.Create(sizeof(pointer));
|
||||||
|
try
|
||||||
|
PrettyPrinter.AddressSize := AContext.SizeOfAddress;
|
||||||
|
|
||||||
|
SetLength(FWatchEntryArray, ProcVal.MemberCount);
|
||||||
|
for i := 0 to ProcVal.MemberCount - 1 do
|
||||||
|
begin
|
||||||
|
m := ProcVal.Member[i];
|
||||||
|
if m <> nil then
|
||||||
|
begin
|
||||||
|
if m.DbgSymbol <> nil then
|
||||||
|
n := m.DbgSymbol.Name
|
||||||
|
else
|
||||||
|
n := '';
|
||||||
|
PrettyPrinter.PrintValue(v, m);
|
||||||
|
FWatchEntryArray[i].TextValue := v;
|
||||||
|
FWatchEntryArray[i].Expression := n;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
PrettyPrinter.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
AContext.ReleaseReference;
|
||||||
|
DoProcessLoop:=false;
|
||||||
|
result := true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TFpDebugLocalsCommand.TextName: string;
|
||||||
|
begin
|
||||||
|
result := 'locals';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFpDebugLocalsCommand.ComposeSuccessEvent(var AnEvent: TFpDebugEvent);
|
||||||
|
begin
|
||||||
|
inherited ComposeSuccessEvent(AnEvent);
|
||||||
|
AnEvent.WatchEntryArray := FWatchEntryArray;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TFpDebugThreadDisassembleCommand }
|
{ TFpDebugThreadDisassembleCommand }
|
||||||
|
|
||||||
function TFpDebugThreadDisassembleCommand.GetAddress: string;
|
function TFpDebugThreadDisassembleCommand.GetAddress: string;
|
||||||
@ -900,6 +979,7 @@ initialization
|
|||||||
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadEvaluateCommand);
|
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadEvaluateCommand);
|
||||||
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadStackTraceCommand);
|
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadStackTraceCommand);
|
||||||
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadDisassembleCommand);
|
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadDisassembleCommand);
|
||||||
|
TFpDebugThreadCommandList.instance.Add(TFpDebugLocalsCommand);
|
||||||
finalization
|
finalization
|
||||||
GFpDebugThreadCommandList.Free;
|
GFpDebugThreadCommandList.Free;
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user