lazarus/components/fpdebug/test/testhelperclasses.pas

913 lines
22 KiB
ObjectPascal

unit TestHelperClasses;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FpImgReaderBase, FpDbgDwarfConst, FpDbgLoader, FpDbgInfo,
DbgIntfBaseTypes, FpdMemoryTools;
const
TestAddrSize = sizeof(Pointer);
type
{ TTestMemReader }
TTestMemReader = class(TFpDbgMemReaderBase)
public
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 ReadMemoryEx({%H-}AnAddress, {%H-}AnAddressSpace: TDbgPtr; {%H-}ASize: Cardinal; {%H-}ADest: Pointer): Boolean; override;
function ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr;
AContext: TFpDbgLocationContext): Boolean; override;
function RegisterSize(ARegNum: Cardinal): Integer; override;
end;
TTestDwarfAbbrev = class;
TTestDwarfInfoEntry = class;
{ TTestDummySection }
TTestDummySection = class
public
Section: TDbgImageSection;
procedure CreateSectionData; virtual;
end;
{ TTestDummyFileSource }
TTestDummyFileSource = class(TDbgImageReader)
private
FSections: TStringList;
function GetTestSection(const AName: String): TTestDummySection;
protected
function GetSection(const AName: String): PDbgImageSection; override;
//procedure LoadSections;
public
class function isValid({%H-}ASource: TDbgFileLoader): Boolean; override;
class function UserName: AnsiString; override;
public
constructor Create; overload;
destructor Destroy; override;
property TestSection[const AName: String]: TTestDummySection read GetTestSection;
end;
{ TTestDummyImageLoader }
TTestDummyImageLoader = class(TDbgImageLoader)
private
FImgReader: TTestDummyFileSource;
protected
public
constructor Create; override;
property TestImgReader: TTestDummyFileSource read FImgReader;
end;
TTestDummyImageLoaderClass = class of TTestDummyImageLoader;
{ TTestDummySectionAbbrevs }
TTestDummySectionAbbrevs = class(TTestDummySection)
private
FCurrentID: Cardinal;
FList: TList;
function GetNextID: Cardinal;
public
constructor Create;
destructor Destroy; override;
function GetNewAbbrevObj: TTestDwarfAbbrev;
procedure CreateSectionData; override;
end;
{ TTestDummySectionInfoEntries }
TTestDummySectionInfoEntries = class(TTestDummySection)
private
FAddrSize: Byte;
FFirstEntry: TTestDwarfInfoEntry;
FVersion: Word;
protected
function CreateInfoEntryObj: TTestDwarfInfoEntry;
public
AbbrevSection: TTestDummySectionAbbrevs;
constructor Create;
destructor Destroy; override;
property Version: Word read FVersion write FVersion;
property AddrSize: Byte read FAddrSize write FAddrSize;
function GetFirstInfoEntryObj: TTestDwarfInfoEntry;
procedure CreateSectionData; override;
end;
{ TTestDwarfAbbrev }
TTestDwarfAbbrev = class
private
FSection: TTestDummySectionAbbrevs;
FChildren: Byte;
FId: Cardinal;
FTag: Cardinal;
FData: Array of Cardinal;
FEncoded: Array of Byte;
procedure Encode;
public
property Id: Cardinal read FId write FId;
property Tag: Cardinal read FTag write FTag;
property Children: Byte read FChildren write FChildren;
procedure Add(ATag, AForm: Cardinal);
function DataLength: Integer;
function Data: Pointer;
end;
{ TTestDwarfInfoEntry }
PTestDwarfInfoEntry = ^TTestDwarfInfoEntry;
TTestDwarfInfoEntry = class
private
FAbbrevObj: TTestDwarfAbbrev;
FSection: TTestDummySectionInfoEntries;
FChildren: TList;
FEncoded: Array of Byte;
FRefList: array of record
Index, FSize: Integer;
AData: TTestDwarfInfoEntry;
ADataRef: PTestDwarfInfoEntry;
end;
function GetChildren: Byte;
function GetTag: Cardinal;
procedure InitEncoded;
procedure SetChildren(AValue: Byte);
procedure SetTag(AValue: Cardinal);
protected
FWrittenAtIndex: Integer;
function DataLengthIncl: Integer; // with Children
procedure WriteToSection(ASectionMem: PByte; AIndex: Integer);
procedure WriteToSectionFIxRef(ASectionMem: PByte);
public
constructor Create;
destructor Destroy; override;
property Tag: Cardinal read GetTag write SetTag;
property Children: Byte read GetChildren write SetChildren;
procedure Add(AnAttrib, AForm: Cardinal; AData: Array of Byte);
procedure Add(AnAttrib, AForm: Cardinal; AData: String);
procedure AddSLEB(AnAttrib, AForm: Cardinal; AData: Int64);
procedure AddULEB(AnAttrib, AForm: Cardinal; AData: QWord);
procedure AddAddr(AnAttrib, AForm: Cardinal; AData: QWord);
procedure Add(AnAttrib, AForm: Cardinal; AData: QWord); // ULEB
function AddRef(AnAttrib, AForm: Cardinal; AData: TTestDwarfInfoEntry): Integer;
function AddRef(AnAttrib, AForm: Cardinal; AData: PTestDwarfInfoEntry): Integer;
procedure SetRef(AIndex: Integer; AData: TTestDwarfInfoEntry);
function GetNewChild: TTestDwarfInfoEntry;
function DataLength: Integer; // Exclude Children
function Data: Pointer;
end;
function ULEB(ANum: QWord): TBytes;
function SLEB(ANum: Int64): TBytes;
function AddrB(ANum: Int64): TBytes;
function AddrB(ANum: Pointer): TBytes;
function NumS(ANum: Int64; ASize: Integer): TBytes;
function NumU(ANum: QWord; ASize: Integer): TBytes;
function Bytes(a: Array of TBytes): TBytes;
function BytesLen1(a: Array of TBytes): TBytes;
function BytesLen2(a: Array of TBytes): TBytes;
function BytesLen4(a: Array of TBytes): TBytes;
function BytesLen8(a: Array of TBytes): TBytes;
function BytesLenU(a: Array of TBytes): TBytes;
operator := (a: Smallint) b: TBytes;
implementation
operator := (a: Smallint)b: TBytes;
begin
assert( (a>= -128) and (a<=255));
SetLength(b, 1);
b[0] := Byte(a and 255);
end;
function Bytes(a: array of TBytes): TBytes;
var
i, l, p: Integer;
begin
l := 0;
for i := low(a) to high(a) do
l := l + Length(a[i]);
SetLength(Result, l);
p := 0;
for i := low(a) to high(a) do begin
l := Length(a[i]);
if l > 0 then
move(a[i][0], Result[p], l*SizeOf(Result[0]));
inc(p, l);
end;
end;
function BytesLen1(a: array of TBytes): TBytes;
var
l: Integer;
d: TBytes;
begin
d := Bytes(a);
l := Length(d);
assert(l <= $ff);
Result := Bytes([Byte(l), d]);
end;
function BytesLen2(a: array of TBytes): TBytes;
var
l: Integer;
b: array[0..1] of Byte;
d: TBytes;
begin
d := Bytes(a);
l := Length(d);
assert(l <= $ffff);
PWord(@b[0])^ := Word(l);
Result := Bytes([b[0], b[1], Bytes(d)]);
end;
function BytesLen4(a: array of TBytes): TBytes;
var
l: Integer;
b: array[0..3] of Byte;
d: TBytes;
begin
d := Bytes(a);
l := Length(d);
assert(l <= $ffff);
PDWord(@b[0])^ := DWord(l);
Result := Bytes([b[0], b[1], b[2], b[3], Bytes(d)]);
end;
function BytesLen8(a: array of TBytes): TBytes;
var
l: Integer;
b: array[0..7] of Byte;
d: TBytes;
begin
d := Bytes(a);
l := Length(d);
assert(l <= $ffff);
PQWord(@b[0])^ := QWord(l);
Result := Bytes([b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], Bytes(d)]);
end;
function BytesLenU(a: array of TBytes): TBytes;
var
l: Integer;
begin
l := Length(a);
Result := Bytes([ULEB(l), Bytes(a)]);
end;
procedure WriteULEB128(ANum: QWord; var ADest: TBytes; ADestIdx: Integer);
procedure AddByte(AByte: Byte);
begin
if ADestIdx >= Length(ADest) then SetLength(ADest, ADestIdx + 1);
ADest[ADestIdx] := AByte;
inc(ADestIdx);
end;
begin
if ANum = 0 then begin
AddByte(0);
exit;
end;;
while ANum <> 0 do begin
if ANum > $7f then
AddByte((ANum and $7f) + $80)
else
AddByte((ANum and $7f));
ANum := ANum shr 7;
end;
end;
procedure WriteSLEB128(ANum: Int64; var ADest: TBytes; ADestIdx: Integer);
procedure AddByte(AByte: Byte);
begin
if ADestIdx >= Length(ADest) then SetLength(ADest, ADestIdx + 1);
ADest[ADestIdx] := AByte;
inc(ADestIdx);
end;
var
n: Integer;
c: Boolean;
UNum: QWord;
begin
if ANum = 0 then begin
AddByte(0);
exit;
end;
if ANum < 0 then begin
UNum := QWord(ANum);
n := 9*7;
while n > 0 do begin
if ( (UNum and (QWord($7f) shl n)) = (high(QWord) and (QWord($7f) shl n)) ) and
( (UNum and (QWord(1) shl (n-1))) <> 0 )
then
UNum := UNum and not(high(QWord) shl n)
else
break;
dec(n, 7);
end;
while UNum <> 0 do begin
if UNum > $7f then
AddByte((UNum and $7f) + $80)
else
AddByte((UNum and $7f));
UNum := UNum shr 7;
end;
end
else begin
c := False;
while (ANum <> 0) or c do begin
c := (ANum and $40) <> 0; // write extra 0, to prevent sign extend
if c or (ANum > $7f) then
AddByte((ANum and $7f) + $80)
else
AddByte((ANum and $7f));
ANum := ANum shr 7;
end;
end;
end;
function ULEB(ANum: QWord): TBytes;
begin
SetLength(Result, 0);
WriteULEB128(ANum, Result, 0);
end;
function SLEB(ANum: Int64): TBytes;
begin
SetLength(Result, 0);
WriteSLEB128(ANum, Result, 0);
end;
function AddrB(ANum: Int64): TBytes;
begin
SetLength(Result, TestAddrSize);
if TestAddrSize = 4
then PInteger(@Result[0])^ := Integer(ANum)
else PInt64(@Result[0])^ := Int64(ANum);
end;
function AddrB(ANum: Pointer): TBytes;
begin
Result := AddrB(Int64(ANum));
end;
function NumS(ANum: Int64; ASize: Integer): TBytes;
begin
SetLength(Result, ASize);
case ASize of
1: PShortInt(@Result[0])^ := ShortInt(ANum);
2: PSmallInt(@Result[0])^ := SmallInt(ANum);
4: PInteger(@Result[0])^ := Integer(ANum);
8: PInt64(@Result[0])^ := Int64(ANum);
end;
end;
function NumU(ANum: QWord; ASize: Integer): TBytes;
begin
SetLength(Result, ASize);
case ASize of
1: PByte(@Result[0])^ := Byte(ANum);
2: PWord(@Result[0])^ := Word(ANum);
4: PDWord(@Result[0])^ := DWord(ANum);
8: PQWord(@Result[0])^ := QWord(ANum);
end;
end;
{ 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;
ADest: Pointer): Boolean;
begin
Result := AnAddress > 1000; // avoid reading at 0x0000
if not Result then exit;
Move(Pointer(AnAddress)^, ADest^, ASize);
end;
function TTestMemReader.ReadMemoryEx(AnAddress, AnAddressSpace: TDbgPtr;
ASize: Cardinal; ADest: Pointer): Boolean;
begin
Result := False;
end;
function TTestMemReader.ReadRegister(ARegNum: Cardinal; out AValue: TDbgPtr;
AContext: TFpDbgLocationContext): Boolean;
begin
Result := True;
AValue := RegisterValues[ARegNum];
end;
function TTestMemReader.RegisterSize(ARegNum: Cardinal): Integer;
begin
Result := RegisterSizes[ARegNum];
end;
{ TTestDwarfInfoEntry }
procedure TTestDwarfInfoEntry.InitEncoded;
begin
SetLength(FEncoded, 0);
WriteULEB128(FAbbrevObj.Id, FEncoded, length(FEncoded));
end;
function TTestDwarfInfoEntry.GetChildren: Byte;
begin
Result := FAbbrevObj.Children;
end;
function TTestDwarfInfoEntry.GetTag: Cardinal;
begin
Result := FAbbrevObj.Tag;
end;
procedure TTestDwarfInfoEntry.SetChildren(AValue: Byte);
begin
FAbbrevObj.Children := AValue;
end;
procedure TTestDwarfInfoEntry.SetTag(AValue: Cardinal);
begin
FAbbrevObj.Tag := AValue;
end;
function TTestDwarfInfoEntry.DataLengthIncl: Integer;
var
i: Integer;
begin
Result := DataLength;
for i := 0 to FChildren.Count - 1 do
Result := Result + TTestDwarfInfoEntry(FChildren[i]).DataLengthIncl;
end;
procedure TTestDwarfInfoEntry.WriteToSection(ASectionMem: PByte; AIndex: Integer);
var
i: Integer;
begin
FWrittenAtIndex := AIndex;
Move(FEncoded[0], (ASectionMem+AIndex)^, Length(FEncoded));
AIndex := AIndex + Length(FEncoded);
if FAbbrevObj.Children <> 0 then begin
for i := 0 to FChildren.Count - 1 do begin
TTestDwarfInfoEntry(FChildren[i]).WriteToSection(ASectionMem, AIndex);
AIndex := AIndex + TTestDwarfInfoEntry(FChildren[i]).DataLengthIncl;
end;
PByte(ASectionMem+AIndex)^ := 0;
AIndex := AIndex + 1;
end
else
Assert(FChildren.Count = 0);
WriteToSectionFIxRef(ASectionMem);
end;
procedure TTestDwarfInfoEntry.WriteToSectionFIxRef(ASectionMem: PByte);
var
i: Integer;
v: Integer;
o: TTestDwarfInfoEntry;
begin
for i := 0 to Length(FRefList) - 1 do begin
assert((FRefList[i].AData <> nil) xor (FRefList[i].ADataRef <> nil));
o := FRefList[i].AData;
if (o = nil) then
o := FRefList[i].ADataRef^;
v := o.FWrittenAtIndex;
case FRefList[i].FSize of
1: PByte(ASectionMem + FWrittenAtIndex + FRefList[i].Index)^ := v;
2: PWord(ASectionMem + FWrittenAtIndex + FRefList[i].Index)^ := v;
4: PCardinal(ASectionMem + FWrittenAtIndex + FRefList[i].Index)^ := v;
8: PQWord(ASectionMem + FWrittenAtIndex + FRefList[i].Index)^ := v;
end;
end;
for i := 0 to FChildren.Count - 1 do
TTestDwarfInfoEntry(FChildren[i]).WriteToSectionFIxRef(ASectionMem);
end;
constructor TTestDwarfInfoEntry.Create;
begin
FChildren := TList.Create;
end;
destructor TTestDwarfInfoEntry.Destroy;
var
i: Integer;
begin
for i := 0 to FChildren.Count - 1 do
TObject(FChildren[i]).Free;
FreeAndNil(FChildren);
inherited Destroy;
end;
procedure TTestDwarfInfoEntry.Add(AnAttrib, AForm: Cardinal; AData: array of Byte);
var
c: Integer;
begin
if Length(FEncoded) = 0 then InitEncoded;
FAbbrevObj.Add(AnAttrib, AForm);
if Length(AData) = 0 then exit;
c := Length(FEncoded);
SetLength(FEncoded, c + Length(AData));
Move(AData[0], FEncoded[c], Length(AData));
end;
procedure TTestDwarfInfoEntry.Add(AnAttrib, AForm: Cardinal; AData: String);
var
c: Integer;
begin
if Length(FEncoded) = 0 then InitEncoded;
FAbbrevObj.Add(AnAttrib, AForm);
if Length(AData) = 0 then exit;
c := Length(FEncoded);
SetLength(FEncoded, c + Length(AData));
Move(AData[1], FEncoded[c], Length(AData));
end;
procedure TTestDwarfInfoEntry.AddSLEB(AnAttrib, AForm: Cardinal; AData: Int64);
begin
if Length(FEncoded) = 0 then InitEncoded;
FAbbrevObj.Add(AnAttrib, AForm);
WriteSLEB128(AData, FEncoded, length(FEncoded));
end;
procedure TTestDwarfInfoEntry.AddULEB(AnAttrib, AForm: Cardinal; AData: QWord);
begin
if Length(FEncoded) = 0 then InitEncoded;
FAbbrevObj.Add(AnAttrib, AForm);
WriteULEB128(AData, FEncoded, length(FEncoded));
end;
procedure TTestDwarfInfoEntry.AddAddr(AnAttrib, AForm: Cardinal; AData: QWord);
var
c: Integer;
begin
if Length(FEncoded) = 0 then InitEncoded;
FAbbrevObj.Add(AnAttrib, AForm);
if FSection.FAddrSize = 4 then begin
c := Length(FEncoded);
SetLength(FEncoded, c + 4);
PCardinal(@FEncoded[c])^ := AData;
end else begin
c := Length(FEncoded);
SetLength(FEncoded, c + 8);
PQWord(@FEncoded[c])^ := AData;
end;
end;
procedure TTestDwarfInfoEntry.Add(AnAttrib, AForm: Cardinal; AData: QWord);
begin
AddULEB(AnAttrib, AForm, AData);
end;
function TTestDwarfInfoEntry.AddRef(AnAttrib, AForm: Cardinal;
AData: TTestDwarfInfoEntry): Integer;
var
c: Integer;
l: Integer;
begin
if Length(FEncoded) = 0 then InitEncoded;
FAbbrevObj.Add(AnAttrib, AForm);
Result := length(FRefList);
SetLength(FRefList, Result + 1);
l := TestAddrSize;
case AForm of
DW_FORM_ref1: l := 1;
DW_FORM_ref2: l := 2;
DW_FORM_ref4: l := 4;
DW_FORM_ref8: l := 8;
DW_FORM_ref_addr: l := FSection.AddrSize;
//DW_FORM_ref_udata: l := 1;
else Assert(false);
end;
FRefList[Result].AData := AData;
FRefList[Result].FSize := l;
FRefList[Result].Index := length(FEncoded);
c := Length(FEncoded);
SetLength(FEncoded, c + l);
case l of
1: PByte(@FEncoded[c])^ := 0;
2: PWord(@FEncoded[c])^ := 0;
4: PCardinal(@FEncoded[c])^ := 0;
8: PQWord(@FEncoded[c])^ := 0;
end;
end;
function TTestDwarfInfoEntry.AddRef(AnAttrib, AForm: Cardinal;
AData: PTestDwarfInfoEntry): Integer;
var
c: Integer;
l: Integer;
begin
if Length(FEncoded) = 0 then InitEncoded;
FAbbrevObj.Add(AnAttrib, AForm);
Result := length(FRefList);
SetLength(FRefList, Result + 1);
l := TestAddrSize;
case AForm of
DW_FORM_ref1: l := 1;
DW_FORM_ref2: l := 2;
DW_FORM_ref4: l := 4;
DW_FORM_ref8: l := 8;
DW_FORM_ref_addr: l := FSection.AddrSize;
//DW_FORM_ref_udata: l := 1;
else Assert(false);
end;
FRefList[Result].ADataRef := AData;
FRefList[Result].FSize := l;
FRefList[Result].Index := length(FEncoded);
c := Length(FEncoded);
SetLength(FEncoded, c + l);
case l of
1: PByte(@FEncoded[c])^ := 0;
2: PWord(@FEncoded[c])^ := 0;
4: PCardinal(@FEncoded[c])^ := 0;
8: PQWord(@FEncoded[c])^ := 0;
end;
end;
procedure TTestDwarfInfoEntry.SetRef(AIndex: Integer; AData: TTestDwarfInfoEntry);
begin
FRefList[AIndex].AData := AData;
end;
function TTestDwarfInfoEntry.GetNewChild: TTestDwarfInfoEntry;
begin
Result := FSection.CreateInfoEntryObj;
FChildren.Add(Result);
end;
function TTestDwarfInfoEntry.DataLength: Integer;
begin
if Length(FEncoded) = 0 then InitEncoded;
Result := Length(FEncoded);
if Children <> 0 then Result := Result + 1;
end;
function TTestDwarfInfoEntry.Data: Pointer;
begin
if Length(FEncoded) = 0 then InitEncoded;
Result := @FEncoded;
end;
{ TTestDummySectionInfoEntries }
function TTestDummySectionInfoEntries.CreateInfoEntryObj: TTestDwarfInfoEntry;
begin
Result := TTestDwarfInfoEntry.Create;
Result.FSection := Self;
assert(AbbrevSection <> nil);
Result.FAbbrevObj := AbbrevSection.GetNewAbbrevObj;
end;
constructor TTestDummySectionInfoEntries.Create;
begin
FVersion := 2;
FAddrSize := TestAddrSize;
end;
destructor TTestDummySectionInfoEntries.Destroy;
begin
FreeAndNil(FFirstEntry);
if Section.RawData <> nil then
Freemem(Section.RawData);
inherited Destroy;
end;
function TTestDummySectionInfoEntries.GetFirstInfoEntryObj: TTestDwarfInfoEntry;
begin
if FFirstEntry= nil then
FFirstEntry := CreateInfoEntryObj;
Result := FFirstEntry;
end;
procedure TTestDummySectionInfoEntries.CreateSectionData;
var
l: Integer;
begin
l := FFirstEntry.DataLengthIncl + 11; // 32 bit 4,2,4,1
Section.Size := l;
Section.RawData := AllocMem(l);
PCardinal(Section.RawData)^ := l - 4;
PWord(Section.RawData+4)^ := FVersion;
PCardinal(Section.RawData+6)^ := 0;
PByte(Section.RawData+10)^ := FAddrSize;
FFirstEntry.WriteToSection(Section.RawData, 11);
end;
{ TTestDwarfAbbrev }
procedure TTestDwarfAbbrev.Encode;
var
i: Integer;
begin
if length(FEncoded) > 0 then
exit;
WriteULEB128(FId, FEncoded, 0);
WriteULEB128(FTag, FEncoded, length(FEncoded));
WriteULEB128(FChildren, FEncoded, length(FEncoded)); // 0 or 1 / 1 byte
for i := 0 to Length(FData)-1 do
WriteULEB128(FData[i], FEncoded, length(FEncoded));
WriteULEB128(0, FEncoded, length(FEncoded));
WriteULEB128(0, FEncoded, length(FEncoded));
end;
procedure TTestDwarfAbbrev.Add(ATag, AForm: Cardinal);
var
c: Integer;
begin
c := Length(FData);
SetLength(FData, c + 2);
FData[c] := ATag;
FData[c+1] := AForm;
end;
function TTestDwarfAbbrev.DataLength: Integer;
begin
Encode;
Result := Length(FEncoded);
end;
function TTestDwarfAbbrev.Data: Pointer;
begin
Encode;
Result := @FEncoded[0];
end;
{ TTestDummySection }
procedure TTestDummySection.CreateSectionData;
begin
//
end;
{ TTestDummyFileSource }
function TTestDummyFileSource.GetTestSection(const AName: String): TTestDummySection;
var
i: Integer;
t: TTestDummySectionInfoEntries;
begin
Result := nil;
i := FSections.IndexOf(AName);
if i < 0 then begin
if AName = '.debug_abbrev' then
i := FSections.AddObject(AName, TTestDummySectionAbbrevs.Create)
else
if AName = '.debug_info' then begin
t := TTestDummySectionInfoEntries.Create;
t.AbbrevSection := GetTestSection('.debug_abbrev') as TTestDummySectionAbbrevs;
i := FSections.AddObject(AName, t);
end
else
i := FSections.AddObject(AName, TTestDummySection.Create);
end;
Result := TTestDummySection(FSections.Objects[i]);
end;
function TTestDummyFileSource.GetSection(const AName: String): PDbgImageSection;
var
i: Integer;
tmp: TTestDummySection;
begin
Result := nil;
i := FSections.IndexOf(AName);
if i < 0 then
exit;
tmp := TTestDummySection(FSections.Objects[i]);
Result := @tmp.Section;
end;
class function TTestDummyFileSource.isValid(ASource: TDbgFileLoader): Boolean;
begin
Result := True;
end;
class function TTestDummyFileSource.UserName: AnsiString;
begin
Result := 'Test Source';
end;
constructor TTestDummyFileSource.Create;
begin
inherited Create(nil, nil, False);
FSections := TStringList.Create;
end;
destructor TTestDummyFileSource.Destroy;
var
i: Integer;
begin
for i := 0 to FSections.Count - 1 do
FSections.Objects[i].Free;
FreeAndNil(FSections);
inherited Destroy;
end;
{ TTestDummyImageLoader }
constructor TTestDummyImageLoader.Create;
begin
FImgReader := TTestDummyFileSource.Create;
ImgReader := FImgReader; // vill be destroyed by base
inherited Create;
end;
{ TTestDummySectionAbbrevs }
function TTestDummySectionAbbrevs.GetNextID: Cardinal;
begin
Result := FCurrentID;
inc(FCurrentID);
end;
constructor TTestDummySectionAbbrevs.Create;
begin
FList := TList.Create;
Section.Size := 0;
Section.RawData := nil;
FCurrentID := 1;;
end;
destructor TTestDummySectionAbbrevs.Destroy;
begin
while FList.Count > 0 do begin
TObject(FList[0]).Free;
FList.Delete(0);
end;
FreeAndNil(FList);
if Section.RawData <> nil then
Freemem(Section.RawData);
inherited Destroy;
end;
function TTestDummySectionAbbrevs.GetNewAbbrevObj: TTestDwarfAbbrev;
begin
Result := TTestDwarfAbbrev.Create;
Result.FSection := Self;
Result.Id := GetNextID;
FList.Add(Result);
end;
procedure TTestDummySectionAbbrevs.CreateSectionData;
var
i, j, l: Integer;
begin
l := 1; // one for zero at end
for i := 0 to FList.Count - 1 do
l := l + TTestDwarfAbbrev(FList[i]).DataLength;
Section.Size := l;
Section.RawData := AllocMem(l);
j := 0;
for i := 0 to FList.Count - 1 do begin
l := TTestDwarfAbbrev(FList[i]).DataLength;
move(TTestDwarfAbbrev(FList[i]).Data^, (Section.RawData+j)^, l);
j := j + l;
end;
PByte(Section.RawData+j)^ := 0;
assert(j < Section.Size);
end;
end.