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.

313 lines
9.6 KiB

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