diff --git a/lld/lib/ReaderWriter/MachO/Atoms.h b/lld/lib/ReaderWriter/MachO/Atoms.h index 3107ee384d6e..24318a0117b1 100644 --- a/lld/lib/ReaderWriter/MachO/Atoms.h +++ b/lld/lib/ReaderWriter/MachO/Atoms.h @@ -17,18 +17,20 @@ namespace mach_o { class MachODefinedAtom : public SimpleDefinedAtom { public: MachODefinedAtom(const File &f, const StringRef name, Scope scope, - ContentType type, Merge merge, bool thumb, + ContentType type, Merge merge, bool thumb, bool noDeadStrip, const ArrayRef content) : SimpleDefinedAtom(f), _name(name), _content(content), - _contentType(type), _scope(scope), _merge(merge), _thumb(thumb) {} + _contentType(type), _scope(scope), _merge(merge), _thumb(thumb), + _noDeadStrip(noDeadStrip) {} // Constructor for zero-fill content MachODefinedAtom(const File &f, const StringRef name, Scope scope, - uint64_t size) + uint64_t size, bool noDeadStrip) : SimpleDefinedAtom(f), _name(name), _content(ArrayRef(nullptr, size)), _contentType(DefinedAtom::typeZeroFill), - _scope(scope), _merge(mergeNo), _thumb(false) {} + _scope(scope), _merge(mergeNo), _thumb(false), + _noDeadStrip(noDeadStrip) {} uint64_t size() const override { return _content.size(); } @@ -45,6 +47,8 @@ public: return deadStripNever; if (_contentType == DefinedAtom::typeTerminatorPtr) return deadStripNever; + if (_noDeadStrip) + return deadStripNever; return deadStripNormal; } @@ -55,13 +59,15 @@ public: bool isThumb() const { return _thumb; } - void addReference(uint32_t offsetInAtom, uint16_t relocType, - const Atom *target, Reference::Addend addend, - Reference::KindArch arch = Reference::KindArch::x86_64, - Reference::KindNamespace ns = Reference::KindNamespace::mach_o) { - SimpleDefinedAtom::addReference(ns, arch, relocType, offsetInAtom, target, addend); + void addReference(uint32_t offsetInAtom, uint16_t relocType, + const Atom *target, Reference::Addend addend, + Reference::KindArch arch = Reference::KindArch::x86_64, + Reference::KindNamespace ns + = Reference::KindNamespace::mach_o) { + SimpleDefinedAtom::addReference(ns, arch, relocType, offsetInAtom, target, + addend); } - + private: const StringRef _name; const ArrayRef _content; @@ -69,25 +75,28 @@ private: const Scope _scope; const Merge _merge; const bool _thumb; + const bool _noDeadStrip; }; class MachODefinedCustomSectionAtom : public MachODefinedAtom { public: - MachODefinedCustomSectionAtom(const File &f, const StringRef name, + MachODefinedCustomSectionAtom(const File &f, const StringRef name, Scope scope, ContentType type, Merge merge, - bool thumb, const ArrayRef content, + bool thumb, bool noDeadStrip, + const ArrayRef content, StringRef sectionName) - : MachODefinedAtom(f, name, scope, type, merge, thumb, content), + : MachODefinedAtom(f, name, scope, type, merge, thumb, noDeadStrip, + content), _sectionName(sectionName) {} SectionChoice sectionChoice() const override { return DefinedAtom::sectionCustomRequired; } - + StringRef customSectionName() const override { return _sectionName; } -private: +private: StringRef _sectionName; }; diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h index bc6a75a39f5a..f3e77e788de9 100644 --- a/lld/lib/ReaderWriter/MachO/File.h +++ b/lld/lib/ReaderWriter/MachO/File.h @@ -32,9 +32,10 @@ public: void addDefinedAtom(StringRef name, Atom::Scope scope, DefinedAtom::ContentType type, DefinedAtom::Merge merge, uint64_t sectionOffset, uint64_t contentSize, bool thumb, - bool copyRefs, const Section *inSection) { + bool noDeadStrip, bool copyRefs, + const Section *inSection) { assert(sectionOffset+contentSize <= inSection->content.size()); - ArrayRef content = inSection->content.slice(sectionOffset, + ArrayRef content = inSection->content.slice(sectionOffset, contentSize); if (copyRefs) { // Make a copy of the atom's name and content that is owned by this file. @@ -42,18 +43,18 @@ public: content = content.copy(_allocator); } MachODefinedAtom *atom = - new (_allocator) MachODefinedAtom(*this, name, scope, type, merge, - thumb, content); + new (_allocator) MachODefinedAtom(*this, name, scope, type, merge, + thumb, noDeadStrip, content); addAtomForSection(inSection, atom, sectionOffset); } void addDefinedAtomInCustomSection(StringRef name, Atom::Scope scope, DefinedAtom::ContentType type, DefinedAtom::Merge merge, - bool thumb, uint64_t sectionOffset, uint64_t contentSize, - StringRef sectionName, bool copyRefs, - const Section *inSection) { + bool thumb, bool noDeadStrip, uint64_t sectionOffset, + uint64_t contentSize, StringRef sectionName, + bool copyRefs, const Section *inSection) { assert(sectionOffset+contentSize <= inSection->content.size()); - ArrayRef content = inSection->content.slice(sectionOffset, + ArrayRef content = inSection->content.slice(sectionOffset, contentSize); if (copyRefs) { // Make a copy of the atom's name and content that is owned by this file. @@ -63,20 +64,22 @@ public: } MachODefinedCustomSectionAtom *atom = new (_allocator) MachODefinedCustomSectionAtom(*this, name, scope, type, - merge, thumb, content, + merge, thumb, + noDeadStrip, content, sectionName); addAtomForSection(inSection, atom, sectionOffset); } void addZeroFillDefinedAtom(StringRef name, Atom::Scope scope, uint64_t sectionOffset, uint64_t size, - bool copyRefs, const Section *inSection) { + bool noDeadStrip, bool copyRefs, + const Section *inSection) { if (copyRefs) { // Make a copy of the atom's name and content that is owned by this file. name = name.copy(_allocator); } MachODefinedAtom *atom = - new (_allocator) MachODefinedAtom(*this, name, scope, size); + new (_allocator) MachODefinedAtom(*this, name, scope, size, noDeadStrip); addAtomForSection(inSection, atom, sectionOffset); } diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp index 1df6e55dc3a8..cf0a9cf58d88 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp @@ -656,6 +656,11 @@ uint16_t Util::descBits(const DefinedAtom* atom) { desc |= N_SYMBOL_RESOLVER; if (_archHandler.isThumbFunction(*atom)) desc |= N_ARM_THUMB_DEF; + if (atom->deadStrip() == DefinedAtom::deadStripNever) { + if ((atom->contentType() != DefinedAtom::typeInitializerPtr) + && (atom->contentType() != DefinedAtom::typeTerminatorPtr)) + desc |= N_NO_DEAD_STRIP; + } return desc; } diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index 9b9c625ab76f..aa4249fc8cd2 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -225,9 +225,10 @@ void atomFromSymbol(DefinedAtom::ContentType atomType, const Section §ion, // difference between this and the next symbol. uint64_t size = nextSymbolAddr - symbolAddr; uint64_t offset = symbolAddr - section.address; + bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP); if (section.type == llvm::MachO::S_ZEROFILL) { - file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size, copyRefs, - §ion); + file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size, + noDeadStrip, copyRefs, §ion); } else { DefinedAtom::Merge merge = (symbolDescFlags & N_WEAK_DEF) ? DefinedAtom::mergeAsWeak : DefinedAtom::mergeNo; @@ -239,15 +240,15 @@ void atomFromSymbol(DefinedAtom::ContentType atomType, const Section §ion, std::string segSectName = section.segmentName.str() + "/" + section.sectionName.str(); file.addDefinedAtomInCustomSection(symbolName, symbolScope, atomType, - merge, thumb,offset, size, segSectName, - true, §ion); + merge, thumb, noDeadStrip, offset, + size, segSectName, true, §ion); } else { if ((atomType == lld::DefinedAtom::typeCode) && (symbolDescFlags & N_SYMBOL_RESOLVER)) { atomType = lld::DefinedAtom::typeResolver; } file.addDefinedAtom(symbolName, symbolScope, atomType, merge, - offset, size, thumb, copyRefs, §ion); + offset, size, thumb, noDeadStrip, copyRefs, §ion); } } } @@ -419,7 +420,7 @@ std::error_code processSection(DefinedAtom::ContentType atomType, "not zero terminated."); } file.addDefinedAtom(StringRef(), scope, atomType, merge, offset, size, - false, copyRefs, §ion); + false, false, copyRefs, §ion); offset += size; } } diff --git a/lld/test/mach-o/parse-function.yaml b/lld/test/mach-o/parse-function.yaml index 9054665d1b44..1bc9878c7087 100644 --- a/lld/test/mach-o/parse-function.yaml +++ b/lld/test/mach-o/parse-function.yaml @@ -19,7 +19,7 @@ sections: address: 0x0000000000000000 content: [ 0xCC, 0xC3, 0x90, 0xC3, 0x90, 0x90, 0xC3, 0x90, 0x90, 0x90, 0xC3, 0x90, 0x90, 0x90, 0x90, 0xC3, - 0x31, 0xC0, 0xC3 ] + 0xCC, 0x31, 0xC0, 0xC3 ] local-symbols: - name: _myStatic type: N_SECT @@ -48,12 +48,18 @@ global-symbols: sect: 1 desc: [ N_WEAK_DEF ] value: 0x0000000000000007 + - name: _myStripNot + type: N_SECT + scope: [ N_EXT ] + sect: 1 + desc: [ N_NO_DEAD_STRIP ] + value: 0x0000000000000010 - name: _myResolver type: N_SECT scope: [ N_EXT ] sect: 1 desc: [ N_SYMBOL_RESOLVER ] - value: 0x0000000000000010 + value: 0x0000000000000011 ... # CHECK-NOT: name: @@ -82,6 +88,11 @@ global-symbols: # CHECK-NOT: scope: hidden # CHECK: content: [ 90, 90, 90, 90, C3 ] +# CHECK: name: _myStripNot +# CHECK: scope: global +# CHECK: content: [ CC ] +# CHECK: dead-strip: never + # CHECK: name: _myResolver # CHECK: scope: global # CHECK: type: resolver