mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-09 22:36:10 +02:00
FpDebug: Allow breakpoints on lines without code (search up to N lines below).
This commit is contained in:
parent
3f1548052d
commit
0b2c6bd8fa
@ -654,7 +654,8 @@ type
|
||||
procedure UpdateState; override;
|
||||
procedure UpdateForLibraryLoaded(ALib: TDbgLibrary); override;
|
||||
public
|
||||
constructor Create(const AProcess: TDbgProcess; const AFileName: String; ALine: Cardinal; AnEnabled: Boolean; ASymInstance: TDbgInstance = nil); virtual;
|
||||
constructor Create(const AProcess: TDbgProcess; const AFileName: String; ALine: Cardinal;
|
||||
AnEnabled: Boolean; ASymInstance: TDbgInstance = nil); virtual;
|
||||
end;
|
||||
|
||||
{ TFpInternalWatchpoint }
|
||||
@ -693,6 +694,7 @@ type
|
||||
|
||||
TDbgConfig = class
|
||||
private
|
||||
FBreakpointSearchMaxLines: integer;
|
||||
// WindowBounds
|
||||
FUseConsoleWinPos: boolean;
|
||||
FUseConsoleWinSize: boolean;
|
||||
@ -722,6 +724,8 @@ type
|
||||
property FileOverwriteStdIn: Boolean read FFileOverwriteStdIn write FFileOverwriteStdIn;
|
||||
property FileOverwriteStdOut: Boolean read FFileOverwriteStdOut write FFileOverwriteStdOut;
|
||||
property FileOverwriteStdErr: Boolean read FFileOverwriteStdErr write FFileOverwriteStdErr;
|
||||
// Breakpoints
|
||||
property BreakpointSearchMaxLines: integer read FBreakpointSearchMaxLines write FBreakpointSearchMaxLines;
|
||||
end;
|
||||
|
||||
{ TDbgInstance }
|
||||
@ -739,7 +743,8 @@ type
|
||||
function GetOSDbgClasses: TOSDbgClasses;
|
||||
function GetPointerSize: Integer;
|
||||
|
||||
function GetLineAddresses(AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray): Boolean;
|
||||
function GetLineAddresses(AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||
AFindSibling: TGetLineAddrFindSibling = fsNone; AMaxSiblingDistance: integer = 0): Boolean;
|
||||
function FindProcSymbol(const AName: String; AIgnoreCase: Boolean = False): TFpSymbol; overload;
|
||||
function FindProcSymbol(AAdress: TDbgPtr): TFpSymbol; overload;
|
||||
protected
|
||||
@ -941,7 +946,8 @@ type
|
||||
function FindSymbolScope(AThreadId, AStackFrame: Integer): TFpDbgSymbolScope;
|
||||
function FindProcStartEndPC(const AAdress: TDbgPtr; out AStartPC, AEndPC: TDBGPtr): boolean;
|
||||
|
||||
function GetLineAddresses(AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray; ASymInstance: TDbgInstance = nil): Boolean;
|
||||
function GetLineAddresses(AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray; ASymInstance: TDbgInstance = nil;
|
||||
AFindSibling: TGetLineAddrFindSibling = fsNone; AMaxSiblingDistance: integer = 0): Boolean;
|
||||
//function ContextFromProc(AThreadId, AStackFrame: Integer; AProcSym: TFpSymbol): TFpDbgLocationContext; inline; deprecated 'use TFpDbgSimpleLocationContext.Create';
|
||||
function GetLib(const AHandle: THandle; out ALib: TDbgLibrary): Boolean;
|
||||
property LibMap: TLibraryMap read FLibMap;
|
||||
@ -2230,12 +2236,14 @@ begin
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TDbgInstance.GetLineAddresses(AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray): Boolean;
|
||||
function TDbgInstance.GetLineAddresses(AFileName: String; ALine: Cardinal;
|
||||
var AResultList: TDBGPtrArray; AFindSibling: TGetLineAddrFindSibling;
|
||||
AMaxSiblingDistance: integer): Boolean;
|
||||
var
|
||||
FoundLine: Integer;
|
||||
begin
|
||||
if Assigned(DbgInfo) and DbgInfo.HasInfo then
|
||||
Result := DbgInfo.GetLineAddresses(AFileName, ALine, AResultList, fsNone, @FoundLine, @FLastLineAddressesFoundFile)
|
||||
Result := DbgInfo.GetLineAddresses(AFileName, ALine, AResultList, AFindSibling, @FoundLine, @FLastLineAddressesFoundFile, AMaxSiblingDistance)
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
@ -2628,24 +2636,25 @@ begin
|
||||
end;
|
||||
|
||||
function TDbgProcess.GetLineAddresses(AFileName: String; ALine: Cardinal;
|
||||
var AResultList: TDBGPtrArray; ASymInstance: TDbgInstance): Boolean;
|
||||
var AResultList: TDBGPtrArray; ASymInstance: TDbgInstance;
|
||||
AFindSibling: TGetLineAddrFindSibling; AMaxSiblingDistance: integer): Boolean;
|
||||
var
|
||||
Lib: TDbgLibrary;
|
||||
begin
|
||||
if ASymInstance <> nil then begin
|
||||
if ASymInstance = self then begin
|
||||
Result := inherited GetLineAddresses(AFileName, ALine, AResultList);
|
||||
Result := inherited GetLineAddresses(AFileName, ALine, AResultList, AFindSibling, AMaxSiblingDistance);
|
||||
end
|
||||
else begin
|
||||
Result := ASymInstance.GetLineAddresses(AFileName, ALine, AResultList);
|
||||
Result := ASymInstance.GetLineAddresses(AFileName, ALine, AResultList, AFindSibling, AMaxSiblingDistance);
|
||||
FLastLineAddressesFoundFile := ASymInstance.FLastLineAddressesFoundFile;
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result := inherited GetLineAddresses(AFileName, ALine, AResultList);
|
||||
Result := inherited GetLineAddresses(AFileName, ALine, AResultList, AFindSibling, AMaxSiblingDistance);
|
||||
for Lib in FLibMap do begin
|
||||
if Lib.GetLineAddresses(AFileName, ALine, AResultList) then
|
||||
if Lib.GetLineAddresses(AFileName, ALine, AResultList, AFindSibling, AMaxSiblingDistance) then
|
||||
Result := True;
|
||||
if Lib.FLastLineAddressesFoundFile then
|
||||
FLastLineAddressesFoundFile := True;
|
||||
@ -4197,29 +4206,38 @@ procedure TFpInternalBreakpointAtFileLine.UpdateForLibraryLoaded(
|
||||
ALib: TDbgLibrary);
|
||||
var
|
||||
addr: TDBGPtrArray;
|
||||
m: Integer;
|
||||
begin
|
||||
if FSymInstance <> nil then // Can not be the newly created ...
|
||||
exit;
|
||||
|
||||
addr := nil;
|
||||
Process.GetLineAddresses(FFileName, FLine, addr, ALib);
|
||||
m := Process.Config.BreakpointSearchMaxLines;
|
||||
if m > 0 then
|
||||
Process.GetLineAddresses(FFileName, FLine, addr, ALib, fsNextFuncLazy, m)
|
||||
else
|
||||
Process.GetLineAddresses(FFileName, FLine, addr, ALib);
|
||||
if Process.FLastLineAddressesFoundFile and (Length(addr) = 0) then
|
||||
FFoundFileWithoutLine := True;
|
||||
AddAddress(addr);
|
||||
end;
|
||||
|
||||
constructor TFpInternalBreakpointAtFileLine.Create(const AProcess: TDbgProcess;
|
||||
const AFileName: String; ALine: Cardinal; AnEnabled: Boolean;
|
||||
ASymInstance: TDbgInstance);
|
||||
const AFileName: String; ALine: Cardinal; AnEnabled: Boolean; ASymInstance: TDbgInstance);
|
||||
var
|
||||
addr: TDBGPtrArray;
|
||||
m: Integer;
|
||||
begin
|
||||
FFileName := AFileName;
|
||||
FLine := ALine;
|
||||
FSymInstance := ASymInstance;
|
||||
|
||||
addr := nil;
|
||||
AProcess.GetLineAddresses(AFileName, ALine, addr, ASymInstance);
|
||||
m := AProcess.Config.BreakpointSearchMaxLines;
|
||||
if m > 0 then
|
||||
AProcess.GetLineAddresses(AFileName, ALine, addr, ASymInstance, fsNextFuncLazy, m)
|
||||
else
|
||||
AProcess.GetLineAddresses(AFileName, ALine, addr, ASymInstance);
|
||||
FFoundFileWithoutLine := AProcess.FLastLineAddressesFoundFile and (Length(addr) = 0);
|
||||
inherited Create(AProcess, addr, AnEnabled);
|
||||
end;
|
||||
|
@ -492,8 +492,12 @@ type
|
||||
procedure Init;
|
||||
procedure SetAddressForLine(ALine: Cardinal; AnAddress: TDBGPtr); inline;
|
||||
function GetAddressesForLine(ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||
NoData: Boolean = False; AFindSibling: TGetLineAddrFindSibling = fsNone;
|
||||
AFoundLine: PInteger = nil): Boolean; inline;
|
||||
NoData: Boolean = False;
|
||||
AFindSibling: TGetLineAddrFindSibling = fsNone;
|
||||
AFoundLine: PInteger = nil;
|
||||
AMaxSiblingDistance: integer = 0;
|
||||
ACU: TDwarfCompilationUnit = nil
|
||||
): Boolean; inline;
|
||||
// NoData: only return True/False, but nothing in AResultList
|
||||
procedure Compress;
|
||||
end;
|
||||
@ -737,7 +741,8 @@ type
|
||||
function GetDefinition(AAbbrevPtr: Pointer; out ADefinition: TDwarfAbbrev): Boolean; inline;
|
||||
function GetLineAddressMap(const AFileName: String): PDWarfLineMap;
|
||||
function GetLineAddresses(const AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||
AFindSibling: TGetLineAddrFindSibling = fsNone; AFoundLine: PInteger = nil; AFoundFilename: PBoolean = nil): boolean;
|
||||
AFindSibling: TGetLineAddrFindSibling = fsNone; AFoundLine: PInteger = nil; AFoundFilename: PBoolean = nil;
|
||||
AMaxSiblingDistance: integer = 0): boolean;
|
||||
procedure BuildLineInfo(AAddressInfo: PDwarfAddressInfo; ADoAll: Boolean);
|
||||
// On Darwin it could be that the debug-information is not included into the executable by the linker.
|
||||
// This function is to map object-file addresses into the corresponding addresses in the executable.
|
||||
@ -815,7 +820,8 @@ type
|
||||
|
||||
//function FindSymbol(const AName: String): TDbgSymbol; override; overload;
|
||||
function GetLineAddresses(const AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||
AFindSibling: TGetLineAddrFindSibling = fsNone; AFoundLine: PInteger = nil; AFoundFilename: PBoolean = nil): Boolean; override;
|
||||
AFindSibling: TGetLineAddrFindSibling = fsNone; AFoundLine: PInteger = nil; AFoundFilename: PBoolean = nil;
|
||||
AMaxSiblingDistance: integer = 0): Boolean; override;
|
||||
function GetLineAddressMap(const AFileName: String): PDWarfLineMap;
|
||||
procedure LoadCallFrameInstructions;
|
||||
function LoadCompilationUnits: Integer;
|
||||
@ -3541,19 +3547,18 @@ begin
|
||||
Addresses[SectLen] := SectCnt + 1;
|
||||
end;
|
||||
|
||||
function TDWarfLineMap.GetAddressesForLine(ALine: Cardinal;
|
||||
var AResultList: TDBGPtrArray; NoData: Boolean;
|
||||
AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger): Boolean;
|
||||
function TDWarfLineMap.GetAddressesForLine(ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||
NoData: Boolean; AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger;
|
||||
AMaxSiblingDistance: integer; ACU: TDwarfCompilationUnit): Boolean;
|
||||
var
|
||||
idx, offset: TDBGPtr;
|
||||
idx, offset, Addr1, Addr2: TDBGPtr;
|
||||
LineOffsets: Array of Byte;
|
||||
Addresses: Array of TDBGPtr;
|
||||
o: Byte;
|
||||
i, j, k, l, CurOffs: Integer;
|
||||
TmpResList: TDBGPtrArray;
|
||||
begin
|
||||
Result := False;
|
||||
if AFoundLine <> nil then
|
||||
AFoundLine^ := ALine;
|
||||
idx := ALine div 256;
|
||||
offset := ALine mod 256;
|
||||
if idx >= Length(FLineIndexList) then begin
|
||||
@ -3579,7 +3584,7 @@ begin
|
||||
offset := 255;
|
||||
Continue;
|
||||
end;
|
||||
fsNext: begin
|
||||
fsNext, fsNextFunc, fsNextFuncLazy: begin
|
||||
inc(idx);
|
||||
if idx >= Length(FLineIndexList) then
|
||||
exit;
|
||||
@ -3604,7 +3609,7 @@ begin
|
||||
offset := 0; // found line before
|
||||
end;
|
||||
end;
|
||||
fsNext: begin
|
||||
fsNext, fsNextFunc, fsNextFuncLazy: begin
|
||||
offset := 0; // found line after/next
|
||||
end;
|
||||
end;
|
||||
@ -3623,6 +3628,33 @@ begin
|
||||
else continue;
|
||||
end;
|
||||
until False;
|
||||
|
||||
l := 256 * idx + CurOffs;
|
||||
if l <> ALine then
|
||||
case AFindSibling of
|
||||
fsBefore:
|
||||
if (AMaxSiblingDistance > 0) and (ALine - l > AMaxSiblingDistance) then exit;
|
||||
fsNext, fsNextFunc, fsNextFuncLazy: begin
|
||||
if (AMaxSiblingDistance > 0) and (l - ALine > AMaxSiblingDistance) then exit;
|
||||
if (AFindSibling = fsNextFunc) or
|
||||
((AFindSibling = fsNextFuncLazy) and (l - ALine > 1))
|
||||
then begin
|
||||
// check same function
|
||||
if ACU = nil then exit;
|
||||
if not ACU.GetProcStartEnd(Addresses[i], Addr1, Addr2) then exit;
|
||||
if GetAddressesForLine(ALine, TmpResList, False, fsBefore) then begin
|
||||
if (Length(TmpResList) = 0) or (TmpResList[0] < Addr1) or (TmpResList[0] > Addr2) then
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (AFoundLine <> nil) and (AFoundLine^ <> -1) then begin
|
||||
if (l > AFoundLine^) then exit; // already have better match
|
||||
if (l < AFoundLine^) then
|
||||
AResultList := nil; // found better match
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if AFoundLine <> nil then
|
||||
AFoundLine^ := 256 * idx + CurOffs;
|
||||
|
||||
@ -3938,20 +3970,22 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TFpDwarfInfo.GetLineAddresses(const AFileName: String;
|
||||
ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||
AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger;
|
||||
AFoundFilename: PBoolean): Boolean;
|
||||
function TFpDwarfInfo.GetLineAddresses(const AFileName: String; ALine: Cardinal;
|
||||
var AResultList: TDBGPtrArray; AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger;
|
||||
AFoundFilename: PBoolean; AMaxSiblingDistance: integer): Boolean;
|
||||
var
|
||||
n: Integer;
|
||||
CU: TDwarfCompilationUnit;
|
||||
begin
|
||||
Result := False;
|
||||
if AFoundLine <> nil then
|
||||
AFoundLine^ := -1;
|
||||
for n := 0 to FCompilationUnits.Count - 1 do
|
||||
begin
|
||||
CU := TDwarfCompilationUnit(FCompilationUnits[n]);
|
||||
CU.WaitForScopeScan;
|
||||
Result := CU.GetLineAddresses(AFileName, ALine, AResultList, AFindSibling, AFoundLine, AFoundFilename) or Result;
|
||||
Result := CU.GetLineAddresses(AFileName, ALine, AResultList, AFindSibling, AFoundLine, AFoundFilename, AMaxSiblingDistance)
|
||||
or Result;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -5215,10 +5249,9 @@ begin
|
||||
Result := PDWarfLineMap(FLineNumberMap.Objects[idx]);
|
||||
end;
|
||||
|
||||
function TDwarfCompilationUnit.GetLineAddresses(const AFileName: String;
|
||||
ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||
AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger;
|
||||
AFoundFilename: PBoolean): boolean;
|
||||
function TDwarfCompilationUnit.GetLineAddresses(const AFileName: String; ALine: Cardinal;
|
||||
var AResultList: TDBGPtrArray; AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger;
|
||||
AFoundFilename: PBoolean; AMaxSiblingDistance: integer): boolean;
|
||||
var
|
||||
Map: PDWarfLineMap;
|
||||
begin
|
||||
@ -5229,7 +5262,7 @@ begin
|
||||
|
||||
if AFoundFilename <> nil then
|
||||
AFoundFilename^ := True;
|
||||
Result := Map^.GetAddressesForLine(ALine, AResultList, False, AFindSibling, AFoundLine);
|
||||
Result := Map^.GetAddressesForLine(ALine, AResultList, False, AFindSibling, AFoundLine, AMaxSiblingDistance, Self);
|
||||
end;
|
||||
|
||||
function TDwarfCompilationUnit.InitLocateAttributeList(AEntry: Pointer;
|
||||
|
@ -679,7 +679,7 @@ type
|
||||
end;
|
||||
|
||||
{ TDbgInfo }
|
||||
TGetLineAddrFindSibling = (fsNone, fsBefore, fsNext);
|
||||
TGetLineAddrFindSibling = (fsNone, fsBefore, fsNext, fsNextFunc, fsNextFuncLazy);
|
||||
|
||||
TDbgInfo = class(TObject)
|
||||
private
|
||||
@ -705,7 +705,8 @@ type
|
||||
|
||||
property HasInfo: Boolean read FHasInfo;
|
||||
function GetLineAddresses(const AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||
AFindSibling: TGetLineAddrFindSibling = fsNone; AFoundLine: PInteger = nil; AFoundFilename: PBoolean = nil): Boolean; virtual;
|
||||
AFindSibling: TGetLineAddrFindSibling = fsNone; AFoundLine: PInteger = nil; AFoundFilename: PBoolean = nil;
|
||||
AMaxSiblingDistance: integer = 0): Boolean; virtual;
|
||||
//property MemManager: TFpDbgMemReaderBase read GetMemManager write SetMemManager;
|
||||
property TargetInfo: TTargetDescriptor read FTargetInfo write FTargetInfo;
|
||||
property MemManager: TFpDbgMemManager read FMemManager;
|
||||
@ -2162,8 +2163,8 @@ begin
|
||||
end;
|
||||
|
||||
function TDbgInfo.GetLineAddresses(const AFileName: String; ALine: Cardinal;
|
||||
var AResultList: TDBGPtrArray; AFindSibling: TGetLineAddrFindSibling;
|
||||
AFoundLine: PInteger; AFoundFilename: PBoolean): Boolean;
|
||||
var AResultList: TDBGPtrArray; AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger;
|
||||
AFoundFilename: PBoolean; AMaxSiblingDistance: integer): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
@ -4097,6 +4097,8 @@ begin
|
||||
FDbgController.CurrentProcess.Config.StdErrRedirFile := FileNameStdErr;
|
||||
FDbgController.CurrentProcess.Config.FileOverwriteStdErr := FileOverwriteStdErr;
|
||||
|
||||
FDbgController.CurrentProcess.Config.BreakpointSearchMaxLines := TFpDebugDebuggerProperties(GetProperties).BreakpointSearchMaxLines;
|
||||
|
||||
FDbgController.AttachToPid := 0;
|
||||
if ACommand = dcAttach then begin
|
||||
FDbgController.AttachToPid := StrToIntDef(String(AParams[0].VAnsiString), 0);
|
||||
|
@ -32,7 +32,7 @@ interface
|
||||
uses
|
||||
FpDbgUtil, FpdMemoryTools, FpPascalParser, FpErrorMessages,
|
||||
{$ifdef FORCE_LAZLOGGER_DUMMY} LazLoggerDummy {$else} LazLoggerBase {$endif},
|
||||
DbgIntfDebuggerBase, sysutils, Classes, syncobjs, Forms, FpDebugStringConstants;
|
||||
DbgIntfDebuggerBase, sysutils, Classes, Math, syncobjs, Forms, FpDebugStringConstants;
|
||||
|
||||
type
|
||||
|
||||
@ -106,6 +106,7 @@ type
|
||||
TFpDebugDebuggerProperties = class(TCommonDebuggerProperties)
|
||||
private
|
||||
FAutoDeref: Boolean;
|
||||
FBreakpointSearchMaxLines: integer;
|
||||
FConsoleTty: string;
|
||||
{$ifdef windows}
|
||||
FForceNewConsole: boolean;
|
||||
@ -114,6 +115,7 @@ type
|
||||
FIntrinsicPrefix: TFpIntrinsicPrefix;
|
||||
FMemLimits: TFpDebugDebuggerPropertiesMemLimits;
|
||||
FNextOnlyStopOnStartLine: boolean;
|
||||
procedure SetBreakpointSearchMaxLines(AValue: integer);
|
||||
procedure SetMemLimits(AValue: TFpDebugDebuggerPropertiesMemLimits);
|
||||
public
|
||||
constructor Create; override;
|
||||
@ -133,6 +135,7 @@ type
|
||||
property HandleDebugBreakInstruction: TFpInt3DebugBreakOptions read FHandleDebugBreakInstruction write FHandleDebugBreakInstruction default [dboIgnoreAll];
|
||||
property IntrinsicPrefix: TFpIntrinsicPrefix read FIntrinsicPrefix write FIntrinsicPrefix default ipColon;
|
||||
property AutoDeref: Boolean read FAutoDeref write FAutoDeref default False;
|
||||
property BreakpointSearchMaxLines: integer read FBreakpointSearchMaxLines write SetBreakpointSearchMaxLines default 3;
|
||||
property InternalExceptionBreakPoints;
|
||||
end;
|
||||
|
||||
@ -401,6 +404,13 @@ begin
|
||||
FMemLimits.Assign(AValue);
|
||||
end;
|
||||
|
||||
procedure TFpDebugDebuggerProperties.SetBreakpointSearchMaxLines(AValue: integer);
|
||||
begin
|
||||
AValue := Max(0, Min(25, AValue));
|
||||
if FBreakpointSearchMaxLines = AValue then Exit;
|
||||
FBreakpointSearchMaxLines := AValue;
|
||||
end;
|
||||
|
||||
constructor TFpDebugDebuggerProperties.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
@ -412,6 +422,7 @@ begin
|
||||
FHandleDebugBreakInstruction := [dboIgnoreAll];
|
||||
FIntrinsicPrefix := ipColon;
|
||||
FAutoDeref := False;
|
||||
FBreakpointSearchMaxLines := 3;
|
||||
end;
|
||||
|
||||
destructor TFpDebugDebuggerProperties.Destroy;
|
||||
@ -433,6 +444,7 @@ begin
|
||||
FHandleDebugBreakInstruction:=TFpDebugDebuggerProperties(Source).FHandleDebugBreakInstruction;
|
||||
FIntrinsicPrefix:=TFpDebugDebuggerProperties(Source).FIntrinsicPrefix;
|
||||
FAutoDeref:=TFpDebugDebuggerProperties(Source).FAutoDeref;
|
||||
FBreakpointSearchMaxLines:=TFpDebugDebuggerProperties(Source).FBreakpointSearchMaxLines;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -29,11 +29,13 @@ begin
|
||||
x := 1;
|
||||
end;
|
||||
|
||||
Procedure StepOverEnd(a: integer);
|
||||
Procedure StepOverEnd(a: integer); // USED FOR line lookup // do not add lines
|
||||
var
|
||||
b: integer;
|
||||
begin
|
||||
begin // TEST_BREAKPOINT=StepOverBegin
|
||||
b := a;
|
||||
// 3 empty lines in function (for line lookup test)
|
||||
//
|
||||
// end returns to the same line
|
||||
if a < 1 then StepOverEnd(a+1); end; // TEST_BREAKPOINT=StepOverEnd
|
||||
|
||||
|
@ -7,8 +7,8 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, math, TestDbgControl, TestDbgTestSuites,
|
||||
TTestWatchUtilities, TestCommonSources, TestDbgConfig, TTestDebuggerClasses,
|
||||
LazDebuggerIntf, LazDebuggerIntfBaseTypes, DbgIntfDebuggerBase,
|
||||
DbgIntfBaseTypes, LazLoggerBase, Forms;
|
||||
LazDebuggerIntf, LazDebuggerIntfBaseTypes, FpDebugDebugger, DbgIntfDebuggerBase,
|
||||
DbgIntfBaseTypes, LazLoggerBase, FPDbgController, FpDbgInfo, Forms;
|
||||
|
||||
type
|
||||
|
||||
@ -57,6 +57,7 @@ type
|
||||
procedure TestLocation(ATestName, ABrkName: String; ABreakHitCount: Integer = 1);
|
||||
procedure TestHitCnt(ATestName, ABrkName: String; ABreakHitCount: Integer);
|
||||
published
|
||||
procedure TestGetAddressForLine;
|
||||
(* Ensure the debugger can correctly run/step after hidding a breakpoit
|
||||
- the original instruction is executed
|
||||
- the breakpoint can be hit again
|
||||
@ -96,7 +97,7 @@ type
|
||||
implementation
|
||||
|
||||
var
|
||||
ControlTest, ControlTestBreak, ControlTestThreadNoSkip,
|
||||
ControlTest, ControlTestGetAddressForLine, ControlTestBreak, ControlTestThreadNoSkip,
|
||||
ControlTestThreadMove1, ControlTestThreadMove2, ControlTestThreadHit,
|
||||
ControlTestThreadIgnoreOther: Pointer;
|
||||
|
||||
@ -118,6 +119,153 @@ begin
|
||||
TestEquals(ATestName+' '+ABrkName+' HitCnt', Debugger.BreakPointByName(ABrkName).HitCount, ABreakHitCount);
|
||||
end;
|
||||
|
||||
procedure TTestBreakPoint.TestGetAddressForLine;
|
||||
var
|
||||
ExeName: String;
|
||||
FpDbg: TFpDebugDebugger;
|
||||
Ctrl: TDbgController;
|
||||
LNum1, LNum2: LongInt;
|
||||
fs: TGetLineAddrFindSibling;
|
||||
|
||||
procedure TestLineExist(ALine: Cardinal; AFindSibling: TGetLineAddrFindSibling;
|
||||
AMaxAfter: integer = 0; ExpFoundLine: Integer = -1);
|
||||
var
|
||||
AName: String;
|
||||
ResLst: TDBGPtrArray;
|
||||
FndLine: Integer;
|
||||
FndFile, r: Boolean;
|
||||
begin
|
||||
AName := 'Found '+IntToStr(ALine);
|
||||
if ExpFoundLine = -1 then ExpFoundLine := ALine;
|
||||
r := Ctrl.CurrentProcess.DbgInfo.GetLineAddresses('StepOverPrg.pas',
|
||||
ALine, ResLst, AFindSibling, @FndLine, @FndFile, AMaxAfter);
|
||||
AssertTrue(AName, r);
|
||||
AssertTrue(AName, FndFile);
|
||||
AssertEquals(AName, ExpFoundLine, FndLine);
|
||||
AssertTrue(AName, Length(ResLst) > 0);
|
||||
AssertTrue(AName, ResLst[0] <> 0);
|
||||
end;
|
||||
|
||||
procedure TestLineNotFound(ALine: Cardinal; AFindSibling: TGetLineAddrFindSibling;
|
||||
AMaxAfter: integer = 0);
|
||||
var
|
||||
AName: String;
|
||||
ResLst: TDBGPtrArray;
|
||||
FndLine: Integer;
|
||||
FndFile, r: Boolean;
|
||||
begin
|
||||
AName := 'Found '+IntToStr(ALine);
|
||||
r := Ctrl.CurrentProcess.DbgInfo.GetLineAddresses('StepOverPrg.pas',
|
||||
ALine, ResLst, AFindSibling, @FndLine, @FndFile, AMaxAfter);
|
||||
AssertFalse(AName, r);
|
||||
//AssertTrue(AName, FndFile);
|
||||
end;
|
||||
|
||||
begin
|
||||
if SkipTest then exit;
|
||||
if not TestControlCanTest(ControlTestGetAddressForLine) then exit;
|
||||
Src := GetCommonSourceFor(AppDir + 'StepOverPrg.pas');
|
||||
TestCompile(Src, ExeName);
|
||||
|
||||
TestTrue('Start debugger', Debugger.StartDebugger(AppDir, ExeName));
|
||||
dbg := Debugger.LazDebugger;
|
||||
try
|
||||
Debugger.SetBreakPoint(Src, 'BrkStart');
|
||||
Debugger.RunToNextPause(dcRun);
|
||||
|
||||
FpDbg := dbg as TFpDebugDebugger;
|
||||
Ctrl := FpDbg.DbgController;
|
||||
|
||||
LNum1 := Src.BreakPoints['StepOverBegin'];
|
||||
LNum2 := Src.BreakPoints['StepOverEnd'];
|
||||
|
||||
for fs := low(TGetLineAddrFindSibling) to high(TGetLineAddrFindSibling) do begin
|
||||
TestLineExist(LNum1, fs, 0, LNum1);
|
||||
TestLineExist(LNum1+1, fs, 0, LNum1+1);
|
||||
TestLineExist(LNum2, fs, 0, LNum2);
|
||||
end;
|
||||
|
||||
// Before begin
|
||||
|
||||
TestLineNotFound(LNum1-1, fsNone);
|
||||
TestLineNotFound(LNum1-1, fsNone, 9); // maxafter ignored
|
||||
TestLineNotFound(LNum1-2, fsNone);
|
||||
|
||||
TestLineNotFound(LNum1-3, fsNext, 1);
|
||||
TestLineNotFound(LNum1-2, fsNext, 1);
|
||||
TestLineExist (LNum1-1, fsNext, 1, LNum1);
|
||||
|
||||
TestLineNotFound(LNum1-3, fsNext, 2);
|
||||
TestLineExist (LNum1-2, fsNext, 2, LNum1);
|
||||
TestLineExist (LNum1-1, fsNext, 2, LNum1);
|
||||
|
||||
TestLineExist (LNum1-3, fsNext, 0, LNum1);
|
||||
TestLineExist (LNum1-2, fsNext, 0, LNum1);
|
||||
TestLineExist (LNum1-1, fsNext, 0, LNum1);
|
||||
|
||||
|
||||
TestLineNotFound(LNum1-2, fsNextFunc, 1);
|
||||
TestLineNotFound(LNum1-2, fsNextFunc, 2);
|
||||
TestLineNotFound(LNum1-2, fsNextFunc, 0);
|
||||
TestLineNotFound(LNum1-1, fsNextFunc, 1);
|
||||
TestLineNotFound(LNum1-1, fsNextFunc, 2);
|
||||
TestLineNotFound(LNum1-1, fsNextFunc, 0);
|
||||
|
||||
TestLineNotFound(LNum1-2, fsNextFuncLazy, 1);
|
||||
TestLineNotFound(LNum1-2, fsNextFuncLazy, 2);
|
||||
TestLineNotFound(LNum1-2, fsNextFuncLazy, 0);
|
||||
TestLineExist (LNum1-1, fsNextFuncLazy, 1, LNum1);
|
||||
TestLineExist (LNum1-1, fsNextFuncLazy, 2, LNum1);
|
||||
TestLineExist (LNum1-1, fsNextFuncLazy, 0, LNum1);
|
||||
|
||||
// mid function
|
||||
TestLineNotFound(LNum2-1, fsNone);
|
||||
TestLineNotFound(LNum2-1, fsNone, 9); // maxafter ignored
|
||||
TestLineNotFound(LNum2-2, fsNone);
|
||||
|
||||
TestLineNotFound(LNum2-3, fsNext, 1);
|
||||
TestLineNotFound(LNum2-2, fsNext, 1);
|
||||
TestLineExist (LNum2-1, fsNext, 1, LNum2);
|
||||
|
||||
TestLineNotFound(LNum2-3, fsNext, 2);
|
||||
TestLineExist (LNum2-2, fsNext, 2, LNum2);
|
||||
TestLineExist (LNum2-1, fsNext, 2, LNum2);
|
||||
|
||||
TestLineExist (LNum2-3, fsNext, 0, LNum2);
|
||||
TestLineExist (LNum2-2, fsNext, 0, LNum2);
|
||||
TestLineExist (LNum2-1, fsNext, 0, LNum2);
|
||||
|
||||
|
||||
TestLineNotFound(LNum2-2, fsNextFunc, 1);
|
||||
TestLineExist (LNum2-2, fsNextFunc, 2, LNum2);
|
||||
TestLineExist (LNum2-2, fsNextFunc, 0, LNum2);
|
||||
TestLineExist (LNum2-1, fsNextFunc, 1, LNum2);
|
||||
TestLineExist (LNum2-1, fsNextFunc, 2, LNum2);
|
||||
TestLineExist (LNum2-1, fsNextFunc, 0, LNum2);
|
||||
|
||||
TestLineNotFound(LNum2-3, fsNextFuncLazy, 1);
|
||||
TestLineNotFound(LNum2-3, fsNextFuncLazy, 2);
|
||||
TestLineExist (LNum2-3, fsNextFuncLazy, 3, LNum2);
|
||||
TestLineExist (LNum2-3, fsNextFuncLazy, 4, LNum2);
|
||||
TestLineExist (LNum2-3, fsNextFuncLazy, 0, LNum2);
|
||||
TestLineNotFound(LNum2-2, fsNextFuncLazy, 1);
|
||||
TestLineExist (LNum2-2, fsNextFuncLazy, 2, LNum2);
|
||||
TestLineExist (LNum2-2, fsNextFuncLazy, 0, LNum2);
|
||||
TestLineExist (LNum2-1, fsNextFuncLazy, 1, LNum2);
|
||||
TestLineExist (LNum2-1, fsNextFuncLazy, 2, LNum2);
|
||||
TestLineExist (LNum2-1, fsNextFuncLazy, 0, LNum2);
|
||||
|
||||
|
||||
|
||||
dbg.Stop;
|
||||
finally
|
||||
Debugger.ClearDebuggerMonitors;
|
||||
Debugger.FreeDebugger;
|
||||
|
||||
AssertTestErrors;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTestBreakPoint.TestBreakPoints;
|
||||
var
|
||||
ExeName: String;
|
||||
@ -988,6 +1136,7 @@ initialization
|
||||
|
||||
RegisterDbgTest(TTestBreakPoint);
|
||||
ControlTest := TestControlRegisterTest('TTestBreak');
|
||||
ControlTestGetAddressForLine := TestControlRegisterTest('TestGetAddressForLine', ControlTest);
|
||||
ControlTestBreak := TestControlRegisterTest('TTestBreakPoint', ControlTest);
|
||||
ControlTestThreadNoSkip := TestControlRegisterTest('TTestBreakThreadNoSkip', ControlTest);
|
||||
ControlTestThreadMove1 := TestControlRegisterTest('TTestBreakThreadMove1', ControlTest);
|
||||
|
Loading…
Reference in New Issue
Block a user