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.

288 lines
9.5 KiB

  1. ;***
  2. ;exsup3.asm
  3. ;
  4. ; Copyright (c) 1994-1997, Microsoft Corporation. All rights reserved.
  5. ;
  6. ;Purpose:
  7. ; Exception handling for i386. This is just the C9.0 version of
  8. ; the language-specific exception handler. The C8.0 version is
  9. ; found in exsup2.asm, and the routines common to both C8 and C9
  10. ; are found in exsup.asm.
  11. ;
  12. ;Notes:
  13. ;
  14. ;Revision History:
  15. ; 01-10-94 PML Create VC/C++ 2.0 (C9.0) version from C8.0 original
  16. ; 01-11-95 SKS Remove MASM 5.X support
  17. ; 04-18-95 JWM Added NLG support
  18. ; 06-07-95 JWM __SetNLGCode() used, for multithread safety.
  19. ; 06-20-95 JWM __SetNLGCode() removed, code passed on stack (11803).
  20. ;
  21. ;*******************************************************************************
  22. ;hnt = -D_WIN32 -Dsmall32 -Dflat32 -Mx $this;
  23. ;Define small32 and flat32 since these are not defined in the NT build process
  24. small32 equ 1
  25. flat32 equ 1
  26. .xlist
  27. include pversion.inc
  28. ?DFDATA = 1
  29. ?NODATA = 1
  30. include cmacros.inc
  31. include exsup.inc
  32. .list
  33. ;REVIEW: can we get rid of _global_unwind2, and just use
  34. ; the C runtimes version, _global_unwind?
  35. extrn __global_unwind2:near
  36. extrn __local_unwind2:near
  37. ;extrn __NLG_Notify:near
  38. ;typedef struct _EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION;
  39. ;struct _EXCEPTION_REGISTRATION{
  40. ;/* _esp, xpointers at negative offset */
  41. ; int _esp;
  42. ; PEXCEPTION_POINTERS xpointers;
  43. ; struct _EXCEPTION_REGISTRATION *prev;
  44. ; void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION, PCONTEXT, PEXCEPTION_RECORD);
  45. ; struct scopetable_entry *scopetable;
  46. ; int trylevel;
  47. ;};
  48. ;private (at negative offsets from node ptr)
  49. _esp = -8
  50. xpointers = -4
  51. _C9_EXCEPTION_REGISTRATION struc ; C9.0 version
  52. ;public:
  53. dd ? ; prev (common)
  54. dd ? ; handler (common)
  55. ;private:
  56. scopetable dd ?
  57. trylevel dd ?
  58. _C9_EXCEPTION_REGISTRATION ends
  59. FRAME_EBP_OFFSET equ 16
  60. ;#define EXCEPTION_MAXIMUM_PARAMETERS 4
  61. ;typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
  62. ;typedef EXCEPTION_RECORD *PEXCEPTION_RECORD;
  63. ;struct _EXCEPTION_RECORD{
  64. ; NTSTATUS ExceptionCode;
  65. ; ULONG ExceptionFlags;
  66. ; struct _EXCEPTION_RECORD *ExceptionRecord;
  67. ; PVOID ExceptionAddress;
  68. ; ULONG NumberParameters;
  69. ; ULONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
  70. ;};
  71. _EXCEPTION_RECORD struc
  72. exception_number dd ?
  73. exception_flags dd ?
  74. exception_record dd ?
  75. exception_address dd ?
  76. number_parameters dd ?
  77. exception_information dd 4 dup(?)
  78. _EXCEPTION_RECORD ends
  79. SIZEOF_EXCEPTION_RECORD equ 36
  80. ;/* following is the structure returned by the _exception_info() intrinsic. */
  81. ;typedef struct _EXCEPTION_POINTERS EXCEPTION_POINTERS;
  82. ;typedef struct EXCEPTION_POINTERS *PEXCEPTION_POINTERS;
  83. ;struct _EXCEPTION_POINTERS{
  84. ; PEXCEPTION_RECORD ExceptionRecord;
  85. ; PCONTEXT Context;
  86. ;};
  87. _EXCEPTION_POINTERS struc
  88. ep_xrecord dd ?
  89. ep_context dd ?
  90. _EXCEPTION_POINTERS ends
  91. SIZEOF_EXCEPTION_POINTERS equ 8
  92. ;extern __NLG_Destination:_NLG_INFO
  93. assumes DS,DATA
  94. assumes FS,DATA
  95. __except_list equ 0
  96. ;struct _SCOPETABLE_ENTRY{
  97. ; int enclosing_level; /* lexical level of enclosing scope */
  98. ; int (*filter)(PEXCEPTION_RECORD); /* NULL for a termination handler */
  99. ; void (*specific_handler)(void); /* xcpt or termination handler */
  100. ;};
  101. ;struct _SCOPETABLE_ENTRY Scopetable[NUMTRYS];
  102. _SCOPETABLE_ENTRY struc
  103. enclosing_level dd ?
  104. filter dd ?
  105. specific_handler dd ?
  106. _SCOPETABLE_ENTRY ends
  107. BeginCODE
  108. ;EXTERN C __SetNLGCode:near
  109. ;/* _EXCEPT_HANDLER3 - Try to find an exception handler listed in the scope
  110. ; * table associated with the given registration record, that wants to accept
  111. ; * the current exception. If we find one, run it (and never return).
  112. ; * RETURNS: (*if* it returns)
  113. ; * DISPOSITION_DISMISS - dismiss the exception.
  114. ; * DISPOSITION_CONTINUE_SEARCH - pass the exception up to enclosing handlers
  115. ; */
  116. ;int _except_handler3(
  117. ; PEXCEPTION_RECORD exception_record,
  118. ; PEXCEPTION_REGISTRATION registration,
  119. ; PCONTEXT context,
  120. ; PEXCEPTION_REGISTRATION dispatcher)
  121. ;{
  122. ; int ix, filter_result;
  123. ;
  124. ; for(ix=registration->trylevel; ix!=-1; ix=registration->xscope[ix].enclosing_level){
  125. ; /* if filter==NULL, then this is an entry for a termination handler */
  126. ; if(registration->xscope[ix].filter){
  127. ; /* NB: call to the filter may trash the callee save
  128. ; registers. (this is *not* a standard cdecl function) */
  129. ; filter_result=(*registration->xscope[ix].filter)(xinfo);
  130. ; if(filter_result==FILTER_DISMISS)
  131. ; return(-1); /* dismiss */
  132. ; if(filter_result==FILTER_ACCEPT){
  133. ; _global_unwind2(registration);
  134. ; _local_unwind2(registration, ix);
  135. ; (*registration->xscope[ix].specific_handler)(void);
  136. ; assert(UNREACHED); /*should never return from handler*/
  137. ; }
  138. ; assert(filter_result==FILTER_CONTINUE_SEARCH);
  139. ; }
  140. ; }
  141. ; return(0); /* didnt find one */
  142. ;}
  143. db 'VC20' ;; VC/C++ 2.0/32-bit (C9.0) version
  144. db 'XC00' ;; so debugger can recognize this proc (cuda:3936)
  145. cProc _except_handler3,<C,PUBLIC>,<IBX,ISI,IDI,IBP>
  146. parmDP xrecord
  147. parmDP registration
  148. parmDP context
  149. parmDP dispatcher
  150. localV xp,SIZEOF_EXCEPTION_POINTERS
  151. cBegin
  152. ;4*4b for callee saves + 4b return address + 4b param = 24
  153. ;DF in indeterminate state at time of exception, so clear it
  154. cld
  155. mov ebx, registration ;ebx= PEXCEPTION_REGISTRATION
  156. mov eax, xrecord
  157. test [eax.exception_flags], EXCEPTION_UNWIND_CONTEXT
  158. jnz _lh_unwinding
  159. ;build the EXCEPTION_POINTERS locally store its address in the
  160. ; registration record. this is the pointer that is returned by
  161. ; the _eception_info intrinsic.
  162. mov xp.ep_xrecord, eax
  163. mov eax, context
  164. mov xp.ep_context, eax
  165. lea eax, xp
  166. mov [ebx.xpointers], eax
  167. mov esi, [ebx.trylevel] ;esi= try level
  168. mov edi, [ebx.scopetable] ;edi= scope table base
  169. _lh_top:
  170. cmp esi, -1
  171. je short _lh_bagit
  172. lea ecx, [esi+esi*2] ;ecx= trylevel*3
  173. cmp dword ptr [(edi+ecx*4).filter], 0
  174. je short _lh_continue ;term handler, so keep looking
  175. ;filter may trash *all* registers, so save ebp and scopetable offset
  176. push esi
  177. push ebp
  178. lea ebp, FRAME_EBP_OFFSET[ebx]
  179. call [(edi+ecx*4).filter] ;call the filter
  180. pop ebp
  181. pop esi
  182. ;ebx may have been trashed by the filter, so we must reload
  183. mov ebx, registration
  184. ; Accept <0, 0, >0 instead of just -1, 0, +1
  185. or eax, eax
  186. jz short _lh_continue
  187. js short _lh_dismiss
  188. ;assert(eax==FILTER_ACCEPT)
  189. ;reload xscope base, cuz it was trashed by the filter call
  190. mov edi, [ebx.scopetable]
  191. ;load handler address before we loose components of address mode
  192. push ebx ;registration*
  193. call __global_unwind2 ;run term handlers
  194. add esp, 4
  195. ;setup ebp for the local unwinder and the specific handler
  196. lea ebp, FRAME_EBP_OFFSET[ebx]
  197. ;the stop try level == accepting except level
  198. push esi ;stop try level
  199. push ebx ;registration*
  200. call __local_unwind2
  201. add esp, 8
  202. lea ecx, [esi+esi*2] ;ecx=trylevel*3
  203. ; push 01h
  204. ; mov eax, [(edi+ecx*4).specific_handler]
  205. ; call __NLG_Notify
  206. ; set the current trylevel to our enclosing level immediately
  207. ; before giving control to the handler. it is the enclosing
  208. ; level, if any, that guards the handler.
  209. mov eax, [(edi+ecx*4).enclosing_level]
  210. mov [ebx.trylevel], eax
  211. call [(edi+ecx*4).specific_handler] ;call the except handler
  212. ;assert(0) ;(NB! should not return)
  213. _lh_continue:
  214. ;reload the scope table base, possibly trashed by call to filter
  215. mov edi, [ebx.scopetable]
  216. lea ecx, [esi+esi*2]
  217. mov esi, [edi+ecx*4+0] ;load the enclosing trylevel
  218. jmp short _lh_top
  219. _lh_dismiss:
  220. mov eax, DISPOSITION_DISMISS ;dismiss the exception
  221. jmp short _lh_return
  222. _lh_bagit:
  223. mov eax, DISPOSITION_CONTINUE_SEARCH
  224. jmp short _lh_return
  225. _lh_unwinding:
  226. push ebp
  227. lea ebp, FRAME_EBP_OFFSET[ebx]
  228. push -1
  229. push ebx
  230. call __local_unwind2
  231. add esp, 8
  232. pop ebp
  233. ;the return value is not really relevent in an unwind context
  234. mov eax, DISPOSITION_CONTINUE_SEARCH
  235. _lh_return:
  236. cEnd
  237. ;public __seh_longjmp_unwind@4
  238. ;__seh_longjmp_unwind@4 proc near
  239. ; push ebp
  240. ; mov ecx, 8[esp]
  241. ; mov ebp, [ecx.saved_ebp]
  242. ; mov eax, [ecx.saved_trylevel]
  243. ; push eax
  244. ; mov eax, [ecx.saved_xregistration]
  245. ; push eax
  246. ; call __local_unwind2
  247. ; add esp, 8
  248. ; pop ebp
  249. ; ret 4
  250. ;__seh_longjmp_unwind@4 endp
  251. EndCODE
  252. END