FPDebug: refactor

git-svn-id: trunk@43276 -
This commit is contained in:
martin 2013-10-18 22:43:02 +00:00
parent 9fb861018a
commit 2c8bcdec98
6 changed files with 415 additions and 191 deletions

View File

@ -70,7 +70,7 @@ type
TDbgSymbolKind = (
skNone, // undefined type
skUser, // userdefined type, this sym refers to another sym defined elswhere
// skUser, // userdefined type, this sym refers to another sym defined elswhere
skInstance, // the main exe/dll, containing all other syms
skUnit, // contains syms defined in this unit
//--------------------------------------------------------------------------
@ -83,6 +83,7 @@ type
//--------------------------------------------------------------------------
skArray,
//--------------------------------------------------------------------------
skPointer,
skInteger, // Basic types, these cannot have references or children
skCardinal, // only size matters ( char(1) = Char, char(2) = WideChar
skBoolean, // cardinal(1) = Byte etc.
@ -101,8 +102,8 @@ type
);
TDbgSymbolFlag =(
sfPointer, // The sym is a pointer to the reference
sfConst, // The sym is a constan and cannot be modified
//sfPointer, // The sym is a pointer to the reference
sfConst, // The sym is a constant and cannot be modified
sfVar,
sfOut,
sfpropGet,
@ -111,6 +112,11 @@ type
);
TDbgSymbolFlags = set of TDbgSymbolFlag;
TDbgSymbolField = (
sfName, sfKind
);
TDbgSymbolFields = set of TDbgSymbolField;
{ TDbgSymbol }
TDbgSymbol = class(TRefCountedObject)
@ -118,7 +124,13 @@ type
FName: String;
FKind: TDbgSymbolKind;
FAddress: TDbgPtr;
FEvaluatedFields: TDbgSymbolFields;
function GetKind: TDbgSymbolKind;
function GetName: String;
protected
function GetPointedToType: TDbgSymbol; virtual;
function GetChild(AIndex: Integer): TDbgSymbol; virtual;
function GetColumn: Cardinal; virtual;
function GetCount: Integer; virtual;
@ -128,23 +140,36 @@ type
function GetParent: TDbgSymbol; virtual;
function GetReference: TDbgSymbol; virtual;
function GetSize: Integer; virtual;
procedure SetName(AValue: String);
procedure SetKind(AValue: TDbgSymbolKind);
procedure KindNeeded; virtual;
procedure NameNeeded; virtual;
public
constructor Create(const AName: String);
constructor Create(const AName: String; AKind: TDbgSymbolKind; AAddress: TDbgPtr);
destructor Destroy; override;
property Count: Integer read GetCount;
property Name: String read FName;
property Kind: TDbgSymbolKind read FKind;
// Basic info
property Name: String read GetName;
property Kind: TDbgSymbolKind read GetKind;
// Memory; Size is also part of type (byte vs word vs ...)
property Address: TDbgPtr read FAddress;
property Size: Integer read GetSize;
// Location
property FileName: String read GetFile;
property Line: Cardinal read GetLine;
property Column: Cardinal read GetColumn;
property Flags: TDbgSymbolFlags read GetFlags;
property Reference: TDbgSymbol read GetReference;
property Parent: TDbgSymbol read GetParent;
property Children[AIndex: Integer]: TDbgSymbol read GetChild;
end;
//
property Flags: TDbgSymbolFlags read GetFlags; deprecated;
property Count: Integer read GetCount; deprecated;
property Reference: TDbgSymbol read GetReference; deprecated;
property Parent: TDbgSymbol read GetParent; deprecated;
//property Children[AIndex: Integer]: TDbgSymbol read GetChild;
// For pointers only
property PointedToType: TDbgSymbol read GetPointedToType;
end;
{ TDbgInfo }
@ -276,7 +301,7 @@ type
end;
{$endif}
function dbgs(ADbgSymbolKind: TDbgSymbolKind): String; overload;
implementation
@ -288,6 +313,12 @@ begin
DebugLn('FpDbg-ERROR: ', GetLastErrorText);
end;
function dbgs(ADbgSymbolKind: TDbgSymbolKind): String;
begin
Result := '';
WriteStr(Result, ADbgSymbolKind);
end;
{$ifdef windows}
{ TDbgInstance }
@ -854,13 +885,18 @@ end;
{ TDbgSymbol }
constructor TDbgSymbol.Create(const AName: String; AKind: TDbgSymbolKind; AAddress: TDbgPtr);
constructor TDbgSymbol.Create(const AName: String);
begin
inherited Create;
AddReference;
if AName <> '' then
SetName(AName);
end;
FName := AName;
FKind := AKind;
constructor TDbgSymbol.Create(const AName: String; AKind: TDbgSymbolKind; AAddress: TDbgPtr);
begin
Create(AName);
SetKind(AKind);
FAddress := AAddress;
end;
@ -869,6 +905,37 @@ begin
inherited Destroy;
end;
function TDbgSymbol.GetKind: TDbgSymbolKind;
begin
if not(sfKind in FEvaluatedFields) then
KindNeeded;
Result := FKind;
end;
function TDbgSymbol.GetName: String;
begin
if not(sfName in FEvaluatedFields) then
NameNeeded;
Result := FName;
end;
function TDbgSymbol.GetPointedToType: TDbgSymbol;
begin
Result := nil;
end;
procedure TDbgSymbol.SetKind(AValue: TDbgSymbolKind);
begin
FKind := AValue;
Include(FEvaluatedFields, sfKind);
end;
procedure TDbgSymbol.SetName(AValue: String);
begin
FName := AValue;
Include(FEvaluatedFields, sfName);
end;
function TDbgSymbol.GetChild(AIndex: Integer): TDbgSymbol;
begin
result := nil;
@ -914,6 +981,16 @@ begin
Result := 0;
end;
procedure TDbgSymbol.KindNeeded;
begin
SetKind(skNone);
end;
procedure TDbgSymbol.NameNeeded;
begin
SetName('');
end;
{$ifdef windows}
{ TDbgBreak }

View File

@ -269,6 +269,8 @@ type
function FindNamedChild(AName: String): TDwarfInformationEntry;
function FindChildByTag(ATag: Cardinal): TDwarfInformationEntry;
function FirstChild: TDwarfInformationEntry;
function Clone: TDwarfInformationEntry;
property Abbrev: TDwarfAbbrev read GetAbbrev write SetAbbrev;
property AbbrevData: PDwarfAbbrevEntry read FAbbrevData; // only valid if Abbrev is available
@ -506,13 +508,13 @@ type
TDbgDwarfIdentifier = class(TDbgSymbol)
private
FCU: TDwarfCompilationUnit;
FIdentifierName: String;
FInformationEntry: TDwarfInformationEntry;
FTypeInfo: TDbgDwarfTypeIdentifier;
FFlags: set of (didtNameRead, didtTypeRead);
function GetIdentifierName: String;
function GetTypeInfo: TDbgDwarfTypeIdentifier;
protected
procedure NameNeeded; override;
//function GetChild(AIndex: Integer): TDbgSymbol; override;
//function GetColumn: Cardinal; override;
//function GetCount: Integer; override;
@ -527,19 +529,17 @@ type
class function GetSubClass(ATag: Cardinal): TDbgDwarfIdentifierClass;
public
class function CreateSubClass(AName: String; AnInformationEntry: TDwarfInformationEntry): TDbgDwarfIdentifier;
constructor Create(AName: String; AnInformationEntry: TDwarfInformationEntry); virtual;
constructor Create(AName: String; AnInformationEntry: TDwarfInformationEntry);
constructor Create(AName: String; AnInformationEntry: TDwarfInformationEntry;
AKind: TDbgSymbolKind; AAddress: TDbgPtr);
destructor Destroy; override;
//constructor Create(AName: String; AAddress: TDbgPtr; ACompilationUnit: TDwarfCompilationUnit;
// AScope: TDwarfScopeInfo);
//destructor Destroy; override;
property IdentifierName: String read GetIdentifierName;
end;
{ TDbgDwarfValueIdentifier }
TDbgDwarfValueIdentifier = class(TDbgDwarfIdentifier) // var, const, member, ...
protected
procedure KindNeeded; override;
public
property TypeInfo;
end;
@ -594,7 +594,6 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
function GetIsBaseType: Boolean; virtual;
function GetIsPointerType: Boolean; virtual;
function GetIsStructType: Boolean; virtual;
function GetPointedToType: TDbgDwarfTypeIdentifier; virtual;
function GetStructTypeInfo: TDbgDwarfIdentifierStructure; virtual;
public
class function CreateTybeSubClass(AName: String; AnInformationEntry: TDwarfInformationEntry): TDbgDwarfTypeIdentifier;
@ -603,24 +602,27 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
property IsPointerType: Boolean read GetIsPointerType;
property IsStructType: Boolean read GetIsStructType;
property PointedToType: TDbgDwarfTypeIdentifier read GetPointedToType;
property StructTypeInfo: TDbgDwarfIdentifierStructure read GetStructTypeInfo;
end;
{ TDbgDwarfBaseTypeIdentifier }
{ TDbgDwarfBaseIdentifierBase }
TDbgDwarfBaseIdentifierBase = class(TDbgDwarfTypeIdentifier)
protected
function GetIsBaseType: Boolean; override;
procedure KindNeeded; override;
end;
{ TDbgDwarfTypeIdentifierModifier }
TDbgDwarfTypeIdentifierModifier = class(TDbgDwarfTypeIdentifier)
protected
procedure KindNeeded; override;
function GetIsBaseType: Boolean; override;
function GetIsPointerType: Boolean; override;
function GetPointedToType: TDbgDwarfTypeIdentifier; override;
function GetPointedToType: TDbgSymbol; override;
function GetIsStructType: Boolean; override;
function GetStructTypeInfo: TDbgDwarfIdentifierStructure; override;
end;
@ -635,8 +637,9 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
TDbgDwarfTypeIdentifierPointer = class(TDbgDwarfTypeIdentifier)
protected
procedure KindNeeded; override;
function GetIsPointerType: Boolean; override;
function GetPointedToType: TDbgDwarfTypeIdentifier; override;
function GetPointedToType: TDbgSymbol; override;
// fpc encodes classes as pointer, not ref (so Obj1 = obj2 compares the pointers)
function GetIsStructType: Boolean; override;
function GetStructTypeInfo: TDbgDwarfIdentifierStructure; override;
@ -652,12 +655,25 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
private
function GetMemberByName(AName: String): TDbgDwarfIdentifierMember;
protected
procedure KindNeeded; override;
function GetIsStructType: Boolean; override;
function GetStructTypeInfo: TDbgDwarfIdentifierStructure; override;
public
property MemberByName[AName: String]: TDbgDwarfIdentifierMember read GetMemberByName;
end;
{ TDbgDwarfIdentifierArray }
TDbgDwarfIdentifierArray = class(TDbgDwarfTypeIdentifier)
private
FDimensionInfo: array of TDwarfInformationEntry;
protected
procedure KindNeeded; override;
public
destructor Destroy; override;
function DimensionCount: Integer;
end;
{ TDbgDwarfProcSymbol }
TDbgDwarfProcSymbol = class(TDbgDwarfIdentifier)
@ -668,6 +684,7 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
FStateMachine: TDwarfLineInfoStateMachine;
function StateMachineValid: Boolean;
protected
procedure KindNeeded; override;
function GetChild(AIndex: Integer): TDbgSymbol; override;
function GetColumn: Cardinal; override;
function GetCount: Integer; override;
@ -1188,6 +1205,63 @@ begin
end;
end;
{ TDbgDwarfValueIdentifier }
procedure TDbgDwarfValueIdentifier.KindNeeded;
var
t: TDbgDwarfTypeIdentifier;
begin
t := TypeInfo;
if t = nil then
inherited KindNeeded
else
SetKind(t.Kind);
end;
{ TDbgDwarfIdentifierArray }
procedure TDbgDwarfIdentifierArray.KindNeeded;
begin
SetKind(skArray); // Todo: static/dynamic?
end;
destructor TDbgDwarfIdentifierArray.Destroy;
var
i: Integer;
begin
inherited Destroy;
for i := 0 to Length(FDimensionInfo) - 1 do
FDimensionInfo[i].ReleaseReference;
end;
function TDbgDwarfIdentifierArray.DimensionCount: Integer;
var
Info: TDwarfInformationEntry;
t: Cardinal;
begin
Result := length(FDimensionInfo);
if Result > 0 then
exit;
Info := FInformationEntry.FirstChild;
Result := 0;
if Info = nil then exit;
while Info.HasValidScope do begin
t := Info.Abbrev.tag;
if (t = DW_TAG_enumeration_type) or (t = DW_TAG_subrange_type) then begin
inc(Result);
SetLength(FDimensionInfo, Result);
FDimensionInfo[Result-1] := Info;
Info := Info.Clone;
end;
Info.GoNext;
end;
ReleaseRefAndNil(Info)
end;
{ TDbgDwarfIdentifierStructure }
function TDbgDwarfIdentifierStructure.GetMemberByName(AName: String): TDbgDwarfIdentifierMember;
@ -1225,6 +1299,14 @@ begin
end;
end;
procedure TDbgDwarfIdentifierStructure.KindNeeded;
begin
if (FInformationEntry.Abbrev.tag = DW_TAG_class_type) then
SetKind(skClass)
else
SetKind(skRecord);
end;
function TDbgDwarfIdentifierStructure.GetIsStructType: Boolean;
begin
Result := True;
@ -1237,6 +1319,17 @@ end;
{ TDbgDwarfTypeIdentifierModifier }
procedure TDbgDwarfTypeIdentifierModifier.KindNeeded;
var
t: TDbgDwarfTypeIdentifier;
begin
t := TypeInfo;
if t = nil then
inherited KindNeeded
else
SetKind(t.Kind);
end;
function TDbgDwarfTypeIdentifierModifier.GetIsBaseType: Boolean;
var
ti: TDbgDwarfTypeIdentifier;
@ -1257,7 +1350,7 @@ begin
else Result := False;
end;
function TDbgDwarfTypeIdentifierModifier.GetPointedToType: TDbgDwarfTypeIdentifier;
function TDbgDwarfTypeIdentifierModifier.GetPointedToType: TDbgSymbol;
begin
Result := TypeInfo;
if Result <> nil then
@ -1285,12 +1378,26 @@ end;
{ TDbgDwarfTypeIdentifierPointer }
procedure TDbgDwarfTypeIdentifierPointer.KindNeeded;
var
ti: TDbgDwarfTypeIdentifier;
begin
ti := TypeInfo;
// fpc encodes classes as pointer, not ref (so Obj1 = obj2 compares the pointers)
if (ti <> nil) and (ti is TDbgDwarfIdentifierStructure) and
(ti.InformationEntry.Abbrev.tag = DW_TAG_class_type)
then
SetKind(skClass)
else
SetKind(skPointer);
end;
function TDbgDwarfTypeIdentifierPointer.GetIsPointerType: Boolean;
begin
Result := True;
end;
function TDbgDwarfTypeIdentifierPointer.GetPointedToType: TDbgDwarfTypeIdentifier;
function TDbgDwarfTypeIdentifierPointer.GetPointedToType: TDbgSymbol;
begin
Result := TypeInfo;
end;
@ -1302,8 +1409,8 @@ begin
Result := False;
ti := TypeInfo;
// fpc encodes classes as pointer, not ref (so Obj1 = obj2 compares the pointers)
if (ti <> nil) and (ti is TDbgDwarfIdentifierStructure) and
(ti.InformationEntry.Abbrev.tag = DW_TAG_class_type)
if (ti <> nil) and (ti is TDbgDwarfIdentifierStructure)
//and (ti.InformationEntry.Abbrev.tag = DW_TAG_class_type)
then
Result := True;
end;
@ -1315,8 +1422,8 @@ begin
Result := nil;
ti := TypeInfo;
// fpc encodes classes as pointer, not ref (so Obj1 = obj2 compares the pointers)
if (ti <> nil) and (ti is TDbgDwarfIdentifierStructure) and
(ti.InformationEntry.Abbrev.tag = DW_TAG_class_type)
if (ti <> nil) and (ti is TDbgDwarfIdentifierStructure)
//and (ti.InformationEntry.Abbrev.tag = DW_TAG_class_type)
then
Result := TDbgDwarfIdentifierStructure(ti);
end;
@ -1328,13 +1435,39 @@ begin
Result := True;
end;
{ TDbgDwarfTypeIdentifier }
function TDbgDwarfTypeIdentifier.GetPointedToType: TDbgDwarfTypeIdentifier;
procedure TDbgDwarfBaseIdentifierBase.KindNeeded;
var
Encoding, ByteSize: Integer;
begin
Result := nil;
if not FInformationEntry.ReadValue(DW_AT_encoding, Encoding) then begin
DebugLn(['Failed reading Encoding']);
inherited KindNeeded;
exit;
end;
if FInformationEntry.ReadValue(DW_AT_byte_size, ByteSize) then
//SetSize(ByteSize);
;
case Encoding of
DW_ATE_address : SetKind(skPointer);
DW_ATE_boolean: SetKind(skBoolean);
//DW_ATE_complex_float:
DW_ATE_float: SetKind(skFloat);
DW_ATE_signed: SetKind(skInteger);
DW_ATE_signed_char: SetKind(skChar);
DW_ATE_unsigned: SetKind(skCardinal);
DW_ATE_unsigned_char: SetKind(skChar);
else
begin
DebugLn(['Unknown Encoding']);
inherited KindNeeded;
end;
end;
end;
{ TDbgDwarfTypeIdentifier }
function TDbgDwarfTypeIdentifier.GetStructTypeInfo: TDbgDwarfIdentifierStructure;
begin
Result := nil;
@ -1363,7 +1496,7 @@ begin
c := GetSubClass(AnInformationEntry.Abbrev.tag);
if c.InheritsFrom(TDbgDwarfTypeIdentifier) then
Result := TDbgDwarfTypeIdentifierClass(c).Create(AName, AnInformationEntry, skNone, 0)
Result := TDbgDwarfTypeIdentifierClass(c).Create(AName, AnInformationEntry)
else
Result := nil;
end;
@ -1543,6 +1676,28 @@ begin
end;
end;
function TDwarfInformationEntry.FirstChild: TDwarfInformationEntry;
var
Scope: TDwarfScopeInfo;
begin
Result := nil;
if (not FScope.IsValid) and (FInformationEntry <> nil) then
if not SearchScope then
exit;
Scope := FScope.Child;
if Scope.IsValid then
Result := TDwarfInformationEntry.Create(FCompUnit, Scope);
end;
function TDwarfInformationEntry.Clone: TDwarfInformationEntry;
begin
if FScope.IsValid then
Result := TDwarfInformationEntry.Create(FCompUnit, FScope)
else
Result := TDwarfInformationEntry.Create(FCompUnit, FInformationEntry);
end;
function TDwarfInformationEntry.HasAttrib(AnAttrib: Cardinal): boolean;
var
i: Integer;
@ -1685,16 +1840,6 @@ end;
{ TDbgDwarfIdentifier }
function TDbgDwarfIdentifier.GetIdentifierName: String;
begin
Result := FIdentifierName;
if (Result <> '') or (didtNameRead in FFlags) then
exit;
include(FFlags, didtNameRead);
FInformationEntry.ReadValue(DW_AT_name, FIdentifierName);
Result := FIdentifierName;
end;
function TDbgDwarfIdentifier.GetTypeInfo: TDbgDwarfTypeIdentifier;
var
FwdInfoPtr: Pointer;
@ -1717,6 +1862,14 @@ begin
end;
end;
procedure TDbgDwarfIdentifier.NameNeeded;
var
AName: String;
begin
FInformationEntry.ReadValue(DW_AT_name, AName);
SetName(AName);
end;
class function TDbgDwarfIdentifier.GetSubClass(ATag: Cardinal): TDbgDwarfIdentifierClass;
begin
case ATag of
@ -1730,13 +1883,14 @@ begin
DW_TAG_const_type,
DW_TAG_volatile_type: Result := TDbgDwarfTypeIdentifierModifier;
DW_TAG_reference_type,
DW_TAG_string_type, DW_TAG_array_type,
DW_TAG_string_type,
DW_TAG_enumeration_type, DW_TAG_subroutine_type,
DW_TAG_union_type, DW_TAG_ptr_to_member_type,
DW_TAG_set_type, DW_TAG_subrange_type, DW_TAG_file_type,
DW_TAG_thrown_type: Result := TDbgDwarfTypeIdentifier;
DW_TAG_structure_type,
DW_TAG_class_type: Result := TDbgDwarfIdentifierStructure;
DW_TAG_array_type: Result := TDbgDwarfIdentifierArray;
else
Result := TDbgDwarfIdentifier;
@ -1746,22 +1900,22 @@ end;
class function TDbgDwarfIdentifier.CreateSubClass(AName: String;
AnInformationEntry: TDwarfInformationEntry): TDbgDwarfIdentifier;
begin
Result := GetSubClass(AnInformationEntry.Abbrev.tag).Create(AName, AnInformationEntry, skNone, 0);
Result := GetSubClass(AnInformationEntry.Abbrev.tag).Create(AName, AnInformationEntry);
end;
constructor TDbgDwarfIdentifier.Create(AName: String;
AnInformationEntry: TDwarfInformationEntry);
begin
Create(AName, AnInformationEntry, skNone, 0);
FCU := AnInformationEntry.CompUnit;
FInformationEntry := AnInformationEntry;
FInformationEntry.AddReference;
inherited Create(AName);
end;
constructor TDbgDwarfIdentifier.Create(AName: String;
AnInformationEntry: TDwarfInformationEntry; AKind: TDbgSymbolKind; AAddress: TDbgPtr);
begin
if AName = '' then
AnInformationEntry.ReadValue(DW_AT_name, AName);
FIdentifierName := AName;
FCU := AnInformationEntry.CompUnit;
FInformationEntry := AnInformationEntry;
FInformationEntry.AddReference;
@ -2469,7 +2623,7 @@ begin
if not Result then exit;
l := FScopeList^.List[FIndex].Link;
assert(l <= FScopeList^.HighestKnown);
Result := (l >= 0) and (l < FIndex);
Result := (l >= 0);
end;
function TDwarfScopeInfo.HasNext: Boolean;
@ -2669,6 +2823,14 @@ begin
SM2.Free;
end;
procedure TDbgDwarfProcSymbol.KindNeeded;
begin
if TypeInfo <> nil then
SetKind(skFunction)
else
SetKind(skProcedure);
end;
{ TDbgDwarf }
constructor TDbgDwarf.Create(ALoader: TDbgImageLoader);
@ -3202,6 +3364,9 @@ var
begin
if FAddressMapBuild then Exit;
// scan to end
LocateEntry(0, FScope, [lefContinuable, lefSearchChild], ResultScope, AttribList);
Scope := FScope;
while Scope.IsValid do
begin

View File

@ -144,20 +144,20 @@ begin
FFileHandle := AFileHandle;
if FFileHandle = INVALID_HANDLE_VALUE
then begin
WriteLN('Invalid file handle');
raise Exception.Create('Invalid file handle');
end;
FMapHandle := CreateFileMapping(FFileHandle, nil, PAGE_READONLY{ or SEC_IMAGE}, 0, 0, nil);
if FMapHandle = 0
then begin
WriteLn('Could not create module mapping');
raise Exception.Create('Could not create module mapping');
Exit;
end;
FModulePtr := MapViewOfFile(FMapHandle, FILE_MAP_READ, 0, 0, 0);
if FModulePtr = nil
then begin
WriteLn('Could not map view');
raise Exception.Create('Could not map view');
Exit;
end;

View File

@ -33,7 +33,7 @@ interface
uses
Classes, SysUtils,
FpImgReaderBase,
FpImgReaderElfTypes; // these files are part of
FpImgReaderElfTypes, LCLProc; // these files are part of
type
@ -231,7 +231,7 @@ begin
New(p);
P^.Offs := fs.FileOfs;
p^.Sect.Size := fs.Size;
p^.Sect.VirtualAdress := 0; // Todo?
p^.Sect.VirtualAdress := 0; // Todo? fs.Address - ImageBase
p^.Loaded := False;
FSections.Objects[idx] := TObject(p);
end;

View File

@ -65,8 +65,7 @@ type
FTextExpression: String;
FExpressionPart: TFpPascalExpressionPart;
FValid: Boolean;
FResultType: TFpPasExprType;
function GetResultType: TFpPasExprType;
function GetResultType: TDbgSymbol;
procedure Parse;
procedure SetError(AMsg: String);
function PosFromPChar(APChar: PChar): Integer;
@ -79,7 +78,7 @@ type
function DebugDump: String;
property Error: String read FError;
property Valid: Boolean read FValid;
property ResultType: TFpPasExprType read GetResultType;
property ResultType: TDbgSymbol read GetResultType;
end;
@ -91,9 +90,9 @@ type
FParent: TFpPascalExpressionPartContainer;
FStartChar: PChar;
FExpression: TFpPascalExpression;
FResultType: TFpPasExprType;
FResultType: TDbgSymbol;
function GetResultType: TDbgSymbol;
function GetSurroundingBracket: TFpPascalExpressionPartBracket;
function GetResultType: TFpPasExprType;
function GetTopParent: TFpPascalExpressionPart;
procedure SetEndChar(AValue: PChar);
procedure SetParent(AValue: TFpPascalExpressionPartContainer);
@ -105,8 +104,7 @@ type
function DebugDump(AIndent: String): String; virtual;
protected
procedure Init; virtual;
procedure DoGetResultType(var AResultType: TFpPasExprType); virtual;
procedure InitResultTypeFromDbgInfo(var AResultType: TFpPasExprType; ADbgInfo: TDbgSymbol);
function DoGetResultType: TDbgSymbol; virtual;
Procedure ReplaceInParent(AReplacement: TFpPascalExpressionPart);
procedure DoHandleEndOfExpression; virtual;
@ -132,7 +130,7 @@ type
property Parent: TFpPascalExpressionPartContainer read FParent write SetParent;
property TopParent: TFpPascalExpressionPart read GetTopParent; // or self
property SurroundingBracket: TFpPascalExpressionPartBracket read GetSurroundingBracket; // incl self
property ResultType: TFpPasExprType read GetResultType;
property ResultType: TDbgSymbol read GetResultType;
end;
{ TFpPascalExpressionPartContainer }
@ -164,7 +162,7 @@ type
private
FDbgType: TDbgSymbol; // may be a variable or function or a type ...
protected
procedure DoGetResultType(var AResultType: TFpPasExprType); override;
function DoGetResultType: TDbgSymbol; override;
public
destructor Destroy; override;
end;
@ -210,7 +208,7 @@ type
TFpPascalExpressionPartBracketSubExpression = class(TFpPascalExpressionPartRoundBracket)
protected
function HandleNextPartInBracket(APart: TFpPascalExpressionPart): TFpPascalExpressionPart; override;
procedure DoGetResultType(var AResultType: TFpPasExprType); override;
function DoGetResultType: TDbgSymbol; override;
end;
{ TFpPascalExpressionPartBracketArgumentList }
@ -290,7 +288,7 @@ type
TFpPascalExpressionPartOperatorAddressOf = class(TFpPascalExpressionPartUnaryOperator) // @
protected
procedure Init; override;
procedure DoGetResultType(var AResultType: TFpPasExprType); override;
function DoGetResultType: TDbgSymbol; override;
end;
{ TFpPascalExpressionPartOperatorMakeRef }
@ -299,7 +297,7 @@ type
protected
procedure Init; override;
function IsValidNextPart(APart: TFpPascalExpressionPart): Boolean; override;
procedure DoGetResultType(var AResultType: TFpPasExprType); override;
//function DoGetResultType: TDbgSymbol; override;
end;
{ TFpPascalExpressionPartOperatorDeRef }
@ -307,7 +305,7 @@ type
TFpPascalExpressionPartOperatorDeRef = class(TFpPascalExpressionPartUnaryOperator) // ptrval^
protected
procedure Init; override;
procedure DoGetResultType(var AResultType: TFpPasExprType); override;
function DoGetResultType: TDbgSymbol; override;
function MaybeHandlePrevPart(APrevPart: TFpPascalExpressionPart;
var AResult: TFpPascalExpressionPart): Boolean; override;
function FindLeftSideOperandByPrecedence(AnOperator: TFpPascalExpressionPartWithPrecedence):
@ -346,7 +344,7 @@ type
protected
procedure Init; override;
function IsValidNextPart(APart: TFpPascalExpressionPart): Boolean; override;
procedure DoGetResultType(var AResultType: TFpPasExprType); override;
function DoGetResultType: TDbgSymbol; override;
end;
implementation
@ -363,6 +361,35 @@ const
PRECEDENCE_MUL_DIV = 10; // a * b
PRECEDENCE_PLUS_MINUS = 11; // a + b
type
{ TPasParserSymbolPointer }
TPasParserSymbolPointer = class(TDbgSymbol)
private
FPointedTo: TDbgSymbol;
protected
// NameNeeded // "^TPointedTo"
function GetPointedToType: TDbgSymbol; override;
public
constructor Create(const APointedTo: TDbgSymbol);
end;
{ TPasParserSymbolPointer }
function TPasParserSymbolPointer.GetPointedToType: TDbgSymbol;
begin
Result := FPointedTo;
end;
constructor TPasParserSymbolPointer.Create(const APointedTo: TDbgSymbol);
begin
FPointedTo := APointedTo;
inherited Create('');
SetKind(skPointer);
end;
{ TFpPascalExpressionPartBracketIndex }
procedure TFpPascalExpressionPartBracketIndex.Init;
@ -529,22 +556,32 @@ begin
Add(APart);
end;
procedure TFpPascalExpressionPartBracketSubExpression.DoGetResultType(var AResultType: TFpPasExprType);
function TFpPascalExpressionPartBracketSubExpression.DoGetResultType: TDbgSymbol;
begin
if Count <> 1 then
AResultType.Kind := ptkInvalid
Result := nil
else
AResultType := Items[0].ResultType;
if AResultType.DbgType <> nil then
AResultType.DbgType.AddReference;
Result := Items[0].ResultType;
if Result <> nil then
Result.AddReference;
end;
{ TFpPascalExpressionPartIdentifer }
procedure TFpPascalExpressionPartIdentifer.DoGetResultType(var AResultType: TFpPasExprType);
function TFpPascalExpressionPartIdentifer.DoGetResultType: TDbgSymbol;
begin
FDbgType := FExpression.GetDbgTyeForIdentifier(GetText);
InitResultTypeFromDbgInfo(AResultType, FDbgType);
if FDbgType = nil then
FDbgType := FExpression.GetDbgTyeForIdentifier(GetText);
if FDbgType = nil then
exit;
if FDbgType is TDbgDwarfValueIdentifier then
Result := TDbgDwarfValueIdentifier(FDbgType).TypeInfo
else
Result := nil; // Todo handled by typecast operator // maybe wrap in TTypeOf class?
if Result <> nil then
Result.AddReference;
end;
destructor TFpPascalExpressionPartIdentifer.Destroy;
@ -708,13 +745,12 @@ begin
FExpressionPart := CurPart;
end;
function TFpPascalExpression.GetResultType: TFpPasExprType;
function TFpPascalExpression.GetResultType: TDbgSymbol;
begin
if (FExpressionPart = nil) or (not Valid) then
FResultType.Kind := ptkInvalid;
if FResultType.Kind = ptkUnknown then
FResultType := FExpressionPart.GetResultType;
Result := FResultType;
Result := nil
else
Result := FExpressionPart.ResultType;
end;
procedure TFpPascalExpression.SetError(AMsg: String);
@ -737,7 +773,6 @@ constructor TFpPascalExpression.Create(ATextExpression: String);
begin
FTextExpression := ATextExpression;
FValid := True;
FResultType.Kind := ptkUnknown;
Parse;
end;
@ -783,10 +818,11 @@ begin
Result := TFpPascalExpressionPartBracket(tmp);
end;
function TFpPascalExpressionPart.GetResultType: TFpPasExprType;
function TFpPascalExpressionPart.GetResultType: TDbgSymbol;
begin
if FResultType.Kind = ptkUnknown then
DoGetResultType(FResultType);
// TODO: flag, so nil=invalid will be cached
if FResultType = nil then
FResultType := DoGetResultType;
Result := FResultType;
end;
@ -836,35 +872,9 @@ begin
//
end;
procedure TFpPascalExpressionPart.DoGetResultType(var AResultType: TFpPasExprType);
function TFpPascalExpressionPart.DoGetResultType: TDbgSymbol;
begin
FResultType.Kind := ptkInvalid;
end;
procedure TFpPascalExpressionPart.InitResultTypeFromDbgInfo(var AResultType: TFpPasExprType;
ADbgInfo: TDbgSymbol);
begin
AResultType.Kind := ptkInvalid;
if (ADbgInfo = nil) then
exit;
if (ADbgInfo is TDbgDwarfTypeIdentifier) then begin
AResultType.DbgType := TDbgDwarfTypeIdentifier(ADbgInfo);
AResultType.DbgType.AddReference;
AResultType.Kind := ptkTypeDbgType;
exit;
end;
if ADbgInfo is TDbgDwarfValueIdentifier then begin
AResultType.DbgType := TDbgDwarfValueIdentifier(ADbgInfo).TypeInfo;
AResultType.DbgType.AddReference;
if AResultType.DbgType <> nil then
AResultType.Kind := ptkValueDbgType;
exit;
end;
debugln(['TFpPascalExpressionPartIdentifer.DoGetResultType UNKNOWN: ', DbgSName(ADbgInfo)]);
Result := nil;
end;
procedure TFpPascalExpressionPart.ReplaceInParent(AReplacement: TFpPascalExpressionPart);
@ -932,14 +942,13 @@ begin
FExpression := AExpression;
FStartChar := AStartChar;
FEndChar := AnEndChar;
FResultType.Kind := ptkUnknown;
Init;
end;
destructor TFpPascalExpressionPart.Destroy;
begin
inherited Destroy;
ReleaseRefAndNil(FResultType.DbgType);
ReleaseRefAndNil(FResultType);
end;
function TFpPascalExpressionPart.HandleNextPart(APart: TFpPascalExpressionPart): TFpPascalExpressionPart;
@ -1237,18 +1246,15 @@ begin
inherited Init;
end;
procedure TFpPascalExpressionPartOperatorAddressOf.DoGetResultType(var AResultType: TFpPasExprType);
function TFpPascalExpressionPartOperatorAddressOf.DoGetResultType: TDbgSymbol;
begin
AResultType.Kind := ptkInvalid;
Result := nil;
if Count <> 1 then exit;
AResultType := Items[0].ResultType;
if AResultType.Kind = ptkValueDbgType then
AResultType.Kind := ptkPointerToValueDbgType
else
AResultType.Kind := ptkInvalid; // can not take address of...
if FResultType.DbgType <> nil then
FResultType.DbgType.AddReference;
Result := Items[0].ResultType;
if Result = nil then
exit;
Result := TPasParserSymbolPointer.Create(Result);
end;
{ TFpPascalExpressionPartOperatorMakeRef }
@ -1265,20 +1271,6 @@ begin
(APart is TFpPascalExpressionPartIdentifer);
end;
procedure TFpPascalExpressionPartOperatorMakeRef.DoGetResultType(var AResultType: TFpPasExprType);
begin
AResultType.Kind := ptkInvalid;
if Count <> 1 then exit;
AResultType := Items[0].ResultType;
if AResultType.Kind = ptkTypeDbgType then
AResultType.Kind := ptkPointerOfTypeDbgType
else
AResultType.Kind := ptkInvalid; // can not take address of...
if FResultType.DbgType <> nil then
FResultType.DbgType.AddReference;
end;
{ TFpPascalExpressionPartOperatorDeRef }
procedure TFpPascalExpressionPartOperatorDeRef.Init;
@ -1287,28 +1279,23 @@ begin
inherited Init;
end;
procedure TFpPascalExpressionPartOperatorDeRef.DoGetResultType(var AResultType: TFpPasExprType);
function TFpPascalExpressionPartOperatorDeRef.DoGetResultType: TDbgSymbol;
begin
AResultType.Kind := ptkInvalid;
Result := nil;
if Count <> 1 then exit;
AResultType := Items[0].ResultType;
case AResultType.Kind of
ptkValueDbgType: begin
AResultType.Kind := ptkInvalid;
if AResultType.DbgType.IsPointerType then begin
AResultType.DbgType := AResultType.DbgType.PointedToType;
if AResultType.DbgType <> nil then
AResultType.Kind := ptkPointerToValueDbgType;
end;
end;
ptkPointerToValueDbgType: AResultType.Kind := ptkValueDbgType;
else
AResultType.Kind := ptkInvalid;
end;
Result := Items[0].ResultType;
if Result = nil then
exit;;
if FResultType.DbgType <> nil then
FResultType.DbgType.AddReference;
if Result.Kind = skPointer then
Result := Result.PointedToType
//if Result.Kind = skArray then // dynarray
else
Result := nil;
if Result <> nil then
Result.AddReference;
end;
function TFpPascalExpressionPartOperatorDeRef.MaybeHandlePrevPart(APrevPart: TFpPascalExpressionPart;
@ -1371,22 +1358,27 @@ begin
Result := Result and (APart is TFpPascalExpressionPartIdentifer);
end;
procedure TFpPascalExpressionPartOperatorMemberOf.DoGetResultType(var AResultType: TFpPasExprType);
function TFpPascalExpressionPartOperatorMemberOf.DoGetResultType: TDbgSymbol;
var
tmp: TFpPasExprType;
struct: TDbgDwarfIdentifierStructure;
member: TDbgDwarfIdentifierMember;
tmp: TDbgSymbol;
begin
AResultType.Kind := ptkInvalid;
Result := nil;
if Count <> 2 then exit;
tmp := Items[0].ResultType;
// Todo unit
if (tmp.Kind = ptkValueDbgType) and (tmp.DbgType.IsStructType) then begin
struct := tmp.DbgType.StructTypeInfo;
member := struct.MemberByName[Items[1].GetText];
InitResultTypeFromDbgInfo(AResultType, member);
ReleaseRefAndNil(member);
if (tmp <> nil) and (tmp is TDbgDwarfTypeIdentifier) and
(TDbgDwarfTypeIdentifier(tmp).IsStructType)
then begin
struct := TDbgDwarfTypeIdentifier(tmp).StructTypeInfo;
tmp := struct.MemberByName[Items[1].GetText];
if (tmp <> nil) and (tmp is TDbgDwarfValueIdentifier) then begin
Result := TDbgDwarfValueIdentifier(tmp).TypeInfo;
Result.AddReference;
end;
ReleaseRefAndNil(tmp);
end;
end;

View File

@ -161,7 +161,7 @@ const
end;
end;
procedure AddType(ASourceExpr: string; ATypeIdent: TDbgDwarfTypeIdentifier; AnIsPointer: Boolean);
procedure AddType(ASourceExpr: string; ATypeIdent: TDbgSymbol);
var
TypeName: String;
IsPointerPointer: Boolean;
@ -169,20 +169,20 @@ const
begin
if (ASourceExpr = '') or (ATypeIdent = nil) then exit;
IsPointerType := ATypeIdent.IsPointerType;
if IsPointerType then begin
IsPointerType := ATypeIdent.Kind = FpDbgClasses.skPointer;
if IsPointerType and (ATypeIdent.PointedToType <> nil) then begin
ATypeIdent := ATypeIdent.PointedToType;
if ATypeIdent = nil then exit;
IsPointerPointer := AnIsPointer or ATypeIdent.IsPointerType;
while (ATypeIdent <> nil) and ATypeIdent.IsPointerType do
IsPointerPointer := ATypeIdent.Kind = FpDbgClasses.skPointer;
while (ATypeIdent.Kind = FpDbgClasses.skPointer) and (ATypeIdent.PointedToType <> nil) do
ATypeIdent := ATypeIdent.PointedToType;
if ATypeIdent = nil then exit;
end;
TypeName := ATypeIdent.IdentifierName;
TypeName := ATypeIdent.Name;
if ATypeIdent.IsBaseType then begin
if ATypeIdent.Kind in [skInteger, skCardinal, skBoolean, skChar, skFloat]
then begin
if IsPointerType then begin
MaybeAdd(gcrtPType, GdbCmdPType + ASourceExpr, Format('type = ^%s', [TypeName]));
MaybeAdd(gcrtPType, GdbCmdWhatIs + ASourceExpr, Format('type = ^%s', [TypeName]));
@ -208,7 +208,6 @@ var
Loc: TDBGPtr;
Ident: TDbgSymbol;
PasExpr: TFpGDBMIPascalExpression;
PasType: TFpPasExprType;
TypeIdent: TDbgDwarfTypeIdentifier;
begin
Result := inherited IndexOf(AThreadId, AStackFrame, ARequest);
@ -227,18 +226,9 @@ DebugLn('############### '+ARequest.Request);
IdentName := trim(copy(ARequest.Request, 8, length(ARequest.Request)));
PasExpr := TFpGDBMIPascalExpression.Create(IdentName, FDebugger, AThreadId, AStackFrame);
PasType := PasExpr.ResultType;
case PasType.Kind of
ptkValueDbgType: begin
AddType(IdentName, PasType.DbgType, False);
Result := inherited IndexOf(AThreadId, AStackFrame, ARequest);
end;
ptkPointerToValueDbgType: begin
AddType(IdentName, PasType.DbgType, True);
Result := inherited IndexOf(AThreadId, AStackFrame, ARequest);
end;
end;
AddType(IdentName, PasExpr.ResultType);
Result := inherited IndexOf(AThreadId, AStackFrame, ARequest);
finally
PasExpr.Free;