-
Notifications
You must be signed in to change notification settings - Fork 1
/
debug.pas
126 lines (112 loc) · 3.26 KB
/
debug.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
{$MODE OBJFPC} { -*- delphi -*- }
{$INCLUDE settings.inc}
{$IFNDEF DEBUG} {$FATAL This unit should only be included in debug mode.} {$ENDIF}
unit debug;
interface
const
HeapInfoSize = 16;
type
PHeapInfo = ^THeapInfo;
THeapInfo = String[HeapInfoSize];
procedure HexDump(var Data; const Size, SubSize: Cardinal);
{$IFNDEF OPT}
function SetHeapInfo(S: THeapInfo): THeapInfo;
function SetHeapInfoTruncated(S: AnsiString): THeapInfo; // only adds the end of the string
{$ENDIF}
implementation
uses
{$WARNINGS OFF} // otherwise it warns that we should use -gl instead of "uses lineinfo", but we want visibility into the unit...
{$IFNDEF OPT}
heaptrc,
lineinfo,
{$ENDIF}
{$WARNINGS ON}
sysutils;
procedure HexDump(var Data; const Size, SubSize: Cardinal);
var
Index, LineIndex: Cardinal;
begin
Index := 0;
LineIndex := 0;
while Index < Size do
begin
Write(IntToHex(PByte(Pointer(@Data) + Index)^, 2));
Inc(Index);
Inc(LineIndex);
if ((LineIndex >= 80) or (Index mod SubSize = 0)) then
begin
Writeln();
LineIndex := 0;
end
else
if (LineIndex mod 8 = 0) then
begin
Write(' ');
end;
end;
end;
{$IFNDEF OPT}
var
CurrentHeapInfo: THeapInfo = '';
ReportAllocations: Boolean = False;
function SetHeapInfo(S: THeapInfo): THeapInfo;
begin
Result := CurrentHeapInfo;
CurrentHeapInfo := S;
end;
function SetHeapInfoTruncated(S: AnsiString): THeapInfo;
begin
Result := CurrentHeapInfo;
if (Length(S) > HeapInfoSize) then
CurrentHeapInfo := Copy(S, Length(S)-HeapInfoSize+1, HeapInfoSize)
else
CurrentHeapInfo := S;
end;
procedure HeapInfoFiller(P: Pointer);
var
FunctionName, SourceFile: ShortString;
LineNumber: Longint;
Frame: Pointer;
begin
if (ReportAllocations) then
begin
ReportAllocations := False;
FunctionName := '';
SourceFile := '';
LineNumber := 0;
Frame := Get_Frame;
while (Assigned(Frame) and
{$HINTS OFF} GetLineInfo(PtrUInt(Get_Caller_Addr(Frame)), {$HINTS ON} FunctionName, SourceFile, LineNumber) and
((SourceFile = '') or (SourceFile = 'lib/heaptrc.pp') or (SourceFile = 'lib/debug.pas'))) do
Frame := Get_Caller_Frame(Frame);
if (SourceFile <> '') then
begin
if (FunctionName <> '') then
Writeln('Allocating memory for ', FunctionName, '() in ', SourceFile, ' line ', LineNumber, '; ', CurrentHeapInfo)
else
Writeln('Allocating memory for ', SourceFile, ' line ', LineNumber, '; ', CurrentHeapInfo);
end;
ReportAllocations := True;
end;
Assert(Assigned(P));
PHeapInfo(P)^ := CurrentHeapInfo;
end;
procedure HeapInfoDisplayer(var PText: Text; P: Pointer);
begin
if (PHeapInfo(P)^ <> '') then
begin
Writeln(PText, 'Debug log: ', PHeapInfo(P)^); // http://bugs.freepascal.org/view.php?id=25916
Writeln(PText);
end;
end;
initialization
Assert(SizeOf(THeapInfo) = HeapInfoSize+1);
SetHeapInfo('initialization');
SetHeapExtraInfo(SizeOf(THeapInfo), @HeapInfoFiller, @HeapInfoDisplayer);
//QuickTrace := False; { ridiculously slow }
//ReportAllocations := True; { ridiculously verbose }
//KeepReleased := True;
finalization
SetHeapInfo('finalisation');
{$ENDIF}
end.