1 | unit UStackTrace;
|
---|
2 |
|
---|
3 | {$mode objfpc}{$H+}
|
---|
4 |
|
---|
5 | interface
|
---|
6 |
|
---|
7 | uses
|
---|
8 | Classes, SysUtils, Contnrs, CustomLineInfo;
|
---|
9 |
|
---|
10 | type
|
---|
11 | TStackFrameInfo = class
|
---|
12 | Index: Integer;
|
---|
13 | LineNumber: Integer;
|
---|
14 | Address: Integer;
|
---|
15 | FunctionClassName: string;
|
---|
16 | FunctionName: string;
|
---|
17 | Source: string;
|
---|
18 | procedure GetFrameInfo(Addr: Pointer);
|
---|
19 | end;
|
---|
20 |
|
---|
21 | { TStackTrace }
|
---|
22 |
|
---|
23 | TStackTrace = class(TObjectList)
|
---|
24 | MaxDepth: Integer;
|
---|
25 | procedure GetExceptionBackTrace;
|
---|
26 | procedure GetCallStack;
|
---|
27 | constructor Create;
|
---|
28 | end;
|
---|
29 |
|
---|
30 |
|
---|
31 | implementation
|
---|
32 |
|
---|
33 | procedure TStackFrameInfo.GetFrameInfo(Addr: Pointer);
|
---|
34 | var
|
---|
35 | Func: shortstring;
|
---|
36 | SourceStr: shortstring;
|
---|
37 | Line: LongInt;
|
---|
38 | Store: TBackTraceStrFunc;
|
---|
39 | Success: Boolean;
|
---|
40 | begin
|
---|
41 | // Reset to prevent infinite recursion if problems inside the code PM
|
---|
42 | Store := BackTraceStrFunc;
|
---|
43 | BackTraceStrFunc := @SysBackTraceStr;
|
---|
44 | Success := GetLineInfo(ptruint(Addr), Func, SourceStr, Line);
|
---|
45 | Address := Integer(Addr);
|
---|
46 | FunctionName := Func;
|
---|
47 | if Pos('__', FunctionName) > 0 then begin
|
---|
48 | FunctionClassName := Copy(FunctionName, 1, Pos('__', FunctionName) - 1);
|
---|
49 | Delete(FunctionName, 1, Length(FunctionClassName) + 2);
|
---|
50 | end else FunctionClassName := '';
|
---|
51 | LineNumber := Line;
|
---|
52 | Source := SourceStr;
|
---|
53 | BackTraceStrFunc := Store;
|
---|
54 | end;
|
---|
55 |
|
---|
56 | procedure TStackTrace.GetCallStack;
|
---|
57 | var
|
---|
58 | I: Longint;
|
---|
59 | prevbp: Pointer;
|
---|
60 | CallerFrame,
|
---|
61 | CallerAddress,
|
---|
62 | bp: Pointer;
|
---|
63 | StackFrameInfo: TStackFrameInfo;
|
---|
64 | begin
|
---|
65 | Clear;
|
---|
66 | //routine adapted from fpc source
|
---|
67 |
|
---|
68 | bp := get_frame;
|
---|
69 | //This trick skip SendCallstack item
|
---|
70 | // bp := get_caller_frame(get_frame);
|
---|
71 | try
|
---|
72 | prevbp := bp - 1;
|
---|
73 | I := 0;
|
---|
74 | //is_dev:=do_isdevice(textrec(f).Handle);
|
---|
75 | while bp > prevbp do begin
|
---|
76 | CallerAddress := get_caller_addr(bp);
|
---|
77 | CallerFrame := get_caller_frame(bp);
|
---|
78 | if (CallerAddress = nil) then
|
---|
79 | Break;
|
---|
80 | StackFrameInfo := TStackFrameInfo.Create;
|
---|
81 | StackFrameInfo.GetFrameInfo(CallerAddress);
|
---|
82 | StackFrameInfo.Index := I + 1;
|
---|
83 | Add(StackFrameInfo);
|
---|
84 | Inc(I);
|
---|
85 | if (I >= MaxDepth) or (CallerFrame = nil) then
|
---|
86 | Break;
|
---|
87 | prevbp := bp;
|
---|
88 | bp := CallerFrame;
|
---|
89 | end;
|
---|
90 | except
|
---|
91 | { prevent endless dump if an exception occured }
|
---|
92 | end;
|
---|
93 | end;
|
---|
94 |
|
---|
95 | constructor TStackTrace.Create;
|
---|
96 | begin
|
---|
97 | inherited;
|
---|
98 | MaxDepth := 20;
|
---|
99 | end;
|
---|
100 |
|
---|
101 | procedure TStackTrace.GetExceptionBackTrace;
|
---|
102 | var
|
---|
103 | FrameCount: Integer;
|
---|
104 | Frames: PPointer;
|
---|
105 | FrameNumber: Integer;
|
---|
106 | StackFrameInfo: TStackFrameInfo;
|
---|
107 | begin
|
---|
108 | Clear;
|
---|
109 | StackFrameInfo := TStackFrameInfo.Create;
|
---|
110 | StackFrameInfo.GetFrameInfo(ExceptAddr);
|
---|
111 | StackFrameInfo.Index := 1;
|
---|
112 | Add(StackFrameInfo);
|
---|
113 | FrameCount := ExceptFrameCount;
|
---|
114 | Frames := ExceptFrames;
|
---|
115 | if FrameCount > MaxDepth then FrameCount := MaxDepth;
|
---|
116 | for FrameNumber := 0 to FrameCount - 1 do begin
|
---|
117 | StackFrameInfo := TStackFrameInfo.Create;
|
---|
118 | StackFrameInfo.GetFrameInfo(Frames[FrameNumber]);
|
---|
119 | StackFrameInfo.Index := FrameNumber + 1;
|
---|
120 | Add(StackFrameInfo);
|
---|
121 | end;
|
---|
122 | end;
|
---|
123 |
|
---|
124 |
|
---|
125 |
|
---|
126 | end.
|
---|
127 |
|
---|