mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-17 00:21:00 +01:00
FpDebugger (pure): - Fixed problem with the recognition of a software breakpoint when a hardware breakpoint has been triggered on the same location
- Ability to check if and which hardware brakpoint has been triggered git-svn-id: trunk@46006 -
This commit is contained in:
parent
33b12a6ca4
commit
c43ebefc0f
@ -149,6 +149,7 @@ type
|
|||||||
procedure BeforeContinue; virtual;
|
procedure BeforeContinue; virtual;
|
||||||
function AddWatchpoint(AnAddr: TDBGPtr): integer; virtual;
|
function AddWatchpoint(AnAddr: TDBGPtr): integer; virtual;
|
||||||
function RemoveWatchpoint(AnId: integer): boolean; virtual;
|
function RemoveWatchpoint(AnId: integer): boolean; virtual;
|
||||||
|
function DetectHardwareWatchpoint: integer; virtual;
|
||||||
procedure PrepareCallStackEntryList(AFrameRequired: Integer = -1); virtual;
|
procedure PrepareCallStackEntryList(AFrameRequired: Integer = -1); virtual;
|
||||||
procedure ClearCallStack;
|
procedure ClearCallStack;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -239,6 +240,7 @@ type
|
|||||||
protected
|
protected
|
||||||
FCurrentBreakpoint: TDbgBreakpoint; // set if we are executing the code at the break
|
FCurrentBreakpoint: TDbgBreakpoint; // set if we are executing the code at the break
|
||||||
// if the singlestep is done, set the break again
|
// if the singlestep is done, set the break again
|
||||||
|
FCurrentWatchpoint: integer;
|
||||||
FReEnableBreakStep: Boolean; // Set when we are reenabling a breakpoint
|
FReEnableBreakStep: Boolean; // Set when we are reenabling a breakpoint
|
||||||
// We need a single step, so the IP is after the break to set
|
// We need a single step, so the IP is after the break to set
|
||||||
|
|
||||||
@ -301,6 +303,7 @@ type
|
|||||||
property ThreadID: integer read FThreadID;
|
property ThreadID: integer read FThreadID;
|
||||||
property ExitCode: DWord read FExitCode;
|
property ExitCode: DWord read FExitCode;
|
||||||
property CurrentBreakpoint: TDbgBreakpoint read FCurrentBreakpoint;
|
property CurrentBreakpoint: TDbgBreakpoint read FCurrentBreakpoint;
|
||||||
|
property CurrentWatchpoint: integer read FCurrentWatchpoint;
|
||||||
|
|
||||||
// Properties valid when last event was an deException
|
// Properties valid when last event was an deException
|
||||||
property ExceptionMessage: string read FExceptionMessage write FExceptionMessage;
|
property ExceptionMessage: string read FExceptionMessage write FExceptionMessage;
|
||||||
@ -659,6 +662,7 @@ begin
|
|||||||
FLibMap := TMap.Create(MAP_ID_SIZE, SizeOf(TDbgLibrary));
|
FLibMap := TMap.Create(MAP_ID_SIZE, SizeOf(TDbgLibrary));
|
||||||
FBreakMap := TMap.Create(MAP_ID_SIZE, SizeOf(TDbgBreakpoint));
|
FBreakMap := TMap.Create(MAP_ID_SIZE, SizeOf(TDbgBreakpoint));
|
||||||
FCurrentBreakpoint := nil;
|
FCurrentBreakpoint := nil;
|
||||||
|
FCurrentWatchpoint := -1;
|
||||||
|
|
||||||
FSymInstances := TList.Create;
|
FSymInstances := TList.Create;
|
||||||
|
|
||||||
@ -811,11 +815,12 @@ begin
|
|||||||
|
|
||||||
// Determine the address where the execution has stopped
|
// Determine the address where the execution has stopped
|
||||||
CurrentAddr:=GetInstructionPointerRegisterValue;
|
CurrentAddr:=GetInstructionPointerRegisterValue;
|
||||||
if not (FMainThread.NextIsSingleStep or assigned(FCurrentBreakpoint)) then
|
FCurrentWatchpoint:=AThread.DetectHardwareWatchpoint;
|
||||||
|
if not (FMainThread.NextIsSingleStep or assigned(FCurrentBreakpoint) or (FCurrentWatchpoint>-1)) then
|
||||||
begin
|
begin
|
||||||
// The debugger did not stop due to single-stepping, so a breakpoint has
|
// The debugger did not stop due to single-stepping or a watchpoint,
|
||||||
// been hit. But breakpoints stop *after* they have been hit. So the
|
// so a breakpoint has been hit. But breakpoints stop *after* they
|
||||||
// decrement the CurrentAddr.
|
// have been hit. So decrement the CurrentAddr.
|
||||||
FMainThread.FNeedIPDecrement:=true;
|
FMainThread.FNeedIPDecrement:=true;
|
||||||
dec(CurrentAddr);
|
dec(CurrentAddr);
|
||||||
end
|
end
|
||||||
@ -1073,6 +1078,11 @@ begin
|
|||||||
result := false;
|
result := false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TDbgThread.DetectHardwareWatchpoint: integer;
|
||||||
|
begin
|
||||||
|
result := -1;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDbgThread.PrepareCallStackEntryList(AFrameRequired: Integer);
|
procedure TDbgThread.PrepareCallStackEntryList(AFrameRequired: Integer);
|
||||||
var
|
var
|
||||||
Address, Frame, LastFrame: QWord;
|
Address, Frame, LastFrame: QWord;
|
||||||
|
|||||||
@ -110,6 +110,7 @@ type
|
|||||||
function ResetInstructionPointerAfterBreakpoint: boolean; override;
|
function ResetInstructionPointerAfterBreakpoint: boolean; override;
|
||||||
function AddWatchpoint(AnAddr: TDBGPtr): integer; override;
|
function AddWatchpoint(AnAddr: TDBGPtr): integer; override;
|
||||||
function RemoveWatchpoint(AnId: integer): boolean; override;
|
function RemoveWatchpoint(AnId: integer): boolean; override;
|
||||||
|
function DetectHardwareWatchpoint: integer; override;
|
||||||
procedure BeforeContinue; override;
|
procedure BeforeContinue; override;
|
||||||
procedure LoadRegisterValues; override;
|
procedure LoadRegisterValues; override;
|
||||||
end;
|
end;
|
||||||
@ -247,6 +248,7 @@ begin
|
|||||||
Log('Failed to call thread_get_state for thread %d. Mach error: '+mach_error_string(aKernResult),[Id]);
|
Log('Failed to call thread_get_state for thread %d. Mach error: '+mach_error_string(aKernResult),[Id]);
|
||||||
end;
|
end;
|
||||||
FRegisterValueListValid:=false;
|
FRegisterValueListValid:=false;
|
||||||
|
FDebugStateRead:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDbgDarwinThread.ReadDebugState: boolean;
|
function TDbgDarwinThread.ReadDebugState: boolean;
|
||||||
@ -421,9 +423,28 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
|
|
||||||
if Process.Mode=dm32 then
|
if Process.Mode=dm32 then
|
||||||
RemoveBreakpoint32(AnId)
|
result := RemoveBreakpoint32(AnId)
|
||||||
else
|
else
|
||||||
RemoveBreakpoint64(AnId);
|
result := RemoveBreakpoint64(AnId);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDbgDarwinThread.DetectHardwareWatchpoint: integer;
|
||||||
|
var
|
||||||
|
dr6: DWord;
|
||||||
|
begin
|
||||||
|
result := -1;
|
||||||
|
if ReadDebugState then
|
||||||
|
begin
|
||||||
|
if Process.Mode=dm32 then
|
||||||
|
dr6 := FDebugState32.__dr6
|
||||||
|
else
|
||||||
|
dr6 := lo(FDebugState64.__dr6);
|
||||||
|
|
||||||
|
if dr6 and 1 = 1 then result := 0
|
||||||
|
else if dr6 and 2 = 2 then result := 1
|
||||||
|
else if dr6 and 4 = 4 then result := 2
|
||||||
|
else if dr6 and 8 = 8 then result := 3;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDbgDarwinThread.BeforeContinue;
|
procedure TDbgDarwinThread.BeforeContinue;
|
||||||
@ -431,6 +452,15 @@ var
|
|||||||
aKernResult: kern_return_t;
|
aKernResult: kern_return_t;
|
||||||
old_StateCnt: mach_msg_Type_number_t;
|
old_StateCnt: mach_msg_Type_number_t;
|
||||||
begin
|
begin
|
||||||
|
if Process.CurrentWatchpoint>-1 then
|
||||||
|
begin
|
||||||
|
if Process.Mode=dm32 then
|
||||||
|
FDebugState32.__dr6:=0
|
||||||
|
else
|
||||||
|
FDebugState64.__dr6:=0;
|
||||||
|
FDebugStateChanged:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
if FDebugStateRead and FDebugStateChanged then
|
if FDebugStateRead and FDebugStateChanged then
|
||||||
begin
|
begin
|
||||||
if Process.Mode=dm32 then
|
if Process.Mode=dm32 then
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user