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; AnInitLocParserData: PInitLocParserData = nil): Boolean; virtual;
function ComputeDataMemberAddress(const AnInformationEntry: TDwarfInformationEntry; function ComputeDataMemberAddress(const AnInformationEntry: TDwarfInformationEntry;
AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation): Boolean; inline; AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation): Boolean; inline;
(* ConstRefOrExprFromAttrData:
See DWARF spec "2.19 Static and Dynamic Properties of Types"
*)
function ConstRefOrExprFromAttrData(const AnAttribData: TDwarfAttribData; function ConstRefOrExprFromAttrData(const AnAttribData: TDwarfAttribData;
AValueObj: TFpValueDwarf; out AValue: Int64; AValueObj: TFpValueDwarf; out AValue: Int64;
AReadState: PFpDwarfAtEntryDataReadState = nil; AReadState: PFpDwarfAtEntryDataReadState = nil;
@ -3796,6 +3799,8 @@ function TFpSymbolDwarf.ConstRefOrExprFromAttrData(
const AnAttribData: TDwarfAttribData; AValueObj: TFpValueDwarf; out const AnAttribData: TDwarfAttribData; AValueObj: TFpValueDwarf; out
AValue: Int64; AReadState: PFpDwarfAtEntryDataReadState; AValue: Int64; AReadState: PFpDwarfAtEntryDataReadState;
ADataSymbol: PFpSymbolDwarfData): Boolean; ADataSymbol: PFpSymbolDwarfData): Boolean;
(* See DWARF spec "2.19 Static and Dynamic Properties of Types"
*)
var var
Form: Cardinal; Form: Cardinal;
FwdInfoPtr: Pointer; FwdInfoPtr: Pointer;
@ -3874,6 +3879,16 @@ begin
else else
if Form in [DW_FORM_block, DW_FORM_block1, DW_FORM_block2, DW_FORM_block4] if Form in [DW_FORM_block, DW_FORM_block1, DW_FORM_block2, DW_FORM_block4]
then begin 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 // TODO: until there always will be an AValueObj
if AValueObj = nil then begin if AValueObj = nil then begin
if AReadState <> nil then if AReadState <> nil then
@ -3893,6 +3908,7 @@ begin
InitLocParserData.ObjectDataAddrPush := False; InitLocParserData.ObjectDataAddrPush := False;
Result := LocationFromAttrData(AnAttribData, AValueObj, t, @InitLocParserData); Result := LocationFromAttrData(AnAttribData, AValueObj, t, @InitLocParserData);
if Result then begin if Result then begin
assert(t.MType in [mlfTargetMem, mlfConstant], 'TFpSymbolDwarf.ConstRefOrExprFromAttrData: t.MType in [mlfTargetMem, mlfConstant]');
AValue := Int64(t.Address); AValue := Int64(t.Address);
end end
else begin else begin
@ -5903,10 +5919,13 @@ begin
FFrameBaseParser := TDwarfLocationExpression.Create(@Val[0], Length(Val), CompilationUnit, FFrameBaseParser := TDwarfLocationExpression.Create(@Val[0], Length(Val), CompilationUnit,
ASender.Context); ASender.Context);
FFrameBaseParser.IsDwAtFrameBase := True;
FFrameBaseParser.Evaluate; FFrameBaseParser.Evaluate;
end; end;
rd := FFrameBaseParser.ResultData; 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 if IsValidLoc(rd) then
Result := rd.Address; Result := rd.Address;

View File

@ -787,6 +787,7 @@ type
FContext: TFpDbgLocationContext; FContext: TFpDbgLocationContext;
FCurrentObjectAddress: TFpDbgMemLocation; FCurrentObjectAddress: TFpDbgMemLocation;
FFrameBase: TDbgPtr; FFrameBase: TDbgPtr;
FIsDwAtFrameBase: Boolean;
FLastError: TFpError; FLastError: TFpError;
FOnFrameBaseNeeded: TNotifyEvent; FOnFrameBaseNeeded: TNotifyEvent;
FStack: TDwarfLocationStack; FStack: TDwarfLocationStack;
@ -807,6 +808,7 @@ type
property Context: TFpDbgLocationContext read FContext write FContext; property Context: TFpDbgLocationContext read FContext write FContext;
// for DW_OP_push_object_address // for DW_OP_push_object_address
property CurrentObjectAddress: TFpDbgMemLocation read FCurrentObjectAddress write FCurrentObjectAddress; property CurrentObjectAddress: TFpDbgMemLocation read FCurrentObjectAddress write FCurrentObjectAddress;
property IsDwAtFrameBase: Boolean read FIsDwAtFrameBase write FIsDwAtFrameBase;
end; end;
function ULEB128toOrdinal(var p: PByte): QWord; function ULEB128toOrdinal(var p: PByte): QWord;
@ -2247,15 +2249,37 @@ begin
DW_OP_consts: FStack.PushConst(ReadSignedFromExpression(CurData, 0)); DW_OP_consts: FStack.PushConst(ReadSignedFromExpression(CurData, 0));
DW_OP_lit0..DW_OP_lit31: FStack.PushConst(CurInstr^-DW_OP_lit0); 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 DW_OP_reg0..DW_OP_reg31: begin
if not FContext.ReadRegister(CurInstr^-DW_OP_reg0, NewValue) then begin FStack.PushTargetRegister(CurInstr^-DW_OP_reg0);
SetError; // Dwarf-5
exit; if FIsDwAtFrameBase then begin
EntryP := FStack.PeekForDeref;
if not ReadAddressFromMemory(EntryP^, AddrSize, NewLoc) then exit;
EntryP^ := NewLoc; // mlfTargetMem;
end; end;
FStack.PushConst(NewValue);
end; end;
DW_OP_regx: begin DW_OP_regx: begin
FStack.PushTargetRegister(ULEB128toOrdinal(CurData)); 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; end;
DW_OP_breg0..DW_OP_breg31: begin DW_OP_breg0..DW_OP_breg31: begin