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

Last change on this file since 5120 was 4555, checked in by sandervl, 25 years ago

Use DosLoadModule instead of O32_LoadLibrary; changed log strings in exception dump (.dll/.exe)

File size: 10.6 KB
Line 
1/* $Id: exceptstackdump.cpp,v 1.3 2000-11-05 13:40:45 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 "oslibmisc.h"
23#include "winexebase.h"
24#include "windllbase.h"
25
26#define DBG_LOCALLOG DBG_exceptstackdump
27#include "dbglocal.h"
28
29int SYSTEM EXPORT WriteLogNoEOL(char *tekst, ...);
30
31#undef dprintf
32#define dprintf(a) if(DbgEnabled[DBG_LOCALLOG] == 1) WriteLogNoEOL a
33
34/* ******************************************************************
35 * *
36 * PART 3: ANALYZE SYMBOL (.SYM) FILE *
37 * *
38 ********************************************************************/
39
40/*
41 *@@ dbgPrintSYMInfo:
42 * this gets called by dbgPrintStack to check if a SYM
43 * file with the same filename exists and try to
44 * get the info from there.
45 *
46 * This gets called for every line of the stack
47 * walk, but only if getting the information from
48 * the debug code failed, e.g. because no debug code
49 * was available.
50 * The file pointer is in the "Source file" column
51 * every time.
52 *
53 * New with V0.84.
54 */
55
56BOOL dbgPrintSYMInfo(CHAR * SymFileName, ULONG Object, ULONG TrapOffset)
57{
58 static FILE *SymFile;
59 static MAPDEF MapDef;
60 static SEGDEF SegDef;
61 static SEGDEF *pSegDef;
62 static SYMDEF32 SymDef32;
63 static SYMDEF16 SymDef16;
64 static char Buffer[256];
65 static int SegNum, SymNum, LastVal;
66 static unsigned long int SegOffset,
67 SymOffset, SymPtrOffset;
68 int rc = FALSE;
69
70 // open .SYM file
71 SymFile = fopen(SymFileName, "rb");
72 if (SymFile == 0)
73 {
74// dprintf(("Could not open symbol file %s", SymFileName));
75 goto endofprintsym;
76 } // endif
77
78 // read in first map definition
79 fread(&MapDef, sizeof(MAPDEF), 1, SymFile);
80
81 SegOffset = SEGDEFOFFSET(MapDef);
82
83 // go thru all segments
84 for (SegNum = 0; SegNum < MapDef.cSegs; SegNum++)
85 {
86 // printf("Scanning segment #%d Offset %4.4hX",SegNum+1,SegOffset);
87 if (fseek(SymFile, SegOffset, SEEK_SET))
88 {
89 dprintf(("Seek error."));
90 goto endofprintsym;
91 }
92
93 // read in segment definition
94 fread(&SegDef, sizeof(SEGDEF), 1, SymFile);
95 if (SegNum == Object)
96 {
97 // stack object found:
98 Buffer[0] = 0x00;
99 LastVal = 0;
100
101 // go thru all symbols in this object
102 for (SymNum = 0; SymNum < SegDef.cSymbols; SymNum++)
103 {
104 // read in symbol offset USHORT
105 SymPtrOffset = SYMDEFOFFSET(SegOffset, SegDef, SymNum);
106 fseek(SymFile, SymPtrOffset, SEEK_SET);
107 fread(&SymOffset, sizeof(unsigned short int), 1, SymFile);
108
109 // go to symbol definition
110 fseek(SymFile, SymOffset + SegOffset, SEEK_SET);
111
112 if (SegDef.bFlags & 0x01)
113 {
114 // 32-bit symbol:
115 fread(&SymDef32, sizeof(SYMDEF32), 1, SymFile);
116#if 0
117 if (SymDef32.wSymVal == TrapOffset)
118 {
119 Buffer[0] = SymDef32.achSymName[0];
120 fread(&Buffer[1], 1, SymDef32.cbSymName, SymFile);
121 Buffer[SymDef32.cbSymName] = 0x00;
122 dprintf(("%s\n", Buffer));
123 rc = TRUE;
124 break;
125 }
126#endif
127 //SvL: If it's an exact match, then the app put a procedure
128 // address on the stack; ignore that
129 if (LastVal == TrapOffset) {
130 break;
131 }
132 if (SymDef32.wSymVal > TrapOffset)
133 {
134 // symbol found
135 dprintf(("between %s + 0x%X", Buffer, TrapOffset - LastVal));
136 }
137 LastVal = SymDef32.wSymVal;
138 Buffer[0] = SymDef32.achSymName[0];
139 fread(&Buffer[1], 1, SymDef32.cbSymName, SymFile);
140 Buffer[SymDef32.cbSymName] = 0x00;
141
142 if (SymDef32.wSymVal > TrapOffset)
143 {
144 // symbol found, as above
145 dprintf((" and %s - 0x%X\n", Buffer, LastVal - TrapOffset));
146 rc = TRUE;
147 break;
148 }
149 /*printf("32 Bit Symbol <%s> Address %p",Buffer,SymDef32.wSymVal); */
150 }
151 else
152 {
153 // 16-bit symbol:
154 fread(&SymDef16, sizeof(SYMDEF16), 1, SymFile);
155
156 //SvL: If it's an exact match, then the app put a procedure
157 // address on the stack; ignore that
158 if (LastVal == TrapOffset) {
159 break;
160 }
161
162 if (SymDef16.wSymVal > TrapOffset)
163 {
164 dprintf(("between %s + %X", Buffer, TrapOffset - LastVal));
165 }
166 LastVal = SymDef16.wSymVal;
167 Buffer[0] = SymDef16.achSymName[0];
168 fread(&Buffer[1], 1, SymDef16.cbSymName, SymFile);
169 Buffer[SymDef16.cbSymName] = 0x00;
170 if (SymDef16.wSymVal > TrapOffset)
171 {
172 dprintf((" and %s - %X\n", Buffer, LastVal - TrapOffset));
173 rc = TRUE;
174 break;
175 }
176 /*printf("16 Bit Symbol <%s> Address %p",Buffer,SymDef16.wSymVal); */
177 } // endif
178 }
179 break;
180 } // endif
181 SegOffset = NEXTSEGDEFOFFSET(SegDef);
182 } // endwhile
183endofprintsym:
184 if(SymFile) fclose(SymFile);
185 if(rc == FALSE) dprintf(("\n"));
186 return rc;
187}
188//******************************************************************************
189//******************************************************************************
190void dbgPrintStack(PEXCEPTIONREPORTRECORD pERepRec,
191 PEXCEPTIONREGISTRATIONRECORD pERegRec,
192 PCONTEXTRECORD pCtxRec,
193 PVOID p)
194{
195 ULONG Size, Attr, hMod, ObjNum, Offset, addr;
196 APIRET rc;
197 PTIB ptib = NULL;
198 PPIB ppib = NULL;
199 CHAR Name[CCHMAXPATH] = "unknown";
200 ULONG *stacktop, *stackbase;
201 UCHAR instr;
202 static BOOL fEntered = FALSE;
203
204 if(DosGetInfoBlocks(&ptib, &ppib) || ptib == NULL) {
205 return;
206 }
207 if(fEntered == TRUE) {
208 return;
209 }
210
211 fEntered = TRUE;
212
213 stacktop = (ULONG *)ptib->tib_pstacklimit - 4;
214 stackbase = (ULONG *)ptib->tib_pstack;
215 if(pCtxRec->ctx_RegEsp < (ULONG)stacktop && pCtxRec->ctx_RegEsp > (ULONG)stackbase)
216 {
217 stackbase = (ULONG *)pCtxRec->ctx_RegEsp;
218 }
219 else
220 if(pCtxRec->ctx_RegEbp < (ULONG)stacktop && pCtxRec->ctx_RegEbp > (ULONG)stackbase)
221 {
222 stackbase = (ULONG *)pCtxRec->ctx_RegEbp;
223 }
224 else stackbase = (ULONG *)getESP();
225
226 dprintf(("** BEGIN STACK DUMP **\n"));
227 while(stacktop > stackbase)
228 {
229 Size = 10;
230 rc = DosQueryMem((PVOID) (stacktop), &Size, &Attr);
231 if(rc != NO_ERROR || !(Attr & PAG_COMMIT) || (Size < 4))
232 {
233 break;
234 }
235
236 addr = *stacktop;
237 Size = 16;
238 rc = DosQueryMem((PVOID) (*stacktop-16), &Size, &Attr);
239 if(rc != NO_ERROR || ((Attr & (PAG_EXECUTE|PAG_READ|PAG_COMMIT)) != (PAG_EXECUTE|PAG_READ|PAG_COMMIT)) || (Size < 16)) {
240// dprintf(("skiploop %x (rc %x, Attr %x Size %d)\n", *stacktop, rc, Attr, Size));
241 if(WinExe && WinExe->insideModule(addr) && WinExe->insideModuleCode(addr)) {
242 sprintf(Name, "%s", WinExe->getModuleName());
243 dprintf(("%-13s at 0x%08x\n", Name, addr));
244 }
245 else {
246 Win32DllBase *dll = Win32DllBase::findModuleByAddr(addr);
247 if(dll && dll->insideModuleCode(addr)) {
248 sprintf(Name, "%s", dll->getModuleName());
249 dprintf(("%-13s at 0x%08x\n", Name, addr));
250 }
251 }
252
253 goto skiploop;
254 }
255#if 0
256 instr = *(UCHAR *)(((ULONG)*stacktop) - 5);
257 if(instr == 0xE8) {//call with displacement
258 addr = *(ULONG *)(((ULONG)*stacktop)-4);
259 addr+= (((ULONG)*stacktop)-5);
260 }
261// else {
262// if(*(UCHAR *)(((ULONG)*stacktop) - 6) == 0xff) {
263// modrm = *(UCHAR *)(((ULONG)*stacktop) - 5);
264// }
265 else
266#endif
267 addr = *stacktop;
268
269 rc = DosQueryModFromEIP(&hMod, &ObjNum, sizeof(Name),
270 Name, &Offset, addr);
271 if(rc == NO_ERROR && ObjNum != -1)
272 {
273 DosQueryModuleName(hMod, sizeof(Name), Name);
274
275 int namelen = strlen(Name);
276 if(namelen > 3)
277 {
278 if(addr > (ULONG)ptib->tib_pstacklimit || addr < (ULONG)ptib->tib_pstack) {
279 // print module and object
280 dprintf(("%-13s %04X at 0x%08x ", OSLibStripPath(Name), ObjNum + 1, addr));
281
282 strcpy(Name + namelen - 3, "SYM");
283 dbgPrintSYMInfo(Name, ObjNum, Offset);
284 }
285 }
286 else
287 {
288 dprintf(("*Unknown* at %x\n", addr));
289 }
290 }
291 else {
292 if(WinExe && WinExe->insideModule(addr) && WinExe->insideModuleCode(addr)) {
293 sprintf(Name, "%s", WinExe->getModuleName());
294 dprintf(("%-13s at 0x%08x\n", Name, addr));
295 }
296 else {
297 Win32DllBase *dll = Win32DllBase::findModuleByAddr(addr);
298 if(dll && dll->insideModuleCode(addr)) {
299 sprintf(Name, "%s", dll->getModuleName());
300 dprintf(("%-13s at 0x%08x\n", Name, addr));
301 }
302 }
303// dprintf(("unknown %x at 0x%x\n", stacktop, addr));
304 }
305skiploop:
306 stacktop -= 1;
307 } //while
308
309 addr = pCtxRec->ctx_RegEip;
310 if(WinExe && WinExe->insideModule(addr) && WinExe->insideModuleCode(addr)) {
311 sprintf(Name, "%s", WinExe->getModuleName());
312 dprintf(("%-13s at 0x%08x\n", Name, addr));
313 }
314 else {
315 Win32DllBase *dll = Win32DllBase::findModuleByAddr(addr);
316 if(dll && dll->insideModuleCode(addr)) {
317 sprintf(Name, "%s", dll->getModuleName());
318 dprintf(("%-13s at 0x%08x\n", Name, addr));
319 }
320 }
321
322 dprintf(("** END OF STACK DUMP **\n"));
323 fEntered = FALSE;
324}
325//******************************************************************************
326//******************************************************************************
Note: See TracBrowser for help on using the repository browser.