mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-21 22:59:27 +02:00
FpDebug: fix for Line-To-AddressMap. Lines for one unit(file) can be split can be split across several CU (generics). Create global line maps. TODO: a single file can also occur in several libraries (separate TFpDwarfInfo) with different line ranges in use.
This commit is contained in:
parent
642cd1e58a
commit
68b94f6b72
@ -3670,7 +3670,7 @@ begin
|
||||
begin
|
||||
CU := TDbgDwarfSymbolBase(sym).CompilationUnit;
|
||||
Result := False;
|
||||
CU.GetLineAddresses(sym.FileName, sym.Line, a);
|
||||
CU.Owner.GetLineAddresses(sym.FileName, sym.Line, a);
|
||||
for b in a do begin
|
||||
Result := b = AnAddr;
|
||||
if Result then break;
|
||||
|
@ -44,7 +44,7 @@ unit FpDbgDwarfDataClasses;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, Types, SysUtils, Contnrs, Math,
|
||||
Classes, Types, SysUtils, Contnrs, Math, fgl,
|
||||
// LazUtils
|
||||
Maps, LazClasses, LazFileUtils, LazUTF8, LazCollections,
|
||||
{$ifdef FORCE_LAZLOGGER_DUMMY} LazLoggerDummy {$else} LazLoggerBase {$endif},
|
||||
@ -498,7 +498,7 @@ type
|
||||
AFindSibling: TGetLineAddrFindSibling = fsNone;
|
||||
AFoundLine: PInteger = nil;
|
||||
AMaxSiblingDistance: integer = 0;
|
||||
ACU: TDwarfCompilationUnit = nil
|
||||
ADbgInfo: TFpDwarfInfo = nil
|
||||
): Boolean; inline;
|
||||
// NoData: only return True/False, but nothing in AResultList
|
||||
procedure Compress;
|
||||
@ -698,8 +698,6 @@ type
|
||||
{$IFDEF DwarfTestAccess} private {$ENDIF}
|
||||
FInitialStateMachine: TDwarfLineInfoStateMachine;
|
||||
|
||||
FLineNumberMap: TStringListUTF8Fast;
|
||||
|
||||
FAddressMap: TMap; // Holds a key for each DW_TAG_subprogram / TFpSymbolDwarfDataProc, stores TDwarfAddressInfo
|
||||
FAddressMapBuild: Boolean;
|
||||
|
||||
@ -744,10 +742,6 @@ type
|
||||
procedure WaitForScopeScan; inline; // MUST be called, before accessing the CU
|
||||
procedure WaitForComputeHashes; inline;
|
||||
function GetDefinition(AAbbrevPtr: Pointer; out ADefinition: TDwarfAbbrev): Boolean; inline;
|
||||
function GetLineAddressMap(const AFileName: String): PDWarfLineMap;
|
||||
function GetLineAddresses(const AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||
AFindSibling: TGetLineAddrFindSibling = fsNone; AFoundLine: PInteger = nil; AFoundFilename: PBoolean = nil;
|
||||
AMaxSiblingDistance: integer = 0): boolean;
|
||||
procedure BuildLineInfo(AAddressInfo: PDwarfAddressInfo; ADoAll: Boolean);
|
||||
// On Darwin it could be that the debug-information is not included into the executable by the linker.
|
||||
// This function is to map object-file addresses into the corresponding addresses in the executable.
|
||||
@ -797,7 +791,9 @@ type
|
||||
property AbbrevList: TDwarfAbbrevList read FAbbrevList;
|
||||
property KnownNameHashes: PKnownNameHashesArray read GetKnownNameHashes; // Only for TOP-LEVEL entries
|
||||
end;
|
||||
|
||||
|
||||
TLineNumberFileMap = specialize TFPGMap<AnsiString, PDWarfLineMap>;
|
||||
|
||||
{ TFpDwarfInfo }
|
||||
|
||||
TFpDwarfInfo = class(TDbgInfo)
|
||||
@ -807,6 +803,8 @@ type
|
||||
FWorkQueue: TFpGlobalThreadWorkerQueue;
|
||||
FFiles: array of TDwarfDebugFile;
|
||||
private
|
||||
FLineNumberMap: TLineNumberFileMap;
|
||||
FLineNumberMapDone: Boolean;
|
||||
FImageBase: QWord;
|
||||
FRelocationOffset: QWord;
|
||||
function GetCompilationUnit(AIndex: Integer): TDwarfCompilationUnit; inline;
|
||||
@ -3586,7 +3584,7 @@ end;
|
||||
|
||||
function TDWarfLineMap.GetAddressesForLine(ALine: Cardinal; var AResultList: TDBGPtrArray;
|
||||
NoData: Boolean; AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger;
|
||||
AMaxSiblingDistance: integer; ACU: TDwarfCompilationUnit): Boolean;
|
||||
AMaxSiblingDistance: integer; ADbgInfo: TFpDwarfInfo): Boolean;
|
||||
var
|
||||
idx: integer;
|
||||
offset, Addr1, Addr2: TDBGPtr;
|
||||
@ -3698,8 +3696,8 @@ begin
|
||||
((AFindSibling = fsNextFuncLazy) and (ln - ALine > 1))
|
||||
then begin
|
||||
// check same function
|
||||
if ACU = nil then exit;
|
||||
if not ACU.GetProcStartEnd(Addresses[i], Addr1, Addr2) then exit;
|
||||
if ADbgInfo = nil then exit;
|
||||
if not ADbgInfo.FindProcStartEndPC(Addresses[i], Addr1, Addr2) then exit;
|
||||
if GetAddressesForLine(ALine, TmpResList, False, fsBefore) then begin
|
||||
if (Length(TmpResList) = 0) or (TmpResList[0] < Addr1) or (TmpResList[0] > Addr2) then
|
||||
exit;
|
||||
@ -3759,6 +3757,7 @@ var
|
||||
p: PDbgImageSection;
|
||||
i: Integer;
|
||||
begin
|
||||
FLineNumberMap := TLineNumberFileMap.Create;
|
||||
FWorkQueue := FpDbgGlobalWorkerQueue;
|
||||
FWorkQueue.AddRef;
|
||||
|
||||
@ -3787,6 +3786,17 @@ begin
|
||||
end;
|
||||
|
||||
destructor TFpDwarfInfo.Destroy;
|
||||
procedure FreeLineNumberMap;
|
||||
var
|
||||
n: Integer;
|
||||
begin
|
||||
if FLineNumberMap = nil then
|
||||
exit;
|
||||
for n := 0 to FLineNumberMap.Count - 1 do
|
||||
Dispose(FLineNumberMap.Data[n]);
|
||||
FreeAndNil(FLineNumberMap);
|
||||
end;
|
||||
|
||||
var
|
||||
n: integer;
|
||||
begin
|
||||
@ -3795,6 +3805,7 @@ begin
|
||||
TObject(FCompilationUnits[n]).Free;
|
||||
FreeAndNil(FCompilationUnits);
|
||||
FreeAndNil(FCallFrameInformationList);
|
||||
FreeLineNumberMap;
|
||||
|
||||
inherited Destroy;
|
||||
end;
|
||||
@ -4032,35 +4043,67 @@ function TFpDwarfInfo.GetLineAddresses(const AFileName: String; ALine: Cardinal;
|
||||
var AResultList: TDBGPtrArray; AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger;
|
||||
AFoundFilename: PBoolean; AMaxSiblingDistance: integer): Boolean;
|
||||
var
|
||||
n: Integer;
|
||||
CU: TDwarfCompilationUnit;
|
||||
Map: PDWarfLineMap;
|
||||
begin
|
||||
Result := False;
|
||||
if AFoundLine <> nil then
|
||||
AFoundLine^ := -1;
|
||||
for n := 0 to FCompilationUnits.Count - 1 do
|
||||
begin
|
||||
CU := TDwarfCompilationUnit(FCompilationUnits[n]);
|
||||
CU.WaitForScopeScan;
|
||||
Result := CU.GetLineAddresses(AFileName, ALine, AResultList, AFindSibling, AFoundLine, AFoundFilename, AMaxSiblingDistance)
|
||||
or Result;
|
||||
end;
|
||||
|
||||
Map := GetLineAddressMap(AFileName);
|
||||
if Map = nil then
|
||||
exit;
|
||||
|
||||
if AFoundFilename <> nil then
|
||||
AFoundFilename^ := True;
|
||||
Result := Map^.GetAddressesForLine(ALine, AResultList, False, AFindSibling, AFoundLine, AMaxSiblingDistance, Self);
|
||||
end;
|
||||
|
||||
function TFpDwarfInfo.GetLineAddressMap(const AFileName: String): PDWarfLineMap;
|
||||
|
||||
|
||||
function FindIndex: Integer;
|
||||
var
|
||||
Name: String;
|
||||
begin
|
||||
// try fullname first
|
||||
Result := FLineNumberMap.IndexOf(AFileName);
|
||||
if Result <> -1 then Exit;
|
||||
|
||||
Name := ExtractFileName(AFileName);
|
||||
Result := FLineNumberMap.IndexOf(Name);
|
||||
if Result <> -1 then Exit;
|
||||
|
||||
for Result := 0 to FLineNumberMap.Count - 1 do
|
||||
if AnsiCompareText(Name, ExtractFileName(FLineNumberMap.Keys[Result])) = 0 then
|
||||
Exit;
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
var
|
||||
n: Integer;
|
||||
n, idx: Integer;
|
||||
CU: TDwarfCompilationUnit;
|
||||
begin
|
||||
// TODO: Deal with line info split on 2 compilation units?
|
||||
for n := 0 to FCompilationUnits.Count - 1 do
|
||||
begin
|
||||
CU := TDwarfCompilationUnit(FCompilationUnits[n]);
|
||||
CU.WaitForScopeScan;
|
||||
Result := CU.GetLineAddressMap(AFileName);
|
||||
if Result <> nil then Exit;
|
||||
end;
|
||||
Result := nil;
|
||||
if FLineNumberMap = nil then Exit;
|
||||
|
||||
if not FLineNumberMapDone then begin
|
||||
// make sure all filenames are there
|
||||
for n := 0 to FCompilationUnits.Count - 1 do
|
||||
begin
|
||||
CU := TDwarfCompilationUnit(FCompilationUnits[n]);
|
||||
CU.WaitForScopeScan;
|
||||
if CU.Valid then
|
||||
CU.BuildLineInfo(nil, True);
|
||||
end;
|
||||
for n := 0 to FLineNumberMap.Count - 1 do
|
||||
FLineNumberMap.Data[n]^.Compress;
|
||||
FLineNumberMapDone := True;
|
||||
end;
|
||||
|
||||
idx := FindIndex;
|
||||
if idx = -1 then Exit;
|
||||
|
||||
Result := FLineNumberMap.Data[idx];
|
||||
end;
|
||||
|
||||
procedure TFpDwarfInfo.LoadCallFrameInstructions;
|
||||
@ -4849,15 +4892,15 @@ begin
|
||||
Line := FLineInfo.StateMachine.Line;
|
||||
|
||||
if (idx < 0) or (CurrentFileName <> FLineInfo.StateMachine.FileName) then begin
|
||||
idx := FLineNumberMap.IndexOf(FLineInfo.StateMachine.FileName);
|
||||
idx := FOwner.FLineNumberMap.IndexOf(FLineInfo.StateMachine.FileName);
|
||||
if idx = -1
|
||||
then begin
|
||||
LineMap := New(PDWarfLineMap);
|
||||
LineMap^.Init;
|
||||
FLineNumberMap.AddObject(FLineInfo.StateMachine.FileName, TObject(LineMap));
|
||||
FOwner.FLineNumberMap.Add(FLineInfo.StateMachine.FileName, LineMap);
|
||||
end
|
||||
else begin
|
||||
LineMap := PDWarfLineMap(FLineNumberMap.Objects[idx]);
|
||||
LineMap := FOwner.FLineNumberMap.Data[idx];
|
||||
end;
|
||||
CurrentFileName := FLineInfo.StateMachine.FileName;
|
||||
end;
|
||||
@ -4895,8 +4938,9 @@ begin
|
||||
|
||||
Iter.Free;
|
||||
|
||||
for Idx := 0 to FLineNumberMap.Count - 1 do
|
||||
PDWarfLineMap(FLineNumberMap.Objects[idx])^.Compress;
|
||||
if not ADoAll then
|
||||
for Idx := 0 to FOwner.FLineNumberMap.Count - 1 do
|
||||
FOwner.FLineNumberMap.Data[idx]^.Compress;
|
||||
end;
|
||||
|
||||
function TDwarfCompilationUnit.GetAddressMap: TMap;
|
||||
@ -5212,9 +5256,6 @@ begin
|
||||
|
||||
// use internally 64 bit target pointer
|
||||
FAddressMap := TMap.Create(itu8, SizeOf(TDwarfAddressInfo));
|
||||
FLineNumberMap := TStringListUTF8Fast.Create;
|
||||
FLineNumberMap.Sorted := True;
|
||||
FLineNumberMap.Duplicates := dupError;
|
||||
|
||||
FFirstScope.Init(nil); // invalid
|
||||
|
||||
@ -5299,17 +5340,6 @@ begin
|
||||
end;
|
||||
|
||||
destructor TDwarfCompilationUnit.Destroy;
|
||||
procedure FreeLineNumberMap;
|
||||
var
|
||||
n: Integer;
|
||||
begin
|
||||
if FLineNumberMap = nil then
|
||||
exit;
|
||||
for n := 0 to FLineNumberMap.Count - 1 do
|
||||
Dispose(PDWarfLineMap(FLineNumberMap.Objects[n]));
|
||||
FreeAndNil(FLineNumberMap);
|
||||
end;
|
||||
|
||||
begin
|
||||
FOwner.WorkQueue.RemoveItem(FComputeNameHashesWorker);
|
||||
FOwner.WorkQueue.RemoveItem(FScanAllWorker);
|
||||
@ -5318,7 +5348,6 @@ begin
|
||||
|
||||
FreeAndNil(FAbbrevList);
|
||||
FreeAndNil(FAddressMap);
|
||||
FreeLineNumberMap;
|
||||
FreeAndNil(FInitialStateMachine);
|
||||
FreeAndNil(FLineInfo.StateMachines);
|
||||
FreeAndNil(FLineInfo.StateMachine);
|
||||
@ -5328,56 +5357,6 @@ begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TDwarfCompilationUnit.GetLineAddressMap(const AFileName: String): PDWarfLineMap;
|
||||
|
||||
function FindIndex: Integer;
|
||||
var
|
||||
Name: String;
|
||||
begin
|
||||
// try fullname first
|
||||
Result := FLineNumberMap.IndexOf(AFileName);
|
||||
if Result <> -1 then Exit;
|
||||
|
||||
Name := ExtractFileName(AFileName);
|
||||
Result := FLineNumberMap.IndexOf(Name);
|
||||
if Result <> -1 then Exit;
|
||||
|
||||
for Result := 0 to FLineNumberMap.Count - 1 do
|
||||
if AnsiCompareText(Name, ExtractFileName(FLineNumberMap[Result])) = 0 then
|
||||
Exit;
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
var
|
||||
idx: Integer;
|
||||
begin
|
||||
Result := nil;
|
||||
if not Valid then Exit;
|
||||
|
||||
// make sure all filenames are there
|
||||
BuildLineInfo(nil, True);
|
||||
idx := FindIndex;
|
||||
if idx = -1 then Exit;
|
||||
|
||||
Result := PDWarfLineMap(FLineNumberMap.Objects[idx]);
|
||||
end;
|
||||
|
||||
function TDwarfCompilationUnit.GetLineAddresses(const AFileName: String; ALine: Cardinal;
|
||||
var AResultList: TDBGPtrArray; AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger;
|
||||
AFoundFilename: PBoolean; AMaxSiblingDistance: integer): boolean;
|
||||
var
|
||||
Map: PDWarfLineMap;
|
||||
begin
|
||||
Result := False;
|
||||
Map := GetLineAddressMap(AFileName);
|
||||
if Map = nil then
|
||||
exit;
|
||||
|
||||
if AFoundFilename <> nil then
|
||||
AFoundFilename^ := True;
|
||||
Result := Map^.GetAddressesForLine(ALine, AResultList, False, AFindSibling, AFoundLine, AMaxSiblingDistance, Self);
|
||||
end;
|
||||
|
||||
function TDwarfCompilationUnit.InitLocateAttributeList(AEntry: Pointer;
|
||||
var AList: TAttribPointerList): Boolean;
|
||||
var
|
||||
|
@ -2380,7 +2380,7 @@ begin
|
||||
AnAddresses := nil;
|
||||
if
|
||||
//(FndLine = HelpSymbol.Line) and
|
||||
HelpSymbol.CompilationUnit.GetLineAddresses(HelpSymbol.FileName, HelpSymbol.Line, AnAddresses, fsBefore, @FndLine) and
|
||||
HelpSymbol.CompilationUnit.Owner.GetLineAddresses(HelpSymbol.FileName, HelpSymbol.Line, AnAddresses, fsBefore, @FndLine) and
|
||||
(Length(AnAddresses) > 1) // may be an internal finally on the begin/end line, sharing a line number
|
||||
then begin
|
||||
for i := 0 to Length(AnAddresses) - 1 do
|
||||
@ -2401,7 +2401,7 @@ begin
|
||||
end;
|
||||
|
||||
AnAddresses := nil;
|
||||
if HelpSymbol.CompilationUnit.GetLineAddresses(HelpSymbol.FileName, HelpSymbol.Line-1, AnAddresses, fsBefore)
|
||||
if HelpSymbol.CompilationUnit.Owner.GetLineAddresses(HelpSymbol.FileName, HelpSymbol.Line-1, AnAddresses, fsBefore)
|
||||
then begin
|
||||
TFpSymbol(HelpSymbol2) := DbgInfo.FindProcSymbol(AnAddresses[0]);
|
||||
if (HelpSymbol2 <> nil) and (HelpSymbol2.CompilationUnit = CompilationUnit) and
|
||||
|
Loading…
Reference in New Issue
Block a user