mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-04 16:37:19 +01:00
FpDebug: Implement location-lists (Dwarf 2/3)
This commit is contained in:
parent
5efaac3f2f
commit
2acd136518
@ -814,7 +814,7 @@ type
|
||||
function FindProcStartEndPC(const AAdress: TDbgPtr; out AStartPC, AEndPC: TDBGPtr): boolean;
|
||||
|
||||
function GetLineAddresses(AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray; ASymInstance: TDbgInstance = nil): Boolean;
|
||||
function ContextFromProc(AThreadId, AStackFrame: Integer; AProcSym: TFpSymbol): TFpDbgLocationContext; inline; deprecated 'use TFpDbgSimpleLocationContext.Create';
|
||||
//function ContextFromProc(AThreadId, AStackFrame: Integer; AProcSym: TFpSymbol): TFpDbgLocationContext; inline; deprecated 'use TFpDbgSimpleLocationContext.Create';
|
||||
function GetLib(const AHandle: THandle; out ALib: TDbgLibrary): Boolean;
|
||||
property LibMap: TLibraryMap read FLibMap;
|
||||
property LastLibrariesLoaded: TDbgLibraryArr read GetLastLibrariesLoaded;
|
||||
@ -2382,11 +2382,11 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDbgProcess.ContextFromProc(AThreadId, AStackFrame: Integer;
|
||||
AProcSym: TFpSymbol): TFpDbgLocationContext;
|
||||
begin
|
||||
Result := TFpDbgSimpleLocationContext.Create(MemManager, LocToAddrOrNil(AProcSym.Address), DBGPTRSIZE[Mode], AThreadId, AStackFrame);
|
||||
end;
|
||||
//function TDbgProcess.ContextFromProc(AThreadId, AStackFrame: Integer;
|
||||
// AProcSym: TFpSymbol): TFpDbgLocationContext;
|
||||
//begin
|
||||
// Result := TFpDbgSimpleLocationContext.Create(MemManager, LocToAddrOrNil(AProcSym.Address), DBGPTRSIZE[Mode], AThreadId, AStackFrame);
|
||||
//end;
|
||||
|
||||
function TDbgProcess.GetLib(const AHandle: THandle; out ALib: TDbgLibrary): Boolean;
|
||||
begin
|
||||
|
||||
@ -580,6 +580,8 @@ type
|
||||
AValueObj: TFpValueDwarf; out AValue: Int64;
|
||||
AReadState: PFpDwarfAtEntryDataReadState = nil;
|
||||
ADataSymbol: PFpSymbolDwarfData = nil): Boolean;
|
||||
function LocationExprFromLocationList(const AnAttribData: TDwarfAttribData; AValueObj: TFpValueDwarf;
|
||||
out AValue: TByteDynArray): boolean;
|
||||
function LocationFromAttrData(const AnAttribData: TDwarfAttribData; AValueObj: TFpValueDwarf;
|
||||
var AnAddress: TFpDbgMemLocation; // kept, if tag does not exist
|
||||
AnInitLocParserData: PInitLocParserData = nil;
|
||||
@ -4497,6 +4499,81 @@ begin
|
||||
AReadState^ := rfError;
|
||||
end;
|
||||
|
||||
function TFpSymbolDwarf.LocationExprFromLocationList(
|
||||
const AnAttribData: TDwarfAttribData; AValueObj: TFpValueDwarf; out
|
||||
AValue: TByteDynArray): boolean;
|
||||
var
|
||||
LocSect: TDwarfSectionInfo;
|
||||
ValOffs: QWord;
|
||||
LocList, LocListEnd: Pointer;
|
||||
Sz, Len: Integer;
|
||||
BaseAddr, PC: TDBGPtr;
|
||||
LowBnd, HighBnd: TDBGPtr;
|
||||
begin
|
||||
Result := False;
|
||||
LocSect := CompilationUnit.DebugFile^.Sections[dsLoc];
|
||||
if (LocSect.RawData = nil) then
|
||||
exit;
|
||||
|
||||
if InformationEntry.ReadValue(AnAttribData, ValOffs) then begin
|
||||
Sz := AValueObj.Context.SizeOfAddress;
|
||||
if ValOffs > LocSect.Size - 2 * Sz - 2 // need at least 1 pair of bounds an a 2 byte len
|
||||
then
|
||||
exit;
|
||||
LocList := LocSect.RawData + ValOffs;
|
||||
LocListEnd := LocList + LocSect.Size - 2 * Sz - 2;
|
||||
|
||||
BaseAddr := 0;
|
||||
if CompilationUnit.Version > 2 then
|
||||
BaseAddr := CompilationUnit.BaseAddress;
|
||||
PC := AValueObj.Context.Address;
|
||||
|
||||
while LocList < LocListEnd do begin
|
||||
case sz of
|
||||
4: begin
|
||||
LowBnd := PDWord(LocList)^;
|
||||
HighBnd := PDWord(LocList)[1];
|
||||
LocList := LocList + 2 * sz;
|
||||
if LowBnd = high(DWORD) then begin
|
||||
BaseAddr := HighBnd;
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
8: begin
|
||||
LowBnd := PQWord(LocList)^;
|
||||
HighBnd := PQWord(LocList)[1];
|
||||
LocList := LocList + 2 * sz;
|
||||
if LowBnd = high(QWORD) then begin
|
||||
BaseAddr := HighBnd;
|
||||
continue;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (LowBnd = 0) and (HighBnd = 0) then
|
||||
exit; // not found
|
||||
|
||||
Len := PWord(LocList)^;
|
||||
|
||||
LowBnd := LowBnd + BaseAddr;
|
||||
HighBnd := HighBnd + BaseAddr;
|
||||
|
||||
if (PC >= LowBnd) and (PC < HighBnd) then begin
|
||||
// found
|
||||
SetLength(AValue, Len);
|
||||
if Len > 0 then
|
||||
move((LocList+2)^, AValue[0], Len);
|
||||
Result := True;
|
||||
exit;
|
||||
end;
|
||||
|
||||
LocList := LocList + 2 * Len;
|
||||
end;
|
||||
|
||||
SetLastError(AValueObj, CreateError(fpErrAnyError));
|
||||
end;
|
||||
end;
|
||||
|
||||
function TFpSymbolDwarf.LocationFromAttrData(
|
||||
const AnAttribData: TDwarfAttribData; AValueObj: TFpValueDwarf;
|
||||
var AnAddress: TFpDbgMemLocation; AnInitLocParserData: PInitLocParserData;
|
||||
@ -4504,19 +4581,32 @@ function TFpSymbolDwarf.LocationFromAttrData(
|
||||
var
|
||||
Val: TByteDynArray;
|
||||
LocationParser: TDwarfLocationExpression;
|
||||
AForm: Cardinal;
|
||||
begin
|
||||
//debugln(FPDBG_DWARF_VERBOSE, ['TDbgDwarfIdentifier.LocationFromAttrData', ClassName, ' ',Name, ' ', DwarfAttributeToString(ATag)]);
|
||||
|
||||
Result := False;
|
||||
AnAddress := InvalidLoc;
|
||||
|
||||
//TODO: avoid copying data
|
||||
// DW_AT_data_member_location in members [ block or const]
|
||||
// DW_AT_location [block or reference] todo: const
|
||||
if not InformationEntry.ReadValue(AnAttribData, Val) then begin
|
||||
DebugLn(FPDBG_DWARF_VERBOSE, ['LocationFromAttrData: failed to read DW_AT_location']);
|
||||
SetLastError(AValueObj, CreateError(fpErrAnyError));
|
||||
exit;
|
||||
AForm := AnAttribData.InformationEntry.AttribForm[AnAttribData.Idx];
|
||||
if (AForm = DW_FORM_data4) or (AForm = DW_FORM_data8) then begin
|
||||
// location list
|
||||
if not LocationExprFromLocationList(AnAttribData, AValueObj, Val) then begin
|
||||
DebugLn(FPDBG_DWARF_VERBOSE, ['LocationFromAttrData: failed to read DW_AT_location from loc-list']);
|
||||
if not IsError(AValueObj.LastError) then
|
||||
SetLastError(AValueObj, CreateError(fpErrAnyError));
|
||||
exit;
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
//TODO: avoid copying data
|
||||
// DW_AT_data_member_location in members [ block or const]
|
||||
// DW_AT_location [block or reference] todo: const
|
||||
if not InformationEntry.ReadValue(AnAttribData, Val) then begin
|
||||
DebugLn(FPDBG_DWARF_VERBOSE, ['LocationFromAttrData: failed to read DW_AT_location']);
|
||||
SetLastError(AValueObj, CreateError(fpErrAnyError));
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
if Length(Val) = 0 then begin
|
||||
|
||||
@ -690,8 +690,8 @@ type
|
||||
FAddressMap: TMap; // Holds a key for each DW_TAG_subprogram / TFpSymbolDwarfDataProc, stores TDwarfAddressInfo
|
||||
FAddressMapBuild: Boolean;
|
||||
|
||||
FMinPC: QWord; // the min and max PC value found in this unit.
|
||||
FMaxPC: QWord; //
|
||||
FMinPC: TDBGPtr; // the min and max PC value found in this unit.
|
||||
FMaxPC: TDBGPtr; //
|
||||
FFirstScope: TDwarfScopeInfo;
|
||||
FScopeList: TDwarfScopeList;
|
||||
FCompUnitScope: TDwarfScopeInfo;
|
||||
@ -755,6 +755,7 @@ type
|
||||
property UnitName: String read GetUnitName;
|
||||
property IdentifierCase: Integer read FIdentifierCase;
|
||||
property Producer: String read FProducer;
|
||||
property BaseAddress: TDBGPtr read FMinPC;
|
||||
|
||||
property Version: Word read FVersion;
|
||||
//property AbbrevOffset: QWord read FAbbrevOffset;
|
||||
|
||||
@ -71,6 +71,7 @@ resourcestring
|
||||
MsgfpErrLocationParserInit = 'Internal Error: Cannot calculate location (Init).';
|
||||
MsgfpErrLocationParserMinStack = 'Not enough elements on stack.'; // internally used
|
||||
MsgfpErrLocationParserNoAddressOnStack = 'Not an address on stack'; // internally used
|
||||
MsgfpErrLocationNotInList = 'Value not available at current code-location';
|
||||
|
||||
// 10000 Process/Control errors
|
||||
MsgfpErrCreateProcess = 'Failed to start process "%1:s".%0:sError message: %2:d "%3:s".%0:s%4:s';
|
||||
@ -109,6 +110,7 @@ const
|
||||
fpErrLocationParserInit = TFpErrorCode(202);
|
||||
fpErrLocationParserMinStack = TFpErrorCode(203);
|
||||
fpErrLocationParserNoAddressOnStack = TFpErrorCode(204);
|
||||
fpErrLocationNotInList = TFpErrorCode(210);
|
||||
|
||||
// 500 parser
|
||||
fpErrPasParserEmptyExpression = TFpErrorCode(500);
|
||||
@ -312,6 +314,7 @@ begin
|
||||
fpErrLocationParserInit: Result := MsgfpErrLocationParserInit;
|
||||
fpErrLocationParserMinStack: Result := MsgfpErrLocationParserMinStack;
|
||||
fpErrLocationParserNoAddressOnStack: Result := MsgfpErrLocationParserNoAddressOnStack;
|
||||
fpErrLocationNotInList: Result := MsgfpErrLocationNotInList;
|
||||
|
||||
fpErrCreateProcess: Result := MsgfpErrCreateProcess;
|
||||
fpErrAttachProcess: Result := MsgfpErrAttachProcess;
|
||||
|
||||
@ -120,7 +120,7 @@ begin
|
||||
ProcVal := ProcSymbol.Value;
|
||||
if (ProcVal <> nil) then begin
|
||||
AContext := TFpDbgSimpleLocationContext.Create(AMemManager,
|
||||
LocToAddrOrNil(ProcSymbol.Address), ATargetWidth div 8, AThread.ID, ADbgCallStack.Index);
|
||||
LocToAddrOrNil(TargetLoc(ADbgCallStack.AnAddress)), ATargetWidth div 8, AThread.ID, ADbgCallStack.Index);
|
||||
|
||||
if AContext <> nil then begin
|
||||
TFpValueDwarf(ProcVal).Context := AContext;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user