source: LogExceptions/UMapFile.pas

Last change on this file was 2, checked in by george, 15 years ago
  • Přidáno: Prvotní načtení tříd.
File size: 6.0 KB
Line 
1unit UMapFile;
2
3interface
4
5uses
6 SysUtils, Classes, Windows, Dialogs;
7
8type
9 TMapFile = class
10 private
11 FMapFileName: String;
12 FSegmentData, FAdressData, FLineData: TStringList;
13 FMapFileBase: DWORD;
14 FExceptAddress: DWORD;
15 FExceptLineNumber: Integer;
16 FExceptMethodName: String;
17 FExceptUnitName: String;
18 FExceptionAnalyzed: Boolean;
19 procedure SetMapFileName(const Value: String);
20 procedure LoadMapFile;
21 protected
22 public
23 constructor Create;
24 destructor Destroy; override;
25
26 procedure LoadExceptionData(Address: Pointer = nil);
27
28 property MapFileName: String read FMapFileName write SetMapFileName;
29 property MapFileBase: DWORD read FMapFileBase write FMapFileBase;
30 property ExceptUnitName: String read FExceptUnitName;
31 property ExceptMethodName: String read FExceptMethodName;
32 property ExceptLineNumber: Integer read FExceptLineNumber;
33 property ExceptAddress: DWORD read FExceptAddress;
34 property ExceptionAnalyzed: Boolean read FExceptionAnalyzed;
35 end;
36
37implementation
38
39{ TMapFile }
40
41constructor TMapFile.Create;
42begin
43 inherited Create;
44 FSegmentData := TStringList.Create;
45 FAdressData := TStringList.Create;
46 FLineData := TStringList.Create;
47 FMapFileName := '';
48 FMapFileBase := $00401000;
49 FExceptAddress := 0;
50 FExceptLineNumber := 0;
51 FExceptMethodName := '';
52 FExceptUnitName := '';
53 FExceptionAnalyzed := False;
54end;
55
56destructor TMapFile.Destroy;
57begin
58 FreeAndNil(FSegmentData);
59 FreeAndNil(FAdressData);
60 FreeAndNil(FLineData);
61 inherited Destroy;
62end;
63
64procedure TMapFile.LoadExceptionData(Address: Pointer);
65var
66 UnitLineDataFound: Boolean;
67 I, J, LastLine: Integer;
68 Start, Stop, ProcAddr, LineAddr: DWORD;
69 Line: String;
70begin
71 // reset
72 FExceptAddress := 0;
73 FExceptLineNumber := 0;
74 FExceptMethodName := '';
75 FExceptUnitName := '';
76 FExceptionAnalyzed := False;
77
78 // load address
79 if Address = nil then
80 Address := ExceptAddr;
81 if Address = nil then
82 Exit;
83
84 // load and adjust exception address
85 FExceptAddress := DWORD(Address) - FMapFileBase;
86
87 // find unit of exception
88 I := 0;
89 while (I < FSegmentData.Count) and (FSegmentData[I] <> '') do
90 begin
91 try
92 // check whether address is within unit address limits
93 Start := DWORD(StrToInt('0x' + Copy(FSegmentData[I], 7, 8)));
94 Stop := Start + DWORD(StrToInt('0x' + Copy(FSegmentData[I], 16, 8)));
95 if (Start <= FExceptAddress) and (FExceptAddress < Stop) then
96 begin
97 Start := Pos('M=', FSegmentData[I]) + 2;
98 Stop := Pos('ACBP=', FSegmentData[I]);
99 if (Start > 0) and (Stop > 0) then
100 FExceptUnitName :=
101 Trim(Copy(FSegmentData[I], Start, Stop - Start - 1));
102 end;
103 except
104 end;
105 Inc(I);
106 end;
107
108 // find function of exception
109 I := 0;
110 while I < FAdressData.Count do
111 begin
112 try
113 ProcAddr := DWORD(StrToInt('0x' + Copy(FAdressData[I], 7, 8)));
114 if ProcAddr >= FExceptAddress then
115 begin
116 if ProcAddr = FExceptAddress then
117 Line := FAdressData[I]
118 else
119 Line := FAdressData[Pred(I)];
120 FExceptMethodName := Trim(Copy(Line, 22, Length(Line)));
121 Break;
122 end;
123 except
124 end;
125 Inc(I);
126 end;
127
128 // find line number of exception
129 I := 0;
130 UnitLineDataFound := False;
131 // search for unit section
132 while I < FLineData.Count do
133 begin
134 if Pos(FExceptUnitName, FLineData[I]) <> 0 then
135 begin
136 UnitLineDataFound := True;
137 Break;
138 end;
139 Inc(I);
140 end;
141 if UnitLineDataFound then
142 begin
143 // search for line number
144 LastLine := 0;
145 LineAddr := 0;
146 Inc(I, 2);
147 while I < FLineData.Count do
148 begin
149 //ShowMessage(FLineData[I]);
150 if Pos('Line numbers for', FLineData[I]) <> 0 then
151 Break;
152 if FLineData[I] <> '' then
153 try
154 for J := 0 to 3 do
155 begin
156 LineAddr := StrToInt('0x' + Copy(FLineData[I], J * 20 + 13, 8));
157 if LineAddr > FExceptAddress then
158 Break;
159 LastLine := StrToInt(Trim(Copy(FLineData[I], J * 20 + 1, 6)));
160 if LineAddr = FExceptAddress then
161 Break;
162 end;
163 except
164 end;
165 Inc(I);
166 end;
167 if LineAddr >= FExceptAddress then
168 FExceptLineNumber := LastLine;
169 end;
170
171 FExceptionAnalyzed := True;
172end;
173
174procedure TMapFile.LoadMapFile;
175var
176 I: Integer;
177begin
178 FSegmentData.Clear;
179 FAdressData.Clear;
180 FLineData.Clear;
181 if FileExists(FMapFileName) then
182 with TStringList.Create do
183 try
184 LoadFromFile(FMapFileName);
185 // find start of detailed segment block
186 I := 0;
187 while I < Count do
188 if Pos('Detailed map of segments', Strings[I]) <> 0 then
189 Break
190 else
191 Inc(I);
192 Inc(I, 2);
193
194 // copy all lines to segment data, until name-address block starts
195 while I < Count do
196 if Pos('Address Publics by Name', Strings[I]) <> 0 then
197 Break
198 else begin
199 FSegmentData.Add(Strings[I]);
200 Inc(I);
201 end;
202
203 // find start of value-address block
204 while I < Count do
205 if Pos('Address Publics by Value', Strings[I]) <> 0 then
206 Break
207 else
208 Inc(I);
209 Inc(I, 3);
210
211 // copy all lines to address data, until line number block starts
212 while I < Count do
213 if Pos('Line numbers for', Strings[I]) <> 0 then
214 Break
215 else begin
216 FAdressData.Add(Strings[I]);
217 Inc(I);
218 end;
219
220 // copy all remaining lines to line data
221 while I < Count do
222 begin
223 FLineData.Add(Strings[I]);
224 Inc(I);
225 end;
226 finally
227 Free;
228 end;
229end;
230
231procedure TMapFile.SetMapFileName(const Value: String);
232begin
233 if FMapFileName <> Value then
234 begin
235 FMapFileName := Value;
236 LoadMapFile;
237 end;
238end;
239
240end.
Note: See TracBrowser for help on using the repository browser.