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; 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;

View File

@ -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