FpDebug, Windows: Forward OutputDebugString to IDE.

git-svn-id: trunk@65475 -
This commit is contained in:
martin 2021-07-19 18:17:06 +00:00
parent d6c215a491
commit b5bf7de6f9
4 changed files with 48 additions and 2 deletions

View File

@ -529,6 +529,8 @@ type
end; end;
TDbgDisassemblerClass = class of TDbgAsmDecoder; TDbgDisassemblerClass = class of TDbgAsmDecoder;
TDebugOutputEvent = procedure(Sender: TObject; ProcessId, ThreadId: Integer; AMessage: String) of object;
{ TDbgProcess } { TDbgProcess }
TDbgProcess = class(TDbgInstance) TDbgProcess = class(TDbgInstance)
@ -541,6 +543,7 @@ type
FExitCode: DWord; FExitCode: DWord;
FGotExitProcess: Boolean; FGotExitProcess: Boolean;
FLastLibraryUnloaded: TDbgLibrary; FLastLibraryUnloaded: TDbgLibrary;
FOnDebugOutputEvent: TDebugOutputEvent;
FOSDbgClasses: TOSDbgClasses; FOSDbgClasses: TOSDbgClasses;
FProcessID: Integer; FProcessID: Integer;
FThreadID: Integer; FThreadID: Integer;
@ -676,6 +679,7 @@ public
// 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;
property ExceptionClass: string read FExceptionClass write FExceptionClass; property ExceptionClass: string read FExceptionClass write FExceptionClass;
property OnDebugOutputEvent: TDebugOutputEvent read FOnDebugOutputEvent write FOnDebugOutputEvent;
property LastEventProcessIdentifier: THandle read GetLastEventProcessIdentifier; property LastEventProcessIdentifier: THandle read GetLastEventProcessIdentifier;
property MainThread: TDbgThread read FMainThread; property MainThread: TDbgThread read FMainThread;

View File

@ -259,6 +259,7 @@ type
FOnLibraryLoadedEvent: TOnLibraryLoadedEvent; FOnLibraryLoadedEvent: TOnLibraryLoadedEvent;
FOnLibraryUnloadedEvent: TOnLibraryUnloadedEvent; FOnLibraryUnloadedEvent: TOnLibraryUnloadedEvent;
FOnThreadBeforeProcessLoop: TNotifyEvent; FOnThreadBeforeProcessLoop: TNotifyEvent;
FOnThreadDebugOutputEvent: TDebugOutputEvent;
FOnThreadProcessLoopCycleEvent: TOnProcessLoopCycleEvent; FOnThreadProcessLoopCycleEvent: TOnProcessLoopCycleEvent;
FOsDbgClasses: TOSDbgClasses; FOsDbgClasses: TOSDbgClasses;
FRunning, FPauseRequest: cardinal; FRunning, FPauseRequest: cardinal;
@ -285,6 +286,7 @@ type
procedure SetEnvironment(AValue: TStrings); procedure SetEnvironment(AValue: TStrings);
procedure SetExecutableFilename(const AValue: string); procedure SetExecutableFilename(const AValue: string);
procedure DoOnDebugInfoLoaded(Sender: TObject); procedure DoOnDebugInfoLoaded(Sender: TObject);
procedure SetOnThreadDebugOutputEvent(AValue: TDebugOutputEvent);
procedure SetParams(AValue: TStringList); procedure SetParams(AValue: TStringList);
procedure CheckExecutableAndLoadClasses; procedure CheckExecutableAndLoadClasses;
@ -402,6 +404,7 @@ type
property OnThreadBeforeProcessLoop: TNotifyEvent read FOnThreadBeforeProcessLoop write FOnThreadBeforeProcessLoop; property OnThreadBeforeProcessLoop: TNotifyEvent read FOnThreadBeforeProcessLoop write FOnThreadBeforeProcessLoop;
property OnThreadProcessLoopCycleEvent: TOnProcessLoopCycleEvent read FOnThreadProcessLoopCycleEvent write FOnThreadProcessLoopCycleEvent; property OnThreadProcessLoopCycleEvent: TOnProcessLoopCycleEvent read FOnThreadProcessLoopCycleEvent write FOnThreadProcessLoopCycleEvent;
property OnThreadDebugOutputEvent: TDebugOutputEvent read FOnThreadDebugOutputEvent write SetOnThreadDebugOutputEvent;
end; end;
implementation implementation
@ -1303,6 +1306,14 @@ begin
FOnDebugInfoLoaded(Self); FOnDebugInfoLoaded(Self);
end; end;
procedure TDbgController.SetOnThreadDebugOutputEvent(AValue: TDebugOutputEvent);
begin
if FOnThreadDebugOutputEvent = AValue then Exit;
FOnThreadDebugOutputEvent := AValue;
if FMainProcess <> nil then
FMainProcess.OnDebugOutputEvent := AValue;
end;
procedure TDbgController.SetParams(AValue: TStringList); procedure TDbgController.SetParams(AValue: TStringList);
begin begin
if FParams=AValue then Exit; if FParams=AValue then Exit;
@ -1577,6 +1588,8 @@ begin
// IF there is a pause-request, we will hit a deCreateProcess. // IF there is a pause-request, we will hit a deCreateProcess.
// No need to indicate FRunning // No need to indicate FRunning
FMainProcess:=FCurrentProcess; FMainProcess:=FCurrentProcess;
if FMainProcess <> nil then
FMainProcess.OnDebugOutputEvent := FOnThreadDebugOutputEvent;
end end
else else
begin begin

View File

@ -1191,6 +1191,8 @@ function TDbgWinProcess.AnalyseDebugEvent(AThread: TDbgThread): TFPDEvent;
then Exit; then Exit;
end; end;
DebugLn(DBG_VERBOSE, '[%d:%d]: %s', [AEvent.dwProcessId, AEvent.dwThreadId, S]); DebugLn(DBG_VERBOSE, '[%d:%d]: %s', [AEvent.dwProcessId, AEvent.dwThreadId, S]);
if OnDebugOutputEvent <> nil then
OnDebugOutputEvent(Self, AEvent.dwProcessId, AEvent.dwThreadId, S);
end; end;
var var

View File

@ -33,8 +33,8 @@ interface
uses uses
Classes, SysUtils, fgl, math, process, Classes, SysUtils, fgl, math, process,
Forms, Dialogs, Forms, Dialogs, syncobjs,
Maps, LazLogger, LazUTF8, Maps, LazLogger, LazUTF8, lazCollections,
DbgIntfBaseTypes, DbgIntfDebuggerBase, DbgIntfBaseTypes, DbgIntfDebuggerBase,
FpDebugDebuggerUtils, FpDebugDebuggerWorkThreads, FpDebugDebuggerUtils, FpDebugDebuggerWorkThreads,
// FpDebug // FpDebug
@ -287,6 +287,8 @@ type
{ TFpDebugDebugger } { TFpDebugDebugger }
TFpDebugDebugger = class(TFpDebugDebuggerBase) TFpDebugDebugger = class(TFpDebugDebuggerBase)
private type
TFpDebugStringQueue = class(specialize TLazThreadedQueue<string>);
private private
FIsIdle: Boolean; FIsIdle: Boolean;
FPrettyPrinter: TFpPascalPrettyPrinter; FPrettyPrinter: TFpPascalPrettyPrinter;
@ -311,7 +313,12 @@ type
FCachePointer: pointer; FCachePointer: pointer;
FCacheThreadId, FCacheStackFrame: Integer; FCacheThreadId, FCacheStackFrame: Integer;
FCacheContext: TFpDbgSymbolScope; FCacheContext: TFpDbgSymbolScope;
FFpDebugOutputQueue: TFpDebugStringQueue;
FFpDebugOutputAsync: integer;
// //
procedure DoDebugOutput(Data: PtrInt);
procedure DoThreadDebugOutput(Sender: TObject; ProcessId,
ThreadId: Integer; AMessage: String);
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);
@ -2823,6 +2830,23 @@ begin
(AnAddr, FDbgController.DefaultContext, DBGPTRSIZE[FDbgController.CurrentProcess.Mode], Result, AnErr); (AnAddr, FDbgController.DefaultContext, DBGPTRSIZE[FDbgController.CurrentProcess.Mode], Result, AnErr);
end; end;
procedure TFpDebugDebugger.DoThreadDebugOutput(Sender: TObject; ProcessId,
ThreadId: Integer; AMessage: String);
begin
FFpDebugOutputQueue.PushItem(Format('%d: %s', [ThreadId, AMessage]));
if InterlockedExchange(FFpDebugOutputAsync, 1) <> 1 then
Application.QueueAsyncCall(@DoDebugOutput, 0);
end;
procedure TFpDebugDebugger.DoDebugOutput(Data: PtrInt);
var
s: string;
begin
InterlockedExchange(FFpDebugOutputAsync, 0);
while FFpDebugOutputQueue.PopItemTimeout(s, 50) = wrSignaled do
EventLogHandler.LogCustomEvent(ecOutput, etOutputDebugString, s);
end;
function TFpDebugDebugger.ReadAnsiString(AnAddr: TDbgPtr): string; function TFpDebugDebugger.ReadAnsiString(AnAddr: TDbgPtr): string;
var var
StrAddr: TDBGPtr; StrAddr: TDBGPtr;
@ -3687,6 +3711,7 @@ begin
FLockList := TFpDbgLockList.Create; FLockList := TFpDbgLockList.Create;
FWorkQueue := TFpThreadPriorityWorkerQueue.Create(100); FWorkQueue := TFpThreadPriorityWorkerQueue.Create(100);
FWorkQueue.OnQueueIdle := @CheckAndRunIdle; FWorkQueue.OnQueueIdle := @CheckAndRunIdle;
FFpDebugOutputQueue := TFpDebugStringQueue.create(100);
FExceptionStepper := TFpDebugExceptionStepping.Create(Self); FExceptionStepper := TFpDebugExceptionStepping.Create(Self);
FPrettyPrinter := TFpPascalPrettyPrinter.Create(sizeof(pointer)); FPrettyPrinter := TFpPascalPrettyPrinter.Create(sizeof(pointer));
FMemReader := TFpDbgMemReader.Create(self); FMemReader := TFpDbgMemReader.Create(self);
@ -3704,6 +3729,7 @@ begin
FDbgController.OnDebugInfoLoaded := @FDbgControllerDebugInfoLoaded; FDbgController.OnDebugInfoLoaded := @FDbgControllerDebugInfoLoaded;
FDbgController.OnLibraryLoadedEvent := @FDbgControllerLibraryLoaded; FDbgController.OnLibraryLoadedEvent := @FDbgControllerLibraryLoaded;
FDbgController.OnLibraryUnloadedEvent := @FDbgControllerLibraryUnloaded; FDbgController.OnLibraryUnloadedEvent := @FDbgControllerLibraryUnloaded;
FDbgController.OnThreadDebugOutputEvent := @DoThreadDebugOutput;
FDbgController.NextOnlyStopOnStartLine := TFpDebugDebuggerProperties(GetProperties).NextOnlyStopOnStartLine; FDbgController.NextOnlyStopOnStartLine := TFpDebugDebuggerProperties(GetProperties).NextOnlyStopOnStartLine;
FDbgController.OnThreadProcessLoopCycleEvent:=@FExceptionStepper.ThreadProcessLoopCycle; FDbgController.OnThreadProcessLoopCycleEvent:=@FExceptionStepper.ThreadProcessLoopCycle;
@ -3727,6 +3753,7 @@ begin
{$IFDEF FPDEBUG_THREAD_CHECK} CurrentFpDebugThreadIdForAssert := MainThreadID;{$ENDIF} {$IFDEF FPDEBUG_THREAD_CHECK} CurrentFpDebugThreadIdForAssert := MainThreadID;{$ENDIF}
Application.RemoveAsyncCalls(Self); Application.RemoveAsyncCalls(Self);
FreeAndNil(FFpDebugOutputQueue);
FreeAndNil(FDbgController); FreeAndNil(FDbgController);
FreeAndNil(FPrettyPrinter); FreeAndNil(FPrettyPrinter);
FreeAndNil(FMemManager); FreeAndNil(FMemManager);