Reland r216808, underlying lldb bug has been fixed.
[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(Signal, SigInfo& sigInfo, PlatformRegisters& context)
56 {
57     void* faultingInstruction = MachineContext::instructionPointer(context);
58     dataLogLnIf(verbose, "starting handler for fault at: ", RawPointer(faultingInstruction));
59
60     dataLogLnIf(verbose, "JIT memory start: ", RawPointer(reinterpret_cast<void*>(startOfFixedExecutableMemoryPool)), " end: ", RawPointer(reinterpret_cast<void*>(endOfFixedExecutableMemoryPool)));
61     // First we need to make sure we are in JIT code before we can aquire any locks. Otherwise,
62     // we might have crashed in code that is already holding one of the locks we want to aquire.
63     if (isJITPC(faultingInstruction)) {
64         bool faultedInActiveFastMemory = false;
65         {
66             void* faultingAddress = sigInfo.faultingAddress;
67             dataLogLnIf(verbose, "checking faulting address: ", RawPointer(faultingAddress), " is in an active fast memory");
68             faultedInActiveFastMemory = Wasm::Memory::addressIsInActiveFastMemory(faultingAddress);
69         }
70         if (faultedInActiveFastMemory) {
71             dataLogLnIf(verbose, "found active fast memory for faulting address");
72             LockHolder locker(codeLocationsLock);
73             for (auto range : codeLocations.get()) {
74                 void* start;
75                 void* end;
76                 std::tie(start, end) = range;
77                 dataLogLnIf(verbose, "function start: ", RawPointer(start), " end: ", RawPointer(end));
78                 if (start <= faultingInstruction && faultingInstruction < end) {
79                     dataLogLnIf(verbose, "found match");
80                     MacroAssemblerCodeRef exceptionStub = Thunks::singleton().existingStub(throwExceptionFromWasmThunkGenerator);
81                     // If for whatever reason we don't have a stub then we should just treat this like a regular crash.
82                     if (!exceptionStub)
83                         break;
84                     dataLogLnIf(verbose, "found stub: ", RawPointer(exceptionStub.code().executableAddress()));
85                     MachineContext::argumentPointer<1>(context) = reinterpret_cast<void*>(ExceptionType::OutOfBoundsMemoryAccess);
86                     MachineContext::instructionPointer(context) = exceptionStub.code().executableAddress();
87                     return SignalAction::Handled;
88                 }
89             }
90         }
91     }
92     return SignalAction::NotHandled;
93 }
94
95 #endif // ENABLE(WEBASSEMBLY_FAST_MEMORY)
96
97 void registerCode(void* start, void* end)
98 {
99     if (!fastMemoryEnabled())
100         return;
101     LockHolder locker(codeLocationsLock);
102     codeLocations->add(std::make_tuple(start, end));
103 }
104
105 void unregisterCode(void* start, void* end)
106 {
107     if (!fastMemoryEnabled())
108         return;
109     LockHolder locker(codeLocationsLock);
110     codeLocations->remove(std::make_tuple(start, end));
111 }
112
113 bool fastMemoryEnabled()
114 {
115     return fastHandlerInstalled;
116 }
117
118 void enableFastMemory()
119 {
120     static std::once_flag once;
121     std::call_once(once, [] {
122         if (!Options::useWebAssemblyFastMemory())
123             return;
124
125 #if ENABLE(WEBASSEMBLY_FAST_MEMORY)
126         installSignalHandler(Signal::Bus, [] (Signal signal, SigInfo& sigInfo, PlatformRegisters& ucontext) {
127             return trapHandler(signal, sigInfo, ucontext);
128         });
129
130         installSignalHandler(Signal::SegV, [] (Signal signal, SigInfo& sigInfo, PlatformRegisters& ucontext) {
131             return trapHandler(signal, sigInfo, ucontext);
132         });
133
134         codeLocations.construct();
135         fastHandlerInstalled = true;
136 #endif // ENABLE(WEBASSEMBLY_FAST_MEMORY)
137     });
138 }
139     
140 } } // namespace JSC::Wasm
141
142 #endif // ENABLE(WEBASSEMBLY)
143