source: trunk/classes/c/c_common/except.c

Last change on this file was 207, checked in by gyoung, 6 months ago

Move Trap/Debug log to LOGFILES directory

File size: 77.6 KB
Line 
1/**********************************************************************/
2/* */
3/* EXCEPTQ */
4/* */
5/* DLL containing an exception handler for gathering trap information */
6/* This DLL dumps all important debugging Data and is accessible */
7/* from both 16 bit and 32 bits programs */
8/**********************************************************************/
9/* Version: 2.2 | Marc Fiammante (FIAMMANT at LGEPROFS) */
10/* | La Gaude FRANCE */
11/* | Internet: fiammante@vnet.ibm.com */
12/* Version: 5.0 | John Currier (JCURRIER at CLTVM1) */
13/* | Internet: currier@vnet.ibm.com */
14/* Version: 6.0 | Kim Rasmussen (krasmus@ibm.net) */
15/* | Denmark */
16/* Version: 6.1 | Anthony Cruise (CRUISE at YKTVMH) */
17/* | Watson Research */
18/* Version: 6.2 | John Currier (JCURRIER at CLTVM1) */
19/* | Internet: currier@vnet.ibm.com */
20/* Version: 6.3 | Kim Rasmussen (kr@belle.dk) */
21/* | Denmark */
22/* | Marc Fiammante (FIAMMANT at LGEPROFS) */
23/* | La Gaude FRANCE */
24/* | Internet: fiammante@vnet.ibm.com */
25/* Version: 6.4 | Kim Rasmussen (kr@belle.dk) */
26/* | Denmark - http://www.belle.dk/kr/ */
27/**********************************************************************/
28/* */
29/**********************************************************************/
30/* History: */
31/* -------- */
32/* */
33/* created: Marc Fiammante December 1992 */
34/* changed: John Currier August 1994 */
35/* changed: Kim Rasmussen, May 1995 */
36/* Dump of auto-variables added (32-bit only) */
37/* changed: Anthony Cruise, May 1995 */
38/* Do not dump duplicate lines (32-bit only) */
39/* fixed : Marc Fiammante thanks to Bill Siddall */
40/* Dump of auto-variables wrong values */
41/* fixed : John Currier fix stack thunk on non fatal exceptions */
42/* fixed DosQueryMem Size test on return */
43/* fixed : Marc Fiammante find stack bottom from top to bottom */
44/* avoid traps on disassemble. */
45/* changed: Support for VisualAge C added (new debug format) */
46/* */
47/**********************************************************************/
48/**********************************************************************/
49/* */
50/* Modified by Chris Wohlgemuth 2002 for use with Audio/Data-CD- */
51/* Creator. */
52/* */
53/**********************************************************************/
54#define INCL_BASE
55#define INCL_TYPES
56#define INCL_DOSEXCEPTIONS
57#define INCL_DOSSEMAPHORES /* Semaphore values */
58
59#include <os2.h>
60
61#include <ctype.h>
62#include <stdlib.h>
63#include <stdio.h>
64#include <string.h>
65#include <time.h>
66#include "sym.h"
67#include "omf.h"
68
69#ifndef DWORD
70#define DWORD unsigned long
71#endif
72#ifndef WORD
73#define WORD unsigned short
74#endif
75#pragma stack16(512)
76#define HF_STDERR 2
77CHAR *ProcessName = "DEBUGGEE.EXE";
78FILE *hTrap;
79static BOOL f32bit = TRUE;
80struct debug_buffer
81 {
82 ULONG Pid; /* Debuggee Process ID */
83 ULONG Tid; /* Debuggee Thread ID */
84 LONG Cmd; /* Command or Notification */
85 LONG Value; /* Generic Data Value */
86 ULONG Addr; /* Debuggee Address */
87 ULONG Buffer; /* Debugger Buffer Address */
88 ULONG Len; /* Length of Range */
89 ULONG Index; /* Generic Identifier Index */
90 ULONG MTE; /* Module Handle */
91 ULONG EAX; /* Register Set */
92 ULONG ECX;
93 ULONG EDX;
94 ULONG EBX;
95 ULONG ESP;
96 ULONG EBP;
97 ULONG ESI;
98 ULONG EDI;
99 ULONG EFlags;
100 ULONG EIP;
101 ULONG CSLim; /* Byte Granular Limits */
102 ULONG CSBase; /* Byte Granular Base */
103 UCHAR CSAcc; /* Access Bytes */
104 UCHAR CSAtr; /* Attribute Bytes */
105 USHORT CS;
106 ULONG DSLim;
107 ULONG DSBase;
108 UCHAR DSAcc;
109 UCHAR DSAtr;
110 USHORT DS;
111 ULONG ESLim;
112 ULONG ESBase;
113 UCHAR ESAcc;
114 UCHAR ESAtr;
115 USHORT ES;
116 ULONG FSLim;
117 ULONG FSBase;
118 UCHAR FSAcc;
119 UCHAR FSAtr;
120 USHORT FS;
121 ULONG GSLim;
122 ULONG GSBase;
123 UCHAR GSAcc;
124 UCHAR GSAtr;
125 USHORT GS;
126 ULONG SSLim;
127 ULONG SSBase;
128 UCHAR SSAcc;
129 UCHAR SSAtr;
130 USHORT SS;
131} DbgBuf;
132
133/* CW
134#define DBG_O_OBJMTE 0x10000000L*/
135#define DBG_C_NumToAddr 13
136#define DBG_C_AddrToObject 28
137#define DBG_C_Connect 21
138#define DBG_L_386 1
139RESULTCODES ReturnCodes;
140UCHAR LoadError[40]; /*DosExecPGM buffer */
141USHORT Passes;
142UCHAR Translate[17];
143UCHAR OldStuff[16];
144
145#ifdef USE_DOSDEBUG
146void GetObjects(struct debug_buffer * pDbgBuf,HMODULE hMte,PSZ pName);
147#endif
148
149VOID ListModules(VOID);
150void CheckMem(PVOID Ptr,PSZ MemoryName);
151/* Better New WalkStack From John Currier */
152static void WalkStack(PUSHORT StackBottom,PUSHORT StackTop,PUSHORT Ebp,PUSHORT ExceptionAddress);
153int Read16CodeView(int fh,int TrapSeg,int TrapOff,CHAR * FileName);
154int Read32PmDebug(int fh,int TrapSeg,int TrapOff,CHAR * FileName);
155APIRET GetLineNum(CHAR * FileName, ULONG Object,ULONG TrapOffset);
156void GetSymbol(CHAR * SymFileName, ULONG Object,ULONG TrapOffset);
157void print_vars(ULONG stackofs);
158
159ULONG func_ofs;
160ULONG pubfunc_ofs;
161char func_name[128];
162ULONG var_ofs = 0;
163
164struct {
165 BYTE name[128];
166 ULONG stack_offset;
167 USHORT type_idx;
168} autovar_def[100];
169
170HMODULE hMod;
171ULONG ObjNum;
172ULONG Offset;
173
174/*-------------------------------------*/
175CHAR Buffer[CCHMAXPATH];
176
177typedef ULONG * _Seg16 PULONG16;
178APIRET16 APIENTRY16 DOS16SIZESEG( USHORT Seg , PULONG16 Size);
179typedef APIRET16 (APIENTRY16 _PFN16)();
180ULONG APIENTRY DosSelToFlat(ULONG);
181/*-------------------------------------*/
182
183/*- DosQProcStatus interface ----------*/
184APIRET16 APIENTRY16 DOSQPROCSTATUS( ULONG * _Seg16 pBuf, USHORT cbBuf);
185#define CONVERT(fp,QSsel) MAKEP((QSsel),OFFSETOF(fp))
186#pragma pack(1)
187/* Global Data Section */
188typedef struct qsGrec_s {
189 ULONG cThrds; /* number of threads in use */
190 ULONG Reserved1;
191 ULONG Reserved2;
192}qsGrec_t;
193
194#define PADSHORT USHORT pad_sh
195#define PADCHAR UCHAR pad_ch
196
197/* Thread Record structure * Holds all per thread information. */
198typedef struct qsTrec_s {
199 ULONG RecType; /* Record Type */
200 /* Thread rectype = 100 */
201 USHORT tid; /* thread ID */
202 USHORT slot; /* "unique" thread slot number */
203 ULONG sleepid; /* sleep id thread is sleeping on */
204 ULONG priority; /* thread priority */
205 ULONG systime; /* thread system time */
206 ULONG usertime; /* thread user time */
207 UCHAR state; /* thread state */
208 PADCHAR;
209 PADSHORT;
210} qsTrec_t;
211
212/* Process and Thread Data Section */
213typedef struct qsPrec_s {
214 ULONG RecType; /* type of record being processed */
215 /* process rectype = 1 */
216 qsTrec_t * pThrdRec; /* ptr to 1st thread rec for this prc*/
217 USHORT pid; /* process ID */
218 USHORT ppid; /* parent process ID */
219 ULONG type; /* process type */
220 ULONG stat; /* process status */
221 ULONG sgid; /* process screen group */
222 USHORT hMte; /* program module handle for process */
223 USHORT cTCB; /* # of TCBs in use in process */
224 ULONG Reserved1;
225 void * Reserved2;
226 USHORT c16Sem; /*# of 16 bit system sems in use by proc*/
227 USHORT cLib; /* number of runtime linked libraries */
228 USHORT cShrMem; /* number of shared memory handles */
229 USHORT Reserved3;
230 USHORT * p16SemRec; /*ptr to head of 16 bit sem inf for proc*/
231 USHORT * pLibRec; /*ptr to list of runtime lib in use by */
232 /*process*/
233 USHORT * pShrMemRec; /*ptr to list of shared mem handles in */
234 /*use by process*/
235 USHORT * Reserved4;
236} qsPrec_t;
237
238/* 16 Bit System Semaphore Section */
239typedef struct qsS16Headrec_s {
240 ULONG RecType; /* semaphore rectype = 3 */
241 ULONG Reserved1; /* overlays NextRec of 1st qsS16rec_t */
242 ULONG Reserved2;
243 ULONG S16TblOff; /* index of first semaphore,SEE PSTAT OUTPUT*/
244 /* System Semaphore Information Section */
245} qsS16Headrec_t;
246/* 16 bit System Semaphore Header Record Structure */
247typedef struct qsS16rec_s {
248 ULONG NextRec; /* offset to next record in buffer */
249 UINT s_SysSemOwner ; /* thread owning this semaphore */
250 UCHAR s_SysSemFlag ; /* system semaphore flag bit field */
251 UCHAR s_SysSemRefCnt ; /* number of references to this */
252 /* system semaphore */
253 UCHAR s_SysSemProcCnt ; /*number of requests by sem owner */
254 UCHAR Reserved1;
255 ULONG Reserved2;
256 UINT Reserved3;
257 CHAR SemName[1]; /* start of semaphore name string */
258} qsS16rec_t;
259
260/* Executable Module Section */
261typedef struct qsLrec_s {
262 void * pNextRec; /* pointer to next record in buffer */
263 USHORT hmte; /* handle for this mte */
264 USHORT Reserved1; /* Reserved */
265 ULONG ctImpMod; /* # of imported modules in table */
266 ULONG Reserved2; /* Reserved */
267/* qsLObjrec_t * Reserved3; Reserved */
268 ULONG * Reserved3; /* Reserved */
269 UCHAR * pName; /* ptr to name string following stru*/
270} qsLrec_t;
271
272/* Shared Memory Segment Section */
273typedef struct qsMrec_s {
274 struct qsMrec_s *MemNextRec; /* offset to next record in buffer */
275 USHORT hmem; /* handle for shared memory */
276 USHORT sel; /* shared memory selector */
277 USHORT refcnt; /* reference count */
278 CHAR Memname[1]; /* start of shared memory name string */
279} qsMrec_t;
280
281/* Pointer Record Section */
282typedef struct qsPtrRec_s {
283 qsGrec_t * pGlobalRec; /* ptr to the global data section */
284 qsPrec_t * pProcRec; /* ptr to process record section */
285 qsS16Headrec_t * p16SemRec; /* ptr to 16 bit sem section */
286 void * Reserved; /* a reserved area */
287 qsMrec_t * pShrMemRec; /* ptr to shared mem section */
288 qsLrec_t * pLibRec; /*ptr to exe module record section*/
289} qsPtrRec_t;
290
291/*-------------------------*/
292ULONG * pBuf,*pTemp;
293USHORT Selector;
294qsPtrRec_t * pRec;
295qsLrec_t * pLib;
296qsMrec_t * pShrMemRec; /* ptr to shared mem section */
297qsPrec_t * pProc;
298qsTrec_t * pThread;
299ULONG ListedThreads=0;
300APIRET16 APIENTRY16 DOS16ALLOCSEG(
301 USHORT cbSize, /* number of bytes requested */
302 USHORT * _Seg16 pSel, /* sector allocated (returned) */
303 USHORT fsAlloc); /* sharing attributes of the allocated segment */
304
305typedef struct
306 {
307 short int ilen; /* Instruction length */
308 long rref; /* Value of any IP relative storage reference */
309 unsigned short sel; /* Selector of any CS:eIP storage reference. */
310 long poff; /* eIP value of any CS:eIP storage reference. */
311 char longoper; /* YES/NO value. Is instr in 32 bit operand mode? **/
312 char longaddr; /* YES/NO value. Is instr in 32 bit address mode? **/
313 char buf[40]; /* String holding disassembled instruction **/
314 } * _Seg16 RETURN_FROM_DISASM;
315
316RETURN_FROM_DISASM CDECL16 DISASM( CHAR * _Seg16 Source, USHORT IPvalue,USHORT segsize );
317RETURN_FROM_DISASM AsmLine;
318
319char *SourceBuffer=0;
320static USHORT BigSeg;
321static ULONG Version[2];
322
323BYTE *type_name[] = {
324 "8 bit signed ",
325 "16 bit signed ",
326 "32 bit signed ",
327 "Unknown (0x83) ",
328 "8 bit unsigned ",
329 "16 bit unsigned ",
330 "32 bit unsigned ",
331 "Unknown (0x87) ",
332 "32 bit real ",
333 "64 bit real ",
334 "80 bit real ",
335 "Unknown (0x8B) ",
336 "64 bit complex ",
337 "128 bit complex ",
338 "160 bit complex ",
339 "Unknown (0x8F) ",
340 "8 bit boolean ",
341 "16 bit boolean ",
342 "32 bit boolean ",
343 "Unknown (0x93) ",
344 "8 bit character ",
345 "16 bit characters ",
346 "32 bit characters ",
347 "void ",
348 "15 bit unsigned ",
349 "24 bit unsigned ",
350 "31 bit unsigned ",
351 "Unknown (0x9B) ",
352 "Unknown (0x9C) ",
353 "Unknown (0x9D) ",
354 "Unknown (0x9E) ",
355 "Unknown (0x9F) ",
356 "near pointer to 8 bit signed ",
357 "near pointer to 16 bit signed ",
358 "near pointer to 32 bit signed ",
359 "Unknown (0xA3) ",
360 "near pointer to 8 bit unsigned ",
361 "near pointer to 16 bit unsigned ",
362 "near pointer to 32 bit unsigned ",
363 "Unknown (0xA7) ",
364 "near pointer to 32 bit real ",
365 "near pointer to 64 bit real ",
366 "near pointer to 80 bit real ",
367 "Unknown (0xAB) ",
368 "near pointer to 64 bit complex ",
369 "near pointer to 128 bit complex ",
370 "near pointer to 160 bit complex ",
371 "Unknown (0xAF) ",
372 "near pointer to 8 bit boolean ",
373 "near pointer to 16 bit boolean ",
374 "near pointer to 32 bit boolean ",
375 "Unknown (0xB3) ",
376 "near pointer to 8 bit character ",
377 "near pointer to 16 bit characters",
378 "near pointer to 32 bit characters",
379 "near pointer to void ",
380 "near pointer to 15 bit unsigned ",
381 "near pointer to 24 bit unsigned ",
382 "near pointer to 31 bit unsigned ",
383 "Unknown (0xBB) ",
384 "Unknown (0xBC) ",
385 "Unknown (0xBD) ",
386 "Unknown (0xBE) ",
387 "Unknown (0xBF) ",
388 "far pointer to 8 bit signed ",
389 "far pointer to 16 bit signed ",
390 "far pointer to 32 bit signed ",
391 "Unknown (0xC3) ",
392 "far pointer to 8 bit unsigned ",
393 "far pointer to 16 bit unsigned ",
394 "far pointer to 32 bit unsigned ",
395 "Unknown (0xC7) ",
396 "far pointer to 32 bit real ",
397 "far pointer to 64 bit real ",
398 "far pointer to 80 bit real ",
399 "Unknown (0xCB) ",
400 "far pointer to 64 bit complex ",
401 "far pointer to 128 bit complex ",
402 "far pointer to 160 bit complex ",
403 "Unknown (0xCF) ",
404 "far pointer to 8 bit boolean ",
405 "far pointer to 16 bit boolean ",
406 "far pointer to 32 bit boolean ",
407 "Unknown (0xD3) ",
408 "far pointer to 8 bit character ",
409 "far pointer to 16 bit characters ",
410 "far pointer to 32 bit characters ",
411 "far pointer to void ",
412 "far pointer to 15 bit unsigned ",
413 "far pointer to 24 bit unsigned ",
414 "far pointer to 31 bit unsigned ",
415};
416
417/*-- --*/
418/*-------------------------------------*/
419
420typedef _PFN16 * _Seg16 PFN16;
421/*-- --*/
422static BOOL InForceExit =FALSE;
423
424/*-------------------------------------*/
425ULONG APIENTRY HandleFatalException (PEXCEPTIONREPORTRECORD pERepRec,
426 PEXCEPTIONREGISTRATIONRECORD pERegRec,
427 PCONTEXTRECORD pCtxRec,
428 PVOID p);
429
430// Thanks to John Currier :
431// Do not call 16 bit code in myHandler function to prevent call
432// to __EDCThunkProlog and problems is guard page exception handling
433// Also reduce the stack size to 1K for true 16 bit calls.
434// 16 bit calls thunk will now only occur on fatal exceptions
435#pragma stack16(1024)
436
437#include "except.h"
438
439static char _GetBootDriveLetter(void)
440{
441 ULONG ulSysValue;
442
443 if(!DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,&ulSysValue,sizeof(ulSysValue)))
444 return 'a'+ulSysValue-1;
445
446 return 'c';
447}
448
449ULONG _System excHandler(PEXCEPTIONREPORTRECORD pERepRec,
450 PLOCALEXCEPTSTRUCT pRegRec2,
451 // PREGREC2 pRegRec2,
452 PCONTEXTRECORD pCtxRec,
453 PVOID pv)
454{
455 ULONG rc = XCPT_CONTINUE_SEARCH;
456#if 0
457 CHAR TrapFile[CCHMAXPATH];
458 CHAR *LogPath;
459#endif
460 if (pERepRec->fHandlerFlags & EH_EXIT_UNWIND)
461 return (XCPT_CONTINUE_SEARCH);
462 if (pERepRec->fHandlerFlags & EH_UNWINDING)
463 return (XCPT_CONTINUE_SEARCH);
464 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
465 return (XCPT_CONTINUE_SEARCH);
466
467#if 0
468 LogPath = getenv( "LOGFILES" );
469 if (!LogPath)
470 sprintf(TrapFile,"%c:\\%s",_GetBootDriveLetter(), EXCEPTION_LOGFILE_NAME);
471 else
472 sprintf(TrapFile,"%s\\%s",LogPath, EXCEPTION_LOGFILE_NAME);
473 hTrap=fopen(TrapFile,"a");
474 fprintf(hTrap,"fHandlerFlags: %x, ExceptionNum: %x\n",pERepRec->fHandlerFlags, pERepRec->ExceptionNum);
475 fclose(hTrap);
476#endif
477 if ((pERepRec->ExceptionNum & XCPT_SEVERITY_CODE) == XCPT_FATAL_EXCEPTION)
478 {
479 DosBeep(5000,30);
480 DosBeep(4000,30);
481 DosBeep(3000,30);
482 DosBeep(4000,30);
483 DosBeep(5000,30);
484
485 if (pERepRec->ExceptionNum != XCPT_PROCESS_TERMINATE &&
486 pERepRec->ExceptionNum != XCPT_UNWIND &&
487 pERepRec->ExceptionNum != XCPT_SIGNAL &&
488 pERepRec->ExceptionNum != XCPT_BREAKPOINT &&
489 pERepRec->ExceptionNum != XCPT_SINGLE_STEP &&
490 pERepRec->ExceptionNum != XCPT_ASYNC_PROCESS_TERMINATE)
491 {
492 // If any of the above conditionals fail then we have to handle
493 // the fatal trap.
494 rc = HandleFatalException(pERepRec, (PEXCEPTIONREGISTRATIONRECORD) pRegRec2, pCtxRec, pv);
495 longjmp(pRegRec2->jmpThread, pERepRec->ExceptionNum);
496 // longjmp(pERegRec->jmpThread, pERepRec->ExceptionNum);
497 }
498 }
499 return rc;
500}
501#if 0
502ULONG APIENTRY myHandler (PEXCEPTIONREPORTRECORD pERepRec,
503 PEXCEPTIONREGISTRATIONRECORD pERegRec,
504 PCONTEXTRECORD pCtxRec,
505 PVOID p)
506{
507 ULONG rc = XCPT_CONTINUE_SEARCH;
508
509 if (pERepRec->fHandlerFlags & EH_EXIT_UNWIND)
510 return (XCPT_CONTINUE_SEARCH);
511 if (pERepRec->fHandlerFlags & EH_UNWINDING)
512 return (XCPT_CONTINUE_SEARCH);
513 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
514 return (XCPT_CONTINUE_SEARCH);
515
516 if ((pERepRec->ExceptionNum & XCPT_SEVERITY_CODE) == XCPT_FATAL_EXCEPTION)
517 {
518 if (pERepRec->ExceptionNum != XCPT_PROCESS_TERMINATE &&
519 pERepRec->ExceptionNum != XCPT_UNWIND &&
520 pERepRec->ExceptionNum != XCPT_SIGNAL &&
521 pERepRec->ExceptionNum != XCPT_BREAKPOINT &&
522 pERepRec->ExceptionNum != XCPT_SINGLE_STEP &&
523 pERepRec->ExceptionNum != XCPT_ASYNC_PROCESS_TERMINATE)
524 {
525 // If any of the above conditionals fail then we have to handle
526 // the fatal trap.
527 rc = HandleFatalException(pERepRec, pERegRec, pCtxRec, p);
528 longjmp(pERegRec->jmpThread, pERepRec->ExceptionNum);
529 }
530 }
531 return rc;
532}
533#endif
534
535
536ULONG APIENTRY HandleFatalException (PEXCEPTIONREPORTRECORD pERepRec,
537 PEXCEPTIONREGISTRATIONRECORD pERegRec,
538 PCONTEXTRECORD pCtxRec,
539 PVOID p)
540{
541 PCHAR SegPtr;
542 PUSHORT StackPtr;
543 PUSHORT ValidStackBottom;
544 PUCHAR TestStackBottom;
545 PUCHAR cStackPtr;
546 ULONG Size,Flags,Attr,CSSize;
547 APIRET rc;
548 APIRET semrc;
549 APIRET16 rc16;
550 PTIB ptib;
551 PPIB ppib;
552 USHORT Count;
553 ULONG Nest;
554 CHAR TrapFile[CCHMAXPATH];
555 CHAR *LogPath;
556 struct debug_buffer DbgBuf;
557 static CHAR Name[CCHMAXPATH];
558
559 /* Do not recurse into Trapper (John Currier) */
560 /* Not necessary anymore because nested calls are catched now CW */
561 static BOOL fAlreadyTrapped = FALSE;
562
563
564 if (InForceExit) {
565 return (XCPT_CONTINUE_SEARCH);
566 } /* endif */
567
568 if ((pERepRec->ExceptionNum&XCPT_SEVERITY_CODE)==XCPT_FATAL_EXCEPTION)
569 {
570
571 if ((pERepRec->ExceptionNum!=XCPT_PROCESS_TERMINATE)&&
572 (pERepRec->ExceptionNum!=XCPT_UNWIND)&&
573 (pERepRec->ExceptionNum!=XCPT_SIGNAL)&&
574 (pERepRec->ExceptionNum!=XCPT_ASYNC_PROCESS_TERMINATE)) {
575 DosEnterMustComplete(&Nest);
576
577 LogPath = getenv( "LOGFILES" );
578 if (!LogPath)
579 sprintf(TrapFile,"%c:\\%s",_GetBootDriveLetter(), EXCEPTION_LOGFILE_NAME);
580 else
581 sprintf(TrapFile,"%s\\%s",LogPath, EXCEPTION_LOGFILE_NAME);
582
583 hTrap=fopen(TrapFile,"a");
584 if (hTrap==NULL)
585 hTrap=stdout;
586
587 // rc=DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR );
588
589 setbuf( hTrap, NULL);/* Unbuffered stream */
590 /* fprintf(hTrap,"A trap occurred in Audio/Data-CD-Creator\n");*/
591 fprintf(hTrap,"----------------------------------------\n\n");
592 fprintf(hTrap,"Exception %8.8lX Occurred",pERepRec->ExceptionNum);
593 fprintf(hTrap," at %s ",_strtime(Buffer));
594 fprintf(hTrap," %s\n\n",_strdate(Buffer));
595 if ( pERepRec->ExceptionNum == XCPT_ACCESS_VIOLATION)
596 {
597 switch (pERepRec->ExceptionInfo[0]) {
598 case XCPT_READ_ACCESS:
599 fprintf(hTrap,"Invalid read address %8.8lX\n",pERepRec->ExceptionInfo[1]);
600 break;
601 case XCPT_WRITE_ACCESS:
602 fprintf(hTrap,"Invalid write address %8.8lX\n",pERepRec->ExceptionInfo[1]);
603 break;
604 case XCPT_SPACE_ACCESS:
605 /* Thanks to John Currier */
606 /* It looks like this is off by one... */
607 fprintf(hTrap,"Invalid Selector: %8.8p",
608 pERepRec->ExceptionInfo[1] ?
609 pERepRec->ExceptionInfo[1] + 1 : 0);
610 break;
611 case XCPT_LIMIT_ACCESS:
612 fprintf(hTrap,"Limit access fault\n");
613 break;
614 case XCPT_UNKNOWN_ACCESS:
615 fprintf(hTrap,"Unknown access fault\n");
616 break;
617 break;
618 default:
619 fprintf(hTrap,"Other Unknown access fault\n");
620 } /* endswitch */
621 } /* endif XCPT_ACCESS_VIOLATION */
622 else if( pERepRec->ExceptionNum == XCPT_INTEGER_DIVIDE_BY_ZERO)
623 {
624 fprintf(hTrap,"Division by zero.\n");
625 }
626 else if( pERepRec->ExceptionNum == XCPT_ILLEGAL_INSTRUCTION)
627 {
628 fprintf(hTrap,"Illegal instruction.\n");
629 }
630 else if( pERepRec->ExceptionNum == XCPT_PRIVILEGED_INSTRUCTION)
631 {
632 fprintf(hTrap,"Privileged instruction.\n");
633 }
634 else if( pERepRec->ExceptionNum == XCPT_INTEGER_OVERFLOW)
635 {
636 fprintf(hTrap,"Integer overflow.\n");
637 }
638
639 /* John Currier's recursion prevention */
640 fprintf(hTrap,"\n\n");
641#if 0 /* Not necessary anymore because nested calls are catched now CW */
642 if (fAlreadyTrapped)
643 {
644 fprintf(hTrap, "Exception Handler Trapped...aborting evaluation!\n");
645 if (hTrap != stderr)
646 fclose(hTrap);
647 DosExitMustComplete(&Nest);
648
649 /* DosUnsetExceptionHandler(pERegRec); */
650 return (XCPT_CONTINUE_SEARCH);
651 }
652#endif
653
654 fAlreadyTrapped = TRUE;
655 /* end John Currier's recursion prevention */
656 rc = DosQuerySysInfo(QSV_VERSION_MAJOR,QSV_VERSION_MINOR,
657 Version,sizeof(Version));
658 if ((rc==0)&&
659 (Version[0]>=20) &&
660 (Version[1]>=10) ) {
661 /* version must be over 2.1 for DosQueryModFromEIP */
662 fprintf(hTrap,"OS/2 Version %d.%d\n",Version[0]/10,Version[1]);
663 rc=DosQueryModFromEIP( &hMod, &ObjNum, CCHMAXPATH,
664 Name, &Offset, (ULONG) pERepRec->ExceptionAddress);
665 if (rc==0) {
666 fprintf(hTrap,"Failing code module internal name : %s\n",Name);
667 rc=DosQueryModuleName(hMod,CCHMAXPATH, Name);
668 fprintf(hTrap,"Failing code module file name : %s\n",Name);
669 fprintf(hTrap,"Failing code Object # %d at Offset %x \n",ObjNum+1,Offset);
670 if (strlen(Name)>3) {
671 fprintf(hTrap," File Line# Public Symbol\n");
672 fprintf(hTrap," ÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄ- ÄÄÄÄÄÄÄÄÄÄÄÄ-\n");
673 rc =GetLineNum(Name,ObjNum,Offset);
674
675 if (rc == 0)
676 print_vars(pCtxRec->ctx_RegEbp);
677
678 /* if no codeview try with symbol files */
679 if (rc!=0) {
680 strcpy(Name+strlen(Name)-3,"SYM"); /* Get Sym File name */
681 GetSymbol(Name,ObjNum,Offset);
682 } /* endif */
683 } /* endif */
684 fprintf(hTrap,"\n");
685 } else {
686 fprintf(hTrap,"Invalid execution address\n");
687 } /* endif */
688 } /* endif */
689 if ( (pCtxRec->ContextFlags) & CONTEXT_CONTROL ) {
690 void * _Seg16 Ptr16;
691 BigSeg=((pCtxRec->ctx_RegEip)>0x00010000);
692 if (BigSeg) {
693 /* Avoid traps in 16:16 Disasm DLL */
694 if (DosAllocMem((PPVOID)&SourceBuffer,0x100,fALLOC)==0) {
695 Size=0x100;
696 rc=DosQueryMem((PVOID)pCtxRec->ctx_RegEip,&Size,&Attr);
697 if (Attr&(PAG_READ|PAG_EXECUTE)) {
698 memcpy(SourceBuffer,(PVOID)pCtxRec->ctx_RegEip,Size);
699#if 0 /*CW*/
700 AsmLine= DISASM( SourceBuffer,
701 (USHORT)pCtxRec->ctx_RegEip, BigSeg );
702 fprintf(hTrap,"\n Failing instruction at CS:EIP : %4.4X:%8.8X is %s\n\n",
703 pCtxRec->ctx_SegCs,
704 pCtxRec->ctx_RegEip,AsmLine->buf);
705#endif
706 } /* endif */
707 }
708 } else {
709 if (CSSize>pCtxRec->ctx_RegEip) {
710#if 0 /*CW*/
711 AsmLine= DISASM(MAKE16P(pCtxRec->ctx_SegCs,
712 pCtxRec->ctx_RegEip),
713 (USHORT)pCtxRec->ctx_RegEip, BigSeg );
714 fprintf(hTrap,"\n Failing instruction at CS:IP : %4.4X:%4.4X is %s\n\n",
715 pCtxRec->ctx_SegCs,
716 pCtxRec->ctx_RegEip,AsmLine->buf);
717#endif
718 } else {
719 fprintf(hTrap,"Invalid execution address\n");
720 } /* endif */
721 } /* endif */
722
723 rc=DosGetInfoBlocks(&ptib,&ppib);
724 if (rc==NO_ERROR) {
725 static CHAR Format[10];
726
727 fprintf(hTrap,"\nThread slot %lu , Id %lu , priority %p\n",
728 ptib->tib_ordinal,
729 ptib->tib_ptib2->tib2_ultid ,
730 ptib->tib_ptib2->tib2_ulpri );
731 Ptr16=ptib->tib_pstack;
732 sprintf(Format,"%8.8lX",Ptr16);
733 fprintf(hTrap,"Stack Bottom : %8.8lX (%4.4s:%4.4s) ;", ptib->tib_pstack ,Format,Format+4);
734 Ptr16=ptib->tib_pstacklimit;
735 sprintf(Format,"%8.8lX",Ptr16);
736 fprintf(hTrap,"Stack Top : %8.8lX (%4.4s:%4.4s) \n",ptib->tib_pstacklimit,Format,Format+4);
737 fprintf(hTrap,"Process Id : %lu ", ppib->pib_ulpid);
738 rc=DosQueryModuleName(ppib->pib_hmte,CCHMAXPATH, Name);
739 if (rc==NO_ERROR) {
740 fprintf(hTrap,".EXE name : %s\n",Name);
741 } else {
742 fprintf(hTrap,".EXE name : ??????\n");
743 } /* endif */
744 /* Better New WalkStack From John Currier */
745 WalkStack((PUSHORT)ptib->tib_pstack,
746 (PUSHORT)ptib->tib_pstacklimit,
747 (PUSHORT)pCtxRec->ctx_RegEbp,
748 (PUSHORT)pERepRec->ExceptionAddress);
749 ListModules();
750 Count=0;
751 } /* endif */
752 } /* endif */
753
754 if (hTrap!=stdout) {
755 fclose(hTrap);
756 }
757 DosExitMustComplete(&Nest);
758
759 /* rc=DosUnsetExceptionHandler(pERegRec); CW */
760 } /* endif */
761 } else {
762 /* printf("Other non fatal exception %8.8lx ",pERepRec->ExceptionNum); */
763 /* printf("At address %8.8lx\n",pERepRec->ExceptionAddress); */
764 } /* endif */
765 return (XCPT_CONTINUE_SEARCH);
766}
767
768#if 0 /*CW */
769APIRET16 APIENTRY16 SETEXCEPT(PEXCEPTIONREGISTRATIONRECORD _Seg16 pxcpthand)
770 {
771 APIRET rc;
772
773 rc=DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR );
774 printf("Set error rc %ld\n",rc);
775 pxcpthand->prev_structure=0;
776 pxcpthand->ExceptionHandler=&myHandler;
777 rc=DosSetExceptionHandler(pxcpthand);
778 printf("Set except rc %ld\n",rc);
779 return rc;/* CW */
780}
781APIRET16 APIENTRY16 UNSETEXCEPT(PEXCEPTIONREGISTRATIONRECORD _Seg16 pxcpthand)
782 {
783 APIRET rc;
784 rc=DosUnsetExceptionHandler(pxcpthand);
785 printf("Unset except rc %ld\n",rc);
786 return rc;/* CW */
787}
788#endif
789
790VOID ListModules() {
791 APIRET rc;
792 APIRET16 rc16;
793#ifdef USE_DOSDEBUG
794 /**----------------------------------***/
795#else
796#if MORE_INFO_WANTED
797 PVOID BaseAddress;
798 ULONG RegionSize;
799 ULONG AllocationFlags;
800 HMODULE LastModule;
801 static CHAR Name[CCHMAXPATH];
802 ULONG Size;
803 LastModule=0;
804 BaseAddress=(PVOID)0x10000;
805 RegionSize =0x3FFFFFFF;
806 fprintf(hTrap,"ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\n");
807 fprintf(hTrap,"³ List of currently accessed modules (DLLs) object addresses ³");
808 rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
809 while (rc==NO_ERROR) {
810 if ((AllocationFlags&PAG_EXECUTE)&&
811 (AllocationFlags&PAG_BASE)) {
812 rc=DosQueryModFromEIP( &hMod, &ObjNum, CCHMAXPATH,
813 Name, &Offset, BaseAddress);
814 if (rc==0) {
815 if (hMod!=LastModule) {
816 rc=DosQueryModuleName(hMod,CCHMAXPATH, Name);
817 fprintf(hTrap,"\nÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ\n");
818 fprintf(hTrap,"³ Module %-48.48s Handle %8.8d ³\n",Name,hMod);
819 fprintf(hTrap,"³ Object Number Address Length Flags Type ³");
820 LastModule=hMod;
821 } /* endif */
822 fprintf(hTrap,"\n³ % 6.6d %8.8lX %8.8lX %8.8lX ",ObjNum,
823 BaseAddress, RegionSize, AllocationFlags);
824 rc16 =DOS16SIZESEG( SELECTOROF(BaseAddress), &Size);
825 if (rc16==0) {
826 fprintf(hTrap," - 16:16 Selector %4.4hX ³",SELECTOROF((PVOID)BaseAddress));
827 } else {
828 fprintf(hTrap," - 32 Bits ³");
829 } /* endif */
830 }
831 }
832 if (AllocationFlags&PAG_FREE) RegionSize =0x10000;
833 RegionSize +=0x0FFF;
834 RegionSize &=0xFFFFF000;
835 BaseAddress=(PVOID)(((PCHAR)BaseAddress)+RegionSize);
836 RegionSize=((PCHAR)0x3FFFFFFF)-(PCHAR)BaseAddress;
837 rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
838 while ((rc==ERROR_INVALID_ADDRESS)||
839 (rc==ERROR_NO_OBJECT)) {
840 BaseAddress=(PVOID)(((PCHAR)BaseAddress)+0x10000);
841 if (BaseAddress>(PVOID)0x3FFFFFFF) {
842 break;
843 } /* endif */
844 RegionSize=((PCHAR)0x3FFFFFFF)-(PCHAR)BaseAddress;
845 rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
846 } /* endwhile */
847 if (BaseAddress>(PVOID)0x3FFFFFFF) {
848 break;
849 } /* endif */
850 } /* endwhile */
851 fprintf(hTrap,"\nÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\n");
852#endif
853#endif
854}
855
856
857void CheckMem(PVOID Ptr,PSZ MemoryName) {
858 APIRET rc;
859 ULONG Size,Flags,Attr;
860 Size=1;
861 rc=DosQueryMem(Ptr,&Size,&Attr);
862 if (rc!=NO_ERROR) {
863 fprintf(hTrap, "³ %3.3s does not point to valid memory ³\n",MemoryName);
864 } else {
865 if (Attr&PAG_FREE) {
866 fprintf(hTrap, "³ %3.3s points to unallocated memory ³\n",MemoryName);
867 } else {
868 if ((Attr&PAG_COMMIT)==0x0U) {
869 fprintf(hTrap,"³ %3.3s points to uncommited memory ³\n",MemoryName);
870 } /* endif */
871 if ((Attr&PAG_WRITE)==0x0U) {
872 fprintf(hTrap,"³ %3.3s points to unwritable memory ³\n",MemoryName);
873 } /* endif */
874 if ((Attr&PAG_READ)==0x0U) {
875 fprintf(hTrap,"³ %3.3s points to unreadable memory ³\n",MemoryName);
876 } /* endif */
877 } /* endif */
878 } /* endif */
879}
880
881PUSHORT Convert(USHORT * _Seg16 p16) {
882 return p16;
883}
884
885/* Better New WalkStack From John Currier */
886static void WalkStack(PUSHORT StackBottom, PUSHORT StackTop, PUSHORT Ebp,
887 PUSHORT ExceptionAddress)
888{
889 PUSHORT RetAddr;
890 PUSHORT LastEbp;
891 APIRET rc;
892 ULONG Size,Attr;
893 USHORT Cs,Ip,Bp,Sp;
894 static char Name[CCHMAXPATH];
895 HMODULE hMod;
896 ULONG ObjNum;
897 ULONG Offset;
898 BOOL fExceptionAddress = TRUE; // Use Exception Addr 1st time thru
899
900 // Note: we can't handle stacks bigger than 64K for now...
901 Sp = (USHORT)(((ULONG)StackBottom) >> 16);
902 Bp = (USHORT)(ULONG)Ebp;
903
904 if (!f32bit)
905 Ebp = (PUSHORT)MAKEULONG(Bp, Sp);
906
907 fprintf(hTrap,"\nCall Stack:\n");
908 fprintf(hTrap," Source Line Nearest\n");
909 fprintf(hTrap," EBP Address Module Obj# File Numbr Public Symbol\n");
910 fprintf(hTrap," ÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄ- ÄÄÄÄÄÄÄÄ ÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄ- ÄÄÄÄÄÄÄÄÄÄÄÄ-\n");
911
912 do
913 {
914 Size = 10;
915 rc = DosQueryMem((PVOID)(Ebp+2), &Size, &Attr);
916 if (rc != NO_ERROR || !(Attr & PAG_COMMIT) || (Size<10) )
917 {
918 fprintf(hTrap,"Invalid EBP: %8.8p\n",Ebp);
919 break;
920 }
921
922 if (fExceptionAddress)
923 RetAddr = ExceptionAddress;
924 else
925 RetAddr = (PUSHORT)(*((PULONG)(Ebp+2)));
926
927 if (RetAddr == (PUSHORT)0x00000053)
928 {
929 // For some reason there's a "return address" of 0x53 following
930 // EBP on the stack and we have to adjust EBP by 44 bytes to get
931 // at the real return address. This has something to do with
932 // thunking from 32bits to 16bits...
933 // Serious kludge, and it's probably dependent on versions of C(++)
934 // runtime or OS, but it works for now!
935 Ebp += 22;
936 RetAddr = (PUSHORT)(*((PULONG)(Ebp+2)));
937 }
938
939 // Get the (possibly) 16bit CS and IP
940 if (fExceptionAddress)
941 {
942 Cs = (USHORT)(((ULONG)ExceptionAddress) >> 16);
943 Ip = (USHORT)(ULONG)ExceptionAddress;
944 }
945 else
946 {
947 Cs = *(Ebp+2);
948 Ip = *(Ebp+1);
949 }
950
951 // if the return address points to the stack then it's really just
952 // a pointer to the return address (UGH!).
953 if ((USHORT)(((ULONG)RetAddr) >> 16) == Sp)
954 RetAddr = (PUSHORT)(*((PULONG)RetAddr));
955
956 if (Ip == 0 && *Ebp == 0)
957 {
958 // End of the stack so these are both shifted by 2 bytes:
959 Cs = *(Ebp+3);
960 Ip = *(Ebp+2);
961 }
962
963 // 16bit programs have on the stack:
964 // BP:IP:CS
965 // where CS may be thunked
966 //
967 // in dump swapped
968 // BP IP CS BP CS IP
969 // 4677 53B5 F7D0 7746 D0F7 B553
970 //
971 // 32bit programs have:
972 // EBP:EIP
973 // and you'd have something like this (with SP added) (not
974 // accurate values)
975 //
976 // in dump swapped
977 // EBP EIP EBP EIP
978 // 4677 2900 53B5 F7D0 0029 7746 D0F7 B553
979 //
980 // So the basic difference is that 32bit programs have a 32bit
981 // EBP and we can attempt to determine whether we have a 32bit
982 // EBP by checking to see if its 'selector' is the same as SP.
983 // Note that this technique limits us to checking stacks < 64K.
984 //
985 // Soooo, if IP (which maps into the same USHORT as the swapped
986 // stack page in EBP) doesn't point to the stack (i.e. it could
987 // be a 16bit IP) then see if CS is valid (as is or thunked).
988 //
989 // Note that there's the possibility of a 16bit return address
990 // that has an offset that's the same as SP so we'll think it's
991 // a 32bit return address and won't be able to successfully resolve
992 // its details.
993 if (Ip != Sp)
994 {
995 if (DOS16SIZESEG(Cs, &Size) == NO_ERROR)
996 {
997 RetAddr = (USHORT * _Seg16)MAKEULONG(Ip, Cs);
998 f32bit = FALSE;
999 }
1000 else if (DOS16SIZESEG((Cs << 3) + 7, &Size) == NO_ERROR)
1001 {
1002 Cs = (Cs << 3) + 7;
1003 RetAddr = (USHORT * _Seg16)MAKEULONG(Ip, Cs);
1004 f32bit = FALSE;
1005 }
1006 else
1007 f32bit = TRUE;
1008 }
1009 else
1010 f32bit = TRUE;
1011
1012
1013 if (fExceptionAddress)
1014 fprintf(hTrap," Trap ->");
1015 else
1016 fprintf(hTrap," %8.8p", Ebp);
1017
1018 if (f32bit)
1019 fprintf(hTrap," :%8.8p", RetAddr);
1020 else
1021 fprintf(hTrap," %04.04X:%04.04X", Cs, Ip);
1022
1023 if (Version[0] >= 20 && Version[1] >= 10)
1024 {
1025 // Make a 'tick' sound to let the user know we're still alive
1026 DosBeep(2000, 1);
1027
1028 Size = 10; /* Inserted by Kim Rasmussen 26/06 1996 to avoid error 87 when Size is 0 */
1029
1030 rc = DosQueryMem((PVOID)RetAddr, &Size, &Attr);
1031 if (rc != NO_ERROR || !(Attr & PAG_COMMIT))
1032 {
1033 fprintf(hTrap,"Invalid RetAddr: %8.8p\n",RetAddr);
1034 break; /* avoid infinite loops */
1035 } else {
1036 rc = DosQueryModFromEIP(&hMod, &ObjNum, sizeof(Name),
1037 Name, &Offset, (ULONG) RetAddr);
1038 if (rc == NO_ERROR && ObjNum != -1)
1039 {
1040 static char szJunk[_MAX_FNAME];
1041 static char szName[_MAX_FNAME];
1042 DosQueryModuleName(hMod, sizeof(Name), Name);
1043 _splitpath(Name, szJunk, szJunk, szName, szJunk);
1044 fprintf(hTrap," %-8s %04X", szName, ObjNum+1);
1045
1046 if (strlen(Name) > 3)
1047 {
1048 rc = GetLineNum(Name, ObjNum, Offset);
1049 /* if no codeview try with symbol files */
1050 if (rc != NO_ERROR)
1051 {
1052 strcpy(Name+strlen(Name)-3,"SYM");
1053 GetSymbol(Name,ObjNum,Offset);
1054 }
1055 }
1056 }
1057 else
1058 {
1059 fprintf(hTrap," *Unknown*");
1060 }
1061 }
1062 }
1063
1064 fprintf(hTrap,"\n");
1065
1066 Bp = *Ebp;
1067 if (Bp == 0 && (*Ebp+1) == 0)
1068 {
1069 fprintf(hTrap,"End of Call Stack\n");
1070 break;
1071 }
1072
1073 if (!fExceptionAddress)
1074 {
1075 LastEbp = Ebp;
1076#if 0
1077 Ebp = (PUSHORT)MAKEULONG(Bp, Sp);
1078#else /* Inserted by Kim Rasmussen 26/06 1996 to allow big stacks */
1079 if (f32bit)
1080 Ebp = (PUSHORT)*(PULONG)LastEbp;
1081 else
1082 Ebp = (PUSHORT)MAKEULONG(Bp, Sp);
1083#endif
1084 if (f32bit) {
1085 print_vars((ULONG)Ebp);
1086 } /* endif */
1087
1088 if (Ebp < LastEbp)
1089 {
1090 fprintf(hTrap,"Lost Stack chain - new EBP below previous\n");
1091 break;
1092 }
1093 }
1094 else
1095 fExceptionAddress = FALSE;
1096
1097 Size = 4;
1098 rc = DosQueryMem((PVOID)Ebp, &Size, &Attr);
1099 if ((rc != NO_ERROR)||(Size<4))
1100 {
1101 fprintf(hTrap,"Lost Stack chain - invalid EBP: %8.8p\n", Ebp);
1102 break;
1103 }
1104 } while (TRUE);
1105
1106 fprintf(hTrap,"\n");
1107}
1108
1109void GetSymbol(CHAR * SymFileName, ULONG Object,ULONG TrapOffset)
1110{
1111 static FILE * SymFile;
1112 static MAPDEF MapDef;
1113 static SEGDEF SegDef;
1114 static SEGDEF *pSegDef;
1115 static SYMDEF32 SymDef32;
1116 static SYMDEF16 SymDef16;
1117 static char Buffer[256];
1118 static int SegNum,SymNum,LastVal;
1119 static unsigned long int SegOffset,SymOffset,SymPtrOffset;
1120 SymFile=fopen(SymFileName,"rb");
1121 if (SymFile==0) {
1122 /*fprintf(hTrap,"Could not open symbol file %s\n",SymFileName);*/
1123 return;
1124 } /* endif */
1125 fread(&MapDef,sizeof(MAPDEF),1,SymFile);
1126 SegOffset= SEGDEFOFFSET(MapDef);
1127 for (SegNum=0;SegNum<MapDef.cSegs;SegNum++) {
1128 /* printf("Scanning segment #%d Offset %4.4hX\n",SegNum+1,SegOffset); */
1129 if (fseek(SymFile,SegOffset,SEEK_SET)) {
1130 fprintf(hTrap,"Seek error ");
1131 return;
1132 }
1133 fread(&SegDef,sizeof(SEGDEF),1,SymFile);
1134 if (SegNum==Object) {
1135 Buffer[0]=0x00;
1136 LastVal=0;
1137 for (SymNum=0;SymNum<SegDef.cSymbols;SymNum++) {
1138 SymPtrOffset=SYMDEFOFFSET(SegOffset,SegDef,SymNum);
1139 fseek(SymFile,SymPtrOffset,SEEK_SET);
1140 fread(&SymOffset,sizeof(unsigned short int),1,SymFile);
1141 fseek(SymFile,SymOffset+SegOffset,SEEK_SET);
1142 if (SegDef.bFlags&0x01) {
1143 fread(&SymDef32,sizeof(SYMDEF32),1,SymFile);
1144 if (SymDef32.wSymVal>TrapOffset) {
1145 fprintf(hTrap,"between %s + %X ",Buffer,TrapOffset-LastVal);
1146 }
1147 LastVal=SymDef32.wSymVal;
1148 Buffer[0]= SymDef32.achSymName[0];
1149 fread(&Buffer[1],1,SymDef32.cbSymName,SymFile);
1150 Buffer[SymDef32.cbSymName]=0x00;
1151 if (SymDef32.wSymVal>TrapOffset) {
1152 fprintf(hTrap,"and %s - %X\n",Buffer,LastVal-TrapOffset);
1153 break;
1154 }
1155 /*printf("32 Bit Symbol <%s> Address %p\n",Buffer,SymDef32.wSymVal);*/
1156 } else {
1157 fread(&SymDef16,sizeof(SYMDEF16),1,SymFile);
1158 if (SymDef16.wSymVal>TrapOffset) {
1159 fprintf(hTrap,"between %s + %X ",Buffer,TrapOffset-LastVal);
1160 }
1161 LastVal=SymDef16.wSymVal;
1162 Buffer[0]=SymDef16.achSymName[0];
1163 fread(&Buffer[1],1,SymDef16.cbSymName,SymFile);
1164 Buffer[SymDef16.cbSymName]=0x00;
1165 if (SymDef16.wSymVal>TrapOffset) {
1166 fprintf(hTrap,"and %s - %X\n",Buffer,LastVal-TrapOffset);
1167 break;
1168 }
1169 /*printf("16 Bit Symbol <%s> Address %p\n",Buffer,SymDef16.wSymVal);*/
1170 } /* endif */
1171 }
1172 break;
1173 } /* endif */
1174 SegOffset=NEXTSEGDEFOFFSET(SegDef);
1175 } /* endwhile */
1176 fclose(SymFile);
1177}
1178
1179#include <newexe.h>
1180#define FOR_EXEHDR 1 /* avoid define conflicts between newexe.h and exe386.h */
1181#ifndef DWORD
1182#define DWORD long int
1183#endif
1184#ifndef WORD
1185#define WORD short int
1186#endif
1187#include <exe386.h>
1188#include <fcntl.h>
1189#include <sys\stat.h>
1190#include <share.h>
1191#include <io.h>
1192/* ------------------------------------------------------------------ */
1193/* Last 8 bytes of 16:16 file when CODEVIEW debugging info is present */
1194#pragma pack(1)
1195 struct _eodbug
1196 {
1197 unsigned short dbug; /* 'NB' signature */
1198 unsigned short ver; /* version */
1199 unsigned long dfaBase; /* size of codeview info */
1200 } eodbug;
1201
1202#define DBUGSIG 0x424E
1203#define SSTMODULES 0x0101
1204#define SSTPUBLICS 0x0102
1205#define SSTTYPES 0x0103
1206#define SSTSYMBOLS 0x0104
1207#define SSTSRCLINES 0x0105
1208#define SSTLIBRARIES 0x0106
1209#define SSTSRCLINES2 0x0109
1210#define SSTSRCLINES32 0x010B
1211
1212 struct _base
1213 {
1214 unsigned short dbug; /* 'NB' signature */
1215 unsigned short ver; /* version */
1216 unsigned long lfoDir; /* file offset to dir entries */
1217 } base;
1218
1219 struct ssDir
1220 {
1221 unsigned short sst; /* SubSection Type */
1222 unsigned short modindex; /* Module index number */
1223 unsigned long lfoStart; /* Start of section */
1224 unsigned short cb; /* Size of section */
1225 } ;
1226
1227 struct ssDir32
1228 {
1229 unsigned short sst; /* SubSection Type */
1230 unsigned short modindex; /* Module index number */
1231 unsigned long lfoStart; /* Start of section */
1232 unsigned long cb; /* Size of section */
1233 } ;
1234
1235 struct ssModule
1236 {
1237 unsigned short csBase; /* code segment base */
1238 unsigned short csOff; /* code segment offset */
1239 unsigned short csLen; /* code segment length */
1240 unsigned short ovrNum; /* overlay number */
1241 unsigned short indxSS; /* Index into sstLib or 0 */
1242 unsigned short reserved;
1243 char csize; /* size of prefix string */
1244 } ssmod;
1245
1246 struct ssModule32
1247 {
1248 unsigned short csBase; /* code segment base */
1249 unsigned long csOff; /* code segment offset */
1250 unsigned long csLen; /* code segment length */
1251 unsigned long ovrNum; /* overlay number */
1252 unsigned short indxSS; /* Index into sstLib or 0 */
1253 unsigned long reserved;
1254 char csize; /* size of prefix string */
1255 } ssmod32;
1256
1257 struct ssPublic
1258 {
1259 unsigned short offset;
1260 unsigned short segment;
1261 unsigned short type;
1262 char csize;
1263 } sspub;
1264
1265 struct ssPublic32
1266 {
1267 unsigned long offset;
1268 unsigned short segment;
1269 unsigned short type;
1270 char csize;
1271 } sspub32;
1272
1273typedef struct _SSLINEENTRY32 {
1274 unsigned short LineNum;
1275 unsigned short FileNum;
1276 unsigned long Offset;
1277} SSLINEENTRY32;
1278typedef struct _FIRSTLINEENTRY32 {
1279 unsigned short LineNum;
1280 unsigned char entry_type;
1281 unsigned char reserved;
1282 unsigned short numlines;
1283 unsigned short segnum;
1284} FIRSTLINEENTRY32;
1285
1286typedef struct _SSFILENUM32 {
1287 unsigned long first_displayable; /* Not used */
1288 unsigned long number_displayable; /* Not used */
1289 unsigned long file_count; /* number of source files */
1290} SSFILENUM32;
1291
1292 struct DbugRec { /* debug info struct ure used in linked * list */
1293 struct DbugRec /*far*/ *pnext; /* next node *//* 013 */
1294 char /*far*/ *SourceFile; /* source file name *013 */
1295 unsigned short TypeOfProgram; /* dll or exe *014* */
1296 unsigned short LineNumber; /* line number in source file */
1297 unsigned short OffSet; /* offset into loaded module */
1298 unsigned short Selector; /* code segment 014 */
1299 unsigned short OpCode; /* Opcode replaced with BreakPt */
1300 unsigned long Count; /* count over Break Point */
1301};
1302
1303/*typedef struct DbugRec DBUG, far * DBUGPTR; */ /* 013 */
1304
1305char szNrPub[128];
1306char szNrLine[128];
1307char szNrFile[128];
1308 struct new_seg *pseg;
1309 struct o32_obj *pobj; /* Flat .EXE object table entry */
1310 struct ssDir *pDirTab;
1311 struct ssDir32 *pDirTab32;
1312unsigned char *pEntTab;
1313unsigned long lfaBase;
1314#pragma pack()
1315/* ------------------------------------------------------------------ */
1316
1317APIRET GetLineNum(CHAR * FileName, ULONG Object,ULONG TrapOffset) {
1318 APIRET rc;
1319 int ModuleFile;
1320 static struct exe_hdr old;
1321 static struct new_exe new1;
1322 static struct e32_exe e32;
1323 strcpy(szNrPub," N/A ");
1324 strcpy(szNrLine," N/A ");
1325 strcpy(szNrFile," ");
1326 ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
1327 if (ModuleFile!=-1) {
1328 /* Read old Exe header */
1329 if (read( ModuleFile ,(void *)&old,64)==-1L) {
1330 fprintf(hTrap,"Could Not Read old exe header %d\n",errno);
1331 close(ModuleFile);
1332 return 2;
1333 }
1334 /* Seek to new Exe header */
1335 if (lseek(ModuleFile,(long)E_LFANEW(old),SEEK_SET)==-1L) {
1336 fprintf(hTrap,"Could Not seek to new exe header %d\n",errno);
1337 close(ModuleFile);
1338 return 3;
1339 }
1340 if (read( ModuleFile ,(void *)&new1,64)==-1L) {
1341 fprintf(hTrap,"Could Not read new exe header %d\n",errno);
1342 close(ModuleFile);
1343 return 4;
1344 }
1345 /* Check EXE signature */
1346 if (NE_MAGIC(new1)==E32MAGIC) {
1347 /* Flat 32 executable */
1348 rc=Read32PmDebug(ModuleFile,Object+1,TrapOffset,FileName);
1349 if (rc==0) {
1350 fprintf(hTrap,"%s",szNrFile);
1351 fprintf(hTrap,"%s",szNrLine);
1352 fprintf(hTrap,"%s",szNrPub);
1353 } /* endif */
1354 close(ModuleFile);
1355 /* rc !=0 try with DBG file */
1356 if (rc!=0) {
1357 strcpy(FileName+strlen(FileName)-3,"DBG"); /* Build DBG File name */
1358 ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
1359 if (ModuleFile!=-1) {
1360 rc=Read32PmDebug(ModuleFile,Object+1,TrapOffset,FileName);
1361 if (rc==0) {
1362 fprintf(hTrap,"%s",szNrFile);
1363 fprintf(hTrap,"%s",szNrLine);
1364 fprintf(hTrap,"%s",szNrPub);
1365 } /* endif */
1366 close(ModuleFile);
1367 }
1368 } /* endif */
1369 return rc;
1370 } else {
1371 if (NE_MAGIC(new1)==NEMAGIC) {
1372 /* 16:16 executable */
1373 if ((pseg = ( struct new_seg *) calloc(NE_CSEG(new1),sizeof( struct new_seg)))==NULL) {
1374 fprintf(hTrap,"Out of memory!");
1375 close(ModuleFile);
1376 return -1;
1377 }
1378 if (lseek(ModuleFile,E_LFANEW(old)+NE_SEGTAB(new1),SEEK_SET)==-1L) {
1379 fprintf(hTrap,"Error %u seeking segment table in %s\n",errno,FileName);
1380 free(pseg);
1381 close(ModuleFile);
1382 return 9;
1383 }
1384
1385 if (read(ModuleFile,(void *)pseg,NE_CSEG(new1)*sizeof( struct new_seg))==-1) {
1386 fprintf(hTrap,"Error %u reading segment table from %s\n",errno,FileName);
1387 free(pseg);
1388 close(ModuleFile);
1389 return 10;
1390 }
1391 rc=Read16CodeView(ModuleFile,Object+1,TrapOffset,FileName);
1392 if (rc==0) {
1393 fprintf(hTrap,"%s",szNrFile);
1394 fprintf(hTrap,"%s",szNrLine);
1395 fprintf(hTrap,"%s",szNrPub);
1396 } /* endif */
1397 free(pseg);
1398 close(ModuleFile);
1399 /* rc !=0 try with DBG file */
1400 if (rc!=0) {
1401 strcpy(FileName+strlen(FileName)-3,"DBG"); /* Build DBG File name */
1402 ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
1403 if (ModuleFile!=-1) {
1404 rc=Read16CodeView(ModuleFile,Object+1,TrapOffset,FileName);
1405 if (rc==0) {
1406 fprintf(hTrap,"%s",szNrFile);
1407 fprintf(hTrap,"%s",szNrLine);
1408 fprintf(hTrap,"%s",szNrPub);
1409 } /* endif */
1410 close(ModuleFile);
1411 }
1412 } /* endif */
1413 return rc;
1414
1415 } else {
1416 /* Unknown executable */
1417 fprintf(hTrap,"Could Not find exe signature");
1418 close(ModuleFile);
1419 return 11;
1420 }
1421 }
1422 /* Read new Exe header */
1423 } else {
1424 fprintf(hTrap,"Could Not open Module File %d",errno);
1425 return 1;
1426 } /* endif */
1427 return 0;
1428}
1429char fname[128],ModName[80];
1430char ename[128],dummy[128];
1431
1432int Read16CodeView(int fh,int TrapSeg,int TrapOff,CHAR * FileName) {
1433 static unsigned short int offset,NrPublic,NrLine,NrEntry,numdir,namelen,numlines,line;
1434 static int ModIndex;
1435 static int bytesread,i,j;
1436 ModIndex=0;
1437 /* See if any CODEVIEW info */
1438 if (lseek(fh,-8L,SEEK_END)==-1) {
1439 fprintf(hTrap,"Error %u seeking CodeView table in %s\n",errno,FileName);
1440 return(18);
1441 }
1442
1443 if (read(fh,(void *)&eodbug,8)==-1) {
1444 fprintf(hTrap,"Error %u reading debug info from %s\n",errno,FileName);
1445 return(19);
1446 }
1447 if (eodbug.dbug!=DBUGSIG) {
1448 /* fprintf(hTrap,"\nNo CodeView information stored.\n"); */
1449 return(100);
1450 }
1451
1452 if ((lfaBase=lseek(fh,-eodbug.dfaBase,SEEK_END))==-1L) {
1453 fprintf(hTrap,"Error %u seeking base codeview data in %s\n",errno,FileName);
1454 return(20);
1455 }
1456
1457 if (read(fh,(void *)&base,8)==-1) {
1458 fprintf(hTrap,"Error %u reading base codeview data in %s\n",errno,FileName);
1459 return(21);
1460 }
1461
1462 if (lseek(fh,base.lfoDir-8,SEEK_CUR)==-1) {
1463 fprintf(hTrap,"Error %u seeking dir codeview data in %s\n",errno,FileName);
1464 return(22);
1465 }
1466
1467 if (read(fh,(void *)&numdir,2)==-1) {
1468 fprintf(hTrap,"Error %u reading dir codeview data in %s\n",errno,FileName);
1469 return(23);
1470 }
1471
1472 /* Read dir table into buffer */
1473 if (( pDirTab = ( struct ssDir *) calloc(numdir,sizeof( struct ssDir)))==NULL) {
1474 fprintf(hTrap,"Out of memory!");
1475 return(-1);
1476 }
1477
1478 if (read(fh,(void *)pDirTab,numdir*sizeof( struct ssDir))==-1) {
1479 fprintf(hTrap,"Error %u reading codeview dir table from %s\n",errno,FileName);
1480 free(pDirTab);
1481 return(24);
1482 }
1483
1484 i=0;
1485 while (i<numdir) {
1486 if (pDirTab[i].sst!=SSTMODULES) {
1487 i++;
1488 continue;
1489 }
1490 NrPublic=0x0;
1491 NrLine=0x0;
1492 /* point to subsection */
1493 lseek(fh, pDirTab[i].lfoStart + lfaBase, SEEK_SET);
1494 read(fh,(void *)&ssmod.csBase,sizeof(ssmod));
1495 read(fh,(void *)ModName,(unsigned)ssmod.csize);
1496 ModIndex=pDirTab[i].modindex;
1497 ModName[ssmod.csize]='\0';
1498 i++;
1499 while (pDirTab[i].modindex ==ModIndex && i<numdir) {
1500 /* point to subsection */
1501 lseek(fh, pDirTab[i].lfoStart + lfaBase, SEEK_SET);
1502 switch(pDirTab[i].sst) {
1503 case SSTPUBLICS:
1504 bytesread=0;
1505 while (bytesread < pDirTab[i].cb) {
1506 bytesread += read(fh,(void *)&sspub.offset,sizeof(sspub));
1507 bytesread += read(fh,(void *)ename,(unsigned)sspub.csize);
1508 ename[sspub.csize]='\0';
1509 if ((sspub.segment==TrapSeg) &&
1510 (sspub.offset<=TrapOff) &&
1511 (sspub.offset>=NrPublic)) {
1512 NrPublic=sspub.offset;
1513 sprintf(szNrPub,"%s %s (%s) %04hX:%04hX\n",
1514 (sspub.type==1) ? " Abs" : " ",ename,ModName,
1515 sspub.segment, sspub.offset
1516 );
1517 }
1518 }
1519 break;
1520
1521 case SSTSRCLINES2:
1522 case SSTSRCLINES:
1523 if (TrapSeg!=ssmod.csBase) break;
1524 namelen=0;
1525 read(fh,(void *)&namelen,1);
1526 read(fh,(void *)ename,namelen);
1527 ename[namelen]='\0';
1528 /* skip 2 zero bytes */
1529 if (pDirTab[i].sst==SSTSRCLINES2) read(fh,(void *)&numlines,2);
1530 read(fh,(void *)&numlines,2);
1531 for (j=0;j<numlines;j++) {
1532 read(fh,(void *)&line,2);
1533 read(fh,(void *)&offset,2);
1534 if (offset<=TrapOff && offset>=NrLine) {
1535 NrLine=offset;
1536 sprintf(szNrLine,"% 6hu", line);
1537 sprintf(szNrFile,"% 13.13s ", ename);
1538 /*sprintf(szNrLine,"%04hX:%04hX line #%hu (%s) (%s)\n",
1539 ssmod.csBase,offset,line,ModName,ename); */
1540 }
1541 }
1542 break;
1543 } /* end switch */
1544 i++;
1545 } /* end while modindex */
1546 } /* End While i < numdir */
1547 free(pDirTab);
1548 return(0);
1549}
1550
1551#define MAX_USERDEFS 150
1552#define MAX_POINTERS 150
1553
1554USHORT userdef_count;
1555USHORT pointer_count;
1556
1557struct one_userdef_rec {
1558 USHORT idx;
1559 USHORT type_index;
1560 BYTE name[33];
1561} one_userdef[MAX_USERDEFS];
1562
1563struct one_pointer_rec {
1564 USHORT idx;
1565 USHORT type_index;
1566 BYTE type_qual;
1567 BYTE name[33];
1568} one_pointer[MAX_POINTERS];
1569
1570int Read32PmDebug(int fh,int TrapSeg,int TrapOff,CHAR * FileName) {
1571 static unsigned int CurrSymSeg, NrSymbol,offset,NrPublic,NrFile,NrLine,NrEntry,numdir,namelen,numlines,line;
1572 static int ModIndex;
1573 static int bytesread,i,j;
1574 static int pOffset;
1575 static SSLINEENTRY32 LineEntry;
1576 static SSFILENUM32 FileInfo;
1577 static FIRSTLINEENTRY32 FirstLine;
1578 static BYTE dump_vars = FALSE;
1579 static USHORT idx;
1580 static BOOL read_types;
1581 static LONG lSize;
1582 static BOOL is_new_debug;
1583
1584 ModIndex=0;
1585 /* See if any CODEVIEW info */
1586 if (lseek(fh,-8L,SEEK_END)==-1) {
1587 fprintf(hTrap,"Error %u seeking CodeView table in %s\n",errno,FileName);
1588 return(18);
1589 }
1590
1591 if (read(fh,(void *)&eodbug,8)==-1) {
1592 fprintf(hTrap,"Error %u reading debug info from %s\n",errno,FileName);
1593 return(19);
1594 }
1595 if (eodbug.dbug!=DBUGSIG) {
1596 /*fprintf(hTrap,"\nNo CodeView information stored.\n");*/
1597 return(100);
1598 }
1599
1600 if ((lfaBase=lseek(fh,-eodbug.dfaBase,SEEK_END))==-1L) {
1601 fprintf(hTrap,"Error %u seeking base codeview data in %s\n",errno,FileName);
1602 return(20);
1603 }
1604
1605 if (read(fh,(void *)&base,8)==-1) {
1606 fprintf(hTrap,"Error %u reading base codeview data in %s\n",errno,FileName);
1607 return(21);
1608 }
1609
1610 if (lseek(fh,base.lfoDir-8+4,SEEK_CUR)==-1) {
1611 fprintf(hTrap,"Error %u seeking dir codeview data in %s\n",errno,FileName);
1612 return(22);
1613 }
1614
1615 if (read(fh,(void *)&numdir,4)==-1) {
1616 fprintf(hTrap,"Error %u reading dir codeview data in %s\n",errno,FileName);
1617 return(23);
1618 }
1619
1620 /* Read dir table into buffer */
1621 if (( pDirTab32 = ( struct ssDir32 *) calloc(numdir,sizeof( struct ssDir32)))==NULL) {
1622 fprintf(hTrap,"Out of memory!");
1623 return(-1);
1624 }
1625
1626 if (read(fh,(void *)pDirTab32,numdir*sizeof( struct ssDir32))==-1) {
1627 fprintf(hTrap,"Error %u reading codeview dir table from %s\n",errno,FileName);
1628 free(pDirTab32);
1629 return(24);
1630 }
1631
1632 i=0;
1633 while (i<numdir) {
1634 if ( pDirTab32[i].sst !=SSTMODULES) {
1635 i++;
1636 continue;
1637 }
1638 NrPublic=0x0;
1639 NrSymbol=0;
1640 NrLine=0x0;
1641 NrFile=0x0;
1642 CurrSymSeg = 0;
1643 /* point to subsection */
1644 lseek(fh, pDirTab32[i].lfoStart + lfaBase, SEEK_SET);
1645 read(fh,(void *)&ssmod32.csBase,sizeof(ssmod32));
1646 read(fh,(void *)ModName,(unsigned)ssmod32.csize);
1647 ModIndex=pDirTab32[i].modindex;
1648 ModName[ssmod32.csize]='\0';
1649 i++;
1650
1651 read_types = FALSE;
1652
1653 while (pDirTab32[i].modindex ==ModIndex && i<numdir) {
1654 /* point to subsection */
1655 lseek(fh, pDirTab32[i].lfoStart + lfaBase, SEEK_SET);
1656 switch(pDirTab32[i].sst) {
1657 case SSTPUBLICS:
1658 bytesread=0;
1659 while (bytesread < pDirTab32[i].cb) {
1660 bytesread += read(fh,(void *)&sspub32.offset,sizeof(sspub32));
1661 bytesread += read(fh,(void *)ename,(unsigned)sspub32.csize);
1662 ename[sspub32.csize]='\0';
1663 if ((sspub32.segment==TrapSeg) &&
1664 (sspub32.offset<=TrapOff) &&
1665 (sspub32.offset>=NrPublic)) {
1666 NrPublic = pubfunc_ofs = sspub32.offset;
1667 read_types = TRUE;
1668 sprintf(szNrPub,"%s %s (%s) %04X:%08lu\n",
1669 (sspub32.type==1) ? " Abs" : " ",ename,ModName,
1670 sspub32.segment, sspub32.offset
1671 );
1672 }
1673 }
1674 break;
1675
1676 /* Read symbols, so we can dump the variables on the stack */
1677 case SSTSYMBOLS:
1678 if (TrapSeg!=ssmod32.csBase) break;
1679
1680 bytesread=0;
1681 while (bytesread < pDirTab32[i].cb) {
1682 static USHORT usLength;
1683 static BYTE b1, b2;
1684 static BYTE bType, *ptr;
1685 static ULONG ofs;
1686 static ULONG last_addr = 0;
1687 static BYTE str[256];
1688 static struct symseg_rec symseg;
1689 static struct symauto_rec symauto;
1690 static struct symproc_rec symproc;
1691
1692 /* Read the length of this subentry */
1693 bytesread += read(fh, &b1, 1);
1694 if (b1 & 0x80) {
1695 bytesread += read(fh, &b2, 1);
1696 usLength = ((b1 & 0x7F) << 8) + b2;
1697 }
1698 else
1699 usLength = b1;
1700
1701 ofs = tell(fh);
1702
1703 bytesread += read(fh, &bType, 1);
1704
1705 switch(bType) {
1706 case SYM_CHANGESEG:
1707 read(fh, &symseg, sizeof(symseg));
1708 CurrSymSeg = symseg.seg_no;
1709 break;
1710
1711 case SYM_PROC:
1712 case SYM_CPPPROC:
1713 read(fh, &symproc, sizeof(symproc));
1714 read(fh, str, symproc.name_len);
1715 str[symproc.name_len] = 0;
1716
1717 if ((CurrSymSeg == TrapSeg) &&
1718 (symproc.offset<=TrapOff) &&
1719 (symproc.offset>=NrSymbol)) {
1720
1721 dump_vars = TRUE;
1722 var_ofs = 0;
1723 NrSymbol = symproc.offset;
1724 func_ofs = symproc.offset;
1725
1726 strcpy(func_name, str);
1727 }
1728 else {
1729 dump_vars = FALSE;
1730 }
1731 break;
1732
1733 case SYM_AUTO:
1734 if (!dump_vars)
1735 break;
1736
1737 read(fh, &symauto, sizeof(symauto));
1738 read(fh, str, symauto.name_len);
1739 str[symauto.name_len] = 0;
1740
1741 strcpy(autovar_def[var_ofs].name, str);
1742 autovar_def[var_ofs].stack_offset = symauto.stack_offset;
1743 autovar_def[var_ofs].type_idx = symauto.type_idx;
1744 var_ofs++;
1745 break;
1746
1747 }
1748
1749 bytesread += usLength;
1750
1751 lseek(fh, ofs+usLength, SEEK_SET);
1752 }
1753 break;
1754
1755 case SSTTYPES:
1756// if (ModIndex != TrapSeg)
1757 if (!read_types)
1758 break;
1759
1760 bytesread=0;
1761 idx = 0x200;
1762 userdef_count = 0;
1763 pointer_count = 0;
1764 while (bytesread < pDirTab32[i].cb) {
1765 static struct type_rec type;
1766 static struct type_userdefrec udef;
1767 static struct type_pointerrec point;
1768 static struct type_funcrec func;
1769 static struct type_structrec struc;
1770 static struct type_list1 list1;
1771 static struct type_list2 list2;
1772 static struct type_list2_1 list2_1;
1773 static ULONG ofs;
1774 static BYTE str[256], b1, b2;
1775 static USHORT n;
1776
1777 /* Read the length of this subentry */
1778 ofs = tell(fh);
1779
1780 read(fh, &type, sizeof(type));
1781 bytesread += sizeof(type);
1782
1783 switch(type.type) {
1784 case TYPE_USERDEF:
1785 if (userdef_count > MAX_USERDEFS)
1786 break;
1787
1788 read(fh, &udef, sizeof(udef));
1789 read(fh, str, udef.name_len);
1790 str[udef.name_len] = 0;
1791
1792 // Insert userdef in table
1793 one_userdef[userdef_count].idx = idx;
1794 one_userdef[userdef_count].type_index = udef.type_index;
1795 memcpy(one_userdef[userdef_count].name, str, min(udef.name_len+1, 32));
1796 one_userdef[userdef_count].name[32] = 0;
1797 userdef_count++;
1798 break;
1799
1800 case TYPE_POINTER:
1801 if (pointer_count > MAX_POINTERS)
1802 break;
1803
1804 read(fh, &point, sizeof(point));
1805 read(fh, str, point.name_len);
1806 str[point.name_len] = 0;
1807
1808 // Insert userdef in table
1809 one_pointer[pointer_count].idx = idx;
1810 one_pointer[pointer_count].type_index = point.type_index;
1811 memcpy(one_pointer[pointer_count].name, str, min(point.name_len+1, 32));
1812 one_pointer[pointer_count].name[32] = 0;
1813 one_pointer[pointer_count].type_qual = type.type_qual;
1814 pointer_count++;
1815 break;
1816 }
1817
1818 ++idx;
1819
1820 bytesread += type.length;
1821
1822 lseek(fh, ofs+type.length+2, SEEK_SET);
1823 }
1824 break;
1825
1826 case SSTSRCLINES32:
1827 if (TrapSeg!=ssmod32.csBase) break;
1828
1829 /* read first line */
1830 do {
1831 read(fh,(void *)&FirstLine,sizeof(FirstLine));
1832
1833 if (FirstLine.LineNum!=0) {
1834 fprintf(hTrap,"Missing Line table information\n");
1835 break;
1836 } /* endif */
1837 numlines= FirstLine.numlines;
1838 /* Other type of data skip 4 more bytes */
1839 if (FirstLine.entry_type < 4) {
1840 read(fh, (void *)&lSize, 4);
1841 if (FirstLine.entry_type == 3)
1842 lseek(fh,lSize,SEEK_CUR);
1843 }
1844 } while(FirstLine.entry_type == 3);
1845
1846 for (j=0;j<numlines;j++) {
1847 switch (FirstLine.entry_type) {
1848 case 0:
1849 read(fh,(void *)&LineEntry,sizeof(LineEntry));
1850 /* Changed by Kim Rasmussen 26/06 1996 to ignore linenumber 0 */
1851 /* if (LineEntry.Offset+ssmod32.csOff<=TrapOff && LineEntry.Offset+ssmod32.csOff>=NrLine) { */
1852 if (LineEntry.LineNum && LineEntry.Offset+ssmod32.csOff<=TrapOff && LineEntry.Offset+ssmod32.csOff>=NrLine) {
1853 NrLine=LineEntry.Offset;
1854 NrFile=LineEntry.FileNum;
1855 /*pOffset =sprintf(szNrLine,"%04X:%08X line #%hu ",
1856 ssmod32.csBase,LineEntry.Offset,
1857 LineEntry.LineNum);*/
1858 sprintf(szNrLine,"% 6hu", LineEntry.LineNum);
1859 }
1860 break;
1861
1862 case 1:
1863 lseek(fh, sizeof(struct linlist_rec), SEEK_CUR);
1864 break;
1865
1866 case 2:
1867 lseek(fh, sizeof(struct linsourcelist_rec), SEEK_CUR);
1868 break;
1869
1870 case 3:
1871 lseek(fh, sizeof(struct filenam_rec), SEEK_CUR);
1872 break;
1873
1874 case 4:
1875 lseek(fh, sizeof(struct pathtab_rec), SEEK_CUR);
1876 break;
1877
1878 }
1879 }
1880 if (NrFile!=0) {
1881 read(fh,(void *)&FileInfo,sizeof(FileInfo));
1882 namelen=0;
1883 for (j=1;j<=FileInfo.file_count;j++) {
1884 namelen=0;
1885 read(fh,(void *)&namelen,1);
1886 read(fh,(void *)ename,namelen);
1887 if (j==NrFile) break;
1888 }
1889 ename[namelen]='\0';
1890 /* pOffset=sprintf(szNrLine+pOffset," (%s) (%s)\n",ename,ModName);*/
1891 sprintf(szNrFile,"% 13.13s ",ename);
1892 } else {
1893 /* strcat(szNrLine,"\n"); avoid new line for empty name fill */
1894 strcpy(szNrFile," ");
1895 } /* endif */
1896 break;
1897 } /* end switch */
1898
1899 i++;
1900 } /* end while modindex */
1901 } /* End While i < numdir */
1902 free(pDirTab32);
1903 return(0);
1904}
1905
1906BYTE *var_value(void *varptr, BYTE type)
1907{
1908 static BYTE value[128];
1909 APIRET rc;
1910
1911 strcpy(value, "Unknown");
1912
1913 if (type == 0)
1914 sprintf(value, "%hhi", *(signed char *)varptr);
1915 else if (type == 1)
1916 sprintf(value, "%hd", *(signed short *)varptr);
1917 else if (type == 2)
1918 sprintf(value, "%ld", *(signed long *)varptr);
1919 else if (type == 4)
1920 sprintf(value, "%hu", *(BYTE *)varptr);
1921 else if (type == 5)
1922 sprintf(value, "%hu", *(USHORT *)varptr);
1923 else if (type == 6)
1924 sprintf(value, "%lu", *(ULONG *)varptr);
1925 else if (type == 8)
1926 sprintf(value, "%f", *(float *)varptr);
1927 else if (type == 9)
1928 sprintf(value, "%f", *(double *)varptr);
1929 else if (type == 10)
1930 sprintf(value, "%Lf", *(long double *)varptr);
1931 else if (type == 16)
1932 sprintf(value, "%s", *(char *)varptr ? "TRUE" : "FALSE");
1933 else if (type == 17)
1934 sprintf(value, "%s", *(short *)varptr ? "TRUE" : "FALSE");
1935 else if (type == 18)
1936 sprintf(value, "%s", *(long *)varptr ? "TRUE" : "FALSE");
1937 else if (type == 20)
1938 sprintf(value, "%c", *(char *)varptr);
1939 else if (type == 21)
1940 sprintf(value, "%hi", *(short *)varptr);
1941 else if (type == 22)
1942 sprintf(value, "%lc", *(long *)varptr);
1943 else if (type == 23)
1944 sprintf(value, "void");
1945 else if (type >= 32) {
1946 ULONG Size,Attr;
1947 Size=1;
1948 rc=DosQueryMem((void*)*(ULONG *)varptr,&Size,&Attr);
1949 if (rc) {
1950 sprintf(value, "0x%p invalid", *(ULONG *)varptr);
1951 } else {
1952 sprintf(value, "0x%p", *(ULONG *)varptr);
1953 if (Attr&PAG_FREE) {
1954 strcat(value," unallocated memory");
1955 } else {
1956 if ((Attr&PAG_COMMIT)==0x0U) {
1957 strcat(value," uncommited");
1958 } /* endif */
1959 if ((Attr&PAG_WRITE)==0x0U) {
1960 strcat(value," unwritable");
1961 } /* endif */
1962 if ((Attr&PAG_READ)==0x0U) {
1963 strcat(value," unreadable");
1964 } /* endif */
1965 } /* endif */
1966 } /* endif */
1967 }
1968
1969 return value;
1970}
1971
1972/* Search the table of userdef's - return TRUE if found */
1973BOOL search_userdefs(ULONG stackofs, USHORT var_no)
1974{
1975 USHORT pos;
1976
1977 for(pos = 0; pos < userdef_count && one_userdef[pos].idx != autovar_def[var_no].type_idx; pos++);
1978
1979 if (pos < userdef_count) {
1980 if (one_userdef[pos].type_index >= 0x80 && one_userdef[pos].type_index <= 0xDA) {
1981 fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
1982 autovar_def[var_no].stack_offset,
1983 autovar_def[var_no].name,
1984 one_userdef[pos].name,
1985 var_value((void *)(stackofs+autovar_def[var_no].stack_offset),
1986 one_userdef[pos].type_index-0x80));
1987 return TRUE;
1988 }
1989 else /* If the result isn't a simple type, let's act as we didn't find it */
1990 return FALSE;
1991 }
1992
1993 return FALSE;
1994}
1995
1996BOOL search_pointers(ULONG stackofs, USHORT var_no)
1997{
1998 USHORT pos, upos;
1999 static BYTE str[35];
2000 BYTE type_index;
2001
2002 for(pos = 0; pos < pointer_count && one_pointer[pos].idx != autovar_def[var_no].type_idx; pos++);
2003
2004 if (pos < pointer_count) {
2005 if (one_pointer[pos].type_index >= 0x80 && one_pointer[pos].type_index <= 0xDA) {
2006 strcpy(str, type_name[one_pointer[pos].type_index-0x80]);
2007 strcat(str, " *");
2008 fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
2009 autovar_def[var_no].stack_offset,
2010 autovar_def[var_no].name,
2011 str,
2012 var_value((void *)(stackofs+autovar_def[var_no].stack_offset), 32));
2013 return TRUE;
2014 }
2015 else { /* If the result isn't a simple type, look for it in the other lists */
2016 for(upos = 0; upos < userdef_count && one_userdef[upos].idx != one_pointer[pos].type_index; upos++);
2017
2018 if (upos < userdef_count) {
2019 strcpy(str, one_userdef[upos].name);
2020 strcat(str, " *");
2021 fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
2022 autovar_def[var_no].stack_offset,
2023 autovar_def[var_no].name,
2024 str,
2025 var_value((void *)(stackofs+autovar_def[var_no].stack_offset), 32));
2026 return TRUE;
2027 }
2028 else { /* If it isn't a userdef, for now give up and just print as much as we know */
2029 sprintf(str, "Pointer to type 0x%X", one_pointer[pos].type_index);
2030
2031 fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
2032 autovar_def[var_no].stack_offset,
2033 autovar_def[var_no].name,
2034 str,
2035 var_value((void *)(stackofs+autovar_def[var_no].stack_offset), 32));
2036
2037 return TRUE;
2038 }
2039 }
2040 }
2041
2042 return FALSE;
2043}
2044
2045void print_vars(ULONG stackofs)
2046{
2047 USHORT n, pos;
2048 BOOL AutoVarsFound=FALSE;
2049
2050/* stackofs += stack_ebp; */
2051 if (1 || func_ofs == pubfunc_ofs) { //fixme GKY 1-22-24 why is this here since its always true
2052 for(n = 0; n < var_ofs; n++) {
2053 if (AutoVarsFound==FALSE) {
2054 AutoVarsFound=TRUE;
2055 fprintf(hTrap, "List of auto variables at EBP %p in %s:\n",stackofs, func_name);
2056 fprintf(hTrap,"Offset Name Type Value \n");
2057 fprintf(hTrap,"ÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n");
2058 }
2059
2060 /* If it's one of the simple types */
2061 if (autovar_def[n].type_idx >= 0x80 && autovar_def[n].type_idx <= 0xDA)
2062 {
2063 fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
2064 autovar_def[n].stack_offset,
2065 autovar_def[n].name,
2066 type_name[autovar_def[n].type_idx-0x80],
2067 var_value((void *)(stackofs+autovar_def[n].stack_offset),
2068 autovar_def[n].type_idx-0x80));
2069 }
2070 else { /* Complex type, check if we know what it is */
2071 if (!search_userdefs(stackofs, n)) {
2072 if (!search_pointers(stackofs, n)) {
2073 fprintf(hTrap, "%- 6d %-20.20s 0x%X\n",
2074 autovar_def[n].stack_offset,
2075 autovar_def[n].name,
2076 autovar_def[n].type_idx);
2077 }
2078 }
2079 }
2080 }
2081 if (AutoVarsFound==FALSE) {
2082 fprintf(hTrap, " No auto variables found in %s.\n", func_name);
2083 }
2084 fprintf(hTrap, "\n");
2085 }
2086}
2087
2088
2089
Note: See TracBrowser for help on using the repository browser.