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:
joost 2014-08-03 20:09:46 +00:00
parent 33b12a6ca4
commit c43ebefc0f
2 changed files with 46 additions and 6 deletions

View File

@ -149,6 +149,7 @@ type
procedure BeforeContinue; virtual;
function AddWatchpoint(AnAddr: TDBGPtr): integer; virtual;
function RemoveWatchpoint(AnId: integer): boolean; virtual;
function DetectHardwareWatchpoint: integer; virtual;
procedure PrepareCallStackEntryList(AFrameRequired: Integer = -1); virtual;
procedure ClearCallStack;
destructor Destroy; override;
@ -239,6 +240,7 @@ type
protected
FCurrentBreakpoint: TDbgBreakpoint; // set if we are executing the code at the break
// if the singlestep is done, set the break again
FCurrentWatchpoint: integer;
FReEnableBreakStep: Boolean; // Set when we are reenabling a breakpoint
// 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 ExitCode: DWord read FExitCode;
property CurrentBreakpoint: TDbgBreakpoint read FCurrentBreakpoint;
property CurrentWatchpoint: integer read FCurrentWatchpoint;
// Properties valid when last event was an deException
property ExceptionMessage: string read FExceptionMessage write FExceptionMessage;
@ -659,6 +662,7 @@ begin
FLibMap := TMap.Create(MAP_ID_SIZE, SizeOf(TDbgLibrary));
FBreakMap := TMap.Create(MAP_ID_SIZE, SizeOf(TDbgBreakpoint));
FCurrentBreakpoint := nil;
FCurrentWatchpoint := -1;
FSymInstances := TList.Create;
@ -811,11 +815,12 @@ begin
// Determine the address where the execution has stopped
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
// The debugger did not stop due to single-stepping, so a breakpoint has
// been hit. But breakpoints stop *after* they have been hit. So the
// decrement the CurrentAddr.
// The debugger did not stop due to single-stepping or a watchpoint,
// so a breakpoint has been hit. But breakpoints stop *after* they
// have been hit. So decrement the CurrentAddr.
FMainThread.FNeedIPDecrement:=true;
dec(CurrentAddr);
end
@ -1073,6 +1078,11 @@ begin
result := false;
end;
function TDbgThread.DetectHardwareWatchpoint: integer;
begin
result := -1;
end;
procedure TDbgThread.PrepareCallStackEntryList(AFrameRequired: Integer);
var
Address, Frame, LastFrame: QWord;

View File

@ -110,6 +110,7 @@ type
function ResetInstructionPointerAfterBreakpoint: boolean; override;
function AddWatchpoint(AnAddr: TDBGPtr): integer; override;
function RemoveWatchpoint(AnId: integer): boolean; override;
function DetectHardwareWatchpoint: integer; override;
procedure BeforeContinue; override;
procedure LoadRegisterValues; override;
end;
@ -247,6 +248,7 @@ begin
Log('Failed to call thread_get_state for thread %d. Mach error: '+mach_error_string(aKernResult),[Id]);
end;
FRegisterValueListValid:=false;
FDebugStateRead:=false;
end;
function TDbgDarwinThread.ReadDebugState: boolean;
@ -421,9 +423,28 @@ begin
exit;
if Process.Mode=dm32 then
RemoveBreakpoint32(AnId)
result := RemoveBreakpoint32(AnId)
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;
procedure TDbgDarwinThread.BeforeContinue;
@ -431,6 +452,15 @@ var
aKernResult: kern_return_t;
old_StateCnt: mach_msg_Type_number_t;
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
begin
if Process.Mode=dm32 then