1/*
2 * Copyright (C) 2012-2019 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 "JITExceptions.h"
28
29#include "CallFrame.h"
30#include "CatchScope.h"
31#include "CodeBlock.h"
32#include "Disassembler.h"
33#include "EntryFrame.h"
34#include "Interpreter.h"
35#include "JSCInlines.h"
36#include "JSCJSValue.h"
37#include "LLIntData.h"
38#include "LLIntOpcode.h"
39#include "LLIntThunks.h"
40#include "Opcode.h"
41#include "ShadowChicken.h"
42#include "VMInlines.h"
43
44namespace JSC {
45
46void genericUnwind(VM& vm, CallFrame* callFrame)
47{
48 auto scope = DECLARE_CATCH_SCOPE(vm);
49 CallFrame* topJSCallFrame = vm.topJSCallFrame();
50 if (Options::breakOnThrow()) {
51 CodeBlock* codeBlock = topJSCallFrame->codeBlock();
52 dataLog("In call frame ", RawPointer(topJSCallFrame), " for code block ", codeBlock, "\n");
53 CRASH();
54 }
55
56 if (auto* shadowChicken = vm.shadowChicken())
57 shadowChicken->log(vm, topJSCallFrame, ShadowChicken::Packet::throwPacket());
58
59 Exception* exception = scope.exception();
60 RELEASE_ASSERT(exception);
61 HandlerInfo* handler = vm.interpreter->unwind(vm, callFrame, exception); // This may update callFrame.
62
63 void* catchRoutine;
64 const Instruction* catchPCForInterpreter = nullptr;
65 if (handler) {
66 // handler->target is meaningless for getting a code offset when catching
67 // the exception in a DFG/FTL frame. This bytecode target offset could be
68 // something that's in an inlined frame, which means an array access
69 // with this bytecode offset in the machine frame is utterly meaningless
70 // and can cause an overflow. OSR exit properly exits to handler->target
71 // in the proper frame.
72 if (!JITCode::isOptimizingJIT(callFrame->codeBlock()->jitType()))
73 catchPCForInterpreter = callFrame->codeBlock()->instructions().at(handler->target).ptr();
74#if ENABLE(JIT)
75 catchRoutine = handler->nativeCode.executableAddress();
76#else
77 if (catchPCForInterpreter->isWide32())
78 catchRoutine = LLInt::getWide32CodePtr(catchPCForInterpreter->opcodeID());
79 else if (catchPCForInterpreter->isWide16())
80 catchRoutine = LLInt::getWide16CodePtr(catchPCForInterpreter->opcodeID());
81 else
82 catchRoutine = LLInt::getCodePtr(catchPCForInterpreter->opcodeID());
83#endif
84 } else
85 catchRoutine = LLInt::getCodePtr<ExceptionHandlerPtrTag>(handleUncaughtException).executableAddress();
86
87 ASSERT(bitwise_cast<uintptr_t>(callFrame) < bitwise_cast<uintptr_t>(vm.topEntryFrame));
88
89 assertIsTaggedWith(catchRoutine, ExceptionHandlerPtrTag);
90 vm.callFrameForCatch = callFrame;
91 vm.targetMachinePCForThrow = catchRoutine;
92 vm.targetInterpreterPCForThrow = catchPCForInterpreter;
93
94 RELEASE_ASSERT(catchRoutine);
95}
96
97} // namespace JSC
98