FpDebug: added some error handling

git-svn-id: trunk@44865 -
This commit is contained in:
martin 2014-04-30 22:15:31 +00:00
parent 594e1f2069
commit f7c6916db6
4 changed files with 157 additions and 91 deletions

View File

@ -15,11 +15,15 @@ resourcestring
MsgfpErrAnyError = '%1:s';
MsgfpErrSymbolNotFound = 'Identifier not found: "%1:s"';
MsgfpErrNoMemberWithName = 'Member not found: %1:s';
MsgfpErrorNotAStructure = 'Cannot get member "%1:s" from none structure type: %2:s';
MsgfpErrPasParserInvalidExpression = 'Invalid Expression';
MsgfpErrPasParserUnexpectedToken = 'Unexpected token ''%1:s'' at pos %2:d';
MsgfpErrPasParserMissingExprAfterComma = 'Expected Expression after Comma, but found closing bracket %1:s';
MsgfpErrPasParserMissingIndexExpression = 'Expected Expression but found closing bracket: %1:s';
MsgfpErrInvalidNumber = 'Can''t parse number: %1:s';
MsgfpErrCannotDereferenceType = 'Can not dereference Expression "%1:s"';
MsgfpErrTypeHasNoIndex = 'Not a type or Array. Cannot access indexed element on expression %1:s';
// 100 memreader error
MsgfpErrfpErrFailedReadMem = 'Failed to read data from target mem';
MsgfpErrCanNotReadInvalidMem = 'Failed to read data from invalid location';
@ -37,11 +41,15 @@ const
fpErrSymbolNotFound = TFpErrorCode(2);
fpErrNoMemberWithName = TFpErrorCode(3);
fpErrPasParserUnexpectedToken = TFpErrorCode(4);
fpErrPasParserMissingExprAfterComma = TFpErrorCode(5);
fpErrPasParserMissingIndexExpression = TFpErrorCode(6);
fpErrInvalidNumber = TFpErrorCode(7);
fpErrCannotDereferenceType = TFpErrorCode(8);
fpErrorNotAStructure = TFpErrorCode(4);
fpErrPasParserInvalidExpression = TFpErrorCode(24);
fpErrPasParserUnexpectedToken = TFpErrorCode(25);
fpErrPasParserMissingExprAfterComma = TFpErrorCode(26);
fpErrPasParserMissingIndexExpression = TFpErrorCode(27);
fpErrInvalidNumber = TFpErrorCode(28);
fpErrCannotDereferenceType = TFpErrorCode(29);
fpErrTypeHasNoIndex = TFpErrorCode(30);
// 100 memreader error
fpErrFailedReadMem = TFpErrorCode(100);
@ -82,8 +90,8 @@ type
public
function CreateError(AnErrorCode: TFpErrorCode; AData: array of const): TFpError;
function CreateError(AnErrorCode: TFpErrorCode; AnError: TFpError; AData: array of const): TFpError;
function ErrorAsString(AnError: TFpError): string;
function ErrorAsString(AnErrorCode: TFpErrorCode; AData: array of const): string;
function ErrorAsString(AnError: TFpError): string; virtual;
function ErrorAsString(AnErrorCode: TFpErrorCode; AData: array of const): string; virtual;
end;
function GetFpErrorHandler: TFpErrorHandler;
@ -157,20 +165,24 @@ begin
fpErrAnyError: Result := MsgfpErrAnyError;
fpErrSymbolNotFound: Result := MsgfpErrSymbolNotFound;
fpErrNoMemberWithName: Result := MsgfpErrNoMemberWithName;
fpErrPasParserUnexpectedToken: Result := MsgfpErrPasParserUnexpectedToken;
fpErrPasParserMissingExprAfterComma: Result := MsgfpErrPasParserMissingExprAfterComma;
fpErrorNotAStructure: Result := MsgfpErrorNotAStructure;
fpErrPasParserInvalidExpression: Result := MsgfpErrPasParserInvalidExpression;
fpErrPasParserUnexpectedToken: Result := MsgfpErrPasParserUnexpectedToken;
fpErrPasParserMissingExprAfterComma: Result := MsgfpErrPasParserMissingExprAfterComma;
fpErrPasParserMissingIndexExpression: Result := MsgfpErrPasParserMissingIndexExpression;
fpErrInvalidNumber: Result := MsgfpErrInvalidNumber;
fpErrCannotDereferenceType: Result := MsgfpErrCannotDereferenceType;
fpErrInvalidNumber: Result := MsgfpErrInvalidNumber;
fpErrCannotDereferenceType: Result := MsgfpErrCannotDereferenceType;
fpErrTypeHasNoIndex: Result := MsgfpErrTypeHasNoIndex;
fpErrCanNotReadInvalidMem: Result := MsgfpErrCanNotReadInvalidMem;
fpErrCanNotReadMemAtAddr: Result := MsgfpErrCanNotReadMemAtAddr;
fpErrFailedReadMem: Result := MsgfpErrfpErrFailedReadMem;
fpErrCanNotReadMemAtAddr: Result := MsgfpErrCanNotReadMemAtAddr;
fpErrFailedReadMem: Result := MsgfpErrfpErrFailedReadMem;
fpErrLocationParser: Result := MsgfpErrLocationParser;
fpErrLocationParserMemRead: Result := MsgfpErrLocationParserMemRead;
fpErrLocationParserInit: Result := MsgfpErrLocationParserInit;
fpErrLocationParserMinStack: Result := MsgfpErrLocationParserMinStack;
fpErrLocationParser: Result := MsgfpErrLocationParser;
fpErrLocationParserMemRead: Result := MsgfpErrLocationParserMemRead;
fpErrLocationParserInit: Result := MsgfpErrLocationParserInit;
fpErrLocationParserMinStack: Result := MsgfpErrLocationParserMinStack;
fpErrLocationParserNoAddressOnStack: Result := MsgfpErrLocationParserNoAddressOnStack;
end;
end;

View File

@ -1014,54 +1014,54 @@ begin
TmpVal.ReleaseReference;
exit;
end;
if (TmpVal.Kind = skArray) then begin
if (svfInteger in TmpIndex.FieldFlags) then
TmpVal2 := TmpVal.Member[TmpIndex.AsInteger]
else
if (svfOrdinal in TmpIndex.FieldFlags) and
(TmpIndex.AsCardinal <= high(Int64))
then
TmpVal2 := TmpVal.Member[TmpIndex.AsCardinal]
else
begin
SetError('Can not calculate Index');
TmpVal.ReleaseReference;
exit;
end;
if TmpVal2 <> nil then TmpVal2.AddReference;
end // Kind = skArray
else
if (TmpVal.Kind = skPointer) then begin
if (svfInteger in TmpIndex.FieldFlags) then
Offs := TmpIndex.AsInteger
else
if (svfOrdinal in TmpIndex.FieldFlags) and (TmpIndex.AsCardinal <= high(Int64))
then
Offs := Int64(TmpIndex.AsCardinal)
else
begin
SetError('Can not calculate Index');
TmpVal.ReleaseReference;
exit;
end;
case TmpVal.Kind of
skArray: begin
if (svfInteger in TmpIndex.FieldFlags) then
TmpVal2 := TmpVal.Member[TmpIndex.AsInteger]
else
if (svfOrdinal in TmpIndex.FieldFlags) and
(TmpIndex.AsCardinal <= high(Int64))
then
TmpVal2 := TmpVal.Member[TmpIndex.AsCardinal]
else
begin
SetError('Can not calculate Index');
TmpVal.ReleaseReference;
exit;
end;
if TmpVal2 <> nil then TmpVal2.AddReference;
end; // Kind = skArray
skPointer: begin
if (svfInteger in TmpIndex.FieldFlags) then
Offs := TmpIndex.AsInteger
else
if (svfOrdinal in TmpIndex.FieldFlags) and (TmpIndex.AsCardinal <= high(Int64))
then
Offs := Int64(TmpIndex.AsCardinal)
else
begin
SetError('Can not calculate Index');
TmpVal.ReleaseReference;
exit;
end;
TmpVal2 := TmpVal.Member[Offs];
if IsError(TmpVal.LastError) then
SetError('Error dereferencing'); // TODO: set correct error
if TmpVal2 <> nil then TmpVal2.AddReference;
end
else
if (TmpVal.Kind = skString) then begin
//TODO
SetError('Not implemented');
TmpVal.ReleaseReference;
exit;
end
else
begin
SetError(fpErrCannotDereferenceType, [GetText]);
TmpVal.ReleaseReference;
exit;
TmpVal2 := TmpVal.Member[Offs];
if IsError(TmpVal.LastError) then
SetError('Error dereferencing'); // TODO: set correct error
if TmpVal2 <> nil then TmpVal2.AddReference;
end;
skString: begin
//TODO
SetError('Not implemented');
TmpVal.ReleaseReference;
exit;
end
else
begin
SetError(fpErrTypeHasNoIndex, [GetText]);
TmpVal.ReleaseReference;
exit;
end;
end;
if TmpVal2 = nil then begin
@ -1206,11 +1206,19 @@ var
begin
Result := nil;
if (Count = 0) then begin
SetError(fpErrPasParserInvalidExpression, []);
exit;
end;
tmp := Items[0].ResultValue;
if (tmp = nil) or (not Expression.Valid) then
exit;
if (Count = 2) then begin
//TODO if tmp is TFpPascalExpressionPartOperatorMakeRef then
// AVOID creating the TPasParserSymbolPointer by calling tmp.DbgSymbol
// it ran be created in TPasParserSymbolValueCastToPointer if needed.
tmp := Items[0].ResultValue;
if (tmp <> nil) and (tmp.DbgSymbol <> nil) and
(tmp.DbgSymbol.SymbolType = stType)
then begin
@ -1221,9 +1229,13 @@ begin
//Result := tmp.DbgSymbol.TypeCastValue(tmp2);
if Result <> nil then
{$IFDEF WITH_REFCOUNT_DEBUG}Result.DbgRenameReference(nil, 'DoGetResultValue'){$ENDIF};
exit;
end;
end;
// Must be function call
SetError('No support for calling functions');
end;
function TFpPascalExpressionPartBracketArgumentList.DoGetIsTypeCast: Boolean;
@ -1582,6 +1594,7 @@ procedure TFpPascalExpression.SetError(AnErrorCode: TFpErrorCode; AData: array o
begin
FValid := False;
FError := ErrorHandler.CreateError(AnErrorCode, AData);
DebugLn(['Setting error ', ErrorHandler.ErrorAsString(FError)]);
end;
function TFpPascalExpression.PosFromPChar(APChar: PChar): Integer;
@ -2223,20 +2236,14 @@ begin
if Result <> nil then
Result.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(nil, 'DoGetResultValue'){$ENDIF};
//tmp2 := TFpPasParserValueDerefPointer.Create(tmp, Expression);
//if (tmp.TypeInfo.TypeInfo <> nil) then
// Result := tmp.TypeInfo.TypeInfo.TypeCastValue(tmp2)
//else
// Result := tmp2;
//{$IFDEF WITH_REFCOUNT_DEBUG} if Result <> nil then Result.DbgRenameReference(nil, 'DoGetResultValue'){$ENDIF};
//if (tmp.TypeInfo.TypeInfo <> nil) then
// tmp2.ReleaseReference;
end;
end
//if tmp.Kind = skArray then // dynarray
else
begin
Result := nil;
SetError(fpErrCannotDereferenceType, [GetText]);
end;
end;
function TFpPascalExpressionPartOperatorDeRef.MaybeHandlePrevPart(APrevPart: TFpPascalExpressionPart;
@ -2460,7 +2467,7 @@ begin
tmp := Items[0].ResultValue;
if (tmp = nil) then exit;
// Todo unit
if (tmp.Kind in [skClass, skRecord, skObject]) then begin
Result := tmp.MemberByName[Items[1].GetText];
if Result = nil then begin
@ -2469,7 +2476,13 @@ begin
end;
Result.AddReference{$IFDEF WITH_REFCOUNT_DEBUG}(nil, 'DoGetResultValue'){$ENDIF};
Assert((Result.DbgSymbol=nil)or(Result.DbgSymbol.SymbolType=stValue), 'member is value');
exit;
end;
// Todo unit
SetError(fpErrorNotAStructure, [Items[1].GetText, Items[0].GetText]);
end;
end.

View File

@ -594,9 +594,10 @@ begin
Field_DynRec2[2].FieldByte2 := 221;
SetLength(Field_DynDynInt1, 5,3);
SetLength(Field_DynDynInt1[0], 2);
Field_DynDynInt1[0][0] := 1000;
Field_DynDynInt1[0][1] := 1001;
Field_DynDynInt1[0][2] := 1002;
//Field_DynDynInt1[0][2] := 1002;
Field_DynDynInt1[1][0] := 1010;
Field_DynDynInt1[1][1] := 1011;
Field_DynDynInt1[1][2] := 1012;
@ -754,9 +755,10 @@ begin
Local_DynRec2[2].FieldByte2 := 221;
SetLength(Local_DynDynInt1, 5,3);
SetLength(Local_DynDynInt1[0], 2);
Local_DynDynInt1[0][0] := 1000;
Local_DynDynInt1[0][1] := 1001;
Local_DynDynInt1[0][2] := 1002;
//Local_DynDynInt1[0][2] := 1002;
Local_DynDynInt1[1][0] := 1010;
Local_DynDynInt1[1][1] := 1011;
Local_DynDynInt1[1][2] := 1012;
@ -995,9 +997,10 @@ begin
ArrayGlob_DynRec2[2].FieldByte2 := 221;
SetLength(ArrayGlob_DynDynInt1, 5,3);
SetLength(ArrayGlob_DynDynInt1[0], 2);
ArrayGlob_DynDynInt1[0][0] := 1000;
ArrayGlob_DynDynInt1[0][1] := 1001;
ArrayGlob_DynDynInt1[0][2] := 1002;
//ArrayGlob_DynDynInt1[0][2] := 1002;
ArrayGlob_DynDynInt1[1][0] := 1010;
ArrayGlob_DynDynInt1[1][1] := 1011;
ArrayGlob_DynDynInt1[1][2] := 1012;

View File

@ -7,7 +7,7 @@ interface
uses
Classes, SysUtils, strutils, fpcunit, testutils, testregistry, TestGDBMIControl,
DbgIntfBaseTypes, DbgIntfDebuggerBase, TestBase, FpGdbmiDebugger, LCLProc, SynRegExpr,
TestWatchUtils, GDBMIDebugger;
TestWatchUtils, GDBMIDebugger, FpErrorMessages;
const
BREAK_COUNT_TestWatchesUnitSimple = 17;
@ -71,6 +71,7 @@ type
AKind: TDBGSymbolKind; ATpNm: string; AFlgs: TWatchExpectationFlags): PWatchExpectation;
function AddFmtDef (AnExpr, AMtch: string; AKind: TDBGSymbolKind; ATpNm: string; AFlgs: TWatchExpectationFlags=[]): PWatchExpectation;
function AddFmtDef (AnExpr: String; AEvalFlags: TDBGEvaluateFlags; AMtch: string; AKind: TDBGSymbolKind; ATpNm: string; AFlgs: TWatchExpectationFlags=[]): PWatchExpectation;
function AddError (AnExpr: String; AnErrorCode: Integer = 0; AMtch: string = ''): PWatchExpectation;
function AddSimpleInt(AnExpr: string; AMtch: Int64; ATpNm: string): PWatchExpectation;
function AddSimpleUInt(AnExpr: string; AMtch: QWord; ATpNm: string): PWatchExpectation;
@ -88,6 +89,13 @@ type
procedure TestWatches;
end;
{ TTestFpErrorHandler }
TTestFpErrorHandler = class(TFpErrorHandler)
public
function ErrorAsString(AnErrorCode: TFpErrorCode; AData: array of const): string; override;
end;
implementation
const
@ -130,6 +138,15 @@ begin
Result := '<'+TypeName+'> = nil';
end;
{ TTestFpErrorHandler }
function TTestFpErrorHandler.ErrorAsString(AnErrorCode: TFpErrorCode;
AData: array of const): string;
begin
Result := inherited ErrorAsString(AnErrorCode, AData);
Result := 'Error ' + IntToStr(AnErrorCode) + ': ' + Result;
end;
{ TTestWatches }
@ -227,6 +244,18 @@ begin
Result := Add(AnExpr, wdfDefault, AEvalFlags, AMtch, AKind, ATpNm, AFlgs );
end;
function TTestWatches.AddError(AnExpr: String; AnErrorCode: Integer;
AMtch: string): PWatchExpectation;
var
s: String;
begin
if AnErrorCode > 0 then
s := 'Error '+IntToStr(AnErrorCode) + ': ' + AMtch
else
s := 'Error ' + AMtch;
AddFmtDef(AnExpr, s, skNone, '', [fTpMtch, IgnKind, fTExpectError]); // ERROR
end;
function TTestWatches.AddSimpleInt(AnExpr: string; AMtch: Int64;
ATpNm: string): PWatchExpectation;
begin
@ -446,6 +475,7 @@ var
BrkIdx, i, i2, j: Integer;
s, s1, s2, s2def: String;
r: PWatchExpectation;
ErrCodeNotFound: TFpErrorCode;
begin
for BrkIdx := 1 to BREAK_COUNT_TestWatchesUnitSimple do begin
FCurrentExpect := @ExpectBreakSimple[BrkIdx];
@ -471,6 +501,11 @@ begin
// 6: passed in object / var arg object
// unit.glob
end;
if (i in [5..7]) and not(BrkIdx in [4, 5]) then
ErrCodeNotFound := fpErrNoMemberWithName
else
ErrCodeNotFound := fpErrSymbolNotFound;
if i in [0, 5] then begin
// Some Expressions that will always fail
@ -490,14 +525,14 @@ begin
9: begin s1 := 'TSimpleClass1(' + s; s2 := ')'; end;
end;
AddFmtDef(Format('%sIDoNotExist%1:s', [s1,s2]), 'Error', skNone, '', [fTpMtch, IgnKind, fTExpectError]); // ERROR
AddError(Format('%sIDoNotExist%1:s', [s1,s2]), ErrCodeNotFound); // ERROR
// procedures
AddFmtDef(Format('%sInitFields%1:s', [s1,s2]), 'Error', skNone, '', [fTpMtch, IgnKind, fTExpectError]); // ERROR
AddFmtDef(Format('%sSimple_NoneNested%1:s', [s1,s2]), 'Error', skNone, '', [fTpMtch, IgnKind, fTExpectError]); // ERROR
AddError(Format('%sInitFields%1:s', [s1,s2]), ErrCodeNotFound); // ERROR
AddError(Format('%sSimple_NoneNested%1:s', [s1,s2]), ErrCodeNotFound); // ERROR
// type
AddFmtDef(Format('%sTSimpleClass1%1:s', [s1,s2]), 'Error', skNone, '', [fTpMtch, IgnKind, fTExpectError]); // ERROR
AddError(Format('%sTSimpleClass1%1:s', [s1,s2]), ErrCodeNotFound); // ERROR
// unit
AddFmtDef(Format('%sTestWatchesUnitSimple%1:s', [s1,s2]), 'Error', skNone, '', [fTpMtch, IgnKind, fTExpectError]); // ERROR
AddError(Format('%sTestWatchesUnitSimple%1:s', [s1,s2]), ErrCodeNotFound); // ERROR
end;
end;
@ -527,8 +562,8 @@ begin
s2 := '^';
end;
AddFmtDef(Format('%sShort1%1:s', [s,s2]), 'Error', skNone, '', [fTpMtch, IgnKind, fTExpectError]); // ERROR
AddFmtDef(Format('%sInt1%1:s', [s,s2]), 'Error', skNone, '', [fTpMtch, IgnKind, fTExpectError]); // ERROR
AddError(Format('%sShort1%1:s', [s,s2]), ErrCodeNotFound); // ERROR
AddError(Format('%sInt1%1:s', [s,s2]), ErrCodeNotFound); // ERROR
end;
continue;
@ -577,7 +612,8 @@ begin
r := AddFmtDef(Format('%sSet2%1:s', [s,s2]), '^\[\]', skSimple, '', [fTpMtch]);
UpdExpRes(r, stDwarf, '', skSimple); // no sets in dwarf2
end; // i2
AddError(Format('%sByte1%1:s^', [s,s2]), fpErrCannotDereferenceType); // ERROR
end; // i2
end; // i
{%endregion Fields }
@ -636,7 +672,7 @@ if not (i in [2,3]) then
if (not (i in [2,3])) or (i2=0) then begin // open array / not valid, pointer is pointer to dyn array
AddSimpleInt(Format('%sDynAInt1%1:s[0]', [s,s2]), 100, M_Int);
AddSimpleInt(Format('%sDynAInt1%1:s[1]', [s,s2]), 101, M_Int);
AddFmtDef(Format('%sDynAInt1%1:s[0][0]', [s,s2]), 'Error', skNone, '', [fTpMtch, IgnKind, fTExpectError]); // ERROR
AddError(Format('%sDynAInt1%1:s[0][0]', [s,s2]), fpErrTypeHasNoIndex); // ERROR
end;
@ -729,16 +765,17 @@ if not (i in [2,3]) then // open array / TODO
'\(.*?FieldByte1 = 220;.*?FieldByte2 = 221;.*?\)',
skArray, '', [fTpMtch]);
// 1st nested has diff len
AddFmtDef(Format('%sDynDynInt1%1:s', [s,s2]), '^[\(L].*?'+
'\(1000, 1001, 1002\), ' + '\(1010, 1011, 1012\), ' + '\(1020, 1021, 1022\)',
'\(1000, 1001\), ' + '\(1010, 1011, 1012\), ' + '\(1020, 1021, 1022\)',
skArray, '', [fTpMtch]);
AddSimpleInt(Format('%sDynDynInt1%1:s[0][0]', [s,s2]), 1000, M_Int);
AddSimpleInt(Format('%sDynDynInt1%1:s[0,0]', [s,s2]), 1000, M_Int);
AddSimpleInt(Format('%0:sDynDynInt1%1:s[%0:sDynDynInt1%1:s[3,0], %0:sDynDynInt1%1:s[3,1]]', [s,s2]), 1012, M_Int);
AddSimpleInt(Format('%0:sDynDynInt1%1:s[%0:sDynDynInt1%1:s[3,0]][%0:sDynDynInt1%1:s[3,1]]', [s,s2]), 1012, M_Int);
//AddFmtDef(Format('%0:sDynDynInt1%1:s[%0:sDynDynInt1%1:s[3,0].NoMember, %0:sDynDynInt1%1:s[3,1]]', [s,s2]), 'Error', skNone, '', [fTpMtch, IgnKind, fTExpectError]); // ERROR
AddError(Format('%0:sDynDynInt1%1:s[FooNoExistFoo, %0:sDynDynInt1%1:s[3,1]]', [s,s2]), fpErrSymbolNotFound); // ERROR
AddError(Format('%0:sDynDynInt1%1:s[%0:sDynDynInt1%1:s[3,0].NoMember, %0:sDynDynInt1%1:s[3,1]]', [s,s2]), fpErrorNotAStructure); // ERROR
AddFmtDef(Format('%sDynDynClass1%1:s', [s,s2]), '^[^\(G]*?\('+ // not GDB:
@ -1026,6 +1063,7 @@ end;
initialization
ErrorHandler := TTestFpErrorHandler.Create;
RegisterDbgTest(TTestWatches);
RegisterTestSelectors(['TTestWatches'
]);