mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-17 22:08:15 +02:00
FpDebug: use threads to scan units for symbol
git-svn-id: trunk@63829 -
This commit is contained in:
parent
c9916553dd
commit
d62e55102b
@ -77,6 +77,25 @@ type
|
|||||||
|
|
||||||
TFpValueDwarf = class;
|
TFpValueDwarf = class;
|
||||||
TFpSymbolDwarf = class;
|
TFpSymbolDwarf = class;
|
||||||
|
TFpDwarfInfoSymbolScope = class;
|
||||||
|
|
||||||
|
TDwarfCompilationUnitArray = array of TDwarfCompilationUnit;
|
||||||
|
|
||||||
|
{ TFpThreadWorkerFindSymbolInUnits }
|
||||||
|
|
||||||
|
TFpThreadWorkerFindSymbolInUnits = class(TFpThreadWorkerItem)
|
||||||
|
protected
|
||||||
|
FScope: TFpDwarfInfoSymbolScope;
|
||||||
|
FCUs: TDwarfCompilationUnitArray;
|
||||||
|
FNameInfo: TNameSearchInfo;
|
||||||
|
|
||||||
|
FFoundInfoEntry: TDwarfInformationEntry;
|
||||||
|
FIsExt: Boolean;
|
||||||
|
procedure DoExecute; override;
|
||||||
|
public
|
||||||
|
constructor Create(AScope: TFpDwarfInfoSymbolScope; CUs: TDwarfCompilationUnitArray; const ANameInfo: TNameSearchInfo);
|
||||||
|
destructor Destroy; override;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TFpDwarfInfoSymbolScope }
|
{ TFpDwarfInfoSymbolScope }
|
||||||
|
|
||||||
@ -99,8 +118,10 @@ type
|
|||||||
function SymbolToValue(ASym: TFpSymbolDwarf): TFpValue; inline;
|
function SymbolToValue(ASym: TFpSymbolDwarf): TFpValue; inline;
|
||||||
function GetSelfParameter: TFpValueDwarf;
|
function GetSelfParameter: TFpValueDwarf;
|
||||||
|
|
||||||
|
function FindExportedSymbolInUnit(CU: TDwarfCompilationUnit; const ANameInfo: TNameSearchInfo;
|
||||||
|
out AnInfoEntry: TDwarfInformationEntry; out AnIsExternal: Boolean): Boolean; inline;
|
||||||
function FindExportedSymbolInUnits(const AName: String; const ANameInfo: TNameSearchInfo;
|
function FindExportedSymbolInUnits(const AName: String; const ANameInfo: TNameSearchInfo;
|
||||||
SkipCompUnit: TDwarfCompilationUnit; out ADbgValue: TFpValue): Boolean; inline;
|
SkipCompUnit: TDwarfCompilationUnit; out ADbgValue: TFpValue): Boolean;
|
||||||
function FindSymbolInStructure(const AName: String; const ANameInfo: TNameSearchInfo;
|
function FindSymbolInStructure(const AName: String; const ANameInfo: TNameSearchInfo;
|
||||||
InfoEntry: TDwarfInformationEntry; out ADbgValue: TFpValue): Boolean; inline;
|
InfoEntry: TDwarfInformationEntry; out ADbgValue: TFpValue): Boolean; inline;
|
||||||
// FindLocalSymbol: for the subroutine itself
|
// FindLocalSymbol: for the subroutine itself
|
||||||
@ -1170,7 +1191,42 @@ begin
|
|||||||
Result := TFpSymbolDwarfUnit.Create(ACompilationUnit.UnitName, AInfoEntry);
|
Result := TFpSymbolDwarfUnit.Create(ACompilationUnit.UnitName, AInfoEntry);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TDbgDwarfInfoAddressContext }
|
{ TFpThreadWorkerFindSymbolInUnits }
|
||||||
|
|
||||||
|
procedure TFpThreadWorkerFindSymbolInUnits.DoExecute;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
InfoEntry: TDwarfInformationEntry;
|
||||||
|
IsExt: Boolean;
|
||||||
|
begin
|
||||||
|
FFoundInfoEntry := nil;
|
||||||
|
for i := 0 to Length(FCUs) - 1 do begin
|
||||||
|
if FScope.FindExportedSymbolInUnit(FCUs[i], FNameInfo, InfoEntry, IsExt) then begin
|
||||||
|
FFoundInfoEntry.ReleaseReference;
|
||||||
|
FFoundInfoEntry := InfoEntry;
|
||||||
|
if FIsExt then
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TFpThreadWorkerFindSymbolInUnits.Create(
|
||||||
|
AScope: TFpDwarfInfoSymbolScope; CUs: TDwarfCompilationUnitArray;
|
||||||
|
const ANameInfo: TNameSearchInfo);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FScope := AScope;
|
||||||
|
FCUs := CUs;
|
||||||
|
FNameInfo := ANameInfo;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TFpThreadWorkerFindSymbolInUnits.Destroy;
|
||||||
|
begin
|
||||||
|
FFoundInfoEntry.ReleaseReference;
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TFpDwarfInfoSymbolScope }
|
||||||
|
|
||||||
function TFpDwarfInfoSymbolScope.GetSymbolAtAddress: TFpSymbol;
|
function TFpDwarfInfoSymbolScope.GetSymbolAtAddress: TFpSymbol;
|
||||||
begin
|
begin
|
||||||
@ -1239,59 +1295,156 @@ begin
|
|||||||
FSelfParameter := Result;
|
FSelfParameter := Result;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFpDwarfInfoSymbolScope.FindExportedSymbolInUnits(const AName: String;
|
function TFpDwarfInfoSymbolScope.FindExportedSymbolInUnit(
|
||||||
const ANameInfo: TNameSearchInfo; SkipCompUnit: TDwarfCompilationUnit; out
|
CU: TDwarfCompilationUnit; const ANameInfo: TNameSearchInfo; out
|
||||||
ADbgValue: TFpValue): Boolean;
|
AnInfoEntry: TDwarfInformationEntry; out AnIsExternal: Boolean): Boolean;
|
||||||
var
|
var
|
||||||
i, ExtVal: Integer;
|
i, ExtVal: Integer;
|
||||||
CU: TDwarfCompilationUnit;
|
InfoEntry: TDwarfInformationEntry;
|
||||||
InfoEntry, FoundInfoEntry: TDwarfInformationEntry;
|
|
||||||
s: String;
|
s: String;
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
|
|
||||||
|
AnInfoEntry := nil;
|
||||||
|
AnIsExternal := False;
|
||||||
|
|
||||||
|
//DebugLn(FPDBG_DWARF_SEARCH, ['TDbgDwarf.FindIdentifier search UNIT Name=', CU.FileName]);
|
||||||
|
|
||||||
|
InfoEntry := TDwarfInformationEntry.Create(CU, nil);
|
||||||
|
InfoEntry.ScopeIndex := CU.FirstScope.Index;
|
||||||
|
|
||||||
|
if not InfoEntry.AbbrevTag = DW_TAG_compile_unit then
|
||||||
|
exit;
|
||||||
|
// compile_unit can not have startscope
|
||||||
|
|
||||||
|
s := CU.UnitName;
|
||||||
|
if (s <> '') and (CompareUtf8BothCase(PChar(ANameInfo.NameUpper), PChar(ANameInfo.NameLower), @s[1])) then begin
|
||||||
|
Result := True;
|
||||||
|
AnInfoEntry := InfoEntry;
|
||||||
|
AnIsExternal := True;
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
if InfoEntry.GoNamedChildEx(ANameInfo) then begin
|
||||||
|
if InfoEntry.IsAddressInStartScope(FAddress) then begin
|
||||||
|
// only variables are marked "external", but types not / so we may need all top level
|
||||||
|
Result := True;
|
||||||
|
AnInfoEntry := InfoEntry;
|
||||||
|
//DebugLn(FPDBG_DWARF_SEARCH, ['TDbgDwarf.FindIdentifier MAYBE FOUND Name=', CU.FileName]);
|
||||||
|
|
||||||
|
// DW_AT_visibility ?
|
||||||
|
|
||||||
|
if InfoEntry.ReadValue(DW_AT_external, ExtVal) then
|
||||||
|
AnIsExternal := ExtVal <> 0;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not Result then
|
||||||
|
InfoEntry.ReleaseReference;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFpDwarfInfoSymbolScope.FindExportedSymbolInUnits(const AName: String;
|
||||||
|
const ANameInfo: TNameSearchInfo; SkipCompUnit: TDwarfCompilationUnit; out
|
||||||
|
ADbgValue: TFpValue): Boolean;
|
||||||
|
const
|
||||||
|
PER_WORKER_CNT = 20;
|
||||||
|
var
|
||||||
|
i, j: Integer;
|
||||||
|
CU: TDwarfCompilationUnit;
|
||||||
|
CUList: TDwarfCompilationUnitArray;
|
||||||
|
InfoEntry, FoundInfoEntry: TDwarfInformationEntry;
|
||||||
|
IsExt: Boolean;
|
||||||
|
WorkItem, PrevWorkItem: TFpThreadWorkerFindSymbolInUnits;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
|
||||||
ADbgValue := nil;
|
ADbgValue := nil;
|
||||||
InfoEntry := nil;
|
|
||||||
FoundInfoEntry := nil;
|
FoundInfoEntry := nil;
|
||||||
|
SetLength(CUList, PER_WORKER_CNT);
|
||||||
|
PrevWorkItem := nil;
|
||||||
|
IsExt := False;
|
||||||
|
|
||||||
i := FDwarf.CompilationUnitsCount;
|
i := FDwarf.CompilationUnitsCount;
|
||||||
while i > 0 do begin
|
while i > 0 do begin
|
||||||
dec(i);
|
j := 0;
|
||||||
CU := FDwarf.CompilationUnits[i];
|
while (j < PER_WORKER_CNT) and (i > 0) do begin
|
||||||
|
dec(i);
|
||||||
|
CU := FDwarf.CompilationUnits[i];
|
||||||
|
|
||||||
if (CU = SkipCompUnit) or
|
if (CU = SkipCompUnit) or
|
||||||
(not CU.KnownNameHashes^[ANameInfo.NameHash and KnownNameHashesBitMask])
|
(not CU.KnownNameHashes^[ANameInfo.NameHash and KnownNameHashesBitMask])
|
||||||
then
|
then
|
||||||
continue;
|
continue;
|
||||||
//DebugLn(FPDBG_DWARF_SEARCH, ['TDbgDwarf.FindIdentifier search UNIT Name=', CU.FileName]);
|
|
||||||
|
|
||||||
InfoEntry.ReleaseReference;
|
CUList[j] := CU;
|
||||||
InfoEntry := TDwarfInformationEntry.Create(CU, nil);
|
inc(j);
|
||||||
InfoEntry.ScopeIndex := CU.FirstScope.Index;
|
|
||||||
|
|
||||||
if not InfoEntry.AbbrevTag = DW_TAG_compile_unit then
|
|
||||||
continue;
|
|
||||||
// compile_unit can not have startscope
|
|
||||||
|
|
||||||
s := CU.UnitName;
|
|
||||||
if (s <> '') and (CompareUtf8BothCase(PChar(ANameInfo.NameUpper), PChar(ANameInfo.NameLower), @s[1])) then begin
|
|
||||||
ReleaseRefAndNil(FoundInfoEntry);
|
|
||||||
ADbgValue := SymbolToValue(TFpSymbolDwarf.CreateSubClass(AName, InfoEntry));
|
|
||||||
break;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if InfoEntry.GoNamedChildEx(ANameInfo) then begin
|
if j < PER_WORKER_CNT then begin
|
||||||
if InfoEntry.IsAddressInStartScope(FAddress) then begin
|
assert(i=0, 'TFpDwarfInfoSymbolScope.FindExportedSymbolInUnits: i=0');
|
||||||
// only variables are marked "external", but types not / so we may need all top level
|
SetLength(CUList, j);
|
||||||
FoundInfoEntry.ReleaseReference;
|
end;
|
||||||
FoundInfoEntry := InfoEntry.Clone;
|
|
||||||
//DebugLn(FPDBG_DWARF_SEARCH, ['TDbgDwarf.FindIdentifier MAYBE FOUND Name=', CU.FileName]);
|
|
||||||
|
|
||||||
// DW_AT_visibility ?
|
if j > 0 then begin
|
||||||
if InfoEntry.ReadValue(DW_AT_external, ExtVal) then
|
WorkItem := TFpThreadWorkerFindSymbolInUnits.Create(Self, CUList, ANameInfo);
|
||||||
if ExtVal <> 0 then
|
WorkItem.AddRef;
|
||||||
break;
|
end
|
||||||
// Search for better ADbgValue
|
else
|
||||||
|
WorkItem := nil;
|
||||||
|
|
||||||
|
if (PrevWorkItem <> nil) and (not PrevWorkItem.IsDone) then begin
|
||||||
|
if WorkItem <> nil then begin
|
||||||
|
WorkItem.Execute;
|
||||||
|
if (WorkItem.FFoundInfoEntry = nil) and (not PrevWorkItem.IsDone) then begin
|
||||||
|
WorkItem.DecRef;
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Dwarf.WorkQueue.WaitForItem(PrevWorkItem); // must check result from Prev first, to keep a stable search order
|
||||||
|
end;
|
||||||
|
|
||||||
|
while PrevWorkItem <> nil do begin
|
||||||
|
assert(PrevWorkItem.IsDone, 'TFpDwarfInfoSymbolScope.FindExportedSymbolInUnits: PrevWorkItem.IsDone');
|
||||||
|
ReadBarrier;
|
||||||
|
if PrevWorkItem.FFoundInfoEntry <> nil then begin
|
||||||
|
FoundInfoEntry.ReleaseReference;
|
||||||
|
FoundInfoEntry := PrevWorkItem.FFoundInfoEntry;
|
||||||
|
FoundInfoEntry.AddReference;
|
||||||
|
IsExt := PrevWorkItem.FIsExt;
|
||||||
|
end;
|
||||||
|
PrevWorkItem.DecRef;
|
||||||
|
PrevWorkItem := nil;
|
||||||
|
if IsExt then begin
|
||||||
|
WorkItem.DecRef;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
if (WorkItem <> nil) and WorkItem.IsDone then begin
|
||||||
|
PrevWorkItem := WorkItem;
|
||||||
|
WorkItem := nil;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if WorkItem <> nil then begin
|
||||||
|
if i = 0 then
|
||||||
|
WorkItem.Execute
|
||||||
|
else
|
||||||
|
Dwarf.WorkQueue.PushItemIdleOrRun(WorkItem);
|
||||||
|
PrevWorkItem := WorkItem;
|
||||||
|
WorkItem := nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if PrevWorkItem <> nil then begin
|
||||||
|
if not IsExt then begin // IsExt => already got a final result
|
||||||
|
if not PrevWorkItem.IsDone then
|
||||||
|
Dwarf.WorkQueue.WaitForItem(PrevWorkItem);
|
||||||
|
if PrevWorkItem.FFoundInfoEntry <> nil then begin
|
||||||
|
FoundInfoEntry.ReleaseReference;
|
||||||
|
FoundInfoEntry := PrevWorkItem.FFoundInfoEntry;
|
||||||
|
FoundInfoEntry.AddReference
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
PrevWorkItem.DecRef;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if FoundInfoEntry <> nil then begin
|
if FoundInfoEntry <> nil then begin
|
||||||
@ -1299,7 +1452,6 @@ begin
|
|||||||
FoundInfoEntry.ReleaseReference;
|
FoundInfoEntry.ReleaseReference;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
InfoEntry.ReleaseReference;
|
|
||||||
Result := ADbgValue <> nil;
|
Result := ADbgValue <> nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user