MachONormalizedFileFromAtoms.cpp revision 303239
1254885Sdumbbell//===- lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp ------------===// 2254885Sdumbbell// 3254885Sdumbbell// The LLVM Linker 4254885Sdumbbell// 5254885Sdumbbell// This file is distributed under the University of Illinois Open Source 6254885Sdumbbell// License. See LICENSE.TXT for details. 7254885Sdumbbell// 8254885Sdumbbell//===----------------------------------------------------------------------===// 9254885Sdumbbell 10254885Sdumbbell/// 11254885Sdumbbell/// \file Converts from in-memory Atoms to in-memory normalized mach-o. 12254885Sdumbbell/// 13254885Sdumbbell/// +------------+ 14254885Sdumbbell/// | normalized | 15254885Sdumbbell/// +------------+ 16254885Sdumbbell/// ^ 17254885Sdumbbell/// | 18254885Sdumbbell/// | 19254885Sdumbbell/// +-------+ 20254885Sdumbbell/// | Atoms | 21254885Sdumbbell/// +-------+ 22254885Sdumbbell 23254885Sdumbbell#include "MachONormalizedFile.h" 24254885Sdumbbell#include "ArchHandler.h" 25254885Sdumbbell#include "MachONormalizedFileBinaryUtils.h" 26254885Sdumbbell#include "lld/Core/Error.h" 27254885Sdumbbell#include "lld/Core/LLVM.h" 28254885Sdumbbell#include "llvm/ADT/StringRef.h" 29254885Sdumbbell#include "llvm/ADT/StringSwitch.h" 30254885Sdumbbell#include "llvm/Support/Casting.h" 31254885Sdumbbell#include "llvm/Support/Debug.h" 32254885Sdumbbell#include "llvm/Support/ErrorHandling.h" 33254885Sdumbbell#include "llvm/Support/Format.h" 34254885Sdumbbell#include "llvm/Support/MachO.h" 35254885Sdumbbell#include <map> 36254885Sdumbbell#include <system_error> 37254885Sdumbbell 38254885Sdumbbellusing llvm::StringRef; 39254885Sdumbbellusing llvm::isa; 40254885Sdumbbellusing namespace llvm::MachO; 41254885Sdumbbellusing namespace lld::mach_o::normalized; 42254885Sdumbbellusing namespace lld; 43254885Sdumbbell 44254885Sdumbbellnamespace { 45254885Sdumbbell 46254885Sdumbbellstruct AtomInfo { 47254885Sdumbbell const DefinedAtom *atom; 48254885Sdumbbell uint64_t offsetInSection; 49254885Sdumbbell}; 50254885Sdumbbell 51254885Sdumbbellstruct SectionInfo { 52254885Sdumbbell SectionInfo(StringRef seg, StringRef sect, SectionType type, 53254885Sdumbbell const MachOLinkingContext &ctxt, uint32_t attr, 54254885Sdumbbell bool relocsToDefinedCanBeImplicit); 55254885Sdumbbell 56254885Sdumbbell StringRef segmentName; 57254885Sdumbbell StringRef sectionName; 58254885Sdumbbell SectionType type; 59254885Sdumbbell uint32_t attributes; 60254885Sdumbbell uint64_t address; 61254885Sdumbbell uint64_t size; 62254885Sdumbbell uint16_t alignment; 63254885Sdumbbell 64258780Seadler /// If this is set, the any relocs in this section which point to defined 65254885Sdumbbell /// addresses can be implicitly generated. This is the case for the 66254885Sdumbbell /// __eh_frame section where references to the function can be implicit if the 67254885Sdumbbell /// function is defined. 68254885Sdumbbell bool relocsToDefinedCanBeImplicit; 69254885Sdumbbell 70254885Sdumbbell 71254885Sdumbbell std::vector<AtomInfo> atomsAndOffsets; 72254885Sdumbbell uint32_t normalizedSectionIndex; 73254885Sdumbbell uint32_t finalSectionIndex; 74254885Sdumbbell}; 75254885Sdumbbell 76254885SdumbbellSectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t, 77254885Sdumbbell const MachOLinkingContext &ctxt, uint32_t attrs, 78254885Sdumbbell bool relocsToDefinedCanBeImplicit) 79254885Sdumbbell : segmentName(sg), sectionName(sct), type(t), attributes(attrs), 80254885Sdumbbell address(0), size(0), alignment(1), 81254885Sdumbbell relocsToDefinedCanBeImplicit(relocsToDefinedCanBeImplicit), 82254885Sdumbbell normalizedSectionIndex(0), finalSectionIndex(0) { 83254885Sdumbbell uint16_t align = 1; 84254885Sdumbbell if (ctxt.sectionAligned(segmentName, sectionName, align)) { 85254885Sdumbbell alignment = align; 86254885Sdumbbell } 87254885Sdumbbell} 88254885Sdumbbell 89254885Sdumbbellstruct SegmentInfo { 90254885Sdumbbell SegmentInfo(StringRef name); 91254885Sdumbbell 92254885Sdumbbell StringRef name; 93254885Sdumbbell uint64_t address; 94254885Sdumbbell uint64_t size; 95254885Sdumbbell uint32_t init_access; 96254885Sdumbbell uint32_t max_access; 97254885Sdumbbell std::vector<SectionInfo*> sections; 98254885Sdumbbell uint32_t normalizedSegmentIndex; 99254885Sdumbbell}; 100254885Sdumbbell 101254885SdumbbellSegmentInfo::SegmentInfo(StringRef n) 102254885Sdumbbell : name(n), address(0), size(0), init_access(0), max_access(0), 103254885Sdumbbell normalizedSegmentIndex(0) { 104254885Sdumbbell} 105254885Sdumbbell 106254885Sdumbbellclass Util { 107254885Sdumbbellpublic: 108254885Sdumbbell Util(const MachOLinkingContext &ctxt) 109254885Sdumbbell : _ctx(ctxt), _archHandler(ctxt.archHandler()), _entryAtom(nullptr), 110254885Sdumbbell _hasTLVDescriptors(false), _subsectionsViaSymbols(true) {} 111254885Sdumbbell ~Util(); 112254885Sdumbbell 113254885Sdumbbell void processDefinedAtoms(const lld::File &atomFile); 114254885Sdumbbell void processAtomAttributes(const DefinedAtom *atom); 115254885Sdumbbell void assignAtomToSection(const DefinedAtom *atom); 116254885Sdumbbell void organizeSections(); 117254885Sdumbbell void assignAddressesToSections(const NormalizedFile &file); 118254885Sdumbbell uint32_t fileFlags(); 119254885Sdumbbell void copySegmentInfo(NormalizedFile &file); 120254885Sdumbbell void copySectionInfo(NormalizedFile &file); 121254885Sdumbbell void updateSectionInfo(NormalizedFile &file); 122254885Sdumbbell void buildAtomToAddressMap(); 123254885Sdumbbell llvm::Error addSymbols(const lld::File &atomFile, NormalizedFile &file); 124254885Sdumbbell void addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file); 125254885Sdumbbell void addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file); 126254885Sdumbbell void addExportInfo(const lld::File &, NormalizedFile &file); 127254885Sdumbbell void addSectionRelocs(const lld::File &, NormalizedFile &file); 128258780Seadler void addFunctionStarts(const lld::File &, NormalizedFile &file); 129254885Sdumbbell void buildDataInCodeArray(const lld::File &, NormalizedFile &file); 130254885Sdumbbell void addDependentDylibs(const lld::File &, NormalizedFile &file); 131254885Sdumbbell void copyEntryPointAddress(NormalizedFile &file); 132254885Sdumbbell void copySectionContent(NormalizedFile &file); 133254885Sdumbbell 134254885Sdumbbell bool allSourceFilesHaveMinVersions() const { 135254885Sdumbbell return _allSourceFilesHaveMinVersions; 136254885Sdumbbell } 137254885Sdumbbell 138254885Sdumbbell uint32_t minVersion() const { 139254885Sdumbbell return _minVersion; 140254885Sdumbbell } 141254885Sdumbbell 142254885Sdumbbell LoadCommandType minVersionCommandType() const { 143254885Sdumbbell return _minVersionCommandType; 144254885Sdumbbell } 145254885Sdumbbell 146254885Sdumbbellprivate: 147254885Sdumbbell typedef std::map<DefinedAtom::ContentType, SectionInfo*> TypeToSection; 148254885Sdumbbell typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress; 149254885Sdumbbell 150254885Sdumbbell struct DylibInfo { int ordinal; bool hasWeak; bool hasNonWeak; }; 151254885Sdumbbell typedef llvm::StringMap<DylibInfo> DylibPathToInfo; 152254885Sdumbbell 153254885Sdumbbell SectionInfo *sectionForAtom(const DefinedAtom*); 154254885Sdumbbell SectionInfo *getRelocatableSection(DefinedAtom::ContentType type); 155254885Sdumbbell SectionInfo *getFinalSection(DefinedAtom::ContentType type); 156254885Sdumbbell void appendAtom(SectionInfo *sect, const DefinedAtom *atom); 157254885Sdumbbell SegmentInfo *segmentForName(StringRef segName); 158254885Sdumbbell void layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr); 159254885Sdumbbell void layoutSectionsInTextSegment(size_t, SegmentInfo *, uint64_t &); 160254885Sdumbbell void copySectionContent(SectionInfo *si, ContentBytes &content); 161254885Sdumbbell uint16_t descBits(const DefinedAtom* atom); 162254885Sdumbbell int dylibOrdinal(const SharedLibraryAtom *sa); 163254885Sdumbbell void segIndexForSection(const SectionInfo *sect, 164254885Sdumbbell uint8_t &segmentIndex, uint64_t &segmentStartAddr); 165254885Sdumbbell const Atom *targetOfLazyPointer(const DefinedAtom *lpAtom); 166254885Sdumbbell const Atom *targetOfStub(const DefinedAtom *stubAtom); 167254885Sdumbbell llvm::Error getSymbolTableRegion(const DefinedAtom* atom, 168254885Sdumbbell bool &inGlobalsRegion, 169254885Sdumbbell SymbolScope &symbolScope); 170254885Sdumbbell void appendSection(SectionInfo *si, NormalizedFile &file); 171254885Sdumbbell uint32_t sectionIndexForAtom(const Atom *atom); 172254885Sdumbbell 173254885Sdumbbell typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex; 174254885Sdumbbell struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; }; 175254885Sdumbbell struct AtomSorter { 176254885Sdumbbell bool operator()(const AtomAndIndex &left, const AtomAndIndex &right); 177254885Sdumbbell }; 178254885Sdumbbell struct SegmentSorter { 179254885Sdumbbell bool operator()(const SegmentInfo *left, const SegmentInfo *right); 180254885Sdumbbell static unsigned weight(const SegmentInfo *); 181254885Sdumbbell }; 182254885Sdumbbell struct TextSectionSorter { 183254885Sdumbbell bool operator()(const SectionInfo *left, const SectionInfo *right); 184254885Sdumbbell static unsigned weight(const SectionInfo *); 185254885Sdumbbell }; 186254885Sdumbbell 187254885Sdumbbell const MachOLinkingContext &_ctx; 188254885Sdumbbell mach_o::ArchHandler &_archHandler; 189254885Sdumbbell llvm::BumpPtrAllocator _allocator; 190258780Seadler std::vector<SectionInfo*> _sectionInfos; 191254885Sdumbbell std::vector<SegmentInfo*> _segmentInfos; 192254885Sdumbbell TypeToSection _sectionMap; 193254885Sdumbbell std::vector<SectionInfo*> _customSections; 194254885Sdumbbell AtomToAddress _atomToAddress; 195254885Sdumbbell DylibPathToInfo _dylibInfo; 196254885Sdumbbell const DefinedAtom *_entryAtom; 197254885Sdumbbell AtomToIndex _atomToSymbolIndex; 198254885Sdumbbell std::vector<const Atom *> _machHeaderAliasAtoms; 199254885Sdumbbell bool _hasTLVDescriptors; 200254885Sdumbbell bool _subsectionsViaSymbols; 201254885Sdumbbell bool _allSourceFilesHaveMinVersions = true; 202254885Sdumbbell LoadCommandType _minVersionCommandType = (LoadCommandType)0; 203254885Sdumbbell uint32_t _minVersion = 0; 204254885Sdumbbell}; 205254885Sdumbbell 206254885SdumbbellUtil::~Util() { 207254885Sdumbbell // The SectionInfo structs are BumpPtr allocated, but atomsAndOffsets needs 208254885Sdumbbell // to be deleted. 209254885Sdumbbell for (SectionInfo *si : _sectionInfos) { 210254885Sdumbbell // clear() destroys vector elements, but does not deallocate. 211254885Sdumbbell // Instead use swap() to deallocate vector buffer. 212254885Sdumbbell std::vector<AtomInfo> empty; 213254885Sdumbbell si->atomsAndOffsets.swap(empty); 214254885Sdumbbell } 215254885Sdumbbell // The SegmentInfo structs are BumpPtr allocated, but sections needs 216254885Sdumbbell // to be deleted. 217254885Sdumbbell for (SegmentInfo *sgi : _segmentInfos) { 218254885Sdumbbell std::vector<SectionInfo*> empty2; 219254885Sdumbbell sgi->sections.swap(empty2); 220254885Sdumbbell } 221254885Sdumbbell} 222254885Sdumbbell 223254885SdumbbellSectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) { 224254885Sdumbbell StringRef segmentName; 225254885Sdumbbell StringRef sectionName; 226254885Sdumbbell SectionType sectionType; 227254885Sdumbbell SectionAttr sectionAttrs; 228254885Sdumbbell bool relocsToDefinedCanBeImplicit; 229254885Sdumbbell 230254885Sdumbbell // Use same table used by when parsing .o files. 231254885Sdumbbell relocatableSectionInfoForContentType(type, segmentName, sectionName, 232254885Sdumbbell sectionType, sectionAttrs, 233254885Sdumbbell relocsToDefinedCanBeImplicit); 234254885Sdumbbell // If we already have a SectionInfo with this name, re-use it. 235254885Sdumbbell // This can happen if two ContentType map to the same mach-o section. 236254885Sdumbbell for (auto sect : _sectionMap) { 237254885Sdumbbell if (sect.second->sectionName.equals(sectionName) && 238254885Sdumbbell sect.second->segmentName.equals(segmentName)) { 239254885Sdumbbell return sect.second; 240254885Sdumbbell } 241254885Sdumbbell } 242254885Sdumbbell // Otherwise allocate new SectionInfo object. 243254885Sdumbbell auto *sect = new (_allocator) 244254885Sdumbbell SectionInfo(segmentName, sectionName, sectionType, _ctx, sectionAttrs, 245254885Sdumbbell relocsToDefinedCanBeImplicit); 246254885Sdumbbell _sectionInfos.push_back(sect); 247254885Sdumbbell _sectionMap[type] = sect; 248254885Sdumbbell return sect; 249254885Sdumbbell} 250254885Sdumbbell 251254885Sdumbbell#define ENTRY(seg, sect, type, atomType) \ 252254885Sdumbbell {seg, sect, type, DefinedAtom::atomType } 253254885Sdumbbell 254254885Sdumbbellstruct MachOFinalSectionFromAtomType { 255254885Sdumbbell StringRef segmentName; 256254885Sdumbbell StringRef sectionName; 257254885Sdumbbell SectionType sectionType; 258254885Sdumbbell DefinedAtom::ContentType atomType; 259254885Sdumbbell}; 260254885Sdumbbell 261254885Sdumbbellconst MachOFinalSectionFromAtomType sectsToAtomType[] = { 262254885Sdumbbell ENTRY("__TEXT", "__text", S_REGULAR, typeCode), 263254885Sdumbbell ENTRY("__TEXT", "__text", S_REGULAR, typeMachHeader), 264254885Sdumbbell ENTRY("__TEXT", "__cstring", S_CSTRING_LITERALS, typeCString), 265254885Sdumbbell ENTRY("__TEXT", "__ustring", S_REGULAR, typeUTF16String), 266254885Sdumbbell ENTRY("__TEXT", "__const", S_REGULAR, typeConstant), 267254885Sdumbbell ENTRY("__TEXT", "__const", S_4BYTE_LITERALS, typeLiteral4), 268254885Sdumbbell ENTRY("__TEXT", "__const", S_8BYTE_LITERALS, typeLiteral8), 269254885Sdumbbell ENTRY("__TEXT", "__const", S_16BYTE_LITERALS, typeLiteral16), 270254885Sdumbbell ENTRY("__TEXT", "__stubs", S_SYMBOL_STUBS, typeStub), 271254885Sdumbbell ENTRY("__TEXT", "__stub_helper", S_REGULAR, typeStubHelper), 272254885Sdumbbell ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR, typeLSDA), 273254885Sdumbbell ENTRY("__TEXT", "__eh_frame", S_COALESCED, typeCFI), 274254885Sdumbbell ENTRY("__TEXT", "__unwind_info", S_REGULAR, typeProcessedUnwindInfo), 275254885Sdumbbell ENTRY("__DATA", "__data", S_REGULAR, typeData), 276254885Sdumbbell ENTRY("__DATA", "__const", S_REGULAR, typeConstData), 277254885Sdumbbell ENTRY("__DATA", "__cfstring", S_REGULAR, typeCFString), 278254885Sdumbbell ENTRY("__DATA", "__la_symbol_ptr", S_LAZY_SYMBOL_POINTERS, 279254885Sdumbbell typeLazyPointer), 280254885Sdumbbell ENTRY("__DATA", "__mod_init_func", S_MOD_INIT_FUNC_POINTERS, 281254885Sdumbbell typeInitializerPtr), 282254885Sdumbbell ENTRY("__DATA", "__mod_term_func", S_MOD_TERM_FUNC_POINTERS, 283254885Sdumbbell typeTerminatorPtr), 284254885Sdumbbell ENTRY("__DATA", "__got", S_NON_LAZY_SYMBOL_POINTERS, 285254885Sdumbbell typeGOT), 286254885Sdumbbell ENTRY("__DATA", "__nl_symbol_ptr", S_NON_LAZY_SYMBOL_POINTERS, 287254885Sdumbbell typeNonLazyPointer), 288254885Sdumbbell ENTRY("__DATA", "__thread_vars", S_THREAD_LOCAL_VARIABLES, 289254885Sdumbbell typeThunkTLV), 290254885Sdumbbell ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR, 291254885Sdumbbell typeTLVInitialData), 292254885Sdumbbell ENTRY("__DATA", "__thread_ptrs", S_THREAD_LOCAL_VARIABLE_POINTERS, 293254885Sdumbbell typeTLVInitializerPtr), 294254885Sdumbbell ENTRY("__DATA", "__thread_bss", S_THREAD_LOCAL_ZEROFILL, 295254885Sdumbbell typeTLVInitialZeroFill), 296254885Sdumbbell ENTRY("__DATA", "__bss", S_ZEROFILL, typeZeroFill), 297254885Sdumbbell ENTRY("__DATA", "__interposing", S_INTERPOSING, typeInterposingTuples), 298254885Sdumbbell}; 299254885Sdumbbell#undef ENTRY 300254885Sdumbbell 301254885SdumbbellSectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) { 302254885Sdumbbell for (auto &p : sectsToAtomType) { 303254885Sdumbbell if (p.atomType != atomType) 304254885Sdumbbell continue; 305254885Sdumbbell SectionAttr sectionAttrs = 0; 306254885Sdumbbell switch (atomType) { 307254885Sdumbbell case DefinedAtom::typeMachHeader: 308254885Sdumbbell case DefinedAtom::typeCode: 309254885Sdumbbell case DefinedAtom::typeStub: 310254885Sdumbbell case DefinedAtom::typeStubHelper: 311254885Sdumbbell sectionAttrs = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS; 312254885Sdumbbell break; 313254885Sdumbbell case DefinedAtom::typeThunkTLV: 314254885Sdumbbell _hasTLVDescriptors = true; 315254885Sdumbbell break; 316254885Sdumbbell default: 317254885Sdumbbell break; 318254885Sdumbbell } 319254885Sdumbbell // If we already have a SectionInfo with this name, re-use it. 320254885Sdumbbell // This can happen if two ContentType map to the same mach-o section. 321254885Sdumbbell for (auto sect : _sectionMap) { 322254885Sdumbbell if (sect.second->sectionName.equals(p.sectionName) && 323254885Sdumbbell sect.second->segmentName.equals(p.segmentName)) { 324254885Sdumbbell return sect.second; 325258780Seadler } 326254885Sdumbbell } 327254885Sdumbbell // Otherwise allocate new SectionInfo object. 328254885Sdumbbell auto *sect = new (_allocator) SectionInfo( 329254885Sdumbbell p.segmentName, p.sectionName, p.sectionType, _ctx, sectionAttrs, 330254885Sdumbbell /* relocsToDefinedCanBeImplicit */ false); 331254885Sdumbbell _sectionInfos.push_back(sect); 332254885Sdumbbell _sectionMap[atomType] = sect; 333254885Sdumbbell return sect; 334254885Sdumbbell } 335254885Sdumbbell llvm_unreachable("content type not yet supported"); 336254885Sdumbbell} 337254885Sdumbbell 338254885SdumbbellSectionInfo *Util::sectionForAtom(const DefinedAtom *atom) { 339254885Sdumbbell if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) { 340254885Sdumbbell // Section for this atom is derived from content type. 341254885Sdumbbell DefinedAtom::ContentType type = atom->contentType(); 342254885Sdumbbell auto pos = _sectionMap.find(type); 343254885Sdumbbell if ( pos != _sectionMap.end() ) 344254885Sdumbbell return pos->second; 345254885Sdumbbell bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); 346254885Sdumbbell return rMode ? getRelocatableSection(type) : getFinalSection(type); 347254885Sdumbbell } else { 348254885Sdumbbell // This atom needs to be in a custom section. 349254885Sdumbbell StringRef customName = atom->customSectionName(); 350254885Sdumbbell // Look to see if we have already allocated the needed custom section. 351254885Sdumbbell for(SectionInfo *sect : _customSections) { 352254885Sdumbbell const DefinedAtom *firstAtom = sect->atomsAndOffsets.front().atom; 353254885Sdumbbell if (firstAtom->customSectionName().equals(customName)) { 354254885Sdumbbell return sect; 355254885Sdumbbell } 356254885Sdumbbell } 357254885Sdumbbell // Not found, so need to create a new custom section. 358254885Sdumbbell size_t seperatorIndex = customName.find('/'); 359254885Sdumbbell assert(seperatorIndex != StringRef::npos); 360254885Sdumbbell StringRef segName = customName.slice(0, seperatorIndex); 361254885Sdumbbell StringRef sectName = customName.drop_front(seperatorIndex + 1); 362254885Sdumbbell auto *sect = 363254885Sdumbbell new (_allocator) SectionInfo(segName, sectName, S_REGULAR, _ctx, 364254885Sdumbbell 0, /* relocsToDefinedCanBeImplicit */ false); 365254885Sdumbbell _customSections.push_back(sect); 366254885Sdumbbell _sectionInfos.push_back(sect); 367254885Sdumbbell return sect; 368254885Sdumbbell } 369254885Sdumbbell} 370254885Sdumbbell 371254885Sdumbbellvoid Util::appendAtom(SectionInfo *sect, const DefinedAtom *atom) { 372254885Sdumbbell // Figure out offset for atom in this section given alignment constraints. 373254885Sdumbbell uint64_t offset = sect->size; 374254885Sdumbbell DefinedAtom::Alignment atomAlign = atom->alignment(); 375254885Sdumbbell uint64_t align = atomAlign.value; 376254885Sdumbbell uint64_t requiredModulus = atomAlign.modulus; 377254885Sdumbbell uint64_t currentModulus = (offset % align); 378254885Sdumbbell if ( currentModulus != requiredModulus ) { 379254885Sdumbbell if ( requiredModulus > currentModulus ) 380254885Sdumbbell offset += requiredModulus-currentModulus; 381254885Sdumbbell else 382254885Sdumbbell offset += align+requiredModulus-currentModulus; 383254885Sdumbbell } 384254885Sdumbbell // Record max alignment of any atom in this section. 385254885Sdumbbell if (align > sect->alignment) 386254885Sdumbbell sect->alignment = atomAlign.value; 387254885Sdumbbell // Assign atom to this section with this offset. 388254885Sdumbbell AtomInfo ai = {atom, offset}; 389254885Sdumbbell sect->atomsAndOffsets.push_back(ai); 390254885Sdumbbell // Update section size to include this atom. 391254885Sdumbbell sect->size = offset + atom->size(); 392254885Sdumbbell} 393254885Sdumbbell 394254885Sdumbbellvoid Util::processDefinedAtoms(const lld::File &atomFile) { 395254885Sdumbbell for (const DefinedAtom *atom : atomFile.defined()) { 396254885Sdumbbell processAtomAttributes(atom); 397254885Sdumbbell assignAtomToSection(atom); 398254885Sdumbbell } 399254885Sdumbbell} 400254885Sdumbbell 401254885Sdumbbellvoid Util::processAtomAttributes(const DefinedAtom *atom) { 402254885Sdumbbell if (auto *machoFile = dyn_cast<mach_o::MachOFile>(&atom->file())) { 403254885Sdumbbell // If the file doesn't use subsections via symbols, then make sure we don't 404254885Sdumbbell // add that flag to the final output file if we have a relocatable file. 405254885Sdumbbell if (!machoFile->subsectionsViaSymbols()) 406254885Sdumbbell _subsectionsViaSymbols = false; 407254885Sdumbbell 408254885Sdumbbell // All the source files must have min versions for us to output an object 409258780Seadler // file with a min version. 410254885Sdumbbell if (auto v = machoFile->minVersion()) 411254885Sdumbbell _minVersion = std::max(_minVersion, v); 412254885Sdumbbell else 413254885Sdumbbell _allSourceFilesHaveMinVersions = false; 414254885Sdumbbell 415254885Sdumbbell // If we don't have a platform load command, but one of the source files 416254885Sdumbbell // does, then take the one from the file. 417254885Sdumbbell if (!_minVersionCommandType) 418254885Sdumbbell if (auto v = machoFile->minVersionLoadCommandKind()) 419254885Sdumbbell _minVersionCommandType = v; 420254885Sdumbbell } 421254885Sdumbbell} 422254885Sdumbbell 423254885Sdumbbellvoid Util::assignAtomToSection(const DefinedAtom *atom) { 424254885Sdumbbell if (atom->contentType() == DefinedAtom::typeMachHeader) { 425254885Sdumbbell _machHeaderAliasAtoms.push_back(atom); 426254885Sdumbbell // Assign atom to this section with this offset. 427254885Sdumbbell AtomInfo ai = {atom, 0}; 428254885Sdumbbell sectionForAtom(atom)->atomsAndOffsets.push_back(ai); 429254885Sdumbbell } else if (atom->contentType() == DefinedAtom::typeDSOHandle) 430254885Sdumbbell _machHeaderAliasAtoms.push_back(atom); 431254885Sdumbbell else 432254885Sdumbbell appendAtom(sectionForAtom(atom), atom); 433254885Sdumbbell} 434254885Sdumbbell 435254885SdumbbellSegmentInfo *Util::segmentForName(StringRef segName) { 436254885Sdumbbell for (SegmentInfo *si : _segmentInfos) { 437254885Sdumbbell if ( si->name.equals(segName) ) 438254885Sdumbbell return si; 439254885Sdumbbell } 440254885Sdumbbell auto *info = new (_allocator) SegmentInfo(segName); 441254885Sdumbbell 442254885Sdumbbell // Set the initial segment protection. 443254885Sdumbbell if (segName.equals("__TEXT")) 444254885Sdumbbell info->init_access = VM_PROT_READ | VM_PROT_EXECUTE; 445254885Sdumbbell else if (segName.equals("__PAGEZERO")) 446254885Sdumbbell info->init_access = 0; 447254885Sdumbbell else if (segName.equals("__LINKEDIT")) 448254885Sdumbbell info->init_access = VM_PROT_READ; 449254885Sdumbbell else { 450254885Sdumbbell // All others default to read-write 451254885Sdumbbell info->init_access = VM_PROT_READ | VM_PROT_WRITE; 452254885Sdumbbell } 453254885Sdumbbell 454254885Sdumbbell // Set max segment protection 455258780Seadler // Note, its overkill to use a switch statement here, but makes it so much 456254885Sdumbbell // easier to use switch coverage to catch new cases. 457254885Sdumbbell switch (_ctx.os()) { 458254885Sdumbbell case lld::MachOLinkingContext::OS::unknown: 459254885Sdumbbell case lld::MachOLinkingContext::OS::macOSX: 460254885Sdumbbell case lld::MachOLinkingContext::OS::iOS_simulator: 461254885Sdumbbell if (segName.equals("__PAGEZERO")) { 462254885Sdumbbell info->max_access = 0; 463254885Sdumbbell break; 464254885Sdumbbell } 465254885Sdumbbell // All others default to all 466254885Sdumbbell info->max_access = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE; 467258780Seadler break; 468254885Sdumbbell case lld::MachOLinkingContext::OS::iOS: 469254885Sdumbbell // iPhoneOS always uses same protection for max and initial 470254885Sdumbbell info->max_access = info->init_access; 471254885Sdumbbell break; 472254885Sdumbbell } 473254885Sdumbbell _segmentInfos.push_back(info); 474254885Sdumbbell return info; 475254885Sdumbbell} 476254885Sdumbbell 477254885Sdumbbellunsigned Util::SegmentSorter::weight(const SegmentInfo *seg) { 478254885Sdumbbell return llvm::StringSwitch<unsigned>(seg->name) 479254885Sdumbbell .Case("__PAGEZERO", 1) 480254885Sdumbbell .Case("__TEXT", 2) 481254885Sdumbbell .Case("__DATA", 3) 482254885Sdumbbell .Default(100); 483254885Sdumbbell} 484254885Sdumbbell 485254885Sdumbbellbool Util::SegmentSorter::operator()(const SegmentInfo *left, 486254885Sdumbbell const SegmentInfo *right) { 487254885Sdumbbell return (weight(left) < weight(right)); 488254885Sdumbbell} 489254885Sdumbbell 490254885Sdumbbellunsigned Util::TextSectionSorter::weight(const SectionInfo *sect) { 491254885Sdumbbell return llvm::StringSwitch<unsigned>(sect->sectionName) 492254885Sdumbbell .Case("__text", 1) 493254885Sdumbbell .Case("__stubs", 2) 494254885Sdumbbell .Case("__stub_helper", 3) 495254885Sdumbbell .Case("__const", 4) 496254885Sdumbbell .Case("__cstring", 5) 497254885Sdumbbell .Case("__unwind_info", 98) 498254885Sdumbbell .Case("__eh_frame", 99) 499254885Sdumbbell .Default(10); 500254885Sdumbbell} 501254885Sdumbbell 502254885Sdumbbellbool Util::TextSectionSorter::operator()(const SectionInfo *left, 503254885Sdumbbell const SectionInfo *right) { 504254885Sdumbbell return (weight(left) < weight(right)); 505254885Sdumbbell} 506254885Sdumbbell 507254885Sdumbbellvoid Util::organizeSections() { 508254885Sdumbbell // NOTE!: Keep this in sync with assignAddressesToSections. 509254885Sdumbbell switch (_ctx.outputMachOType()) { 510254885Sdumbbell case llvm::MachO::MH_EXECUTE: 511254885Sdumbbell // Main executables, need a zero-page segment 512254885Sdumbbell segmentForName("__PAGEZERO"); 513254885Sdumbbell // Fall into next case. 514254885Sdumbbell case llvm::MachO::MH_DYLIB: 515254885Sdumbbell case llvm::MachO::MH_BUNDLE: 516254885Sdumbbell // All dynamic code needs TEXT segment to hold the load commands. 517254885Sdumbbell segmentForName("__TEXT"); 518254885Sdumbbell break; 519254885Sdumbbell default: 520254885Sdumbbell break; 521254885Sdumbbell } 522254885Sdumbbell segmentForName("__LINKEDIT"); 523254885Sdumbbell 524254885Sdumbbell // Group sections into segments. 525254885Sdumbbell for (SectionInfo *si : _sectionInfos) { 526254885Sdumbbell SegmentInfo *seg = segmentForName(si->segmentName); 527254885Sdumbbell seg->sections.push_back(si); 528254885Sdumbbell } 529254885Sdumbbell // Sort segments. 530254885Sdumbbell std::sort(_segmentInfos.begin(), _segmentInfos.end(), SegmentSorter()); 531254885Sdumbbell 532254885Sdumbbell // Sort sections within segments. 533254885Sdumbbell for (SegmentInfo *seg : _segmentInfos) { 534254885Sdumbbell if (seg->name.equals("__TEXT")) { 535254885Sdumbbell std::sort(seg->sections.begin(), seg->sections.end(), 536254885Sdumbbell TextSectionSorter()); 537254885Sdumbbell } 538254885Sdumbbell } 539254885Sdumbbell 540254885Sdumbbell // Record final section indexes. 541254885Sdumbbell uint32_t segmentIndex = 0; 542254885Sdumbbell uint32_t sectionIndex = 1; 543254885Sdumbbell for (SegmentInfo *seg : _segmentInfos) { 544254885Sdumbbell seg->normalizedSegmentIndex = segmentIndex++; 545254885Sdumbbell for (SectionInfo *sect : seg->sections) 546254885Sdumbbell sect->finalSectionIndex = sectionIndex++; 547254885Sdumbbell } 548254885Sdumbbell} 549254885Sdumbbell 550254885Sdumbbellvoid Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) { 551254885Sdumbbell seg->address = addr; 552254885Sdumbbell for (SectionInfo *sect : seg->sections) { 553254885Sdumbbell sect->address = llvm::alignTo(addr, sect->alignment); 554254885Sdumbbell addr = sect->address + sect->size; 555254885Sdumbbell } 556254885Sdumbbell seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize()); 557254885Sdumbbell} 558254885Sdumbbell 559254885Sdumbbell// __TEXT segment lays out backwards so padding is at front after load commands. 560254885Sdumbbellvoid Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg, 561254885Sdumbbell uint64_t &addr) { 562254885Sdumbbell seg->address = addr; 563254885Sdumbbell // Walks sections starting at end to calculate padding for start. 564254885Sdumbbell int64_t taddr = 0; 565254885Sdumbbell for (auto it = seg->sections.rbegin(); it != seg->sections.rend(); ++it) { 566254885Sdumbbell SectionInfo *sect = *it; 567254885Sdumbbell taddr -= sect->size; 568254885Sdumbbell taddr = taddr & (0 - sect->alignment); 569254885Sdumbbell } 570254885Sdumbbell int64_t padding = taddr - hlcSize; 571254885Sdumbbell while (padding < 0) 572254885Sdumbbell padding += _ctx.pageSize(); 573254885Sdumbbell // Start assigning section address starting at padded offset. 574254885Sdumbbell addr += (padding + hlcSize); 575254885Sdumbbell for (SectionInfo *sect : seg->sections) { 576254885Sdumbbell sect->address = llvm::alignTo(addr, sect->alignment); 577254885Sdumbbell addr = sect->address + sect->size; 578254885Sdumbbell } 579254885Sdumbbell seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize()); 580254885Sdumbbell} 581254885Sdumbbell 582254885Sdumbbellvoid Util::assignAddressesToSections(const NormalizedFile &file) { 583254885Sdumbbell // NOTE!: Keep this in sync with organizeSections. 584254885Sdumbbell size_t hlcSize = headerAndLoadCommandsSize(file); 585254885Sdumbbell uint64_t address = 0; 586254885Sdumbbell for (SegmentInfo *seg : _segmentInfos) { 587254885Sdumbbell if (seg->name.equals("__PAGEZERO")) { 588254885Sdumbbell seg->size = _ctx.pageZeroSize(); 589254885Sdumbbell address += seg->size; 590254885Sdumbbell } 591254885Sdumbbell else if (seg->name.equals("__TEXT")) { 592254885Sdumbbell // _ctx.baseAddress() == 0 implies it was either unspecified or 593254885Sdumbbell // pageZeroSize is also 0. In either case resetting address is safe. 594254885Sdumbbell address = _ctx.baseAddress() ? _ctx.baseAddress() : address; 595254885Sdumbbell layoutSectionsInTextSegment(hlcSize, seg, address); 596254885Sdumbbell } else 597254885Sdumbbell layoutSectionsInSegment(seg, address); 598254885Sdumbbell 599254885Sdumbbell address = llvm::alignTo(address, _ctx.pageSize()); 600254885Sdumbbell } 601254885Sdumbbell DEBUG_WITH_TYPE("WriterMachO-norm", 602254885Sdumbbell llvm::dbgs() << "assignAddressesToSections()\n"; 603254885Sdumbbell for (SegmentInfo *sgi : _segmentInfos) { 604254885Sdumbbell llvm::dbgs() << " address=" << llvm::format("0x%08llX", sgi->address) 605254885Sdumbbell << ", size=" << llvm::format("0x%08llX", sgi->size) 606254885Sdumbbell << ", segment-name='" << sgi->name 607254885Sdumbbell << "'\n"; 608254885Sdumbbell for (SectionInfo *si : sgi->sections) { 609254885Sdumbbell llvm::dbgs()<< " addr=" << llvm::format("0x%08llX", si->address) 610254885Sdumbbell << ", size=" << llvm::format("0x%08llX", si->size) 611254885Sdumbbell << ", section-name='" << si->sectionName 612254885Sdumbbell << "\n"; 613254885Sdumbbell } 614254885Sdumbbell } 615254885Sdumbbell ); 616254885Sdumbbell} 617254885Sdumbbell 618254885Sdumbbellvoid Util::copySegmentInfo(NormalizedFile &file) { 619254885Sdumbbell for (SegmentInfo *sgi : _segmentInfos) { 620254885Sdumbbell Segment seg; 621254885Sdumbbell seg.name = sgi->name; 622254885Sdumbbell seg.address = sgi->address; 623254885Sdumbbell seg.size = sgi->size; 624254885Sdumbbell seg.init_access = sgi->init_access; 625254885Sdumbbell seg.max_access = sgi->max_access; 626254885Sdumbbell file.segments.push_back(seg); 627254885Sdumbbell } 628254885Sdumbbell} 629254885Sdumbbell 630254885Sdumbbellvoid Util::appendSection(SectionInfo *si, NormalizedFile &file) { 631254885Sdumbbell // Add new empty section to end of file.sections. 632254885Sdumbbell Section temp; 633254885Sdumbbell file.sections.push_back(std::move(temp)); 634254885Sdumbbell Section* normSect = &file.sections.back(); 635254885Sdumbbell // Copy fields to normalized section. 636254885Sdumbbell normSect->segmentName = si->segmentName; 637254885Sdumbbell normSect->sectionName = si->sectionName; 638254885Sdumbbell normSect->type = si->type; 639254885Sdumbbell normSect->attributes = si->attributes; 640254885Sdumbbell normSect->address = si->address; 641254885Sdumbbell normSect->alignment = si->alignment; 642254885Sdumbbell // Record where normalized section is. 643254885Sdumbbell si->normalizedSectionIndex = file.sections.size()-1; 644254885Sdumbbell} 645254885Sdumbbell 646254885Sdumbbellvoid Util::copySectionContent(NormalizedFile &file) { 647254885Sdumbbell const bool r = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); 648254885Sdumbbell 649254885Sdumbbell // Utility function for ArchHandler to find address of atom in output file. 650254885Sdumbbell auto addrForAtom = [&] (const Atom &atom) -> uint64_t { 651254885Sdumbbell auto pos = _atomToAddress.find(&atom); 652254885Sdumbbell assert(pos != _atomToAddress.end()); 653254885Sdumbbell return pos->second; 654254885Sdumbbell }; 655254885Sdumbbell 656254885Sdumbbell auto sectionAddrForAtom = [&] (const Atom &atom) -> uint64_t { 657254885Sdumbbell for (const SectionInfo *sectInfo : _sectionInfos) 658254885Sdumbbell for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets) 659254885Sdumbbell if (atomInfo.atom == &atom) 660254885Sdumbbell return sectInfo->address; 661254885Sdumbbell llvm_unreachable("atom not assigned to section"); 662254885Sdumbbell }; 663254885Sdumbbell 664254885Sdumbbell for (SectionInfo *si : _sectionInfos) { 665254885Sdumbbell Section *normSect = &file.sections[si->normalizedSectionIndex]; 666254885Sdumbbell if (isZeroFillSection(si->type)) { 667254885Sdumbbell const uint8_t *empty = nullptr; 668254885Sdumbbell normSect->content = llvm::makeArrayRef(empty, si->size); 669254885Sdumbbell continue; 670254885Sdumbbell } 671254885Sdumbbell // Copy content from atoms to content buffer for section. 672254885Sdumbbell llvm::MutableArrayRef<uint8_t> sectionContent; 673254885Sdumbbell if (si->size) { 674254885Sdumbbell uint8_t *sectContent = file.ownedAllocations.Allocate<uint8_t>(si->size); 675254885Sdumbbell sectionContent = llvm::MutableArrayRef<uint8_t>(sectContent, si->size); 676254885Sdumbbell normSect->content = sectionContent; 677254885Sdumbbell } 678254885Sdumbbell for (AtomInfo &ai : si->atomsAndOffsets) { 679254885Sdumbbell if (!ai.atom->size()) { 680254885Sdumbbell assert(ai.atom->begin() == ai.atom->end() && 681254885Sdumbbell "Cannot have references without content"); 682254885Sdumbbell continue; 683254885Sdumbbell } 684254885Sdumbbell auto atomContent = sectionContent.slice(ai.offsetInSection, 685254885Sdumbbell ai.atom->size()); 686254885Sdumbbell _archHandler.generateAtomContent(*ai.atom, r, addrForAtom, 687254885Sdumbbell sectionAddrForAtom, _ctx.baseAddress(), 688254885Sdumbbell atomContent); 689254885Sdumbbell } 690254885Sdumbbell } 691254885Sdumbbell} 692254885Sdumbbell 693254885Sdumbbellvoid Util::copySectionInfo(NormalizedFile &file) { 694254885Sdumbbell file.sections.reserve(_sectionInfos.size()); 695254885Sdumbbell // Write sections grouped by segment. 696254885Sdumbbell for (SegmentInfo *sgi : _segmentInfos) { 697254885Sdumbbell for (SectionInfo *si : sgi->sections) { 698254885Sdumbbell appendSection(si, file); 699254885Sdumbbell } 700254885Sdumbbell } 701254885Sdumbbell} 702254885Sdumbbell 703254885Sdumbbellvoid Util::updateSectionInfo(NormalizedFile &file) { 704254885Sdumbbell file.sections.reserve(_sectionInfos.size()); 705254885Sdumbbell // sections grouped by segment. 706254885Sdumbbell for (SegmentInfo *sgi : _segmentInfos) { 707254885Sdumbbell Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex]; 708254885Sdumbbell normSeg->address = sgi->address; 709254885Sdumbbell normSeg->size = sgi->size; 710254885Sdumbbell for (SectionInfo *si : sgi->sections) { 711254885Sdumbbell Section *normSect = &file.sections[si->normalizedSectionIndex]; 712254885Sdumbbell normSect->address = si->address; 713254885Sdumbbell } 714254885Sdumbbell } 715254885Sdumbbell} 716254885Sdumbbell 717254885Sdumbbellvoid Util::copyEntryPointAddress(NormalizedFile &nFile) { 718254885Sdumbbell if (!_entryAtom) { 719254885Sdumbbell nFile.entryAddress = 0; 720254885Sdumbbell return; 721254885Sdumbbell } 722254885Sdumbbell 723254885Sdumbbell if (_ctx.outputTypeHasEntry()) { 724254885Sdumbbell if (_archHandler.isThumbFunction(*_entryAtom)) 725254885Sdumbbell nFile.entryAddress = (_atomToAddress[_entryAtom] | 1); 726254885Sdumbbell else 727254885Sdumbbell nFile.entryAddress = _atomToAddress[_entryAtom]; 728254885Sdumbbell } 729254885Sdumbbell} 730254885Sdumbbell 731254885Sdumbbellvoid Util::buildAtomToAddressMap() { 732254885Sdumbbell DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() 733254885Sdumbbell << "assign atom addresses:\n"); 734254885Sdumbbell const bool lookForEntry = _ctx.outputTypeHasEntry(); 735254885Sdumbbell for (SectionInfo *sect : _sectionInfos) { 736254885Sdumbbell for (const AtomInfo &info : sect->atomsAndOffsets) { 737254885Sdumbbell _atomToAddress[info.atom] = sect->address + info.offsetInSection; 738254885Sdumbbell if (lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) && 739254885Sdumbbell (info.atom->size() != 0) && 740254885Sdumbbell info.atom->name() == _ctx.entrySymbolName()) { 741254885Sdumbbell _entryAtom = info.atom; 742254885Sdumbbell } 743254885Sdumbbell DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() 744254885Sdumbbell << " address=" 745254885Sdumbbell << llvm::format("0x%016X", _atomToAddress[info.atom]) 746254885Sdumbbell << llvm::format(" 0x%09lX", info.atom) 747254885Sdumbbell << ", file=#" 748254885Sdumbbell << info.atom->file().ordinal() 749254885Sdumbbell << ", atom=#" 750254885Sdumbbell << info.atom->ordinal() 751254885Sdumbbell << ", name=" 752254885Sdumbbell << info.atom->name() 753254885Sdumbbell << ", type=" 754254885Sdumbbell << info.atom->contentType() 755254885Sdumbbell << "\n"); 756254885Sdumbbell } 757254885Sdumbbell } 758254885Sdumbbell DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() 759254885Sdumbbell << "assign header alias atom addresses:\n"); 760254885Sdumbbell for (const Atom *atom : _machHeaderAliasAtoms) { 761254885Sdumbbell _atomToAddress[atom] = _ctx.baseAddress(); 762254885Sdumbbell#ifndef NDEBUG 763254885Sdumbbell if (auto *definedAtom = dyn_cast<DefinedAtom>(atom)) { 764254885Sdumbbell DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() 765254885Sdumbbell << " address=" 766254885Sdumbbell << llvm::format("0x%016X", _atomToAddress[atom]) 767254885Sdumbbell << llvm::format(" 0x%09lX", atom) 768254885Sdumbbell << ", file=#" 769254885Sdumbbell << definedAtom->file().ordinal() 770254885Sdumbbell << ", atom=#" 771254885Sdumbbell << definedAtom->ordinal() 772254885Sdumbbell << ", name=" 773254885Sdumbbell << definedAtom->name() 774258780Seadler << ", type=" 775254885Sdumbbell << definedAtom->contentType() 776254885Sdumbbell << "\n"); 777254885Sdumbbell } else { 778254885Sdumbbell DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() 779254885Sdumbbell << " address=" 780254885Sdumbbell << llvm::format("0x%016X", _atomToAddress[atom]) 781254885Sdumbbell << " atom=" << atom 782254885Sdumbbell << " name=" << atom->name() << "\n"); 783254885Sdumbbell } 784254885Sdumbbell#endif 785254885Sdumbbell } 786254885Sdumbbell} 787254885Sdumbbell 788254885Sdumbbelluint16_t Util::descBits(const DefinedAtom* atom) { 789254885Sdumbbell uint16_t desc = 0; 790254885Sdumbbell switch (atom->merge()) { 791254885Sdumbbell case lld::DefinedAtom::mergeNo: 792254885Sdumbbell case lld::DefinedAtom::mergeAsTentative: 793254885Sdumbbell break; 794254885Sdumbbell case lld::DefinedAtom::mergeAsWeak: 795254885Sdumbbell case lld::DefinedAtom::mergeAsWeakAndAddressUsed: 796254885Sdumbbell desc |= N_WEAK_DEF; 797254885Sdumbbell break; 798254885Sdumbbell case lld::DefinedAtom::mergeSameNameAndSize: 799254885Sdumbbell case lld::DefinedAtom::mergeByLargestSection: 800258780Seadler case lld::DefinedAtom::mergeByContent: 801254885Sdumbbell llvm_unreachable("Unsupported DefinedAtom::merge()"); 802254885Sdumbbell break; 803254885Sdumbbell } 804254885Sdumbbell if (atom->contentType() == lld::DefinedAtom::typeResolver) 805254885Sdumbbell desc |= N_SYMBOL_RESOLVER; 806258780Seadler if (atom->contentType() == lld::DefinedAtom::typeMachHeader) 807254885Sdumbbell desc |= REFERENCED_DYNAMICALLY; 808254885Sdumbbell if (_archHandler.isThumbFunction(*atom)) 809254885Sdumbbell desc |= N_ARM_THUMB_DEF; 810254885Sdumbbell if (atom->deadStrip() == DefinedAtom::deadStripNever) { 811254885Sdumbbell if ((atom->contentType() != DefinedAtom::typeInitializerPtr) 812254885Sdumbbell && (atom->contentType() != DefinedAtom::typeTerminatorPtr)) 813254885Sdumbbell desc |= N_NO_DEAD_STRIP; 814254885Sdumbbell } 815254885Sdumbbell return desc; 816254885Sdumbbell} 817254885Sdumbbell 818254885Sdumbbellbool Util::AtomSorter::operator()(const AtomAndIndex &left, 819254885Sdumbbell const AtomAndIndex &right) { 820254885Sdumbbell return (left.atom->name().compare(right.atom->name()) < 0); 821254885Sdumbbell} 822254885Sdumbbell 823254885Sdumbbellllvm::Error Util::getSymbolTableRegion(const DefinedAtom* atom, 824254885Sdumbbell bool &inGlobalsRegion, 825254885Sdumbbell SymbolScope &scope) { 826254885Sdumbbell bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); 827254885Sdumbbell switch (atom->scope()) { 828254885Sdumbbell case Atom::scopeTranslationUnit: 829254885Sdumbbell scope = 0; 830254885Sdumbbell inGlobalsRegion = false; 831254885Sdumbbell return llvm::Error(); 832254885Sdumbbell case Atom::scopeLinkageUnit: 833254885Sdumbbell if ((_ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) && 834254885Sdumbbell _ctx.exportSymbolNamed(atom->name())) { 835254885Sdumbbell return llvm::make_error<GenericError>( 836254885Sdumbbell Twine("cannot export hidden symbol ") + atom->name()); 837254885Sdumbbell } 838254885Sdumbbell if (rMode) { 839254885Sdumbbell if (_ctx.keepPrivateExterns()) { 840254885Sdumbbell // -keep_private_externs means keep in globals region as N_PEXT. 841254885Sdumbbell scope = N_PEXT | N_EXT; 842254885Sdumbbell inGlobalsRegion = true; 843254885Sdumbbell return llvm::Error(); 844254885Sdumbbell } 845254885Sdumbbell } 846254885Sdumbbell // scopeLinkageUnit symbols are no longer global once linked. 847254885Sdumbbell scope = N_PEXT; 848254885Sdumbbell inGlobalsRegion = false; 849254885Sdumbbell return llvm::Error(); 850254885Sdumbbell case Atom::scopeGlobal: 851254885Sdumbbell if (_ctx.exportRestrictMode()) { 852254885Sdumbbell if (_ctx.exportSymbolNamed(atom->name())) { 853254885Sdumbbell scope = N_EXT; 854254885Sdumbbell inGlobalsRegion = true; 855254885Sdumbbell return llvm::Error(); 856254885Sdumbbell } else { 857254885Sdumbbell scope = N_PEXT; 858254885Sdumbbell inGlobalsRegion = false; 859254885Sdumbbell return llvm::Error(); 860254885Sdumbbell } 861254885Sdumbbell } else { 862254885Sdumbbell scope = N_EXT; 863254885Sdumbbell inGlobalsRegion = true; 864254885Sdumbbell return llvm::Error(); 865254885Sdumbbell } 866254885Sdumbbell break; 867254885Sdumbbell } 868254885Sdumbbell llvm_unreachable("atom->scope() unknown enum value"); 869254885Sdumbbell} 870254885Sdumbbell 871254885Sdumbbellllvm::Error Util::addSymbols(const lld::File &atomFile, 872254885Sdumbbell NormalizedFile &file) { 873254885Sdumbbell bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); 874254885Sdumbbell // Mach-O symbol table has three regions: locals, globals, undefs. 875254885Sdumbbell 876254885Sdumbbell // Add all local (non-global) symbols in address order 877254885Sdumbbell std::vector<AtomAndIndex> globals; 878254885Sdumbbell globals.reserve(512); 879254885Sdumbbell for (SectionInfo *sect : _sectionInfos) { 880254885Sdumbbell for (const AtomInfo &info : sect->atomsAndOffsets) { 881254885Sdumbbell const DefinedAtom *atom = info.atom; 882254885Sdumbbell if (!atom->name().empty()) { 883254885Sdumbbell SymbolScope symbolScope; 884254885Sdumbbell bool inGlobalsRegion; 885254885Sdumbbell if (auto ec = getSymbolTableRegion(atom, inGlobalsRegion, symbolScope)){ 886254885Sdumbbell return ec; 887254885Sdumbbell } 888254885Sdumbbell if (inGlobalsRegion) { 889254885Sdumbbell AtomAndIndex ai = { atom, sect->finalSectionIndex, symbolScope }; 890254885Sdumbbell globals.push_back(ai); 891254885Sdumbbell } else { 892254885Sdumbbell Symbol sym; 893254885Sdumbbell sym.name = atom->name(); 894254885Sdumbbell sym.type = N_SECT; 895254885Sdumbbell sym.scope = symbolScope; 896254885Sdumbbell sym.sect = sect->finalSectionIndex; 897254885Sdumbbell sym.desc = descBits(atom); 898254885Sdumbbell sym.value = _atomToAddress[atom]; 899254885Sdumbbell _atomToSymbolIndex[atom] = file.localSymbols.size(); 900254885Sdumbbell file.localSymbols.push_back(sym); 901254885Sdumbbell } 902254885Sdumbbell } else if (rMode && _archHandler.needsLocalSymbolInRelocatableFile(atom)){ 903254885Sdumbbell // Create 'Lxxx' labels for anonymous atoms if archHandler says so. 904254885Sdumbbell static unsigned tempNum = 1; 905254885Sdumbbell char tmpName[16]; 906254885Sdumbbell sprintf(tmpName, "L%04u", tempNum++); 907254885Sdumbbell StringRef tempRef(tmpName); 908254885Sdumbbell Symbol sym; 909254885Sdumbbell sym.name = tempRef.copy(file.ownedAllocations); 910254885Sdumbbell sym.type = N_SECT; 911254885Sdumbbell sym.scope = 0; 912254885Sdumbbell sym.sect = sect->finalSectionIndex; 913254885Sdumbbell sym.desc = 0; 914254885Sdumbbell sym.value = _atomToAddress[atom]; 915254885Sdumbbell _atomToSymbolIndex[atom] = file.localSymbols.size(); 916254885Sdumbbell file.localSymbols.push_back(sym); 917254885Sdumbbell } 918254885Sdumbbell } 919254885Sdumbbell } 920254885Sdumbbell 921254885Sdumbbell // Sort global symbol alphabetically, then add to symbol table. 922254885Sdumbbell std::sort(globals.begin(), globals.end(), AtomSorter()); 923254885Sdumbbell const uint32_t globalStartIndex = file.localSymbols.size(); 924254885Sdumbbell for (AtomAndIndex &ai : globals) { 925254885Sdumbbell Symbol sym; 926254885Sdumbbell sym.name = ai.atom->name(); 927254885Sdumbbell sym.type = N_SECT; 928254885Sdumbbell sym.scope = ai.scope; 929254885Sdumbbell sym.sect = ai.index; 930254885Sdumbbell sym.desc = descBits(static_cast<const DefinedAtom*>(ai.atom)); 931254885Sdumbbell sym.value = _atomToAddress[ai.atom]; 932254885Sdumbbell _atomToSymbolIndex[ai.atom] = globalStartIndex + file.globalSymbols.size(); 933254885Sdumbbell file.globalSymbols.push_back(sym); 934254885Sdumbbell } 935254885Sdumbbell 936254885Sdumbbell // Sort undefined symbol alphabetically, then add to symbol table. 937254885Sdumbbell std::vector<AtomAndIndex> undefs; 938254885Sdumbbell undefs.reserve(128); 939254885Sdumbbell for (const UndefinedAtom *atom : atomFile.undefined()) { 940254885Sdumbbell AtomAndIndex ai = { atom, 0, N_EXT }; 941254885Sdumbbell undefs.push_back(ai); 942254885Sdumbbell } 943254885Sdumbbell for (const SharedLibraryAtom *atom : atomFile.sharedLibrary()) { 944254885Sdumbbell AtomAndIndex ai = { atom, 0, N_EXT }; 945254885Sdumbbell undefs.push_back(ai); 946254885Sdumbbell } 947254885Sdumbbell std::sort(undefs.begin(), undefs.end(), AtomSorter()); 948254885Sdumbbell const uint32_t start = file.globalSymbols.size() + file.localSymbols.size(); 949254885Sdumbbell for (AtomAndIndex &ai : undefs) { 950254885Sdumbbell Symbol sym; 951254885Sdumbbell uint16_t desc = 0; 952254885Sdumbbell if (!rMode) { 953254885Sdumbbell uint8_t ordinal = 0; 954254885Sdumbbell if (!_ctx.useFlatNamespace()) 955254885Sdumbbell ordinal = dylibOrdinal(dyn_cast<SharedLibraryAtom>(ai.atom)); 956254885Sdumbbell llvm::MachO::SET_LIBRARY_ORDINAL(desc, ordinal); 957254885Sdumbbell } 958254885Sdumbbell sym.name = ai.atom->name(); 959254885Sdumbbell sym.type = N_UNDF; 960254885Sdumbbell sym.scope = ai.scope; 961254885Sdumbbell sym.sect = 0; 962254885Sdumbbell sym.desc = desc; 963254885Sdumbbell sym.value = 0; 964254885Sdumbbell _atomToSymbolIndex[ai.atom] = file.undefinedSymbols.size() + start; 965254885Sdumbbell file.undefinedSymbols.push_back(sym); 966254885Sdumbbell } 967254885Sdumbbell 968254885Sdumbbell return llvm::Error(); 969254885Sdumbbell} 970254885Sdumbbell 971254885Sdumbbellconst Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) { 972254885Sdumbbell for (const Reference *ref : *lpAtom) { 973254885Sdumbbell if (_archHandler.isLazyPointer(*ref)) { 974254885Sdumbbell return ref->target(); 975254885Sdumbbell } 976254885Sdumbbell } 977254885Sdumbbell return nullptr; 978254885Sdumbbell} 979254885Sdumbbell 980254885Sdumbbellconst Atom *Util::targetOfStub(const DefinedAtom *stubAtom) { 981254885Sdumbbell for (const Reference *ref : *stubAtom) { 982254885Sdumbbell if (const Atom *ta = ref->target()) { 983254885Sdumbbell if (const DefinedAtom *lpAtom = dyn_cast<DefinedAtom>(ta)) { 984254885Sdumbbell const Atom *target = targetOfLazyPointer(lpAtom); 985254885Sdumbbell if (target) 986254885Sdumbbell return target; 987254885Sdumbbell } 988254885Sdumbbell } 989254885Sdumbbell } 990254885Sdumbbell return nullptr; 991254885Sdumbbell} 992254885Sdumbbell 993254885Sdumbbellvoid Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) { 994254885Sdumbbell for (SectionInfo *si : _sectionInfos) { 995254885Sdumbbell Section &normSect = file.sections[si->normalizedSectionIndex]; 996254885Sdumbbell switch (si->type) { 997254885Sdumbbell case llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS: 998254885Sdumbbell for (const AtomInfo &info : si->atomsAndOffsets) { 999254885Sdumbbell bool foundTarget = false; 1000254885Sdumbbell for (const Reference *ref : *info.atom) { 1001254885Sdumbbell const Atom *target = ref->target(); 1002254885Sdumbbell if (target) { 1003254885Sdumbbell if (isa<const SharedLibraryAtom>(target)) { 1004254885Sdumbbell uint32_t index = _atomToSymbolIndex[target]; 1005254885Sdumbbell normSect.indirectSymbols.push_back(index); 1006254885Sdumbbell foundTarget = true; 1007254885Sdumbbell } else { 1008254885Sdumbbell normSect.indirectSymbols.push_back( 1009254885Sdumbbell llvm::MachO::INDIRECT_SYMBOL_LOCAL); 1010254885Sdumbbell } 1011254885Sdumbbell } 1012254885Sdumbbell } 1013254885Sdumbbell if (!foundTarget) { 1014254885Sdumbbell normSect.indirectSymbols.push_back( 1015254885Sdumbbell llvm::MachO::INDIRECT_SYMBOL_ABS); 1016254885Sdumbbell } 1017254885Sdumbbell } 1018254885Sdumbbell break; 1019254885Sdumbbell case llvm::MachO::S_LAZY_SYMBOL_POINTERS: 1020254885Sdumbbell for (const AtomInfo &info : si->atomsAndOffsets) { 1021254885Sdumbbell const Atom *target = targetOfLazyPointer(info.atom); 1022254885Sdumbbell if (target) { 1023254885Sdumbbell uint32_t index = _atomToSymbolIndex[target]; 1024254885Sdumbbell normSect.indirectSymbols.push_back(index); 1025254885Sdumbbell } 1026254885Sdumbbell } 1027254885Sdumbbell break; 1028254885Sdumbbell case llvm::MachO::S_SYMBOL_STUBS: 1029254885Sdumbbell for (const AtomInfo &info : si->atomsAndOffsets) { 1030254885Sdumbbell const Atom *target = targetOfStub(info.atom); 1031254885Sdumbbell if (target) { 1032254885Sdumbbell uint32_t index = _atomToSymbolIndex[target]; 1033254885Sdumbbell normSect.indirectSymbols.push_back(index); 1034254885Sdumbbell } 1035254885Sdumbbell } 1036254885Sdumbbell break; 1037254885Sdumbbell default: 1038254885Sdumbbell break; 1039254885Sdumbbell } 1040254885Sdumbbell } 1041254885Sdumbbell} 1042254885Sdumbbell 1043254885Sdumbbellvoid Util::addDependentDylibs(const lld::File &atomFile,NormalizedFile &nFile) { 1044254885Sdumbbell // Scan all imported symbols and build up list of dylibs they are from. 1045254885Sdumbbell int ordinal = 1; 1046254885Sdumbbell for (const SharedLibraryAtom *slAtom : atomFile.sharedLibrary()) { 1047254885Sdumbbell StringRef loadPath = slAtom->loadName(); 1048254885Sdumbbell DylibPathToInfo::iterator pos = _dylibInfo.find(loadPath); 1049254885Sdumbbell if (pos == _dylibInfo.end()) { 1050254885Sdumbbell DylibInfo info; 1051254885Sdumbbell bool flatNamespaceAtom = &slAtom->file() == _ctx.flatNamespaceFile(); 1052254885Sdumbbell 1053254885Sdumbbell // If we're in -flat_namespace mode (or this atom came from the flat 1054254885Sdumbbell // namespace file under -undefined dynamic_lookup) then use the flat 1055254885Sdumbbell // lookup ordinal. 1056254885Sdumbbell if (flatNamespaceAtom || _ctx.useFlatNamespace()) 1057254885Sdumbbell info.ordinal = BIND_SPECIAL_DYLIB_FLAT_LOOKUP; 1058254885Sdumbbell else 1059254885Sdumbbell info.ordinal = ordinal++; 1060254885Sdumbbell info.hasWeak = slAtom->canBeNullAtRuntime(); 1061254885Sdumbbell info.hasNonWeak = !info.hasWeak; 1062254885Sdumbbell _dylibInfo[loadPath] = info; 1063254885Sdumbbell 1064254885Sdumbbell // Unless this was a flat_namespace atom, record the source dylib. 1065258780Seadler if (!flatNamespaceAtom) { 1066254885Sdumbbell DependentDylib depInfo; 1067254885Sdumbbell depInfo.path = loadPath; 1068254885Sdumbbell depInfo.kind = llvm::MachO::LC_LOAD_DYLIB; 1069254885Sdumbbell depInfo.currentVersion = _ctx.dylibCurrentVersion(loadPath); 1070254885Sdumbbell depInfo.compatVersion = _ctx.dylibCompatVersion(loadPath); 1071254885Sdumbbell nFile.dependentDylibs.push_back(depInfo); 1072254885Sdumbbell } 1073254885Sdumbbell } else { 1074254885Sdumbbell if ( slAtom->canBeNullAtRuntime() ) 1075254885Sdumbbell pos->second.hasWeak = true; 1076254885Sdumbbell else 1077254885Sdumbbell pos->second.hasNonWeak = true; 1078254885Sdumbbell } 1079254885Sdumbbell } 1080254885Sdumbbell // Automatically weak link dylib in which all symbols are weak (canBeNull). 1081254885Sdumbbell for (DependentDylib &dep : nFile.dependentDylibs) { 1082254885Sdumbbell DylibInfo &info = _dylibInfo[dep.path]; 1083254885Sdumbbell if (info.hasWeak && !info.hasNonWeak) 1084254885Sdumbbell dep.kind = llvm::MachO::LC_LOAD_WEAK_DYLIB; 1085254885Sdumbbell else if (_ctx.isUpwardDylib(dep.path)) 1086254885Sdumbbell dep.kind = llvm::MachO::LC_LOAD_UPWARD_DYLIB; 1087254885Sdumbbell } 1088254885Sdumbbell} 1089254885Sdumbbell 1090254885Sdumbbellint Util::dylibOrdinal(const SharedLibraryAtom *sa) { 1091254885Sdumbbell return _dylibInfo[sa->loadName()].ordinal; 1092254885Sdumbbell} 1093254885Sdumbbell 1094254885Sdumbbellvoid Util::segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex, 1095254885Sdumbbell uint64_t &segmentStartAddr) { 1096254885Sdumbbell segmentIndex = 0; 1097254885Sdumbbell for (const SegmentInfo *seg : _segmentInfos) { 1098254885Sdumbbell if ((seg->address <= sect->address) 1099254885Sdumbbell && (seg->address+seg->size >= sect->address+sect->size)) { 1100254885Sdumbbell segmentStartAddr = seg->address; 1101254885Sdumbbell return; 1102254885Sdumbbell } 1103254885Sdumbbell ++segmentIndex; 1104254885Sdumbbell } 1105254885Sdumbbell llvm_unreachable("section not in any segment"); 1106254885Sdumbbell} 1107254885Sdumbbell 1108254885Sdumbbelluint32_t Util::sectionIndexForAtom(const Atom *atom) { 1109254885Sdumbbell uint64_t address = _atomToAddress[atom]; 1110254885Sdumbbell for (const SectionInfo *si : _sectionInfos) { 1111254885Sdumbbell if ((si->address <= address) && (address < si->address+si->size)) 1112254885Sdumbbell return si->finalSectionIndex; 1113254885Sdumbbell } 1114254885Sdumbbell llvm_unreachable("atom not in any section"); 1115254885Sdumbbell} 1116254885Sdumbbell 1117254885Sdumbbellvoid Util::addSectionRelocs(const lld::File &, NormalizedFile &file) { 1118254885Sdumbbell if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT) 1119254885Sdumbbell return; 1120254885Sdumbbell 1121254885Sdumbbell // Utility function for ArchHandler to find symbol index for an atom. 1122254885Sdumbbell auto symIndexForAtom = [&] (const Atom &atom) -> uint32_t { 1123254885Sdumbbell auto pos = _atomToSymbolIndex.find(&atom); 1124254885Sdumbbell assert(pos != _atomToSymbolIndex.end()); 1125254885Sdumbbell return pos->second; 1126254885Sdumbbell }; 1127254885Sdumbbell 1128254885Sdumbbell // Utility function for ArchHandler to find section index for an atom. 1129254885Sdumbbell auto sectIndexForAtom = [&] (const Atom &atom) -> uint32_t { 1130254885Sdumbbell return sectionIndexForAtom(&atom); 1131254885Sdumbbell }; 1132254885Sdumbbell 1133254885Sdumbbell // Utility function for ArchHandler to find address of atom in output file. 1134254885Sdumbbell auto addressForAtom = [&] (const Atom &atom) -> uint64_t { 1135254885Sdumbbell auto pos = _atomToAddress.find(&atom); 1136254885Sdumbbell assert(pos != _atomToAddress.end()); 1137254885Sdumbbell return pos->second; 1138254885Sdumbbell }; 1139254885Sdumbbell 1140254885Sdumbbell for (SectionInfo *si : _sectionInfos) { 1141254885Sdumbbell Section &normSect = file.sections[si->normalizedSectionIndex]; 1142254885Sdumbbell for (const AtomInfo &info : si->atomsAndOffsets) { 1143254885Sdumbbell const DefinedAtom *atom = info.atom; 1144254885Sdumbbell for (const Reference *ref : *atom) { 1145254885Sdumbbell // Skip emitting relocs for sections which are always able to be 1146254885Sdumbbell // implicitly regenerated and where the relocation targets an address 1147254885Sdumbbell // which is defined. 1148254885Sdumbbell if (si->relocsToDefinedCanBeImplicit && isa<DefinedAtom>(ref->target())) 1149254885Sdumbbell continue; 1150254885Sdumbbell _archHandler.appendSectionRelocations(*atom, info.offsetInSection, *ref, 1151254885Sdumbbell symIndexForAtom, 1152254885Sdumbbell sectIndexForAtom, 1153254885Sdumbbell addressForAtom, 1154254885Sdumbbell normSect.relocations); 1155254885Sdumbbell } 1156254885Sdumbbell } 1157254885Sdumbbell } 1158254885Sdumbbell} 1159254885Sdumbbell 1160254885Sdumbbellvoid Util::addFunctionStarts(const lld::File &, NormalizedFile &file) { 1161254885Sdumbbell if (!_ctx.generateFunctionStartsLoadCommand()) 1162254885Sdumbbell return; 1163254885Sdumbbell file.functionStarts.reserve(8192); 1164254885Sdumbbell // Delta compress function starts, starting with the mach header symbol. 1165254885Sdumbbell const uint64_t badAddress = ~0ULL; 1166254885Sdumbbell uint64_t addr = badAddress; 1167254885Sdumbbell for (SectionInfo *si : _sectionInfos) { 1168254885Sdumbbell for (const AtomInfo &info : si->atomsAndOffsets) { 1169254885Sdumbbell auto type = info.atom->contentType(); 1170254885Sdumbbell if (type == DefinedAtom::typeMachHeader) { 1171254885Sdumbbell addr = _atomToAddress[info.atom]; 1172254885Sdumbbell continue; 1173254885Sdumbbell } 1174254885Sdumbbell if (type != DefinedAtom::typeCode) 1175254885Sdumbbell continue; 1176254885Sdumbbell assert(addr != badAddress && "Missing mach header symbol"); 1177254885Sdumbbell // Skip atoms which have 0 size. This is so that LC_FUNCTION_STARTS 1178254885Sdumbbell // can't spill in to the next section. 1179254885Sdumbbell if (!info.atom->size()) 1180254885Sdumbbell continue; 1181254885Sdumbbell uint64_t nextAddr = _atomToAddress[info.atom]; 1182254885Sdumbbell if (_archHandler.isThumbFunction(*info.atom)) 1183254885Sdumbbell nextAddr |= 1; 1184254885Sdumbbell uint64_t delta = nextAddr - addr; 1185254885Sdumbbell if (delta) { 1186254885Sdumbbell ByteBuffer buffer; 1187254885Sdumbbell buffer.append_uleb128(delta); 1188254885Sdumbbell file.functionStarts.insert(file.functionStarts.end(), buffer.bytes(), 1189254885Sdumbbell buffer.bytes() + buffer.size()); 1190254885Sdumbbell } 1191254885Sdumbbell addr = nextAddr; 1192254885Sdumbbell } 1193254885Sdumbbell } 1194254885Sdumbbell 1195254885Sdumbbell // Null terminate, and pad to pointer size for this arch. 1196254885Sdumbbell file.functionStarts.push_back(0); 1197254885Sdumbbell 1198254885Sdumbbell auto size = file.functionStarts.size(); 1199254885Sdumbbell for (unsigned i = size, e = llvm::alignTo(size, _ctx.is64Bit() ? 8 : 4); 1200254885Sdumbbell i != e; ++i) 1201254885Sdumbbell file.functionStarts.push_back(0); 1202254885Sdumbbell} 1203254885Sdumbbell 1204254885Sdumbbellvoid Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) { 1205254885Sdumbbell if (!_ctx.generateDataInCodeLoadCommand()) 1206254885Sdumbbell return; 1207254885Sdumbbell for (SectionInfo *si : _sectionInfos) { 1208254885Sdumbbell for (const AtomInfo &info : si->atomsAndOffsets) { 1209254885Sdumbbell // Atoms that contain data-in-code have "transition" references 1210254885Sdumbbell // which mark a point where the embedded data starts of ends. 1211254885Sdumbbell // This needs to be converted to the mach-o format which is an array 1212254885Sdumbbell // of data-in-code ranges. 1213254885Sdumbbell uint32_t startOffset = 0; 1214254885Sdumbbell DataRegionType mode = DataRegionType(0); 1215254885Sdumbbell for (const Reference *ref : *info.atom) { 1216254885Sdumbbell if (ref->kindNamespace() != Reference::KindNamespace::mach_o) 1217254885Sdumbbell continue; 1218254885Sdumbbell if (_archHandler.isDataInCodeTransition(ref->kindValue())) { 1219254885Sdumbbell DataRegionType nextMode = (DataRegionType)ref->addend(); 1220254885Sdumbbell if (mode != nextMode) { 1221254885Sdumbbell if (mode != 0) { 1222254885Sdumbbell // Found end data range, so make range entry. 1223254885Sdumbbell DataInCode entry; 1224254885Sdumbbell entry.offset = si->address + info.offsetInSection + startOffset; 1225254885Sdumbbell entry.length = ref->offsetInAtom() - startOffset; 1226254885Sdumbbell entry.kind = mode; 1227254885Sdumbbell file.dataInCode.push_back(entry); 1228254885Sdumbbell } 1229254885Sdumbbell } 1230254885Sdumbbell mode = nextMode; 1231254885Sdumbbell startOffset = ref->offsetInAtom(); 1232254885Sdumbbell } 1233254885Sdumbbell } 1234254885Sdumbbell if (mode != 0) { 1235254885Sdumbbell // Function ends with data (no end transition). 1236254885Sdumbbell DataInCode entry; 1237254885Sdumbbell entry.offset = si->address + info.offsetInSection + startOffset; 1238254885Sdumbbell entry.length = info.atom->size() - startOffset; 1239254885Sdumbbell entry.kind = mode; 1240254885Sdumbbell file.dataInCode.push_back(entry); 1241254885Sdumbbell } 1242254885Sdumbbell } 1243254885Sdumbbell } 1244254885Sdumbbell} 1245254885Sdumbbell 1246254885Sdumbbellvoid Util::addRebaseAndBindingInfo(const lld::File &atomFile, 1247254885Sdumbbell NormalizedFile &nFile) { 1248254885Sdumbbell if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT) 1249254885Sdumbbell return; 1250254885Sdumbbell 1251254885Sdumbbell uint8_t segmentIndex; 1252254885Sdumbbell uint64_t segmentStartAddr; 1253254885Sdumbbell for (SectionInfo *sect : _sectionInfos) { 1254254885Sdumbbell segIndexForSection(sect, segmentIndex, segmentStartAddr); 1255254885Sdumbbell for (const AtomInfo &info : sect->atomsAndOffsets) { 1256254885Sdumbbell const DefinedAtom *atom = info.atom; 1257254885Sdumbbell for (const Reference *ref : *atom) { 1258254885Sdumbbell uint64_t segmentOffset = _atomToAddress[atom] + ref->offsetInAtom() 1259254885Sdumbbell - segmentStartAddr; 1260254885Sdumbbell const Atom* targ = ref->target(); 1261254885Sdumbbell if (_archHandler.isPointer(*ref)) { 1262254885Sdumbbell // A pointer to a DefinedAtom requires rebasing. 1263254885Sdumbbell if (isa<DefinedAtom>(targ)) { 1264254885Sdumbbell RebaseLocation rebase; 1265254885Sdumbbell rebase.segIndex = segmentIndex; 1266254885Sdumbbell rebase.segOffset = segmentOffset; 1267254885Sdumbbell rebase.kind = llvm::MachO::REBASE_TYPE_POINTER; 1268254885Sdumbbell nFile.rebasingInfo.push_back(rebase); 1269254885Sdumbbell } 1270254885Sdumbbell // A pointer to an SharedLibraryAtom requires binding. 1271254885Sdumbbell if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) { 1272254885Sdumbbell BindLocation bind; 1273254885Sdumbbell bind.segIndex = segmentIndex; 1274254885Sdumbbell bind.segOffset = segmentOffset; 1275254885Sdumbbell bind.kind = llvm::MachO::BIND_TYPE_POINTER; 1276254885Sdumbbell bind.canBeNull = sa->canBeNullAtRuntime(); 1277254885Sdumbbell bind.ordinal = dylibOrdinal(sa); 1278254885Sdumbbell bind.symbolName = targ->name(); 1279254885Sdumbbell bind.addend = ref->addend(); 1280254885Sdumbbell nFile.bindingInfo.push_back(bind); 1281254885Sdumbbell } 1282254885Sdumbbell } 1283254885Sdumbbell else if (_archHandler.isLazyPointer(*ref)) { 1284254885Sdumbbell BindLocation bind; 1285254885Sdumbbell if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) { 1286254885Sdumbbell bind.ordinal = dylibOrdinal(sa); 1287254885Sdumbbell } else { 1288254885Sdumbbell bind.ordinal = llvm::MachO::BIND_SPECIAL_DYLIB_SELF; 1289254885Sdumbbell } 1290254885Sdumbbell bind.segIndex = segmentIndex; 1291254885Sdumbbell bind.segOffset = segmentOffset; 1292254885Sdumbbell bind.kind = llvm::MachO::BIND_TYPE_POINTER; 1293254885Sdumbbell bind.canBeNull = false; //sa->canBeNullAtRuntime(); 1294254885Sdumbbell bind.symbolName = targ->name(); 1295254885Sdumbbell bind.addend = ref->addend(); 1296254885Sdumbbell nFile.lazyBindingInfo.push_back(bind); 1297254885Sdumbbell } 1298254885Sdumbbell } 1299254885Sdumbbell } 1300254885Sdumbbell } 1301254885Sdumbbell} 1302254885Sdumbbell 1303254885Sdumbbellvoid Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) { 1304254885Sdumbbell if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT) 1305254885Sdumbbell return; 1306254885Sdumbbell 1307254885Sdumbbell for (SectionInfo *sect : _sectionInfos) { 1308254885Sdumbbell for (const AtomInfo &info : sect->atomsAndOffsets) { 1309254885Sdumbbell const DefinedAtom *atom = info.atom; 1310254885Sdumbbell if (atom->scope() != Atom::scopeGlobal) 1311254885Sdumbbell continue; 1312254885Sdumbbell if (_ctx.exportRestrictMode()) { 1313254885Sdumbbell if (!_ctx.exportSymbolNamed(atom->name())) 1314254885Sdumbbell continue; 1315254885Sdumbbell } 1316254885Sdumbbell Export exprt; 1317254885Sdumbbell exprt.name = atom->name(); 1318254885Sdumbbell exprt.offset = _atomToAddress[atom] - _ctx.baseAddress(); 1319254885Sdumbbell exprt.kind = EXPORT_SYMBOL_FLAGS_KIND_REGULAR; 1320254885Sdumbbell if (atom->merge() == DefinedAtom::mergeAsWeak) 1321254885Sdumbbell exprt.flags = EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; 1322254885Sdumbbell else 1323254885Sdumbbell exprt.flags = 0; 1324254885Sdumbbell exprt.otherOffset = 0; 1325254885Sdumbbell exprt.otherName = StringRef(); 1326254885Sdumbbell nFile.exportInfo.push_back(exprt); 1327254885Sdumbbell } 1328254885Sdumbbell } 1329254885Sdumbbell} 1330254885Sdumbbell 1331254885Sdumbbelluint32_t Util::fileFlags() { 1332254885Sdumbbell // FIXME: these need to determined at runtime. 1333254885Sdumbbell if (_ctx.outputMachOType() == MH_OBJECT) { 1334254885Sdumbbell return _subsectionsViaSymbols ? MH_SUBSECTIONS_VIA_SYMBOLS : 0; 1335254885Sdumbbell } else { 1336254885Sdumbbell uint32_t flags = MH_DYLDLINK; 1337254885Sdumbbell if (!_ctx.useFlatNamespace()) 1338254885Sdumbbell flags |= MH_TWOLEVEL | MH_NOUNDEFS; 1339254885Sdumbbell if ((_ctx.outputMachOType() == MH_EXECUTE) && _ctx.PIE()) 1340254885Sdumbbell flags |= MH_PIE; 1341254885Sdumbbell if (_hasTLVDescriptors) 1342254885Sdumbbell flags |= (MH_PIE | MH_HAS_TLV_DESCRIPTORS); 1343254885Sdumbbell return flags; 1344254885Sdumbbell } 1345254885Sdumbbell} 1346254885Sdumbbell 1347254885Sdumbbell} // end anonymous namespace 1348254885Sdumbbell 1349254885Sdumbbellnamespace lld { 1350254885Sdumbbellnamespace mach_o { 1351254885Sdumbbellnamespace normalized { 1352254885Sdumbbell 1353254885Sdumbbell/// Convert a set of Atoms into a normalized mach-o file. 1354254885Sdumbbellllvm::Expected<std::unique_ptr<NormalizedFile>> 1355254885SdumbbellnormalizedFromAtoms(const lld::File &atomFile, 1356254885Sdumbbell const MachOLinkingContext &context) { 1357254885Sdumbbell // The util object buffers info until the normalized file can be made. 1358254885Sdumbbell Util util(context); 1359254885Sdumbbell util.processDefinedAtoms(atomFile); 1360254885Sdumbbell util.organizeSections(); 1361254885Sdumbbell 1362254885Sdumbbell std::unique_ptr<NormalizedFile> f(new NormalizedFile()); 1363254885Sdumbbell NormalizedFile &normFile = *f.get(); 1364254885Sdumbbell normFile.arch = context.arch(); 1365254885Sdumbbell normFile.fileType = context.outputMachOType(); 1366254885Sdumbbell normFile.flags = util.fileFlags(); 1367254885Sdumbbell normFile.stackSize = context.stackSize(); 1368254885Sdumbbell normFile.installName = context.installName(); 1369254885Sdumbbell normFile.currentVersion = context.currentVersion(); 1370254885Sdumbbell normFile.compatVersion = context.compatibilityVersion(); 1371254885Sdumbbell normFile.os = context.os(); 1372254885Sdumbbell 1373254885Sdumbbell // If we are emitting an object file, then the min version is the maximum 1374254885Sdumbbell // of the min's of all the source files and the cmdline. 1375254885Sdumbbell if (normFile.fileType == llvm::MachO::MH_OBJECT) 1376254885Sdumbbell normFile.minOSverson = std::max(context.osMinVersion(), util.minVersion()); 1377254885Sdumbbell else 1378254885Sdumbbell normFile.minOSverson = context.osMinVersion(); 1379254885Sdumbbell 1380254885Sdumbbell normFile.minOSVersionKind = util.minVersionCommandType(); 1381254885Sdumbbell 1382254885Sdumbbell normFile.sdkVersion = context.sdkVersion(); 1383254885Sdumbbell normFile.sourceVersion = context.sourceVersion(); 1384254885Sdumbbell 1385254885Sdumbbell if (context.generateVersionLoadCommand() && 1386254885Sdumbbell context.os() != MachOLinkingContext::OS::unknown) 1387254885Sdumbbell normFile.hasMinVersionLoadCommand = true; 1388254885Sdumbbell else if (normFile.fileType == llvm::MachO::MH_OBJECT && 1389254885Sdumbbell util.allSourceFilesHaveMinVersions() && 1390254885Sdumbbell ((normFile.os != MachOLinkingContext::OS::unknown) || 1391254885Sdumbbell util.minVersionCommandType())) { 1392254885Sdumbbell // If we emit an object file, then it should contain a min version load 1393254885Sdumbbell // command if all of the source files also contained min version commands. 1394254885Sdumbbell // Also, we either need to have a platform, or found a platform from the 1395254885Sdumbbell // source object files. 1396254885Sdumbbell normFile.hasMinVersionLoadCommand = true; 1397254885Sdumbbell } 1398254885Sdumbbell normFile.generateDataInCodeLoadCommand = 1399254885Sdumbbell context.generateDataInCodeLoadCommand(); 1400254885Sdumbbell normFile.pageSize = context.pageSize(); 1401254885Sdumbbell normFile.rpaths = context.rpaths(); 1402254885Sdumbbell util.addDependentDylibs(atomFile, normFile); 1403254885Sdumbbell util.copySegmentInfo(normFile); 1404254885Sdumbbell util.copySectionInfo(normFile); 1405254885Sdumbbell util.assignAddressesToSections(normFile); 1406254885Sdumbbell util.buildAtomToAddressMap(); 1407254885Sdumbbell util.updateSectionInfo(normFile); 1408254885Sdumbbell util.copySectionContent(normFile); 1409254885Sdumbbell if (auto ec = util.addSymbols(atomFile, normFile)) { 1410254885Sdumbbell return std::move(ec); 1411254885Sdumbbell } 1412254885Sdumbbell util.addIndirectSymbols(atomFile, normFile); 1413254885Sdumbbell util.addRebaseAndBindingInfo(atomFile, normFile); 1414254885Sdumbbell util.addExportInfo(atomFile, normFile); 1415254885Sdumbbell util.addSectionRelocs(atomFile, normFile); 1416254885Sdumbbell util.addFunctionStarts(atomFile, normFile); 1417254885Sdumbbell util.buildDataInCodeArray(atomFile, normFile); 1418254885Sdumbbell util.copyEntryPointAddress(normFile); 1419254885Sdumbbell 1420254885Sdumbbell return std::move(f); 1421254885Sdumbbell} 1422254885Sdumbbell 1423254885Sdumbbell} // namespace normalized 1424254885Sdumbbell} // namespace mach_o 1425254885Sdumbbell} // namespace lld 1426254885Sdumbbell