mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-24 15:59:14 +02:00
FPDebug: refactor
git-svn-id: trunk@43392 -
This commit is contained in:
parent
4cc7a3f380
commit
98508349df
@ -811,6 +811,17 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TDbgDwarfUnit }
|
||||||
|
|
||||||
|
TDbgDwarfUnit = class(TDbgDwarfIdentifier)
|
||||||
|
private
|
||||||
|
FLastChildByName: TDbgSymbol;
|
||||||
|
protected
|
||||||
|
procedure Init; override;
|
||||||
|
function GetMemberByName(AIndex: String): TDbgSymbol; override;
|
||||||
|
public
|
||||||
|
destructor Destroy; override;
|
||||||
|
end;
|
||||||
|
|
||||||
type
|
type
|
||||||
TDwarfSection = (dsAbbrev, dsARanges, dsFrame, dsInfo, dsLine, dsLoc, dsMacinfo, dsPubNames, dsPubTypes, dsRanges, dsStr);
|
TDwarfSection = (dsAbbrev, dsARanges, dsFrame, dsInfo, dsLine, dsLoc, dsMacinfo, dsPubNames, dsPubTypes, dsRanges, dsStr);
|
||||||
@ -833,6 +844,7 @@ const
|
|||||||
{ TDbgDwarf }
|
{ TDbgDwarf }
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
TDbgDwarf = class(TDbgInfo)
|
TDbgDwarf = class(TDbgInfo)
|
||||||
private
|
private
|
||||||
FCompilationUnits: TList;
|
FCompilationUnits: TList;
|
||||||
@ -842,12 +854,13 @@ type
|
|||||||
protected
|
protected
|
||||||
function GetCompilationUnitClass: TDwarfCompilationUnitClass; virtual;
|
function GetCompilationUnitClass: TDwarfCompilationUnitClass; virtual;
|
||||||
function FindCompilationUnitByOffs(AOffs: QWord): TDwarfCompilationUnit;
|
function FindCompilationUnitByOffs(AOffs: QWord): TDwarfCompilationUnit;
|
||||||
|
function FindProcSymbol(AAddress: TDbgPtr): TDbgSymbol;
|
||||||
public
|
public
|
||||||
constructor Create(ALoader: TDbgImageLoader); override;
|
constructor Create(ALoader: TDbgImageLoader); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
function FindContext(AAddress: TDbgPtr): TDbgInfoAddressContext; override;
|
||||||
function FindSymbol(AAddress: TDbgPtr): TDbgSymbol; override;
|
function FindSymbol(AAddress: TDbgPtr): TDbgSymbol; override;
|
||||||
//function FindSymbol(const AName: String): TDbgSymbol; override;
|
//function FindSymbol(const AName: String): TDbgSymbol; override;
|
||||||
function FindIdentifier(AAddress: TDbgPtr; AName: String): TDbgSymbol;
|
|
||||||
function GetLineAddress(const AFileName: String; ALine: Cardinal): TDbgPtr; override;
|
function GetLineAddress(const AFileName: String; ALine: Cardinal): TDbgPtr; override;
|
||||||
function GetLineAddressMap(const AFileName: String): PDWarfLineMap;
|
function GetLineAddressMap(const AFileName: String): PDWarfLineMap;
|
||||||
function LoadCompilationUnits: Integer;
|
function LoadCompilationUnits: Integer;
|
||||||
@ -865,6 +878,22 @@ type
|
|||||||
public
|
public
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TDbgDwarfInfoAddressContext }
|
||||||
|
|
||||||
|
TDbgDwarfInfoAddressContext = class(TDbgInfoAddressContext)
|
||||||
|
private
|
||||||
|
FSymbol: TDbgSymbol;
|
||||||
|
FAddress: TDbgPtr;
|
||||||
|
FDwarf: TDbgDwarf;
|
||||||
|
protected
|
||||||
|
function GetSymbolAtAddress: TDbgSymbol; override;
|
||||||
|
function GetAddress: TDbgPtr; override;
|
||||||
|
public
|
||||||
|
constructor Create(AnAddress: TDbgPtr; ASymbol: TDbgSymbol; ADwarf: TDbgDwarf);
|
||||||
|
destructor Destroy; override;
|
||||||
|
function FindSymbol(const AName: String): TDbgSymbol; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function DwarfTagToString(AValue: Integer): String;
|
function DwarfTagToString(AValue: Integer): String;
|
||||||
function DwarfAttributeToString(AValue: Integer): String;
|
function DwarfAttributeToString(AValue: Integer): String;
|
||||||
@ -1331,6 +1360,119 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TDbgDwarfInfoAddressContext }
|
||||||
|
|
||||||
|
function TDbgDwarfInfoAddressContext.GetSymbolAtAddress: TDbgSymbol;
|
||||||
|
begin
|
||||||
|
Result := FSymbol;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDbgDwarfInfoAddressContext.GetAddress: TDbgPtr;
|
||||||
|
begin
|
||||||
|
Result := FAddress;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TDbgDwarfInfoAddressContext.Create(AnAddress: TDbgPtr; ASymbol: TDbgSymbol;
|
||||||
|
ADwarf: TDbgDwarf);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
AddReference;
|
||||||
|
FAddress := AnAddress;
|
||||||
|
FDwarf := ADwarf;
|
||||||
|
FSymbol := ASymbol;
|
||||||
|
FSymbol.AddReference;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TDbgDwarfInfoAddressContext.Destroy;
|
||||||
|
begin
|
||||||
|
FSymbol.ReleaseReference;
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDbgDwarfInfoAddressContext.FindSymbol(const AName: String): TDbgSymbol;
|
||||||
|
var
|
||||||
|
SubRoutine: TDbgDwarfProcSymbol; // TDbgSymbol;
|
||||||
|
CU: TDwarfCompilationUnit;
|
||||||
|
//Scope,
|
||||||
|
StartScopeIdx: Integer;
|
||||||
|
InfoEntry: TDwarfInformationEntry;
|
||||||
|
s, InfoName: String;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
if (FSymbol = nil) or not(FSymbol is TDbgDwarfProcSymbol) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
SubRoutine := TDbgDwarfProcSymbol(FSymbol);
|
||||||
|
s := UpperCase(AName);
|
||||||
|
|
||||||
|
try
|
||||||
|
CU := SubRoutine.FCU;
|
||||||
|
InfoEntry := SubRoutine.InformationEntry.Clone;
|
||||||
|
//InfoEntry := TDwarfInformationEntry.Create(CU, nil);
|
||||||
|
//InfoEntry.ScopeIndex := SubRoutine.FAddressInfo^.ScopeIndex;
|
||||||
|
|
||||||
|
while InfoEntry.HasValidScope do begin
|
||||||
|
debugln(FPDBG_DWARF_SEARCH, ['TDbgDwarf.FindIdentifier Searching ', dbgs(InfoEntry.FScope, CU)]);
|
||||||
|
StartScopeIdx := InfoEntry.ScopeIndex;
|
||||||
|
|
||||||
|
if InfoEntry.ReadValue(DW_AT_name, InfoName) then begin
|
||||||
|
if UpperCase(InfoName) = s then begin
|
||||||
|
Result := TDbgDwarfIdentifier.CreateSubClass(AName, InfoEntry);
|
||||||
|
DebugLn(FPDBG_DWARF_SEARCH, ['TDbgDwarf.FindIdentifier found ', dbgs(InfoEntry.FScope, CU), DbgSName(Result)]);
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if InfoEntry.GoNamedChildEx(AName) then begin
|
||||||
|
Result := TDbgDwarfIdentifier.CreateSubClass(AName, InfoEntry);
|
||||||
|
DebugLn(FPDBG_DWARF_SEARCH, ['TDbgDwarf.FindIdentifier found ', dbgs(InfoEntry.FScope, CU), DbgSName(Result)]);
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Search parent(s)
|
||||||
|
InfoEntry.ScopeIndex := StartScopeIdx;
|
||||||
|
InfoEntry.GoParent;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// other units
|
||||||
|
|
||||||
|
finally
|
||||||
|
ReleaseRefAndNil(InfoEntry);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TDbgDwarfUnit }
|
||||||
|
|
||||||
|
procedure TDbgDwarfUnit.Init;
|
||||||
|
begin
|
||||||
|
inherited Init;
|
||||||
|
SetSymbolType(stNone);
|
||||||
|
SetKind(skUnit);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDbgDwarfUnit.GetMemberByName(AIndex: String): TDbgSymbol;
|
||||||
|
var
|
||||||
|
Ident: TDwarfInformationEntry;
|
||||||
|
ti: TDbgSymbol;
|
||||||
|
begin
|
||||||
|
// Todo, param to only search external.
|
||||||
|
ReleaseRefAndNil(FLastChildByName);
|
||||||
|
Result := nil;
|
||||||
|
|
||||||
|
Ident := FInformationEntry.Clone;
|
||||||
|
Ident.GoNamedChildEx(AIndex);
|
||||||
|
if Ident <> nil then
|
||||||
|
Result := TDbgDwarfIdentifier.CreateSubClass('', Ident);
|
||||||
|
ReleaseRefAndNil(Ident);
|
||||||
|
FLastChildByName := Result;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TDbgDwarfUnit.Destroy;
|
||||||
|
begin
|
||||||
|
ReleaseRefAndNil(FLastChildByName);
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TDbgDwarfIdentifierSubRange }
|
{ TDbgDwarfIdentifierSubRange }
|
||||||
|
|
||||||
procedure TDbgDwarfIdentifierSubRange.ReadBounds;
|
procedure TDbgDwarfIdentifierSubRange.ReadBounds;
|
||||||
@ -2577,6 +2719,8 @@ begin
|
|||||||
// Value types
|
// Value types
|
||||||
DW_TAG_member: Result := TDbgDwarfIdentifierMember;
|
DW_TAG_member: Result := TDbgDwarfIdentifierMember;
|
||||||
DW_TAG_subprogram: Result := TDbgDwarfProcSymbol;
|
DW_TAG_subprogram: Result := TDbgDwarfProcSymbol;
|
||||||
|
//
|
||||||
|
DW_TAG_compile_unit: Result := TDbgDwarfUnit;
|
||||||
|
|
||||||
else
|
else
|
||||||
Result := TDbgDwarfIdentifier;
|
Result := TDbgDwarfIdentifier;
|
||||||
@ -3571,110 +3715,22 @@ begin
|
|||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDbgDwarf.FindSymbol(AAddress: TDbgPtr): TDbgSymbol;
|
function TDbgDwarf.FindContext(AAddress: TDbgPtr): TDbgInfoAddressContext;
|
||||||
var
|
var
|
||||||
n: Integer;
|
Proc: TDbgSymbol;
|
||||||
CU: TDwarfCompilationUnit;
|
|
||||||
Iter: TMapIterator;
|
|
||||||
Info: PDwarfAddressInfo;
|
|
||||||
MinMaxSet: boolean;
|
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
for n := 0 to FCompilationUnits.Count - 1 do
|
Proc := FindProcSymbol(AAddress);
|
||||||
begin
|
if Proc = nil then
|
||||||
CU := TDwarfCompilationUnit(FCompilationUnits[n]);
|
|
||||||
if not CU.Valid then Continue;
|
|
||||||
MinMaxSet := CU.FMinPC <> CU.FMaxPC;
|
|
||||||
if MinMaxSet and ((AAddress < CU.FMinPC) or (AAddress > CU.FMaxPC))
|
|
||||||
then Continue;
|
|
||||||
|
|
||||||
CU.BuildAddressMap;
|
|
||||||
|
|
||||||
Iter := TMapIterator.Create(CU.FAddressMap);
|
|
||||||
try
|
|
||||||
if Iter.EOM
|
|
||||||
then begin
|
|
||||||
if MinMaxSet
|
|
||||||
then Exit // minmaxset and no procs defined ???
|
|
||||||
else Continue;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if not Iter.Locate(AAddress)
|
|
||||||
then begin
|
|
||||||
if not Iter.BOM
|
|
||||||
then Iter.Previous;
|
|
||||||
|
|
||||||
if Iter.BOM
|
|
||||||
then begin
|
|
||||||
if MinMaxSet
|
|
||||||
then Exit // minmaxset and no proc @ minpc ???
|
|
||||||
else Continue;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// iter is at the closest defined adress before AAddress
|
|
||||||
Info := Iter.DataPtr;
|
|
||||||
if AAddress > Info^.EndPC
|
|
||||||
then begin
|
|
||||||
if MinMaxSet
|
|
||||||
then Exit // minmaxset and no proc @ maxpc ???
|
|
||||||
else Continue;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Result := TDbgDwarfProcSymbol.Create(CU, Iter.DataPtr, AAddress);
|
|
||||||
finally
|
|
||||||
Iter.Free;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TDbgDwarf.FindIdentifier(AAddress: TDbgPtr; AName: String): TDbgSymbol;
|
|
||||||
var
|
|
||||||
SubRoutine: TDbgDwarfProcSymbol; // TDbgSymbol;
|
|
||||||
CU: TDwarfCompilationUnit;
|
|
||||||
//Scope,
|
|
||||||
StartScopeIdx: Integer;
|
|
||||||
InfoEntry: TDwarfInformationEntry;
|
|
||||||
begin
|
|
||||||
Result := nil;
|
|
||||||
SubRoutine := TDbgDwarfProcSymbol(FindSymbol(AAddress));
|
|
||||||
if SubRoutine = nil then
|
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
try
|
Result := TDbgDwarfInfoAddressContext.Create(AAddress, Proc, Self);
|
||||||
CU := SubRoutine.FCU;
|
Proc.ReleaseReference;
|
||||||
InfoEntry := TDwarfInformationEntry.Create(CU, nil);
|
end;
|
||||||
InfoEntry.ScopeIndex := SubRoutine.FAddressInfo^.ScopeIndex;
|
|
||||||
|
|
||||||
while InfoEntry.HasValidScope do begin
|
function TDbgDwarf.FindSymbol(AAddress: TDbgPtr): TDbgSymbol;
|
||||||
debugln(FPDBG_DWARF_SEARCH, ['TDbgDwarf.FindIdentifier Searching ', dbgs(InfoEntry.FScope, CU)]);
|
begin
|
||||||
StartScopeIdx := InfoEntry.ScopeIndex;
|
Result := FindProcSymbol(AAddress);
|
||||||
|
|
||||||
if InfoEntry.GoNamedChildEx(AName) then begin
|
|
||||||
Result := TDbgDwarfIdentifier.CreateSubClass(AName, InfoEntry);
|
|
||||||
DebugLn(FPDBG_DWARF_SEARCH, ['TDbgDwarf.FindIdentifier found ', dbgs(InfoEntry.FScope, CU), DbgSName(Result)]);
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Search parent(s)
|
|
||||||
InfoEntry.ScopeIndex := StartScopeIdx;
|
|
||||||
InfoEntry.GoParent;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// unitname?
|
|
||||||
|
|
||||||
//// debugln:
|
|
||||||
// if Result <> nil then begin
|
|
||||||
// TDbgDwarfIdentifier(Result).TypeInfo; // debugln...
|
|
||||||
// if TDbgDwarfIdentifier(Result).TypeInfo <> nil then TDbgDwarfIdentifier(Result).TypeInfo.TypeInfo;
|
|
||||||
// end;
|
|
||||||
//// end debugln
|
|
||||||
|
|
||||||
|
|
||||||
finally
|
|
||||||
ReleaseRefAndNil(SubRoutine);
|
|
||||||
ReleaseRefAndNil(InfoEntry);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDbgDwarf.GetCompilationUnit(AIndex: Integer): TDwarfCompilationUnit;
|
function TDbgDwarf.GetCompilationUnit(AIndex: Integer): TDwarfCompilationUnit;
|
||||||
@ -3708,6 +3764,63 @@ begin
|
|||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TDbgDwarf.FindProcSymbol(AAddress: TDbgPtr): TDbgSymbol;
|
||||||
|
var
|
||||||
|
n: Integer;
|
||||||
|
CU: TDwarfCompilationUnit;
|
||||||
|
Iter: TMapIterator;
|
||||||
|
Info: PDwarfAddressInfo;
|
||||||
|
MinMaxSet: boolean;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
for n := 0 to FCompilationUnits.Count - 1 do
|
||||||
|
begin
|
||||||
|
CU := TDwarfCompilationUnit(FCompilationUnits[n]);
|
||||||
|
if not CU.Valid then Continue;
|
||||||
|
MinMaxSet := CU.FMinPC <> CU.FMaxPC;
|
||||||
|
if MinMaxSet and ((AAddress < CU.FMinPC) or (AAddress > CU.FMaxPC))
|
||||||
|
then Continue;
|
||||||
|
|
||||||
|
CU.BuildAddressMap;
|
||||||
|
|
||||||
|
Iter := TMapIterator.Create(CU.FAddressMap);
|
||||||
|
try
|
||||||
|
if Iter.EOM
|
||||||
|
then begin
|
||||||
|
if MinMaxSet
|
||||||
|
then Exit // minmaxset and no procs defined ???
|
||||||
|
else Continue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not Iter.Locate(AAddress)
|
||||||
|
then begin
|
||||||
|
if not Iter.BOM
|
||||||
|
then Iter.Previous;
|
||||||
|
|
||||||
|
if Iter.BOM
|
||||||
|
then begin
|
||||||
|
if MinMaxSet
|
||||||
|
then Exit // minmaxset and no proc @ minpc ???
|
||||||
|
else Continue;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// iter is at the closest defined adress before AAddress
|
||||||
|
Info := Iter.DataPtr;
|
||||||
|
if AAddress > Info^.EndPC
|
||||||
|
then begin
|
||||||
|
if MinMaxSet
|
||||||
|
then Exit // minmaxset and no proc @ maxpc ???
|
||||||
|
else Continue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := TDbgDwarfProcSymbol.Create(CU, Iter.DataPtr, AAddress);
|
||||||
|
finally
|
||||||
|
Iter.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TDbgDwarf.GetLineAddress(const AFileName: String; ALine: Cardinal): TDbgPtr;
|
function TDbgDwarf.GetLineAddress(const AFileName: String; ALine: Cardinal): TDbgPtr;
|
||||||
var
|
var
|
||||||
n: Integer;
|
n: Integer;
|
||||||
|
@ -209,6 +209,19 @@ type
|
|||||||
function GetMemberCount: Integer; override;
|
function GetMemberCount: Integer; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TDbgInfoAddressContext }
|
||||||
|
|
||||||
|
TDbgInfoAddressContext = class(TRefCountedObject)
|
||||||
|
protected
|
||||||
|
function GetAddress: TDbgPtr; virtual; abstract;
|
||||||
|
function GetSymbolAtAddress: TDbgSymbol; virtual;
|
||||||
|
public
|
||||||
|
property Address: TDbgPtr read GetAddress;
|
||||||
|
property SymbolAtAddress: TDbgSymbol read GetSymbolAtAddress;
|
||||||
|
// search this, and all parent context
|
||||||
|
function FindSymbol(const AName: String): TDbgSymbol; virtual;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TDbgInfo }
|
{ TDbgInfo }
|
||||||
|
|
||||||
TDbgInfo = class(TObject)
|
TDbgInfo = class(TObject)
|
||||||
@ -218,8 +231,9 @@ type
|
|||||||
procedure SetHasInfo;
|
procedure SetHasInfo;
|
||||||
public
|
public
|
||||||
constructor Create({%H-}ALoader: TDbgImageLoader); virtual;
|
constructor Create({%H-}ALoader: TDbgImageLoader); virtual;
|
||||||
function FindSymbol(const {%H-}AName: String): TDbgSymbol; virtual;
|
function FindContext({%H-}AAddress: TDbgPtr): TDbgInfoAddressContext; virtual;
|
||||||
function FindSymbol({%H-}AAddress: TDbgPtr): TDbgSymbol; virtual;
|
function FindSymbol(const {%H-}AName: String): TDbgSymbol; virtual; deprecated;
|
||||||
|
function FindSymbol({%H-}AAddress: TDbgPtr): TDbgSymbol; virtual; deprecated;
|
||||||
property HasInfo: Boolean read FHasInfo;
|
property HasInfo: Boolean read FHasInfo;
|
||||||
function GetLineAddress(const {%H-}AFileName: String; {%H-}ALine: Cardinal): TDbgPtr; virtual;
|
function GetLineAddress(const {%H-}AFileName: String; {%H-}ALine: Cardinal): TDbgPtr; virtual;
|
||||||
end;
|
end;
|
||||||
@ -234,6 +248,18 @@ begin
|
|||||||
WriteStr(Result, ADbgSymbolKind);
|
WriteStr(Result, ADbgSymbolKind);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TDbgInfoAddressContext }
|
||||||
|
|
||||||
|
function TDbgInfoAddressContext.GetSymbolAtAddress: TDbgSymbol;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDbgInfoAddressContext.FindSymbol(const AName: String): TDbgSymbol;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TDbgSymbol }
|
{ TDbgSymbol }
|
||||||
|
|
||||||
constructor TDbgSymbol.Create(const AName: String);
|
constructor TDbgSymbol.Create(const AName: String);
|
||||||
@ -661,6 +687,11 @@ begin
|
|||||||
inherited Create;
|
inherited Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TDbgInfo.FindContext(AAddress: TDbgPtr): TDbgInfoAddressContext;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
function TDbgInfo.FindSymbol(const AName: String): TDbgSymbol;
|
function TDbgInfo.FindSymbol(const AName: String): TDbgSymbol;
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
|
@ -392,6 +392,15 @@ begin
|
|||||||
TestExpr([0,0,1], TFpPascalExpressionPartIdentifer, 'a', 0);
|
TestExpr([0,0,1], TFpPascalExpressionPartIdentifer, 'a', 0);
|
||||||
TestExpr([0,1], TFpPascalExpressionPartIdentifer, 'b', 0);
|
TestExpr([0,1], TFpPascalExpressionPartIdentifer, 'b', 0);
|
||||||
|
|
||||||
|
CreateExpr('f[a]', True);
|
||||||
|
TestExpr([], TFpPascalExpressionPartBracketIndex, '[', 2);
|
||||||
|
TestExpr([0], TFpPascalExpressionPartIdentifer, 'f', 0);
|
||||||
|
TestExpr([1], TFpPascalExpressionPartIdentifer, 'a', 0);
|
||||||
|
|
||||||
|
CreateExpr('TFoo(f^[0]).a', True);
|
||||||
|
|
||||||
|
CreateExpr('^^int(1)', True);
|
||||||
|
|
||||||
finally
|
finally
|
||||||
CurrentTestExprObj.Free;
|
CurrentTestExprObj.Free;
|
||||||
end;
|
end;
|
||||||
|
@ -44,10 +44,14 @@ var
|
|||||||
function TTestPascalExpression.GetDbgTyeForIdentifier(AnIdent: String): TDbgSymbol;
|
function TTestPascalExpression.GetDbgTyeForIdentifier(AnIdent: String): TDbgSymbol;
|
||||||
var
|
var
|
||||||
Loc: TDBGPtr;
|
Loc: TDBGPtr;
|
||||||
|
Ctx: TDbgInfoAddressContext;
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
if (FDwarfInfo <> nil) and (AnIdent <> '') then
|
if (FDwarfInfo <> nil) and (AnIdent <> '') then begin
|
||||||
Result := FDwarfInfo.FindIdentifier(Location, AnIdent);
|
Ctx := FDwarfInfo.FindContext(Location);
|
||||||
|
Result := Ctx.FindSymbol(AnIdent);
|
||||||
|
Ctx.ReleaseReference;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestTypInfo.LoadDwarf(AFileName: String);
|
procedure TTestTypInfo.LoadDwarf(AFileName: String);
|
||||||
@ -261,6 +265,8 @@ GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
|||||||
DoTest('testc2.a5', skArray);
|
DoTest('testc2.a5', skArray);
|
||||||
AssertTrue(TestText + ' Flag: ', sfStatArray in Expr.ResultType.Flags);
|
AssertTrue(TestText + ' Flag: ', sfStatArray in Expr.ResultType.Flags);
|
||||||
GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
||||||
|
GetTypeAsDeclaration(s, Expr.ResultType, [tdfSkipClassBody, tdfSkipRecordBody]); DebugLn(s);
|
||||||
|
|
||||||
|
|
||||||
DoTest('testc2.a6', skArray);
|
DoTest('testc2.a6', skArray);
|
||||||
AssertTrue(TestText + ' Flag: ', sfDynArray in Expr.ResultType.Flags);
|
AssertTrue(TestText + ' Flag: ', sfDynArray in Expr.ResultType.Flags);
|
||||||
@ -272,6 +278,37 @@ GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DoTest('a1[1]', skBoolean);
|
||||||
|
GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
||||||
|
|
||||||
|
DoTest('a1[3]', skBoolean);
|
||||||
|
GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
||||||
|
|
||||||
|
|
||||||
|
DoTest('a1b[1]', skArray);
|
||||||
|
GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
||||||
|
|
||||||
|
DoTest('a1b[3]', skArray);
|
||||||
|
GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
||||||
|
|
||||||
|
|
||||||
|
DoTest('a1b[1][3]', skBoolean);
|
||||||
|
GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
||||||
|
|
||||||
|
DoTest('a1b[3][4]', skBoolean);
|
||||||
|
GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
||||||
|
|
||||||
|
|
||||||
|
DoTest('TTestClass(0)', skClass);
|
||||||
|
GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
||||||
|
|
||||||
|
DoTest('TTestClass(0).FWord', skCardinal);
|
||||||
|
GetTypeAsDeclaration(s, Expr.ResultType); DebugLn(s);
|
||||||
|
|
||||||
|
|
||||||
|
DoTest('TTestClass2(0).enum4', skPointer);
|
||||||
|
DoTest('TTestClass2(0).enum4^', skEnum);
|
||||||
|
|
||||||
FreeAndNil(expr);
|
FreeAndNil(expr);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -292,5 +329,6 @@ end;
|
|||||||
initialization
|
initialization
|
||||||
|
|
||||||
RegisterTest(TTestTypInfo);
|
RegisterTest(TTestTypInfo);
|
||||||
|
DebugLogger.FindOrRegisterLogGroup('FPDBG_DWARF_SEARCH' {$IFDEF FPDBG_DWARF_SEARCH} , True {$ENDIF} )^.Enabled := True;
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -38,12 +38,19 @@ type
|
|||||||
property Debugger: TFpGDBMIDebugger read FDebugger;
|
property Debugger: TFpGDBMIDebugger read FDebugger;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
MAX_CTX_CACHE = 10;
|
||||||
|
|
||||||
|
type
|
||||||
{ TFpGDBMIDebugger }
|
{ TFpGDBMIDebugger }
|
||||||
|
|
||||||
TFpGDBMIDebugger = class(TGDBMIDebugger)
|
TFpGDBMIDebugger = class(TGDBMIDebugger)
|
||||||
private
|
private
|
||||||
FImageLoader: TDbgImageLoader;
|
FImageLoader: TDbgImageLoader;
|
||||||
FDwarfInfo: TDbgDwarf;
|
FDwarfInfo: TDbgDwarf;
|
||||||
|
// cache last context
|
||||||
|
FlastStackFrame, FLastThread: Integer;
|
||||||
|
FLastContext: array [0..MAX_CTX_CACHE-1] of TDbgInfoAddressContext;
|
||||||
protected
|
protected
|
||||||
function CreateCommandStartDebugging(AContinueCommand: TGDBMIDebuggerCommand): TGDBMIDebuggerCommandStartDebugging; override;
|
function CreateCommandStartDebugging(AContinueCommand: TGDBMIDebuggerCommand): TGDBMIDebuggerCommandStartDebugging; override;
|
||||||
function CreateLineInfo: TDBGLineInfo; override;
|
function CreateLineInfo: TDBGLineInfo; override;
|
||||||
@ -56,6 +63,7 @@ type
|
|||||||
|
|
||||||
procedure GetCurrentContext(out AThreadId, AStackFrame: Integer);
|
procedure GetCurrentContext(out AThreadId, AStackFrame: Integer);
|
||||||
function GetLocationForContext(AThreadId, AStackFrame: Integer): TDBGPtr;
|
function GetLocationForContext(AThreadId, AStackFrame: Integer): TDBGPtr;
|
||||||
|
function GetInfoContextForContext(AThreadId, AStackFrame: Integer): TDbgInfoAddressContext;
|
||||||
function CreateTypeRequestCache: TGDBPTypeRequestCache; override;
|
function CreateTypeRequestCache: TGDBPTypeRequestCache; override;
|
||||||
public
|
public
|
||||||
class function Caption: String; override;
|
class function Caption: String; override;
|
||||||
@ -113,13 +121,19 @@ type
|
|||||||
function TFpGDBMIPascalExpression.GetDbgTyeForIdentifier(AnIdent: String): TDbgSymbol;
|
function TFpGDBMIPascalExpression.GetDbgTyeForIdentifier(AnIdent: String): TDbgSymbol;
|
||||||
var
|
var
|
||||||
Loc: TDBGPtr;
|
Loc: TDBGPtr;
|
||||||
|
Ctx: TDbgInfoAddressContext;
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
if FDebugger.HasDwarf then begin
|
if FDebugger.HasDwarf then begin
|
||||||
if AnIdent <> '' then begin
|
if AnIdent <> '' then begin
|
||||||
Loc := FDebugger.GetLocationForContext(FThreadId, FStackFrame);
|
//Loc := FDebugger.GetLocationForContext(FThreadId, FStackFrame);
|
||||||
if (Loc <> 0) then
|
//if (Loc <> 0) then begin
|
||||||
Result := FDebugger.FDwarfInfo.FindIdentifier(Loc, AnIdent);
|
Ctx := FDebugger.GetInfoContextForContext(FThreadId, FStackFrame);
|
||||||
|
//Ctx := FDebugger.FDwarfInfo.FindContext(Loc);
|
||||||
|
if Ctx <> nil then
|
||||||
|
Result := Ctx.FindSymbol(AnIdent);
|
||||||
|
//Ctx.ReleaseReference;
|
||||||
|
//end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -439,7 +453,7 @@ const
|
|||||||
ASrcTypeName, ADeRefTypeName, ABaseTypeName: String;
|
ASrcTypeName, ADeRefTypeName, ABaseTypeName: String;
|
||||||
ASrcType, ABaseType: TDbgSymbol);
|
ASrcType, ABaseType: TDbgSymbol);
|
||||||
var
|
var
|
||||||
s, s2: String;
|
s: String;
|
||||||
ElemPointerLevel: Integer;
|
ElemPointerLevel: Integer;
|
||||||
ElemDeRefType, ElemBaseType: TDbgSymbol;
|
ElemDeRefType, ElemBaseType: TDbgSymbol;
|
||||||
ElemSrcTypeName, ElemDeRefTypeName, ElemBaseTypeName: String;
|
ElemSrcTypeName, ElemDeRefTypeName, ElemBaseTypeName: String;
|
||||||
@ -724,10 +738,16 @@ end;
|
|||||||
{ TFpGDBMIDebugger }
|
{ TFpGDBMIDebugger }
|
||||||
|
|
||||||
procedure TFpGDBMIDebugger.DoState(const OldState: TDBGState);
|
procedure TFpGDBMIDebugger.DoState(const OldState: TDBGState);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
inherited DoState(OldState);
|
inherited DoState(OldState);
|
||||||
if State in [dsStop, dsError, dsNone] then
|
if State in [dsStop, dsError, dsNone] then
|
||||||
UnLoadDwarf;
|
UnLoadDwarf;
|
||||||
|
|
||||||
|
if OldState in [dsPause, dsInternalPause] then
|
||||||
|
for i := 0 to MAX_CTX_CACHE-1 do
|
||||||
|
ReleaseRefAndNil(FLastContext[i]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFpGDBMIDebugger.HasDwarf: Boolean;
|
function TFpGDBMIDebugger.HasDwarf: Boolean;
|
||||||
@ -830,6 +850,40 @@ begin
|
|||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TFpGDBMIDebugger.GetInfoContextForContext(AThreadId,
|
||||||
|
AStackFrame: Integer): TDbgInfoAddressContext;
|
||||||
|
var
|
||||||
|
Addr: TDBGPtr;
|
||||||
|
begin
|
||||||
|
if (AThreadId <= 0) then begin
|
||||||
|
GetCurrentContext(AThreadId, AStackFrame);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Addr := GetLocationForContext(AThreadId, AStackFrame);
|
||||||
|
|
||||||
|
if Addr = 0 then begin
|
||||||
|
Result := nil;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (AStackFrame >= FlastStackFrame) and
|
||||||
|
(AStackFrame - FlastStackFrame < MAX_CTX_CACHE) and
|
||||||
|
(FLastContext[AStackFrame - FlastStackFrame] <> nil) and
|
||||||
|
(FLastContext[AStackFrame - FlastStackFrame].Address = Addr)
|
||||||
|
then begin
|
||||||
|
DebugLn('cached contex');
|
||||||
|
Result := FLastContext[AStackFrame - FlastStackFrame];
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := FDwarfInfo.FindContext(Addr);
|
||||||
|
|
||||||
|
FLastThread := AThreadId;
|
||||||
|
FlastStackFrame := AStackFrame;
|
||||||
|
FLastContext[0].ReleaseReference;
|
||||||
|
FLastContext[0] := Result;
|
||||||
|
end;
|
||||||
|
|
||||||
type
|
type
|
||||||
TGDBMIDwarfTypeIdentifier = class(TDbgDwarfTypeIdentifier)
|
TGDBMIDwarfTypeIdentifier = class(TDbgDwarfTypeIdentifier)
|
||||||
public
|
public
|
||||||
|
Loading…
Reference in New Issue
Block a user