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