FPDebug: start using mem-manager

git-svn-id: trunk@44028 -
This commit is contained in:
martin 2014-02-12 15:21:28 +00:00
parent 1dfc8873d3
commit 2978fbf036
6 changed files with 387 additions and 242 deletions

View File

@ -430,7 +430,7 @@ procedure DebugLoop;
end;
WriteLn(sym.FileName, ' ', sym.Line, ':', sym.Column, ' ', sym.Name);
Write(' [', FormatAddress(sym.Address), '+', a-sym.Address, '] ');
Write(' [', FormatAddress(LocToAddrOrNil(sym.Address)), '+', a-LocToAddrOrNil(sym.Address), '] ');
Name := sym.Filename;
if not FileExistsUTF8(Name)

File diff suppressed because it is too large Load Diff

View File

@ -141,9 +141,9 @@ type
function GetAsString: AnsiString; virtual;
function GetAsWideString: WideString; virtual;
function GetAddress: TDbgPtr; virtual;
function GetAddress: TFpDbgMemLocation; virtual;
function GetSize: Integer; virtual; // returns -1, if not available
function GetDataAddress: TDbgPtr; virtual;
function GetDataAddress: TFpDbgMemLocation; virtual;
function GetDataSize: Integer; virtual;
function GetMember(AIndex: Integer): TDbgSymbolValue; virtual;
@ -172,9 +172,9 @@ type
// complex
// double
property Address: TDbgPtr read GetAddress; // Address of variable
property Address: TFpDbgMemLocation read GetAddress; // Address of variable
property Size: Integer read GetSize; // Size of variable
property DataAddress: TDbgPtr read GetDataAddress; // Address of Data, if avail (e.g. String, TObject, ..., BUT NOT record)
property DataAddress: TFpDbgMemLocation read GetDataAddress; // Address of Data, if avail (e.g. String, TObject, ..., BUT NOT record)
property DataSize: Integer read GetDataSize; // Sive of Data, if avail (e.g. String, TObject, ..., BUT NOT record)
// memdump
public
@ -228,14 +228,14 @@ type
TDbgSymbolValueConstAddress = class(TDbgSymbolValue)
private
FAddress: TDbgPtr;
FAddress: TFpDbgMemLocation;
protected
property Address: QWord read FAddress write FAddress;
property Address: TFpDbgMemLocation read FAddress write FAddress;
//function GetKind: TDbgSymbolKind; override; // no kind
function GetFieldFlags: TDbgSymbolValueFieldFlags; override;
function GetAddress: TDbgPtr; override;
function GetAddress: TFpDbgMemLocation; override;
public
constructor Create(AnAddress: TDbgPtr);
constructor Create(AnAddress: TFpDbgMemLocation);
end;
{ TDbgSymbol }
@ -248,7 +248,7 @@ type
FName: String;
FKind: TDbgSymbolKind;
FSymbolType: TDbgSymbolType;
FAddress: TDbgPtr;
FAddress: TFpDbgMemLocation;
FSize: Integer;
FTypeInfo: TDbgSymbol;
FMemberVisibility: TDbgSymbolMemberVisibility; // Todo: not cached
@ -257,7 +257,7 @@ type
function GetKind: TDbgSymbolKind; inline;
function GetName: String; inline;
function GetSize: Integer; inline;
function GetAddress: TDbgPtr; inline;
function GetAddress: TFpDbgMemLocation; inline;
function GetTypeInfo: TDbgSymbol; inline;
function GetMemberVisibility: TDbgSymbolMemberVisibility; inline;
protected
@ -287,7 +287,7 @@ type
procedure SetName(AValue: String); inline;
procedure SetKind(AValue: TDbgSymbolKind); inline;
procedure SetSymbolType(AValue: TDbgSymbolType); inline;
procedure SetAddress(AValue: TDbgPtr); inline;
procedure SetAddress(AValue: TFpDbgMemLocation); inline;
procedure SetSize(AValue: Integer); inline;
procedure SetTypeInfo(AValue: TDbgSymbol); inline;
procedure SetMemberVisibility(AValue: TDbgSymbolMemberVisibility); inline;
@ -302,7 +302,7 @@ type
//procedure Needed; virtual;
public
constructor Create(const AName: String);
constructor Create(const AName: String; AKind: TDbgSymbolKind; AAddress: TDbgPtr);
constructor Create(const AName: String; AKind: TDbgSymbolKind; AAddress: TFpDbgMemLocation);
destructor Destroy; override;
// Basic info
property Name: String read GetName;
@ -310,7 +310,7 @@ type
property Kind: TDbgSymbolKind read GetKind;
// Memory; Size is also part of type (byte vs word vs ...)
// HasAddress // (register does not have)
property Address: TDbgPtr read GetAddress;
property Address: TFpDbgMemLocation read GetAddress;
property Size: Integer read GetSize; // In Bytes
// TypeInfo used by
// stValue (Variable): Type
@ -393,14 +393,14 @@ type
protected
function GetAddress: TDbgPtr; virtual; abstract;
function GetSymbolAtAddress: TDbgSymbol; virtual;
function GetMemReader: TFpDbgMemReaderBase; virtual;
function GetMemManager: TFpDbgMemManager; virtual;
function GetSizeOfAddress: Integer; virtual;
public
property Address: TDbgPtr read GetAddress;
property SymbolAtAddress: TDbgSymbol read GetSymbolAtAddress;
// search this, and all parent context
function FindSymbol(const {%H-}AName: String): TDbgSymbol; virtual;
property MemReader: TFpDbgMemReaderBase read GetMemReader;
property MemManager: TFpDbgMemManager read GetMemManager;
property SizeOfAddress: Integer read GetSizeOfAddress;
end;
@ -418,6 +418,7 @@ type
function FindSymbol({%H-}AAddress: TDbgPtr): TDbgSymbol; virtual; deprecated;
property HasInfo: Boolean read FHasInfo;
function GetLineAddress(const {%H-}AFileName: String; {%H-}ALine: Cardinal): TDbgPtr; virtual;
//property MemManager: TFpDbgMemReaderBase read GetMemManager write SetMemManager;
end;
function dbgs(ADbgSymbolKind: TDbgSymbolKind): String; overload;
@ -437,12 +438,12 @@ begin
Result := [svfAddress, svfSizeOfPointer]
end;
function TDbgSymbolValueConstAddress.GetAddress: TDbgPtr;
function TDbgSymbolValueConstAddress.GetAddress: TFpDbgMemLocation;
begin
Result := FAddress;
end;
constructor TDbgSymbolValueConstAddress.Create(AnAddress: TDbgPtr);
constructor TDbgSymbolValueConstAddress.Create(AnAddress: TFpDbgMemLocation);
begin
inherited Create;
FAddress := AnAddress;
@ -601,14 +602,14 @@ begin
Result := 0;
end;
function TDbgSymbolValue.GetAddress: TDbgPtr;
function TDbgSymbolValue.GetAddress: TFpDbgMemLocation;
begin
Result := 0;
Result := InvalidLoc;
end;
function TDbgSymbolValue.GetDataAddress: TDbgPtr;
function TDbgSymbolValue.GetDataAddress: TFpDbgMemLocation;
begin
Result := 0;
Result := InvalidLoc;
end;
function TDbgSymbolValue.GetDataSize: Integer;
@ -673,7 +674,7 @@ end;
{ TDbgInfoAddressContext }
function TDbgInfoAddressContext.GetMemReader: TFpDbgMemReaderBase;
function TDbgInfoAddressContext.GetMemManager: TFpDbgMemManager;
begin
Result := nil;
end;
@ -703,7 +704,8 @@ begin
SetName(AName);
end;
constructor TDbgSymbol.Create(const AName: String; AKind: TDbgSymbolKind; AAddress: TDbgPtr);
constructor TDbgSymbol.Create(const AName: String; AKind: TDbgSymbolKind;
AAddress: TFpDbgMemLocation);
begin
Create(AName);
SetKind(AKind);
@ -721,7 +723,7 @@ begin
Result := nil;
end;
function TDbgSymbol.GetAddress: TDbgPtr;
function TDbgSymbol.GetAddress: TFpDbgMemLocation;
begin
if not(sfiAddress in FEvaluatedFields) then
AddressNeeded;
@ -815,7 +817,7 @@ begin
Result := 0;
end;
procedure TDbgSymbol.SetAddress(AValue: TDbgPtr);
procedure TDbgSymbol.SetAddress(AValue: TFpDbgMemLocation);
begin
FAddress := AValue;
Include(FEvaluatedFields, sfiAddress);
@ -917,7 +919,7 @@ end;
procedure TDbgSymbol.AddressNeeded;
begin
SetAddress(0);
SetAddress(InvalidLoc);
end;
procedure TDbgSymbol.SizeNeeded;

View File

@ -8,7 +8,7 @@ uses
Classes, SysUtils;
type
TDbgPtr = QWord; // PtrUInt;
TDbgPtr = QWord; // TODO, use from IdeDebuggerInterface, once that is done.
TFpDbgMemReaderBase = class
public
@ -20,6 +20,7 @@ type
end;
// Todo, cpu/language specific operations, endianess, sign extend, float .... default int value for bool
// TODO: currently it assumes target and own mem are in the same format
TFpDbgMemConvertor = class
public
(* To copy a smaller int/cardinal (e.g. word) into a bigger (e.g. dword),
@ -62,12 +63,13 @@ type
* TODO: allow to pre-read and cache Target mem (e.g. before reading all fields of a record
*)
TFpDbgMemLocationType = (
mlfInvalid,
mlfTargetMem, // an address in the target (debuggee) process
mlfSelfMem, // an address in this(the debuggers) process memory
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
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
mlfConstant // an (up to) SizeOf(TDbgPtr) (=8) Bytes Value (endian in format of debug process)
);
TFpDbgMemLocation = record
@ -88,20 +90,46 @@ type
function ReadMemoryEx(ALocation: TFpDbgMemLocation; AnAddressSpace: TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean;
function ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr): Boolean;
function ReadAddress(ALocation: TFpDbgMemLocation; ASize: Cardinal): TFpDbgMemLocation;
function ReadAddressEx(ALocation: TFpDbgMemLocation; AnAddressSpace: TDbgPtr; ASize: Cardinal): TFpDbgMemLocation;
property MemConvertor: TFpDbgMemConvertor read FMemConvertor;
end;
function NilLoc: TFpDbgMemLocation; inline;
function InvalidLoc: TFpDbgMemLocation; inline;
function TargetLoc(AnAddress: TDbgPtr): TFpDbgMemLocation; inline;
function RegisterLoc(ARegNum: Cardinal): TFpDbgMemLocation; inline;
function RegisterSignedLoc(ARegNum: Cardinal): TFpDbgMemLocation; inline;
function SelfLoc(AnAddress: TDbgPtr): TFpDbgMemLocation; inline;
function SelfLoc(AnAddress: Pointer): TFpDbgMemLocation; inline;
function ConstLoc(AValue: QWord): TFpDbgMemLocation; inline;
function IsTargetAddr(ALocation: TFpDbgMemLocation): Boolean; inline;
function LocToAddr(ALocation: TFpDbgMemLocation): TDbgPtr; inline;
function IsValidLoc(ALocation: TFpDbgMemLocation): Boolean; inline; // Valid, Nil allowed
function IsReadableLoc(ALocation: TFpDbgMemLocation): Boolean; inline; // Valid and not Nil
function IsTargetNil(ALocation: TFpDbgMemLocation): Boolean; inline; // valid targed = nil
function IsTargetNotNil(ALocation: TFpDbgMemLocation): Boolean; inline; // valid targed <> nil
function LocToAddr(ALocation: TFpDbgMemLocation): TDbgPtr; inline; // does not check valid
function LocToAddrOrNil(ALocation: TFpDbgMemLocation): TDbgPtr; inline; // save version
function dbgs(ALocation: TFpDbgMemLocation): String; overload;
implementation
function NilLoc: TFpDbgMemLocation;
begin
Result.Address := 0;
Result.MType := mlfTargetMem;
end;
function InvalidLoc: TFpDbgMemLocation;
begin
Result.Address := 0;
Result.MType := mlfInvalid;
end;
function TargetLoc(AnAddress: TDbgPtr): TFpDbgMemLocation;
begin
Result.Address := AnAddress;
@ -126,6 +154,12 @@ begin
Result.MType := mlfSelfMem;
end;
function SelfLoc(AnAddress: Pointer): TFpDbgMemLocation;
begin
Result.Address := TDbgPtr(AnAddress);
Result.MType := mlfSelfMem;
end;
function ConstLoc(AValue: QWord): TFpDbgMemLocation;
begin
Result.Address := AValue;
@ -137,12 +171,52 @@ begin
Result := ALocation.MType = mlfTargetMem;
end;
function IsValidLoc(ALocation: TFpDbgMemLocation): Boolean;
begin
Result := (ALocation.MType <> mlfInvalid);
end;
function IsReadableLoc(ALocation: TFpDbgMemLocation): Boolean;
begin
Result := (ALocation.MType <> mlfInvalid) and
( (not(ALocation.MType in [mlfTargetMem, mlfSelfMem])) or
(ALocation.Address <> 0)
);
end;
function IsTargetNil(ALocation: TFpDbgMemLocation): Boolean;
begin
Result := (ALocation.MType = mlfTargetMem) and (ALocation.Address = 0);
end;
function IsTargetNotNil(ALocation: TFpDbgMemLocation): Boolean;
begin
Result := (ALocation.MType = mlfTargetMem) and (ALocation.Address <> 0);
end;
function LocToAddr(ALocation: TFpDbgMemLocation): TDbgPtr;
begin
assert(ALocation.MType = mlfTargetMem, 'LocToAddr for other than mlfTargetMem');
Result := ALocation.Address;
end;
function LocToAddrOrNil(ALocation: TFpDbgMemLocation): TDbgPtr;
begin
if (ALocation.MType = mlfTargetMem) then
Result := ALocation.Address
else
Result := 0;
end;
function dbgs(ALocation: TFpDbgMemLocation): String;
begin
Result := '';
if not (ALocation.MType in [low(TFpDbgMemLocationType)..high(TFpDbgMemLocationType)]) then
Result := 'Location=out-of-range'
else
WriteStr(Result, 'Location=', ALocation.Address, ',', ALocation.MType)
end;
{ TFpDbgMemConvertorLittleEndian }
procedure TFpDbgMemConvertorLittleEndian.AdjustIntPointer(var ADestPointer: Pointer;
@ -194,6 +268,7 @@ var
begin
Result := False;
case ALocation.MType of
mlfInvalid: ;
mlfTargetMem:
Result := FMemReader.ReadMemory(ALocation.Address, ASize, ADest);
mlfSelfMem:
@ -252,5 +327,45 @@ begin
Result := FMemReader.ReadRegister(ARegNum, AValue);
end;
function TFpDbgMemManager.ReadAddress(ALocation: TFpDbgMemLocation;
ASize: Cardinal): TFpDbgMemLocation;
var
Dest: PQWord;
begin
Assert(ASize < SizeOf(Result.Address), 'TFpDbgMemManager.ReadAddress');
if ASize > SizeOf(Result.Address) then begin
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;
end;
function TFpDbgMemManager.ReadAddressEx(ALocation: TFpDbgMemLocation; AnAddressSpace: TDbgPtr;
ASize: Cardinal): TFpDbgMemLocation;
var
Dest: PQWord;
begin
Assert(ASize < SizeOf(Result.Address), 'TFpDbgMemManager.ReadAddress');
if ASize > SizeOf(Result.Address) then begin
Result := InvalidLoc;
exit;
end;
Result.Address := 0;
Dest := @Result.Address;
MemConvertor.AdjustIntPointer(Dest, ASize, SizeOf(Result.Address));
if ReadMemoryEx(ALocation, AnAddressSpace, ASize, Dest) then
Result.MType := mlfTargetMem
else
Result := InvalidLoc;
end;
end.

View File

@ -447,7 +447,7 @@ type
function GetFieldFlags: TDbgSymbolValueFieldFlags; override;
function GetTypeInfo: TDbgSymbol; override;
function GetAsCardinal: QWord; override;
function GetDataAddress: TDbgPtr; override;
function GetDataAddress: TFpDbgMemLocation; override;
public
constructor Create(AValue: TDbgSymbolValue; ATypeInfo: TDbgSymbol);
destructor Destroy; override;
@ -477,13 +477,13 @@ type
private
FValue: TDbgSymbolValue;
FExpression: TFpPascalExpression; // MemReader / AddrSize
FCardinal: QWord;
FCardinal: QWord; // todo: TFpDbgMemLocation ?
FCardinalRead: Boolean;
protected
function DebugText(AIndent: String): String; override;
protected
function GetFieldFlags: TDbgSymbolValueFieldFlags; override;
function GetAddress: TDbgPtr; override;
function GetAddress: TFpDbgMemLocation; override;
function GetSize: Integer; override;
function GetAsCardinal: QWord; override; // reads men
function GetTypeInfo: TDbgSymbol; override;
@ -509,7 +509,7 @@ type
function GetAsInteger: Int64; override;
function GetAsCardinal: QWord; override;
function GetTypeInfo: TDbgSymbol; override;
function GetDataAddress: TDbgPtr; override;
function GetDataAddress: TFpDbgMemLocation; override;
public
constructor Create(AValue: TDbgSymbolValue);
destructor Destroy; override;
@ -574,9 +574,9 @@ begin
Result := 0;
end;
function TPasParserSymbolValueCastToPointer.GetDataAddress: TDbgPtr;
function TPasParserSymbolValueCastToPointer.GetDataAddress: TFpDbgMemLocation;
begin
Result := TDbgPtr(FValue.AsCardinal);
Result := TargetLoc(TDbgPtr(FValue.AsCardinal));
end;
constructor TPasParserSymbolValueCastToPointer.Create(AValue: TDbgSymbolValue;
@ -656,13 +656,13 @@ begin
if t <> nil then
if t.Kind = skPointer then begin
//Result := Result + [svfSizeOfPointer];
Result := Result + [svfSizeOfPointer, svfCardinal, svfOrdinal];
Result := Result + [svfSizeOfPointer, svfCardinal, svfOrdinal]; // TODO: svfCardinal ???
end
else
Result := Result + [svfSize];
end;
function TPasParserSymbolValueDerefPointer.GetAddress: TDbgPtr;
function TPasParserSymbolValueDerefPointer.GetAddress: TFpDbgMemLocation;
begin
Result := FValue.DataAddress;
end;
@ -681,8 +681,8 @@ end;
function TPasParserSymbolValueDerefPointer.GetAsCardinal: QWord;
var
m: TFpDbgMemReaderBase;
Addr: TDbgPtr;
m: TFpDbgMemManager;
Addr: TFpDbgMemLocation;
Ctx: TDbgInfoAddressContext;
AddrSize: Integer;
begin
@ -693,14 +693,14 @@ begin
if Ctx = nil then exit;
AddrSize := Ctx.SizeOfAddress;
if (AddrSize <= 0) or (AddrSize > SizeOf(FCardinal)) then exit;
m := Ctx.MemReader;
m := Ctx.MemManager;
if m = nil then exit;
FCardinal := 0;
FCardinalRead := True;
Addr := GetAddress;
if Addr = 0 then exit;
m.ReadMemory(Addr, Ctx.SizeOfAddress, @FCardinal);
if not IsReadableLoc(Addr) then exit;
FCardinal := LocToAddrOrNil(m.ReadAddress(Addr, Ctx.SizeOfAddress));
Result := FCardinal;
end;
@ -758,12 +758,12 @@ end;
function TPasParserSymbolValueAddressOf.GetAsInteger: Int64;
begin
Result := Int64(FValue.Address);
Result := Int64(LocToAddrOrNil(FValue.Address));
end;
function TPasParserSymbolValueAddressOf.GetAsCardinal: QWord;
begin
Result := QWord(FValue.Address);
Result := QWord(LocToAddrOrNil(FValue.Address));
end;
function TPasParserSymbolValueAddressOf.GetTypeInfo: TDbgSymbol;
@ -779,7 +779,7 @@ begin
Result := FTypeInfo;
end;
function TPasParserSymbolValueAddressOf.GetDataAddress: TDbgPtr;
function TPasParserSymbolValueAddressOf.GetDataAddress: TFpDbgMemLocation;
begin
Result := FValue.Address;
end;
@ -1878,7 +1878,7 @@ begin
if Count <> 1 then exit;
tmp := Items[0].ResultValue;
if (tmp = nil) or (tmp.Address = 0) then
if (tmp = nil) or not IsTargetAddr(tmp.Address) then
exit;
Result := TPasParserSymbolValueAddressOf.Create(tmp);
@ -1958,7 +1958,7 @@ begin
end
else
if tmp.Kind = skPointer then begin
if (svfDataAddress in tmp.FieldFlags) and (tmp.DataAddress <> 0) and
if (svfDataAddress in tmp.FieldFlags) and (IsReadableLoc(tmp.DataAddress)) and
(tmp.TypeInfo <> nil) //and (tmp.TypeInfo.TypeInfo <> nil)
then begin
//TODO: maybe introduce a method TypeCastFromAddress, so we can skip the twp2 object

View File

@ -25,6 +25,7 @@ type
FExpression: TFpPascalExpression;
FImageLoader: TTestDummyImageLoader;
FMemReader: TTestMemReader;
FMemManager: TFpDbgMemManager;
procedure AssertEqualsQW(const AMessage: string; Expected, Actual: QWord);
@ -163,9 +164,9 @@ begin
ExpFlags([Field]);
WriteStr(s, FCurrentTestName, Field);
case Field of
svfAddress: AssertEqualsQW('VAlue for '+s, ExpValue, AVal.Address);
svfAddress: AssertEqualsQW('VAlue for '+s, ExpValue, LocToAddrOrNil(AVal.Address));
svfSize: AssertEqualsQW('VAlue for '+s, ExpValue, AVal.Size);
svfDataAddress: AssertEqualsQW('VAlue for '+s, ExpValue, AVal.DataAddress);
svfDataAddress: AssertEqualsQW('VAlue for '+s, ExpValue, LocToAddrOrNil(AVal.DataAddress));
svfDataSize: AssertEqualsQW('VAlue for '+s, ExpValue, AVal.DataSize);
svfInteger: AssertEqualsQW('VAlue for '+s, ExpValue, AVal.AsInteger);
svfCardinal: AssertEqualsQW('VAlue for '+s, ExpValue, AVal.AsCardinal);
@ -182,9 +183,9 @@ begin
ExpFlags([Field]);
WriteStr(s, FCurrentTestName, Field);
case Field of
svfAddress: AssertEquals('VAlue for '+s, ExpValue, AVal.Address);
svfAddress: AssertEquals('VAlue for '+s, ExpValue, LocToAddrOrNil(AVal.Address));
svfSize: AssertEquals('VAlue for '+s, ExpValue, AVal.Size);
svfDataAddress: AssertEquals('VAlue for '+s, ExpValue, AVal.DataAddress);
svfDataAddress: AssertEquals('VAlue for '+s, ExpValue, LocToAddrOrNil(AVal.DataAddress));
svfDataSize: AssertEquals('VAlue for '+s, ExpValue, AVal.DataSize);
svfInteger: AssertEquals('VAlue for '+s, ExpValue, AVal.AsInteger);
svfCardinal: AssertEquals('VAlue for '+s, ExpValue, AVal.AsCardinal);
@ -314,9 +315,10 @@ procedure TTestTypeInfo.InitDwarf(ALoaderClass: TTestDummyImageLoaderClass);
begin
FImageLoader := ALoaderClass.Create;
FMemReader := TTestMemReader.Create;
FMemManager := TFpDbgMemManager.Create(FMemReader, TFpDbgMemConvertorLittleEndian.Create);
FDwarfInfo := TDbgDwarf.Create(FImageLoader);
FDwarfInfo.MemManager := FMemManager;
FDwarfInfo.LoadCompilationUnits;
FDwarfInfo.MemReader := FMemReader;
end;
procedure TTestTypeInfo.SetUp;
@ -324,6 +326,7 @@ begin
inherited SetUp;
FImageLoader := nil;
FMemReader := nil;
FMemManager := nil;
FDwarfInfo := nil;
FCurrentTestName := '';
FCurrentContext := nil;
@ -337,6 +340,9 @@ begin
FDwarfInfo.Free;
FImageLoader.Free;
FMemReader.Free;
if FMemManager <> nil then
FMemManager.MemConvertor.Free;
FreeAndNil(FMemManager);
inherited TearDown;
end;