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.

602 lines
16 KiB

  1. title "Miscellaneous Exception Handling"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; xcptmisc.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements miscellaneous routines that are required to
  13. ; support exception handling. Functions are provided to call an exception
  14. ; handler for an exception, call an exception handler for unwinding, get
  15. ; the caller's stack pointer, get the caller's frame pointer, get the
  16. ; caller's floating status, get the caller's processor state, get the
  17. ; caller's extended processor status, and get the current stack limits.
  18. ;
  19. ; Author:
  20. ;
  21. ; David N. Cutler (davec) 14-Aug-1989
  22. ;
  23. ; Environment:
  24. ;
  25. ; Any mode.
  26. ;
  27. ; Revision History:
  28. ;
  29. ; 6 April 90 bryanwi
  30. ;
  31. ; 386 version created
  32. ;
  33. ;--
  34. .386p
  35. .xlist
  36. include ks386.inc
  37. include callconv.inc ; calling convention macros
  38. .list
  39. ;
  40. ; Unwind flags.
  41. ;
  42. Unwind equ EXCEPTION_UNWINDING OR EXCEPTION_EXIT_UNWIND
  43. _TEXT$01 SEGMENT DWORD PUBLIC 'CODE'
  44. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  45. page
  46. subttl "Execute Handler for Exception"
  47. ;++
  48. ;
  49. ; EXCEPTION_DISPOSITION
  50. ; RtlpExecuteHandlerForException (
  51. ; IN PEXCEPTION_RECORD ExceptionRecord,
  52. ; IN PVOID EstablisherFrame,
  53. ; IN OUT PCONTEXT ContextRecord,
  54. ; IN OUT PVOID DispatcherContext,
  55. ; IN PEXCEPTION_ROUTINE ExceptionRoutine
  56. ; )
  57. ;
  58. ; Routine Description:
  59. ;
  60. ; This function allocates a call frame, stores the handler address and
  61. ; establisher frame pointer in the frame, establishes an exception
  62. ; handler, and then calls the specified exception handler as an exception
  63. ; handler. If a nested exception occurs, then the exception handler of
  64. ; of this function is called and the handler address and establisher
  65. ; frame pointer are returned to the exception dispatcher via the dispatcher
  66. ; context parameter. If control is returned to this routine, then the
  67. ; frame is deallocated and the disposition status is returned to the
  68. ; exception dispatcher.
  69. ;
  70. ; Arguments:
  71. ;
  72. ; ExceptionRecord (ebp+8) - Supplies a pointer to an exception record.
  73. ;
  74. ; EstablisherFrame (ebp+12) - Supplies the frame pointer of the establisher
  75. ; of the exception handler that is to be called.
  76. ;
  77. ; ContextRecord (ebp+16) - Supplies a pointer to a context record.
  78. ;
  79. ; DispatcherContext (ebp+20) - Supplies a pointer to the dispatcher context
  80. ; record.
  81. ;
  82. ; ExceptionRoutine (ebp+24) - supplies a pointer to the exception handler
  83. ; that is to be called.
  84. ;
  85. ; Return Value:
  86. ;
  87. ; The disposition value returned by the specified exception handler is
  88. ; returned as the function value.
  89. ;
  90. ;--
  91. cPublicProc _RtlpExecuteHandlerForException,5
  92. mov edx,offset FLAT:ExceptionHandler ; Set who to register
  93. jmp ExecuteHandler ; jump to common code
  94. stdENDP _RtlpExecuteHandlerForException
  95. page
  96. subttl "Execute Handler for Unwind"
  97. ;++
  98. ;
  99. ; EXCEPTION_DISPOSITION
  100. ; RtlpExecuteHandlerForUnwind (
  101. ; IN PEXCEPTION_RECORD ExceptionRecord,
  102. ; IN PVOID EstablisherFrame,
  103. ; IN OUT PCONTEXT ContextRecord,
  104. ; IN OUT PVOID DispatcherContext,
  105. ; IN PEXCEPTION_ROUTINE ExceptionRoutine
  106. ; )
  107. ;
  108. ; Routine Description:
  109. ;
  110. ; This function allocates a call frame, stores the handler address and
  111. ; establisher frame pointer in the frame, establishes an exception
  112. ; handler, and then calls the specified exception handler as an unwind
  113. ; handler. If a collided unwind occurs, then the exception handler of
  114. ; of this function is called and the handler address and establisher
  115. ; frame pointer are returned to the unwind dispatcher via the dispatcher
  116. ; context parameter. If control is returned to this routine, then the
  117. ; frame is deallocated and the disposition status is returned to the
  118. ; unwind dispatcher.
  119. ;
  120. ; Arguments:
  121. ;
  122. ; ExceptionRecord (ebp+8) - Supplies a pointer to an exception record.
  123. ;
  124. ; EstablisherFrame (ebp+12) - Supplies the frame pointer of the establisher
  125. ; of the exception handler that is to be called.
  126. ;
  127. ; ContextRecord (ebp+16) - Supplies a pointer to a context record.
  128. ;
  129. ; DispatcherContext (ebp+20) - Supplies a pointer to the dispatcher context
  130. ; record.
  131. ;
  132. ; ExceptionRoutine (ebp+24) - supplies a pointer to the exception handler
  133. ; that is to be called.
  134. ;
  135. ; Return Value:
  136. ;
  137. ; The disposition value returned by the specified exception handler is
  138. ; returned as the function value.
  139. ;
  140. ;--
  141. cPublicProc _RtlpExecuteHandlerForUnwind ,5
  142. mov edx,offset FLAT:UnwindHandler
  143. ;; N.B. - FALL into ExecuteHandler
  144. stdENDP _RtlpExecuteHandlerForUnwind
  145. ;
  146. ; ExecuteHandler is the common tail for RtlpExecuteHandlerForException
  147. ; and RtlpExecuteHandlerForUnwind - we clean up some registers so they don't
  148. ; leak through the handler, then call the real execute code.
  149. ;
  150. ; (edx) = handler (Exception or Unwind) address
  151. ;
  152. cPublicProc ExecuteHandler,5
  153. push ebx
  154. push esi
  155. push edi
  156. xor eax, eax
  157. xor ebx, ebx
  158. xor esi, esi
  159. xor edi, edi
  160. push [esp+32] ; ExceptionRoutine
  161. push [esp+32] ; DispatcherContext
  162. push [esp+32] ; ContextRecord
  163. push [esp+32] ; EstablisherFrame
  164. push [esp+32] ; ExceptionRecord
  165. call ExecuteHandler2
  166. pop edi
  167. pop esi
  168. pop ebx
  169. stdRET ExecuteHandler
  170. stdENDP ExecuteHandler
  171. ExceptionRecord equ [ebp+8]
  172. EstablisherFrame equ [ebp+12]
  173. ContextRecord equ [ebp+16]
  174. DispatcherContext equ [ebp+20]
  175. ExceptionRoutine equ [ebp+24]
  176. cPublicProc ExecuteHandler2,5
  177. push ebp
  178. mov ebp,esp
  179. push EstablisherFrame ; Save context of exception handler
  180. ; that we're about to call.
  181. .errnz ErrHandler-4
  182. push edx ; Set Handler address
  183. .errnz ErrNext-0
  184. push fs:PcExceptionList ; Set next pointer
  185. mov fs:PcExceptionList,esp ; Link us on
  186. ; Call the specified exception handler.
  187. push DispatcherContext
  188. push ContextRecord
  189. push EstablisherFrame
  190. push ExceptionRecord
  191. mov ecx,ExceptionRoutine
  192. call ecx
  193. mov esp,fs:PcExceptionList
  194. ; Don't clean stack here, code in front of ret will blow it off anyway
  195. ; Disposition is in eax, so all we do is deregister handler and return
  196. .errnz ErrNext-0
  197. pop fs:PcExceptionList
  198. mov esp,ebp
  199. pop ebp
  200. stdRET ExecuteHandler2
  201. stdENDP ExecuteHandler2
  202. page
  203. subttl "Local Exception Handler"
  204. ;++
  205. ;
  206. ; EXCEPTION_DISPOSITION
  207. ; ExceptionHandler (
  208. ; IN PEXCEPTION_RECORD ExceptionRecord,
  209. ; IN PVOID EstablisherFrame,
  210. ; IN OUT PCONTEXT ContextRecord,
  211. ; IN OUT PVOID DispatcherContext
  212. ; )
  213. ;
  214. ; Routine Description:
  215. ;
  216. ; This function is called when a nested exception occurs. Its function
  217. ; is to retrieve the establisher frame pointer and handler address from
  218. ; its establisher's call frame, store this information in the dispatcher
  219. ; context record, and return a disposition value of nested exception.
  220. ;
  221. ; Arguments:
  222. ;
  223. ; ExceptionRecord (exp+4) - Supplies a pointer to an exception record.
  224. ;
  225. ; EstablisherFrame (esp+8) - Supplies the frame pointer of the establisher
  226. ; of this exception handler.
  227. ;
  228. ; ContextRecord (esp+12) - Supplies a pointer to a context record.
  229. ;
  230. ; DispatcherContext (esp+16) - Supplies a pointer to the dispatcher context
  231. ; record.
  232. ;
  233. ; Return Value:
  234. ;
  235. ; A disposition value ExceptionNestedException is returned if an unwind
  236. ; is not in progress. Otherwise a value of ExceptionContinueSearch is
  237. ; returned.
  238. ;
  239. ;--
  240. stdPROC ExceptionHandler,4
  241. mov ecx,dword ptr [esp+4] ; (ecx) -> ExceptionRecord
  242. test dword ptr [ecx.ErExceptionFlags],Unwind
  243. mov eax,ExceptionContinueSearch ; Assume unwind
  244. jnz eh10 ; unwind, go return
  245. ;
  246. ; Unwind is not in progress - return nested exception disposition.
  247. ;
  248. mov ecx,[esp+8] ; (ecx) -> EstablisherFrame
  249. mov edx,[esp+16] ; (edx) -> DispatcherContext
  250. mov eax,[ecx+8] ; (eax) -> EstablisherFrame for the
  251. ; handler active when we
  252. ; nested.
  253. mov [edx],eax ; Set DispatcherContext field.
  254. mov eax,ExceptionNestedException
  255. eh10: stdRET ExceptionHandler
  256. stdENDP ExceptionHandler
  257. page
  258. subttl "Local Unwind Handler"
  259. ;++
  260. ;
  261. ; EXCEPTION_DISPOSITION
  262. ; UnwindHandler (
  263. ; IN PEXCEPTION_RECORD ExceptionRecord,
  264. ; IN PVOID EstablisherFrame,
  265. ; IN OUT PCONTEXT ContextRecord,
  266. ; IN OUT PVOID DispatcherContext
  267. ; )
  268. ;
  269. ; Routine Description:
  270. ;
  271. ; This function is called when a collided unwind occurs. Its function
  272. ; is to retrieve the establisher frame pointer and handler address from
  273. ; its establisher's call frame, store this information in the dispatcher
  274. ; context record, and return a disposition value of nested unwind.
  275. ;
  276. ; Arguments:
  277. ;
  278. ; ExceptionRecord (esp+4) - Supplies a pointer to an exception record.
  279. ;
  280. ; EstablisherFrame (esp+8) - Supplies the frame pointer of the establisher
  281. ; of this exception handler.
  282. ;
  283. ; ContextRecord (esp+12) - Supplies a pointer to a context record.
  284. ;
  285. ; DispatcherContext (esp+16) - Supplies a pointer to the dispatcher context
  286. ; record.
  287. ;
  288. ; Return Value:
  289. ;
  290. ; A disposition value ExceptionCollidedUnwind is returned if an unwind is
  291. ; in progress. Otherwise a value of ExceptionContinueSearch is returned.
  292. ;
  293. ;--
  294. stdPROC UnwindHandler,4
  295. mov ecx,dword ptr [esp+4] ; (ecx) -> ExceptionRecord
  296. test dword ptr [ecx.ErExceptionFlags],Unwind
  297. mov eax,ExceptionContinueSearch ; Assume NOT unwind
  298. jz uh10 ; not unwind, go return
  299. ;
  300. ; Unwind is in progress - return collided unwind disposition.
  301. ;
  302. mov ecx,[esp+8] ; (ecx) -> EstablisherFrame
  303. mov edx,[esp+16] ; (edx) -> DispatcherContext
  304. mov eax,[ecx+8] ; (eax) -> EstablisherFrame for the
  305. ; handler active when we
  306. ; nested.
  307. mov [edx],eax ; Set DispatcherContext field.
  308. mov eax,ExceptionCollidedUnwind
  309. uh10: stdRET UnwindHandler
  310. stdENDP UnwindHandler
  311. page
  312. subttl "Unlink Exception Registration Record & Handler"
  313. ;++
  314. ;
  315. ; VOID
  316. ; RtlpUnlinkHandler(PEXCEPTION_REGISTRATION_RECORD UnlinkPointer)
  317. ;
  318. ; Routine Description:
  319. ;
  320. ; This function removes the specified exception registration record
  321. ; (and thus the relevent handler) from the exception traversal
  322. ; chain.
  323. ;
  324. ; Arguments:
  325. ;
  326. ; UnlinkPointer (esp+4) - Address of registration record to unlink.
  327. ;
  328. ; Return Value:
  329. ;
  330. ; The caller's return address.
  331. ;
  332. ;--
  333. cPublicProc _RtlpUnlinkHandler ,1
  334. mov ecx,dword ptr [esp+4]
  335. mov ecx,[ecx.ErrNext]
  336. mov fs:PcExceptionList,ecx
  337. stdRET _RtlpUnlinkHandler
  338. stdENDP _RtlpUnlinkHandler
  339. page
  340. subttl "Capture Context"
  341. ;++
  342. ;
  343. ; VOID
  344. ; RtlCaptureContext (PCONTEXT ContextRecord)
  345. ; RtlpCaptureContext (PCONTEXT ContextRecord)
  346. ;
  347. ; Routine Description:
  348. ;
  349. ; This fucntion fills in the specified context record with the
  350. ; current state of the machine, except that the values of EBP
  351. ; and ESP are computed to be those of the caller's caller.
  352. ;
  353. ; N.B. This function assumes it is called from a 'C' procedure with
  354. ; the old ebp at [ebp], the return address at [ebp+4], and
  355. ; old esp = ebp + 8.
  356. ;
  357. ; Certain 'C' optimizations may cause this to not be true.
  358. ;
  359. ; N.B. This function does NOT adjust ESP to pop the arguments off
  360. ; the caller's stack. In other words, it provides a __cdecl ESP,
  361. ; NOT a __stdcall ESP. This is mainly because we can't figure
  362. ; out how many arguments the caller takes.
  363. ;
  364. ; N.B. Floating point state is NOT captured.
  365. ;
  366. ; RtlpCaptureContext does not capture volitales.
  367. ; RtlCaptureContext captures volitales.
  368. ;
  369. ; Arguments:
  370. ;
  371. ; ContextRecord (esp+4) - Address of context record to fill in.
  372. ;
  373. ; Return Value:
  374. ;
  375. ; The caller's return address.
  376. ;
  377. ;--
  378. cPublicProc _RtlCaptureContext ,1
  379. push ebx
  380. mov ebx,[esp+8] ; (ebx) -> ContextRecord
  381. mov dword ptr [ebx.CsEax],eax
  382. mov dword ptr [ebx.CsEcx],ecx
  383. mov dword ptr [ebx.CsEdx],edx
  384. mov eax, [esp]
  385. mov dword ptr [ebx.CsEbx],eax
  386. mov dword ptr [ebx.CsEsi],esi
  387. mov dword ptr [ebx.CsEdi],edi
  388. jmp RtlpCaptureCommon
  389. stdENDP _RtlCaptureContext
  390. cPublicProc _RtlpCaptureContext ,1
  391. push ebx
  392. mov ebx,[esp+8] ; (ebx) -> ContextRecord
  393. mov dword ptr [ebx.CsEax],0
  394. mov dword ptr [ebx.CsEcx],0
  395. mov dword ptr [ebx.CsEdx],0
  396. mov dword ptr [ebx.CsEbx],0
  397. mov dword ptr [ebx.CsEsi],0
  398. mov dword ptr [ebx.CsEdi],0
  399. RtlpCaptureCommon:
  400. mov [ebx.CsSegCs],cs
  401. mov [ebx.CsSegDs],ds
  402. mov [ebx.CsSegEs],es
  403. mov [ebx.CsSegFs],fs
  404. mov [ebx.CsSegGs],gs
  405. mov [ebx.CsSegSs],ss
  406. pushfd
  407. pop [ebx.CsEflags]
  408. mov eax,[ebp+4]
  409. mov [ebx.CsEip],eax
  410. mov eax,[ebp]
  411. mov [ebx.CsEbp],eax
  412. lea eax,[ebp+8]
  413. mov [ebx.CsEsp],eax
  414. pop ebx
  415. stdRET _RtlpCaptureContext
  416. stdENDP _RtlpCaptureContext
  417. page
  418. subttl "Capture Context (private)"
  419. ;++
  420. ;
  421. ; VOID
  422. ; RtlCaptureContext (PCONTEXT ContextRecord)
  423. ;
  424. ; Routine Description:
  425. ;
  426. ; This function is similiar too RtlpCaptureContext expect that
  427. ; volitales are captured as well.
  428. ;
  429. ; This fucntion fills in the specified context record with the
  430. ; current state of the machine, except that the values of EBP
  431. ; and ESP are computed to be those of the caller's caller.
  432. ;
  433. ; N.B. This function does NOT adjust ESP to pop the arguments off
  434. ; the caller's stack. In other words, it provides a __cdecl ESP,
  435. ; NOT a __stdcall ESP. This is mainly because we can't figure
  436. ; out how many arguments the caller takes.
  437. ;
  438. ; N.B. Floating point state is NOT captured.
  439. ;
  440. ; Arguments:
  441. ;
  442. ; ContextRecord (esp+4) - Address of context record to fill in.
  443. ;
  444. ; Return Value:
  445. ;
  446. ; The caller's return address.
  447. ;
  448. ;--
  449. ifndef WX86_i386
  450. page
  451. subttl "Get Stack Limits"
  452. ;++
  453. ;
  454. ; VOID
  455. ; RtlpGetStackLimits (
  456. ; OUT PULONG LowLimit,
  457. ; OUT PULONG HighLimit
  458. ; )
  459. ;
  460. ; Routine Description:
  461. ;
  462. ; This function returns the current stack limits based on the current
  463. ; processor mode.
  464. ;
  465. ; On the 386 we always store the stack limits in the PCR, and address
  466. ; both PCR and TEB the same way, so this code is mode independent.
  467. ;
  468. ; Arguments:
  469. ;
  470. ; LowLimit (esp+4) - Supplies a pointer to a variable that is to receive
  471. ; the low limit of the stack.
  472. ;
  473. ; HighLimit (esp+8) - Supplies a pointer to a variable that is to receive
  474. ; the high limit of the stack.
  475. ;
  476. ; Return Value:
  477. ;
  478. ; None.
  479. ;
  480. ;--
  481. cPublicProc _RtlpGetStackLimits ,2
  482. ;cPublicFpo 2,0
  483. mov eax,fs:PcStackLimit
  484. mov ecx,[esp+4]
  485. mov [ecx],eax ; Save low limit
  486. mov eax,fs:PcInitialStack
  487. mov ecx,[esp+8]
  488. mov [ecx],eax ; Save high limit
  489. stdRET _RtlpGetStackLimits
  490. stdENDP _RtlpGetStackLimits
  491. endif
  492. page
  493. subttl "Get Exception Registration List Head"
  494. ;++
  495. ;
  496. ; PVOID
  497. ; RtlpGetRegistrationHead()
  498. ;
  499. ; Routine Description:
  500. ;
  501. ; This function returns the address of the first Exception
  502. ; registration record for the current context.
  503. ;
  504. ; Arguments:
  505. ;
  506. ; None.
  507. ;
  508. ; Return Value:
  509. ;
  510. ; The address of the first registration record.
  511. ;
  512. ;--
  513. cPublicProc _RtlpGetRegistrationHead ,0
  514. ;cPublicFpo 0,0
  515. mov eax,fs:PcExceptionList
  516. stdRET _RtlpGetRegistrationHead
  517. stdENDP _RtlpGetRegistrationHead
  518. _TEXT$01 ends
  519. end