mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 06:45:42 +00:00
Bug 1753061 - revert bug 1709578. r=rhunt
Differential Revision: https://phabricator.services.mozilla.com/D137628
This commit is contained in:
parent
ba01be44f5
commit
89a10888d3
@ -958,46 +958,6 @@ def wasm_memory64(value, cranelift, simulator, target):
|
||||
set_config("ENABLE_WASM_MEMORY64", wasm_memory64)
|
||||
set_define("ENABLE_WASM_MEMORY64", wasm_memory64)
|
||||
|
||||
# Support for checking for indirect call to null via traps
|
||||
# =====================================================
|
||||
|
||||
|
||||
@depends(milestone.is_nightly, "--enable-jit", "--enable-simulator")
|
||||
def default_wasm_call_indirect_null(is_nightly, enable_jit, simulator):
|
||||
if not enable_jit:
|
||||
return
|
||||
|
||||
if simulator:
|
||||
return
|
||||
|
||||
if is_nightly:
|
||||
return True
|
||||
|
||||
|
||||
option(
|
||||
"--enable-wasm-call-indirect-null",
|
||||
default=default_wasm_call_indirect_null,
|
||||
help="{Enable|Disable} WebAssembly call-indirect-to-null optimization",
|
||||
)
|
||||
|
||||
|
||||
@depends("--enable-wasm-call-indirect-null", "--enable-jit", "--enable-simulator")
|
||||
def wasm_call_indirect_null(value, enable_jit, simulator):
|
||||
if not value:
|
||||
return
|
||||
|
||||
if not enable_jit:
|
||||
return
|
||||
|
||||
if simulator:
|
||||
return
|
||||
|
||||
return True
|
||||
|
||||
|
||||
set_config("ENABLE_WASM_CALL_INDIRECT_NULL", wasm_call_indirect_null)
|
||||
set_define("ENABLE_WASM_CALL_INDIRECT_NULL", wasm_call_indirect_null)
|
||||
|
||||
# Options for generating the shell as a script
|
||||
# ============================================
|
||||
option("--with-qemu-exe", nargs=1, help="Use path as an arm emulator on host platforms")
|
||||
|
@ -3946,19 +3946,12 @@ CodeOffset MacroAssembler::wasmCallIndirect(const wasm::CallSiteDesc& desc,
|
||||
|
||||
loadPtr(Address(scratch, offsetof(wasm::FunctionTableElem, code)), scratch);
|
||||
|
||||
#ifdef ENABLE_WASM_CALL_INDIRECT_NULL
|
||||
CodeOffset callOffset = call(desc, scratch);
|
||||
append(wasm::Trap::IndirectCallToNull,
|
||||
wasm::TrapSite(callOffset.offset(), trapOffset));
|
||||
return callOffset;
|
||||
#else
|
||||
Label nonNull;
|
||||
branchTestPtr(Assembler::NonZero, scratch, scratch, &nonNull);
|
||||
wasmTrap(wasm::Trap::IndirectCallToNull, trapOffset);
|
||||
bind(&nonNull);
|
||||
|
||||
return call(desc, scratch);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MacroAssembler::nopPatchableToCall(const wasm::CallSiteDesc& desc) {
|
||||
|
@ -471,103 +471,6 @@ struct AutoHandlingTrap {
|
||||
MOZ_ASSERT(sAlreadyHandlingTrap.get());
|
||||
|
||||
uint8_t* pc = ContextToPC(context);
|
||||
|
||||
# ifdef ENABLE_WASM_CALL_INDIRECT_NULL
|
||||
// If pc is null and a plausible return address can be obtained then the pc
|
||||
// will be set to that address and indirectCallToNull will be set to true.
|
||||
// After that, the normal filtering will validate the pc, and we will check
|
||||
// below that there is an IndirectCallToNull trap at that address.
|
||||
|
||||
bool indirectCallToNull = false;
|
||||
if (pc == nullptr) {
|
||||
# if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
|
||||
|
||||
// On Intel we must read the return address from the stack, but before
|
||||
// doing that we want to validate the sp as much as possible.
|
||||
|
||||
uint8_t* sp = ContextToSP(context);
|
||||
|
||||
// Check that sp has pointer alignment.
|
||||
|
||||
if (uintptr_t(sp) & (sizeof(uintptr_t) - 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the stack would be aligned for the Wasm ABI after popping the
|
||||
// return address. Outgoing argument areas are a multiple of
|
||||
// WasmStackAlignment but calls are only aligned to JitStackAlignment.
|
||||
|
||||
static_assert(jit::WasmStackAlignment >= jit::JitStackAlignment,
|
||||
"subsumes");
|
||||
if (uintptr_t(sp + sizeof(uintptr_t)) & (jit::JitStackAlignment - 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the SP/FP relationship is sane.
|
||||
|
||||
if (sp >= ContextToFP(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that sp is within the stack base and limit, when we can.
|
||||
|
||||
if (assertCx) {
|
||||
if (uintptr_t(sp) >= assertCx->nativeStackBase() ||
|
||||
uintptr_t(sp) < assertCx->jitStackLimitNoInterrupt) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// (Darwin-on-Intel only) We're on a different thread, hence TlsContext
|
||||
// could supply no JSContext to us, and we can't verify that the sp points
|
||||
// into the stack area. It may not matter much, because if we get a wild
|
||||
// sp value then either it points to unmapped memory and we will fault, or
|
||||
// it points to an address that is either not code or does not have the
|
||||
// correct trap value associated with it.
|
||||
}
|
||||
|
||||
// Even when we know sp points into a stack and is aligned, we don't know
|
||||
// for sure whether the memory at *sp will be mapped, and the load could
|
||||
// fault. That would indicate buggy code however, and regular recursive
|
||||
// SIGSEGV handling should take care of it, see comments above.
|
||||
//
|
||||
// One reason for unmapped stack is that the stack has never extended that
|
||||
// far down before. In this case the sp could have been moved into the
|
||||
// unmapped area by a bug. Importantly the sp will not be moved into the
|
||||
// unmapped area by a legitimate call instruction, since it pushes the
|
||||
// return address and a page will be mapped in for that through a mechanism
|
||||
// that does not affect us here (as we're guarded on pc==0, which would not
|
||||
// be the case for a stack fault).
|
||||
//
|
||||
// Another reason for unmapped stack is that the memory could have become
|
||||
// unmapped *after* the return address was successfully pushed and the pc
|
||||
// updated. This would be a weird race, again a bug.
|
||||
|
||||
pc = *reinterpret_cast<uint8_t**>(sp);
|
||||
indirectCallToNull = true;
|
||||
|
||||
# elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || \
|
||||
defined(JS_CODEGEN_MIPS64)
|
||||
|
||||
uint8_t* lr = ContextToLR(context);
|
||||
|
||||
// Check that the return address is a plausible code pointer. On these
|
||||
// platforms, instructions are all four bytes long.
|
||||
|
||||
if (uintptr_t(lr) & 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pc = lr;
|
||||
indirectCallToNull = true;
|
||||
|
||||
# else
|
||||
|
||||
# error "Platform code needed"
|
||||
|
||||
# endif
|
||||
}
|
||||
# endif // ENABLE_WASM_CALL_INDIRECT_NULL
|
||||
|
||||
const CodeSegment* codeSegment = LookupCodeSegment(pc);
|
||||
if (!codeSegment || !codeSegment->isModule()) {
|
||||
return false;
|
||||
@ -581,26 +484,11 @@ struct AutoHandlingTrap {
|
||||
return false;
|
||||
}
|
||||
|
||||
# ifdef ENABLE_WASM_CALL_INDIRECT_NULL
|
||||
if (indirectCallToNull) {
|
||||
// Final validation: We must find the right trap type at the call.
|
||||
if (trap != Trap::IndirectCallToNull) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Roll the PC back to the return point in the caller.
|
||||
SetContextPC(context, pc);
|
||||
}
|
||||
# endif
|
||||
|
||||
// We have a safe, expected wasm trap, so fp is well-defined to be a Frame*.
|
||||
// For the first sanity check, the Trap::IndirectCallBadSig special case is
|
||||
// due to this trap occurring in the indirect call prologue, while fp points
|
||||
// to the caller's Frame which can be in a different Module. In any case,
|
||||
// though, the containing JSContext is the same.
|
||||
//
|
||||
// (Note the special case does not apply to Trap::IndirectCallToNull because
|
||||
// in that case the pc has been rolled back to the caller.)
|
||||
|
||||
auto* frame = reinterpret_cast<Frame*>(ContextToFP(context));
|
||||
Instance* instance = GetNearestEffectiveTls(frame)->instance;
|
||||
|
Loading…
Reference in New Issue
Block a user