forked from emscripten-core/emscripten
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcxa_exception_emscripten.cpp
More file actions
118 lines (101 loc) · 4.16 KB
/
cxa_exception_emscripten.cpp
File metadata and controls
118 lines (101 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//===------------------- cxa_exception_emscripten.cpp ---------------------===//
//
// This code contains Emscripten specific code for exception handling.
// Emscripten has two modes of exception handling: Emscripten EH, which uses JS
// glue code, and Wasm EH, which uses the new Wasm exception handling proposal
// and meant to be faster. Code for different modes is demarcated with
// '__USING_EMSCRIPTEN_EXCEPTIONS__' and '__USING_WASM_EXCEPTIONS__'.
//
//===----------------------------------------------------------------------===//
#include "cxa_exception.h"
#include "private_typeinfo.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#if !defined(__USING_WASM_EXCEPTIONS__)
// Until recently, Rust's `rust_eh_personality` for emscripten referred to this
// symbol. If Emscripten doesn't provide it, there will be errors when linking
// rust. The rust personality function is never called so we can just abort.
// We need this to support old versions of Rust.
// https://github.com/rust-lang/rust/pull/97888
// TODO: Remove this when Rust doesn't need it anymore.
extern "C" _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
__gxx_personality_v0(int version,
_Unwind_Action actions,
uint64_t exceptionClass,
_Unwind_Exception* unwind_exception,
_Unwind_Context* context) {
abort();
}
#endif // !defined(__USING_WASM_EXCEPTIONS__)
#if defined(__USING_EMSCRIPTEN_EXCEPTIONS__) || \
defined(__USING_WASM_EXCEPTIONS__)
using namespace __cxxabiv1;
// Some utility routines are copied from cxa_exception.cpp
static inline __cxa_exception*
cxa_exception_from_thrown_object(void* thrown_object) {
return static_cast<__cxa_exception*>(thrown_object) - 1;
}
// Note: This is never called when exception_header is masquerading as a
// __cxa_dependent_exception.
static inline void*
thrown_object_from_cxa_exception(__cxa_exception* exception_header) {
return static_cast<void*>(exception_header + 1);
}
// Get the exception object from the unwind pointer.
// Relies on the structure layout, where the unwind pointer is right in
// front of the user's exception object
static inline __cxa_exception* cxa_exception_from_unwind_exception(
_Unwind_Exception* unwind_exception) {
return cxa_exception_from_thrown_object(unwind_exception + 1);
}
static inline void* thrown_object_from_unwind_exception(
_Unwind_Exception* unwind_exception) {
__cxa_exception* exception_header =
cxa_exception_from_unwind_exception(unwind_exception);
return thrown_object_from_cxa_exception(exception_header);
}
extern "C" {
void* __thrown_object_from_unwind_exception(
_Unwind_Exception* unwind_exception) {
return thrown_object_from_unwind_exception(unwind_exception);
}
char* __get_exception_message(void* thrown_object, bool terminate=false) {
__cxa_exception* exception_header =
cxa_exception_from_thrown_object(thrown_object);
const __shim_type_info* thrown_type =
static_cast<const __shim_type_info*>(exception_header->exceptionType);
const char* type_name = thrown_type->name();
int status = 0;
char* demangled_buf = __cxa_demangle(type_name, 0, 0, &status);
if (status == 0 && demangled_buf) {
type_name = demangled_buf;
}
const __shim_type_info* catch_type =
static_cast<const __shim_type_info*>(&typeid(std::exception));
int can_catch = catch_type->can_catch(thrown_type, thrown_object);
char* result = NULL;
if (can_catch) {
const char* what =
static_cast<const std::exception*>(thrown_object)->what();
asprintf(&result,
(terminate ? "terminating with uncaught exception of type %s: %s"
: "exception of type %s: %s"),
type_name,
what);
} else {
asprintf(&result,
(terminate ? "terminating with uncaught exception of type %s"
: "exception of type %s"),
type_name);
}
if (demangled_buf) {
free(demangled_buf);
}
return result;
}
char* __get_exception_terminate_message(void *thrown_object) {
return __get_exception_message(thrown_object, true);
}
}
#endif // __USING_EMSCRIPTEN_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__