source: trunk/dll/excputil.c@ 1673

Last change on this file since 1673 was 1673, checked in by Gregg Young, 13 years ago

Update to Doxygen comment style Ticket 55. Also some minor code cleanup.

  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 KB
RevLine 
[1673]1/***********************************************************
[1331]2
[1673]3 $Id: excputil.c 1673 2012-12-30 18:51:01Z gyoung $
[1331]4
[1673]5 exception handlers
6
[1331]7 Copyright (c) 2008 Steven H. Levine
8
9 Write to exceptq .trp file or ?:\fm2_trap.log
10 where ? is boot volume
11
12 06 Dec 08 SHL Baseline (Ticket #26)
13
[1673]14************************************************************/
[1331]15
16#include <stdio.h> // fprintf
17#include <string.h> // strcpy
18#include <time.h> // tm
19#include <process.h> // _beginthread
20
21#define INCL_DOSMODULEMGR // DosQueryModFromEIP
22#define INCL_DOSPROCESS // PPIB PTIB
23#define INCL_DOSEXCEPTIONS // XCTP_...
24#define INCL_DOSMISC // DosDumpProcess?
25#define INCL_DOSERRORS // NO_ERROR
[1332]26// #include <os2.h>
[1331]27
28#include "wrappers.h" // xmalloc xfree
29#include "errutil.h" // Dos_Error Runtime_Error
30#include "fm3str.h" // IDS_COULDNTSTARTTHREADTEXT
31#include "strutil.h" // GetPString
32
[1332]33#include "excputil.h"
[1442]34#include "fortify.h"
[1331]35
36static PSZ pszSrcFile = __FILE__;
37
38typedef struct {
39 VOID (*pfnThread)(PVOID);
40 PVOID *pvArgs;
41} THREADDATA;
42
43/**
44 * Wrapper thread that installs exception handler and invokes
45 * function passed to xbeginthread
46 */
47
48static VOID WrapperThread(PVOID pvArgs)
49{
[1332]50 EXCEPTIONREGISTRATIONRECORD regRec = { NULL, NULL };
[1331]51 APIRET apiret;
52 THREADDATA *ptd = (THREADDATA*)pvArgs;
53
54# ifdef FORTIFY
55 Fortify_EnterScope();
56 Fortify_BecomeOwner(pvArgs);
57# endif
58
[1332]59 regRec.ExceptionHandler = HandleException;
60 apiret = DosSetExceptionHandler(&regRec);
[1331]61 if (apiret != NO_ERROR) {
62 Dos_Error(MB_ENTER, apiret, HWND_DESKTOP, pszSrcFile, __LINE__,
63 "DosSetExceptionHandler");
64 }
65
[1332]66#if 0 // 11 Dec 08 SHL fixme tobe gone - debug
67 {
68 static UINT when;
69 if (++when == 2)
70 *(char*)0 = 0;
71 }
72#endif
73
[1331]74 (*ptd->pfnThread)(ptd->pvArgs); // Invoke thread
75
76 xfree(pvArgs, pszSrcFile, __LINE__);
77
78 if (apiret == NO_ERROR) {
[1332]79 apiret = DosUnsetExceptionHandler(&regRec);
[1331]80 if (apiret != NO_ERROR) {
81 Dos_Error(MB_ENTER, apiret, HWND_DESKTOP, pszSrcFile, __LINE__,
82 "DosUnsetExceptionHandler");
83 }
84 }
85
86# ifdef FORTIFY
87 Fortify_LeaveScope();
88# endif
89
90 // Time to disappear
91
92}
93
94/**
95 * _beginthread wrapper which supplies exception handler support
96 */
97
98int xbeginthread(VOID (*pfnThread)(PVOID),
99 UINT cStackBytes,
[1332]100 PVOID pvArgs,
101 PSZ pszSrcFile,
102 UINT uiLineNumber)
[1331]103{
104 int rc;
105 THREADDATA *ptd = (THREADDATA *)xmalloc(sizeof(THREADDATA), pszSrcFile, __LINE__);
106 ptd->pfnThread = pfnThread;
107 ptd->pvArgs = pvArgs;
108 rc = _beginthread(WrapperThread, NULL, cStackBytes, ptd);
109 if (rc == -1)
[1332]110 Runtime_Error(pszSrcFile, uiLineNumber,
[1331]111 GetPString(IDS_COULDNTSTARTTHREADTEXT));
112 return rc;
113}
114
115/**
116 * Handle exception
117 * Calls exceptq if available or handles internally
118 */
119
120ULONG HandleException(PEXCEPTIONREPORTRECORD pReport,
121 PEXCEPTIONREGISTRATIONRECORD pReg,
122 PCONTEXTRECORD pContext,
123 PVOID pv)
124{
125 BOOL handled = FALSE;
126 ULONG ex = pReport->ExceptionNum;
127 time_t now;
128 struct tm *ptm;
129 char *pszTime;
130 PIB *ppib;
131 TIB *ptib;
[1332]132 ULONG ulpid;
133 ULONG ultid;
[1331]134 APIRET apiret;
[1332]135 HMODULE hmod;
[1331]136
137 static unsigned working;
[1332]138 static PSZ pszExcpMsg = "Caught exception %lx in process %lx (%lu) thread %u at %.24s";
[1331]139
[1332]140 // Try to report cascading exceptions in handler only once
141 // This simple test can get confused if multiple threads trap at same time
[1331]142 if (++working > 1) {
143 if (working == 2) {
[1332]144 DbgMsg(pszSrcFile, __LINE__, "Caught exception %lx at %p while handler active",
[1331]145 ex, pContext->ctx_RegEip);
146 }
147 working--;
148 return XCPT_CONTINUE_SEARCH;
149 }
150
[1332]151 // Bypass exceptions we don't handle or exceptions we ignore
152 // Keep in sync with exceptq selections since exceptq will ignore anyway
[1331]153 if ((pReport->fHandlerFlags & (EH_UNWINDING | EH_NESTED_CALL)) ||
[1332]154 (ex & XCPT_SEVERITY_CODE) != XCPT_FATAL_EXCEPTION ||
155 ex == XCPT_ASYNC_PROCESS_TERMINATE ||
156 ex == XCPT_PROCESS_TERMINATE ||
157 ex == XCPT_UNWIND ||
158 ex == XCPT_SIGNAL ||
159 ex == XCPT_BREAKPOINT ||
160 ex == XCPT_SINGLE_STEP)
[1331]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) {
[1332]172 ulpid = 0;
173 ultid = 0;
[1331]174 }
[1332]175 else {
176 ulpid = ppib->pib_ulpid;
177 ultid = ptib->tib_ptib2->tib2_ultid;
178 }
[1331]179
[1332]180 DbgMsg(pszSrcFile, __LINE__, pszExcpMsg,
181 ex, ulpid, ulpid, ultid, pszTime);
[1331]182
[1332]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);
[1331]194 else {
[1332]195 // DbgMsg(pszSrcFile, __LINE__, "Invoking exceptq handler at %p", pfn);
196 (*pfn)(pReport, pReg, pContext, pv);
197 handled = TRUE;
[1331]198 }
[1332]199 DosFreeModule(hmod);
200 }
[1331]201
[1332]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;
[1544]227 CHAR *modea = "a";
[1331]228
[1332]229 handled = TRUE;
[1331]230
[1332]231 // Write stack trace to log file - let kernel do popuplog.os2
[1544]232 fp = xfopen("fm2_trap.log", modea, pszSrcFile, __LINE__, TRUE);
[1332]233 if (!fp)
234 fp = stderr; // Oh well
[1331]235
[1332]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);
[1331]243
[1332]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;
[1533]252 u.stk16.usIP = (SHORT) pContext->ctx_RegEip;
253 u.stk16.usBP = (SHORT) pContext->ctx_RegEbp;
[1332]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;
[1331]261 }
262 else {
[1332]263 ulEIP = ((ULONG) (pContext->ctx_SegCs & ~7) << 13) | u.stk16.usIP;
264 ulEBP = ((ULONG) (pContext->ctx_SegSs & ~7) << 13) | u.stk16.usBP;
[1331]265 }
266
[1332]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
[1331]276
[1332]277 fprintf(fp, " Stack frame %u @ %lx:%lx %s %lx:%lx\n",
278 c,
279 pContext->ctx_SegCs, ulEIP,
280 szFileName, ulObjNum, ulOffset);
[1331]281
[1332]282 if (apiret)
283 break;
[1331]284
[1332]285 if (!ulEBP || ulEBP <= ulOldEBP)
286 break;
[1331]287
[1332]288 cnt = sizeof(u);
[1331]289
[1332]290 apiret = DosQueryMem((void*)ulEBP, &cnt, &flags);
291 if (apiret || (flags & (PAG_COMMIT | PAG_READ)) != (PAG_COMMIT | PAG_READ))
292 break; // We are lost
[1331]293
[1332]294 ulOldEBP = ulEBP;
295 memcpy((void*)&u, (void*)ulEBP, sizeof(u));
[1331]296
[1332]297 } // for
[1331]298
[1332]299 if (fp || fp != stderr)
300 fclose(fp);
[1331]301
[1332]302 } // if !handled
[1331]303
[1332]304 // DbgMsg(pszSrcFile, __LINE__, "We are going to die now");
[1331]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.