diff --git a/lld/lib/ReaderWriter/MachO/Atoms.h b/lld/lib/ReaderWriter/MachO/Atoms.h index 6fb81ccabdfb..b3d3e2aa1ea1 100644 --- a/lld/lib/ReaderWriter/MachO/Atoms.h +++ b/lld/lib/ReaderWriter/MachO/Atoms.h @@ -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 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: diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h index b52f47036b31..c466231e4006 100644 --- a/lld/lib/ReaderWriter/MachO/File.h +++ b/lld/lib/ReaderWriter/MachO/File.h @@ -35,6 +35,22 @@ public: addAtom(*atom); } + void addDefinedAtomInCustomSection(StringRef name, Atom::Scope scope, + DefinedAtom::ContentType type, DefinedAtom::Merge merge, + ArrayRef 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) { diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp index 4797a14ba87d..017307613185 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp @@ -149,6 +149,7 @@ private: std::vector _sectionInfos; std::vector _segmentInfos; TypeToSection _sectionMap; + std::vector _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; + } } diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index 60f2ffbd8e81..4f2edbc4a455 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -83,8 +83,25 @@ static Atom::Scope atomScope(uint8_t scope) { } static DefinedAtom::ContentType atomTypeFromSection(const Section §ion) { - // 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(); } diff --git a/lld/test/mach-o/parse-data.yaml b/lld/test/mach-o/parse-data.yaml index a854317a4691..e7b7d2c69e7c 100644 --- a/lld/test/mach-o/parse-data.yaml +++ b/lld/test/mach-o/parse-data.yaml @@ -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 ]