FpDebug: Fix DW_OP_reg0..31 should return the register-location, not the value in the register (except for DW_AT_frame_base). See note_732607024 in merge-request !28

This commit is contained in:
Martin 2021-11-14 11:29:15 +01:00
parent 0a7f1b1da9
commit eac49ae44f
2 changed files with 47 additions and 4 deletions

View File

@ -523,6 +523,9 @@ type
AnInitLocParserData: PInitLocParserData = nil): Boolean; virtual;
function ComputeDataMemberAddress(const AnInformationEntry: TDwarfInformationEntry;
AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation): Boolean; inline;
(* ConstRefOrExprFromAttrData:
See DWARF spec "2.19 Static and Dynamic Properties of Types"
*)
function ConstRefOrExprFromAttrData(const AnAttribData: TDwarfAttribData;
AValueObj: TFpValueDwarf; out AValue: Int64;
AReadState: PFpDwarfAtEntryDataReadState = nil;
@ -3796,6 +3799,8 @@ function TFpSymbolDwarf.ConstRefOrExprFromAttrData(
const AnAttribData: TDwarfAttribData; AValueObj: TFpValueDwarf; out
AValue: Int64; AReadState: PFpDwarfAtEntryDataReadState;
ADataSymbol: PFpSymbolDwarfData): Boolean;
(* See DWARF spec "2.19 Static and Dynamic Properties of Types"
*)
var
Form: Cardinal;
FwdInfoPtr: Pointer;
@ -3874,6 +3879,16 @@ begin
else
if Form in [DW_FORM_block, DW_FORM_block1, DW_FORM_block2, DW_FORM_block4]
then begin
(* Dwarf Spec:
"For a block / For an exprloc, the value is interpreted as a DWARF
expression; evaluation of the expression yields the value of the
attribute"
- The examples given in the spec, show that the "location" returned, is
not used as address. It is treated as the integer result.
- Thus this not be a register-location.
- It may be a constant (DW_OP_lit/DW_OP_const), but those should probably
be DW_FORM_data.
*)
// TODO: until there always will be an AValueObj
if AValueObj = nil then begin
if AReadState <> nil then
@ -3893,6 +3908,7 @@ begin
InitLocParserData.ObjectDataAddrPush := False;
Result := LocationFromAttrData(AnAttribData, AValueObj, t, @InitLocParserData);
if Result then begin
assert(t.MType in [mlfTargetMem, mlfConstant], 'TFpSymbolDwarf.ConstRefOrExprFromAttrData: t.MType in [mlfTargetMem, mlfConstant]');
AValue := Int64(t.Address);
end
else begin
@ -5903,10 +5919,13 @@ begin
FFrameBaseParser := TDwarfLocationExpression.Create(@Val[0], Length(Val), CompilationUnit,
ASender.Context);
FFrameBaseParser.IsDwAtFrameBase := True;
FFrameBaseParser.Evaluate;
end;
rd := FFrameBaseParser.ResultData;
// TODO: should mlfConstant be allowed?
assert(rd.MType in [mlfTargetMem, mlfConstant], 'TFpSymbolDwarfDataProc.GetFrameBase: rd.MType in [mlfTargetMem, mlfConstant]');
if IsValidLoc(rd) then
Result := rd.Address;

View File

@ -787,6 +787,7 @@ type
FContext: TFpDbgLocationContext;
FCurrentObjectAddress: TFpDbgMemLocation;
FFrameBase: TDbgPtr;
FIsDwAtFrameBase: Boolean;
FLastError: TFpError;
FOnFrameBaseNeeded: TNotifyEvent;
FStack: TDwarfLocationStack;
@ -807,6 +808,7 @@ type
property Context: TFpDbgLocationContext read FContext write FContext;
// for DW_OP_push_object_address
property CurrentObjectAddress: TFpDbgMemLocation read FCurrentObjectAddress write FCurrentObjectAddress;
property IsDwAtFrameBase: Boolean read FIsDwAtFrameBase write FIsDwAtFrameBase;
end;
function ULEB128toOrdinal(var p: PByte): QWord;
@ -2247,15 +2249,37 @@ begin
DW_OP_consts: FStack.PushConst(ReadSignedFromExpression(CurData, 0));
DW_OP_lit0..DW_OP_lit31: FStack.PushConst(CurInstr^-DW_OP_lit0);
(* DW_OP_reg0..31 and DW_OP_regx
The DWARF spec does *not* specify that those should push the result on
the stack.
However it does not matter, since there can be no other instruction
after it to access the stack.
From the spec:
"A register location description must stand alone as the entire
description of an object or a piece of an object"
For DW_AT_frame_base the spec (dwarf 5) says:
"The use of one of the DW_OP_reg<n> operations in this context is
equivalent to using DW_OP_breg<n>(0) but more compact"
However, it does not say if this removes the "stand alone" restriction.
*)
DW_OP_reg0..DW_OP_reg31: begin
if not FContext.ReadRegister(CurInstr^-DW_OP_reg0, NewValue) then begin
SetError;
exit;
FStack.PushTargetRegister(CurInstr^-DW_OP_reg0);
// Dwarf-5
if FIsDwAtFrameBase then begin
EntryP := FStack.PeekForDeref;
if not ReadAddressFromMemory(EntryP^, AddrSize, NewLoc) then exit;
EntryP^ := NewLoc; // mlfTargetMem;
end;
FStack.PushConst(NewValue);
end;
DW_OP_regx: begin
FStack.PushTargetRegister(ULEB128toOrdinal(CurData));
// Dwarf-5
if FIsDwAtFrameBase then begin
EntryP := FStack.PeekForDeref;
if not ReadAddressFromMemory(EntryP^, AddrSize, NewLoc) then exit;
EntryP^ := NewLoc; // mlfTargetMem;
end;
end;
DW_OP_breg0..DW_OP_breg31: begin