FPDebug: tests

git-svn-id: trunk@43959 -
This commit is contained in:
martin 2014-02-08 18:18:09 +00:00
parent 7b11f22871
commit 82bb935fdd
4 changed files with 3324 additions and 2411 deletions

View File

@ -1,3 +1,248 @@
This tool can be used to generate the dwarf setup data for the testcase.
Warning: Very slow
The output can be processed in the IDE with the below pas script macro.
NOTE: avoid variables of the same name in different scopes.
const
AddressLen = 8; // chars in hex = 4 bytes
VarNamePrefix = 'GLOBTESTSETUP1';
VarNamePrefixRepl = 'GlobTestSetup1.Var';
VarParamPrefix = '';
VarParamPrefixRepl = 'TestStackFrame.';
VarParamOffset = 'TestStackFrame.EndPoint';
const HexDigits= '0123456789ABCDEF';
function IntToHex(Value: int64; Digits: integer): string;
var i: integer;
begin
If Digits=0 then
Digits:=1;
SetLength(result, digits);
for i := 0 to digits - 1 do
begin
result[digits - i] := HexDigits[(value and 15+1)];
value := value shr 4;
end ;
while value <> 0 do begin
result := HexDigits[(value and 15+1)] + result;
value := value shr 4;
end;
end ;
function GetCurrentLineId: String;
var p : TPoint;
begin
p := Caller.CaretXY;
ecLineStart;
caller.SelectWord;
Result := caller.SelText;
Caller.CaretXY := p;
end;
function GetCurrentLineIndent: String;
var p : TPoint;
begin
Result := '';
if copy(caller.LineAtCaret, 1,1) <> ' ' then exit;
p := Caller.CaretXY;
Caller.CaretX := 1;
ecSelWordRight;
Result := caller.SelText;
Caller.CaretXY := p;
end;
function FindTAG(ATag: String; var StartPoint: TPoint; out ID: String): Boolean;
begin
Result := Caller.SearchReplaceEx('.Tag := '+ATag+';', '', [], StartPoint) > 0;
if not Result Then exit;
StartPoint := Caller.CaretXY;
StartPoint.y := StartPoint.y + 1;
ID := GetCurrentLineId;
end;
function FindTAGEx(ATag, AnIndent: String; var StartPoint: TPoint; out ID: String): Boolean;
begin
repeat
Result := Caller.SearchReplaceEx('.Tag := '+ATag+';', '', [], StartPoint) > 0;
if not Result Then exit;
if (Copy(caller.LineAtCaret, 1, length(AnIndent)) = AnIndent) and
(Copy(caller.LineAtCaret, length(AnIndent),1) <> ' ')
then exit;
until not result;
end;
function FindAttr(AnAttr, AnID: String; FindInLine: String): Boolean;
var i: Integer;
begin
Result := Caller.SearchReplaceEx('^ *'+AnId+'\..*\('+AnAttr+' *,', '', [ssoRegExpr], Point(1,1)) > 0;
if (not Result) or (FindInLine='') then exit;
i := pos(FindInLine, caller.LineAtCaret);
Result := i > 0;
if not result then exit;
Caller.LogicalCaretXY := Point(i, Caller.CaretY);
end;
function FindName(AnID: String): String;
begin
Result := AnId;
if not FindAttr('DW_AT_name', ANId, '+#0') then exit;
while (Caller.LogicalCaretX > 1) and (caller.LineAtCaret[caller.LogicalCaretX] <> '''') do ecLeft;
while (Caller.LogicalCaretX > 1) and (caller.LineAtCaret[caller.LogicalCaretX-1] <> '''') do ecSelLeft;
Result := caller.SelText;
end;
function PrefIxIdParagraph(AnId, ANewLine: String): Boolean;
begin
Result := Caller.SearchReplaceEx(AnId+' :=', '', [ssoWholeWord], Point(1,1)) > 0;
if not Result Then exit;
Caller.CaretX := 1; ecSelWordRight;
if copy(caller.LineAtCaret, 1,1) = ' ' then
ANewLine := caller.SelText+ ANewLine;
Caller.CaretX := 1;
caller.SelText := ANewLine + #13+#10;
end;
function ReplaceHexAddrInLine(NewText: String): Boolean;
var p,p2: TPoint;
begin
p := Caller.CaretXY;
p2 := p; p2.x := 1;
Result := Caller.SearchReplaceEx('\$[0-9a-f]+', '', [ssoRegExpr], p2) > 0;
Result := Result and (Caller.CaretY = p.y);
if Result then
caller.SelText := NewText;
Caller.CaretXY := p;
end;
function ReplaceSLEBInLine(NewText: String): Boolean;
var p,p2: TPoint;
begin
p := Caller.CaretXY;
p2 := p; p2.x := 1;
Result := Caller.SearchReplaceEx('SLEB\(-?[0-9]+\)', '', [ssoRegExpr], p2) > 0;
Result := Result and (Caller.CaretY = p.y);
if Result then
caller.SelText := 'SLEB('+NewText+')';
Caller.CaretXY := p;
end;
function ReplacePreFix(AText, APrefix, ANew: String): String;
begin
Result := AText;
if copy(Result,1,length(APrefix))=APrefix
then Result := ANew+copy(Result,1+length(APrefix),length(Result));
end;
var
MainComment: String;
UnitAddr, UnitIncr: Int64;
UnitFoundPos : TPoint;
UnitId, UnitName: string;
ProcAddr, ProcIncr: Int64;
ProcFoundPos : TPoint;
ProcEndLine: Integer;
ProcId, ProcName: string;
VarFoundPos : TPoint;
VarId, VarName, VarNewName: string;
p : TPoint;
s:String;
begin
UnitAddr := $400000;
UnitIncr := $100000;
ProcAddr := $400000;
ProcIncr := $001000;
UnitFoundPos:=Point(1,1);
if FindTag('DW_TAG_compile_unit', UnitFoundPos, UnitId) then begin
UnitName:=FindName(UnitId);
if FindAttr('DW_AT_low_pc', UnitId, '') then begin
if ReplaceHexAddrInLine('$'+inttohex(UnitAddr, AddressLen))
then MainComment := MainComment + '// '+UnitName+' DW_AT_low_pc at $'+ inttohex(UnitAddr, AddressLen)+ #13+#10
else MainComment := MainComment + '// '+UnitName+' DW_AT_low_pc at Addr NOT found'+ #13+#10;
UnitAddr := UnitAddr + UnitIncr;
end;
if FindAttr('DW_AT_high_pc', UnitId, '') then begin
ReplaceHexAddrInLine('$'+inttohex(UnitAddr-1, AddressLen));
end;
ProcFoundPos:=Point(1,1);
while FindTag('DW_TAG_subprogram', ProcFoundPos, ProcId) do begin
ProcName := FindName(ProcID);
if FindAttr('DW_AT_low_pc', ProcId, '') then begin
if ReplaceHexAddrInLine('$'+inttohex(ProcAddr, AddressLen))
then MainComment := MainComment + '// '+ProcName+' DW_AT_low_pc at $'+ inttohex(ProcAddr, AddressLen)+ #13+#10
else MainComment := MainComment + '// '+ProcName+' DW_AT_low_pc at Addr NOT found'+ #13+#10;
ProcAddr := ProcAddr + ProcIncr;
end;
if FindAttr('DW_AT_high_pc', ProcId, '') then begin
ReplaceHexAddrInLine('$'+inttohex(ProcAddr-1, AddressLen));
end;
end;
VarFoundPos:=Point(1,1);
while FindTag('DW_TAG_variable', VarFoundPos, VarId) do begin
VarName := FindName(VarID);
if not( (VarName='this') or (VarName='result') or (VarName='self') or (VarName='vmt') ) then begin
if FindAttr('DW_AT_location', VarId, 'SLEB') then begin
// local var
VarNewName := ReplacePreFix(VarName, VarParamPrefix, VarParamPrefixRepl);
s := 'StackOffs := @'+VarNewName+' - @'+VarParamOffset+';'
if ReplaceSLEBInLine('StackOffs')
then MainComment := MainComment + '// param '+UnitName+'.'+VarName+' = ' + VarNewName+ #13+#10
else MainComment := MainComment + '// param '+UnitName+'.'+VarName+' Addr NOT FOUND'+ #13+#10;
PrefIxIdParagraph(VarID, s);
end
else
if FindAttr('DW_AT_location', VarId, '$') then begin
// Global var
VarNewName := ReplacePreFix(VarName, VarNamePrefix, VarNamePrefixRepl);
if ReplaceHexAddrInLine('@'+VarNewName)
then MainComment := MainComment + '// var '+UnitName+'.'+VarName+' = ' + VarNewName+ #13+#10
else MainComment := MainComment + '// var '+UnitName+'.'+VarName+' Addr NOT FOUND'+ #13+#10;
end
else
MainComment := MainComment + '// var '+UnitName+'.'+VarName+' DW_AT_location NOT FOUND'+ #13+#10;
end;
end;
VarFoundPos:=Point(1,1);
while FindTag('DW_TAG_formal_parameter', VarFoundPos, VarId) do begin
VarName := FindName(VarID);
if not( (VarName='this') or (VarName='result') or (VarName='self') or (VarName='vmt') ) then begin
if FindAttr('DW_AT_location', VarId, '') then begin
VarNewName := ReplacePreFix(VarName, VarParamPrefix, VarParamPrefixRepl);
s := 'StackOffs := @'+VarNewName+' - @'+VarParamOffset+';'
if ReplaceSLEBInLine('StackOffs')
then MainComment := MainComment + '// param '+UnitName+'.'+VarName+' = ' + VarNewName+ #13+#10
else MainComment := MainComment + '// param '+UnitName+'.'+VarName+' Addr NOT FOUND'+ #13+#10;
PrefIxIdParagraph(VarID, s);
end
else
MainComment := MainComment + '// param '+UnitName+'.'+VarName+' DW_AT_location NOT FOUND'+ #13+#10;
end;
end;
end;
Caller.LogicalCaretXY := Point(1,1);
caller.SelText:=MainComment;
end.

View File

@ -1,5 +1,11 @@
program ProgFoo;
{$mode objfpc}{$H+}
{$IF FPC_FULLVERSION>=20701}
{$OPTIMIZATION NOREMOVEEMPTYPROCS}
{$OPTIMIZATION NOORDERFIELDS}
{$ENDIF}
{$OPTIMIZATION OFF}
{$A2}
type
@ -14,17 +20,30 @@ type
end;
PTestSetup1Record = ^TTestSetup1Record;
TTestSetup1Record2 = record // same size
FWord: Word;
FBool: Boolean;
FTest: TTestSetup1Class;
end;
PTestSetup1Record2 = ^TTestSetup1Record2;
TTestSetup1Record3 = record // other size
FWord: Word;
end;
PTestSetup1Record3 = ^TTestSetup1Record3;
{ TTestSetup1Class }
TTestSetup1Class = class
public
FBool: Boolean;
FWord: Word;
FWordL: QWord;
FInt: ShortInt;
FIntL: Int64;
FBool: Boolean;
FTest: TTestSetup1Class;
procedure f0(a:integer); virtual;
FByte: Byte;
procedure ClassProc0(a:integer); virtual;
end;
PTestSetup1Class = ^TTestSetup1Class;
@ -34,6 +53,13 @@ type
end;
PTestSetup1ClassChild = ^TTestSetup1ClassChild;
TTestSetup1Class2 = class
public
FInt: Integer;
FWord: Word;
end;
PTestSetup1Class2 = ^TTestSetup1Class2;
TTestSetup1ClassClass = class of TTestSetup1Class;
TTestSetup1ClassChildClass = class of TTestSetup1ClassChild;
@ -49,10 +75,42 @@ type
FBool2: LongBool;
FBool3: ByteBool;
FTest: TTestSetup1Class;
procedure f0(a:integer); virtual;
procedure ObjProc0(o1:integer); virtual;
//only with a wirtual method, will there be a vptr entry
end;
PTestSetup1Object = ^TTestSetup1Object;
{ TTestSetup1Object2 }
TTestSetup1Object2 = object // same size
public
FWord: Word;
FWordL: QWord;
FInt: ShortInt;
FIntL: Int64;
FBool: Boolean;
FBool2: LongBool;
FBool3: ByteBool;
FTest: TTestSetup1Class;
procedure ObjProc1(o2:integer); virtual;
end;
PTestSetup1Object2 = ^TTestSetup1Object2;
{ TTestSetup1Object3 }
TTestSetup1Object3 = object // diff size
public
FWord: Word;
procedure ObjProc1(o2:integer); virtual;
end;
PTestSetup1Object3 = ^TTestSetup1Object3;
TTestSetup1Object4 = object // looks like a record....
public
FWord: Word;
end;
PTestSetup1Object4 = ^TTestSetup1Object4;
Pint = ^ integer;
PPInt = ^Pint;
PPPInt = ^PPint;
@ -61,23 +119,35 @@ type
var // Globals
GlobTestSetup1Record: TTestSetup1Record;
GlobTestSetup1RecordP: PTestSetup1Record;
GlobTestSetup1Record2: TTestSetup1Record2;
GlobTestSetup1Record2P: PTestSetup1Record2;
GlobTestSetup1Record3: TTestSetup1Record3;
GlobTestSetup1Record3P: PTestSetup1Record3;
GlobTestSetup1Class: TTestSetup1Class;
GlobTestSetup1ClassP: PTestSetup1Class;
GlobTestSetup1ClassChild: TTestSetup1ClassChild;
GlobTestSetup1ClassChildP: PTestSetup1ClassChild;
GlobTestSetup1Class2: TTestSetup1Class2;
GlobTestSetup1Class2P: PTestSetup1Class2;
GlobTestSetup1ClassClass: TTestSetup1ClassClass;
GlobTestSetup1ClassChildClass: TTestSetup1ClassChildClass;
GlobTestSetup1Object: TTestSetup1Object;
GlobTestSetup1ObjectP: PTestSetup1Object;
GlobTestSetup1Object2: TTestSetup1Object2;
GlobTestSetup1Object2P: PTestSetup1Object2;
GlobTestSetup1Object3: TTestSetup1Object3;
GlobTestSetup1Object3P: PTestSetup1Object3;
GlobTestSetup1Object4: TTestSetup1Object4;
GlobTestSetup1Object4P: PTestSetup1Object4;
GlobTestSetup1Pointer: Pointer;
GlobTestSetup1QWord: QWord;
function TestSetup1Bar(
ParamTestSetup1Record: TTestSetup1Record;
ParamTestRecord: PTestSetup1Record;
ParamTestSetup1RecordP: PTestSetup1Record;
ParamTestSetup1Class: TTestSetup1Class;
ParamTestSetup1ClassP: PTestSetup1Class;
@ -140,17 +210,31 @@ begin
subr3 := #9;
end;
{ TTestSetup1Object3 }
procedure TTestSetup1Class.f0(a: integer);
procedure TTestSetup1Object3.ObjProc1(o2: integer);
begin
FWord := 0;//
end;
{ TTestSetup1Object2 }
procedure TTestSetup1Object2.ObjProc1(o2: integer);
begin
FWord := 0;
end;
procedure TTestSetup1Class.ClassProc0(a: integer);
begin
FWord := 0;
end;
{ TTestSetup1Object }
procedure TTestSetup1Object.f0(a: integer);
procedure TTestSetup1Object.ObjProc0(o1: integer);
begin
FWord := 0;
end;
begin

File diff suppressed because one or more lines are too long

View File

@ -17,6 +17,9 @@ type
TTestTypInfo = class(TTestCase)
protected
FDwarfInfo: TDbgDwarf;
public
//procedure SetUp; override;
//procedure TearDown; override;
published
Procedure TestExpressions;
procedure TestCompareUtf8BothCase;
@ -253,7 +256,7 @@ begin
FDwarfInfo.MemReader := MemReader;
//////////////////////////////////////////////////////////
Ctx := FDwarfInfo.FindContext($00401010);
Ctx := FDwarfInfo.FindContext(TTestSetup1ProcBarAddr);
AssertTrue('got ctx', Ctx <> nil);
sym := Ctx.FindSymbol('Int1');
@ -402,6 +405,7 @@ begin
ImageLoader.TestStackFrame.VParamTestSetup1Class := @ImageLoader.TestStackFrame.Obj1;
ImageLoader.TestStackFrame.VParamTestSetup1ClassP := @ImageLoader.TestStackFrame.PObj1;
Obj1.FWord := 1019;
Obj1.FBool := Boolean($9aa99aa9); // Make sure there is data, if other fields read to much
Obj1.FWordL := QWord($9aa99aa97bb7b77b); // Make sure there is data, if other fields read to much
for i := 0 to 23 do begin