1/* 2 * Copyright (C) 2013, 2014 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 "FTLUnwindInfo.h" 28 29#if ENABLE(FTL_JIT) 30 31#include <mach-o/compact_unwind_encoding.h> 32#include <wtf/ListDump.h> 33 34namespace JSC { namespace FTL { 35 36UnwindInfo::UnwindInfo() { } 37UnwindInfo::~UnwindInfo() { } 38 39namespace { 40 41struct CompactUnwind { 42 void* function; 43 uint32_t size; 44 compact_unwind_encoding_t encoding; 45 void* personality; 46 void* lsda; 47}; 48 49} // anonymous namespace 50 51bool UnwindInfo::parse(void* section, size_t size, GeneratedFunction generatedFunction) 52{ 53 m_registers.clear(); 54 55 RELEASE_ASSERT(!!section == !!size); 56 if (!section) 57 return false; 58 59 RELEASE_ASSERT(size >= sizeof(CompactUnwind)); 60 61 CompactUnwind* data = bitwise_cast<CompactUnwind*>(section); 62 63 RELEASE_ASSERT(!data->personality); // We don't know how to handle this. 64 RELEASE_ASSERT(!data->lsda); // We don't know how to handle this. 65 RELEASE_ASSERT(data->function == generatedFunction); // The unwind data better be for our function. 66 67 compact_unwind_encoding_t encoding = data->encoding; 68 RELEASE_ASSERT(!(encoding & UNWIND_IS_NOT_FUNCTION_START)); 69 RELEASE_ASSERT(!(encoding & UNWIND_HAS_LSDA)); 70 RELEASE_ASSERT(!(encoding & UNWIND_PERSONALITY_MASK)); 71 72#if CPU(X86_64) 73 RELEASE_ASSERT((encoding & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_RBP_FRAME); 74 75 int32_t offset = -((encoding & UNWIND_X86_64_RBP_FRAME_OFFSET) >> 16) * 8; 76 uint32_t nextRegisters = encoding; 77 for (unsigned i = 5; i--;) { 78 uint32_t currentRegister = nextRegisters & 7; 79 nextRegisters >>= 3; 80 81 switch (currentRegister) { 82 case UNWIND_X86_64_REG_NONE: 83 break; 84 85 case UNWIND_X86_64_REG_RBX: 86 m_registers.append(RegisterAtOffset(X86Registers::ebx, offset)); 87 break; 88 89 case UNWIND_X86_64_REG_R12: 90 m_registers.append(RegisterAtOffset(X86Registers::r12, offset)); 91 break; 92 93 case UNWIND_X86_64_REG_R13: 94 m_registers.append(RegisterAtOffset(X86Registers::r13, offset)); 95 break; 96 97 case UNWIND_X86_64_REG_R14: 98 m_registers.append(RegisterAtOffset(X86Registers::r14, offset)); 99 break; 100 101 case UNWIND_X86_64_REG_R15: 102 m_registers.append(RegisterAtOffset(X86Registers::r15, offset)); 103 break; 104 105 case UNWIND_X86_64_REG_RBP: 106 m_registers.append(RegisterAtOffset(X86Registers::ebp, offset)); 107 break; 108 109 default: 110 RELEASE_ASSERT_NOT_REACHED(); 111 } 112 113 offset += 8; 114 } 115#elif CPU(ARM64) 116 RELEASE_ASSERT((encoding & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_FRAME); 117 118 m_registers.append(RegisterAtOffset(ARM64Registers::fp, 0)); 119 120 int32_t offset = 0; 121 if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { 122 m_registers.append(RegisterAtOffset(ARM64Registers::x19, offset -= 8)); 123 m_registers.append(RegisterAtOffset(ARM64Registers::x20, offset -= 8)); 124 } 125 if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { 126 m_registers.append(RegisterAtOffset(ARM64Registers::x21, offset -= 8)); 127 m_registers.append(RegisterAtOffset(ARM64Registers::x22, offset -= 8)); 128 } 129 if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { 130 m_registers.append(RegisterAtOffset(ARM64Registers::x23, offset -= 8)); 131 m_registers.append(RegisterAtOffset(ARM64Registers::x24, offset -= 8)); 132 } 133 if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { 134 m_registers.append(RegisterAtOffset(ARM64Registers::x25, offset -= 8)); 135 m_registers.append(RegisterAtOffset(ARM64Registers::x26, offset -= 8)); 136 } 137 if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { 138 m_registers.append(RegisterAtOffset(ARM64Registers::x27, offset -= 8)); 139 m_registers.append(RegisterAtOffset(ARM64Registers::x28, offset -= 8)); 140 } 141 if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { 142 m_registers.append(RegisterAtOffset(ARM64Registers::q8, offset -= 8)); 143 m_registers.append(RegisterAtOffset(ARM64Registers::q9, offset -= 8)); 144 } 145 if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { 146 m_registers.append(RegisterAtOffset(ARM64Registers::q10, offset -= 8)); 147 m_registers.append(RegisterAtOffset(ARM64Registers::q11, offset -= 8)); 148 } 149 if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { 150 m_registers.append(RegisterAtOffset(ARM64Registers::q12, offset -= 8)); 151 m_registers.append(RegisterAtOffset(ARM64Registers::q13, offset -= 8)); 152 } 153 if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { 154 m_registers.append(RegisterAtOffset(ARM64Registers::q14, offset -= 8)); 155 m_registers.append(RegisterAtOffset(ARM64Registers::q15, offset -= 8)); 156 } 157#else 158#error "Unrecognized architecture" 159#endif 160 161 std::sort(m_registers.begin(), m_registers.end()); 162 return true; 163} 164 165void UnwindInfo::dump(PrintStream& out) const 166{ 167 out.print(listDump(m_registers)); 168} 169 170RegisterAtOffset* UnwindInfo::find(Reg reg) const 171{ 172 return tryBinarySearch<RegisterAtOffset, Reg>(m_registers, m_registers.size(), reg, RegisterAtOffset::getReg); 173} 174 175unsigned UnwindInfo::indexOf(Reg reg) const 176{ 177 if (RegisterAtOffset* pointer = find(reg)) 178 return pointer - m_registers.begin(); 179 return UINT_MAX; 180} 181 182} } // namespace JSC::FTL 183 184#endif // ENABLE(FTL_JIT) 185 186