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.

302 lines
8.9 KiB

  1. ;***
  2. ;exsup.asm
  3. ;
  4. ; Copyright (c) 1993-2001, Microsoft Corporation. All rights reserved.
  5. ;
  6. ;Purpose:
  7. ; Exception handling for i386. This file contains those routines
  8. ; common to both C8.0 and C9.0.
  9. ;
  10. ;Notes:
  11. ;
  12. ;Revision History:
  13. ; 04-13-93 JWM setjmp(), longjmp() & raisex() moved to setjmp.asm;
  14. ; common data definitions moved to exsup.inc.
  15. ; 10-18-93 GJF Ensure direction flag is clear in _except_handler2
  16. ; 12-16-93 PML Accept <0,0,>0 from except filter, not just -1,0,+1
  17. ; 01-10-94 PML Moved C8-specific __except_handler2 to exsup2.inc.
  18. ; Only C8/C9 common routines left here.
  19. ; 01-20-94 GJF Gave _EXCEPTION_REGISTRATION a _COMMON suffix (fix
  20. ; from SteveWo).
  21. ; 02-10-94 GJF -1 is the end-of-exception-handler chain marker, not 0.
  22. ; 01-11-95 SKS Remove MASM 5.X support
  23. ; 04-18-95 JWM Added NLG support
  24. ; 04-21-95 JWM NLG routines moved from setjmp.asm, NLG data from
  25. ; frame.cpp.
  26. ; 04-25-95 JWM Added __NLG_Return2 label.
  27. ; 06-07-95 JWM NLG now multithread safe.
  28. ; 06-20-95 JWM dwCode passed on stack (11803).
  29. ; 07-11-95 JWM unwanted prologue removed from NLG_Notify (11803).
  30. ; 07-21-95 JWM Added new entry point, _NLG_Notify1 (16585).
  31. ; 03-09-01 PML Add FPO directives for proper callstacks (vs7#221754)
  32. ;
  33. ;*******************************************************************************
  34. ;hnt = -D_WIN32 -Dsmall32 -Dflat32 -Mx $this;
  35. ;Define small32 and flat32 since these are not defined in the NT build process
  36. small32 equ 1
  37. flat32 equ 1
  38. .xlist
  39. include pversion.inc
  40. ?DFDATA = 1
  41. ?NODATA = 1
  42. include cmacros.inc
  43. include exsup.inc
  44. .list
  45. ;REVIEW: can we get rid of _global_unwind2, and just use
  46. ; the C runtimes version, _global_unwind?
  47. ifndef _BUILD_DLL_LIB_
  48. extrn _RtlUnwind@16:near
  49. endif ; _BUILD_DLL_LIB_
  50. ;typedef struct _EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION;
  51. ;struct _EXCEPTION_REGISTRATION{
  52. ; struct _EXCEPTION_REGISTRATION *prev;
  53. ; void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION, PCONTEXT, PEXCEPTION_RECORD);
  54. ; struct scopetable_entry *scopetable;
  55. ; int trylevel;
  56. ;};
  57. _EXCEPTION_REGISTRATION_COMMON struc ; C8.0/C9.0 common only
  58. dd ? ; prev (OS-req, def'd in exsup.inc)
  59. dd ? ; handler (ditto)
  60. ;private:
  61. scopetable dd ? ; C8/C9 common
  62. trylevel dd ? ; C8/C9 common
  63. _EXCEPTION_REGISTRATION_COMMON ends
  64. ;#define EXCEPTION_MAXIMUM_PARAMETERS 4
  65. ;typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
  66. ;typedef EXCEPTION_RECORD *PEXCEPTION_RECORD;
  67. ;struct _EXCEPTION_RECORD{
  68. ; NTSTATUS ExceptionCode;
  69. ; ULONG ExceptionFlags;
  70. ; struct _EXCEPTION_RECORD *ExceptionRecord;
  71. ; PVOID ExceptionAddress;
  72. ; ULONG NumberParameters;
  73. ; ULONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
  74. ;};
  75. _EXCEPTION_RECORD struc
  76. exception_number dd ?
  77. exception_flags dd ?
  78. exception_record dd ?
  79. exception_address dd ?
  80. number_parameters dd ?
  81. exception_information dd 4 dup(?)
  82. _EXCEPTION_RECORD ends
  83. SIZEOF_EXCEPTION_RECORD equ 36
  84. assumes DS,DATA
  85. assumes FS,DATA
  86. public __except_list
  87. __except_list equ 0
  88. ;struct _SCOPETABLE_ENTRY{
  89. ; int enclosing_level; /* lexical level of enclosing scope */
  90. ; int (*filter)(PEXCEPTION_RECORD); /* NULL for a termination handler */
  91. ; void (*specific_handler)(void); /* xcpt or termination handler */
  92. ;};
  93. ;struct _SCOPETABLE_ENTRY Scopetable[NUMTRYS];
  94. _SCOPETABLE_ENTRY struc
  95. enclosing_level dd ?
  96. filter dd ?
  97. specific_handler dd ?
  98. _SCOPETABLE_ENTRY ends
  99. BeginDATA
  100. __NLG_Destination _NLG_INFO <>
  101. PUBLIC __NLG_Destination
  102. EndDATA
  103. BeginCODE
  104. ifndef _BUILD_DLL_LIB_
  105. ;NB: call to RtlUnwind appears to trash ebx! and possibly others so just
  106. ; to be safe, we save all callee save regs.
  107. cProc _global_unwind2,<C,PUBLIC>,<IBX,ISI,IDI,IBP>
  108. parmDP stop
  109. cBegin
  110. push 0 ; ReturnValue
  111. push 0 ; ExceptionRecord
  112. push offset flat:_gu_return ; TargetIp
  113. push stop ; TargetFrame
  114. call _RtlUnwind@16
  115. _gu_return:
  116. cEnd
  117. endif ; _BUILD_DLL_LIB_
  118. ;_unwind_handler(
  119. ; PEXCEPTION_RECORD xr,
  120. ; PREGISTRATION_RECORD establisher,
  121. ; PCONTEXT context,
  122. ; PREGISTRATION_RECORD dispatcher);
  123. ;
  124. ;this is a special purpose handler used to guard our local unwinder.
  125. ; its job is to catch collided unwinds.
  126. ;
  127. ;NB: this code is basically stolen from the NT routine xcptmisc.asm
  128. ; and is basically the same method used by the system unwinder (RtlUnwind).
  129. ;
  130. cProc _unwind_handler,<C>
  131. cBegin
  132. mov ecx, dword ptr [esp+4]
  133. test dword ptr [ecx.exception_flags], EXCEPTION_UNWIND_CONTEXT
  134. mov eax, DISPOSITION_CONTINUE_SEARCH
  135. jz short _uh_return
  136. ; We collide in a _local_unwind. We set the dispatched to the
  137. ; establisher just before the local handler so we can unwind
  138. ; any future local handlers.
  139. mov eax, [esp+8] ; Our establisher is the one
  140. ; in front of the local one
  141. mov edx, [esp+16]
  142. mov [edx], eax ; set dispatcher to local_unwind2
  143. mov eax, DISPOSITION_COLLIDED_UNWIND
  144. _uh_return:
  145. cEnd
  146. ;/* _LOCAL_UNWIND2 - run all termination handlers listed in the scope table
  147. ; * associated with the given registration record, from the current lexical
  148. ; * level through enclosing levels up to, but not including the given 'stop'
  149. ; * level.
  150. ; */
  151. ;void _local_unwind2(PEXCEPTION_REGISTRATION xr, int stop)
  152. ;{
  153. ; int ix;
  154. ;
  155. ; for(ix=xr->trylevel; ix!=-1 && ix!=stop; ix=xr->xscope[i].enclosing_level){
  156. ; /* NULL indicates that this entry is for a termination handler */
  157. ; if(xr->xscope[i].filter==NULL){
  158. ; /* NB: call to the termination handler may trash callee save regs */
  159. ; (*xr->xscope[i].specific_handler)();
  160. ; }
  161. ; }
  162. ; xr->trylevel=stop;
  163. ;}
  164. ;/* NOTE: frame (ebp) is setup by caller of __local_unwind2 */
  165. PUBLIC __NLG_Return2
  166. cProc _local_unwind2,<C,PUBLIC>
  167. cBegin
  168. .FPO (0,2,3,3,0,0)
  169. push ebx
  170. push esi
  171. push edi ;call to the handler may trash, so we must save it
  172. mov eax, [esp+16] ; (eax) = PEXCEPTION_REGISTRATION
  173. ;link in a handler to guard our unwind
  174. push eax
  175. push TRYLEVEL_INVALID
  176. push OFFSET FLAT:__unwind_handler
  177. push fs:__except_list
  178. mov fs:__except_list, esp
  179. _lu_top:
  180. mov eax, [esp+32] ; (eax) = PEXCEPTION_REGISTRATION
  181. mov ebx, [eax.scopetable]
  182. mov esi, [eax.trylevel]
  183. cmp esi, -1 ; REVIEW: do we need this extra check?
  184. je short _lu_done
  185. cmp esi, [esp+36]
  186. je short _lu_done
  187. lea esi, [esi+esi*2] ; esi*= 3
  188. mov ecx, [(ebx+esi*4).enclosing_level]
  189. mov [esp+8], ecx ; save enclosing level
  190. mov [eax.trylevel], ecx
  191. cmp dword ptr [(ebx+esi*4).filter], 0
  192. jnz short _lu_continue
  193. push 0101h
  194. mov eax, [(ebx+esi*4).specific_handler]
  195. call _NLG_Notify
  196. call [(ebx+esi*4).specific_handler]
  197. __NLG_Return2::
  198. _lu_continue:
  199. jmp short _lu_top
  200. _lu_done:
  201. pop fs:__except_list
  202. add esp, 4*3 ; cleanup stack
  203. pop edi ; restore c-runtime registers
  204. pop esi
  205. pop ebx
  206. cEnd
  207. ;/* _ABNORMAL_TERMINATION - return TRUE if __finally clause entered via
  208. ; * _local_unwind2.
  209. ; */
  210. ;BOOLEAN _abnormal_termination(void);
  211. cProc _abnormal_termination,<C,PUBLIC>
  212. cBegin
  213. .FPO (0,0,0,0,0,0)
  214. xor eax, eax ; assume FALSE
  215. mov ecx, fs:__except_list
  216. cmp [ecx.handler], offset FLAT:__unwind_handler
  217. jne short _at_done ; UnwindHandler first?
  218. mov edx, [ecx+12] ; establisher of local_unwind2
  219. mov edx, [edx.trylevel] ; is trylevel the same as the
  220. cmp [ecx+8], edx ; local_unwind level?
  221. jne short _at_done ; no - then FALSE
  222. mov eax, 1 ; currently in _abnormal_termination
  223. _at_done:
  224. cEnd
  225. ;
  226. ; NLG entrypoints, for debugger support
  227. ; On entry: address of non-local goto in eax
  228. ;
  229. public __NLG_Dispatch
  230. OPTION PROLOGUE:NONE
  231. OPTION EPILOGUE:NONE
  232. _NLG_Notify1 PROC C PUBLIC
  233. push ebx
  234. push ecx
  235. mov ebx, OFFSET __NLG_Destination
  236. jmp __NLG_go ; ecx is already set
  237. _NLG_Notify1 ENDP
  238. _NLG_Notify PROC C PUBLIC, dwInCode:DWORD
  239. push ebx
  240. push ecx
  241. mov ebx, OFFSET __NLG_Destination
  242. mov ecx, dwInCode
  243. __NLG_Go:
  244. mov [ebx.dwCode], ecx
  245. mov [ebx.uoffDestination], eax
  246. mov [ebx.uoffFramePointer], ebp
  247. __NLG_Dispatch::
  248. pop ecx
  249. pop ebx
  250. ret 4
  251. _NLG_Notify ENDP
  252. OPTION PROLOGUE:PROLOGUEDEF
  253. OPTION EPILOGUE:EPILOGUEDEF
  254. EndCODE
  255. END