mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-07 21:38:00 +02:00
LazDebugger, lldb: refactor run command / move break handling to run cmd / hook, auto run thread list
git-svn-id: trunk@58839 -
This commit is contained in:
parent
301ca8011f
commit
5570f33576
@ -6307,12 +6307,12 @@ end;
|
||||
procedure TDebuggerIntf.LockRelease;
|
||||
begin
|
||||
inc(FReleaseLock);
|
||||
DebugLnEnter(DBG_VERBOSE, ['> TLldbDebugger.LockRelease ',FReleaseLock]);
|
||||
DebugLnEnter(DBG_VERBOSE, ['> TDebuggerIntf.LockRelease ',FReleaseLock]);
|
||||
end;
|
||||
|
||||
procedure TDebuggerIntf.UnlockRelease;
|
||||
begin
|
||||
DebugLnExit(DBG_VERBOSE, ['< TLldbDebugger.UnlockRelease ',FReleaseLock]);
|
||||
DebugLnExit(DBG_VERBOSE, ['< TDebuggerIntf.UnlockRelease ',FReleaseLock]);
|
||||
dec(FReleaseLock);
|
||||
if (FReleaseLock = 0) and (State = dsDestroying)
|
||||
then Release;
|
||||
|
@ -61,6 +61,7 @@ type
|
||||
protected
|
||||
function GetCommandAsString(): String; virtual;
|
||||
procedure SendCommandDataToDbg(); virtual;
|
||||
procedure SetStateRunning;
|
||||
function ProcessInputFromDbg(const AData: String): Boolean; virtual; abstract; // True if data was handled
|
||||
|
||||
// function GetTimeOutVerifier: TDBGInstruction; virtual;
|
||||
@ -273,6 +274,12 @@ begin
|
||||
FState := disDataSent;
|
||||
end;
|
||||
|
||||
procedure TDBGInstruction.SetStateRunning;
|
||||
begin
|
||||
Assert(FState=disQueued, 'FState=disQueued');
|
||||
FState := disDataSent;
|
||||
end;
|
||||
|
||||
procedure TDBGInstruction.Init;
|
||||
begin
|
||||
//
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,7 @@ uses
|
||||
|
||||
function LastPos(ASearch, AString: string): Integer;
|
||||
|
||||
function StrStartsWith(AString, AStart: string): Boolean;
|
||||
function StrStartsWith(AString, AStart: string; ACheckStartNotEmpty: Boolean = False): Boolean;
|
||||
function StrContains(AString, AFind: string): Boolean;
|
||||
function StrMatches(AString: string; AFind: array of string): Boolean;
|
||||
function StrMatches(AString: string; AFind: array of string; out AGapsContent: TStringArray): Boolean;
|
||||
@ -23,9 +23,13 @@ function ParseFrameLocation(AnInput: String; out AnId: Integer;
|
||||
out AnArgs: TStringList; out AFile: String; out ALine: Integer;
|
||||
out AReminder: String): Boolean;
|
||||
function ParseNewFrameLocation(AnInput: String; out AnId: Integer;
|
||||
out AnIsCurrent: Boolean; out AnAddr: TDBGPtr; out AFuncName: String;
|
||||
out AnIsCurrent: Boolean; out AnAddr, AnStack, AnFrame: TDBGPtr; out AFuncName: String;
|
||||
out AnArgs: TStringList; out AFile, AFullFile: String; out ALine: Integer;
|
||||
out AReminder: String): Boolean;
|
||||
function ParseNewThreadLocation(AnInput: String; out AnId: Integer;
|
||||
out AnIsCurrent: Boolean; out AName: String; out AnAddr, AnStack, AnFrame: TDBGPtr;
|
||||
out AFuncName: String; out AnArgs: TStringList; out AFile, AFullFile: String;
|
||||
out ALine: Integer; out AReminder: String): Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
@ -41,9 +45,10 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function StrStartsWith(AString, AStart: string): Boolean;
|
||||
function StrStartsWith(AString, AStart: string; ACheckStartNotEmpty: Boolean
|
||||
): Boolean;
|
||||
begin
|
||||
Result := LeftStr(AString, Length(AStart)) = AStart;
|
||||
Result := ( (not ACheckStartNotEmpty) or (AStart <> '') ) and (LeftStr(AString, Length(AStart)) = AStart);
|
||||
end;
|
||||
|
||||
function StrContains(AString, AFind: string): Boolean;
|
||||
@ -238,23 +243,19 @@ begin
|
||||
ParseLocation(AnInput, AnAddr, AFuncName, AnArgs, AFile, ALine, AReminder);
|
||||
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;
|
||||
function ParseFrameOrThread(AnInput: String; out AnAddr, AnStack, AnFrame: 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},
|
||||
if not StrMatches(AnInput, [''{addr}, ', ' {sp}, ', ' {fp},
|
||||
' &&//FULL: '{fullfile}, ' &&//SHORT: '{file},' &&//LINE: '{line},
|
||||
' &&//MOD: '{mod},' &&//FUNC: '{func}, '',' <<&&//FRAME', ''
|
||||
], found) then begin
|
||||
AnId := -1;
|
||||
AnAddr := 0;
|
||||
AFile := '';
|
||||
AFullFile := '';
|
||||
@ -265,17 +266,18 @@ begin
|
||||
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];
|
||||
AnAddr := StrToInt64Def(found[0], 0);
|
||||
AnStack := StrToInt64Def(found[1], 0);
|
||||
AnFrame := StrToInt64Def(found[2], 0);
|
||||
AFullFile := found[3];
|
||||
AFile := found[4];
|
||||
ALine := StrToIntDef(found[5], -1);
|
||||
AFuncName := found[7];
|
||||
AnArgs := nil;
|
||||
AReminder := found[7];
|
||||
AReminder := found[8];
|
||||
|
||||
if AFuncName = '' then begin
|
||||
AFuncName := '<'+found[5]+'>';
|
||||
AFuncName := '<'+found[6]+'>';
|
||||
end
|
||||
else begin
|
||||
AnInput := AFuncName;
|
||||
@ -293,5 +295,53 @@ begin
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function ParseNewFrameLocation(AnInput: String; out AnId: Integer; out
|
||||
AnIsCurrent: Boolean; out AnAddr, AnStack, AnFrame: TDBGPtr; out
|
||||
AFuncName: String; out AnArgs: TStringList; out AFile, AFullFile: String; out
|
||||
ALine: Integer; out AReminder: String): Boolean;
|
||||
var
|
||||
found: TStringArray;
|
||||
begin
|
||||
AnIsCurrent := (Length(AnInput) > 3) and (AnInput[3] = '*');
|
||||
if AnIsCurrent then AnInput[3] := ' ';
|
||||
|
||||
if StrMatches(AnInput, [' frame #'{id}, ': '{}, ''], found) then begin
|
||||
AnId := StrToIntDef(found[0], -1);
|
||||
AnInput := found[1];
|
||||
end
|
||||
else begin
|
||||
AnId := -1;
|
||||
AnInput := '';
|
||||
end;
|
||||
|
||||
Result := ParseFrameOrThread(AnInput, AnAddr, AnStack, AnFrame,
|
||||
AFuncName, AnArgs, AFile, AFullFile, ALine, AReminder);
|
||||
end;
|
||||
|
||||
function ParseNewThreadLocation(AnInput: String; out AnId: Integer; out
|
||||
AnIsCurrent: Boolean; out AName: String; out AnAddr, AnStack,
|
||||
AnFrame: TDBGPtr; out AFuncName: String; out AnArgs: TStringList; out AFile,
|
||||
AFullFile: String; out ALine: Integer; out AReminder: String): Boolean;
|
||||
var
|
||||
found: TStringArray;
|
||||
begin
|
||||
AnIsCurrent := (Length(AnInput) > 1) and (AnInput[1] = '*');
|
||||
if AnIsCurrent then AnInput[1] := ' ';
|
||||
|
||||
if StrMatches(AnInput, [' thread #'{id}, ': tid='{tid}, ': '{}, ''], found) then begin
|
||||
AnId := StrToIntDef(found[0], -1);
|
||||
AName := found[1];
|
||||
AnInput := found[2];
|
||||
end
|
||||
else begin
|
||||
AnId := -1;
|
||||
AName := '';
|
||||
AnInput := '';
|
||||
end;
|
||||
|
||||
Result := ParseFrameOrThread(AnInput, AnAddr, AnStack, AnFrame,
|
||||
AFuncName, AnArgs, AFile, AFullFile, ALine, AReminder);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -76,6 +76,15 @@ type
|
||||
constructor Create;
|
||||
end;
|
||||
|
||||
{ TLldbInstructionTargetStopHook }
|
||||
|
||||
TLldbInstructionTargetStopHook = class(TLldbInstruction)
|
||||
protected
|
||||
function ProcessInputFromDbg(const AData: String): Boolean; override;
|
||||
public
|
||||
constructor Create(const ACmd: String);
|
||||
end;
|
||||
|
||||
{ TLldbInstructionProcessLaunch }
|
||||
|
||||
TLldbInstructionProcessLaunch = class(TLldbInstruction)
|
||||
@ -308,6 +317,14 @@ type
|
||||
property Res: TStringArray read FRes;
|
||||
end;
|
||||
|
||||
{ TLldbInstructionThreadListReader }
|
||||
|
||||
TLldbInstructionThreadListReader = class(TLldbInstructionThreadList)
|
||||
protected
|
||||
procedure SendCommandDataToDbg(); override;
|
||||
function ProcessInputFromDbg(const AData: String): Boolean; override;
|
||||
end;
|
||||
|
||||
{ TLldbInstructionStackTrace }
|
||||
|
||||
TLldbInstructionStackTrace = class(TLldbInstruction)
|
||||
@ -416,10 +433,6 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
if StrMatches(ALine, ['Process ', ' stopped']) then begin // TODO: needed?
|
||||
ALine := '';
|
||||
end;
|
||||
|
||||
// TODO: detect the echo, and flag if data is for RunningInstruction;
|
||||
|
||||
// if LeftStr(ALine, 7) = 'error: ' then begin
|
||||
@ -454,6 +467,15 @@ begin
|
||||
Instr.Cancel;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (RunningInstruction <> nil) and
|
||||
(TLldbInstruction(RunningInstruction).OwningCommand = ACommand) and
|
||||
(not RunningInstruction.IsCompleted)
|
||||
then begin
|
||||
RunningInstruction.OnFailure := nil;
|
||||
RunningInstruction.OnFinish := nil;
|
||||
RunningInstruction.Cancel;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TLldbInstruction }
|
||||
@ -542,13 +564,31 @@ begin
|
||||
inherited Create('target delete 0');
|
||||
end;
|
||||
|
||||
{ TLldbInstructionTargetStopHook }
|
||||
|
||||
function TLldbInstructionTargetStopHook.ProcessInputFromDbg(const AData: String
|
||||
): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
if StrStartsWith(AData, 'Stop hook ') and (pos(' added', AData) > 8) then begin
|
||||
SetContentReceieved;
|
||||
end
|
||||
else
|
||||
Result := inherited;
|
||||
end;
|
||||
|
||||
constructor TLldbInstructionTargetStopHook.Create(const ACmd: String);
|
||||
begin
|
||||
inherited Create(Format('target stop-hook add -o "%s"', [ACmd]));
|
||||
end;
|
||||
|
||||
{ TLldbInstructionProcessLaunch }
|
||||
|
||||
function TLldbInstructionProcessLaunch.ProcessInputFromDbg(const AData: String
|
||||
): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
if (LeftStr(AData, 8) = 'Process ') and (pos(' launched:', AData) > 8) then begin
|
||||
if StrStartsWith(AData, 'Process ') and (pos(' launched:', AData) > 8) then begin
|
||||
SetContentReceieved;
|
||||
end
|
||||
else
|
||||
@ -910,6 +950,7 @@ end;
|
||||
procedure TLldbInstructionReadExpression.SendCommandDataToDbg();
|
||||
begin
|
||||
// do not sent data
|
||||
SetStateRunning;
|
||||
end;
|
||||
|
||||
constructor TLldbInstructionReadExpression.Create;
|
||||
@ -1114,6 +1155,32 @@ begin
|
||||
FRes := nil;
|
||||
end;
|
||||
|
||||
{ TLldbInstructionThreadListReader }
|
||||
|
||||
procedure TLldbInstructionThreadListReader.SendCommandDataToDbg();
|
||||
begin
|
||||
// send nothing
|
||||
SetStateRunning;
|
||||
FReading := True;
|
||||
end;
|
||||
|
||||
function TLldbInstructionThreadListReader.ProcessInputFromDbg(
|
||||
const AData: String): Boolean;
|
||||
begin
|
||||
if StrMatches(AData, ['* stopped in thread #', ', stop reason = ', '']) then begin
|
||||
FRes := nil;
|
||||
Result := False; // no data
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result := inherited ProcessInputFromDbg(AData);
|
||||
|
||||
if StrMatches(AData, ['Process ', 'stopped']) then begin
|
||||
MarkAsSuccess;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TLldbInstructionStackTrace }
|
||||
|
||||
procedure TLldbInstructionStackTrace.SendCommandDataToDbg();
|
||||
|
Loading…
Reference in New Issue
Block a user