diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp --- a/lld/MachO/UnwindInfoSection.cpp +++ b/lld/MachO/UnwindInfoSection.cpp @@ -179,6 +179,9 @@ DenseMap lsdaIndex; std::vector secondLevelPages; uint64_t level2PagesOffset = 0; + + // The final ending address (this should covered folded entries as well) + uint64_t finalEndingAddress = 0; }; UnwindInfoSection::UnwindInfoSection() @@ -458,6 +461,10 @@ return cuEntries[a].functionAddress < cuEntries[b].functionAddress; }); + // Remember the ending boundary before we fold the entries. + finalEndingAddress = cuEntries[cuIndices.back()].functionAddress + + cuEntries[cuIndices.back()].functionLength; + // Fold adjacent entries with matching encoding+personality and without LSDA // We use three iterators on the same cuIndices to fold in-situ: // (1) `foldBegin` is the first of a potential sequence of matching entries @@ -649,8 +656,7 @@ } // Level-1 sentinel const CompactUnwindEntry &cuEnd = cuEntries[cuIndices.back()]; - iep->functionOffset = - cuEnd.functionAddress - in.header->addr + cuEnd.functionLength; + iep->functionOffset = finalEndingAddress - in.header->addr; iep->secondLevelPagesSectionOffset = 0; iep->lsdaIndexArraySectionOffset = lsdaOffset + entriesWithLsda.size() * diff --git a/lld/test/MachO/compact-unwind-folding-bug.s b/lld/test/MachO/compact-unwind-folding-bug.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/compact-unwind-folding-bug.s @@ -0,0 +1,236 @@ +# Test to verify that the folded CUEs covered up to the last entries, even if they were removed/folded. +# TODO: fill in the assertions and remove boilerpalte + + .section __TEXT,__text,regular,pure_instructions + .globl _main ## -- Begin function main + .p2align 4, 0x90 +_main: ## @main + .cfi_startproc +## %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + subq $16, %rsp + movl $0, -4(%rbp) + movl $12, %edi + callq _catchFunc + xorl %eax, %eax + addq $16, %rsp + popq %rbp + retq + .cfi_endproc + ## -- End function + .p2align 4, 0x90 ## -- Begin function catchFunc +_catchFunc: ## @catchFunc +Lfunc_begin0: + .cfi_startproc + .cfi_personality 155, ___objc_personality_v0 + .cfi_lsda 16, Lexception0 +## %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + subq $32, %rsp + movl %edi, -4(%rbp) + movl -4(%rbp), %edi +Ltmp0: + callq _middleFunc1 +Ltmp1: + jmp LBB1_1 +LBB1_1: + jmp LBB1_2 +LBB1_2: + addq $32, %rsp + popq %rbp + retq +LBB1_3: +Ltmp2: + movq %rax, %rcx + movl %edx, %eax + movq %rcx, -16(%rbp) + movl %eax, -20(%rbp) +## %bb.4: + movl -20(%rbp), %eax + movl $1, %ecx + cmpl %ecx, %eax + jne LBB1_8 +## %bb.5: + movq -16(%rbp), %rdi + callq _objc_begin_catch + movq %rax, %rdi + movq _objc_retain@GOTPCREL(%rip), %rax + callq *%rax + movq %rax, -32(%rbp) +Ltmp3: + leaq L__unnamed_cfstring_(%rip), %rdi + xorl %eax, %eax + ## kill: def $al killed $al killed $eax + callq _NSLog +Ltmp4: + jmp LBB1_6 +LBB1_6: + leaq -32(%rbp), %rdi + xorl %eax, %eax + movl %eax, %esi + callq _objc_storeStrong + callq _objc_end_catch + jmp LBB1_2 +LBB1_7: +Ltmp5: + movq %rax, %rcx + movl %edx, %eax + movq %rcx, -16(%rbp) + movl %eax, -20(%rbp) + callq _objc_end_catch +LBB1_8: + movq -16(%rbp), %rdi + callq __Unwind_Resume +Lfunc_end0: + .cfi_endproc + .section __TEXT,__gcc_except_tab + .p2align 2 +GCC_except_table1: +Lexception0: + .byte 255 ## @LPStart Encoding = omit + .byte 155 ## @TType Encoding = indirect pcrel sdata4 + .uleb128 Lttbase0-Lttbaseref0 +Lttbaseref0: + .byte 1 ## Call site Encoding = uleb128 + .uleb128 Lcst_end0-Lcst_begin0 +Lcst_begin0: + .uleb128 Ltmp0-Lfunc_begin0 ## >> Call Site 1 << + .uleb128 Ltmp1-Ltmp0 ## Call between Ltmp0 and Ltmp1 + .uleb128 Ltmp2-Lfunc_begin0 ## jumps to Ltmp2 + .byte 1 ## On action: 1 + .uleb128 Ltmp1-Lfunc_begin0 ## >> Call Site 2 << + .uleb128 Ltmp3-Ltmp1 ## Call between Ltmp1 and Ltmp3 + .byte 0 ## has no landing pad + .byte 0 ## On action: cleanup + .uleb128 Ltmp3-Lfunc_begin0 ## >> Call Site 3 << + .uleb128 Ltmp4-Ltmp3 ## Call between Ltmp3 and Ltmp4 + .uleb128 Ltmp5-Lfunc_begin0 ## jumps to Ltmp5 + .byte 0 ## On action: cleanup + .uleb128 Ltmp4-Lfunc_begin0 ## >> Call Site 4 << + .uleb128 Lfunc_end0-Ltmp4 ## Call between Ltmp4 and Lfunc_end0 + .byte 0 ## has no landing pad + .byte 0 ## On action: cleanup +Lcst_end0: + .byte 1 ## >> Action Record 1 << + ## Catch TypeInfo 1 + .byte 0 ## No further actions + .p2align 2 + ## >> Catch TypeInfos << + .long _OBJC_EHTYPE_$_NSException@GOTPCREL+4 ## TypeInfo 1 +Lttbase0: + .p2align 2 + ## -- End function + .section __TEXT,__text,regular,pure_instructions + .p2align 4, 0x90 ## -- Begin function middleFunc1 +_middleFunc1: ## @middleFunc1 + .cfi_startproc +## %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + subq $16, %rsp + movl %edi, -4(%rbp) + movl -4(%rbp), %edi + callq _throwExcFunc + addq $16, %rsp + popq %rbp + retq + .cfi_endproc + ## -- End function + .p2align 4, 0x90 ## -- Begin function throwExcFunc +_throwExcFunc: ## @throwExcFunc + .cfi_startproc +## %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + subq $16, %rsp + movl %edi, -4(%rbp) + movq _OBJC_CLASSLIST_REFERENCES_$_(%rip), %rdi + movq _OBJC_SELECTOR_REFERENCES_(%rip), %rsi + leaq L__unnamed_cfstring_.2(%rip), %rdx + leaq L__unnamed_cfstring_.4(%rip), %rcx + movq _objc_msgSend@GOTPCREL(%rip), %rax + xorl %r8d, %r8d + ## kill: def $r8 killed $r8d + callq *%rax + movq %rax, %rdi + callq _objc_retainAutoreleasedReturnValue + movq %rax, -16(%rbp) + movq -16(%rbp), %rdi + callq _objc_retainAutorelease + movq %rax, %rdi + callq _objc_exception_throw + .cfi_endproc + ## -- End function + .section __TEXT,__cstring,cstring_literals +L_.str: ## @.str + .asciz "^^^^caught the exception!!!" + + .section __DATA,__cfstring + .p2align 3 ## @_unnamed_cfstring_ +L__unnamed_cfstring_: + .quad ___CFConstantStringClassReference + .long 1992 ## 0x7c8 + .space 4 + .quad L_.str + .quad 27 ## 0x1b + + .section __DATA,__objc_classrefs,regular,no_dead_strip + .p2align 3 ## @"OBJC_CLASSLIST_REFERENCES_$_" +_OBJC_CLASSLIST_REFERENCES_$_: + .quad _OBJC_CLASS_$_NSException + + .section __TEXT,__cstring,cstring_literals +L_.str.1: ## @.str.1 + .asciz "MyCaughtException" + + .section __DATA,__cfstring + .p2align 3 ## @_unnamed_cfstring_.2 +L__unnamed_cfstring_.2: + .quad ___CFConstantStringClassReference + .long 1992 ## 0x7c8 + .space 4 + .quad L_.str.1 + .quad 17 ## 0x11 + + .section __TEXT,__cstring,cstring_literals +L_.str.3: ## @.str.3 + .asciz "Fake exception thrown WITH CATCH" + + .section __DATA,__cfstring + .p2align 3 ## @_unnamed_cfstring_.4 +L__unnamed_cfstring_.4: + .quad ___CFConstantStringClassReference + .long 1992 ## 0x7c8 + .space 4 + .quad L_.str.3 + .quad 32 ## 0x20 + + .section __TEXT,__objc_methname,cstring_literals +L_OBJC_METH_VAR_NAME_: ## @OBJC_METH_VAR_NAME_ + .asciz "exceptionWithName:reason:userInfo:" + + .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip + .p2align 3 ## @OBJC_SELECTOR_REFERENCES_ +_OBJC_SELECTOR_REFERENCES_: + .quad L_OBJC_METH_VAR_NAME_ + + .section __DATA,__objc_imageinfo,regular,no_dead_strip +L_OBJC_IMAGE_INFO: + .long 0 + .long 96 + +.subsections_via_symbols