mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-29 09:22:44 +02:00
LLDB Debugger: use custom stack trace format / support debug output win
git-svn-id: trunk@58392 -
This commit is contained in:
parent
b38a1c3102
commit
2025b4dfcd
@ -1839,6 +1839,7 @@ type
|
|||||||
Errors should also be reported by debugger
|
Errors should also be reported by debugger
|
||||||
*)
|
*)
|
||||||
class function RequiresLocalExecutable: Boolean; virtual;
|
class function RequiresLocalExecutable: Boolean; virtual;
|
||||||
|
procedure TestCmd(const ACommand: String); virtual;// For internal debugging purposes
|
||||||
public
|
public
|
||||||
constructor Create(const AExternalDebugger: String); virtual;
|
constructor Create(const AExternalDebugger: String); virtual;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -6061,6 +6062,11 @@ begin
|
|||||||
Result := True;
|
Result := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDebuggerIntf.TestCmd(const ACommand: String);
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDebuggerIntf.SetState(const AValue: TDBGState);
|
procedure TDebuggerIntf.SetState(const AValue: TDBGState);
|
||||||
var
|
var
|
||||||
OldState: TDBGState;
|
OldState: TDBGState;
|
||||||
|
@ -132,6 +132,7 @@ type
|
|||||||
procedure DoAfterLineReceived(var ALine: String);
|
procedure DoAfterLineReceived(var ALine: String);
|
||||||
procedure DoBeforeLineReceived(var ALine: String);
|
procedure DoBeforeLineReceived(var ALine: String);
|
||||||
procedure DoCmdLineDebuggerTerminated(Sender: TObject);
|
procedure DoCmdLineDebuggerTerminated(Sender: TObject);
|
||||||
|
procedure DoLineSentToDbg(Sender: TObject; ALine: String);
|
||||||
function LldbRun: Boolean;
|
function LldbRun: Boolean;
|
||||||
function LldbStep(AStepAction: TLldbInstructionProcessStepAction): Boolean;
|
function LldbStep(AStepAction: TLldbInstructionProcessStepAction): Boolean;
|
||||||
function LldbStop: Boolean;
|
function LldbStop: Boolean;
|
||||||
@ -178,6 +179,7 @@ type
|
|||||||
function GetLocation: TDBGLocationRec; override;
|
function GetLocation: TDBGLocationRec; override;
|
||||||
// function GetProcessList({%H-}AList: TRunningProcessInfoList): boolean; override;
|
// function GetProcessList({%H-}AList: TRunningProcessInfoList): boolean; override;
|
||||||
// function NeedReset: Boolean; override;
|
// function NeedReset: Boolean; override;
|
||||||
|
procedure TestCmd(const ACommand: String); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -438,7 +440,7 @@ var
|
|||||||
found, foundArg: TStringArray;
|
found, foundArg: TStringArray;
|
||||||
Arguments: TStringList;
|
Arguments: TStringList;
|
||||||
It: TMapIterator;
|
It: TMapIterator;
|
||||||
s, func, filename, d: String;
|
s, func, filename, d, fullfile: String;
|
||||||
frame: LongInt;
|
frame: LongInt;
|
||||||
IsCur: Boolean;
|
IsCur: Boolean;
|
||||||
addr: TDBGPtr;
|
addr: TDBGPtr;
|
||||||
@ -452,10 +454,10 @@ begin
|
|||||||
|
|
||||||
for i := 0 to Length(Instr.Res) - 1 do begin
|
for i := 0 to Length(Instr.Res) - 1 do begin
|
||||||
s := Instr.Res[i];
|
s := Instr.Res[i];
|
||||||
ParseFrameLocation(s, FId, IsCur, addr, func, Arguments, filename, line, d);
|
ParseNewFrameLocation(s, FId, IsCur, addr, func, Arguments, filename, fullfile, line, d);
|
||||||
if It.Locate(FId) then begin
|
if It.Locate(FId) then begin
|
||||||
e := TCallStackEntry(It.DataPtr^);
|
e := TCallStackEntry(It.DataPtr^);
|
||||||
e.Init(addr, Arguments, func, filename, '', line);
|
e.Init(addr, Arguments, func, filename, fullfile, line);
|
||||||
end;
|
end;
|
||||||
Arguments.Free;
|
Arguments.Free;
|
||||||
end;
|
end;
|
||||||
@ -885,6 +887,16 @@ procedure TLldbDebuggerCommandInit.DoExecute;
|
|||||||
var
|
var
|
||||||
Instr: TLldbInstructionSettingSet;
|
Instr: TLldbInstructionSettingSet;
|
||||||
begin
|
begin
|
||||||
|
Instr := TLldbInstructionSettingSet.Create('frame-format',
|
||||||
|
'"frame #${frame.index}: ${frame.pc}' +
|
||||||
|
' &&//FULL: {${line.file.fullpath}} &&//SHORT: {${line.file.basename}} &&//LINE: {${line.number}}' +
|
||||||
|
' &&//MOD: {${module.file.basename}} &&//FUNC: {${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}' +
|
||||||
|
' <<&&//FRAME\n"'
|
||||||
|
// ' { ${frame.fp} } \n"'
|
||||||
|
);
|
||||||
|
QueueInstruction(Instr);
|
||||||
|
Instr.ReleaseReference;
|
||||||
|
|
||||||
Instr := TLldbInstructionSettingSet.Create('stop-line-count-after', '0');
|
Instr := TLldbInstructionSettingSet.Create('stop-line-count-after', '0');
|
||||||
QueueInstruction(Instr);
|
QueueInstruction(Instr);
|
||||||
Instr.ReleaseReference;
|
Instr.ReleaseReference;
|
||||||
@ -1040,7 +1052,7 @@ var
|
|||||||
AnId, SrcLine: Integer;
|
AnId, SrcLine: Integer;
|
||||||
AnIsCurrent: Boolean;
|
AnIsCurrent: Boolean;
|
||||||
AnAddr: TDBGPtr;
|
AnAddr: TDBGPtr;
|
||||||
AFuncName, AFile, AReminder: String;
|
AFuncName, AFile, AReminder, AFullFile: String;
|
||||||
AnArgs: TStringList;
|
AnArgs: TStringList;
|
||||||
begin
|
begin
|
||||||
if ALine = '' then
|
if ALine = '' then
|
||||||
@ -1067,13 +1079,14 @@ begin
|
|||||||
Instr.ReleaseReference;
|
Instr.ReleaseReference;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if ParseFrameLocation(ALine, AnId, AnIsCurrent, AnAddr, AFuncName, AnArgs,
|
if ParseNewFrameLocation(ALine, AnId, AnIsCurrent, AnAddr, AFuncName, AnArgs,
|
||||||
AFile, SrcLine, AReminder)
|
AFile, AFullFile, SrcLine, AReminder)
|
||||||
then begin
|
then begin
|
||||||
AnArgs.Free;
|
AnArgs.Free;
|
||||||
FCurrentLocation.Address := AnAddr;
|
FCurrentLocation.Address := AnAddr;
|
||||||
FCurrentLocation.FuncName := AFuncName;
|
FCurrentLocation.FuncName := AFuncName;
|
||||||
FCurrentLocation.SrcFile := AFile;
|
FCurrentLocation.SrcFile := AFile;
|
||||||
|
FCurrentLocation.SrcFullName := AFullFile;
|
||||||
FCurrentLocation.SrcLine := SrcLine;
|
FCurrentLocation.SrcLine := SrcLine;
|
||||||
DoCurrent(FCurrentLocation);
|
DoCurrent(FCurrentLocation);
|
||||||
ALine := '';
|
ALine := '';
|
||||||
@ -1082,9 +1095,7 @@ end;
|
|||||||
|
|
||||||
procedure TLldbDebugger.DoBeforeLineReceived(var ALine: String);
|
procedure TLldbDebugger.DoBeforeLineReceived(var ALine: String);
|
||||||
begin
|
begin
|
||||||
if StrMatches(ALine, ['Process ', ' stopped']) then begin // TODO: needed?
|
DoDbgOutput(ALine);
|
||||||
ALine := '';
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TLldbDebugger.DoBeginReceivingLines(Sender: TObject);
|
procedure TLldbDebugger.DoBeginReceivingLines(Sender: TObject);
|
||||||
@ -1097,6 +1108,11 @@ begin
|
|||||||
SetState(dsError);
|
SetState(dsError);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TLldbDebugger.DoLineSentToDbg(Sender: TObject; ALine: String);
|
||||||
|
begin
|
||||||
|
DoDbgOutput('>> '+ALine);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TLldbDebugger.DoEndReceivingLines(Sender: TObject);
|
procedure TLldbDebugger.DoEndReceivingLines(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
UnlockRelease;
|
UnlockRelease;
|
||||||
@ -1240,6 +1256,7 @@ constructor TLldbDebugger.Create(const AExternalDebugger: String);
|
|||||||
begin
|
begin
|
||||||
inherited Create(AExternalDebugger);
|
inherited Create(AExternalDebugger);
|
||||||
FDebugProcess := TDebugProcess.Create(AExternalDebugger);
|
FDebugProcess := TDebugProcess.Create(AExternalDebugger);
|
||||||
|
FDebugProcess.OnLineSent := @DoLineSentToDbg;
|
||||||
|
|
||||||
FDebugInstructionQueue := TLldbInstructionQueue.Create(FDebugProcess);
|
FDebugInstructionQueue := TLldbInstructionQueue.Create(FDebugProcess);
|
||||||
FDebugInstructionQueue.OnBeginLinesReceived := @DoBeginReceivingLines;
|
FDebugInstructionQueue.OnBeginLinesReceived := @DoBeginReceivingLines;
|
||||||
@ -1296,6 +1313,11 @@ begin
|
|||||||
Result := FCurrentLocation;
|
Result := FCurrentLocation;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TLldbDebugger.TestCmd(const ACommand: String);
|
||||||
|
begin
|
||||||
|
FDebugProcess.SendCmdLn(ACommand);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure Register;
|
procedure Register;
|
||||||
begin
|
begin
|
||||||
RegisterDebugger(TLldbDebugger);
|
RegisterDebugger(TLldbDebugger);
|
||||||
|
@ -22,6 +22,10 @@ function ParseFrameLocation(AnInput: String; out AnId: Integer;
|
|||||||
out AnIsCurrent: Boolean; out AnAddr: TDBGPtr; out AFuncName: String;
|
out AnIsCurrent: Boolean; out AnAddr: TDBGPtr; out AFuncName: String;
|
||||||
out AnArgs: TStringList; out AFile: String; out ALine: Integer;
|
out AnArgs: TStringList; out AFile: String; out ALine: Integer;
|
||||||
out AReminder: String): Boolean;
|
out AReminder: String): Boolean;
|
||||||
|
function ParseNewFrameLocation(AnInput: String; out AnId: Integer;
|
||||||
|
out AnIsCurrent: Boolean; out AnAddr: TDBGPtr; out AFuncName: String;
|
||||||
|
out AnArgs: TStringList; out AFile, AFullFile: String; out ALine: Integer;
|
||||||
|
out AReminder: String): Boolean;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -234,5 +238,60 @@ begin
|
|||||||
ParseLocation(AnInput, AnAddr, AFuncName, AnArgs, AFile, ALine, AReminder);
|
ParseLocation(AnInput, AnAddr, AFuncName, AnArgs, AFile, ALine, AReminder);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function ParseNewFrameLocation(AnInput: String; out AnId: Integer; out
|
||||||
|
AnIsCurrent: Boolean; out AnAddr: TDBGPtr; out AFuncName: String; out
|
||||||
|
AnArgs: TStringList; out AFile, AFullFile: String; out ALine: Integer; out
|
||||||
|
AReminder: String): Boolean;
|
||||||
|
var
|
||||||
|
found: TStringArray;
|
||||||
|
i, j, k: SizeInt;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
AnIsCurrent := (Length(AnInput) > 3) and (AnInput[3] = '*');
|
||||||
|
if AnIsCurrent then AnInput[3] := ' ';
|
||||||
|
|
||||||
|
if not StrMatches(AnInput, [' frame #'{id}, ': '{addr},
|
||||||
|
' &&//FULL: '{fullfile}, ' &&//SHORT: '{file},' &&//LINE: '{line},
|
||||||
|
' &&//MOD: '{mod},' &&//FUNC: '{func}, '',' <<&&//FRAME', ''
|
||||||
|
], found) then begin
|
||||||
|
AnId := -1;
|
||||||
|
AnAddr := 0;
|
||||||
|
AFile := '';
|
||||||
|
AFullFile := '';
|
||||||
|
ALine := -1;
|
||||||
|
AFuncName := '';
|
||||||
|
AReminder := '';
|
||||||
|
AnArgs := nil;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
AnId := StrToIntDef(found[0], -1);
|
||||||
|
AnAddr := StrToInt64Def(found[1], 0);
|
||||||
|
AFullFile := found[2];
|
||||||
|
AFile := found[3];
|
||||||
|
ALine := StrToIntDef(found[4], -1);
|
||||||
|
AFuncName := found[6];
|
||||||
|
AnArgs := nil;
|
||||||
|
AReminder := found[7];
|
||||||
|
|
||||||
|
if AFuncName = '' then begin
|
||||||
|
AFuncName := '<'+found[5]+'>';
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
AnInput := AFuncName;
|
||||||
|
i := pos(' ', AnInput);
|
||||||
|
j := pos('(', AnInput);
|
||||||
|
k := pos(')', AnInput);
|
||||||
|
if ((i = 0) or (i > j)) and (j > 1) and (k > j) then begin
|
||||||
|
AFuncName := Copy(AnInput, 1, j-1);
|
||||||
|
AnArgs := TStringList.Create;
|
||||||
|
AnArgs.CommaText := copy(AnInput, j+1, k-j-1);
|
||||||
|
AnInput := Copy(AnInput, k+1, Length(AnInput));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -242,6 +242,8 @@ end;
|
|||||||
|
|
||||||
procedure TLldbInstructionQueue.DoBeforeHandleLineReceived(var ALine: String);
|
procedure TLldbInstructionQueue.DoBeforeHandleLineReceived(var ALine: String);
|
||||||
begin
|
begin
|
||||||
|
inherited DoBeforeHandleLineReceived(ALine); // Do first send to DebugOutput window
|
||||||
|
|
||||||
while LeftStr(ALine, 7) = '(lldb) ' do begin
|
while LeftStr(ALine, 7) = '(lldb) ' do begin
|
||||||
Delete(ALine, 1, 7);
|
Delete(ALine, 1, 7);
|
||||||
end;
|
end;
|
||||||
@ -251,7 +253,9 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
inherited DoBeforeHandleLineReceived(ALine);
|
if StrMatches(ALine, ['Process ', ' stopped']) then begin // TODO: needed?
|
||||||
|
ALine := '';
|
||||||
|
end;
|
||||||
|
|
||||||
// TODO: detect the echo, and flag if data is for RunningInstruction;
|
// TODO: detect the echo, and flag if data is for RunningInstruction;
|
||||||
|
|
||||||
@ -630,7 +634,7 @@ begin
|
|||||||
//<< << TCmdLineDebugger.ReadLn "0x005ff280: 0x60 0x10 0x77 0x04"
|
//<< << TCmdLineDebugger.ReadLn "0x005ff280: 0x60 0x10 0x77 0x04"
|
||||||
|
|
||||||
|
|
||||||
if StrMatches(AData, ['(', ')', ' = ', '112234', '']) then begin
|
if StrStartsWith(AData, 'lldb version ') then begin
|
||||||
MarkAsSuccess;
|
MarkAsSuccess;
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
@ -641,7 +645,7 @@ end;
|
|||||||
procedure TLldbInstructionMemory.SendCommandDataToDbg();
|
procedure TLldbInstructionMemory.SendCommandDataToDbg();
|
||||||
begin
|
begin
|
||||||
inherited SendCommandDataToDbg();
|
inherited SendCommandDataToDbg();
|
||||||
Queue.SendDataToDBG(Self, 'p 112234'); // end marker // do not sent before new prompt
|
Queue.SendDataToDBG(Self, 'version'); // end marker // do not sent before new prompt
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TLldbInstructionMemory.Create(AnAddress: TDBGPtr; ALen: Cardinal);
|
constructor TLldbInstructionMemory.Create(AnAddress: TDBGPtr; ALen: Cardinal);
|
||||||
@ -693,7 +697,7 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if StrMatches(AData, ['(', ')', ' = ', '112235', '']) then begin
|
if StrStartsWith(AData, 'lldb version ') then begin
|
||||||
MarkAsSuccess;
|
MarkAsSuccess;
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
@ -723,7 +727,7 @@ end;
|
|||||||
procedure TLldbInstructionRegister.SendCommandDataToDbg();
|
procedure TLldbInstructionRegister.SendCommandDataToDbg();
|
||||||
begin
|
begin
|
||||||
inherited SendCommandDataToDbg();
|
inherited SendCommandDataToDbg();
|
||||||
Queue.SendDataToDBG(Self, 'p 112235'); // end marker // do not sent before new prompt
|
Queue.SendDataToDBG(Self, 'version'); // end marker // do not sent before new prompt
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TLldbInstructionRegister.Create(AThread, AFrame: Integer);
|
constructor TLldbInstructionRegister.Create(AThread, AFrame: Integer);
|
||||||
@ -742,7 +746,7 @@ end;
|
|||||||
procedure TLldbInstructionThreadList.SendCommandDataToDbg();
|
procedure TLldbInstructionThreadList.SendCommandDataToDbg();
|
||||||
begin
|
begin
|
||||||
inherited SendCommandDataToDbg();
|
inherited SendCommandDataToDbg();
|
||||||
Queue.SendDataToDBG(Self, 'p 112236'); // end marker // do not sent before new prompt
|
Queue.SendDataToDBG(Self, 'version'); // end marker // do not sent before new prompt
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLldbInstructionThreadList.ProcessInputFromDbg(const AData: String
|
function TLldbInstructionThreadList.ProcessInputFromDbg(const AData: String
|
||||||
@ -773,7 +777,7 @@ DebugLn(['######### add ',AData]);
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if StrMatches(AData, ['(', ')', ' = ', '112236', '']) then begin
|
if StrStartsWith(AData, 'lldb version ') then begin
|
||||||
MarkAsSuccess;
|
MarkAsSuccess;
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
@ -797,7 +801,7 @@ end;
|
|||||||
procedure TLldbInstructionStackTrace.SendCommandDataToDbg();
|
procedure TLldbInstructionStackTrace.SendCommandDataToDbg();
|
||||||
begin
|
begin
|
||||||
inherited SendCommandDataToDbg();
|
inherited SendCommandDataToDbg();
|
||||||
Queue.SendDataToDBG(Self, 'p 112233'); // end marker // do not sent before new prompt
|
Queue.SendDataToDBG(Self, 'version'); // end marker // do not sent before new prompt
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLldbInstructionStackTrace.ProcessInputFromDbg(const AData: String
|
function TLldbInstructionStackTrace.ProcessInputFromDbg(const AData: String
|
||||||
@ -827,7 +831,7 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if StrMatches(AData, ['(', ')', ' = ', '112233', '']) then begin
|
if StrStartsWith(AData, 'lldb version ') then begin
|
||||||
MarkAsSuccess;
|
MarkAsSuccess;
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
@ -145,9 +145,7 @@ end;
|
|||||||
{$IFDEF DBG_WITH_DEBUGGER_DEBUG}
|
{$IFDEF DBG_WITH_DEBUGGER_DEBUG}
|
||||||
procedure TDbgOutputForm.Button1Click(Sender: TObject);
|
procedure TDbgOutputForm.Button1Click(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
if DebugBoss.Debugger is TCmdLineDebugger then begin
|
DebugBoss.Debugger.TestCmd(Edit1.Text);
|
||||||
TCmdLineDebugger(DebugBoss.Debugger).TestCmd(Edit1.Text);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user