Title: [218782] trunk
Revision
218782
Author
[email protected]
Date
2017-06-23 19:54:02 -0700 (Fri, 23 Jun 2017)

Log Message

Switch VMTraps to use halt instructions rather than breakpoint instructions
https://bugs.webkit.org/show_bug.cgi?id=173677
Source/_javascript_Core:

<rdar://problem/32178892>

Reviewed by JF Bastien.

Using the breakpoint instruction for VMTraps caused issues with lldb.
Since we only need some way to stop execution we can, in theory, use
any exceptioning instruction we want. I went with the halt instruction
on X86 since that is the only one byte instruction that does not
breakpoint (in my tests both 0xf1 and 0xd6 produced EXC_BREAKPOINT).
On ARM we use the data cache clearing instruction with the zero register,
which triggers a segmentation fault.

Also, update the platform code to only use signaling VMTraps
on where we have an appropriate instruction (x86 and ARM64).

* API/tests/ExecutionTimeLimitTest.cpp:
(testExecutionTimeLimit):
* assembler/ARM64Assembler.h:
(JSC::ARM64Assembler::replaceWithVMHalt):
(JSC::ARM64Assembler::dataCacheZeroVirtualAddress):
(JSC::ARM64Assembler::replaceWithBkpt): Deleted.
* assembler/ARMAssembler.h:
(JSC::ARMAssembler::replaceWithBkpt): Deleted.
* assembler/ARMv7Assembler.h:
(JSC::ARMv7Assembler::replaceWithBkpt): Deleted.
* assembler/MIPSAssembler.h:
(JSC::MIPSAssembler::replaceWithBkpt): Deleted.
* assembler/MacroAssemblerARM.h:
(JSC::MacroAssemblerARM::replaceWithBreakpoint): Deleted.
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::replaceWithVMHalt):
(JSC::MacroAssemblerARM64::replaceWithBreakpoint): Deleted.
* assembler/MacroAssemblerARMv7.h:
(JSC::MacroAssemblerARMv7::storeFence):
(JSC::MacroAssemblerARMv7::replaceWithBreakpoint): Deleted.
* assembler/MacroAssemblerMIPS.h:
(JSC::MacroAssemblerMIPS::replaceWithBreakpoint): Deleted.
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::replaceWithVMHalt):
(JSC::MacroAssemblerX86Common::replaceWithBreakpoint): Deleted.
* assembler/X86Assembler.h:
(JSC::X86Assembler::replaceWithHlt):
(JSC::X86Assembler::replaceWithInt3): Deleted.
* dfg/DFGJumpReplacement.cpp:
(JSC::DFG::JumpReplacement::installVMTrapBreakpoint):
* runtime/VMTraps.cpp:
(JSC::SignalContext::SignalContext):
(JSC::installSignalHandler):
(JSC::SignalContext::adjustPCToPointToTrappingInstruction): Deleted.
* wasm/WasmFaultSignalHandler.cpp:
(JSC::Wasm::enableFastMemory):

Source/WTF:

<rdar://problem/32178892>

Reviewed by JF Bastien.

Remove the Trap signal handler code since it plays badly with lldb and combine
SIGBUS with SIGSEGV since distiguishing them is generally non-portable.

Also, update the platform code to only use signaling VMTraps
on where we have an appropriate instruction (x86 and ARM64).

* wtf/Platform.h:
* wtf/threads/Signals.cpp:
(WTF::fromMachException):
(WTF::toMachMask):
(WTF::installSignalHandler):
(WTF::jscSignalHandler):
* wtf/threads/Signals.h:
(WTF::toSystemSignal):
(WTF::fromSystemSignal):

Tools:

Reviewed by JF Bastien.

* TestWebKitAPI/Tests/WTF/ThreadMessages.cpp:
(TEST):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/API/tests/ExecutionTimeLimitTest.cpp (218781 => 218782)


--- trunk/Source/_javascript_Core/API/tests/ExecutionTimeLimitTest.cpp	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/API/tests/ExecutionTimeLimitTest.cpp	2017-06-24 02:54:02 UTC (rev 218782)
@@ -121,8 +121,8 @@
     static const TierOptions tierOptionsList[] = {
         { "LLINT",    0,   "--useConcurrentJIT=false --useLLInt=true --useJIT=false" },
         { "Baseline", 0,   "--useConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=false" },
-        { "DFG",      0,   "--useConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=false" },
-        { "FTL",      200, "--useConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=true" },
+        { "DFG",      200,   "--useConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=false" },
+        { "FTL",      500, "--useConcurrentJIT=false --useLLInt=true --useJIT=true --useDFGJIT=true --useFTLJIT=true" },
     };
     
     bool failed = false;
@@ -151,7 +151,39 @@
         JSObjectRef currentCPUTimeFunction = JSObjectMakeFunctionWithCallback(context, currentCPUTimeStr, currentCPUTimeAsJSFunctionCallback);
         JSObjectSetProperty(context, globalObject, currentCPUTimeStr, currentCPUTimeFunction, kJSPropertyAttributeNone, nullptr);
         JSStringRelease(currentCPUTimeStr);
-        
+
+        /* Test script on another thread: */
+        timeLimit = (100 + tierAdjustmentMillis) / 1000.0;
+        JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, shouldTerminateCallback, 0);
+        {
+            unsigned timeAfterWatchdogShouldHaveFired = 300 + tierAdjustmentMillis;
+
+            JSStringRef script = JSStringCreateWithUTF8CString("function foo() { while (true) { } } foo();");
+            exception = nullptr;
+            JSValueRef* exn = &exception;
+            shouldTerminateCallbackWasCalled = false;
+            auto thread = Thread::create("Rogue thread", [=] {
+                JSEvaluateScript(context, script, nullptr, nullptr, 1, exn);
+            });
+
+            sleep(Seconds(timeAfterWatchdogShouldHaveFired / 1000.0));
+
+            if (shouldTerminateCallbackWasCalled)
+                printf("PASS: %s script timed out as expected.\n", tierOptions.tier);
+            else {
+                printf("FAIL: %s script timeout callback was not called.\n", tierOptions.tier);
+                exit(1);
+            }
+
+            if (!exception) {
+                printf("FAIL: %s TerminatedExecutionException was not thrown.\n", tierOptions.tier);
+                exit(1);
+            }
+
+            thread->waitForCompletion();
+            testResetAfterTimeout(failed);
+        }
+
         /* Test script timeout: */
         timeLimit = (100 + tierAdjustmentMillis) / 1000.0;
         JSContextGroupSetExecutionTimeLimit(contextGroup, timeLimit, shouldTerminateCallback, 0);

Modified: trunk/Source/_javascript_Core/API/tests/testapi.c (218781 => 218782)


--- trunk/Source/_javascript_Core/API/tests/testapi.c	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/API/tests/testapi.c	2017-06-24 02:54:02 UTC (rev 218782)
@@ -1348,6 +1348,7 @@
     ::SetErrorMode(0);
 #endif
 
+    testExecutionTimeLimit();
     testCompareAndSwap();
     startMultithreadedMultiVMExecutionTest();
 

Modified: trunk/Source/_javascript_Core/ChangeLog (218781 => 218782)


--- trunk/Source/_javascript_Core/ChangeLog	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-06-24 02:54:02 UTC (rev 218782)
@@ -1,3 +1,59 @@
+2017-06-23  Keith Miller  <[email protected]>
+
+        Switch VMTraps to use halt instructions rather than breakpoint instructions
+        https://bugs.webkit.org/show_bug.cgi?id=173677
+        <rdar://problem/32178892>
+
+        Reviewed by JF Bastien.
+
+        Using the breakpoint instruction for VMTraps caused issues with lldb.
+        Since we only need some way to stop execution we can, in theory, use
+        any exceptioning instruction we want. I went with the halt instruction
+        on X86 since that is the only one byte instruction that does not
+        breakpoint (in my tests both 0xf1 and 0xd6 produced EXC_BREAKPOINT).
+        On ARM we use the data cache clearing instruction with the zero register,
+        which triggers a segmentation fault.
+
+        Also, update the platform code to only use signaling VMTraps
+        on where we have an appropriate instruction (x86 and ARM64).
+
+        * API/tests/ExecutionTimeLimitTest.cpp:
+        (testExecutionTimeLimit):
+        * assembler/ARM64Assembler.h:
+        (JSC::ARM64Assembler::replaceWithVMHalt):
+        (JSC::ARM64Assembler::dataCacheZeroVirtualAddress):
+        (JSC::ARM64Assembler::replaceWithBkpt): Deleted.
+        * assembler/ARMAssembler.h:
+        (JSC::ARMAssembler::replaceWithBkpt): Deleted.
+        * assembler/ARMv7Assembler.h:
+        (JSC::ARMv7Assembler::replaceWithBkpt): Deleted.
+        * assembler/MIPSAssembler.h:
+        (JSC::MIPSAssembler::replaceWithBkpt): Deleted.
+        * assembler/MacroAssemblerARM.h:
+        (JSC::MacroAssemblerARM::replaceWithBreakpoint): Deleted.
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::replaceWithVMHalt):
+        (JSC::MacroAssemblerARM64::replaceWithBreakpoint): Deleted.
+        * assembler/MacroAssemblerARMv7.h:
+        (JSC::MacroAssemblerARMv7::storeFence):
+        (JSC::MacroAssemblerARMv7::replaceWithBreakpoint): Deleted.
+        * assembler/MacroAssemblerMIPS.h:
+        (JSC::MacroAssemblerMIPS::replaceWithBreakpoint): Deleted.
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::replaceWithVMHalt):
+        (JSC::MacroAssemblerX86Common::replaceWithBreakpoint): Deleted.
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::replaceWithHlt):
+        (JSC::X86Assembler::replaceWithInt3): Deleted.
+        * dfg/DFGJumpReplacement.cpp:
+        (JSC::DFG::JumpReplacement::installVMTrapBreakpoint):
+        * runtime/VMTraps.cpp:
+        (JSC::SignalContext::SignalContext):
+        (JSC::installSignalHandler):
+        (JSC::SignalContext::adjustPCToPointToTrappingInstruction): Deleted.
+        * wasm/WasmFaultSignalHandler.cpp:
+        (JSC::Wasm::enableFastMemory):
+
 2017-06-22  Saam Barati  <[email protected]>
 
         The lowering of Identity in the DFG backend needs to use ManualOperandSpeculation

Modified: trunk/Source/_javascript_Core/assembler/ARM64Assembler.h (218781 => 218782)


--- trunk/Source/_javascript_Core/assembler/ARM64Assembler.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/assembler/ARM64Assembler.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -2602,9 +2602,10 @@
         linkPointer(addressOf(code, where), valuePtr);
     }
 
-    static void replaceWithBkpt(void* where)
+    static void replaceWithVMHalt(void* where)
     {
-        int insn = excepnGeneration(ExcepnOp_BREAKPOINT, 0, 0);
+        // This should try to write to null which should always Segfault.
+        int insn = dataCacheZeroVirtualAddress(ARM64Registers::zr);
         performJITMemcpy(where, &insn, sizeof(int));
         cacheFlush(where, sizeof(int));
     }
@@ -3655,6 +3656,11 @@
     {
         return hintPseudo(0);
     }
+
+    ALWAYS_INLINE static int dataCacheZeroVirtualAddress(RegisterID rt)
+    {
+        return system(0, 1, 0x3, 0x7, 0x4, 0x1, rt);
+    }
     
     // 'op' means negate
     ALWAYS_INLINE static int testAndBranchImmediate(bool op, int b50, int imm14, RegisterID rt)

Modified: trunk/Source/_javascript_Core/assembler/ARMAssembler.h (218781 => 218782)


--- trunk/Source/_javascript_Core/assembler/ARMAssembler.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/assembler/ARMAssembler.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -995,13 +995,6 @@
             return reinterpret_cast<void*>(readPointer(reinterpret_cast<void*>(getAbsoluteJumpAddress(from))));
         }
 
-        static void replaceWithBkpt(void* instructionStart)
-        {
-            ARMWord* instruction = reinterpret_cast<ARMWord*>(instructionStart);
-            instruction[0] = BKPT;
-            cacheFlush(instruction, sizeof(ARMWord));
-        }
-
         static void replaceWithJump(void* instructionStart, void* to)
         {
             ARMWord* instruction = reinterpret_cast<ARMWord*>(instructionStart);

Modified: trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h (218781 => 218782)


--- trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -2328,16 +2328,6 @@
         return reinterpret_cast<void*>(readInt32(where));
     }
 
-    static void replaceWithBkpt(void* instructionStart)
-    {
-        ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 1));
-
-        uint16_t* ptr = reinterpret_cast<uint16_t*>(instructionStart);
-        uint16_t instructions = OP_BKPT;
-        performJITMemcpy(ptr, &instructions, sizeof(uint16_t));
-        cacheFlush(ptr, sizeof(uint16_t));
-    }
-
     static void replaceWithJump(void* instructionStart, void* to)
     {
         ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 1));

Modified: trunk/Source/_javascript_Core/assembler/MIPSAssembler.h (218781 => 218782)


--- trunk/Source/_javascript_Core/assembler/MIPSAssembler.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/assembler/MIPSAssembler.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -941,15 +941,6 @@
         cacheFlush(insn, codeSize);
     }
 
-    static void replaceWithBkpt(void* instructionStart)
-    {
-        ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 3));
-        MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(instructionStart));
-        int value = 512; /* BRK_BUG */
-        insn[0] = (0x0000000d | ((value & 0x3ff) << OP_SH_CODE));
-        cacheFlush(instructionStart, sizeof(MIPSWord));
-    }
-
     static void replaceWithJump(void* instructionStart, void* to)
     {
         ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 3));

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h (218781 => 218782)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -1499,11 +1499,6 @@
         return FunctionPtr(reinterpret_cast<void(*)()>(ARMAssembler::readCallTarget(call.dataLocation())));
     }
 
-    static void replaceWithBreakpoint(CodeLocationLabel instructionStart)
-    {
-        ARMAssembler::replaceWithBkpt(instructionStart.executableAddress());
-    }
-
     static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
     {
         ARMAssembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation());

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (218781 => 218782)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -3713,9 +3713,9 @@
         return FunctionPtr(reinterpret_cast<void(*)()>(ARM64Assembler::readCallTarget(call.dataLocation())));
     }
 
-    static void replaceWithBreakpoint(CodeLocationLabel instructionStart)
+    static void replaceWithVMHalt(CodeLocationLabel instructionStart)
     {
-        ARM64Assembler::replaceWithBkpt(instructionStart.executableAddress());
+        ARM64Assembler::replaceWithVMHalt(instructionStart.executableAddress());
     }
 
     static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h (218781 => 218782)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -1354,11 +1354,6 @@
     {
         m_assembler.dmbISHST();
     }
-    
-    static void replaceWithBreakpoint(CodeLocationLabel instructionStart)
-    {
-        ARMv7Assembler::replaceWithBkpt(instructionStart.dataLocation());
-    }
 
     static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
     {

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h (218781 => 218782)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -3072,11 +3072,6 @@
         return FunctionPtr(reinterpret_cast<void(*)()>(MIPSAssembler::readCallTarget(call.dataLocation())));
     }
 
-    static void replaceWithBreakpoint(CodeLocationLabel instructionStart)
-    {
-        MIPSAssembler::replaceWithBkpt(instructionStart.executableAddress());
-    }
-
     static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
     {
         MIPSAssembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation());

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (218781 => 218782)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -3803,9 +3803,9 @@
     }
 #endif
 
-    static void replaceWithBreakpoint(CodeLocationLabel instructionStart)
+    static void replaceWithVMHalt(CodeLocationLabel instructionStart)
     {
-        X86Assembler::replaceWithInt3(instructionStart.executableAddress());
+        X86Assembler::replaceWithHlt(instructionStart.executableAddress());
     }
 
     static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)

Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (218781 => 218782)


--- trunk/Source/_javascript_Core/assembler/X86Assembler.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -3637,10 +3637,10 @@
         return reinterpret_cast<void**>(where)[-1];
     }
 
-    static void replaceWithInt3(void* instructionStart)
+    static void replaceWithHlt(void* instructionStart)
     {
         uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart);
-        ptr[0] = static_cast<uint8_t>(OP_INT3);
+        ptr[0] = static_cast<uint8_t>(OP_HLT);
     }
 
     static void replaceWithJump(void* instructionStart, void* to)

Modified: trunk/Source/_javascript_Core/dfg/DFGJumpReplacement.cpp (218781 => 218782)


--- trunk/Source/_javascript_Core/dfg/DFGJumpReplacement.cpp	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/dfg/DFGJumpReplacement.cpp	2017-06-24 02:54:02 UTC (rev 218782)
@@ -43,7 +43,11 @@
 
 void JumpReplacement::installVMTrapBreakpoint()
 {
-    MacroAssembler::replaceWithBreakpoint(m_source);
+#if ENABLE(SIGNAL_BASED_VM_TRAPS)
+    MacroAssembler::replaceWithVMHalt(m_source);
+#else
+    UNREACHABLE_FOR_PLATFORM();
+#endif
 }
 
 } } // namespace JSC::DFG

Modified: trunk/Source/_javascript_Core/runtime/VMTraps.cpp (218781 => 218782)


--- trunk/Source/_javascript_Core/runtime/VMTraps.cpp	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/runtime/VMTraps.cpp	2017-06-24 02:54:02 UTC (rev 218782)
@@ -59,19 +59,8 @@
         , stackPointer(MachineContext::stackPointer(registers))
         , framePointer(MachineContext::framePointer(registers))
     {
-#if CPU(X86_64) || CPU(X86)
-        // On X86_64, SIGTRAP reports the address after the trapping PC. So, dec by 1.
-        trapPC = reinterpret_cast<uint8_t*>(trapPC) - 1;
-#endif
     }
 
-    void adjustPCToPointToTrappingInstruction()
-    {
-#if CPU(X86_64) || CPU(X86)
-        MachineContext::instructionPointer(registers) = trapPC;
-#endif
-    }
-
     PlatformRegisters& registers;
     void* trapPC;
     void* stackPointer;
@@ -130,7 +119,7 @@
 
 static void installSignalHandler()
 {
-    installSignalHandler(Signal::Trap, [] (Signal, SigInfo&, PlatformRegisters& registers) -> SignalAction {
+    installSignalHandler(Signal::BadAccess, [] (Signal, SigInfo&, PlatformRegisters& registers) -> SignalAction {
         SignalContext context(registers);
 
         if (!isJITPC(context.trapPC))
@@ -297,10 +286,6 @@
         return false;
 
     invalidateCodeBlocksOnStack(codeBlockSetLocker, topCallFrame);
-
-    // Re-run the trapping instruction now that we've patched it with the invalidation
-    // OSR exit off-ramp.
-    context.adjustPCToPointToTrappingInstruction();
     return true;
 }
 

Modified: trunk/Source/_javascript_Core/wasm/WasmFaultSignalHandler.cpp (218781 => 218782)


--- trunk/Source/_javascript_Core/wasm/WasmFaultSignalHandler.cpp	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/_javascript_Core/wasm/WasmFaultSignalHandler.cpp	2017-06-24 02:54:02 UTC (rev 218782)
@@ -123,14 +123,10 @@
             return;
 
 #if ENABLE(WEBASSEMBLY_FAST_MEMORY)
-        installSignalHandler(Signal::Bus, [] (Signal signal, SigInfo& sigInfo, PlatformRegisters& ucontext) {
+        installSignalHandler(Signal::BadAccess, [] (Signal signal, SigInfo& sigInfo, PlatformRegisters& ucontext) {
             return trapHandler(signal, sigInfo, ucontext);
         });
 
-        installSignalHandler(Signal::SegV, [] (Signal signal, SigInfo& sigInfo, PlatformRegisters& ucontext) {
-            return trapHandler(signal, sigInfo, ucontext);
-        });
-
         codeLocations.construct();
         fastHandlerInstalled = true;
 #endif // ENABLE(WEBASSEMBLY_FAST_MEMORY)

Modified: trunk/Source/WTF/ChangeLog (218781 => 218782)


--- trunk/Source/WTF/ChangeLog	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/WTF/ChangeLog	2017-06-24 02:54:02 UTC (rev 218782)
@@ -1,3 +1,27 @@
+2017-06-23  Keith Miller  <[email protected]>
+
+        Switch VMTraps to use halt instructions rather than breakpoint instructions
+        https://bugs.webkit.org/show_bug.cgi?id=173677
+        <rdar://problem/32178892>
+
+        Reviewed by JF Bastien.
+
+        Remove the Trap signal handler code since it plays badly with lldb and combine
+        SIGBUS with SIGSEGV since distiguishing them is generally non-portable.
+
+        Also, update the platform code to only use signaling VMTraps
+        on where we have an appropriate instruction (x86 and ARM64).
+
+        * wtf/Platform.h:
+        * wtf/threads/Signals.cpp:
+        (WTF::fromMachException):
+        (WTF::toMachMask):
+        (WTF::installSignalHandler):
+        (WTF::jscSignalHandler):
+        * wtf/threads/Signals.h:
+        (WTF::toSystemSignal):
+        (WTF::fromSystemSignal):
+
 2017-06-23  Antti Koivisto  <[email protected]>
 
         Add notifyutil registrations for going in and out of simulated low memory state

Modified: trunk/Source/WTF/wtf/Platform.h (218781 => 218782)


--- trunk/Source/WTF/wtf/Platform.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/WTF/wtf/Platform.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -974,7 +974,7 @@
 #endif
 #endif
 
-#if ENABLE(JIT) && HAVE(MACHINE_CONTEXT)
+#if ENABLE(JIT) && HAVE(MACHINE_CONTEXT) && (CPU(X86) || CPU(X86_64) || CPU(ARM64))
 #define ENABLE_SIGNAL_BASED_VM_TRAPS 1
 #endif
 

Modified: trunk/Source/WTF/wtf/threads/Signals.cpp (218781 => 218782)


--- trunk/Source/WTF/wtf/threads/Signals.cpp	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/WTF/wtf/threads/Signals.cpp	2017-06-24 02:54:02 UTC (rev 218782)
@@ -117,9 +117,8 @@
 static Signal fromMachException(exception_type_t type)
 {
     switch (type) {
-    case EXC_BAD_ACCESS: return Signal::SegV;
+    case EXC_BAD_ACCESS: return Signal::BadAccess;
     case EXC_BAD_INSTRUCTION: return Signal::Ill;
-    case EXC_BREAKPOINT: return Signal::Trap;
     default: break;
     }
     return Signal::Unknown;
@@ -128,9 +127,8 @@
 static exception_mask_t toMachMask(Signal signal)
 {
     switch (signal) {
-    case Signal::SegV: return EXC_MASK_BAD_ACCESS;
+    case Signal::BadAccess: return EXC_MASK_BAD_ACCESS;
     case Signal::Ill: return EXC_MASK_BAD_INSTRUCTION;
-    case Signal::Trap: return EXC_MASK_BREAKPOINT;
     default: break;
     }
     RELEASE_ASSERT_NOT_REACHED();
@@ -166,6 +164,11 @@
     mach_msg_type_number_t* outStateCount)
 {
     RELEASE_ASSERT(port == exceptionPort);
+    // If we wanted to distinguish between SIGBUS and SIGSEGV for EXC_BAD_ACCESS on Darwin we could do:
+    // if (exceptionData[0] == KERN_INVALID_ADDRESS)
+    //    signal = SIGSEGV;
+    // else
+    //    signal = SIGBUS;
     Signal signal = fromMachException(exceptionType);
     RELEASE_ASSERT(signal != Signal::Unknown);
 
@@ -187,7 +190,7 @@
 #endif
 
     SigInfo info;
-    if (signal == Signal::SegV) {
+    if (signal == Signal::BadAccess) {
         ASSERT_UNUSED(dataCount, dataCount == 2);
         info.faultingAddress = reinterpret_cast<void*>(exceptionData[1]);
     }
@@ -249,6 +252,13 @@
 static constexpr bool useMach = false;
 #endif // HAVE(MACH_EXCEPTIONS)
 
+
+inline size_t offsetForSystemSignal(int sig)
+{
+    Signal signal = fromSystemSignal(sig);
+    return static_cast<size_t>(signal) + (sig == SIGBUS);
+}
+
 static void jscSignalHandler(int, siginfo_t*, void*);
 
 void installSignalHandler(Signal signal, SignalHandler&& handler)
@@ -255,12 +265,6 @@
 {
     ASSERT(signal < Signal::Unknown);
 #if HAVE(MACH_EXCEPTIONS)
-    // Since mach only has EXC_BAD_ACCESS, which covers both SegV and Bus, we arbitarily choose to make
-    // mach EXC_BAD_ACCESSes map to SegV.
-    // FIXME: We should just use a single Signal::BadAccess value instead of SegV/Bus.
-    // See: https://bugs.webkit.org/show_bug.cgi?id=172063
-    if (signal == Signal::Bus && useMach)
-        return;
     ASSERT(!useMach || signal != Signal::Usr);
 
     if (useMach)
@@ -276,7 +280,10 @@
             auto result = sigfillset(&action.sa_mask);
             RELEASE_ASSERT(!result);
             action.sa_flags = SA_SIGINFO;
-            result = sigaction(toSystemSignal(signal), &action, &oldActions[static_cast<size_t>(signal)]);
+            auto systemSignals = toSystemSignal(signal);
+            result = sigaction(std::get<0>(systemSignals), &action, &oldActions[offsetForSystemSignal(std::get<0>(systemSignals))]);
+            if (std::get<1>(systemSignals))
+                result |= sigaction(*std::get<1>(systemSignals), &action, &oldActions[offsetForSystemSignal(*std::get<1>(systemSignals))]);
             RELEASE_ASSERT(!result);
         }
 
@@ -316,7 +323,7 @@
     }
 
     SigInfo sigInfo;
-    if (signal == Signal::SegV || signal == Signal::Bus)
+    if (signal == Signal::BadAccess)
         sigInfo.faultingAddress = info->si_addr;
 
     PlatformRegisters& registers = registersFromUContext(reinterpret_cast<ucontext_t*>(ucontext));
@@ -341,7 +348,8 @@
         return;
     }
 
-    struct sigaction& oldAction = oldActions[static_cast<size_t>(signal)];
+    unsigned oldActionIndex = static_cast<size_t>(signal) + (sig == SIGBUS);
+    struct sigaction& oldAction = oldActions[static_cast<size_t>(oldActionIndex)];
     if (signal == Signal::Usr) {
         if (oldAction.sa_sigaction)
             oldAction.sa_sigaction(sig, info, ucontext);

Modified: trunk/Source/WTF/wtf/threads/Signals.h (218781 => 218782)


--- trunk/Source/WTF/wtf/threads/Signals.h	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Source/WTF/wtf/threads/Signals.h	2017-06-24 02:54:02 UTC (rev 218782)
@@ -29,6 +29,7 @@
 
 #include <signal.h>
 #include <wtf/Function.h>
+#include <wtf/Optional.h>
 #include <wtf/PlatformRegisters.h>
 
 namespace WTF {
@@ -41,22 +42,18 @@
 
     // These signals will only chain if we don't have a handler that can process them. If there is nothing
     // to chain to we restore the default handler and crash.
-    Trap,
     Ill,
-    SegV,
-    Bus,
-    NumberOfSignals,
+    BadAccess, // For posix this is both SIGSEGV and SIGBUS
+    NumberOfSignals = BadAccess + 2, // BadAccess is really two signals.
     Unknown = NumberOfSignals
 };
 
-inline int toSystemSignal(Signal signal)
+inline std::tuple<int, std::optional<int>> toSystemSignal(Signal signal)
 {
     switch (signal) {
-    case Signal::SegV: return SIGSEGV;
-    case Signal::Bus: return SIGBUS;
-    case Signal::Ill: return SIGILL;
-    case Signal::Usr: return SIGUSR2;
-    case Signal::Trap: return SIGTRAP;
+    case Signal::BadAccess: return std::make_tuple(SIGSEGV, SIGBUS);
+    case Signal::Ill: return std::make_tuple(SIGILL, std::nullopt);
+    case Signal::Usr: return std::make_tuple(SIGILL, std::nullopt);
     default: break;
     }
     RELEASE_ASSERT_NOT_REACHED();
@@ -65,11 +62,10 @@
 inline Signal fromSystemSignal(int signal)
 {
     switch (signal) {
-    case SIGSEGV: return Signal::SegV;
-    case SIGBUS: return Signal::Bus;
+    case SIGSEGV: return Signal::BadAccess;
+    case SIGBUS: return Signal::BadAccess;
     case SIGILL: return Signal::Ill;
     case SIGUSR2: return Signal::Usr;
-    case SIGTRAP: return Signal::Trap;
     default: return Signal::Unknown;
     }
 }

Modified: trunk/Tools/ChangeLog (218781 => 218782)


--- trunk/Tools/ChangeLog	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Tools/ChangeLog	2017-06-24 02:54:02 UTC (rev 218782)
@@ -1,3 +1,13 @@
+2017-06-23  Keith Miller  <[email protected]>
+
+        Switch VMTraps to use halt instructions rather than breakpoint instructions
+        https://bugs.webkit.org/show_bug.cgi?id=173677
+
+        Reviewed by JF Bastien.
+
+        * TestWebKitAPI/Tests/WTF/ThreadMessages.cpp:
+        (TEST):
+
 2017-06-23  Youenn Fablet  <[email protected]>
 
         Set getUserMedia permission to true by default on WTR

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/ThreadMessages.cpp (218781 => 218782)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/ThreadMessages.cpp	2017-06-24 02:45:51 UTC (rev 218781)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/ThreadMessages.cpp	2017-06-24 02:54:02 UTC (rev 218782)
@@ -114,7 +114,7 @@
         receiverShouldKeepRunning.store(false);
         EXPECT_FALSE(static_cast<ReflectedThread*>(receiverThread.get())->hasExited());
         sleep(1);
-        signalFired = !pthread_kill(static_cast<ReflectedThread*>(receiverThread.get())->m_handle, toSystemSignal(Signal::Usr));
+        signalFired = !pthread_kill(static_cast<ReflectedThread*>(receiverThread.get())->m_handle, std::get<0>(toSystemSignal(Signal::Usr)));
     }
 
     receiverThread->waitForCompletion();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to