[lld] 8a7b5eb - [lld/mac] Don't crash when dead-stripping removes all unwind info

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 7 10:05:58 PDT 2021


Author: Nico Weber
Date: 2021-07-07T13:05:40-04:00
New Revision: 8a7b5ebf4d8fd5f4cfe1daf72e0e58df7f716e4c

URL: https://github.com/llvm/llvm-project/commit/8a7b5ebf4d8fd5f4cfe1daf72e0e58df7f716e4c
DIFF: https://github.com/llvm/llvm-project/commit/8a7b5ebf4d8fd5f4cfe1daf72e0e58df7f716e4c.diff

LOG: [lld/mac] Don't crash when dead-stripping removes all unwind info

If the input has compact unwind info but all of it is removed
after dead stripping, we would crash. Now we don't write any
__unwind_info section at all, like ld64.

This is a bit awkward to implement because we only know the final
state of unwind info after UnwindInfoSectionImpl<Ptr>::finalize(),
which is called after sections are added. So add a small amount of
bookkeeping to relocateCompactUnwind() instead (which runs earlier)
so that we can predict what finalize() will do before it runs.

Fixes PR51010.

Differential Revision: https://reviews.llvm.org/D105557

Added: 
    

Modified: 
    lld/MachO/UnwindInfoSection.cpp
    lld/MachO/UnwindInfoSection.h
    lld/test/MachO/compact-unwind.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index 4864a248d6b16..6bd07c42af819 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -165,6 +165,14 @@ void UnwindInfoSectionImpl<Ptr>::prepareRelocations(ConcatInputSection *isec) {
   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;
@@ -402,6 +410,13 @@ template <class Ptr> void UnwindInfoSectionImpl<Ptr>::finalize() {
                        }),
       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
@@ -531,6 +546,8 @@ template <class Ptr> void UnwindInfoSectionImpl<Ptr>::finalize() {
 
 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;

diff  --git a/lld/MachO/UnwindInfoSection.h b/lld/MachO/UnwindInfoSection.h
index 11503aaed0da9..fca11de6eeb1a 100644
--- a/lld/MachO/UnwindInfoSection.h
+++ b/lld/MachO/UnwindInfoSection.h
@@ -28,7 +28,7 @@ template <class Ptr> struct CompactUnwindEntry {
 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;
@@ -43,6 +43,7 @@ class UnwindInfoSection : public SyntheticSection {
 
   ConcatOutputSection *compactUnwindSection;
   uint64_t unwindInfoSize = 0;
+  bool allEntriesAreOmitted = true;
 };
 
 UnwindInfoSection *makeUnwindInfoSection();

diff  --git a/lld/test/MachO/compact-unwind.s b/lld/test/MachO/compact-unwind.s
index 7aeae89239879..d1d4f23fb51e2 100644
--- a/lld/test/MachO/compact-unwind.s
+++ b/lld/test/MachO/compact-unwind.s
@@ -62,6 +62,16 @@
 # 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
@@ -146,3 +156,16 @@ _exception1:
   .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


        


More information about the llvm-commits mailing list