mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-20 13:19:21 +02:00
FpDebug, LazDebuggerFp: Implement step to except/finally / step over ignored exception
git-svn-id: trunk@62344 -
This commit is contained in:
parent
c1611124b4
commit
489625b121
@ -150,7 +150,8 @@ type
|
|||||||
FCallStackEntryList: TDbgCallstackEntryList;
|
FCallStackEntryList: TDbgCallstackEntryList;
|
||||||
FRegisterValueListValid: boolean;
|
FRegisterValueListValid: boolean;
|
||||||
FRegisterValueList: TDbgRegisterValueList;
|
FRegisterValueList: TDbgRegisterValueList;
|
||||||
FStoreStepSrcFilename: string;
|
FStoreStepSrcFilename, FStoreStepFuncName: string;
|
||||||
|
FStoreStepStartAddr, FStoreStepEndAddr: TDBGPtr;
|
||||||
FStoreStepSrcLineNo: integer;
|
FStoreStepSrcLineNo: integer;
|
||||||
FStoreStepFuncAddr: TDBGPtr;
|
FStoreStepFuncAddr: TDBGPtr;
|
||||||
procedure LoadRegisterValues; virtual;
|
procedure LoadRegisterValues; virtual;
|
||||||
@ -173,7 +174,7 @@ type
|
|||||||
procedure PrepareCallStackEntryList(AFrameRequired: Integer = -1); virtual;
|
procedure PrepareCallStackEntryList(AFrameRequired: Integer = -1); virtual;
|
||||||
procedure ClearCallStack;
|
procedure ClearCallStack;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function CompareStepInfo(AnAddr: TDBGPtr = 0): TFPDCompareStepInfo;
|
function CompareStepInfo(AnAddr: TDBGPtr = 0; ASubLine: Boolean = False): TFPDCompareStepInfo;
|
||||||
function IsAtStartOfLine: boolean;
|
function IsAtStartOfLine: boolean;
|
||||||
procedure StoreStepInfo(AnAddr: TDBGPtr = 0);
|
procedure StoreStepInfo(AnAddr: TDBGPtr = 0);
|
||||||
property ID: Integer read FID;
|
property ID: Integer read FID;
|
||||||
@ -181,6 +182,7 @@ type
|
|||||||
property NextIsSingleStep: boolean read FNextIsSingleStep write FNextIsSingleStep;
|
property NextIsSingleStep: boolean read FNextIsSingleStep write FNextIsSingleStep;
|
||||||
property RegisterValueList: TDbgRegisterValueList read GetRegisterValueList;
|
property RegisterValueList: TDbgRegisterValueList read GetRegisterValueList;
|
||||||
property CallStackEntryList: TDbgCallstackEntryList read FCallStackEntryList;
|
property CallStackEntryList: TDbgCallstackEntryList read FCallStackEntryList;
|
||||||
|
property StoreStepFuncName: String read FStoreStepFuncName;
|
||||||
end;
|
end;
|
||||||
TDbgThreadClass = class of TDbgThread;
|
TDbgThreadClass = class of TDbgThread;
|
||||||
|
|
||||||
@ -1999,7 +2001,8 @@ begin
|
|||||||
result := FRegisterValueList;
|
result := FRegisterValueList;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDbgThread.CompareStepInfo(AnAddr: TDBGPtr): TFPDCompareStepInfo;
|
function TDbgThread.CompareStepInfo(AnAddr: TDBGPtr; ASubLine: Boolean
|
||||||
|
): TFPDCompareStepInfo;
|
||||||
var
|
var
|
||||||
Sym: TFpSymbol;
|
Sym: TFpSymbol;
|
||||||
l: TDBGPtr;
|
l: TDBGPtr;
|
||||||
@ -2011,6 +2014,21 @@ begin
|
|||||||
|
|
||||||
if AnAddr = 0 then
|
if AnAddr = 0 then
|
||||||
AnAddr := GetInstructionPointerRegisterValue;
|
AnAddr := GetInstructionPointerRegisterValue;
|
||||||
|
|
||||||
|
if (FStoreStepStartAddr <> 0) then begin
|
||||||
|
if (AnAddr > FStoreStepStartAddr) and (AnAddr < FStoreStepEndAddr)
|
||||||
|
then begin
|
||||||
|
result := dcsiSameLine;
|
||||||
|
exit;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if ASubLine then begin
|
||||||
|
// this is used for the (unmarked) proloque of finally handlers in 3.1.1
|
||||||
|
result := dcsiNewLine; // may have the same line number, but has a new address block
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
sym := FProcess.FindProcSymbol(AnAddr);
|
sym := FProcess.FindProcSymbol(AnAddr);
|
||||||
if assigned(sym) then
|
if assigned(sym) then
|
||||||
begin
|
begin
|
||||||
@ -2064,11 +2082,16 @@ begin
|
|||||||
if AnAddr = 0 then
|
if AnAddr = 0 then
|
||||||
AnAddr := GetInstructionPointerRegisterValue;
|
AnAddr := GetInstructionPointerRegisterValue;
|
||||||
sym := FProcess.FindProcSymbol(AnAddr);
|
sym := FProcess.FindProcSymbol(AnAddr);
|
||||||
|
FStoreStepStartAddr := AnAddr;
|
||||||
|
FStoreStepEndAddr := AnAddr;
|
||||||
if assigned(sym) then
|
if assigned(sym) then
|
||||||
begin
|
begin
|
||||||
FStoreStepSrcFilename:=sym.FileName;
|
FStoreStepSrcFilename:=sym.FileName;
|
||||||
FStoreStepFuncAddr:=sym.Address.Address;
|
FStoreStepFuncAddr:=sym.Address.Address;
|
||||||
|
FStoreStepFuncName:=sym.Name;
|
||||||
if sym is TFpSymbolDwarfDataProc then begin
|
if sym is TFpSymbolDwarfDataProc then begin
|
||||||
|
FStoreStepStartAddr := TFpSymbolDwarfDataProc(sym).LineStartAddress;
|
||||||
|
FStoreStepEndAddr := TFpSymbolDwarfDataProc(sym).LineEndAddress;
|
||||||
FStoreStepSrcLineNo := TFpSymbolDwarfDataProc(sym).LineUnfixed;
|
FStoreStepSrcLineNo := TFpSymbolDwarfDataProc(sym).LineUnfixed;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -16,22 +16,28 @@ uses
|
|||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
TDbgController = class;
|
||||||
|
TDbgControllerCmd = class;
|
||||||
|
|
||||||
TOnCreateProcessEvent = procedure(var continue: boolean) of object;
|
TOnCreateProcessEvent = procedure(var continue: boolean) of object;
|
||||||
TOnHitBreakpointEvent = procedure(var continue: boolean; const Breakpoint: TFpDbgBreakpoint) of object;
|
TOnHitBreakpointEvent = procedure(var continue: boolean; const Breakpoint: TFpDbgBreakpoint) of object;
|
||||||
TOnExceptionEvent = procedure(var continue: boolean; const ExceptionClass, ExceptionMessage: string) of object;
|
TOnExceptionEvent = procedure(var continue: boolean; const ExceptionClass, ExceptionMessage: string) of object;
|
||||||
TOnProcessExitEvent = procedure(ExitCode: DWord) of object;
|
TOnProcessExitEvent = procedure(ExitCode: DWord) of object;
|
||||||
TOnLibraryLoadedEvent = procedure(var continue: boolean; ALib: TDbgLibrary) of object;
|
TOnLibraryLoadedEvent = procedure(var continue: boolean; ALib: TDbgLibrary) of object;
|
||||||
TOnLibraryUnloadedEvent = procedure(var continue: boolean; ALib: TDbgLibrary) of object;
|
TOnLibraryUnloadedEvent = procedure(var continue: boolean; ALib: TDbgLibrary) of object;
|
||||||
|
TOnProcessLoopCycleEvent = procedure(var AFinishLoopAndSendEvents: boolean; var AnEventType: TFPDEvent;
|
||||||
TDbgController = class;
|
var ACurCommand: TDbgControllerCmd; var AnIsFinished: boolean) of object;
|
||||||
|
|
||||||
{ TDbgControllerCmd }
|
{ TDbgControllerCmd }
|
||||||
|
|
||||||
TDbgControllerCmd = class
|
TDbgControllerCmd = class
|
||||||
|
private
|
||||||
|
procedure SetThread(AValue: TDbgThread);
|
||||||
protected
|
protected
|
||||||
FController: TDbgController;
|
FController: TDbgController;
|
||||||
FThread: TDbgThread;
|
FThread: TDbgThread;
|
||||||
FProcess: TDbgProcess;
|
FProcess: TDbgProcess;
|
||||||
|
FThreadRemoved: boolean;
|
||||||
FIsInitialized: Boolean;
|
FIsInitialized: Boolean;
|
||||||
procedure Init; virtual;
|
procedure Init; virtual;
|
||||||
function IsAtCallInstruction: Integer;
|
function IsAtCallInstruction: Integer;
|
||||||
@ -42,6 +48,7 @@ type
|
|||||||
procedure DoBeforeLoopStart;
|
procedure DoBeforeLoopStart;
|
||||||
procedure DoContinue(AProcess: TDbgProcess; AThread: TDbgThread); virtual; abstract;
|
procedure DoContinue(AProcess: TDbgProcess; AThread: TDbgThread); virtual; abstract;
|
||||||
procedure ResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Finished: boolean); virtual;
|
procedure ResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Finished: boolean); virtual;
|
||||||
|
property Thread: TDbgThread read FThread write SetThread;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TDbgControllerContinueCmd }
|
{ TDbgControllerContinueCmd }
|
||||||
@ -83,6 +90,7 @@ type
|
|||||||
function IsAtOrOutOfHiddenBreakFrame: Boolean; inline; // Stopped in/out-of the origin frame, maybe by a breakpoint after an exception
|
function IsAtOrOutOfHiddenBreakFrame: Boolean; inline; // Stopped in/out-of the origin frame, maybe by a breakpoint after an exception
|
||||||
procedure SetHiddenBreak(AnAddr: TDBGPtr);
|
procedure SetHiddenBreak(AnAddr: TDBGPtr);
|
||||||
procedure RemoveHiddenBreak;
|
procedure RemoveHiddenBreak;
|
||||||
|
property NextInstruction: TInstruction read FNextInstruction;
|
||||||
|
|
||||||
function CheckForCallAndSetBreak: boolean; // True, if break is newly set
|
function CheckForCallAndSetBreak: boolean; // True, if break is newly set
|
||||||
|
|
||||||
@ -110,10 +118,16 @@ type
|
|||||||
|
|
||||||
TDbgControllerLineStepBaseCmd = class(TDbgControllerHiddenBreakStepBaseCmd)
|
TDbgControllerLineStepBaseCmd = class(TDbgControllerHiddenBreakStepBaseCmd)
|
||||||
private
|
private
|
||||||
|
FStartedInFuncName: String;
|
||||||
FStepInfoUpdatedForStepOut, FStepInfoUnavailAfterStepOut: Boolean;
|
FStepInfoUpdatedForStepOut, FStepInfoUnavailAfterStepOut: Boolean;
|
||||||
|
FStoreStepInfoAtInit: Boolean;
|
||||||
protected
|
protected
|
||||||
|
procedure Init; override;
|
||||||
procedure UpdateThreadStepInfoAfterStepOut;
|
procedure UpdateThreadStepInfoAfterStepOut;
|
||||||
function HasSteppedAwayFromOriginLine: boolean; // Call only, if in original frame (or updated frame)
|
function HasSteppedAwayFromOriginLine: boolean; // Call only, if in original frame (or updated frame)
|
||||||
|
public
|
||||||
|
constructor Create(AController: TDbgController; AStoreStepInfoAtInit: Boolean = False);
|
||||||
|
property StartedInFuncName: String read FStartedInFuncName;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TDbgControllerStepIntoLineCmd }
|
{ TDbgControllerStepIntoLineCmd }
|
||||||
@ -123,9 +137,10 @@ type
|
|||||||
FState: (siSteppingCurrent, siSteppingIn, siSteppingNested, siRunningStepOut);
|
FState: (siSteppingCurrent, siSteppingIn, siSteppingNested, siRunningStepOut);
|
||||||
FStepCount, FNestDepth: Integer;
|
FStepCount, FNestDepth: Integer;
|
||||||
protected
|
protected
|
||||||
procedure Init; override;
|
|
||||||
procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Finished: boolean); override;
|
procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Finished: boolean); override;
|
||||||
procedure InternalContinue(AProcess: TDbgProcess; AThread: TDbgThread); override;
|
procedure InternalContinue(AProcess: TDbgProcess; AThread: TDbgThread); override;
|
||||||
|
public
|
||||||
|
constructor Create(AController: TDbgController);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TDbgControllerStepOverLineCmd }
|
{ TDbgControllerStepOverLineCmd }
|
||||||
@ -135,6 +150,8 @@ type
|
|||||||
procedure Init; override;
|
procedure Init; override;
|
||||||
procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Finished: boolean); override;
|
procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Finished: boolean); override;
|
||||||
procedure InternalContinue(AProcess: TDbgProcess; AThread: TDbgThread); override;
|
procedure InternalContinue(AProcess: TDbgProcess; AThread: TDbgThread); override;
|
||||||
|
public
|
||||||
|
constructor Create(AController: TDbgController);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TDbgControllerStepOutCmd }
|
{ TDbgControllerStepOutCmd }
|
||||||
@ -146,10 +163,10 @@ type
|
|||||||
FWasOutsideFrame: boolean;
|
FWasOutsideFrame: boolean;
|
||||||
protected
|
protected
|
||||||
function GetOutsideFrame(var AnOutside: Boolean): Boolean;
|
function GetOutsideFrame(var AnOutside: Boolean): Boolean;
|
||||||
procedure SetReturnAdressBreakpoint(AProcess: TDbgProcess; AnOutsideFrame: Boolean);
|
|
||||||
procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Finished: boolean); override;
|
procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Finished: boolean); override;
|
||||||
procedure InternalContinue(AProcess: TDbgProcess; AThread: TDbgThread); override;
|
procedure InternalContinue(AProcess: TDbgProcess; AThread: TDbgThread); override;
|
||||||
public
|
public
|
||||||
|
procedure SetReturnAdressBreakpoint(AProcess: TDbgProcess; AnOutsideFrame: Boolean);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TDbgControllerRunToCmd }
|
{ TDbgControllerRunToCmd }
|
||||||
@ -171,6 +188,8 @@ type
|
|||||||
private
|
private
|
||||||
FOnLibraryLoadedEvent: TOnLibraryLoadedEvent;
|
FOnLibraryLoadedEvent: TOnLibraryLoadedEvent;
|
||||||
FOnLibraryUnloadedEvent: TOnLibraryUnloadedEvent;
|
FOnLibraryUnloadedEvent: TOnLibraryUnloadedEvent;
|
||||||
|
FOnThreadBeforeProcessLoop: TNotifyEvent;
|
||||||
|
FOnThreadProcessLoopCycleEvent: TOnProcessLoopCycleEvent;
|
||||||
FRunning, FPauseRequest: cardinal;
|
FRunning, FPauseRequest: cardinal;
|
||||||
FAttachToPid: Integer;
|
FAttachToPid: Integer;
|
||||||
FDetaching: cardinal;
|
FDetaching: cardinal;
|
||||||
@ -204,18 +223,22 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create; virtual;
|
constructor Create; virtual;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
(* InitializeCommand: set new command
|
||||||
|
Not called if command is replaced by OnThreadProcessLoopCycleEvent *)
|
||||||
procedure InitializeCommand(ACommand: TDbgControllerCmd);
|
procedure InitializeCommand(ACommand: TDbgControllerCmd);
|
||||||
|
procedure AbortCurrentCommand;
|
||||||
function Run: boolean;
|
function Run: boolean;
|
||||||
procedure Stop;
|
procedure Stop;
|
||||||
procedure StepIntoInstr;
|
procedure StepIntoInstr;
|
||||||
procedure StepOverInstr;
|
procedure StepOverInstr;
|
||||||
procedure Next;
|
procedure Next;
|
||||||
procedure Step;
|
procedure Step;
|
||||||
procedure StepOut;
|
procedure StepOut(AForceStoreStepInfo: Boolean = False);
|
||||||
function Pause: boolean;
|
function Pause: boolean;
|
||||||
function Detach: boolean;
|
function Detach: boolean;
|
||||||
procedure ProcessLoop;
|
procedure ProcessLoop;
|
||||||
procedure SendEvents(out continue: boolean);
|
procedure SendEvents(out continue: boolean);
|
||||||
|
property CurrentCommand: TDbgControllerCmd read FCommand;
|
||||||
|
|
||||||
property ExecutableFilename: string read FExecutableFilename write SetExecutableFilename;
|
property ExecutableFilename: string read FExecutableFilename write SetExecutableFilename;
|
||||||
property AttachToPid: Integer read FAttachToPid write FAttachToPid;
|
property AttachToPid: Integer read FAttachToPid write FAttachToPid;
|
||||||
@ -244,6 +267,14 @@ type
|
|||||||
property OnDebugInfoLoaded: TNotifyEvent read FOnDebugInfoLoaded write FOnDebugInfoLoaded;
|
property OnDebugInfoLoaded: TNotifyEvent read FOnDebugInfoLoaded write FOnDebugInfoLoaded;
|
||||||
property OnLibraryLoadedEvent: TOnLibraryLoadedEvent read FOnLibraryLoadedEvent write FOnLibraryLoadedEvent;
|
property OnLibraryLoadedEvent: TOnLibraryLoadedEvent read FOnLibraryLoadedEvent write FOnLibraryLoadedEvent;
|
||||||
property OnLibraryUnloadedEvent: TOnLibraryUnloadedEvent read FOnLibraryUnloadedEvent write FOnLibraryUnloadedEvent;
|
property OnLibraryUnloadedEvent: TOnLibraryUnloadedEvent read FOnLibraryUnloadedEvent write FOnLibraryUnloadedEvent;
|
||||||
|
(* Events fired inside the debug thread.
|
||||||
|
The "continue" param, is true by default. It is treated as: "continue to sent this event in procedure "SendEvents"
|
||||||
|
By setting "continue" to false, the event can be hidden.
|
||||||
|
That is, the debug thread will not interrupt for "SendEvents"
|
||||||
|
*)
|
||||||
|
|
||||||
|
property OnThreadBeforeProcessLoop: TNotifyEvent read FOnThreadBeforeProcessLoop write FOnThreadBeforeProcessLoop;
|
||||||
|
property OnThreadProcessLoopCycleEvent: TOnProcessLoopCycleEvent read FOnThreadProcessLoopCycleEvent write FOnThreadProcessLoopCycleEvent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -253,6 +284,14 @@ var
|
|||||||
|
|
||||||
{ TDbgControllerCmd }
|
{ TDbgControllerCmd }
|
||||||
|
|
||||||
|
procedure TDbgControllerCmd.SetThread(AValue: TDbgThread);
|
||||||
|
begin
|
||||||
|
if FThread = AValue then Exit;
|
||||||
|
FThread := AValue;
|
||||||
|
if AValue = nil then
|
||||||
|
FThreadRemoved := True; // Only get here if FThread was <> nil;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDbgControllerCmd.Init;
|
procedure TDbgControllerCmd.Init;
|
||||||
begin
|
begin
|
||||||
//
|
//
|
||||||
@ -301,13 +340,16 @@ procedure TDbgControllerCmd.ResolveEvent(var AnEvent: TFPDEvent;
|
|||||||
var
|
var
|
||||||
dummy: TDbgThread;
|
dummy: TDbgThread;
|
||||||
begin
|
begin
|
||||||
Finished := False;
|
Finished := FThreadRemoved;
|
||||||
|
if Finished then
|
||||||
|
exit;
|
||||||
if AnEventThread = nil then
|
if AnEventThread = nil then
|
||||||
exit;
|
exit;
|
||||||
if FThread <> nil then begin
|
if FThread <> nil then begin
|
||||||
// ResolveDebugEvent will have removed the thread, but not yet destroyed it
|
// ResolveDebugEvent will have removed the thread, but not yet destroyed it
|
||||||
// Finish, if the thread has gone.
|
// Finish, if the thread has gone.
|
||||||
Finished := not FProcess.GetThread(FThread.ID, dummy);
|
FThreadRemoved := (not FProcess.GetThread(FThread.ID, dummy)) or (FThread <> dummy);
|
||||||
|
Finished := FThreadRemoved;
|
||||||
if Finished then
|
if Finished then
|
||||||
exit;
|
exit;
|
||||||
// Only react to events for the correct thread. (Otherwise return Finished = False)
|
// Only react to events for the correct thread. (Otherwise return Finished = False)
|
||||||
@ -511,6 +553,15 @@ end;
|
|||||||
|
|
||||||
{ TDbgControllerLineStepBaseCmd }
|
{ TDbgControllerLineStepBaseCmd }
|
||||||
|
|
||||||
|
procedure TDbgControllerLineStepBaseCmd.Init;
|
||||||
|
begin
|
||||||
|
if FStoreStepInfoAtInit then begin
|
||||||
|
FThread.StoreStepInfo;
|
||||||
|
FStartedInFuncName := FThread.StoreStepFuncName;
|
||||||
|
end;
|
||||||
|
inherited Init;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDbgControllerLineStepBaseCmd.UpdateThreadStepInfoAfterStepOut;
|
procedure TDbgControllerLineStepBaseCmd.UpdateThreadStepInfoAfterStepOut;
|
||||||
begin
|
begin
|
||||||
if FStepInfoUpdatedForStepOut or not IsSteppedOut then
|
if FStepInfoUpdatedForStepOut or not IsSteppedOut then
|
||||||
@ -565,6 +616,13 @@ begin
|
|||||||
Result := True;
|
Result := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
constructor TDbgControllerLineStepBaseCmd.Create(AController: TDbgController;
|
||||||
|
AStoreStepInfoAtInit: Boolean);
|
||||||
|
begin
|
||||||
|
FStoreStepInfoAtInit := AStoreStepInfoAtInit;
|
||||||
|
inherited Create(AController);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TDbgControllerStepIntoLineCmd }
|
{ TDbgControllerStepIntoLineCmd }
|
||||||
|
|
||||||
procedure TDbgControllerStepIntoLineCmd.InternalContinue(AProcess: TDbgProcess;
|
procedure TDbgControllerStepIntoLineCmd.InternalContinue(AProcess: TDbgProcess;
|
||||||
@ -583,10 +641,9 @@ begin
|
|||||||
FProcess.Continue(FProcess, FThread, FState <> siRunningStepOut);
|
FProcess.Continue(FProcess, FThread, FState <> siRunningStepOut);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDbgControllerStepIntoLineCmd.Init;
|
constructor TDbgControllerStepIntoLineCmd.Create(AController: TDbgController);
|
||||||
begin
|
begin
|
||||||
FThread.StoreStepInfo;
|
inherited Create(AController, True);
|
||||||
inherited Init;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDbgControllerStepIntoLineCmd.DoResolveEvent(var AnEvent: TFPDEvent;
|
procedure TDbgControllerStepIntoLineCmd.DoResolveEvent(var AnEvent: TFPDEvent;
|
||||||
@ -651,6 +708,11 @@ begin
|
|||||||
FProcess.Continue(FProcess, FThread, FHiddenBreakpoint = nil);
|
FProcess.Continue(FProcess, FThread, FHiddenBreakpoint = nil);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
constructor TDbgControllerStepOverLineCmd.Create(AController: TDbgController);
|
||||||
|
begin
|
||||||
|
inherited Create(AController, True);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDbgControllerStepOverLineCmd.Init;
|
procedure TDbgControllerStepOverLineCmd.Init;
|
||||||
begin
|
begin
|
||||||
FThread.StoreStepInfo;
|
FThread.StoreStepInfo;
|
||||||
@ -900,6 +962,15 @@ begin
|
|||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDbgController.AbortCurrentCommand;
|
||||||
|
begin
|
||||||
|
if FCommand = nil then
|
||||||
|
exit;
|
||||||
|
assert(FCommandToBeFreed=nil, 'TDbgController.AbortCurrentCommand: FCommandToBeFreed=nil');
|
||||||
|
FCommandToBeFreed := FCommand;
|
||||||
|
FCommand := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDbgController.InitializeCommand(ACommand: TDbgControllerCmd);
|
procedure TDbgController.InitializeCommand(ACommand: TDbgControllerCmd);
|
||||||
begin
|
begin
|
||||||
if assigned(FCommand) then
|
if assigned(FCommand) then
|
||||||
@ -974,9 +1045,9 @@ begin
|
|||||||
InitializeCommand(TDbgControllerStepIntoLineCmd.Create(self));
|
InitializeCommand(TDbgControllerStepIntoLineCmd.Create(self));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDbgController.StepOut;
|
procedure TDbgController.StepOut(AForceStoreStepInfo: Boolean);
|
||||||
begin
|
begin
|
||||||
InitializeCommand(TDbgControllerStepOutCmd.Create(self));
|
InitializeCommand(TDbgControllerStepOutCmd.Create(self, AForceStoreStepInfo));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDbgController.Pause: boolean;
|
function TDbgController.Pause: boolean;
|
||||||
@ -1014,6 +1085,7 @@ var
|
|||||||
IsFinished, b: boolean;
|
IsFinished, b: boolean;
|
||||||
EventProcess: TDbgProcess;
|
EventProcess: TDbgProcess;
|
||||||
DummyThread: TDbgThread;
|
DummyThread: TDbgThread;
|
||||||
|
CurCmd: TDbgControllerCmd;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
AExit:=false;
|
AExit:=false;
|
||||||
@ -1031,6 +1103,9 @@ begin
|
|||||||
|
|
||||||
FCurrentProcess.ThreadsClearCallStack;
|
FCurrentProcess.ThreadsClearCallStack;
|
||||||
|
|
||||||
|
if Assigned(FOnThreadBeforeProcessLoop) then
|
||||||
|
FOnThreadBeforeProcessLoop(Self);
|
||||||
|
|
||||||
repeat
|
repeat
|
||||||
if assigned(FCurrentProcess) and not assigned(FMainProcess) then begin
|
if assigned(FCurrentProcess) and not assigned(FMainProcess) then begin
|
||||||
// IF there is a pause-request, we will hit a deCreateProcess.
|
// IF there is a pause-request, we will hit a deCreateProcess.
|
||||||
@ -1060,10 +1135,13 @@ begin
|
|||||||
|
|
||||||
// TODO: replace the dangling pointer with the next best value....
|
// TODO: replace the dangling pointer with the next best value....
|
||||||
// There is still a race condition, for another thread to access it...
|
// There is still a race condition, for another thread to access it...
|
||||||
if (FCurrentThread <> nil) and not FCurrentProcess.GetThread(FCurrentThread.ID, DummyThread) then
|
if (FCurrentThread <> nil) and not FCurrentProcess.GetThread(FCurrentThread.ID, DummyThread) then begin
|
||||||
|
if (FCommand <> nil) and (FCommand.FThread = FCurrentThread) then
|
||||||
|
FCommand.Thread := nil;
|
||||||
FreeAndNil(FCurrentThread);
|
FreeAndNil(FCurrentThread);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
if not FCurrentProcess.WaitForDebugEvent(AProcessIdentifier, AThreadIdentifier) then
|
if not FCurrentProcess.WaitForDebugEvent(AProcessIdentifier, AThreadIdentifier) then
|
||||||
Continue;
|
Continue;
|
||||||
InterLockedExchange(FRunning, 0);
|
InterLockedExchange(FRunning, 0);
|
||||||
@ -1130,8 +1208,10 @@ begin
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
IsFinished:=false;
|
IsFinished:=false;
|
||||||
if FPDEvent=deExitProcess then
|
if FPDEvent=deExitProcess then begin
|
||||||
FreeAndNil(FCommand)
|
FreeAndNil(FCommand);
|
||||||
|
break;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
if assigned(FCommand) then
|
if assigned(FCommand) then
|
||||||
begin
|
begin
|
||||||
@ -1148,7 +1228,7 @@ begin
|
|||||||
b := FCurrentProcess.GetAndClearPauseRequested;
|
b := FCurrentProcess.GetAndClearPauseRequested;
|
||||||
AExit := (FCurrentProcess.CurrentBreakpoint <> nil) or
|
AExit := (FCurrentProcess.CurrentBreakpoint <> nil) or
|
||||||
( (FCurrentProcess.CurrentWatchpoint <> nil) and (FCurrentProcess.CurrentWatchpoint <> Pointer(-1)) ) or
|
( (FCurrentProcess.CurrentWatchpoint <> nil) and (FCurrentProcess.CurrentWatchpoint <> Pointer(-1)) ) or
|
||||||
(b and (InterLockedExchangeAdd(FPauseRequest, 0) = 1))
|
(b and (InterLockedExchangeAdd(FPauseRequest, 0) = 1));
|
||||||
end;
|
end;
|
||||||
{ deLoadLibrary :
|
{ deLoadLibrary :
|
||||||
begin
|
begin
|
||||||
@ -1165,8 +1245,25 @@ begin
|
|||||||
end; }
|
end; }
|
||||||
end; {case}
|
end; {case}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if assigned(FOnThreadProcessLoopCycleEvent) then begin
|
||||||
|
CurCmd := FCommand;
|
||||||
|
FOnThreadProcessLoopCycleEvent(AExit, FPDEvent, CurCmd, IsFinished);
|
||||||
|
if CurCmd = FCommand then begin
|
||||||
if IsFinished then
|
if IsFinished then
|
||||||
FreeAndNil(FCommand);
|
FreeAndNil(FCommand);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
FreeAndNil(FCommand);
|
||||||
|
FCommand := CurCmd;
|
||||||
|
if FCommand <> nil then
|
||||||
|
FCommand.DoBeforeLoopStart;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if IsFinished then
|
||||||
|
FreeAndNil(FCommand);
|
||||||
|
|
||||||
until AExit or (InterLockedExchangeAdd(FPauseRequest, 0) = 1);
|
until AExit or (InterLockedExchangeAdd(FPauseRequest, 0) = 1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -896,6 +896,8 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
|
|||||||
FAddressInfo: PDwarfAddressInfo;
|
FAddressInfo: PDwarfAddressInfo;
|
||||||
FStateMachine: TDwarfLineInfoStateMachine;
|
FStateMachine: TDwarfLineInfoStateMachine;
|
||||||
FFrameBaseParser: TDwarfLocationExpression;
|
FFrameBaseParser: TDwarfLocationExpression;
|
||||||
|
function GetLineEndAddress: TDBGPtr;
|
||||||
|
function GetLineStartAddress: TDBGPtr;
|
||||||
function GetLineUnfixed: TDBGPtr;
|
function GetLineUnfixed: TDBGPtr;
|
||||||
function StateMachineValid: Boolean;
|
function StateMachineValid: Boolean;
|
||||||
function ReadVirtuality(out AFlags: TDbgSymbolFlags): Boolean;
|
function ReadVirtuality(out AFlags: TDbgSymbolFlags): Boolean;
|
||||||
@ -917,6 +919,9 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
|
|||||||
function CreateContext(AThreadId, AStackFrame: Integer; ADwarfInfo: TFpDwarfInfo): TFpDbgInfoContext; override;
|
function CreateContext(AThreadId, AStackFrame: Integer; ADwarfInfo: TFpDwarfInfo): TFpDbgInfoContext; override;
|
||||||
// TODO members = locals ?
|
// TODO members = locals ?
|
||||||
function GetSelfParameter(AnAddress: TDbgPtr = 0): TFpValueDwarf;
|
function GetSelfParameter(AnAddress: TDbgPtr = 0): TFpValueDwarf;
|
||||||
|
// Contineous (sub-)part of the line
|
||||||
|
property LineStartAddress: TDBGPtr read GetLineStartAddress;
|
||||||
|
property LineEndAddress: TDBGPtr read GetLineEndAddress;
|
||||||
property LineUnfixed: TDBGPtr read GetLineUnfixed; // with 0 lines
|
property LineUnfixed: TDBGPtr read GetLineUnfixed; // with 0 lines
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -5109,6 +5114,31 @@ begin
|
|||||||
else Result := inherited GetLine;
|
else Result := inherited GetLine;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TFpSymbolDwarfDataProc.GetLineEndAddress: TDBGPtr;
|
||||||
|
var
|
||||||
|
sm: TDwarfLineInfoStateMachine;
|
||||||
|
begin
|
||||||
|
if StateMachineValid
|
||||||
|
then begin
|
||||||
|
sm := FStateMachine.Clone;
|
||||||
|
if sm.NextLine then
|
||||||
|
Result := sm.Address
|
||||||
|
else
|
||||||
|
Result := 0;
|
||||||
|
sm.Free;
|
||||||
|
end
|
||||||
|
else Result := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFpSymbolDwarfDataProc.GetLineStartAddress: TDBGPtr;
|
||||||
|
begin
|
||||||
|
if StateMachineValid
|
||||||
|
then
|
||||||
|
Result := FStateMachine.Address
|
||||||
|
else
|
||||||
|
Result := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
function TFpSymbolDwarfDataProc.GetLineUnfixed: TDBGPtr;
|
function TFpSymbolDwarfDataProc.GetLineUnfixed: TDBGPtr;
|
||||||
begin
|
begin
|
||||||
if StateMachineValid
|
if StateMachineValid
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user