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.

299 lines
9.1 KiB

  1. ;***
  2. ;exsup.asm
  3. ;
  4. ; Copyright (c) 1993-1997, 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. ;
  32. ;*******************************************************************************
  33. ;hnt = -D_WIN32 -Dsmall32 -Dflat32 -Mx $this;
  34. ;Define small32 and flat32 since these are not defined in the NT build process
  35. small32 equ 1
  36. flat32 equ 1
  37. .xlist
  38. include pversion.inc
  39. ?DFDATA = 1
  40. ?NODATA = 1
  41. include cmacros.inc
  42. include exsup.inc
  43. .list
  44. ;REVIEW: can we get rid of _global_unwind2, and just use
  45. ; the C runtimes version, _global_unwind?
  46. ifndef _BUILD_DLL_LIB_
  47. extrn _RtlUnwind@16:near
  48. endif ; _BUILD_DLL_LIB_
  49. ;typedef struct _EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION;
  50. ;struct _EXCEPTION_REGISTRATION{
  51. ; struct _EXCEPTION_REGISTRATION *prev;
  52. ; void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION, PCONTEXT, PEXCEPTION_RECORD);
  53. ; struct scopetable_entry *scopetable;
  54. ; int trylevel;
  55. ;};
  56. _EXCEPTION_REGISTRATION_COMMON struc ; C8.0/C9.0 common only
  57. dd ? ; prev (OS-req, def'd in exsup.inc)
  58. dd ? ; handler (ditto)
  59. ;private:
  60. scopetable dd ? ; C8/C9 common
  61. trylevel dd ? ; C8/C9 common
  62. _EXCEPTION_REGISTRATION_COMMON ends
  63. ;#define EXCEPTION_MAXIMUM_PARAMETERS 4
  64. ;typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
  65. ;typedef EXCEPTION_RECORD *PEXCEPTION_RECORD;
  66. ;struct _EXCEPTION_RECORD{
  67. ; NTSTATUS ExceptionCode;
  68. ; ULONG ExceptionFlags;
  69. ; struct _EXCEPTION_RECORD *ExceptionRecord;
  70. ; PVOID ExceptionAddress;
  71. ; ULONG NumberParameters;
  72. ; ULONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
  73. ;};
  74. _EXCEPTION_RECORD struc
  75. exception_number dd ?
  76. exception_flags dd ?
  77. exception_record dd ?
  78. exception_address dd ?
  79. number_parameters dd ?
  80. exception_information dd 4 dup(?)
  81. _EXCEPTION_RECORD ends
  82. SIZEOF_EXCEPTION_RECORD equ 36
  83. assumes DS,DATA
  84. assumes FS,DATA
  85. public __except_list
  86. __except_list equ 0
  87. ;struct _SCOPETABLE_ENTRY{
  88. ; int enclosing_level; /* lexical level of enclosing scope */
  89. ; int (*filter)(PEXCEPTION_RECORD); /* NULL for a termination handler */
  90. ; void (*specific_handler)(void); /* xcpt or termination handler */
  91. ;};
  92. ;struct _SCOPETABLE_ENTRY Scopetable[NUMTRYS];
  93. _SCOPETABLE_ENTRY struc
  94. enclosing_level dd ?
  95. filter dd ?
  96. specific_handler dd ?
  97. _SCOPETABLE_ENTRY ends
  98. ;BeginDATA
  99. ;
  100. ;__NLG_Destination _NLG_INFO <>
  101. ;PUBLIC __NLG_Destination
  102. ;
  103. ;EndDATA
  104. BeginCODE
  105. ifndef _BUILD_DLL_LIB_
  106. ;NB: call to RtlUnwind appears to trash ebx! and possibly others so just
  107. ; to be save, we save all callee save regs.
  108. cProc _global_unwind2,<C,PUBLIC>,<IBX,ISI,IDI,IBP>
  109. parmDP stop
  110. cBegin
  111. push 0 ; ReturnValue
  112. push 0 ; ExceptionRecord
  113. push offset flat:_gu_return ; TargetIp
  114. push stop ; TargetFrame
  115. call _RtlUnwind@16
  116. _gu_return:
  117. cEnd
  118. endif ; _BUILD_DLL_LIB_
  119. ;_unwind_handler(
  120. ; PEXCEPTION_RECORD xr,
  121. ; PREGISTRATION_RECORD establisher,
  122. ; PCONTEXT context,
  123. ; PREGISTRATION_RECORD dispatcher);
  124. ;
  125. ;this is a special purpose handler used to guard our local unwinder.
  126. ; its job is to catch collided unwinds.
  127. ;
  128. ;NB: this code is basically stolen from the NT routine xcptmisc.asm
  129. ; and is basically the same method used by the system unwinder (RtlUnwind).
  130. ;
  131. cProc _unwind_handler,<C>
  132. cBegin
  133. mov ecx, dword ptr [esp+4]
  134. test dword ptr [ecx.exception_flags], EXCEPTION_UNWIND_CONTEXT
  135. mov eax, DISPOSITION_CONTINUE_SEARCH
  136. jz short _uh_return
  137. ; We collide in a _local_unwind. We set the dispatched to the
  138. ; establisher just before the local handler so we can unwind
  139. ; any future local handlers.
  140. mov eax, [esp+8] ; Our establisher is the one
  141. ; in front of the local one
  142. mov edx, [esp+16]
  143. mov [edx], eax ; set dispatcher to local_unwind2
  144. mov eax, DISPOSITION_COLLIDED_UNWIND
  145. _uh_return:
  146. cEnd
  147. ;/* _LOCAL_UNWIND2 - run all termination handlers listed in the scope table
  148. ; * associated with the given registration record, from the current lexical
  149. ; * level through enclosing levels up to, but not including the given 'stop'
  150. ; * level.
  151. ; */
  152. ;void _local_unwind2(PEXCEPTION_REGISTRATION xr, int stop)
  153. ;{
  154. ; int ix;
  155. ;
  156. ; for(ix=xr->trylevel; ix!=-1 && ix!=stop; ix=xr->xscope[i].enclosing_level){
  157. ; /* NULL indicates that this entry is for a termination handler */
  158. ; if(xr->xscope[i].filter==NULL){
  159. ; /* NB: call to the termination handler may trash callee save regs */
  160. ; (*xr->xscope[i].specific_handler)();
  161. ; }
  162. ; }
  163. ; xr->trylevel=stop;
  164. ;}
  165. ;/* NOTE: frame (ebp) is setup by caller of __local_unwind2 */
  166. ;PUBLIC __NLG_Return2
  167. cProc _local_unwind2,<C,PUBLIC>
  168. cBegin
  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. ; xor eax, eax ; assume FALSE
  214. ;
  215. ; mov ecx, fs:__except_list
  216. ; cmp [ecx.handler], offset FLAT:__unwind_handler
  217. ; jne short _at_done ; UnwindHandler first?
  218. ;
  219. ; mov edx, [ecx+12] ; establisher of local_unwind2
  220. ; mov edx, [edx.trylevel] ; is trylevel the same as the
  221. ; cmp [ecx+8], edx ; local_unwind level?
  222. ; jne short _at_done ; no - then FALSE
  223. ;
  224. ; mov eax, 1 ; currently in _abnormal_termination
  225. ;_at_done:
  226. ;cEnd
  227. ;
  228. ; NLG entrypoints, for debugger support
  229. ; On entry: address of non-local goto in eax
  230. ;
  231. ;public __NLG_Dispatch
  232. ;OPTION PROLOGUE:NONE
  233. ;OPTION EPILOGUE:NONE
  234. ;_NLG_Notify1 PROC C PUBLIC
  235. ; push ebx
  236. ; push ecx
  237. ; mov ebx, OFFSET __NLG_Destination
  238. ; jmp __NLG_go ; ecx is already set
  239. ;_NLG_Notify1 ENDP
  240. ;
  241. ;_NLG_Notify PROC C PUBLIC, dwInCode:DWORD
  242. ; push ebx
  243. ; push ecx
  244. ; mov ebx, OFFSET __NLG_Destination
  245. ; mov ecx, dwInCode
  246. ;__NLG_Go:
  247. ; mov [ebx.dwCode], ecx
  248. ; mov [ebx.uoffDestination], eax
  249. ; mov [ebx.uoffFramePointer], ebp
  250. ;__NLG_Dispatch::
  251. ; pop ecx
  252. ; pop ebx
  253. ; ret 4
  254. ;_NLG_Notify ENDP
  255. ;
  256. ;OPTION PROLOGUE:PROLOGUEDEF
  257. ;OPTION EPILOGUE:EPILOGUEDEF
  258. EndCODE
  259. END