Leaked source code of windows server 2003
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.

492 lines
14 KiB

  1. // TITLE("Miscellaneous Exception Handling")
  2. //++
  3. //
  4. // Module Name:
  5. //
  6. // xcptmisc.s
  7. //
  8. // Abstract:
  9. //
  10. // This module implements miscellaneous routines that are required to
  11. // support exception handling. Functions are provided to call an exception
  12. // handler for an exception, call an exception handler for unwinding, call
  13. // an exception filter, and call a termination handler.
  14. //
  15. // Author:
  16. //
  17. // William K. Cheung (wcheung) 15-Jan-1996
  18. //
  19. // based on the version by David N. Cutler (davec) 12-Sep-1990
  20. //
  21. // Environment:
  22. //
  23. // Any mode.
  24. //
  25. // Revision History:
  26. //
  27. // Updated to EAS2.1
  28. //
  29. //--
  30. #include "ksia64.h"
  31. .file "xcptmisc.s"
  32. //++
  33. //
  34. // EXCEPTION_DISPOSITION
  35. // RtlpExceptionHandler (
  36. // IN PEXCEPTION_RECORD ExceptionRecord,
  37. // IN FRAME_POINTERS EstablisherFrame,
  38. // IN OUT PCONTEXT ContextRecord,
  39. // IN OUT PDISPATCHER_CONTEXT DispatcherContext
  40. // )
  41. //
  42. // Routine Description:
  43. //
  44. // This function is called when a nested exception occurs. Its function
  45. // is to retrieve the establisher frame pointer from its establisher's
  46. // call frame, store this information in the dispatcher context record,
  47. // and return a disposition value of nested exception.
  48. //
  49. // Arguments:
  50. //
  51. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  52. //
  53. // EstablisherFrame (a1,a2) - Supplies the memory stack and backing store
  54. // frame pointers of the establisher of this exception handler.
  55. //
  56. // ContextRecord (a3) - Supplies a pointer to a context record.
  57. //
  58. // DispatcherContext (a4) - Supplies a pointer to the dispatcher context
  59. // record.
  60. //
  61. // Return Value:
  62. //
  63. // A disposition value ExceptionNestedException is returned if an unwind
  64. // is not in progress. Otherwise a value of ExceptionContinueSearch is
  65. // returned.
  66. //
  67. //--
  68. LEAF_ENTRY(RtlpExceptionHandler)
  69. //
  70. // register aliases
  71. //
  72. pUwnd = pt0
  73. pNot = pt1
  74. //
  75. // Check if unwind is in progress.
  76. //
  77. add t0 = ErExceptionFlags, a0
  78. ;;
  79. ld4.nt1 t0 = [t0]
  80. mov t1 = EXCEPTION_UNWIND
  81. ;;
  82. add t3 = -8, a1
  83. and t0 = t0, t1
  84. add t2 = DcEstablisherFrame, a4
  85. ;;
  86. ld8.nt1 t4 = [t3] // get dispatcher context addr
  87. cmp4.ne pUwnd, pNot = zero, t0 // if ne, unwind in progress
  88. ;;
  89. (pNot) add t5 = DcEstablisherFrame, t4
  90. ;;
  91. //
  92. // If unwind is not in progress - return nested exception disposition.
  93. // And copy the establisher frame pointer structure (i.e. FRAME_POINTERS)
  94. // to the current dispatcher context.
  95. //
  96. // Otherwise, return continue search disposition
  97. //
  98. (pNot) ld8.nt1 t6 = [t5], 8
  99. (pNot) mov v0 = ExceptionNestedException // set disposition value
  100. (pUwnd) mov v0 = ExceptionContinueSearch // set disposition value
  101. ;;
  102. (pNot) ld8.nt1 t7 = [t5]
  103. (pNot) st8 [t2] = t6, 8
  104. nop.i 0
  105. ;;
  106. (pNot) st8 [t2] = t7
  107. nop.m 0
  108. br.ret.sptk.clr brp
  109. ;;
  110. LEAF_EXIT(RtlpExceptionHandler)
  111. //++
  112. //
  113. // EXCEPTION_DISPOSITION
  114. // RtlpExecuteEmHandlerForException (
  115. // IN PEXCEPTION_RECORD ExceptionRecord,
  116. // IN ULONGLONG MemoryStack,
  117. // IN ULONGLONG BackingStore,
  118. // IN OUT PCONTEXT ContextRecord,
  119. // IN OUT PDISPATCHER_CONTEXT DispatcherContext,
  120. // IN ULONGLONG GlobalPointer,
  121. // IN PEXCEPTION_ROUTINE ExceptionRoutine
  122. // )
  123. //
  124. // Routine Description:
  125. //
  126. // This function stores the establisher's dispatcher context in the stack
  127. // scratch area, establishes an exception handler, and then calls
  128. // the specified exception handler as an exception handler. If a nested
  129. // exception occurs, then the exception handler of this function is called
  130. // and the establisher frame pointer in the saved dispatcher context
  131. // is returned to the exception dispatcher via the dispatcher context
  132. // parameter of this function's exception handler. If control is returned
  133. // to this routine, then the disposition status is returned to the
  134. // exception dispatcher.
  135. //
  136. // Arguments:
  137. //
  138. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  139. //
  140. // MemoryStack (a1) - Supplies the memory stack frame pointer of the
  141. // activation record whose exception handler is to be called.
  142. //
  143. // BackingStore (a2) - Supplies the backing store pointer of the
  144. // activation record whose exception handler is to be called.
  145. //
  146. // ContextRecord (a3) - Supplies a pointer to a context record.
  147. //
  148. // DispatcherContext (a4) - Supplies a pointer to the dispatcher context
  149. // record.
  150. //
  151. // GlobalPointer (a5) - Supplies the global pointer value of the module
  152. // to which the function belongs.
  153. //
  154. // ExceptionRoutine (a6) - supplies a pointer to the exception handler
  155. // that is to be called.
  156. //
  157. // Return Value:
  158. //
  159. // The disposition value returned by the specified exception handler is
  160. // returned as the function value.
  161. //
  162. //--
  163. NESTED_ENTRY_EX(RtlpExecuteEmHandlerForException,RtlpExceptionHandler)
  164. //
  165. // register aliases
  166. //
  167. rpT0 = t8
  168. rpT1 = t9
  169. .prologue
  170. .fframe 32, tg30
  171. alloc t1 = ar.pfs, 0, 0, 7, 0
  172. mov t0 = brp
  173. mov rpT0 = sp
  174. add rpT1 = 8, sp
  175. [tg30:] add sp = -32, sp
  176. ;;
  177. .savesp rp, 32
  178. st8 [rpT0] = t0, -8 // save brp
  179. .savesp ar.pfs, 32+8
  180. st8 [rpT1] = t1, 8 // save pfs
  181. ;;
  182. PROLOGUE_END
  183. //
  184. // Setup global pointer and branch register for the except handler
  185. //
  186. ld8 t2 = [a6], PlGlobalPointer - PlEntryPoint
  187. st8.nta [rpT0] = a4 // save dispatcher context addr
  188. ;;
  189. ld8 gp = [a6]
  190. mov bt0 = t2
  191. br.call.sptk.many brp = bt0 // call except handler
  192. //
  193. // Save swizzled dispatcher context address onto the stack
  194. //
  195. .restore tg40
  196. [tg40:] add sp = 32, sp // deallocate stack frame
  197. ;;
  198. ld8.nt1 t0 = [sp]
  199. add rpT1 = 8, sp
  200. ;;
  201. ld8.nt1 t1 = [rpT1]
  202. nop.f 0
  203. mov brp = t0 // restore return branch
  204. ;;
  205. nop.m 0
  206. mov ar.pfs = t1 // restore pfs
  207. br.ret.sptk.clr brp // return
  208. NESTED_EXIT(RtlpExecuteEmHandlerForException)
  209. //++
  210. //
  211. // EXCEPTION_DISPOSITION
  212. // RtlpEmUnwindHandler (
  213. // IN PEXCEPTION_RECORD ExceptionRecord,
  214. // IN FRAME_POINTERS EstablisherFrame,
  215. // IN OUT PCONTEXT ContextRecord,
  216. // IN OUT PVOID DispatcherContext
  217. // )
  218. //
  219. // Routine Description:
  220. //
  221. // This function is called when a collided unwind occurs. Its function
  222. // is to retrieve the establisher dispatcher context, copy it to the
  223. // current dispatcher context, and return a disposition value of nested
  224. // unwind.
  225. //
  226. // Arguments:
  227. //
  228. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  229. //
  230. // EstablisherFrame (a1,a2) - Supplies the memory stack and backing store
  231. // frame pointers of the establisher of this exception handler.
  232. //
  233. // ContextRecord (a3) - Supplies a pointer to a context record.
  234. //
  235. // DispatcherContext (a4) - Supplies a pointer to the dispatcher context
  236. // record.
  237. //
  238. // Return Value:
  239. //
  240. // A disposition value ExceptionCollidedUnwind is returned if an unwind is
  241. // in progress. Otherwise, a value of ExceptionContinueSearch is returned.
  242. //
  243. //--
  244. LEAF_ENTRY(RtlpEmUnwindHandler)
  245. //
  246. // register aliases
  247. //
  248. pUwnd = pt0
  249. pNot = pt1
  250. //
  251. // Check if unwind is in progress.
  252. //
  253. add t0 = ErExceptionFlags, a0
  254. ;;
  255. ld4.nt1 t0 = [t0]
  256. mov t1 = EXCEPTION_UNWIND
  257. ;;
  258. and t0 = t0, t1
  259. ;;
  260. cmp4.eq pNot, pUwnd = zero, t0 // if eq, unwind not in progress
  261. (pNot) br.cond.sptk Ruh10
  262. add t2 = -8, a1
  263. add t1 = 8, a4 // -> target dispatch context+8
  264. ;;
  265. ld8.nt1 t2 = [t2] // -> source dispatch context
  266. ;;
  267. add t3 = 8, t2 // -> source dispatch context+8
  268. nop.i 0
  269. ;;
  270. //
  271. // Copy the establisher dispatcher context (i.e. DISPATCHER_CONTEXT) contents
  272. // to the current dispatcher context.
  273. //
  274. ld8 t6 = [t2], 16
  275. ld8 t7 = [t3], 16
  276. nop.i 0
  277. ;;
  278. ld8 t8 = [t2], 16
  279. ld8 t9 = [t3], 16
  280. nop.i 0
  281. ;;
  282. st8 [a4] = t6, 16
  283. st8 [t1] = t7, 16
  284. nop.i 0
  285. ld8 t10 = [t2], 16
  286. ld8 t11 = [t3], 16
  287. nop.i 0
  288. ;;
  289. ld8 t12 = [t2], 16
  290. ld8 t13 = [t3]
  291. nop.i 0
  292. ;;
  293. st8 [a4] = t8, 16
  294. st8 [t1] = t9, 16
  295. mov v0 = ExceptionCollidedUnwind // set disposition value
  296. ;;
  297. ld8 t8 = [t2]
  298. st8 [a4] = t10, 16
  299. st8 [t1] = t11, 16
  300. nop.i 0
  301. ;;
  302. st8 [a4] = t12, 16
  303. st8 [t1] = t13
  304. ;;
  305. st8 [a4] = t8
  306. br.ret.sptk.clr brp // return
  307. ;;
  308. Ruh10:
  309. //
  310. // If branched to here,
  311. // unwind is not in progress - return continue search disposition.
  312. //
  313. nop.m 0
  314. (pNot) mov v0 = ExceptionContinueSearch // set disposition value
  315. br.ret.sptk.clr brp // return
  316. LEAF_EXIT(RtlpEmUnwindHandler)
  317. //++
  318. //
  319. // EXCEPTION_DISPOSITION
  320. // RtlpExecuteEmHandlerForUnwind (
  321. // IN PEXCEPTION_RECORD ExceptionRecord,
  322. // IN ULONGLONG MemoryStack,
  323. // IN ULONGLONG BackingStore,
  324. // IN OUT PCONTEXT ContextRecord,
  325. // IN OUT PVOID DispatcherContext,
  326. // IN ULONGLONG GlobalPointer,
  327. // IN PEXCEPTION_ROUTINE ExceptionRoutine
  328. // )
  329. //
  330. // Routine Description:
  331. //
  332. // This function allocates a call frame, stores the establisher frame
  333. // pointer and the context record address in the frame, establishes an
  334. // exception handler, and then calls the specified exception handler as
  335. // an unwind handler. If a collided unwind occurs, then the exception
  336. // handler of of this function is called and the establisher frame pointer
  337. // and context record address are returned to the unwind dispatcher via
  338. // the dispatcher context parameter. If control is returned to this routine,
  339. // then the frame is deallocated and the disposition status is returned to
  340. // the unwind dispatcher.
  341. //
  342. // Arguments:
  343. //
  344. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  345. //
  346. // MemoryStack (a1) - Supplies the memory stack frame pointer of the
  347. // activation record whose exception handler is to be called.
  348. //
  349. // BackingStore (a2) - Supplies the backing store pointer of the
  350. // activation record whose exception handler is to be called.
  351. //
  352. // ContextRecord (a3) - Supplies a pointer to a context record.
  353. //
  354. // DispatcherContext (a4) - Supplies a pointer to the dispatcher context
  355. // record.
  356. //
  357. // GlobalPointer (a5) - Supplies the global pointer value of the module
  358. // to which the function belongs.
  359. //
  360. // ExceptionRoutine (a6) - supplies a pointer to the exception handler
  361. // that is to be called.
  362. //
  363. // Return Value:
  364. //
  365. // The disposition value returned by the specified exception handler is
  366. // returned as the function value.
  367. //
  368. //--
  369. NESTED_ENTRY_EX(RtlpExecuteEmHandlerForUnwind, RtlpEmUnwindHandler)
  370. //
  371. // register aliases
  372. //
  373. .prologue
  374. .fframe 32, tg10
  375. rpT0 = t8
  376. rpT1 = t9
  377. alloc t1 = ar.pfs, 0, 0, 7, 0
  378. mov t0 = brp
  379. mov rpT0 = sp
  380. add rpT1 = 8, sp
  381. [tg10:] add sp = -32, sp
  382. ;;
  383. .savepsp rp, 0
  384. st8 [rpT0] = t0, -8 // save brp
  385. .savepsp ar.pfs, -8
  386. st8 [rpT1] = t1, 8 // save pfs
  387. ;;
  388. PROLOGUE_END
  389. //
  390. // Setup global pointer and branch register for the except handler
  391. //
  392. ld8 t2 = [a6], PlGlobalPointer - PlEntryPoint
  393. st8.nta [rpT0] = a4 // save dispatcher context addr
  394. ;;
  395. ld8 gp = [a6]
  396. mov bt0 = t2
  397. (p0) br.call.sptk.many brp = bt0 // call except handler
  398. //
  399. // Save swizzled dispatcher context address onto the stack
  400. //
  401. .restore tg20
  402. [tg20:] add sp = 32, sp // deallocate stack frame
  403. ;;
  404. ld8.nt1 t0 = [sp]
  405. add rpT1 = 8, sp
  406. ;;
  407. ld8.nt1 t1 = [rpT1]
  408. nop.f 0
  409. mov brp = t0 // restore return branch
  410. ;;
  411. nop.m 0
  412. mov ar.pfs = t1 // restore pfs
  413. br.ret.sptk.clr brp // return
  414. ;;
  415. NESTED_EXIT(RtlpExecuteEmHandlerForUnwind)