1 | /*
|
---|
2 | *@@sourcefile debug.c:
|
---|
3 | * this file contains debugging functions for the
|
---|
4 | * exception handlers in except.c.
|
---|
5 | *
|
---|
6 | * This code is capable of unwinding the stack from
|
---|
7 | * a given address and trying to get function names
|
---|
8 | * and source line numbers, either from the respective
|
---|
9 | * module's debug code (if present) or from a SYM file,
|
---|
10 | * which is searched for in the directory of the module
|
---|
11 | * or in ?:\OS2\PDPSI\PMDF\WARP4.
|
---|
12 | *
|
---|
13 | * This file incorporates code from the following:
|
---|
14 | * -- Marc Fiammante, John Currier, Kim Rasmussen,
|
---|
15 | * Anthony Cruise (EXCEPT3.ZIP package for a generic
|
---|
16 | * exception handling DLL, available at Hobbes).
|
---|
17 | *
|
---|
18 | * Usage: All OS/2 programs.
|
---|
19 | *
|
---|
20 | * Note: Version numbering in this file relates to XWorkplace version
|
---|
21 | * numbering.
|
---|
22 | *
|
---|
23 | *@@changed V0.9.0 [umoeller]: made some declarations C++-compatible
|
---|
24 | *@@changed V0.9.1 (2000-01-30) [umoeller]: greatly cleaned up this file
|
---|
25 | *
|
---|
26 | *@@header "helpers\debug.h"
|
---|
27 | */
|
---|
28 |
|
---|
29 | /*
|
---|
30 | * This file Copyright (C) 1992-99 Ulrich Mller,
|
---|
31 | * Kim Rasmussen,
|
---|
32 | * Marc Fiammante,
|
---|
33 | * John Currier,
|
---|
34 | * Anthony Cruise.
|
---|
35 | * This file is part of the "XWorkplace helpers" source package.
|
---|
36 | * This is free software; you can redistribute it and/or modify
|
---|
37 | * it under the terms of the GNU General Public License as published
|
---|
38 | * by the Free Software Foundation, in version 2 as it comes in the
|
---|
39 | * "COPYING" file of the XWorkplace main distribution.
|
---|
40 | * This program is distributed in the hope that it will be useful,
|
---|
41 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
42 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
43 | * GNU General Public License for more details.
|
---|
44 | */
|
---|
45 |
|
---|
46 | //#define DEBUG_SYMDUMP // enable to dump sym file to log V1.0.0 (2002-08-21) [paperino]
|
---|
47 |
|
---|
48 | #define OS2EMX_PLAIN_CHAR
|
---|
49 | // this is needed for "os2emx.h"; if this is defined,
|
---|
50 | // emx will define PSZ as _signed_ char, otherwise
|
---|
51 | // as unsigned char
|
---|
52 |
|
---|
53 | #define INCL_DOSPROCESS
|
---|
54 | #define INCL_DOSMODULEMGR
|
---|
55 | #define INCL_DOSMISC
|
---|
56 | #define INCL_DOSERRORS
|
---|
57 | #include <os2.h>
|
---|
58 |
|
---|
59 | #include <stdlib.h>
|
---|
60 | #include <stdio.h>
|
---|
61 | #include <string.h>
|
---|
62 |
|
---|
63 | #define DONT_REPLACE_MALLOC
|
---|
64 | #include "setup.h" // code generation and debugging options
|
---|
65 |
|
---|
66 | #include "helpers\debug.h"
|
---|
67 | #include "helpers\dosh.h"
|
---|
68 |
|
---|
69 | #pragma hdrstop
|
---|
70 |
|
---|
71 | #include <fcntl.h>
|
---|
72 | #ifdef __EMX__
|
---|
73 | #include <sys\types.h> // required for sys\stat.h; UM 99-10-22
|
---|
74 | #endif
|
---|
75 | #include <sys\stat.h>
|
---|
76 | #include <share.h>
|
---|
77 | #include <io.h>
|
---|
78 |
|
---|
79 | #ifndef DWORD
|
---|
80 | #define DWORD unsigned long
|
---|
81 | #endif
|
---|
82 | #ifndef WORD
|
---|
83 | #define WORD unsigned short
|
---|
84 | #endif
|
---|
85 |
|
---|
86 | #pragma stack16(512)
|
---|
87 | #define HF_STDERR 2
|
---|
88 |
|
---|
89 | /*
|
---|
90 | *@@category: Helpers\Control program helpers\Exceptions/debugging
|
---|
91 | * See except.c and debug.c.
|
---|
92 | */
|
---|
93 |
|
---|
94 | /* ******************************************************************
|
---|
95 | *
|
---|
96 | * Global variables
|
---|
97 | *
|
---|
98 | ********************************************************************/
|
---|
99 |
|
---|
100 | // this specifies whether we're dealing with 32-bit code;
|
---|
101 | // this gets changed whenever 16-bit count is detected
|
---|
102 | STATIC BOOL f32bit = TRUE;
|
---|
103 |
|
---|
104 | /*
|
---|
105 | * Global variables for Read32PmDebug:
|
---|
106 | *
|
---|
107 | */
|
---|
108 |
|
---|
109 | ULONG func_ofs;
|
---|
110 | ULONG pubfunc_ofs;
|
---|
111 | char func_name[128];
|
---|
112 | ULONG var_ofs = 0;
|
---|
113 |
|
---|
114 | struct {
|
---|
115 | BYTE name[128];
|
---|
116 | ULONG stack_offset;
|
---|
117 | USHORT type_idx;
|
---|
118 | } autovar_def[100];
|
---|
119 |
|
---|
120 | #pragma pack(1)
|
---|
121 |
|
---|
122 | BYTE *type_name[] =
|
---|
123 | {
|
---|
124 | "8 bit signed ",
|
---|
125 | "16 bit signed ",
|
---|
126 | "32 bit signed ",
|
---|
127 | "Unknown (0x83) ",
|
---|
128 | "8 bit unsigned ",
|
---|
129 | "16 bit unsigned ",
|
---|
130 | "32 bit unsigned ",
|
---|
131 | "Unknown (0x87) ",
|
---|
132 | "32 bit real ",
|
---|
133 | "64 bit real ",
|
---|
134 | "80 bit real ",
|
---|
135 | "Unknown (0x8B) ",
|
---|
136 | "64 bit complex ",
|
---|
137 | "128 bit complex ",
|
---|
138 | "160 bit complex ",
|
---|
139 | "Unknown (0x8F) ",
|
---|
140 | "8 bit boolean ",
|
---|
141 | "16 bit boolean ",
|
---|
142 | "32 bit boolean ",
|
---|
143 | "Unknown (0x93) ",
|
---|
144 | "8 bit character ",
|
---|
145 | "16 bit characters ",
|
---|
146 | "32 bit characters ",
|
---|
147 | "void ",
|
---|
148 | "15 bit unsigned ",
|
---|
149 | "24 bit unsigned ",
|
---|
150 | "31 bit unsigned ",
|
---|
151 | "Unknown (0x9B) ",
|
---|
152 | "Unknown (0x9C) ",
|
---|
153 | "Unknown (0x9D) ",
|
---|
154 | "Unknown (0x9E) ",
|
---|
155 | "Unknown (0x9F) ",
|
---|
156 | "near pointer to 8 bit signed ",
|
---|
157 | "near pointer to 16 bit signed ",
|
---|
158 | "near pointer to 32 bit signed ",
|
---|
159 | "Unknown (0xA3) ",
|
---|
160 | "near pointer to 8 bit unsigned ",
|
---|
161 | "near pointer to 16 bit unsigned ",
|
---|
162 | "near pointer to 32 bit unsigned ",
|
---|
163 | "Unknown (0xA7) ",
|
---|
164 | "near pointer to 32 bit real ",
|
---|
165 | "near pointer to 64 bit real ",
|
---|
166 | "near pointer to 80 bit real ",
|
---|
167 | "Unknown (0xAB) ",
|
---|
168 | "near pointer to 64 bit complex ",
|
---|
169 | "near pointer to 128 bit complex ",
|
---|
170 | "near pointer to 160 bit complex ",
|
---|
171 | "Unknown (0xAF) ",
|
---|
172 | "near pointer to 8 bit boolean ",
|
---|
173 | "near pointer to 16 bit boolean ",
|
---|
174 | "near pointer to 32 bit boolean ",
|
---|
175 | "Unknown (0xB3) ",
|
---|
176 | "near pointer to 8 bit character ",
|
---|
177 | "near pointer to 16 bit characters",
|
---|
178 | "near pointer to 32 bit characters",
|
---|
179 | "near pointer to void ",
|
---|
180 | "near pointer to 15 bit unsigned ",
|
---|
181 | "near pointer to 24 bit unsigned ",
|
---|
182 | "near pointer to 31 bit unsigned ",
|
---|
183 | "Unknown (0xBB) ",
|
---|
184 | "Unknown (0xBC) ",
|
---|
185 | "Unknown (0xBD) ",
|
---|
186 | "Unknown (0xBE) ",
|
---|
187 | "Unknown (0xBF) ",
|
---|
188 | "far pointer to 8 bit signed ",
|
---|
189 | "far pointer to 16 bit signed ",
|
---|
190 | "far pointer to 32 bit signed ",
|
---|
191 | "Unknown (0xC3) ",
|
---|
192 | "far pointer to 8 bit unsigned ",
|
---|
193 | "far pointer to 16 bit unsigned ",
|
---|
194 | "far pointer to 32 bit unsigned ",
|
---|
195 | "Unknown (0xC7) ",
|
---|
196 | "far pointer to 32 bit real ",
|
---|
197 | "far pointer to 64 bit real ",
|
---|
198 | "far pointer to 80 bit real ",
|
---|
199 | "Unknown (0xCB) ",
|
---|
200 | "far pointer to 64 bit complex ",
|
---|
201 | "far pointer to 128 bit complex ",
|
---|
202 | "far pointer to 160 bit complex ",
|
---|
203 | "Unknown (0xCF) ",
|
---|
204 | "far pointer to 8 bit boolean ",
|
---|
205 | "far pointer to 16 bit boolean ",
|
---|
206 | "far pointer to 32 bit boolean ",
|
---|
207 | "Unknown (0xD3) ",
|
---|
208 | "far pointer to 8 bit character ",
|
---|
209 | "far pointer to 16 bit characters ",
|
---|
210 | "far pointer to 32 bit characters ",
|
---|
211 | "far pointer to void ",
|
---|
212 | "far pointer to 15 bit unsigned ",
|
---|
213 | "far pointer to 24 bit unsigned ",
|
---|
214 | "far pointer to 31 bit unsigned ",
|
---|
215 | };
|
---|
216 |
|
---|
217 | // Thanks to John Currier:
|
---|
218 | // Do not call 16 bit code in myHandler function to prevent call
|
---|
219 | // to __EDCThunkProlog and problems is guard page exception handling
|
---|
220 | // Also reduce the stack size to 1K for true 16 bit calls.
|
---|
221 | // 16 bit calls thunk will now only occur on fatal exceptions
|
---|
222 | #pragma stack16(1024)
|
---|
223 |
|
---|
224 | // ------------------------------------------------------------------
|
---|
225 | // Last 8 bytes of 16:16 file when CODEVIEW debugging info is present
|
---|
226 | #pragma pack(1)
|
---|
227 | struct _eodbug
|
---|
228 | {
|
---|
229 | unsigned short dbug; // 'NB' signature
|
---|
230 | unsigned short ver; // version
|
---|
231 | unsigned long dfaBase; // size of codeview info
|
---|
232 | } G_eodbug;
|
---|
233 |
|
---|
234 | #define DBUGSIG 0x424E
|
---|
235 | #define SSTMODULES 0x0101
|
---|
236 | #define SSTPUBLICS 0x0102
|
---|
237 | #define SSTTYPES 0x0103
|
---|
238 | #define SSTSYMBOLS 0x0104
|
---|
239 | #define SSTSRCLINES 0x0105
|
---|
240 | #define SSTLIBRARIES 0x0106
|
---|
241 | #define SSTSRCLINES2 0x0109
|
---|
242 | #define SSTSRCLINES32 0x010B
|
---|
243 |
|
---|
244 | typedef struct _SYMBASE
|
---|
245 | {
|
---|
246 | unsigned short dbug; // 'NB' signature
|
---|
247 | unsigned short ver; // version
|
---|
248 | unsigned long lfoDir; // file offset to dir entries
|
---|
249 | } SYMBASE;
|
---|
250 |
|
---|
251 | typedef struct _SSDIR
|
---|
252 | {
|
---|
253 | unsigned short sst; // SubSection Type
|
---|
254 | unsigned short modindex; // Module index number
|
---|
255 | unsigned long lfoStart; // Start of section
|
---|
256 | unsigned short cb; // Size of section
|
---|
257 | } SSDIR;
|
---|
258 |
|
---|
259 | typedef struct _SSDIR32
|
---|
260 | {
|
---|
261 | unsigned short sst; // SubSection Type
|
---|
262 | unsigned short modindex; // Module index number
|
---|
263 | unsigned long lfoStart; // Start of section
|
---|
264 | unsigned long cb; // Size of section
|
---|
265 | } SSDIR32;
|
---|
266 |
|
---|
267 | typedef struct _SSMODULE
|
---|
268 | {
|
---|
269 | unsigned short csBase; // code segment base
|
---|
270 | unsigned short csOff; // code segment offset
|
---|
271 | unsigned short csLen; // code segment length
|
---|
272 | unsigned short ovrNum; // overlay number
|
---|
273 | unsigned short indxSS; // Index into sstLib or 0
|
---|
274 | unsigned short reserved;
|
---|
275 | char csize; // size of prefix string
|
---|
276 | } SSMODULE;
|
---|
277 |
|
---|
278 | typedef struct _SSMOD32
|
---|
279 | {
|
---|
280 | unsigned short csBase; // code segment base
|
---|
281 | unsigned long csOff; // code segment offset
|
---|
282 | unsigned long csLen; // code segment length
|
---|
283 | unsigned long ovrNum; // overlay number
|
---|
284 | unsigned short indxSS; // Index into sstLib or 0
|
---|
285 | unsigned long reserved;
|
---|
286 | char csize; // size of prefix string
|
---|
287 | } SSMOD32;
|
---|
288 |
|
---|
289 | typedef struct _SSPUBLIC
|
---|
290 | {
|
---|
291 | unsigned short offset;
|
---|
292 | unsigned short segment;
|
---|
293 | unsigned short type;
|
---|
294 | char csize;
|
---|
295 | } SSPUBLIC;
|
---|
296 |
|
---|
297 | typedef struct _SSPUBLIC32
|
---|
298 | {
|
---|
299 | unsigned long offset;
|
---|
300 | unsigned short segment;
|
---|
301 | unsigned short type;
|
---|
302 | char csize;
|
---|
303 | } SSPUBLIC32;
|
---|
304 |
|
---|
305 | typedef struct _SSLINEENTRY32
|
---|
306 | {
|
---|
307 | unsigned short LineNum;
|
---|
308 | unsigned short FileNum;
|
---|
309 | unsigned long Offset;
|
---|
310 | } SSLINEENTRY32;
|
---|
311 |
|
---|
312 | typedef struct _FIRSTLINEENTRY32
|
---|
313 | {
|
---|
314 | unsigned short LineNum;
|
---|
315 | unsigned char entry_type;
|
---|
316 | unsigned char reserved;
|
---|
317 | unsigned short numlines;
|
---|
318 | unsigned short segnum;
|
---|
319 | } FIRSTLINEENTRY32;
|
---|
320 |
|
---|
321 | typedef struct _SSFILENUM32
|
---|
322 | {
|
---|
323 | unsigned long first_displayable; // Not used
|
---|
324 | unsigned long number_displayable; // Not used
|
---|
325 | unsigned long file_count; // number of source files
|
---|
326 | } SSFILENUM32;
|
---|
327 |
|
---|
328 | /*
|
---|
329 | *@@ XDEBUGINFO:
|
---|
330 | * buffers for Read... funcs.
|
---|
331 | *
|
---|
332 | *@@added V0.9.4 (2000-06-15) [umoeller]
|
---|
333 | */
|
---|
334 |
|
---|
335 | typedef struct _XDEBUGINFO
|
---|
336 | {
|
---|
337 | char szNrFile[300]; // receives source file
|
---|
338 | char szNrLine[300]; // receives line number
|
---|
339 | char szNrPub[300]; // receives function name
|
---|
340 |
|
---|
341 | struct new_seg *pseg;
|
---|
342 | struct o32_obj *pobj; // flat .EXE object table entry
|
---|
343 |
|
---|
344 | SYMBASE base;
|
---|
345 |
|
---|
346 | SSDIR *pDirTab;
|
---|
347 | SSDIR32 *pDirTab32;
|
---|
348 | unsigned char *pEntTab;
|
---|
349 | unsigned long lfaBase;
|
---|
350 | SSMOD32 ssmod32;
|
---|
351 | SSPUBLIC32 sspub32;
|
---|
352 |
|
---|
353 | SSMODULE ssmod;
|
---|
354 | SSPUBLIC sspub;
|
---|
355 | } XDEBUGINFO, *PXDEBUGINFO;
|
---|
356 |
|
---|
357 | #pragma pack()
|
---|
358 |
|
---|
359 | /* ******************************************************************
|
---|
360 | *
|
---|
361 | * PART 1: ANALYZE DEBUG CODE
|
---|
362 | *
|
---|
363 | ********************************************************************/
|
---|
364 |
|
---|
365 | STATIC int Read16CodeView(FILE *LogFile, PXDEBUGINFO pxdi, int fh, int TrapSeg, int TrapOff, CHAR *FileName);
|
---|
366 | STATIC int Read32PmDebug(FILE *LogFile, PXDEBUGINFO pxdi, int fh, int TrapSeg, int TrapOff, CHAR *FileName);
|
---|
367 |
|
---|
368 | /*
|
---|
369 | *@@ WriteAddressInfo:
|
---|
370 | * formats and writes a line into the trap log
|
---|
371 | * file.
|
---|
372 | *
|
---|
373 | * This gets called for each line from the
|
---|
374 | * stack dump. At this point, the line in the
|
---|
375 | * trap log already has:
|
---|
376 | *
|
---|
377 | + CS:EIP : 000109FF XMLVIEW :0
|
---|
378 | + ^^^ and we write here
|
---|
379 | * After this call, we have.
|
---|
380 | *
|
---|
381 | + CS:EIP : 000109FF XMLVIEW :0 xxx.c 123 ConfirmCreate__Fv
|
---|
382 | + ^^^ and we write here
|
---|
383 | *
|
---|
384 | *@@added V0.9.12 (2001-05-12) [umoeller]
|
---|
385 | */
|
---|
386 |
|
---|
387 | STATIC VOID WriteDebugInfo(FILE *LogFile, // in: open log file
|
---|
388 | PXDEBUGINFO pxdi) // in: debug info
|
---|
389 | {
|
---|
390 | fprintf(LogFile,
|
---|
391 | "%s%s%s",
|
---|
392 | pxdi->szNrFile,
|
---|
393 | pxdi->szNrLine,
|
---|
394 | pxdi->szNrPub);
|
---|
395 | }
|
---|
396 |
|
---|
397 | /*
|
---|
398 | *@@ dbgPrintDebugInfo:
|
---|
399 | * this is the main entry point into analyzing debug
|
---|
400 | * code.
|
---|
401 | *
|
---|
402 | * This analyzes a given address and tries to find
|
---|
403 | * debug code descriptions for this address. If found,
|
---|
404 | * the information is written to the given log file.
|
---|
405 | *
|
---|
406 | * Gets called from dbgPrintStack.
|
---|
407 | *
|
---|
408 | * This returns NO_ERROR if the could was successfully
|
---|
409 | * analyzed or something != 0 if we failed.
|
---|
410 | *
|
---|
411 | * New with V0.84.
|
---|
412 | */
|
---|
413 |
|
---|
414 | APIRET dbgPrintDebugInfo(FILE *LogFile, // out: log file to write to
|
---|
415 | CHAR *FileName, // in: EXE/DLL module file name
|
---|
416 | ULONG Object, // in: trapping object (from DosQueryModFromEIP)
|
---|
417 | ULONG TrapOffset) // in: trapping address (from DosQueryModFromEIP)
|
---|
418 | {
|
---|
419 | APIRET rc = 0;
|
---|
420 | int ModuleFile = 0;
|
---|
421 | static struct exe_hdr OldExeHeader;
|
---|
422 | static struct new_exe NewExeHeader;
|
---|
423 |
|
---|
424 | ULONG ulSegment = Object + 1; // segment no. is object no. + 1
|
---|
425 |
|
---|
426 | XDEBUGINFO xdi;
|
---|
427 | memset(&xdi, 0, sizeof(xdi));
|
---|
428 |
|
---|
429 | // open the module file for reading to analyze the code
|
---|
430 | ModuleFile = sopen(FileName, O_RDONLY | O_BINARY, SH_DENYNO);
|
---|
431 |
|
---|
432 | if (ModuleFile != -1)
|
---|
433 | {
|
---|
434 | // file found:
|
---|
435 | // read old Exe header
|
---|
436 | if (read(ModuleFile, (void*)&OldExeHeader, 64) == -1L)
|
---|
437 | {
|
---|
438 | fprintf(LogFile, "errno %d reading old exe header\n", errno);
|
---|
439 | close(ModuleFile);
|
---|
440 | return 2;
|
---|
441 | }
|
---|
442 | // seek to new Exe header
|
---|
443 | if (lseek(ModuleFile, (long)E_LFANEW(OldExeHeader), SEEK_SET) == -1L)
|
---|
444 | {
|
---|
445 | fprintf(LogFile, "errno %d seeking to new exe header\n", errno);
|
---|
446 | close(ModuleFile);
|
---|
447 | return 3;
|
---|
448 | }
|
---|
449 | if (read(ModuleFile, (void *)&NewExeHeader, 64) == -1L)
|
---|
450 | {
|
---|
451 | fprintf(LogFile, "errno %d reading new exe header\n", errno);
|
---|
452 | close(ModuleFile);
|
---|
453 | return 4;
|
---|
454 | }
|
---|
455 |
|
---|
456 | // check EXE signature
|
---|
457 | if (NE_MAGIC(NewExeHeader) == E32MAGIC)
|
---|
458 | {
|
---|
459 | /*
|
---|
460 | * flat 32 executable:
|
---|
461 | *
|
---|
462 | */
|
---|
463 |
|
---|
464 | // do analysis for 32-bit code
|
---|
465 | if (!(rc = Read32PmDebug(LogFile,
|
---|
466 | &xdi, // output
|
---|
467 | ModuleFile,
|
---|
468 | ulSegment,
|
---|
469 | TrapOffset,
|
---|
470 | FileName)))
|
---|
471 | WriteDebugInfo(LogFile, &xdi);
|
---|
472 |
|
---|
473 | close(ModuleFile);
|
---|
474 |
|
---|
475 | // rc !=0 try with DBG file
|
---|
476 | if (rc != 0)
|
---|
477 | {
|
---|
478 | strcpy(FileName + strlen(FileName) - 3, "DBG"); // Build DBG File name
|
---|
479 | ModuleFile = sopen(FileName, O_RDONLY | O_BINARY, SH_DENYNO);
|
---|
480 | if (ModuleFile != -1)
|
---|
481 | {
|
---|
482 | if (!(rc = Read32PmDebug(LogFile,
|
---|
483 | &xdi,
|
---|
484 | ModuleFile,
|
---|
485 | ulSegment,
|
---|
486 | TrapOffset,
|
---|
487 | FileName)))
|
---|
488 | WriteDebugInfo(LogFile, &xdi);
|
---|
489 |
|
---|
490 | close(ModuleFile);
|
---|
491 | }
|
---|
492 | }
|
---|
493 |
|
---|
494 | return rc;
|
---|
495 | }
|
---|
496 | else
|
---|
497 | {
|
---|
498 | if (NE_MAGIC(NewExeHeader) == NEMAGIC)
|
---|
499 | {
|
---|
500 | /*
|
---|
501 | * 16:16 executable:
|
---|
502 | *
|
---|
503 | */
|
---|
504 |
|
---|
505 | if ((xdi.pseg = (struct new_seg *)calloc(NE_CSEG(NewExeHeader),
|
---|
506 | sizeof(struct new_seg)))
|
---|
507 | == NULL)
|
---|
508 | {
|
---|
509 | fprintf(LogFile, "Out of memory!");
|
---|
510 | close(ModuleFile);
|
---|
511 | return -1;
|
---|
512 | }
|
---|
513 | if ( lseek(ModuleFile,
|
---|
514 | E_LFANEW(OldExeHeader) + NE_SEGTAB(NewExeHeader),
|
---|
515 | SEEK_SET) == -1L)
|
---|
516 | {
|
---|
517 | fprintf(LogFile, "Error %u seeking segment table in %s\n", errno, FileName);
|
---|
518 | free(xdi.pseg);
|
---|
519 | close(ModuleFile);
|
---|
520 | return 9;
|
---|
521 | }
|
---|
522 |
|
---|
523 | if (read(ModuleFile,
|
---|
524 | (void *)xdi.pseg,
|
---|
525 | NE_CSEG(NewExeHeader) * sizeof(struct new_seg))
|
---|
526 | == -1)
|
---|
527 | {
|
---|
528 | fprintf(LogFile, "Error %u reading segment table from %s\n", errno, FileName);
|
---|
529 | free(xdi.pseg);
|
---|
530 | close(ModuleFile);
|
---|
531 | return 10;
|
---|
532 | }
|
---|
533 |
|
---|
534 | if (!(rc = Read16CodeView(LogFile,
|
---|
535 | &xdi,
|
---|
536 | ModuleFile,
|
---|
537 | ulSegment,
|
---|
538 | TrapOffset,
|
---|
539 | FileName)))
|
---|
540 | WriteDebugInfo(LogFile, &xdi);
|
---|
541 |
|
---|
542 | free(xdi.pseg);
|
---|
543 | close(ModuleFile);
|
---|
544 |
|
---|
545 | // rc !=0 try with DBG file
|
---|
546 | if (rc != 0)
|
---|
547 | {
|
---|
548 | strcpy(FileName + strlen(FileName) - 3, "DBG"); // Build DBG File name
|
---|
549 | ModuleFile = sopen(FileName,
|
---|
550 | O_RDONLY | O_BINARY, SH_DENYNO);
|
---|
551 | if (ModuleFile != -1)
|
---|
552 | {
|
---|
553 | if (!(rc = Read16CodeView(LogFile,
|
---|
554 | &xdi,
|
---|
555 | ModuleFile,
|
---|
556 | ulSegment,
|
---|
557 | TrapOffset,
|
---|
558 | FileName)))
|
---|
559 | WriteDebugInfo(LogFile, &xdi);
|
---|
560 |
|
---|
561 | close(ModuleFile);
|
---|
562 | }
|
---|
563 | }
|
---|
564 | return rc;
|
---|
565 | }
|
---|
566 | else
|
---|
567 | {
|
---|
568 | /*
|
---|
569 | * Unknown executable:
|
---|
570 | *
|
---|
571 | */
|
---|
572 |
|
---|
573 | fprintf(LogFile, "Error, could not find exe signature");
|
---|
574 | close(ModuleFile);
|
---|
575 | return 11;
|
---|
576 | }
|
---|
577 | }
|
---|
578 | } // end if (ModuleFile != -1)
|
---|
579 | else
|
---|
580 | {
|
---|
581 | fprintf(LogFile, "Error %d opening module file %s", errno, FileName);
|
---|
582 | return 1;
|
---|
583 | } // endif
|
---|
584 |
|
---|
585 | // return 0; we never get here
|
---|
586 | }
|
---|
587 |
|
---|
588 | char fname[128],
|
---|
589 | ModName[80];
|
---|
590 | char ename[128],
|
---|
591 | dummy[128];
|
---|
592 |
|
---|
593 | #define MAX_USERDEFS 300 // raised from 150 V0.9.1 (2000-01-30) [umoeller]
|
---|
594 | #define MAX_POINTERS 300 // raised from 150 V0.9.1 (2000-01-30) [umoeller]
|
---|
595 |
|
---|
596 | USHORT userdef_count;
|
---|
597 | USHORT pointer_count;
|
---|
598 |
|
---|
599 | struct one_userdef_rec
|
---|
600 | {
|
---|
601 | USHORT idx;
|
---|
602 | USHORT type_index;
|
---|
603 | BYTE name[33];
|
---|
604 | } one_userdef[MAX_USERDEFS];
|
---|
605 |
|
---|
606 | struct one_pointer_rec
|
---|
607 | {
|
---|
608 | USHORT idx;
|
---|
609 | USHORT type_index;
|
---|
610 | BYTE type_qual;
|
---|
611 | BYTE name[33];
|
---|
612 | } one_pointer[MAX_POINTERS];
|
---|
613 |
|
---|
614 | /*
|
---|
615 | * Read32PmDebug:
|
---|
616 | * parses 32-bit debug code.
|
---|
617 | * Called from dbgPrintDebugInfo for 32-bit modules.
|
---|
618 | */
|
---|
619 |
|
---|
620 | STATIC int Read32PmDebug(FILE *LogFile, // in: text log file to write to
|
---|
621 | PXDEBUGINFO pxdi,
|
---|
622 | int ModuleFile, // in: module file opened with sopen()
|
---|
623 | int TrapSeg,
|
---|
624 | int TrapOff,
|
---|
625 | CHAR *FileName)
|
---|
626 | {
|
---|
627 | static unsigned int CurrSymSeg, NrSymbol,
|
---|
628 | /* offset, */ NrPublic,
|
---|
629 | NrFile, NrLine, /* NrEntry */
|
---|
630 | numdir, namelen,
|
---|
631 | numlines /* , line */;
|
---|
632 | static int ModIndex;
|
---|
633 | static int bytesread, i, j;
|
---|
634 | static SSLINEENTRY32 LineEntry;
|
---|
635 | static SSFILENUM32 FileInfo;
|
---|
636 | static FIRSTLINEENTRY32 FirstLine;
|
---|
637 | static BYTE dump_vars = FALSE;
|
---|
638 | static USHORT idx;
|
---|
639 | static BOOL read_types;
|
---|
640 | static LONG lSize;
|
---|
641 |
|
---|
642 | ModIndex = 0;
|
---|
643 | // See if any CODEVIEW info
|
---|
644 | if (lseek(ModuleFile, -8L, SEEK_END) == -1)
|
---|
645 | {
|
---|
646 | fprintf(LogFile, "Error %u seeking CodeView table in %s\n", errno, FileName);
|
---|
647 | return (18);
|
---|
648 | }
|
---|
649 |
|
---|
650 | if (read(ModuleFile,
|
---|
651 | (void *)&G_eodbug, 8)
|
---|
652 | == -1)
|
---|
653 | {
|
---|
654 | fprintf(LogFile, "Error %u reading debug info from %s\n", errno, FileName);
|
---|
655 | return (19);
|
---|
656 | }
|
---|
657 | if (G_eodbug.dbug != DBUGSIG)
|
---|
658 | {
|
---|
659 | // fprintf(LogFile,"\nNo CodeView information stored.\n");
|
---|
660 | return (100);
|
---|
661 | }
|
---|
662 |
|
---|
663 | if ( (pxdi->lfaBase = lseek(ModuleFile,
|
---|
664 | -(LONG)G_eodbug.dfaBase,
|
---|
665 | SEEK_END))
|
---|
666 | == -1L)
|
---|
667 | {
|
---|
668 | fprintf(LogFile, "Error %u seeking base codeview data in %s\n", errno, FileName);
|
---|
669 | return (20);
|
---|
670 | }
|
---|
671 |
|
---|
672 | if (read(ModuleFile,
|
---|
673 | (void *)&pxdi->base, 8)
|
---|
674 | == -1)
|
---|
675 | {
|
---|
676 | fprintf(LogFile, "Error %u reading base codeview data in %s\n", errno, FileName);
|
---|
677 | return (21);
|
---|
678 | }
|
---|
679 |
|
---|
680 | if (lseek(ModuleFile,
|
---|
681 | pxdi->base.lfoDir - 8 + 4,
|
---|
682 | SEEK_CUR)
|
---|
683 | == -1)
|
---|
684 | {
|
---|
685 | fprintf(LogFile, "Error %u seeking dir codeview data in %s\n", errno, FileName);
|
---|
686 | return (22);
|
---|
687 | }
|
---|
688 |
|
---|
689 | if (read(ModuleFile,
|
---|
690 | (void *)&numdir, 4)
|
---|
691 | == -1)
|
---|
692 | {
|
---|
693 | fprintf(LogFile, "Error %u reading dir codeview data in %s\n", errno, FileName);
|
---|
694 | return (23);
|
---|
695 | }
|
---|
696 |
|
---|
697 | // Read dir table into buffer
|
---|
698 | if ( (pxdi->pDirTab32 = (SSDIR32*)calloc(numdir,
|
---|
699 | sizeof(SSDIR32)))
|
---|
700 | == NULL)
|
---|
701 | {
|
---|
702 | fprintf(LogFile, "Out of memory!");
|
---|
703 | return (-1);
|
---|
704 | }
|
---|
705 |
|
---|
706 | if (read(ModuleFile,
|
---|
707 | (void*)pxdi->pDirTab32,
|
---|
708 | numdir * sizeof(SSDIR32))
|
---|
709 | == -1)
|
---|
710 | {
|
---|
711 | fprintf(LogFile, "Error %u reading codeview dir table from %s\n", errno, FileName);
|
---|
712 | free(pxdi->pDirTab32);
|
---|
713 | return (24);
|
---|
714 | }
|
---|
715 |
|
---|
716 | i = 0;
|
---|
717 | while (i < numdir)
|
---|
718 | {
|
---|
719 | if (pxdi->pDirTab32[i].sst != SSTMODULES)
|
---|
720 | {
|
---|
721 | i++;
|
---|
722 | continue;
|
---|
723 | }
|
---|
724 |
|
---|
725 | NrPublic = 0x0;
|
---|
726 | NrSymbol = 0;
|
---|
727 | NrLine = 0x0;
|
---|
728 | NrFile = 0x0;
|
---|
729 | CurrSymSeg = 0;
|
---|
730 | // point to subsection
|
---|
731 | lseek(ModuleFile,
|
---|
732 | pxdi->pDirTab32[i].lfoStart + pxdi->lfaBase,
|
---|
733 | SEEK_SET);
|
---|
734 | read(ModuleFile,
|
---|
735 | (void*)&pxdi->ssmod32.csBase,
|
---|
736 | sizeof(SSMOD32));
|
---|
737 | read(ModuleFile,
|
---|
738 | (void*)ModName,
|
---|
739 | (unsigned)pxdi->ssmod32.csize);
|
---|
740 | ModIndex = pxdi->pDirTab32[i].modindex;
|
---|
741 | ModName[pxdi->ssmod32.csize] = '\0';
|
---|
742 | i++;
|
---|
743 |
|
---|
744 | read_types = FALSE;
|
---|
745 |
|
---|
746 | while ( (pxdi->pDirTab32[i].modindex == ModIndex)
|
---|
747 | && (i < numdir)
|
---|
748 | )
|
---|
749 | {
|
---|
750 | // point to subsection
|
---|
751 | lseek(ModuleFile,
|
---|
752 | pxdi->pDirTab32[i].lfoStart + pxdi->lfaBase,
|
---|
753 | SEEK_SET);
|
---|
754 |
|
---|
755 | switch (pxdi->pDirTab32[i].sst)
|
---|
756 | {
|
---|
757 | case SSTPUBLICS:
|
---|
758 | bytesread = 0;
|
---|
759 | while (bytesread < pxdi->pDirTab32[i].cb)
|
---|
760 | {
|
---|
761 | bytesread += read(ModuleFile,
|
---|
762 | (void *)&pxdi->sspub32.offset,
|
---|
763 | sizeof(pxdi->sspub32));
|
---|
764 | bytesread += read(ModuleFile,
|
---|
765 | (void*)ename,
|
---|
766 | (unsigned)pxdi->sspub32.csize);
|
---|
767 | ename[pxdi->sspub32.csize] = '\0';
|
---|
768 | if ( (pxdi->sspub32.segment == TrapSeg)
|
---|
769 | && (pxdi->sspub32.offset <= TrapOff)
|
---|
770 | && (pxdi->sspub32.offset >= NrPublic)
|
---|
771 | )
|
---|
772 | {
|
---|
773 | NrPublic = pubfunc_ofs = pxdi->sspub32.offset;
|
---|
774 | read_types = TRUE;
|
---|
775 | sprintf(pxdi->szNrPub,
|
---|
776 | "%s %s (%s)\n",
|
---|
777 | (pxdi->sspub32.type == 1)
|
---|
778 | ? " Abs"
|
---|
779 | : " ",
|
---|
780 | ename,
|
---|
781 | ModName
|
---|
782 | );
|
---|
783 | // but continue, because there might be a
|
---|
784 | // symbol that comes closer
|
---|
785 | }
|
---|
786 | }
|
---|
787 | break;
|
---|
788 |
|
---|
789 | // Read symbols, so we can dump the variables on the stack
|
---|
790 | case SSTSYMBOLS:
|
---|
791 | if (TrapSeg != pxdi->ssmod32.csBase)
|
---|
792 | break;
|
---|
793 |
|
---|
794 | bytesread = 0;
|
---|
795 | while (bytesread < pxdi->pDirTab32[i].cb)
|
---|
796 | {
|
---|
797 | static USHORT usLength;
|
---|
798 | static BYTE b1,
|
---|
799 | b2;
|
---|
800 | static BYTE bType;
|
---|
801 | // *ptr;
|
---|
802 | static ULONG ofs;
|
---|
803 | // static ULONG last_addr = 0;
|
---|
804 | static BYTE str[256];
|
---|
805 | static struct symseg_rec symseg;
|
---|
806 | static struct symauto_rec symauto;
|
---|
807 | static struct symproc_rec symproc;
|
---|
808 |
|
---|
809 | // Read the length of this subentry
|
---|
810 | bytesread += read(ModuleFile, &b1, 1);
|
---|
811 | if (b1 & 0x80)
|
---|
812 | {
|
---|
813 | bytesread += read(ModuleFile, &b2, 1);
|
---|
814 | usLength = ((b1 & 0x7F) << 8) + b2;
|
---|
815 | }
|
---|
816 | else
|
---|
817 | usLength = b1;
|
---|
818 |
|
---|
819 | ofs = tell(ModuleFile);
|
---|
820 |
|
---|
821 | bytesread += read(ModuleFile, &bType, 1);
|
---|
822 |
|
---|
823 | switch (bType)
|
---|
824 | {
|
---|
825 | case SYM_CHANGESEG:
|
---|
826 | read(ModuleFile, &symseg, sizeof(symseg));
|
---|
827 | CurrSymSeg = symseg.seg_no;
|
---|
828 | break;
|
---|
829 |
|
---|
830 | case SYM_PROC:
|
---|
831 | case SYM_CPPPROC:
|
---|
832 | read(ModuleFile, &symproc, sizeof(symproc));
|
---|
833 | read(ModuleFile, str, symproc.name_len);
|
---|
834 | str[symproc.name_len] = 0;
|
---|
835 |
|
---|
836 | if ((CurrSymSeg == TrapSeg) &&
|
---|
837 | (symproc.offset <= TrapOff) &&
|
---|
838 | (symproc.offset >= NrSymbol))
|
---|
839 | {
|
---|
840 |
|
---|
841 | dump_vars = TRUE;
|
---|
842 | var_ofs = 0;
|
---|
843 | NrSymbol = symproc.offset;
|
---|
844 | func_ofs = symproc.offset;
|
---|
845 |
|
---|
846 | strcpy(func_name, str);
|
---|
847 | }
|
---|
848 | else
|
---|
849 | {
|
---|
850 | dump_vars = FALSE;
|
---|
851 | }
|
---|
852 | break;
|
---|
853 |
|
---|
854 | case SYM_AUTO:
|
---|
855 | if (!dump_vars)
|
---|
856 | break;
|
---|
857 |
|
---|
858 | read(ModuleFile, &symauto, sizeof(symauto));
|
---|
859 | read(ModuleFile, str, symauto.name_len);
|
---|
860 | str[symauto.name_len] = 0;
|
---|
861 |
|
---|
862 | strcpy(autovar_def[var_ofs].name, str);
|
---|
863 | autovar_def[var_ofs].stack_offset = symauto.stack_offset;
|
---|
864 | autovar_def[var_ofs].type_idx = symauto.type_idx;
|
---|
865 | var_ofs++;
|
---|
866 | break;
|
---|
867 |
|
---|
868 | }
|
---|
869 |
|
---|
870 | bytesread += usLength;
|
---|
871 |
|
---|
872 | lseek(ModuleFile, ofs + usLength, SEEK_SET);
|
---|
873 | }
|
---|
874 | break;
|
---|
875 |
|
---|
876 | case SSTTYPES:
|
---|
877 | // if (ModIndex != TrapSeg)
|
---|
878 | if (!read_types)
|
---|
879 | break;
|
---|
880 |
|
---|
881 | bytesread = 0;
|
---|
882 | idx = 0x200;
|
---|
883 | userdef_count = 0;
|
---|
884 | pointer_count = 0;
|
---|
885 | while (bytesread < pxdi->pDirTab32[i].cb)
|
---|
886 | {
|
---|
887 | static struct type_rec type;
|
---|
888 | static struct type_userdefrec udef;
|
---|
889 | static struct type_pointerrec point;
|
---|
890 | static ULONG ofs;
|
---|
891 | static BYTE str[256];
|
---|
892 |
|
---|
893 | // Read the length of this subentry
|
---|
894 | ofs = tell(ModuleFile);
|
---|
895 |
|
---|
896 | read(ModuleFile, &type, sizeof(type));
|
---|
897 | bytesread += sizeof(type);
|
---|
898 |
|
---|
899 | switch (type.type)
|
---|
900 | {
|
---|
901 | case TYPE_USERDEF:
|
---|
902 | if (userdef_count >= MAX_USERDEFS)
|
---|
903 | break;
|
---|
904 |
|
---|
905 | read(ModuleFile, &udef, sizeof(udef));
|
---|
906 | read(ModuleFile, str, udef.name_len);
|
---|
907 | str[udef.name_len] = 0;
|
---|
908 |
|
---|
909 | // Insert userdef in table
|
---|
910 | one_userdef[userdef_count].idx = idx;
|
---|
911 | one_userdef[userdef_count].type_index = udef.type_index;
|
---|
912 | memcpy(one_userdef[userdef_count].name,
|
---|
913 | str,
|
---|
914 | _min(udef.name_len + 1, 32));
|
---|
915 | one_userdef[userdef_count].name[32] = 0;
|
---|
916 | userdef_count++;
|
---|
917 | break;
|
---|
918 |
|
---|
919 | case TYPE_POINTER:
|
---|
920 | if (pointer_count >= MAX_POINTERS)
|
---|
921 | break;
|
---|
922 |
|
---|
923 | read(ModuleFile, &point, sizeof(point));
|
---|
924 | read(ModuleFile, str, point.name_len);
|
---|
925 | str[point.name_len] = 0;
|
---|
926 |
|
---|
927 | // Insert userdef in table
|
---|
928 | one_pointer[pointer_count].idx = idx;
|
---|
929 | one_pointer[pointer_count].type_index = point.type_index;
|
---|
930 | memcpy(one_pointer[pointer_count].name,
|
---|
931 | str,
|
---|
932 | _min(point.name_len + 1, 32));
|
---|
933 | one_pointer[pointer_count].name[32] = 0;
|
---|
934 | one_pointer[pointer_count].type_qual = type.type_qual;
|
---|
935 | pointer_count++;
|
---|
936 | break;
|
---|
937 | }
|
---|
938 |
|
---|
939 | ++idx;
|
---|
940 |
|
---|
941 | bytesread += type.length;
|
---|
942 |
|
---|
943 | lseek(ModuleFile, ofs + type.length + 2, SEEK_SET);
|
---|
944 | }
|
---|
945 | break;
|
---|
946 |
|
---|
947 | case SSTSRCLINES32:
|
---|
948 | if (TrapSeg != pxdi->ssmod32.csBase)
|
---|
949 | break;
|
---|
950 |
|
---|
951 | // read first line
|
---|
952 | do
|
---|
953 | {
|
---|
954 | read(ModuleFile, (void *)&FirstLine, sizeof(FirstLine));
|
---|
955 |
|
---|
956 | if (FirstLine.LineNum != 0)
|
---|
957 | {
|
---|
958 | fprintf(LogFile, "Missing Line table information\n");
|
---|
959 | break;
|
---|
960 | } // endif
|
---|
961 | numlines = FirstLine.numlines;
|
---|
962 | // Other type of data skip 4 more bytes
|
---|
963 | if (FirstLine.entry_type < 4)
|
---|
964 | {
|
---|
965 | read(ModuleFile, (void *)&lSize, 4);
|
---|
966 | if (FirstLine.entry_type == 3)
|
---|
967 | lseek(ModuleFile, lSize, SEEK_CUR);
|
---|
968 | }
|
---|
969 | }
|
---|
970 | while (FirstLine.entry_type == 3);
|
---|
971 |
|
---|
972 | for (j = 0; j < numlines; j++)
|
---|
973 | {
|
---|
974 | switch (FirstLine.entry_type)
|
---|
975 | {
|
---|
976 | case 0:
|
---|
977 | read(ModuleFile, (void *)&LineEntry, sizeof(LineEntry));
|
---|
978 | // Changed by Kim Rasmussen 26/06 1996 to ignore linenumber 0
|
---|
979 | // if (LineEntry.Offset+ssmod32.csOff<=TrapOff && LineEntry.Offset+ssmod32.csOff>=NrLine) {
|
---|
980 | if ( (LineEntry.LineNum)
|
---|
981 | && (LineEntry.Offset + pxdi->ssmod32.csOff
|
---|
982 | <= TrapOff)
|
---|
983 | && (LineEntry.Offset + pxdi->ssmod32.csOff >= NrLine)
|
---|
984 | )
|
---|
985 | {
|
---|
986 | NrLine = LineEntry.Offset;
|
---|
987 | NrFile = LineEntry.FileNum;
|
---|
988 | /*pOffset =sprintf(szNrLine,"%04X:%08X line #%hu ",
|
---|
989 | * ssmod32.csBase,LineEntry.Offset,
|
---|
990 | * LineEntry.LineNum); */
|
---|
991 | sprintf(pxdi->szNrLine, "% 6hu", LineEntry.LineNum);
|
---|
992 | }
|
---|
993 | break;
|
---|
994 |
|
---|
995 | case 1:
|
---|
996 | lseek(ModuleFile, sizeof(struct linlist_rec), SEEK_CUR);
|
---|
997 | break;
|
---|
998 |
|
---|
999 | case 2:
|
---|
1000 | lseek(ModuleFile, sizeof(struct linsourcelist_rec), SEEK_CUR);
|
---|
1001 | break;
|
---|
1002 |
|
---|
1003 | case 3:
|
---|
1004 | lseek(ModuleFile, sizeof(struct filenam_rec), SEEK_CUR);
|
---|
1005 | break;
|
---|
1006 |
|
---|
1007 | case 4:
|
---|
1008 | lseek(ModuleFile, sizeof(struct pathtab_rec), SEEK_CUR);
|
---|
1009 | break;
|
---|
1010 |
|
---|
1011 | }
|
---|
1012 | }
|
---|
1013 |
|
---|
1014 | if (NrFile != 0)
|
---|
1015 | {
|
---|
1016 | // file found:
|
---|
1017 | read(ModuleFile, (void*)&FileInfo, sizeof(FileInfo));
|
---|
1018 | namelen = 0;
|
---|
1019 | for (j = 1; j <= FileInfo.file_count; j++)
|
---|
1020 | {
|
---|
1021 | namelen = 0;
|
---|
1022 | read(ModuleFile, (void *)&namelen, 1);
|
---|
1023 | read(ModuleFile, (void *)ename, namelen);
|
---|
1024 | if (j == NrFile)
|
---|
1025 | break;
|
---|
1026 | }
|
---|
1027 | ename[namelen] = '\0';
|
---|
1028 | // pOffset=sprintf(szNrLine+pOffset," (%s) (%s)\n",ename,ModName);
|
---|
1029 | sprintf(pxdi->szNrFile, "%11.11s ", ename);
|
---|
1030 | }
|
---|
1031 | else
|
---|
1032 | {
|
---|
1033 | // strcat(szNrLine,"\n"); avoid new line for empty name fill
|
---|
1034 | strcpy(pxdi->szNrFile, "file? ");
|
---|
1035 | } // endif
|
---|
1036 | break;
|
---|
1037 | } // end switch
|
---|
1038 |
|
---|
1039 | i++;
|
---|
1040 | } // end while modindex
|
---|
1041 | } // End While i < numdir
|
---|
1042 | free(pxdi->pDirTab32);
|
---|
1043 | return (0);
|
---|
1044 | }
|
---|
1045 |
|
---|
1046 | /*
|
---|
1047 | * Read16CodeView:
|
---|
1048 | * parses 16-bit debug code.
|
---|
1049 | * Called from dbgPrintDebugInfo for 16-bit modules.
|
---|
1050 | */
|
---|
1051 |
|
---|
1052 | STATIC int Read16CodeView(FILE *LogFile, // in: text log file to write to
|
---|
1053 | PXDEBUGINFO pxdi,
|
---|
1054 | int fh,
|
---|
1055 | int TrapSeg,
|
---|
1056 | int TrapOff,
|
---|
1057 | CHAR *FileName)
|
---|
1058 | {
|
---|
1059 | static unsigned short int offset,
|
---|
1060 | NrPublic, NrLine,
|
---|
1061 | numdir,
|
---|
1062 | namelen, numlines,
|
---|
1063 | line;
|
---|
1064 | static int ModIndex;
|
---|
1065 | static int bytesread, i, j;
|
---|
1066 |
|
---|
1067 | ModIndex = 0;
|
---|
1068 | // See if any CODEVIEW info
|
---|
1069 | if (lseek(fh, -8L, SEEK_END) == -1)
|
---|
1070 | {
|
---|
1071 | fprintf(LogFile, "Error %u seeking CodeView table in %s\n", errno, FileName);
|
---|
1072 | return (18);
|
---|
1073 | }
|
---|
1074 |
|
---|
1075 | if (read(fh, (void *)&G_eodbug, 8) == -1)
|
---|
1076 | {
|
---|
1077 | fprintf(LogFile, "Error %u reading debug info from %s\n", errno, FileName);
|
---|
1078 | return (19);
|
---|
1079 | }
|
---|
1080 | if (G_eodbug.dbug != DBUGSIG)
|
---|
1081 | {
|
---|
1082 | // fprintf(LogFile,"\nNo CodeView information stored.\n");
|
---|
1083 | return (100);
|
---|
1084 | }
|
---|
1085 |
|
---|
1086 | if ((pxdi->lfaBase = lseek(fh, -(LONG)G_eodbug.dfaBase, SEEK_END)) == -1L)
|
---|
1087 | {
|
---|
1088 | fprintf(LogFile, "Error %u seeking base codeview data in %s\n", errno, FileName);
|
---|
1089 | return (20);
|
---|
1090 | }
|
---|
1091 |
|
---|
1092 | if (read(fh, (void *)&pxdi->base, 8) == -1)
|
---|
1093 | {
|
---|
1094 | fprintf(LogFile, "Error %u reading base codeview data in %s\n", errno, FileName);
|
---|
1095 | return (21);
|
---|
1096 | }
|
---|
1097 |
|
---|
1098 | if (lseek(fh, pxdi->base.lfoDir - 8, SEEK_CUR) == -1)
|
---|
1099 | {
|
---|
1100 | fprintf(LogFile, "Error %u seeking dir codeview data in %s\n", errno, FileName);
|
---|
1101 | return (22);
|
---|
1102 | }
|
---|
1103 |
|
---|
1104 | if (read(fh, (void *)&numdir, 2) == -1)
|
---|
1105 | {
|
---|
1106 | fprintf(LogFile, "Error %u reading dir codeview data in %s\n", errno, FileName);
|
---|
1107 | return (23);
|
---|
1108 | }
|
---|
1109 |
|
---|
1110 | // Read dir table into buffer
|
---|
1111 | if ((pxdi->pDirTab = (SSDIR*)calloc(numdir, sizeof(SSDIR))) == NULL)
|
---|
1112 | {
|
---|
1113 | fprintf(LogFile, "Out of memory!");
|
---|
1114 | return (-1);
|
---|
1115 | }
|
---|
1116 |
|
---|
1117 | if (read(fh, (void*)pxdi->pDirTab, numdir * sizeof(SSDIR)) == -1)
|
---|
1118 | {
|
---|
1119 | fprintf(LogFile, "Error %u reading codeview dir table from %s\n", errno, FileName);
|
---|
1120 | free(pxdi->pDirTab);
|
---|
1121 | return (24);
|
---|
1122 | }
|
---|
1123 |
|
---|
1124 | i = 0;
|
---|
1125 | while (i < numdir)
|
---|
1126 | {
|
---|
1127 | if (pxdi->pDirTab[i].sst != SSTMODULES)
|
---|
1128 | {
|
---|
1129 | i++;
|
---|
1130 | continue;
|
---|
1131 | }
|
---|
1132 | NrPublic = 0x0;
|
---|
1133 | NrLine = 0x0;
|
---|
1134 | // point to subsection
|
---|
1135 | lseek(fh, pxdi->pDirTab[i].lfoStart + pxdi->lfaBase, SEEK_SET);
|
---|
1136 | read(fh, (void *)&pxdi->ssmod.csBase, sizeof(SSMODULE));
|
---|
1137 | read(fh, (void *)ModName, (unsigned)pxdi->ssmod.csize);
|
---|
1138 | ModIndex = pxdi->pDirTab[i].modindex;
|
---|
1139 | ModName[pxdi->ssmod.csize] = '\0';
|
---|
1140 | i++;
|
---|
1141 | while (pxdi->pDirTab[i].modindex == ModIndex && i < numdir)
|
---|
1142 | {
|
---|
1143 | // point to subsection
|
---|
1144 | lseek(fh, pxdi->pDirTab[i].lfoStart + pxdi->lfaBase, SEEK_SET);
|
---|
1145 | switch (pxdi->pDirTab[i].sst)
|
---|
1146 | {
|
---|
1147 | case SSTPUBLICS:
|
---|
1148 | bytesread = 0;
|
---|
1149 | while (bytesread < pxdi->pDirTab[i].cb)
|
---|
1150 | {
|
---|
1151 | bytesread += read(fh, (void *)&pxdi->sspub.offset, sizeof(pxdi->sspub));
|
---|
1152 | bytesread += read(fh, (void *)ename, (unsigned)pxdi->sspub.csize);
|
---|
1153 | ename[pxdi->sspub.csize] = '\0';
|
---|
1154 | if ((pxdi->sspub.segment == TrapSeg) &&
|
---|
1155 | (pxdi->sspub.offset <= TrapOff) &&
|
---|
1156 | (pxdi->sspub.offset >= NrPublic))
|
---|
1157 | {
|
---|
1158 | NrPublic = pxdi->sspub.offset;
|
---|
1159 | sprintf(pxdi->szNrPub, "%s %s (%s) %04hX:%04hX\n",
|
---|
1160 | (pxdi->sspub.type == 1) ? " Abs" : " ", ename,
|
---|
1161 | ModName, // ()
|
---|
1162 | pxdi->sspub.segment,
|
---|
1163 | pxdi->sspub.offset
|
---|
1164 | );
|
---|
1165 | }
|
---|
1166 | }
|
---|
1167 | break;
|
---|
1168 |
|
---|
1169 | case SSTSRCLINES2:
|
---|
1170 | case SSTSRCLINES:
|
---|
1171 | if (TrapSeg != pxdi->ssmod.csBase)
|
---|
1172 | break;
|
---|
1173 | namelen = 0;
|
---|
1174 | read(fh, (void *)&namelen, 1);
|
---|
1175 | read(fh, (void *)ename, namelen);
|
---|
1176 | ename[namelen] = '\0';
|
---|
1177 | // skip 2 zero bytes
|
---|
1178 | if (pxdi->pDirTab[i].sst == SSTSRCLINES2)
|
---|
1179 | read(fh, (void *)&numlines, 2);
|
---|
1180 | read(fh, (void *)&numlines, 2);
|
---|
1181 | for (j = 0; j < numlines; j++)
|
---|
1182 | {
|
---|
1183 | read(fh, (void *)&line, 2);
|
---|
1184 | read(fh, (void *)&offset, 2);
|
---|
1185 | if (offset <= TrapOff && offset >= NrLine)
|
---|
1186 | {
|
---|
1187 | NrLine = offset;
|
---|
1188 | sprintf(pxdi->szNrFile, "% 12.12s ", ename);
|
---|
1189 | sprintf(pxdi->szNrLine, "% 6hu", line);
|
---|
1190 | /*sprintf(szNrLine,"%04hX:%04hX line #%hu (%s) (%s)\n",
|
---|
1191 | * ssmod.csBase,offset,line,ModName,ename); */
|
---|
1192 | }
|
---|
1193 | }
|
---|
1194 | break;
|
---|
1195 | } // end switch
|
---|
1196 | i++;
|
---|
1197 | } // end while modindex
|
---|
1198 | } // End While i < numdir
|
---|
1199 | free(pxdi->pDirTab);
|
---|
1200 | return (0);
|
---|
1201 | }
|
---|
1202 |
|
---|
1203 | /* ******************************************************************
|
---|
1204 | *
|
---|
1205 | * PART 2: ANALYZE VARIABLES
|
---|
1206 | *
|
---|
1207 | ********************************************************************/
|
---|
1208 |
|
---|
1209 | /*
|
---|
1210 | * var_value:
|
---|
1211 | * writes a description of a variable type to
|
---|
1212 | * the specified buffer, depending on "type".
|
---|
1213 | *
|
---|
1214 | *@@changed V0.9.1 (2000-01-30) [umoeller]: changed prototype to use external buffer
|
---|
1215 | */
|
---|
1216 |
|
---|
1217 | STATIC VOID var_value(void *varptr, // in: address of the variable on the stack
|
---|
1218 | char *pszBuf, // out: information
|
---|
1219 | BYTE type) // in: type; if >= 32, we'll call DosQueryMem
|
---|
1220 | {
|
---|
1221 | ULONG Size = 1,
|
---|
1222 | Attr = 0;
|
---|
1223 |
|
---|
1224 | if (DosQueryMem(varptr, &Size, &Attr) != NO_ERROR)
|
---|
1225 | {
|
---|
1226 | sprintf(pszBuf, "type %d, DosQueryMem failed", type);
|
---|
1227 | return;
|
---|
1228 | }
|
---|
1229 |
|
---|
1230 | if ((Attr & PAG_READ) == 0)
|
---|
1231 | {
|
---|
1232 | sprintf(pszBuf, "type %d, read-access to value denied", type);
|
---|
1233 | return;
|
---|
1234 | }
|
---|
1235 |
|
---|
1236 | if (type == 0)
|
---|
1237 | sprintf(pszBuf, "%hd", *(signed char*)varptr);
|
---|
1238 | else if (type == 1)
|
---|
1239 | sprintf(pszBuf, "%hd", *(signed short*)varptr);
|
---|
1240 | else if (type == 2)
|
---|
1241 | sprintf(pszBuf, "%ld", *(signed long*)varptr);
|
---|
1242 | else if (type == 4)
|
---|
1243 | sprintf(pszBuf, "%hu", *(BYTE*) varptr);
|
---|
1244 | else if (type == 5)
|
---|
1245 | sprintf(pszBuf, "%hu", *(USHORT*)varptr);
|
---|
1246 | else if (type == 6)
|
---|
1247 | sprintf(pszBuf, "0x%lX (%lu)", *((ULONG*)varptr), *((ULONG*)varptr));
|
---|
1248 | else if (type == 8)
|
---|
1249 | sprintf(pszBuf, "%f", *(float*)varptr);
|
---|
1250 | else if (type == 9)
|
---|
1251 | sprintf(pszBuf, "%f", *(double*)varptr);
|
---|
1252 | else if (type == 10)
|
---|
1253 | sprintf(pszBuf, "%f", (double)(*(long double*)varptr));
|
---|
1254 | else if (type == 16)
|
---|
1255 | sprintf(pszBuf, "%s", *(char*)varptr ? "TRUE" : "FALSE");
|
---|
1256 | else if (type == 17)
|
---|
1257 | sprintf(pszBuf, "%s", *(short*)varptr ? "TRUE" : "FALSE");
|
---|
1258 | else if (type == 18)
|
---|
1259 | sprintf(pszBuf, "%s", *(long*)varptr ? "TRUE" : "FALSE");
|
---|
1260 | else if (type == 20)
|
---|
1261 | sprintf(pszBuf, "%c", *(char*)varptr);
|
---|
1262 | else if (type == 21)
|
---|
1263 | sprintf(pszBuf, "%hd", (*(short*)varptr));
|
---|
1264 | else if (type == 22)
|
---|
1265 | sprintf(pszBuf, "%ld", *(long*)varptr);
|
---|
1266 | else if (type == 23)
|
---|
1267 | sprintf(pszBuf, "void");
|
---|
1268 | else if (type >= 32)
|
---|
1269 | {
|
---|
1270 | sprintf(pszBuf, "0x%p", (void*)(*(ULONG*)varptr));
|
---|
1271 | if (Attr & PAG_FREE)
|
---|
1272 | {
|
---|
1273 | strcat(pszBuf, " unallocated memory");
|
---|
1274 | }
|
---|
1275 | else
|
---|
1276 | {
|
---|
1277 | if ((Attr & PAG_COMMIT) == 0x0U)
|
---|
1278 | {
|
---|
1279 | strcat(pszBuf, " uncommitted");
|
---|
1280 | } // endif
|
---|
1281 | if ((Attr & PAG_WRITE) == 0x0U)
|
---|
1282 | {
|
---|
1283 | strcat(pszBuf, " unwritable");
|
---|
1284 | } // endif
|
---|
1285 | if ((Attr & PAG_READ) == 0x0U)
|
---|
1286 | {
|
---|
1287 | strcat(pszBuf, " unreadable");
|
---|
1288 | } // endif
|
---|
1289 | } // endif
|
---|
1290 | } // endif
|
---|
1291 | else
|
---|
1292 | sprintf(pszBuf, "Unknown type %d", type);
|
---|
1293 | }
|
---|
1294 |
|
---|
1295 | /*
|
---|
1296 | * search_userdefs:
|
---|
1297 | * searches the table of userdef's-
|
---|
1298 | * Return TRUE if found.
|
---|
1299 | */
|
---|
1300 |
|
---|
1301 | STATIC BOOL search_userdefs(FILE *LogFile, // in: text log file to write to
|
---|
1302 | ULONG stackofs,
|
---|
1303 | USHORT var_no)
|
---|
1304 | {
|
---|
1305 | USHORT pos;
|
---|
1306 |
|
---|
1307 | for (pos = 0;
|
---|
1308 | pos < userdef_count;
|
---|
1309 | pos++)
|
---|
1310 | {
|
---|
1311 | if (one_userdef[pos].idx == autovar_def[var_no].type_idx)
|
---|
1312 | {
|
---|
1313 | if ( (one_userdef[pos].type_index >= 0x80)
|
---|
1314 | // && (one_userdef[pos].type_index <= 0xDA)
|
---|
1315 | )
|
---|
1316 | {
|
---|
1317 | static char sszVar3[500] = "complex";
|
---|
1318 | if (one_userdef[pos].type_index <= 0xDA)
|
---|
1319 | var_value((void*)(stackofs + autovar_def[var_no].stack_offset),
|
---|
1320 | sszVar3,
|
---|
1321 | one_userdef[pos].type_index - 0x80);
|
---|
1322 |
|
---|
1323 | fprintf(LogFile,
|
---|
1324 | " %- 6ld %- 20.20s %- 33.33s %s (user)\n",
|
---|
1325 | autovar_def[var_no].stack_offset, // stack offset
|
---|
1326 | autovar_def[var_no].name, // identifier
|
---|
1327 | one_userdef[pos].name, // type name
|
---|
1328 | sszVar3 // composed by var_value
|
---|
1329 | );
|
---|
1330 | return TRUE;
|
---|
1331 | }
|
---|
1332 | else
|
---|
1333 | return FALSE;
|
---|
1334 | }
|
---|
1335 | }
|
---|
1336 |
|
---|
1337 | return FALSE;
|
---|
1338 | }
|
---|
1339 |
|
---|
1340 | /*
|
---|
1341 | * search_pointers:
|
---|
1342 | *
|
---|
1343 | */
|
---|
1344 |
|
---|
1345 | STATIC BOOL search_pointers(FILE *LogFile, // in: text log file to write to
|
---|
1346 | ULONG stackofs,
|
---|
1347 | USHORT var_no)
|
---|
1348 | {
|
---|
1349 | USHORT pos, upos;
|
---|
1350 | static BYTE str[35];
|
---|
1351 | static char sszVar[500];
|
---|
1352 |
|
---|
1353 | // BYTE type_index;
|
---|
1354 |
|
---|
1355 | for (pos = 0;
|
---|
1356 | ( (pos < pointer_count)
|
---|
1357 | && (one_pointer[pos].idx != autovar_def[var_no].type_idx)
|
---|
1358 | );
|
---|
1359 | pos++);
|
---|
1360 |
|
---|
1361 | if (pos < pointer_count)
|
---|
1362 | {
|
---|
1363 | if ( (one_pointer[pos].type_index >= 0x80)
|
---|
1364 | && (one_pointer[pos].type_index <= 0xDA)
|
---|
1365 | )
|
---|
1366 | {
|
---|
1367 | strcpy(str, type_name[one_pointer[pos].type_index - 0x80]);
|
---|
1368 | strcat(str, " *");
|
---|
1369 | var_value((void*)(stackofs + autovar_def[var_no].stack_offset),
|
---|
1370 | sszVar,
|
---|
1371 | 32);
|
---|
1372 | fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr1)\n",
|
---|
1373 | autovar_def[var_no].stack_offset,
|
---|
1374 | autovar_def[var_no].name,
|
---|
1375 | str,
|
---|
1376 | sszVar);
|
---|
1377 | return TRUE;
|
---|
1378 | }
|
---|
1379 | else
|
---|
1380 | {
|
---|
1381 | // If the result isn't a simple type, look for it in the other lists
|
---|
1382 | for (upos = 0;
|
---|
1383 | ( (upos < userdef_count)
|
---|
1384 | && (one_userdef[upos].idx != one_pointer[pos].type_index)
|
---|
1385 | );
|
---|
1386 | upos++)
|
---|
1387 | ;
|
---|
1388 |
|
---|
1389 | if (upos < userdef_count)
|
---|
1390 | {
|
---|
1391 | strcpy(str, one_userdef[upos].name);
|
---|
1392 | strcat(str, " *");
|
---|
1393 | var_value((void *)(stackofs + autovar_def[var_no].stack_offset),
|
---|
1394 | sszVar,
|
---|
1395 | 32);
|
---|
1396 | fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr2)\n",
|
---|
1397 | autovar_def[var_no].stack_offset,
|
---|
1398 | autovar_def[var_no].name,
|
---|
1399 | str,
|
---|
1400 | sszVar);
|
---|
1401 | return TRUE;
|
---|
1402 | }
|
---|
1403 | else
|
---|
1404 | {
|
---|
1405 | // if it isn't a userdef, for now give up and just print
|
---|
1406 | // as much as we know
|
---|
1407 | sprintf(str, "Pointer to type 0x%X", one_pointer[pos].type_index);
|
---|
1408 |
|
---|
1409 | var_value((void *)(stackofs + autovar_def[var_no].stack_offset),
|
---|
1410 | sszVar,
|
---|
1411 | 32);
|
---|
1412 | fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (ptr3)\n",
|
---|
1413 | autovar_def[var_no].stack_offset,
|
---|
1414 | autovar_def[var_no].name,
|
---|
1415 | str,
|
---|
1416 | sszVar);
|
---|
1417 |
|
---|
1418 | return TRUE;
|
---|
1419 | }
|
---|
1420 | }
|
---|
1421 | }
|
---|
1422 |
|
---|
1423 | return FALSE;
|
---|
1424 | }
|
---|
1425 |
|
---|
1426 | /*
|
---|
1427 | *@@ dbgPrintVariables:
|
---|
1428 | * Dumps variables for the specified stack offset
|
---|
1429 | * to the specified log file.
|
---|
1430 | *
|
---|
1431 | * New with V0.84.
|
---|
1432 | */
|
---|
1433 |
|
---|
1434 | void dbgPrintVariables(FILE *LogFile, // in: text log file to write to
|
---|
1435 | ULONG stackofs)
|
---|
1436 | {
|
---|
1437 | USHORT n; // , pos;
|
---|
1438 | BOOL AutoVarsFound = FALSE;
|
---|
1439 |
|
---|
1440 | if (/* 1 || */ func_ofs == pubfunc_ofs)
|
---|
1441 | {
|
---|
1442 | for (n = 0;
|
---|
1443 | n < var_ofs;
|
---|
1444 | n++)
|
---|
1445 | {
|
---|
1446 | if (AutoVarsFound == FALSE)
|
---|
1447 | {
|
---|
1448 | AutoVarsFound = TRUE;
|
---|
1449 | fprintf(LogFile, " List of auto variables at EBP %p in %s:\n",
|
---|
1450 | (PVOID)stackofs,
|
---|
1451 | func_name);
|
---|
1452 | fprintf(LogFile, " Offset Name Type Value \n");
|
---|
1453 | fprintf(LogFile, " ÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n");
|
---|
1454 | }
|
---|
1455 |
|
---|
1456 | // If it's one of the simple types
|
---|
1457 | if ( (autovar_def[n].type_idx >= 0x80)
|
---|
1458 | && (autovar_def[n].type_idx <= 0xDA)
|
---|
1459 | )
|
---|
1460 | {
|
---|
1461 | static char sszVar2[500];
|
---|
1462 |
|
---|
1463 | var_value((void *)(stackofs + autovar_def[n].stack_offset),
|
---|
1464 | sszVar2,
|
---|
1465 | autovar_def[n].type_idx - 0x80);
|
---|
1466 |
|
---|
1467 | fprintf(LogFile, " %- 6ld %- 20.20s %- 33.33s %s (simple)\n",
|
---|
1468 | autovar_def[n].stack_offset,
|
---|
1469 | autovar_def[n].name,
|
---|
1470 | type_name[autovar_def[n].type_idx - 0x80],
|
---|
1471 | sszVar2);
|
---|
1472 | }
|
---|
1473 | else
|
---|
1474 | { // Complex type, check if we know what it is
|
---|
1475 | if (!search_userdefs(LogFile, stackofs, n))
|
---|
1476 | {
|
---|
1477 | if (!search_pointers(LogFile, stackofs, n))
|
---|
1478 | {
|
---|
1479 | fprintf(LogFile, " %- 6ld %-20.20s 0x%X (unknown)\n",
|
---|
1480 | autovar_def[n].stack_offset,
|
---|
1481 | autovar_def[n].name,
|
---|
1482 | autovar_def[n].type_idx);
|
---|
1483 | }
|
---|
1484 | }
|
---|
1485 | }
|
---|
1486 | }
|
---|
1487 | /* if (AutoVarsFound == FALSE)
|
---|
1488 | {
|
---|
1489 | fprintf(LogFile, " No auto variables found in %s.\n", func_name);
|
---|
1490 | } */
|
---|
1491 | fprintf(LogFile, "\n");
|
---|
1492 | }
|
---|
1493 | }
|
---|
1494 |
|
---|
1495 | /* ******************************************************************
|
---|
1496 | *
|
---|
1497 | * PART 3: ANALYZE SYMBOL (.SYM) FILE
|
---|
1498 | *
|
---|
1499 | ********************************************************************/
|
---|
1500 |
|
---|
1501 | /*
|
---|
1502 | *@@ dbgPrintSYMInfo:
|
---|
1503 | * this gets called by dbgPrintStack if dbgPrintDebugInfo
|
---|
1504 | * failed (because no debug code was found) to check if
|
---|
1505 | * maybe a SYM file with the same filename exists and try
|
---|
1506 | * to get the info from there.
|
---|
1507 | *
|
---|
1508 | * This gets called for every line of the stack
|
---|
1509 | * walk, but only if getting the information from
|
---|
1510 | * the debug code failed, e.g. because no debug code
|
---|
1511 | * was available for an address.
|
---|
1512 | *
|
---|
1513 | * The file pointer is in the "Source file" column
|
---|
1514 | * every time this gets called.
|
---|
1515 | *
|
---|
1516 | * New with V0.84.
|
---|
1517 | *
|
---|
1518 | * Returns 0 if reading the SYM file was successful.
|
---|
1519 | *
|
---|
1520 | *@@changed V0.9.1 (2000-01-30) [umoeller]: added return code; this used to be VOID
|
---|
1521 | */
|
---|
1522 |
|
---|
1523 | int dbgPrintSYMInfo(FILE *LogFile, // in: text log file to write to
|
---|
1524 | CHAR *SymFileName, // in: SYM file name (can be fully q'fied)
|
---|
1525 | ULONG Object,
|
---|
1526 | ULONG TrapOffset)
|
---|
1527 | {
|
---|
1528 | static FILE *SymFile;
|
---|
1529 | static MAPDEF MapDef;
|
---|
1530 | static SEGDEF SegDef;
|
---|
1531 | static SYMDEF32 SymDef32;
|
---|
1532 | static SYMDEF16 SymDef16;
|
---|
1533 | static char Buffer[256];
|
---|
1534 | static int SegNum, SymNum, LastVal;
|
---|
1535 | static unsigned long int SegOffset,
|
---|
1536 | SymOffset, SymPtrOffset;
|
---|
1537 |
|
---|
1538 | // open .SYM file
|
---|
1539 | #ifdef DEBUG_SYMDUMP // V1.0.0 (2002-08-21) [paperino]
|
---|
1540 | fprintf(LogFile,"Dump of '%s' for object %d\n",SymFileName,Object);
|
---|
1541 | #endif
|
---|
1542 | SymFile = fopen(SymFileName, "rb");
|
---|
1543 | if (SymFile == 0)
|
---|
1544 | return (2);
|
---|
1545 |
|
---|
1546 | // read in first map definition
|
---|
1547 | fread(&MapDef, sizeof(MAPDEF), 1, SymFile);
|
---|
1548 | #ifdef DEBUG_SYMDUMP
|
---|
1549 | Buffer[0] = MapDef.achModName[0];
|
---|
1550 | fread(&Buffer[1], 1, MapDef.cbModName-1, SymFile);
|
---|
1551 | Buffer[MapDef.cbModName] = 0x00;
|
---|
1552 | fprintf(LogFile,"Module name '%s'\n",Buffer);
|
---|
1553 | #endif
|
---|
1554 |
|
---|
1555 | SegOffset = SEGDEFOFFSET(MapDef);
|
---|
1556 | #ifdef DEBUG_SYMDUMP
|
---|
1557 | fprintf(LogFile,"SegOffset %0x\n",SegOffset);
|
---|
1558 | #endif
|
---|
1559 |
|
---|
1560 | // go thru all segments
|
---|
1561 | for (SegNum = 0;
|
---|
1562 | SegNum < MapDef.cSegs;
|
---|
1563 | SegNum++)
|
---|
1564 | {
|
---|
1565 | #ifdef DEBUG_SYMDUMP
|
---|
1566 | fprintf(LogFile,"Scanning segment #%d Offset %08X\n",SegNum,SegOffset);
|
---|
1567 | #endif
|
---|
1568 | if (fseek(SymFile, SegOffset, SEEK_SET))
|
---|
1569 | // seek error
|
---|
1570 | return (3);
|
---|
1571 |
|
---|
1572 | // read in segment definition
|
---|
1573 | fread(&SegDef, sizeof(SEGDEF), 1, SymFile);
|
---|
1574 | Buffer[0] = SegDef.achSegName[0];
|
---|
1575 | fread(&Buffer[1], 1, SegDef.cbSegName-1, SymFile);
|
---|
1576 | Buffer[SegDef.cbSegName] = 0x00;
|
---|
1577 | #ifdef DEBUG_SYMDUMP
|
---|
1578 | fprintf(LogFile,"Segment name '%s', number %d, flags %02x\n",Buffer,SegNum,SegDef.bFlags);
|
---|
1579 | #endif
|
---|
1580 |
|
---|
1581 | if (SegNum == Object)
|
---|
1582 | {
|
---|
1583 | // stack object found:
|
---|
1584 | Buffer[0] = 0x00;
|
---|
1585 | LastVal = 0;
|
---|
1586 |
|
---|
1587 | // go thru all symbols in this object
|
---|
1588 | #ifdef DEBUG_SYMDUMP
|
---|
1589 | fprintf(LogFile,"Scanning #%d symbols\n",SegDef.cSymbols);
|
---|
1590 | #endif
|
---|
1591 | for (SymNum = 0; SymNum < SegDef.cSymbols; SymNum++)
|
---|
1592 | {
|
---|
1593 | // fixed syms > 64 K V1.0.0 (2002-08-21) [paperino]
|
---|
1594 | if (SegDef.bFlags & 0x01)
|
---|
1595 | {
|
---|
1596 | // 32-bit symbol:
|
---|
1597 | fread(&SymDef32, sizeof(SYMDEF32), 1, SymFile);
|
---|
1598 | if (SymDef32.wSymVal > TrapOffset)
|
---|
1599 | {
|
---|
1600 | // symbol found
|
---|
1601 | fprintf(LogFile,
|
---|
1602 | "between %s + 0x%lX ",
|
---|
1603 | Buffer,
|
---|
1604 | TrapOffset - LastVal);
|
---|
1605 | /* fprintf(LogFile, "(ppLineDef: 0x%lX) ",
|
---|
1606 | LINEDEFOFFSET(SegDef)
|
---|
1607 | ); */
|
---|
1608 | fprintf(LogFile, "\n");
|
---|
1609 | }
|
---|
1610 |
|
---|
1611 | LastVal = SymDef32.wSymVal;
|
---|
1612 | Buffer[0] = SymDef32.achSymName[0];
|
---|
1613 | fread(&Buffer[1], 1, SymDef32.cbSymName-1, SymFile);
|
---|
1614 | Buffer[SymDef32.cbSymName] = 0x00;
|
---|
1615 | #ifdef DEBUG_SYMDUMP
|
---|
1616 | fprintf(LogFile,"32 Bit Symbol Address %08p <%s> \n",SymDef32.wSymVal,Buffer);
|
---|
1617 | #endif
|
---|
1618 |
|
---|
1619 | if (SymDef32.wSymVal > TrapOffset)
|
---|
1620 | {
|
---|
1621 | // symbol found, as above
|
---|
1622 | fprintf(LogFile,
|
---|
1623 | " "
|
---|
1624 | "and %s - 0x%lX ",
|
---|
1625 | Buffer,
|
---|
1626 | LastVal - TrapOffset);
|
---|
1627 | fprintf(LogFile, "\n");
|
---|
1628 | break;
|
---|
1629 | }
|
---|
1630 | }
|
---|
1631 | else
|
---|
1632 | {
|
---|
1633 | // 16-bit symbol:
|
---|
1634 | fread(&SymDef16, sizeof(SYMDEF16), 1, SymFile);
|
---|
1635 | if (SymDef16.wSymVal > TrapOffset)
|
---|
1636 | {
|
---|
1637 | fprintf(LogFile,
|
---|
1638 | "between %s + %lX\n",
|
---|
1639 | Buffer,
|
---|
1640 | TrapOffset - LastVal);
|
---|
1641 | }
|
---|
1642 | LastVal = SymDef16.wSymVal;
|
---|
1643 | Buffer[0] = SymDef16.achSymName[0];
|
---|
1644 | fread(&Buffer[1], 1, SymDef16.cbSymName-1, SymFile);
|
---|
1645 | Buffer[SymDef16.cbSymName] = 0x00;
|
---|
1646 | if (SymDef16.wSymVal > TrapOffset)
|
---|
1647 | {
|
---|
1648 | fprintf(LogFile,
|
---|
1649 | " "
|
---|
1650 | "and %s - %lX\n",
|
---|
1651 | Buffer,
|
---|
1652 | LastVal - TrapOffset);
|
---|
1653 | break;
|
---|
1654 | }
|
---|
1655 | #ifdef DEBUG_SYMDUMP
|
---|
1656 | fprintf(LogFile,"16 Bit Symbol <%s> Address %p\n",Buffer,SymDef16.wSymVal);
|
---|
1657 | #endif
|
---|
1658 | } // endif
|
---|
1659 | }
|
---|
1660 | break;
|
---|
1661 | } // endif
|
---|
1662 | SegOffset = NEXTSEGDEFOFFSET(SegDef);
|
---|
1663 | } // endwhile
|
---|
1664 | fclose(SymFile);
|
---|
1665 | return (0); // no error
|
---|
1666 | }
|
---|
1667 |
|
---|
1668 | /* ******************************************************************
|
---|
1669 | *
|
---|
1670 | * PART 4: dbgPrintStack
|
---|
1671 | *
|
---|
1672 | ********************************************************************/
|
---|
1673 |
|
---|
1674 | /*
|
---|
1675 | *@@ dbgPrintStackFrame:
|
---|
1676 | * parses and dumps one stack frame.
|
---|
1677 | * Called from excPrintStackFrame.
|
---|
1678 | *
|
---|
1679 | * This calls dbgPrintDebugInfo and, if
|
---|
1680 | * that fails, dbgPrintSYMInfo.
|
---|
1681 | *
|
---|
1682 | *@@added V0.9.2 (2000-03-10) [umoeller]
|
---|
1683 | *@@changed V0.9.3 (2000-04-10) [umoeller]: added support for non-Warp 4 SYM files
|
---|
1684 | *@@changed V0.9.3 (2000-04-26) [umoeller]: this broke Warp 4 FP 13, fixed
|
---|
1685 | */
|
---|
1686 |
|
---|
1687 | BOOL dbgPrintStackFrame(FILE *LogFile,
|
---|
1688 | PSZ pszModuleName, // in: module name (fully q'fied)
|
---|
1689 | ULONG ulObject,
|
---|
1690 | ULONG ulOffset)
|
---|
1691 | {
|
---|
1692 | APIRET arc = 0;
|
---|
1693 | // "Source file"... columns
|
---|
1694 |
|
---|
1695 | // first attempt to analyze the debug code
|
---|
1696 | arc = dbgPrintDebugInfo(LogFile,
|
---|
1697 | pszModuleName,
|
---|
1698 | ulObject,
|
---|
1699 | ulOffset);
|
---|
1700 | // if no debug code is available, analyze
|
---|
1701 | // the SYM file instead
|
---|
1702 | if (arc != NO_ERROR)
|
---|
1703 | {
|
---|
1704 | CHAR szSymName[CCHMAXPATH];
|
---|
1705 | strcpy(szSymName, pszModuleName);
|
---|
1706 | strcpy(szSymName + strlen(szSymName) - 3, "SYM");
|
---|
1707 | arc = dbgPrintSYMInfo(LogFile,
|
---|
1708 | szSymName,
|
---|
1709 | ulObject,
|
---|
1710 | ulOffset);
|
---|
1711 | if (arc != 0)
|
---|
1712 | {
|
---|
1713 | // SYM file not found in current directory:
|
---|
1714 | // check the SYM files in the \OS2 directory,
|
---|
1715 | // depending on the OS/2 version level:
|
---|
1716 | CHAR szSymFile2[CCHMAXPATH];
|
---|
1717 | PSZ pszFilename = strrchr(szSymName, '\\');
|
---|
1718 | if (pszFilename)
|
---|
1719 | {
|
---|
1720 | PSZ pszVersionDir = "WARP4";
|
---|
1721 | ULONG aulBuf[3];
|
---|
1722 |
|
---|
1723 | DosQuerySysInfo(QSV_VERSION_MAJOR, // 11
|
---|
1724 | QSV_VERSION_MINOR, // 12
|
---|
1725 | &aulBuf, sizeof(aulBuf));
|
---|
1726 | // Warp 3 is reported as 20.30
|
---|
1727 | // Warp 4 is reported as 20.40
|
---|
1728 | // Aurora is reported as 20.45
|
---|
1729 |
|
---|
1730 | if (aulBuf[0] == 20)
|
---|
1731 | {
|
---|
1732 | if (aulBuf[1] == 30)
|
---|
1733 | // Warp 3:
|
---|
1734 | pszVersionDir = "WARP3";
|
---|
1735 | else if (aulBuf[1] >= 40)
|
---|
1736 | // Warp 4 or higher:
|
---|
1737 | // (NOTE: Warp 4 FP 13 now returns 45 also,
|
---|
1738 | // but the SYM files are still in the WARP4 directory...)
|
---|
1739 | // V0.9.3 (2000-04-26) [umoeller]
|
---|
1740 | pszVersionDir = "WARP4";
|
---|
1741 | }
|
---|
1742 |
|
---|
1743 | pszFilename++;
|
---|
1744 | sprintf(szSymFile2,
|
---|
1745 | "%c:\\OS2\\PDPSI\\PMDF\\%s\\%s",
|
---|
1746 | doshQueryBootDrive(),
|
---|
1747 | pszVersionDir,
|
---|
1748 | pszFilename);
|
---|
1749 | arc = dbgPrintSYMInfo(LogFile,
|
---|
1750 | szSymFile2,
|
---|
1751 | ulObject,
|
---|
1752 | ulOffset);
|
---|
1753 |
|
---|
1754 | // V0.9.3 (2000-04-26) [umoeller]
|
---|
1755 | if ( (arc != 0) // still not found
|
---|
1756 | && (aulBuf[1] == 45) // and running Aurora or Warp 4 FP13?
|
---|
1757 | )
|
---|
1758 | {
|
---|
1759 | // Warp Server for e-Business (aka Warp 4.5):
|
---|
1760 | // we use the SYM files for the UNI kernel,
|
---|
1761 | // I have found no way to find out whether
|
---|
1762 | // we're running on an SMP kernel
|
---|
1763 | sprintf(szSymFile2,
|
---|
1764 | "%c:\\OS2\\PDPSI\\PMDF\\%s\\%s",
|
---|
1765 | doshQueryBootDrive(),
|
---|
1766 | "WARP45_U",
|
---|
1767 | pszFilename);
|
---|
1768 | arc = dbgPrintSYMInfo(LogFile,
|
---|
1769 | szSymFile2,
|
---|
1770 | ulObject,
|
---|
1771 | ulOffset);
|
---|
1772 | }
|
---|
1773 | }
|
---|
1774 | }
|
---|
1775 |
|
---|
1776 | if (arc == 2) // file not found
|
---|
1777 | fprintf(LogFile,
|
---|
1778 | "Cannot find symbol file %s\n",
|
---|
1779 | szSymName);
|
---|
1780 | else if (arc != 0)
|
---|
1781 | fprintf(LogFile,
|
---|
1782 | "Error %lu reading symbol file %s\n",
|
---|
1783 | arc,
|
---|
1784 | szSymName);
|
---|
1785 | }
|
---|
1786 |
|
---|
1787 | return (arc == NO_ERROR);
|
---|
1788 | }
|
---|
1789 |
|
---|
1790 | /*
|
---|
1791 | *@@ dbgPrintStack:
|
---|
1792 | * this takes stack data from the TIB and
|
---|
1793 | * context record data structures and tries
|
---|
1794 | * to analyse what the different stack frames
|
---|
1795 | * point to.
|
---|
1796 | *
|
---|
1797 | * For each stack frame, this calls dbgPrintDebugInfo,
|
---|
1798 | * and, if that fails, dbgPrintSYMInfo.
|
---|
1799 | *
|
---|
1800 | * New with V0.84.
|
---|
1801 | *
|
---|
1802 | *@@changed V0.9.2 (2000-03-08) [umoeller]: now searching OS2\PDPSI\PMDF for SYM files also
|
---|
1803 | */
|
---|
1804 |
|
---|
1805 | VOID dbgPrintStack(FILE *LogFile, // in: text log file to write to
|
---|
1806 | PUSHORT StackBottom,
|
---|
1807 | PUSHORT StackTop,
|
---|
1808 | PUSHORT Ebp,
|
---|
1809 | PUSHORT ExceptionAddress)
|
---|
1810 | {
|
---|
1811 | PUSHORT RetAddr = 0;
|
---|
1812 | PUSHORT LastEbp = 0;
|
---|
1813 | APIRET rc = 0;
|
---|
1814 | ULONG Size = 0,
|
---|
1815 | Attr = 0;
|
---|
1816 | USHORT Cs = 0,
|
---|
1817 | Ip = 0,
|
---|
1818 | // Bp,
|
---|
1819 | Sp = 0;
|
---|
1820 | static char Name[CCHMAXPATH];
|
---|
1821 | HMODULE hMod = 0;
|
---|
1822 | ULONG ObjNum = 0;
|
---|
1823 | ULONG Offset = 0;
|
---|
1824 | BOOL fExceptionAddress = TRUE; // Use Exception Addr 1st time thru
|
---|
1825 |
|
---|
1826 | // Note: we can't handle stacks bigger than 64K for now...
|
---|
1827 | Sp = (USHORT) (((ULONG) StackBottom) >> 16);
|
---|
1828 | // Bp = ;
|
---|
1829 |
|
---|
1830 | if (!f32bit)
|
---|
1831 | Ebp = (PUSHORT) MAKEULONG(((USHORT)(ULONG)Ebp), Sp);
|
---|
1832 |
|
---|
1833 | fprintf(LogFile, "\n\nCall stack:\n");
|
---|
1834 | fprintf(LogFile, " Source Line Nearest\n");
|
---|
1835 | fprintf(LogFile, " EBP Address Module Obj# File Numbr Public Symbol\n");
|
---|
1836 | fprintf(LogFile, " ÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄ- ÄÄÄÄÄÄÄÄ ÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄ-\n");
|
---|
1837 |
|
---|
1838 | do
|
---|
1839 | {
|
---|
1840 | Size = 10;
|
---|
1841 | rc = DosQueryMem((PVOID) (Ebp + 2), &Size, &Attr);
|
---|
1842 | if (rc != NO_ERROR)
|
---|
1843 | {
|
---|
1844 | fprintf(LogFile, "Invalid EBP %8.8lX (DosQueryMem returned %lu)\n", (ULONG)Ebp, rc);
|
---|
1845 | break;
|
---|
1846 | }
|
---|
1847 | if (!(Attr & PAG_COMMIT))
|
---|
1848 | {
|
---|
1849 | fprintf(LogFile, "Invalid EBP %8.8lX (not committed)\n", (ULONG)Ebp);
|
---|
1850 | break;
|
---|
1851 | }
|
---|
1852 | if (Size < 10)
|
---|
1853 | {
|
---|
1854 | fprintf(LogFile, "Invalid EBP %8.8lX (mem block size < 10)\n", (ULONG)Ebp);
|
---|
1855 | break;
|
---|
1856 | }
|
---|
1857 |
|
---|
1858 | if (fExceptionAddress)
|
---|
1859 | RetAddr = ExceptionAddress;
|
---|
1860 | else
|
---|
1861 | RetAddr = (PUSHORT) (*((PULONG) (Ebp + 2)));
|
---|
1862 |
|
---|
1863 | if (RetAddr == (PUSHORT) 0x00000053)
|
---|
1864 | {
|
---|
1865 | // For some reason there's a "return address" of 0x53 following
|
---|
1866 | // EBP on the stack and we have to adjust EBP by 44 bytes to get
|
---|
1867 | // at the real return address. This has something to do with
|
---|
1868 | // thunking from 32bits to 16bits...
|
---|
1869 | // Serious kludge, and it's probably dependent on versions of C(++)
|
---|
1870 | // runtime or OS, but it works for now!
|
---|
1871 | Ebp += 22;
|
---|
1872 | RetAddr = (PUSHORT) (*((PULONG) (Ebp + 2)));
|
---|
1873 | }
|
---|
1874 |
|
---|
1875 | // Get the (possibly) 16bit CS and IP
|
---|
1876 | if (fExceptionAddress)
|
---|
1877 | {
|
---|
1878 | Cs = (USHORT) (((ULONG) ExceptionAddress) >> 16);
|
---|
1879 | Ip = (USHORT) (ULONG) ExceptionAddress;
|
---|
1880 | }
|
---|
1881 | else
|
---|
1882 | {
|
---|
1883 | Cs = *(Ebp + 2);
|
---|
1884 | Ip = *(Ebp + 1);
|
---|
1885 | }
|
---|
1886 |
|
---|
1887 | // if the return address points to the stack then it's really just
|
---|
1888 | // a pointer to the return address (UGH!).
|
---|
1889 | if ( (USHORT) (((ULONG) RetAddr) >> 16) == Sp
|
---|
1890 | )
|
---|
1891 | RetAddr = (PUSHORT) (*((PULONG) RetAddr));
|
---|
1892 |
|
---|
1893 | if (Ip == 0 && *Ebp == 0)
|
---|
1894 | {
|
---|
1895 | // End of the stack so these are both shifted by 2 bytes:
|
---|
1896 | Cs = *(Ebp + 3);
|
---|
1897 | Ip = *(Ebp + 2);
|
---|
1898 | }
|
---|
1899 |
|
---|
1900 | // 16bit programs have on the stack:
|
---|
1901 | // BP:IP:CS
|
---|
1902 | // where CS may be thunked
|
---|
1903 | //
|
---|
1904 | // in dump swapped
|
---|
1905 | // BP IP CS BP CS IP
|
---|
1906 | // 4677 53B5 F7D0 7746 D0F7 B553
|
---|
1907 | //
|
---|
1908 | // 32bit programs have:
|
---|
1909 | // EBP:EIP
|
---|
1910 | // and you'd have something like this (with SP added) (not
|
---|
1911 | // accurate values)
|
---|
1912 | //
|
---|
1913 | // in dump swapped
|
---|
1914 | // EBP EIP EBP EIP
|
---|
1915 | // 4677 2900 53B5 F7D0 0029 7746 D0F7 B553
|
---|
1916 | //
|
---|
1917 | // So the basic difference is that 32bit programs have a 32bit
|
---|
1918 | // EBP and we can attempt to determine whether we have a 32bit
|
---|
1919 | // EBP by checking to see if its 'selector' is the same as SP.
|
---|
1920 | // Note that this technique limits us to checking stacks < 64K.
|
---|
1921 | //
|
---|
1922 | // Soooo, if IP (which maps into the same USHORT as the swapped
|
---|
1923 | // stack page in EBP) doesn't point to the stack (i.e. it could
|
---|
1924 | // be a 16bit IP) then see if CS is valid (as is or thunked).
|
---|
1925 | //
|
---|
1926 | // Note that there's the possibility of a 16bit return address
|
---|
1927 | // that has an offset that's the same as SP so we'll think it's
|
---|
1928 | // a 32bit return address and won't be able to successfully resolve
|
---|
1929 | // its details.
|
---|
1930 | if (Ip != Sp)
|
---|
1931 | {
|
---|
1932 | if (DOS16SIZESEG(Cs, &Size) == NO_ERROR)
|
---|
1933 | {
|
---|
1934 | RetAddr = (USHORT * _Seg16) MAKEULONG(Ip, Cs);
|
---|
1935 | f32bit = FALSE;
|
---|
1936 | }
|
---|
1937 | else if (DOS16SIZESEG((Cs << 3) + 7, &Size) == NO_ERROR)
|
---|
1938 | {
|
---|
1939 | Cs = (Cs << 3) + 7;
|
---|
1940 | RetAddr = (USHORT * _Seg16) MAKEULONG(Ip, Cs);
|
---|
1941 | f32bit = FALSE;
|
---|
1942 | }
|
---|
1943 | else
|
---|
1944 | f32bit = TRUE;
|
---|
1945 | }
|
---|
1946 | else
|
---|
1947 | f32bit = TRUE;
|
---|
1948 |
|
---|
1949 |
|
---|
1950 | // "EBP" column
|
---|
1951 | if (fExceptionAddress)
|
---|
1952 | fprintf(LogFile, " Trap -> ");
|
---|
1953 | else
|
---|
1954 | fprintf(LogFile, " %8.8lX ", (ULONG)Ebp);
|
---|
1955 |
|
---|
1956 | // "Address" column
|
---|
1957 | if (f32bit)
|
---|
1958 | fprintf(LogFile, ":%8.8lX ", (ULONG)RetAddr);
|
---|
1959 | else
|
---|
1960 | fprintf(LogFile, "%04.04X:%04.04X ", Cs, Ip);
|
---|
1961 |
|
---|
1962 | // Version check omitted; the following requires
|
---|
1963 | // OS/2 2.10 or later (*UM)
|
---|
1964 | // if (Version[0] >= 20 && Version[1] >= 10)
|
---|
1965 | {
|
---|
1966 | // Make a 'tick' sound to let the user know we're still alive
|
---|
1967 | DosBeep(2000, 10);
|
---|
1968 |
|
---|
1969 | Size = 10; // Inserted by Kim Rasmussen 26/06 1996 to avoid error 87 when Size is 0
|
---|
1970 |
|
---|
1971 | // "Module"/"Object" columns
|
---|
1972 | rc = DosQueryMem((PVOID) RetAddr, &Size, &Attr);
|
---|
1973 | if (rc != NO_ERROR || !(Attr & PAG_COMMIT))
|
---|
1974 | {
|
---|
1975 | fprintf(LogFile, "Invalid RetAddr: %8.8lX\n", (ULONG)RetAddr);
|
---|
1976 | break; // avoid infinite loops
|
---|
1977 | }
|
---|
1978 | else
|
---|
1979 | {
|
---|
1980 | rc = DOSQUERYMODFROMEIP(&hMod,
|
---|
1981 | &ObjNum,
|
---|
1982 | sizeof(Name), Name,
|
---|
1983 | &Offset,
|
---|
1984 | (PVOID)RetAddr);
|
---|
1985 | if ( (rc == NO_ERROR)
|
---|
1986 | // && (ObjNum != -1)
|
---|
1987 | )
|
---|
1988 | {
|
---|
1989 | // static char szJunk[_MAX_FNAME];
|
---|
1990 | static char szName[_MAX_FNAME];
|
---|
1991 |
|
---|
1992 | DosQueryModuleName(hMod, sizeof(Name), Name);
|
---|
1993 | // _splitpath(Name, szJunk, szJunk, szName, szJunk);
|
---|
1994 |
|
---|
1995 | // print module and object
|
---|
1996 | fprintf(LogFile, "%-8s %04lX ", szName, ObjNum + 1);
|
---|
1997 |
|
---|
1998 | if (strlen(Name) > 3)
|
---|
1999 | {
|
---|
2000 | dbgPrintStackFrame(LogFile,
|
---|
2001 | Name,
|
---|
2002 | ObjNum,
|
---|
2003 | Offset);
|
---|
2004 | }
|
---|
2005 | }
|
---|
2006 | else
|
---|
2007 | fprintf(LogFile,
|
---|
2008 | "DosQueryModFromEIP failed, returned %lu\n",
|
---|
2009 | rc);
|
---|
2010 | }
|
---|
2011 | }
|
---|
2012 |
|
---|
2013 | if ( ((*Ebp) == 0)
|
---|
2014 | && ((*Ebp + 1) == 0)
|
---|
2015 | )
|
---|
2016 | {
|
---|
2017 | fprintf(LogFile, "End of call stack\n");
|
---|
2018 | break;
|
---|
2019 | }
|
---|
2020 |
|
---|
2021 | if (!fExceptionAddress)
|
---|
2022 | {
|
---|
2023 | LastEbp = Ebp;
|
---|
2024 | #if 0
|
---|
2025 | Ebp = (PUSHORT) MAKEULONG(Bp, Sp);
|
---|
2026 | #else // Inserted by Kim Rasmussen 26/06 1996 to allow big stacks
|
---|
2027 | if (f32bit)
|
---|
2028 | Ebp = (PUSHORT) *(PULONG) LastEbp;
|
---|
2029 | else
|
---|
2030 | Ebp = (PUSHORT) MAKEULONG((*Ebp), Sp);
|
---|
2031 | #endif
|
---|
2032 | if (f32bit)
|
---|
2033 | {
|
---|
2034 | dbgPrintVariables(LogFile, (ULONG) Ebp);
|
---|
2035 | } // endif
|
---|
2036 |
|
---|
2037 | if (Ebp < LastEbp)
|
---|
2038 | {
|
---|
2039 | fprintf(LogFile, "... lost stack chain - new EBP below previous\n");
|
---|
2040 | break;
|
---|
2041 | }
|
---|
2042 | }
|
---|
2043 | else
|
---|
2044 | fExceptionAddress = FALSE;
|
---|
2045 |
|
---|
2046 | Size = 4;
|
---|
2047 | rc = DosQueryMem((PVOID) Ebp, &Size, &Attr);
|
---|
2048 | if ((rc != NO_ERROR) || (Size < 4))
|
---|
2049 | {
|
---|
2050 | fprintf(LogFile, "... lost stack chain - invalid EBP: %8.8lX\n", (ULONG)Ebp);
|
---|
2051 | break;
|
---|
2052 | }
|
---|
2053 | } while (TRUE);
|
---|
2054 |
|
---|
2055 | fprintf(LogFile, "\n");
|
---|
2056 | }
|
---|
2057 |
|
---|