source: trunk/dll/excputil.c@ 1801

Last change on this file since 1801 was 1801, checked in by Steven Levine, 10 years ago

HandleException: check for ignore before checking for cascade

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