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

Last change on this file since 21302 was 21302, checked in by ydario, 16 years ago

Kernel32 updates.

File size: 13.0 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, CHAR *Info, ULONG cbInfo)
74{
75 static FILE *SymFile;
76 static MAPDEF MapDef;
77 static SEGDEF SegDef;
78 static SEGDEF *pSegDef;
79 static SYMDEF32 SymDef32;
80 static SYMDEF16 SymDef16;
81 static char Buffer[256];
82 static int SegNum, SymNum, LastVal;
83 static unsigned long int SegOffset,
84 SymOffset, SymPtrOffset;
85 int rc = FALSE;
86
87 // open .SYM file
88 SymFile = fopen(SymFileName, "rb");
89 if (SymFile == 0)
90 {
91// dprintf(("Could not open symbol file %s", SymFileName));
92 goto endofprintsym;
93 } // endif
94
95 // read in first map definition
96 fread(&MapDef, sizeof(MAPDEF), 1, SymFile);
97
98 SegOffset = SEGDEFOFFSET(MapDef);
99
100 // go thru all segments
101 for (SegNum = 0; SegNum < MapDef.cSegs; SegNum++)
102 {
103 // printf("Scanning segment #%d Offset %4.4hX",SegNum+1,SegOffset);
104 if (fseek(SymFile, SegOffset, SEEK_SET))
105 {
106// dprintf(("Seek error."));
107 goto endofprintsym;
108 }
109
110 // read in segment definition
111 fread(&SegDef, sizeof(SEGDEF), 1, SymFile);
112 if (SegNum == Object)
113 {
114 // stack object found:
115 Buffer[0] = 0x00;
116 LastVal = 0;
117
118#ifdef FIX64KLIMIT
119 // Custom build dll's SYM file is much greater than 64K.
120 // SYM file structures use 16 bit offsets in the file and
121 // therefore these offsets can't be directly used as they
122 // are overflowed.
123 // Some offsets like segment definition offsets are
124 // paragraph (*16) ones and will overflow for an 1 meg file.
125 // In particular this affects SYMbol searching algorithm
126 // used here.
127 // With the #ifdef it will be changed to so we will
128 // extract symbol by symbol from the file instead of using
129 // symbol table that is far further 64K fence.
130
131 // Offset of first symbol
132 SymOffset = sizeof (SEGDEF) - 1 + SegDef.cbSegName;
133#endif
134
135 // go thru all symbols in this object
136 for (SymNum = 0; SymNum < SegDef.cSymbols; SymNum++)
137 {
138#ifndef FIX64KLIMIT
139 // read in symbol offset USHORT
140 SymPtrOffset = SYMDEFOFFSET(SegOffset, SegDef, SymNum);
141 fseek(SymFile, SymPtrOffset, SEEK_SET);
142 fread(&SymOffset, sizeof(unsigned short int), 1, SymFile);
143#endif
144
145 // go to symbol definition
146 fseek(SymFile, SymOffset + SegOffset, SEEK_SET);
147
148 if (SegDef.bFlags & 0x01)
149 {
150 // 32-bit symbol:
151 fread(&SymDef32, sizeof(SYMDEF32), 1, SymFile);
152#if 0
153 if (SymDef32.wSymVal == TrapOffset)
154 {
155 Buffer[0] = SymDef32.achSymName[0];
156 fread(&Buffer[1], 1, SymDef32.cbSymName, SymFile);
157 Buffer[SymDef32.cbSymName] = 0x00;
158// dprintf(("%s\n", Buffer));
159 strcpy (Info, Buffer);
160 rc = TRUE;
161 break;
162 }
163#endif
164 //SvL: If it's an exact match, then the app put a procedure
165 // address on the stack; ignore that
166 if (LastVal == TrapOffset) {
167 break;
168 }
169 if (SymDef32.wSymVal > TrapOffset)
170 {
171 // symbol found
172#ifdef RAS
173 snprintf(Info, cbInfo, "between %s + 0x%X", Buffer, TrapOffset - LastVal);
174#else
175 sprintf(Info, "between %s + 0x%X", Buffer, TrapOffset - LastVal);
176#endif
177 }
178 LastVal = SymDef32.wSymVal;
179 Buffer[0] = SymDef32.achSymName[0];
180 fread(&Buffer[1], 1, SymDef32.cbSymName, SymFile);
181 Buffer[SymDef32.cbSymName] = 0x00;
182
183 if (SymDef32.wSymVal > TrapOffset)
184 {
185 // symbol found, as above
186#ifdef RAS
187 snprintf(&Info[strlen(Info)], cbInfo - strlen(Info), " and %s - 0x%X\n", Buffer, LastVal - TrapOffset);
188#else
189 sprintf(&Info[strlen(Info)], " and %s - 0x%X\n", Buffer, LastVal - TrapOffset);
190#endif
191 rc = TRUE;
192 break;
193 }
194 /*printf("32 Bit Symbol <%s> Address %p",Buffer,SymDef32.wSymVal); */
195#ifdef FIX64KLIMIT
196 SymOffset += sizeof (SYMDEF32) + SymDef32.cbSymName - 1;
197#endif
198 }
199 else
200 {
201 // 16-bit symbol:
202 fread(&SymDef16, sizeof(SYMDEF16), 1, SymFile);
203
204 //SvL: If it's an exact match, then the app put a procedure
205 // address on the stack; ignore that
206 if (LastVal == TrapOffset) {
207 break;
208 }
209
210 if (SymDef16.wSymVal > TrapOffset)
211 {
212#ifdef RAS
213 snprintf(Info, cbInfo, "between %s + 0x%X", Buffer, TrapOffset - LastVal);
214#else
215 sprintf(Info, "between %s + 0x%X", Buffer, TrapOffset - LastVal);
216#endif
217 }
218 LastVal = SymDef16.wSymVal;
219 Buffer[0] = SymDef16.achSymName[0];
220 fread(&Buffer[1], 1, SymDef16.cbSymName, SymFile);
221 Buffer[SymDef16.cbSymName] = 0x00;
222 if (SymDef16.wSymVal > TrapOffset)
223 {
224#ifdef RAS
225 snprintf(&Info[strlen(Info)], cbInfo - strlen(Info), " and %s - 0x%X\n", Buffer, LastVal - TrapOffset);
226#else
227 sprintf(&Info[strlen(Info)], " and %s - 0x%X\n", Buffer, LastVal - TrapOffset);
228#endif
229 rc = TRUE;
230 break;
231 }
232 /*printf("16 Bit Symbol <%s> Address %p",Buffer,SymDef16.wSymVal); */
233#ifdef FIX64KLIMIT
234 SymOffset += sizeof (SYMDEF16) + SymDef16.cbSymName - 1;
235#endif
236 } // endif
237 }
238#ifdef FIX64KLIMIT
239 if (SymNum < SegDef.cSymbols)
240 {
241#endif
242 break;
243#ifdef FIX64KLIMIT
244 }
245#endif
246 } // endif
247 SegOffset = NEXTSEGDEFOFFSET(SegDef);
248 } // endwhile
249endofprintsym:
250 if(SymFile) fclose(SymFile);
251// if(rc == FALSE) dprintf(("\n"));
252 if(rc == FALSE) strcpy (Info, "\n");
253 return rc;
254}
255BOOL dbgPrintSYMInfo(CHAR * SymFileName, ULONG Object, ULONG TrapOffset)
256{
257 static char szInfo[256];
258 BOOL rc = dbgGetSYMInfo (SymFileName, Object, TrapOffset, szInfo, sizeof (szInfo));
259 dprintf(("%s", szInfo));
260 return rc;
261}
262//******************************************************************************
263//******************************************************************************
264void dbgPrintStack(PEXCEPTIONREPORTRECORD pERepRec,
265 PEXCEPTIONREGISTRATIONRECORD pERegRec,
266 PCONTEXTRECORD pCtxRec,
267 PVOID p)
268{
269 ULONG Size, Attr, hMod, ObjNum, Offset, addr;
270 APIRET rc;
271 PTIB ptib = NULL;
272 PPIB ppib = NULL;
273 CHAR Name[CCHMAXPATH] = "unknown";
274 ULONG *stacktop, *stackbase;
275 UCHAR instr;
276 static BOOL fEntered = FALSE;
277
278 if(DosGetInfoBlocks(&ptib, &ppib) || ptib == NULL) {
279 return;
280 }
281 if(fEntered == TRUE) {
282 return;
283 }
284
285 fEntered = TRUE;
286
287 stacktop = (ULONG *)ptib->tib_pstacklimit - 4;
288 stackbase = (ULONG *)ptib->tib_pstack;
289 if(pCtxRec->ctx_RegEsp < (ULONG)stacktop && pCtxRec->ctx_RegEsp > (ULONG)stackbase)
290 {
291 stackbase = (ULONG *)pCtxRec->ctx_RegEsp;
292 }
293 else
294 if(pCtxRec->ctx_RegEbp < (ULONG)stacktop && pCtxRec->ctx_RegEbp > (ULONG)stackbase)
295 {
296 stackbase = (ULONG *)pCtxRec->ctx_RegEbp;
297 }
298 else stackbase = (ULONG *)getESP();
299
300 dprintf(("** BEGIN STACK DUMP **\n"));
301 while(stacktop > stackbase)
302 {
303 Size = 10;
304 rc = DosQueryMem((PVOID) (stacktop), &Size, &Attr);
305 if(rc != NO_ERROR || !(Attr & PAG_COMMIT) || (Size < 4))
306 {
307 break;
308 }
309
310 addr = *stacktop;
311 Size = 16;
312 rc = DosQueryMem((PVOID) (*stacktop-16), &Size, &Attr);
313 if(rc != NO_ERROR || ((Attr & (PAG_EXECUTE|PAG_READ|PAG_COMMIT)) != (PAG_EXECUTE|PAG_READ|PAG_COMMIT)) || (Size < 16)) {
314// dprintf(("skiploop %x (rc %x, Attr %x Size %d)\n", *stacktop, rc, Attr, Size));
315 if(WinExe && WinExe->insideModule(addr) && WinExe->insideModuleCode(addr)) {
316 sprintf(Name, "%s", WinExe->getModuleName());
317 dprintf(("%-13s at 0x%08x\n", Name, addr));
318 }
319 else {
320 Win32DllBase *dll = Win32DllBase::findModuleByAddr(addr);
321 if(dll && dll->insideModuleCode(addr)) {
322 sprintf(Name, "%s", dll->getModuleName());
323 dprintf(("%-13s at 0x%08x\n", Name, addr));
324 }
325 }
326
327 goto skiploop;
328 }
329#if 0
330 instr = *(UCHAR *)(((ULONG)*stacktop) - 5);
331 if(instr == 0xE8) {//call with displacement
332 addr = *(ULONG *)(((ULONG)*stacktop)-4);
333 addr+= (((ULONG)*stacktop)-5);
334 }
335// else {
336// if(*(UCHAR *)(((ULONG)*stacktop) - 6) == 0xff) {
337// modrm = *(UCHAR *)(((ULONG)*stacktop) - 5);
338// }
339 else
340#endif
341 addr = *stacktop;
342
343 rc = DosQueryModFromEIP(&hMod, &ObjNum, sizeof(Name),
344 Name, &Offset, addr);
345 if(rc == NO_ERROR && ObjNum != -1)
346 {
347 DosQueryModuleName(hMod, sizeof(Name), Name);
348
349 int namelen = strlen(Name);
350 if(namelen > 3)
351 {
352 if(addr > (ULONG)ptib->tib_pstacklimit || addr < (ULONG)ptib->tib_pstack) {
353 // print module and object
354 dprintf(("%-13s %04X at 0x%08x ", OSLibStripPath(Name), ObjNum + 1, addr));
355
356 strcpy(Name + namelen - 3, "SYM");
357 dbgPrintSYMInfo(Name, ObjNum, Offset);
358 }
359 }
360 else
361 {
362 dprintf(("*Unknown* at %x\n", addr));
363 }
364 }
365 else {
366 if(WinExe && WinExe->insideModule(addr) && WinExe->insideModuleCode(addr)) {
367 sprintf(Name, "%s", WinExe->getModuleName());
368 dprintf(("%-13s at 0x%08x\n", Name, addr));
369 }
370 else {
371 Win32DllBase *dll = Win32DllBase::findModuleByAddr(addr);
372 if(dll && dll->insideModuleCode(addr)) {
373 sprintf(Name, "%s", dll->getModuleName());
374 dprintf(("%-13s at 0x%08x\n", Name, addr));
375 }
376 }
377// dprintf(("unknown %x at 0x%x\n", stacktop, addr));
378 }
379skiploop:
380 stacktop -= 1;
381 } //while
382
383 addr = pCtxRec->ctx_RegEip;
384 if(WinExe && WinExe->insideModule(addr) && WinExe->insideModuleCode(addr)) {
385 sprintf(Name, "%s", WinExe->getModuleName());
386 dprintf(("%-13s at 0x%08x\n", Name, addr));
387 }
388 else {
389 Win32DllBase *dll = Win32DllBase::findModuleByAddr(addr);
390 if(dll && dll->insideModuleCode(addr)) {
391 sprintf(Name, "%s", dll->getModuleName());
392 dprintf(("%-13s at 0x%08x\n", Name, addr));
393 }
394 }
395
396 dprintf(("** END OF STACK DUMP **\n"));
397 fEntered = FALSE;
398}
399//******************************************************************************
400//******************************************************************************
Note: See TracBrowser for help on using the repository browser.