home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / except2x.zip / exceptq.x < prev    next >
Text File  |  1994-09-12  |  65KB  |  1,644 lines

  1. /**********************************************************************/
  2. /*                           IBM Internal Use Only                    */
  3. /**********************************************************************/
  4. /*                                                                    */
  5. /*  EXCEPTQ                                                           */
  6. /*                                                                    */
  7. /* DLL containing an exception handler for gathering trap information */
  8. /* This DLL dumps all important debugging Data and is accessible      */
  9. /* from both 16 bit and 32 bits programs                              */
  10. /**********************************************************************/
  11. /* Version: 2.3             |   Marc Fiammante (FIAMMANT at LGEVM2)   */
  12. /*                          |   La Gaude FRANCE                       */
  13. /*                          | +WalkStack From John Currier            */
  14. /*                          |   V$IJNC at CTLVM1                      */
  15. /*                          |   Charlotte USA                         */
  16. /**********************************************************************/
  17. /*                                                                    */
  18. /**********************************************************************/
  19. /* History:                                                           */
  20. /* --------                                                           */
  21. /*                                                                    */
  22. /* created: Marc Fiammante December 1992                              */
  23. /* Last Modified:          August   1994 changed WalkStack            */
  24. /*                         to John Currier's                          */
  25. /**********************************************************************/
  26. #define INCL_BASE
  27. #define INCL_DOSEXCEPTIONS
  28. #define INCL_DOSSEMAPHORES   /* Semaphore values */
  29. #include <os2.h>
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <time.h>
  33. #include "sym.h"
  34.  
  35. #define HF_STDERR 2
  36. UCHAR *ProcessName = "DEBUGGEE.EXE";
  37. FILE   *hTrap;
  38. static BOOL   f32bit;
  39. struct debug_buffer
  40.  {
  41.    ULONG   Pid;        /* Debuggee Process ID */
  42.    ULONG   Tid;        /* Debuggee Thread ID */
  43.    LONG    Cmd;        /* Command or Notification */
  44.    LONG    Value;      /* Generic Data Value */
  45.    ULONG   Addr;       /* Debuggee Address */
  46.    ULONG   Buffer;     /* Debugger Buffer Address */
  47.    ULONG   Len;        /* Length of Range */
  48.    ULONG   Index;      /* Generic Identifier Index */
  49.    ULONG   MTE;        /* Module Handle */
  50.    ULONG   EAX;        /* Register Set */
  51.    ULONG   ECX;
  52.    ULONG   EDX;
  53.    ULONG   EBX;
  54.    ULONG   ESP;
  55.    ULONG   EBP;
  56.    ULONG   ESI;
  57.    ULONG   EDI;
  58.    ULONG   EFlags;
  59.    ULONG   EIP;
  60.    ULONG   CSLim;      /* Byte Granular Limits */
  61.    ULONG   CSBase;     /* Byte Granular Base */
  62.    UCHAR   CSAcc;      /* Access Bytes */
  63.    UCHAR   CSAtr;      /* Attribute Bytes */
  64.    USHORT  CS;
  65.    ULONG   DSLim;
  66.    ULONG   DSBase;
  67.    UCHAR   DSAcc;
  68.    UCHAR   DSAtr;
  69.    USHORT  DS;
  70.    ULONG   ESLim;
  71.    ULONG   ESBase;
  72.    UCHAR   ESAcc;
  73.    UCHAR   ESAtr;
  74.    USHORT  ES;
  75.    ULONG   FSLim;
  76.    ULONG   FSBase;
  77.    UCHAR   FSAcc;
  78.    UCHAR   FSAtr;
  79.    USHORT  FS;
  80.    ULONG   GSLim;
  81.    ULONG   GSBase;
  82.    UCHAR   GSAcc;
  83.    UCHAR   GSAtr;
  84.    USHORT  GS;
  85.    ULONG   SSLim;
  86.    ULONG   SSBase;
  87.    UCHAR   SSAcc;
  88.    UCHAR   SSAtr;
  89.    USHORT  SS;
  90. } DbgBuf;
  91. /*-------------------------------------*/
  92. APIRET APIENTRY DOSQUERYMODFROMEIP( HMODULE *phMod,
  93.                                     ULONG *pObjNum,
  94.                                     ULONG BuffLen,
  95.                                     PCHAR pBuff,
  96.                                     ULONG *pOffset,
  97.                                     PVOID Address );
  98. APIRET APIENTRY DosQueryModFromEIP( HMODULE *phMod,
  99.                                     ULONG *pObjNum,
  100.                                     ULONG BuffLen,
  101.                                     PCHAR pBuff,
  102.                                     ULONG *pOffset,
  103.                                     PVOID Address );
  104.  
  105. /*-------------------------------------*/
  106. #define DBG_O_OBJMTE       0x10000000L
  107. #define DBG_C_NumToAddr            13
  108. #define DBG_C_AddrToObject         28
  109. #define DBG_C_Connect              21
  110. #define DBG_L_386                   1
  111. RESULTCODES ReturnCodes;
  112. UCHAR   LoadError[40]; /*DosExecPGM buffer */
  113. UCHAR   Translate[17];
  114. #ifdef USE_DOSDEBUG
  115. void    GetObjects(struct debug_buffer * pDbgBuf,HMODULE hMte,PSZ pName);
  116. #endif
  117. VOID    ListModules(VOID);
  118. void    CheckMem(PVOID Ptr,PSZ MemoryName);
  119. /* Better New WalkStack From John Currier */
  120. static void WalkStack(PUSHORT StackBottom,PUSHORT StackTop,PUSHORT Ebp,PUSHORT ExceptionAddress);
  121. int    Read16CodeView(int fh,int TrapSeg,int TrapOff,CHAR * FileName);
  122. int    Read32PmDebug(int fh,int TrapSeg,int TrapOff,CHAR * FileName);
  123. APIRET GetLineNum(CHAR * FileName, ULONG Object,ULONG TrapOffset);
  124. void GetSymbol(CHAR * SymFileName, ULONG Object,ULONG TrapOffset);
  125. HMODULE hMod;
  126. ULONG   ObjNum;
  127. ULONG   Offset;
  128. /*-------------------------------------*/
  129. CHAR    Buffer[CCHMAXPATH];
  130.  
  131. typedef ULONG     * _Seg16 PULONG16;
  132. APIRET16 APIENTRY16 DOS16SIZESEG( USHORT Seg , PULONG16 Size);
  133. typedef  APIRET16  (APIENTRY16  _PFN16)();
  134. ULONG  APIENTRY DosSelToFlat(ULONG);
  135. /*-------------------------------------*/
  136. /*- DosQProcStatus interface ----------*/
  137. APIRET16 APIENTRY16 DOSQPROCSTATUS(  ULONG * _Seg16 pBuf, USHORT cbBuf);
  138. #define CONVERT(fp,QSsel) MAKEP((QSsel),OFFSETOF(fp))
  139. #pragma pack(1)
  140. /*  Global Data Section */
  141. typedef struct qsGrec_s {
  142.     ULONG     cThrds;  /* number of threads in use */
  143.     ULONG     Reserved1;
  144.     ULONG     Reserved2;
  145. }qsGrec_t;
  146. /* Thread Record structure *   Holds all per thread information. */
  147. typedef struct qsTrec_s {
  148.     ULONG     RecType;    /* Record Type */
  149.                           /* Thread rectype = 100 */
  150.     USHORT    tid;        /* thread ID */
  151.     USHORT    slot;       /* "unique" thread slot number */
  152.     ULONG     sleepid;    /* sleep id thread is sleeping on */
  153.     ULONG     priority;   /* thread priority */
  154.     ULONG     systime;    /* thread system time */
  155.     ULONG     usertime;   /* thread user time */
  156.     UCHAR     state;      /* thread state */
  157.     UCHAR     PADCHAR;
  158.     USHORT    PADSHORT;
  159. } qsTrec_t;
  160. /* Process and Thread Data Section */
  161. typedef struct qsPrec_s {
  162.     ULONG           RecType;    /* type of record being processed */
  163.                           /* process rectype = 1       */
  164.     qsTrec_t *      pThrdRec;  /* ptr to 1st thread rec for this prc*/
  165.     USHORT          pid;       /* process ID */
  166.     USHORT          ppid;      /* parent process ID */
  167.     ULONG           type;      /* process type */
  168.     ULONG           stat;      /* process status */
  169.     ULONG           sgid;      /* process screen group */
  170.     USHORT          hMte;      /* program module handle for process */
  171.     USHORT          cTCB;      /* # of TCBs in use in process */
  172.     ULONG           Reserved1;
  173.     void   *        Reserved2;
  174.     USHORT          c16Sem;     /*# of 16 bit system sems in use by proc*/
  175.     USHORT          cLib;       /* number of runtime linked libraries */
  176.     USHORT          cShrMem;    /* number of shared memory handles */
  177.     USHORT          Reserved3;
  178.     USHORT *        p16SemRec;   /*ptr to head of 16 bit sem inf for proc*/
  179.     USHORT *        pLibRec;     /*ptr to list of runtime lib in use by */
  180.                                   /*process*/
  181.     USHORT *        pShrMemRec;  /*ptr to list of shared mem handles in */
  182.                                   /*use by process*/
  183.     USHORT *        Reserved4;
  184. } qsPrec_t;
  185. /* 16 Bit System Semaphore Section */
  186. typedef struct qsS16Headrec_s {
  187.     ULONG     RecType;   /* semaphore rectype = 3 */
  188.     ULONG     Reserved1;  /* overlays NextRec of 1st qsS16rec_t */
  189.     ULONG     Reserved2;
  190.     ULONG     S16TblOff;  /* index of first semaphore,SEE PSTAT OUTPUT*/
  191.                           /* System Semaphore Information Section     */
  192. } qsS16Headrec_t;
  193. /*  16 bit System Semaphore Header Record Structure */
  194. typedef struct qsS16rec_s {
  195.     ULONG      NextRec;          /* offset to next record in buffer */
  196.     UINT       s_SysSemOwner ;   /* thread owning this semaphore    */
  197.     UCHAR      s_SysSemFlag ;    /* system semaphore flag bit field */
  198.     UCHAR      s_SysSemRefCnt ;  /* number of references to this    */
  199.                                  /*  system semaphore               */
  200.     UCHAR      s_SysSemProcCnt ; /*number of requests by sem owner  */
  201.     UCHAR      Reserved1;
  202.     ULONG      Reserved2;
  203.     UINT       Reserved3;
  204.     CHAR       SemName[1];       /* start of semaphore name string */
  205. } qsS16rec_t;
  206. /*  Executable Module Section */
  207. typedef struct qsLrec_s {
  208.     void        * pNextRec;    /* pointer to next record in buffer */
  209.     USHORT        hmte;         /* handle for this mte */
  210.     USHORT        Reserved1;    /* Reserved */
  211.     ULONG         ctImpMod;     /* # of imported modules in table */
  212.     ULONG         Reserved2;    /* Reserved */
  213. /*  qsLObjrec_t * Reserved3;       Reserved */
  214.     ULONG       * Reserved3;    /* Reserved */
  215.     UCHAR       * pName;        /* ptr to name string following stru*/
  216. } qsLrec_t;
  217. /*  Shared Memory Segment Section */
  218. typedef struct qsMrec_s {
  219.     struct qsMrec_s *MemNextRec;    /* offset to next record in buffer */
  220.     USHORT    hmem;          /* handle for shared memory */
  221.     USHORT    sel;           /* shared memory selector */
  222.     USHORT    refcnt;        /* reference count */
  223.     CHAR      Memname[1];    /* start of shared memory name string */
  224. } qsMrec_t;
  225. /*  Pointer Record Section */
  226. typedef struct qsPtrRec_s {
  227.     qsGrec_t       *  pGlobalRec;        /* ptr to the global data section */
  228.     qsPrec_t       *  pProcRec;          /* ptr to process record section  */
  229.     qsS16Headrec_t *  p16SemRec;         /* ptr to 16 bit sem section      */
  230.     void           *  Reserved;          /* a reserved area                */
  231.     qsMrec_t       *  pShrMemRec;        /* ptr to shared mem section      */
  232.     qsLrec_t       *  pLibRec;           /*ptr to exe module record section*/
  233. } qsPtrRec_t;
  234. /*-------------------------*/
  235. ULONG * pBuf,*pTemp;
  236. USHORT  Selector;
  237. qsPtrRec_t * pRec;
  238. qsLrec_t   * pLib;
  239. qsMrec_t   * pShrMemRec;        /* ptr to shared mem section      */
  240. qsPrec_t   * pProc;
  241. qsTrec_t   * pThread;
  242. ULONG      ListedThreads=0;
  243. APIRET16 APIENTRY16 DOS16ALLOCSEG(
  244.         USHORT          cbSize,          /* number of bytes requested                   */
  245.         USHORT  * _Seg16 pSel,           /* sector allocated (returned)                 */
  246.         USHORT fsAlloc);                 /* sharing attributes of the allocated segment */
  247. typedef struct
  248.   {
  249.     short int      ilen;     /* Instruction length */
  250.     long           rref;     /* Value of any IP relative storage reference */
  251.     unsigned short sel;      /* Selector of any CS:eIP storage reference.   */
  252.     long           poff;     /* eIP value of any CS:eIP storage reference. */
  253.     char           longoper; /* YES/NO value. Is instr in 32 bit operand mode? **/
  254.     char           longaddr; /* YES/NO value. Is instr in 32 bit address mode? **/
  255.     char           buf[40];  /* String holding disassembled instruction **/
  256.   } * _Seg16 RETURN_FROM_DISASM;
  257. RETURN_FROM_DISASM CDECL16 DISASM( CHAR * _Seg16 Source, USHORT IPvalue,USHORT segsize );
  258. RETURN_FROM_DISASM AsmLine;
  259. static USHORT BigSeg;
  260. static ULONG  Version[2];
  261. /*--                                 --*/
  262. /*-------------------------------------*/
  263.  
  264.  
  265. typedef  _PFN16 * _Seg16 PFN16;
  266. /*--                                 --*/
  267. static BOOL InForceExit =FALSE;
  268. /*-------------------------------------*/
  269.  
  270. ULONG APIENTRY myHandler (PEXCEPTIONREPORTRECORD       pERepRec,
  271.                           PEXCEPTIONREGISTRATIONRECORD pERegRec,
  272.                           PCONTEXTRECORD               pCtxRec,
  273.                           PVOID                        p)
  274. {
  275.   PCHAR   SegPtr;
  276.   PUSHORT StackPtr;
  277.   PUSHORT ValidStackBottom;
  278.   PUCHAR  TestStackBottom;
  279.   PUCHAR  cStackPtr;
  280.   ULONG Size,Flags,Attr,CSSize;
  281.   APIRET rc;
  282.   APIRET semrc;
  283.   APIRET16 rc16;
  284.   PTIB   ptib;
  285.   PPIB   ppib;
  286.   USHORT Count;
  287.   ULONG  Nest;
  288.   UCHAR  TrapFile[20];
  289.   struct debug_buffer DbgBuf;
  290.   static CHAR Name[CCHMAXPATH];
  291.   /* Do not recurse into Trapper (John Currier) */
  292.    static BOOL fAlreadyTrapped = FALSE;
  293.  
  294.   if (InForceExit) {
  295.       return (XCPT_CONTINUE_SEARCH);
  296.   } /* endif */
  297.   if ((pERepRec->ExceptionNum&XCPT_SEVERITY_CODE)==XCPT_FATAL_EXCEPTION)
  298.   {
  299.     if ((pERepRec->ExceptionNum!=XCPT_PROCESS_TERMINATE)&&
  300.         (pERepRec->ExceptionNum!=XCPT_UNWIND)&&
  301.         (pERepRec->ExceptionNum!=XCPT_SIGNAL)&&
  302.         (pERepRec->ExceptionNum!=XCPT_ASYNC_PROCESS_TERMINATE)) {
  303.         DosEnterMustComplete(&Nest);
  304.         rc=DosGetInfoBlocks(&ptib,&ppib);
  305.         if (rc==NO_ERROR) {
  306.            sprintf(TrapFile,"%d%d.TRP",
  307.                    ppib->pib_ulpid,ptib->tib_ptib2->tib2_ultid);
  308.         } else {
  309.            sprintf(TrapFile,"TRAP.TRP");
  310.         }
  311.         printf("Creating %s\n",TrapFile);
  312.         hTrap=fopen(TrapFile,"a");
  313.         if (hTrap==NULL) {
  314.            printf("hTrap NULL\n");
  315.            hTrap=stdout;
  316.         }
  317.         setbuf( hTrap, NULL);
  318.         fprintf(hTrap,"--------------------------\n");
  319.         fprintf(hTrap,"Exception %8.8lX Occurred\n",pERepRec->ExceptionNum);
  320.         fprintf(hTrap," at %s ",_strtime(Buffer));
  321.         fprintf(hTrap," %s\n",_strdate(Buffer));
  322.         if ( pERepRec->ExceptionNum     ==         XCPT_ACCESS_VIOLATION)
  323.         {
  324.            switch (pERepRec->ExceptionInfo[0]) {
  325.                 case XCPT_READ_ACCESS:
  326.                 case XCPT_WRITE_ACCESS:
  327.                    fprintf(hTrap,"Invalid linear address %8.8lX\n",pERepRec->ExceptionInfo[1]);
  328.                    break;
  329.                case XCPT_SPACE_ACCESS:
  330.                   /* Thanks to John Currier              */
  331.                   /* It looks like this is off by one... */
  332.                   fprintf(hTrap,"Invalid Selector: %8.8p",
  333.                                  pERepRec->ExceptionInfo[1] ?
  334.                                  pERepRec->ExceptionInfo[1] + 1 : 0);
  335.                   break;
  336.                 case XCPT_LIMIT_ACCESS:
  337.                    fprintf(hTrap,"Limit access fault\n");
  338.                    break;
  339.                 case XCPT_UNKNOWN_ACCESS:
  340.                    fprintf(hTrap,"Unknown access fault\n");
  341.                    break;
  342.               break;
  343.            default:
  344.                    fprintf(hTrap,"Other Unknown access fault\n");
  345.            } /* endswitch */
  346.         } /* endif */
  347.        /* John Currier's recursion prevention */
  348.          fprintf(hTrap,"\n\n");
  349.  
  350.          if (fAlreadyTrapped)
  351.          {
  352.             fprintf(hTrap, "Exception Handler Trapped...aborting evaluation!\n");
  353.             if (hTrap != stderr)
  354.                fclose(hTrap);
  355.             DosExitMustComplete(&Nest);
  356.             DosUnsetExceptionHandler(pERegRec);
  357.             return (XCPT_CONTINUE_SEARCH);
  358.          }
  359.  
  360.          fAlreadyTrapped = TRUE;
  361.        /* end  John Currier's recursion prevention */
  362.         rc = DosQuerySysInfo(QSV_VERSION_MAJOR,QSV_VERSION_MINOR,
  363.                              Version,sizeof(Version));
  364.         if ((rc==0)&&
  365.             (Version[0]>=20) &&
  366.             (Version[1]>=10) ) {
  367.             /* version must be over 2.1 for DOSQUERYMODFROMEIP */
  368.             fprintf(hTrap,"OS/2 Version %d.%d\n",Version[0]/10,Version[1]);
  369.             rc=DOSQUERYMODFROMEIP( &hMod, &ObjNum, CCHMAXPATH,
  370.                                 Name, &Offset, pERepRec->ExceptionAddress);
  371.             if (rc==0) {
  372.               fprintf(hTrap,"Failing code module internal name : %s\n",Name);
  373.               rc=DosQueryModuleName(hMod,CCHMAXPATH, Name);
  374.               fprintf(hTrap,"Failing code module file name : %s\n",Name);
  375.               fprintf(hTrap,"Failing code Object # %d at Offset %x \n",ObjNum+1,Offset);
  376.               if (strlen(Name)>3) {
  377.                 fprintf(hTrap,"     Source    Line      Nearest\n");
  378.                 fprintf(hTrap,"      File     Numbr  Public Symbol\n");
  379.                 fprintf(hTrap,"  ------------ -----  -------------\n");
  380.                  rc =GetLineNum(Name,ObjNum,Offset);
  381.                  /* if no codeview try with symbol files */
  382.                  if (rc!=0) {
  383.                     strcpy(Name+strlen(Name)-3,"SYM"); /* Get Sym File name */
  384.                     GetSymbol(Name,ObjNum,Offset);
  385.                  } /* endif */
  386.               } /* endif */
  387.               fprintf(hTrap,"\n\n");
  388.             } else {
  389.                fprintf(hTrap,"Invalid execution address\n");
  390.             } /* endif */
  391.         } /* endif */
  392.         if ( (pCtxRec->ContextFlags) & CONTEXT_SEGMENTS ) {
  393.              fprintf(hTrap,"GS  : %4.4lX     ",pCtxRec->ctx_SegGs);
  394.              fprintf(hTrap,"FS  : %4.4lX     ",pCtxRec->ctx_SegFs);
  395.              fprintf(hTrap,"ES  : %4.4lX     ",pCtxRec->ctx_SegEs);
  396.              fprintf(hTrap,"DS  : %4.4lX     \n",pCtxRec->ctx_SegDs);
  397.         } /* endif */
  398.         if ( (pCtxRec->ContextFlags) & CONTEXT_INTEGER  ) {
  399.              fprintf(hTrap,"EDI : %8.8lX ",pCtxRec->ctx_RegEdi  );
  400.              fprintf(hTrap,"ESI : %8.8lX ",pCtxRec->ctx_RegEsi  );
  401.              fprintf(hTrap,"EAX : %8.8lX ",pCtxRec->ctx_RegEax  );
  402.              fprintf(hTrap,"EBX : %8.8lX\n",pCtxRec->ctx_RegEbx  );
  403.              fprintf(hTrap,"ECX : %8.8lX ",pCtxRec->ctx_RegEcx  );
  404.              fprintf(hTrap,"EDX : %8.8lX\n",pCtxRec->ctx_RegEdx  );
  405.         } /* endif */
  406.         if ( (pCtxRec->ContextFlags) & CONTEXT_CONTROL  ) {
  407.              void * _Seg16 Ptr16;
  408.              fprintf(hTrap,"EBP : %8.8lX ",pCtxRec->ctx_RegEbp  );
  409.              fprintf(hTrap,"EIP : %8.8lX ",pCtxRec->ctx_RegEip  );
  410.              fprintf(hTrap,"EFLG: %8.8lX ",pCtxRec->ctx_EFlags  );
  411.              fprintf(hTrap,"ESP : %8.8lX\n",pCtxRec->ctx_RegEsp  );
  412.              fprintf(hTrap,"CS  : %4.4lX     ",pCtxRec->ctx_SegCs   );
  413.              fprintf(hTrap,"SS  : %4.4lX\n",pCtxRec->ctx_SegSs   );
  414.              SegPtr =MAKEP((SHORT)pCtxRec->ctx_SegCs,0);
  415.              rc16 =DOS16SIZESEG( (USHORT)pCtxRec->ctx_SegCs , &CSSize);
  416.              if (rc16==NO_ERROR) {
  417.                 fprintf(hTrap,"CSLIM: %8.8lX ",CSSize);
  418.              } else {
  419.                 CSSize=0;
  420.              } /* endif */
  421.              rc16 =DOS16SIZESEG( (USHORT)pCtxRec->ctx_SegSs , &Size);
  422.              if (rc16==NO_ERROR) {
  423.                 fprintf(hTrap,"SSLIM: %8.8lX \n",Size);
  424.              } /* endif */
  425.              BigSeg=((pCtxRec->ctx_RegEip)>0x00010000);
  426.              if (BigSeg) {
  427.                  AsmLine= DISASM( (PVOID) pCtxRec->ctx_RegEip,
  428.                                   (USHORT)pCtxRec->ctx_RegEip, BigSeg );
  429.                  fprintf(hTrap,"\n Failing instruction at CS:EIP : %4.4X:%8.8X is  %s\n\n",
  430.                          pCtxRec->ctx_SegCs,
  431.                          pCtxRec->ctx_RegEip,AsmLine->buf);
  432.                  fprintf(hTrap,"Information on Registers :\n");
  433.                  CheckMem( (PVOID)pCtxRec->ctx_RegEax,"EAX");
  434.                  CheckMem( (PVOID)pCtxRec->ctx_RegEbx,"EBX");
  435.                  CheckMem( (PVOID)pCtxRec->ctx_RegEcx,"ECX");
  436.                  CheckMem( (PVOID)pCtxRec->ctx_RegEdx,"EDX");
  437.                  CheckMem( (PVOID)pCtxRec->ctx_RegEdi,"EDI");
  438.                  CheckMem( (PVOID)pCtxRec->ctx_RegEsi,"ESI");
  439.                  fprintf(hTrap,"\n");
  440.              } else {
  441.                  if (CSSize>pCtxRec->ctx_RegEip) {
  442.                     AsmLine= DISASM(MAKE16P(pCtxRec->ctx_SegCs,
  443.                                             pCtxRec->ctx_RegEip),
  444.                                     (USHORT)pCtxRec->ctx_RegEip, BigSeg );
  445.                     fprintf(hTrap,"\n Failing instruction at CS:IP : %4.4X:%4.4X is   %s\n\n",
  446.                            pCtxRec->ctx_SegCs,
  447.                            pCtxRec->ctx_RegEip,AsmLine->buf);
  448.                  } else {
  449.                      fprintf(hTrap,"Invalid execution address\n");
  450.                  } /* endif */
  451.                  fprintf(hTrap,"Information on Source Destination registers pairs :\n");
  452.                  rc16 =DOS16SIZESEG( (USHORT)pCtxRec->ctx_SegDs , &Size);
  453.                  if (rc16==NO_ERROR) {
  454.                     if ((USHORT)Size<(USHORT)pCtxRec->ctx_RegEsi) {
  455.                        fprintf(hTrap," DS:SI points outside Data Segment\n");
  456.                     } /* endif */
  457.                  } else {
  458.                     fprintf(hTrap," DS (Data Segment) Is Invalid\n");
  459.                  } /* endif */
  460.                  rc16 =DOS16SIZESEG( (USHORT)pCtxRec->ctx_SegEs , &Size);
  461.                  if (rc16==NO_ERROR) {
  462.                     if ((USHORT)Size<(USHORT)pCtxRec->ctx_RegEdi) {
  463.                        fprintf(hTrap," ES:DI points outside Extra Segment\n");
  464.                     } /* endif */
  465.                  } else {
  466.                     fprintf(hTrap," ES (Extra Segment) Is Invalid\n");
  467.                  } /* endif */
  468.              } /* endif */
  469.              rc=DosGetInfoBlocks(&ptib,&ppib);
  470.              if (rc==NO_ERROR) {
  471.                 static CHAR Format[10];
  472.                 fprintf(hTrap,"\nThread slot %lu , Id %lu , priority %p\n",
  473.                         ptib->tib_ordinal,
  474.                         ptib->tib_ptib2->tib2_ultid ,
  475.                         ptib->tib_ptib2->tib2_ulpri );
  476.                 Ptr16=ptib->tib_pstack;
  477.                 sprintf(Format,"%8.8lX",Ptr16);
  478.                 fprintf(hTrap,"Stack Bottom : %8.8lX (%4.4s:%4.4s) ;", ptib->tib_pstack ,Format,Format+4);
  479.                 Ptr16=ptib->tib_pstacklimit;
  480.                 sprintf(Format,"%8.8lX",Ptr16);
  481.                 fprintf(hTrap,"Stack Top    : %8.8lX (%4.4s:%4.4s) \n",ptib->tib_pstacklimit,Format,Format+4);
  482.                 fprintf(hTrap,"Process Id : %lu ", ppib->pib_ulpid);
  483.                 rc=DosQueryModuleName(ppib->pib_hmte,CCHMAXPATH, Name);
  484.                 if (rc==NO_ERROR) {
  485.                    fprintf(hTrap,".EXE name : %s\n",Name);
  486.                 } else {
  487.                    fprintf(hTrap,".EXE name : ??????\n");
  488.                 } /* endif */
  489.                /* Better New WalkStack From John Currier */
  490.                WalkStack((PUSHORT)ptib->tib_pstack,
  491.                          (PUSHORT)ptib->tib_pstacklimit,
  492.                          (PUSHORT)pCtxRec->ctx_RegEbp,
  493.                          (PUSHORT)pERepRec->ExceptionAddress);
  494.                 ListModules();
  495.                 Count=0;
  496.                 Translate[0]=0x00;
  497.  
  498.                 fprintf(hTrap,"\n/*----- Stack Bottom ---*/\n");
  499.                 /* round to start of page to check first stack valid page  */
  500.                /* Thanks to John Currier for pointing me the guard page problem */
  501.                 TestStackBottom =(PUCHAR)(((ULONG)ptib->tib_pstack)&0xFFFFE000);
  502.                 Size=0x1000;
  503.                 do {
  504.                    ValidStackBottom =(PUSHORT)TestStackBottom;
  505.                    rc=DosQueryMem(TestStackBottom,&Size,&Attr);
  506.                    TestStackBottom +=0x1000; /* One more page for next test */
  507.                 } while (
  508.                    ( (rc!=0) ||
  509.                      ((Attr&PAG_COMMIT)==0x0U) ||
  510.                      ((Attr&PAG_READ)==0x0U)
  511.                    ) &&
  512.                    (TestStackBottom <(PUCHAR)ptib->tib_pstacklimit)
  513.                 );
  514.                 if ( (rc==0)&&
  515.                      (Attr&PAG_COMMIT) &&
  516.                      (Attr&PAG_READ) &&
  517.                      (ValidStackBottom <(PUSHORT)ptib->tib_pstacklimit)
  518.                    )
  519.                 {
  520.                    fprintf(hTrap,"\n/*----- Accessible Stack Bottom at %p ---*/\n",ValidStackBottom);
  521.                    for (StackPtr=ValidStackBottom;
  522.                         StackPtr<(PUSHORT)ptib->tib_pstacklimit;
  523.                         StackPtr++) {
  524.                         if (Count==0) {
  525.                            fprintf(hTrap,"  %s\n %8.8X :",Translate,StackPtr);
  526.                            Translate[0]=0x00;
  527.                         } /* endif */
  528.                        /* Change Formatting way (John Currier)*/
  529.                        fprintf(hTrap,"%4.4hX ",*StackPtr >> 8 | *StackPtr << 8);
  530.                         cStackPtr=(PUCHAR)StackPtr;
  531.                         if ((isprint(*cStackPtr)) &&
  532.                             (*cStackPtr>=0x20)  ) {
  533.                            Translate[2*Count]=*cStackPtr;
  534.                         } else {
  535.                            Translate[2*Count]='.';
  536.                         } /* endif */
  537.                         cStackPtr++;
  538.                         if ((isprint(*cStackPtr) )&&
  539.                             ( *cStackPtr >=0x20 )  ) {
  540.                            Translate[2*Count+1]=*cStackPtr;
  541.                         } else {
  542.                            Translate[2*Count+1]='.';
  543.                         } /* endif */
  544.                         Count++;
  545.                         Translate[2*Count]=0x00;
  546.                         if (Count==8) {
  547.                             Count=0;
  548.                         } /* endif */
  549.                    } /* endfor */
  550.                 } /* endif */
  551.                 fprintf(hTrap,"%s\n/*----- Stack Top -----*/\n",Translate);
  552.  
  553.              } /* endif */
  554.         } /* endif */
  555.         if (hTrap!=stdout) {
  556.            fclose(hTrap);
  557.         }
  558.         DosExitMustComplete(&Nest);
  559.         rc=DosUnsetExceptionHandler(pERegRec);
  560.      } /* endif */
  561.   } else {
  562.      printf("Other non fatal exception %8.8lx ",pERepRec->ExceptionNum);
  563.      printf("At address                %8.8lx\n",pERepRec->ExceptionAddress);
  564.   } /* endif */
  565.   return (XCPT_CONTINUE_SEARCH);
  566.  
  567. }
  568. APIRET16 APIENTRY16 SETEXCEPT(PEXCEPTIONREGISTRATIONRECORD _Seg16 pxcpthand)
  569.  {
  570.    APIRET rc;
  571.  
  572.    rc=DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR );
  573.    printf("Set error rc %ld\n",rc);
  574.    pxcpthand->prev_structure=0;
  575.    pxcpthand->ExceptionHandler=&myHandler;
  576.    rc=DosSetExceptionHandler(pxcpthand);
  577.    printf("Set except rc %ld\n",rc);
  578. }
  579. APIRET16 APIENTRY16 UNSETEXCEPT(PEXCEPTIONREGISTRATIONRECORD _Seg16 pxcpthand)
  580.  {
  581.    APIRET rc;
  582.    rc=DosUnsetExceptionHandler(pxcpthand);
  583.    printf("Unset except rc %ld\n",rc);
  584. }
  585. VOID ListModules() {
  586.   APIRET   rc;
  587.   APIRET16 rc16;
  588. #ifdef USE_DOSDEBUG
  589.   /**----------------------------------***/
  590.   rc16=DOS16ALLOCSEG( 0xFFFF , &Selector , 0);
  591.   if (rc16==0) {
  592.      pBuf=MAKEP(Selector,0);
  593.      rc16=DOSQPROCSTATUS(pBuf, 0xFFFF );
  594.      if (rc16==0) {
  595.         rc = DosExecPgm(LoadError,          /* Object name buffer */
  596.                         sizeof(LoadError),  /* Length of object name buffer */
  597.                         EXEC_TRACE,         /* Asynchronous/Trace flags */
  598.                         "Debug",            /* Argument string */
  599.                         NULL,               /* Environment string */
  600.                         &ReturnCodes,       /* Termination codes */
  601.                         ProcessName);           /* Program file name */
  602.         if (rc != NO_ERROR) {
  603.             fprintf(hTrap,"rc = %d Process ID %d  Return Code %d \n",
  604.                   rc,
  605.                   ReturnCodes.codeTerminate,
  606.                   ReturnCodes.codeResult);
  607.             return;
  608.         }
  609.        fprintf(hTrap,"Connecting  to PID %d\n",ReturnCodes.codeTerminate);
  610.        DbgBuf.Cmd = DBG_C_Connect; /* Indicate that a Connect is requested */
  611.        DbgBuf.Pid = ReturnCodes.codeTerminate;
  612.        DbgBuf.Tid = 0;
  613.        DbgBuf.Value = DBG_L_386;
  614.        rc = DosDebug(&DbgBuf);
  615.        if (rc != 0) {
  616.            fprintf(hTrap,"DosDebug error: return code = %ld Note %8.8lX\n", rc,DbgBuf.Cmd);
  617.            fprintf(hTrap,"Value          = %8.8lX %ld\n",DbgBuf.Value,DbgBuf.Value);
  618.        }
  619.        fprintf(hTrap,"Connected to PID %d\n",ReturnCodes.codeTerminate);
  620.        /*****************************/
  621.        pRec=(qsPtrRec_t *) pBuf;
  622.        pLib=pRec->pLibRec;
  623.        while (pLib) {
  624.            GetObjects(&DbgBuf,pLib->hmte,pLib->pName);
  625.            pLib =pLib->pNextRec;
  626.        } /* endwhile */
  627.      } else {
  628.        fprintf(hTrap,"DosQProcStatus Failed %hd\n",rc16);
  629.      } /* endif */
  630.   } else {
  631.      fprintf(hTrap,"DosAllocSeg Failed %hd\n",rc16);
  632.   } /* endif */
  633. #else
  634.   PVOID BaseAddress;
  635.   ULONG RegionSize;
  636.   ULONG AllocationFlags;
  637.   HMODULE LastModule;
  638.   static CHAR Name[CCHMAXPATH];
  639.   ULONG Size;
  640.   LastModule=0;
  641.   BaseAddress=(PVOID)0x10000;
  642.   RegionSize =0x3FFFFFFF;
  643.   rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
  644.   while (rc==NO_ERROR) {
  645.      if ((AllocationFlags&PAG_EXECUTE)&&
  646.          (AllocationFlags&PAG_BASE)) {
  647.         rc=DOSQUERYMODFROMEIP( &hMod, &ObjNum, CCHMAXPATH,
  648.                               Name, &Offset, BaseAddress);
  649.         if (rc==0) {
  650.             if (hMod!=LastModule) {
  651.                rc=DosQueryModuleName(hMod,CCHMAXPATH, Name);
  652.                fprintf(hTrap,"\nModule %s Handle %d\n",Name,hMod);
  653.                fprintf(hTrap,"Object Number    Address    Length     Flags      Type\n");
  654.                LastModule=hMod;
  655.             } /* endif */
  656.             fprintf(hTrap,"      % 6.6d    %8.8lX   %8.8lX   %8.8lX ",ObjNum,
  657.                       BaseAddress, RegionSize, AllocationFlags);
  658.             rc16 =DOS16SIZESEG( SELECTOROF(BaseAddress), &Size);
  659.             if (rc16==0) {
  660.                fprintf(hTrap," - 16:16  Selector %4.4hX\n",SELECTOROF((PVOID)BaseAddress));
  661.             } else {
  662.                fprintf(hTrap," - 32 Bits\n");
  663.             } /* endif */
  664.         }
  665.      }
  666.      if (AllocationFlags&PAG_FREE) RegionSize =0x10000;
  667.      RegionSize +=0x0FFF;
  668.      RegionSize &=0xFFFFF000;
  669.      BaseAddress=(PVOID)(((PCHAR)BaseAddress)+RegionSize);
  670.      RegionSize=((PCHAR)0x3FFFFFFF)-(PCHAR)BaseAddress;
  671.      rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
  672.      while ((rc==ERROR_INVALID_ADDRESS)||
  673.             (rc==ERROR_NO_OBJECT)) {
  674.          BaseAddress=(PVOID)(((PCHAR)BaseAddress)+0x10000);
  675.          if (BaseAddress>(PVOID)0x3FFFFFFF) {
  676.             break;
  677.          } /* endif */
  678.          RegionSize=((PCHAR)0x3FFFFFFF)-(PCHAR)BaseAddress;
  679.          rc=DosQueryMem(BaseAddress,&RegionSize,&AllocationFlags);
  680.      } /* endwhile */
  681.      if (BaseAddress>(PVOID)0x3FFFFFFF) {
  682.         break;
  683.      } /* endif */
  684.   } /* endwhile */
  685. #endif
  686. }
  687. #ifdef USE_DOSDEBUG
  688. VOID  GetObjects(struct debug_buffer * pDbgBuf,HMODULE hMte,PSZ pName) {
  689.     APIRET rc;
  690.     int  object;
  691.     pDbgBuf->MTE  = (ULONG) hMte;
  692.     rc=0;
  693.     fprintf(hTrap,"DLL %s Handle %d\n",pName,hMte);
  694.     fprintf(hTrap,"Object Number    Address    Length     Flags      Type\n");
  695.     for (object=1;object<256;object++ ) {
  696.         pDbgBuf->Cmd   = DBG_C_NumToAddr;
  697.         pDbgBuf->Pid   = ReturnCodes.codeTerminate;
  698.         pDbgBuf->Value = object; /* Get nth object address in module with given MTE */
  699.         pDbgBuf->Buffer= 0;
  700.         pDbgBuf->Len   = 0;
  701.         rc = DosDebug(pDbgBuf);
  702.         if ((rc == NO_ERROR)&&
  703.             (pDbgBuf->Cmd==NO_ERROR)) {
  704.             ULONG Size;
  705.             ULONG Flags;
  706.             APIRET16 rc16;
  707.             pDbgBuf->Len   = 0;
  708.             pDbgBuf->Value = 0;
  709.             if (pDbgBuf->Addr!=0) {
  710.                 pDbgBuf->Cmd   = DBG_C_AddrToObject;
  711.                 pDbgBuf->Pid   = ReturnCodes.codeTerminate;
  712.                 rc = DosDebug(pDbgBuf);
  713.                 if ((rc != NO_ERROR) ||
  714.                     (pDbgBuf->Cmd|=NO_ERROR)) {
  715.                    pDbgBuf->Len   = 0;
  716.                    pDbgBuf->Value = 0;
  717.                 }
  718.             }
  719.             fprintf(hTrap,"      % 6.6d    %8.8lX   %8.8lX   %8.8lX ",object,
  720.                       pDbgBuf->Addr, pDbgBuf->Len, pDbgBuf->Value);
  721.             if (pDbgBuf->Addr!=0) {
  722.                 rc16 =DOS16SIZESEG( SELECTOROF(pDbgBuf->Addr), &Size);
  723.                 if (rc16==0) {
  724.                    fprintf(hTrap," - 16:16  Selector %4.4hX\n",SELECTOROF((PVOID)pDbgBuf->Addr));
  725.                 } else {
  726.                    fprintf(hTrap," - 32 Bits\n");
  727.                 } /* endif */
  728.             } else {
  729.                fprintf(hTrap," - ?\n");
  730.             } /* endif */
  731.         } else {
  732. //         printf("DosDebug return code = %ld Notification %8.8lX\n", rc,pDbgBuf->Cmd);
  733. //         printf("Value                = %8.8lX %ld\n",pDbgBuf->Value,pDbgBuf->Value);
  734.            break;
  735.         }
  736.     } /* endfor */
  737.     fprintf(hTrap,"\n");
  738. }
  739. #endif
  740. void    CheckMem(PVOID Ptr,PSZ MemoryName) {
  741.    APIRET rc;
  742.    ULONG Size,Flags,Attr;
  743.    Size=1;
  744.    rc=DosQueryMem(Ptr,&Size,&Attr);
  745.    if (rc!=NO_ERROR) {
  746.       fprintf(hTrap," %s does not point to valid memory\n",MemoryName);
  747.    } else {
  748.       if (Attr&PAG_FREE) {
  749.          fprintf(hTrap," %s points to unallocated memory\n",MemoryName);
  750.       } else {
  751.          if ((Attr&PAG_COMMIT)==0x0U) {
  752.             fprintf(hTrap," %s points to uncommited  memory\n",MemoryName);
  753.          } /* endif */
  754.          if ((Attr&PAG_WRITE)==0x0U) {
  755.             fprintf(hTrap," %s points to unwritable  memory\n",MemoryName);
  756.          } /* endif */
  757.          if ((Attr&PAG_READ)==0x0U) {
  758.             fprintf(hTrap," %s points to unreadable  memory\n",MemoryName);
  759.          } /* endif */
  760.       } /* endif */
  761.    } /* endif */
  762. }
  763. PUSHORT Convert(USHORT * _Seg16 p16) {
  764.    return p16;
  765. }
  766. /* Better New WalkStack From John Currier */
  767. static void WalkStack(PUSHORT StackBottom, PUSHORT StackTop, PUSHORT Ebp,
  768.                       PUSHORT ExceptionAddress)
  769. {
  770.    PUSHORT  RetAddr;
  771.    PUSHORT  LastEbp;
  772.    APIRET   rc;
  773.    ULONG    Size,Attr;
  774.    USHORT   Cs,Ip,Bp,Sp;
  775.    static char Name[CCHMAXPATH];
  776.    HMODULE  hMod;
  777.    ULONG    ObjNum;
  778.    ULONG    Offset;
  779.    BOOL     fExceptionAddress = TRUE;  // Use Exception Addr 1st time thru
  780.  
  781.    // Note: we can't handle stacks bigger than 64K for now...
  782.    Sp = (USHORT)(((ULONG)StackBottom) >> 16);
  783.    Bp = (USHORT)(ULONG)Ebp;
  784.  
  785.    if (!f32bit)
  786.       Ebp = (PUSHORT)MAKEULONG(Bp, Sp);
  787.  
  788.    fprintf(hTrap,"\nCall Stack:\n");
  789.    fprintf(hTrap,"                                        Source    Line      Nearest\n");
  790.    fprintf(hTrap,"   EBP      Address    Module  Obj#      File     Numbr  Public Symbol\n");
  791.    fprintf(hTrap," --------  ---------  -------- ----  ------------ -----  -------------\n");
  792.  
  793.    do
  794.    {
  795.       Size = 4096;
  796.  
  797.       if (fExceptionAddress)
  798.          RetAddr = ExceptionAddress;
  799.       else
  800.       {
  801.          rc = DosQueryMem((PVOID)(Ebp+2), &Size, &Attr);
  802.          if (rc != NO_ERROR || !(Attr & PAG_COMMIT) || Size < sizeof(RetAddr))
  803.          {
  804.             fprintf(hTrap,"Invalid EBP: %8.8p\n",Ebp);
  805.             break;
  806.          }
  807.  
  808.          RetAddr = (PUSHORT)(*((PULONG)(Ebp+2)));
  809.       }
  810.  
  811.       if (RetAddr == (PUSHORT)0x00000053)
  812.       {
  813.          // For some reason there's a "return address" of 0x53 following
  814.          // EBP on the stack and we have to adjust EBP by 44 bytes to get
  815.          // at the real return address.  This has something to do with
  816.          // thunking from 32bits to 16bits...
  817.          // Serious kludge, and it's probably dependent on versions of C(++)
  818.          // runtime or OS, but it works for now!
  819.          const cbKludgeFactor = 44;
  820.  
  821.          if (Size < sizeof(RetAddr) + cbKludgeFactor)
  822.          {
  823.             fprintf(hTrap,"Invalid EBP: %8.8p\n",Ebp);
  824.             break;
  825.          }
  826.  
  827.          Ebp += cbKludgeFactor / sizeof(*Ebp);
  828.          RetAddr = (PUSHORT)(*((PULONG)(Ebp+2)));
  829.          Size -= cbKludgeFactor;
  830.       }
  831.  
  832.       // Get the (possibly) 16bit CS and IP
  833.       if (fExceptionAddress)
  834.       {
  835.          Cs = (USHORT)(((ULONG)ExceptionAddress) >> 16);
  836.          Ip = (USHORT)(ULONG)ExceptionAddress;
  837.       }
  838.       else
  839.       {
  840.          Cs = *(Ebp+2);
  841.          Ip = *(Ebp+1);
  842.       }
  843.  
  844.       // if the return address points to the stack then it's really just
  845.       // a pointer to the return address (UGH!).
  846.       if ((USHORT)(((ULONG)RetAddr) >> 16) == Sp)
  847.          RetAddr = (PUSHORT)(*((PULONG)RetAddr));
  848.  
  849.       if (Ip == 0 && *Ebp == 0)
  850.       {
  851.          if (Size < sizeof(RetAddr) + sizeof(*Ebp))
  852.          {
  853.             fprintf(hTrap,"Invalid EBP: %8.8p\n",Ebp);
  854.             break;
  855.          }
  856.  
  857.          // End of the stack so these are both shifted by 2 bytes:
  858.          Cs = *(Ebp+3);
  859.          Ip = *(Ebp+2);
  860.       }
  861.  
  862.       // 16bit programs have on the stack:
  863.       //   BP:IP:CS
  864.       //   where CS may be thunked
  865.       //
  866.       //         in dump                 swapped
  867.       //    BP        IP   CS          BP   CS   IP
  868.       //   4677      53B5 F7D0        7746 D0F7 B553
  869.       //
  870.       // 32bit programs have:
  871.       //   EBP:EIP
  872.       // and you'd have something like this (with SP added) (not
  873.       // accurate values)
  874.       //
  875.       //         in dump               swapped
  876.       //      EBP       EIP         EBP       EIP
  877.       //   4677 2900 53B5 F7D0   0029 7746 D0F7 B553
  878.       //
  879.       // So the basic difference is that 32bit programs have a 32bit
  880.       // EBP and we can attempt to determine whether we have a 32bit
  881.       // EBP by checking to see if its 'selector' is the same as SP.
  882.       // Note that this technique limits us to checking stacks < 64K.
  883.       //
  884.       // Soooo, if IP (which maps into the same USHORT as the swapped
  885.       // stack page in EBP) doesn't point to the stack (i.e. it could
  886.       // be a 16bit IP) then see if CS is valid (as is or thunked).
  887.       //
  888.       // Note that there's the possibility of a 16bit return address
  889.       // that has an offset that's the same as SP so we'll think it's
  890.       // a 32bit return address and won't be able to successfully resolve
  891.       // its details.
  892.       if (Ip != Sp)
  893.       {
  894.          if (DOS16SIZESEG(Cs, &Size) == NO_ERROR)
  895.          {
  896.             RetAddr = (USHORT * _Seg16)MAKEULONG(Ip, Cs);
  897.             f32bit = FALSE;
  898.          }
  899.          else if (DOS16SIZESEG((Cs << 3) + 7, &Size) == NO_ERROR)
  900.          {
  901.             Cs = (Cs << 3) + 7;
  902.             RetAddr = (USHORT * _Seg16)MAKEULONG(Ip, Cs);
  903.             f32bit = FALSE;
  904.          }
  905.          else
  906.             f32bit = TRUE;
  907.       }
  908.       else
  909.          f32bit = TRUE;
  910.  
  911.  
  912.       if (fExceptionAddress)
  913.          fprintf(hTrap," Trap  ->");
  914.       else
  915.          fprintf(hTrap," %8.8p", Ebp);
  916.  
  917.       if (f32bit)
  918.          fprintf(hTrap,"  :%8.8p", RetAddr);
  919.       else
  920.          fprintf(hTrap,"  %04.04X:%04.04X", Cs, Ip);
  921.  
  922.       if (Version[0] >= 20 && Version[1] >= 10)
  923.       {
  924.          // Make a 'tick' sound to let the user know we're still alive
  925.          DosBeep(2000, 1);
  926.  
  927.          rc = DosQueryMem((PVOID)RetAddr, &Size, &Attr);
  928.          if (rc != NO_ERROR || !(Attr & PAG_COMMIT))
  929.          {
  930.             fprintf(hTrap,"Invalid RetAddr: %8.8p\n",RetAddr);
  931.          }
  932.          else
  933.          {
  934.             rc = DOSQUERYMODFROMEIP(&hMod, &ObjNum, sizeof(Name),
  935.                                     Name, &Offset, (PVOID)RetAddr);
  936.             if (rc == NO_ERROR && ObjNum != -1)
  937.             {
  938.                static char szJunk[_MAX_FNAME];
  939.                static char szName[_MAX_FNAME];
  940.                DosQueryModuleName(hMod, sizeof(Name), Name);
  941.                _splitpath(Name, szJunk, szJunk, szName, szJunk);
  942.                fprintf(hTrap,"  %-8s %04X", szName, ObjNum+1);
  943.  
  944.                if (strlen(Name) > 3)
  945.                {
  946.                   rc = GetLineNum(Name, ObjNum, Offset);
  947.                   /* if no codeview try with symbol files */
  948.                   if (rc != NO_ERROR)
  949.                   {
  950.                      strcpy(Name+strlen(Name)-3,"SYM");
  951.                      GetSymbol(Name,ObjNum,Offset);
  952.                   }
  953.                }
  954.             }
  955.             else
  956.             {
  957.                fprintf(hTrap,"  *Unknown*");
  958.             }
  959.          }
  960.       }
  961.  
  962.       fprintf(hTrap,"\n");
  963.  
  964.       Bp = *Ebp;
  965.       if (Bp == 0 && (*Ebp+1) == 0)
  966.       {
  967.          fprintf(hTrap,"End of Call Stack\n");
  968.          break;
  969.       }
  970.  
  971.       if (!fExceptionAddress)
  972.       {
  973.          LastEbp = Ebp;
  974.          Ebp = (PUSHORT)MAKEULONG(Bp, Sp);
  975.  
  976.          if (Ebp < LastEbp)
  977.          {
  978.             fprintf(hTrap,"Lost Stack chain - new EBP below previous\n");
  979.             break;
  980.          }
  981.       }
  982.       else
  983.          fExceptionAddress = FALSE;
  984.  
  985.       Size = 4096;
  986.       rc = DosQueryMem((PVOID)Ebp, &Size, &Attr);
  987.       if (rc != NO_ERROR || Size < sizeof(Ebp))
  988.       {
  989.          fprintf(hTrap,"Lost Stack chain - invalid EBP: %8.8p\n", Ebp);
  990.          break;
  991.       }
  992.    } while (TRUE);
  993.  
  994.    fprintf(hTrap,"\n");
  995. }
  996.  
  997. void GetSymbol(CHAR * SymFileName, ULONG Object,ULONG TrapOffset)
  998. {
  999.    static FILE * SymFile;
  1000.    static MAPDEF MapDef;
  1001.    static SEGDEF   SegDef;
  1002.    static SEGDEF *pSegDef;
  1003.    static SYMDEF32 SymDef32;
  1004.    static SYMDEF16 SymDef16;
  1005.    static char    Buffer[256];
  1006.    static int     SegNum,SymNum,LastVal;
  1007.    static unsigned short int SegOffset,SymOffset,SymPtrOffset;
  1008.    SymFile=fopen(SymFileName,"rb");
  1009.    if (SymFile==0) {
  1010.        /*fprintf(hTrap,"Could not open symbol file %s\n",SymFileName);*/
  1011.        return;
  1012.    } /* endif */
  1013.    fread(&MapDef,sizeof(MAPDEF),1,SymFile);
  1014.    SegOffset= SEGDEFOFFSET(MapDef);
  1015.    for (SegNum=0;SegNum<MapDef.cSegs;SegNum++) {
  1016.         /* printf("Scanning segment #%d Offset %4.4hX\n",SegNum+1,SegOffset); */
  1017.         if (fseek(SymFile,SegOffset,SEEK_SET)) {
  1018.            fprintf(hTrap,"Seek error ");
  1019.            return;
  1020.         }
  1021.         fread(&SegDef,sizeof(SEGDEF),1,SymFile);
  1022.         if (SegNum==Object) {
  1023.            Buffer[0]=0x00;
  1024.            LastVal=0;
  1025.            for (SymNum=0;SymNum<SegDef.cSymbols;SymNum++) {
  1026.               SymPtrOffset=SYMDEFOFFSET(SegOffset,SegDef,SymNum);
  1027.               fseek(SymFile,SymPtrOffset,SEEK_SET);
  1028.               fread(&SymOffset,sizeof(unsigned short int),1,SymFile);
  1029.               fseek(SymFile,SymOffset+SegOffset,SEEK_SET);
  1030.               if (SegDef.bFlags&0x01) {
  1031.                  fread(&SymDef32,sizeof(SYMDEF32),1,SymFile);
  1032.                  if (SymDef32.wSymVal>TrapOffset) {
  1033.                     fprintf(hTrap,"between %s + %X ",Buffer,TrapOffset-LastVal);
  1034.                  }
  1035.                  LastVal=SymDef32.wSymVal;
  1036.                  Buffer[0]= SymDef32.achSymName[0];
  1037.                  fread(&Buffer[1],1,SymDef32.cbSymName,SymFile);
  1038.                  Buffer[SymDef32.cbSymName]=0x00;
  1039.                  if (SymDef32.wSymVal>TrapOffset) {
  1040.                     fprintf(hTrap,"and %s - %X\n",Buffer,LastVal-TrapOffset);
  1041.                     break;
  1042.                  }
  1043.                  /*printf("32 Bit Symbol <%s> Address %p\n",Buffer,SymDef32.wSymVal);*/
  1044.               } else {
  1045.                  fread(&SymDef16,sizeof(SYMDEF16),1,SymFile);
  1046.                  if (SymDef16.wSymVal>TrapOffset) {
  1047.                     fprintf(hTrap,"between %s + %X ",Buffer,TrapOffset-LastVal);
  1048.                  }
  1049.                  LastVal=SymDef16.wSymVal;
  1050.                  Buffer[0]=SymDef16.achSymName[0];
  1051.                  fread(&Buffer[1],1,SymDef16.cbSymName,SymFile);
  1052.                  Buffer[SymDef16.cbSymName]=0x00;
  1053.                  if (SymDef16.wSymVal>TrapOffset) {
  1054.                     fprintf(hTrap,"and %s - %X\n",Buffer,LastVal-TrapOffset);
  1055.                     break;
  1056.                  }
  1057.                  /*printf("16 Bit Symbol <%s> Address %p\n",Buffer,SymDef16.wSymVal);*/
  1058.               } /* endif */
  1059.            }
  1060.            break;
  1061.         } /* endif */
  1062.         SegOffset=NEXTSEGDEFOFFSET(SegDef);
  1063.    } /* endwhile */
  1064.    fclose(SymFile);
  1065. }
  1066. VOID WakeThreads(VOID);
  1067. void APIENTRY ForceExit() {
  1068.     EXCEPTIONREPORTRECORD except;
  1069.     PCHAR  Trap;
  1070.     InForceExit =TRUE;
  1071.     fclose(stderr); /* I don't want error messages since all is intentional */
  1072.     DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR );
  1073.     DosEnterCritSec();
  1074.     WakeThreads();
  1075.     printf("Exiting by exception\n");
  1076.     Trap=NULL;
  1077.     DosSetPriority(PRTYS_THREAD,PRTYC_FOREGROUNDSERVER,PRTYD_MAXIMUM,0);
  1078.     DosExitCritSec();
  1079.     *Trap=0x00;
  1080. }
  1081. VOID WakeThreads() {
  1082.   APIRET   rc;
  1083.   APIRET16 rc16;
  1084.   qsPrec_t   * pProc;
  1085.   qsTrec_t   * pThread;
  1086.   ULONG      ListedThreads=0;
  1087.   PTIB   ptib;
  1088.   PPIB   ppib;
  1089.   DosGetInfoBlocks(&ptib,&ppib);
  1090.   /**----------------------------------***/
  1091.   rc16=DOS16ALLOCSEG( 0xFFFF , &Selector , 0);
  1092.   if (rc16==0) {
  1093.      pBuf=MAKEP(Selector,0);
  1094.      rc16=DOSQPROCSTATUS(pBuf, 0xFFFF );
  1095.      if (rc16==0) {
  1096.         /*****************************/
  1097.         pRec=(qsPtrRec_t *) pBuf;
  1098.         pProc =(qsPrec_t *)(pRec->pProcRec);
  1099.         ListedThreads=0;
  1100.         while (ListedThreads<pRec->pGlobalRec->cThrds) {
  1101.            int Tid;
  1102.            if (pProc->pThrdRec==NULL) break;
  1103.            ListedThreads+= pProc->cTCB;
  1104.            if (ppib->pib_ulpid==pProc->pid) {
  1105.               for (Tid=0;Tid<pProc->cTCB;Tid++ ) {
  1106.                  pThread =pProc->pThrdRec+Tid;
  1107.                  if (pThread->state==0x09) {
  1108.                     printf("Resuming Thread %d\n",(TID)pThread->tid);
  1109.                     DosResumeThread((TID)pThread->tid);
  1110.                  }
  1111.               } /* endfor */
  1112.               break;
  1113.            } /* endif  */
  1114.            pProc =(qsPrec_t *)( ((PUCHAR)pProc)
  1115.                                  +sizeof(qsPrec_t)
  1116.                                  +sizeof(USHORT)*(pProc->c16Sem+
  1117.                                                   pProc->cLib+
  1118.                                                   pProc->cShrMem)
  1119.                                  +(pProc->cTCB)*sizeof(qsTrec_t));
  1120.  
  1121.         } /* endwhile */
  1122.      } else {
  1123.         printf("DosQProcStatus Failed %hd\n",rc16);
  1124.      } /* endif */
  1125.   } else {
  1126.      printf("DosAllocSeg Failed %hd\n",rc16);
  1127.   } /* endif */
  1128. }
  1129.  
  1130.  
  1131. #include <exe.h>
  1132. #include <newexe.h>
  1133. #define  FOR_EXEHDR  1  /* avoid define conflicts between newexe.h and exe386.h */
  1134. #ifndef DWORD
  1135. #define DWORD long int
  1136. #endif
  1137. #ifndef WORD
  1138. #define WORD  short int
  1139. #endif
  1140. #include <exe386.h>
  1141. #include <fcntl.h>
  1142. #include <sys\stat.h>
  1143. #include <share.h>
  1144. #include <io.h>
  1145. #ifdef __cplusplus
  1146. #include <demangle.h>   // for demangling C++ names
  1147. #endif
  1148. /* ------------------------------------------------------------------ */
  1149. /* Last 8 bytes of 16:16 file when CODEVIEW debugging info is present */
  1150. #pragma pack(1)
  1151.  struct  _eodbug
  1152.         {
  1153.         unsigned short dbug;          /* 'NB' signature */
  1154.         unsigned short ver;           /* version        */
  1155.         unsigned long dfaBase;        /* size of codeview info */
  1156.         } eodbug;
  1157.  
  1158. #define         DBUGSIG         0x424E
  1159. #define         SSTMODULES      0x0101
  1160. #define         SSTPUBLICS      0x0102
  1161. #define         SSTTYPES        0x0103
  1162. #define         SSTSYMBOLS      0x0104
  1163. #define         SSTSRCLINES     0x0105
  1164. #define         SSTLIBRARIES    0x0106
  1165. #define         SSTSRCLINES2    0x0109
  1166. #define         SSTSRCLINES32   0x010B
  1167.  
  1168.  struct  _base
  1169.         {
  1170.         unsigned short dbug;          /* 'NB' signature */
  1171.         unsigned short ver;           /* version        */
  1172.         unsigned long lfoDir;   /* file offset to dir entries */
  1173.         } base;
  1174.  
  1175.  struct  ssDir
  1176.         {
  1177.         unsigned short sst;           /* SubSection Type */
  1178.         unsigned short modindex;      /* Module index number */
  1179.         unsigned long lfoStart;       /* Start of section */
  1180.         unsigned short cb;            /* Size of section */
  1181.         } ;
  1182.  
  1183.  struct  ssDir32
  1184.         {
  1185.         unsigned short sst;           /* SubSection Type */
  1186.         unsigned short modindex;      /* Module index number */
  1187.         unsigned long lfoStart;       /* Start of section */
  1188.         unsigned long  cb;            /* Size of section */
  1189.         } ;
  1190.  
  1191.  struct  ssModule
  1192.    {
  1193.    unsigned short          csBase;             /* code segment base */
  1194.    unsigned short          csOff;              /* code segment offset */
  1195.    unsigned short          csLen;              /* code segment length */
  1196.    unsigned short          ovrNum;             /* overlay number */
  1197.    unsigned short          indxSS;             /* Index into sstLib or 0 */
  1198.    unsigned short          reserved;
  1199.    char              csize;              /* size of prefix string */
  1200.    } ssmod;
  1201.  
  1202.  struct  ssModule32
  1203.    {
  1204.    unsigned short          csBase;             /* code segment base */
  1205.    unsigned long           csOff;              /* code segment offset */
  1206.    unsigned long           csLen;              /* code segment length */
  1207.    unsigned long           ovrNum;             /* overlay number */
  1208.    unsigned short          indxSS;             /* Index into sstLib or 0 */
  1209.    unsigned long           reserved;
  1210.    char                    csize;              /* size of prefix string */
  1211.    } ssmod32;
  1212.  
  1213.  struct  ssPublic
  1214.         {
  1215.         unsigned short  offset;
  1216.         unsigned short  segment;
  1217.         unsigned short  type;
  1218.         char      csize;
  1219.         } sspub;
  1220.  
  1221.  struct  ssPublic32
  1222.         {
  1223.         unsigned long   offset;
  1224.         unsigned short  segment;
  1225.         unsigned short  type;
  1226.         char      csize;
  1227.         } sspub32;
  1228.  
  1229. typedef  struct _SSLINEENTRY32 {
  1230.    unsigned short LineNum;
  1231.    unsigned short FileNum;
  1232.    unsigned long  Offset;
  1233. } SSLINEENTRY32;
  1234. typedef  struct _FIRSTLINEENTRY32 {
  1235.    unsigned short LineNum;
  1236.    unsigned short FileNum;
  1237.    unsigned short numlines;
  1238.    unsigned short segnum;
  1239. } FIRSTLINEENTRY32;
  1240.  
  1241. typedef  struct _SSFILENUM32 {
  1242.     unsigned long first_displayable;  /* Not used */
  1243.     unsigned long number_displayable; /* Not used */
  1244.     unsigned long file_count;         /* number of source files */
  1245. } SSFILENUM32;
  1246.  
  1247.  struct  DbugRec {                       /* debug info struct ure used in linked * list */
  1248.     struct  DbugRec  *pnext;             /* next node *//* 013 */
  1249.    char              *SourceFile;               /* source file name *013 */
  1250.    unsigned short          TypeOfProgram;       /* dll or exe *014* */
  1251.    unsigned short          LineNumber;          /* line number in source file */
  1252.    unsigned short          OffSet;              /* offset into loaded module */
  1253.    unsigned short          Selector;            /* code segment 014 */
  1254.    unsigned short          OpCode;              /* Opcode replaced with BreakPt */
  1255.    unsigned long     Count;                     /* count over Break Point */
  1256. };
  1257.  
  1258. typedef  struct  DbugRec DBUG, * DBUGPTR;     /* 013 */
  1259. char szNrPub[128];
  1260. char szNrLine[128];
  1261.  struct  new_seg *pseg;
  1262.  struct  o32_obj *pobj;        /* Flat .EXE object table entry */
  1263.  struct  ssDir *pDirTab;
  1264.  struct  ssDir32 *pDirTab32;
  1265. unsigned char *pEntTab;
  1266. unsigned long lfaBase;
  1267. #pragma pack()
  1268. /* ------------------------------------------------------------------ */
  1269.  
  1270. APIRET GetLineNum(char * FileName, ULONG Object, ULONG TrapOffset) {
  1271.    APIRET rc;
  1272.    int ModuleFile;
  1273.    static  struct  exe_hdr oldHdr;
  1274.    static  struct  new_exe newHdr;
  1275.    strcpy(szNrPub,"   None found.");
  1276.    strcpy(szNrLine,"   None found.");
  1277.    ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
  1278.    if (ModuleFile!=-1) {
  1279.       /* Read old Exe header */
  1280.       if (read( ModuleFile ,(void *)&oldHdr,64)==-1L) {
  1281.         fprintf(hTrap,"Could Not Read old exe header %d\n",errno);
  1282.         close(ModuleFile);
  1283.         return 2;
  1284.       }
  1285.       /* Seek to new Exe header */
  1286.       if (lseek(ModuleFile,(long)E_LFANEW(oldHdr),SEEK_SET)==-1L) {
  1287.         fprintf(hTrap,"Could Not seek to new exe header %d\n",errno);
  1288.         close(ModuleFile);
  1289.         return 3;
  1290.       }
  1291.       if (read( ModuleFile ,(void *)&newHdr,64)==-1L) {
  1292.         fprintf(hTrap,"Could Not read new exe header %d\n",errno);
  1293.         close(ModuleFile);
  1294.         return 4;
  1295.       }
  1296.       /* Check EXE signature */
  1297.       if (NE_MAGIC(newHdr)==E32MAGIC) {
  1298.          /* Flat 32 executable */
  1299.          rc=Read32PmDebug(ModuleFile,Object+1,TrapOffset,FileName);
  1300.          if (rc==0)
  1301.             fprintf(hTrap," %s %s", szNrLine, szNrPub);
  1302.          close(ModuleFile);
  1303.          /* rc !=0 try with DBG file */
  1304.          if (rc!=0) {
  1305.             strcpy(FileName+strlen(FileName)-3,"DBG"); /* Build DBG File name */
  1306.             ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
  1307.             if (ModuleFile!=-1) {
  1308.                rc=Read32PmDebug(ModuleFile,Object+1,TrapOffset,FileName);
  1309.                if (rc==0)
  1310.                   fprintf(hTrap," %s %s", szNrLine, szNrPub);
  1311.                close(ModuleFile);
  1312.             }
  1313.          } /* endif */
  1314.          return rc;
  1315.       } else {
  1316.          if (NE_MAGIC(newHdr)==NEMAGIC) {
  1317.             /* 16:16 executable */
  1318.             if ((pseg = ( struct  new_seg *) calloc(NE_CSEG(newHdr),sizeof( struct  new_seg)))==NULL) {
  1319.                fprintf(hTrap,"Out of memory!");
  1320.                close(ModuleFile);
  1321.                return -1;
  1322.             }
  1323.             if (lseek(ModuleFile,E_LFANEW(oldHdr)+NE_SEGTAB(newHdr),SEEK_SET)==-1L) {
  1324.                fprintf(hTrap,"Error %u seeking segment table in %s\n",errno,FileName);
  1325.                free(pseg);
  1326.                close(ModuleFile);
  1327.                return 9;
  1328.             }
  1329.  
  1330.             if (read(ModuleFile,(void *)pseg,NE_CSEG(newHdr)*sizeof( struct  new_seg))==-1) {
  1331.                fprintf(hTrap,"Error %u reading segment table from %s\n",errno,FileName);
  1332.                free(pseg);
  1333.                close(ModuleFile);
  1334.                return 10;
  1335.             }
  1336.             rc=Read16CodeView(ModuleFile,Object+1,TrapOffset,FileName);
  1337.             if (rc==0) {
  1338.                if ((NS_FLAGS(pseg[Object]) & NSTYPE)==NSCODE)
  1339.                   fprintf(hTrap," %s", szNrLine);
  1340.                fprintf(hTrap," %s", szNrPub);
  1341.             } /* endif */
  1342.             free(pseg);
  1343.             close(ModuleFile);
  1344.             /* rc !=0 try with DBG file */
  1345.             if (rc!=0) {
  1346.                strcpy(FileName+strlen(FileName)-3,"DBG"); /* Build DBG File name */
  1347.                ModuleFile =sopen(FileName,O_RDONLY|O_BINARY,SH_DENYNO);
  1348.                if (ModuleFile!=-1) {
  1349.                   rc=Read16CodeView(ModuleFile,Object+1,TrapOffset,FileName);
  1350.                   if (rc==0)
  1351.                      fprintf(hTrap," %s %s", szNrLine, szNrPub);
  1352.                   close(ModuleFile);
  1353.                }
  1354.             } /* endif */
  1355.             return rc;
  1356.  
  1357.          } else {
  1358.             /* Unknown executable */
  1359.             fprintf(hTrap,"Could Not find exe signature");
  1360.             close(ModuleFile);
  1361.             return 11;
  1362.          }
  1363.       }
  1364.       /* Read new Exe header */
  1365.    } else {
  1366.       fprintf(hTrap,"Could Not open Module File %d",errno);
  1367.       return 1;
  1368.    } /* endif */
  1369. }
  1370. char fname[128],ModName[80];
  1371. char ename[128];
  1372. int Read16CodeView(int fh,int TrapSeg,int TrapOff,CHAR * FileName) {
  1373.     static unsigned short int offset,NrPublic,NrLine,NrEntry,numdir,namelen,numlines,line;
  1374.     static int ModIndex;
  1375.     static int bytesread,i,j;
  1376.     ModIndex=0;
  1377.     /* See if any CODEVIEW info */
  1378.     if (lseek(fh,-8L,SEEK_END)==-1) {
  1379.         fprintf(hTrap,"Error %u seeking CodeView table in %s\n",errno,FileName);
  1380.         return(18);
  1381.     }
  1382.  
  1383.     if (read(fh,(void *)&eodbug,8)==-1) {
  1384.        fprintf(hTrap,"Error %u reading debug info from %s\n",errno,FileName);
  1385.        return(19);
  1386.     }
  1387.     if (eodbug.dbug!=DBUGSIG) {
  1388.        /* fprintf(hTrap,"\nNo CodeView information stored.\n"); */
  1389.        return(100);
  1390.     }
  1391.  
  1392.     if ((lfaBase=lseek(fh,-eodbug.dfaBase,SEEK_END))==-1L) {
  1393.        fprintf(hTrap,"Error %u seeking base codeview data in %s\n",errno,FileName);
  1394.        return(20);
  1395.     }
  1396.  
  1397.     if (read(fh,(void *)&base,8)==-1) {
  1398.        fprintf(hTrap,"Error %u reading base codeview data in %s\n",errno,FileName);
  1399.        return(21);
  1400.     }
  1401.  
  1402.     if (lseek(fh,base.lfoDir-8,SEEK_CUR)==-1) {
  1403.        fprintf(hTrap,"Error %u seeking dir codeview data in %s\n",errno,FileName);
  1404.        return(22);
  1405.     }
  1406.  
  1407.     if (read(fh,(void *)&numdir,2)==-1) {
  1408.        fprintf(hTrap,"Error %u reading dir codeview data in %s\n",errno,FileName);
  1409.        return(23);
  1410.     }
  1411.  
  1412.     /* Read dir table into buffer */
  1413.     if (( pDirTab = ( struct  ssDir *) calloc(numdir,sizeof( struct  ssDir)))==NULL) {
  1414.        fprintf(hTrap,"Out of memory!");
  1415.        return(-1);
  1416.     }
  1417.  
  1418.     if (read(fh,(void *)pDirTab,numdir*sizeof( struct  ssDir))==-1) {
  1419.        fprintf(hTrap,"Error %u reading codeview dir table from %s\n",errno,FileName);
  1420.        free(pDirTab);
  1421.        return(24);
  1422.     }
  1423.  
  1424.     i=0;
  1425.     while (i<numdir) {
  1426.        if (pDirTab[i].sst!=SSTMODULES) {
  1427.            i++;
  1428.            continue;
  1429.        }
  1430.        NrPublic=0x0;
  1431.        NrLine=0x0;
  1432.        /* point to subsection */
  1433.        lseek(fh, pDirTab[i].lfoStart + lfaBase, SEEK_SET);
  1434.        read(fh,(void *)&ssmod.csBase,sizeof(ssmod));
  1435.        read(fh,(void *)ModName,(unsigned)ssmod.csize);
  1436.        ModIndex=pDirTab[i].modindex;
  1437.        ModName[ssmod.csize]='\0';
  1438.        i++;
  1439.        while (pDirTab[i].modindex ==ModIndex && i<numdir) {
  1440.           /* point to subsection */
  1441.           lseek(fh, pDirTab[i].lfoStart + lfaBase, SEEK_SET);
  1442.           switch(pDirTab[i].sst) {
  1443.             case SSTPUBLICS:
  1444.                bytesread=0;
  1445.                while (bytesread < pDirTab[i].cb) {
  1446.                    bytesread += read(fh,(void *)&sspub.offset,sizeof(sspub));
  1447.                    bytesread += read(fh,(void *)ename,(unsigned)sspub.csize);
  1448.                    ename[sspub.csize]='\0';
  1449.                    if ((sspub.segment==TrapSeg) &&
  1450.                        (sspub.offset<=TrapOff) &&
  1451.                        (sspub.offset>=NrPublic)) {
  1452.                        NrPublic=sspub.offset;
  1453.  
  1454.                        #ifdef __cplusplus
  1455.                        char *rest = NULL;
  1456.                        Name *name = Demangle(ename, rest, RegularNames);
  1457.                        sprintf(szNrPub," %s", name == NULL ? ename : name->Text());
  1458.                        if (name)
  1459.                           free(name);
  1460.                        #else
  1461.                        sprintf(szNrPub," %s", ename);
  1462.                        #endif
  1463.                    }
  1464.                }
  1465.                break;
  1466.  
  1467.             case SSTSRCLINES2:
  1468.             case SSTSRCLINES:
  1469.                if (TrapSeg!=ssmod.csBase) break;
  1470.                namelen=0;
  1471.                read(fh,(void *)&namelen,1);
  1472.                read(fh,(void *)ename,namelen);
  1473.                ename[namelen]='\0';
  1474.                /* skip 2 zero bytes */
  1475.                if (pDirTab[i].sst==SSTSRCLINES2) read(fh,(void *)&numlines,2);
  1476.                read(fh,(void *)&numlines,2);
  1477.                for (j=0;j<numlines;j++) {
  1478.                   read(fh,(void *)&line,2);
  1479.                   read(fh,(void *)&offset,2);
  1480.                   if (offset<=TrapOff && offset>=NrLine) {
  1481.                      static char szJunk[_MAX_FNAME];
  1482.                      static char szName[_MAX_FNAME];
  1483.                      static char szExt[_MAX_EXT];
  1484.                      NrLine=offset;
  1485.                      _splitpath(ename, szJunk, szJunk, szName, szExt);
  1486.                      sprintf(szNrLine," %-8.8s%-4.4s % 5hu", szName, szExt, line);
  1487.                   }
  1488.                }
  1489.                break;
  1490.           } /* end switch */
  1491.           i++;
  1492.        } /* end while modindex */
  1493.     } /* End While i < numdir */
  1494.     free(pDirTab);
  1495.     return(0);
  1496. }
  1497. int Read32PmDebug(int fh,int TrapSeg,int TrapOff,CHAR * FileName) {
  1498.     static unsigned int offset,NrPublic,NrFile,NrLine,NrEntry,numdir,namelen,numlines,line;
  1499.     static int ModIndex;
  1500.     static int bytesread,i,j;
  1501.     static SSLINEENTRY32 LineEntry;
  1502.     static SSFILENUM32 FileInfo;
  1503.     static FIRSTLINEENTRY32 FirstLine;
  1504.     ModIndex=0;
  1505.     /* See if any CODEVIEW info */
  1506.     if (lseek(fh,-8L,SEEK_END)==-1) {
  1507.         fprintf(hTrap,"Error %u seeking CodeView table in %s\n",errno,FileName);
  1508.         return(18);
  1509.     }
  1510.  
  1511.     if (read(fh,(void *)&eodbug,8)==-1) {
  1512.        fprintf(hTrap,"Error %u reading debug info from %s\n",errno,FileName);
  1513.        return(19);
  1514.     }
  1515.     if (eodbug.dbug!=DBUGSIG) {
  1516.        /*fprintf(hTrap,"\nNo CodeView information stored.\n");*/
  1517.        return(100);
  1518.     }
  1519.  
  1520.     if ((lfaBase=lseek(fh,-eodbug.dfaBase,SEEK_END))==-1L) {
  1521.        fprintf(hTrap,"Error %u seeking base codeview data in %s\n",errno,FileName);
  1522.        return(20);
  1523.     }
  1524.  
  1525.     if (read(fh,(void *)&base,8)==-1) {
  1526.        fprintf(hTrap,"Error %u reading base codeview data in %s\n",errno,FileName);
  1527.        return(21);
  1528.     }
  1529.  
  1530.     if (lseek(fh,base.lfoDir-8+4,SEEK_CUR)==-1) {
  1531.        fprintf(hTrap,"Error %u seeking dir codeview data in %s\n",errno,FileName);
  1532.        return(22);
  1533.     }
  1534.  
  1535.     if (read(fh,(void *)&numdir,4)==-1) {
  1536.        fprintf(hTrap,"Error %u reading dir codeview data in %s\n",errno,FileName);
  1537.        return(23);
  1538.     }
  1539.  
  1540.     /* Read dir table into buffer */
  1541.     if (( pDirTab32 = ( struct  ssDir32 *) calloc(numdir,sizeof( struct  ssDir32)))==NULL) {
  1542.        fprintf(hTrap,"Out of memory!");
  1543.        return(-1);
  1544.     }
  1545.  
  1546.     if (read(fh,(void *)pDirTab32,numdir*sizeof( struct  ssDir32))==-1) {
  1547.        fprintf(hTrap,"Error %u reading codeview dir table from %s\n",errno,FileName);
  1548.        free(pDirTab32);
  1549.        return(24);
  1550.     }
  1551.  
  1552.     i=0;
  1553.     while (i<numdir) {
  1554.        if ( pDirTab32[i].sst !=SSTMODULES) {
  1555.            i++;
  1556.            continue;
  1557.        }
  1558.        NrPublic=0x0;
  1559.        NrLine=0x0;
  1560.        NrFile=0x0;
  1561.        /* point to subsection */
  1562.        lseek(fh, pDirTab32[i].lfoStart + lfaBase, SEEK_SET);
  1563.        read(fh,(void *)&ssmod32.csBase,sizeof(ssmod32));
  1564.        read(fh,(void *)ModName,(unsigned)ssmod32.csize);
  1565.        ModIndex=pDirTab32[i].modindex;
  1566.        ModName[ssmod32.csize]='\0';
  1567.        i++;
  1568.        while (pDirTab32[i].modindex ==ModIndex && i<numdir) {
  1569.           /* point to subsection */
  1570.           lseek(fh, pDirTab32[i].lfoStart + lfaBase, SEEK_SET);
  1571.           switch(pDirTab32[i].sst) {
  1572.             case SSTPUBLICS:
  1573.                bytesread=0;
  1574.                while (bytesread < pDirTab32[i].cb) {
  1575.                    bytesread += read(fh,(void *)&sspub32.offset,sizeof(sspub32));
  1576.                    bytesread += read(fh,(void *)ename,(unsigned)sspub32.csize);
  1577.                    ename[sspub32.csize]='\0';
  1578.                    if ((sspub32.segment==TrapSeg) &&
  1579.                        (sspub32.offset<=TrapOff) &&
  1580.                        (sspub32.offset>=NrPublic)) {
  1581.                        NrPublic=sspub32.offset;
  1582.  
  1583.                        #ifdef __cplusplus
  1584.                        char *rest = NULL;
  1585.                        Name *name = Demangle(ename, rest, RegularNames);
  1586.                        sprintf(szNrPub," %s", name == NULL ? ename : name->Text());
  1587.                        if (name)
  1588.                           free(name);
  1589.                        #else
  1590.                        sprintf(szNrPub," %s", ename);
  1591.                        #endif
  1592.                    }
  1593.                }
  1594.                break;
  1595.  
  1596.             case SSTSRCLINES32:
  1597.                if (TrapSeg!=ssmod32.csBase) break;
  1598.                /* read first line */
  1599.                read(fh,(void *)&FirstLine,sizeof(FirstLine));
  1600.                if (FirstLine.LineNum!=0) {
  1601.                   fprintf(hTrap,"Missing Line table information\n");
  1602.                   break;
  1603.                } /* endif */
  1604.                numlines= FirstLine.numlines;
  1605.                /* Other type of data skip 4 more bytes */
  1606.                if (FirstLine.segnum!=0) {
  1607.                   lseek(fh,4,SEEK_CUR);
  1608.                }
  1609.                for (j=0;j<numlines;j++) {
  1610.                   read(fh,(void *)&LineEntry,sizeof(LineEntry));
  1611.                   if (LineEntry.Offset+ssmod32.csOff<=TrapOff && LineEntry.Offset+ssmod32.csOff>=NrLine) {
  1612.                      NrLine=LineEntry.Offset;
  1613.                      NrFile=LineEntry.FileNum;
  1614.                      sprintf(szNrLine," % 5hu", LineEntry.LineNum);
  1615.                   }
  1616.                }
  1617.                if (NrFile!=0) {
  1618.                   static char szJunk[_MAX_FNAME];
  1619.                   static char szName[_MAX_FNAME];
  1620.                   static char szExt[_MAX_EXT];
  1621.                   read(fh,(void *)&FileInfo,sizeof(FileInfo));
  1622.                   namelen=0;
  1623.                   for (j=1;j<=FileInfo.file_count;j++) {
  1624.                      namelen=0;
  1625.                      read(fh,(void *)&namelen,1);
  1626.                      read(fh,(void *)ename,namelen);
  1627.                      if (j==NrFile) break;
  1628.                   }
  1629.                   ename[namelen]='\0';
  1630.                   _splitpath(ename, szJunk, szJunk, szName, szExt);
  1631.                   strcpy(szJunk, szNrLine);
  1632.                   sprintf(szNrLine," %-8.8s%-4.4s",szName,szExt);
  1633.                   strcat(szNrLine, szJunk);
  1634.                }
  1635.                break;
  1636.           } /* end switch */
  1637.  
  1638.           i++;
  1639.        } /* end while modindex */
  1640.     } /* End While i < numdir */
  1641.     free(pDirTab32);
  1642.     return(0);
  1643. }
  1644.