source: trunk/dll/excputil.c@ 1533

Last change on this file since 1533 was 1533, checked in by Gregg Young, 15 years ago

Fixed possible loss of precision compiler warnings by casting the variables in question.

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