source: branches/v2.9/mediafolder/c/helper/except.cpp

Last change on this file was 2, checked in by stevenhl, 8 years ago

Import sources from cwmm-full.zip dated 2005-03-21

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