mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-22 08:59:32 +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
|
||||
JSonEvent: TJSONObject;
|
||||
JSonLocationRec: TJSONObject;
|
||||
JSonStackArray: TJSONArray;
|
||||
JSonStackEntry: TJSONObject;
|
||||
JSonArray: TJSONArray;
|
||||
JSonArrayEntry: TJSONObject;
|
||||
i: Integer;
|
||||
begin
|
||||
JSonEvent := TJSONObject.Create;
|
||||
@ -192,41 +192,53 @@ begin
|
||||
JSonEvent.Add('message',AnEvent.Message);
|
||||
if length(AnEvent.StackEntryArray)>0 then
|
||||
begin
|
||||
JSonStackArray := TJSONArray.Create;
|
||||
JSonArray := TJSONArray.Create;
|
||||
for i := 0 to high(AnEvent.StackEntryArray) do
|
||||
begin
|
||||
JSonStackEntry := TJSONObject.Create;
|
||||
JSonStackEntry.Add('address', FormatAddress(AnEvent.StackEntryArray[i].AnAddress));
|
||||
JSonStackEntry.Add('frameaddress', FormatAddress(AnEvent.StackEntryArray[i].FrameAdress));
|
||||
JSonStackEntry.Add('sourcefile', AnEvent.StackEntryArray[i].SourceFile);
|
||||
JSonStackEntry.Add('line', AnEvent.StackEntryArray[i].Line);
|
||||
JSonStackEntry.Add('functionname', AnEvent.StackEntryArray[i].FunctionName);
|
||||
JSonStackArray.Add(JSonStackEntry);
|
||||
JSonArrayEntry := TJSONObject.Create;
|
||||
JSonArrayEntry.Add('address', FormatAddress(AnEvent.StackEntryArray[i].AnAddress));
|
||||
JSonArrayEntry.Add('frameaddress', FormatAddress(AnEvent.StackEntryArray[i].FrameAdress));
|
||||
JSonArrayEntry.Add('sourcefile', AnEvent.StackEntryArray[i].SourceFile);
|
||||
JSonArrayEntry.Add('line', AnEvent.StackEntryArray[i].Line);
|
||||
JSonArrayEntry.Add('functionname', AnEvent.StackEntryArray[i].FunctionName);
|
||||
JSonArray.Add(JSonArrayEntry);
|
||||
end;
|
||||
JSonEvent.Add('callstack', JSonStackArray);
|
||||
JSonEvent.Add('callstack', JSonArray);
|
||||
end;
|
||||
if length(AnEvent.DisassemblerEntryArray)>0 then
|
||||
begin
|
||||
JSonStackArray := TJSONArray.Create;
|
||||
JSonArray := TJSONArray.Create;
|
||||
for i := 0 to high(AnEvent.DisassemblerEntryArray) do
|
||||
begin
|
||||
JSonStackEntry := TJSONObject.Create;
|
||||
JSonStackEntry.Add('address', FormatAddress(AnEvent.DisassemblerEntryArray[i].Addr));
|
||||
JSonStackEntry.Add('dump', AnEvent.DisassemblerEntryArray[i].Dump);
|
||||
JSonStackEntry.Add('statement', AnEvent.DisassemblerEntryArray[i].Statement);
|
||||
JSonStackEntry.Add('srcfilename', AnEvent.DisassemblerEntryArray[i].SrcFileName);
|
||||
JSonStackEntry.Add('srcfileline', AnEvent.DisassemblerEntryArray[i].SrcFileLine);
|
||||
JSonStackEntry.Add('srcstatementindex', AnEvent.DisassemblerEntryArray[i].SrcStatementIndex);
|
||||
JSonStackEntry.Add('srcstatementcount', AnEvent.DisassemblerEntryArray[i].SrcStatementCount);
|
||||
JSonStackEntry.Add('functionname', AnEvent.DisassemblerEntryArray[i].FuncName);
|
||||
JSonStackEntry.Add('offset', AnEvent.DisassemblerEntryArray[i].Offset);
|
||||
JSonStackArray.Add(JSonStackEntry);
|
||||
JSonArrayEntry := TJSONObject.Create;
|
||||
JSonArrayEntry.Add('address', FormatAddress(AnEvent.DisassemblerEntryArray[i].Addr));
|
||||
JSonArrayEntry.Add('dump', AnEvent.DisassemblerEntryArray[i].Dump);
|
||||
JSonArrayEntry.Add('statement', AnEvent.DisassemblerEntryArray[i].Statement);
|
||||
JSonArrayEntry.Add('srcfilename', AnEvent.DisassemblerEntryArray[i].SrcFileName);
|
||||
JSonArrayEntry.Add('srcfileline', AnEvent.DisassemblerEntryArray[i].SrcFileLine);
|
||||
JSonArrayEntry.Add('srcstatementindex', AnEvent.DisassemblerEntryArray[i].SrcStatementIndex);
|
||||
JSonArrayEntry.Add('srcstatementcount', AnEvent.DisassemblerEntryArray[i].SrcStatementCount);
|
||||
JSonArrayEntry.Add('functionname', AnEvent.DisassemblerEntryArray[i].FuncName);
|
||||
JSonArrayEntry.Add('offset', AnEvent.DisassemblerEntryArray[i].Offset);
|
||||
JSonArray.Add(JSonArrayEntry);
|
||||
end;
|
||||
JSonEvent.Add('disassembly', JSonStackArray);
|
||||
JSonEvent.Add('disassembly', JSonArray);
|
||||
JSonEvent.Add('startaddress', FormatAddress(AnEvent.Addr1));
|
||||
JSonEvent.Add('endaddress', FormatAddress(AnEvent.Addr2));
|
||||
JSonEvent.Add('lastentryendaddress', FormatAddress(AnEvent.Addr3));
|
||||
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;
|
||||
finally
|
||||
JSonEvent.Free;
|
||||
|
@ -48,8 +48,14 @@ type
|
||||
FunctionName: string;
|
||||
Line: integer;
|
||||
end;
|
||||
TFpDebugEventWatchEntry = record
|
||||
TextValue: string;
|
||||
Expression: string;
|
||||
end;
|
||||
|
||||
TFpDebugEventCallStackEntryArray = array of TFpDebugEventCallStackEntry;
|
||||
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.
|
||||
TFpDebugEvent = record
|
||||
@ -69,6 +75,7 @@ type
|
||||
Addr3: TDBGPtr;
|
||||
StackEntryArray: TFpDebugEventCallStackEntryArray;
|
||||
DisassemblerEntryArray: TFpDebugEventDisassemblerEntryArray;
|
||||
WatchEntryArray: TFpDebugEventWatchEntryArray;
|
||||
end;
|
||||
|
||||
// Each listener should implement this interface.
|
||||
@ -323,6 +330,7 @@ begin
|
||||
AnEvent.Validity:=ddsUnknown;
|
||||
SetLength(AnEvent.StackEntryArray,0);
|
||||
SetLength(AnEvent.DisassemblerEntryArray,0);
|
||||
SetLength(AnEvent.WatchEntryArray,0);
|
||||
AnEvent.Addr1:=0;
|
||||
AnEvent.Addr2:=0;
|
||||
AnEvent.Addr3:=0;
|
||||
|
@ -225,11 +225,90 @@ type
|
||||
property LinesBefore: integer read FLinesBefore write FLinesBefore;
|
||||
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
|
||||
|
||||
uses
|
||||
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 }
|
||||
|
||||
function TFpDebugThreadDisassembleCommand.GetAddress: string;
|
||||
@ -900,6 +979,7 @@ initialization
|
||||
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadEvaluateCommand);
|
||||
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadStackTraceCommand);
|
||||
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadDisassembleCommand);
|
||||
TFpDebugThreadCommandList.instance.Add(TFpDebugLocalsCommand);
|
||||
finalization
|
||||
GFpDebugThreadCommandList.Free;
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user