2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
3 * Copyright (C) 2014 Samsung Electronics
4 * Copyright (C) 2014 University of Szeged
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ==============================================================================
29 * University of Illinois/NCSA
32 * Copyright (c) 2009-2014 by the contributors of LLVM/libc++abi project.
34 * All rights reserved.
40 * University of Illinois at Urbana-Champaign
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:
51 * * Redistributions of source code must retain the above copyright notice,
52 * this list of conditions and the following disclaimers.
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.
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.
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
71 * ==============================================================================
73 * Copyright (c) 2009-2014 by the contributors of LLVM/libc++abi project.
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:
82 * The above copyright notice and this permission notice shall be included in
83 * all copies or substantial portions of the Software.
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
95 #include "FTLUnwindInfo.h"
100 #include <mach-o/compact_unwind_encoding.h>
102 #include <wtf/ListDump.h>
104 namespace JSC
{ namespace FTL
{
106 UnwindInfo::UnwindInfo() { }
107 UnwindInfo::~UnwindInfo() { }
112 struct CompactUnwind
{
115 compact_unwind_encoding_t encoding
;
120 // DWARF unwind instructions
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
141 DW_CFA_operand_mask
= 0x3F // low 6 bits mask for opcode-encoded operands in DW_CFA_advance_loc and DW_CFA_offset
144 // FSF exception handling Pointer-Encoding constants
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
161 DW_EH_PE_relative_mask
= 0x70
164 // 64-bit x86_64 registers
175 DW_X86_64_RET_addr
= 16
245 static uint8_t get8(uintptr_t addr
) { return *((uint8_t*)addr
); }
246 static uint16_t get16(uintptr_t addr
) { return *((uint16_t*)addr
); }
247 static uint32_t get32(uintptr_t addr
) { return *((uint32_t*)addr
); }
248 static uint64_t get64(uintptr_t addr
) { return *((uint64_t*)addr
); }
250 static uintptr_t getP(uintptr_t addr
)
252 // FIXME: add support for 32 bit pointers on 32 bit architectures
256 static uint64_t getULEB128(uintptr_t& addr
, uintptr_t end
)
258 const uint8_t* p
= (uint8_t*)addr
;
259 const uint8_t* pend
= (uint8_t*)end
;
265 RELEASE_ASSERT(p
!= pend
); // truncated uleb128 expression
269 RELEASE_ASSERT(!(bit
>= 64 || b
<< bit
>> bit
!= b
)); // malformed uleb128 expression
273 } while (*p
++ >= 0x80);
278 static int64_t getSLEB128(uintptr_t& addr
, uintptr_t end
)
280 const uint8_t* p
= (uint8_t*)addr
;
281 const uint8_t* pend
= (uint8_t*)end
;
287 RELEASE_ASSERT(p
!= pend
); // truncated sleb128 expression
290 result
|= ((byte
& 0x7f) << bit
);
292 } while (byte
& 0x80);
293 // sign extend negative numbers
295 result
|= (-1LL) << bit
;
300 static uintptr_t getEncodedP(uintptr_t& addr
, uintptr_t end
, uint8_t encoding
)
302 uintptr_t startAddr
= addr
;
303 const uint8_t* p
= (uint8_t*)addr
;
307 switch (encoding
& 0x0F) {
310 p
+= sizeof(uintptr_t);
313 case DW_EH_PE_uleb128
:
314 result
= getULEB128(addr
, end
);
316 case DW_EH_PE_udata2
:
317 result
= get16(addr
);
321 case DW_EH_PE_udata4
:
322 result
= get32(addr
);
326 case DW_EH_PE_udata8
:
327 result
= get64(addr
);
331 case DW_EH_PE_sleb128
:
332 result
= getSLEB128(addr
, end
);
334 case DW_EH_PE_sdata2
:
335 result
= (int16_t)get16(addr
);
339 case DW_EH_PE_sdata4
:
340 result
= (int32_t)get32(addr
);
344 case DW_EH_PE_sdata8
:
345 result
= get64(addr
);
350 RELEASE_ASSERT_NOT_REACHED(); // unknown pointer encoding
353 // then add relative offset
354 switch (encoding
& DW_EH_PE_relative_mask
) {
355 case DW_EH_PE_absptr
:
362 RELEASE_ASSERT_NOT_REACHED(); // unsupported or unknown pointer encoding
365 if (encoding
& DW_EH_PE_indirect
)
366 result
= getP(result
);
371 // Information encoded in a CIE (Common Information Entry)
375 uintptr_t cieInstructions
;
376 uint8_t pointerEncoding
;
377 uint8_t lsdaEncoding
;
378 uint8_t personalityEncoding
;
379 uint8_t personalityOffsetInCIE
;
380 uintptr_t personality
;
382 bool fdesHaveAugmentationData
;
385 // Information about an FDE (Frame Description Entry)
389 uintptr_t fdeInstructions
;
393 // Information about a frame layout and registers saved determined
394 // by "running" the dwarf FDE "instructions"
396 enum { MaxRegisterNumber
= 120 };
398 enum { MaxRegisterNumber
= 17 };
400 #error "Unrecognized architecture"
403 struct RegisterLocation
{
409 uint32_t cfaRegister
;
410 int32_t cfaRegisterOffset
; // CFA = (cfaRegister)+cfaRegisterOffset
411 RegisterLocation savedRegisters
[MaxRegisterNumber
]; // from where to restore registers
414 static void parseCIE(uintptr_t cie
, CIE_Info
* cieInfo
)
416 cieInfo
->pointerEncoding
= 0;
417 cieInfo
->lsdaEncoding
= 0;
418 cieInfo
->personalityEncoding
= 0;
419 cieInfo
->personalityOffsetInCIE
= 0;
420 cieInfo
->personality
= 0;
421 cieInfo
->dataAlignFactor
= 0;
422 cieInfo
->fdesHaveAugmentationData
= false;
423 cieInfo
->cieStart
= cie
;
426 uint64_t cieLength
= get32(p
);
428 uintptr_t cieContentEnd
= p
+ cieLength
;
429 if (cieLength
== 0xffffffff) {
430 // 0xffffffff means length is really next 8 bytes
431 cieLength
= get64(p
);
433 cieContentEnd
= p
+ cieLength
;
436 RELEASE_ASSERT(cieLength
);
438 // CIE ID is always 0
439 RELEASE_ASSERT(!get32(p
)); // CIE ID is not zero
441 // Version is always 1 or 3
442 uint8_t version
= get8(p
);
443 RELEASE_ASSERT((version
== 1) || (version
== 3)); // CIE version is not 1 or 3
446 // save start of augmentation string and find end
447 uintptr_t strStart
= p
;
451 // parse code aligment factor
452 getULEB128(p
, cieContentEnd
);
453 // parse data alignment factor
454 cieInfo
->dataAlignFactor
= getSLEB128(p
, cieContentEnd
);
455 // parse return address register
456 getULEB128(p
, cieContentEnd
);
457 // parse augmentation data based on augmentation string
458 if (get8(strStart
) == 'z') {
459 // parse augmentation data length
460 getULEB128(p
, cieContentEnd
);
461 for (uintptr_t s
= strStart
; get8(s
) != '\0'; ++s
) {
464 cieInfo
->fdesHaveAugmentationData
= true;
466 case 'P': // FIXME: should assert on personality (just to keep in sync with the CU behaviour)
467 cieInfo
->personalityEncoding
= get8(p
);
469 cieInfo
->personalityOffsetInCIE
= p
- cie
;
470 cieInfo
->personality
= getEncodedP(p
, cieContentEnd
, cieInfo
->personalityEncoding
);
472 case 'L': // FIXME: should assert on LSDA (just to keep in sync with the CU behaviour)
473 cieInfo
->lsdaEncoding
= get8(p
);
477 cieInfo
->pointerEncoding
= get8(p
);
481 // ignore unknown letters
486 cieInfo
->cieLength
= cieContentEnd
- cieInfo
->cieStart
;
487 cieInfo
->cieInstructions
= p
;
490 static void findFDE(uintptr_t pc
, uintptr_t ehSectionStart
, uint32_t sectionLength
, FDE_Info
* fdeInfo
, CIE_Info
* cieInfo
)
492 uintptr_t p
= ehSectionStart
;
493 const uintptr_t ehSectionEnd
= p
+ sectionLength
;
494 while (p
< ehSectionEnd
) {
495 uintptr_t currentCFI
= p
;
496 uint64_t cfiLength
= get32(p
);
498 if (cfiLength
== 0xffffffff) {
499 // 0xffffffff means length is really next 8 bytes
500 cfiLength
= get64(p
);
503 RELEASE_ASSERT(cfiLength
); // end marker reached before finding FDE for pc
505 uint32_t id
= get32(p
);
510 // process FDE to see if it covers pc
511 uintptr_t nextCFI
= p
+ cfiLength
;
512 uint32_t ciePointer
= get32(p
);
513 uintptr_t cieStart
= p
- ciePointer
;
514 // validate pointer to CIE is within section
515 RELEASE_ASSERT((ehSectionStart
<= cieStart
) && (cieStart
< ehSectionEnd
)); // malformed FDE. CIE is bad
517 parseCIE(cieStart
, cieInfo
);
520 // parse pc begin and range
521 uintptr_t pcStart
= getEncodedP(p
, nextCFI
, cieInfo
->pointerEncoding
);
522 uintptr_t pcRange
= getEncodedP(p
, nextCFI
, cieInfo
->pointerEncoding
& 0x0F);
524 // test if pc is within the function this FDE covers
525 // if pc is not in begin/range, skip this FDE
526 if ((pcStart
<= pc
) && (pc
< pcStart
+pcRange
)) {
527 // parse rest of info
529 // check for augmentation length
530 if (cieInfo
->fdesHaveAugmentationData
) {
531 uintptr_t augLen
= getULEB128(p
, nextCFI
);
532 uintptr_t endOfAug
= p
+ augLen
;
533 if (cieInfo
->lsdaEncoding
) {
534 // peek at value (without indirection). Zero means no lsda
535 uintptr_t lsdaStart
= p
;
536 if (getEncodedP(p
, nextCFI
, cieInfo
->lsdaEncoding
& 0x0F)) {
537 // reset pointer and re-parse lsda address
539 fdeInfo
->lsda
= getEncodedP(p
, nextCFI
, cieInfo
->lsdaEncoding
);
544 fdeInfo
->fdeStart
= currentCFI
;
545 fdeInfo
->fdeLength
= nextCFI
- currentCFI
;
546 fdeInfo
->fdeInstructions
= p
;
555 RELEASE_ASSERT_NOT_REACHED(); // no FDE found for pc
558 static void executeDefCFARegister(uint64_t reg
, PrologInfo
* results
)
560 RELEASE_ASSERT(reg
<= MaxRegisterNumber
); // reg too big
561 results
->cfaRegister
= reg
;
564 static void executeDefCFAOffset(int64_t offset
, PrologInfo
* results
)
566 RELEASE_ASSERT(offset
<= 0x80000000); // cfa has negative offset (dwarf might contain epilog)
567 results
->cfaRegisterOffset
= offset
;
570 static void executeOffset(uint64_t reg
, int64_t offset
, PrologInfo
*results
)
572 if (reg
> MaxRegisterNumber
)
575 RELEASE_ASSERT(!results
->savedRegisters
[reg
].saved
);
576 results
->savedRegisters
[reg
].saved
= true;
577 results
->savedRegisters
[reg
].offset
= offset
;
580 static void parseInstructions(uintptr_t instructions
, uintptr_t instructionsEnd
, const CIE_Info
& cieInfo
, PrologInfo
* results
)
582 uintptr_t p
= instructions
;
584 // see Dwarf Spec, section 6.4.2 for details on unwind opcodes
585 while ((p
< instructionsEnd
)) {
587 uint8_t opcode
= get8(p
);
594 getEncodedP(p
, instructionsEnd
, cieInfo
.pointerEncoding
);
596 case DW_CFA_advance_loc1
:
599 case DW_CFA_advance_loc2
:
602 case DW_CFA_advance_loc4
:
606 executeDefCFARegister(getULEB128(p
, instructionsEnd
), results
);
607 executeDefCFAOffset(getULEB128(p
, instructionsEnd
), results
);
609 case DW_CFA_def_cfa_sf
:
610 executeDefCFARegister(getULEB128(p
, instructionsEnd
), results
);
611 executeDefCFAOffset(getSLEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
, results
);
613 case DW_CFA_def_cfa_register
:
614 executeDefCFARegister(getULEB128(p
, instructionsEnd
), results
);
616 case DW_CFA_def_cfa_offset
:
617 executeDefCFAOffset(getULEB128(p
, instructionsEnd
), results
);
619 case DW_CFA_def_cfa_offset_sf
:
620 executeDefCFAOffset(getSLEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
, results
);
622 case DW_CFA_offset_extended
:
623 reg
= getULEB128(p
, instructionsEnd
);
624 executeOffset(reg
, getULEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
, results
);
626 case DW_CFA_offset_extended_sf
:
627 reg
= getULEB128(p
, instructionsEnd
);
628 executeOffset(reg
, getSLEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
, results
);
631 operand
= opcode
& DW_CFA_operand_mask
;
632 switch (opcode
& ~DW_CFA_operand_mask
) {
634 executeOffset(operand
, getULEB128(p
, instructionsEnd
) * cieInfo
.dataAlignFactor
, results
);
636 case DW_CFA_advance_loc
:
639 RELEASE_ASSERT_NOT_REACHED(); // unknown or unsupported CFA opcode
645 static void parseFDEInstructions(const FDE_Info
& fdeInfo
, const CIE_Info
& cieInfo
, PrologInfo
* results
)
648 bzero(results
, sizeof(PrologInfo
));
650 // parse CIE then FDE instructions
651 parseInstructions(cieInfo
.cieInstructions
, cieInfo
.cieStart
+ cieInfo
.cieLength
, cieInfo
, results
);
652 parseInstructions(fdeInfo
.fdeInstructions
, fdeInfo
.fdeStart
+ fdeInfo
.fdeLength
, cieInfo
, results
);
655 } // anonymous namespace
657 bool UnwindInfo::parse(void* section
, size_t size
, GeneratedFunction generatedFunction
)
660 RELEASE_ASSERT(!!section
);
665 RELEASE_ASSERT(size
>= sizeof(CompactUnwind
));
667 CompactUnwind
* data
= bitwise_cast
<CompactUnwind
*>(section
);
669 RELEASE_ASSERT(!data
->personality
); // We don't know how to handle this.
670 RELEASE_ASSERT(!data
->lsda
); // We don't know how to handle this.
671 RELEASE_ASSERT(data
->function
== generatedFunction
); // The unwind data better be for our function.
673 compact_unwind_encoding_t encoding
= data
->encoding
;
674 RELEASE_ASSERT(!(encoding
& UNWIND_IS_NOT_FUNCTION_START
));
675 RELEASE_ASSERT(!(encoding
& UNWIND_HAS_LSDA
));
676 RELEASE_ASSERT(!(encoding
& UNWIND_PERSONALITY_MASK
));
679 RELEASE_ASSERT((encoding
& UNWIND_X86_64_MODE_MASK
) == UNWIND_X86_64_MODE_RBP_FRAME
);
681 int32_t offset
= -((encoding
& UNWIND_X86_64_RBP_FRAME_OFFSET
) >> 16) * 8;
682 uint32_t nextRegisters
= encoding
;
683 for (unsigned i
= 5; i
--;) {
684 uint32_t currentRegister
= nextRegisters
& 7;
687 switch (currentRegister
) {
688 case UNWIND_X86_64_REG_NONE
:
691 case UNWIND_X86_64_REG_RBX
:
692 m_registers
.append(RegisterAtOffset(X86Registers::ebx
, offset
));
695 case UNWIND_X86_64_REG_R12
:
696 m_registers
.append(RegisterAtOffset(X86Registers::r12
, offset
));
699 case UNWIND_X86_64_REG_R13
:
700 m_registers
.append(RegisterAtOffset(X86Registers::r13
, offset
));
703 case UNWIND_X86_64_REG_R14
:
704 m_registers
.append(RegisterAtOffset(X86Registers::r14
, offset
));
707 case UNWIND_X86_64_REG_R15
:
708 m_registers
.append(RegisterAtOffset(X86Registers::r15
, offset
));
711 case UNWIND_X86_64_REG_RBP
:
712 m_registers
.append(RegisterAtOffset(X86Registers::ebp
, offset
));
716 RELEASE_ASSERT_NOT_REACHED();
722 RELEASE_ASSERT((encoding
& UNWIND_ARM64_MODE_MASK
) == UNWIND_ARM64_MODE_FRAME
);
724 m_registers
.append(RegisterAtOffset(ARM64Registers::fp
, 0));
727 if (encoding
& UNWIND_ARM64_FRAME_X19_X20_PAIR
) {
728 m_registers
.append(RegisterAtOffset(ARM64Registers::x19
, offset
-= 8));
729 m_registers
.append(RegisterAtOffset(ARM64Registers::x20
, offset
-= 8));
731 if (encoding
& UNWIND_ARM64_FRAME_X21_X22_PAIR
) {
732 m_registers
.append(RegisterAtOffset(ARM64Registers::x21
, offset
-= 8));
733 m_registers
.append(RegisterAtOffset(ARM64Registers::x22
, offset
-= 8));
735 if (encoding
& UNWIND_ARM64_FRAME_X23_X24_PAIR
) {
736 m_registers
.append(RegisterAtOffset(ARM64Registers::x23
, offset
-= 8));
737 m_registers
.append(RegisterAtOffset(ARM64Registers::x24
, offset
-= 8));
739 if (encoding
& UNWIND_ARM64_FRAME_X25_X26_PAIR
) {
740 m_registers
.append(RegisterAtOffset(ARM64Registers::x25
, offset
-= 8));
741 m_registers
.append(RegisterAtOffset(ARM64Registers::x26
, offset
-= 8));
743 if (encoding
& UNWIND_ARM64_FRAME_X27_X28_PAIR
) {
744 m_registers
.append(RegisterAtOffset(ARM64Registers::x27
, offset
-= 8));
745 m_registers
.append(RegisterAtOffset(ARM64Registers::x28
, offset
-= 8));
747 if (encoding
& UNWIND_ARM64_FRAME_D8_D9_PAIR
) {
748 m_registers
.append(RegisterAtOffset(ARM64Registers::q8
, offset
-= 8));
749 m_registers
.append(RegisterAtOffset(ARM64Registers::q9
, offset
-= 8));
751 if (encoding
& UNWIND_ARM64_FRAME_D10_D11_PAIR
) {
752 m_registers
.append(RegisterAtOffset(ARM64Registers::q10
, offset
-= 8));
753 m_registers
.append(RegisterAtOffset(ARM64Registers::q11
, offset
-= 8));
755 if (encoding
& UNWIND_ARM64_FRAME_D12_D13_PAIR
) {
756 m_registers
.append(RegisterAtOffset(ARM64Registers::q12
, offset
-= 8));
757 m_registers
.append(RegisterAtOffset(ARM64Registers::q13
, offset
-= 8));
759 if (encoding
& UNWIND_ARM64_FRAME_D14_D15_PAIR
) {
760 m_registers
.append(RegisterAtOffset(ARM64Registers::q14
, offset
-= 8));
761 m_registers
.append(RegisterAtOffset(ARM64Registers::q15
, offset
-= 8));
764 #error "Unrecognized architecture"
772 findFDE((uintptr_t)generatedFunction
, (uintptr_t)section
, size
, &fdeInfo
, &cieInfo
);
773 parseFDEInstructions(fdeInfo
, cieInfo
, &prolog
);
776 RELEASE_ASSERT(prolog
.cfaRegister
== UNW_X86_64_rbp
);
777 RELEASE_ASSERT(prolog
.cfaRegisterOffset
== 16);
778 RELEASE_ASSERT(prolog
.savedRegisters
[UNW_X86_64_rbp
].saved
);
779 RELEASE_ASSERT(prolog
.savedRegisters
[UNW_X86_64_rbp
].offset
== -prolog
.cfaRegisterOffset
);
781 for (int i
= 0; i
< MaxRegisterNumber
; ++i
) {
782 if (prolog
.savedRegisters
[i
].saved
) {
785 m_registers
.append(RegisterAtOffset(X86Registers::ebx
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
788 m_registers
.append(RegisterAtOffset(X86Registers::r12
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
791 m_registers
.append(RegisterAtOffset(X86Registers::r13
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
794 m_registers
.append(RegisterAtOffset(X86Registers::r14
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
797 m_registers
.append(RegisterAtOffset(X86Registers::r15
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
800 m_registers
.append(RegisterAtOffset(X86Registers::ebp
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
802 case DW_X86_64_RET_addr
:
805 RELEASE_ASSERT_NOT_REACHED(); // non-standard register being saved in prolog
810 RELEASE_ASSERT(prolog
.cfaRegister
== UNW_ARM64_fp
);
811 RELEASE_ASSERT(prolog
.cfaRegisterOffset
== 16);
812 RELEASE_ASSERT(prolog
.savedRegisters
[UNW_ARM64_fp
].saved
);
813 RELEASE_ASSERT(prolog
.savedRegisters
[UNW_ARM64_fp
].offset
== -prolog
.cfaRegisterOffset
);
815 for (int i
= 0; i
< MaxRegisterNumber
; ++i
) {
816 if (prolog
.savedRegisters
[i
].saved
) {
819 m_registers
.append(RegisterAtOffset(ARM64Registers::x0
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
822 m_registers
.append(RegisterAtOffset(ARM64Registers::x1
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
825 m_registers
.append(RegisterAtOffset(ARM64Registers::x2
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
828 m_registers
.append(RegisterAtOffset(ARM64Registers::x3
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
831 m_registers
.append(RegisterAtOffset(ARM64Registers::x4
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
834 m_registers
.append(RegisterAtOffset(ARM64Registers::x5
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
837 m_registers
.append(RegisterAtOffset(ARM64Registers::x6
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
840 m_registers
.append(RegisterAtOffset(ARM64Registers::x7
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
843 m_registers
.append(RegisterAtOffset(ARM64Registers::x8
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
846 m_registers
.append(RegisterAtOffset(ARM64Registers::x9
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
849 m_registers
.append(RegisterAtOffset(ARM64Registers::x10
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
852 m_registers
.append(RegisterAtOffset(ARM64Registers::x11
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
855 m_registers
.append(RegisterAtOffset(ARM64Registers::x12
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
858 m_registers
.append(RegisterAtOffset(ARM64Registers::x13
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
861 m_registers
.append(RegisterAtOffset(ARM64Registers::x14
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
864 m_registers
.append(RegisterAtOffset(ARM64Registers::x15
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
867 m_registers
.append(RegisterAtOffset(ARM64Registers::x16
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
870 m_registers
.append(RegisterAtOffset(ARM64Registers::x17
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
873 m_registers
.append(RegisterAtOffset(ARM64Registers::x18
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
876 m_registers
.append(RegisterAtOffset(ARM64Registers::x19
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
879 m_registers
.append(RegisterAtOffset(ARM64Registers::x20
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
882 m_registers
.append(RegisterAtOffset(ARM64Registers::x21
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
885 m_registers
.append(RegisterAtOffset(ARM64Registers::x22
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
888 m_registers
.append(RegisterAtOffset(ARM64Registers::x23
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
891 m_registers
.append(RegisterAtOffset(ARM64Registers::x24
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
894 m_registers
.append(RegisterAtOffset(ARM64Registers::x25
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
897 m_registers
.append(RegisterAtOffset(ARM64Registers::x26
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
900 m_registers
.append(RegisterAtOffset(ARM64Registers::x27
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
903 m_registers
.append(RegisterAtOffset(ARM64Registers::x28
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
906 m_registers
.append(RegisterAtOffset(ARM64Registers::fp
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
909 m_registers
.append(RegisterAtOffset(ARM64Registers::x30
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
912 m_registers
.append(RegisterAtOffset(ARM64Registers::sp
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
915 m_registers
.append(RegisterAtOffset(ARM64Registers::q0
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
918 m_registers
.append(RegisterAtOffset(ARM64Registers::q1
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
921 m_registers
.append(RegisterAtOffset(ARM64Registers::q2
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
924 m_registers
.append(RegisterAtOffset(ARM64Registers::q3
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
927 m_registers
.append(RegisterAtOffset(ARM64Registers::q4
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
930 m_registers
.append(RegisterAtOffset(ARM64Registers::q5
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
933 m_registers
.append(RegisterAtOffset(ARM64Registers::q6
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
936 m_registers
.append(RegisterAtOffset(ARM64Registers::q7
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
939 m_registers
.append(RegisterAtOffset(ARM64Registers::q8
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
942 m_registers
.append(RegisterAtOffset(ARM64Registers::q9
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
945 m_registers
.append(RegisterAtOffset(ARM64Registers::q10
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
948 m_registers
.append(RegisterAtOffset(ARM64Registers::q11
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
951 m_registers
.append(RegisterAtOffset(ARM64Registers::q12
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
954 m_registers
.append(RegisterAtOffset(ARM64Registers::q13
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
957 m_registers
.append(RegisterAtOffset(ARM64Registers::q14
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
960 m_registers
.append(RegisterAtOffset(ARM64Registers::q15
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
963 m_registers
.append(RegisterAtOffset(ARM64Registers::q16
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
966 m_registers
.append(RegisterAtOffset(ARM64Registers::q17
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
969 m_registers
.append(RegisterAtOffset(ARM64Registers::q18
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
972 m_registers
.append(RegisterAtOffset(ARM64Registers::q19
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
975 m_registers
.append(RegisterAtOffset(ARM64Registers::q20
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
978 m_registers
.append(RegisterAtOffset(ARM64Registers::q21
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
981 m_registers
.append(RegisterAtOffset(ARM64Registers::q22
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
984 m_registers
.append(RegisterAtOffset(ARM64Registers::q23
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
987 m_registers
.append(RegisterAtOffset(ARM64Registers::q24
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
990 m_registers
.append(RegisterAtOffset(ARM64Registers::q25
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
993 m_registers
.append(RegisterAtOffset(ARM64Registers::q26
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
996 m_registers
.append(RegisterAtOffset(ARM64Registers::q27
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
999 m_registers
.append(RegisterAtOffset(ARM64Registers::q28
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
1002 m_registers
.append(RegisterAtOffset(ARM64Registers::q29
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
1005 m_registers
.append(RegisterAtOffset(ARM64Registers::q30
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
1008 m_registers
.append(RegisterAtOffset(ARM64Registers::q31
, prolog
.savedRegisters
[i
].offset
+ prolog
.cfaRegisterOffset
));
1011 RELEASE_ASSERT_NOT_REACHED(); // non-standard register being saved in prolog
1016 #error "Unrecognized architecture"
1020 std::sort(m_registers
.begin(), m_registers
.end());
1024 void UnwindInfo::dump(PrintStream
& out
) const
1026 out
.print(listDump(m_registers
));
1029 RegisterAtOffset
* UnwindInfo::find(Reg reg
) const
1031 return tryBinarySearch
<RegisterAtOffset
, Reg
>(m_registers
, m_registers
.size(), reg
, RegisterAtOffset::getReg
);
1034 unsigned UnwindInfo::indexOf(Reg reg
) const
1036 if (RegisterAtOffset
* pointer
= find(reg
))
1037 return pointer
- m_registers
.begin();
1041 } } // namespace JSC::FTL
1043 #endif // ENABLE(FTL_JIT)