mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-22 09:39:31 +02:00
FpDebugServer: Added disassemble command
git-svn-id: trunk@49287 -
This commit is contained in:
parent
bff355cf81
commit
a8ae389b6f
@ -205,6 +205,28 @@ begin
|
||||
end;
|
||||
JSonEvent.Add('callstack', JSonStackArray);
|
||||
end;
|
||||
if length(AnEvent.DisassemblerEntryArray)>0 then
|
||||
begin
|
||||
JSonStackArray := 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);
|
||||
end;
|
||||
JSonEvent.Add('disassembly', JSonStackArray);
|
||||
JSonEvent.Add('startaddress', FormatAddress(AnEvent.Addr1));
|
||||
JSonEvent.Add('endaddress', FormatAddress(AnEvent.Addr2));
|
||||
JSonEvent.Add('lastentryendaddress', FormatAddress(AnEvent.Addr3));
|
||||
end;
|
||||
result := JSonEvent.AsJSON;
|
||||
finally
|
||||
JSonEvent.Free;
|
||||
|
@ -49,6 +49,7 @@ type
|
||||
Line: integer;
|
||||
end;
|
||||
TFpDebugEventCallStackEntryArray = array of TFpDebugEventCallStackEntry;
|
||||
TFpDebugEventDisassemblerEntryArray = array of TDisassemblerEntry;
|
||||
|
||||
// This record is used to pass debugging-events. Not every field is applicable for each type of event.
|
||||
TFpDebugEvent = record
|
||||
@ -63,7 +64,11 @@ type
|
||||
BreakpointAddr: TDBGPtr;
|
||||
LocationRec: TDBGLocationRec;
|
||||
Validity: TDebuggerDataState;
|
||||
Addr1: TDBGPtr;
|
||||
Addr2: TDBGPtr;
|
||||
Addr3: TDBGPtr;
|
||||
StackEntryArray: TFpDebugEventCallStackEntryArray;
|
||||
DisassemblerEntryArray: TFpDebugEventDisassemblerEntryArray;
|
||||
end;
|
||||
|
||||
// Each listener should implement this interface.
|
||||
@ -317,6 +322,10 @@ begin
|
||||
AnEvent.LocationRec.Address:=0;
|
||||
AnEvent.Validity:=ddsUnknown;
|
||||
SetLength(AnEvent.StackEntryArray,0);
|
||||
SetLength(AnEvent.DisassemblerEntryArray,0);
|
||||
AnEvent.Addr1:=0;
|
||||
AnEvent.Addr2:=0;
|
||||
AnEvent.Addr3:=0;
|
||||
end;
|
||||
|
||||
procedure TFpDebugThread.FControllerDebugInfoLoaded(Sender: TObject);
|
||||
|
@ -200,12 +200,150 @@ type
|
||||
procedure ComposeSuccessEvent(var AnEvent: TFpDebugEvent); override;
|
||||
end;
|
||||
|
||||
{ TFpDebugThreadDisassembleCommand }
|
||||
|
||||
TFpDebugThreadDisassembleCommand = class(TFpDebugThreadCommand)
|
||||
private
|
||||
FAddressValue: TDBGPtr;
|
||||
FLines: integer;
|
||||
FDisassemblerEntryArray: TFpDebugEventDisassemblerEntryArray;
|
||||
FStartAddr: TDBGPtr;
|
||||
FEndAddr: TDBGPtr;
|
||||
FLastEntryEndAddr: TDBGPtr;
|
||||
function GetAddress: string;
|
||||
procedure SetAddress(AValue: string);
|
||||
public
|
||||
constructor Create(AListenerIdentifier: integer; AnUID: variant; AOnLog: TOnLog); override;
|
||||
function Execute(AController: TDbgController; out DoProcessLoop: boolean): boolean; override;
|
||||
class function TextName: string; override;
|
||||
procedure ComposeSuccessEvent(var AnEvent: TFpDebugEvent); override;
|
||||
published
|
||||
property Address: string read GetAddress write SetAddress;
|
||||
property Lines: integer read FLines write FLines;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TFpDebugThreadCommandList }
|
||||
uses
|
||||
FpDbgDisasX86;
|
||||
|
||||
{ TFpDebugThreadDisassembleCommand }
|
||||
|
||||
function TFpDebugThreadDisassembleCommand.GetAddress: string;
|
||||
begin
|
||||
result := FormatAddress(FAddressValue);
|
||||
end;
|
||||
|
||||
procedure TFpDebugThreadDisassembleCommand.SetAddress(AValue: string);
|
||||
begin
|
||||
FAddressValue := Hex2Dec(AValue);
|
||||
end;
|
||||
|
||||
constructor TFpDebugThreadDisassembleCommand.Create(AListenerIdentifier: integer; AnUID: variant; AOnLog: TOnLog);
|
||||
begin
|
||||
inherited Create(AListenerIdentifier, AnUID, AOnLog);
|
||||
FLines:=10;
|
||||
end;
|
||||
|
||||
function TFpDebugThreadDisassembleCommand.Execute(AController: TDbgController; out DoProcessLoop: boolean): boolean;
|
||||
var
|
||||
GFpDebugThreadCommandList: TFpDebugThreadCommandList = nil;
|
||||
AnAddr: TDBGPtr;
|
||||
CodeBin: array[0..20] of byte;
|
||||
p: pointer;
|
||||
ADump,
|
||||
AStatement,
|
||||
ASrcFileName: string;
|
||||
ASrcFileLine: integer;
|
||||
i,j: Integer;
|
||||
Sym: TFpDbgSymbol;
|
||||
StatIndex: integer;
|
||||
FirstIndex: integer;
|
||||
|
||||
begin
|
||||
result := false;
|
||||
DoProcessLoop:=false;
|
||||
if not assigned(AController.CurrentProcess) then
|
||||
begin
|
||||
log('Failed to dissasemble: No process', dllInfo);
|
||||
exit;
|
||||
end;
|
||||
|
||||
Sym:=nil;
|
||||
ASrcFileLine:=0;
|
||||
ASrcFileName:='';
|
||||
StatIndex:=0;
|
||||
FirstIndex:=0;
|
||||
if FAddressValue=0 then
|
||||
FStartAddr:=AController.CurrentProcess.GetInstructionPointerRegisterValue
|
||||
else
|
||||
FStartAddr:=FAddressValue;
|
||||
AnAddr:=FStartAddr;
|
||||
setlength(FDisassemblerEntryArray, FLines);
|
||||
|
||||
for i := 0 to FLines-1 do
|
||||
begin
|
||||
FDisassemblerEntryArray[i].Addr:=AnAddr;
|
||||
if not AController.CurrentProcess.ReadData(AnAddr, sizeof(CodeBin),CodeBin) then
|
||||
begin
|
||||
Log(Format('Disassemble: Failed to read memory at %s.', [FormatAddress(AnAddr)]), dllDebug);
|
||||
FDisassemblerEntryArray[i].Statement := 'Failed to read memory';
|
||||
inc(AnAddr);
|
||||
end
|
||||
else
|
||||
begin
|
||||
p := @CodeBin;
|
||||
FpDbgDisasX86.Disassemble(p, AController.CurrentProcess.Mode=dm64, ADump, AStatement);
|
||||
|
||||
Sym := AController.CurrentProcess.FindSymbol(AnAddr);
|
||||
|
||||
// If this is the last statement for this source-code-line, fill the
|
||||
// SrcStatementCount from the prior statements.
|
||||
if (assigned(sym) and ((ASrcFileName<>sym.FileName) or (ASrcFileLine<>sym.Line))) or
|
||||
(not assigned(sym) and ((ASrcFileLine<>0) or (ASrcFileName<>''))) then
|
||||
begin
|
||||
for j := 0 to StatIndex-1 do
|
||||
FDisassemblerEntryArray[FirstIndex+j].SrcStatementCount:=StatIndex;
|
||||
StatIndex:=0;
|
||||
FirstIndex:=i;
|
||||
end;
|
||||
|
||||
if assigned(sym) then
|
||||
begin
|
||||
ASrcFileName:=sym.FileName;
|
||||
ASrcFileLine:=sym.Line;
|
||||
end
|
||||
else
|
||||
begin
|
||||
ASrcFileName:='';
|
||||
ASrcFileLine:=0;
|
||||
end;
|
||||
FDisassemblerEntryArray[i].Dump := ADump;
|
||||
FDisassemblerEntryArray[i].Statement := AStatement;
|
||||
FDisassemblerEntryArray[i].SrcFileLine:=ASrcFileLine;
|
||||
FDisassemblerEntryArray[i].SrcFileName:=ASrcFileName;
|
||||
FDisassemblerEntryArray[i].SrcStatementIndex:=StatIndex;
|
||||
inc(StatIndex);
|
||||
FEndAddr:=AnAddr;
|
||||
Inc(AnAddr, {%H-}PtrUInt(p) - {%H-}PtrUInt(@CodeBin));
|
||||
end;
|
||||
end;
|
||||
FLastEntryEndAddr:=AnAddr;
|
||||
result := true;
|
||||
end;
|
||||
|
||||
class function TFpDebugThreadDisassembleCommand.TextName: string;
|
||||
begin
|
||||
result := 'disassemble';
|
||||
end;
|
||||
|
||||
procedure TFpDebugThreadDisassembleCommand.ComposeSuccessEvent(var AnEvent: TFpDebugEvent);
|
||||
begin
|
||||
inherited ComposeSuccessEvent(AnEvent);
|
||||
AnEvent.DisassemblerEntryArray := FDisassemblerEntryArray;
|
||||
AnEvent.Addr1:=FStartAddr;
|
||||
AnEvent.Addr2:=FEndAddr;
|
||||
AnEvent.Addr3:=FLastEntryEndAddr;
|
||||
end;
|
||||
|
||||
{ TFpDebugThreadSetConsoleTtyCommand }
|
||||
|
||||
@ -582,6 +720,11 @@ begin
|
||||
result := 'addbreakpoint';
|
||||
end;
|
||||
|
||||
{ TFpDebugThreadCommandList }
|
||||
|
||||
var
|
||||
GFpDebugThreadCommandList: TFpDebugThreadCommandList = nil;
|
||||
|
||||
class function TFpDebugThreadCommandList.instance: TFpDebugThreadCommandList;
|
||||
begin
|
||||
if not assigned(GFpDebugThreadCommandList) then
|
||||
@ -661,6 +804,7 @@ initialization
|
||||
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadGetLocationInfoCommand);
|
||||
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadEvaluateCommand);
|
||||
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadStackTraceCommand);
|
||||
TFpDebugThreadCommandList.instance.Add(TFpDebugThreadDisassembleCommand);
|
||||
finalization
|
||||
GFpDebugThreadCommandList.Free;
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user