Bug 1830962: Update wasm2c to disable Wasm exception handling code from runtime r=glandium

Differential Revision: https://phabricator.services.mozilla.com/D176949
This commit is contained in:
Shravan Narayan 2023-05-04 02:57:19 +00:00
parent 309bff70a7
commit b6f5e0b726
11 changed files with 78 additions and 150 deletions

View file

@ -9,8 +9,8 @@ origin:
description: wasm2c fork used for rlbox sandboxing
url: https://github.com/WebAssembly/wabt
release: 805bebffde3c41fe4f1255deccc7bcb5b7e05dfa (2023-04-26T15:06:45Z).
revision: 805bebffde3c41fe4f1255deccc7bcb5b7e05dfa
release: 5abbeaab97eb802acccf866d9c8cc021c1f7e570 (2023-05-02T18:27:21Z).
revision: 5abbeaab97eb802acccf866d9c8cc021c1f7e570
license: Apache-2.0
license-file: LICENSE
@ -44,3 +44,4 @@ vendoring:
- src/tools/wast*
- src/tools/wat*
- src/tools/wasm2w*
- wasm2c/wasm-rt-exceptions*

View file

@ -502,7 +502,7 @@ $(WASM_ARCHIVE): $(CWASMOBJS) $(CPPWASMOBJS) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOB
$(WASM_CXX) -o $@ -Wl,--export-all -Wl,--stack-first -Wl,-z,stack-size=$(if $(MOZ_OPTIMIZE),262144,1048576) -Wl,--no-entry -Wl,--growable-table -Wl,--import-memory -Wl,--import-table $(CWASMOBJS) $(CPPWASMOBJS) -lwasi-emulated-process-clocks
$(addsuffix .c,$(WASM_ARCHIVE)): $(WASM_ARCHIVE) $(DIST)/host/bin/wasm2c$(HOST_BIN_SUFFIX)
$(DIST)/host/bin/wasm2c$(HOST_BIN_SUFFIX) -o $@ $<
$(DIST)/host/bin/wasm2c$(HOST_BIN_SUFFIX) -o $@ --disable-simd $<
ifeq ($(OS_ARCH),WINNT)
# Import libraries are created by the rules creating shared libraries.

View file

@ -19,6 +19,7 @@
#include <functional>
#include "wabt/common.h"
#include "wabt/feature.h"
#include "wabt/ir.h"
namespace wabt {
@ -28,6 +29,8 @@ class Stream;
struct WriteCOptions {
std::string_view module_name;
/* Set of wasm features enabled for wasm2c */
Features* features;
/*
* name_to_output_file_index takes const iterators to begin and end of a list
* of all functions in the module, number of imported functions, and number of

View file

@ -297,6 +297,7 @@ class CWriter {
static void SerializeFuncType(const FuncType&, std::string&);
std::string GetGlobalName(ModuleFieldType, const std::string&) const;
std::string GetLocalName(const std::string&, bool is_label) const;
void Indent(int size = INDENT_SIZE);
void Dedent(int size = INDENT_SIZE);
@ -367,6 +368,7 @@ class CWriter {
const std::string&);
void WriteCallIndirectFuncDeclaration(const FuncDeclaration&,
const std::string&);
void WriteFeatureMacros();
void WriteModuleInstance();
void WriteGlobals();
void WriteGlobal(const Global&, const std::string&);
@ -910,6 +912,13 @@ std::string CWriter::DefineLocalScopeName(std::string_view name,
kLocalSymbolPrefix + MangleName(StripLeadingDollar(name)));
}
std::string CWriter::GetLocalName(const std::string& name,
bool is_label) const {
std::string mangled = name + (is_label ? kLabelSuffix : kParamSuffix);
assert(local_sym_map_.count(mangled) == 1);
return local_sym_map_.at(mangled);
}
std::string CWriter::DefineParamName(std::string_view name) {
return DefineLocalScopeName(name, false);
}
@ -1021,21 +1030,15 @@ void CWriter::Write(std::string_view s) {
}
void CWriter::Write(const ParamName& name) {
std::string mangled = name.name + kParamSuffix;
assert(local_sym_map_.count(mangled) == 1);
Write(local_sym_map_[mangled]);
Write(GetLocalName(name.name, false));
}
void CWriter::Write(const LabelName& name) {
std::string mangled = name.name + kLabelSuffix;
assert(local_sym_map_.count(mangled) == 1);
Write(local_sym_map_[mangled]);
Write(GetLocalName(name.name, true));
}
void CWriter::Write(const GlobalName& name) {
std::string mangled = name.name + MangleField(name.type);
assert(global_sym_map_.count(mangled) == 1);
Write(global_sym_map_.at(mangled));
Write(GetGlobalName(name.type, name.name));
}
void CWriter::Write(const ExternalPtr& name) {
@ -1787,6 +1790,15 @@ void CWriter::WriteCallIndirectFuncDeclaration(const FuncDeclaration& decl,
Write(")");
}
void CWriter::WriteFeatureMacros() {
if (options_.features->exceptions_enabled()) {
Write("#define WASM_RT_ENABLE_EXCEPTION_HANDLING", Newline(), Newline());
}
if (options_.features->simd_enabled()) {
Write("#define WASM_RT_ENABLE_SIMD", Newline(), Newline());
}
}
void CWriter::WriteModuleInstance() {
BeginInstance();
WriteGlobals();
@ -5120,6 +5132,7 @@ void CWriter::WriteCHeader() {
Write("#ifndef ", guard, Newline());
Write("#define ", guard, Newline());
Write(Newline());
WriteFeatureMacros();
Write(s_header_top);
Write(Newline());
WriteModuleInstance();

View file

@ -4,6 +4,13 @@ R"w2c_template(
#include "wasm-rt.h"
)w2c_template"
R"w2c_template(
#if defined(WASM_RT_ENABLE_EXCEPTION_HANDLING)
)w2c_template"
R"w2c_template(#include "wasm-rt-exceptions.h"
)w2c_template"
R"w2c_template(#endif
)w2c_template"
R"w2c_template(
#if defined(WASM_RT_ENABLE_SIMD)
)w2c_template"
R"w2c_template(#include "simde/wasm/simd128.h"

View file

@ -60,7 +60,7 @@ examples:
static const std::string supported_features[] = {
"multi-memory", "multi-value", "sign-extension", "saturating-float-to-int",
"exceptions", "memory64", "extended-const"};
"exceptions", "memory64", "extended-const", "simd"};
static bool IsFeatureSupported(const std::string& feature) {
return std::find(std::begin(supported_features), std::end(supported_features),
@ -100,12 +100,13 @@ static void ParseOptions(int argc, char** argv) {
ConvertBackslashToSlash(&s_infile);
});
parser.Parse(argc, argv);
s_write_c_options.features = &s_features;
bool any_non_supported_feature = false;
#define WABT_FEATURE(variable, flag, default_, help) \
any_non_supported_feature |= \
(s_features.variable##_enabled() != default_) && \
!IsFeatureSupported(flag);
s_features.variable##_enabled() && !IsFeatureSupported(flag);
#include "wabt/feature.def"
#undef WABT_FEATURE

View file

@ -820,7 +820,7 @@ Result Validator::CheckModule() {
f->elem_segment.elem_type);
// Init expr.
if (f->elem_segment.offset.size()) {
if (f->elem_segment.kind == SegmentKind::Active) {
result_ |= validator_.BeginInitExpr(field.loc, Type::I32);
ExprVisitor visitor(this);
result_ |= visitor.VisitExprList(
@ -881,7 +881,7 @@ Result Validator::CheckModule() {
f->data_segment.kind);
// Init expr.
if (f->data_segment.offset.size()) {
if (f->data_segment.kind == SegmentKind::Active) {
Type offset_type = Type::I32;
Index memory_index = module->GetMemoryIndex(f->data_segment.memory_var);
if (memory_index < module->memories.size() &&

View file

@ -341,8 +341,9 @@ exhaustion.
### Runtime support for exception handling
Several additional symbols must be defined if wasm2c is being run with
support for exceptions (`--enable-exceptions`):
Several additional symbols must be defined if wasm2c is being run with support
for exceptions (`--enable-exceptions`). These are defined in
`wasm-rt-exceptions.h`. These symbols are:
```c
void wasm_rt_load_exception(const char* tag, uint32_t size, const void* values);
@ -357,7 +358,7 @@ wasm_rt_try(target)
```
A C implementation of these functions is also available in
[`wasm-rt-impl.h`](wasm-rt-impl.h) and [`wasm-rt-impl.c`](wasm-rt-impl.c).
[`wasm-rt-exceptions-impl.c`](wasm-rt-exceptions-impl.c).
`wasm_rt_load_exception` sets the active exception to a given tag, size, and contents.

View file

@ -36,13 +36,7 @@
#include <sys/mman.h>
#endif
#if _MSC_VER
#include <malloc.h>
#define alloca _alloca
#endif
#define PAGE_SIZE 65536
#define MAX_EXCEPTION_SIZE PAGE_SIZE
#if WASM_RT_INSTALL_SIGNAL_HANDLER
static bool g_signal_handler_installed = false;
@ -60,12 +54,6 @@ WASM_RT_THREAD_LOCAL uint32_t wasm_rt_saved_call_stack_depth;
WASM_RT_THREAD_LOCAL wasm_rt_jmp_buf g_wasm_rt_jmp_buf;
static WASM_RT_THREAD_LOCAL wasm_rt_tag_t g_active_exception_tag;
static WASM_RT_THREAD_LOCAL uint8_t g_active_exception[MAX_EXCEPTION_SIZE];
static WASM_RT_THREAD_LOCAL uint32_t g_active_exception_size;
static WASM_RT_THREAD_LOCAL wasm_rt_jmp_buf* g_unwind_target;
#ifdef WASM_RT_TRAP_HANDLER
extern void WASM_RT_TRAP_HANDLER(wasm_rt_trap_t code);
#endif
@ -88,45 +76,6 @@ void wasm_rt_trap(wasm_rt_trap_t code) {
#endif
}
void wasm_rt_load_exception(const wasm_rt_tag_t tag,
uint32_t size,
const void* values) {
if (size > MAX_EXCEPTION_SIZE) {
wasm_rt_trap(WASM_RT_TRAP_EXHAUSTION);
}
g_active_exception_tag = tag;
g_active_exception_size = size;
if (size) {
memcpy(g_active_exception, values, size);
}
}
WASM_RT_NO_RETURN void wasm_rt_throw(void) {
WASM_RT_LONGJMP(*g_unwind_target, WASM_RT_TRAP_UNCAUGHT_EXCEPTION);
}
WASM_RT_UNWIND_TARGET* wasm_rt_get_unwind_target(void) {
return g_unwind_target;
}
void wasm_rt_set_unwind_target(WASM_RT_UNWIND_TARGET* target) {
g_unwind_target = target;
}
wasm_rt_tag_t wasm_rt_exception_tag(void) {
return g_active_exception_tag;
}
uint32_t wasm_rt_exception_size(void) {
return g_active_exception_size;
}
void* wasm_rt_exception(void) {
return g_active_exception;
}
#ifdef _WIN32
static void* os_mmap(size_t size) {
void* ret = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS);
@ -399,7 +348,7 @@ uint64_t wasm_rt_grow_memory(wasm_rt_memory_t* memory, uint64_t delta) {
void wasm_rt_free_memory(wasm_rt_memory_t* memory) {
#if WASM_RT_USE_MMAP
const uint64_t mmap_size = get_allocation_size_for_mmap(memory);
os_munmap(memory->data, mmap_size); // ignore error
os_munmap(memory->data, mmap_size); // ignore error
#else
free(memory->data);
#endif

View file

@ -30,19 +30,6 @@ extern "C" {
/** A setjmp buffer used for handling traps. */
extern WASM_RT_THREAD_LOCAL wasm_rt_jmp_buf g_wasm_rt_jmp_buf;
#if WASM_RT_INSTALL_SIGNAL_HANDLER && !defined(_WIN32)
#define WASM_RT_LONGJMP_UNCHECKED(buf, val) siglongjmp(buf, val)
#else
#define WASM_RT_LONGJMP_UNCHECKED(buf, val) longjmp(buf, val)
#endif
#define WASM_RT_LONGJMP(buf, val) \
/* Abort on failure as this may be called in the trap handler */ \
if (!((buf).initialized)) \
abort(); \
(buf).initialized = false; \
WASM_RT_LONGJMP_UNCHECKED((buf).buffer, val)
#if WASM_RT_USE_STACK_DEPTH_COUNT
/** Saved call stack depth that will be restored in case a trap occurs. */
extern WASM_RT_THREAD_LOCAL uint32_t wasm_rt_saved_call_stack_depth;

View file

@ -317,6 +317,38 @@ bool wasm_rt_is_initialized(void);
/** Free the runtime's state. */
void wasm_rt_free(void);
/**
* A hardened jmp_buf that allows checking for initialization before use
*/
typedef struct {
/* Is the jmp buf intialized? */
bool initialized;
/* jmp_buf contents */
jmp_buf buffer;
} wasm_rt_jmp_buf;
#if WASM_RT_INSTALL_SIGNAL_HANDLER && !defined(_WIN32)
#define WASM_RT_SETJMP_SETBUF(buf) sigsetjmp(buf, 1)
#else
#define WASM_RT_SETJMP_SETBUF(buf) setjmp(buf)
#endif
#define WASM_RT_SETJMP(buf) \
((buf).initialized = true, WASM_RT_SETJMP_SETBUF((buf).buffer))
#if WASM_RT_INSTALL_SIGNAL_HANDLER && !defined(_WIN32)
#define WASM_RT_LONGJMP_UNCHECKED(buf, val) siglongjmp(buf, val)
#else
#define WASM_RT_LONGJMP_UNCHECKED(buf, val) longjmp(buf, val)
#endif
#define WASM_RT_LONGJMP(buf, val) \
/* Abort on failure as this may be called in the trap handler */ \
if (!((buf).initialized)) \
abort(); \
(buf).initialized = false; \
WASM_RT_LONGJMP_UNCHECKED((buf).buffer, val)
/**
* Stop execution immediately and jump back to the call to `wasm_rt_impl_try`.
* The result of `wasm_rt_impl_try` will be the provided trap reason.
@ -330,72 +362,6 @@ WASM_RT_NO_RETURN void wasm_rt_trap(wasm_rt_trap_t);
*/
const char* wasm_rt_strerror(wasm_rt_trap_t trap);
/**
* A tag is represented as an arbitrary pointer.
*/
typedef const void* wasm_rt_tag_t;
/**
* Set the active exception to given tag, size, and contents.
*/
void wasm_rt_load_exception(const wasm_rt_tag_t tag,
uint32_t size,
const void* values);
/**
* Throw the active exception.
*/
WASM_RT_NO_RETURN void wasm_rt_throw(void);
/**
* A hardened jmp_buf that allows us to checks if it is initialized before use
*/
typedef struct {
/* Is the jmp buf intialized? */
bool initialized;
/* jmp_buf contents */
jmp_buf buffer;
} wasm_rt_jmp_buf;
/**
* The type of an unwind target if an exception is thrown and caught.
*/
#define WASM_RT_UNWIND_TARGET wasm_rt_jmp_buf
/**
* Get the current unwind target if an exception is thrown.
*/
WASM_RT_UNWIND_TARGET* wasm_rt_get_unwind_target(void);
/**
* Set the unwind target if an exception is thrown.
*/
void wasm_rt_set_unwind_target(WASM_RT_UNWIND_TARGET* target);
/**
* Tag of the active exception.
*/
wasm_rt_tag_t wasm_rt_exception_tag(void);
/**
* Size of the active exception.
*/
uint32_t wasm_rt_exception_size(void);
/**
* Contents of the active exception.
*/
void* wasm_rt_exception(void);
#if WASM_RT_INSTALL_SIGNAL_HANDLER && !defined(_WIN32)
#define WASM_RT_SETJMP_SETBUF(buf) sigsetjmp(buf, 1)
#else
#define WASM_RT_SETJMP_SETBUF(buf) setjmp(buf)
#endif
#define WASM_RT_SETJMP(buf) \
((buf).initialized = true, WASM_RT_SETJMP_SETBUF((buf).buffer))
#define wasm_rt_try(target) WASM_RT_SETJMP(target)
/**