summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp')
-rw-r--r--Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp1044
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)
-