mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-11 01:48:17 +02:00
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:
parent
0a7f1b1da9
commit
eac49ae44f
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user