Windows NT 4.0 source code leak
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
8.7 KiB

4 years ago
  1. ;***
  2. ;exsup.asm
  3. ;
  4. ; Copyright (c) 1993-1994 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. ; 02-10-94 GJF -1 is the end-of-exception-handler chain marker, not
  20. ; 0.
  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. ifdef _WIN32_
  28. _WIN32_OR_POSIX_ equ 1
  29. endif
  30. ifdef _POSIX_
  31. _WIN32_OR_POSIX_ equ 1
  32. endif
  33. .xlist
  34. include pversion.inc
  35. ?DFDATA = 1
  36. ?NODATA = 1
  37. include cmacros.mas
  38. include exsup.inc
  39. .list
  40. ;REVIEW: can we get rid of _global_unwind2, and just use
  41. ; the C runtimes version, _global_unwind?
  42. ifdef _WIN32_OR_POSIX_
  43. extrn _RtlUnwind@16:near
  44. endif
  45. ;typedef struct _EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION;
  46. ;struct _EXCEPTION_REGISTRATION{
  47. ; struct _EXCEPTION_REGISTRATION *prev;
  48. ; void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION, PCONTEXT, PEXCEPTION_RECORD);
  49. ; struct scopetable_entry *scopetable;
  50. ; int trylevel;
  51. ;};
  52. _EXCEPTION_REGISTRATION_COMMON struc ; C8.0/C9.0 common only
  53. dd ? ; prev (OS-req, def'd in exsup.inc)
  54. dd ? ; handler (ditto)
  55. scopetable dd ? ; C8/C9 common
  56. trylevel dd ? ; C8/C9 common
  57. _EXCEPTION_REGISTRATION_COMMON ends
  58. ;#define EXCEPTION_MAXIMUM_PARAMETERS 4
  59. ;typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
  60. ;typedef EXCEPTION_RECORD *PEXCEPTION_RECORD;
  61. ;struct _EXCEPTION_RECORD{
  62. ; NTSTATUS ExceptionCode;
  63. ; ULONG ExceptionFlags;
  64. ; struct _EXCEPTION_RECORD *ExceptionRecord;
  65. ; PVOID ExceptionAddress;
  66. ; ULONG NumberParameters;
  67. ; ULONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
  68. ;};
  69. _EXCEPTION_RECORD struc
  70. exception_number dd ?
  71. exception_flags dd ?
  72. exception_record dd ?
  73. exception_address dd ?
  74. number_parameters dd ?
  75. exception_information dd 4 dup(?)
  76. _EXCEPTION_RECORD ends
  77. SIZEOF_EXCEPTION_RECORD equ 36
  78. assumes DS,DATA
  79. assumes FS,DATA
  80. public __except_list
  81. __except_list equ 0
  82. ;struct _SCOPETABLE_ENTRY{
  83. ; int enclosing_level; /* lexical level of enclosing scope */
  84. ; int (*filter)(PEXCEPTION_RECORD); /* NULL for a termination handler */
  85. ; void (*specific_handler)(void); /* xcpt or termination handler */
  86. ;};
  87. ;struct _SCOPETABLE_ENTRY Scopetable[NUMTRYS];
  88. _SCOPETABLE_ENTRY struc
  89. enclosing_level dd ?
  90. filter dd ?
  91. specific_handler dd ?
  92. _SCOPETABLE_ENTRY ends
  93. BeginCODE
  94. if @Version LT 600
  95. ifdef _WIN32_OR_POSIX_
  96. ;this needs to go here to work around a masm5 bug. (emits wrong fixup)
  97. assumes CS,FLAT
  98. else
  99. assumes CS,CODE
  100. endif
  101. endif
  102. ifdef _WIN32_OR_POSIX_ ;{
  103. ;NB: call to RtlUnwind appears to trash ebx! and possibly others so just
  104. ; to be save, we save all callee save regs.
  105. cProc _global_unwind2,<C,PUBLIC>,<IBX,ISI,IDI,IBP>
  106. parmDP stop
  107. cBegin
  108. push 0 ; ReturnValue
  109. push 0 ; ExceptionRecord
  110. push offset flat:_gu_return ; TargetIp
  111. push stop ; TargetFrame
  112. call _RtlUnwind@16
  113. _gu_return:
  114. cEnd
  115. else ;}{
  116. ;/* _GLOBAL_UNWIND2 - */
  117. ;void _global_unwind2(PEXCEPTION_REGISTRATION *stop)
  118. ;{
  119. ; for(xr=__except_list; xr!=stop; xr=xr->prev){
  120. ; assert(xr!=NULL);
  121. ; /* NOTE: must set ebp to this scopes frame before call */
  122. ; _local_unwind2(xr, -1);
  123. ; }
  124. ;}
  125. cProc _global_unwind2,<C,PUBLIC>,<ISI,IDI>
  126. parmDP stop
  127. localV xr,SIZEOF_EXCEPTION_RECORD
  128. cBegin
  129. ;build an EXCEPTION_RECORD to pass to language handler for unwinding
  130. lea esi, xr
  131. mov [esi.exception_number], 0
  132. mov [esi.exception_flags], EXCEPTION_UNWIND_CONTEXT
  133. ;REVIEW: fill in the rest of the struct?
  134. mov edi, dword ptr fs:__except_list
  135. _gu_top:
  136. cmp edi, stop
  137. je short _gu_done
  138. cmp edi, -1 ; -1 means no higher-level handler
  139. je short _gu_error
  140. push edi
  141. push esi
  142. call [edi.handler]
  143. add esp, 8
  144. mov edi, [edi.prev]
  145. mov dword ptr fs:__except_list, edi
  146. jmp short _gu_top
  147. _gu_error:
  148. ;assert(0);
  149. _gu_done:
  150. cEnd
  151. endif ;}
  152. ;_unwind_handler(
  153. ; PEXCEPTION_RECORD xr,
  154. ; PREGISTRATION_RECORD establisher,
  155. ; PCONTEXT context,
  156. ; PREGISTRATION_RECORD dispatcher);
  157. ;
  158. ;this is a special purpose handler used to guard our local unwinder.
  159. ; its job is to catch collided unwinds.
  160. ;
  161. ;NB: this code is basically stolen from the NT routine xcptmisc.asm
  162. ; and is basically the same method used by the system unwinder (RtlUnwind).
  163. ;
  164. cProc _unwind_handler,<C>
  165. cBegin
  166. mov ecx, dword ptr [esp+4]
  167. test dword ptr [ecx.exception_flags], EXCEPTION_UNWIND_CONTEXT
  168. mov eax, DISPOSITION_CONTINUE_SEARCH
  169. jz short _uh_return
  170. ; We collide in a _local_unwind. We set the dispatched to the
  171. ; establisher just before the local handler so we can unwind
  172. ; any future local handlers.
  173. mov eax, [esp+8] ; Our establisher is the one
  174. ; in front of the local one
  175. mov edx, [esp+16]
  176. mov [edx], eax ; set dispatcher to local_unwind2
  177. mov eax, DISPOSITION_COLLIDED_UNWIND
  178. _uh_return:
  179. cEnd
  180. ;/* _LOCAL_UNWIND2 - run all termination handlers listed in the scope table
  181. ; * associated with the given registration record, from the current lexical
  182. ; * level through enclosing levels up to, but not including the given 'stop'
  183. ; * level.
  184. ; */
  185. ;void _local_unwind2(PEXCEPTION_REGISTRATION xr, int stop)
  186. ;{
  187. ; int ix;
  188. ;
  189. ; for(ix=xr->trylevel; ix!=-1 && ix!=stop; ix=xr->xscope[i].enclosing_level){
  190. ; /* NULL indicates that this entry is for a termination handler */
  191. ; if(xr->xscope[i].filter==NULL){
  192. ; /* NB: call to the termination handler may trash callee save regs */
  193. ; (*xr->xscope[i].specific_handler)();
  194. ; }
  195. ; }
  196. ; xr->trylevel=stop;
  197. ;}
  198. ;/* NOTE: frame (ebp) is setup by caller of __local_unwind2 */
  199. cProc _local_unwind2,<C,PUBLIC>
  200. cBegin
  201. push ebx
  202. push esi
  203. push edi ;call to the handler may trash, so we must save it
  204. mov eax, [esp+16] ; (eax) = PEXCEPTION_REGISTRATION
  205. ;link in a handler to guard our unwind
  206. push eax
  207. push TRYLEVEL_INVALID
  208. push OFFSET FLAT:__unwind_handler
  209. push fs:__except_list
  210. mov fs:__except_list, esp
  211. _lu_top:
  212. mov eax, [esp+32] ; (eax) = PEXCEPTION_REGISTRATION
  213. mov ebx, [eax.scopetable]
  214. mov esi, [eax.trylevel]
  215. cmp esi, -1 ; REVIEW: do we need this extra check?
  216. je short _lu_done
  217. cmp esi, [esp+36]
  218. je short _lu_done
  219. lea esi, [esi+esi*2] ; esi*= 3
  220. mov ecx, [(ebx+esi*4).enclosing_level]
  221. mov [esp+8], ecx ; save enclosing level
  222. mov [eax.trylevel], ecx
  223. cmp dword ptr [(ebx+esi*4).filter], 0
  224. jnz short _lu_continue
  225. call [(ebx+esi*4).specific_handler]
  226. _lu_continue:
  227. jmp short _lu_top
  228. _lu_done:
  229. pop fs:__except_list
  230. add esp, 4*3 ; cleanup stack
  231. pop edi ; restore c-runtime registers
  232. pop esi
  233. pop ebx
  234. cEnd
  235. ;/* _ABNORMAL_TERMINATION - return TRUE if __finally clause entered via
  236. ; * _local_unwind2.
  237. ; */
  238. ;BOOLEAN _abnormal_termination(void);
  239. cProc _abnormal_termination,<C,PUBLIC>
  240. cBegin
  241. xor eax, eax ; assume FALSE
  242. mov ecx, fs:__except_list
  243. cmp [ecx.handler], offset FLAT:__unwind_handler
  244. jne short _at_done ; UnwindHandler first?
  245. mov edx, [ecx+12] ; establisher of local_unwind2
  246. mov edx, [edx.trylevel] ; is trylevel the same as the
  247. cmp [ecx+8], edx ; local_unwind level?
  248. jne short _at_done ; no - then FALSE
  249. mov eax, 1 ; currently in _abnormal_termination
  250. _at_done:
  251. cEnd
  252. EndCODE
  253. END