forked from OSchip/llvm-project
[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:
parent
34fcca723b
commit
7820c80f7d
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue