[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
This commit is contained in:
parent
d4cb286b05
commit
8a7b5ebf4d
|
@ -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;
|
||||
|
|
|
@ -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 @@ protected:
|
|||
|
||||
ConcatOutputSection *compactUnwindSection;
|
||||
uint64_t unwindInfoSize = 0;
|
||||
bool allEntriesAreOmitted = true;
|
||||
};
|
||||
|
||||
UnwindInfoSection *makeUnwindInfoSection();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue