mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-06 22:26:29 +02:00
FPDebug: testcase
git-svn-id: trunk@43867 -
This commit is contained in:
parent
627e03971e
commit
513a42d90d
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1276,6 +1276,7 @@ components/fpdebug/test/asmtest.lpi svneol=native#text/plain
|
||||
components/fpdebug/test/asmtest.lpr svneol=native#text/pascal
|
||||
components/fpdebug/test/asmtestunit.lfm svneol=native#text/plain
|
||||
components/fpdebug/test/asmtestunit.pas svneol=native#text/pascal
|
||||
components/fpdebug/test/testdwarfsetup1.pas svneol=native#text/pascal
|
||||
components/fpdebug/test/testhelperclasses.pas svneol=native#text/pascal
|
||||
components/fpdebug/test/testpascalparser.pas svneol=native#text/pascal
|
||||
components/fpdebug/test/testtypeinfo.pas svneol=native#text/pascal
|
||||
|
@ -299,6 +299,7 @@ type
|
||||
FData: PByte;
|
||||
FMaxData: PByte;
|
||||
public
|
||||
//TODO: caller keeps data, and determines livetime of data
|
||||
constructor Create(AExpressionData: Pointer; AMaxCount: Integer; ACU: TDwarfCompilationUnit);
|
||||
procedure Evaluate;
|
||||
function ResultKind: TDwarfLocationStackEntryKind;
|
||||
|
@ -42,7 +42,7 @@
|
||||
<PackageName Value="FCL"/>
|
||||
</Item4>
|
||||
</RequiredPackages>
|
||||
<Units Count="3">
|
||||
<Units Count="5">
|
||||
<Unit0>
|
||||
<Filename Value="FpTest.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
@ -58,6 +58,16 @@
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="TestTypeInfo"/>
|
||||
</Unit2>
|
||||
<Unit3>
|
||||
<Filename Value="testhelperclasses.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="TestHelperClasses"/>
|
||||
</Unit3>
|
||||
<Unit4>
|
||||
<Filename Value="testdwarfsetup1.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="TestDwarfSetup1"/>
|
||||
</Unit4>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
@ -3,7 +3,8 @@ program FpTest;
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
Interfaces, Forms, GuiTestRunner, TestPascalParser, TestTypeInfo, TestHelperClasses;
|
||||
Interfaces, Forms, GuiTestRunner, TestPascalParser, TestTypeInfo, TestHelperClasses,
|
||||
TestDwarfSetup1;
|
||||
|
||||
{$R *.res}
|
||||
|
||||
|
2462
components/fpdebug/test/testdwarfsetup1.pas
Normal file
2462
components/fpdebug/test/testdwarfsetup1.pas
Normal file
File diff suppressed because one or more lines are too long
@ -5,10 +5,23 @@ unit TestHelperClasses;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, FpImgReaderBase, FpDbgDwarfConst, FpDbgLoader;
|
||||
Classes, SysUtils, FpImgReaderBase, FpDbgDwarfConst, FpDbgLoader, FpDbgInfo;
|
||||
|
||||
const
|
||||
TestAddrSize = sizeof(Pointer);
|
||||
|
||||
type
|
||||
|
||||
{ TTestMemReader }
|
||||
|
||||
TTestMemReader = class(TFpDbgMemReaderBase)
|
||||
public
|
||||
RegisterValues: array[0..30] of TDbgPtr;
|
||||
function ReadMemory(AnAddress: FpDbgInfo.TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||
function ReadMemoryEx({%H-}AnAddress, {%H-}AnAddressSpace: FpDbgInfo.TDbgPtr; {%H-}ASize: Cardinal; {%H-}ADest: Pointer): Boolean; override;
|
||||
function ReadRegister(ARegNum: Integer; out AValue: FpDbgInfo.TDbgPtr): Boolean; override;
|
||||
end;
|
||||
|
||||
TTestDwarfAbbrev = class;
|
||||
TTestDwarfInfoEntry = class;
|
||||
|
||||
@ -20,56 +33,6 @@ type
|
||||
procedure CreateSectionData; virtual;
|
||||
end;
|
||||
|
||||
{ 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;
|
||||
|
||||
(*
|
||||
TDwarfCUHeader32 = record
|
||||
Length: LongWord;
|
||||
Version: Word;
|
||||
AbbrevOffset: LongWord;
|
||||
AddressSize: Byte;
|
||||
end;
|
||||
|
||||
TDwarfCUHeader64 = record
|
||||
Signature: LongWord;
|
||||
Length: QWord;
|
||||
Version: Word;
|
||||
AbbrevOffset: QWord;
|
||||
AddressSize: Byte;
|
||||
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;
|
||||
|
||||
{ TTestDummyFileSource }
|
||||
|
||||
TTestDummyFileSource = class(TDbgImageReader)
|
||||
@ -95,10 +58,42 @@ type
|
||||
FImgReader: TTestDummyFileSource;
|
||||
protected
|
||||
public
|
||||
constructor Create; virtual;
|
||||
constructor Create; override;
|
||||
property TestImgReader: TTestDummyFileSource read FImgReader;
|
||||
end;
|
||||
|
||||
{ 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 }
|
||||
|
||||
@ -122,6 +117,7 @@ type
|
||||
|
||||
{ TTestDwarfInfoEntry }
|
||||
|
||||
PTestDwarfInfoEntry = ^TTestDwarfInfoEntry;
|
||||
TTestDwarfInfoEntry = class
|
||||
private
|
||||
FAbbrevObj: TTestDwarfAbbrev;
|
||||
@ -131,6 +127,7 @@ type
|
||||
FRefList: array of record
|
||||
Index, FSize: Integer;
|
||||
AData: TTestDwarfInfoEntry;
|
||||
ADataRef: PTestDwarfInfoEntry;
|
||||
end;
|
||||
function GetChildren: Byte;
|
||||
function GetTag: Cardinal;
|
||||
@ -155,6 +152,7 @@ type
|
||||
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);
|
||||
|
||||
@ -163,8 +161,105 @@ type
|
||||
function Data: Pointer;
|
||||
end;
|
||||
|
||||
function ULEB(ANum: QWord): TBytes;
|
||||
function SLEB(ANum: Int64): TBytes;
|
||||
function AddrB(ANum: Int64): 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
|
||||
@ -197,30 +292,32 @@ procedure WriteSLEB128(ANum: Int64; var ADest: TBytes; ADestIdx: Integer);
|
||||
var
|
||||
n: Integer;
|
||||
c: Boolean;
|
||||
UNum: QWord;
|
||||
begin
|
||||
if ANum = 0 then begin
|
||||
AddByte(0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
if ANum < 0 then begin;
|
||||
n := 10*7;
|
||||
if ANum < 0 then begin
|
||||
UNum := QWord(ANum);
|
||||
n := 9*7;
|
||||
while n > 0 do begin
|
||||
if (ANum and ($7f shl n) = (Int64(-1) and ($7f shl n)) ) and
|
||||
(ANum and (int64(1) shl (n-1)) <> 0)
|
||||
if ( (UNum and (QWord($7f) shl n)) = (high(QWord) and (QWord($7f) shl n)) ) and
|
||||
( (UNum and (QWord(1) shl (n-1))) <> 0 )
|
||||
then
|
||||
ANum := ANum and not(-1 shl n)
|
||||
UNum := UNum and not(high(QWord) shl n)
|
||||
else
|
||||
break;
|
||||
dec(n, 7);
|
||||
end;
|
||||
|
||||
while ANum <> 0 do begin
|
||||
if ANum > $7f then
|
||||
AddByte((ANum and $7f) + $80)
|
||||
while UNum <> 0 do begin
|
||||
if UNum > $7f then
|
||||
AddByte((UNum and $7f) + $80)
|
||||
else
|
||||
AddByte((ANum and $7f));
|
||||
ANum := ANum shr 7;
|
||||
AddByte((UNum and $7f));
|
||||
UNum := UNum shr 7;
|
||||
end;
|
||||
|
||||
end
|
||||
@ -232,13 +329,76 @@ begin
|
||||
AddByte((ANum and $7f) + $80)
|
||||
else
|
||||
AddByte((ANum and $7f));
|
||||
c := (ANum and $40) <> 0; // write extra 0, to prlevent sign extend
|
||||
c := (ANum and $40) <> 0; // write extra 0, to prevent sign extend
|
||||
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 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 }
|
||||
|
||||
function TTestMemReader.ReadMemory(AnAddress: FpDbgInfo.TDbgPtr; ASize: Cardinal;
|
||||
ADest: Pointer): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
Move(Pointer(AnAddress)^, ADest^, ASize);
|
||||
end;
|
||||
|
||||
function TTestMemReader.ReadMemoryEx(AnAddress, AnAddressSpace: FpDbgInfo.TDbgPtr;
|
||||
ASize: Cardinal; ADest: Pointer): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TTestMemReader.ReadRegister(ARegNum: Integer; out AValue: FpDbgInfo.TDbgPtr): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
AValue := RegisterValues[ARegNum];
|
||||
end;
|
||||
|
||||
{ TTestDwarfInfoEntry }
|
||||
|
||||
procedure TTestDwarfInfoEntry.InitEncoded;
|
||||
@ -302,9 +462,14 @@ procedure TTestDwarfInfoEntry.WriteToSectionFIxRef(ASectionMem: PByte);
|
||||
var
|
||||
i: Integer;
|
||||
v: Integer;
|
||||
o: TTestDwarfInfoEntry;
|
||||
begin
|
||||
for i := 0 to Length(FRefList) - 1 do begin
|
||||
v := FRefList[i].AData.FWrittenAtIndex;
|
||||
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;
|
||||
@ -405,7 +570,7 @@ begin
|
||||
Result := length(FRefList);
|
||||
SetLength(FRefList, Result + 1);
|
||||
|
||||
l := 4;
|
||||
l := TestAddrSize;
|
||||
case AForm of
|
||||
DW_FORM_ref1: l := 1;
|
||||
DW_FORM_ref2: l := 2;
|
||||
@ -430,6 +595,43 @@ begin
|
||||
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;
|
||||
@ -467,7 +669,7 @@ end;
|
||||
constructor TTestDummySectionInfoEntries.Create;
|
||||
begin
|
||||
FVersion := 2;
|
||||
FAddrSize := 4;
|
||||
FAddrSize := TestAddrSize;
|
||||
end;
|
||||
|
||||
destructor TTestDummySectionInfoEntries.Destroy;
|
||||
|
@ -5,12 +5,10 @@ unit TestTypeInfo;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, FpPascalParser, FpDbgDwarf, FpDbgInfo, FpDbgLoader, FpPascalBuilder,
|
||||
FpDbgUtil, FpDbgDwarfConst, FileUtil, LazLoggerBase, LazUTF8, fpcunit, testutils,
|
||||
testregistry, TestHelperClasses;
|
||||
FpPascalParser, FpDbgDwarf, FpDbgInfo,
|
||||
FpDbgUtil, FpDbgDwarfConst, LazLoggerBase, LazUTF8, sysutils, fpcunit,
|
||||
testregistry, TestHelperClasses, TestDwarfSetup1;
|
||||
|
||||
const
|
||||
TESTPROG1_FUNC_BAR_LINE = 185;
|
||||
|
||||
type
|
||||
|
||||
@ -25,17 +23,6 @@ type
|
||||
constructor Create(ATextExpression: String; AContext: TDbgInfoAddressContext);
|
||||
end;
|
||||
|
||||
{ TTestMemReader }
|
||||
|
||||
TTestMemReader = class(TFpDbgMemReaderBase)
|
||||
public
|
||||
RegisterValues: array[0..30] of TDbgPtr;
|
||||
function ReadMemory(AnAddress: FpDbgInfo.TDbgPtr; ASize: Cardinal; ADest: Pointer): Boolean; override;
|
||||
function ReadMemoryEx({%H-}AnAddress, {%H-}AnAddressSpace: FpDbgInfo.TDbgPtr; {%H-}ASize: Cardinal; {%H-}ADest: Pointer): Boolean; override;
|
||||
function ReadRegister(ARegNum: Integer; out AValue: FpDbgInfo.TDbgPtr): Boolean; override;
|
||||
end;
|
||||
|
||||
|
||||
{ TTestTypInfo }
|
||||
|
||||
TTestTypInfo = class(TTestCase)
|
||||
@ -48,27 +35,6 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
{ TTestMemReader }
|
||||
|
||||
function TTestMemReader.ReadMemory(AnAddress: FpDbgInfo.TDbgPtr; ASize: Cardinal;
|
||||
ADest: Pointer): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
Move(Pointer(AnAddress)^, ADest^, ASize);
|
||||
end;
|
||||
|
||||
function TTestMemReader.ReadMemoryEx(AnAddress, AnAddressSpace: FpDbgInfo.TDbgPtr;
|
||||
ASize: Cardinal; ADest: Pointer): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TTestMemReader.ReadRegister(ARegNum: Integer; out AValue: FpDbgInfo.TDbgPtr): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
AValue := RegisterValues[ARegNum];
|
||||
end;
|
||||
|
||||
{ TTestPascalExpression }
|
||||
|
||||
function TTestPascalExpression.GetDbgSymbolForIdentifier(AnIdent: String): TDbgSymbol;
|
||||
@ -97,132 +63,222 @@ end;
|
||||
|
||||
procedure TTestTypInfo.New1;
|
||||
var
|
||||
ImageLoader: TTestDummyImageLoader;
|
||||
SectionDbgInfo: TTestDummySectionInfoEntries;
|
||||
CompUnit, Prog1, Prog2,
|
||||
GlobVar1, TypeInt, TypeIntDecl: TTestDwarfInfoEntry;
|
||||
ImageLoader: TTestLoaderSetup1;
|
||||
MemReader: TTestMemReader;
|
||||
Ctx: TDbgInfoAddressContext;
|
||||
sym: TDbgSymbol;
|
||||
MemReader: TTestMemReader;
|
||||
|
||||
TestStackFrame: record
|
||||
AVal: Integer; // -8
|
||||
AVal2: Integer; // -4
|
||||
EndPoint: Cardinal;
|
||||
end;
|
||||
obj1: TTestSetup1Class;
|
||||
vobj1: TTestSetup1Object;
|
||||
|
||||
Expression: TTestPascalExpression;
|
||||
begin
|
||||
ImageLoader := TTestDummyImageLoader.Create;
|
||||
SectionDbgInfo := ImageLoader.TestImgReader.TestSection['.debug_info'] as TTestDummySectionInfoEntries;
|
||||
ImageLoader := TTestLoaderSetup1.Create;
|
||||
|
||||
{%region}
|
||||
CompUnit := SectionDbgInfo.GetFirstInfoEntryObj;
|
||||
CompUnit.Tag := DW_TAG_compile_unit;
|
||||
CompUnit.Children := 1; //DW_CHILDREN_yes
|
||||
CompUnit.Add(DW_AT_name, DW_FORM_string, 'testprog1.pas'+#0);
|
||||
CompUnit.Add(DW_AT_producer, DW_FORM_string, 'Free Pascal 2.6.2 2013/02/16'+#0);
|
||||
CompUnit.Add(DW_AT_comp_dir, DW_FORM_string, 'B:/lazarus_latest/components/fpdebug/test/testapps/'+#0);
|
||||
CompUnit.Add(DW_AT_language, DW_FORM_data1, [$09]);
|
||||
CompUnit.Add(DW_AT_identifier_case, DW_FORM_data1, [$03]);
|
||||
CompUnit.Add(DW_AT_stmt_list, DW_FORM_data4, [$00, $00, $00, $00]);
|
||||
CompUnit.AddAddr(DW_AT_low_pc, DW_FORM_addr, $00400000);
|
||||
CompUnit.AddAddr(DW_AT_high_pc, DW_FORM_addr, $00501A50);
|
||||
|
||||
Prog1 := CompUnit.GetNewChild;
|
||||
Prog1.Tag := DW_TAG_subprogram;
|
||||
Prog1.Children := 1;
|
||||
Prog1.Add(DW_AT_name, DW_FORM_string, 'BAR'+#0);
|
||||
Prog1.Add(DW_AT_prototyped, DW_FORM_flag, [$01]);
|
||||
Prog1.Add(DW_AT_calling_convention, DW_FORM_data1, [$41]);
|
||||
Prog1.Add(DW_AT_external, DW_FORM_flag, [$01]);
|
||||
Prog1.AddAddr(DW_AT_low_pc, DW_FORM_addr, $00401000);
|
||||
Prog1.AddAddr(DW_AT_high_pc, DW_FORM_addr, $00402000);
|
||||
|
||||
Prog2 := CompUnit.GetNewChild;
|
||||
Prog2.Tag := DW_TAG_subprogram;
|
||||
Prog2.Children := 0;
|
||||
Prog2.Add(DW_AT_name, DW_FORM_string, 'BAR2'+#0);
|
||||
Prog2.Add(DW_AT_prototyped, DW_FORM_flag, [$01]);
|
||||
Prog2.Add(DW_AT_calling_convention, DW_FORM_data1, [$41]);
|
||||
Prog2.Add(DW_AT_external, DW_FORM_flag, [$01]);
|
||||
Prog2.AddAddr(DW_AT_low_pc, DW_FORM_addr, $00403000);
|
||||
Prog2.AddAddr(DW_AT_high_pc, DW_FORM_addr, $00404000);
|
||||
obj1 := TTestSetup1Class.Create;
|
||||
ImageLoader.TestStackFrame.Int1 := -299;
|
||||
ImageLoader.TestStackFrame.Rec1.FWord := 1021;
|
||||
ImageLoader.TestStackFrame.VObj1 := @vobj1;
|
||||
ImageLoader.TestStackFrame.Obj1 := obj1;
|
||||
|
||||
|
||||
TypeInt := CompUnit.GetNewChild;
|
||||
TypeInt.Tag := DW_TAG_base_type;
|
||||
TypeInt.Children := 0;
|
||||
TypeInt.Add(DW_AT_name, DW_FORM_string, 'LONGINT'+#0);
|
||||
TypeInt.Add(DW_AT_encoding, DW_FORM_data1, [$05]);
|
||||
TypeInt.Add(DW_AT_byte_size, DW_FORM_data1, [$04]);
|
||||
|
||||
TypeIntDecl := CompUnit.GetNewChild;
|
||||
TypeIntDecl.Tag := DW_TAG_typedef;
|
||||
TypeIntDecl.Children := 0;
|
||||
TypeIntDecl.Add(DW_AT_name, DW_FORM_string, 'LONGINT'+#0);
|
||||
TypeIntDecl.AddRef(DW_AT_type, DW_FORM_ref4, TypeInt); // $7A, $06, $00, $00
|
||||
|
||||
GlobVar1 := CompUnit.GetNewChild;
|
||||
GlobVar1.Tag := DW_TAG_variable;
|
||||
GlobVar1.Children := 0;
|
||||
GlobVar1.Add(DW_AT_name, DW_FORM_string, 'INT1'+#0);
|
||||
GlobVar1.Add(DW_AT_location, DW_FORM_block1, [$02, $75, $78]); // DW_OP_breg5-8
|
||||
GlobVar1.AddRef(DW_AT_type, DW_FORM_ref4, TypeIntDecl);
|
||||
|
||||
{%endregion}
|
||||
|
||||
TestStackFrame.AVal := -299;
|
||||
|
||||
|
||||
SectionDbgInfo.CreateSectionData;
|
||||
SectionDbgInfo.AbbrevSection.CreateSectionData;
|
||||
MemReader := TTestMemReader.Create;
|
||||
MemReader.RegisterValues[5] := TDbgPtr(@TestStackFrame.EndPoint);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
MemReader.RegisterValues[5] := TDbgPtr(@ImageLoader.TestStackFrame.EndPoint);
|
||||
|
||||
Ctx := nil;
|
||||
FDwarfInfo := TDbgDwarf.Create(ImageLoader);
|
||||
FDwarfInfo.LoadCompilationUnits;
|
||||
FDwarfInfo.MemReader := MemReader;
|
||||
try
|
||||
FDwarfInfo.LoadCompilationUnits;
|
||||
FDwarfInfo.MemReader := MemReader;
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
Ctx := FDwarfInfo.FindContext($00401010);
|
||||
AssertTrue('got ctx', Ctx <> nil);
|
||||
Ctx := FDwarfInfo.FindContext($00401010);
|
||||
AssertTrue('got ctx', Ctx <> nil);
|
||||
|
||||
sym := Ctx.FindSymbol('Int1');
|
||||
AssertTrue('got sym', sym <> nil);
|
||||
sym.ReleaseReference();
|
||||
sym := Ctx.FindSymbol('Int1');
|
||||
AssertTrue('got sym', sym <> nil);
|
||||
sym.ReleaseReference();
|
||||
|
||||
Expression := TTestPascalExpression.Create('Int1', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(Expression.ResultValue.AsInteger, -299 );
|
||||
Expression.Free;
|
||||
Expression := TTestPascalExpression.Create('Int1', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(-299, Expression.ResultValue.AsInteger);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('@Int1', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(Expression.ResultValue.AsInteger, PtrInt(@TestStackFrame.AVal));
|
||||
Expression.Free;
|
||||
Expression := TTestPascalExpression.Create('@Int1', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(PtrInt(@ImageLoader.TestStackFrame.Int1), Expression.ResultValue.AsInteger);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('@Int1^', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(Expression.ResultValue.AsInteger, -299 );
|
||||
Expression.Free;
|
||||
Expression := TTestPascalExpression.Create('@Int1^', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(-299, Expression.ResultValue.AsInteger);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('(@Int1)^', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(Expression.ResultValue.AsInteger, -299 );
|
||||
Expression.Free;
|
||||
Expression := TTestPascalExpression.Create('(@Int1)^', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(-299, Expression.ResultValue.AsInteger);
|
||||
Expression.Free;
|
||||
|
||||
// Class/Object
|
||||
Expression := TTestPascalExpression.Create('Obj1', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
Expression.ResultValue; // just access it
|
||||
Expression.Free;
|
||||
|
||||
Obj1.FWord := 1019;
|
||||
Expression := TTestPascalExpression.Create('Obj1.FWord', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(1019, Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('TTestSetup1Class(Obj1).FWord', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(1019, Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('Obj1.FTest', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('TTestSetup1Class(Obj1).FTest', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
Expression.Free;
|
||||
|
||||
obj1.FTest := obj1;
|
||||
Expression := TTestPascalExpression.Create('Obj1.FTest.FWord', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(1019, Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('TTestSetup1Class(Obj1).FTest.FWord', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(1019, Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('TTestSetup1Class(TTestSetup1Class(Obj1).FTest).FWord', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(1019, Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
|
||||
Expression := TTestPascalExpression.Create('Obj1.NotExisting', Ctx);
|
||||
if Expression.Valid then;
|
||||
Expression.ResultValue; // just access it
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('TObject(Obj1).FWord', Ctx);
|
||||
if Expression.Valid then;
|
||||
Expression.ResultValue; // just access it
|
||||
Expression.Free;
|
||||
|
||||
// @
|
||||
Expression := TTestPascalExpression.Create('@Obj1', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
//TODO
|
||||
//AssertEquals(PtrUint(@obj1), Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('@Obj1.FWord', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(PtrUint(@obj1.FWord), Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('@Obj1.FTest', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
//TODO
|
||||
//AssertEquals(PtrUint(@obj1), Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('@Obj1.FWord^', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(1019, Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('(@Obj1^).FWord', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(1019, Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('@(Obj1.FWord)^', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(1019, Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
// Record
|
||||
Expression := TTestPascalExpression.Create('Rec1', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
Expression.ResultValue; // just access it
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('Rec1.FWord', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(1021, Expression.ResultValue.AsInteger);
|
||||
Expression.Free;
|
||||
|
||||
// var param // old style object
|
||||
vobj1.FWord := 1122;
|
||||
vobj1.FInt := -122;
|
||||
Expression := TTestPascalExpression.Create('vobj1', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
Expression.ResultValue; // just access it
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('vobj1.FWord', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(1122, Expression.ResultValue.AsCardinal);
|
||||
Expression.Free;
|
||||
|
||||
Expression := TTestPascalExpression.Create('vobj1.FInt', Ctx);
|
||||
AssertTrue(Expression.Valid);
|
||||
AssertTrue(Expression.ResultValue <> nil);
|
||||
AssertEquals(-122, Expression.ResultValue.AsInteger);
|
||||
Expression.Free;
|
||||
|
||||
|
||||
|
||||
// Not existing
|
||||
Expression := TTestPascalExpression.Create('NotExisting1399', Ctx);
|
||||
//AssertTrue(Expression.Valid);
|
||||
if Expression.Valid then;
|
||||
Expression.ResultValue; // just access it
|
||||
Expression.Free;
|
||||
|
||||
// Not Existing Typecast
|
||||
Expression := TTestPascalExpression.Create('TNotExisting1399(Int1)', Ctx);
|
||||
//AssertTrue(Expression.Valid);
|
||||
if Expression.Valid then;
|
||||
Expression.ResultValue; // just access it
|
||||
Expression.Free;
|
||||
|
||||
|
||||
Ctx.ReleaseReference;
|
||||
|
||||
///////////////////////////
|
||||
FDwarfInfo.Free;
|
||||
ImageLoader.Free;
|
||||
MemReader.Free;
|
||||
finally
|
||||
Ctx.ReleaseReference;
|
||||
FDwarfInfo.Free;
|
||||
ImageLoader.Free;
|
||||
MemReader.Free;
|
||||
obj1.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user