Let the TProcess call decide, if calls must be made in the correct thread (debugger-thread). Linux/trace only allows the dbg thread access.

git-svn-id: trunk@62752 -
This commit is contained in:
martin 2020-03-12 14:21:08 +00:00
parent 0aed1400c1
commit b014fcdeeb
3 changed files with 116 additions and 98 deletions

View File

@ -470,6 +470,7 @@ type
function DoBreak(BreakpointAddress: TDBGPtr; AThreadID: integer): Boolean; function DoBreak(BreakpointAddress: TDBGPtr; AThreadID: integer): Boolean;
procedure SetLastLibraryUnloaded(ALib: TDbgLibrary); procedure SetLastLibraryUnloaded(ALib: TDbgLibrary);
procedure SetLastLibraryUnloadedNil(ALib: TDbgLibrary); procedure SetLastLibraryUnloadedNil(ALib: TDbgLibrary);
function GetRequiresExecutionInDebuggerThread: boolean; virtual;
function InsertBreakInstructionCode(const ALocation: TDBGPtr; out OrigValue: Byte): Boolean; virtual; function InsertBreakInstructionCode(const ALocation: TDBGPtr; out OrigValue: Byte): Boolean; virtual;
function RemoveBreakInstructionCode(const ALocation: TDBGPtr; const OrigValue: Byte): Boolean; virtual; function RemoveBreakInstructionCode(const ALocation: TDBGPtr; const OrigValue: Byte): Boolean; virtual;
@ -553,6 +554,7 @@ public
function Detach(AProcess: TDbgProcess; AThread: TDbgThread): boolean; virtual; function Detach(AProcess: TDbgProcess; AThread: TDbgThread): boolean; virtual;
property OSDbgClasses: TOSDbgClasses read FOSDbgClasses; property OSDbgClasses: TOSDbgClasses read FOSDbgClasses;
property RequiresExecutionInDebuggerThread: boolean read GetRequiresExecutionInDebuggerThread;
property Handle: THandle read GetHandle; property Handle: THandle read GetHandle;
property Name: String read FFileName write SetFileName; property Name: String read FFileName write SetFileName;
property ProcessID: integer read FProcessID; property ProcessID: integer read FProcessID;
@ -1908,6 +1910,11 @@ begin
Result := Boolean(InterLockedExchangeAdd(FPauseRequested, 0)); Result := Boolean(InterLockedExchangeAdd(FPauseRequested, 0));
end; end;
function TDbgProcess.GetRequiresExecutionInDebuggerThread: boolean;
begin
Result := False;
end;
function TDbgProcess.GetLastLibraryLoaded: TDbgLibrary; function TDbgProcess.GetLastLibraryLoaded: TDbgLibrary;
begin begin
Result := FLibMap.LastLibraryAdded; Result := FLibMap.LastLibraryAdded;

View File

@ -287,6 +287,7 @@ type
procedure OnForkEvent(Sender : TObject); procedure OnForkEvent(Sender : TObject);
{$endif} {$endif}
protected protected
function GetRequiresExecutionInDebuggerThread: boolean; override;
procedure InitializeLoaders; override; procedure InitializeLoaders; override;
function CreateThread(AthreadIdentifier: THandle; out IsMainThread: boolean): TDbgThread; override; function CreateThread(AthreadIdentifier: THandle; out IsMainThread: boolean): TDbgThread; override;
function AnalyseDebugEvent(AThread: TDbgThread): TFPDEvent; override; function AnalyseDebugEvent(AThread: TDbgThread): TFPDEvent; override;
@ -706,6 +707,11 @@ end;
{ TDbgLinuxProcess } { TDbgLinuxProcess }
function TDbgLinuxProcess.GetRequiresExecutionInDebuggerThread: boolean;
begin
Result := True;
end;
procedure TDbgLinuxProcess.InitializeLoaders; procedure TDbgLinuxProcess.InitializeLoaders;
begin begin
TDbgImageLoader.Create(Name).AddToLoaderList(LoaderList); TDbgImageLoader.Create(Name).AddToLoaderList(LoaderList);

View File

@ -203,7 +203,7 @@ type
FMemManager: TFpDbgMemManager; FMemManager: TFpDbgMemManager;
FExceptionStepper: TFpDebugExceptionStepping; FExceptionStepper: TFpDebugExceptionStepping;
FConsoleOutputThread: TThread; FConsoleOutputThread: TThread;
{$ifdef linux} // Helper vars to run in debug-thread
FCacheLine: cardinal; FCacheLine: cardinal;
FCacheFileName: string; FCacheFileName: string;
FCacheLib: TDbgLibrary; FCacheLib: TDbgLibrary;
@ -215,7 +215,7 @@ type
FCacheScope: TDBGWatchPointScope; FCacheScope: TDBGWatchPointScope;
FCacheThreadId, FCacheStackFrame: Integer; FCacheThreadId, FCacheStackFrame: Integer;
FCacheContext: TFpDbgInfoContext; FCacheContext: TFpDbgInfoContext;
{$endif linux} //
function GetClassInstanceName(AnAddr: TDBGPtr): string; function GetClassInstanceName(AnAddr: TDBGPtr): string;
function ReadAnsiString(AnAddr: TDbgPtr): string; function ReadAnsiString(AnAddr: TDbgPtr): string;
procedure HandleSoftwareException(out AnExceptionLocation: TDBGLocationRec; var continue: boolean); procedure HandleSoftwareException(out AnExceptionLocation: TDBGLocationRec; var continue: boolean);
@ -267,8 +267,8 @@ type
procedure DoOnIdle; procedure DoOnIdle;
procedure DoState(const OldState: TDBGState); override; procedure DoState(const OldState: TDBGState); override;
function GetIsIdle: Boolean; override; function GetIsIdle: Boolean; override;
{$ifdef linux}
protected protected
// Helper vars to run in debug-thread
FCallStackEntryListThread: TDbgThread; FCallStackEntryListThread: TDbgThread;
FCallStackEntryListFrameRequired: Integer; FCallStackEntryListFrameRequired: Integer;
FParamAsString: String; FParamAsString: String;
@ -284,7 +284,7 @@ type
procedure DoFreeBreakpoint; procedure DoFreeBreakpoint;
procedure DoFindContext; procedure DoFindContext;
procedure DoGetParamsAsString; procedure DoGetParamsAsString;
{$endif linux} //
function AddBreak(const ALocation: TDbgPtr; AnEnabled: Boolean = True): TFpDbgBreakpoint; overload; function AddBreak(const ALocation: TDbgPtr; AnEnabled: Boolean = True): TFpDbgBreakpoint; overload;
function AddBreak(const AFileName: String; ALine: Cardinal; AnEnabled: Boolean = True): TFpDbgBreakpoint; overload; function AddBreak(const AFileName: String; ALine: Cardinal; AnEnabled: Boolean = True): TFpDbgBreakpoint; overload;
function AddBreak(const AFuncName: String; ALib: TDbgLibrary = nil; AnEnabled: Boolean = True): TFpDbgBreakpoint; overload; function AddBreak(const AFuncName: String; ALib: TDbgLibrary = nil; AnEnabled: Boolean = True): TFpDbgBreakpoint; overload;
@ -455,7 +455,8 @@ implementation
uses uses
FpDbgUtil, FpDbgUtil,
FpDbgDisasX86; FpDbgDisasX86,
FpDbgCommon;
var var
DBG_VERBOSE, DBG_BREAKPOINTS, FPDBG_COMMANDS: PLazLoggerLogGroup; DBG_VERBOSE, DBG_BREAKPOINTS, FPDBG_COMMANDS: PLazLoggerLogGroup;
@ -467,13 +468,11 @@ type
TFpDbgMemReader = class(TDbgMemReader) TFpDbgMemReader = class(TDbgMemReader)
private private
FFpDebugDebugger: TFpDebugDebugger; FFpDebugDebugger: TFpDebugDebugger;
{$ifdef linux}
FRegNum: Cardinal; FRegNum: Cardinal;
FRegValue: TDbgPtr; FRegValue: TDbgPtr;
FRegContext: TFpDbgAddressContext; FRegContext: TFpDbgAddressContext;
FRegResult: Boolean; FRegResult: Boolean;
procedure DoReadRegister; procedure DoReadRegister;
{$endif linux}
protected protected
function GetDbgProcess: TDbgProcess; override; function GetDbgProcess: TDbgProcess; override;
function GetDbgThread(AContext: TFpDbgAddressContext): TDbgThread; override; function GetDbgThread(AContext: TFpDbgAddressContext): TDbgThread; override;
@ -799,12 +798,10 @@ begin
Result := FFpDebugDebugger.FDbgController.CurrentThread; Result := FFpDebugDebugger.FDbgController.CurrentThread;
end; end;
{$ifdef linux}
procedure TFpDbgMemReader.DoReadRegister; procedure TFpDbgMemReader.DoReadRegister;
begin begin
FRegResult := inherited ReadRegister(FRegNum, FRegValue, FRegContext); FRegResult := inherited ReadRegister(FRegNum, FRegValue, FRegContext);
end; end;
{$endif linux}
constructor TFpDbgMemReader.create(AFpDebugDebuger: TFpDebugDebugger); constructor TFpDbgMemReader.create(AFpDebugDebuger: TFpDebugDebugger);
begin begin
@ -825,15 +822,16 @@ end;
function TFpDbgMemReader.ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr; function TFpDbgMemReader.ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr;
AContext: TFpDbgAddressContext): Boolean; AContext: TFpDbgAddressContext): Boolean;
begin begin
{$ifdef linux} if FFpDebugDebugger.FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
FRegNum := ARegNum; begin
FRegContext := AContext; FRegNum := ARegNum;
FFpDebugDebugger.ExecuteInDebugThread(@DoReadRegister); FRegContext := AContext;
AValue := FRegValue; FFpDebugDebugger.ExecuteInDebugThread(@DoReadRegister);
result := FRegResult; AValue := FRegValue;
{$else linux} result := FRegResult;
result := inherited ReadRegister(ARegNum, AValue, AContext); end
{$endif linux} else
result := inherited ReadRegister(ARegNum, AValue, AContext);
end; end;
{ TCallstackAsyncRequest } { TCallstackAsyncRequest }
@ -2907,7 +2905,6 @@ begin
Result := FIsIdle; Result := FIsIdle;
end; end;
{$ifdef linux}
procedure TFpDebugDebugger.DoAddBreakLine; procedure TFpDebugDebugger.DoAddBreakLine;
begin begin
FCacheBreakpoint := TDbgInstance(FDbgController.CurrentProcess).AddBreak(FCacheFileName, FCacheLine, FCacheBoolean); FCacheBreakpoint := TDbgInstance(FDbgController.CurrentProcess).AddBreak(FCacheFileName, FCacheLine, FCacheBoolean);
@ -2959,94 +2956,99 @@ begin
FParamAsString := FParamAsStringStackEntry.GetParamsAsString(FParamAsStringPrettyPrinter); FParamAsString := FParamAsStringStackEntry.GetParamsAsString(FParamAsStringPrettyPrinter);
end; end;
{$endif linux}
function TFpDebugDebugger.AddBreak(const ALocation: TDbgPtr; AnEnabled: Boolean function TFpDebugDebugger.AddBreak(const ALocation: TDbgPtr; AnEnabled: Boolean
): TFpDbgBreakpoint; ): TFpDbgBreakpoint;
begin begin
{$ifdef linux} if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
FCacheLocation:=ALocation; begin
FCacheBoolean:=AnEnabled; FCacheLocation:=ALocation;
ExecuteInDebugThread(@DoAddBreakLocation); FCacheBoolean:=AnEnabled;
result := FCacheBreakpoint; ExecuteInDebugThread(@DoAddBreakLocation);
{$else linux} result := FCacheBreakpoint;
if ALocation = 0 then end
result := FDbgController.CurrentProcess.AddBreak(nil, AnEnabled)
else else
result := FDbgController.CurrentProcess.AddBreak(ALocation, AnEnabled); if ALocation = 0 then
{$endif linux} result := FDbgController.CurrentProcess.AddBreak(nil, AnEnabled)
else
result := FDbgController.CurrentProcess.AddBreak(ALocation, AnEnabled);
end; end;
function TFpDebugDebugger.AddBreak(const AFileName: String; ALine: Cardinal; function TFpDebugDebugger.AddBreak(const AFileName: String; ALine: Cardinal;
AnEnabled: Boolean): TFpDbgBreakpoint; AnEnabled: Boolean): TFpDbgBreakpoint;
begin begin
{$ifdef linux} if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
FCacheFileName:=AFileName; begin
FCacheLine:=ALine; FCacheFileName:=AFileName;
FCacheBoolean:=AnEnabled; FCacheLine:=ALine;
ExecuteInDebugThread(@DoAddBreakLine); FCacheBoolean:=AnEnabled;
result := FCacheBreakpoint; ExecuteInDebugThread(@DoAddBreakLine);
{$else linux} result := FCacheBreakpoint;
result := TDbgInstance(FDbgController.CurrentProcess).AddBreak(AFileName, ALine, AnEnabled); end
{$endif linux} else
result := TDbgInstance(FDbgController.CurrentProcess).AddBreak(AFileName, ALine, AnEnabled);
end; end;
function TFpDebugDebugger.AddBreak(const AFuncName: String; ALib: TDbgLibrary; function TFpDebugDebugger.AddBreak(const AFuncName: String; ALib: TDbgLibrary;
AnEnabled: Boolean): TFpDbgBreakpoint; AnEnabled: Boolean): TFpDbgBreakpoint;
begin begin
{$ifdef linux} if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
FCacheFileName:=AFuncName; begin
FCacheLib:=ALib; FCacheFileName:=AFuncName;
FCacheBoolean:=AnEnabled; FCacheLib:=ALib;
ExecuteInDebugThread(@DoAddBreakFuncLib); FCacheBoolean:=AnEnabled;
result := FCacheBreakpoint; ExecuteInDebugThread(@DoAddBreakFuncLib);
{$else linux} result := FCacheBreakpoint;
if ALib <> nil then end
result := ALib.AddBreak(AFuncName, AnEnabled)
else else
result := TDbgInstance(FDbgController.CurrentProcess).AddBreak(AFuncName, AnEnabled); if ALib <> nil then
{$endif linux} result := ALib.AddBreak(AFuncName, AnEnabled)
else
result := TDbgInstance(FDbgController.CurrentProcess).AddBreak(AFuncName, AnEnabled);
end; end;
function TFpDebugDebugger.AddWatch(const ALocation: TDBGPtr; ASize: Cardinal; function TFpDebugDebugger.AddWatch(const ALocation: TDBGPtr; ASize: Cardinal;
AReadWrite: TDBGWatchPointKind; AScope: TDBGWatchPointScope AReadWrite: TDBGWatchPointKind; AScope: TDBGWatchPointScope
): TFpDbgBreakpoint; ): TFpDbgBreakpoint;
begin begin
{$ifdef linux} if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
FCacheLocation:=ALocation; begin
FCacheLine:=ASize; FCacheLocation:=ALocation;
FCacheReadWrite:=AReadWrite; FCacheLine:=ASize;
FCacheScope:=AScope; FCacheReadWrite:=AReadWrite;
ExecuteInDebugThread(@DoAddBWatch); FCacheScope:=AScope;
result := FCacheBreakpoint; ExecuteInDebugThread(@DoAddBWatch);
{$else linux} result := FCacheBreakpoint;
result := FDbgController.CurrentProcess.AddWatch(ALocation, ASize, AReadWrite, AScope); end
{$endif linux} else
result := FDbgController.CurrentProcess.AddWatch(ALocation, ASize, AReadWrite, AScope);
end; end;
procedure TFpDebugDebugger.FreeBreakpoint( procedure TFpDebugDebugger.FreeBreakpoint(
const ABreakpoint: TFpDbgBreakpoint); const ABreakpoint: TFpDbgBreakpoint);
begin begin
{$ifdef linux}
if ABreakpoint = nil then exit; if ABreakpoint = nil then exit;
FCacheBreakpoint:=ABreakpoint; if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
ExecuteInDebugThread(@DoFreeBreakpoint); begin
{$else linux} FCacheBreakpoint:=ABreakpoint;
ABreakpoint.Free; ExecuteInDebugThread(@DoFreeBreakpoint);
{$endif linux} end
else
ABreakpoint.Free;
end; end;
function TFpDebugDebugger.ReadData(const AAdress: TDbgPtr; const ASize: Cardinal; out AData): Boolean; function TFpDebugDebugger.ReadData(const AAdress: TDbgPtr; const ASize: Cardinal; out AData): Boolean;
begin begin
{$ifdef linux} if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
FCacheLocation := AAdress; begin
FCacheLine:=ASize; FCacheLocation := AAdress;
FCachePointer := @AData; FCacheLine:=ASize;
ExecuteInDebugThread(@DoReadData); FCachePointer := @AData;
result := FCacheBoolean; ExecuteInDebugThread(@DoReadData);
{$else linux} result := FCacheBoolean;
result:=FDbgController.CurrentProcess.ReadData(AAdress, ASize, AData); end
{$endif linux} else
result:=FDbgController.CurrentProcess.ReadData(AAdress, ASize, AData);
end; end;
function TFpDebugDebugger.ReadAddress(const AAdress: TDbgPtr; out AData: TDBGPtr): Boolean; function TFpDebugDebugger.ReadAddress(const AAdress: TDbgPtr; out AData: TDBGPtr): Boolean;
@ -3078,38 +3080,41 @@ begin
(AThread.CallStackEntryList <> nil) and (AThread.CallStackEntryList <> nil) and
(AFrameRequired < AThread.CallStackEntryList.Count) then (AFrameRequired < AThread.CallStackEntryList.Count) then
exit; exit;
{$ifdef linux} if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
FCallStackEntryListThread := AThread; begin
FCallStackEntryListFrameRequired := AFrameRequired; FCallStackEntryListThread := AThread;
ExecuteInDebugThread(@DoPrepareCallStackEntryList); FCallStackEntryListFrameRequired := AFrameRequired;
{$else linux} ExecuteInDebugThread(@DoPrepareCallStackEntryList);
AThread.PrepareCallStackEntryList(AFrameRequired); end
{$endif linux} else
AThread.PrepareCallStackEntryList(AFrameRequired);
end; end;
function TFpDebugDebugger.FindContext(AThreadId, AStackFrame: Integer): TFpDbgInfoContext; function TFpDebugDebugger.FindContext(AThreadId, AStackFrame: Integer): TFpDbgInfoContext;
begin begin
{$ifdef linux} if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
FCacheThreadId := AThreadId; begin
FCacheStackFrame := AStackFrame; FCacheThreadId := AThreadId;
ExecuteInDebugThread(@DoFindContext); FCacheStackFrame := AStackFrame;
Result := FCacheContext; ExecuteInDebugThread(@DoFindContext);
{$else linux} Result := FCacheContext;
Result := FDbgController.CurrentProcess.FindContext(AThreadId, AStackFrame); end
{$endif linux} else
Result := FDbgController.CurrentProcess.FindContext(AThreadId, AStackFrame);
end; end;
function TFpDebugDebugger.GetParamsAsString(AStackEntry: TDbgCallstackEntry; function TFpDebugDebugger.GetParamsAsString(AStackEntry: TDbgCallstackEntry;
APrettyPrinter: TFpPascalPrettyPrinter): string; APrettyPrinter: TFpPascalPrettyPrinter): string;
begin begin
{$ifdef linux} if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
FParamAsStringStackEntry := AStackEntry; begin
FParamAsStringPrettyPrinter := APrettyPrinter; FParamAsStringStackEntry := AStackEntry;
ExecuteInDebugThread(@DoGetParamsAsString); FParamAsStringPrettyPrinter := APrettyPrinter;
Result := FParamAsString; ExecuteInDebugThread(@DoGetParamsAsString);
{$else linux} Result := FParamAsString;
Result := AStackEntry.GetParamsAsString(APrettyPrinter); end
{$endif linux} else
Result := AStackEntry.GetParamsAsString(APrettyPrinter);
end; end;
constructor TFpDebugDebugger.Create(const AExternalDebugger: String); constructor TFpDebugDebugger.Create(const AExternalDebugger: String);