[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