Leaked source code of windows server 2003
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.

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