2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "FTLUnwindInfo.h"
31 #include <mach-o/compact_unwind_encoding.h>
32 #include <wtf/ListDump.h>
34 namespace JSC
{ namespace FTL
{
36 UnwindInfo::UnwindInfo() { }
37 UnwindInfo::~UnwindInfo() { }
41 struct CompactUnwind
{
44 compact_unwind_encoding_t encoding
;
49 } // anonymous namespace
51 bool UnwindInfo::parse(void* section
, size_t size
, GeneratedFunction generatedFunction
)
55 RELEASE_ASSERT(!!section
== !!size
);
59 RELEASE_ASSERT(size
>= sizeof(CompactUnwind
));
61 CompactUnwind
* data
= bitwise_cast
<CompactUnwind
*>(section
);
63 RELEASE_ASSERT(!data
->personality
); // We don't know how to handle this.
64 RELEASE_ASSERT(!data
->lsda
); // We don't know how to handle this.
65 RELEASE_ASSERT(data
->function
== generatedFunction
); // The unwind data better be for our function.
67 compact_unwind_encoding_t encoding
= data
->encoding
;
68 RELEASE_ASSERT(!(encoding
& UNWIND_IS_NOT_FUNCTION_START
));
69 RELEASE_ASSERT(!(encoding
& UNWIND_HAS_LSDA
));
70 RELEASE_ASSERT(!(encoding
& UNWIND_PERSONALITY_MASK
));
73 RELEASE_ASSERT((encoding
& UNWIND_X86_64_MODE_MASK
) == UNWIND_X86_64_MODE_RBP_FRAME
);
75 int32_t offset
= -((encoding
& UNWIND_X86_64_RBP_FRAME_OFFSET
) >> 16) * 8;
76 uint32_t nextRegisters
= encoding
;
77 for (unsigned i
= 5; i
--;) {
78 uint32_t currentRegister
= nextRegisters
& 7;
81 switch (currentRegister
) {
82 case UNWIND_X86_64_REG_NONE
:
85 case UNWIND_X86_64_REG_RBX
:
86 m_registers
.append(RegisterAtOffset(X86Registers::ebx
, offset
));
89 case UNWIND_X86_64_REG_R12
:
90 m_registers
.append(RegisterAtOffset(X86Registers::r12
, offset
));
93 case UNWIND_X86_64_REG_R13
:
94 m_registers
.append(RegisterAtOffset(X86Registers::r13
, offset
));
97 case UNWIND_X86_64_REG_R14
:
98 m_registers
.append(RegisterAtOffset(X86Registers::r14
, offset
));
101 case UNWIND_X86_64_REG_R15
:
102 m_registers
.append(RegisterAtOffset(X86Registers::r15
, offset
));
105 case UNWIND_X86_64_REG_RBP
:
106 m_registers
.append(RegisterAtOffset(X86Registers::ebp
, offset
));
110 RELEASE_ASSERT_NOT_REACHED();
116 RELEASE_ASSERT((encoding
& UNWIND_ARM64_MODE_MASK
) == UNWIND_ARM64_MODE_FRAME
);
118 m_registers
.append(RegisterAtOffset(ARM64Registers::fp
, 0));
121 if (encoding
& UNWIND_ARM64_FRAME_X19_X20_PAIR
) {
122 m_registers
.append(RegisterAtOffset(ARM64Registers::x19
, offset
-= 8));
123 m_registers
.append(RegisterAtOffset(ARM64Registers::x20
, offset
-= 8));
125 if (encoding
& UNWIND_ARM64_FRAME_X21_X22_PAIR
) {
126 m_registers
.append(RegisterAtOffset(ARM64Registers::x21
, offset
-= 8));
127 m_registers
.append(RegisterAtOffset(ARM64Registers::x22
, offset
-= 8));
129 if (encoding
& UNWIND_ARM64_FRAME_X23_X24_PAIR
) {
130 m_registers
.append(RegisterAtOffset(ARM64Registers::x23
, offset
-= 8));
131 m_registers
.append(RegisterAtOffset(ARM64Registers::x24
, offset
-= 8));
133 if (encoding
& UNWIND_ARM64_FRAME_X25_X26_PAIR
) {
134 m_registers
.append(RegisterAtOffset(ARM64Registers::x25
, offset
-= 8));
135 m_registers
.append(RegisterAtOffset(ARM64Registers::x26
, offset
-= 8));
137 if (encoding
& UNWIND_ARM64_FRAME_X27_X28_PAIR
) {
138 m_registers
.append(RegisterAtOffset(ARM64Registers::x27
, offset
-= 8));
139 m_registers
.append(RegisterAtOffset(ARM64Registers::x28
, offset
-= 8));
141 if (encoding
& UNWIND_ARM64_FRAME_D8_D9_PAIR
) {
142 m_registers
.append(RegisterAtOffset(ARM64Registers::q8
, offset
-= 8));
143 m_registers
.append(RegisterAtOffset(ARM64Registers::q9
, offset
-= 8));
145 if (encoding
& UNWIND_ARM64_FRAME_D10_D11_PAIR
) {
146 m_registers
.append(RegisterAtOffset(ARM64Registers::q10
, offset
-= 8));
147 m_registers
.append(RegisterAtOffset(ARM64Registers::q11
, offset
-= 8));
149 if (encoding
& UNWIND_ARM64_FRAME_D12_D13_PAIR
) {
150 m_registers
.append(RegisterAtOffset(ARM64Registers::q12
, offset
-= 8));
151 m_registers
.append(RegisterAtOffset(ARM64Registers::q13
, offset
-= 8));
153 if (encoding
& UNWIND_ARM64_FRAME_D14_D15_PAIR
) {
154 m_registers
.append(RegisterAtOffset(ARM64Registers::q14
, offset
-= 8));
155 m_registers
.append(RegisterAtOffset(ARM64Registers::q15
, offset
-= 8));
158 #error "Unrecognized architecture"
161 std::sort(m_registers
.begin(), m_registers
.end());
165 void UnwindInfo::dump(PrintStream
& out
) const
167 out
.print(listDump(m_registers
));
170 RegisterAtOffset
* UnwindInfo::find(Reg reg
) const
172 return tryBinarySearch
<RegisterAtOffset
, Reg
>(m_registers
, m_registers
.size(), reg
, RegisterAtOffset::getReg
);
175 unsigned UnwindInfo::indexOf(Reg reg
) const
177 if (RegisterAtOffset
* pointer
= find(reg
))
178 return pointer
- m_registers
.begin();
182 } } // namespace JSC::FTL
184 #endif // ENABLE(FTL_JIT)