source: ExceptionLogger/UStackTrace.pas@ 100

Last change on this file since 100 was 39, checked in by george, 15 years ago
File size: 2.9 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 MaxDepth: Integer;
25 procedure GetExceptionBackTrace;
26 procedure GetCallStack;
27 constructor Create;
28 end;
29
30
31implementation
32
33procedure TStackFrameInfo.GetFrameInfo(Addr: Pointer);
34var
35 Func: shortstring;
36 SourceStr: shortstring;
37 Line: LongInt;
38 Store: TBackTraceStrFunc;
39 Success: Boolean;
40begin
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;
54end;
55
56procedure TStackTrace.GetCallStack;
57var
58 I: Longint;
59 prevbp: Pointer;
60 CallerFrame,
61 CallerAddress,
62 bp: Pointer;
63 StackFrameInfo: TStackFrameInfo;
64begin
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;
93end;
94
95constructor TStackTrace.Create;
96begin
97 inherited;
98 MaxDepth := 20;
99end;
100
101procedure TStackTrace.GetExceptionBackTrace;
102var
103 FrameCount: Integer;
104 Frames: PPointer;
105 FrameNumber: Integer;
106 StackFrameInfo: TStackFrameInfo;
107begin
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;
122end;
123
124
125
126end.
127
Note: See TracBrowser for help on using the repository browser.