* Re factorization to move windows-specific code from fpdcommand.pas to fpdbgwinclasses.pas

git-svn-id: trunk@44349 -
This commit is contained in:
joost 2014-03-05 10:13:31 +00:00
parent 51c51a18b9
commit 1d789ef144
6 changed files with 216 additions and 124 deletions

View File

@ -141,10 +141,6 @@ end;
procedure HandleRun(AParams: String);
var
StartupInfo: TStartupInfo;
ProcessInformation: TProcessInformation;
ThreadAttributes: TSecurityAttributes;
begin
if GState <> dsStop
then begin
@ -158,26 +154,14 @@ begin
Exit;
end;
ZeroMemory(@StartUpInfo, SizeOf(StartupInfo));
StartUpInfo.cb := SizeOf(StartupInfo);
StartUpInfo.dwFlags := {STARTF_USESTDHANDLES or} STARTF_USESHOWWINDOW;
StartUpInfo.wShowWindow := SW_SHOWNORMAL or SW_SHOW;
GCurrentProcess := OSDbgClasses.DbgProcessClass.StartInstance(GFileName, AParams);
if assigned(GCurrentProcess) then
begin
WriteLN('Got PID:', GCurrentProcess.Handle, ', TID: ', GCurrentProcess.Handle);
// ZeroMemory(@ThreadAttributes, SizeOf(ThreadAttributes));
// ThreadAttributes.nLength := SizeOf(ThreadAttributes);
// ThreadAttributes.lpSecurityDescriptor
ZeroMemory(@ProcessInformation, SizeOf(ProcessInformation));
if not CreateProcess(nil, PChar(GFileName), nil, nil, True, DETACHED_PROCESS or DEBUG_PROCESS or CREATE_NEW_PROCESS_GROUP, nil, nil, StartUpInfo, ProcessInformation)
then begin
WriteLN('Create process failed: ', GetLastErrorText);
Exit;
end;
WriteLN('Got PID:', ProcessInformation.dwProcessId, ', TID: ',ProcessInformation.dwThreadId);
GState := dsRun;
DebugLoop;
GState := dsRun;
DebugLoop;
end;
end;
procedure HandleBreak(AParams: String);

View File

@ -39,7 +39,6 @@ uses
SysUtils, FPDType, Maps, FpDbgUtil, FpDbgClasses, FpDbgWinExtra;
type
TFPDState = (dsStop, dsRun, dsPause, dsQuit, dsEvent);
TFPDMode = (dm32, dm64);
TFPDImageInfo = (iiNone, iiName, iiDetail);

View File

@ -48,12 +48,8 @@ implementation
uses
FPDGlobal, FPDPEImage, FPDType;
var
MDebugEvent: TDebugEvent;
procedure HandleCreateProcess(const AEvent: TDebugEvent);
var
Proc: TDbgProcess;
S: String;
begin
WriteLN(Format('hFile: 0x%x', [AEvent.CreateProcessInfo.hFile]));
@ -66,15 +62,14 @@ begin
if AEvent.CreateProcessInfo.lpBaseOfImage <> nil
then DumpPEImage(AEvent.CreateProcessInfo.hProcess, TDbgPtr(AEvent.CreateProcessInfo.lpBaseOfImage));
if GMainProcess = nil
then S := GFileName;
Proc := TDbgWinProcess.Create(S, AEvent.dwProcessId, AEvent.dwThreadId, AEvent.CreateProcessInfo);
if GMainProcess = nil
then GMainProcess := Proc;
GProcessMap.Add(AEvent.dwProcessId, Proc);
if not assigned(GCurrentProcess) then
GCurrentProcess := GMainProcess;
(GCurrentProcess as TDbgWinProcess).StartProcess(GFileName, AEvent.CreateProcessInfo);
GProcessMap.Add(AEvent.dwProcessId, GCurrentProcess);
if GBreakOnLibraryLoad
then GState := dsPause;
GCurrentProcess := proc;
end;
procedure HandleCreateThread(const AEvent: TDebugEvent);
@ -462,29 +457,29 @@ procedure DebugLoop;
S.Free;
end;
var
AFirstLoop: boolean;
begin
repeat
if (GCurrentProcess <> nil) and (GState = dsPause)
if (GState in [dsStop, dsPause, dsEvent])
then begin
(GCurrentProcess as TDbgWinProcess).ContinueDebugEvent(GCurrentThread, MDebugEvent);
end;
if GState in [dsStop, dsPause, dsEvent]
then begin
case MDebugEvent.Exception.ExceptionRecord.ExceptionCode of
EXCEPTION_BREAKPOINT,
EXCEPTION_SINGLE_STEP: ContinueDebugEvent(MDebugEvent.dwProcessId, MDebugEvent.dwThreadId, DBG_CONTINUE);
else
ContinueDebugEvent(MDebugEvent.dwProcessId, MDebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
end;
GCurrentProcess.Continue(GCurrentProcess, GCurrentThread, GState);
GState := dsRun;
end;
if not WaitForDebugEvent(MDebugEvent, 10) then Continue;
if assigned(GCurrentProcess) and not assigned(GMainProcess) then
begin
GMainProcess:=GCurrentProcess;
AFirstLoop:=true;
end
else
AFirstLoop:=false;
GCurrentProcess := nil;
GCurrentThread := nil;
if not GetProcess(MDebugEvent.dwProcessId, GCurrentPRocess) and (GMainProcess <> nil) then Continue;
if not GetProcess(MDebugEvent.dwProcessId, GCurrentPRocess) and not AFirstLoop then Continue;
GState := dsEvent;
if GCurrentProcess <> nil

View File

@ -41,6 +41,8 @@ uses
FpDbgInfo, FpdMemoryTools, LazLoggerBase, LazClasses, DbgIntfBaseTypes;
type
TFPDState = (dsStop, dsRun, dsPause, dsQuit, dsEvent);
TDbgProcess = class;
TDbgThread = class(TObject)
@ -86,39 +88,39 @@ type
private
FName: String;
FProcess: TDbgProcess;
FModuleHandle: THandle;
FBaseAddr: TDbgPtr;
FBreakList: TList;
FDbgInfo: TDbgInfo;
FLoader: TDbgImageLoader;
procedure LoadInfo; virtual;
procedure CheckName;
procedure SetName(const AValue: String);
protected
procedure LoadInfo; virtual;
function InitializeLoader: TDbgImageLoader; virtual;
function GetModuleFileName(AModuleHandle: THandle): string; virtual;
procedure SetName(const AValue: String);
public
constructor Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle; const ABaseAddr, ANameAddr: TDbgPtr; const AUnicode: Boolean); virtual;
constructor Create(const AProcess: TDbgProcess); virtual;
destructor Destroy; override;
function AddBreak(const AFileName: String; ALine: Cardinal): TDbgBreakpoint;
function AddrOffset: Int64; // gives the offset between the loaded addresses and the compiled addresses
function AddrOffset: Int64; virtual; // gives the offset between the loaded addresses and the compiled addresses
function FindSymbol(AAdress: TDbgPtr): TFpDbgSymbol;
function RemoveBreak(const AFileName: String; ALine: Cardinal): Boolean;
property Process: TDbgProcess read FProcess;
property ModuleHandle: THandle read FModuleHandle;
property BaseAddr: TDbgPtr read FBaseAddr;
property DbgInfo: TDbgInfo read FDbgInfo;
end;
{ TDbgLibrary }
TDbgLibrary = class(TDbgInstance)
private
FModuleHandle: THandle;
FBaseAddr: TDBGPtr;
public
constructor Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle; const ABaseAddr, ANameAddr: TDbgPtr; const AUnicode: Boolean);
constructor Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle; const ABaseAddr: TDbgPtr);
property Name: String read FName;
property ModuleHandle: THandle read FModuleHandle;
property BaseAddr: TDBGPtr read FBaseAddr;
end;
{ TDbgProcess }
@ -128,7 +130,6 @@ type
FProcessID: Integer;
FThreadID: Integer;
procedure SetName(const AValue: String);
procedure ThreadDestroyed(const AThread: TDbgThread);
protected
FCurrentBreakpoint: TDbgBreakpoint; // set if we are executing the code at the break
@ -143,10 +144,10 @@ type
FBreakMap: TMap; // map BreakAddr -> BreakObject
FMainThread: TDbgThread;
property ProcessID: integer read FProcessID;
function GetHandle: THandle; virtual;
public
constructor Create(const ADefaultName: String; const AProcessID, AThreadID: Integer; const AModuleHandle: THandle; const ABaseAddr, ANameAddr: TDbgPtr; const AUnicode: boolean);
class function StartInstance(AFileName: string; AParams: string): TDbgProcess; virtual;
constructor Create(const AProcessID, AThreadID: Integer);
destructor Destroy; override;
function AddBreak(const ALocation: TDbgPtr): TDbgBreakpoint;
function FindSymbol(const AName: String): TFpDbgSymbol;
@ -161,10 +162,14 @@ type
function ReadString(const AAdress: TDbgPtr; const AMaxSize: Cardinal; out AData: String): Boolean; virtual;
function ReadWString(const AAdress: TDbgPtr; const AMaxSize: Cardinal; out AData: WideString): Boolean; virtual;
function Continue(AProcess: TDbgProcess; AThread: TDbgThread; AState: TFPDState): boolean; virtual;
function WriteData(const AAdress: TDbgPtr; const ASize: Cardinal; const AData): Boolean; virtual;
property Handle: THandle read GetHandle;
property Name: String read FName write SetName;
property ProcessID: integer read FProcessID;
property ThreadID: integer read FThreadID;
end;
TDbgProcessClass = class of TDbgProcess;
@ -217,52 +222,15 @@ end;
function TDbgInstance.AddrOffset: Int64;
begin
Result := FLoader.ImageBase - BaseAddr;
Result := FLoader.ImageBase;
end;
procedure TDbgInstance.CheckName;
constructor TDbgInstance.Create(const AProcess: TDbgProcess);
begin
if FName = ''
then FName := Format('@%p', [Pointer(PtrUInt(FBaseAddr))]);
end;
constructor TDbgInstance.Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle; const ABaseAddr, ANameAddr: TDbgPtr; const AUnicode: Boolean);
var
NamePtr: TDbgPtr;
S: String;
W: WideString;
begin
FBaseAddr := ABaseAddr;
FModuleHandle := AModuleHandle;
FBreakList := TList.Create;
FProcess := AProcess;
inherited Create;
W := '';
if AProcess.ReadOrdinal(ANameAddr, NamePtr)
then begin
if AUnicode
then begin
AProcess.ReadWString(NamePtr, MAX_PATH, W);
end
else begin
if AProcess.ReadString(NamePtr, MAX_PATH, S)
then W := S;
end;
end;
if W = ''
then begin
W := GetModuleFileName(FModuleHandle);
end;
if W = ''
then W := ADefaultName;
SetName(W);
LoadInfo;
end;
destructor TDbgInstance.Destroy;
@ -308,7 +276,6 @@ end;
procedure TDbgInstance.SetName(const AValue: String);
begin
FName := AValue;
CheckName;
end;
function TDbgInstance.InitializeLoader: TDbgImageLoader;
@ -323,9 +290,12 @@ end;
{ TDbgLibrary }
constructor TDbgLibrary.Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle; const ABaseAddr, ANameAddr: TDbgPtr; const AUnicode: Boolean);
constructor TDbgLibrary.Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle; const ABaseAddr: TDbgPtr);
begin
inherited Create(AProcess, ADefaultName, AModuleHandle, ABaseAddr, ANameAddr, AUnicode);
inherited Create(AProcess);
FModuleHandle:=AModuleHandle;
FBaseAddr:=ABaseAddr;
end;
{ TDbgProcess }
@ -336,7 +306,7 @@ begin
FBreakMap.Add(ALocation, Result);
end;
constructor TDbgProcess.Create(const ADefaultName: String; const AProcessID, AThreadID: Integer; const AModuleHandle: THandle; const ABaseAddr, ANameAddr: TDbgPtr; const AUnicode: boolean);
constructor TDbgProcess.Create(const AProcessID, AThreadID: Integer);
const
{.$IFDEF CPU64}
MAP_ID_SIZE = itu8;
@ -354,17 +324,13 @@ begin
FSymInstances := TList.Create;
inherited Create(Self, ADefaultName, AModuleHandle, ABaseAddr, ANameAddr, AUnicode);
inherited Create(Self);
FThreadMap.Add(AThreadID, FMainThread);
if FDbgInfo.HasInfo
then FSymInstances.Add(Self);
end;
destructor TDbgProcess.Destroy;
begin
// CloseHandle(FInfo.hThread);
FreeAndNil(FBreakMap);
FreeAndNil(FThreadMap);
FreeAndNil(FLibMap);
@ -442,6 +408,11 @@ begin
result := false;
end;
function TDbgProcess.Continue(AProcess: TDbgProcess; AThread: TDbgThread; AState: TFPDState): boolean;
begin
result := false;
end;
function TDbgProcess.RemoveBreak(const ALocation: TDbgPtr): Boolean;
begin
if FBreakMap = nil
@ -455,16 +426,17 @@ begin
FThreadMap.Delete(AID);
end;
procedure TDbgProcess.SetName(const AValue: String);
begin
FName := AValue;
end;
function TDbgProcess.GetHandle: THandle;
begin
result := 0;
end;
class function TDbgProcess.StartInstance(AFileName: string; AParams: string): TDbgProcess;
begin
Log('Debug support for this platform is not available.');
result := nil;
end;
procedure TDbgProcess.ThreadDestroyed(const AThread: TDbgThread);
begin
if AThread = FMainThread

View File

@ -80,7 +80,6 @@ type
function GetHandle: THandle; override;
function InitializeLoader: TDbgImageLoader; override;
public
constructor Create(const ADefaultName: String; const AProcessID, AThreadID: Integer; const AInfo: TCreateProcessDebugInfo);
destructor Destroy; override;
function ReadData(const AAdress: TDbgPtr; const ASize: Cardinal; out AData): Boolean; override;
@ -92,11 +91,28 @@ type
procedure ContinueDebugEvent(const AThread: TDbgThread; const ADebugEvent: TDebugEvent);
function HandleDebugEvent(const ADebugEvent: TDebugEvent): Boolean;
class function StartInstance(AFileName: string; AParams: string): TDbgProcess; override;
function Continue(AProcess: TDbgProcess; AThread: TDbgThread; AState: TFPDState): boolean; override;
procedure StartProcess(const ADefaultName: String; const AInfo: TCreateProcessDebugInfo);
function AddrOffset: Int64; override;
function AddLib(const AInfo: TLoadDLLDebugInfo): TDbgLibrary;
procedure AddThread(const AID: Integer; const AInfo: TCreateThreadDebugInfo);
procedure RemoveLib(const AInfo: TUnloadDLLDebugInfo);
end;
{ tDbgWinLibrary }
tDbgWinLibrary = class(TDbgLibrary)
private
FInfo: TLoadDLLDebugInfo;
protected
function InitializeLoader: TDbgImageLoader; override;
public
constructor Create(const AProcess: TDbgProcess; const ADefaultName: String;
const AModuleHandle: THandle; const ABaseAddr: TDbgPtr; AInfo: TLoadDLLDebugInfo);
end;
procedure RegisterDbgClasses;
@ -114,6 +130,52 @@ begin
DebugLn('FpDbg-ERROR: ', GetLastErrorText);
end;
{ tDbgWinLibrary }
function tDbgWinLibrary.InitializeLoader: TDbgImageLoader;
begin
result := TDbgImageLoader.Create(FInfo.hFile);
end;
constructor tDbgWinLibrary.Create(const AProcess: TDbgProcess;
const ADefaultName: String; const AModuleHandle: THandle;
const ABaseAddr: TDbgPtr; AInfo: TLoadDLLDebugInfo);
var
NamePtr: TDbgPtr;
S: String;
W: WideString;
begin
inherited Create(AProcess, ADefaultName, AModuleHandle, ABaseAddr);
FInfo := AInfo;
W := '';
if Process.ReadOrdinal(TDbgPtr(FInfo.lpImageName), NamePtr)
then begin
if FInfo.fUnicode<>0
then begin
Process.ReadWString(NamePtr, MAX_PATH, W);
end
else begin
if Process.ReadString(NamePtr, MAX_PATH, S)
then W := S;
end;
end;
if W = ''
then begin
W := GetModuleFileName(AModuleHandle);
end;
if W = ''
then W := ADefaultName;
SetName(W);
LoadInfo;
end;
{ TDbgWinProcess }
function TDbgWinProcess.GetModuleFileName(AModuleHandle: THandle): string;
@ -139,14 +201,7 @@ end;
function TDbgWinProcess.InitializeLoader: TDbgImageLoader;
begin
result := TDbgImageLoader.Create(ModuleHandle);
end;
constructor TDbgWinProcess.Create(const ADefaultName: String; const AProcessID, AThreadID: Integer; const AInfo: TCreateProcessDebugInfo);
begin
FInfo := AInfo;
inherited Create(ADefaultName, AProcessID, AThreadID, AInfo.hFile, TDbgPtr(AInfo.lpBaseOfImage), TDbgPtr(AInfo.lpImageName), AInfo.fUnicode <> 0);
FMainThread := OSDbgClasses.DbgThreadClass.Create(Self, AThreadID, AInfo.hThread, AInfo.lpThreadLocalBase, AInfo.lpStartAddress);
result := TDbgImageLoader.Create(FInfo.hFile);
end;
destructor TDbgWinProcess.Destroy;
@ -352,11 +407,97 @@ begin
end;
end;
class function TDbgWinProcess.StartInstance(AFileName: string; AParams: string): TDbgProcess;
var
StartupInfo: TStartupInfo;
ProcessInformation: TProcessInformation;
ThreadAttributes: TSecurityAttributes;
begin
ZeroMemory(@StartUpInfo, SizeOf(StartupInfo));
StartUpInfo.cb := SizeOf(StartupInfo);
StartUpInfo.dwFlags := {STARTF_USESTDHANDLES or} STARTF_USESHOWWINDOW;
StartUpInfo.wShowWindow := SW_SHOWNORMAL or SW_SHOW;
// ZeroMemory(@ThreadAttributes, SizeOf(ThreadAttributes));
// ThreadAttributes.nLength := SizeOf(ThreadAttributes);
// ThreadAttributes.lpSecurityDescriptor
ZeroMemory(@ProcessInformation, SizeOf(ProcessInformation));
if CreateProcess(nil, PChar(AFileName), nil, nil, True, DETACHED_PROCESS or DEBUG_PROCESS or CREATE_NEW_PROCESS_GROUP, nil, nil, StartUpInfo, ProcessInformation)
then begin
result := TDbgWinProcess.Create(ProcessInformation.dwProcessId,ProcessInformation.dwThreadId);
end else begin
WriteLN('Create process failed: ', GetLastErrorText);
result := nil;
end;
end;
function TDbgWinProcess.Continue(AProcess: TDbgProcess; AThread: TDbgThread; AState: TFPDState): boolean;
begin
if (AState = dsPause)
then begin
TDbgWinProcess(AProcess).ContinueDebugEvent(AThread, MDebugEvent);
end;
case MDebugEvent.Exception.ExceptionRecord.ExceptionCode of
EXCEPTION_BREAKPOINT,
EXCEPTION_SINGLE_STEP: Windows.ContinueDebugEvent(MDebugEvent.dwProcessId, MDebugEvent.dwThreadId, DBG_CONTINUE);
else
Windows.ContinueDebugEvent(MDebugEvent.dwProcessId, MDebugEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
end;
result := true;
end;
procedure TDbgWinProcess.StartProcess(const ADefaultName: String; const AInfo: TCreateProcessDebugInfo);
var
NamePtr: TDbgPtr;
S: String;
W: WideString;
begin
FInfo := AInfo;
W := '';
if Process.ReadOrdinal(TDbgPtr(AInfo.lpImageName), NamePtr)
then begin
if AInfo.fUnicode <> 0
then begin
Process.ReadWString(NamePtr, MAX_PATH, W);
end
else begin
if Process.ReadString(NamePtr, MAX_PATH, S)
then W := S;
end;
end;
if W = ''
then begin
W := GetModuleFileName(AInfo.hFile);
end;
if W = ''
then W := ADefaultName;
SetName(W);
LoadInfo;
if DbgInfo.HasInfo
then FSymInstances.Add(Self);
FMainThread := OSDbgClasses.DbgThreadClass.Create(Self, ThreadID, AInfo.hThread, AInfo.lpThreadLocalBase, AInfo.lpStartAddress);
end;
function TDbgWinProcess.AddrOffset: Int64;
begin
Result:=inherited AddrOffset - TDbgPtr(FInfo.lpBaseOfImage);
end;
function TDbgWinProcess.AddLib(const AInfo: TLoadDLLDebugInfo): TDbgLibrary;
var
ID: TDbgPtr;
begin
Result := TDbgLibrary.Create(Self, HexValue(AInfo.lpBaseOfDll, SizeOf(Pointer), [hvfIncludeHexchar]), AInfo.hFile, TDbgPtr(AInfo.lpBaseOfDll), TDbgPtr(AInfo.lpImageName), AInfo.fUnicode <> 0);
Result := TDbgWinLibrary.Create(Self, HexValue(AInfo.lpBaseOfDll, SizeOf(Pointer), [hvfIncludeHexchar]), AInfo.hFile, TDbgPtr(AInfo.lpBaseOfDll), AInfo);
ID := TDbgPtr(AInfo.lpBaseOfDll);
FLibMap.Add(ID, Result);
if Result.DbgInfo.HasInfo

View File

@ -50,6 +50,7 @@ function GetLastErrorText: String; {$IFNDEF FPC} overload; {$ENDIF}
{$ifdef windows}
var
GCurrentContext: PContext;
MDebugEvent: TDebugEvent;
{$endif}
//function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwThreadId: DWORD): THandle; stdcall;