mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-05 10:57:55 +02:00
1183 lines
37 KiB
ObjectPascal
1183 lines
37 KiB
ObjectPascal
unit FpDbgDwarfVerbosePrinter;
|
|
|
|
{$mode objfpc}{$H+}
|
|
{$IFDEF INLINE_OFF}{$INLINE OFF}{$ENDIF}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, Math, SysUtils, FpDbgDwarf, FpDbgLoader, FpDbgDwarfConst, FpdMemoryTools, FpDbgUtil,
|
|
FpImgReaderBase, FpDbgDwarfDataClasses, {$ifdef FORCE_LAZLOGGER_DUMMY} LazLoggerDummy {$else} LazLoggerBase {$endif}, maps;
|
|
|
|
type
|
|
|
|
{ TDwarfAbbrevDecoder }
|
|
|
|
TDwarfAbbrevDecoder = class(TObject)
|
|
private
|
|
FCU: TDwarfCompilationUnit;
|
|
function ReadTargetAddressFromDwarfSection(var AData: Pointer; AIncPointer: Boolean = False): TFpDbgMemLocation;
|
|
function ReadDwarfSectionOffsetOrLenFromDwarfSection(var AData: Pointer; AIncPointer: Boolean = False): TFpDbgMemLocation;
|
|
procedure InternalDecode(AData: Pointer; AMaxData: Pointer; const AIndent: String = '');
|
|
protected
|
|
procedure DecodeLocation(AData: PByte; ASize: QWord; const AIndent: String = '');
|
|
procedure DecodeLocationList({%H-}AReference: QWord; const {%H-}AIndent: String = '');
|
|
function MakeAddressString(AData: Pointer): string;
|
|
public
|
|
constructor Create(ACompilationUnit: TDwarfCompilationUnit);
|
|
procedure Decode;
|
|
end;
|
|
|
|
{ TDwarfStatementDecoder }
|
|
|
|
TDwarfStatementDecoder = class(TObject)
|
|
private
|
|
FCU: TDwarfCompilationUnit;
|
|
procedure InternalDecode(AData: Pointer; {%H-}AMaxData: Pointer; const {%H-}AIndent: String = '');
|
|
protected
|
|
public
|
|
constructor Create(ACompilationUnit: TDwarfCompilationUnit);
|
|
procedure Decode(AData: Pointer); // Adata := FCU.FLineInfo.Header
|
|
end;
|
|
|
|
{ TVerboseDwarfCallframeDecoder }
|
|
|
|
TVerboseDwarfCallframeDecoder = class(TObject)
|
|
private
|
|
FLoader: TDbgImageLoader;
|
|
procedure InternalDecode(AData: Pointer; ASize, AStart: QWord);
|
|
protected
|
|
public
|
|
constructor Create(ALoader: TDbgImageLoader);
|
|
procedure Decode;
|
|
end;
|
|
|
|
implementation
|
|
var
|
|
FPDBG_DWARF_VERBOSE, FPDBG_DWARF_WARNINGS: PLazLoggerLogGroup;
|
|
|
|
{ TDwarfAbbrevDecoder }
|
|
|
|
constructor TDwarfAbbrevDecoder.Create(ACompilationUnit: TDwarfCompilationUnit);
|
|
begin
|
|
inherited Create;
|
|
FCU := ACompilationUnit;
|
|
end;
|
|
|
|
procedure TDwarfAbbrevDecoder.Decode;
|
|
var
|
|
Iter: TMapIterator;
|
|
Info: TDwarfAddressInfo;
|
|
Scope: TDwarfScopeInfo;
|
|
begin
|
|
// force all abbrevs to be loaded
|
|
InternalDecode(FCU.InfoData, FCU.InfoData + FCU.InfoDataLength);
|
|
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['addresses: ']);
|
|
Iter := TMapIterator.Create(FCU.AddressMap);
|
|
while not Iter.EOM do
|
|
begin
|
|
Iter.GetData(Info);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [' ']);
|
|
Scope.Init(Info.ScopeList);
|
|
Scope.Index := Info.ScopeIndex;
|
|
Scope := Scope.Parent;
|
|
while Scope.IsValid do
|
|
begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['.']);
|
|
Scope := Scope.Parent;
|
|
end;
|
|
DebugLn(FPDBG_DWARF_VERBOSE, [Info.Name, ': $', IntToHex(Info.StartPC, FCU.AddressSize * 2), '..$', IntToHex(Info.EndPC, FCU.AddressSize * 2)]);
|
|
Iter.Next;
|
|
end;
|
|
Iter.Free;
|
|
|
|
end;
|
|
|
|
procedure TDwarfAbbrevDecoder.DecodeLocation(AData: PByte; ASize: QWord; const AIndent: String);
|
|
var
|
|
MaxData: PByte;
|
|
v: Int64;
|
|
begin
|
|
MaxData := AData + ASize - 1;
|
|
while AData <= MaxData do
|
|
begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [AIndent]);
|
|
case AData^ of
|
|
DW_OP_addr: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_addr ', MakeAddressString(@AData[1])]);
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_OP_deref: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_deref']);
|
|
end;
|
|
DW_OP_const1u: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_const1u ', AData[1]]);
|
|
Inc(AData, 1);
|
|
end;
|
|
DW_OP_const1s: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_const1s ', PShortInt(@AData[1])^]);
|
|
Inc(AData, 1);
|
|
end;
|
|
DW_OP_const2u: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_const2u ', PWord(@AData[1])^]);
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_OP_const2s: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_const2s ', PSmallInt(@AData[1])^]);
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_OP_const4u: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_const4u ', PLongWord(@AData[1])^]);
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_OP_const4s: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_const4s ', PLongInt(@AData[1])^]);
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_OP_const8u: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_const8u ', PQWord(@AData[1])^]);
|
|
Inc(AData, 8);
|
|
end;
|
|
DW_OP_const8s: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_const8s ', PInt64(@AData[1])^]);
|
|
Inc(AData, 8);
|
|
end;
|
|
DW_OP_constu: begin
|
|
Inc(AData);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_constu ', ULEB128toOrdinal(AData)]);;
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_consts: begin
|
|
Inc(AData);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_consts ', SLEB128toOrdinal(AData)]);;
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_dup: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_dup']);
|
|
end;
|
|
DW_OP_drop: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_drop']);
|
|
end;
|
|
DW_OP_over: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_over']);
|
|
end;
|
|
DW_OP_pick: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_pick ', AData[1]]);
|
|
Inc(AData, 1);
|
|
end;
|
|
DW_OP_swap: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_swap']);
|
|
end;
|
|
DW_OP_rot: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_rot']);
|
|
end;
|
|
DW_OP_xderef: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_xderef']);
|
|
end;
|
|
DW_OP_abs: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_abs']);
|
|
end;
|
|
DW_OP_and: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_and']);
|
|
end;
|
|
DW_OP_div: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_div']);
|
|
end;
|
|
DW_OP_minus: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_minus']);
|
|
end;
|
|
DW_OP_mod: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_mod']);
|
|
end;
|
|
DW_OP_mul: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_mul']);
|
|
end;
|
|
DW_OP_neg: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_neg']);
|
|
end;
|
|
DW_OP_not: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_not']);
|
|
end;
|
|
DW_OP_or: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_or']);
|
|
end;
|
|
DW_OP_plus: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_plus']);
|
|
end;
|
|
DW_OP_plus_uconst: begin
|
|
Inc(AData);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_plus_uconst ', ULEB128toOrdinal(AData)]);;
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_shl: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_shl']);
|
|
end;
|
|
DW_OP_shr: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_shr']);
|
|
end;
|
|
DW_OP_shra: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_shra']);
|
|
end;
|
|
DW_OP_xor: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_xor']);
|
|
end;
|
|
DW_OP_skip: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_skip ', PSmallInt(@AData[1])^]);
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_OP_bra: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_bra ', PSmallInt(@AData[1])^]);
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_OP_eq: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_eq']);
|
|
end;
|
|
DW_OP_ge: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_ge']);
|
|
end;
|
|
DW_OP_gt: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_gt']);
|
|
end;
|
|
DW_OP_le: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_le']);
|
|
end;
|
|
DW_OP_lt: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_lt']);
|
|
end;
|
|
DW_OP_ne: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_ne']);
|
|
end;
|
|
DW_OP_lit0..DW_OP_lit31: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_lit', AData^ - DW_OP_lit0]);
|
|
end;
|
|
DW_OP_reg0..DW_OP_reg31: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_reg', AData^ - DW_OP_reg0]);
|
|
end;
|
|
DW_OP_breg0..DW_OP_breg31: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_breg', AData^ - DW_OP_breg0]);
|
|
Inc(AData);
|
|
v := SLEB128toOrdinal(AData);
|
|
Dec(AData);
|
|
if v >= 0
|
|
then DbgOut(FPDBG_DWARF_VERBOSE, ['+']);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [v]);
|
|
end;
|
|
DW_OP_regx: begin
|
|
Inc(AData);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_regx ', ULEB128toOrdinal(AData)]);
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_fbreg: begin
|
|
Inc(AData);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_fbreg ', SLEB128toOrdinal(AData)]);
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_bregx: begin
|
|
Inc(AData);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_bregx ', ULEB128toOrdinal(AData)]);
|
|
v := SLEB128toOrdinal(AData);
|
|
Dec(AData);
|
|
if v >= 0
|
|
then DbgOut(FPDBG_DWARF_VERBOSE, ['+']);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [v]);
|
|
end;
|
|
DW_OP_piece: begin
|
|
Inc(AData);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_piece ', ULEB128toOrdinal(AData)]);
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_deref_size: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_deref_size ', AData[1]]);
|
|
Inc(AData);
|
|
end;
|
|
DW_OP_xderef_size: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_xderef_size', AData[1]]);
|
|
Inc(AData);
|
|
end;
|
|
DW_OP_nop: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_nop']);
|
|
end;
|
|
DW_OP_push_object_address: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_push_object_address']);
|
|
end;
|
|
DW_OP_call2: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_call2 ', PWord(@AData[1])^]);
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_OP_call4: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_call4 ', PLongWord(@AData[1])^]);
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_OP_call_ref: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_call_ref ', MakeAddressString(@AData[1])]);
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_OP_form_tls_address: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_form_tls_address']);
|
|
end;
|
|
DW_OP_call_frame_cfa: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_call_frame_cfa']);
|
|
end;
|
|
DW_OP_bit_piece: begin
|
|
Inc(AData);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_bit_piece ', ULEB128toOrdinal(AData), ' ', ULEB128toOrdinal(AData)]);
|
|
Dec(AData);
|
|
end;
|
|
DW_OP_lo_user..DW_OP_hi_user: begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_OP_user=', AData^]);
|
|
end;
|
|
else
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['Unknown DW_OP_', AData^]);
|
|
end;
|
|
Inc(AData);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['']);
|
|
end;
|
|
end;
|
|
|
|
procedure TDwarfAbbrevDecoder.DecodeLocationList(AReference: QWord; const AIndent: String);
|
|
begin
|
|
|
|
end;
|
|
|
|
function TDwarfAbbrevDecoder.ReadTargetAddressFromDwarfSection(
|
|
var AData: Pointer; AIncPointer: Boolean): TFpDbgMemLocation;
|
|
begin
|
|
// do not need mem reader, address is in dwarf. Should be in correct format
|
|
if FCU.AddressSize = 4
|
|
then Result := TargetLoc(PLongWord(AData)^)
|
|
else Result := TargetLoc(PQWord(AData)^);
|
|
if AIncPointer then inc(AData, FCU.AddressSize);
|
|
end;
|
|
|
|
function TDwarfAbbrevDecoder.ReadDwarfSectionOffsetOrLenFromDwarfSection(var AData: Pointer;
|
|
AIncPointer: Boolean): TFpDbgMemLocation;
|
|
begin
|
|
// do not need mem reader, address is in dwarf. Should be in correct format
|
|
if FCU.AddressSize = 4 // TODO Dwarf3 depends on FIsDwarf64
|
|
then Result := TargetLoc(PLongWord(AData)^)
|
|
else Result := TargetLoc(PQWord(AData)^);
|
|
if AIncPointer then inc(AData, FCU.AddressSize);
|
|
end;
|
|
|
|
procedure TDwarfAbbrevDecoder.InternalDecode(AData: Pointer; AMaxData: Pointer; const AIndent: String);
|
|
procedure Dump(var p: PByte; count: QWord);
|
|
var
|
|
n: integer;
|
|
begin
|
|
for n := 1 to Min(80, count) do
|
|
begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [IntToHex(p^, 2), ' ']);
|
|
Inc(p);
|
|
end;
|
|
if Count > 80
|
|
then begin
|
|
Inc(p, Count - 80);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['...']);
|
|
end;
|
|
end;
|
|
procedure DumpStr(var p: PChar);
|
|
begin
|
|
while p^ <> #0 do
|
|
begin
|
|
case p^ of
|
|
#32..#127: DbgOut(FPDBG_DWARF_VERBOSE, [p^]);
|
|
else
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['<', IntToHex(Ord(p^), 2), '>']);
|
|
end;
|
|
Inc(p);
|
|
end;
|
|
Inc(p);
|
|
end;
|
|
|
|
var
|
|
Attribute: Cardinal;
|
|
Abbrev, Form: Cardinal;
|
|
Def: TDwarfAbbrev;
|
|
idx: Integer;
|
|
Value: QWord;
|
|
ValueSize: QWord;
|
|
ValuePtr, p: Pointer;
|
|
Indent: String;
|
|
Level: Integer;
|
|
ADefs: PDwarfAbbrevEntry;
|
|
begin
|
|
Indent := AIndent;
|
|
Level := 0;
|
|
ADefs := FCU.AbbrevList.EntryPointer[0];
|
|
while (AData <= AMaxData) and (Level >= 0) do
|
|
begin
|
|
p := AData;
|
|
Abbrev := ULEB128toOrdinal(AData);
|
|
if Abbrev = 0
|
|
then begin
|
|
Dec(Level);
|
|
SetLength(Indent, Length(Indent) - 2);
|
|
if Level >= 0
|
|
then DebugLn(FPDBG_DWARF_VERBOSE, [Indent, ' \--']);
|
|
Continue;
|
|
end;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [Indent, 'abbrev: ', Abbrev]);
|
|
if not FCU.GetDefinition(p, Def)
|
|
then begin
|
|
DebugLn(FPDBG_DWARF_WARNINGS, ['Error: Abbrev not found: ', Abbrev]);
|
|
Exit;
|
|
end;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', tag: ', Def.tag, '=', DwarfTagToString(Def.tag)]);
|
|
if (dafHasChildren in Def.flags)
|
|
then begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['']);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, [', has children']);
|
|
Inc(Level);
|
|
end
|
|
else DebugLn(FPDBG_DWARF_VERBOSE, ['']);
|
|
|
|
for idx := Def.Index to Def.Index + Def.Count - 1 do
|
|
begin
|
|
Form := ADefs[idx].Form;
|
|
Attribute := ADefs[idx].Attribute;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [Indent, ' attrib: ', Attribute, '=', DwarfAttributeToString(Attribute)]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', form: ', Form, '=', DwarfAttributeFormToString(Form)]);
|
|
|
|
ValueSize := 0;
|
|
ValuePtr := nil;
|
|
Value := 0;
|
|
repeat
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', value: ']);
|
|
case Form of
|
|
DW_FORM_addr : begin
|
|
Value := LocToAddrOrNil(ReadTargetAddressFromDwarfSection(AData));
|
|
ValuePtr := {%H-}Pointer(PtrUInt(Value));
|
|
ValueSize := FCU.AddressSize;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, FCU.AddressSize * 2)]);
|
|
Inc(AData, FCU.AddressSize);
|
|
end;
|
|
DW_FORM_block : begin
|
|
ValueSize := ULEB128toOrdinal(AData);
|
|
ValuePtr := AData;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['Size=', ValueSize, ', Data=']);
|
|
Dump(AData, ValueSize);
|
|
end;
|
|
DW_FORM_block1 : begin
|
|
ValueSize := PByte(AData)^;
|
|
Inc(AData, 1);
|
|
ValuePtr := AData;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['Size=', ValueSize, ', Data=']);
|
|
Dump(AData, ValueSize);
|
|
end;
|
|
DW_FORM_block2 : begin
|
|
ValueSize := PWord(AData)^;
|
|
Inc(AData, 2);
|
|
ValuePtr := AData;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['Size=', ValueSize, ', Data=']);
|
|
Dump(AData, ValueSize);
|
|
end;
|
|
DW_FORM_block4 : begin
|
|
ValueSize := PLongWord(AData)^;
|
|
Inc(AData, 4);
|
|
ValuePtr := AData;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['Size=', ValueSize, ', Data=']);
|
|
Dump(AData, ValueSize);
|
|
end;
|
|
DW_FORM_data1 : begin
|
|
Value := PByte(AData)^;
|
|
ValueSize := 1;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, 2)]);
|
|
Inc(AData, 1);
|
|
end;
|
|
DW_FORM_data2 : begin
|
|
Value := PWord(AData)^;
|
|
ValueSize := 2;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, 4)]);
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_FORM_data4 : begin
|
|
Value := PLongWord(AData)^;
|
|
ValueSize := 4;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, 8)]);
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_FORM_data8 : begin
|
|
Value := PQWord(AData)^;
|
|
ValueSize := 8;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, 16)]);
|
|
Inc(AData, 8);
|
|
end;
|
|
DW_FORM_sdata : begin
|
|
p := AData;
|
|
Value := ULEB128toOrdinal(AData);
|
|
ValueSize := {%H-}PtrUInt(AData) - {%H-}PtrUInt(p);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, ValueSize * 2)]);
|
|
end;
|
|
DW_FORM_udata : begin
|
|
p := AData;
|
|
Value := ULEB128toOrdinal(AData);
|
|
ValueSize := {%H-}PtrUInt(AData) - {%H-}PtrUInt(p);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, ValueSize * 2)]);
|
|
end;
|
|
DW_FORM_flag : begin
|
|
Value := PByte(AData)^;
|
|
ValueSize := 1;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, 2)]);
|
|
Inc(AData, 1);
|
|
end;
|
|
DW_FORM_ref1 : begin
|
|
Value := PByte(AData)^;
|
|
ValueSize := 1;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, 2)]);
|
|
Inc(AData, 1);
|
|
end;
|
|
DW_FORM_ref2 : begin
|
|
Value := PWord(AData)^;
|
|
ValueSize := 2;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, 4)]);
|
|
Inc(AData, 2);
|
|
end;
|
|
DW_FORM_ref4 : begin
|
|
Value := PLongWord(AData)^;
|
|
ValueSize := 4;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, 8)]);
|
|
Inc(AData, 4);
|
|
end;
|
|
DW_FORM_ref8 : begin
|
|
Value := PQWord(AData)^;
|
|
ValueSize := 8;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, 16)]);
|
|
Inc(AData, 8);
|
|
end;
|
|
DW_FORM_ref_udata: begin
|
|
p := AData;
|
|
Value := ULEB128toOrdinal(AData);
|
|
ValueSize := {%H-}PtrUInt(AData) - {%H-}PtrUInt(p);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, ValueSize * 2)]);
|
|
end;
|
|
DW_FORM_ref_addr : begin
|
|
Value := LocToAddrOrNil(ReadDwarfSectionOffsetOrLenFromDwarfSection(AData));
|
|
ValuePtr := {%H-}Pointer(PtrUInt(Value));
|
|
ValueSize := FCU.AddressSize;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, FCU.AddressSize * 2)]);
|
|
Inc(AData, FCU.AddressSize);
|
|
end;
|
|
DW_FORM_string : begin
|
|
ValuePtr := AData;
|
|
DumpStr(AData);
|
|
ValueSize := {%H-}PtrUInt(AData) - {%H-}PtrUInt(ValuePtr);
|
|
end;
|
|
DW_FORM_strp : begin
|
|
Value := LocToAddrOrNil(ReadDwarfSectionOffsetOrLenFromDwarfSection(AData));
|
|
ValueSize := FCU.AddressSize;
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['$'+IntToHex(Value, FCU.AddressSize * 2)]);
|
|
Inc(AData, FCU.AddressSize);
|
|
end;
|
|
DW_FORM_indirect : begin
|
|
Form := ULEB128toOrdinal(AData);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['indirect form: ', Form, '=', DwarfAttributeFormToString(Form)]);
|
|
Continue;
|
|
end;
|
|
else
|
|
DebugLn(FPDBG_DWARF_WARNINGS, ['Error: Unknown Form: ', Form]);
|
|
Exit;
|
|
end;
|
|
Break;
|
|
until False;
|
|
|
|
case Attribute of
|
|
DW_AT_accessibility: begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['=', DwarfAccessibilityToString(Value)]);
|
|
end;
|
|
DW_AT_data_member_location: begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['-->']);
|
|
DecodeLocation(ValuePtr, ValueSize, Indent + ' ');
|
|
end;
|
|
DW_AT_encoding: begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['=', DwarfBaseTypeEncodingToString(Value)]);
|
|
end;
|
|
DW_AT_language: begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['=', DwarfLanguageToString(Value)]);
|
|
end;
|
|
DW_AT_identifier_case: begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['=', DwarfIdentifierCaseToString(Value)]);
|
|
end;
|
|
DW_AT_location: begin
|
|
if ValuePtr = nil
|
|
then begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['-->']);
|
|
DecodeLocationList(Value, AIndent + ' ');
|
|
end
|
|
else begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['-->']);
|
|
DecodeLocation(ValuePtr, ValueSize, Indent + ' ');
|
|
end;
|
|
end;
|
|
DW_AT_type: begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['-->']);
|
|
try
|
|
p := FCU.DebugFile^.Sections[dsInfo].RawData + Value - FCU.Owner.ImageBase - FCU.DebugFile^.Sections[dsInfo].VirtualAddress;
|
|
InternalDecode(p, p, Indent + ' ');
|
|
except
|
|
on E: Exception do DebugLn(FPDBG_DWARF_WARNINGS, [AIndent, ' ', E.Message]);
|
|
end;
|
|
end;
|
|
else
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['']);
|
|
end;
|
|
end;
|
|
|
|
if (dafHasChildren in Def.flags)
|
|
then begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, [Indent, ' /--']);
|
|
Indent := Indent + ' |';
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TDwarfAbbrevDecoder.MakeAddressString(AData: Pointer): string;
|
|
begin
|
|
if FCU.AddressSize = 4
|
|
then Result := '$'+IntToHex(PLongWord(AData)^, 8)
|
|
else Result := '$'+IntToHex(PQWord(AData)^, 16);
|
|
end;
|
|
|
|
{ TDwarfStatementDecoder }
|
|
|
|
constructor TDwarfStatementDecoder.Create(ACompilationUnit: TDwarfCompilationUnit);
|
|
begin
|
|
inherited Create;
|
|
FCU := ACompilationUnit;
|
|
end;
|
|
|
|
procedure TDwarfStatementDecoder.Decode(AData: Pointer);
|
|
begin
|
|
if AData = nil
|
|
then begin
|
|
DebugLn(FPDBG_DWARF_WARNINGS, ['No lineinfo']);
|
|
Exit;
|
|
end;
|
|
InternalDecode(AData, FCU.DebugFile^.Sections[dsInfo].RawData + FCU.DebugFile^.Sections[dsInfo].Size);
|
|
end;
|
|
|
|
procedure TDwarfStatementDecoder.InternalDecode(AData: Pointer; AMaxData: Pointer; const AIndent: String);
|
|
var
|
|
Info: PDwarfLNPInfoHeader;
|
|
|
|
Address: QWord;
|
|
Line: Int64;
|
|
FileNr: Cardinal;
|
|
Column: Cardinal;
|
|
IsStmt: Boolean;
|
|
BasicBlock: Boolean;
|
|
PrologueEnd: Boolean;
|
|
EpilogueBegin: Boolean;
|
|
Isa: QWord;
|
|
|
|
procedure AddRow(ALast: Boolean = False);
|
|
begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['> ']);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['Address=$', IntToHex(Address, FCU.AddressSize * 2)]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', Line=',Line]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', FileNr=',FileNr]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', Column=',Column]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', IsStmt=',IsStmt]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', BasicBlock=',BasicBlock]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', PrologueEnd=',PrologueEnd]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', EpilogueBegin=',EpilogueBegin]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', Isa=',Isa]);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['']);
|
|
if ALast
|
|
then DebugLn(FPDBG_DWARF_VERBOSE, ['> ---------']);
|
|
end;
|
|
|
|
procedure DoAdjust(AOpcode: Byte);
|
|
begin
|
|
Dec(AOpcode, Info^.OpcodeBase);
|
|
if Info^.LineRange = 0
|
|
then begin
|
|
Inc(Address, AOpcode * Info^.MinimumInstructionLength);
|
|
end
|
|
else begin
|
|
Inc(Address, (AOpcode div Info^.LineRange) * Info^.MinimumInstructionLength);
|
|
Inc(Line, Info^.LineBase + (AOpcode mod Info^.LineRange));
|
|
end;
|
|
end;
|
|
|
|
procedure DoReset;
|
|
begin
|
|
Address := 0;
|
|
Line := 1;
|
|
FileNr := 1;
|
|
Column := 0;
|
|
IsStmt := Info^.DefaultIsStmt <> 0;
|
|
BasicBlock := False;
|
|
PrologueEnd := False;
|
|
EpilogueBegin := False;
|
|
Isa := 0;
|
|
end;
|
|
|
|
|
|
var
|
|
LNP32: PDwarfLNPHeader32 absolute AData;
|
|
LNP64: PDwarfLNPHeader64 absolute AData;
|
|
UnitLength: QWord;
|
|
Version: Word;
|
|
HeaderLength: QWord;
|
|
n: integer;
|
|
ptr: Pointer;
|
|
p: Pointer;
|
|
pb: PByte absolute p;
|
|
pc: PChar absolute p;
|
|
DataEnd: Pointer;
|
|
DataStart: Pointer;
|
|
UValue: QWord;
|
|
SValue: Int64;
|
|
begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['FileName: ', FCU.FileName]);
|
|
|
|
if LNP64^.Signature = DWARF_HEADER64_SIGNATURE
|
|
then begin
|
|
UnitLength := LNP64^.UnitLength;
|
|
DataEnd := Pointer(@LNP64^.Version) + UnitLength;
|
|
Version := LNP64^.Version;
|
|
HeaderLength := LNP64^.HeaderLength;
|
|
Info := @LNP64^.Info;
|
|
end
|
|
else begin
|
|
UnitLength := LNP32^.UnitLength;
|
|
DataEnd := Pointer(@LNP32^.Version) + UnitLength;
|
|
Version := LNP32^.Version;
|
|
HeaderLength := LNP32^.HeaderLength;
|
|
Info := @LNP32^.Info;
|
|
end;
|
|
DataStart := PByte(Info) + HeaderLength;
|
|
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['UnitLength: ', UnitLength]);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['Version: ', Version]);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['HeaderLength: ', HeaderLength]);
|
|
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['MinimumInstructionLength: ', Info^.MinimumInstructionLength]);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DefaultIsStmt: ', Info^.DefaultIsStmt]);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['LineBase: ', Info^.LineBase]);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['LineRange: ', Info^.LineRange]);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['OpcodeBase: ', Info^.OpcodeBase]);
|
|
p := @Info^.StandardOpcodeLengths;
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['StandardOpcodeLengths:']);
|
|
for n := 1 to Info^.OpcodeBase - 1 do
|
|
begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, [' [', n, '] ', pb^]);
|
|
Inc(pb);
|
|
end;
|
|
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['IncludeDirectories:']);
|
|
while pc^ <> #0 do
|
|
begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [' ']);
|
|
repeat
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [pc^]);
|
|
Inc(pc);
|
|
until pc^ = #0;
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['']);
|
|
Inc(pc);
|
|
end;
|
|
Inc(pc);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['FileNames:']);
|
|
while pc^ <> #0 do
|
|
begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [' ']);
|
|
repeat
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [pc^]);
|
|
Inc(pc);
|
|
until pc^ = #0;
|
|
Inc(pc);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', diridx=', ULEB128toOrdinal(p)]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', last modified=', ULEB128toOrdinal(p)]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', length=', ULEB128toOrdinal(p)]);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['']);
|
|
end;
|
|
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['Program:']);
|
|
|
|
p := DataStart;
|
|
DoReset;
|
|
|
|
while p < DataEnd do
|
|
begin
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [' ']);
|
|
if (pb^ > 0) and (pb^ < Info^.OpcodeBase)
|
|
then begin
|
|
// Standard opcode
|
|
case pb^ of
|
|
DW_LNS_copy: begin
|
|
Inc(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_copy']);
|
|
AddRow;
|
|
BasicBlock := False;
|
|
PrologueEnd := False;
|
|
EpilogueBegin := False;
|
|
end;
|
|
DW_LNS_advance_pc: begin
|
|
Inc(p);
|
|
UValue := ULEB128toOrdinal(p);
|
|
Inc(Address, UValue);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_advance_pc ', UValue]);
|
|
end;
|
|
DW_LNS_advance_line: begin
|
|
Inc(p);
|
|
SValue := SLEB128toOrdinal(p);
|
|
Inc(Line, SValue);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_advance_line ', SValue]);
|
|
end;
|
|
DW_LNS_set_file: begin
|
|
Inc(p);
|
|
UValue := ULEB128toOrdinal(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_set_file ', UVAlue]);
|
|
FileNr := UValue;
|
|
end;
|
|
DW_LNS_set_column: begin
|
|
Inc(p);
|
|
UValue := ULEB128toOrdinal(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_set_column ', UValue]);
|
|
Column := UValue;
|
|
end;
|
|
DW_LNS_negate_stmt: begin
|
|
Inc(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_negate_stmt']);
|
|
IsStmt := not IsStmt;
|
|
end;
|
|
DW_LNS_set_basic_block: begin
|
|
Inc(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_set_basic_block']);
|
|
BasicBlock := True;
|
|
end;
|
|
DW_LNS_const_add_pc: begin
|
|
Inc(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_const_add_pc']);
|
|
DoAdjust(255);
|
|
end;
|
|
DW_LNS_fixed_advance_pc: begin
|
|
Inc(p);
|
|
Inc(Address, PWord(p)^);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_fixed_advance_pc ', PWord(p)^]);
|
|
Inc(p, 2);
|
|
end;
|
|
DW_LNS_set_prologue_end: begin
|
|
Inc(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_set_prologue_end']);
|
|
PrologueEnd := True;
|
|
end;
|
|
DW_LNS_set_epilogue_begin: begin
|
|
Inc(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_set_epilogue_begin']);
|
|
EpilogueBegin := True;
|
|
end;
|
|
DW_LNS_set_isa: begin
|
|
Inc(p);
|
|
UValue := ULEB128toOrdinal(p);
|
|
Isa := UValue;
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNS_set_isa ', UValue]);
|
|
end;
|
|
else
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['unknown opcode: ', pb^]);
|
|
Inc(p, PByte(@Info^.StandardOpcodeLengths)[pb^-1]);
|
|
end;
|
|
Continue;
|
|
end;
|
|
|
|
if pb^ = 0
|
|
then begin
|
|
// Extended opcode
|
|
Inc(p);
|
|
UValue := ULEB128toOrdinal(p); // instruction length
|
|
|
|
case pb^ of
|
|
DW_LNE_end_sequence: begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNE_end_sequence']);
|
|
AddRow(True);
|
|
DoReset;
|
|
//Inc(p, UValue);
|
|
//Break;
|
|
end;
|
|
DW_LNE_set_address: begin
|
|
if LNP64^.Signature = DWARF_HEADER64_SIGNATURE
|
|
then Address := PQWord(pb+1)^
|
|
else Address := PLongWord(pb+1)^;
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_LNE_set_address $', IntToHex(Address, FCU.AddressSize * 2)]);
|
|
end;
|
|
DW_LNE_define_file: begin
|
|
ptr := p;
|
|
Inc(ptr);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_LNE_define_file name=']);
|
|
repeat
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [PChar(ptr)^]);
|
|
Inc(ptr);
|
|
until PChar(ptr)^ = #0;
|
|
Inc(ptr);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', diridx=', ULEB128toOrdinal(ptr)]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', last modified=', ULEB128toOrdinal(ptr)]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [', length=', ULEB128toOrdinal(ptr)]);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['']);
|
|
end;
|
|
else
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['unknown extended opcode: ', pb^]);
|
|
end;
|
|
Inc(p, UValue);
|
|
end
|
|
else begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['Special opcode: ', pb^]);
|
|
// Special opcode
|
|
DoAdjust(pb^);
|
|
AddRow;
|
|
BasicBlock := False;
|
|
PrologueEnd := False;
|
|
EpilogueBegin := False;
|
|
Inc(p);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ TVerboseDwarfCallframeDecoder }
|
|
|
|
constructor TVerboseDwarfCallframeDecoder.Create(ALoader: TDbgImageLoader);
|
|
begin
|
|
inherited Create;
|
|
FLoader := Aloader;
|
|
end;
|
|
|
|
procedure TVerboseDwarfCallframeDecoder.Decode;
|
|
var
|
|
Section: PDbgImageSection;
|
|
begin
|
|
Section := FLoader.Section[DWARF_SECTION_NAME[dsFrame]];
|
|
if Section <> nil
|
|
then InternalDecode(Section^.RawData, Section^.Size, Section^.VirtualAddress);
|
|
end;
|
|
|
|
procedure TVerboseDwarfCallframeDecoder.InternalDecode(AData: Pointer; ASize: QWord; AStart: QWord);
|
|
var
|
|
Is64bit: boolean;
|
|
|
|
procedure DecodeInstructions(p: Pointer; MaxAddr: Pointer);
|
|
var
|
|
pb: PByte absolute p;
|
|
pw: PWord absolute p;
|
|
pc: PCardinal absolute p;
|
|
pq: PQWord absolute p;
|
|
q: QWord;
|
|
begin
|
|
repeat
|
|
DbgOut(FPDBG_DWARF_VERBOSE, [' ']);
|
|
Inc(pb);
|
|
case pb[-1] of
|
|
DW_CFA_nop: begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_nop']);
|
|
end;
|
|
DW_CFA_set_loc: begin
|
|
// address
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_CFA_set_loc $']);
|
|
if Is64Bit
|
|
then begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, [IntToHex(pq^, 16)]);
|
|
Inc(pq);
|
|
end
|
|
else begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, [IntToHex(pc^, 8)]);
|
|
Inc(pc);
|
|
end;
|
|
end;
|
|
DW_CFA_advance_loc1: begin
|
|
// 1-byte delta
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_advance_loc1 ', pb^, ' * caf']);
|
|
Inc(pb);
|
|
end;
|
|
DW_CFA_advance_loc2: begin
|
|
// 2-byte delta
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_advance_loc2 ', pw^, ' * caf']);
|
|
Inc(pw);
|
|
end;
|
|
DW_CFA_advance_loc4: begin
|
|
// 4-byte delta
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_advance_loc4 ', pc^, ' * caf']);
|
|
Inc(pw);
|
|
end;
|
|
DW_CFA_offset_extended: begin
|
|
// ULEB128 register, ULEB128 offset
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_offset_extended R', ULEB128toOrdinal(p), ' + ', ULEB128toOrdinal(p), ' * daf']);
|
|
end;
|
|
DW_CFA_restore_extended: begin
|
|
// ULEB128 register
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_restore_extended R', ULEB128toOrdinal(p)]);
|
|
end;
|
|
DW_CFA_undefined: begin
|
|
// ULEB128 register
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_undefined R', ULEB128toOrdinal(p)]);
|
|
end;
|
|
DW_CFA_same_value: begin
|
|
// ULEB128 register
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_same_value R', ULEB128toOrdinal(p)]);
|
|
end;
|
|
DW_CFA_register: begin
|
|
// ULEB128 register, ULEB128 register
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_register R', ULEB128toOrdinal(p), ' R', ULEB128toOrdinal(p)]);
|
|
end;
|
|
DW_CFA_remember_state: begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_remember_state']);
|
|
end;
|
|
DW_CFA_restore_state: begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_restore_state']);
|
|
end;
|
|
DW_CFA_def_cfa: begin
|
|
// ULEB128 register, ULEB128 offset
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_def_cfa R', ULEB128toOrdinal(p), ' + ', ULEB128toOrdinal(p)]);
|
|
end;
|
|
DW_CFA_def_cfa_register: begin
|
|
// ULEB128 register
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_def_cfa_register R', ULEB128toOrdinal(p)]);
|
|
end;
|
|
DW_CFA_def_cfa_offset: begin
|
|
// ULEB128 offset
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_def_cfa_offset ', ULEB128toOrdinal(p)]);
|
|
end;
|
|
// --- DWARF3 ---
|
|
DW_CFA_def_cfa_expression: begin
|
|
// BLOCK
|
|
q := ULEB128toOrdinal(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_def_cfa_expression, lenght=',q]);
|
|
Inc(p, q);
|
|
end;
|
|
DW_CFA_expression: begin
|
|
// ULEB128 register, BLOCK
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_CFA_expression R', ULEB128toOrdinal(p), ' lenght=',q]);
|
|
q := ULEB128toOrdinal(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, [q]);
|
|
Inc(p, q);
|
|
end;
|
|
DW_CFA_offset_extended_sf: begin
|
|
// ULEB128 register, SLEB128 offset
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_offset_extended_sf R', ULEB128toOrdinal(p), ' + ', SLEB128toOrdinal(p), ' * daf']);
|
|
end;
|
|
DW_CFA_def_cfa_sf: begin
|
|
// ULEB128 register, SLEB128 offset
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_def_cfa_sf R', ULEB128toOrdinal(p), ' + ', SLEB128toOrdinal(p), ' * daf']);
|
|
end;
|
|
DW_CFA_def_cfa_offset_sf: begin
|
|
// SLEB128 offset
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_def_cfa_offset_sf ', SLEB128toOrdinal(p), ' * daf' ]);
|
|
end;
|
|
DW_CFA_val_offset: begin
|
|
// ULEB128 , ULEB128
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_val_offset R', ULEB128toOrdinal(p), ' + ', ULEB128toOrdinal(p), ' * daf']);
|
|
end;
|
|
DW_CFA_val_offset_sf: begin
|
|
// ULEB128 , SLEB128
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_val_offset_sf R', ULEB128toOrdinal(p), ' + ', SLEB128toOrdinal(p), ' * daf']);
|
|
end;
|
|
DW_CFA_val_expression: begin
|
|
// ULEB128 , BLOCK
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['DW_CFA_val_expression R', ULEB128toOrdinal(p), ' lenght=',q]);
|
|
q := ULEB128toOrdinal(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, [q]);
|
|
Inc(p, q);
|
|
end;
|
|
// --- ---
|
|
DW_CFA_lo_user..DW_CFA_hi_user: begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_user=', pb^]);
|
|
end;
|
|
// --- ---
|
|
DW_CFA_advance_loc..DW_CFA_offset-1: begin
|
|
// delta
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_advance_loc ', pb[-1] and $3F, ' * caf']);
|
|
end;
|
|
DW_CFA_offset..DW_CFA_restore-1: begin
|
|
// register ULEB128 offset
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_offset R', pb[-1] and $3F, ' + ', ULEB128toOrdinal(p),' * caf']);
|
|
end;
|
|
DW_CFA_restore..$FF: begin
|
|
// register
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['DW_CFA_restore R', pb[-1] and $3F]);
|
|
end;
|
|
else
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['Undefined $', IntToHex(pb[-1], 2)]);
|
|
end;
|
|
until p >= MaxAddr;
|
|
end;
|
|
|
|
var
|
|
p, next: Pointer;
|
|
pb: PByte absolute p;
|
|
pi: PInteger absolute p;
|
|
pc: PCardinal absolute p;
|
|
pq: PQWord absolute p;
|
|
|
|
len: QWord;
|
|
version: Byte;
|
|
IsCie: Boolean;
|
|
|
|
s: String;
|
|
begin
|
|
p := AData;
|
|
while p < Adata + ASize do
|
|
begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['[', {%H-}PtrUInt(p) - {%H-}PtrUInt(AData), ']']);
|
|
|
|
Is64bit := pi^ = -1;
|
|
if Is64bit
|
|
then begin
|
|
Inc(pi);
|
|
len := pq^;
|
|
Inc(pq);
|
|
IsCie := Int64(pq^) = -1;
|
|
end
|
|
else begin
|
|
len := pc^;
|
|
Inc(pc);
|
|
IsCie := pi^ = -1;
|
|
end;
|
|
next := p + len;
|
|
|
|
if IsCie
|
|
then DebugLn(FPDBG_DWARF_VERBOSE, ['=== CIE ==='])
|
|
else DebugLn(FPDBG_DWARF_VERBOSE, ['--- FDE ---']);
|
|
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['Length: ', len]);
|
|
|
|
if IsCie
|
|
then begin
|
|
Inc(pi);
|
|
version := pb^;
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['Version: ', version]);
|
|
Inc(pb);
|
|
S := Pchar(p);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['Augmentation: ', S]);
|
|
Inc(p, Length(s) + 1);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['Code alignment factor (caf): ', ULEB128toOrdinal(p)]);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['Data alignment factor (daf): ', SLEB128toOrdinal(p)]);
|
|
DbgOut(FPDBG_DWARF_VERBOSE, ['Return addr: R']);
|
|
if version <= 2
|
|
then begin
|
|
DebugLn(FPDBG_DWARF_VERBOSE, [pb^]);
|
|
Inc(pb);
|
|
end
|
|
else DebugLn(FPDBG_DWARF_VERBOSE, [ULEB128toOrdinal(p)]);
|
|
end
|
|
else begin
|
|
if pc^ > ASize
|
|
then DebugLn(FPDBG_DWARF_VERBOSE, ['CIE: $', IntToHex(pc^, 8), ' (=address ?) -> offset: ', pc^ - AStart - FLoader.ImageBase])
|
|
else DebugLn(FPDBG_DWARF_VERBOSE, ['CIE: ', pc^]);
|
|
Inc(pc);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['InitialLocation: $', IntToHex(pc^, 8)]);
|
|
Inc(pc);
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['Address range: ', pc^]);
|
|
Inc(pc);
|
|
end;
|
|
DebugLn(FPDBG_DWARF_VERBOSE, ['Instructions:']);
|
|
DecodeInstructions(p, next);
|
|
|
|
p := next;
|
|
end;
|
|
end;
|
|
|
|
initialization
|
|
FPDBG_DWARF_VERBOSE := DebugLogger.FindOrRegisterLogGroup('FPDBG_DWARF_VERBOSE' {$IFDEF FPDBG_DWARF_VERBOSE} , True {$ENDIF} );
|
|
FPDBG_DWARF_WARNINGS := DebugLogger.FindOrRegisterLogGroup('FPDBG_DWARF_WARNINGS' {$IFDEF FPDBG_DWARF_WARNINGS} , True {$ENDIF} );
|
|
end.
|
|
|