Unreviewed, rolling out r216808.
[WebKit-https.git] / Source / JavaScriptCore / wasm / WasmFaultSignalHandler.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WasmFaultSignalHandler.h"
28
29 #if ENABLE(WEBASSEMBLY)
30
31 #include "ExecutableAllocator.h"
32 #include "MachineContext.h"
33 #include "VM.h"
34 #include "WasmExceptionType.h"
35 #include "WasmMemory.h"
36 #include "WasmThunks.h"
37
38 #include <wtf/Lock.h>
39 #include <wtf/NeverDestroyed.h>
40 #include <wtf/threads/Signals.h>
41
42 namespace JSC { namespace Wasm {
43
44 namespace {
45 static const bool verbose = false;
46 }
47
48 static StaticLock codeLocationsLock;
49 static LazyNeverDestroyed<HashSet<std::tuple<void*, void*>>> codeLocations; // (start, end)
50
51 #if ENABLE(WEBASSEMBLY_FAST_MEMORY)
52
53 static bool fastHandlerInstalled { false };
54
55 static SignalAction trapHandler(int, siginfo_t* sigInfo, void* ucontext)
56 {
57     mcontext_t& context = static_cast<ucontext_t*>(ucontext)->uc_mcontext;
58     void* faultingInstruction = MachineContext::instructionPointer(context);
59     dataLogLnIf(verbose, "starting handler for fault at: ", RawPointer(faultingInstruction));
60
61     dataLogLnIf(verbose, "JIT memory start: ", RawPointer(reinterpret_cast<void*>(startOfFixedExecutableMemoryPool)), " end: ", RawPointer(reinterpret_cast<void*>(endOfFixedExecutableMemoryPool)));
62     // First we need to make sure we are in JIT code before we can aquire any locks. Otherwise,
63     // we might have crashed in code that is already holding one of the locks we want to aquire.
64     if (isJITPC(faultingInstruction)) {
65         bool faultedInActiveFastMemory = false;
66         {
67             void* faultingAddress = sigInfo->si_addr;
68             dataLogLnIf(verbose, "checking faulting address: ", RawPointer(faultingAddress), " is in an active fast memory");
69             faultedInActiveFastMemory = Wasm::Memory::addressIsInActiveFastMemory(faultingAddress);
70         }
71         if (faultedInActiveFastMemory) {
72             dataLogLnIf(verbose, "found active fast memory for faulting address");
73             LockHolder locker(codeLocationsLock);
74             for (auto range : codeLocations.get()) {
75                 void* start;
76                 void* end;
77                 std::tie(start, end) = range;
78                 dataLogLnIf(verbose, "function start: ", RawPointer(start), " end: ", RawPointer(end));
79                 if (start <= faultingInstruction && faultingInstruction < end) {
80                     dataLogLnIf(verbose, "found match");
81                     MacroAssemblerCodeRef exceptionStub = Thunks::singleton().existingStub(throwExceptionFromWasmThunkGenerator);
82                     // If for whatever reason we don't have a stub then we should just treat this like a regular crash.
83                     if (!exceptionStub)
84                         break;
85                     dataLogLnIf(verbose, "found stub: ", RawPointer(exceptionStub.code().executableAddress()));
86                     MachineContext::argumentPointer<1>(context) = reinterpret_cast<void*>(ExceptionType::OutOfBoundsMemoryAccess);
87                     MachineContext::instructionPointer(context) = exceptionStub.code().executableAddress();
88                     return SignalAction::Handled;
89                 }
90             }
91         }
92     }
93     return SignalAction::NotHandled;
94 }
95
96 #endif // ENABLE(WEBASSEMBLY_FAST_MEMORY)
97
98 void registerCode(void* start, void* end)
99 {
100     if (!fastMemoryEnabled())
101         return;
102     LockHolder locker(codeLocationsLock);
103     codeLocations->add(std::make_tuple(start, end));
104 }
105
106 void unregisterCode(void* start, void* end)
107 {
108     if (!fastMemoryEnabled())
109         return;
110     LockHolder locker(codeLocationsLock);
111     codeLocations->remove(std::make_tuple(start, end));
112 }
113
114 bool fastMemoryEnabled()
115 {
116     return fastHandlerInstalled;
117 }
118
119 void enableFastMemory()
120 {
121     static std::once_flag once;
122     std::call_once(once, [] {
123         if (!Options::useWebAssemblyFastMemory())
124             return;
125
126 #if ENABLE(WEBASSEMBLY_FAST_MEMORY)
127         installSignalHandler(Signal::Bus, [] (int signal, siginfo_t* sigInfo, void* ucontext) {
128             return trapHandler(signal, sigInfo, ucontext);
129         });
130
131         installSignalHandler(Signal::SegV, [] (int signal, siginfo_t* sigInfo, void* ucontext) {
132             return trapHandler(signal, sigInfo, ucontext);
133         });
134
135         codeLocations.construct();
136         fastHandlerInstalled = true;
137 #endif // ENABLE(WEBASSEMBLY_FAST_MEMORY)
138     });
139 }
140     
141 } } // namespace JSC::Wasm
142
143 #endif // ENABLE(WEBASSEMBLY)
144