Index: lld/MachO/UnwindInfoSection.cpp =================================================================== --- lld/MachO/UnwindInfoSection.cpp +++ lld/MachO/UnwindInfoSection.cpp @@ -256,9 +256,9 @@ // There should only be a handful of unique personality pointers, so we can // encode them as 2-bit indices into a small array. template -void encodePersonalities( - const std::vector *> &cuPtrVector, - std::vector &personalities) { +static void +encodePersonalities(const std::vector *> &cuPtrVector, + std::vector &personalities) { for (CompactUnwindEntry *cu : cuPtrVector) { if (cu->personality == 0) continue; @@ -280,6 +280,34 @@ ") for compact unwind to encode"); } +template +static void addEntriesForFunctionsWithoutUnwindInfo( + std::vector> &cuVector) { + DenseSet hasUnwindInfo; + for (CompactUnwindEntry &cuEntry : cuVector) + if (cuEntry.functionAddress != UINT64_MAX) + hasUnwindInfo.insert(cuEntry.functionAddress); + + // Add explicit "has no unwind info" entries for all global and local symbols + // without unwind info. + auto markNoUnwindInfo = [&cuVector, &hasUnwindInfo](const Defined *d) { + if (d->isLive() && isCodeSection(d->isec)) { + Ptr ptr = d->getVA(); + if (!hasUnwindInfo.count(ptr)) + cuVector.push_back({ptr, 0, 0, 0, 0}); + } + }; + for (Symbol *sym : symtab->getSymbols()) + if (auto *d = dyn_cast(sym)) + markNoUnwindInfo(d); + for (const InputFile *file : inputFiles) + if (auto *objFile = dyn_cast(file)) + for (Symbol *sym : objFile->symbols) + if (auto *d = dyn_cast_or_null(sym)) + if (!d->isExternal()) + markNoUnwindInfo(d); +} + // Scan the __LD,__compact_unwind entries and compute the space needs of // __TEXT,__unwind_info and __TEXT,__eh_frame template void UnwindInfoSectionImpl::finalize() { @@ -301,6 +329,8 @@ cuVector.resize(cuCount); relocateCompactUnwind(compactUnwindSection, cuVector); + addEntriesForFunctionsWithoutUnwindInfo(cuVector); + // Rather than sort & fold the 32-byte entries directly, we create a // vector of pointers to entries and sort & fold that instead. cuPtrVector.reserve(cuCount); Index: lld/test/MachO/compact-unwind.s =================================================================== --- lld/test/MachO/compact-unwind.s +++ lld/test/MachO/compact-unwind.s @@ -33,7 +33,9 @@ # CHECK: SYMBOL TABLE: # CHECK-DAG: [[#%x,MAIN:]] g F __TEXT,__text _main +# CHECK-DAG: [[#%x,QUUX:]] g F __TEXT,__text _quux # CHECK-DAG: [[#%x,FOO:]] l F __TEXT,__text _foo +# CHECK-DAG: [[#%x,BAZ:]] l F __TEXT,__text _baz # CHECK-DAG: [[#%x,EXCEPTION0:]] g O __TEXT,__gcc_except_tab _exception0 # CHECK-DAG: [[#%x,EXCEPTION1:]] g O __TEXT,__gcc_except_tab _exception1 @@ -44,6 +46,11 @@ # CHECK: LSDA descriptors: # CHECK-DAG: function offset=0x[[#%.8x,FOO-BASE]], LSDA offset=0x[[#%.8x,EXCEPTION0-BASE]] # CHECK-DAG: function offset=0x[[#%.8x,MAIN-BASE]], LSDA offset=0x[[#%.8x,EXCEPTION1-BASE]] +# CHECK: Second level indices: +# CHECK-DAG: function offset=0x[[#%.8x,MAIN-BASE]], encoding +# CHECK-DAG: function offset=0x[[#%.8x,FOO-BASE]], encoding +# CHECK-DAG: function offset=0x[[#%.8x,BAZ-BASE]], encoding +# CHECK-DAG: function offset=0x[[#%.8x,QUUX-BASE]], encoding{{.*}}=0x00000000 ## Check that we do not add rebase opcodes to the compact unwind section. # CHECK: Rebase table: @@ -83,7 +90,7 @@ .space 1 #--- main.s -.globl _main, _my_personality, _exception1 +.globl _main, _quux, _my_personality, _exception1 .text .p2align 2 @@ -95,6 +102,14 @@ ret .cfi_endproc +## _quux has no unwind information. +## (In real life, it'd be part of a separate TU that was built with +## -fno-exceptions, while the previous and next TU might be Objective-C++ +## which has unwind info for Objective-C). +.p2align 2 +_quux: + ret + .p2align 2 _baz: .cfi_startproc Index: lld/test/MachO/tools/validate-unwind-info.py =================================================================== --- lld/test/MachO/tools/validate-unwind-info.py +++ lld/test/MachO/tools/validate-unwind-info.py @@ -37,9 +37,12 @@ if not object_encodings_map: sys.exit("no object encodings found in input") + # generate-cfi-funcs.py doesn't generate unwind info for _main. + object_encodings_map['_main'] = '00000000' + program_symbols_map = {address:symbol for address, symbol in - re.findall(r"^%s(%s) g\s+F __TEXT,__text (x\1)$" % (hex8, hex8), + re.findall(r"^%s(%s) g\s+F __TEXT,__text (x\1|_main)$" % (hex8, hex8), objdump_string, re.MULTILINE)} if not program_symbols_map: sys.exit("no program symbols found in input")