source: ExceptionLogger/UStackTrace.pas

Last change on this file was 264, checked in by george, 13 years ago
  • Modified: Now detailed info is displayed after user click Details. User will see at first only necessary error message.
  • Modified: Now methods in TStackTrace class loads call stack and exception stack only as list of frame address. Then delayed GetInfo method should be called to fully load call stack debug information. This is useful in case of external debug file where loading time could be significant.
File size: 2.7 KB
Line 
1unit UStackTrace;
2
3{$mode objfpc}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, Contnrs, CustomLineInfo;
9
10type
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 Frames: array of Pointer;
25 MaxDepth: Integer;
26 procedure GetExceptionBackTrace;
27 procedure GetCallStack(BP: Pointer);
28 procedure GetCurrentCallStack;
29 procedure GetInfo;
30 constructor Create;
31 end;
32
33
34implementation
35
36procedure TStackFrameInfo.GetFrameInfo(Addr: Pointer);
37var
38 Func: shortstring;
39 SourceStr: shortstring;
40 Line: LongInt;
41 Store: TBackTraceStrFunc;
42 Success: Boolean;
43begin
44 // Reset to prevent infinite recursion if problems inside the code PM
45 Store := BackTraceStrFunc;
46 BackTraceStrFunc := @SysBackTraceStr;
47 Success := GetLineInfo(ptruint(Addr), Func, SourceStr, Line);
48 Address := Integer(Addr);
49 FunctionName := Func;
50 if Pos('__', FunctionName) > 0 then begin
51 FunctionClassName := Copy(FunctionName, 1, Pos('__', FunctionName) - 1);
52 Delete(FunctionName, 1, Length(FunctionClassName) + 2);
53 end else FunctionClassName := '';
54 LineNumber := Line;
55 Source := SourceStr;
56 BackTraceStrFunc := Store;
57end;
58
59procedure TStackTrace.GetCallStack(BP: Pointer);
60var
61 I: Longint;
62 prevbp: Pointer;
63 CallerFrame: Pointer;
64 CallerAddress: Pointer;
65 StackFrameInfo: TStackFrameInfo;
66begin
67 Clear;
68 try
69 I := 0;
70 SetLength(Frames, 0);
71 while (BP <> nil) and (I < MaxDepth) do begin
72 SetLength(Frames, Length(Frames) + 1);
73 Frames[I] := TStackFrameInfo(get_caller_addr(BP));
74 Inc(I);
75 BP := TStackFrameInfo(get_caller_frame(BP));
76 end;
77 except
78 { prevent endless dump if an exception occured }
79 end;
80end;
81
82constructor TStackTrace.Create;
83begin
84 inherited;
85 MaxDepth := 20;
86end;
87
88procedure TStackTrace.GetExceptionBackTrace;
89var
90 FrameCount: Integer;
91 FramesList: PPointer;
92 FrameNumber: Integer;
93begin
94 SetLength(Frames, 1);
95 Frames[0] := ExceptAddr;
96 FrameCount := ExceptFrameCount;
97 FramesList := ExceptFrames;
98 if FrameCount > MaxDepth then FrameCount := MaxDepth;
99 SetLength(Frames, FrameCount + 1);
100 for FrameNumber := 0 to FrameCount - 1 do begin
101 Frames[FrameNumber + 1] := FramesList[FrameNumber]
102 end;
103end;
104
105procedure TStackTrace.GetCurrentCallStack;
106begin
107 GetCallStack(get_frame);
108end;
109
110procedure TStackTrace.GetInfo;
111var
112 I: Integer;
113 StackFrameInfo: TStackFrameInfo;
114begin
115 Clear;
116 for I := 0 to High(Frames) do begin
117 StackFrameInfo := TStackFrameInfo.Create;
118 StackFrameInfo.GetFrameInfo(Frames[I]);
119 StackFrameInfo.Index := I + 1;
120 Add(StackFrameInfo);
121 end;
122end;
123
124end.
125
Note: See TracBrowser for help on using the repository browser.