[mach-o] Add support for custom sections

llvm-svn: 209928
This commit is contained in:
Nick Kledzik 2014-05-30 22:51:04 +00:00
parent 5435224a53
commit acfad80250
5 changed files with 155 additions and 31 deletions

View File

@ -62,6 +62,26 @@ private:
const Merge _merge;
};
class MachODefinedCustomSectionAtom : public MachODefinedAtom {
public:
MachODefinedCustomSectionAtom(const File &f, const StringRef name,
Scope scope, ContentType type, Merge merge,
const ArrayRef<uint8_t> content,
StringRef sectionName)
: MachODefinedAtom(f, name, scope, type, merge, content),
_sectionName(sectionName) {}
SectionChoice sectionChoice() const override {
return DefinedAtom::sectionCustomRequired;
}
StringRef customSectionName() const override {
return _sectionName;
}
private:
StringRef _sectionName;
};
class MachOTentativeDefAtom : public SimpleDefinedAtom {
public:

View File

@ -35,6 +35,22 @@ public:
addAtom(*atom);
}
void addDefinedAtomInCustomSection(StringRef name, Atom::Scope scope,
DefinedAtom::ContentType type, DefinedAtom::Merge merge,
ArrayRef<uint8_t> content, StringRef sectionName,
bool copyRefs) {
if (copyRefs) {
// Make a copy of the atom's name and content that is owned by this file.
name = name.copy(_allocator);
content = content.copy(_allocator);
sectionName = sectionName.copy(_allocator);
}
MachODefinedCustomSectionAtom *atom =
new (_allocator) MachODefinedCustomSectionAtom(*this, name, scope, type,
merge, content, sectionName);
addAtom(*atom);
}
void addZeroFillDefinedAtom(StringRef name, Atom::Scope scope, uint64_t size,
bool copyRefs) {
if (copyRefs) {

View File

@ -149,6 +149,7 @@ private:
std::vector<SectionInfo*> _sectionInfos;
std::vector<SegmentInfo*> _segmentInfos;
TypeToSection _sectionMap;
std::vector<SectionInfo*> _customSections;
AtomToAddress _atomToAddress;
DylibPathToInfo _dylibInfo;
const DefinedAtom *_entryAtom;
@ -206,6 +207,18 @@ SectionInfo *Util::makeSection(DefinedAtom::ContentType type) {
case DefinedAtom::typeCompactUnwindInfo:
return new (_allocator) SectionInfo("__LD", "__compact_unwind",
S_REGULAR);
case DefinedAtom::typeConstant:
return new (_allocator) SectionInfo("__TEXT", "__const",
S_REGULAR);
case DefinedAtom::typeData:
return new (_allocator) SectionInfo("__DATA", "__data",
S_REGULAR);
case DefinedAtom::typeConstData:
return new (_allocator) SectionInfo("__DATA", "__const",
S_REGULAR);
case DefinedAtom::typeLSDA:
return new (_allocator) SectionInfo("__TEXT", "__gcc_except_tab",
S_REGULAR);
default:
llvm_unreachable("TO DO: add support for more sections");
break;
@ -215,14 +228,36 @@ SectionInfo *Util::makeSection(DefinedAtom::ContentType type) {
SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
DefinedAtom::ContentType type = atom->contentType();
auto pos = _sectionMap.find(type);
if ( pos != _sectionMap.end() )
return pos->second;
SectionInfo *si = makeSection(type);
_sectionInfos.push_back(si);
_sectionMap[type] = si;
return si;
if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
// Section for this atom is derived from content type.
DefinedAtom::ContentType type = atom->contentType();
auto pos = _sectionMap.find(type);
if ( pos != _sectionMap.end() )
return pos->second;
SectionInfo *si = makeSection(type);
_sectionInfos.push_back(si);
_sectionMap[type] = si;
return si;
} else {
// This atom needs to be in a custom section.
StringRef customName = atom->customSectionName();
// Look to see if we have already allocated the needed custom section.
for(SectionInfo *sect : _customSections) {
const DefinedAtom *firstAtom = sect->atomsAndOffsets.front().atom;
if (firstAtom->customSectionName().equals(customName)) {
return sect;
}
}
// Not found, so need to create a new custom section.
size_t seperatorIndex = customName.find('/');
assert(seperatorIndex != StringRef::npos);
StringRef segName = customName.slice(0, seperatorIndex-1);
StringRef sectName = customName.drop_front(seperatorIndex);
SectionInfo *sect = new (_allocator) SectionInfo(segName, sectName,
S_REGULAR);
_customSections.push_back(sect);
return sect;
}
}

View File

@ -83,8 +83,25 @@ static Atom::Scope atomScope(uint8_t scope) {
}
static DefinedAtom::ContentType atomTypeFromSection(const Section &section) {
// FIX ME
return DefinedAtom::typeCode;
if (section.attributes & S_ATTR_PURE_INSTRUCTIONS)
return DefinedAtom::typeCode;
if (section.segmentName.equals("__TEXT")) {
if (section.sectionName.equals("__StaticInit"))
return DefinedAtom::typeCode;
if (section.sectionName.equals("__gcc_except_tab"))
return DefinedAtom::typeLSDA;
if (section.sectionName.startswith("__text"))
return DefinedAtom::typeCode;
if (section.sectionName.startswith("__const"))
return DefinedAtom::typeConstant;
} else if (section.segmentName.equals("__DATA")) {
if (section.sectionName.startswith("__data"))
return DefinedAtom::typeData;
if (section.sectionName.startswith("__const"))
return DefinedAtom::typeConstData;
}
return DefinedAtom::typeUnknown;
}
static error_code
@ -124,8 +141,19 @@ processSymbol(const NormalizedFile &normalizedFile, MachOFile &file,
DefinedAtom::Merge m = DefinedAtom::mergeNo;
if (sym.desc & N_WEAK_DEF)
m = DefinedAtom::mergeAsWeak;
file.addDefinedAtom(sym.name, atomScope(sym.scope),
atomTypeFromSection(section), m, atomContent, copyRefs);
DefinedAtom::ContentType type = atomTypeFromSection(section);
if (type == DefinedAtom::typeUnknown) {
// Mach-O needs a segment and section name. Concatentate those two
// with a / seperator (e.g. "seg/sect") to fit into the lld model
// of just a section name.
std::string segSectName = section.segmentName.str()
+ "/" + section.sectionName.str();
file.addDefinedAtomInCustomSection(sym.name, atomScope(sym.scope), type,
m, atomContent, segSectName, true);
} else {
file.addDefinedAtom(sym.name, atomScope(sym.scope), type, m, atomContent,
copyRefs);
}
}
return error_code::success();
}

View File

@ -27,18 +27,25 @@ sections:
content: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x11, 0x12, 0x13, 0x14, 0x21, 0x22, 0x23, 0x24,
0x31, 0x32, 0x33, 0x34, 0x41, 0x42, 0x43, 0x44 ]
- segment: __CUST
section: __custom
type: S_REGULAR
attributes: [ ]
alignment: 3
address: 0x0000000000000018
content: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ]
- segment: __DATA
section: __bss
type: S_ZEROFILL
attributes: [ ]
alignment: 2
address: 0x0000000000000018
address: 0x0000000000000020
size: 4
local-symbols:
- name: _s1
type: N_SECT
sect: 2
value: 0x0000000000000018
sect: 3
value: 0x0000000000000020
- name: _s2
type: N_SECT
sect: 1
@ -65,30 +72,48 @@ global-symbols:
sect: 1
desc: [ N_WEAK_DEF ]
value: 0x0000000000000014
- name: _kustom
type: N_SECT
scope: [ N_EXT ]
sect: 2
value: 0x0000000000000018
...
# CHECK: defined-atoms:
# CHECK: - name: _a
# CHECK: scope: global
# CHECK: type: data
# CHECK: content: [ 01, 02, 03, 04, 05, 06, 07, 08 ]
# CHECK: - name: _b
# CHECK: scope: global
# CHECK: type: data
# CHECK: content: [ 11, 12, 13, 14 ]
# CHECK: - name: _c
# CHECK: scope: global
# CHECK: type: data
# CHECK: content: [ 21, 22, 23, 24 ]
# CHECK: - name: _cWeak
# CHECK: scope: global
# CHECK: type: data
# CHECK: content: [ 41, 42, 43, 44 ]
# CHECK: merge: as-weak
# CHECK: - name: _s2
# CHECK: type: data
# CHECK: content: [ 31, 32, 33, 34 ]
# CHECK: - name: _s1
# CHECK: type: zero-fill
# CHECK: size: 4
# CHECK: - name: _a
# CHECK: - name: _kustom
# CHECK: scope: global
# CHECK: type: unknown
# CHECK: content: [ 01, 02, 03, 04, 05, 06, 07, 08 ]
# CHECK: section-choice: custom-required
# CHECK: section-name: __CUST/__custom
# CHECK: - name: _b
# CHECK: scope: global
# CHECK: content: [ 11, 12, 13, 14 ]
# CHECK: - name: _c
# CHECK: scope: global
# CHECK: content: [ 21, 22, 23, 24 ]
# CHECK: - name: _cWeak
# CHECK: scope: global
# CHECK: content: [ 41, 42, 43, 44 ]
# CHECK: merge: as-weak
# CHECK: - name: _s2
# CHECK: content: [ 31, 32, 33, 34 ]