mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-27 11:00:37 +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;
|
procedure TDebuggerIntf.LockRelease;
|
||||||
begin
|
begin
|
||||||
inc(FReleaseLock);
|
inc(FReleaseLock);
|
||||||
DebugLnEnter(DBG_VERBOSE, ['> TLldbDebugger.LockRelease ',FReleaseLock]);
|
DebugLnEnter(DBG_VERBOSE, ['> TDebuggerIntf.LockRelease ',FReleaseLock]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDebuggerIntf.UnlockRelease;
|
procedure TDebuggerIntf.UnlockRelease;
|
||||||
begin
|
begin
|
||||||
DebugLnExit(DBG_VERBOSE, ['< TLldbDebugger.UnlockRelease ',FReleaseLock]);
|
DebugLnExit(DBG_VERBOSE, ['< TDebuggerIntf.UnlockRelease ',FReleaseLock]);
|
||||||
dec(FReleaseLock);
|
dec(FReleaseLock);
|
||||||
if (FReleaseLock = 0) and (State = dsDestroying)
|
if (FReleaseLock = 0) and (State = dsDestroying)
|
||||||
then Release;
|
then Release;
|
||||||
|
@ -61,6 +61,7 @@ type
|
|||||||
protected
|
protected
|
||||||
function GetCommandAsString(): String; virtual;
|
function GetCommandAsString(): String; virtual;
|
||||||
procedure SendCommandDataToDbg(); virtual;
|
procedure SendCommandDataToDbg(); virtual;
|
||||||
|
procedure SetStateRunning;
|
||||||
function ProcessInputFromDbg(const AData: String): Boolean; virtual; abstract; // True if data was handled
|
function ProcessInputFromDbg(const AData: String): Boolean; virtual; abstract; // True if data was handled
|
||||||
|
|
||||||
// function GetTimeOutVerifier: TDBGInstruction; virtual;
|
// function GetTimeOutVerifier: TDBGInstruction; virtual;
|
||||||
@ -273,6 +274,12 @@ begin
|
|||||||
FState := disDataSent;
|
FState := disDataSent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDBGInstruction.SetStateRunning;
|
||||||
|
begin
|
||||||
|
Assert(FState=disQueued, 'FState=disQueued');
|
||||||
|
FState := disDataSent;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDBGInstruction.Init;
|
procedure TDBGInstruction.Init;
|
||||||
begin
|
begin
|
||||||
//
|
//
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,7 @@ uses
|
|||||||
|
|
||||||
function LastPos(ASearch, AString: string): Integer;
|
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 StrContains(AString, AFind: string): Boolean;
|
||||||
function StrMatches(AString: string; AFind: array of string): Boolean;
|
function StrMatches(AString: string; AFind: array of string): Boolean;
|
||||||
function StrMatches(AString: string; AFind: array of string; out AGapsContent: TStringArray): 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 AnArgs: TStringList; out AFile: String; out ALine: Integer;
|
||||||
out AReminder: String): Boolean;
|
out AReminder: String): Boolean;
|
||||||
function ParseNewFrameLocation(AnInput: String; out AnId: Integer;
|
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 AnArgs: TStringList; out AFile, AFullFile: String; out ALine: Integer;
|
||||||
out AReminder: String): Boolean;
|
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
|
implementation
|
||||||
|
|
||||||
@ -41,9 +45,10 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function StrStartsWith(AString, AStart: string): Boolean;
|
function StrStartsWith(AString, AStart: string; ACheckStartNotEmpty: Boolean
|
||||||
|
): Boolean;
|
||||||
begin
|
begin
|
||||||
Result := LeftStr(AString, Length(AStart)) = AStart;
|
Result := ( (not ACheckStartNotEmpty) or (AStart <> '') ) and (LeftStr(AString, Length(AStart)) = AStart);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function StrContains(AString, AFind: string): Boolean;
|
function StrContains(AString, AFind: string): Boolean;
|
||||||
@ -238,23 +243,19 @@ 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
|
function ParseFrameOrThread(AnInput: String; out AnAddr, AnStack, AnFrame: TDBGPtr;
|
||||||
AnIsCurrent: Boolean; out AnAddr: TDBGPtr; out AFuncName: String; out
|
out AFuncName: String; out AnArgs: TStringList; out AFile, AFullFile: String;
|
||||||
AnArgs: TStringList; out AFile, AFullFile: String; out ALine: Integer; out
|
out ALine: Integer; out AReminder: String): Boolean;
|
||||||
AReminder: String): Boolean;
|
|
||||||
var
|
var
|
||||||
found: TStringArray;
|
found: TStringArray;
|
||||||
i, j, k: SizeInt;
|
i, j, k: SizeInt;
|
||||||
begin
|
begin
|
||||||
Result := False;
|
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},
|
' &&//FULL: '{fullfile}, ' &&//SHORT: '{file},' &&//LINE: '{line},
|
||||||
' &&//MOD: '{mod},' &&//FUNC: '{func}, '',' <<&&//FRAME', ''
|
' &&//MOD: '{mod},' &&//FUNC: '{func}, '',' <<&&//FRAME', ''
|
||||||
], found) then begin
|
], found) then begin
|
||||||
AnId := -1;
|
|
||||||
AnAddr := 0;
|
AnAddr := 0;
|
||||||
AFile := '';
|
AFile := '';
|
||||||
AFullFile := '';
|
AFullFile := '';
|
||||||
@ -265,17 +266,18 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
AnId := StrToIntDef(found[0], -1);
|
AnAddr := StrToInt64Def(found[0], 0);
|
||||||
AnAddr := StrToInt64Def(found[1], 0);
|
AnStack := StrToInt64Def(found[1], 0);
|
||||||
AFullFile := found[2];
|
AnFrame := StrToInt64Def(found[2], 0);
|
||||||
AFile := found[3];
|
AFullFile := found[3];
|
||||||
ALine := StrToIntDef(found[4], -1);
|
AFile := found[4];
|
||||||
AFuncName := found[6];
|
ALine := StrToIntDef(found[5], -1);
|
||||||
|
AFuncName := found[7];
|
||||||
AnArgs := nil;
|
AnArgs := nil;
|
||||||
AReminder := found[7];
|
AReminder := found[8];
|
||||||
|
|
||||||
if AFuncName = '' then begin
|
if AFuncName = '' then begin
|
||||||
AFuncName := '<'+found[5]+'>';
|
AFuncName := '<'+found[6]+'>';
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
AnInput := AFuncName;
|
AnInput := AFuncName;
|
||||||
@ -293,5 +295,53 @@ begin
|
|||||||
Result := True;
|
Result := True;
|
||||||
end;
|
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.
|
end.
|
||||||
|
|
||||||
|
@ -76,6 +76,15 @@ type
|
|||||||
constructor Create;
|
constructor Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TLldbInstructionTargetStopHook }
|
||||||
|
|
||||||
|
TLldbInstructionTargetStopHook = class(TLldbInstruction)
|
||||||
|
protected
|
||||||
|
function ProcessInputFromDbg(const AData: String): Boolean; override;
|
||||||
|
public
|
||||||
|
constructor Create(const ACmd: String);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TLldbInstructionProcessLaunch }
|
{ TLldbInstructionProcessLaunch }
|
||||||
|
|
||||||
TLldbInstructionProcessLaunch = class(TLldbInstruction)
|
TLldbInstructionProcessLaunch = class(TLldbInstruction)
|
||||||
@ -308,6 +317,14 @@ type
|
|||||||
property Res: TStringArray read FRes;
|
property Res: TStringArray read FRes;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TLldbInstructionThreadListReader }
|
||||||
|
|
||||||
|
TLldbInstructionThreadListReader = class(TLldbInstructionThreadList)
|
||||||
|
protected
|
||||||
|
procedure SendCommandDataToDbg(); override;
|
||||||
|
function ProcessInputFromDbg(const AData: String): Boolean; override;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TLldbInstructionStackTrace }
|
{ TLldbInstructionStackTrace }
|
||||||
|
|
||||||
TLldbInstructionStackTrace = class(TLldbInstruction)
|
TLldbInstructionStackTrace = class(TLldbInstruction)
|
||||||
@ -416,10 +433,6 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
// if LeftStr(ALine, 7) = 'error: ' then begin
|
// if LeftStr(ALine, 7) = 'error: ' then begin
|
||||||
@ -454,6 +467,15 @@ begin
|
|||||||
Instr.Cancel;
|
Instr.Cancel;
|
||||||
end;
|
end;
|
||||||
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;
|
end;
|
||||||
|
|
||||||
{ TLldbInstruction }
|
{ TLldbInstruction }
|
||||||
@ -542,13 +564,31 @@ begin
|
|||||||
inherited Create('target delete 0');
|
inherited Create('target delete 0');
|
||||||
end;
|
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 }
|
{ TLldbInstructionProcessLaunch }
|
||||||
|
|
||||||
function TLldbInstructionProcessLaunch.ProcessInputFromDbg(const AData: String
|
function TLldbInstructionProcessLaunch.ProcessInputFromDbg(const AData: String
|
||||||
): Boolean;
|
): Boolean;
|
||||||
begin
|
begin
|
||||||
Result := True;
|
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;
|
SetContentReceieved;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -910,6 +950,7 @@ end;
|
|||||||
procedure TLldbInstructionReadExpression.SendCommandDataToDbg();
|
procedure TLldbInstructionReadExpression.SendCommandDataToDbg();
|
||||||
begin
|
begin
|
||||||
// do not sent data
|
// do not sent data
|
||||||
|
SetStateRunning;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TLldbInstructionReadExpression.Create;
|
constructor TLldbInstructionReadExpression.Create;
|
||||||
@ -1114,6 +1155,32 @@ begin
|
|||||||
FRes := nil;
|
FRes := nil;
|
||||||
end;
|
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 }
|
{ TLldbInstructionStackTrace }
|
||||||
|
|
||||||
procedure TLldbInstructionStackTrace.SendCommandDataToDbg();
|
procedure TLldbInstructionStackTrace.SendCommandDataToDbg();
|
||||||
|
Loading…
Reference in New Issue
Block a user