diff options
Diffstat (limited to 'Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp')
| -rw-r--r-- | Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp | 1044 |
1 files changed, 0 insertions, 1044 deletions
diff --git a/Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp b/Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp deleted file mode 100644 index 2867a7245..000000000 --- a/Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp +++ /dev/null @@ -1,1044 +0,0 @@ -/* - * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. - * Copyright (C) 2014 Samsung Electronics - * Copyright (C) 2014 University of Szeged - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ============================================================================== - * - * University of Illinois/NCSA - * Open Source License - * - * Copyright (c) 2009-2014 by the contributors of LLVM/libc++abi project. - * - * All rights reserved. - * - * Developed by: - * - * LLVM Team - * - * University of Illinois at Urbana-Champaign - * - * http://llvm.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal with - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is furnished to do - * so, subject to the following conditions: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimers. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimers in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the names of the LLVM Team, University of Illinois at - * Urbana-Champaign, nor the names of its contributors may be used to - * endorse or promote products derived from this Software without specific - * prior written permission. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE - * SOFTWARE. - * - * ============================================================================== - * - * Copyright (c) 2009-2014 by the contributors of LLVM/libc++abi project. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "config.h" -#include "FTLUnwindInfo.h" - -#if ENABLE(FTL_JIT) - -#if OS(DARWIN) -#include <mach-o/compact_unwind_encoding.h> -#endif -#include <wtf/ListDump.h> - -namespace JSC { namespace FTL { - -UnwindInfo::UnwindInfo() { } -UnwindInfo::~UnwindInfo() { } - - -namespace { -#if OS(DARWIN) -struct CompactUnwind { - void* function; - uint32_t size; - compact_unwind_encoding_t encoding; - void* personality; - void* lsda; -}; -#elif OS(LINUX) -// DWARF unwind instructions -enum { - DW_CFA_nop = 0x0, - DW_CFA_set_loc = 0x1, - DW_CFA_advance_loc1 = 0x2, - DW_CFA_advance_loc2 = 0x3, - DW_CFA_advance_loc4 = 0x4, - DW_CFA_offset_extended = 0x5, - DW_CFA_def_cfa = 0xC, - DW_CFA_def_cfa_register = 0xD, - DW_CFA_def_cfa_offset = 0xE, - DW_CFA_offset_extended_sf = 0x11, - DW_CFA_def_cfa_sf = 0x12, - DW_CFA_def_cfa_offset_sf = 0x13, - // high 2 bits are 0x1, lower 6 bits are delta - DW_CFA_advance_loc = 0x40, - // high 2 bits are 0x2, lower 6 bits are register - DW_CFA_offset = 0x80 -}; - -enum { - DW_CFA_operand_mask = 0x3F // low 6 bits mask for opcode-encoded operands in DW_CFA_advance_loc and DW_CFA_offset -}; - -// FSF exception handling Pointer-Encoding constants -enum { - DW_EH_PE_ptr = 0x00, - DW_EH_PE_uleb128 = 0x01, - DW_EH_PE_udata2 = 0x02, - DW_EH_PE_udata4 = 0x03, - DW_EH_PE_udata8 = 0x04, - DW_EH_PE_sleb128 = 0x09, - DW_EH_PE_sdata2 = 0x0A, - DW_EH_PE_sdata4 = 0x0B, - DW_EH_PE_sdata8 = 0x0C, - DW_EH_PE_absptr = 0x00, - DW_EH_PE_pcrel = 0x10, - DW_EH_PE_indirect = 0x80 -}; - -enum { - DW_EH_PE_relative_mask = 0x70 -}; - -// 64-bit x86_64 registers -enum { - UNW_X86_64_rbx = 3, - UNW_X86_64_rbp = 6, - UNW_X86_64_r12 = 12, - UNW_X86_64_r13 = 13, - UNW_X86_64_r14 = 14, - UNW_X86_64_r15 = 15 -}; - -enum { - DW_X86_64_RET_addr = 16 -}; - -enum { - UNW_ARM64_x0 = 0, - UNW_ARM64_x1 = 1, - UNW_ARM64_x2 = 2, - UNW_ARM64_x3 = 3, - UNW_ARM64_x4 = 4, - UNW_ARM64_x5 = 5, - UNW_ARM64_x6 = 6, - UNW_ARM64_x7 = 7, - UNW_ARM64_x8 = 8, - UNW_ARM64_x9 = 9, - UNW_ARM64_x10 = 10, - UNW_ARM64_x11 = 11, - UNW_ARM64_x12 = 12, - UNW_ARM64_x13 = 13, - UNW_ARM64_x14 = 14, - UNW_ARM64_x15 = 15, - UNW_ARM64_x16 = 16, - UNW_ARM64_x17 = 17, - UNW_ARM64_x18 = 18, - UNW_ARM64_x19 = 19, - UNW_ARM64_x20 = 20, - UNW_ARM64_x21 = 21, - UNW_ARM64_x22 = 22, - UNW_ARM64_x23 = 23, - UNW_ARM64_x24 = 24, - UNW_ARM64_x25 = 25, - UNW_ARM64_x26 = 26, - UNW_ARM64_x27 = 27, - UNW_ARM64_x28 = 28, - UNW_ARM64_fp = 29, - UNW_ARM64_x30 = 30, - UNW_ARM64_sp = 31, - UNW_ARM64_v0 = 64, - UNW_ARM64_v1 = 65, - UNW_ARM64_v2 = 66, - UNW_ARM64_v3 = 67, - UNW_ARM64_v4 = 68, - UNW_ARM64_v5 = 69, - UNW_ARM64_v6 = 70, - UNW_ARM64_v7 = 71, - UNW_ARM64_v8 = 72, - UNW_ARM64_v9 = 73, - UNW_ARM64_v10 = 74, - UNW_ARM64_v11 = 75, - UNW_ARM64_v12 = 76, - UNW_ARM64_v13 = 77, - UNW_ARM64_v14 = 78, - UNW_ARM64_v15 = 79, - UNW_ARM64_v16 = 80, - UNW_ARM64_v17 = 81, - UNW_ARM64_v18 = 82, - UNW_ARM64_v19 = 83, - UNW_ARM64_v20 = 84, - UNW_ARM64_v21 = 85, - UNW_ARM64_v22 = 86, - UNW_ARM64_v23 = 87, - UNW_ARM64_v24 = 88, - UNW_ARM64_v25 = 89, - UNW_ARM64_v26 = 90, - UNW_ARM64_v27 = 91, - UNW_ARM64_v28 = 92, - UNW_ARM64_v29 = 93, - UNW_ARM64_v30 = 94, - UNW_ARM64_v31 = 95 -}; - -static uint8_t get8(uintptr_t addr) { return *((uint8_t*)addr); } -static uint16_t get16(uintptr_t addr) { return *((uint16_t*)addr); } -static uint32_t get32(uintptr_t addr) { return *((uint32_t*)addr); } -static uint64_t get64(uintptr_t addr) { return *((uint64_t*)addr); } - -static uintptr_t getP(uintptr_t addr) -{ - // FIXME: add support for 32 bit pointers on 32 bit architectures - return get64(addr); -} - -static uint64_t getULEB128(uintptr_t& addr, uintptr_t end) -{ - const uint8_t* p = (uint8_t*)addr; - const uint8_t* pend = (uint8_t*)end; - uint64_t result = 0; - int bit = 0; - do { - uint64_t b; - - RELEASE_ASSERT(p != pend); // truncated uleb128 expression - - b = *p & 0x7f; - - RELEASE_ASSERT(!(bit >= 64 || b << bit >> bit != b)); // malformed uleb128 expression - - result |= b << bit; - bit += 7; - } while (*p++ >= 0x80); - addr = (uintptr_t)p; - return result; -} - -static int64_t getSLEB128(uintptr_t& addr, uintptr_t end) -{ - const uint8_t* p = (uint8_t*)addr; - const uint8_t* pend = (uint8_t*)end; - - int64_t result = 0; - int bit = 0; - uint8_t byte; - do { - RELEASE_ASSERT(p != pend); // truncated sleb128 expression - - byte = *p++; - result |= ((byte & 0x7f) << bit); - bit += 7; - } while (byte & 0x80); - // sign extend negative numbers - if ((byte & 0x40)) - result |= (-1LL) << bit; - addr = (uintptr_t)p; - return result; -} - -static uintptr_t getEncodedP(uintptr_t& addr, uintptr_t end, uint8_t encoding) -{ - uintptr_t startAddr = addr; - const uint8_t* p = (uint8_t*)addr; - uintptr_t result; - - // first get value - switch (encoding & 0x0F) { - case DW_EH_PE_ptr: - result = getP(addr); - p += sizeof(uintptr_t); - addr = (uintptr_t)p; - break; - case DW_EH_PE_uleb128: - result = getULEB128(addr, end); - break; - case DW_EH_PE_udata2: - result = get16(addr); - p += 2; - addr = (uintptr_t)p; - break; - case DW_EH_PE_udata4: - result = get32(addr); - p += 4; - addr = (uintptr_t)p; - break; - case DW_EH_PE_udata8: - result = get64(addr); - p += 8; - addr = (uintptr_t)p; - break; - case DW_EH_PE_sleb128: - result = getSLEB128(addr, end); - break; - case DW_EH_PE_sdata2: - result = (int16_t)get16(addr); - p += 2; - addr = (uintptr_t)p; - break; - case DW_EH_PE_sdata4: - result = (int32_t)get32(addr); - p += 4; - addr = (uintptr_t)p; - break; - case DW_EH_PE_sdata8: - result = get64(addr); - p += 8; - addr = (uintptr_t)p; - break; - default: - RELEASE_ASSERT_NOT_REACHED(); // unknown pointer encoding - } - - // then add relative offset - switch (encoding & DW_EH_PE_relative_mask) { - case DW_EH_PE_absptr: - // do nothing - break; - case DW_EH_PE_pcrel: - result += startAddr; - break; - default: - RELEASE_ASSERT_NOT_REACHED(); // unsupported or unknown pointer encoding - } - - if (encoding & DW_EH_PE_indirect) - result = getP(result); - - return result; -} - -// Information encoded in a CIE (Common Information Entry) -struct CIE_Info { - uintptr_t cieStart; - uintptr_t cieLength; - uintptr_t cieInstructions; - uint8_t pointerEncoding; - uint8_t lsdaEncoding; - uint8_t personalityEncoding; - uint8_t personalityOffsetInCIE; - uintptr_t personality; - int dataAlignFactor; - bool fdesHaveAugmentationData; -}; - -// Information about an FDE (Frame Description Entry) -struct FDE_Info { - uintptr_t fdeStart; - uintptr_t fdeLength; - uintptr_t fdeInstructions; - uintptr_t lsda; -}; - -// Information about a frame layout and registers saved determined -// by "running" the dwarf FDE "instructions" -#if CPU(ARM64) -enum { MaxRegisterNumber = 120 }; -#elif CPU(X86_64) -enum { MaxRegisterNumber = 17 }; -#else -#error "Unrecognized architecture" -#endif - -struct RegisterLocation { - bool saved; - int64_t offset; -}; - -struct PrologInfo { - uint32_t cfaRegister; - int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset - RegisterLocation savedRegisters[MaxRegisterNumber]; // from where to restore registers -}; - -static void parseCIE(uintptr_t cie, CIE_Info* cieInfo) -{ - cieInfo->pointerEncoding = 0; - cieInfo->lsdaEncoding = 0; - cieInfo->personalityEncoding = 0; - cieInfo->personalityOffsetInCIE = 0; - cieInfo->personality = 0; - cieInfo->dataAlignFactor = 0; - cieInfo->fdesHaveAugmentationData = false; - cieInfo->cieStart = cie; - - uintptr_t p = cie; - uint64_t cieLength = get32(p); - p += 4; - uintptr_t cieContentEnd = p + cieLength; - if (cieLength == 0xffffffff) { - // 0xffffffff means length is really next 8 bytes - cieLength = get64(p); - p += 8; - cieContentEnd = p + cieLength; - } - - RELEASE_ASSERT(cieLength); - - // CIE ID is always 0 - RELEASE_ASSERT(!get32(p)); // CIE ID is not zero - p += 4; - // Version is always 1 or 3 - uint8_t version = get8(p); - RELEASE_ASSERT((version == 1) || (version == 3)); // CIE version is not 1 or 3 - - ++p; - // save start of augmentation string and find end - uintptr_t strStart = p; - while (get8(p)) - ++p; - ++p; - // parse code aligment factor - getULEB128(p, cieContentEnd); - // parse data alignment factor - cieInfo->dataAlignFactor = getSLEB128(p, cieContentEnd); - // parse return address register - getULEB128(p, cieContentEnd); - // parse augmentation data based on augmentation string - if (get8(strStart) == 'z') { - // parse augmentation data length - getULEB128(p, cieContentEnd); - for (uintptr_t s = strStart; get8(s) != '\0'; ++s) { - switch (get8(s)) { - case 'z': - cieInfo->fdesHaveAugmentationData = true; - break; - case 'P': // FIXME: should assert on personality (just to keep in sync with the CU behaviour) - cieInfo->personalityEncoding = get8(p); - ++p; - cieInfo->personalityOffsetInCIE = p - cie; - cieInfo->personality = getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding); - break; - case 'L': // FIXME: should assert on LSDA (just to keep in sync with the CU behaviour) - cieInfo->lsdaEncoding = get8(p); - ++p; - break; - case 'R': - cieInfo->pointerEncoding = get8(p); - ++p; - break; - default: - // ignore unknown letters - break; - } - } - } - cieInfo->cieLength = cieContentEnd - cieInfo->cieStart; - cieInfo->cieInstructions = p; -} - -static void findFDE(uintptr_t pc, uintptr_t ehSectionStart, uint32_t sectionLength, FDE_Info* fdeInfo, CIE_Info* cieInfo) -{ - uintptr_t p = ehSectionStart; - const uintptr_t ehSectionEnd = p + sectionLength; - while (p < ehSectionEnd) { - uintptr_t currentCFI = p; - uint64_t cfiLength = get32(p); - p += 4; - if (cfiLength == 0xffffffff) { - // 0xffffffff means length is really next 8 bytes - cfiLength = get64(p); - p += 8; - } - RELEASE_ASSERT(cfiLength); // end marker reached before finding FDE for pc - - uint32_t id = get32(p); - if (!id) { - // skip over CIEs - p += cfiLength; - } else { - // process FDE to see if it covers pc - uintptr_t nextCFI = p + cfiLength; - uint32_t ciePointer = get32(p); - uintptr_t cieStart = p - ciePointer; - // validate pointer to CIE is within section - RELEASE_ASSERT((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)); // malformed FDE. CIE is bad - - parseCIE(cieStart, cieInfo); - - p += 4; - // parse pc begin and range - uintptr_t pcStart = getEncodedP(p, nextCFI, cieInfo->pointerEncoding); - uintptr_t pcRange = getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F); - - // test if pc is within the function this FDE covers - // if pc is not in begin/range, skip this FDE - if ((pcStart <= pc) && (pc < pcStart+pcRange)) { - // parse rest of info - fdeInfo->lsda = 0; - // check for augmentation length - if (cieInfo->fdesHaveAugmentationData) { - uintptr_t augLen = getULEB128(p, nextCFI); - uintptr_t endOfAug = p + augLen; - if (cieInfo->lsdaEncoding) { - // peek at value (without indirection). Zero means no lsda - uintptr_t lsdaStart = p; - if (getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F)) { - // reset pointer and re-parse lsda address - p = lsdaStart; - fdeInfo->lsda = getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); - } - } - p = endOfAug; - } - fdeInfo->fdeStart = currentCFI; - fdeInfo->fdeLength = nextCFI - currentCFI; - fdeInfo->fdeInstructions = p; - - return; // FDE found - } - - p = nextCFI; - } - } - - RELEASE_ASSERT_NOT_REACHED(); // no FDE found for pc -} - -static void executeDefCFARegister(uint64_t reg, PrologInfo* results) -{ - RELEASE_ASSERT(reg <= MaxRegisterNumber); // reg too big - results->cfaRegister = reg; -} - -static void executeDefCFAOffset(int64_t offset, PrologInfo* results) -{ - RELEASE_ASSERT(offset <= 0x80000000); // cfa has negative offset (dwarf might contain epilog) - results->cfaRegisterOffset = offset; -} - -static void executeOffset(uint64_t reg, int64_t offset, PrologInfo *results) -{ - if (reg > MaxRegisterNumber) - return; - - RELEASE_ASSERT(!results->savedRegisters[reg].saved); - results->savedRegisters[reg].saved = true; - results->savedRegisters[reg].offset = offset; -} - -static void parseInstructions(uintptr_t instructions, uintptr_t instructionsEnd, const CIE_Info& cieInfo, PrologInfo* results) -{ - uintptr_t p = instructions; - - // see Dwarf Spec, section 6.4.2 for details on unwind opcodes - while ((p < instructionsEnd)) { - uint64_t reg; - uint8_t opcode = get8(p); - uint8_t operand; - ++p; - switch (opcode) { - case DW_CFA_nop: - break; - case DW_CFA_set_loc: - getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding); - break; - case DW_CFA_advance_loc1: - p += 1; - break; - case DW_CFA_advance_loc2: - p += 2; - break; - case DW_CFA_advance_loc4: - p += 4; - break; - case DW_CFA_def_cfa: - executeDefCFARegister(getULEB128(p, instructionsEnd), results); - executeDefCFAOffset(getULEB128(p, instructionsEnd), results); - break; - case DW_CFA_def_cfa_sf: - executeDefCFARegister(getULEB128(p, instructionsEnd), results); - executeDefCFAOffset(getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results); - break; - case DW_CFA_def_cfa_register: - executeDefCFARegister(getULEB128(p, instructionsEnd), results); - break; - case DW_CFA_def_cfa_offset: - executeDefCFAOffset(getULEB128(p, instructionsEnd), results); - break; - case DW_CFA_def_cfa_offset_sf: - executeDefCFAOffset(getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results); - break; - case DW_CFA_offset_extended: - reg = getULEB128(p, instructionsEnd); - executeOffset(reg, getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results); - break; - case DW_CFA_offset_extended_sf: - reg = getULEB128(p, instructionsEnd); - executeOffset(reg, getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results); - break; - default: - operand = opcode & DW_CFA_operand_mask; - switch (opcode & ~DW_CFA_operand_mask) { - case DW_CFA_offset: - executeOffset(operand, getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results); - break; - case DW_CFA_advance_loc: - break; - default: - RELEASE_ASSERT_NOT_REACHED(); // unknown or unsupported CFA opcode - } - } - } -} - -static void parseFDEInstructions(const FDE_Info& fdeInfo, const CIE_Info& cieInfo, PrologInfo* results) -{ - // clear results - bzero(results, sizeof(PrologInfo)); - - // parse CIE then FDE instructions - parseInstructions(cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength, cieInfo, results); - parseInstructions(fdeInfo.fdeInstructions, fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, results); -} -#endif -} // anonymous namespace - -bool UnwindInfo::parse(void* section, size_t size, GeneratedFunction generatedFunction) -{ - m_registers.clear(); - RELEASE_ASSERT(!!section); - if (!section) - return false; - -#if OS(DARWIN) - RELEASE_ASSERT(size >= sizeof(CompactUnwind)); - - CompactUnwind* data = bitwise_cast<CompactUnwind*>(section); - - RELEASE_ASSERT(!data->personality); // We don't know how to handle this. - RELEASE_ASSERT(!data->lsda); // We don't know how to handle this. - RELEASE_ASSERT(data->function == generatedFunction); // The unwind data better be for our function. - - compact_unwind_encoding_t encoding = data->encoding; - RELEASE_ASSERT(!(encoding & UNWIND_IS_NOT_FUNCTION_START)); - RELEASE_ASSERT(!(encoding & UNWIND_HAS_LSDA)); - RELEASE_ASSERT(!(encoding & UNWIND_PERSONALITY_MASK)); - -#if CPU(X86_64) - RELEASE_ASSERT((encoding & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_RBP_FRAME); - - int32_t offset = -((encoding & UNWIND_X86_64_RBP_FRAME_OFFSET) >> 16) * 8; - uint32_t nextRegisters = encoding; - for (unsigned i = 5; i--;) { - uint32_t currentRegister = nextRegisters & 7; - nextRegisters >>= 3; - - switch (currentRegister) { - case UNWIND_X86_64_REG_NONE: - break; - - case UNWIND_X86_64_REG_RBX: - m_registers.append(RegisterAtOffset(X86Registers::ebx, offset)); - break; - - case UNWIND_X86_64_REG_R12: - m_registers.append(RegisterAtOffset(X86Registers::r12, offset)); - break; - - case UNWIND_X86_64_REG_R13: - m_registers.append(RegisterAtOffset(X86Registers::r13, offset)); - break; - - case UNWIND_X86_64_REG_R14: - m_registers.append(RegisterAtOffset(X86Registers::r14, offset)); - break; - - case UNWIND_X86_64_REG_R15: - m_registers.append(RegisterAtOffset(X86Registers::r15, offset)); - break; - - case UNWIND_X86_64_REG_RBP: - m_registers.append(RegisterAtOffset(X86Registers::ebp, offset)); - break; - - default: - RELEASE_ASSERT_NOT_REACHED(); - } - - offset += 8; - } -#elif CPU(ARM64) - RELEASE_ASSERT((encoding & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_FRAME); - - m_registers.append(RegisterAtOffset(ARM64Registers::fp, 0)); - - int32_t offset = 0; - if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - m_registers.append(RegisterAtOffset(ARM64Registers::x19, offset -= 8)); - m_registers.append(RegisterAtOffset(ARM64Registers::x20, offset -= 8)); - } - if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - m_registers.append(RegisterAtOffset(ARM64Registers::x21, offset -= 8)); - m_registers.append(RegisterAtOffset(ARM64Registers::x22, offset -= 8)); - } - if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - m_registers.append(RegisterAtOffset(ARM64Registers::x23, offset -= 8)); - m_registers.append(RegisterAtOffset(ARM64Registers::x24, offset -= 8)); - } - if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - m_registers.append(RegisterAtOffset(ARM64Registers::x25, offset -= 8)); - m_registers.append(RegisterAtOffset(ARM64Registers::x26, offset -= 8)); - } - if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - m_registers.append(RegisterAtOffset(ARM64Registers::x27, offset -= 8)); - m_registers.append(RegisterAtOffset(ARM64Registers::x28, offset -= 8)); - } - if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { - m_registers.append(RegisterAtOffset(ARM64Registers::q8, offset -= 8)); - m_registers.append(RegisterAtOffset(ARM64Registers::q9, offset -= 8)); - } - if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { - m_registers.append(RegisterAtOffset(ARM64Registers::q10, offset -= 8)); - m_registers.append(RegisterAtOffset(ARM64Registers::q11, offset -= 8)); - } - if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { - m_registers.append(RegisterAtOffset(ARM64Registers::q12, offset -= 8)); - m_registers.append(RegisterAtOffset(ARM64Registers::q13, offset -= 8)); - } - if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { - m_registers.append(RegisterAtOffset(ARM64Registers::q14, offset -= 8)); - m_registers.append(RegisterAtOffset(ARM64Registers::q15, offset -= 8)); - } -#else -#error "Unrecognized architecture" -#endif - -#elif OS(LINUX) - FDE_Info fdeInfo; - CIE_Info cieInfo; - PrologInfo prolog; - - findFDE((uintptr_t)generatedFunction, (uintptr_t)section, size, &fdeInfo, &cieInfo); - parseFDEInstructions(fdeInfo, cieInfo, &prolog); - -#if CPU(X86_64) - RELEASE_ASSERT(prolog.cfaRegister == UNW_X86_64_rbp); - RELEASE_ASSERT(prolog.cfaRegisterOffset == 16); - RELEASE_ASSERT(prolog.savedRegisters[UNW_X86_64_rbp].saved); - RELEASE_ASSERT(prolog.savedRegisters[UNW_X86_64_rbp].offset == -prolog.cfaRegisterOffset); - - for (int i = 0; i < MaxRegisterNumber; ++i) { - if (prolog.savedRegisters[i].saved) { - switch (i) { - case UNW_X86_64_rbx: - m_registers.append(RegisterAtOffset(X86Registers::ebx, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_X86_64_r12: - m_registers.append(RegisterAtOffset(X86Registers::r12, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_X86_64_r13: - m_registers.append(RegisterAtOffset(X86Registers::r13, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_X86_64_r14: - m_registers.append(RegisterAtOffset(X86Registers::r14, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_X86_64_r15: - m_registers.append(RegisterAtOffset(X86Registers::r15, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_X86_64_rbp: - m_registers.append(RegisterAtOffset(X86Registers::ebp, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case DW_X86_64_RET_addr: - break; - default: - RELEASE_ASSERT_NOT_REACHED(); // non-standard register being saved in prolog - } - } - } -#elif CPU(ARM64) - RELEASE_ASSERT(prolog.cfaRegister == UNW_ARM64_fp); - RELEASE_ASSERT(prolog.cfaRegisterOffset == 16); - RELEASE_ASSERT(prolog.savedRegisters[UNW_ARM64_fp].saved); - RELEASE_ASSERT(prolog.savedRegisters[UNW_ARM64_fp].offset == -prolog.cfaRegisterOffset); - - for (int i = 0; i < MaxRegisterNumber; ++i) { - if (prolog.savedRegisters[i].saved) { - switch (i) { - case UNW_ARM64_x0: - m_registers.append(RegisterAtOffset(ARM64Registers::x0, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x1: - m_registers.append(RegisterAtOffset(ARM64Registers::x1, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x2: - m_registers.append(RegisterAtOffset(ARM64Registers::x2, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x3: - m_registers.append(RegisterAtOffset(ARM64Registers::x3, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x4: - m_registers.append(RegisterAtOffset(ARM64Registers::x4, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x5: - m_registers.append(RegisterAtOffset(ARM64Registers::x5, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x6: - m_registers.append(RegisterAtOffset(ARM64Registers::x6, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x7: - m_registers.append(RegisterAtOffset(ARM64Registers::x7, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x8: - m_registers.append(RegisterAtOffset(ARM64Registers::x8, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x9: - m_registers.append(RegisterAtOffset(ARM64Registers::x9, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x10: - m_registers.append(RegisterAtOffset(ARM64Registers::x10, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x11: - m_registers.append(RegisterAtOffset(ARM64Registers::x11, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x12: - m_registers.append(RegisterAtOffset(ARM64Registers::x12, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x13: - m_registers.append(RegisterAtOffset(ARM64Registers::x13, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x14: - m_registers.append(RegisterAtOffset(ARM64Registers::x14, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x15: - m_registers.append(RegisterAtOffset(ARM64Registers::x15, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x16: - m_registers.append(RegisterAtOffset(ARM64Registers::x16, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x17: - m_registers.append(RegisterAtOffset(ARM64Registers::x17, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x18: - m_registers.append(RegisterAtOffset(ARM64Registers::x18, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x19: - m_registers.append(RegisterAtOffset(ARM64Registers::x19, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x20: - m_registers.append(RegisterAtOffset(ARM64Registers::x20, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x21: - m_registers.append(RegisterAtOffset(ARM64Registers::x21, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x22: - m_registers.append(RegisterAtOffset(ARM64Registers::x22, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x23: - m_registers.append(RegisterAtOffset(ARM64Registers::x23, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x24: - m_registers.append(RegisterAtOffset(ARM64Registers::x24, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x25: - m_registers.append(RegisterAtOffset(ARM64Registers::x25, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x26: - m_registers.append(RegisterAtOffset(ARM64Registers::x26, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x27: - m_registers.append(RegisterAtOffset(ARM64Registers::x27, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x28: - m_registers.append(RegisterAtOffset(ARM64Registers::x28, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_fp: - m_registers.append(RegisterAtOffset(ARM64Registers::fp, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_x30: - m_registers.append(RegisterAtOffset(ARM64Registers::x30, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_sp: - m_registers.append(RegisterAtOffset(ARM64Registers::sp, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v0: - m_registers.append(RegisterAtOffset(ARM64Registers::q0, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v1: - m_registers.append(RegisterAtOffset(ARM64Registers::q1, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v2: - m_registers.append(RegisterAtOffset(ARM64Registers::q2, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v3: - m_registers.append(RegisterAtOffset(ARM64Registers::q3, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v4: - m_registers.append(RegisterAtOffset(ARM64Registers::q4, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v5: - m_registers.append(RegisterAtOffset(ARM64Registers::q5, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v6: - m_registers.append(RegisterAtOffset(ARM64Registers::q6, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v7: - m_registers.append(RegisterAtOffset(ARM64Registers::q7, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v8: - m_registers.append(RegisterAtOffset(ARM64Registers::q8, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v9: - m_registers.append(RegisterAtOffset(ARM64Registers::q9, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v10: - m_registers.append(RegisterAtOffset(ARM64Registers::q10, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v11: - m_registers.append(RegisterAtOffset(ARM64Registers::q11, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v12: - m_registers.append(RegisterAtOffset(ARM64Registers::q12, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v13: - m_registers.append(RegisterAtOffset(ARM64Registers::q13, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v14: - m_registers.append(RegisterAtOffset(ARM64Registers::q14, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v15: - m_registers.append(RegisterAtOffset(ARM64Registers::q15, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v16: - m_registers.append(RegisterAtOffset(ARM64Registers::q16, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v17: - m_registers.append(RegisterAtOffset(ARM64Registers::q17, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v18: - m_registers.append(RegisterAtOffset(ARM64Registers::q18, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v19: - m_registers.append(RegisterAtOffset(ARM64Registers::q19, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v20: - m_registers.append(RegisterAtOffset(ARM64Registers::q20, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v21: - m_registers.append(RegisterAtOffset(ARM64Registers::q21, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v22: - m_registers.append(RegisterAtOffset(ARM64Registers::q22, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v23: - m_registers.append(RegisterAtOffset(ARM64Registers::q23, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v24: - m_registers.append(RegisterAtOffset(ARM64Registers::q24, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v25: - m_registers.append(RegisterAtOffset(ARM64Registers::q25, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v26: - m_registers.append(RegisterAtOffset(ARM64Registers::q26, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v27: - m_registers.append(RegisterAtOffset(ARM64Registers::q27, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v28: - m_registers.append(RegisterAtOffset(ARM64Registers::q28, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v29: - m_registers.append(RegisterAtOffset(ARM64Registers::q29, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v30: - m_registers.append(RegisterAtOffset(ARM64Registers::q30, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - case UNW_ARM64_v31: - m_registers.append(RegisterAtOffset(ARM64Registers::q31, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset)); - break; - default: - RELEASE_ASSERT_NOT_REACHED(); // non-standard register being saved in prolog - } - } - } -#else -#error "Unrecognized architecture" -#endif - -#endif - std::sort(m_registers.begin(), m_registers.end()); - return true; -} - -void UnwindInfo::dump(PrintStream& out) const -{ - out.print(listDump(m_registers)); -} - -RegisterAtOffset* UnwindInfo::find(Reg reg) const -{ - return tryBinarySearch<RegisterAtOffset, Reg>(m_registers, m_registers.size(), reg, RegisterAtOffset::getReg); -} - -unsigned UnwindInfo::indexOf(Reg reg) const -{ - if (RegisterAtOffset* pointer = find(reg)) - return pointer - m_registers.begin(); - return UINT_MAX; -} - -} } // namespace JSC::FTL - -#endif // ENABLE(FTL_JIT) - |
