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

Last change on this file was 144, checked in by gyoung, 19 months ago

Fix compiler warnings

File size: 77.3 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#endif
459 if (pERepRec->fHandlerFlags & EH_EXIT_UNWIND)
460 return (XCPT_CONTINUE_SEARCH);
461 if (pERepRec->fHandlerFlags & EH_UNWINDING)
462 return (XCPT_CONTINUE_SEARCH);
463 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
464 return (XCPT_CONTINUE_SEARCH);
465
466#if 0
467 sprintf(TrapFile,"%c:\\%s",_GetBootDriveLetter(), EXCEPTION_LOGFILE_NAME);
468 hTrap=fopen(TrapFile,"a");
469 fprintf(hTrap,"fHandlerFlags: %x, ExceptionNum: %x\n",pERepRec->fHandlerFlags, pERepRec->ExceptionNum);
470 fclose(hTrap);
471#endif
472 if ((pERepRec->ExceptionNum & XCPT_SEVERITY_CODE) == XCPT_FATAL_EXCEPTION)
473 {
474 DosBeep(5000,30);
475 DosBeep(4000,30);
476 DosBeep(3000,30);
477 DosBeep(4000,30);
478 DosBeep(5000,30);
479
480 if (pERepRec->ExceptionNum != XCPT_PROCESS_TERMINATE &&
481 pERepRec->ExceptionNum != XCPT_UNWIND &&
482 pERepRec->ExceptionNum != XCPT_SIGNAL &&
483 pERepRec->ExceptionNum != XCPT_BREAKPOINT &&
484 pERepRec->ExceptionNum != XCPT_SINGLE_STEP &&
485 pERepRec->ExceptionNum != XCPT_ASYNC_PROCESS_TERMINATE)
486 {
487 // If any of the above conditionals fail then we have to handle
488 // the fatal trap.
489 rc = HandleFatalException(pERepRec, (PEXCEPTIONREGISTRATIONRECORD) pRegRec2, pCtxRec, pv);
490 longjmp(pRegRec2->jmpThread, pERepRec->ExceptionNum);
491 // longjmp(pERegRec->jmpThread, pERepRec->ExceptionNum);
492 }
493 }
494 return rc;
495}
496#if 0
497ULONG APIENTRY myHandler (PEXCEPTIONREPORTRECORD pERepRec,
498 PEXCEPTIONREGISTRATIONRECORD pERegRec,
499 PCONTEXTRECORD pCtxRec,
500 PVOID p)
501{
502 ULONG rc = XCPT_CONTINUE_SEARCH;
503
504 if (pERepRec->fHandlerFlags & EH_EXIT_UNWIND)
505 return (XCPT_CONTINUE_SEARCH);
506 if (pERepRec->fHandlerFlags & EH_UNWINDING)
507 return (XCPT_CONTINUE_SEARCH);
508 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
509 return (XCPT_CONTINUE_SEARCH);
510
511 if ((pERepRec->ExceptionNum & XCPT_SEVERITY_CODE) == XCPT_FATAL_EXCEPTION)
512 {
513 if (pERepRec->ExceptionNum != XCPT_PROCESS_TERMINATE &&
514 pERepRec->ExceptionNum != XCPT_UNWIND &&
515 pERepRec->ExceptionNum != XCPT_SIGNAL &&
516 pERepRec->ExceptionNum != XCPT_BREAKPOINT &&
517 pERepRec->ExceptionNum != XCPT_SINGLE_STEP &&
518 pERepRec->ExceptionNum != XCPT_ASYNC_PROCESS_TERMINATE)
519 {
520 // If any of the above conditionals fail then we have to handle
521 // the fatal trap.
522 rc = HandleFatalException(pERepRec, pERegRec, pCtxRec, p);
523 longjmp(pERegRec->jmpThread, pERepRec->ExceptionNum);
524 }
525 }
526 return rc;
527}
528#endif
529
530
531ULONG APIENTRY HandleFatalException (PEXCEPTIONREPORTRECORD pERepRec,
532 PEXCEPTIONREGISTRATIONRECORD pERegRec,
533 PCONTEXTRECORD pCtxRec,
534 PVOID p)
535{
536 PCHAR SegPtr;
537 PUSHORT StackPtr;
538 PUSHORT ValidStackBottom;
539 PUCHAR TestStackBottom;
540 PUCHAR cStackPtr;
541 ULONG Size,Flags,Attr,CSSize;
542 APIRET rc;
543 APIRET semrc;
544 APIRET16 rc16;
545 PTIB ptib;
546 PPIB ppib;
547 USHORT Count;
548 ULONG Nest;
549 CHAR TrapFile[CCHMAXPATH];
550 struct debug_buffer DbgBuf;
551 static CHAR Name[CCHMAXPATH];
552
553 /* Do not recurse into Trapper (John Currier) */
554 /* Not necessary anymore because nested calls are catched now CW */
555 static BOOL fAlreadyTrapped = FALSE;
556
557
558 if (InForceExit) {
559 return (XCPT_CONTINUE_SEARCH);
560 } /* endif */
561
562 if ((pERepRec->ExceptionNum&XCPT_SEVERITY_CODE)==XCPT_FATAL_EXCEPTION)
563 {
564
565 if ((pERepRec->ExceptionNum!=XCPT_PROCESS_TERMINATE)&&
566 (pERepRec->ExceptionNum!=XCPT_UNWIND)&&
567 (pERepRec->ExceptionNum!=XCPT_SIGNAL)&&
568 (pERepRec->ExceptionNum!=XCPT_ASYNC_PROCESS_TERMINATE)) {
569 DosEnterMustComplete(&Nest);
570
571 sprintf(TrapFile,"%c:\\%s",_GetBootDriveLetter(), EXCEPTION_LOGFILE_NAME);
572
573 hTrap=fopen(TrapFile,"a");
574 if (hTrap==NULL)
575 hTrap=stdout;
576
577 // rc=DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR );
578
579 setbuf( hTrap, NULL);/* Unbuffered stream */
580 /* fprintf(hTrap,"A trap occurred in Audio/Data-CD-Creator\n");*/
581 fprintf(hTrap,"----------------------------------------\n\n");
582 fprintf(hTrap,"Exception %8.8lX Occurred",pERepRec->ExceptionNum);
583 fprintf(hTrap," at %s ",_strtime(Buffer));
584 fprintf(hTrap," %s\n\n",_strdate(Buffer));
585 if ( pERepRec->ExceptionNum == XCPT_ACCESS_VIOLATION)
586 {
587 switch (pERepRec->ExceptionInfo[0]) {
588 case XCPT_READ_ACCESS:
589 fprintf(hTrap,"Invalid read address %8.8lX\n",pERepRec->ExceptionInfo[1]);
590 break;
591 case XCPT_WRITE_ACCESS:
592 fprintf(hTrap,"Invalid write address %8.8lX\n",pERepRec->ExceptionInfo[1]);
593 break;
594 case XCPT_SPACE_ACCESS:
595 /* Thanks to John Currier */
596 /* It looks like this is off by one... */
597 fprintf(hTrap,"Invalid Selector: %8.8p",
598 pERepRec->ExceptionInfo[1] ?
599 pERepRec->ExceptionInfo[1] + 1 : 0);
600 break;
601 case XCPT_LIMIT_ACCESS:
602 fprintf(hTrap,"Limit access fault\n");
603 break;
604 case XCPT_UNKNOWN_ACCESS:
605 fprintf(hTrap,"Unknown access fault\n");
606 break;
607 break;
608 default:
609 fprintf(hTrap,"Other Unknown access fault\n");
610 } /* endswitch */
611 } /* endif XCPT_ACCESS_VIOLATION */
612 else if( pERepRec->ExceptionNum == XCPT_INTEGER_DIVIDE_BY_ZERO)
613 {
614 fprintf(hTrap,"Division by zero.\n");
615 }
616 else if( pERepRec->ExceptionNum == XCPT_ILLEGAL_INSTRUCTION)
617 {
618 fprintf(hTrap,"Illegal instruction.\n");
619 }
620 else if( pERepRec->ExceptionNum == XCPT_PRIVILEGED_INSTRUCTION)
621 {
622 fprintf(hTrap,"Privileged instruction.\n");
623 }
624 else if( pERepRec->ExceptionNum == XCPT_INTEGER_OVERFLOW)
625 {
626 fprintf(hTrap,"Integer overflow.\n");
627 }
628
629 /* John Currier's recursion prevention */
630 fprintf(hTrap,"\n\n");
631#if 0 /* Not necessary anymore because nested calls are catched now CW */
632 if (fAlreadyTrapped)
633 {
634 fprintf(hTrap, "Exception Handler Trapped...aborting evaluation!\n");
635 if (hTrap != stderr)
636 fclose(hTrap);
637 DosExitMustComplete(&Nest);
638
639 /* DosUnsetExceptionHandler(pERegRec); */
640 return (XCPT_CONTINUE_SEARCH);
641 }
642#endif
643
644 fAlreadyTrapped = TRUE;
645 /* end John Currier's recursion prevention */
646 rc = DosQuerySysInfo(QSV_VERSION_MAJOR,QSV_VERSION_MINOR,
647 Version,sizeof(Version));
648 if ((rc==0)&&
649 (Version[0]>=20) &&
650 (Version[1]>=10) ) {
651 /* version must be over 2.1 for DosQueryModFromEIP */
652 fprintf(hTrap,"OS/2 Version %d.%d\n",Version[0]/10,Version[1]);
653 rc=DosQueryModFromEIP( &hMod, &ObjNum, CCHMAXPATH,
654 Name, &Offset, (ULONG) pERepRec->ExceptionAddress);
655 if (rc==0) {
656 fprintf(hTrap,"Failing code module internal name : %s\n",Name);
657 rc=DosQueryModuleName(hMod,CCHMAXPATH, Name);
658 fprintf(hTrap,"Failing code module file name : %s\n",Name);
659 fprintf(hTrap,"Failing code Object # %d at Offset %x \n",ObjNum+1,Offset);
660 if (strlen(Name)>3) {
661 fprintf(hTrap," File Line# Public Symbol\n");
662 fprintf(hTrap," ÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄ- ÄÄÄÄÄÄÄÄÄÄÄÄ-\n");
663 rc =GetLineNum(Name,ObjNum,Offset);
664
665 if (rc == 0)
666 print_vars(pCtxRec->ctx_RegEbp);
667
668 /* if no codeview try with symbol files */
669 if (rc!=0) {
670 strcpy(Name+strlen(Name)-3,"SYM"); /* Get Sym File name */
671 GetSymbol(Name,ObjNum,Offset);
672 } /* endif */
673 } /* endif */
674 fprintf(hTrap,"\n");
675 } else {
676 fprintf(hTrap,"Invalid execution address\n");
677 } /* endif */
678 } /* endif */
679 if ( (pCtxRec->ContextFlags) & CONTEXT_CONTROL ) {
680 void * _Seg16 Ptr16;
681 BigSeg=((pCtxRec->ctx_RegEip)>0x00010000);
682 if (BigSeg) {
683 /* Avoid traps in 16:16 Disasm DLL */
684 if (DosAllocMem((PPVOID)&SourceBuffer,0x100,fALLOC)==0) {
685 Size=0x100;
686 rc=DosQueryMem((PVOID)pCtxRec->ctx_RegEip,&Size,&Attr);
687 if (Attr&(PAG_READ|PAG_EXECUTE)) {
688 memcpy(SourceBuffer,(PVOID)pCtxRec->ctx_RegEip,Size);
689#if 0 /*CW*/
690 AsmLine= DISASM( SourceBuffer,
691 (USHORT)pCtxRec->ctx_RegEip, BigSeg );
692 fprintf(hTrap,"\n Failing instruction at CS:EIP : %4.4X:%8.8X is %s\n\n",
693 pCtxRec->ctx_SegCs,
694 pCtxRec->ctx_RegEip,AsmLine->buf);
695#endif
696 } /* endif */
697 }
698 } else {
699 if (CSSize>pCtxRec->ctx_RegEip) {
700#if 0 /*CW*/
701 AsmLine= DISASM(MAKE16P(pCtxRec->ctx_SegCs,
702 pCtxRec->ctx_RegEip),
703 (USHORT)pCtxRec->ctx_RegEip, BigSeg );
704 fprintf(hTrap,"\n Failing instruction at CS:IP : %4.4X:%4.4X is %s\n\n",
705 pCtxRec->ctx_SegCs,
706 pCtxRec->ctx_RegEip,AsmLine->buf);
707#endif
708 } else {
709 fprintf(hTrap,"Invalid execution address\n");
710 } /* endif */
711 } /* endif */
712
713 rc=DosGetInfoBlocks(&ptib,&ppib);
714 if (rc==NO_ERROR) {
715 static CHAR Format[10];
716
717 fprintf(hTrap,"\nThread slot %lu , Id %lu , priority %p\n",
718 ptib->tib_ordinal,
719 ptib->tib_ptib2->tib2_ultid ,
720 ptib->tib_ptib2->tib2_ulpri );
721 Ptr16=ptib->tib_pstack;
722 sprintf(Format,"%8.8lX",Ptr16);
723 fprintf(hTrap,"Stack Bottom : %8.8lX (%4.4s:%4.4s) ;", ptib->tib_pstack ,Format,Format+4);
724 Ptr16=ptib->tib_pstacklimit;
725 sprintf(Format,"%8.8lX",Ptr16);
726 fprintf(hTrap,"Stack Top : %8.8lX (%4.4s:%4.4s) \n",ptib->tib_pstacklimit,Format,Format+4);
727 fprintf(hTrap,"Process Id : %lu ", ppib->pib_ulpid);
728 rc=DosQueryModuleName(ppib->pib_hmte,CCHMAXPATH, Name);
729 if (rc==NO_ERROR) {
730 fprintf(hTrap,".EXE name : %s\n",Name);
731 } else {
732 fprintf(hTrap,".EXE name : ??????\n");
733 } /* endif */
734 /* Better New WalkStack From John Currier */
735 WalkStack((PUSHORT)ptib->tib_pstack,
736 (PUSHORT)ptib->tib_pstacklimit,
737 (PUSHORT)pCtxRec->ctx_RegEbp,
738 (PUSHORT)pERepRec->ExceptionAddress);
739 ListModules();
740 Count=0;
741 } /* endif */
742 } /* endif */
743
744 if (hTrap!=stdout) {
745 fclose(hTrap);
746 }
747 DosExitMustComplete(&Nest);
748
749 /* rc=DosUnsetExceptionHandler(pERegRec); CW */
750 } /* endif */
751 } else {
752 /* printf("Other non fatal exception %8.8lx ",pERepRec->ExceptionNum); */
753 /* printf("At address %8.8lx\n",pERepRec->ExceptionAddress); */
754 } /* endif */
755 return (XCPT_CONTINUE_SEARCH);
756}
757
758#if 0 /*CW */
759APIRET16 APIENTRY16 SETEXCEPT(PEXCEPTIONREGISTRATIONRECORD _Seg16 pxcpthand)
760 {
761 APIRET rc;
762
763 rc=DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR );
764 printf("Set error rc %ld\n",rc);
765 pxcpthand->prev_structure=0;
766 pxcpthand->ExceptionHandler=&myHandler;
767 rc=DosSetExceptionHandler(pxcpthand);
768 printf("Set except rc %ld\n",rc);
769 return rc;/* CW */
770}
771APIRET16 APIENTRY16 UNSETEXCEPT(PEXCEPTIONREGISTRATIONRECORD _Seg16 pxcpthand)
772 {
773 APIRET rc;
774 rc=DosUnsetExceptionHandler(pxcpthand);
775 printf("Unset except rc %ld\n",rc);
776 return rc;/* CW */
777}
778#endif
779
780VOID ListModules() {
781 APIRET rc;
782 APIRET16 rc16;
783#ifdef USE_DOSDEBUG
784 /**----------------------------------***/
785#else
786#if MORE_INFO_WANTED
787 PVOID BaseAddress;
788 ULONG RegionSize;
789 ULONG AllocationFlags;
790 HMODULE LastModule;
791 static CHAR Name[CCHMAXPATH];
792 ULONG Size;
793 LastModule=0;
794 BaseAddress=(PVOID)0x10000;
795 RegionSize =0x3FFFFFFF;
796 fprintf(hTrap,"ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\n");
797 fprintf(hTrap,"³ List of currently accessed modules (DLLs) object addresses ³");
798 rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
799 while (rc==NO_ERROR) {
800 if ((AllocationFlags&PAG_EXECUTE)&&
801 (AllocationFlags&PAG_BASE)) {
802 rc=DosQueryModFromEIP( &hMod, &ObjNum, CCHMAXPATH,
803 Name, &Offset, BaseAddress);
804 if (rc==0) {
805 if (hMod!=LastModule) {
806 rc=DosQueryModuleName(hMod,CCHMAXPATH, Name);
807 fprintf(hTrap,"\nÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŽ\n");
808 fprintf(hTrap,"³ Module %-48.48s Handle %8.8d ³\n",Name,hMod);
809 fprintf(hTrap,"³ Object Number Address Length Flags Type ³");
810 LastModule=hMod;
811 } /* endif */
812 fprintf(hTrap,"\n³ % 6.6d %8.8lX %8.8lX %8.8lX ",ObjNum,
813 BaseAddress, RegionSize, AllocationFlags);
814 rc16 =DOS16SIZESEG( SELECTOROF(BaseAddress), &Size);
815 if (rc16==0) {
816 fprintf(hTrap," - 16:16 Selector %4.4hX ³",SELECTOROF((PVOID)BaseAddress));
817 } else {
818 fprintf(hTrap," - 32 Bits ³");
819 } /* endif */
820 }
821 }
822 if (AllocationFlags&PAG_FREE) RegionSize =0x10000;
823 RegionSize +=0x0FFF;
824 RegionSize &=0xFFFFF000;
825 BaseAddress=(PVOID)(((PCHAR)BaseAddress)+RegionSize);
826 RegionSize=((PCHAR)0x3FFFFFFF)-(PCHAR)BaseAddress;
827 rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
828 while ((rc==ERROR_INVALID_ADDRESS)||
829 (rc==ERROR_NO_OBJECT)) {
830 BaseAddress=(PVOID)(((PCHAR)BaseAddress)+0x10000);
831 if (BaseAddress>(PVOID)0x3FFFFFFF) {
832 break;
833 } /* endif */
834 RegionSize=((PCHAR)0x3FFFFFFF)-(PCHAR)BaseAddress;
835 rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
836 } /* endwhile */
837 if (BaseAddress>(PVOID)0x3FFFFFFF) {
838 break;
839 } /* endif */
840 } /* endwhile */
841 fprintf(hTrap,"\nÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\n");
842#endif
843#endif
844}
845
846
847void CheckMem(PVOID Ptr,PSZ MemoryName) {
848 APIRET rc;
849 ULONG Size,Flags,Attr;
850 Size=1;
851 rc=DosQueryMem(Ptr,&Size,&Attr);
852 if (rc!=NO_ERROR) {
853 fprintf(hTrap, "³ %3.3s does not point to valid memory ³\n",MemoryName);
854 } else {
855 if (Attr&PAG_FREE) {
856 fprintf(hTrap, "³ %3.3s points to unallocated memory ³\n",MemoryName);
857 } else {
858 if ((Attr&PAG_COMMIT)==0x0U) {
859 fprintf(hTrap,"³ %3.3s points to uncommited memory ³\n",MemoryName);
860 } /* endif */
861 if ((Attr&PAG_WRITE)==0x0U) {
862 fprintf(hTrap,"³ %3.3s points to unwritable memory ³\n",MemoryName);
863 } /* endif */
864 if ((Attr&PAG_READ)==0x0U) {
865 fprintf(hTrap,"³ %3.3s points to unreadable memory ³\n",MemoryName);
866 } /* endif */
867 } /* endif */
868 } /* endif */
869}
870
871PUSHORT Convert(USHORT * _Seg16 p16) {
872 return p16;
873}
874
875/* Better New WalkStack From John Currier */
876static void WalkStack(PUSHORT StackBottom, PUSHORT StackTop, PUSHORT Ebp,
877 PUSHORT ExceptionAddress)
878{
879 PUSHORT RetAddr;
880 PUSHORT LastEbp;
881 APIRET rc;
882 ULONG Size,Attr;
883 USHORT Cs,Ip,Bp,Sp;
884 static char Name[CCHMAXPATH];
885 HMODULE hMod;
886 ULONG ObjNum;
887 ULONG Offset;
888 BOOL fExceptionAddress = TRUE; // Use Exception Addr 1st time thru
889
890 // Note: we can't handle stacks bigger than 64K for now...
891 Sp = (USHORT)(((ULONG)StackBottom) >> 16);
892 Bp = (USHORT)(ULONG)Ebp;
893
894 if (!f32bit)
895 Ebp = (PUSHORT)MAKEULONG(Bp, Sp);
896
897 fprintf(hTrap,"\nCall Stack:\n");
898 fprintf(hTrap," Source Line Nearest\n");
899 fprintf(hTrap," EBP Address Module Obj# File Numbr Public Symbol\n");
900 fprintf(hTrap," ÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄ- ÄÄÄÄÄÄÄÄ ÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄ- ÄÄÄÄÄÄÄÄÄÄÄÄ-\n");
901
902 do
903 {
904 Size = 10;
905 rc = DosQueryMem((PVOID)(Ebp+2), &Size, &Attr);
906 if (rc != NO_ERROR || !(Attr & PAG_COMMIT) || (Size<10) )
907 {
908 fprintf(hTrap,"Invalid EBP: %8.8p\n",Ebp);
909 break;
910 }
911
912 if (fExceptionAddress)
913 RetAddr = ExceptionAddress;
914 else
915 RetAddr = (PUSHORT)(*((PULONG)(Ebp+2)));
916
917 if (RetAddr == (PUSHORT)0x00000053)
918 {
919 // For some reason there's a "return address" of 0x53 following
920 // EBP on the stack and we have to adjust EBP by 44 bytes to get
921 // at the real return address. This has something to do with
922 // thunking from 32bits to 16bits...
923 // Serious kludge, and it's probably dependent on versions of C(++)
924 // runtime or OS, but it works for now!
925 Ebp += 22;
926 RetAddr = (PUSHORT)(*((PULONG)(Ebp+2)));
927 }
928
929 // Get the (possibly) 16bit CS and IP
930 if (fExceptionAddress)
931 {
932 Cs = (USHORT)(((ULONG)ExceptionAddress) >> 16);
933 Ip = (USHORT)(ULONG)ExceptionAddress;
934 }
935 else
936 {
937 Cs = *(Ebp+2);
938 Ip = *(Ebp+1);
939 }
940
941 // if the return address points to the stack then it's really just
942 // a pointer to the return address (UGH!).
943 if ((USHORT)(((ULONG)RetAddr) >> 16) == Sp)
944 RetAddr = (PUSHORT)(*((PULONG)RetAddr));
945
946 if (Ip == 0 && *Ebp == 0)
947 {
948 // End of the stack so these are both shifted by 2 bytes:
949 Cs = *(Ebp+3);
950 Ip = *(Ebp+2);
951 }
952
953 // 16bit programs have on the stack:
954 // BP:IP:CS
955 // where CS may be thunked
956 //
957 // in dump swapped
958 // BP IP CS BP CS IP
959 // 4677 53B5 F7D0 7746 D0F7 B553
960 //
961 // 32bit programs have:
962 // EBP:EIP
963 // and you'd have something like this (with SP added) (not
964 // accurate values)
965 //
966 // in dump swapped
967 // EBP EIP EBP EIP
968 // 4677 2900 53B5 F7D0 0029 7746 D0F7 B553
969 //
970 // So the basic difference is that 32bit programs have a 32bit
971 // EBP and we can attempt to determine whether we have a 32bit
972 // EBP by checking to see if its 'selector' is the same as SP.
973 // Note that this technique limits us to checking stacks < 64K.
974 //
975 // Soooo, if IP (which maps into the same USHORT as the swapped
976 // stack page in EBP) doesn't point to the stack (i.e. it could
977 // be a 16bit IP) then see if CS is valid (as is or thunked).
978 //
979 // Note that there's the possibility of a 16bit return address
980 // that has an offset that's the same as SP so we'll think it's
981 // a 32bit return address and won't be able to successfully resolve
982 // its details.
983 if (Ip != Sp)
984 {
985 if (DOS16SIZESEG(Cs, &Size) == NO_ERROR)
986 {
987 RetAddr = (USHORT * _Seg16)MAKEULONG(Ip, Cs);
988 f32bit = FALSE;
989 }
990 else if (DOS16SIZESEG((Cs << 3) + 7, &Size) == NO_ERROR)
991 {
992 Cs = (Cs << 3) + 7;
993 RetAddr = (USHORT * _Seg16)MAKEULONG(Ip, Cs);
994 f32bit = FALSE;
995 }
996 else
997 f32bit = TRUE;
998 }
999 else
1000 f32bit = TRUE;
1001
1002
1003 if (fExceptionAddress)
1004 fprintf(hTrap," Trap ->");
1005 else
1006 fprintf(hTrap," %8.8p", Ebp);
1007
1008 if (f32bit)
1009 fprintf(hTrap," :%8.8p", RetAddr);
1010 else
1011 fprintf(hTrap," %04.04X:%04.04X", Cs, Ip);
1012
1013 if (Version[0] >= 20 && Version[1] >= 10)
1014 {
1015 // Make a 'tick' sound to let the user know we're still alive
1016 DosBeep(2000, 1);
1017
1018 Size = 10; /* Inserted by Kim Rasmussen 26/06 1996 to avoid error 87 when Size is 0 */
1019
1020 rc = DosQueryMem((PVOID)RetAddr, &Size, &Attr);
1021 if (rc != NO_ERROR || !(Attr & PAG_COMMIT))
1022 {
1023 fprintf(hTrap,"Invalid RetAddr: %8.8p\n",RetAddr);
1024 break; /* avoid infinite loops */
1025 } else {
1026 rc = DosQueryModFromEIP(&hMod, &ObjNum, sizeof(Name),
1027 Name, &Offset, (ULONG) RetAddr);
1028 if (rc == NO_ERROR && ObjNum != -1)
1029 {
1030 static char szJunk[_MAX_FNAME];
1031 static char szName[_MAX_FNAME];
1032 DosQueryModuleName(hMod, sizeof(Name), Name);
1033 _splitpath(Name, szJunk, szJunk, szName, szJunk);
1034 fprintf(hTrap," %-8s %04X", szName, ObjNum+1);
1035
1036 if (strlen(Name) > 3)
1037 {
1038 rc = GetLineNum(Name, ObjNum, Offset);
1039 /* if no codeview try with symbol files */
1040 if (rc != NO_ERROR)
1041 {
1042 strcpy(Name+strlen(Name)-3,"SYM");
1043 GetSymbol(Name,ObjNum,Offset);
1044 }
1045 }
1046 }
1047 else
1048 {
1049 fprintf(hTrap," *Unknown*");
1050 }
1051 }
1052 }
1053
1054 fprintf(hTrap,"\n");
1055
1056 Bp = *Ebp;
1057 if (Bp == 0 && (*Ebp+1) == 0)
1058 {
1059 fprintf(hTrap,"End of Call Stack\n");
1060 break;
1061 }
1062
1063 if (!fExceptionAddress)
1064 {
1065 LastEbp = Ebp;
1066#if 0
1067 Ebp = (PUSHORT)MAKEULONG(Bp, Sp);
1068#else /* Inserted by Kim Rasmussen 26/06 1996 to allow big stacks */
1069 if (f32bit)
1070 Ebp = (PUSHORT)*(PULONG)LastEbp;
1071 else
1072 Ebp = (PUSHORT)MAKEULONG(Bp, Sp);
1073#endif
1074 if (f32bit) {
1075 print_vars((ULONG)Ebp);
1076 } /* endif */
1077
1078 if (Ebp < LastEbp)
1079 {
1080 fprintf(hTrap,"Lost Stack chain - new EBP below previous\n");
1081 break;
1082 }
1083 }
1084 else
1085 fExceptionAddress = FALSE;
1086
1087 Size = 4;
1088 rc = DosQueryMem((PVOID)Ebp, &Size, &Attr);
1089 if ((rc != NO_ERROR)||(Size<4))
1090 {
1091 fprintf(hTrap,"Lost Stack chain - invalid EBP: %8.8p\n", Ebp);
1092 break;
1093 }
1094 } while (TRUE);
1095
1096 fprintf(hTrap,"\n");
1097}
1098
1099void GetSymbol(CHAR * SymFileName, ULONG Object,ULONG TrapOffset)
1100{
1101 static FILE * SymFile;
1102 static MAPDEF MapDef;
1103 static SEGDEF SegDef;
1104 static SEGDEF *pSegDef;
1105 static SYMDEF32 SymDef32;
1106 static SYMDEF16 SymDef16;
1107 static char Buffer[256];
1108 static int SegNum,SymNum,LastVal;
1109 static unsigned long int SegOffset,SymOffset,SymPtrOffset;
1110 SymFile=fopen(SymFileName,"rb");
1111 if (SymFile==0) {
1112 /*fprintf(hTrap,"Could not open symbol file %s\n",SymFileName);*/
1113 return;
1114 } /* endif */
1115 fread(&MapDef,sizeof(MAPDEF),1,SymFile);
1116 SegOffset= SEGDEFOFFSET(MapDef);
1117 for (SegNum=0;SegNum<MapDef.cSegs;SegNum++) {
1118 /* printf("Scanning segment #%d Offset %4.4hX\n",SegNum+1,SegOffset); */
1119 if (fseek(SymFile,SegOffset,SEEK_SET)) {
1120 fprintf(hTrap,"Seek error ");
1121 return;
1122 }
1123 fread(&SegDef,sizeof(SEGDEF),1,SymFile);
1124 if (SegNum==Object) {
1125 Buffer[0]=0x00;
1126 LastVal=0;
1127 for (SymNum=0;SymNum<SegDef.cSymbols;SymNum++) {
1128 SymPtrOffset=SYMDEFOFFSET(SegOffset,SegDef,SymNum);
1129 fseek(SymFile,SymPtrOffset,SEEK_SET);
1130 fread(&SymOffset,sizeof(unsigned short int),1,SymFile);
1131 fseek(SymFile,SymOffset+SegOffset,SEEK_SET);
1132 if (SegDef.bFlags&0x01) {
1133 fread(&SymDef32,sizeof(SYMDEF32),1,SymFile);
1134 if (SymDef32.wSymVal>TrapOffset) {
1135 fprintf(hTrap,"between %s + %X ",Buffer,TrapOffset-LastVal);
1136 }
1137 LastVal=SymDef32.wSymVal;
1138 Buffer[0]= SymDef32.achSymName[0];
1139 fread(&Buffer[1],1,SymDef32.cbSymName,SymFile);
1140 Buffer[SymDef32.cbSymName]=0x00;
1141 if (SymDef32.wSymVal>TrapOffset) {
1142 fprintf(hTrap,"and %s - %X\n",Buffer,LastVal-TrapOffset);
1143 break;
1144 }
1145 /*printf("32 Bit Symbol <%s> Address %p\n",Buffer,SymDef32.wSymVal);*/
1146 } else {
1147 fread(&SymDef16,sizeof(SYMDEF16),1,SymFile);
1148 if (SymDef16.wSymVal>TrapOffset) {
1149 fprintf(hTrap,"between %s + %X ",Buffer,TrapOffset-LastVal);
1150 }
1151 LastVal=SymDef16.wSymVal;
1152 Buffer[0]=SymDef16.achSymName[0];
1153 fread(&Buffer[1],1,SymDef16.cbSymName,SymFile);
1154 Buffer[SymDef16.cbSymName]=0x00;
1155 if (SymDef16.wSymVal>TrapOffset) {
1156 fprintf(hTrap,"and %s - %X\n",Buffer,LastVal-TrapOffset);
1157 break;
1158 }
1159 /*printf("16 Bit Symbol <%s> Address %p\n",Buffer,SymDef16.wSymVal);*/
1160 } /* endif */
1161 }
1162 break;
1163 } /* endif */
1164 SegOffset=NEXTSEGDEFOFFSET(SegDef);
1165 } /* endwhile */
1166 fclose(SymFile);
1167}
1168
1169#include <newexe.h>
1170#define FOR_EXEHDR 1 /* avoid define conflicts between newexe.h and exe386.h */
1171#ifndef DWORD
1172#define DWORD long int
1173#endif
1174#ifndef WORD
1175#define WORD short int
1176#endif
1177#include <exe386.h>
1178#include <fcntl.h>
1179#include <sys\stat.h>
1180#include <share.h>
1181#include <io.h>
1182/* ------------------------------------------------------------------ */
1183/* Last 8 bytes of 16:16 file when CODEVIEW debugging info is present */
1184#pragma pack(1)
1185 struct _eodbug
1186 {
1187 unsigned short dbug; /* 'NB' signature */
1188 unsigned short ver; /* version */
1189 unsigned long dfaBase; /* size of codeview info */
1190 } eodbug;
1191
1192#define DBUGSIG 0x424E
1193#define SSTMODULES 0x0101
1194#define SSTPUBLICS 0x0102
1195#define SSTTYPES 0x0103
1196#define SSTSYMBOLS 0x0104
1197#define SSTSRCLINES 0x0105
1198#define SSTLIBRARIES 0x0106
1199#define SSTSRCLINES2 0x0109
1200#define SSTSRCLINES32 0x010B
1201
1202 struct _base
1203 {
1204 unsigned short dbug; /* 'NB' signature */
1205 unsigned short ver; /* version */
1206 unsigned long lfoDir; /* file offset to dir entries */
1207 } base;
1208
1209 struct ssDir
1210 {
1211 unsigned short sst; /* SubSection Type */
1212 unsigned short modindex; /* Module index number */
1213 unsigned long lfoStart; /* Start of section */
1214 unsigned short cb; /* Size of section */
1215 } ;
1216
1217 struct ssDir32
1218 {
1219 unsigned short sst; /* SubSection Type */
1220 unsigned short modindex; /* Module index number */
1221 unsigned long lfoStart; /* Start of section */
1222 unsigned long cb; /* Size of section */
1223 } ;
1224
1225 struct ssModule
1226 {
1227 unsigned short csBase; /* code segment base */
1228 unsigned short csOff; /* code segment offset */
1229 unsigned short csLen; /* code segment length */
1230 unsigned short ovrNum; /* overlay number */
1231 unsigned short indxSS; /* Index into sstLib or 0 */
1232 unsigned short reserved;
1233 char csize; /* size of prefix string */
1234 } ssmod;
1235
1236 struct ssModule32
1237 {
1238 unsigned short csBase; /* code segment base */
1239 unsigned long csOff; /* code segment offset */
1240 unsigned long csLen; /* code segment length */
1241 unsigned long ovrNum; /* overlay number */
1242 unsigned short indxSS; /* Index into sstLib or 0 */
1243 unsigned long reserved;
1244 char csize; /* size of prefix string */
1245 } ssmod32;
1246
1247 struct ssPublic
1248 {
1249 unsigned short offset;
1250 unsigned short segment;
1251 unsigned short type;
1252 char csize;
1253 } sspub;
1254
1255 struct ssPublic32
1256 {
1257 unsigned long offset;
1258 unsigned short segment;
1259 unsigned short type;
1260 char csize;
1261 } sspub32;
1262
1263typedef struct _SSLINEENTRY32 {
1264 unsigned short LineNum;
1265 unsigned short FileNum;
1266 unsigned long Offset;
1267} SSLINEENTRY32;
1268typedef struct _FIRSTLINEENTRY32 {
1269 unsigned short LineNum;
1270 unsigned char entry_type;
1271 unsigned char reserved;
1272 unsigned short numlines;
1273 unsigned short segnum;
1274} FIRSTLINEENTRY32;
1275
1276typedef struct _SSFILENUM32 {
1277 unsigned long first_displayable; /* Not used */
1278 unsigned long number_displayable; /* Not used */
1279 unsigned long file_count; /* number of source files */
1280} SSFILENUM32;
1281
1282 struct DbugRec { /* debug info struct ure used in linked * list */
1283 struct DbugRec /*far*/ *pnext; /* next node *//* 013 */
1284 char /*far*/ *SourceFile; /* source file name *013 */
1285 unsigned short TypeOfProgram; /* dll or exe *014* */
1286 unsigned short LineNumber; /* line number in source file */
1287 unsigned short OffSet; /* offset into loaded module */
1288 unsigned short Selector; /* code segment 014 */
1289 unsigned short OpCode; /* Opcode replaced with BreakPt */
1290 unsigned long Count; /* count over Break Point */
1291};
1292
1293/*typedef struct DbugRec DBUG, far * DBUGPTR; */ /* 013 */
1294
1295char szNrPub[128];
1296char szNrLine[128];
1297char szNrFile[128];
1298 struct new_seg *pseg;
1299 struct o32_obj *pobj; /* Flat .EXE object table entry */
1300 struct ssDir *pDirTab;
1301 struct ssDir32 *pDirTab32;
1302unsigned char *pEntTab;
1303unsigned long lfaBase;
1304#pragma pack()
1305/* ------------------------------------------------------------------ */
1306
1307APIRET GetLineNum(CHAR * FileName, ULONG Object,ULONG TrapOffset) {
1308 APIRET rc;
1309 int ModuleFile;
1310 static struct exe_hdr old;
1311 static struct new_exe new1;
1312 static struct e32_exe e32;
1313 strcpy(szNrPub," N/A ");
1314 strcpy(szNrLine," N/A ");
1315 strcpy(szNrFile," ");
1316 ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
1317 if (ModuleFile!=-1) {
1318 /* Read old Exe header */
1319 if (read( ModuleFile ,(void *)&old,64)==-1L) {
1320 fprintf(hTrap,"Could Not Read old exe header %d\n",errno);
1321 close(ModuleFile);
1322 return 2;
1323 }
1324 /* Seek to new Exe header */
1325 if (lseek(ModuleFile,(long)E_LFANEW(old),SEEK_SET)==-1L) {
1326 fprintf(hTrap,"Could Not seek to new exe header %d\n",errno);
1327 close(ModuleFile);
1328 return 3;
1329 }
1330 if (read( ModuleFile ,(void *)&new1,64)==-1L) {
1331 fprintf(hTrap,"Could Not read new exe header %d\n",errno);
1332 close(ModuleFile);
1333 return 4;
1334 }
1335 /* Check EXE signature */
1336 if (NE_MAGIC(new1)==E32MAGIC) {
1337 /* Flat 32 executable */
1338 rc=Read32PmDebug(ModuleFile,Object+1,TrapOffset,FileName);
1339 if (rc==0) {
1340 fprintf(hTrap,"%s",szNrFile);
1341 fprintf(hTrap,"%s",szNrLine);
1342 fprintf(hTrap,"%s",szNrPub);
1343 } /* endif */
1344 close(ModuleFile);
1345 /* rc !=0 try with DBG file */
1346 if (rc!=0) {
1347 strcpy(FileName+strlen(FileName)-3,"DBG"); /* Build DBG File name */
1348 ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
1349 if (ModuleFile!=-1) {
1350 rc=Read32PmDebug(ModuleFile,Object+1,TrapOffset,FileName);
1351 if (rc==0) {
1352 fprintf(hTrap,"%s",szNrFile);
1353 fprintf(hTrap,"%s",szNrLine);
1354 fprintf(hTrap,"%s",szNrPub);
1355 } /* endif */
1356 close(ModuleFile);
1357 }
1358 } /* endif */
1359 return rc;
1360 } else {
1361 if (NE_MAGIC(new1)==NEMAGIC) {
1362 /* 16:16 executable */
1363 if ((pseg = ( struct new_seg *) calloc(NE_CSEG(new1),sizeof( struct new_seg)))==NULL) {
1364 fprintf(hTrap,"Out of memory!");
1365 close(ModuleFile);
1366 return -1;
1367 }
1368 if (lseek(ModuleFile,E_LFANEW(old)+NE_SEGTAB(new1),SEEK_SET)==-1L) {
1369 fprintf(hTrap,"Error %u seeking segment table in %s\n",errno,FileName);
1370 free(pseg);
1371 close(ModuleFile);
1372 return 9;
1373 }
1374
1375 if (read(ModuleFile,(void *)pseg,NE_CSEG(new1)*sizeof( struct new_seg))==-1) {
1376 fprintf(hTrap,"Error %u reading segment table from %s\n",errno,FileName);
1377 free(pseg);
1378 close(ModuleFile);
1379 return 10;
1380 }
1381 rc=Read16CodeView(ModuleFile,Object+1,TrapOffset,FileName);
1382 if (rc==0) {
1383 fprintf(hTrap,"%s",szNrFile);
1384 fprintf(hTrap,"%s",szNrLine);
1385 fprintf(hTrap,"%s",szNrPub);
1386 } /* endif */
1387 free(pseg);
1388 close(ModuleFile);
1389 /* rc !=0 try with DBG file */
1390 if (rc!=0) {
1391 strcpy(FileName+strlen(FileName)-3,"DBG"); /* Build DBG File name */
1392 ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
1393 if (ModuleFile!=-1) {
1394 rc=Read16CodeView(ModuleFile,Object+1,TrapOffset,FileName);
1395 if (rc==0) {
1396 fprintf(hTrap,"%s",szNrFile);
1397 fprintf(hTrap,"%s",szNrLine);
1398 fprintf(hTrap,"%s",szNrPub);
1399 } /* endif */
1400 close(ModuleFile);
1401 }
1402 } /* endif */
1403 return rc;
1404
1405 } else {
1406 /* Unknown executable */
1407 fprintf(hTrap,"Could Not find exe signature");
1408 close(ModuleFile);
1409 return 11;
1410 }
1411 }
1412 /* Read new Exe header */
1413 } else {
1414 fprintf(hTrap,"Could Not open Module File %d",errno);
1415 return 1;
1416 } /* endif */
1417 return 0;
1418}
1419char fname[128],ModName[80];
1420char ename[128],dummy[128];
1421
1422int Read16CodeView(int fh,int TrapSeg,int TrapOff,CHAR * FileName) {
1423 static unsigned short int offset,NrPublic,NrLine,NrEntry,numdir,namelen,numlines,line;
1424 static int ModIndex;
1425 static int bytesread,i,j;
1426 ModIndex=0;
1427 /* See if any CODEVIEW info */
1428 if (lseek(fh,-8L,SEEK_END)==-1) {
1429 fprintf(hTrap,"Error %u seeking CodeView table in %s\n",errno,FileName);
1430 return(18);
1431 }
1432
1433 if (read(fh,(void *)&eodbug,8)==-1) {
1434 fprintf(hTrap,"Error %u reading debug info from %s\n",errno,FileName);
1435 return(19);
1436 }
1437 if (eodbug.dbug!=DBUGSIG) {
1438 /* fprintf(hTrap,"\nNo CodeView information stored.\n"); */
1439 return(100);
1440 }
1441
1442 if ((lfaBase=lseek(fh,-eodbug.dfaBase,SEEK_END))==-1L) {
1443 fprintf(hTrap,"Error %u seeking base codeview data in %s\n",errno,FileName);
1444 return(20);
1445 }
1446
1447 if (read(fh,(void *)&base,8)==-1) {
1448 fprintf(hTrap,"Error %u reading base codeview data in %s\n",errno,FileName);
1449 return(21);
1450 }
1451
1452 if (lseek(fh,base.lfoDir-8,SEEK_CUR)==-1) {
1453 fprintf(hTrap,"Error %u seeking dir codeview data in %s\n",errno,FileName);
1454 return(22);
1455 }
1456
1457 if (read(fh,(void *)&numdir,2)==-1) {
1458 fprintf(hTrap,"Error %u reading dir codeview data in %s\n",errno,FileName);
1459 return(23);
1460 }
1461
1462 /* Read dir table into buffer */
1463 if (( pDirTab = ( struct ssDir *) calloc(numdir,sizeof( struct ssDir)))==NULL) {
1464 fprintf(hTrap,"Out of memory!");
1465 return(-1);
1466 }
1467
1468 if (read(fh,(void *)pDirTab,numdir*sizeof( struct ssDir))==-1) {
1469 fprintf(hTrap,"Error %u reading codeview dir table from %s\n",errno,FileName);
1470 free(pDirTab);
1471 return(24);
1472 }
1473
1474 i=0;
1475 while (i<numdir) {
1476 if (pDirTab[i].sst!=SSTMODULES) {
1477 i++;
1478 continue;
1479 }
1480 NrPublic=0x0;
1481 NrLine=0x0;
1482 /* point to subsection */
1483 lseek(fh, pDirTab[i].lfoStart + lfaBase, SEEK_SET);
1484 read(fh,(void *)&ssmod.csBase,sizeof(ssmod));
1485 read(fh,(void *)ModName,(unsigned)ssmod.csize);
1486 ModIndex=pDirTab[i].modindex;
1487 ModName[ssmod.csize]='\0';
1488 i++;
1489 while (pDirTab[i].modindex ==ModIndex && i<numdir) {
1490 /* point to subsection */
1491 lseek(fh, pDirTab[i].lfoStart + lfaBase, SEEK_SET);
1492 switch(pDirTab[i].sst) {
1493 case SSTPUBLICS:
1494 bytesread=0;
1495 while (bytesread < pDirTab[i].cb) {
1496 bytesread += read(fh,(void *)&sspub.offset,sizeof(sspub));
1497 bytesread += read(fh,(void *)ename,(unsigned)sspub.csize);
1498 ename[sspub.csize]='\0';
1499 if ((sspub.segment==TrapSeg) &&
1500 (sspub.offset<=TrapOff) &&
1501 (sspub.offset>=NrPublic)) {
1502 NrPublic=sspub.offset;
1503 sprintf(szNrPub,"%s %s (%s) %04hX:%04hX\n",
1504 (sspub.type==1) ? " Abs" : " ",ename,ModName,
1505 sspub.segment, sspub.offset
1506 );
1507 }
1508 }
1509 break;
1510
1511 case SSTSRCLINES2:
1512 case SSTSRCLINES:
1513 if (TrapSeg!=ssmod.csBase) break;
1514 namelen=0;
1515 read(fh,(void *)&namelen,1);
1516 read(fh,(void *)ename,namelen);
1517 ename[namelen]='\0';
1518 /* skip 2 zero bytes */
1519 if (pDirTab[i].sst==SSTSRCLINES2) read(fh,(void *)&numlines,2);
1520 read(fh,(void *)&numlines,2);
1521 for (j=0;j<numlines;j++) {
1522 read(fh,(void *)&line,2);
1523 read(fh,(void *)&offset,2);
1524 if (offset<=TrapOff && offset>=NrLine) {
1525 NrLine=offset;
1526 sprintf(szNrLine,"% 6hu", line);
1527 sprintf(szNrFile,"% 13.13s ", ename);
1528 /*sprintf(szNrLine,"%04hX:%04hX line #%hu (%s) (%s)\n",
1529 ssmod.csBase,offset,line,ModName,ename); */
1530 }
1531 }
1532 break;
1533 } /* end switch */
1534 i++;
1535 } /* end while modindex */
1536 } /* End While i < numdir */
1537 free(pDirTab);
1538 return(0);
1539}
1540
1541#define MAX_USERDEFS 150
1542#define MAX_POINTERS 150
1543
1544USHORT userdef_count;
1545USHORT pointer_count;
1546
1547struct one_userdef_rec {
1548 USHORT idx;
1549 USHORT type_index;
1550 BYTE name[33];
1551} one_userdef[MAX_USERDEFS];
1552
1553struct one_pointer_rec {
1554 USHORT idx;
1555 USHORT type_index;
1556 BYTE type_qual;
1557 BYTE name[33];
1558} one_pointer[MAX_POINTERS];
1559
1560int Read32PmDebug(int fh,int TrapSeg,int TrapOff,CHAR * FileName) {
1561 static unsigned int CurrSymSeg, NrSymbol,offset,NrPublic,NrFile,NrLine,NrEntry,numdir,namelen,numlines,line;
1562 static int ModIndex;
1563 static int bytesread,i,j;
1564 static int pOffset;
1565 static SSLINEENTRY32 LineEntry;
1566 static SSFILENUM32 FileInfo;
1567 static FIRSTLINEENTRY32 FirstLine;
1568 static BYTE dump_vars = FALSE;
1569 static USHORT idx;
1570 static BOOL read_types;
1571 static LONG lSize;
1572 static BOOL is_new_debug;
1573
1574 ModIndex=0;
1575 /* See if any CODEVIEW info */
1576 if (lseek(fh,-8L,SEEK_END)==-1) {
1577 fprintf(hTrap,"Error %u seeking CodeView table in %s\n",errno,FileName);
1578 return(18);
1579 }
1580
1581 if (read(fh,(void *)&eodbug,8)==-1) {
1582 fprintf(hTrap,"Error %u reading debug info from %s\n",errno,FileName);
1583 return(19);
1584 }
1585 if (eodbug.dbug!=DBUGSIG) {
1586 /*fprintf(hTrap,"\nNo CodeView information stored.\n");*/
1587 return(100);
1588 }
1589
1590 if ((lfaBase=lseek(fh,-eodbug.dfaBase,SEEK_END))==-1L) {
1591 fprintf(hTrap,"Error %u seeking base codeview data in %s\n",errno,FileName);
1592 return(20);
1593 }
1594
1595 if (read(fh,(void *)&base,8)==-1) {
1596 fprintf(hTrap,"Error %u reading base codeview data in %s\n",errno,FileName);
1597 return(21);
1598 }
1599
1600 if (lseek(fh,base.lfoDir-8+4,SEEK_CUR)==-1) {
1601 fprintf(hTrap,"Error %u seeking dir codeview data in %s\n",errno,FileName);
1602 return(22);
1603 }
1604
1605 if (read(fh,(void *)&numdir,4)==-1) {
1606 fprintf(hTrap,"Error %u reading dir codeview data in %s\n",errno,FileName);
1607 return(23);
1608 }
1609
1610 /* Read dir table into buffer */
1611 if (( pDirTab32 = ( struct ssDir32 *) calloc(numdir,sizeof( struct ssDir32)))==NULL) {
1612 fprintf(hTrap,"Out of memory!");
1613 return(-1);
1614 }
1615
1616 if (read(fh,(void *)pDirTab32,numdir*sizeof( struct ssDir32))==-1) {
1617 fprintf(hTrap,"Error %u reading codeview dir table from %s\n",errno,FileName);
1618 free(pDirTab32);
1619 return(24);
1620 }
1621
1622 i=0;
1623 while (i<numdir) {
1624 if ( pDirTab32[i].sst !=SSTMODULES) {
1625 i++;
1626 continue;
1627 }
1628 NrPublic=0x0;
1629 NrSymbol=0;
1630 NrLine=0x0;
1631 NrFile=0x0;
1632 CurrSymSeg = 0;
1633 /* point to subsection */
1634 lseek(fh, pDirTab32[i].lfoStart + lfaBase, SEEK_SET);
1635 read(fh,(void *)&ssmod32.csBase,sizeof(ssmod32));
1636 read(fh,(void *)ModName,(unsigned)ssmod32.csize);
1637 ModIndex=pDirTab32[i].modindex;
1638 ModName[ssmod32.csize]='\0';
1639 i++;
1640
1641 read_types = FALSE;
1642
1643 while (pDirTab32[i].modindex ==ModIndex && i<numdir) {
1644 /* point to subsection */
1645 lseek(fh, pDirTab32[i].lfoStart + lfaBase, SEEK_SET);
1646 switch(pDirTab32[i].sst) {
1647 case SSTPUBLICS:
1648 bytesread=0;
1649 while (bytesread < pDirTab32[i].cb) {
1650 bytesread += read(fh,(void *)&sspub32.offset,sizeof(sspub32));
1651 bytesread += read(fh,(void *)ename,(unsigned)sspub32.csize);
1652 ename[sspub32.csize]='\0';
1653 if ((sspub32.segment==TrapSeg) &&
1654 (sspub32.offset<=TrapOff) &&
1655 (sspub32.offset>=NrPublic)) {
1656 NrPublic = pubfunc_ofs = sspub32.offset;
1657 read_types = TRUE;
1658 sprintf(szNrPub,"%s %s (%s) %04X:%08lu\n",
1659 (sspub32.type==1) ? " Abs" : " ",ename,ModName,
1660 sspub32.segment, sspub32.offset
1661 );
1662 }
1663 }
1664 break;
1665
1666 /* Read symbols, so we can dump the variables on the stack */
1667 case SSTSYMBOLS:
1668 if (TrapSeg!=ssmod32.csBase) break;
1669
1670 bytesread=0;
1671 while (bytesread < pDirTab32[i].cb) {
1672 static USHORT usLength;
1673 static BYTE b1, b2;
1674 static BYTE bType, *ptr;
1675 static ULONG ofs;
1676 static ULONG last_addr = 0;
1677 static BYTE str[256];
1678 static struct symseg_rec symseg;
1679 static struct symauto_rec symauto;
1680 static struct symproc_rec symproc;
1681
1682 /* Read the length of this subentry */
1683 bytesread += read(fh, &b1, 1);
1684 if (b1 & 0x80) {
1685 bytesread += read(fh, &b2, 1);
1686 usLength = ((b1 & 0x7F) << 8) + b2;
1687 }
1688 else
1689 usLength = b1;
1690
1691 ofs = tell(fh);
1692
1693 bytesread += read(fh, &bType, 1);
1694
1695 switch(bType) {
1696 case SYM_CHANGESEG:
1697 read(fh, &symseg, sizeof(symseg));
1698 CurrSymSeg = symseg.seg_no;
1699 break;
1700
1701 case SYM_PROC:
1702 case SYM_CPPPROC:
1703 read(fh, &symproc, sizeof(symproc));
1704 read(fh, str, symproc.name_len);
1705 str[symproc.name_len] = 0;
1706
1707 if ((CurrSymSeg == TrapSeg) &&
1708 (symproc.offset<=TrapOff) &&
1709 (symproc.offset>=NrSymbol)) {
1710
1711 dump_vars = TRUE;
1712 var_ofs = 0;
1713 NrSymbol = symproc.offset;
1714 func_ofs = symproc.offset;
1715
1716 strcpy(func_name, str);
1717 }
1718 else {
1719 dump_vars = FALSE;
1720 }
1721 break;
1722
1723 case SYM_AUTO:
1724 if (!dump_vars)
1725 break;
1726
1727 read(fh, &symauto, sizeof(symauto));
1728 read(fh, str, symauto.name_len);
1729 str[symauto.name_len] = 0;
1730
1731 strcpy(autovar_def[var_ofs].name, str);
1732 autovar_def[var_ofs].stack_offset = symauto.stack_offset;
1733 autovar_def[var_ofs].type_idx = symauto.type_idx;
1734 var_ofs++;
1735 break;
1736
1737 }
1738
1739 bytesread += usLength;
1740
1741 lseek(fh, ofs+usLength, SEEK_SET);
1742 }
1743 break;
1744
1745 case SSTTYPES:
1746// if (ModIndex != TrapSeg)
1747 if (!read_types)
1748 break;
1749
1750 bytesread=0;
1751 idx = 0x200;
1752 userdef_count = 0;
1753 pointer_count = 0;
1754 while (bytesread < pDirTab32[i].cb) {
1755 static struct type_rec type;
1756 static struct type_userdefrec udef;
1757 static struct type_pointerrec point;
1758 static struct type_funcrec func;
1759 static struct type_structrec struc;
1760 static struct type_list1 list1;
1761 static struct type_list2 list2;
1762 static struct type_list2_1 list2_1;
1763 static ULONG ofs;
1764 static BYTE str[256], b1, b2;
1765 static USHORT n;
1766
1767 /* Read the length of this subentry */
1768 ofs = tell(fh);
1769
1770 read(fh, &type, sizeof(type));
1771 bytesread += sizeof(type);
1772
1773 switch(type.type) {
1774 case TYPE_USERDEF:
1775 if (userdef_count > MAX_USERDEFS)
1776 break;
1777
1778 read(fh, &udef, sizeof(udef));
1779 read(fh, str, udef.name_len);
1780 str[udef.name_len] = 0;
1781
1782 // Insert userdef in table
1783 one_userdef[userdef_count].idx = idx;
1784 one_userdef[userdef_count].type_index = udef.type_index;
1785 memcpy(one_userdef[userdef_count].name, str, min(udef.name_len+1, 32));
1786 one_userdef[userdef_count].name[32] = 0;
1787 userdef_count++;
1788 break;
1789
1790 case TYPE_POINTER:
1791 if (pointer_count > MAX_POINTERS)
1792 break;
1793
1794 read(fh, &point, sizeof(point));
1795 read(fh, str, point.name_len);
1796 str[point.name_len] = 0;
1797
1798 // Insert userdef in table
1799 one_pointer[pointer_count].idx = idx;
1800 one_pointer[pointer_count].type_index = point.type_index;
1801 memcpy(one_pointer[pointer_count].name, str, min(point.name_len+1, 32));
1802 one_pointer[pointer_count].name[32] = 0;
1803 one_pointer[pointer_count].type_qual = type.type_qual;
1804 pointer_count++;
1805 break;
1806 }
1807
1808 ++idx;
1809
1810 bytesread += type.length;
1811
1812 lseek(fh, ofs+type.length+2, SEEK_SET);
1813 }
1814 break;
1815
1816 case SSTSRCLINES32:
1817 if (TrapSeg!=ssmod32.csBase) break;
1818
1819 /* read first line */
1820 do {
1821 read(fh,(void *)&FirstLine,sizeof(FirstLine));
1822
1823 if (FirstLine.LineNum!=0) {
1824 fprintf(hTrap,"Missing Line table information\n");
1825 break;
1826 } /* endif */
1827 numlines= FirstLine.numlines;
1828 /* Other type of data skip 4 more bytes */
1829 if (FirstLine.entry_type < 4) {
1830 read(fh, (void *)&lSize, 4);
1831 if (FirstLine.entry_type == 3)
1832 lseek(fh,lSize,SEEK_CUR);
1833 }
1834 } while(FirstLine.entry_type == 3);
1835
1836 for (j=0;j<numlines;j++) {
1837 switch (FirstLine.entry_type) {
1838 case 0:
1839 read(fh,(void *)&LineEntry,sizeof(LineEntry));
1840 /* Changed by Kim Rasmussen 26/06 1996 to ignore linenumber 0 */
1841 /* if (LineEntry.Offset+ssmod32.csOff<=TrapOff && LineEntry.Offset+ssmod32.csOff>=NrLine) { */
1842 if (LineEntry.LineNum && LineEntry.Offset+ssmod32.csOff<=TrapOff && LineEntry.Offset+ssmod32.csOff>=NrLine) {
1843 NrLine=LineEntry.Offset;
1844 NrFile=LineEntry.FileNum;
1845 /*pOffset =sprintf(szNrLine,"%04X:%08X line #%hu ",
1846 ssmod32.csBase,LineEntry.Offset,
1847 LineEntry.LineNum);*/
1848 sprintf(szNrLine,"% 6hu", LineEntry.LineNum);
1849 }
1850 break;
1851
1852 case 1:
1853 lseek(fh, sizeof(struct linlist_rec), SEEK_CUR);
1854 break;
1855
1856 case 2:
1857 lseek(fh, sizeof(struct linsourcelist_rec), SEEK_CUR);
1858 break;
1859
1860 case 3:
1861 lseek(fh, sizeof(struct filenam_rec), SEEK_CUR);
1862 break;
1863
1864 case 4:
1865 lseek(fh, sizeof(struct pathtab_rec), SEEK_CUR);
1866 break;
1867
1868 }
1869 }
1870 if (NrFile!=0) {
1871 read(fh,(void *)&FileInfo,sizeof(FileInfo));
1872 namelen=0;
1873 for (j=1;j<=FileInfo.file_count;j++) {
1874 namelen=0;
1875 read(fh,(void *)&namelen,1);
1876 read(fh,(void *)ename,namelen);
1877 if (j==NrFile) break;
1878 }
1879 ename[namelen]='\0';
1880 /* pOffset=sprintf(szNrLine+pOffset," (%s) (%s)\n",ename,ModName);*/
1881 sprintf(szNrFile,"% 13.13s ",ename);
1882 } else {
1883 /* strcat(szNrLine,"\n"); avoid new line for empty name fill */
1884 strcpy(szNrFile," ");
1885 } /* endif */
1886 break;
1887 } /* end switch */
1888
1889 i++;
1890 } /* end while modindex */
1891 } /* End While i < numdir */
1892 free(pDirTab32);
1893 return(0);
1894}
1895
1896BYTE *var_value(void *varptr, BYTE type)
1897{
1898 static BYTE value[128];
1899 APIRET rc;
1900
1901 strcpy(value, "Unknown");
1902
1903 if (type == 0)
1904 sprintf(value, "%hhi", *(signed char *)varptr);
1905 else if (type == 1)
1906 sprintf(value, "%hd", *(signed short *)varptr);
1907 else if (type == 2)
1908 sprintf(value, "%ld", *(signed long *)varptr);
1909 else if (type == 4)
1910 sprintf(value, "%hu", *(BYTE *)varptr);
1911 else if (type == 5)
1912 sprintf(value, "%hu", *(USHORT *)varptr);
1913 else if (type == 6)
1914 sprintf(value, "%lu", *(ULONG *)varptr);
1915 else if (type == 8)
1916 sprintf(value, "%f", *(float *)varptr);
1917 else if (type == 9)
1918 sprintf(value, "%f", *(double *)varptr);
1919 else if (type == 10)
1920 sprintf(value, "%Lf", *(long double *)varptr);
1921 else if (type == 16)
1922 sprintf(value, "%s", *(char *)varptr ? "TRUE" : "FALSE");
1923 else if (type == 17)
1924 sprintf(value, "%s", *(short *)varptr ? "TRUE" : "FALSE");
1925 else if (type == 18)
1926 sprintf(value, "%s", *(long *)varptr ? "TRUE" : "FALSE");
1927 else if (type == 20)
1928 sprintf(value, "%c", *(char *)varptr);
1929 else if (type == 21)
1930 sprintf(value, "%hi", *(short *)varptr);
1931 else if (type == 22)
1932 sprintf(value, "%lc", *(long *)varptr);
1933 else if (type == 23)
1934 sprintf(value, "void");
1935 else if (type >= 32) {
1936 ULONG Size,Attr;
1937 Size=1;
1938 rc=DosQueryMem((void*)*(ULONG *)varptr,&Size,&Attr);
1939 if (rc) {
1940 sprintf(value, "0x%p invalid", *(ULONG *)varptr);
1941 } else {
1942 sprintf(value, "0x%p", *(ULONG *)varptr);
1943 if (Attr&PAG_FREE) {
1944 strcat(value," unallocated memory");
1945 } else {
1946 if ((Attr&PAG_COMMIT)==0x0U) {
1947 strcat(value," uncommited");
1948 } /* endif */
1949 if ((Attr&PAG_WRITE)==0x0U) {
1950 strcat(value," unwritable");
1951 } /* endif */
1952 if ((Attr&PAG_READ)==0x0U) {
1953 strcat(value," unreadable");
1954 } /* endif */
1955 } /* endif */
1956 } /* endif */
1957 }
1958
1959 return value;
1960}
1961
1962/* Search the table of userdef's - return TRUE if found */
1963BOOL search_userdefs(ULONG stackofs, USHORT var_no)
1964{
1965 USHORT pos;
1966
1967 for(pos = 0; pos < userdef_count && one_userdef[pos].idx != autovar_def[var_no].type_idx; pos++);
1968
1969 if (pos < userdef_count) {
1970 if (one_userdef[pos].type_index >= 0x80 && one_userdef[pos].type_index <= 0xDA) {
1971 fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
1972 autovar_def[var_no].stack_offset,
1973 autovar_def[var_no].name,
1974 one_userdef[pos].name,
1975 var_value((void *)(stackofs+autovar_def[var_no].stack_offset),
1976 one_userdef[pos].type_index-0x80));
1977 return TRUE;
1978 }
1979 else /* If the result isn't a simple type, let's act as we didn't find it */
1980 return FALSE;
1981 }
1982
1983 return FALSE;
1984}
1985
1986BOOL search_pointers(ULONG stackofs, USHORT var_no)
1987{
1988 USHORT pos, upos;
1989 static BYTE str[35];
1990 BYTE type_index;
1991
1992 for(pos = 0; pos < pointer_count && one_pointer[pos].idx != autovar_def[var_no].type_idx; pos++);
1993
1994 if (pos < pointer_count) {
1995 if (one_pointer[pos].type_index >= 0x80 && one_pointer[pos].type_index <= 0xDA) {
1996 strcpy(str, type_name[one_pointer[pos].type_index-0x80]);
1997 strcat(str, " *");
1998 fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
1999 autovar_def[var_no].stack_offset,
2000 autovar_def[var_no].name,
2001 str,
2002 var_value((void *)(stackofs+autovar_def[var_no].stack_offset), 32));
2003 return TRUE;
2004 }
2005 else { /* If the result isn't a simple type, look for it in the other lists */
2006 for(upos = 0; upos < userdef_count && one_userdef[upos].idx != one_pointer[pos].type_index; upos++);
2007
2008 if (upos < userdef_count) {
2009 strcpy(str, one_userdef[upos].name);
2010 strcat(str, " *");
2011 fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
2012 autovar_def[var_no].stack_offset,
2013 autovar_def[var_no].name,
2014 str,
2015 var_value((void *)(stackofs+autovar_def[var_no].stack_offset), 32));
2016 return TRUE;
2017 }
2018 else { /* If it isn't a userdef, for now give up and just print as much as we know */
2019 sprintf(str, "Pointer to type 0x%X", one_pointer[pos].type_index);
2020
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
2027 return TRUE;
2028 }
2029 }
2030 }
2031
2032 return FALSE;
2033}
2034
2035void print_vars(ULONG stackofs)
2036{
2037 USHORT n, pos;
2038 BOOL AutoVarsFound=FALSE;
2039
2040/* stackofs += stack_ebp; */
2041 if (1 || func_ofs == pubfunc_ofs) { //fixme GKY 1-22-24 why is this here since its always true
2042 for(n = 0; n < var_ofs; n++) {
2043 if (AutoVarsFound==FALSE) {
2044 AutoVarsFound=TRUE;
2045 fprintf(hTrap, "List of auto variables at EBP %p in %s:\n",stackofs, func_name);
2046 fprintf(hTrap,"Offset Name Type Value \n");
2047 fprintf(hTrap,"ÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\n");
2048 }
2049
2050 /* If it's one of the simple types */
2051 if (autovar_def[n].type_idx >= 0x80 && autovar_def[n].type_idx <= 0xDA)
2052 {
2053 fprintf(hTrap, "%- 6d %- 20.20s %- 33.33s %s\n",
2054 autovar_def[n].stack_offset,
2055 autovar_def[n].name,
2056 type_name[autovar_def[n].type_idx-0x80],
2057 var_value((void *)(stackofs+autovar_def[n].stack_offset),
2058 autovar_def[n].type_idx-0x80));
2059 }
2060 else { /* Complex type, check if we know what it is */
2061 if (!search_userdefs(stackofs, n)) {
2062 if (!search_pointers(stackofs, n)) {
2063 fprintf(hTrap, "%- 6d %-20.20s 0x%X\n",
2064 autovar_def[n].stack_offset,
2065 autovar_def[n].name,
2066 autovar_def[n].type_idx);
2067 }
2068 }
2069 }
2070 }
2071 if (AutoVarsFound==FALSE) {
2072 fprintf(hTrap, " No auto variables found in %s.\n", func_name);
2073 }
2074 fprintf(hTrap, "\n");
2075 }
2076}
2077
2078
2079
Note: See TracBrowser for help on using the repository browser.