FpDebug: Implement location-lists (Dwarf 2/3)

This commit is contained in:
Martin 2023-11-29 13:25:29 +01:00
parent 5efaac3f2f
commit 2acd136518
5 changed files with 110 additions and 16 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;