Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

693 lines
17 KiB

  1. #include <windows.h>
  2. #include "faultrep.h"
  3. #include "util.h"
  4. #include "stdio.h"
  5. #include "malloc.h"
  6. BOOL g_fDebug = FALSE;
  7. enum EFaultType
  8. {
  9. eftAV = 0,
  10. eftMisalign,
  11. eftArrayBound,
  12. eftStackOverflowFunc,
  13. eftStackOverflowAlloc,
  14. eftInstrPriv,
  15. eftInstrBad,
  16. eftIntDivZero,
  17. eftIntOverflow,
  18. eftFltDivZero,
  19. eftFltOverflow,
  20. eftFltUnderflow,
  21. eftFltStack,
  22. eftFltInexact,
  23. eftFltDenormal,
  24. eftFltInvalid,
  25. eftExBadRet,
  26. eftExNonCont,
  27. };
  28. // ***************************************************************************
  29. void ShowUsage(void)
  30. {
  31. printf("\n");
  32. printf("gpfme [command] [exception type]\n");
  33. printf("\nCommand options:\n");
  34. printf(" -a: Access violation (default if no command is specified)\n");
  35. #ifndef _WIN64
  36. printf(" -b: Array bound violation\n");
  37. #endif
  38. printf(" -i: Integer divide by 0 (default)\n");
  39. printf(" -iz: Integer divide by 0\n");
  40. printf(" -io: Integer overflow\n");
  41. #ifdef _WIN64
  42. printf(" -m: Data misalignment fault (not available on x86)\n");
  43. #endif
  44. printf(" -s: Stack overflow via infinite recursion (default) \n");
  45. printf(" -sa: Stack overflow via alloca\n");
  46. printf(" -sf: Stack overflow via infinite recursion\n");
  47. printf(" -f: Floating point divide by 0 (default)\n");
  48. printf(" -fi: Floating point inexact result\n");
  49. printf(" -fn: Floating point invalid operation\n");
  50. printf(" -fo: Floating point overflow\n");
  51. printf(" -fu: Floating point underflow\n");
  52. printf(" -fz: Floating point divide by 0\n");
  53. printf(" -n: Execute privilidged instruction (default)\n");
  54. printf(" -ni: Execute invalid instruction\n");
  55. printf(" -np: Execute privilidged instruction\n");
  56. }
  57. // ***************************************************************************
  58. LONG MyFilter(EXCEPTION_POINTERS *pep)
  59. {
  60. static BOOL fGotHere = FALSE;
  61. EFaultRepRetVal frrv;
  62. pfn_REPORTFAULT pfn = NULL;
  63. HMODULE hmodFaultRep = NULL;
  64. WCHAR szDebugger[2 * MAX_PATH];
  65. BOOL fGotDbgr = FALSE;
  66. char wszMsg[2048];
  67. if (g_fDebug &&
  68. (pep->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT ||
  69. pep->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP))
  70. return EXCEPTION_CONTINUE_SEARCH;
  71. if (g_fDebug && fGotHere)
  72. return EXCEPTION_CONTINUE_SEARCH;
  73. fGotHere = TRUE;
  74. if (g_fDebug)
  75. DebugBreak();
  76. if (GetProfileStringW(L"AeDebug", L"Debugger", NULL, szDebugger, sizeofSTRW(szDebugger) - 1))
  77. fGotDbgr = TRUE;
  78. hmodFaultRep = LoadLibrary("faultrep.dll");
  79. if (hmodFaultRep != NULL)
  80. {
  81. pfn = (pfn_REPORTFAULT)GetProcAddress(hmodFaultRep, "ReportFault");
  82. if (pfn != NULL)
  83. {
  84. frrv = (*pfn)(pep, fGotDbgr);
  85. }
  86. else
  87. {
  88. printf("Unable to get ReportFault function\n");
  89. return EXCEPTION_CONTINUE_SEARCH;
  90. }
  91. }
  92. else
  93. {
  94. printf("Unable to load faultrep.dll\n");
  95. return EXCEPTION_CONTINUE_SEARCH;
  96. }
  97. switch(frrv)
  98. {
  99. case frrvOk:
  100. printf("DW completed fine.\n");
  101. break;
  102. case frrvOkManifest:
  103. printf("DW completed fine in manifest mode.\n");
  104. break;
  105. case frrvOkQueued:
  106. printf("DW completed fine in queue mode.\n");
  107. break;
  108. case frrvLaunchDebugger:
  109. printf("DW completed fine & says to launch debugger.\n");
  110. break;
  111. case frrvErrNoDW:
  112. printf("DW could not be launched.\n");
  113. break;
  114. case frrvErr:
  115. printf("An error occurred.\n");
  116. break;
  117. case frrvErrTimeout:
  118. printf("Timed out waiting for DW to complete.\n");
  119. break;
  120. default:
  121. printf("unexpected return value...\n");
  122. break;
  123. }
  124. if (hmodFaultRep != NULL)
  125. FreeLibrary(hmodFaultRep);
  126. return EXCEPTION_EXECUTE_HANDLER;
  127. };
  128. // ***************************************************************************
  129. void NukeStack(void)
  130. {
  131. DWORD rgdw[512];
  132. DWORD a = 1;
  133. // the compiler tries to be smart and not let me deliberately write a
  134. // infinitely recursive function, so gotta do this to work around it.
  135. if(a == 1)
  136. NukeStack();
  137. }
  138. // ***************************************************************************
  139. typedef DWORD (*FAULT_FN)(void);
  140. void DoException(EFaultType eft)
  141. {
  142. switch(eft)
  143. {
  144. // access violation
  145. default:
  146. case eftAV:
  147. {
  148. int *p = NULL;
  149. fprintf(stderr, "Generating an access violation\n");
  150. *p = 1;
  151. fprintf(stderr, "Error: No exception thrown.\n");
  152. break;
  153. }
  154. #ifdef _WIN64
  155. // data misalignment
  156. case eftMisalign:
  157. {
  158. DWORD *pdw;
  159. BYTE rg[8];
  160. fprintf(stderr, "Generating an misalignment fault.\n");
  161. pdw = (DWORD *)&rg[2];
  162. *pdw = 1;
  163. fprintf(stderr, "Error: No exception thrown.\n");
  164. break;
  165. }
  166. #endif
  167. #ifndef _WIN64
  168. // array bounds failure
  169. case eftArrayBound:
  170. {
  171. fprintf(stderr, "Generating an out-of-bounds exception\n");
  172. __int64 li;
  173. DWORD *pdw = (DWORD *)&li;
  174. *pdw = 1;
  175. pdw++;
  176. *pdw = 2;
  177. // bound will throw an 'array out of bounds' exception
  178. _asm mov eax, 0
  179. _asm bound eax, li
  180. fprintf(stderr, "Error: No exception thrown.\n");
  181. break;
  182. }
  183. #endif
  184. // stack overflow
  185. case eftStackOverflowFunc:
  186. {
  187. fprintf(stderr, "Generating an stack overflow via recursion\n");
  188. NukeStack();
  189. fprintf(stderr, "Error: No exception thrown.\n");
  190. break;
  191. }
  192. // stack overflow
  193. case eftStackOverflowAlloc:
  194. {
  195. LPVOID pv;
  196. DWORD i;
  197. fprintf(stderr, "Generating an stack overflow via alloca\n");
  198. for (i = 0; i < 0xffffffff; i++)
  199. pv = _alloca(512);
  200. fprintf(stderr, "Error: No exception thrown.\n");
  201. break;
  202. }
  203. // integer divide by 0
  204. case eftIntDivZero:
  205. {
  206. DWORD x = 4, y = 0;
  207. fprintf(stderr, "Generating an integer div by 0\n");
  208. x = x / y;
  209. fprintf(stderr, "Error: No exception thrown.\n");
  210. break;
  211. }
  212. // integer overflow
  213. case eftIntOverflow:
  214. {
  215. fprintf(stderr, "Generating an integer overflow\n");
  216. #ifdef _WIN64
  217. __int64 x = 0x7fffffffffffffff, y = 0x7fffffffffffffff;
  218. x = x + y;
  219. #else
  220. DWORD x = 0x7fffffff, y = 0x7fffffff;
  221. x = x + y;
  222. _asm into
  223. #endif
  224. fprintf(stderr, "Error: No exception thrown.\n");
  225. break;
  226. }
  227. // floating point divide by 0
  228. case eftFltDivZero:
  229. {
  230. double x = 4.1, y = 0.0;
  231. WORD wCtl, wCtlNew;
  232. fprintf(stderr, "Generating an floating point div by 0\n");
  233. #ifdef _WIN64
  234. x = x / y;
  235. #else
  236. // got to unmask the floating point exceptions so that the
  237. // processor doesn't handle them on it's own
  238. _asm fnstcw wCtl
  239. wCtlNew = wCtl & 0xffc0;
  240. _asm fldcw wCtlNew
  241. x = x / y;
  242. _asm fldcw wCtl
  243. #endif
  244. fprintf(stderr, "Error: No exception thrown.\n");
  245. break;
  246. }
  247. // floating point stack overflow
  248. case eftFltStack:
  249. {
  250. double x;
  251. WORD wCtl, wCtlNew;
  252. fprintf(stderr, "Generating an floating point stack overflow\n");
  253. #ifdef _WIN64
  254. #else
  255. // Got to unmask the floating point exceptions so that the
  256. // processor doesn't handle them on it's own
  257. _asm fnstcw wCtl
  258. wCtlNew = wCtl & 0xffc0;
  259. _asm fldcw wCtlNew
  260. // there should be 8 floating point stack registers, so attempting
  261. // to add a 9th element should nuke it
  262. _asm fld x
  263. _asm fld x
  264. _asm fld x
  265. _asm fld x
  266. _asm fld x
  267. _asm fld x
  268. _asm fld x
  269. _asm fld x
  270. _asm fld x
  271. _asm fldcw wCtl
  272. #endif
  273. fprintf(stderr, "Error: No exception thrown.\n");
  274. break;
  275. }
  276. // floating point overflow
  277. case eftFltOverflow:
  278. {
  279. double x = 1.0, y = 10.0;
  280. WORD wCtl, wCtlNew;
  281. DWORD i;
  282. fprintf(stderr, "Generating an floating point overflow\n");
  283. #ifdef _WIN64
  284. #else
  285. // Got to unmask the floating point exceptions so that the
  286. // processor doesn't handle them on it's own
  287. _asm fnstcw wCtl
  288. wCtlNew = wCtl & 0xffe0;
  289. _asm fldcw wCtlNew
  290. #endif
  291. for(i = 0; i < 100000; i++)
  292. x = x * y;
  293. fprintf(stderr, "Error: No exception thrown.\n");
  294. break;
  295. }
  296. // floating point invalid op
  297. case eftFltInvalid:
  298. {
  299. double x = 1.0, y = 10.0;
  300. WORD wCtl, wCtlNew;
  301. DWORD i;
  302. #ifdef _WIN64
  303. #else
  304. // Got to unmask the floating point exceptions so that the
  305. // processor doesn't handle them on it's own
  306. _asm fnstcw wCtl
  307. wCtlNew = wCtl & 0xffe0;
  308. _asm fldcw wCtlNew
  309. #endif
  310. fprintf(stderr, "Generating an floating point invalid operation\n");
  311. for(i = 0; i < 100000; i++)
  312. x = x / y;
  313. fprintf(stderr, "Error: No exception thrown.\n");
  314. break;
  315. }
  316. // floating point inexact result
  317. case eftFltInexact:
  318. {
  319. double x = 1.0, y = 10.0;
  320. WORD wCtl, wCtlNew;
  321. DWORD i;
  322. #ifdef _WIN64
  323. #else
  324. // Got to unmask the floating point exceptions so that the
  325. // processor doesn't handle them on it's own
  326. _asm fnstcw wCtl
  327. wCtlNew = wCtl & 0xffc0;
  328. _asm fldcw wCtlNew
  329. #endif
  330. fprintf(stderr, "Generating an floating point underflow\n");
  331. for(i = 0; i < 100000; i++)
  332. x = x / y;
  333. fprintf(stderr, "Error: No exception thrown.\n");
  334. break;
  335. }
  336. // floating point denormal value
  337. case eftFltDenormal:
  338. {
  339. double x = 1.0;
  340. DWORD i;
  341. WORD wCtl, wCtlNew;
  342. BYTE rg[8] = { 1, 0, 0, 0, 0, 0, 6, 0 };
  343. fprintf(stderr, "Generating a floating point denormal exception\n");
  344. #ifdef _WIN64
  345. #else
  346. // Got to unmask the floating point exceptions so that the
  347. // processor doesn't handle them on it's own
  348. memcpy(&x, rg, 8);
  349. _asm fnstcw wCtl
  350. wCtlNew = wCtl & 0xf2fc;
  351. _asm fldcw wCtlNew
  352. _asm fld x
  353. #endif
  354. fprintf(stderr, "Error: No exception thrown.\n");
  355. break;
  356. }
  357. // executing a privilidged instruction
  358. case eftInstrPriv:
  359. {
  360. fprintf(stderr, "Generating an privilidged instruction exception\n");
  361. #ifdef _WIN64
  362. #else
  363. // must be ring 0 to execute HLT
  364. _asm hlt
  365. #endif
  366. fprintf(stderr, "Error: No exception thrown.\n");
  367. break;
  368. }
  369. // executing an invalid instruction
  370. case eftInstrBad:
  371. {
  372. FAULT_FN pfn;
  373. BYTE rgc[2048];
  374. FillMemory(rgc, sizeof(rgc), 0);
  375. pfn = (FAULT_FN)(DWORD_PTR)rgc;
  376. fprintf(stderr, "Generating an invalid instruction exception\n");
  377. (*pfn)();
  378. fprintf(stderr, "Error: No exception thrown.\n");
  379. break;
  380. }
  381. case eftExNonCont:
  382. {
  383. fprintf(stderr, "Generating an non-continuable exception- **not implemented**\n");
  384. fprintf(stderr, "Error: No exception thrown.\n");
  385. break;
  386. }
  387. case eftExBadRet:
  388. {
  389. fprintf(stderr, "Generating an bad exception filter exception- **not implemented**\n");
  390. fprintf(stderr, "Error: No exception thrown.\n");
  391. break;
  392. }
  393. }
  394. }
  395. // ***************************************************************************
  396. int __cdecl main(int argc, char **argv)
  397. {
  398. EFaultType eft = eftAV;
  399. BOOL fCheckDebug = FALSE;
  400. BOOL fUseTry = FALSE;
  401. BOOL fUseFilter = FALSE;
  402. if (argc >= 3 && (argv[2][0] == '/' || argv[2][0] == '-'))
  403. {
  404. switch(argv[2][1])
  405. {
  406. case 't':
  407. case 'T':
  408. if (argv[2][2] == 'D' || argv[2][2] == 'd')
  409. g_fDebug = TRUE;
  410. fUseTry = TRUE;
  411. break;
  412. case 'g':
  413. case 'G':
  414. if (argv[2][2] == 'D' || argv[2][2] == 'd')
  415. g_fDebug = TRUE;
  416. fUseFilter = TRUE;
  417. break;
  418. }
  419. }
  420. if (argc >= 2 && (argv[1][0] == '/' || argv[1][0] == '-'))
  421. {
  422. switch(argv[1][1])
  423. {
  424. case 't':
  425. case 'T':
  426. if (argv[1][2] == 'D' || argv[1][2] == 'd')
  427. g_fDebug = TRUE;
  428. fUseTry = TRUE;
  429. break;
  430. case 'g':
  431. case 'G':
  432. if (argv[1][2] == 'D' || argv[1][2] == 'd')
  433. g_fDebug = TRUE;
  434. fUseFilter = TRUE;
  435. break;
  436. // AV
  437. default:
  438. case 'a':
  439. case 'A':
  440. eft = eftAV;
  441. break;
  442. #ifndef _WIN64
  443. // array bounds
  444. case 'b':
  445. case 'B':
  446. eft = eftArrayBound;
  447. break;
  448. #endif
  449. #ifdef _WIN64
  450. // Misalignment
  451. case 'm':
  452. case 'M':
  453. eft = eftMisalign;
  454. break;
  455. #endif
  456. // Stack overflow
  457. case 's':
  458. case 'S':
  459. switch(argv[1][2])
  460. {
  461. default:
  462. case 'f':
  463. case 'F':
  464. eft = eftStackOverflowFunc;
  465. break;
  466. case 'a':
  467. case 'A':
  468. eft = eftStackOverflowAlloc;
  469. break;
  470. };
  471. break;
  472. // integer exceptions
  473. case 'i':
  474. case 'I':
  475. switch(argv[1][2])
  476. {
  477. default:
  478. case 'z':
  479. case 'Z':
  480. eft = eftIntDivZero;
  481. break;
  482. case 'o':
  483. case 'O':
  484. eft = eftIntOverflow;
  485. break;
  486. };
  487. break;
  488. // floating point exceptions
  489. case 'f':
  490. case 'F':
  491. switch(argv[1][2])
  492. {
  493. default:
  494. case 'z':
  495. case 'Z':
  496. eft = eftFltDivZero;
  497. break;
  498. case 'o':
  499. case 'O':
  500. eft = eftFltOverflow;
  501. break;
  502. case 'u':
  503. case 'U':
  504. eft = eftFltUnderflow;
  505. break;
  506. case 'S':
  507. case 's':
  508. eft = eftFltStack;
  509. break;
  510. case 'I':
  511. case 'i':
  512. eft = eftFltInexact;
  513. break;
  514. case 'D':
  515. case 'd':
  516. eft = eftFltDenormal;
  517. break;
  518. case 'N':
  519. case 'n':
  520. eft = eftFltInvalid;
  521. break;
  522. };
  523. break;
  524. // CPU instruction exceptions
  525. case 'n':
  526. case 'N':
  527. switch(argv[1][2])
  528. {
  529. default:
  530. case 'p':
  531. case 'P':
  532. eft = eftInstrPriv;
  533. break;
  534. case 'i':
  535. case 'I':
  536. eft = eftInstrBad;
  537. break;
  538. };
  539. break;
  540. case 'E':
  541. case 'e':
  542. switch(argv[1][2])
  543. {
  544. default:
  545. case 'n':
  546. case 'N':
  547. eft = eftExNonCont;
  548. break;
  549. case 'i':
  550. case 'I':
  551. eft = eftExBadRet;
  552. break;
  553. };
  554. break;
  555. // help
  556. case '?':
  557. ShowUsage();
  558. return 0;
  559. }
  560. }
  561. else
  562. {
  563. eft = eftAV;
  564. }
  565. if (fUseFilter)
  566. {
  567. fUseTry = FALSE;
  568. SetUnhandledExceptionFilter(MyFilter);
  569. }
  570. if (fUseTry)
  571. {
  572. __try
  573. {
  574. DoException(eft);
  575. }
  576. __except(MyFilter(GetExceptionInformation()))
  577. {
  578. }
  579. }
  580. else
  581. {
  582. DoException(eft);
  583. }
  584. return 0;
  585. }