FpDebug: implement watching bitpacked array/record

git-svn-id: trunk@62012 -
This commit is contained in:
martin 2019-10-09 20:06:21 +00:00
parent f96c6b9f66
commit cbe21ff4f3
12 changed files with 1215 additions and 500 deletions

File diff suppressed because it is too large Load Diff

View File

@ -191,6 +191,8 @@ const
DW_AT_elemental = $66 ; // flag
DW_AT_pure = $67 ; // flag
DW_AT_recursive = $68 ; // flag
// -- DWARF 4 --
DW_AT_data_bit_offset = $6b ; // constant // block, constant, reference
// --- ---
DW_AT_lo_user = $2000; // ---
DW_AT_hi_user = $3fff; // ---

View File

@ -1788,6 +1788,7 @@ procedure TDwarfLocationStack.PushConst(const AVal: TDBGPtr);
begin
if Length(FList) <= FCount then
IncCapacity;
FList[FCount] := Default(TFpDbgMemLocation);
with FList[FCount] do begin
Address := AVal;
MType := mlfConstant;
@ -1799,6 +1800,7 @@ procedure TDwarfLocationStack.PushTargetMem(const AVal: TDBGPtr);
begin
if Length(FList) <= FCount then
IncCapacity;
FList[FCount] := Default(TFpDbgMemLocation);
with FList[FCount] do begin
Address := AVal;
MType := mlfTargetMem;
@ -1900,7 +1902,7 @@ var
begin
//TODO: zero fill / sign extend
if (ASize > SizeOf(AValue)) or (ASize > AddrSize) then exit(False);
Result := FMemManager.ReadAddress(AnAddress, ASize, AValue, FContext);
Result := FMemManager.ReadAddress(AnAddress, SizeVal(ASize), AValue, FContext);
if not Result then
SetError;
end;
@ -1909,7 +1911,7 @@ var
begin
//TODO: zero fill / sign extend
if (ASize > SizeOf(AValue)) or (ASize > AddrSize) then exit(False);
AValue := FMemManager.ReadAddressEx(AnAddress, AnAddrSpace, ASize, FContext);
AValue := FMemManager.ReadAddressEx(AnAddress, AnAddrSpace, SizeVal(ASize), FContext);
Result := IsValidLoc(AValue);
if not Result then
SetError;

View File

@ -118,7 +118,7 @@ type
function GetDataAddressNext(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation;
out ADoneWork: Boolean; ATargetType: TFpSymbolDwarfType): Boolean; override;
function GetTypedValueObject(ATypeCast: Boolean; AnOuterType: TFpSymbolDwarfType = nil): TFpValueDwarf; override;
function DataSize: Integer; override;
function DataSize: TFpDbgValueSize; override;
public
property IsInternalPointer: Boolean read GetIsInternalPointer write FIsInternalPointer; // Class (also DynArray, but DynArray is handled without this)
end;
@ -668,7 +668,7 @@ begin
Result := AValueObj.MemManager <> nil;
if not Result then
exit;
AnAddress := AValueObj.MemManager.ReadAddress(AnAddress, CompilationUnit.AddressSize);
AnAddress := AValueObj.MemManager.ReadAddress(AnAddress, SizeVal(CompilationUnit.AddressSize));
Result := IsValidLoc(AnAddress);
if (not Result) and
@ -689,14 +689,14 @@ begin
Result := inherited GetTypedValueObject(ATypeCast, AnOuterType);
end;
function TFpSymbolDwarfFreePascalTypePointer.DataSize: Integer;
function TFpSymbolDwarfFreePascalTypePointer.DataSize: TFpDbgValueSize;
var
Size: QWord;
Size: TFpDbgValueSize;
begin
if Kind = skClass then begin
// TODO: get a value object // though fpc does not yet write variable sizes
if not NestedTypeInfo.ReadSize(nil, Size) then begin
Result := 0;
Result := ZeroSize;
SetLastError(CreateError(fpErrAnyError, ['unknown size']));
exit;
end;
@ -780,7 +780,8 @@ end;
function TFpValueDwarfV2FreePascalShortString.GetAsString: AnsiString;
var
len, Size: QWord;
len: QWord;
Size: TFpDbgValueSize;
LenSym, StSym: TFpValueDwarf;
begin
if FValueDone then
@ -795,7 +796,7 @@ begin
SetLastError(CreateError(fpErrAnyError));
exit('');
end;
if (Size < 0) or (len > Size) then begin
if (Size < len) then begin
SetLastError(CreateError(fpErrAnyError));
exit('');
end;
@ -806,7 +807,7 @@ begin
SetLength(Result, len);
if len > 0 then
if not MemManager.ReadMemory(StSym.DataAddress, len, @Result[1]) then begin
if not MemManager.ReadMemory(StSym.DataAddress, SizeVal(len), @Result[1]) then begin
Result := ''; // TODO: error
SetLastError(MemManager.LastError);
StSym.ReleaseReference;
@ -907,7 +908,7 @@ begin
exit(0); // dyn array, but bad data
Addr.Address := Addr.Address - AddressSize;
//debugln(['TFpValueDwarfArray.GetMemberCount XXXXXXXXXXXXXXX dwarf 2 read len']);
if MemManager.ReadSignedInt(Addr, AddressSize, h) then begin
if MemManager.ReadSignedInt(Addr, SizeVal(AddressSize), h) then begin
Result := Integer(h)+1;
exit;
end
@ -928,7 +929,7 @@ var
Info: TDwarfInformationEntry;
t: Cardinal;
t2: TFpSymbol;
CharSize: QWord;
CharSize: TFpDbgValueSize;
begin
Result := FArrayOrStringType;
if Result <> iasUnknown then
@ -959,8 +960,8 @@ begin
// TODO: check the location parser, if it is a reference
//FIsShortString := iasShortString;
if not t2.ReadSize(nil, CharSize) then
CharSize := 0; // TODO: error
if (CharSize = 2) then
CharSize := ZeroSize; // TODO: error
if (CharSize.Size = 2) then
FArrayOrStringType := iasUnicodeString
else
FArrayOrStringType := iasAnsiString;
@ -1095,7 +1096,7 @@ begin
// read data and check for DW_OP_shr ?
Addr2 := Addr;
Addr2.Address := Addr2.Address - AddressSize;
if MemManager.ReadSignedInt(Addr2, AddressSize, i) then begin
if MemManager.ReadSignedInt(Addr2, SizeVal(AddressSize), i) then begin
if (i shr 1) = HighBound then
HighBound := i;
end
@ -1116,7 +1117,7 @@ begin
if t.Kind = skWideString then begin
SetLength(WResult, HighBound-LowBound+1);
if not MemManager.ReadMemory(Addr, (HighBound-LowBound+1)*2, @WResult[1]) then begin
if not MemManager.ReadMemory(Addr, SizeVal((HighBound-LowBound+1)*2), @WResult[1]) then begin
WResult := '';
SetLastError(MemManager.LastError);
end;
@ -1124,7 +1125,7 @@ begin
end else begin
SetLength(Result, HighBound-LowBound+1);
if not MemManager.ReadMemory(Addr, HighBound-LowBound+1, @Result[1]) then begin
if not MemManager.ReadMemory(Addr, SizeVal(HighBound-LowBound+1), @Result[1]) then begin
Result := '';
SetLastError(MemManager.LastError);
end;

View File

@ -96,7 +96,7 @@ type
private
FEvalFlags: set of (efSizeDone, efSizeUnavail);
FLastError: TFpError;
FSize: QWord;
FSize: TFpDbgValueSize;
protected
procedure Reset; virtual; // keeps lastmember and structureninfo
procedure SetLastError(ALastError: TFpError);
@ -112,9 +112,9 @@ type
function GetAsFloat: Extended; virtual;
function GetAddress: TFpDbgMemLocation; virtual;
function DoGetSize(out ASize: QWord): Boolean; virtual;
function DoGetSize(out ASize: TFpDbgValueSize): Boolean; virtual;
function GetDataAddress: TFpDbgMemLocation; virtual;
function GetDataSize: QWord; virtual;
function GetDataSize: TFpDbgValueSize; virtual;
function GetHasBounds: Boolean; virtual;
function GetOrdHighBound: Int64; virtual;
@ -137,7 +137,7 @@ type
constructor Create;
property RefCount;
function GetSize(out ASize: QWord): Boolean; inline;
function GetSize(out ASize: TFpDbgValueSize): Boolean; inline;
// Kind: determines which types of value are available
property Kind: TDbgSymbolKind read GetKind;
@ -159,7 +159,7 @@ type
*)
property Address: TFpDbgMemLocation read GetAddress;
property DataAddress: TFpDbgMemLocation read GetDataAddress; //
property DataSize: QWord read GetDataSize;
property DataSize: TFpDbgValueSize read GetDataSize;
property HasBounds: Boolean read GetHasBounds;
property OrdLowBound: Int64 read GetOrdLowBound; // need typecast for QuadWord
@ -352,7 +352,7 @@ type
procedure NameNeeded; virtual;
procedure SymbolTypeNeeded; virtual;
procedure AddressNeeded; virtual;
function DoReadSize(const AValueObj: TFpValue; out ASize: QWord): Boolean; virtual;
function DoReadSize(const AValueObj: TFpValue; out ASize: TFpDbgValueSize): Boolean; virtual;
procedure TypeInfoNeeded; virtual;
procedure MemberVisibilityNeeded; virtual;
//procedure Needed; virtual;
@ -367,7 +367,7 @@ type
// Memory; Size is also part of type (byte vs word vs ...)
property Address: TFpDbgMemLocation read GetAddress; // used by Proc/func
// ReadSize: Return False means no value available, and an error may or may not have occurred
function ReadSize(const AValueObj: TFpValue; out ASize: QWord{TDbgPtr}): Boolean; inline;
function ReadSize(const AValueObj: TFpValue; out ASize: TFpDbgValueSize): Boolean; inline;
// TypeInfo used by
// stValue (Variable): Type
// stType: Pointer: type pointed to / Array: Element Type / Func: Result / Class: itheritance
@ -431,7 +431,7 @@ type
procedure KindNeeded; override;
procedure NameNeeded; override;
procedure SymbolTypeNeeded; override;
function DoReadSize(const AValueObj: TFpValue; out ASize: QWord): Boolean; override;
function DoReadSize(const AValueObj: TFpValue; out ASize: TFpDbgValueSize): Boolean; override;
procedure TypeInfoNeeded; override;
procedure MemberVisibilityNeeded; override;
@ -672,7 +672,7 @@ begin
Result := InvalidLoc;
end;
function TFpValue.DoGetSize(out ASize: QWord): Boolean;
function TFpValue.DoGetSize(out ASize: TFpDbgValueSize): Boolean;
var
ti: TFpSymbol;
begin
@ -691,12 +691,12 @@ begin
Result := Address;
end;
function TFpValue.GetDataSize: QWord;
function TFpValue.GetDataSize: TFpDbgValueSize;
begin
GetSize(Result);
end;
function TFpValue.GetSize(out ASize: QWord): Boolean;
function TFpValue.GetSize(out ASize: TFpDbgValueSize): Boolean;
begin
Result := False;
if (efSizeUnavail in FEvalFlags) then // If there was an error, then LastError should still be set
@ -914,8 +914,8 @@ begin
inherited Destroy;
end;
function TFpSymbol.ReadSize(const AValueObj: TFpValue; out ASize: QWord
): Boolean;
function TFpSymbol.ReadSize(const AValueObj: TFpValue; out
ASize: TFpDbgValueSize): Boolean;
begin
Result := DoReadSize(AValueObj, ASize);
end;
@ -1120,10 +1120,10 @@ begin
SetAddress(InvalidLoc);
end;
function TFpSymbol.DoReadSize(const AValueObj: TFpValue; out ASize: QWord
): Boolean;
function TFpSymbol.DoReadSize(const AValueObj: TFpValue; out
ASize: TFpDbgValueSize): Boolean;
begin
ASize := 0;
ASize := ZeroSize;
Result := False;
end;
@ -1206,7 +1206,7 @@ begin
end;
function TFpSymbolForwarder.DoReadSize(const AValueObj: TFpValue; out
ASize: QWord): Boolean;
ASize: TFpDbgValueSize): Boolean;
var
p: TFpSymbol;
begin

View File

@ -92,6 +92,7 @@ begin
i := FFpSymbolInfo.FSymbolList.IndexOf(AName);
if i > -1 then
begin
val := Default(TFpDbgMemLocation);
val.Address:=FFpSymbolInfo.FSymbolList.Data[i];
val.MType:=mlfTargetMem;
result := TFpValueConstAddress.Create(val);

File diff suppressed because it is too large Load Diff

View File

@ -767,13 +767,13 @@ function TFpPascalPrettyPrinter.InternalPrintValue(out APrintedValue: String;
procedure DoInt;
var
n: Integer;
ValSize: QWord;
ValSize: TFpDbgValueSize;
begin
case ADisplayFormat of
wdfUnsigned: APrintedValue := IntToStr(QWord(AValue.AsInteger));
wdfHex: begin
if (svfSize in AValue.FieldFlags) and AValue.GetSize(ValSize) then
n := ValSize* 2
n := SizeToFullBytes(ValSize)* 2
else begin
n := 16;
if QWord(AValue.AsInteger) <= high(Cardinal) then n := 8;
@ -797,13 +797,13 @@ function TFpPascalPrettyPrinter.InternalPrintValue(out APrintedValue: String;
procedure DoCardinal;
var
n: Integer;
ValSize: QWord;
ValSize: TFpDbgValueSize;
begin
case ADisplayFormat of
wdfDecimal: APrintedValue := IntToStr(Int64(AValue.AsCardinal));
wdfHex: begin
if (svfSize in AValue.FieldFlags) and AValue.GetSize(ValSize) then
n := ValSize* 2
n := SizeToFullBytes(ValSize)* 2
else begin
n := 16;
if AValue.AsCardinal <= high(Cardinal) then n := 8;
@ -960,7 +960,7 @@ function TFpPascalPrettyPrinter.InternalPrintValue(out APrintedValue: String;
end;
if (MemManager <> nil) and (MemManager.CacheManager <> nil) then
Cache := MemManager.CacheManager.AddCache(AValue.DataAddress.Address, AValue.DataSize)
Cache := MemManager.CacheManager.AddCache(AValue.DataAddress.Address, SizeToFullBytes(AValue.DataSize))
else
Cache := nil;
try
@ -1114,7 +1114,7 @@ var
MemSize: Integer;
MemDest: array of Byte;
i: Integer;
ValSize: QWord;
ValSize: TFpDbgValueSize;
begin
if ADBGTypeInfo <> nil then ADBGTypeInfo^ := nil;
if ANestLevel > 0 then begin
@ -1126,21 +1126,21 @@ begin
MemAddr := UnInitializedLoc;
if svfDataAddress in AValue.FieldFlags then begin
MemAddr := AValue.DataAddress;
MemSize := AValue.DataSize;
MemSize := SizeToFullBytes(AValue.DataSize);
end
else
if svfAddress in AValue.FieldFlags then begin
MemAddr := AValue.Address;
if not AValue.GetSize(ValSize) then
ValSize := 256;
MemSize := ValSize;
ValSize := SizeVal(256);
MemSize := SizeToFullBytes(ValSize);
end;
if MemSize < ARepeatCount then MemSize := ARepeatCount;
if MemSize <= 0 then MemSize := 256;
if IsTargetAddr(MemAddr) then begin
SetLength(MemDest, MemSize);
if FMemManager.ReadMemory(MemAddr, MemSize, @MemDest[0]) then begin
if FMemManager.ReadMemory(MemAddr, SizeVal(MemSize), @MemDest[0]) then begin
APrintedValue := IntToHex(MemAddr.Address, AnAddressSize*2)+ ':' + LineEnding;
for i := 0 to high(MemDest) do begin
if (i > 0) and (i mod 16 = 0) then

View File

@ -522,7 +522,7 @@ type
protected
function GetFieldFlags: TFpValueFieldFlags; override;
function GetAddress: TFpDbgMemLocation; override;
function DoGetSize(out ASize: QWord): Boolean; override;
function DoGetSize(out ASize: TFpDbgValueSize): Boolean; override;
function GetAsCardinal: QWord; override; // reads men
function GetTypeInfo: TFpSymbol; override; // TODO: Cardinal? Why? // TODO: does not handle AOffset
public
@ -621,7 +621,7 @@ begin
Result := FValue.AsCardinal
else
if svfAddress in f then begin
if not FContext.MemManager.ReadUnsignedInt(FValue.Address, FContext.SizeOfAddress, Result) then
if not FContext.MemManager.ReadUnsignedInt(FValue.Address, SizeVal(FContext.SizeOfAddress), Result) then
Result := 0;
end
else
@ -638,7 +638,7 @@ var
ti: TFpSymbol;
addr: TFpDbgMemLocation;
Tmp: TFpValueConstAddress;
Size: QWord;
Size: TFpDbgValueSize;
begin
Result := nil;
@ -656,7 +656,7 @@ begin
SetLastError(CreateError(fpErrAnyError, ['Can index element of unknown size']));
exit;
end;
AIndex := AIndex * Size;
AIndex := AIndex * SizeToFullBytes(Size);
end;
addr.Address := addr.Address + AIndex;
{$POP}
@ -766,7 +766,7 @@ end;
function TFpPasParserValueDerefPointer.GetAddress: TFpDbgMemLocation;
begin
Result := FValue.DataAddress;
Result := Context.MemManager.ReadAddress(Result, Context.SizeOfAddress);
Result := Context.MemManager.ReadAddress(Result, SizeVal(Context.SizeOfAddress));
if FAddressOffset <> 0 then begin
assert(IsTargetAddr(Result ), 'TFpPasParserValueDerefPointer.GetAddress: TargetLoc(Result)');
@ -777,7 +777,8 @@ begin
end;
end;
function TFpPasParserValueDerefPointer.DoGetSize(out ASize: QWord): Boolean;
function TFpPasParserValueDerefPointer.DoGetSize(out ASize: TFpDbgValueSize
): Boolean;
var
t: TFpSymbol;
begin
@ -810,7 +811,7 @@ begin
FCardinalRead := True;
Addr := GetAddress;
if not IsReadableLoc(Addr) then exit;
FCardinal := LocToAddrOrNil(m.ReadAddress(Addr, Ctx.SizeOfAddress));
FCardinal := LocToAddrOrNil(m.ReadAddress(Addr, SizeVal(Ctx.SizeOfAddress)));
Result := FCardinal;
end;
@ -905,7 +906,7 @@ var
ti: TFpSymbol;
addr: TFpDbgMemLocation;
Tmp: TFpValueConstAddress;
Size: QWord;
Size: TFpDbgValueSize;
begin
if (AIndex = 0) or (FValue = nil) then begin
Result := FValue;
@ -927,7 +928,7 @@ begin
SetLastError(CreateError(fpErrAnyError, ['Can index element of unknown size']));
exit;
end;
AIndex := AIndex * Size;
AIndex := AIndex * SizeToFullBytes(Size);
end;
addr.Address := addr.Address + AIndex;
{$POP}

View File

@ -871,7 +871,7 @@ var
CurContext: TFpDbgInfoContext;
WatchPasExpr: TFpPascalExpression;
R: TFpValue;
s: QWord;
s: TFpDbgValueSize;
begin
assert(FInternalBreakpoint=nil);
debuglnEnter(DBG_BREAKPOINTS, ['>> TFPBreakpoint.SetBreak ADD ',FSource,':',FLine,'/',dbghex(Address),' ' ]);
@ -887,7 +887,7 @@ begin
// TODO: Cache current value
if WatchPasExpr.Valid and IsTargetNotNil(R.Address) and R.GetSize(s) then begin
// pass context
FInternalBreakpoint := TFpDebugDebugger(Debugger).AddWatch(R.Address.Address, s, WatchKind, WatchScope);
FInternalBreakpoint := TFpDebugDebugger(Debugger).AddWatch(R.Address.Address, SizeToFullBytes(s), WatchKind, WatchScope);
end;
WatchPasExpr.Free;
CurContext.ReleaseReference;
@ -1412,16 +1412,16 @@ begin
if (ResValue.Kind = skClass) and (ResValue.AsCardinal <> 0) and (defClassAutoCast in EvalFlags)
then begin
CastName := '';
if FMemManager.ReadAddress(ResValue.DataAddress, AContext.SizeOfAddress, ClassAddr) then begin
if FMemManager.ReadAddress(ResValue.DataAddress, SizeVal(AContext.SizeOfAddress), ClassAddr) then begin
{$PUSH}{$Q-}
ClassAddr.Address := ClassAddr.Address + TDBGPtr(3 * AContext.SizeOfAddress);
{$POP}
if FMemManager.ReadAddress(ClassAddr, AContext.SizeOfAddress, CNameAddr) then begin
if (FMemManager.ReadUnsignedInt(CNameAddr, 1, NameLen)) then
if FMemManager.ReadAddress(ClassAddr, SizeVal(AContext.SizeOfAddress), CNameAddr) then begin
if (FMemManager.ReadUnsignedInt(CNameAddr, SizeVal(1), NameLen)) then
if NameLen > 0 then begin
SetLength(CastName, NameLen);
CNameAddr.Address := CNameAddr.Address + 1;
FMemManager.ReadMemory(CNameAddr, NameLen, @CastName[1]);
FMemManager.ReadMemory(CNameAddr, SizeVal(NameLen), @CastName[1]);
PasExpr2 := TFpPascalExpression.Create(CastName+'('+AExpression+')', AContext);
PasExpr2.ResultValue;
if PasExpr2.Valid then begin

View File

@ -1052,14 +1052,14 @@ DebugLn(DBG_VERBOSE, [ErrorHandler.ErrorAsString(PasExpr.Error)]);
if (ResValue.Kind = skClass) and (ResValue.AsCardinal <> 0) and (defClassAutoCast in EvalFlags)
then begin
CastName := '';
if FMemManager.ReadAddress(ResValue.DataAddress, Ctx.SizeOfAddress, ClassAddr) then begin
if FMemManager.ReadAddress(ResValue.DataAddress, SizeVal(Ctx.SizeOfAddress), ClassAddr) then begin
ClassAddr.Address := ClassAddr.Address + 3 * Ctx.SizeOfAddress;
if FMemManager.ReadAddress(ClassAddr, Ctx.SizeOfAddress, CNameAddr) then begin
if (FMemManager.ReadUnsignedInt(CNameAddr, 1, NameLen)) then
if FMemManager.ReadAddress(ClassAddr, SizeVal(Ctx.SizeOfAddress), CNameAddr) then begin
if (FMemManager.ReadUnsignedInt(CNameAddr, SizeVal(1), NameLen)) then
if NameLen > 0 then begin
SetLength(CastName, NameLen);
CNameAddr.Address := CNameAddr.Address + 1;
FMemManager.ReadMemory(CNameAddr, NameLen, @CastName[1]);
FMemManager.ReadMemory(CNameAddr, SizeVal(NameLen), @CastName[1]);
PasExpr2 := TFpPascalExpression.Create(CastName+'('+AExpression+')', Ctx);
PasExpr2.ResultValue;
if PasExpr2.Valid then begin

View File

@ -1494,14 +1494,14 @@ DebugLn(DBG_VERBOSE, [ErrorHandler.ErrorAsString(PasExpr.Error)]);
if (ResValue.Kind = skClass) and (ResValue.AsCardinal <> 0) and (defClassAutoCast in EvalFlags)
then begin
CastName := '';
if FMemManager.ReadAddress(ResValue.DataAddress, Ctx.SizeOfAddress, ClassAddr) then begin
if FMemManager.ReadAddress(ResValue.DataAddress, SizeVal(Ctx.SizeOfAddress), ClassAddr) then begin
ClassAddr.Address := ClassAddr.Address + 3 * Ctx.SizeOfAddress;
if FMemManager.ReadAddress(ClassAddr, Ctx.SizeOfAddress, CNameAddr) then begin
if (FMemManager.ReadUnsignedInt(CNameAddr, 1, NameLen)) then
if FMemManager.ReadAddress(ClassAddr, SizeVal(Ctx.SizeOfAddress), CNameAddr) then begin
if (FMemManager.ReadUnsignedInt(CNameAddr, SizeVal(1), NameLen)) then
if NameLen > 0 then begin
SetLength(CastName, NameLen);
CNameAddr.Address := CNameAddr.Address + 1;
FMemManager.ReadMemory(CNameAddr, NameLen, @CastName[1]);
FMemManager.ReadMemory(CNameAddr, SizeVal(NameLen), @CastName[1]);
PasExpr2 := TFpPascalExpression.Create(CastName+'('+AExpression+')', Ctx);
PasExpr2.ResultValue;
if PasExpr2.Valid then begin