mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-01 20:03:39 +02:00
813 lines
26 KiB
ObjectPascal
813 lines
26 KiB
ObjectPascal
unit Unit1;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
FpImgReaderWinPE, Classes, SysUtils, math, FileUtil, LazLogger, LazLoggerProfiling,
|
|
lazutf8sysutils, FpDbgLoader, FpDbgDwarf, FpDbgDwarfConst, FpPascalParser, FpDbgInfo,
|
|
FpDbgDwarfDataClasses, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls, EditBtn,
|
|
Menus, Clipbrd, maps, types, strutils;
|
|
|
|
type
|
|
|
|
{ TForm1 }
|
|
|
|
TForm1 = class(TForm)
|
|
btnCopyAll: TButton;
|
|
btnLoad: TButton;
|
|
btnShowUnit: TButton;
|
|
btnCopyOne: TButton;
|
|
btnLines: TButton;
|
|
FileNameEdit1: TFileNameEdit;
|
|
CompUnitListBox: TListBox;
|
|
StatusBar1: TStatusBar;
|
|
TreeView1: TTreeView;
|
|
procedure btnCopyAllClick(Sender: TObject);
|
|
procedure btnCopyOneClick(Sender: TObject);
|
|
procedure btnLoadClick(Sender: TObject);
|
|
procedure btnShowUnitClick(Sender: TObject);
|
|
procedure btnLinesClick(Sender: TObject);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormDestroy(Sender: TObject);
|
|
private
|
|
{ private declarations }
|
|
NameList: TStringList;
|
|
FFileName: String;
|
|
FTestCaseTexts: TStringList;
|
|
FImageLoaderList: TDbgImageLoaderList;
|
|
FDwarfInfo: TFpDwarfInfo;
|
|
FCUCount : Integer;
|
|
FShowingUnit: Boolean;
|
|
public
|
|
{ public declarations }
|
|
procedure LoadDwarf;
|
|
procedure UnLoadDwarf;
|
|
end;
|
|
|
|
var
|
|
Form1: TForm1;
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
type
|
|
TDwarfCompilationUnitHack = class(TDwarfCompilationUnit)
|
|
public
|
|
property FirstScope;
|
|
property AbbrevList;
|
|
end;
|
|
|
|
{ TForm1 }
|
|
|
|
procedure TForm1.btnLoadClick(Sender: TObject);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if FileNameEdit1.FileName = '' then
|
|
FileNameEdit1.RunDialog;
|
|
FFileName := FileNameEdit1.FileName;
|
|
LoadDwarf;
|
|
|
|
if FDwarfInfo = nil then
|
|
exit;
|
|
|
|
CompUnitListBox.Clear;
|
|
for i := 0 to FCUCount - 1 do begin
|
|
CompUnitListBox.AddItem(FDwarfInfo.CompilationUnits[i].FileName,
|
|
FDwarfInfo.CompilationUnits[i] );
|
|
end;
|
|
end;
|
|
|
|
procedure TForm1.btnCopyOneClick(Sender: TObject);
|
|
var
|
|
n: TTreeNode;
|
|
i: PtrInt;
|
|
begin
|
|
n := TreeView1.Selected;
|
|
if n = nil then exit;
|
|
i := ptrint(n.Data)-1;
|
|
if i < 0 then exit;
|
|
debugln(['TForm1.MenuItem1Click ']);
|
|
Clipboard.AsText := FTestCaseTexts[i];
|
|
end;
|
|
|
|
procedure TForm1.btnLinesClick(Sender: TObject);
|
|
const
|
|
B: Array [Boolean] of string = ('F', 'T');
|
|
var
|
|
i: Integer;
|
|
Node, ParentNode: TTreeNode;
|
|
CU: TDwarfCompilationUnitHack;
|
|
SM: TDwarfLineInfoStateMachine;
|
|
begin
|
|
TreeView1.BeginUpdate;
|
|
try
|
|
TreeView1.Items.Clear;
|
|
i := CompUnitListBox.ItemIndex;
|
|
if i < 0 then exit;
|
|
CU := TDwarfCompilationUnitHack(CompUnitListBox.Items.Objects[i]);
|
|
if CU = nil then exit;
|
|
|
|
SM := CU.FLineInfo.StateMachine;
|
|
SM.Reset;
|
|
ParentNode := nil;
|
|
|
|
while SM.NextLine do
|
|
begin
|
|
|
|
Node := TreeView1.Items.AddChild(ParentNode,
|
|
Format('Line: %2d, Col: %2d, Addr: %s, IsStmt: %s, Basic: %s, EndSeq: %s, Prol: %s, Epil: %s, ISA: %u, File: %s // Ended: %s',
|
|
[SM.Line, SM.Column, IntToHex(SM.Address,16), b[SM.IsStmt], b[SM.BasicBlock],
|
|
b[SM.EndSequence], b[SM.PrologueEnd], b[SM.EpilogueBegin], SM.Isa, sm.FileName, b[SM.Ended] ]));
|
|
|
|
if ParentNode = nil then ParentNode := Node;
|
|
if SM.EndSequence then begin
|
|
ParentNode := nil;
|
|
if not SM.NextLine then break;
|
|
end;
|
|
end;
|
|
|
|
finally
|
|
TreeView1.EndUpdate;
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure TForm1.btnCopyAllClick(Sender: TObject);
|
|
var
|
|
nm: TStringList;
|
|
vars: String;
|
|
procedure AddChildren(n: TTreeNode; var s: string; idnt: String);
|
|
var
|
|
i: PtrInt;
|
|
s2: String;
|
|
begin
|
|
n := n.GetFirstChild;
|
|
while n <> nil do begin
|
|
i := ptrint(n.Data)-1;
|
|
s2 := 'XXXXXXXXXXX.';
|
|
if i >= 0 then
|
|
s2 := FTestCaseTexts[i];
|
|
nm.Add(copy(s2, 1, max(0, pos('.', s2)-1)));
|
|
if i >= 0 then begin
|
|
vars := vars + nm[nm.Count-1] +', ';
|
|
if s2 <> '' then begin
|
|
s2 := nm[nm.Count-1] + ' := ' + nm[nm.Count-2] + '.GetNewChild;' +LineEnding
|
|
+ s2;
|
|
|
|
s2 := AnsiReplaceStr(s2, LineEnding, LineEnding+idnt);
|
|
s := s + idnt + s2 + LineEnding;;
|
|
end;
|
|
end;
|
|
AddChildren(n, s, idnt+' ');
|
|
nm.Delete(nm.Count-1);
|
|
n := n.GetNextSibling;
|
|
end;
|
|
end;
|
|
var
|
|
s: String;
|
|
n: TTreeNode;
|
|
i: PtrInt;
|
|
i2: Integer;
|
|
begin
|
|
nm := TStringList.Create;
|
|
n := TreeView1.Selected;
|
|
if n = nil then exit;
|
|
i := ptrint(n.Data)-1;
|
|
if i < 0 then exit;
|
|
debugln(['TForm1.MenuItem1Click ']);
|
|
s := FTestCaseTexts[i] + LineEnding;
|
|
nm.Add(copy(s, 1, pos('.',s)-1));
|
|
vars := vars + nm[nm.Count-1] +', ';
|
|
|
|
AddChildren(n, s, ' ');
|
|
|
|
s := 'var '+vars + LineEnding + LineEnding + LineEnding + s;
|
|
for i2 := 0 to NameList.count - 1 do
|
|
s := AnsiReplaceStr(s, NameList.Names[i2], NameList.ValueFromIndex[i2]);
|
|
|
|
Clipboard.AsText := s;
|
|
nm.Free;
|
|
end;
|
|
|
|
procedure TForm1.LoadDwarf;
|
|
var
|
|
ImageLoader: TDbgImageLoader;
|
|
begin
|
|
UnLoadDwarf;
|
|
ImageLoader := TDbgImageLoader.Create(FFileName);
|
|
FImageLoaderList := TDbgImageLoaderList.Create(True);
|
|
FImageLoaderList.Add(ImageLoader);
|
|
FDwarfInfo := TFpDwarfInfo.Create(FImageLoaderList);
|
|
FCUCount := FDwarfInfo.LoadCompilationUnits;
|
|
end;
|
|
|
|
|
|
procedure TForm1.btnShowUnitClick(Sender: TObject);
|
|
var
|
|
CU: TDwarfCompilationUnitHack;
|
|
BaseScopeAddr: Pointer;
|
|
|
|
function ToHex(var p: pbyte; l : integer):String; inline;
|
|
begin
|
|
Result := '';
|
|
while l > 0 do begin
|
|
Result := IntToHex(p^,2) + Result;
|
|
inc(p);
|
|
dec(l);
|
|
end;
|
|
end;
|
|
|
|
function ToHexCommaList(p: pbyte; l : integer):String;
|
|
begin
|
|
Result := '';
|
|
while l > 0 do begin
|
|
if Result <> ''
|
|
then Result := Result + ', ' + '$'+IntToHex(p^,2)
|
|
else Result := Result + '$'+IntToHex(p^,2);
|
|
inc(p);
|
|
dec(l);
|
|
end;
|
|
end;
|
|
|
|
function DecodeLocation(AData: PByte; ASize: QWord): String;
|
|
function MakeAddressString(AData: Pointer): string;
|
|
begin
|
|
Result := '$'+IntToHex(PLongWord(AData)^, 8)
|
|
//Result := '$'+IntToHex(PQWord(AData)^, 16);
|
|
end;
|
|
var
|
|
MaxData: PByte;
|
|
v: Int64;
|
|
begin
|
|
MaxData := AData + ASize - 1;
|
|
while AData <= MaxData do
|
|
begin
|
|
if Result <> '' then Result := Result + ', ';
|
|
case AData^ of
|
|
DW_OP_addr: begin
|
|
Result := Result + 'DW_OP_addr, AddrB(' + MakeAddressString(@AData[1]) + ')';
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_OP_deref: begin
|
|
Result := Result + 'DW_OP_deref';
|
|
end;
|
|
DW_OP_const1u: begin
|
|
Result := Result + 'DW_OP_const1u, ' + IntToStr(AData[1]);
|
|
Inc(AData, 1);
|
|
end;
|
|
DW_OP_const1s: begin
|
|
Result := Result + 'DW_OP_const1s, ' + IntToStr(PShortInt(@AData[1])^);
|
|
Inc(AData, 1);
|
|
end;
|
|
DW_OP_const2u: begin
|
|
Result := Result + 'DW_OP_const2u, NumU(' + IntToStr(PWord(@AData[1])^) + ',2)';
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_OP_const2s: begin
|
|
Result := Result + 'DW_OP_const2s, NumS(' + IntToStr(PSmallInt(@AData[1])^) + ',2)';
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_OP_const4u: begin
|
|
Result := Result + 'DW_OP_const4u, NumU(' + IntToStr(PLongWord(@AData[1])^) + ',4)';
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_OP_const4s: begin
|
|
Result := Result + 'DW_OP_const4s, NumS(' + IntToStr(PLongInt(@AData[1])^) + ',4)';
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_OP_const8u: begin
|
|
Result := Result + 'DW_OP_const8u, NumU' + IntToStr(PQWord(@AData[1])^) + ',8)';
|
|
Inc(AData, 8);
|
|
end;
|
|
DW_OP_const8s: begin
|
|
Result := Result + 'DW_OP_const8s, NumS' + IntToStr(PInt64(@AData[1])^) + ',8)';
|
|
Inc(AData, 8);
|
|
end;
|
|
DW_OP_constu: begin
|
|
Inc(AData);
|
|
Result := Result + 'DW_OP_constu, ULEB' + IntToStr(ULEB128toOrdinal(AData)) + ')';
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_consts: begin
|
|
Inc(AData);
|
|
Result := Result + 'DW_OP_consts, SLEB(' + IntToStr(SLEB128toOrdinal(AData)) + ')';
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_dup: begin
|
|
Result := Result + 'DW_OP_dup';
|
|
end;
|
|
DW_OP_drop: begin
|
|
Result := Result + 'DW_OP_drop';
|
|
end;
|
|
DW_OP_over: begin
|
|
Result := Result + 'DW_OP_over';
|
|
end;
|
|
DW_OP_pick: begin
|
|
Result := Result + 'DW_OP_pick, ' + IntToStr(AData[1]);
|
|
Inc(AData, 1);
|
|
end;
|
|
DW_OP_swap: begin
|
|
Result := Result + 'DW_OP_swap';
|
|
end;
|
|
DW_OP_rot: begin
|
|
Result := Result + 'DW_OP_rot';
|
|
end;
|
|
DW_OP_xderef: begin
|
|
Result := Result + 'DW_OP_xderef';
|
|
end;
|
|
DW_OP_abs: begin
|
|
Result := Result + 'DW_OP_abs';
|
|
end;
|
|
DW_OP_and: begin
|
|
Result := Result + 'DW_OP_and';
|
|
end;
|
|
DW_OP_div: begin
|
|
Result := Result + 'DW_OP_div';
|
|
end;
|
|
DW_OP_minus: begin
|
|
Result := Result + 'DW_OP_minus';
|
|
end;
|
|
DW_OP_mod: begin
|
|
Result := Result + 'DW_OP_mod';
|
|
end;
|
|
DW_OP_mul: begin
|
|
Result := Result + 'DW_OP_mul';
|
|
end;
|
|
DW_OP_neg: begin
|
|
Result := Result + 'DW_OP_neg';
|
|
end;
|
|
DW_OP_not: begin
|
|
Result := Result + 'DW_OP_not';
|
|
end;
|
|
DW_OP_or: begin
|
|
Result := Result + 'DW_OP_or';
|
|
end;
|
|
DW_OP_plus: begin
|
|
Result := Result + 'DW_OP_plus';
|
|
end;
|
|
DW_OP_plus_uconst: begin
|
|
Inc(AData);
|
|
Result := Result + 'DW_OP_plus_uconst, ULEB(' + IntToStr(ULEB128toOrdinal(AData))+')';
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_shl: begin
|
|
Result := Result + 'DW_OP_shl';
|
|
end;
|
|
DW_OP_shr: begin
|
|
Result := Result + 'DW_OP_shr';
|
|
end;
|
|
DW_OP_shra: begin
|
|
Result := Result + 'DW_OP_shra';
|
|
end;
|
|
DW_OP_xor: begin
|
|
Result := Result + 'DW_OP_xor';
|
|
end;
|
|
DW_OP_skip: begin
|
|
Result := Result + 'DW_OP_skip, NumS(' + IntToStr(PSmallInt(@AData[1])^) + ',2)';
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_OP_bra: begin
|
|
Result := Result + 'DW_OP_bra, NumS(' + IntToStr(PSmallInt(@AData[1])^) + ',2)';
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_OP_eq: begin
|
|
Result := Result + 'DW_OP_eq';
|
|
end;
|
|
DW_OP_ge: begin
|
|
Result := Result + 'DW_OP_ge';
|
|
end;
|
|
DW_OP_gt: begin
|
|
Result := Result + 'DW_OP_gt';
|
|
end;
|
|
DW_OP_le: begin
|
|
Result := Result + 'DW_OP_le';
|
|
end;
|
|
DW_OP_lt: begin
|
|
Result := Result + 'DW_OP_lt';
|
|
end;
|
|
DW_OP_ne: begin
|
|
Result := Result + 'DW_OP_ne';
|
|
end;
|
|
DW_OP_lit0..DW_OP_lit31: begin
|
|
Result := Result + 'DW_OP_lit' + IntToStr(AData^ - DW_OP_lit0);
|
|
end;
|
|
DW_OP_reg0..DW_OP_reg31: begin
|
|
Result := Result + 'DW_OP_reg' + IntToStr(AData^ - DW_OP_reg0);
|
|
end;
|
|
DW_OP_breg0..DW_OP_breg31: begin
|
|
Result := Result + 'DW_OP_breg' + IntToStr(AData^ - DW_OP_breg0);
|
|
Inc(AData);
|
|
v := SLEB128toOrdinal(AData);
|
|
Dec(AData);
|
|
Result := Result + ', SLEB(';
|
|
Result := Result + IntToStr(v) + ')';
|
|
end;
|
|
DW_OP_regx: begin
|
|
Inc(AData);
|
|
Result := Result + 'DW_OP_regx, ULEB(' + IntToStr(ULEB128toOrdinal(AData)) + ')';
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_fbreg: begin
|
|
Inc(AData);
|
|
Result := Result + 'DW_OP_fbreg, SLEB(' + IntToStr(SLEB128toOrdinal(AData)) + ')';
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_bregx: begin
|
|
Inc(AData);
|
|
Result := Result + 'DW_OP_bregx, ULEB(' + IntToStr(ULEB128toOrdinal(AData)) + ')';
|
|
v := SLEB128toOrdinal(AData);
|
|
Dec(AData);
|
|
Result := Result + ', SLEB(';
|
|
Result := Result + IntToStr(v) + ')';
|
|
end;
|
|
DW_OP_piece: begin
|
|
Inc(AData);
|
|
Result := Result + 'DW_OP_piece, ULEB(' + IntToStr(ULEB128toOrdinal(AData)) + ')';
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_deref_size: begin
|
|
Result := Result + 'DW_OP_deref_size, ' + IntToStr(AData[1]);
|
|
Inc(AData);
|
|
end;
|
|
DW_OP_xderef_size: begin
|
|
Result := Result + 'DW_OP_xderef_size, ' + IntToStr(AData[1]);
|
|
Inc(AData);
|
|
end;
|
|
DW_OP_nop: begin
|
|
Result := Result + 'DW_OP_nop';
|
|
end;
|
|
DW_OP_push_object_address: begin
|
|
Result := Result + 'DW_OP_push_object_address';
|
|
end;
|
|
DW_OP_call2: begin
|
|
Result := Result + 'DW_OP_call2, ' + IntToStr(PWord(@AData[1])^);
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_OP_call4: begin
|
|
Result := Result + 'DW_OP_call4, ' + IntToStr(PLongWord(@AData[1])^);
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_OP_call_ref: begin
|
|
Result := Result + 'DW_OP_call_ref, AddrB(' + MakeAddressString(@AData[1]) + ')';
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_OP_form_tls_address: begin
|
|
Result := Result + 'DW_OP_form_tls_address';
|
|
end;
|
|
DW_OP_call_frame_cfa: begin
|
|
Result := Result + 'DW_OP_call_frame_cfa';
|
|
end;
|
|
DW_OP_bit_piece: begin
|
|
Inc(AData);
|
|
Result := Result + 'DW_OP_bit_piece, ULEB(' + IntToStr(ULEB128toOrdinal(AData)) + '), ULEB(' + IntToStr(ULEB128toOrdinal(AData)) + ')';
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_lo_user..DW_OP_hi_user: begin
|
|
Result := Result + 'DW_OP_user, ' + IntToStr(AData^);
|
|
end;
|
|
else
|
|
Result := Result + 'Unknown DW_OP_' + IntToStr(AData^);
|
|
end;
|
|
Inc(AData);
|
|
//Result := Result +' / ';
|
|
end;
|
|
end;
|
|
|
|
function AddAbbrev(AParent: TTreeNode; s: TDwarfScopeInfo; Def: TDwarfAbbrev;
|
|
var PascalTestCAseCode: String; namePreFix: String = ''): String;
|
|
var
|
|
p: Pointer;
|
|
Form: Cardinal;
|
|
Attribute: Cardinal;
|
|
i: Integer;
|
|
s1, s2, s3, s4, stest: String;
|
|
ValueSize: QWord;
|
|
Value: qword;
|
|
SValue: int64;
|
|
p2: Pointer;
|
|
addednode: TTreeNode;
|
|
begin
|
|
Result := '';
|
|
PascalTestCAseCode := '';
|
|
p := s.Entry;
|
|
ULEB128toOrdinal(p);
|
|
for i := def.index to Def.index + Def.count - 1 do begin
|
|
Form := CU.AbbrevList.EntryPointer[i]^.Form;
|
|
Attribute := CU.AbbrevList.EntryPointer[i]^.Attribute;
|
|
s1 := DwarfAttributeToString(Attribute);
|
|
s2 := DwarfAttributeFormToString(Form);
|
|
p2 := p;
|
|
|
|
case Form of
|
|
DW_FORM_addr : begin
|
|
s3 := ToHex(p, 4 {FCU.FAddressSize});
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'AddAddr(%s, %s, $%s);%s', [s1, s2, s3, LineEnding]);
|
|
end;
|
|
DW_FORM_block : begin
|
|
p2 := p;
|
|
ValueSize := ULEB128toOrdinal(p);
|
|
stest := ToHexCommaList(p,ValueSize);
|
|
p2 := p;
|
|
s3 := IntToStr(ValueSize) + ': ' + ToHex(p, ValueSize);
|
|
if (Attribute = DW_AT_location) or (Attribute = DW_AT_data_member_location) then
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, BytesLenU([%s])); // %s%s', [s1, s2, DecodeLocation(p2, ValueSize), stest, LineEnding])
|
|
else
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, BytesLenU([%s]));%s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_block1 : begin
|
|
ValueSize := PByte(p)^;
|
|
Inc(p, 1);
|
|
p2 := p;
|
|
stest := ToHexCommaList(p,ValueSize);
|
|
s3 := IntToStr(ValueSize) + ': ' + ToHex(p, ValueSize);
|
|
if (Attribute = DW_AT_location) or (Attribute = DW_AT_data_member_location) then
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, BytesLen1([%s])); // %s%s', [s1, s2, DecodeLocation(p2, ValueSize), stest, LineEnding])
|
|
else
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, BytesLen1([%s]));%s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_block2 : begin
|
|
ValueSize := PWord(p)^;
|
|
Inc(p, 2);
|
|
p2 := p;
|
|
stest := ToHexCommaList(p,ValueSize);
|
|
s3 := IntToStr(ValueSize) + ': ' + ToHex(p, ValueSize);
|
|
if (Attribute = DW_AT_location) or (Attribute = DW_AT_data_member_location) then
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, BytesLen2([%s])); // %s%s', [s1, s2, DecodeLocation(p2, ValueSize), stest, LineEnding])
|
|
else
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, BytesLen2([%s]));%s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_block4 : begin
|
|
ValueSize := PLongWord(p)^;
|
|
Inc(p, 4);
|
|
p2 := p;
|
|
stest := ToHexCommaList(p,ValueSize);
|
|
s3 := IntToStr(ValueSize) + ': ' + ToHex(p, ValueSize);
|
|
if (Attribute = DW_AT_location) or (Attribute = DW_AT_data_member_location) then
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, BytesLen4([%s])); // %s%s', [s1, s2, DecodeLocation(p2, ValueSize), stest, LineEnding])
|
|
else
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, BytesLen4([%s]));%s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_data1 : begin
|
|
stest := ToHexCommaList(p,1);
|
|
s3 := ToHex(p, 1);
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, [%s]);%s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_data2 : begin
|
|
stest := ToHexCommaList(p,2);
|
|
s3 := ToHex(p, 2);
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, [%s]);%s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_data4 : begin
|
|
stest := ToHexCommaList(p,4);
|
|
s3 := ToHex(p, 4);
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, [%s]);%s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_data8 : begin
|
|
stest := ToHexCommaList(p,8);
|
|
s3 := ToHex(p, 8);
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, [%s]);%s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_sdata : begin
|
|
SValue := SLEB128toOrdinal(p);
|
|
s3 := IntToStr(SValue);
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'AddSLEB(%s, %s, %d);%s', [s1, s2, SValue, LineEnding]);
|
|
end;
|
|
DW_FORM_udata : begin
|
|
Value := ULEB128toOrdinal(p);
|
|
s3 := IntToStr(Value);
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'AddULEB(%s, %s, %u);%s', [s1, s2, Value, LineEnding]);
|
|
end;
|
|
DW_FORM_flag : begin
|
|
stest := ToHexCommaList(p,1);
|
|
s3 := ToHex(p, 1);
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, [%s]);%s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_ref1 : begin
|
|
stest := ToHexCommaList(p,1);
|
|
s3 := ToHex(p, 1);
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'AddRef(%s, %s, @Info__%s_); // %s %s', [s1, s2, IntToStr(PByte(p-1)^), stest, LineEnding]);
|
|
//Format(namePreFix+'AddRef(%s, %s, FOO); // %s %s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_ref2 : begin
|
|
stest := ToHexCommaList(p,3);
|
|
s3 := ToHex(p, 2);
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'AddRef(%s, %s, @Info__%s_); // %s %s', [s1, s2, IntToStr(PWord(p-2)^), stest, LineEnding]);
|
|
//Format(namePreFix+'AddRef(%s, %s, FOO); // %s %s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_ref4 : begin
|
|
stest := ToHexCommaList(p,4);
|
|
s4 := IntToHex(PInteger(p)^ -11, 8);;
|
|
s3 := ToHex(p, 4) + ' // '+ s4;
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'AddRef(%s, %s, @Info__%s_); // %s %s', [s1, s2, IntToStr(PDWord(p-4)^), stest, LineEnding]);
|
|
//Format(namePreFix+'AddRef(%s, %s, FOO); // %s %s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_ref8 : begin
|
|
stest := ToHexCommaList(p,8);
|
|
s3 := ToHex(p, 8);
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'AddRef(%s, %s, @Info__%s_); // %s %s', [s1, s2, IntToStr(PQWord(p-8)^), stest, LineEnding]);
|
|
//Format(namePreFix+'AddRef(%s, %s, FOO); // %s %s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_ref_udata: begin
|
|
Value := ULEB128toOrdinal(p);
|
|
s3 := IntToStr(Value);
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'AddRef(%s, %s, FOO); // %u // ULEB %s', [s1, s2, Value, LineEnding]);
|
|
end;
|
|
DW_FORM_ref_addr : begin
|
|
stest := ToHexCommaList(p,4);
|
|
s3 := ToHex(p, 4 {FCU.FAddressSize});
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'AddRef(%s, %s, FOO); // %s // %s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_string : begin
|
|
s3 := copy(pchar(p),1,1000);
|
|
while pbyte( p)^ <> 0 do begin
|
|
inc(pbyte(p));
|
|
end;
|
|
inc(pbyte(p));
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, ''%s''+#0);%s', [s1, s2, s3, LineEnding]);
|
|
end;
|
|
DW_FORM_strp : begin
|
|
stest := ToHexCommaList(p,4);
|
|
s3 := ToHex(p, 4 {FCU.FAddressSize});
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, [%s]);%s', [s1, s2, stest, LineEnding]);
|
|
end;
|
|
DW_FORM_indirect : begin
|
|
Value := ULEB128toOrdinal(p);
|
|
s3 := IntToStr(Value);
|
|
//Form := ULEB128toOrdinal(p);
|
|
//Continue;
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'AddULEB(%s, %s, %u);%s', [s1, s2, Value, LineEnding]);
|
|
end;
|
|
else
|
|
s3 := '?????';
|
|
PascalTestCAseCode := PascalTestCAseCode +
|
|
Format(namePreFix+'Add(%s, %s, %s);%s', [s1, s2, '???????????', LineEnding]);
|
|
end;
|
|
|
|
if Attribute = DW_AT_name then Result := s3;
|
|
|
|
if (Attribute = DW_AT_location) or (Attribute = DW_AT_data_member_location) then begin
|
|
stest := DecodeLocation(p2, ValueSize);
|
|
s3 := s3 + ' // ' +stest;
|
|
end;
|
|
|
|
addednode := TreeView1.Items.AddChild(AParent, Format(' -- Attr: %20s(%4x) Form: %18s(%4x) >> %s', [s1, Attribute, s2, Form, s3]));
|
|
|
|
end;
|
|
end;
|
|
|
|
function AddNode(AParent, Asibling: TTreeNode; s: TDwarfScopeInfo): TTreeNode;
|
|
var
|
|
p: Pointer;
|
|
Abbrev: QWord;
|
|
Node: TTreeNode;
|
|
s2: TDwarfScopeInfo;
|
|
n: TTreeNode;
|
|
i: Integer;
|
|
Def: TDwarfAbbrev;
|
|
entryname: String;
|
|
TestCaseText: String;
|
|
NMLIdx: Integer;
|
|
pre, sName: String;
|
|
begin
|
|
p := s.Entry;
|
|
Abbrev := ULEB128toOrdinal(p);
|
|
p := s.Entry;
|
|
CU.GetDefinition(p, Def);
|
|
Node := TreeView1.Items.AddChild(AParent, Format('Abr: %d Tag: %d %s ', [Abbrev, Def.tag, DwarfTagToString(Def.tag)]));
|
|
|
|
sName := 'Info__'+IntToStr(s.Entry - BaseScopeAddr + 11)+'_.';
|
|
entryname := AddAbbrev(Node, s, Def, TestCaseText, sName);
|
|
|
|
pre := '';
|
|
Case def.tag of
|
|
DW_TAG_base_type, DW_TAG_string_type, DW_TAG_union_type, DW_TAG_ptr_to_member_type,
|
|
DW_TAG_file_type, DW_TAG_thrown_type, DW_TAG_subroutine_type, DW_TAG_packed_type,
|
|
DW_TAG_const_type, DW_TAG_volatile_type, DW_TAG_reference_type,
|
|
DW_TAG_subrange_type, DW_TAG_enumeration_type,
|
|
DW_TAG_enumerator, DW_TAG_set_type, DW_TAG_structure_type, DW_TAG_class_type,
|
|
DW_TAG_array_type: pre:= 'Type';
|
|
DW_TAG_typedef: pre:= 'TypeDecl';
|
|
DW_TAG_pointer_type: pre:= 'TypePtr';
|
|
DW_TAG_variable, DW_TAG_formal_parameter, DW_TAG_member: pre:= 'Var';
|
|
DW_TAG_subprogram: pre:= 'Prog';
|
|
DW_TAG_compile_unit: pre:= 'Unit';
|
|
else pre:= 'XX';
|
|
end;
|
|
pre := pre + entryname;
|
|
pre := AnsiReplaceStr(pre, '$', '');
|
|
pre := AnsiReplaceStr(pre, '.', '_');
|
|
pre := AnsiReplaceStr(pre, ' ', '_');
|
|
pre := AnsiReplaceStr(pre, ' ', '_');
|
|
|
|
NameList.Values['Info__'+IntToStr(s.Entry - BaseScopeAddr + 11)+'_']
|
|
:= pre+'_'+IntToStr(FTestCaseTexts.Count);
|
|
i := 0;
|
|
if s.HasChild then i := 1;
|
|
TestCaseText :=
|
|
Format('%sTag := %s;%s',
|
|
[sName, DwarfTagToString(Def.tag), LineEnding])
|
|
+ Format('%sChildren := %d;%s', [sName, i, LineEnding])
|
|
+ TestCaseText;
|
|
node.Data := pointer(ptruint(FTestCaseTexts.Add(TestCaseText)+1));
|
|
|
|
i := 0;
|
|
if s.HasChild then begin
|
|
n:=nil;
|
|
s2 := s.Child;
|
|
while s2.IsValid do begin
|
|
n := AddNode(Node,n,s2);
|
|
s2.GoNext;
|
|
inc(i);
|
|
if (i and 31) = 0 then begin
|
|
StatusBar1.SimpleText := IntToHex(s2.Index,8) + ' / '+ IntToHex(CU.InfoDataLength,8);
|
|
Application.ProcessMessages;
|
|
if not FShowingUnit then break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Node.Text := Format('At %4x Abr: %d Tag: %d %s ChildCnt: %d %s', [s.Entry-BaseScopeAddr, Abbrev, Def.tag, DwarfTagToString(Def.tag), i, entryname]);
|
|
end;
|
|
|
|
var
|
|
i: Integer;
|
|
s: TDwarfScopeInfo;
|
|
Node: TTreeNode;
|
|
rs: TDwarfScopeInfo;
|
|
begin
|
|
FShowingUnit := not FShowingUnit;//////////////////
|
|
if not FShowingUnit then exit;/////////////////
|
|
TreeView1.BeginUpdate;
|
|
try
|
|
TreeView1.Items.Clear;
|
|
i := CompUnitListBox.ItemIndex;
|
|
if i < 0 then exit;
|
|
CU := TDwarfCompilationUnitHack(CompUnitListBox.Items.Objects[i]);
|
|
if CU = nil then exit;
|
|
s := CU.FirstScope;
|
|
BaseScopeAddr := s.Entry;
|
|
CU.LocateEntry(0, rs);
|
|
|
|
Node := nil;
|
|
while s.IsValid do begin
|
|
Node := AddNode(nil,Node,s);
|
|
s.GoNext;
|
|
end;
|
|
finally
|
|
TreeView1.EndUpdate;
|
|
FShowingUnit := False; ////////////////////
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TForm1.FormCreate(Sender: TObject);
|
|
begin
|
|
FTestCaseTexts:= TStringList.Create;
|
|
NameList:= TStringList.Create;
|
|
end;
|
|
|
|
procedure TForm1.FormDestroy(Sender: TObject);
|
|
begin
|
|
UnLoadDwarf;
|
|
FTestCaseTexts.Free;
|
|
end;
|
|
|
|
procedure TForm1.UnLoadDwarf;
|
|
begin
|
|
FreeAndNil(FDwarfInfo);
|
|
FreeAndNil(FImageLoaderList);
|
|
FCUCount := 0;
|
|
end;
|
|
|
|
end.
|
|
|