[mach-o] support N_NO_DEAD_STRIP nlist.desc bit

Mach-O symbols can have an attribute on them means their content should never be
dead code stripped.  This translates to deadStrip() == deadStripNever.

llvm-svn: 216234
This commit is contained in:
Nick Kledzik 2014-08-21 22:18:30 +00:00
parent 34fcca723b
commit 7820c80f7d
5 changed files with 63 additions and 34 deletions

View File

@ -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<uint8_t> 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<uint8_t>(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<uint8_t> _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<uint8_t> content,
bool thumb, bool noDeadStrip,
const ArrayRef<uint8_t> 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;
};

View File

@ -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<uint8_t> content = inSection->content.slice(sectionOffset,
ArrayRef<uint8_t> 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<uint8_t> content = inSection->content.slice(sectionOffset,
ArrayRef<uint8_t> 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);
}

View File

@ -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;
}

View File

@ -225,9 +225,10 @@ void atomFromSymbol(DefinedAtom::ContentType atomType, const Section &section,
// 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,
&section);
file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size,
noDeadStrip, copyRefs, &section);
} else {
DefinedAtom::Merge merge = (symbolDescFlags & N_WEAK_DEF)
? DefinedAtom::mergeAsWeak : DefinedAtom::mergeNo;
@ -239,15 +240,15 @@ void atomFromSymbol(DefinedAtom::ContentType atomType, const Section &section,
std::string segSectName = section.segmentName.str()
+ "/" + section.sectionName.str();
file.addDefinedAtomInCustomSection(symbolName, symbolScope, atomType,
merge, thumb,offset, size, segSectName,
true, &section);
merge, thumb, noDeadStrip, offset,
size, segSectName, true, &section);
} else {
if ((atomType == lld::DefinedAtom::typeCode) &&
(symbolDescFlags & N_SYMBOL_RESOLVER)) {
atomType = lld::DefinedAtom::typeResolver;
}
file.addDefinedAtom(symbolName, symbolScope, atomType, merge,
offset, size, thumb, copyRefs, &section);
offset, size, thumb, noDeadStrip, copyRefs, &section);
}
}
}
@ -419,7 +420,7 @@ std::error_code processSection(DefinedAtom::ContentType atomType,
"not zero terminated.");
}
file.addDefinedAtom(StringRef(), scope, atomType, merge, offset, size,
false, copyRefs, &section);
false, false, copyRefs, &section);
offset += size;
}
}

View File

@ -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