mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 00:40:03 +01: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