for (size_t i = 0; i < isec->relocs.size(); ++i) {
Reloc &r = isec->relocs[i];
assert(target->hasAttr(r.type, RelocAttrBits::UNSIGNED));
+
+ if (r.offset % sizeof(CompactUnwindEntry<Ptr>) == 0) {
+ if (auto *referentIsec = r.referent.dyn_cast<InputSection *>())
+ if (!cast<ConcatInputSection>(referentIsec)->shouldOmitFromOutput())
+ allEntriesAreOmitted = false;
+ continue;
+ }
+
if (r.offset % sizeof(CompactUnwindEntry<Ptr>) !=
offsetof(CompactUnwindEntry<Ptr>, personality))
continue;
}),
cuPtrVector.end());
+ // If there are no entries left after adding explicit "no unwind info"
+ // entries and removing entries for dead-stripped functions, don't write
+ // an __unwind_info section at all.
+ assert(allEntriesAreOmitted == cuPtrVector.empty());
+ if (cuPtrVector.empty())
+ return;
+
// Fold adjacent entries with matching encoding+personality+lsda
// We use three iterators on the same cuPtrVector to fold in-situ:
// (1) `foldBegin` is the first of a potential sequence of matching entries
template <class Ptr>
void UnwindInfoSectionImpl<Ptr>::writeTo(uint8_t *buf) const {
+ assert(!cuPtrVector.empty() && "call only if there is unwind info");
+
// section header
auto *uip = reinterpret_cast<unwind_info_section_header *>(buf);
uip->version = 1;
class UnwindInfoSection : public SyntheticSection {
public:
bool isNeeded() const override {
- return !compactUnwindSection->inputs.empty();
+ return !compactUnwindSection->inputs.empty() && !allEntriesAreOmitted;
}
uint64_t getSize() const override { return unwindInfoSize; }
virtual void addInput(ConcatInputSection *) = 0;
ConcatOutputSection *compactUnwindSection;
uint64_t unwindInfoSize = 0;
+ bool allEntriesAreOmitted = true;
};
UnwindInfoSection *makeUnwindInfoSection();
# CHECK-NEXT: __DATA_CONST __got 0x{{[0-9A-F]*}} pointer
# CHECK-NOT: __TEXT
+## Check that we don't create an __unwind_info section if no unwind info
+## remains after dead-stripping.
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 \
+# RUN: %t/empty-after-dead-strip.s -o %t/x86_64-empty-after-dead-strip.o
+# RUN: %lld -dylib -dead_strip -arch x86_64 -lSystem \
+# RUN: %t/x86_64-empty-after-dead-strip.o -o %t/x86_64-empty-after-strip.dylib
+# RUN: llvm-objdump --macho --unwind-info %t/x86_64-empty-after-strip.dylib | \
+# RUN: FileCheck %s --check-prefixes=NOUNWIND --allow-empty
+# NOUNWIND-NOT: Contents of __unwind_info section:
+
#--- my-personality.s
.globl _my_personality, _exception0
.text
.space 1
.subsections_via_symbols
+
+#--- empty-after-dead-strip.s
+.text
+
+## Local symbol with unwind info.
+## The symbol is removed by -dead_strip.
+_foo :
+ .cfi_startproc
+ .cfi_def_cfa_offset 16
+ retq
+ .cfi_endproc
+
+.subsections_via_symbols