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