diff options
| author | Nick Kledzik <kledzik@apple.com> | 2014-07-30 00:58:06 +0000 |
|---|---|---|
| committer | Nick Kledzik <kledzik@apple.com> | 2014-07-30 00:58:06 +0000 |
| commit | 2fcbe822c0be8773505afd9e4080d71f8a05953d (patch) | |
| tree | 255020232526c15b71f88569408a13cd6146244b /lld/lib/ReaderWriter | |
| parent | f73da98f488c8177eb69b846a9f6045e01db6792 (diff) | |
| download | bcm5719-llvm-2fcbe822c0be8773505afd9e4080d71f8a05953d.tar.gz bcm5719-llvm-2fcbe822c0be8773505afd9e4080d71f8a05953d.zip | |
[mach-o] Add support for -sectalign option
The -sectalign option is used to increase the alignment required for a section.
It required some reworking of how the __TEXT segment is laid out because that
segment also contains the mach_header and load commands. And the size of load
commands depend on the number of segments, sections, and dependent dylibs used.
Using this option will simplify some future test cases because the final
address of code can be pinned down, making tests of its content easier.
llvm-svn: 214268
Diffstat (limited to 'lld/lib/ReaderWriter')
3 files changed, 117 insertions, 45 deletions
diff --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp index c05772b6054..5fa74d14564 100644 --- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp +++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp @@ -422,4 +422,24 @@ ArchHandler &MachOLinkingContext::archHandler() const { } +void MachOLinkingContext::addSectionAlignment(StringRef seg, StringRef sect, + uint8_t align2) { + SectionAlign entry; + entry.segmentName = seg; + entry.sectionName = sect; + entry.align2 = align2; + _sectAligns.push_back(entry); +} + +bool MachOLinkingContext::sectionAligned(StringRef seg, StringRef sect, + uint8_t &align2) const { + for (const SectionAlign &entry : _sectAligns) { + if (seg.equals(entry.segmentName) && sect.equals(entry.sectionName)) { + align2 = entry.align2; + return true; + } + } + return false; +} + } // end namespace lld diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp index fc90e8b34cb..5d9f46dd582 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp @@ -58,6 +58,9 @@ public: /// Returns the final file size as computed in the constructor. size_t size() const; + // Returns size of the mach_header and load commands. + size_t headerAndLoadCommandsSize() const; + /// Writes the normalized file as a binary mach-o file to the specified /// path. This does not have a stream interface because the generated /// file may need the 'x' bit set. @@ -200,7 +203,7 @@ private: size_t headerAndLoadCommandsSize(const NormalizedFile &file) { MachOFileLayout layout(file); - return layout.size(); + return layout.headerAndLoadCommandsSize(); } StringRef MachOFileLayout::dyldPath() { @@ -212,6 +215,9 @@ uint32_t MachOFileLayout::pointerAlign(uint32_t value) { } +size_t MachOFileLayout::headerAndLoadCommandsSize() const { + return _endOfLoadCommands; +} MachOFileLayout::MachOFileLayout(const NormalizedFile &file) diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp index e181a212de3..9f8fa42847a 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp @@ -51,7 +51,8 @@ struct AtomInfo { }; struct SectionInfo { - SectionInfo(StringRef seg, StringRef sect, SectionType type, uint32_t attr=0); + SectionInfo(StringRef seg, StringRef sect, SectionType type, + const MachOLinkingContext &ctxt, uint32_t attr=0); StringRef segmentName; StringRef sectionName; @@ -65,10 +66,15 @@ struct SectionInfo { uint32_t finalSectionIndex; }; -SectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t, uint32_t a) - : segmentName(sg), sectionName(sct), type(t), attributes(a), +SectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t, + const MachOLinkingContext &ctxt, uint32_t attrs) + : segmentName(sg), sectionName(sct), type(t), attributes(attrs), address(0), size(0), alignment(0), normalizedSectionIndex(0), finalSectionIndex(0) { + uint8_t align; + if (ctxt.sectionAligned(segmentName, sectionName, align)) { + alignment = align; + } } struct SegmentInfo { @@ -79,10 +85,11 @@ struct SegmentInfo { uint64_t size; uint32_t access; std::vector<SectionInfo*> sections; + uint32_t normalizedSegmentIndex; }; SegmentInfo::SegmentInfo(StringRef n) - : name(n), address(0), size(0), access(0) { + : name(n), address(0), size(0), access(0), normalizedSegmentIndex(0) { } @@ -93,10 +100,11 @@ public: void assignAtomsToSections(const lld::File &atomFile); void organizeSections(); - void assignAddressesToSections(); + void assignAddressesToSections(const NormalizedFile &file); uint32_t fileFlags(); void copySegmentInfo(NormalizedFile &file); - void copySections(NormalizedFile &file); + void copySectionInfo(NormalizedFile &file); + void updateSectionInfo(NormalizedFile &file); void buildAtomToAddressMap(); void addSymbols(const lld::File &atomFile, NormalizedFile &file); void addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file); @@ -105,6 +113,7 @@ public: void buildDataInCodeArray(const lld::File &, NormalizedFile &file); void addDependentDylibs(const lld::File &, NormalizedFile &file); void copyEntryPointAddress(NormalizedFile &file); + void copySectionContent(NormalizedFile &file); private: typedef std::map<DefinedAtom::ContentType, SectionInfo*> TypeToSection; @@ -119,7 +128,7 @@ private: void appendAtom(SectionInfo *sect, const DefinedAtom *atom); SegmentInfo *segmentForName(StringRef segName); void layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr); - void layoutSectionsInTextSegment(SegmentInfo *seg, uint64_t &addr); + void layoutSectionsInTextSegment(size_t, SegmentInfo *, uint64_t &); void copySectionContent(SectionInfo *si, ContentBytes &content); uint8_t scopeBits(const DefinedAtom* atom); uint16_t descBits(const DefinedAtom* atom); @@ -180,7 +189,8 @@ SectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) { } // Otherwise allocate new SectionInfo object. SectionInfo *sect = new (_allocator) SectionInfo(segmentName, sectionName, - sectionType, sectionAttrs); + sectionType, _context, + sectionAttrs); _sectionInfos.push_back(sect); _sectionMap[type] = sect; return sect; @@ -255,6 +265,7 @@ SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) { SectionInfo *sect = new (_allocator) SectionInfo(p.segmentName, p.sectionName, p.sectionType, + _context, sectionAttrs); _sectionInfos.push_back(sect); _sectionMap[atomType] = sect; @@ -290,7 +301,7 @@ SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) { StringRef segName = customName.slice(0, seperatorIndex); StringRef sectName = customName.drop_front(seperatorIndex + 1); SectionInfo *sect = new (_allocator) SectionInfo(segName, sectName, - S_REGULAR); + S_REGULAR, _context); _customSections.push_back(sect); _sectionInfos.push_back(sect); return sect; @@ -402,11 +413,13 @@ void Util::organizeSections() { } // Record final section indexes. + uint32_t segmentIndex = 0; uint32_t sectionIndex = 1; for (SegmentInfo *seg : _segmentInfos) { - for (SectionInfo *sect : seg->sections) { - sect->finalSectionIndex = sectionIndex++; - } + seg->normalizedSegmentIndex = segmentIndex++; + for (SectionInfo *sect : seg->sections) { + sect->finalSectionIndex = sectionIndex++; + } } } @@ -428,7 +441,8 @@ void Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) { // __TEXT segment lays out backwards so padding is at front after load commands. -void Util::layoutSectionsInTextSegment(SegmentInfo *seg, uint64_t &addr) { +void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg, + uint64_t &addr) { seg->address = addr; // Walks sections starting at end to calculate padding for start. int64_t taddr = 0; @@ -437,11 +451,11 @@ void Util::layoutSectionsInTextSegment(SegmentInfo *seg, uint64_t &addr) { taddr -= sect->size; taddr = taddr & (0 - (1 << sect->alignment)); } - int64_t padding = taddr; + int64_t padding = taddr - hlcSize; while (padding < 0) padding += _context.pageSize(); // Start assigning section address starting at padded offset. - addr += padding; + addr += (padding + hlcSize); for (SectionInfo *sect : seg->sections) { sect->address = alignTo(addr, sect->alignment); addr = sect->address + sect->size; @@ -450,7 +464,8 @@ void Util::layoutSectionsInTextSegment(SegmentInfo *seg, uint64_t &addr) { } -void Util::assignAddressesToSections() { +void Util::assignAddressesToSections(const NormalizedFile &file) { + size_t hlcSize = headerAndLoadCommandsSize(file); uint64_t address = 0; // FIXME if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) { for (SegmentInfo *seg : _segmentInfos) { @@ -459,7 +474,7 @@ void Util::assignAddressesToSections() { address += seg->size; } else if (seg->name.equals("__TEXT")) - layoutSectionsInTextSegment(seg, address); + layoutSectionsInTextSegment(hlcSize, seg, address); else layoutSectionsInSegment(seg, address); @@ -510,16 +525,7 @@ void Util::copySegmentInfo(NormalizedFile &file) { } void Util::appendSection(SectionInfo *si, NormalizedFile &file) { - const bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT); - - // Utility function for ArchHandler to find address of atom in output file. - auto addrForAtom = [&] (const Atom &atom) -> uint64_t { - auto pos = _atomToAddress.find(&atom); - assert(pos != _atomToAddress.end()); - return pos->second; - }; - - // Add new empty section to end of file.sections. + // Add new empty section to end of file.sections. Section temp; file.sections.push_back(std::move(temp)); Section* normSect = &file.sections.back(); @@ -532,19 +538,35 @@ void Util::appendSection(SectionInfo *si, NormalizedFile &file) { normSect->alignment = si->alignment; // Record where normalized section is. si->normalizedSectionIndex = file.sections.size()-1; - // Copy content from atoms to content buffer for section. - if (si->type == llvm::MachO::S_ZEROFILL) - return; - uint8_t *sectionContent = file.ownedAllocations.Allocate<uint8_t>(si->size); - normSect->content = llvm::makeArrayRef(sectionContent, si->size); - for (AtomInfo &ai : si->atomsAndOffsets) { - uint8_t *atomContent = reinterpret_cast<uint8_t*> +} + +void Util::copySectionContent(NormalizedFile &file) { + const bool r = (_context.outputMachOType() == llvm::MachO::MH_OBJECT); + + // Utility function for ArchHandler to find address of atom in output file. + auto addrForAtom = [&] (const Atom &atom) -> uint64_t { + auto pos = _atomToAddress.find(&atom); + assert(pos != _atomToAddress.end()); + return pos->second; + }; + + for (SectionInfo *si : _sectionInfos) { + if (si->type == llvm::MachO::S_ZEROFILL) + continue; + // Copy content from atoms to content buffer for section. + uint8_t *sectionContent = file.ownedAllocations.Allocate<uint8_t>(si->size); + Section *normSect = &file.sections[si->normalizedSectionIndex]; + normSect->content = llvm::makeArrayRef(sectionContent, si->size); + for (AtomInfo &ai : si->atomsAndOffsets) { + uint8_t *atomContent = reinterpret_cast<uint8_t*> (§ionContent[ai.offsetInSection]); - _archHandler.generateAtomContent(*ai.atom, rMode, addrForAtom, atomContent); + _archHandler.generateAtomContent(*ai.atom, r, addrForAtom, atomContent); + } } } -void Util::copySections(NormalizedFile &file) { + +void Util::copySectionInfo(NormalizedFile &file) { file.sections.reserve(_sectionInfos.size()); // For final linked images, write sections grouped by segment. if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) { @@ -561,6 +583,28 @@ void Util::copySections(NormalizedFile &file) { } } +void Util::updateSectionInfo(NormalizedFile &file) { + file.sections.reserve(_sectionInfos.size()); + if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) { + // For final linked images, sections grouped by segment. + for (SegmentInfo *sgi : _segmentInfos) { + Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex]; + normSeg->address = sgi->address; + normSeg->size = sgi->size; + for (SectionInfo *si : sgi->sections) { + Section *normSect = &file.sections[si->normalizedSectionIndex]; + normSect->address = si->address; + } + } + } else { + // Object files write sections in default order. + for (SectionInfo *si : _sectionInfos) { + Section *normSect = &file.sections[si->normalizedSectionIndex]; + normSect->address = si->address; + } + } +} + void Util::copyEntryPointAddress(NormalizedFile &nFile) { if (_context.outputTypeHasEntry()) { if (_archHandler.isThumbFunction(*_entryAtom)) @@ -1020,18 +1064,20 @@ normalizedFromAtoms(const lld::File &atomFile, Util util(context); util.assignAtomsToSections(atomFile); util.organizeSections(); - util.assignAddressesToSections(); - util.buildAtomToAddressMap(); std::unique_ptr<NormalizedFile> f(new NormalizedFile()); NormalizedFile &normFile = *f.get(); - f->arch = context.arch(); - f->fileType = context.outputMachOType(); - f->flags = util.fileFlags(); - f->installName = context.installName(); - util.copySegmentInfo(normFile); - util.copySections(normFile); + normFile.arch = context.arch(); + normFile.fileType = context.outputMachOType(); + normFile.flags = util.fileFlags(); + normFile.installName = context.installName(); util.addDependentDylibs(atomFile, normFile); + util.copySegmentInfo(normFile); + util.copySectionInfo(normFile); + util.assignAddressesToSections(normFile); + util.buildAtomToAddressMap(); + util.updateSectionInfo(normFile); + util.copySectionContent(normFile); util.addSymbols(atomFile, normFile); util.addIndirectSymbols(atomFile, normFile); util.addRebaseAndBindingInfo(atomFile, normFile); |

