ReactOS 0.4.16-dev-2122-g1628f5e
handler4.c
Go to the documentation of this file.
1/*
2 * C++ exception handling (ver. 4)
3 *
4 * Copyright 2020 Piotr Caban
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <corecrt.h>
22
23#if defined(__x86_64__) && _MSVCR_VER>=140
24
25#include <stdarg.h>
26#include <stdlib.h>
27
28#include "wine/exception.h"
29#include "wine/debug.h"
30#include "cppexcept.h"
31#include "msvcrt.h"
32
34
35static DWORD fls_index;
36
37typedef struct
38{
40 UINT bbt_flags;
41 UINT unwind_count;
42 UINT unwind_map;
43 UINT tryblock_count;
44 UINT tryblock_map;
45 UINT ip_count;
46 UINT ip_map;
47 UINT frame;
48} cxx_function_descr_v4;
49#define FUNC_DESCR_IS_CATCH 0x01
50#define FUNC_DESCR_IS_SEPARATED 0x02
51#define FUNC_DESCR_BBT 0x04
52#define FUNC_DESCR_UNWIND_MAP 0x08
53#define FUNC_DESCR_TRYBLOCK_MAP 0x10
54#define FUNC_DESCR_EHS 0x20
55#define FUNC_DESCR_NO_EXCEPT 0x40
56#define FUNC_DESCR_RESERVED 0x80
57
58typedef struct
59{
60 UINT type;
61 BYTE *prev;
64} unwind_info_v4;
65
66typedef struct
67{
69 UINT flags;
71 int offset;
73 UINT ret_addr[2];
74} catchblock_info_v4;
75#define CATCHBLOCK_FLAGS 0x01
76#define CATCHBLOCK_TYPE_INFO 0x02
77#define CATCHBLOCK_OFFSET 0x04
78#define CATCHBLOCK_SEPARATED 0x08
79#define CATCHBLOCK_RET_ADDR_MASK 0x30
80#define CATCHBLOCK_RET_ADDR 0x10
81#define CATCHBLOCK_TWO_RET_ADDRS 0x20
82
83#define UNWIND_TYPE_NO_HANDLER 0
84#define UNWIND_TYPE_DTOR_OBJ 1
85#define UNWIND_TYPE_DTOR_PTR 2
86#define UNWIND_TYPE_FRAME 3
87
88#define CONSOLIDATE_UNWIND_PARAMETER_COUNT 10
89
90typedef struct
91{
93 BOOL rethrow;
94 INT search_state;
95 INT unwind_state;
96 EXCEPTION_RECORD *prev_rec;
98
99typedef struct
100{
101 ULONG64 dest_frame;
102 ULONG64 orig_frame;
103 EXCEPTION_RECORD *seh_rec;
105 const cxx_function_descr_v4 *descr;
106 int trylevel;
108
109static UINT decode_uint(BYTE **b)
110{
111 UINT ret;
112 BYTE *p = *b;
113
114 if ((*p & 1) == 0)
115 {
116 ret = p[0] >> 1;
117 p += 1;
118 }
119 else if ((*p & 3) == 1)
120 {
121 ret = (p[0] >> 2) + (p[1] << 6);
122 p += 2;
123 }
124 else if ((*p & 7) == 3)
125 {
126 ret = (p[0] >> 3) + (p[1] << 5) + (p[2] << 13);
127 p += 3;
128 }
129 else if ((*p & 15) == 7)
130 {
131 ret = (p[0] >> 4) + (p[1] << 4) + (p[2] << 12) + (p[3] << 20);
132 p += 4;
133 }
134 else
135 {
136 FIXME("not implemented - expect crash\n");
137 ret = 0;
138 p += 5;
139 }
140
141 *b = p;
142 return ret;
143}
144
145static UINT read_rva(BYTE **b)
146{
147 UINT ret = *(UINT*)(*b);
148 *b += sizeof(UINT);
149 return ret;
150}
151
152static void read_unwind_info(BYTE **b, unwind_info_v4 *ui)
153{
154 BYTE *p = *b;
155
156 memset(ui, 0, sizeof(*ui));
157 ui->type = decode_uint(b);
158 ui->prev = p - (ui->type >> 2);
159 ui->type &= 0x3;
160
161 switch (ui->type)
162 {
163 case UNWIND_TYPE_NO_HANDLER:
164 break;
165 case UNWIND_TYPE_DTOR_OBJ:
166 ui->handler = read_rva(b);
167 ui->object = decode_uint(b); /* frame offset to object */
168 break;
169 case UNWIND_TYPE_DTOR_PTR:
170 ui->handler = read_rva(b);
171 ui->object = decode_uint(b); /* frame offset to pointer to object */
172 break;
173 case UNWIND_TYPE_FRAME:
174 ui->handler = read_rva(b);
175 break;
176 }
177}
178
179static void read_tryblock_info(BYTE **b, tryblock_info *ti, ULONG64 image_base)
180{
181 BYTE *count, *count_end;
182
183 ti->start_level = decode_uint(b);
184 ti->end_level = decode_uint(b);
185 ti->catch_level = decode_uint(b);
186 ti->catchblock = read_rva(b);
187
188 if (ti->catchblock)
189 {
190 count = count_end = rtti_rva(ti->catchblock, image_base);
191 ti->catchblock_count = decode_uint(&count_end);
192 ti->catchblock += count_end - count;
193 }
194 else
195 {
196 ti->catchblock_count = 0;
197 }
198}
199
200static BOOL read_catchblock_info(BYTE **b, catchblock_info_v4 *ci, DWORD func_rva)
201{
202 BYTE ret_addr_type;
203 memset(ci, 0, sizeof(*ci));
204 ci->header = **b;
205 (*b)++;
206 if (ci->header & ~(CATCHBLOCK_FLAGS | CATCHBLOCK_TYPE_INFO | CATCHBLOCK_OFFSET |
207 CATCHBLOCK_SEPARATED | CATCHBLOCK_RET_ADDR_MASK))
208 {
209 FIXME("unknown header: %x\n", ci->header);
210 return FALSE;
211 }
212 ret_addr_type = ci->header & CATCHBLOCK_RET_ADDR_MASK;
213 if (ret_addr_type == (CATCHBLOCK_RET_ADDR | CATCHBLOCK_TWO_RET_ADDRS))
214 {
215 FIXME("unsupported ret addr type.\n");
216 return FALSE;
217 }
218
219 if (ci->header & CATCHBLOCK_FLAGS) ci->flags = decode_uint(b);
220 if (ci->header & CATCHBLOCK_TYPE_INFO) ci->type_info = read_rva(b);
221 if (ci->header & CATCHBLOCK_OFFSET) ci->offset = decode_uint(b);
222 ci->handler = read_rva(b);
223 if (ci->header & CATCHBLOCK_SEPARATED)
224 {
225 if (ret_addr_type == CATCHBLOCK_RET_ADDR || ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
226 ci->ret_addr[0] = read_rva(b);
227 if (ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
228 ci->ret_addr[1] = read_rva(b);
229 }
230 else
231 {
232 if (ret_addr_type == CATCHBLOCK_RET_ADDR || ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
233 ci->ret_addr[0] = decode_uint(b) + func_rva;
234 if (ret_addr_type == CATCHBLOCK_TWO_RET_ADDRS)
235 ci->ret_addr[1] = decode_uint(b) + func_rva;
236 }
237
238 return TRUE;
239}
240
241static void read_ipmap_info(BYTE **b, ipmap_info *ii)
242{
243 ii->ip = decode_uint(b);
244 ii->state = (INT)decode_uint(b) - 1;
245}
246
247static BOOL validate_cxx_function_descr4(const cxx_function_descr_v4 *descr, DISPATCHER_CONTEXT *dispatch)
248{
249 ULONG64 image_base = dispatch->ImageBase;
250 BYTE *unwind_map = rtti_rva(descr->unwind_map, image_base);
251 BYTE *tryblock_map = rtti_rva(descr->tryblock_map, image_base);
252 BYTE *ip_map = rtti_rva(descr->ip_map, image_base);
253 UINT i, j;
254 char *ip;
255
256 TRACE("header 0x%x\n", descr->header);
257 TRACE("basic block transformations flags: 0x%x\n", descr->bbt_flags);
258
259 TRACE("unwind table: 0x%x(%p) %d\n", descr->unwind_map, unwind_map, descr->unwind_count);
260 for (i = 0; i < descr->unwind_count; i++)
261 {
262 BYTE *entry = unwind_map;
263 unwind_info_v4 ui;
264
265 read_unwind_info(&unwind_map, &ui);
266 if (ui.prev < (BYTE*)rtti_rva(descr->unwind_map, image_base)) ui.prev = NULL;
267 TRACE(" %d (%p): type 0x%x prev %p func 0x%x object 0x%x\n",
268 i, entry, ui.type, ui.prev, ui.handler, ui.object);
269 }
270
271 TRACE("try table: 0x%x(%p) %d\n", descr->tryblock_map, tryblock_map, descr->tryblock_count);
272 for (i = 0; i < descr->tryblock_count; i++)
273 {
274 tryblock_info ti;
275 BYTE *catchblock;
276
277 read_tryblock_info(&tryblock_map, &ti, image_base);
278 catchblock = rtti_rva(ti.catchblock, image_base);
279 TRACE(" %d: start %d end %d catchlevel %d catch 0x%x(%p) %d\n",
281 ti.catchblock, catchblock, ti.catchblock_count);
282 for (j = 0; j < ti.catchblock_count; j++)
283 {
284 catchblock_info_v4 ci;
285 if (!read_catchblock_info(&catchblock, &ci,
286 dispatch->FunctionEntry->BeginAddress)) return FALSE;
287 TRACE(" %d: header 0x%x offset %d handler 0x%x "
288 "ret addr[0] %#x ret_addr[1] %#x type %#x %s\n", j, ci.header, ci.offset,
289 ci.handler, ci.ret_addr[0], ci.ret_addr[1], ci.type_info,
290 dbgstr_type_info(ci.type_info ? rtti_rva(ci.type_info, image_base) : NULL));
291 }
292 }
293
294 TRACE("ipmap: 0x%x(%p) %d\n", descr->ip_map, ip_map, descr->ip_count);
295 ip = rtti_rva(dispatch->FunctionEntry->BeginAddress, image_base);
296 for (i = 0; i < descr->ip_count; i++)
297 {
298 ipmap_info ii;
299
300 read_ipmap_info(&ip_map, &ii);
301 ip += ii.ip;
302 TRACE(" %d: ip offset 0x%x (%p) state %d\n", i, ii.ip, ip, ii.state);
303 }
304
305 TRACE("establisher frame: %x\n", descr->frame);
306 return TRUE;
307}
308
309static inline int ip_to_state4(const cxx_function_descr_v4 *descr, DISPATCHER_CONTEXT *dispatch, ULONG64 ip)
310{
311 BYTE *ip_map = rtti_rva( descr->ip_map, dispatch->ImageBase );
312 ULONG64 state_ip;
313 ipmap_info ii;
314 int ret = -1;
315 UINT i;
316
317 state_ip = dispatch->ImageBase + dispatch->FunctionEntry->BeginAddress;
318 for (i = 0; i < descr->ip_count; i++)
319 {
320 read_ipmap_info(&ip_map, &ii);
321 state_ip += ii.ip;
322 if (ip < state_ip) break;
323 ret = ii.state;
324 }
325
326 TRACE("%I64x -> state %d\n", ip, ret);
327 return ret;
328}
329
330static void cxx_local_unwind4(ULONG64 frame, DISPATCHER_CONTEXT *dispatch,
331 const cxx_function_descr_v4 *descr, int trylevel, int last_level)
332{
333 void (__cdecl *handler_dtor)(void *obj, ULONG64 frame);
334 BYTE *unwind_data, *last;
335 unwind_info_v4 ui;
336 void *obj;
337 int i;
338
339 if (trylevel == -2) trylevel = ip_to_state4( descr, dispatch, get_exception_pc(dispatch) );
340
341 TRACE("current level: %d, last level: %d\n", trylevel, last_level);
342
343 if (trylevel<-1 || trylevel>=(int)descr->unwind_count)
344 {
345 ERR("invalid trylevel %d\n", trylevel);
346 terminate();
347 }
348
349 if (trylevel <= last_level) return;
350
351 unwind_data = rtti_rva(descr->unwind_map, dispatch->ImageBase);
352 last = unwind_data - 1;
353 for (i = 0; i < trylevel; i++)
354 {
355 BYTE *addr = unwind_data;
356 read_unwind_info(&unwind_data, &ui);
357 if (i == last_level) last = addr;
358 }
359
360 while (unwind_data > last)
361 {
362 read_unwind_info(&unwind_data, &ui);
363 unwind_data = ui.prev;
364
365 if (ui.handler)
366 {
367 handler_dtor = rtti_rva(ui.handler, dispatch->ImageBase);
368 obj = (void *)(frame + ui.object);
369 if(ui.type == UNWIND_TYPE_DTOR_PTR)
370 obj = *(void**)obj;
371 TRACE("handler: %p object: %p\n", handler_dtor, obj);
372 handler_dtor(obj, frame);
373 }
374 }
375}
376
378{
379 EXCEPTION_RECORD *rec = eptrs->ExceptionRecord;
381
382 if (rec->ExceptionCode == CXX_EXCEPTION && !rec->ExceptionInformation[1] && !rec->ExceptionInformation[2])
384
385 FlsSetValue(fls_index, (void*)(DWORD_PTR)ctx->search_state);
386 if (rec->ExceptionCode != CXX_EXCEPTION)
388 if (rec->ExceptionInformation[1] == ctx->prev_rec->ExceptionInformation[1])
389 ctx->rethrow = TRUE;
391}
392
393static void CALLBACK cxx_catch_cleanup(BOOL normal, void *c)
394{
396 __CxxUnregisterExceptionObject(&ctx->frame_info, ctx->rethrow);
397
398 FlsSetValue(fls_index, (void*)(DWORD_PTR)ctx->unwind_state);
399}
400
401static void* WINAPI call_catch_block4(EXCEPTION_RECORD *rec)
402{
403 EXCEPTION_RECORD *untrans_rec = (void*)rec->ExceptionInformation[4];
404 EXCEPTION_RECORD *prev_rec = (void*)rec->ExceptionInformation[6];
405 CONTEXT *context = (void*)rec->ExceptionInformation[7];
406 EXCEPTION_POINTERS ep = { prev_rec, context };
408 void *ret_addr = NULL;
409
410 ctx.rethrow = FALSE;
411 __CxxRegisterExceptionObject(&ep, &ctx.frame_info);
412 ctx.search_state = rec->ExceptionInformation[2];
413 ctx.unwind_state = rec->ExceptionInformation[3];
414 ctx.prev_rec = prev_rec;
415 (*__processing_throw())--;
416 __TRY
417 {
418 __TRY
419 {
420 ret_addr = call_catch_handler( rec );
421 }
423 {
424 TRACE("detect rethrow: exception code: %lx\n", prev_rec->ExceptionCode);
425 ctx.rethrow = TRUE;
426 FlsSetValue(fls_index, (void*)(DWORD_PTR)ctx.search_state);
427
428 if (untrans_rec)
429 {
431 RaiseException(untrans_rec->ExceptionCode, untrans_rec->ExceptionFlags,
432 untrans_rec->NumberParameters, untrans_rec->ExceptionInformation);
433 }
434 else
435 {
436 RaiseException(prev_rec->ExceptionCode, prev_rec->ExceptionFlags,
437 prev_rec->NumberParameters, prev_rec->ExceptionInformation);
438 }
439 }
441 }
443
444 FlsSetValue(fls_index, (void*)-2);
445 TRACE("handler returned %p, ret_addr[0] %#Ix, ret_addr[1] %#Ix.\n",
446 ret_addr, rec->ExceptionInformation[8], rec->ExceptionInformation[9]);
447
448 if (rec->ExceptionInformation[9])
449 {
450 if ((ULONG_PTR)ret_addr > 1)
451 {
452 ERR("unexpected handler result %p.\n", ret_addr);
453 abort();
454 }
455 return (void*)rec->ExceptionInformation[8 + (ULONG_PTR)ret_addr];
456 }
457 return rec->ExceptionInformation[8] ? (void *)rec->ExceptionInformation[8] : ret_addr;
458}
459
460static inline BOOL cxx_is_consolidate(const EXCEPTION_RECORD *rec)
461{
463 && rec->NumberParameters == CONSOLIDATE_UNWIND_PARAMETER_COUNT
464 && rec->ExceptionInformation[0] == (ULONG_PTR)call_catch_block4;
465}
466
467static inline void find_catch_block4(EXCEPTION_RECORD *rec, CONTEXT *context,
469 const cxx_function_descr_v4 *descr, cxx_exception_type *info,
470 ULONG64 orig_frame, int trylevel)
471{
472 ULONG64 exc_base = (rec->NumberParameters == 4 ? rec->ExceptionInformation[3] : 0);
473 int *processing_throw = __processing_throw();
474 EXCEPTION_RECORD catch_record;
475 BYTE *tryblock_map;
476 CONTEXT ctx;
477 UINT i, j;
478
479 (*processing_throw)++;
480
481 if (trylevel == -2) trylevel = ip_to_state4( descr, dispatch, get_exception_pc(dispatch) );
482 TRACE("current trylevel: %d\n", trylevel);
483
484 tryblock_map = rtti_rva(descr->tryblock_map, dispatch->ImageBase);
485 for (i=0; i<descr->tryblock_count; i++)
486 {
487 tryblock_info tryblock;
488 BYTE *catchblock;
489
490 read_tryblock_info(&tryblock_map, &tryblock, dispatch->ImageBase);
491
492 if (trylevel < tryblock.start_level) continue;
493 if (trylevel > tryblock.end_level) continue;
494
495 /* got a try block */
496 catchblock = rtti_rva(tryblock.catchblock, dispatch->ImageBase);
497 for (j=0; j<tryblock.catchblock_count; j++)
498 {
499 catchblock_info_v4 ci;
500
501 read_catchblock_info(&catchblock, &ci, dispatch->FunctionEntry->BeginAddress);
502
503 if (info)
504 {
505 const type_info *catch_ti = NULL;
506 const cxx_type_info *type;
507
508 if (ci.type_info) catch_ti = rtti_rva( ci.type_info, dispatch->ImageBase );
509 if (!(type = find_caught_type( info, exc_base, catch_ti, ci.flags ))) continue;
510
511 TRACE("matched type %p in tryblock %d catchblock %d\n", type, i, j);
512
513 if (catch_ti && catch_ti->mangled[0] && ci.offset)
514 {
515 /* copy the exception to its destination on the stack */
516 void **dest = (void **)(orig_frame + ci.offset);
517 copy_exception( (void *)rec->ExceptionInformation[1], dest, ci.flags, type, exc_base );
518 }
519 }
520 else
521 {
522 /* no CXX_EXCEPTION only proceed with a catch(...) block*/
523 if (ci.type_info)
524 continue;
525 TRACE("found catch(...) block\n");
526 }
527
528 /* unwind stack and call catch */
529 memset(&catch_record, 0, sizeof(catch_record));
532 catch_record.NumberParameters = CONSOLIDATE_UNWIND_PARAMETER_COUNT;
533 catch_record.ExceptionInformation[0] = (ULONG_PTR)call_catch_block4;
534 catch_record.ExceptionInformation[1] = orig_frame;
535 catch_record.ExceptionInformation[2] = tryblock.catch_level;
536 catch_record.ExceptionInformation[3] = tryblock.start_level;
537 catch_record.ExceptionInformation[4] = (ULONG_PTR)untrans_rec;
538 catch_record.ExceptionInformation[5] = (ULONG_PTR)rtti_rva(ci.handler, dispatch->ImageBase);
539 /* 3ds Max plugin expect ExceptionInformation[6] to contain exception record */
540 catch_record.ExceptionInformation[6] = (ULONG_PTR)rec;
541 catch_record.ExceptionInformation[7] = (ULONG_PTR)context;
542 if (ci.ret_addr[0])
543 {
544 catch_record.ExceptionInformation[8] = (ULONG_PTR)rtti_rva(
545 ci.ret_addr[0], dispatch->ImageBase);
546 }
547 if (ci.ret_addr[1])
548 {
549 catch_record.ExceptionInformation[9] = (ULONG_PTR)rtti_rva(
550 ci.ret_addr[1], dispatch->ImageBase);
551 }
552 RtlUnwindEx((void*)frame, (void*)dispatch->ControlPc, &catch_record, NULL, &ctx, NULL);
553 }
554 }
555
556 TRACE("no matching catch block found\n");
557 (*processing_throw)--;
558}
559
561{
564 cxx_exception_type *exc_type;
565
566 if (rec->ExceptionCode != CXX_EXCEPTION)
567 {
568 TRACE("non-c++ exception thrown in SEH handler: %lx\n", rec->ExceptionCode);
569 terminate();
570 }
571
572 exc_type = (cxx_exception_type *)rec->ExceptionInformation[2];
573 find_catch_block4(rec, ep->ContextRecord, ctx->seh_rec, ctx->dest_frame, ctx->dispatch,
574 ctx->descr, exc_type, ctx->orig_frame, ctx->trylevel);
575
578}
579
580/* Hacky way to obtain se_translator */
581static inline _se_translator_function get_se_translator(void)
582{
583 return __current_exception()[-2];
584}
585
586static void check_noexcept( PEXCEPTION_RECORD rec, const cxx_function_descr_v4 *descr )
587{
588 if (!(descr->header & FUNC_DESCR_IS_CATCH) &&
590 (descr->header & FUNC_DESCR_NO_EXCEPT))
591 {
592 ERR("noexcept function propagating exception\n");
593 terminate();
594 }
595}
596
597static DWORD cxx_frame_handler4(EXCEPTION_RECORD *rec, ULONG64 frame,
599 const cxx_function_descr_v4 *descr, int trylevel)
600{
601 cxx_exception_type *exc_type;
602 ULONG64 orig_frame = frame;
603
604 if (descr->header & FUNC_DESCR_IS_CATCH)
605 {
606 TRACE("nested exception detected\n");
607 orig_frame = *(ULONG64 *)(frame + descr->frame);
608 TRACE("setting orig_frame to %Ix\n", orig_frame);
609 }
610
612 {
613 int last_level = -1;
615 last_level = rec->ExceptionInformation[3];
617 last_level = ip_to_state4( descr, dispatch, dispatch->TargetIp );
618
619 cxx_local_unwind4(orig_frame, dispatch, descr, trylevel, last_level);
621 }
622 if (!descr->tryblock_map)
623 {
624 check_noexcept(rec, descr);
626 }
627
628 if (rec->ExceptionCode == CXX_EXCEPTION)
629 {
630 if (!rec->ExceptionInformation[1] && !rec->ExceptionInformation[2])
631 {
632 TRACE("rethrow detected.\n");
634 }
635
636 exc_type = (cxx_exception_type *)rec->ExceptionInformation[2];
637
638 if (TRACE_ON(seh))
639 {
640 TRACE("handling C++ exception rec %p frame %Ix descr %p\n", rec, frame, descr);
642 }
643 }
644 else
645 {
646 _se_translator_function se_translator = get_se_translator();
647
648 exc_type = NULL;
649 TRACE("handling C exception code %lx rec %p frame %Ix descr %p\n",
650 rec->ExceptionCode, rec, frame, descr);
651
652 if (se_translator) {
653 EXCEPTION_POINTERS except_ptrs;
655
656 ctx.dest_frame = frame;
657 ctx.orig_frame = orig_frame;
658 ctx.seh_rec = rec;
659 ctx.dispatch = dispatch;
660 ctx.descr = descr;
661 ctx.trylevel = trylevel;
662 __TRY
663 {
664 except_ptrs.ExceptionRecord = rec;
665 except_ptrs.ContextRecord = context;
666 se_translator(rec->ExceptionCode, &except_ptrs);
667 }
669 {
670 }
672 }
673 }
674
675 find_catch_block4(rec, context, NULL, frame, dispatch, descr, exc_type, orig_frame, trylevel);
676 check_noexcept(rec, descr);
678}
679
680EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler4(EXCEPTION_RECORD *rec,
682{
683 cxx_function_descr_v4 descr;
684 BYTE *p, *count, *count_end;
685 int trylevel;
686
687 TRACE("%p %Ix %p %p\n", rec, frame, context, dispatch);
688
689 trylevel = (DWORD_PTR)FlsGetValue(fls_index);
690 FlsSetValue(fls_index, (void*)-2);
691
692 memset(&descr, 0, sizeof(descr));
693 p = rtti_rva(*(UINT*)dispatch->HandlerData, dispatch->ImageBase);
694 descr.header = *p++;
695
696 if ((descr.header & FUNC_DESCR_EHS) &&
698 !cxx_is_consolidate(rec) &&
700 return ExceptionContinueSearch; /* handle only c++ exceptions */
701
702 if (descr.header & ~(FUNC_DESCR_IS_CATCH | FUNC_DESCR_IS_SEPARATED |
703 FUNC_DESCR_UNWIND_MAP | FUNC_DESCR_TRYBLOCK_MAP | FUNC_DESCR_EHS |
704 FUNC_DESCR_NO_EXCEPT))
705 {
706 FIXME("unsupported flags: %x\n", descr.header);
708 }
709
710 if (descr.header & FUNC_DESCR_BBT) descr.bbt_flags = decode_uint(&p);
711 if (descr.header & FUNC_DESCR_UNWIND_MAP)
712 {
713 descr.unwind_map = read_rva(&p);
714 count_end = count = rtti_rva(descr.unwind_map, dispatch->ImageBase);
715 descr.unwind_count = decode_uint(&count_end);
716 descr.unwind_map += count_end - count;
717 }
718 if (descr.header & FUNC_DESCR_TRYBLOCK_MAP)
719 {
720 descr.tryblock_map = read_rva(&p);
721 count_end = count = rtti_rva(descr.tryblock_map, dispatch->ImageBase);
722 descr.tryblock_count = decode_uint(&count_end);
723 descr.tryblock_map += count_end - count;
724 }
725 descr.ip_map = read_rva(&p);
726 if (descr.header & FUNC_DESCR_IS_SEPARATED)
727 {
728 UINT i, num, func;
729 BYTE *map = rtti_rva(descr.ip_map, dispatch->ImageBase);
730
731 num = decode_uint(&map);
732 for (i = 0; i < num; i++)
733 {
734 func = read_rva(&map);
735 descr.ip_map = read_rva(&map);
736 if (func == dispatch->FunctionEntry->BeginAddress)
737 break;
738 }
739 if (i == num)
740 {
741 FIXME("function ip_map not found\n");
743 }
744 }
745 count_end = count = rtti_rva(descr.ip_map, dispatch->ImageBase);
746 descr.ip_count = decode_uint(&count_end);
747 descr.ip_map += count_end - count;
748 if (descr.header & FUNC_DESCR_IS_CATCH) descr.frame = decode_uint(&p);
749
750 if (!validate_cxx_function_descr4(&descr, dispatch))
752
753 return cxx_frame_handler4(rec, frame, context, dispatch, &descr, trylevel);
754}
755
756BOOL msvcrt_init_handler4(void)
757{
758 fls_index = FlsAlloc(NULL);
759 if (fls_index == FLS_OUT_OF_INDEXES)
760 return FALSE;
761 msvcrt_attach_handler4();
762 return TRUE;
763}
764
765void msvcrt_attach_handler4(void)
766{
767 FlsSetValue(fls_index, (void*)-2);
768}
769
770void msvcrt_free_handler4(void)
771{
772 FlsFree(fls_index);
773}
774
775#endif
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
void dispatch(HANDLE hStopEvent)
Definition: dispatch.c:70
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
Definition: _map.h:48
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
@ ExceptionContinueSearch
Definition: compat.h:91
#define __TRY
Definition: compat.h:80
enum _EXCEPTION_DISPOSITION EXCEPTION_DISPOSITION
#define TRACE_ON(x)
Definition: compat.h:75
#define __ENDTRY
Definition: compat.h:82
#define CALLBACK
Definition: compat.h:35
VOID WINAPI RaiseException(_In_ DWORD dwExceptionCode, _In_ DWORD dwExceptionFlags, _In_ DWORD nNumberOfArguments, _In_opt_ const ULONG_PTR *lpArguments)
Definition: except.c:700
PVOID WINAPI FlsGetValue(DWORD dwFlsIndex)
Definition: fiber.c:460
BOOL WINAPI FlsSetValue(DWORD dwFlsIndex, PVOID lpFlsData)
Definition: fiber.c:481
BOOL WINAPI FlsFree(DWORD dwFlsIndex)
Definition: fiber.c:400
DWORD WINAPI FlsAlloc(PFLS_CALLBACK_FUNCTION lpCallback)
Definition: fiber.c:341
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7512
void CDECL terminate(void)
Definition: cpp.c:698
#define CXX_EXCEPTION
Definition: cppexcept.h:34
static const char * dbgstr_type_info(const type_info *info)
Definition: cppexcept.h:169
static const cxx_type_info * find_caught_type(cxx_exception_type *exc_type, uintptr_t base, const type_info *catch_ti, UINT catch_flags)
Definition: cppexcept.h:214
#define TRACE_EXCEPTION_TYPE(type, base)
Definition: cppexcept.h:265
static void copy_exception(void *object, void **dest, UINT catch_flags, const cxx_type_info *type, uintptr_t base)
Definition: cppexcept.h:241
void * call_catch_handler(EXCEPTION_RECORD *rec)
ULONG_PTR get_exception_pc(DISPATCHER_CONTEXT *dispatch)
struct __type_info type_info
static void * rtti_rva(unsigned int rva, uintptr_t base)
Definition: cxx.h:469
static void check_noexcept(PEXCEPTION_RECORD rec, const cxx_function_descr *descr, BOOL nested)
Definition: except.c:359
void CDECL __DestructExceptionObject(EXCEPTION_RECORD *rec)
Definition: except.c:950
static BOOL cxx_is_consolidate(const EXCEPTION_RECORD *rec)
Definition: except.c:258
static void CALLBACK cxx_catch_cleanup(BOOL normal, void *c)
Definition: except.c:204
static LONG CALLBACK se_translation_filter(EXCEPTION_POINTERS *ep, void *c)
Definition: except.c:339
void CDECL __CxxUnregisterExceptionObject(cxx_frame_info *frame_info, BOOL in_use)
Definition: except.c:992
BOOL CDECL __CxxRegisterExceptionObject(EXCEPTION_POINTERS *ep, cxx_frame_info *frame_info)
Definition: except.c:968
static LONG CALLBACK cxx_rethrow_filter(PEXCEPTION_POINTERS eptrs, void *c)
Definition: except.c:190
#define __cdecl
Definition: corecrt.h:121
void(__cdecl * _se_translator_function)(unsigned int code, struct _EXCEPTION_POINTERS *info)
Definition: eh.h:37
void **__cdecl __current_exception(void)
int *__cdecl __processing_throw(void)
static void * image_base(void)
Definition: dll_register.c:28
return ret
Definition: mutex.c:146
#define ULONG_PTR
Definition: config.h:101
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLenum func
Definition: glext.h:6028
GLintptr offset
Definition: glext.h:5920
const GLubyte * c
Definition: glext.h:8905
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLbitfield flags
Definition: glext.h:7161
GLenum const GLvoid * addr
Definition: glext.h:9621
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLuint num
Definition: glext.h:9618
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define abort()
Definition: i386-dis.c:34
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:91
uint32_t entry
Definition: isohybrid.c:63
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
if(dx< 0)
Definition: linetemp.h:194
unsigned __int64 ULONG64
Definition: imports.h:198
static UINT UINT last
Definition: font.c:45
static char * dest
Definition: rtl.c:135
static void __cdecl se_translator(unsigned int u, EXCEPTION_POINTERS *ep)
Definition: misc.c:1359
unsigned int UINT
Definition: ndis.h:50
#define STATUS_LONGJUMP
Definition: ntstatus.h:297
#define STATUS_UNWIND_CONSOLIDATE
Definition: ntstatus.h:300
UINT ui
Definition: oleauto.h:49
@ normal
Definition: optimize.h:166
long LONG
Definition: pedump.c:60
#define INT
Definition: polytest.cpp:20
NTSYSAPI void WINAPI RtlUnwindEx(void *, void *, EXCEPTION_RECORD *, void *, CONTEXT *, UNWIND_HISTORY_TABLE *)
const char * descr
Definition: boot.c:45
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:200
PCONTEXT ContextRecord
Definition: rtltypes.h:201
DWORD ExceptionCode
Definition: compat.h:208
DWORD NumberParameters
Definition: compat.h:212
DWORD ExceptionFlags
Definition: compat.h:209
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
char mangled[128]
Definition: cxx.h:335
Definition: http.c:7252
Definition: dhcpd.h:62
int state
Definition: cppexcept.h:39
UINT ip
Definition: cppexcept.h:38
UINT catchblock_count
Definition: cppexcept.h:107
UINT catchblock
Definition: cppexcept.h:108
#define EXCEPTION_NONCONTINUABLE
Definition: stubs.h:23
#define DWORD_PTR
Definition: treelist.c:76
uint32_t DWORD_PTR
Definition: typedefs.h:65
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define FLS_OUT_OF_INDEXES
Definition: winbase.h:556
#define WINAPI
Definition: msvc.h:6
#define __EXCEPT_CTX(func, ctx)
Definition: exception.h:63
#define __FINALLY_CTX(func, ctx)
Definition: exception.h:68
#define EXCEPTION_EXIT_UNWIND
Definition: rtltypes.h:156
#define EXCEPTION_UNWINDING
Definition: rtltypes.h:155
#define EXCEPTION_TARGET_UNWIND
Definition: rtltypes.h:159
unsigned char BYTE
Definition: xxhash.c:193