diff --git a/components/fpdebug/fpdbgdwarf.pas b/components/fpdebug/fpdbgdwarf.pas index b2e2b25126..f2b464a951 100644 --- a/components/fpdebug/fpdbgdwarf.pas +++ b/components/fpdebug/fpdbgdwarf.pas @@ -496,6 +496,7 @@ type TFpValueDwarfSubroutine = class(TFpValueDwarf) protected function IsValidTypeCast: Boolean; override; + function GetEntryPCAddress: TFpDbgMemLocation; override; end; {%endregion Value objects } @@ -1045,6 +1046,8 @@ DECL = DW_AT_decl_column, DW_AT_decl_file, DW_AT_decl_line function GetValueObject: TFpValue; override; function GetValueAddress(AValueObj: TFpValueDwarf; out AnAddress: TFpDbgMemLocation): Boolean; override; + function GetEntryPCAddress(AValueObj: TFpValueDwarf; out + AnAddress: TFpDbgMemLocation): Boolean; property DbgInfo: TFpDwarfInfo read FDwarf; property ProcAddress: TDBGPtr read FAddress; @@ -1190,6 +1193,16 @@ begin Result := False; end; +function TFpValueDwarfSubroutine.GetEntryPCAddress: TFpDbgMemLocation; +begin + Result := InvalidLoc; + if (FDataSymbol = nil) then + exit; + assert(FDataSymbol is TFpSymbolDwarfDataProc, 'TFpValueDwarfSubroutine.GetEntryPCAddress: FDataSymbol is TFpSymbolDwarfDataProc'); + if not TFpSymbolDwarfDataProc(FDataSymbol).GetEntryPCAddress(Self, Result) then + Result := InvalidLoc; +end; + { TFpDwarfDefaultSymbolClassMap } class function TFpDwarfDefaultSymbolClassMap.GetExistingClassMap: PFpDwarfSymbolClassMap; @@ -6278,6 +6291,45 @@ begin Result := IsValidLoc(AnAddress); end; +function TFpSymbolDwarfDataProc.GetEntryPCAddress(AValueObj: TFpValueDwarf; out + AnAddress: TFpDbgMemLocation): Boolean; +var + AttrData: TDwarfAttribData; + Addr: TDBGPtr; + Offs: QWord; + f: Cardinal; +begin + AnAddress := InvalidLoc; + Offs := 0; + + if InformationEntry.GetAttribData(DW_AT_entry_pc, AttrData) then begin + f := AttrData.InformationEntry.AttribForm[AttrData.Idx]; + if f = DW_FORM_addr then begin + Result := InformationEntry.ReadAddressValue(AttrData, Addr); + if Result then + AnAddress := TargetLoc(Addr); + exit; + end + else + // DWARF 5: DW_AT_entry_pc can be an unsigned offset to DW_AT_low_pc + if f in [DW_FORM_data1, DW_FORM_data2, DW_FORM_data4, DW_FORM_data8, DW_FORM_sdata, DW_FORM_udata] then begin + Result := InformationEntry.ReadValue(AttrData, Offs); + if not Result then + exit; + end + else + exit(False); // error + end; + + if InformationEntry.GetAttribData(DW_AT_low_pc, AttrData) then + if InformationEntry.ReadAddressValue(AttrData, Addr) then + {$PUSH}{$R-}{$Q-} + AnAddress := TargetLoc(Addr + Offs); + {$POP} + //DW_AT_ranges + Result := IsValidLoc(AnAddress); +end; + function TFpSymbolDwarfDataProc.StateMachineValid: Boolean; var SM1, SM2: TDwarfLineInfoStateMachine; diff --git a/components/fpdebug/fpdbginfo.pas b/components/fpdebug/fpdbginfo.pas index bff2684618..1c62fec8be 100644 --- a/components/fpdebug/fpdbginfo.pas +++ b/components/fpdebug/fpdbginfo.pas @@ -134,6 +134,7 @@ type function DoGetSize(out ASize: TFpDbgValueSize): Boolean; virtual; function GetDataAddress: TFpDbgMemLocation; virtual; function GetDerefAddress: TFpDbgMemLocation; virtual; + function GetEntryPCAddress: TFpDbgMemLocation; virtual; function GetDataSize: TFpDbgValueSize; virtual; function GetHasBounds: Boolean; virtual; @@ -180,6 +181,7 @@ type property Address: TFpDbgMemLocation read GetAddress; property DataAddress: TFpDbgMemLocation read GetDataAddress; // property DerefAddress: TFpDbgMemLocation read GetDerefAddress; // + property EntryPCAddress: TFpDbgMemLocation read GetEntryPCAddress; property DataSize: TFpDbgValueSize read GetDataSize; property HasBounds: Boolean read GetHasBounds; @@ -1035,6 +1037,11 @@ begin Result := 0; end; +function TFpValue.GetEntryPCAddress: TFpDbgMemLocation; +begin + Result := InvalidLoc; +end; + procedure TFpValue.Reset; begin FEvalFlags := []; diff --git a/components/lazdebuggers/lazdebuggerfp/fpdebugdebuggerworkthreads.pas b/components/lazdebuggers/lazdebuggerfp/fpdebugdebuggerworkthreads.pas index ba219b41d6..d7f9332fd2 100644 --- a/components/lazdebuggers/lazdebuggerfp/fpdebugdebuggerworkthreads.pas +++ b/components/lazdebuggers/lazdebuggerfp/fpdebugdebuggerworkthreads.pas @@ -898,7 +898,7 @@ begin // check params - ProcAddress := AFunctionValue.DataAddress; + ProcAddress := AFunctionValue.EntryPCAddress; if not IsReadableLoc(ProcAddress) then begin DebugLn(['Error proc addr']); AnError := CreateError(fpErrAnyError, ['Unable to calculate function address']);