mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-06 18:27:48 +02:00
FpDebug, Windows: Forward OutputDebugString to IDE.
git-svn-id: trunk@65475 -
This commit is contained in:
parent
d6c215a491
commit
b5bf7de6f9
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user