DBG: Display more info for error-state

git-svn-id: trunk@30806 -
This commit is contained in:
martin 2011-05-19 12:08:22 +00:00
parent cbb2956bdd
commit ccd2349b54
5 changed files with 124 additions and 22 deletions

View File

@ -57,6 +57,8 @@ type
function WaitForHandles(const AHandles: array of Integer; var ATimeOut: Integer): Integer; overload; function WaitForHandles(const AHandles: array of Integer; var ATimeOut: Integer): Integer; overload;
function WaitForHandles(const AHandles: array of Integer): Integer; overload; function WaitForHandles(const AHandles: array of Integer): Integer; overload;
protected protected
procedure DoReadError; virtual;
procedure DoWriteError; virtual;
function GetDebugProcessRunning: Boolean; virtual; function GetDebugProcessRunning: Boolean; virtual;
procedure ProcessWhileWaitForHandles; virtual; procedure ProcessWhileWaitForHandles; virtual;
function CreateDebugProcess(const AOptions: String): Boolean; virtual; function CreateDebugProcess(const AOptions: String): Boolean; virtual;
@ -264,6 +266,16 @@ begin
Result := WaitForHandles(AHandles, t); Result := WaitForHandles(AHandles, t);
end; end;
procedure TCmdLineDebugger.DoReadError;
begin
SetState(dsError);
end;
procedure TCmdLineDebugger.DoWriteError;
begin
SetState(dsError);
end;
procedure TCmdLineDebugger.ProcessWhileWaitForHandles; procedure TCmdLineDebugger.ProcessWhileWaitForHandles;
begin begin
// nothing // nothing
@ -417,7 +429,7 @@ begin
if (WaitSet = 0) and not FReadLineTimedOut if (WaitSet = 0) and not FReadLineTimedOut
then begin then begin
SmartWriteln('[TCmdLineDebugger.Getoutput] Error waiting '); SmartWriteln('[TCmdLineDebugger.Getoutput] Error waiting ');
SetState(dsError); DoReadError;
Break; Break;
end; end;
@ -477,7 +489,7 @@ begin
end end
else begin else begin
DebugLn('[TCmdLineDebugger.SendCmdLn] Unable to send <', ACommand, '>. No process running.'); DebugLn('[TCmdLineDebugger.SendCmdLn] Unable to send <', ACommand, '>. No process running.');
SetState(dsError); DoWriteError;
end; end;
end; end;

View File

@ -2310,6 +2310,8 @@ type
FCurEnvironment: TStrings; FCurEnvironment: TStrings;
FDisassembler: TDBGDisassembler; FDisassembler: TDBGDisassembler;
FEnvironment: TStrings; FEnvironment: TStrings;
FErrorStateInfo: String;
FErrorStateMessage: String;
FExceptions: TDBGExceptions; FExceptions: TDBGExceptions;
FExitCode: Integer; FExitCode: Integer;
FExternalDebugger: String; FExternalDebugger: String;
@ -2374,6 +2376,7 @@ type
virtual; abstract; // True if succesful virtual; abstract; // True if succesful
procedure SetExitCode(const AValue: Integer); procedure SetExitCode(const AValue: Integer);
procedure SetState(const AValue: TDBGState); procedure SetState(const AValue: TDBGState);
procedure SetErrorState(const AMsg: String; const AInfo: String = '');
procedure DoRelease; virtual; procedure DoRelease; virtual;
public public
class function Caption: String; virtual; // The name of the debugger as shown in the debuggeroptions class function Caption: String; virtual; // The name of the debugger as shown in the debuggeroptions
@ -2440,6 +2443,8 @@ type
property Threads: TThreadsSupplier read FThreads; property Threads: TThreadsSupplier read FThreads;
property WorkingDir: String read FWorkingDir write FWorkingDir; // The working dir of the exe being debugged property WorkingDir: String read FWorkingDir write FWorkingDir; // The working dir of the exe being debugged
property IsIdle: Boolean read GetIsIdle; // Nothing queued property IsIdle: Boolean read GetIsIdle; // Nothing queued
property ErrorStateMessage: String read FErrorStateMessage;
property ErrorStateInfo: String read FErrorStateInfo;
// Events // Events
property OnCurrent: TDBGCurrentLineEvent read FOnCurrent write FOnCurrent; // Passes info about the current line being debugged property OnCurrent: TDBGCurrentLineEvent read FOnCurrent write FOnCurrent; // Passes info about the current line being debugged
property OnDbgOutput: TDBGOutputEvent read FOnDbgOutput write FOnDbgOutput; // Passes all debuggeroutput property OnDbgOutput: TDBGOutputEvent read FOnDbgOutput write FOnDbgOutput; // Passes all debuggeroutput
@ -4725,6 +4730,8 @@ end;
procedure TDebugger.Init; procedure TDebugger.Init;
begin begin
FExitCode := 0; FExitCode := 0;
FErrorStateMessage := '';
FErrorStateInfo := '';
SetState(dsIdle); SetState(dsIdle);
end; end;
@ -4861,6 +4868,15 @@ begin
end; end;
end; end;
procedure TDebugger.SetErrorState(const AMsg: String; const AInfo: String = '');
begin
if FErrorStateMessage = ''
then FErrorStateMessage := AMsg;
if FErrorStateInfo = ''
then FErrorStateInfo := AInfo;
SetState(dsError);
end;
procedure TDebugger.DoRelease; procedure TDebugger.DoRelease;
begin begin
Self.Free; Self.Free;

View File

@ -5,7 +5,7 @@ object DbgFeedbackDlg: TDbgFeedbackDlg
Width = 605 Width = 605
AutoSize = True AutoSize = True
BorderIcons = [biSystemMenu] BorderIcons = [biSystemMenu]
BorderStyle = bsDialog BorderStyle = bsSizeToolWin
Caption = 'DbgFeedbackDlg' Caption = 'DbgFeedbackDlg'
ClientHeight = 212 ClientHeight = 212
ClientWidth = 605 ClientWidth = 605

View File

@ -185,14 +185,22 @@ type
FState : TGDBMIDebuggerCommandState; FState : TGDBMIDebuggerCommandState;
FSeenStates: TGDBMIDebuggerCommandStates; FSeenStates: TGDBMIDebuggerCommandStates;
FTheDebugger: TGDBMIDebugger; // Set during Execute FTheDebugger: TGDBMIDebugger; // Set during Execute
FLastExecCommand: String;
FLastExecResult: TGDBMIExecResult; FLastExecResult: TGDBMIExecResult;
FLogWarnings: String; FLogWarnings: String;
function GetDebuggerProperties: TGDBMIDebuggerProperties; function GetDebuggerProperties: TGDBMIDebuggerProperties;
function GetDebuggerState: TDBGState; function GetDebuggerState: TDBGState;
function GetTargetInfo: PGDBMITargetInfo; function GetTargetInfo: PGDBMITargetInfo;
procedure SetKeepFinished(const AValue: Boolean); procedure SetKeepFinished(const AValue: Boolean);
protected protected
procedure SetDebuggerState(const AValue: TDBGState); procedure SetDebuggerState(const AValue: TDBGState);
procedure SetDebuggerErrorState(const AMsg: String; const AInfo: String = '');
function ErrorStateMessage: String; virtual;
function ErrorStateInfo: String; virtual;
property DebuggerState: TDBGState read GetDebuggerState;
property DebuggerProperties: TGDBMIDebuggerProperties read GetDebuggerProperties;
property TargetInfo: PGDBMITargetInfo read GetTargetInfo;
protected
procedure SetState(NewState: TGDBMIDebuggerCommandState); procedure SetState(NewState: TGDBMIDebuggerCommandState);
procedure DoStateChanged(OldState: TGDBMIDebuggerCommandState); virtual; procedure DoStateChanged(OldState: TGDBMIDebuggerCommandState); virtual;
procedure DoFree; virtual; procedure DoFree; virtual;
@ -204,9 +212,8 @@ type
procedure DoOnExecuted; procedure DoOnExecuted;
procedure DoCancel; virtual; procedure DoCancel; virtual;
procedure DoOnCanceled; procedure DoOnCanceled;
property SeenStates: TGDBMIDebuggerCommandStates read FSeenStates; property SeenStates: TGDBMIDebuggerCommandStates read FSeenStates;
property DebuggerState: TDBGState read GetDebuggerState; property QueueRunLevel: Integer read FQueueRunLevel write FQueueRunLevel; // if queue is nested
property DebuggerProperties: TGDBMIDebuggerProperties read GetDebuggerProperties;
protected protected
// ExecuteCommand does execute direct. It does not use the queue // ExecuteCommand does execute direct. It does not use the queue
function ExecuteCommand(const ACommand: String; function ExecuteCommand(const ACommand: String;
@ -249,15 +256,13 @@ type
function GetPtrValue(const AExpression: String; const AValues: array of const; ConvertNegative: Boolean = False): TDbgPtr; function GetPtrValue(const AExpression: String; const AValues: array of const; ConvertNegative: Boolean = False): TDbgPtr;
function CheckHasType(TypeName: String; TypeFlag: TGDBMITargetFlag): TGDBMIExecResult; function CheckHasType(TypeName: String; TypeFlag: TGDBMITargetFlag): TGDBMIExecResult;
function PointerTypeCast: string; function PointerTypeCast: string;
function FrameToLocation(const AFrame: String = ''): TDBGLocationRec; function FrameToLocation(const AFrame: String = ''): TDBGLocationRec;
procedure ProcessFrame(const ALocation: TDBGLocationRec); overload; procedure ProcessFrame(const ALocation: TDBGLocationRec); overload;
procedure ProcessFrame(const AFrame: String = ''); overload; procedure ProcessFrame(const AFrame: String = ''); overload;
procedure DoDbgEvent(const ACategory: TDBGEventCategory; const AEventType: TDBGEventType; const AText: String); procedure DoDbgEvent(const ACategory: TDBGEventCategory; const AEventType: TDBGEventType; const AText: String);
property TargetInfo: PGDBMITargetInfo read GetTargetInfo;
property LastExecResult: TGDBMIExecResult read FLastExecResult; property LastExecResult: TGDBMIExecResult read FLastExecResult;
property DefaultTimeOut: Integer read FDefaultTimeOut write FDefaultTimeOut; property DefaultTimeOut: Integer read FDefaultTimeOut write FDefaultTimeOut;
property ProcessResultTimedOut: Boolean read FProcessResultTimedOut; property ProcessResultTimedOut: Boolean read FProcessResultTimedOut;
property QueueRunLevel: Integer read FQueueRunLevel write FQueueRunLevel; // if queue is nested
public public
constructor Create(AOwner: TGDBMIDebugger); constructor Create(AOwner: TGDBMIDebugger);
destructor Destroy; override; destructor Destroy; override;
@ -362,6 +367,7 @@ type
function StartDebugging(AContinueCommand: TGDBMIDebuggerCommand = nil): Boolean; function StartDebugging(AContinueCommand: TGDBMIDebuggerCommand = nil): Boolean;
protected protected
FErrorHandlingFlags: set of (ehfDeferReadWriteError, ehfGotReadError, ehfGotWriteError);
{$IFDEF MSWindows} {$IFDEF MSWindows}
FPauseRequestInThreadID: Cardinal; FPauseRequestInThreadID: Cardinal;
{$ENDIF} {$ENDIF}
@ -389,6 +395,8 @@ type
procedure ClearCommandQueue; procedure ClearCommandQueue;
function GetIsIdle: Boolean; override; function GetIsIdle: Boolean; override;
procedure DoState(const OldState: TDBGState); override; procedure DoState(const OldState: TDBGState); override;
procedure DoReadError; override;
procedure DoWriteError; override;
procedure DoThreadChanged; procedure DoThreadChanged;
property TargetPID: Integer read FTargetInfo.TargetPID; property TargetPID: Integer read FTargetInfo.TargetPID;
property TargetPtrSize: Byte read FTargetInfo.TargetPtrSize; property TargetPtrSize: Byte read FTargetInfo.TargetPtrSize;
@ -440,6 +448,15 @@ resourcestring
+ 'Press "Stop" to end the debug session'; + 'Press "Stop" to end the debug session';
gdbmiTimeOutForCmd = 'Time-out for command: "%s"'; gdbmiTimeOutForCmd = 'Time-out for command: "%s"';
gdbmiFatalErrorOccured = 'Unrecoverable Error: "%s"'; gdbmiFatalErrorOccured = 'Unrecoverable Error: "%s"';
gdbmiErrorStateGenericInfo = 'Error in: %1:s %0:s';
gdbmiErrorStateInfoCommandError =
'%0:sThe GDB command:%0:s"%1:s"%0:sreturned the error:%0:s"%2:s"%0:s';
gdbmiErrorStateInfoCommandNoResult =
'%0:sThe GDB command:%0:s"%1:s"%0:sdid not return any result%0:s';
gdbmiErrorStateInfoFailedWrite = '%0:sCould not send a command to GDB%0:s';
gdbmiErrorStateInfoFailedRead = '%0:sCould not read output from GDB.%0:s';
gdbmiErrorStateInfoGDBGone = '%0:sThe GDB process is no longer running.%0:s';
implementation implementation
@ -1351,7 +1368,6 @@ type
{ TGDBStringIterator } { TGDBStringIterator }
TGDBStringIterator=class TGDBStringIterator=class
private
protected protected
FDataSize: Integer; FDataSize: Integer;
FReadPointer: Integer; FReadPointer: Integer;
@ -5442,6 +5458,20 @@ begin
inherited DoState(OldState); inherited DoState(OldState);
end; end;
procedure TGDBMIDebugger.DoReadError;
begin
include(FErrorHandlingFlags, ehfGotReadError);
if not(ehfDeferReadWriteError in FErrorHandlingFlags)
then inherited DoReadError;
end;
procedure TGDBMIDebugger.DoWriteError;
begin
include(FErrorHandlingFlags, ehfGotWriteError);
if not(ehfDeferReadWriteError in FErrorHandlingFlags)
then inherited DoWriteError;
end;
procedure TGDBMIDebugger.DoThreadChanged; procedure TGDBMIDebugger.DoThreadChanged;
begin begin
TGDBMICallstack(CallStack).DoThreadChanged; TGDBMICallstack(CallStack).DoThreadChanged;
@ -6252,6 +6282,7 @@ begin
LockRelease; LockRelease;
try try
FPauseWaitState := pwsNone; FPauseWaitState := pwsNone;
FErrorHandlingFlags := [];
FInExecuteCount := 0; FInExecuteCount := 0;
Options := '-silent -i mi -nx'; Options := '-silent -i mi -nx';
@ -8704,6 +8735,35 @@ begin
FTheDebugger.SetState(AValue); FTheDebugger.SetState(AValue);
end; end;
procedure TGDBMIDebuggerCommand.SetDebuggerErrorState(const AMsg: String;
const AInfo: String);
begin
FTheDebugger.SetErrorState(AMsg, AInfo);
end;
function TGDBMIDebuggerCommand.ErrorStateMessage: String;
begin
Result := '';
if ehfGotWriteError in FTheDebugger.FErrorHandlingFlags
then Result := Result + Format(gdbmiErrorStateInfoFailedWrite, [LineEnding])
else
if ehfGotReadError in FTheDebugger.FErrorHandlingFlags
then Result := Result + Format(gdbmiErrorStateInfoFailedRead, [LineEnding]);
if not FTheDebugger.DebugProcessRunning
then Result := Result + Format(gdbmiErrorStateInfoGDBGone, [LineEnding]);
end;
function TGDBMIDebuggerCommand.ErrorStateInfo: String;
begin
Result := Format(gdbmiErrorStateGenericInfo, [LineEnding, DebugText]);
if FLastExecResult.Values = ''
then Result := Format(gdbmiErrorStateInfoCommandNoResult, [LineEnding, FLastExecCommand])
else Result := Format(gdbmiErrorStateInfoCommandError, [LineEnding, FLastExecCommand, FLastExecResult.Values]);
if not FTheDebugger.DebugProcessRunning
then Result := Result + Format(gdbmiErrorStateInfoGDBGone, [LineEnding]);
end;
procedure TGDBMIDebuggerCommand.SetState(NewState: TGDBMIDebuggerCommandState); procedure TGDBMIDebuggerCommand.SetState(NewState: TGDBMIDebuggerCommandState);
var var
OldState: TGDBMIDebuggerCommandState; OldState: TGDBMIDebuggerCommandState;
@ -8846,29 +8906,42 @@ begin
AResult.Values := ''; AResult.Values := '';
AResult.State := dsNone; AResult.State := dsNone;
AResult.Flags := []; AResult.Flags := [];
FLastExecCommand := ACommand;
if (ATimeOut = -1) and (DefaultTimeOut > 0) if (ATimeOut = -1) and (DefaultTimeOut > 0)
then ATimeOut := DefaultTimeOut; then ATimeOut := DefaultTimeOut;
FTheDebugger.SendCmdLn(ACommand); try
FTheDebugger.FErrorHandlingFlags := FTheDebugger.FErrorHandlingFlags
+ [ehfDeferReadWriteError] - [ehfGotReadError, ehfGotWriteError];
Result := ProcessResult(AResult, ATimeOut); FTheDebugger.SendCmdLn(ACommand);
FLastExecResult := AResult; if ehfGotWriteError in FTheDebugger.FErrorHandlingFlags then begin
ProcessResult(AResult, 50); // not expecting anything
Result := False;
end
else begin
Result := ProcessResult(AResult, ATimeOut);
FLastExecResult := AResult;
if ProcessResultTimedOut then if ProcessResultTimedOut then
Result := RevorerTimeOut; Result := RevorerTimeOut;
end;
finally
Exclude(FTheDebugger.FErrorHandlingFlags, ehfDeferReadWriteError);
end;
if not Result if not Result
then begin then begin
// either gdb did not return a Result Record: "^xxxx," // either gdb did not return a Result Record: "^xxxx,"
// or the Result Record was not a known one: 'done', 'running', 'exit', 'error' // or the Result Record was not a known one: 'done', 'running', 'exit', 'error'
DebugLn('[WARNING] TGDBMIDebugger: ExecuteCommand "',ACommand,'" failed.'); DebugLn('[WARNING] TGDBMIDebugger: ExecuteCommand "',ACommand,'" failed.');
SetDebuggerState(dsError); SetDebuggerErrorState(ErrorStateMessage, ErrorStateInfo);
AResult.State := dsError; AResult.State := dsError;
end; end;
if (cfCheckError in AFlags) and (AResult.State = dsError) if (cfCheckError in AFlags) and (AResult.State = dsError)
then SetDebuggerState(AResult.State); then SetDebuggerErrorState(ErrorStateMessage, ErrorStateInfo);
if (cfCheckState in AFlags) and not (AResult.State in [dsError, dsNone]) if (cfCheckState in AFlags) and not (AResult.State in [dsError, dsNone])
then SetDebuggerState(AResult.State); then SetDebuggerState(AResult.State);

View File

@ -925,10 +925,11 @@ begin
{$endif} {$endif}
// shutting down lazarus may kill gdb, so we get an error // shutting down lazarus may kill gdb, so we get an error
if not Application.Terminated if not Application.Terminated
then MessageDlg(lisDebuggerError, then FeedbackDlg.ExecuteFeedbackDialog
Format(lisDebuggerErrorOoopsTheDebuggerEnteredTheErrorState, [#13#13, (Format(lisDebuggerErrorOoopsTheDebuggerEnteredTheErrorState,
#13, #13#13]), [LineEnding+LineEnding, LineEnding, LineEnding+LineEnding])
mtError, [mbOK],0); + LineEnding + LineEnding + FDebugger.ErrorStateMessage,
FDebugger.ErrorStateInfo, ftError, [frStop]);
end; end;
dsStop: begin dsStop: begin
if (OldState<>dsIdle) if (OldState<>dsIdle)