mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-04 14:00:41 +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;
|
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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user