Ignore:
Timestamp:
Sep 11, 2014, 1:52:22 AM (11 years ago)
Author:
[email protected]
Message:

[JavaScriptCore] Fix FTL on platform EFL.
https://bugs.webkit.org/show_bug.cgi?id=133571

Reviewed by Filip Pizlo.

.:

Revert r169181.

  • Source/cmake/FindLIBCXXABI.cmake: Removed.
  • Source/cmake/OptionsEfl.cmake:

Source/JavaScriptCore:

There are no compact_unwind sections on Linux systems so FTL crashes.
We have to parse eh_frame in FTLUnwindInfo instead of compact_unwind
and get the information for stack unwinding from there.

  • CMakeLists.txt: Revert r169181.
  • ftl/FTLCompile.cpp:

Change section name literals to use SECTION_NAME macro, because of architecture differencies.
(JSC::FTL::mmAllocateCodeSection):
(JSC::FTL::mmAllocateDataSection):
(JSC::FTL::compile):

  • ftl/FTLJITCode.h:

We need the SECTION_NAME macro in FTLCompile and FTLLink, so we define it here.

  • ftl/FTLLink.cpp:

(JSC::FTL::link):

  • ftl/FTLState.h:
  • ftl/FTLState.cpp:

(JSC::FTL::State::State):

  • ftl/FTLUnwindInfo.h:
  • ftl/FTLUnwindInfo.cpp:

Lift the eh_frame parsing method from LLVM/libcxxabi project and modify it for our purposes.
Parse eh_frame on Linux instead of compact_unwind.
(JSC::FTL::UnwindInfo::parse):

Tools:

  • efl/install-dependencies: Revert r169181.
  • efl/jhbuild.modules: Clone and build a custom branch.

This branch contains some fix for FTL of platform EFL.
The branch is a fork of llvm r206311.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ftl/FTLUnwindInfo.cpp

    r164456 r173509  
    11/*
    22 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
     3 * Copyright (C) 2014 Samsung Electronics
     4 * Copyright (C) 2014 University of Szeged
    35 *
    46 * Redistribution and use in source and binary forms, with or without
     
    2123 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    2224 * (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.
     25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 *
     27 * ==============================================================================
     28 *
     29 * University of Illinois/NCSA
     30 * Open Source License
     31 *
     32 * Copyright (c) 2009-2014 by the contributors of LLVM/libc++abi project.
     33 *
     34 * All rights reserved.
     35 *
     36 * Developed by:
     37 *
     38 *    LLVM Team
     39 *
     40 *    University of Illinois at Urbana-Champaign
     41 *
     42 *    http://llvm.org
     43 *
     44 * Permission is hereby granted, free of charge, to any person obtaining a copy of
     45 * this software and associated documentation files (the "Software"), to deal with
     46 * the Software without restriction, including without limitation the rights to
     47 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
     48 * of the Software, and to permit persons to whom the Software is furnished to do
     49 * so, subject to the following conditions:
     50 *
     51 *    * Redistributions of source code must retain the above copyright notice,
     52 *      this list of conditions and the following disclaimers.
     53 *
     54 *    * Redistributions in binary form must reproduce the above copyright notice,
     55 *      this list of conditions and the following disclaimers in the
     56 *      documentation and/or other materials provided with the distribution.
     57 *
     58 *    * Neither the names of the LLVM Team, University of Illinois at
     59 *      Urbana-Champaign, nor the names of its contributors may be used to
     60 *      endorse or promote products derived from this Software without specific
     61 *      prior written permission.
     62 *
     63 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     64 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
     65 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     66 * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     67 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     68 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
     69 * SOFTWARE.
     70 *
     71 * ==============================================================================
     72 *
     73 * Copyright (c) 2009-2014 by the contributors of LLVM/libc++abi project.
     74 *
     75 * Permission is hereby granted, free of charge, to any person obtaining a copy
     76 * of this software and associated documentation files (the "Software"), to deal
     77 * in the Software without restriction, including without limitation the rights
     78 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     79 * copies of the Software, and to permit persons to whom the Software is
     80 * furnished to do so, subject to the following conditions:
     81 *
     82 * The above copyright notice and this permission notice shall be included in
     83 * all copies or substantial portions of the Software.
     84 *
     85 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     86 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     87 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     88 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     89 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     90 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     91 * THE SOFTWARE.
    2492 */
    2593
     
    2997#if ENABLE(FTL_JIT)
    3098
     99#if OS(DARWIN)
    31100#include <mach-o/compact_unwind_encoding.h>
     101#endif
    32102#include <wtf/ListDump.h>
    33103
     
    37107UnwindInfo::~UnwindInfo() { }
    38108
     109
    39110namespace {
    40 
     111#if OS(DARWIN)
    41112struct CompactUnwind {
    42113    void* function;
     
    46117    void* lsda;
    47118};
    48 
     119#elif OS(LINUX)
     120// DWARF unwind instructions
     121enum {
     122    DW_CFA_nop                 = 0x0,
     123    DW_CFA_set_loc             = 0x1,
     124    DW_CFA_advance_loc1        = 0x2,
     125    DW_CFA_advance_loc2        = 0x3,
     126    DW_CFA_advance_loc4        = 0x4,
     127    DW_CFA_offset_extended     = 0x5,
     128    DW_CFA_def_cfa             = 0xC,
     129    DW_CFA_def_cfa_register    = 0xD,
     130    DW_CFA_def_cfa_offset      = 0xE,
     131    DW_CFA_offset_extended_sf = 0x11,
     132    DW_CFA_def_cfa_sf         = 0x12,
     133    DW_CFA_def_cfa_offset_sf  = 0x13,
     134    // high 2 bits are 0x1, lower 6 bits are delta
     135    DW_CFA_advance_loc        = 0x40,
     136    // high 2 bits are 0x2, lower 6 bits are register
     137    DW_CFA_offset             = 0x80
     138};
     139
     140enum {
     141    DW_CFA_operand_mask = 0x3F // low 6 bits mask for opcode-encoded operands in DW_CFA_advance_loc and DW_CFA_offset
     142};
     143
     144// FSF exception handling Pointer-Encoding constants
     145enum {
     146    DW_EH_PE_ptr       = 0x00,
     147    DW_EH_PE_uleb128   = 0x01,
     148    DW_EH_PE_udata2    = 0x02,
     149    DW_EH_PE_udata4    = 0x03,
     150    DW_EH_PE_udata8    = 0x04,
     151    DW_EH_PE_sleb128   = 0x09,
     152    DW_EH_PE_sdata2    = 0x0A,
     153    DW_EH_PE_sdata4    = 0x0B,
     154    DW_EH_PE_sdata8    = 0x0C,
     155    DW_EH_PE_absptr    = 0x00,
     156    DW_EH_PE_pcrel     = 0x10,
     157    DW_EH_PE_indirect  = 0x80
     158};
     159
     160enum {
     161    DW_EH_PE_relative_mask = 0x70
     162};
     163
     164// 64-bit x86_64 registers
     165enum {
     166    UNW_X86_64_rbx =  3,
     167    UNW_X86_64_rbp =  6,
     168    UNW_X86_64_r12 = 12,
     169    UNW_X86_64_r13 = 13,
     170    UNW_X86_64_r14 = 14,
     171    UNW_X86_64_r15 = 15
     172};
     173
     174enum {
     175    DW_X86_64_RET_addr = 16
     176};
     177
     178static uint8_t get8(uintptr_t addr)    { return *((uint8_t*)addr); }
     179static uint16_t get16(uintptr_t addr)  { return *((uint16_t*)addr); }
     180static uint32_t get32(uintptr_t addr)  { return *((uint32_t*)addr); }
     181static uint64_t get64(uintptr_t addr)  { return *((uint64_t*)addr); }
     182
     183static uintptr_t getP(uintptr_t addr)
     184{
     185    // FIXME: add support for 32 bit pointers on 32 bit architectures
     186    return get64(addr);
     187}
     188
     189static uint64_t getULEB128(uintptr_t& addr, uintptr_t end)
     190{
     191    const uint8_t* p = (uint8_t*)addr;
     192    const uint8_t* pend = (uint8_t*)end;
     193    uint64_t result = 0;
     194    int bit = 0;
     195    do  {
     196        uint64_t b;
     197
     198        RELEASE_ASSERT(p != pend); // truncated uleb128 expression
     199
     200        b = *p & 0x7f;
     201
     202        RELEASE_ASSERT(!(bit >= 64 || b << bit >> bit != b)); // malformed uleb128 expression
     203
     204        result |= b << bit;
     205        bit += 7;
     206    } while (*p++ >= 0x80);
     207    addr = (uintptr_t)p;
     208    return result;
     209}
     210
     211static int64_t getSLEB128(uintptr_t& addr, uintptr_t end)
     212{
     213    const uint8_t* p = (uint8_t*)addr;
     214    const uint8_t* pend = (uint8_t*)end;
     215
     216    int64_t result = 0;
     217    int bit = 0;
     218    uint8_t byte;
     219    do {
     220        RELEASE_ASSERT(p != pend); // truncated sleb128 expression
     221
     222        byte = *p++;
     223        result |= ((byte & 0x7f) << bit);
     224        bit += 7;
     225    } while (byte & 0x80);
     226    // sign extend negative numbers
     227    if ((byte & 0x40))
     228        result |= (-1LL) << bit;
     229    addr = (uintptr_t)p;
     230    return result;
     231}
     232
     233static uintptr_t getEncodedP(uintptr_t& addr, uintptr_t end, uint8_t encoding)
     234{
     235    uintptr_t startAddr = addr;
     236    const uint8_t* p = (uint8_t*)addr;
     237    uintptr_t result;
     238
     239    // first get value
     240    switch (encoding & 0x0F) {
     241    case DW_EH_PE_ptr:
     242        result = getP(addr);
     243        p += sizeof(uintptr_t);
     244        addr = (uintptr_t)p;
     245        break;
     246    case DW_EH_PE_uleb128:
     247        result = getULEB128(addr, end);
     248        break;
     249    case DW_EH_PE_udata2:
     250        result = get16(addr);
     251        p += 2;
     252        addr = (uintptr_t)p;
     253        break;
     254    case DW_EH_PE_udata4:
     255        result = get32(addr);
     256        p += 4;
     257        addr = (uintptr_t)p;
     258        break;
     259    case DW_EH_PE_udata8:
     260        result = get64(addr);
     261        p += 8;
     262        addr = (uintptr_t)p;
     263        break;
     264    case DW_EH_PE_sleb128:
     265        result = getSLEB128(addr, end);
     266        break;
     267    case DW_EH_PE_sdata2:
     268        result = (int16_t)get16(addr);
     269        p += 2;
     270        addr = (uintptr_t)p;
     271        break;
     272    case DW_EH_PE_sdata4:
     273        result = (int32_t)get32(addr);
     274        p += 4;
     275        addr = (uintptr_t)p;
     276        break;
     277    case DW_EH_PE_sdata8:
     278        result = get64(addr);
     279        p += 8;
     280        addr = (uintptr_t)p;
     281        break;
     282    default:
     283        RELEASE_ASSERT_NOT_REACHED(); // unknown pointer encoding
     284    }
     285
     286    // then add relative offset
     287    switch (encoding & DW_EH_PE_relative_mask) {
     288    case DW_EH_PE_absptr:
     289        // do nothing
     290        break;
     291    case DW_EH_PE_pcrel:
     292        result += startAddr;
     293        break;
     294    default:
     295        RELEASE_ASSERT_NOT_REACHED(); // unsupported or unknown pointer encoding
     296    }
     297
     298    if (encoding & DW_EH_PE_indirect)
     299        result = getP(result);
     300
     301    return result;
     302}
     303
     304// Information encoded in a CIE (Common Information Entry)
     305struct CIE_Info {
     306    uintptr_t cieStart;
     307    uintptr_t cieLength;
     308    uintptr_t cieInstructions;
     309    uint8_t pointerEncoding;
     310    uint8_t lsdaEncoding;
     311    uint8_t personalityEncoding;
     312    uint8_t personalityOffsetInCIE;
     313    uintptr_t personality;
     314    int dataAlignFactor;
     315    bool fdesHaveAugmentationData;
     316};
     317
     318// Information about an FDE (Frame Description Entry)
     319struct FDE_Info {
     320    uintptr_t fdeStart;
     321    uintptr_t fdeLength;
     322    uintptr_t fdeInstructions;
     323    uintptr_t lsda;
     324};
     325
     326// Information about a frame layout and registers saved determined
     327// by "running" the dwarf FDE "instructions"
     328enum { MaxRegisterNumber = 17 };
     329
     330struct RegisterLocation {
     331    bool saved;
     332    int64_t offset;
     333};
     334
     335struct PrologInfo {
     336    uint32_t cfaRegister;
     337    int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
     338    RegisterLocation savedRegisters[MaxRegisterNumber]; // from where to restore registers
     339};
     340
     341static void parseCIE(uintptr_t cie, CIE_Info* cieInfo)
     342{
     343    cieInfo->pointerEncoding = 0;
     344    cieInfo->lsdaEncoding = 0;
     345    cieInfo->personalityEncoding = 0;
     346    cieInfo->personalityOffsetInCIE = 0;
     347    cieInfo->personality = 0;
     348    cieInfo->dataAlignFactor = 0;
     349    cieInfo->fdesHaveAugmentationData = false;
     350    cieInfo->cieStart = cie;
     351
     352    uintptr_t p = cie;
     353    uint64_t cieLength = get32(p);
     354    p += 4;
     355    uintptr_t cieContentEnd = p + cieLength;
     356    if (cieLength == 0xffffffff) {
     357        // 0xffffffff means length is really next 8 bytes
     358        cieLength = get64(p);
     359        p += 8;
     360        cieContentEnd = p + cieLength;
     361    }
     362
     363    RELEASE_ASSERT(cieLength);
     364
     365    // CIE ID is always 0
     366    RELEASE_ASSERT(!get32(p)); // CIE ID is not zero
     367    p += 4;
     368    // Version is always 1 or 3
     369    uint8_t version = get8(p);
     370    RELEASE_ASSERT((version == 1) || (version == 3)); // CIE version is not 1 or 3
     371
     372    ++p;
     373    // save start of augmentation string and find end
     374    uintptr_t strStart = p;
     375    while (get8(p))
     376        ++p;
     377    ++p;
     378    // parse code aligment factor
     379    getULEB128(p, cieContentEnd);
     380    // parse data alignment factor
     381    cieInfo->dataAlignFactor = getSLEB128(p, cieContentEnd);
     382    // parse return address register
     383    getULEB128(p, cieContentEnd);
     384    // parse augmentation data based on augmentation string
     385    if (get8(strStart) == 'z') {
     386        // parse augmentation data length
     387        getULEB128(p, cieContentEnd);
     388        for (uintptr_t s = strStart; get8(s) != '\0'; ++s) {
     389            switch (get8(s)) {
     390            case 'z':
     391                cieInfo->fdesHaveAugmentationData = true;
     392                break;
     393            case 'P': // FIXME: should assert on personality (just to keep in sync with the CU behaviour)
     394                cieInfo->personalityEncoding = get8(p);
     395                ++p;
     396                cieInfo->personalityOffsetInCIE = p - cie;
     397                cieInfo->personality = getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
     398                break;
     399            case 'L': // FIXME: should assert on LSDA (just to keep in sync with the CU behaviour)
     400                cieInfo->lsdaEncoding = get8(p);
     401                ++p;
     402                break;
     403            case 'R':
     404                cieInfo->pointerEncoding = get8(p);
     405                ++p;
     406                break;
     407            default:
     408                // ignore unknown letters
     409                break;
     410            }
     411        }
     412    }
     413    cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
     414    cieInfo->cieInstructions = p;
     415}
     416
     417static void findFDE(uintptr_t pc, uintptr_t ehSectionStart, uint32_t sectionLength, FDE_Info* fdeInfo, CIE_Info* cieInfo)
     418{
     419    uintptr_t p = ehSectionStart;
     420    const uintptr_t ehSectionEnd = p + sectionLength;
     421    while (p < ehSectionEnd) {
     422        uintptr_t currentCFI = p;
     423        uint64_t cfiLength = get32(p);
     424        p += 4;
     425        if (cfiLength == 0xffffffff) {
     426            // 0xffffffff means length is really next 8 bytes
     427            cfiLength = get64(p);
     428            p += 8;
     429        }
     430        RELEASE_ASSERT(cfiLength); // end marker reached before finding FDE for pc
     431
     432        uint32_t id = get32(p);
     433        if (!id) {
     434            // skip over CIEs
     435            p += cfiLength;
     436        } else {
     437            // process FDE to see if it covers pc
     438            uintptr_t nextCFI = p + cfiLength;
     439            uint32_t ciePointer = get32(p);
     440            uintptr_t cieStart = p - ciePointer;
     441            // validate pointer to CIE is within section
     442            RELEASE_ASSERT((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)); // malformed FDE. CIE is bad
     443
     444            parseCIE(cieStart, cieInfo);
     445
     446            p += 4;
     447            // parse pc begin and range
     448            uintptr_t pcStart = getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
     449            uintptr_t pcRange = getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
     450
     451            // test if pc is within the function this FDE covers
     452            // if pc is not in begin/range, skip this FDE
     453            if ((pcStart <= pc) && (pc < pcStart+pcRange)) {
     454                // parse rest of info
     455                fdeInfo->lsda = 0;
     456                // check for augmentation length
     457                if (cieInfo->fdesHaveAugmentationData) {
     458                    uintptr_t augLen = getULEB128(p, nextCFI);
     459                    uintptr_t endOfAug = p + augLen;
     460                    if (cieInfo->lsdaEncoding) {
     461                        // peek at value (without indirection). Zero means no lsda
     462                        uintptr_t lsdaStart = p;
     463                        if (getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F)) {
     464                            // reset pointer and re-parse lsda address
     465                            p = lsdaStart;
     466                            fdeInfo->lsda = getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
     467                        }
     468                    }
     469                    p = endOfAug;
     470                }
     471                fdeInfo->fdeStart = currentCFI;
     472                fdeInfo->fdeLength = nextCFI - currentCFI;
     473                fdeInfo->fdeInstructions = p;
     474
     475                return; // FDE found
     476            }
     477
     478            p = nextCFI;
     479        }
     480    }
     481
     482    RELEASE_ASSERT_NOT_REACHED(); // no FDE found for pc
     483}
     484
     485static void executeDefCFARegister(uint64_t reg, PrologInfo* results)
     486{
     487    RELEASE_ASSERT(reg <= MaxRegisterNumber); // reg too big
     488    results->cfaRegister = reg;
     489}
     490
     491static void executeDefCFAOffset(int64_t offset, PrologInfo* results)
     492{
     493    RELEASE_ASSERT(offset <= 0x80000000); // cfa has negative offset (dwarf might contain epilog)
     494    results->cfaRegisterOffset = offset;
     495}
     496
     497static void executeOffset(uint64_t reg, int64_t offset, PrologInfo *results)
     498{
     499    if (reg > MaxRegisterNumber)
     500        return;
     501
     502    RELEASE_ASSERT(!results->savedRegisters[reg].saved);
     503    results->savedRegisters[reg].saved = true;
     504    results->savedRegisters[reg].offset = offset;
     505}
     506
     507static void parseInstructions(uintptr_t instructions, uintptr_t instructionsEnd, const CIE_Info& cieInfo, PrologInfo* results)
     508{
     509    uintptr_t p = instructions;
     510
     511    // see Dwarf Spec, section 6.4.2 for details on unwind opcodes
     512    while ((p < instructionsEnd)) {
     513        uint64_t reg;
     514        uint8_t opcode = get8(p);
     515        uint8_t operand;
     516        ++p;
     517        switch (opcode) {
     518        case DW_CFA_nop:
     519            break;
     520        case DW_CFA_set_loc:
     521            getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
     522            break;
     523        case DW_CFA_advance_loc1:
     524            p += 1;
     525            break;
     526        case DW_CFA_advance_loc2:
     527            p += 2;
     528            break;
     529        case DW_CFA_advance_loc4:
     530            p += 4;
     531            break;
     532        case DW_CFA_def_cfa:
     533            executeDefCFARegister(getULEB128(p, instructionsEnd), results);
     534            executeDefCFAOffset(getULEB128(p, instructionsEnd), results);
     535            break;
     536        case DW_CFA_def_cfa_sf:
     537            executeDefCFARegister(getULEB128(p, instructionsEnd), results);
     538            executeDefCFAOffset(getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
     539            break;
     540        case DW_CFA_def_cfa_register:
     541            executeDefCFARegister(getULEB128(p, instructionsEnd), results);
     542            break;
     543        case DW_CFA_def_cfa_offset:
     544            executeDefCFAOffset(getULEB128(p, instructionsEnd), results);
     545            break;
     546        case DW_CFA_def_cfa_offset_sf:
     547            executeDefCFAOffset(getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
     548            break;
     549        case DW_CFA_offset_extended:
     550            reg = getULEB128(p, instructionsEnd);
     551            executeOffset(reg, getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
     552            break;
     553        case DW_CFA_offset_extended_sf:
     554            reg = getULEB128(p, instructionsEnd);
     555            executeOffset(reg, getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
     556            break;
     557        default:
     558            operand = opcode & DW_CFA_operand_mask;
     559            switch (opcode & ~DW_CFA_operand_mask) {
     560            case DW_CFA_offset:
     561                executeOffset(operand, getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
     562                break;
     563            case DW_CFA_advance_loc:
     564                break;
     565            default:
     566                RELEASE_ASSERT_NOT_REACHED(); // unknown or unsupported CFA opcode
     567            }
     568        }
     569    }
     570}
     571
     572static void parseFDEInstructions(const FDE_Info& fdeInfo, const CIE_Info& cieInfo, PrologInfo* results)
     573{
     574    // clear results
     575    bzero(results, sizeof(PrologInfo));
     576
     577    // parse CIE then FDE instructions
     578    parseInstructions(cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength, cieInfo, results);
     579    parseInstructions(fdeInfo.fdeInstructions, fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, results);
     580}
     581#endif
    49582} // anonymous namespace
    50583
     
    52585{
    53586    m_registers.clear();
    54    
    55     RELEASE_ASSERT(!!section == !!size);
     587    RELEASE_ASSERT(!!section);
    56588    if (!section)
    57589        return false;
    58    
     590
     591#if OS(DARWIN)
    59592    RELEASE_ASSERT(size >= sizeof(CompactUnwind));
    60593   
     
    158691#error "Unrecognized architecture"
    159692#endif
    160    
     693
     694#elif OS(LINUX)
     695    FDE_Info fdeInfo;
     696    CIE_Info cieInfo;
     697    PrologInfo prolog;
     698
     699    findFDE((uintptr_t)generatedFunction, (uintptr_t)section, size, &fdeInfo, &cieInfo);
     700    parseFDEInstructions(fdeInfo, cieInfo, &prolog);
     701
     702#if CPU(X86_64)
     703    RELEASE_ASSERT(prolog.cfaRegister == UNW_X86_64_rbp);
     704    RELEASE_ASSERT(prolog.cfaRegisterOffset == 16);
     705    RELEASE_ASSERT(prolog.savedRegisters[UNW_X86_64_rbp].saved);
     706    RELEASE_ASSERT(prolog.savedRegisters[UNW_X86_64_rbp].offset == -prolog.cfaRegisterOffset);
     707
     708    for (int i = 0; i < MaxRegisterNumber; ++i) {
     709        if (prolog.savedRegisters[i].saved) {
     710            switch (i) {
     711            case UNW_X86_64_rbx:
     712                m_registers.append(RegisterAtOffset(X86Registers::ebx, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
     713                break;
     714            case UNW_X86_64_r12:
     715                m_registers.append(RegisterAtOffset(X86Registers::r12, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
     716                break;
     717            case UNW_X86_64_r13:
     718                m_registers.append(RegisterAtOffset(X86Registers::r13, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
     719                break;
     720            case UNW_X86_64_r14:
     721                m_registers.append(RegisterAtOffset(X86Registers::r14, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
     722                break;
     723            case UNW_X86_64_r15:
     724                m_registers.append(RegisterAtOffset(X86Registers::r15, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
     725                break;
     726            case UNW_X86_64_rbp:
     727                m_registers.append(RegisterAtOffset(X86Registers::ebp, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
     728                break;
     729            case DW_X86_64_RET_addr:
     730                break;
     731            default:
     732                RELEASE_ASSERT_NOT_REACHED(); // non-standard register being saved in prolog
     733            }
     734        }
     735    }
     736#elif CPU(ARM64)
     737    // FIXME: Implement stackunwinding based on eh_frame on ARM64
     738#else
     739#error "Unrecognized architecture"
     740#endif
     741
     742#endif
    161743    std::sort(m_registers.begin(), m_registers.end());
    162744    return true;
Note: See TracChangeset for help on using the changeset viewer.