source: trunk/dll/excputil.c@ 1880

Last change on this file since 1880 was 1880, checked in by Gregg Young, 10 years ago

Remove dead code and comments from remaining c files. #if 0 and #if NEVER were not addressed

  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 KB
Line 
1/***********************************************************
2
3 $Id: excputil.c 1880 2015-10-12 18:26:16Z gyoung $
4
5 exception handlers
6
7 Copyright (c) 2008, 2015 Steven H. Levine
8
9 Write to exceptq .trp file or ?:\fm2_trap.log
10 where ? is boot volume
11
12 2008-12-06 SHL Baseline (Ticket #26)
13 2015-04-03 SHL HandleException: check for ignore before checking for cascade
14 2015-08-09 SHL Use xDosGetInfoBlocks
15
16************************************************************/
17
18#include <stdio.h> // fprintf
19#include <string.h> // strcpy
20#include <time.h> // tm
21#include <process.h> // _beginthread
22
23#define INCL_DOSMODULEMGR // DosQueryModFromEIP
24#define INCL_DOSPROCESS // PPIB PTIB
25#define INCL_DOSEXCEPTIONS // XCTP_...
26#define INCL_DOSMISC // DosDumpProcess?
27#define INCL_DOSERRORS // NO_ERROR
28
29#include "wrappers.h" // xmalloc xfree
30#include "errutil.h" // Dos_Error Runtime_Error
31#include "fm3str.h" // IDS_COULDNTSTARTTHREADTEXT
32#include "strutil.h" // GetPString
33
34#include "excputil.h"
35#include "fortify.h"
36
37static PSZ pszSrcFile = __FILE__;
38
39typedef struct {
40 VOID (*pfnThread)(PVOID);
41 PVOID *pvArgs;
42} THREADDATA;
43
44/**
45 * Wrapper thread that installs exception handler and invokes
46 * function passed to xbeginthread
47 */
48
49static VOID WrapperThread(PVOID pvArgs)
50{
51 EXCEPTIONREGISTRATIONRECORD regRec = { NULL, NULL };
52 APIRET apiret;
53 THREADDATA *ptd = (THREADDATA*)pvArgs;
54
55# ifdef FORTIFY
56 Fortify_EnterScope();
57 Fortify_BecomeOwner(pvArgs);
58# endif
59
60 regRec.ExceptionHandler = HandleException;
61 apiret = DosSetExceptionHandler(&regRec);
62 if (apiret != NO_ERROR) {
63 Dos_Error(MB_ENTER, apiret, HWND_DESKTOP, pszSrcFile, __LINE__,
64 "DosSetExceptionHandler");
65 }
66
67 (*ptd->pfnThread)(ptd->pvArgs); // Invoke thread
68
69 xfree(pvArgs, pszSrcFile, __LINE__);
70
71 if (apiret == NO_ERROR) {
72 apiret = DosUnsetExceptionHandler(&regRec);
73 if (apiret != NO_ERROR) {
74 Dos_Error(MB_ENTER, apiret, HWND_DESKTOP, pszSrcFile, __LINE__,
75 "DosUnsetExceptionHandler");
76 }
77 }
78
79# ifdef FORTIFY
80 Fortify_LeaveScope();
81# endif
82
83 // Time to disappear
84
85}
86
87/**
88 * _beginthread wrapper which supplies exception handler support
89 */
90
91int xbeginthread(VOID (*pfnThread)(PVOID),
92 UINT cStackBytes,
93 PVOID pvArgs,
94 PSZ pszSrcFile,
95 UINT uiLineNumber)
96{
97 int rc;
98 THREADDATA *ptd = (THREADDATA *)xmalloc(sizeof(THREADDATA), pszSrcFile, __LINE__);
99 ptd->pfnThread = pfnThread;
100 ptd->pvArgs = pvArgs;
101 rc = _beginthread(WrapperThread, NULL, cStackBytes, ptd);
102 if (rc == -1)
103 Runtime_Error(pszSrcFile, uiLineNumber,
104 GetPString(IDS_COULDNTSTARTTHREADTEXT));
105 return rc;
106}
107
108/**
109 * Handle exception
110 * Calls exceptq if available or handles internally
111 */
112
113ULONG HandleException(PEXCEPTIONREPORTRECORD pReport,
114 PEXCEPTIONREGISTRATIONRECORD pReg,
115 PCONTEXTRECORD pContext,
116 PVOID pv)
117{
118 BOOL handled = FALSE;
119 ULONG ex = pReport->ExceptionNum;
120 time_t now;
121 struct tm *ptm;
122 char *pszTime;
123 PIB *ppib;
124 TIB *ptib;
125 ULONG ulpid;
126 ULONG ultid;
127 APIRET apiret;
128 HMODULE hmod;
129
130 static unsigned working;
131 static PSZ pszExcpMsg = "Caught exception %lx in process %lx (%lu) thread %u at %.24s";
132
133 // Bypass exceptions we don't handle or exceptions we ignore
134 // Keep in sync with exceptq selections since exceptq will ignore anyway
135 if ((pReport->fHandlerFlags & (EH_UNWINDING | EH_NESTED_CALL)) ||
136 (ex & XCPT_SEVERITY_CODE) != XCPT_FATAL_EXCEPTION ||
137 ex == XCPT_ASYNC_PROCESS_TERMINATE ||
138 ex == XCPT_PROCESS_TERMINATE ||
139 ex == XCPT_UNWIND ||
140 ex == XCPT_SIGNAL ||
141 ex == XCPT_BREAKPOINT ||
142 ex == XCPT_SINGLE_STEP)
143 {
144 return XCPT_CONTINUE_SEARCH;
145 }
146
147 // Try to report cascading exceptions in handler only once
148 // This simple test can get confused if multiple threads trap at same time
149 if (++working > 1) {
150 if (working == 2) {
151 DbgMsg(pszSrcFile, __LINE__, "Caught exception %lx at %p while handler active",
152 ex, pContext->ctx_RegEip);
153 }
154 working--;
155 return XCPT_CONTINUE_SEARCH;
156 }
157
158 now = time(NULL);
159 ptm = localtime(&now);
160 pszTime = asctime(ptm);
161
162 apiret = xDosGetInfoBlocks(&ptib, &ppib);
163 if (apiret) {
164 ulpid = 0;
165 ultid = 0;
166 }
167 else {
168 ulpid = ppib->pib_ulpid;
169 ultid = ptib->tib_ptib2->tib2_ultid;
170 }
171
172 DbgMsg(pszSrcFile, __LINE__, pszExcpMsg,
173 ex, ulpid, ulpid, ultid, pszTime);
174
175 // Report errors with DbgMsg, Dos_Error unsafe here
176 apiret = DosLoadModule (0, 0, "exceptq" ,&hmod);
177 if (apiret) {
178 if (apiret != ERROR_FILE_NOT_FOUND)
179 DbgMsg(pszSrcFile, __LINE__, "DosLoadModule(exceptq) reported error %u", apiret);
180 }
181 else {
182 ERR pfn;
183 apiret = DosQueryProcAddr(hmod, 0, "MYHANDLER", (PFN*)&pfn);
184 if (apiret)
185 DbgMsg(pszSrcFile, __LINE__, "DosQueryProcAddr(MYHANDLER) reported error %u", apiret);
186 else {
187 // DbgMsg(pszSrcFile, __LINE__, "Invoking exceptq handler at %p", pfn);
188 (*pfn)(pReport, pReg, pContext, pv);
189 handled = TRUE;
190 }
191 DosFreeModule(hmod);
192 }
193
194 // If exceptq not available use local handler
195 if (!handled) {
196 union {
197 struct {
198 ULONG ulEBP;
199 ULONG ulEIP;
200 } stk32;
201 struct {
202 USHORT usBP;
203 USHORT usIP;
204 USHORT usCS; // > 1 and < 0xfff
205 } stk16;
206 } u;
207 ULONG ulObjNum;
208 ULONG ulOffset;
209 ULONG ulEIP;
210 ULONG ulEBP;
211 CHAR szFileName[CCHMAXPATH];
212 BOOL is32Bit;
213 APIRET apiret;
214 ULONG flags;
215 ULONG cnt;
216 ULONG ulOldEBP = 0;
217 INT c;
218 FILE* fp;
219 CHAR *modea = "a";
220
221 handled = TRUE;
222
223 // Write stack trace to log file - let kernel do popuplog.os2
224 fp = xfopen("fm2_trap.log", modea, pszSrcFile, __LINE__, TRUE);
225 if (!fp)
226 fp = stderr; // Oh well
227
228 if (fp != stderr) {
229 fputc('\n', fp);
230 fprintf(fp, pszExcpMsg,
231 ex, ulpid, ulpid, ultid, pszTime);
232 fputc('\n', stderr);
233 }
234 fputc('\n', stderr);
235
236 // fixme to support mixed 32-bit/16-bit stacks, 5b = FLAT_CS
237 if (pContext->ctx_SegCs == 0x5b) {
238 is32Bit = TRUE; // Assume 32-bit
239 u.stk32.ulEIP = pContext->ctx_RegEip;
240 u.stk32.ulEBP = pContext->ctx_RegEbp;
241 }
242 else {
243 is32Bit = FALSE;
244 u.stk16.usIP = (SHORT) pContext->ctx_RegEip;
245 u.stk16.usBP = (SHORT) pContext->ctx_RegEbp;
246 }
247
248 // Walk stack frames
249 for (c = 0; c < 100; c++) {
250 if (is32Bit) {
251 ulEIP = u.stk32.ulEIP;
252 ulEBP = u.stk32.ulEBP;
253 }
254 else {
255 ulEIP = ((ULONG) (pContext->ctx_SegCs & ~7) << 13) | u.stk16.usIP;
256 ulEBP = ((ULONG) (pContext->ctx_SegSs & ~7) << 13) | u.stk16.usBP;
257 }
258
259 apiret = DosQueryModFromEIP(&hmod, &ulObjNum, CCHMAXPATH, szFileName,
260 &ulOffset, ulEIP);
261 if (apiret) {
262 ulObjNum = 0;
263 ulOffset = 0;
264 strcpy(szFileName, "n/a");
265 }
266 else
267 ulObjNum++; // Number from 1..n for display
268
269 fprintf(fp, " Stack frame %u @ %lx:%lx %s %lx:%lx\n",
270 c,
271 pContext->ctx_SegCs, ulEIP,
272 szFileName, ulObjNum, ulOffset);
273
274 if (apiret)
275 break;
276
277 if (!ulEBP || ulEBP <= ulOldEBP)
278 break;
279
280 cnt = sizeof(u);
281
282 apiret = DosQueryMem((void*)ulEBP, &cnt, &flags);
283 if (apiret || (flags & (PAG_COMMIT | PAG_READ)) != (PAG_COMMIT | PAG_READ))
284 break; // We are lost
285
286 ulOldEBP = ulEBP;
287 memcpy((void*)&u, (void*)ulEBP, sizeof(u));
288
289 } // for
290
291 if (fp || fp != stderr)
292 fclose(fp);
293
294 } // if !handled
295
296 // DbgMsg(pszSrcFile, __LINE__, "We are going to die now");
297
298 working--;
299
300 return XCPT_CONTINUE_SEARCH; // Let other handlers see exception
301
302}
Note: See TracBrowser for help on using the repository browser.