mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-17 03:49:30 +02:00
FPDebug: mem-manager
git-svn-id: trunk@44068 -
This commit is contained in:
parent
e7d4722d9d
commit
f580daeb56
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1291,6 +1291,7 @@ components/fpdebug/test/testdwarfsetuparray.pas svneol=native#text/pascal
|
|||||||
components/fpdebug/test/testdwarfsetupbasic.pas svneol=native#text/pascal
|
components/fpdebug/test/testdwarfsetupbasic.pas svneol=native#text/pascal
|
||||||
components/fpdebug/test/testdwarfvarious.pas svneol=native#text/pascal
|
components/fpdebug/test/testdwarfvarious.pas svneol=native#text/pascal
|
||||||
components/fpdebug/test/testhelperclasses.pas svneol=native#text/pascal
|
components/fpdebug/test/testhelperclasses.pas svneol=native#text/pascal
|
||||||
|
components/fpdebug/test/testmemmanager.pas svneol=native#text/pascal
|
||||||
components/fpdebug/test/testpascalparser.pas svneol=native#text/pascal
|
components/fpdebug/test/testpascalparser.pas svneol=native#text/pascal
|
||||||
components/fpdebug/test/testtypeinfo.pas svneol=native#text/pascal
|
components/fpdebug/test/testtypeinfo.pas svneol=native#text/pascal
|
||||||
components/fppkg/images/archive.png -text
|
components/fppkg/images/archive.png -text
|
||||||
|
@ -629,6 +629,8 @@ type
|
|||||||
private
|
private
|
||||||
FSize: Integer;
|
FSize: Integer;
|
||||||
protected
|
protected
|
||||||
|
function OrdOrDataAddr: TFpDbgMemLocation;
|
||||||
|
function DataAddr: TFpDbgMemLocation;
|
||||||
function ReadMemory(ADest: Pointer): Boolean; // ADest must point to FSize amount of bytes
|
function ReadMemory(ADest: Pointer): Boolean; // ADest must point to FSize amount of bytes
|
||||||
function CanUseTypeCastAddress: Boolean;
|
function CanUseTypeCastAddress: Boolean;
|
||||||
function GetFieldFlags: TDbgSymbolValueFieldFlags; override;
|
function GetFieldFlags: TDbgSymbolValueFieldFlags; override;
|
||||||
@ -646,7 +648,6 @@ type
|
|||||||
FEvaluated: set of (doneUInt, doneInt);
|
FEvaluated: set of (doneUInt, doneInt);
|
||||||
protected
|
protected
|
||||||
procedure Reset; override;
|
procedure Reset; override;
|
||||||
function GetCardinalValue: QWord;
|
|
||||||
function GetFieldFlags: TDbgSymbolValueFieldFlags; override;
|
function GetFieldFlags: TDbgSymbolValueFieldFlags; override;
|
||||||
function IsValidTypeCast: Boolean; override;
|
function IsValidTypeCast: Boolean; override;
|
||||||
function GetAsCardinal: QWord; override;
|
function GetAsCardinal: QWord; override;
|
||||||
@ -2095,6 +2096,25 @@ end;
|
|||||||
|
|
||||||
{ TDbgDwarfSizedSymbolValue }
|
{ TDbgDwarfSizedSymbolValue }
|
||||||
|
|
||||||
|
function TDbgDwarfSizedSymbolValue.OrdOrDataAddr: TFpDbgMemLocation;
|
||||||
|
begin
|
||||||
|
if HasTypeCastInfo and (svfOrdinal in FTypeCastSourceValue.FieldFlags) then
|
||||||
|
Result := ConstLoc(FTypeCastSourceValue.AsCardinal)
|
||||||
|
else
|
||||||
|
Result := DataAddr;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDbgDwarfSizedSymbolValue.DataAddr: TFpDbgMemLocation;
|
||||||
|
begin
|
||||||
|
if FValueSymbol <> nil then
|
||||||
|
Result := FValueSymbol.Address
|
||||||
|
else
|
||||||
|
if HasTypeCastInfo then
|
||||||
|
Result := FTypeCastSourceValue.Address
|
||||||
|
else
|
||||||
|
Result := InvalidLoc;
|
||||||
|
end;
|
||||||
|
|
||||||
function TDbgDwarfSizedSymbolValue.ReadMemory(ADest: Pointer): Boolean;
|
function TDbgDwarfSizedSymbolValue.ReadMemory(ADest: Pointer): Boolean;
|
||||||
var
|
var
|
||||||
addr: TFpDbgMemLocation;
|
addr: TFpDbgMemLocation;
|
||||||
@ -2102,15 +2122,8 @@ begin
|
|||||||
// TODO: memory representation of values is not dwarf, but platform - move
|
// TODO: memory representation of values is not dwarf, but platform - move
|
||||||
Result := False;
|
Result := False;
|
||||||
|
|
||||||
if ( (FValueSymbol <> nil) or
|
if (MemManager <> nil) then begin
|
||||||
(HasTypeCastInfo and CanUseTypeCastAddress)
|
addr := DataAddr;
|
||||||
) and (MemManager <> nil)
|
|
||||||
then begin
|
|
||||||
if FValueSymbol <> nil then
|
|
||||||
addr := FValueSymbol.Address
|
|
||||||
else
|
|
||||||
addr := FTypeCastSourceValue.Address;
|
|
||||||
|
|
||||||
Result := IsReadableLoc(addr);
|
Result := IsReadableLoc(addr);
|
||||||
if not Result then
|
if not Result then
|
||||||
exit;
|
exit;
|
||||||
@ -2566,26 +2579,6 @@ begin
|
|||||||
FEvaluated := [];
|
FEvaluated := [];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDbgDwarfNumericSymbolValue.GetCardinalValue: QWord;
|
|
||||||
begin
|
|
||||||
if (FSize <= 0) or (FSize > SizeOf(Result)) then begin
|
|
||||||
Result := inherited GetAsCardinal;
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
if HasTypeCastInfo and (svfOrdinal in FTypeCastSourceValue.FieldFlags) then begin
|
|
||||||
Result := FTypeCastSourceValue.AsCardinal;
|
|
||||||
Result := Result and (QWord(-1) shr ((SizeOf(Result)-FSize) * 8));
|
|
||||||
end
|
|
||||||
|
|
||||||
else begin
|
|
||||||
// TODO endian
|
|
||||||
Result := 0; // GetMem only reads FSize
|
|
||||||
if not ReadMemory(@Result) then // ReadMemory stores to FValue
|
|
||||||
Result := inherited GetAsCardinal;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TDbgDwarfNumericSymbolValue.GetFieldFlags: TDbgSymbolValueFieldFlags;
|
function TDbgDwarfNumericSymbolValue.GetFieldFlags: TDbgSymbolValueFieldFlags;
|
||||||
begin
|
begin
|
||||||
Result := inherited GetFieldFlags;
|
Result := inherited GetFieldFlags;
|
||||||
@ -2610,7 +2603,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
Include(FEvaluated, doneUInt);
|
Include(FEvaluated, doneUInt);
|
||||||
|
|
||||||
Result := GetCardinalValue;
|
if (FSize <= 0) or (FSize > SizeOf(Result)) then
|
||||||
|
Result := inherited GetAsCardinal
|
||||||
|
else
|
||||||
|
if not MemManager.ReadUnsignedInt(OrdOrDataAddr, FSize, Result) then
|
||||||
|
Result := 0; // TODO: error
|
||||||
|
|
||||||
FValue := Result;
|
FValue := Result;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2622,10 +2620,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
Include(FEvaluated, doneInt);
|
Include(FEvaluated, doneInt);
|
||||||
|
|
||||||
Result := Int64(GetCardinalValue);
|
if (FSize <= 0) or (FSize > SizeOf(Result)) then
|
||||||
// sign extend
|
Result := inherited GetAsInteger
|
||||||
if Result and (int64(1) shl (FSize * 8 - 1)) <> 0 then
|
else
|
||||||
Result := Result or (int64(-1) shl (FSize * 8));
|
if not MemManager.ReadSignedInt(OrdOrDataAddr, FSize, Result) then
|
||||||
|
Result := 0; // TODO: error
|
||||||
|
|
||||||
FIntValue := Result;
|
FIntValue := Result;
|
||||||
end;
|
end;
|
||||||
@ -5252,9 +5251,6 @@ end;
|
|||||||
|
|
||||||
function TDbgDwarfTypeIdentifierRef.GetDataAddress(var AnAddress: TFpDbgMemLocation;
|
function TDbgDwarfTypeIdentifierRef.GetDataAddress(var AnAddress: TFpDbgMemLocation;
|
||||||
ATargetType: TDbgDwarfTypeIdentifier): Boolean;
|
ATargetType: TDbgDwarfTypeIdentifier): Boolean;
|
||||||
//var
|
|
||||||
// Addr4: DWORD;
|
|
||||||
// Addr8: QWord;
|
|
||||||
begin
|
begin
|
||||||
if ATargetType = Self then begin
|
if ATargetType = Self then begin
|
||||||
Result := True;
|
Result := True;
|
||||||
@ -5264,18 +5260,6 @@ begin
|
|||||||
if not Result then
|
if not Result then
|
||||||
exit;
|
exit;
|
||||||
AnAddress := FCU.FOwner.MemManager.ReadAddress(AnAddress, FCU.FAddressSize);
|
AnAddress := FCU.FOwner.MemManager.ReadAddress(AnAddress, FCU.FAddressSize);
|
||||||
//case FCU.FAddressSize of
|
|
||||||
// 4: begin
|
|
||||||
// FCU.FOwner.MemManager.ReadMemory(AnAddress, 4, @Addr4);
|
|
||||||
// AnAddress := Addr4;
|
|
||||||
// end;
|
|
||||||
// 8: begin
|
|
||||||
// FCU.FOwner.MemManager.ReadMemory(AnAddress, 8, @Addr8);
|
|
||||||
// AnAddress := Addr8;
|
|
||||||
// end;
|
|
||||||
// else
|
|
||||||
// Result := False;
|
|
||||||
//end;
|
|
||||||
if Result then
|
if Result then
|
||||||
Result := inherited GetDataAddress(AnAddress, ATargetType);
|
Result := inherited GetDataAddress(AnAddress, ATargetType);
|
||||||
end;
|
end;
|
||||||
@ -5340,9 +5324,6 @@ end;
|
|||||||
|
|
||||||
function TDbgDwarfTypeIdentifierPointer.GetDataAddress(var AnAddress: TFpDbgMemLocation;
|
function TDbgDwarfTypeIdentifierPointer.GetDataAddress(var AnAddress: TFpDbgMemLocation;
|
||||||
ATargetType: TDbgDwarfTypeIdentifier): Boolean;
|
ATargetType: TDbgDwarfTypeIdentifier): Boolean;
|
||||||
//var
|
|
||||||
// Addr4: DWORD;
|
|
||||||
// Addr8: QWord;
|
|
||||||
begin
|
begin
|
||||||
if ATargetType = Self then begin
|
if ATargetType = Self then begin
|
||||||
Result := True;
|
Result := True;
|
||||||
@ -5352,18 +5333,7 @@ begin
|
|||||||
if not Result then
|
if not Result then
|
||||||
exit;
|
exit;
|
||||||
AnAddress := FCU.FOwner.MemManager.ReadAddress(AnAddress, FCU.FAddressSize);
|
AnAddress := FCU.FOwner.MemManager.ReadAddress(AnAddress, FCU.FAddressSize);
|
||||||
//case FCU.FAddressSize of
|
Result := IsTargetNotNil(AnAddress);
|
||||||
// 4: begin
|
|
||||||
// FCU.FOwner.MemManager.ReadMemory(AnAddress, 4, @Addr4);
|
|
||||||
// AnAddress := Addr4;
|
|
||||||
// end;
|
|
||||||
// 8: begin
|
|
||||||
// FCU.FOwner.MemManager.ReadMemory(AnAddress, 8, @Addr8);
|
|
||||||
// AnAddress := Addr8;
|
|
||||||
// end;
|
|
||||||
// else
|
|
||||||
// Result := False;
|
|
||||||
//end;
|
|
||||||
if Result then
|
if Result then
|
||||||
Result := inherited GetDataAddress(AnAddress, ATargetType);
|
Result := inherited GetDataAddress(AnAddress, ATargetType);
|
||||||
end;
|
end;
|
||||||
@ -5467,7 +5437,9 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
Assert((TypeInfo is TDbgDwarfIdentifier) and (TypeInfo.SymbolType = stType), 'TDbgDwarfValueIdentifier.GetDataAddress');
|
Assert((TypeInfo is TDbgDwarfIdentifier) and (TypeInfo.SymbolType = stType), 'TDbgDwarfValueIdentifier.GetDataAddress');
|
||||||
AnAddress := Address;
|
AnAddress := Address;
|
||||||
Result := TDbgDwarfTypeIdentifier(TypeInfo).GetDataAddress(AnAddress, ATargetType);
|
Result := IsReadableLoc(AnAddress);
|
||||||
|
if Result then
|
||||||
|
Result := TDbgDwarfTypeIdentifier(TypeInfo).GetDataAddress(AnAddress, ATargetType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDbgDwarfValueIdentifier.KindNeeded;
|
procedure TDbgDwarfValueIdentifier.KindNeeded;
|
||||||
@ -7751,10 +7723,10 @@ end;
|
|||||||
function TDwarfCompilationUnit.ReadAddressAtPointer(var AData: Pointer;
|
function TDwarfCompilationUnit.ReadAddressAtPointer(var AData: Pointer;
|
||||||
AIncPointer: Boolean): TFpDbgMemLocation;
|
AIncPointer: Boolean): TFpDbgMemLocation;
|
||||||
begin
|
begin
|
||||||
Result := FOwner.MemManager.ReadAddress(SelfLoc(AData), FAddressSize); // TODO Dwarf3 depends on FIsDwarf64
|
// do not need mem reader, address is in dwarf. Should be in correct format
|
||||||
//if FAddressSize = 4 // TODO Dwarf3 depends on FIsDwarf64
|
if FAddressSize = 4 // TODO Dwarf3 depends on FIsDwarf64
|
||||||
//then Result := PLongWord(AData)^
|
then Result := TargetLoc(PLongWord(AData)^)
|
||||||
//else Result := PQWord(AData)^;
|
else Result := TargetLoc(PQWord(AData)^);
|
||||||
if AIncPointer then inc(AData, FAddressSize);
|
if AIncPointer then inc(AData, FAddressSize);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -2,10 +2,29 @@ unit FpdMemoryTools;
|
|||||||
|
|
||||||
{$mode objfpc}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
(* Tools to read data from Target or Own memory.
|
||||||
|
|
||||||
|
This is to deal in one place with all conversion of data from target format
|
||||||
|
to debugger format.
|
||||||
|
|
||||||
|
A typical read would involve the following steps:
|
||||||
|
|
||||||
|
The code calls MemoryManager with an Address, a Size and a space for the data.
|
||||||
|
|
||||||
|
If the data needs to be extended (SizeOf(data) > TargetSize), then
|
||||||
|
MemConvertor is called to decide where in rovided space the read data should
|
||||||
|
initially be stored.
|
||||||
|
|
||||||
|
Then the data is read using MemReader.
|
||||||
|
|
||||||
|
And finally MemConvertor is given a chance to extend or convert the data.
|
||||||
|
|
||||||
|
*)
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils;
|
Classes, SysUtils, math;
|
||||||
|
|
||||||
type
|
type
|
||||||
TDbgPtr = QWord; // TODO, use from IdeDebuggerInterface, once that is done.
|
TDbgPtr = QWord; // TODO, use from IdeDebuggerInterface, once that is done.
|
||||||
@ -14,38 +33,120 @@ type
|
|||||||
public
|
public
|
||||||
function ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; virtual; abstract;
|
function ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; virtual; abstract;
|
||||||
function ReadMemoryEx(AnAddress, AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; virtual; abstract;
|
function ReadMemoryEx(AnAddress, AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; virtual; abstract;
|
||||||
|
// ReadRegister may need TargetMemConvertor
|
||||||
|
// Register with reduced size are treated as unsigned
|
||||||
function ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr): Boolean; virtual; abstract;
|
function ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr): Boolean; virtual; abstract;
|
||||||
function RegisterSize(ARegNum: Cardinal): Integer; virtual; abstract;
|
function RegisterSize(ARegNum: Cardinal): Integer; virtual; abstract;
|
||||||
// Registernum from name
|
// Registernum from name
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
(* Options for all read operation // TODO *)
|
||||||
|
|
||||||
|
TFpDbgMemReadOptions = record
|
||||||
|
(* potential flags
|
||||||
|
target bit start/shift (method to map dwarf2/3 bit offse to dwarf 4
|
||||||
|
target bit size
|
||||||
|
target assume big/little endian
|
||||||
|
float precisson
|
||||||
|
AddressSpace
|
||||||
|
|
||||||
|
( rmBigEndian, rmLittleEndian, rmUseAddressSpace, UseBitSize)
|
||||||
|
AddressSpace, BitOffset, precission
|
||||||
|
*)
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
TFpDbgMemReadDataType = (
|
||||||
|
rdtAddress, rdtSignedInt, rdtUnsignedInt
|
||||||
|
);
|
||||||
|
|
||||||
|
TFpDbgMemConvData = record
|
||||||
|
NewTargetAddress: TDbgPtr;
|
||||||
|
NewDestAddress: Pointer;
|
||||||
|
NewReadSize: Cardinal;
|
||||||
|
PrivData1, PrivData2: Pointer;
|
||||||
|
end;
|
||||||
|
|
||||||
// Todo, cpu/language specific operations, endianess, sign extend, float .... default int value for bool
|
// Todo, cpu/language specific operations, endianess, sign extend, float .... default int value for bool
|
||||||
|
// convert from debugge format to debuger format and back
|
||||||
// TODO: currently it assumes target and own mem are in the same format
|
// TODO: currently it assumes target and own mem are in the same format
|
||||||
TFpDbgMemConvertor = class
|
TFpDbgMemConvertor = class
|
||||||
public
|
public
|
||||||
(* To copy a smaller int/cardinal (e.g. word) into a bigger (e.g. dword),
|
(* PrepareTargetRead
|
||||||
|
called before every Read operation.
|
||||||
|
In case of reading from a bit-offset more memory may be needed, and must be allocated here
|
||||||
|
*)
|
||||||
|
function PrepareTargetRead(AReadDataType: TFpDbgMemReadDataType;
|
||||||
|
ATargetPointer: TDbgPtr; ADestPointer: Pointer;
|
||||||
|
ATargetSize, ADestSize: Cardinal;
|
||||||
|
out AConvertorData: TFpDbgMemConvData
|
||||||
|
): boolean; virtual; abstract;
|
||||||
|
function PrepareTargetRead(AReadDataType: TFpDbgMemReadDataType;
|
||||||
|
ATargetPointer: TDbgPtr; ADestPointer: Pointer;
|
||||||
|
ATargetSize, ADestSize: Cardinal;
|
||||||
|
AnOpts: TFpDbgMemReadOptions;
|
||||||
|
out AConvertorData: TFpDbgMemConvData
|
||||||
|
): boolean; virtual; abstract;
|
||||||
|
|
||||||
|
(* FinishTargetRead
|
||||||
|
called after every Read operation.
|
||||||
|
*)
|
||||||
|
function FinishTargetRead(AReadDataType: TFpDbgMemReadDataType;
|
||||||
|
ATargetPointer: TDbgPtr; ADestPointer: Pointer;
|
||||||
|
ATargetSize, ADestSize: Cardinal;
|
||||||
|
AConvertorData: TFpDbgMemConvData
|
||||||
|
): boolean; virtual; abstract;
|
||||||
|
function FinishTargetRead(AReadDataType: TFpDbgMemReadDataType;
|
||||||
|
ATargetPointer: TDbgPtr; ADestPointer: Pointer;
|
||||||
|
ATargetSize, ADestSize: Cardinal;
|
||||||
|
AnOpts: TFpDbgMemReadOptions;
|
||||||
|
AConvertorData: TFpDbgMemConvData
|
||||||
|
): boolean; virtual; abstract;
|
||||||
|
|
||||||
|
// just to free any data
|
||||||
|
procedure FailedTargetRead(AConvertorData: TFpDbgMemConvData); virtual; abstract;
|
||||||
|
|
||||||
|
(* AdjustIntPointer:
|
||||||
|
To copy a smaller int/cardinal (e.g. word) into a bigger (e.g. dword),
|
||||||
adjust ADestPointer so it points to the low value part of the dest
|
adjust ADestPointer so it points to the low value part of the dest
|
||||||
|
No conversion
|
||||||
*)
|
*)
|
||||||
procedure AdjustIntPointer(var ADestPointer: Pointer; ASourceSize, ADestSize: Cardinal); virtual; abstract;
|
procedure AdjustIntPointer(var ADataPointer: Pointer; ADataSize, ANewSize: Cardinal); virtual; abstract;
|
||||||
(* Expects a signed integer value of ASourceSize bytes in the low value end
|
//(* SignExtend:
|
||||||
of the memory (total memory ADataPointer, ADestSize)
|
// Expects a signed integer value of ASourceSize bytes in the low value end
|
||||||
Does zero fill the memory, if no sign extend is needed
|
// of the memory (total memory ADataPointer, ADestSize)
|
||||||
*)
|
// Does zero fill the memory, if no sign extend is needed
|
||||||
procedure SignExtend(ADataPointer: Pointer; ASourceSize, ADestSize: Cardinal); virtual; abstract;
|
//*)
|
||||||
(* Expects an unsigned integer value of ASourceSize bytes in the low value end
|
//procedure SignExtend(ADataPointer: Pointer; ASourceSize, ADestSize: Cardinal); virtual; abstract;
|
||||||
of the memory (total memory ADataPointer, ADestSize)
|
//(* Expects an unsigned integer value of ASourceSize bytes in the low value end
|
||||||
Basically zero fill the memory
|
// of the memory (total memory ADataPointer, ADestSize)
|
||||||
*)
|
// Basically zero fill the memory
|
||||||
procedure UnsignSignedExtend(ADataPointer: Pointer; ASourceSize, ADestSize: Cardinal); virtual; abstract;
|
//*)
|
||||||
|
//procedure UnsignedExtend(ADataPointer: Pointer; ASourceSize, ADestSize: Cardinal); virtual; abstract;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TFpDbgMemConvertorLittleEndian }
|
{ TFpDbgMemConvertorLittleEndian }
|
||||||
|
|
||||||
TFpDbgMemConvertorLittleEndian = class(TFpDbgMemConvertor)
|
TFpDbgMemConvertorLittleEndian = class(TFpDbgMemConvertor)
|
||||||
public
|
public
|
||||||
procedure AdjustIntPointer(var ADestPointer: Pointer; ASourceSize, ADestSize: Cardinal); override;
|
function PrepareTargetRead(AReadDataType: TFpDbgMemReadDataType;
|
||||||
procedure SignExtend(ADataPointer: Pointer; ASourceSize, ADestSize: Cardinal); override;
|
ATargetPointer: TDbgPtr; ADestPointer: Pointer;
|
||||||
procedure UnsignSignedExtend(ADataPointer: Pointer; ASourceSize, ADestSize: Cardinal); override;
|
ATargetSize, ADestSize: Cardinal;
|
||||||
|
out AConvertorData: TFpDbgMemConvData
|
||||||
|
): boolean; override;
|
||||||
|
|
||||||
|
function FinishTargetRead(AReadDataType: TFpDbgMemReadDataType;
|
||||||
|
ATargetPointer: TDbgPtr; ADestPointer: Pointer;
|
||||||
|
ATargetSize, ADestSize: Cardinal;
|
||||||
|
AConvertorData: TFpDbgMemConvData
|
||||||
|
): boolean; override;
|
||||||
|
procedure FailedTargetRead(AConvertorData: TFpDbgMemConvData); override;
|
||||||
|
|
||||||
|
procedure AdjustIntPointer(var ADataPointer: Pointer; ADataSize, ANewSize: Cardinal); override;
|
||||||
|
|
||||||
|
|
||||||
|
//procedure SignExtend(ADataPointer: Pointer; ASourceSize, ADestSize: Cardinal); override;
|
||||||
|
//procedure UnsignedExtend(ADataPointer: Pointer; ASourceSize, ADestSize: Cardinal); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(* TFpDbgMemManager
|
(* TFpDbgMemManager
|
||||||
@ -68,7 +169,6 @@ type
|
|||||||
mlfSelfMem, // an address in this(the debuggers) process memory; the data is in TARGET format (endian, ...)
|
mlfSelfMem, // an address in this(the debuggers) process memory; the data is in TARGET format (endian, ...)
|
||||||
// the below will be mapped (and extended) according to endianess
|
// the below will be mapped (and extended) according to endianess
|
||||||
mlfTargetRegister, // reads from the register
|
mlfTargetRegister, // reads from the register
|
||||||
mlfTargetRegisterSigned, // reads from the register and sign extends if needed (may be limited to 8 bytes)
|
|
||||||
mlfConstant // an (up to) SizeOf(TDbgPtr) (=8) Bytes Value (endian in format of debug process)
|
mlfConstant // an (up to) SizeOf(TDbgPtr) (=8) Bytes Value (endian in format of debug process)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -77,30 +177,70 @@ type
|
|||||||
MType: TFpDbgMemLocationType;
|
MType: TFpDbgMemLocationType;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TFpDbgMemManager }
|
{ TFpDbgMemManager }
|
||||||
|
|
||||||
TFpDbgMemManager = class
|
TFpDbgMemManager = class
|
||||||
private
|
private
|
||||||
FMemReader: TFpDbgMemReaderBase;
|
FMemReader: TFpDbgMemReaderBase;
|
||||||
FMemConvertor: TFpDbgMemConvertor;
|
FTargetMemConvertor: TFpDbgMemConvertor;
|
||||||
|
FSelfMemConvertor: TFpDbgMemConvertor; // used when resizing constants (or register values, which are already in self format)
|
||||||
|
protected
|
||||||
|
function ReadMemory(AReadDataType: TFpDbgMemReadDataType;
|
||||||
|
const ALocation: TFpDbgMemLocation; ATargetSize: Cardinal;
|
||||||
|
ADest: Pointer; ADestSize: Cardinal): Boolean;
|
||||||
public
|
public
|
||||||
constructor Create(AMemReader: TFpDbgMemReaderBase; AMemConvertor: TFpDbgMemConvertor);
|
constructor Create(AMemReader: TFpDbgMemReaderBase; AMemConvertor: TFpDbgMemConvertor);
|
||||||
|
constructor Create(AMemReader: TFpDbgMemReaderBase; ATargenMemConvertor, ASelfMemConvertor: TFpDbgMemConvertor);
|
||||||
|
|
||||||
function ReadMemory(ALocation: TFpDbgMemLocation; ASize: Cardinal; ADest: Pointer): Boolean;
|
function ReadMemory(const ALocation: TFpDbgMemLocation; ASize: Cardinal; ADest: Pointer): Boolean;
|
||||||
function ReadMemoryEx(ALocation: TFpDbgMemLocation; AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean;
|
function ReadMemoryEx(const ALocation: TFpDbgMemLocation; AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean;
|
||||||
function ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr): Boolean;
|
function ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr): Boolean;
|
||||||
|
|
||||||
function ReadAddress(ALocation: TFpDbgMemLocation; ASize: Cardinal): TFpDbgMemLocation;
|
// location will be invalid, if read failed
|
||||||
function ReadAddressEx(ALocation: TFpDbgMemLocation; AnAddressSpace: TDbgPtr; ASize: Cardinal): TFpDbgMemLocation;
|
function ReadAddress(const ALocation: TFpDbgMemLocation; ASize: Cardinal): TFpDbgMemLocation;
|
||||||
|
function ReadAddressEx(const ALocation: TFpDbgMemLocation; AnAddressSpace: TDbgPtr; ASize: Cardinal): TFpDbgMemLocation;
|
||||||
|
|
||||||
property MemConvertor: TFpDbgMemConvertor read FMemConvertor;
|
function ReadAddress (const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
out AnAddress: TFpDbgMemLocation): Boolean; inline;
|
||||||
|
//function ReadAddress (const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
// out AnAddress: TFpDbgMemLocation;
|
||||||
|
// AnOpts: TFpDbgMemReadOptions): Boolean;
|
||||||
|
function ReadUnsignedInt(const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
out AValue: QWord): Boolean; inline;
|
||||||
|
//function ReadUnsignedInt(const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
// out AValue: QWord;
|
||||||
|
// AnOpts: TFpDbgMemReadOptions): Boolean;
|
||||||
|
function ReadSignedInt (const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
out AValue: Int64): Boolean; inline;
|
||||||
|
//function ReadSignedInt (const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
// out AValue: Int64;
|
||||||
|
// AnOpts: TFpDbgMemReadOptions): Boolean;
|
||||||
|
// //enum/set: may need bitorder swapped
|
||||||
|
//function ReadEnum (const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
// out AValue: QWord): Boolean; inline;
|
||||||
|
//function ReadEnum (const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
// out AValue: QWord;
|
||||||
|
// AnOpts: TFpDbgMemReadOptions): Boolean;
|
||||||
|
//function ReadSet (const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
// out AValue: TBytes): Boolean; inline;
|
||||||
|
//function ReadSet (const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
// out AValue: TBytes;
|
||||||
|
// AnOpts: TFpDbgMemReadOptions): Boolean;
|
||||||
|
//function ReadFloat (const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
// out AValue: Double): Boolean; inline;
|
||||||
|
//function ReadFloat (const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
// out AValue: Double;
|
||||||
|
// AnOpts: TFpDbgMemReadOptions): Boolean;
|
||||||
|
|
||||||
|
property TargetMemConvertor: TFpDbgMemConvertor read FTargetMemConvertor;
|
||||||
|
property SelfMemConvertor: TFpDbgMemConvertor read FSelfMemConvertor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function NilLoc: TFpDbgMemLocation; inline;
|
function NilLoc: TFpDbgMemLocation; inline;
|
||||||
function InvalidLoc: TFpDbgMemLocation; inline;
|
function InvalidLoc: TFpDbgMemLocation; inline;
|
||||||
function TargetLoc(AnAddress: TDbgPtr): TFpDbgMemLocation; inline;
|
function TargetLoc(AnAddress: TDbgPtr): TFpDbgMemLocation; inline;
|
||||||
function RegisterLoc(ARegNum: Cardinal): TFpDbgMemLocation; inline;
|
function RegisterLoc(ARegNum: Cardinal): TFpDbgMemLocation; inline;
|
||||||
function RegisterSignedLoc(ARegNum: Cardinal): TFpDbgMemLocation; inline;
|
|
||||||
function SelfLoc(AnAddress: TDbgPtr): TFpDbgMemLocation; inline;
|
function SelfLoc(AnAddress: TDbgPtr): TFpDbgMemLocation; inline;
|
||||||
function SelfLoc(AnAddress: Pointer): TFpDbgMemLocation; inline;
|
function SelfLoc(AnAddress: Pointer): TFpDbgMemLocation; inline;
|
||||||
function ConstLoc(AValue: QWord): TFpDbgMemLocation; inline;
|
function ConstLoc(AValue: QWord): TFpDbgMemLocation; inline;
|
||||||
@ -114,6 +254,8 @@ function IsTargetNotNil(ALocation: TFpDbgMemLocation): Boolean; inline; // valid
|
|||||||
function LocToAddr(ALocation: TFpDbgMemLocation): TDbgPtr; inline; // does not check valid
|
function LocToAddr(ALocation: TFpDbgMemLocation): TDbgPtr; inline; // does not check valid
|
||||||
function LocToAddrOrNil(ALocation: TFpDbgMemLocation): TDbgPtr; inline; // save version
|
function LocToAddrOrNil(ALocation: TFpDbgMemLocation): TDbgPtr; inline; // save version
|
||||||
|
|
||||||
|
function EmptyMemReadOpts:TFpDbgMemReadOptions;
|
||||||
|
|
||||||
function dbgs(ALocation: TFpDbgMemLocation): String; overload;
|
function dbgs(ALocation: TFpDbgMemLocation): String; overload;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -142,12 +284,6 @@ begin
|
|||||||
Result.MType := mlfTargetRegister;
|
Result.MType := mlfTargetRegister;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function RegisterSignedLoc(ARegNum: Cardinal): TFpDbgMemLocation;
|
|
||||||
begin
|
|
||||||
Result.Address := ARegNum;
|
|
||||||
Result.MType := mlfTargetRegisterSigned;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function SelfLoc(AnAddress: TDbgPtr): TFpDbgMemLocation;
|
function SelfLoc(AnAddress: TDbgPtr): TFpDbgMemLocation;
|
||||||
begin
|
begin
|
||||||
Result.Address := AnAddress;
|
Result.Address := AnAddress;
|
||||||
@ -208,6 +344,11 @@ begin
|
|||||||
Result := 0;
|
Result := 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function EmptyMemReadOpts: TFpDbgMemReadOptions;
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
function dbgs(ALocation: TFpDbgMemLocation): String;
|
function dbgs(ALocation: TFpDbgMemLocation): String;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
Result := '';
|
||||||
@ -219,52 +360,169 @@ end;
|
|||||||
|
|
||||||
{ TFpDbgMemConvertorLittleEndian }
|
{ TFpDbgMemConvertorLittleEndian }
|
||||||
|
|
||||||
procedure TFpDbgMemConvertorLittleEndian.AdjustIntPointer(var ADestPointer: Pointer;
|
function TFpDbgMemConvertorLittleEndian.PrepareTargetRead(AReadDataType: TFpDbgMemReadDataType;
|
||||||
ASourceSize, ADestSize: Cardinal);
|
ATargetPointer: TDbgPtr; ADestPointer: Pointer; ATargetSize, ADestSize: Cardinal; out
|
||||||
|
AConvertorData: TFpDbgMemConvData): boolean;
|
||||||
begin
|
begin
|
||||||
|
Result := True;
|
||||||
|
case AReadDataType of
|
||||||
|
rdtAddress, rdtSignedInt, rdtUnsignedInt: begin
|
||||||
|
Result := ATargetSize <= ADestSize;
|
||||||
|
// just read to begin of data
|
||||||
|
AConvertorData.NewTargetAddress := ATargetPointer;
|
||||||
|
AConvertorData.NewDestAddress := ADestPointer;
|
||||||
|
AConvertorData.NewReadSize := Min(ATargetSize, ADestSize);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFpDbgMemConvertorLittleEndian.FinishTargetRead(AReadDataType: TFpDbgMemReadDataType;
|
||||||
|
ATargetPointer: TDbgPtr; ADestPointer: Pointer; ATargetSize, ADestSize: Cardinal;
|
||||||
|
AConvertorData: TFpDbgMemConvData): boolean;
|
||||||
|
begin
|
||||||
|
Result := True;
|
||||||
|
case AReadDataType of
|
||||||
|
rdtAddress, rdtUnsignedInt: begin
|
||||||
|
if ATargetSize < ADestSize then
|
||||||
|
FillByte((ADestPointer + ATargetSize)^, ADestSize-ATargetSize, $00)
|
||||||
|
end;
|
||||||
|
rdtSignedInt: begin
|
||||||
|
if ATargetSize < ADestSize then
|
||||||
|
if (ATargetSize > 0) and ((PByte(ADestPointer + ATargetSize - 1)^ and $80) <> 0)
|
||||||
|
then
|
||||||
|
FillByte((ADestPointer + ATargetSize)^, ADestSize-ATargetSize, $FF)
|
||||||
|
else
|
||||||
|
FillByte((ADestPointer + ATargetSize)^, ADestSize-ATargetSize, $00);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFpDbgMemConvertorLittleEndian.FailedTargetRead(AConvertorData: TFpDbgMemConvData);
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFpDbgMemConvertorLittleEndian.AdjustIntPointer(var ADataPointer: Pointer;
|
||||||
|
ADataSize, ANewSize: Cardinal);
|
||||||
|
begin
|
||||||
|
Assert(ANewSize <= ADataSize, 'TFpDbgMemConvertorLittleEndian.AdjustIntPointer');
|
||||||
// no adjustment needed
|
// no adjustment needed
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpDbgMemConvertorLittleEndian.SignExtend(ADataPointer: Pointer; ASourceSize,
|
//procedure TFpDbgMemConvertorLittleEndian.SignExtend(ADataPointer: Pointer; ASourceSize,
|
||||||
ADestSize: Cardinal);
|
// ADestSize: Cardinal);
|
||||||
begin
|
//begin
|
||||||
Assert(ASourceSize > 0, 'TFpDbgMemConvertorLittleEndian.SignExtend');
|
// Assert(ASourceSize > 0, 'TFpDbgMemConvertorLittleEndian.SignExtend');
|
||||||
if ASourceSize >= ADestSize then
|
// if ASourceSize >= ADestSize then
|
||||||
exit;
|
// exit;
|
||||||
|
//
|
||||||
if (PByte(ADataPointer + ASourceSize - 1)^ and $80) <> 0 then
|
// if (PByte(ADataPointer + ASourceSize - 1)^ and $80) <> 0 then
|
||||||
FillByte((ADataPointer + ASourceSize)^, ADestSize-ASourceSize, $ff)
|
// FillByte((ADataPointer + ASourceSize)^, ADestSize-ASourceSize, $ff)
|
||||||
else
|
// else
|
||||||
FillByte((ADataPointer + ASourceSize)^, ADestSize-ASourceSize, $00)
|
// FillByte((ADataPointer + ASourceSize)^, ADestSize-ASourceSize, $00)
|
||||||
end;
|
//end;
|
||||||
|
//
|
||||||
procedure TFpDbgMemConvertorLittleEndian.UnsignSignedExtend(ADataPointer: Pointer;
|
//procedure TFpDbgMemConvertorLittleEndian.UnsignedExtend(ADataPointer: Pointer;
|
||||||
ASourceSize, ADestSize: Cardinal);
|
// ASourceSize, ADestSize: Cardinal);
|
||||||
begin
|
//begin
|
||||||
Assert(ASourceSize > 0, 'TFpDbgMemConvertorLittleEndian.SignExtend');
|
// Assert(ASourceSize > 0, 'TFpDbgMemConvertorLittleEndian.SignExtend');
|
||||||
if ASourceSize >= ADestSize then
|
// if ASourceSize >= ADestSize then
|
||||||
exit;
|
// exit;
|
||||||
|
//
|
||||||
FillByte((ADataPointer + ASourceSize)^, ADestSize-ASourceSize, $00)
|
// FillByte((ADataPointer + ASourceSize)^, ADestSize-ASourceSize, $00)
|
||||||
end;
|
//end;
|
||||||
|
|
||||||
{ TFpDbgMemManager }
|
{ TFpDbgMemManager }
|
||||||
|
|
||||||
|
function TFpDbgMemManager.ReadMemory(AReadDataType: TFpDbgMemReadDataType;
|
||||||
|
const ALocation: TFpDbgMemLocation; ATargetSize: Cardinal; ADest: Pointer;
|
||||||
|
ADestSize: Cardinal): Boolean;
|
||||||
|
var
|
||||||
|
Addr2: Pointer;
|
||||||
|
i: Integer;
|
||||||
|
TmpVal: TDbgPtr;
|
||||||
|
ConvData: TFpDbgMemConvData;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
case ALocation.MType of
|
||||||
|
mlfInvalid: ;
|
||||||
|
mlfTargetMem, mlfSelfMem: begin
|
||||||
|
Result := TargetMemConvertor.PrepareTargetRead(AReadDataType, ALocation.Address,
|
||||||
|
ADest, ATargetSize, ADestSize, ConvData);
|
||||||
|
if not Result then exit;
|
||||||
|
|
||||||
|
if ALocation.MType = mlfTargetMem then
|
||||||
|
Result := FMemReader.ReadMemory(ConvData.NewTargetAddress, ConvData.NewReadSize, ConvData.NewDestAddress)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
move(Pointer(ConvData.NewTargetAddress)^, ConvData.NewDestAddress^, ConvData.NewReadSize);
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Result then
|
||||||
|
Result := TargetMemConvertor.FinishTargetRead(AReadDataType, ALocation.Address,
|
||||||
|
ADest, ATargetSize, ADestSize, ConvData)
|
||||||
|
else
|
||||||
|
TargetMemConvertor.FailedTargetRead(ConvData);
|
||||||
|
end;
|
||||||
|
mlfConstant, mlfTargetRegister:
|
||||||
|
begin
|
||||||
|
case ALocation.MType of
|
||||||
|
mlfConstant: begin
|
||||||
|
TmpVal := ALocation.Address;
|
||||||
|
i := SizeOf(ALocation.Address);
|
||||||
|
end;
|
||||||
|
mlfTargetRegister: begin
|
||||||
|
i := FMemReader.RegisterSize(Cardinal(ALocation.Address));
|
||||||
|
if i = 0 then
|
||||||
|
exit; // failed
|
||||||
|
if not FMemReader.ReadRegister(Cardinal(ALocation.Address), TmpVal) then
|
||||||
|
exit; // failed
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if i > ATargetSize then
|
||||||
|
i := ATargetSize;
|
||||||
|
|
||||||
|
Addr2 := @TmpVal;
|
||||||
|
if SizeOf(TmpVal) <> i then
|
||||||
|
FSelfMemConvertor.AdjustIntPointer(Addr2, SizeOf(TmpVal), i);
|
||||||
|
|
||||||
|
Result := FSelfMemConvertor.PrepareTargetRead(AReadDataType, TDbgPtr(Addr2),
|
||||||
|
ADest, i, ADestSize, ConvData);
|
||||||
|
if not Result then exit;
|
||||||
|
|
||||||
|
move(Pointer(ConvData.NewTargetAddress)^, ConvData.NewDestAddress^, ConvData.NewReadSize);
|
||||||
|
|
||||||
|
Result := TargetMemConvertor.FinishTargetRead(AReadDataType, TDbgPtr(Addr2),
|
||||||
|
ADest, i, ADestSize, ConvData);
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TFpDbgMemManager.Create(AMemReader: TFpDbgMemReaderBase;
|
constructor TFpDbgMemManager.Create(AMemReader: TFpDbgMemReaderBase;
|
||||||
AMemConvertor: TFpDbgMemConvertor);
|
AMemConvertor: TFpDbgMemConvertor);
|
||||||
begin
|
begin
|
||||||
FMemReader := AMemReader;
|
FMemReader := AMemReader;
|
||||||
FMemConvertor := AMemConvertor;
|
FTargetMemConvertor := AMemConvertor;
|
||||||
|
FSelfMemConvertor := AMemConvertor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFpDbgMemManager.ReadMemory(ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
constructor TFpDbgMemManager.Create(AMemReader: TFpDbgMemReaderBase; ATargenMemConvertor,
|
||||||
|
ASelfMemConvertor: TFpDbgMemConvertor);
|
||||||
|
begin
|
||||||
|
FMemReader := AMemReader;
|
||||||
|
FTargetMemConvertor := ATargenMemConvertor;
|
||||||
|
FSelfMemConvertor := ASelfMemConvertor;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFpDbgMemManager.ReadMemory(const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
ADest: Pointer): Boolean;
|
ADest: Pointer): Boolean;
|
||||||
const
|
|
||||||
ConstValSize = SizeOf(ALocation.Address);
|
|
||||||
var
|
var
|
||||||
Addr2: Pointer;
|
Addr2: Pointer;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
TmpVal: TDbgPtr;
|
TmpVal: TDbgPtr;
|
||||||
|
ConvData: TFpDbgMemConvData;
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
case ALocation.MType of
|
case ALocation.MType of
|
||||||
@ -276,14 +534,14 @@ begin
|
|||||||
move(Pointer(ALocation.Address)^, ADest^, ASize);
|
move(Pointer(ALocation.Address)^, ADest^, ASize);
|
||||||
Result := True;
|
Result := True;
|
||||||
end;
|
end;
|
||||||
mlfConstant, mlfTargetRegister, mlfTargetRegisterSigned:
|
mlfConstant, mlfTargetRegister:
|
||||||
begin
|
begin
|
||||||
case ALocation.MType of
|
case ALocation.MType of
|
||||||
mlfConstant: begin
|
mlfConstant: begin
|
||||||
TmpVal := ALocation.Address;
|
TmpVal := ALocation.Address;
|
||||||
i := ConstValSize;
|
i := SizeOf(ALocation.Address);
|
||||||
end;
|
end;
|
||||||
mlfTargetRegister, mlfTargetRegisterSigned: begin
|
mlfTargetRegister: begin
|
||||||
i := FMemReader.RegisterSize(Cardinal(ALocation.Address));
|
i := FMemReader.RegisterSize(Cardinal(ALocation.Address));
|
||||||
if i = 0 then
|
if i = 0 then
|
||||||
exit; // failed
|
exit; // failed
|
||||||
@ -292,29 +550,27 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if ASize < i then begin
|
Addr2 := @TmpVal;
|
||||||
Addr2 := @TmpVal;
|
if SizeOf(TmpVal) <> i then
|
||||||
FMemConvertor.AdjustIntPointer(Addr2, ASize, i);
|
FSelfMemConvertor.AdjustIntPointer(Addr2, SizeOf(TmpVal), i);
|
||||||
move(Addr2^, ADest^, i);
|
|
||||||
end
|
Result := FSelfMemConvertor.PrepareTargetRead(rdtUnsignedInt, TDbgPtr(Addr2),
|
||||||
else begin
|
ADest, i, ASize, ConvData);
|
||||||
Addr2 := ADest;
|
if not Result then exit;
|
||||||
FMemConvertor.AdjustIntPointer(Addr2, i, ASize);
|
|
||||||
PQWord(Addr2)^ := TmpVal;
|
move(Pointer(ConvData.NewTargetAddress)^, ConvData.NewDestAddress^, ConvData.NewReadSize);
|
||||||
if ALocation.MType = mlfTargetRegisterSigned then
|
|
||||||
FMemConvertor.SignExtend(ADest, i, ASize)
|
Result := TargetMemConvertor.FinishTargetRead(rdtUnsignedInt, TDbgPtr(Addr2),
|
||||||
else
|
ADest, i, ASize, ConvData);
|
||||||
FMemConvertor.UnsignSignedExtend(ADest, i, ASize);
|
|
||||||
end;
|
|
||||||
Result := True;
|
Result := True;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFpDbgMemManager.ReadMemoryEx(ALocation: TFpDbgMemLocation; AnAddressSpace: TDbgPtr;
|
function TFpDbgMemManager.ReadMemoryEx(const ALocation: TFpDbgMemLocation;
|
||||||
ASize: Cardinal; ADest: Pointer): Boolean;
|
AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean;
|
||||||
begin
|
begin
|
||||||
// AnAddressSpace is ignored, except for target address
|
// AnAddressSpace is ignored, when not actually reading from target address
|
||||||
case ALocation.MType of
|
case ALocation.MType of
|
||||||
mlfTargetMem: Result := FMemReader.ReadMemoryEx(ALocation.Address, AnAddressSpace, ASize, ADest);
|
mlfTargetMem: Result := FMemReader.ReadMemoryEx(ALocation.Address, AnAddressSpace, ASize, ADest);
|
||||||
else
|
else
|
||||||
@ -327,44 +583,39 @@ begin
|
|||||||
Result := FMemReader.ReadRegister(ARegNum, AValue);
|
Result := FMemReader.ReadRegister(ARegNum, AValue);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFpDbgMemManager.ReadAddress(ALocation: TFpDbgMemLocation;
|
function TFpDbgMemManager.ReadAddress(const ALocation: TFpDbgMemLocation;
|
||||||
ASize: Cardinal): TFpDbgMemLocation;
|
ASize: Cardinal): TFpDbgMemLocation;
|
||||||
var
|
|
||||||
Dest: PQWord;
|
|
||||||
begin
|
begin
|
||||||
Assert(ASize < SizeOf(Result.Address), 'TFpDbgMemManager.ReadAddress');
|
Result.MType := mlfTargetMem;
|
||||||
if ASize > SizeOf(Result.Address) then begin
|
if not ReadMemory(rdtAddress, ALocation, ASize, @Result.Address, SizeOf(Result.Address)) then
|
||||||
Result := InvalidLoc;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Result.Address := 0;
|
|
||||||
Dest := @Result.Address;
|
|
||||||
MemConvertor.AdjustIntPointer(Dest, ASize, SizeOf(Result.Address));
|
|
||||||
if ReadMemory(ALocation, ASize, Dest) then
|
|
||||||
Result.MType := mlfTargetMem
|
|
||||||
else
|
|
||||||
Result := InvalidLoc;
|
Result := InvalidLoc;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFpDbgMemManager.ReadAddressEx(ALocation: TFpDbgMemLocation; AnAddressSpace: TDbgPtr;
|
function TFpDbgMemManager.ReadAddressEx(const ALocation: TFpDbgMemLocation;
|
||||||
ASize: Cardinal): TFpDbgMemLocation;
|
AnAddressSpace: TDbgPtr; ASize: Cardinal): TFpDbgMemLocation;
|
||||||
var
|
|
||||||
Dest: PQWord;
|
|
||||||
begin
|
begin
|
||||||
Assert(ASize < SizeOf(Result.Address), 'TFpDbgMemManager.ReadAddress');
|
Result := InvalidLoc;
|
||||||
if ASize > SizeOf(Result.Address) then begin
|
end;
|
||||||
Result := InvalidLoc;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Result.Address := 0;
|
function TFpDbgMemManager.ReadAddress(const ALocation: TFpDbgMemLocation; ASize: Cardinal; out
|
||||||
Dest := @Result.Address;
|
AnAddress: TFpDbgMemLocation): Boolean;
|
||||||
MemConvertor.AdjustIntPointer(Dest, ASize, SizeOf(Result.Address));
|
begin
|
||||||
if ReadMemoryEx(ALocation, AnAddressSpace, ASize, Dest) then
|
Result := ReadMemory(rdtAddress, ALocation, ASize, @AnAddress, SizeOf(AnAddress));
|
||||||
Result.MType := mlfTargetMem
|
if Result
|
||||||
else
|
then AnAddress.MType := mlfTargetMem
|
||||||
Result := InvalidLoc;
|
else AnAddress.MType := mlfInvalid;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFpDbgMemManager.ReadUnsignedInt(const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
out AValue: QWord): Boolean;
|
||||||
|
begin
|
||||||
|
Result := ReadMemory(rdtUnsignedInt, ALocation, ASize, @AValue, SizeOf(AValue));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFpDbgMemManager.ReadSignedInt(const ALocation: TFpDbgMemLocation; ASize: Cardinal;
|
||||||
|
out AValue: Int64): Boolean;
|
||||||
|
begin
|
||||||
|
Result := ReadMemory(rdtSignedInt, ALocation, ASize, @AValue, SizeOf(AValue));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -4,7 +4,7 @@ program FpTest;
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Interfaces, Forms, GuiTestRunner, TestPascalParser, TestTypeInfo, TestHelperClasses,
|
Interfaces, Forms, GuiTestRunner, TestPascalParser, TestTypeInfo, TestHelperClasses,
|
||||||
TestDwarfSetup1, TestDwarfSetupBasic, TestDwarfVarious, testdwarfsetupArray;
|
TestDwarfSetup1, TestDwarfSetupBasic, TestDwarfVarious, testdwarfsetupArray, TestMemManager;
|
||||||
|
|
||||||
{$R *.res}
|
{$R *.res}
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ type
|
|||||||
TTestMemReader = class(TFpDbgMemReaderBase)
|
TTestMemReader = class(TFpDbgMemReaderBase)
|
||||||
public
|
public
|
||||||
RegisterValues: array[0..30] of TDbgPtr;
|
RegisterValues: array[0..30] of TDbgPtr;
|
||||||
|
RegisterSizes: array[0..30] of Integer;
|
||||||
|
constructor Create;
|
||||||
function ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
function ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||||
function ReadMemoryEx({%H-}AnAddress, {%H-}AnAddressSpace: TDbgPtr; {%H-}ASize: Cardinal; {%H-}ADest: Pointer): Boolean; override;
|
function ReadMemoryEx({%H-}AnAddress, {%H-}AnAddressSpace: TDbgPtr; {%H-}ASize: Cardinal; {%H-}ADest: Pointer): Boolean; override;
|
||||||
function ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr): Boolean; override;
|
function ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr): Boolean; override;
|
||||||
@ -388,6 +390,14 @@ end;
|
|||||||
|
|
||||||
{ TTestMemReader }
|
{ TTestMemReader }
|
||||||
|
|
||||||
|
constructor TTestMemReader.Create;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
for i := 0 to length(RegisterSizes) - 1 do RegisterSizes[i] := 4;
|
||||||
|
end;
|
||||||
|
|
||||||
function TTestMemReader.ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal;
|
function TTestMemReader.ReadMemory(AnAddress: TDbgPtr; ASize: Cardinal;
|
||||||
ADest: Pointer): Boolean;
|
ADest: Pointer): Boolean;
|
||||||
begin
|
begin
|
||||||
@ -409,7 +419,7 @@ end;
|
|||||||
|
|
||||||
function TTestMemReader.RegisterSize(ARegNum: Cardinal): Integer;
|
function TTestMemReader.RegisterSize(ARegNum: Cardinal): Integer;
|
||||||
begin
|
begin
|
||||||
Result := 4; // TODO
|
Result := RegisterSizes[ARegNum];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TTestDwarfInfoEntry }
|
{ TTestDwarfInfoEntry }
|
||||||
|
251
components/fpdebug/test/testmemmanager.pas
Normal file
251
components/fpdebug/test/testmemmanager.pas
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
unit TestMemManager;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
FpDbgDwarf, FpDbgUtil, FpdMemoryTools, TestHelperClasses, LazLoggerBase, LazUTF8, sysutils,
|
||||||
|
fpcunit, testregistry;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TestDwarfVarious }
|
||||||
|
|
||||||
|
{ TTestMemManager }
|
||||||
|
|
||||||
|
TTestMemManager = class(TTestCase)
|
||||||
|
protected
|
||||||
|
FCurrentTestName: String;
|
||||||
|
FMemReader: TTestMemReader;
|
||||||
|
FMemConvTarget: TFpDbgMemConvertorLittleEndian;
|
||||||
|
FMemConvSelf: TFpDbgMemConvertorLittleEndian;
|
||||||
|
FMemManager: TFpDbgMemManager;
|
||||||
|
|
||||||
|
procedure InitMemMgr;
|
||||||
|
procedure SetUp; override;
|
||||||
|
procedure TearDown; override;
|
||||||
|
published
|
||||||
|
procedure TestMemMgr;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
procedure TTestMemManager.InitMemMgr;
|
||||||
|
begin
|
||||||
|
FMemReader := TTestMemReader.Create;
|
||||||
|
FMemConvTarget := TFpDbgMemConvertorLittleEndian.Create;
|
||||||
|
FMemConvSelf := TFpDbgMemConvertorLittleEndian.Create;
|
||||||
|
FMemManager := TFpDbgMemManager.Create(FMemReader, FMemConvTarget, FMemConvSelf);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestMemManager.SetUp;
|
||||||
|
begin
|
||||||
|
inherited SetUp;
|
||||||
|
FMemReader := nil;
|
||||||
|
FMemConvTarget := nil;
|
||||||
|
FMemConvSelf := nil;
|
||||||
|
FMemManager := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestMemManager.TearDown;
|
||||||
|
begin
|
||||||
|
inherited TearDown;
|
||||||
|
FreeAndNil(FMemReader);
|
||||||
|
FreeAndNil(FMemConvTarget);
|
||||||
|
FreeAndNil(FMemConvSelf);
|
||||||
|
FreeAndNil(FMemManager);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestMemManager.TestMemMgr;
|
||||||
|
var
|
||||||
|
i, j: Integer;
|
||||||
|
TestBaseName: String;
|
||||||
|
Data: QWord;
|
||||||
|
MemValue: QWord;
|
||||||
|
GotRes: Boolean;
|
||||||
|
GotInt: Int64;
|
||||||
|
GotUInt: QWord;
|
||||||
|
GotAddr: TFpDbgMemLocation;
|
||||||
|
|
||||||
|
procedure SetData(Aval: QWord);
|
||||||
|
begin
|
||||||
|
Data := Aval;
|
||||||
|
FMemReader.RegisterValues[2] := Aval;
|
||||||
|
FCurrentTestName := TestBaseName + ' ' + IntToHex(Aval, 16) + ': ';
|
||||||
|
end;
|
||||||
|
procedure CheckIntRes(AName: String; AExp: int64);
|
||||||
|
begin
|
||||||
|
AssertTrue(FCurrentTestName + AName + 'Read OK', GotRes);
|
||||||
|
AssertEquals(FCurrentTestName + AName + 'Val', AExp, GotInt);
|
||||||
|
end;
|
||||||
|
procedure CheckUIntRes(AName: String; AExp: int64);
|
||||||
|
begin
|
||||||
|
AssertTrue(FCurrentTestName + AName + 'Read OK', GotRes);
|
||||||
|
AssertEquals(FCurrentTestName + AName + 'Val', AExp, GotUInt);
|
||||||
|
end;
|
||||||
|
procedure CheckAddrRes(AName: String; AExp: int64);
|
||||||
|
begin
|
||||||
|
AssertTrue(FCurrentTestName + AName + 'Read OK', GotRes);
|
||||||
|
AssertTrue(FCurrentTestName + AName + 'Valid', IsValidLoc(GotAddr));
|
||||||
|
AssertEquals(FCurrentTestName + AName + 'Val', AExp, GotAddr.Address);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure DoSignedIntTests(ReadSize: Cardinal; ExpIntVal: Int64);
|
||||||
|
var
|
||||||
|
a: Cardinal;
|
||||||
|
begin
|
||||||
|
GotRes := FMemManager.ReadSignedInt(TargetLoc(TDbgPtr(@Data)), ReadSize, GotInt);
|
||||||
|
CheckIntRes('signed target', ExpIntVal);
|
||||||
|
|
||||||
|
GotRes := FMemManager.ReadSignedInt(SelfLoc(@Data), ReadSize, GotInt);
|
||||||
|
CheckIntRes('signed self', ExpIntVal);
|
||||||
|
|
||||||
|
FMemReader.RegisterSizes[2] := ReadSize;
|
||||||
|
GotRes := FMemManager.ReadSignedInt(RegisterLoc(2), ReadSize, GotInt);
|
||||||
|
CheckIntRes('signed Reg ', ExpIntVal);
|
||||||
|
|
||||||
|
for a := ReadSize+1 to 8 do begin
|
||||||
|
// expanded
|
||||||
|
FMemReader.RegisterSizes[2] := ReadSize;
|
||||||
|
GotRes := FMemManager.ReadSignedInt(RegisterLoc(2), a, GotInt);
|
||||||
|
CheckIntRes('signed Reg readsize='+IntToStr(a), ExpIntVal);
|
||||||
|
|
||||||
|
FMemReader.RegisterSizes[2] := a;
|
||||||
|
GotRes := FMemManager.ReadSignedInt(RegisterLoc(2), ReadSize, GotInt);
|
||||||
|
CheckIntRes('signed Reg regsize'+IntToStr(a), ExpIntVal);
|
||||||
|
end;
|
||||||
|
|
||||||
|
GotRes := FMemManager.ReadSignedInt(ConstLoc(QWord(ExpIntVal)), ReadSize, GotInt);
|
||||||
|
CheckIntRes('signed const (pre-expanded)', ExpIntVal);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure DoUnsignedIntTests(ReadSize: Cardinal; ExpIntVal: QWord);
|
||||||
|
var
|
||||||
|
a: Cardinal;
|
||||||
|
begin
|
||||||
|
GotRes := FMemManager.ReadUnsignedInt(TargetLoc(TDbgPtr(@Data)), ReadSize, GotUInt);
|
||||||
|
CheckUIntRes('unsigned target', ExpIntVal);
|
||||||
|
|
||||||
|
GotRes := FMemManager.ReadUnsignedInt(SelfLoc(@Data), ReadSize, GotUInt);
|
||||||
|
CheckUIntRes('unsigned self', ExpIntVal);
|
||||||
|
|
||||||
|
FMemReader.RegisterSizes[2] := ReadSize;
|
||||||
|
GotRes := FMemManager.ReadUnsignedInt(RegisterLoc(2), ReadSize, GotUInt);
|
||||||
|
CheckUIntRes('unsigned Reg ', ExpIntVal);
|
||||||
|
|
||||||
|
for a := ReadSize+1 to 8 do begin
|
||||||
|
// expanded
|
||||||
|
FMemReader.RegisterSizes[2] := ReadSize;
|
||||||
|
GotRes := FMemManager.ReadUnsignedInt(RegisterLoc(2), a, GotUInt);
|
||||||
|
CheckUIntRes('unsigned Reg readsize='+IntToStr(a), ExpIntVal);
|
||||||
|
|
||||||
|
FMemReader.RegisterSizes[2] := a;
|
||||||
|
GotRes := FMemManager.ReadUnsignedInt(RegisterLoc(2), ReadSize, GotUInt);
|
||||||
|
CheckUIntRes('unsigned Reg regsize'+IntToStr(a), ExpIntVal);
|
||||||
|
end;
|
||||||
|
|
||||||
|
GotRes := FMemManager.ReadUnsignedInt(ConstLoc(QWord(ExpIntVal)), ReadSize, GotUInt);
|
||||||
|
CheckUIntRes('unsigned const (pre-expanded)', ExpIntVal);
|
||||||
|
|
||||||
|
//////
|
||||||
|
// Address
|
||||||
|
GotRes := FMemManager.ReadAddress(TargetLoc(TDbgPtr(@Data)), ReadSize, GotAddr);
|
||||||
|
CheckAddrRes('addr target', ExpIntVal);
|
||||||
|
|
||||||
|
GotRes := FMemManager.ReadAddress(SelfLoc(@Data), ReadSize, GotAddr);
|
||||||
|
CheckAddrRes('addr self', ExpIntVal);
|
||||||
|
|
||||||
|
FMemReader.RegisterSizes[2] := ReadSize;
|
||||||
|
GotRes := FMemManager.ReadAddress(RegisterLoc(2), ReadSize, GotAddr);
|
||||||
|
CheckAddrRes('addr Reg ', ExpIntVal);
|
||||||
|
|
||||||
|
for a := ReadSize+1 to 8 do begin
|
||||||
|
// expanded
|
||||||
|
FMemReader.RegisterSizes[2] := ReadSize;
|
||||||
|
GotRes := FMemManager.ReadAddress(RegisterLoc(2), a, GotAddr);
|
||||||
|
CheckAddrRes('addr Reg readsize='+IntToStr(a), ExpIntVal);
|
||||||
|
|
||||||
|
FMemReader.RegisterSizes[2] := a;
|
||||||
|
GotRes := FMemManager.ReadAddress(RegisterLoc(2), ReadSize, GotAddr);
|
||||||
|
CheckAddrRes('addr Reg regsize'+IntToStr(a), ExpIntVal);
|
||||||
|
end;
|
||||||
|
|
||||||
|
GotRes := FMemManager.ReadAddress(ConstLoc(QWord(ExpIntVal)), ReadSize, GotAddr);
|
||||||
|
CheckAddrRes('addr const (pre-expanded)', ExpIntVal);
|
||||||
|
|
||||||
|
//////
|
||||||
|
// Address
|
||||||
|
GotAddr := FMemManager.ReadAddress(TargetLoc(TDbgPtr(@Data)), ReadSize);
|
||||||
|
GotRes := isValidLoc(GotAddr);
|
||||||
|
CheckAddrRes('addr target', ExpIntVal);
|
||||||
|
|
||||||
|
GotAddr := FMemManager.ReadAddress(SelfLoc(@Data), ReadSize);
|
||||||
|
GotRes := isValidLoc(GotAddr);
|
||||||
|
CheckAddrRes('addr self', ExpIntVal);
|
||||||
|
|
||||||
|
FMemReader.RegisterSizes[2] := ReadSize;
|
||||||
|
GotAddr := FMemManager.ReadAddress(RegisterLoc(2), ReadSize);
|
||||||
|
GotRes := isValidLoc(GotAddr);
|
||||||
|
CheckAddrRes('addr Reg ', ExpIntVal);
|
||||||
|
|
||||||
|
for a := ReadSize+1 to 8 do begin
|
||||||
|
// expanded
|
||||||
|
FMemReader.RegisterSizes[2] := ReadSize;
|
||||||
|
GotAddr := FMemManager.ReadAddress(RegisterLoc(2), a);
|
||||||
|
GotRes := isValidLoc(GotAddr);
|
||||||
|
CheckAddrRes('addr Reg readsize='+IntToStr(a), ExpIntVal);
|
||||||
|
|
||||||
|
FMemReader.RegisterSizes[2] := a;
|
||||||
|
GotAddr := FMemManager.ReadAddress(RegisterLoc(2), ReadSize);
|
||||||
|
GotRes := isValidLoc(GotAddr);
|
||||||
|
CheckAddrRes('addr Reg regsize'+IntToStr(a), ExpIntVal);
|
||||||
|
end;
|
||||||
|
|
||||||
|
GotAddr := FMemManager.ReadAddress(ConstLoc(QWord(ExpIntVal)), ReadSize);
|
||||||
|
GotRes := isValidLoc(GotAddr);
|
||||||
|
CheckAddrRes('addr const (pre-expanded)', ExpIntVal);
|
||||||
|
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
InitMemMgr;
|
||||||
|
|
||||||
|
TestBaseName := 'size 1';
|
||||||
|
SetData($00); DoSignedIntTests(1, 0);
|
||||||
|
SetData($08); DoSignedIntTests(1, 8);
|
||||||
|
SetData($7f); DoSignedIntTests(1, 127);
|
||||||
|
SetData($FB); DoSignedIntTests(1, -5);
|
||||||
|
SetData($80); DoSignedIntTests(1,-128);
|
||||||
|
SetData($FF); DoSignedIntTests(1, -1);
|
||||||
|
SetData($0108); DoSignedIntTests(1, 8);
|
||||||
|
|
||||||
|
TestBaseName := 'size 2';
|
||||||
|
SetData($0000); DoSignedIntTests(2, 0);
|
||||||
|
SetData($0108); DoSignedIntTests(2, 264);
|
||||||
|
SetData($00FB); DoSignedIntTests(2, 251);
|
||||||
|
SetData($FFFB); DoSignedIntTests(2, -5);
|
||||||
|
SetData($010208); DoSignedIntTests(2, 520);
|
||||||
|
|
||||||
|
TestBaseName := 'size 8';
|
||||||
|
SetData($7FAAFFBBFFCCFFDD); DoSignedIntTests(8, $7FAAFFBBFFCCFFDD);
|
||||||
|
SetData(QWord(-3)); DoSignedIntTests(8, -3);
|
||||||
|
|
||||||
|
|
||||||
|
TestBaseName := 'size 1';
|
||||||
|
SetData($00); DoUnsignedIntTests(1, 0);
|
||||||
|
SetData($08); DoUnsignedIntTests(1, 8);
|
||||||
|
SetData($7f); DoUnsignedIntTests(1, 127);
|
||||||
|
SetData($FB); DoUnsignedIntTests(1, 251);
|
||||||
|
SetData($80); DoUnsignedIntTests(1, 128);
|
||||||
|
SetData($FF); DoUnsignedIntTests(1, 255);
|
||||||
|
SetData($0108); DoSignedIntTests(1, 8);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
|
||||||
|
RegisterTest(TTestMemManager);
|
||||||
|
end.
|
||||||
|
|
@ -341,7 +341,7 @@ begin
|
|||||||
FImageLoader.Free;
|
FImageLoader.Free;
|
||||||
FMemReader.Free;
|
FMemReader.Free;
|
||||||
if FMemManager <> nil then
|
if FMemManager <> nil then
|
||||||
FMemManager.MemConvertor.Free;
|
FMemManager.TargetMemConvertor.Free;
|
||||||
FreeAndNil(FMemManager);
|
FreeAndNil(FMemManager);
|
||||||
inherited TearDown;
|
inherited TearDown;
|
||||||
end;
|
end;
|
||||||
@ -382,6 +382,16 @@ begin
|
|||||||
ExpResult(svfSize, SizeOf(ImgLoader.GlobalVar.VarSub5));
|
ExpResult(svfSize, SizeOf(ImgLoader.GlobalVar.VarSub5));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
StartTest('QWord($1122334455667748)', skCardinal, []);
|
||||||
|
ExpResult(svfCardinal, $1122334455667748);
|
||||||
|
|
||||||
|
StartTest('ShortInt(QWord($1122334455667748))', skInteger, []);
|
||||||
|
ExpResult(svfInteger, integer($48));
|
||||||
|
|
||||||
|
StartTest('ShortInt(QWord($11223344556677F8))', skInteger, []);
|
||||||
|
ExpResult(svfInteger, -8);
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestTypeInfo.TestExpressionBool;
|
procedure TTestTypeInfo.TestExpressionBool;
|
||||||
@ -471,7 +481,9 @@ begin
|
|||||||
StartTest('VarDynIntArray', skArray, [ttHasType]);
|
StartTest('VarDynIntArray', skArray, [ttHasType]);
|
||||||
StartTest('VarStatIntArray1', skArray, [ttHasType]);
|
StartTest('VarStatIntArray1', skArray, [ttHasType]);
|
||||||
|
|
||||||
|
ImgLoader.GlobalVar.VarDynIntArray := nil;
|
||||||
StartInvalTest('VarDynIntArray[0]', 'xxx');
|
StartInvalTest('VarDynIntArray[0]', 'xxx');
|
||||||
|
StartInvalTest('VarDynIntArray[1]', 'xxx');
|
||||||
|
|
||||||
SetLength(ImgLoader.GlobalVar.VarDynIntArray,33);
|
SetLength(ImgLoader.GlobalVar.VarDynIntArray,33);
|
||||||
ImgLoader.GlobalVar.VarDynIntArray[0] := 10;
|
ImgLoader.GlobalVar.VarDynIntArray[0] := 10;
|
||||||
|
Loading…
Reference in New Issue
Block a user