source: trunk/src/kernel32/exceptstackdump.cpp@ 21611

Last change on this file since 21611 was 21611, checked in by dmik, 14 years ago

kernel32: Added missing \n to the funciton name when performing a search in .SYM (caused the last character to be eaten in the stack trace).

File size: 14.5 KB
Line 
1/* $Id: exceptstackdump.cpp,v 1.5 2002-05-10 14:55:11 sandervl Exp $ */
2/*
3 * Stack dump code
4 *
5 * Based on XFolder's stack dumping facility:
6 * Copyright (C) 1992-99 Ulrich M”ller,
7 * Kim Rasmussen,
8 * Marc Fiammante,
9 * John Currier,
10 * Anthony Cruise.
11 *
12 */
13
14#define INCL_MISC
15#define INCL_BASE
16#include <os2.h> //No wrappers needed
17#include <stdio.h>
18#include <string.h>
19#include <misc.h>
20#include "exceptstackdump.h"
21#include "exceptutil.h"
22#include "asmutil.h"
23#include "oslibmisc.h"
24#include "winexebase.h"
25#include "windllbase.h"
26
27#include <_ras.h>
28
29#define DBG_LOCALLOG DBG_exceptstackdump
30#include "dbglocal.h"
31
32int SYSTEM EXPORT WriteLogNoEOL(char *tekst, ...);
33
34#define FIX64KLIMIT
35
36#undef dprintf
37#ifdef RAS
38# ifdef DEBUG
39# define dprintf(a) RasLogNoEOL a; if(DbgEnabledKERNEL32[DBG_LOCALLOG] == 1) WriteLogNoEOL a
40# else
41# define dprintf(a) RasLogNoEOL a;
42# endif
43#else
44# ifdef DEBUG
45# define dprintf(a) if(DbgEnabledKERNEL32[DBG_LOCALLOG] == 1) WriteLogNoEOL a
46# else
47# define dprintf(a)
48# endif
49#endif
50
51/* ******************************************************************
52 * *
53 * PART 3: ANALYZE SYMBOL (.SYM) FILE *
54 * *
55 ********************************************************************/
56
57/*
58 *@@ dbgPrintSYMInfo:
59 * this gets called by dbgPrintStack to check if a SYM
60 * file with the same filename exists and try to
61 * get the info from there.
62 *
63 * This gets called for every line of the stack
64 * walk, but only if getting the information from
65 * the debug code failed, e.g. because no debug code
66 * was available.
67 * The file pointer is in the "Source file" column
68 * every time.
69 *
70 * New with V0.84.
71 */
72
73BOOL dbgGetSYMInfo(CHAR * SymFileName, ULONG Object, ULONG TrapOffset,
74 CHAR *Info, ULONG cbInfo, BOOL fExactMatch)
75{
76 FILE *SymFile;
77 MAPDEF MapDef;
78 SEGDEF SegDef;
79 SEGDEF *pSegDef;
80 SYMDEF32 SymDef32;
81 SYMDEF16 SymDef16;
82 char Buffer[256];
83 int SegNum, SymNum, LastVal;
84 unsigned long int SegOffset,
85 SymOffset, SymPtrOffset;
86 int rc = FALSE;
87
88 // open .SYM file
89 SymFile = fopen(SymFileName, "rb");
90 if (SymFile == 0)
91 {
92// dprintf(("Could not open symbol file %s", SymFileName));
93 goto endofprintsym;
94 } // endif
95
96 // read in first map definition
97 fread(&MapDef, sizeof(MAPDEF), 1, SymFile);
98
99 SegOffset = SEGDEFOFFSET(MapDef);
100
101 // go thru all segments
102 for (SegNum = 0; SegNum < MapDef.cSegs; SegNum++)
103 {
104 // printf("Scanning segment #%d Offset %4.4hX",SegNum+1,SegOffset);
105 if (fseek(SymFile, SegOffset, SEEK_SET))
106 {
107// dprintf(("Seek error."));
108 goto endofprintsym;
109 }
110
111 // read in segment definition
112 fread(&SegDef, sizeof(SEGDEF), 1, SymFile);
113 if (SegNum == Object)
114 {
115 // stack object found:
116 Buffer[0] = 0x00;
117 LastVal = 0;
118
119#ifdef FIX64KLIMIT
120 // Custom build dll's SYM file is much greater than 64K.
121 // SYM file structures use 16 bit offsets in the file and
122 // therefore these offsets can't be directly used as they
123 // are overflowed.
124 // Some offsets like segment definition offsets are
125 // paragraph (*16) ones and will overflow for an 1 meg file.
126 // In particular this affects SYMbol searching algorithm
127 // used here.
128 // With the #ifdef it will be changed to so we will
129 // extract symbol by symbol from the file instead of using
130 // symbol table that is far further 64K fence.
131
132 // Offset of first symbol
133 SymOffset = sizeof (SEGDEF) - 1 + SegDef.cbSegName;
134#endif
135
136 // go thru all symbols in this object
137 for (SymNum = 0; SymNum < SegDef.cSymbols; SymNum++)
138 {
139#ifndef FIX64KLIMIT
140 // read in symbol offset USHORT
141 SymPtrOffset = SYMDEFOFFSET(SegOffset, SegDef, SymNum);
142 fseek(SymFile, SymPtrOffset, SEEK_SET);
143 fread(&SymOffset, sizeof(unsigned short int), 1, SymFile);
144#endif
145
146 // go to symbol definition
147 fseek(SymFile, SymOffset + SegOffset, SEEK_SET);
148
149 if (SegDef.bFlags & 0x01)
150 {
151 // 32-bit symbol:
152 fread(&SymDef32, sizeof(SYMDEF32), 1, SymFile);
153
154 if (fExactMatch)
155 {
156 if (SymDef32.wSymVal == TrapOffset)
157 {
158 Buffer[0] = SymDef32.achSymName[0];
159 fread(&Buffer[1], 1, SymDef32.cbSymName - 1, SymFile);
160 Buffer[SymDef32.cbSymName] = 0x00;
161// dprintf(("%s\n", Buffer));
162#ifdef RAS
163 strncpy(Info, Buffer, cbInfo);
164 strncat(Info, "\n", cbInfo);
165#else
166 strcpy (Info, Buffer);
167 strcat(Info, "\n");
168#endif
169 rc = TRUE;
170 break;
171 }
172 }
173 else
174 {
175 //SvL: If it's an exact match, then the app put a procedure
176 // address on the stack; ignore that
177 if (LastVal == TrapOffset) {
178 break;
179 }
180 }
181
182 if (SymDef32.wSymVal > TrapOffset)
183 {
184 // symbol found
185#ifdef RAS
186 snprintf(Info, cbInfo, "between %s + 0x%X", Buffer, TrapOffset - LastVal);
187#else
188 sprintf(Info, "between %s + 0x%X", Buffer, TrapOffset - LastVal);
189#endif
190 }
191 LastVal = SymDef32.wSymVal;
192 Buffer[0] = SymDef32.achSymName[0];
193 fread(&Buffer[1], 1, SymDef32.cbSymName, SymFile);
194 Buffer[SymDef32.cbSymName] = 0x00;
195
196 if (SymDef32.wSymVal > TrapOffset)
197 {
198 // symbol found, as above
199#ifdef RAS
200 snprintf(&Info[strlen(Info)], cbInfo - strlen(Info), " and %s - 0x%X\n", Buffer, LastVal - TrapOffset);
201#else
202 sprintf(&Info[strlen(Info)], " and %s - 0x%X\n", Buffer, LastVal - TrapOffset);
203#endif
204 rc = TRUE;
205 break;
206 }
207 /*printf("32 Bit Symbol <%s> Address %p",Buffer,SymDef32.wSymVal); */
208#ifdef FIX64KLIMIT
209 SymOffset += sizeof (SYMDEF32) + SymDef32.cbSymName - 1;
210#endif
211 }
212 else
213 {
214 // 16-bit symbol:
215 fread(&SymDef16, sizeof(SYMDEF16), 1, SymFile);
216
217 if (fExactMatch)
218 {
219 if (SymDef16.wSymVal == TrapOffset)
220 {
221 Buffer[0] = SymDef16.achSymName[0];
222 fread(&Buffer[1], 1, SymDef16.cbSymName - 1, SymFile);
223 Buffer[SymDef16.cbSymName] = 0x00;
224// dprintf(("%s\n", Buffer));
225#ifdef RAS
226 strncpy(Info, Buffer, cbInfo);
227 strncat(Info, "\n", cbInfo);
228#else
229 strcpy (Info, Buffer);
230 strcat(Info, "\n");
231#endif
232 rc = TRUE;
233 break;
234 }
235 }
236 else
237 {
238 //SvL: If it's an exact match, then the app put a procedure
239 // address on the stack; ignore that
240 if (LastVal == TrapOffset) {
241 break;
242 }
243 }
244
245 if (SymDef16.wSymVal > TrapOffset)
246 {
247#ifdef RAS
248 snprintf(Info, cbInfo, "between %s + 0x%X", Buffer, TrapOffset - LastVal);
249#else
250 sprintf(Info, "between %s + 0x%X", Buffer, TrapOffset - LastVal);
251#endif
252 }
253 LastVal = SymDef16.wSymVal;
254 Buffer[0] = SymDef16.achSymName[0];
255 fread(&Buffer[1], 1, SymDef16.cbSymName, SymFile);
256 Buffer[SymDef16.cbSymName] = 0x00;
257 if (SymDef16.wSymVal > TrapOffset)
258 {
259#ifdef RAS
260 snprintf(&Info[strlen(Info)], cbInfo - strlen(Info), " and %s - 0x%X\n", Buffer, LastVal - TrapOffset);
261#else
262 sprintf(&Info[strlen(Info)], " and %s - 0x%X\n", Buffer, LastVal - TrapOffset);
263#endif
264 rc = TRUE;
265 break;
266 }
267 /*printf("16 Bit Symbol <%s> Address %p",Buffer,SymDef16.wSymVal); */
268#ifdef FIX64KLIMIT
269 SymOffset += sizeof (SYMDEF16) + SymDef16.cbSymName - 1;
270#endif
271 } // endif
272 }
273#ifdef FIX64KLIMIT
274 if (SymNum < SegDef.cSymbols)
275 {
276#endif
277 break;
278#ifdef FIX64KLIMIT
279 }
280#endif
281 } // endif
282 SegOffset = NEXTSEGDEFOFFSET(SegDef);
283 } // endwhile
284endofprintsym:
285 if(SymFile) fclose(SymFile);
286// if(rc == FALSE) dprintf(("\n"));
287 if(rc == FALSE) strcpy (Info, "\n");
288 return rc;
289}
290BOOL dbgPrintSYMInfo(CHAR * SymFileName, ULONG Object, ULONG TrapOffset,
291 BOOL fExactMatch)
292{
293 static char szInfo[256];
294 BOOL rc = dbgGetSYMInfo (SymFileName, Object, TrapOffset,
295 szInfo, sizeof (szInfo), fExactMatch);
296 dprintf(("%s", szInfo));
297 return rc;
298}
299//******************************************************************************
300//******************************************************************************
301void dbgPrintStack(PEXCEPTIONREPORTRECORD pERepRec,
302 PEXCEPTIONREGISTRATIONRECORD pERegRec,
303 PCONTEXTRECORD pCtxRec,
304 PVOID p)
305{
306 ULONG Size, Attr, hMod, ObjNum, Offset, addr;
307 APIRET rc;
308 PTIB ptib = NULL;
309 PPIB ppib = NULL;
310 CHAR Name[CCHMAXPATH] = "unknown";
311 ULONG *stacktop, *stackbase;
312 UCHAR instr;
313 static BOOL fEntered = FALSE;
314
315 if(DosGetInfoBlocks(&ptib, &ppib) || ptib == NULL) {
316 return;
317 }
318 if(fEntered == TRUE) {
319 return;
320 }
321
322 fEntered = TRUE;
323
324 stacktop = (ULONG *)ptib->tib_pstacklimit - 4;
325 stackbase = (ULONG *)ptib->tib_pstack;
326 if(pCtxRec->ctx_RegEsp < (ULONG)stacktop && pCtxRec->ctx_RegEsp > (ULONG)stackbase)
327 {
328 stackbase = (ULONG *)pCtxRec->ctx_RegEsp;
329 }
330 else
331 if(pCtxRec->ctx_RegEbp < (ULONG)stacktop && pCtxRec->ctx_RegEbp > (ULONG)stackbase)
332 {
333 stackbase = (ULONG *)pCtxRec->ctx_RegEbp;
334 }
335 else stackbase = (ULONG *)getESP();
336
337 dprintf(("** BEGIN STACK DUMP **\n"));
338 while(stacktop > stackbase)
339 {
340 Size = 10;
341 rc = DosQueryMem((PVOID) (stacktop), &Size, &Attr);
342 if(rc != NO_ERROR || !(Attr & PAG_COMMIT) || (Size < 4))
343 {
344 break;
345 }
346
347 addr = *stacktop;
348 Size = 16;
349 rc = DosQueryMem((PVOID) (*stacktop-16), &Size, &Attr);
350 if(rc != NO_ERROR || ((Attr & (PAG_EXECUTE|PAG_READ|PAG_COMMIT)) != (PAG_EXECUTE|PAG_READ|PAG_COMMIT)) || (Size < 16)) {
351// dprintf(("skiploop %x (rc %x, Attr %x Size %d)\n", *stacktop, rc, Attr, Size));
352 if(WinExe && WinExe->insideModule(addr) && WinExe->insideModuleCode(addr)) {
353 sprintf(Name, "%s", WinExe->getModuleName());
354 dprintf(("%-13s at 0x%08x\n", Name, addr));
355 }
356 else {
357 Win32DllBase *dll = Win32DllBase::findModuleByAddr(addr);
358 if(dll && dll->insideModuleCode(addr)) {
359 sprintf(Name, "%s", dll->getModuleName());
360 dprintf(("%-13s at 0x%08x\n", Name, addr));
361 }
362 }
363
364 goto skiploop;
365 }
366#if 0
367 instr = *(UCHAR *)(((ULONG)*stacktop) - 5);
368 if(instr == 0xE8) {//call with displacement
369 addr = *(ULONG *)(((ULONG)*stacktop)-4);
370 addr+= (((ULONG)*stacktop)-5);
371 }
372// else {
373// if(*(UCHAR *)(((ULONG)*stacktop) - 6) == 0xff) {
374// modrm = *(UCHAR *)(((ULONG)*stacktop) - 5);
375// }
376 else
377#endif
378 addr = *stacktop;
379
380 rc = DosQueryModFromEIP(&hMod, &ObjNum, sizeof(Name),
381 Name, &Offset, addr);
382 if(rc == NO_ERROR && ObjNum != -1)
383 {
384 DosQueryModuleName(hMod, sizeof(Name), Name);
385
386 int namelen = strlen(Name);
387 if(namelen > 3)
388 {
389 if(addr > (ULONG)ptib->tib_pstacklimit || addr < (ULONG)ptib->tib_pstack) {
390 // print module and object
391 dprintf(("%-13s %04X at 0x%08x ", OSLibStripPath(Name), ObjNum + 1, addr));
392
393 strcpy(Name + namelen - 3, "SYM");
394 dbgPrintSYMInfo(Name, ObjNum, Offset, FALSE);
395 }
396 }
397 else
398 {
399 dprintf(("*Unknown* at %x\n", addr));
400 }
401 }
402 else {
403 if(WinExe && WinExe->insideModule(addr) && WinExe->insideModuleCode(addr)) {
404 sprintf(Name, "%s", WinExe->getModuleName());
405 dprintf(("%-13s at 0x%08x\n", Name, addr));
406 }
407 else {
408 Win32DllBase *dll = Win32DllBase::findModuleByAddr(addr);
409 if(dll && dll->insideModuleCode(addr)) {
410 sprintf(Name, "%s", dll->getModuleName());
411 dprintf(("%-13s at 0x%08x\n", Name, addr));
412 }
413 }
414// dprintf(("unknown %x at 0x%x\n", stacktop, addr));
415 }
416skiploop:
417 stacktop -= 1;
418 } //while
419
420 addr = pCtxRec->ctx_RegEip;
421 if(WinExe && WinExe->insideModule(addr) && WinExe->insideModuleCode(addr)) {
422 sprintf(Name, "%s", WinExe->getModuleName());
423 dprintf(("%-13s at 0x%08x\n", Name, addr));
424 }
425 else {
426 Win32DllBase *dll = Win32DllBase::findModuleByAddr(addr);
427 if(dll && dll->insideModuleCode(addr)) {
428 sprintf(Name, "%s", dll->getModuleName());
429 dprintf(("%-13s at 0x%08x\n", Name, addr));
430 }
431 }
432
433 dprintf(("** END OF STACK DUMP **\n"));
434 fEntered = FALSE;
435}
436//******************************************************************************
437//******************************************************************************
Note: See TracBrowser for help on using the repository browser.