FpDebugServer: Added locals command

git-svn-id: trunk@49370 -
This commit is contained in:
joost 2015-06-19 20:23:19 +00:00
parent 8d3d8a4032
commit 6d32f521e9
3 changed files with 124 additions and 24 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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.