From 23065e004cbab281b869e3d230199b40fdb311fa Mon Sep 17 00:00:00 2001 From: ccrause Date: Sun, 4 Jul 2021 08:36:33 +0200 Subject: [PATCH] Add functionality to get proc start/end addresses from debug info. Used to scan prologue and epilogue for frame information on AVR target. --- components/fpdebug/fpdbgclasses.pp | 27 +++++++++ components/fpdebug/fpdbgdwarfdataclasses.pas | 62 ++++++++++++++++++++ components/fpdebug/fpdbginfo.pas | 11 ++++ 3 files changed, 100 insertions(+) diff --git a/components/fpdebug/fpdbgclasses.pp b/components/fpdebug/fpdbgclasses.pp index 363e6823c6..fd08bbaaff 100644 --- a/components/fpdebug/fpdbgclasses.pp +++ b/components/fpdebug/fpdbgclasses.pp @@ -463,6 +463,8 @@ type function AddrOffset: TDBGPtr; virtual; // gives the offset between the loaded addresses and the compiled addresses function FindProcSymbol(const AName: String): TFpSymbol; overload; function FindProcSymbol(AAdress: TDbgPtr): TFpSymbol; overload; + function FindProcStartEndPC(AAdress: TDbgPtr; out AStartPC, AEndPC: TDBGPtr): boolean; + procedure LoadInfo; virtual; property Process: TDbgProcess read FProcess; @@ -617,6 +619,8 @@ public function FindProcSymbol(const AName, ALibraryName: String; IsFullLibName: Boolean = True): TFpSymbol; overload; function FindProcSymbol(AAdress: TDbgPtr): TFpSymbol; overload; function FindSymbolScope(AThreadId, AStackFrame: Integer): TFpDbgSymbolScope; + function FindProcStartEndPC(const AAdress: TDbgPtr; out AStartPC, AEndPC: TDBGPtr): boolean; + function ContextFromProc(AThreadId, AStackFrame: Integer; AProcSym: TFpSymbol): TFpDbgLocationContext; inline; deprecated 'use TFpDbgSimpleLocationContext.Create'; function GetLib(const AHandle: THandle; out ALib: TDbgLibrary): Boolean; property LastLibraryLoaded: TDbgLibrary read GetLastLibraryLoaded; @@ -1623,6 +1627,15 @@ begin result := FSymbolTableInfo.FindProcSymbol(AAdress); end; +function TDbgInstance.FindProcStartEndPC(AAdress: TDbgPtr; out AStartPC, + AEndPC: TDBGPtr): boolean; +begin + {$PUSH}{$R-}{$Q-} + AAdress := AAdress + AddrOffset; + {$POP} + Result := FDbgInfo.FindProcStartEndPC(AAdress, AStartPC, AEndPC); +end; + procedure TDbgInstance.LoadInfo; begin InitializeLoaders; @@ -1871,6 +1884,20 @@ begin Ctx.ReleaseReference; end; +function TDbgProcess.FindProcStartEndPC(const AAdress: TDbgPtr; out AStartPC, + AEndPC: TDBGPtr): boolean; +var + n: Integer; + Inst: TDbgInstance; +begin + for n := 0 to FSymInstances.Count - 1 do + begin + Inst := TDbgInstance(FSymInstances[n]); + Result := Inst.FindProcStartEndPC(AAdress, AStartPC, AEndPC); + if Result then Exit; + end; +end; + function TDbgProcess.ContextFromProc(AThreadId, AStackFrame: Integer; AProcSym: TFpSymbol): TFpDbgLocationContext; begin diff --git a/components/fpdebug/fpdbgdwarfdataclasses.pas b/components/fpdebug/fpdbgdwarfdataclasses.pas index 550f8b3a0f..6a164e79b8 100644 --- a/components/fpdebug/fpdbgdwarfdataclasses.pas +++ b/components/fpdebug/fpdbgdwarfdataclasses.pas @@ -683,6 +683,8 @@ type // 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. function MapAddressToNewValue(AValue: QWord): QWord; + // Get start/end addresses of proc + function GetProcStartEnd(const AAddress: TDBGPtr; out AStartPC, AEndPC: TDBGPtr): boolean; property Valid: Boolean read FValid; property FileName: String read FFileName; @@ -736,6 +738,8 @@ type function FindSymbolScope(ALocationContext: TFpDbgLocationContext; AAddress: TDbgPtr = 0): TFpDbgSymbolScope; override; function FindDwarfProcSymbol(AAddress: TDbgPtr): TDbgDwarfSymbolBase; inline; function FindProcSymbol(AAddress: TDbgPtr): TFpSymbol; override; overload; + function FindProcStartEndPC(const AAddress: TDbgPtr; out AStartPC, AEndPC: TDBGPtr): boolean; override; + //function FindSymbol(const AName: String): TDbgSymbol; override; overload; function GetLineAddresses(const AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray): Boolean; override; function GetLineAddressMap(const AFileName: String): PDWarfLineMap; @@ -3640,6 +3644,29 @@ begin end; end; +function TFpDwarfInfo.FindProcStartEndPC(const AAddress: TDbgPtr; out AStartPC, + AEndPC: TDBGPtr): boolean; +var + n: Integer; + CU: TDwarfCompilationUnit; + Iter: TLockedMapIterator; + Info: PDwarfAddressInfo; + MinMaxSet: boolean; +begin + for n := 0 to FCompilationUnits.Count - 1 do + begin + CU := TDwarfCompilationUnit(FCompilationUnits[n]); + CU.WaitForScopeScan; + if not CU.Valid then Continue; + MinMaxSet := CU.FMinPC <> CU.FMaxPC; + if MinMaxSet and ((AAddress < CU.FMinPC) or (AAddress > CU.FMaxPC)) + then Continue; + + Result := CU.GetProcStartEnd(AAddress, AStartPC, AEndPC); + if Result then exit; + end; +end; + function TFpDwarfInfo.FindDwarfUnitSymbol(AAddress: TDbgPtr ): TDbgDwarfSymbolBase; var @@ -4771,6 +4798,41 @@ begin end; end; +function TDwarfCompilationUnit.GetProcStartEnd(const AAddress: TDBGPtr; out + AStartPC, AEndPC: TDBGPtr): boolean; +var + Iter: TLockedMapIterator; + Info: PDwarfAddressInfo; +begin + if not FAddressMapBuild then + BuildAddressMap; + + Result := false; + Iter := TLockedMapIterator.Create(FAddressMap); + try + if not Iter.Locate(AAddress) then + begin + if not Iter.BOM then + Iter.Previous; + + if Iter.BOM then + Exit; + end; + + // iter is at the closest defined address before AAddress + Info := Iter.DataPtr; + if (AAddress >= Info^.StartPC) or (AAddress <= Info^.EndPC) then + begin + AStartPC := Info^.StartPC; + AEndPC := Info^.EndPC; + Result := true; + end; + + finally + Iter.Free; + end; +end; + function TDwarfCompilationUnit.ReadValue(AAttribute: Pointer; AForm: Cardinal; out AValue: Cardinal): Boolean; begin Result := True; diff --git a/components/fpdebug/fpdbginfo.pas b/components/fpdebug/fpdbginfo.pas index 53a233523d..2966fa4b32 100644 --- a/components/fpdebug/fpdbginfo.pas +++ b/components/fpdebug/fpdbginfo.pas @@ -598,6 +598,9 @@ type function FindSymbolScope(ALocationContext: TFpDbgLocationContext; {%H-}AAddress: TDbgPtr = 0): TFpDbgSymbolScope; virtual; function FindProcSymbol(AAddress: TDbgPtr): TFpSymbol; virtual; overload; function FindProcSymbol(const {%H-}AName: String): TFpSymbol; virtual; overload; + + function FindProcStartEndPC(const AAddress: TDbgPtr; out AStartPC, AEndPC: TDBGPtr): boolean; virtual; + property HasInfo: Boolean read FHasInfo; function GetLineAddresses(const AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray): Boolean; virtual; //property MemManager: TFpDbgMemReaderBase read GetMemManager write SetMemManager; @@ -1746,6 +1749,14 @@ begin Result := nil; end; +function TDbgInfo.FindProcStartEndPC(const AAddress: TDbgPtr; out AStartPC, + AEndPC: TDBGPtr): boolean; +begin + AStartPC := 0; + AEndPC := 0; + Result := false; +end; + function TDbgInfo.GetLineAddresses(const AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray): Boolean; begin