MachONormalizedFileFromAtoms.cpp revision 293258
116009Sserb//===- lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp ------------===// 216009Sserb// 316009Sserb// The LLVM Linker 416009Sserb// 516009Sserb// This file is distributed under the University of Illinois Open Source 616009Sserb// License. See LICENSE.TXT for details. 716009Sserb// 816009Sserb//===----------------------------------------------------------------------===// 916009Sserb 1016009Sserb/// 1116009Sserb/// \file Converts from in-memory Atoms to in-memory normalized mach-o. 1216009Sserb/// 1316009Sserb/// +------------+ 1416009Sserb/// | normalized | 1516009Sserb/// +------------+ 1616009Sserb/// ^ 1716009Sserb/// | 1816009Sserb/// | 1916009Sserb/// +-------+ 2016009Sserb/// | Atoms | 2116009Sserb/// +-------+ 2216009Sserb 2316009Sserb#include "MachONormalizedFile.h" 2416009Sserb#include "ArchHandler.h" 2516009Sserb#include "MachONormalizedFileBinaryUtils.h" 2616009Sserb#include "lld/Core/Error.h" 2716009Sserb#include "lld/Core/LLVM.h" 2816009Sserb#include "llvm/ADT/StringRef.h" 2916009Sserb#include "llvm/ADT/StringSwitch.h" 3016009Sserb#include "llvm/Support/Casting.h" 3116009Sserb#include "llvm/Support/Debug.h" 3216009Sserb#include "llvm/Support/ErrorHandling.h" 3316009Sserb#include "llvm/Support/Format.h" 3416009Sserb#include "llvm/Support/MachO.h" 3516009Sserb#include <map> 3616009Sserb#include <system_error> 3716009Sserb 3816009Sserbusing llvm::StringRef; 3916009Sserbusing llvm::isa; 4016009Sserbusing namespace llvm::MachO; 4116009Sserbusing namespace lld::mach_o::normalized; 4216009Sserbusing namespace lld; 4316009Sserb 4416009Sserbnamespace { 4516009Sserb 4616009Sserbstruct AtomInfo { 4716009Sserb const DefinedAtom *atom; 4816009Sserb uint64_t offsetInSection; 4916009Sserb}; 5016009Sserb 5116009Sserbstruct SectionInfo { 5216009Sserb SectionInfo(StringRef seg, StringRef sect, SectionType type, 5316009Sserb const MachOLinkingContext &ctxt, uint32_t attr=0); 5416009Sserb 5516009Sserb StringRef segmentName; 5616009Sserb StringRef sectionName; 5716009Sserb SectionType type; 5816009Sserb uint32_t attributes; 5916009Sserb uint64_t address; 6016009Sserb uint64_t size; 6116009Sserb uint16_t alignment; 6216009Sserb std::vector<AtomInfo> atomsAndOffsets; 6316009Sserb uint32_t normalizedSectionIndex; 6416009Sserb uint32_t finalSectionIndex; 6516009Sserb}; 6616009Sserb 6716009SserbSectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t, 6816009Sserb const MachOLinkingContext &ctxt, uint32_t attrs) 6916009Sserb : segmentName(sg), sectionName(sct), type(t), attributes(attrs), 7016009Sserb address(0), size(0), alignment(1), 7116009Sserb normalizedSectionIndex(0), finalSectionIndex(0) { 7216009Sserb uint16_t align = 1; 7316009Sserb if (ctxt.sectionAligned(segmentName, sectionName, align)) { 7416009Sserb alignment = align; 7516009Sserb } 7616009Sserb} 7716009Sserb 7816009Sserbstruct SegmentInfo { 7916009Sserb SegmentInfo(StringRef name); 8016009Sserb 8116009Sserb StringRef name; 8216009Sserb uint64_t address; 8316009Sserb uint64_t size; 8416009Sserb uint32_t access; 8516009Sserb std::vector<SectionInfo*> sections; 8616009Sserb uint32_t normalizedSegmentIndex; 8716009Sserb}; 8816009Sserb 8916009SserbSegmentInfo::SegmentInfo(StringRef n) 9016009Sserb : name(n), address(0), size(0), access(0), normalizedSegmentIndex(0) { 9116009Sserb} 9216009Sserb 9316009Sserbclass Util { 9416009Sserbpublic: 9516009Sserb Util(const MachOLinkingContext &ctxt) 9616009Sserb : _ctx(ctxt), _archHandler(ctxt.archHandler()), _entryAtom(nullptr), 9716009Sserb _hasTLVDescriptors(false) {} 9816009Sserb ~Util(); 9916009Sserb 10016009Sserb void assignAtomsToSections(const lld::File &atomFile); 10116009Sserb void organizeSections(); 10216009Sserb void assignAddressesToSections(const NormalizedFile &file); 10316009Sserb uint32_t fileFlags(); 10416009Sserb void copySegmentInfo(NormalizedFile &file); 10516009Sserb void copySectionInfo(NormalizedFile &file); 10616009Sserb void updateSectionInfo(NormalizedFile &file); 10716009Sserb void buildAtomToAddressMap(); 10816009Sserb std::error_code addSymbols(const lld::File &atomFile, NormalizedFile &file); 10916009Sserb void addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file); 11016009Sserb void addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file); 11116009Sserb void addExportInfo(const lld::File &, NormalizedFile &file); 11216009Sserb void addSectionRelocs(const lld::File &, NormalizedFile &file); 11316009Sserb void buildDataInCodeArray(const lld::File &, NormalizedFile &file); 11416009Sserb void addDependentDylibs(const lld::File &, NormalizedFile &file); 11516009Sserb void copyEntryPointAddress(NormalizedFile &file); 11616009Sserb void copySectionContent(NormalizedFile &file); 11716009Sserb 11816009Sserbprivate: 11916009Sserb typedef std::map<DefinedAtom::ContentType, SectionInfo*> TypeToSection; 12016009Sserb typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress; 12116009Sserb 12216009Sserb struct DylibInfo { int ordinal; bool hasWeak; bool hasNonWeak; }; 12316009Sserb typedef llvm::StringMap<DylibInfo> DylibPathToInfo; 12416009Sserb 12516009Sserb SectionInfo *sectionForAtom(const DefinedAtom*); 12616009Sserb SectionInfo *getRelocatableSection(DefinedAtom::ContentType type); 12716009Sserb SectionInfo *getFinalSection(DefinedAtom::ContentType type); 12816009Sserb void appendAtom(SectionInfo *sect, const DefinedAtom *atom); 12916009Sserb SegmentInfo *segmentForName(StringRef segName); 13016009Sserb void layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr); 13116009Sserb void layoutSectionsInTextSegment(size_t, SegmentInfo *, uint64_t &); 13216009Sserb void copySectionContent(SectionInfo *si, ContentBytes &content); 13316009Sserb uint16_t descBits(const DefinedAtom* atom); 13416009Sserb int dylibOrdinal(const SharedLibraryAtom *sa); 13516009Sserb void segIndexForSection(const SectionInfo *sect, 13616009Sserb uint8_t &segmentIndex, uint64_t &segmentStartAddr); 13716009Sserb const Atom *targetOfLazyPointer(const DefinedAtom *lpAtom); 13816009Sserb const Atom *targetOfStub(const DefinedAtom *stubAtom); 13916009Sserb std::error_code getSymbolTableRegion(const DefinedAtom* atom, 14016009Sserb bool &inGlobalsRegion, 14116009Sserb SymbolScope &symbolScope); 14216009Sserb void appendSection(SectionInfo *si, NormalizedFile &file); 14316009Sserb uint32_t sectionIndexForAtom(const Atom *atom); 14416009Sserb 14516009Sserb typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex; 14616009Sserb struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; }; 14716009Sserb struct AtomSorter { 14816009Sserb bool operator()(const AtomAndIndex &left, const AtomAndIndex &right); 14916009Sserb }; 15016009Sserb struct SegmentSorter { 15116009Sserb bool operator()(const SegmentInfo *left, const SegmentInfo *right); 15216009Sserb static unsigned weight(const SegmentInfo *); 15316009Sserb }; 15416009Sserb struct TextSectionSorter { 15516009Sserb bool operator()(const SectionInfo *left, const SectionInfo *right); 15616009Sserb static unsigned weight(const SectionInfo *); 15716009Sserb }; 15816009Sserb 15916009Sserb const MachOLinkingContext &_ctx; 16016009Sserb mach_o::ArchHandler &_archHandler; 16116009Sserb llvm::BumpPtrAllocator _allocator; 16216009Sserb std::vector<SectionInfo*> _sectionInfos; 16316009Sserb std::vector<SegmentInfo*> _segmentInfos; 16416009Sserb TypeToSection _sectionMap; 16516009Sserb std::vector<SectionInfo*> _customSections; 16616009Sserb AtomToAddress _atomToAddress; 16716009Sserb DylibPathToInfo _dylibInfo; 16816009Sserb const DefinedAtom *_entryAtom; 16916009Sserb AtomToIndex _atomToSymbolIndex; 17016009Sserb std::vector<const Atom *> _machHeaderAliasAtoms; 17116009Sserb bool _hasTLVDescriptors; 17216009Sserb}; 17316009Sserb 17416009SserbUtil::~Util() { 17516009Sserb // The SectionInfo structs are BumpPtr allocated, but atomsAndOffsets needs 17616009Sserb // to be deleted. 17716009Sserb for (SectionInfo *si : _sectionInfos) { 17816009Sserb // clear() destroys vector elements, but does not deallocate. 17916009Sserb // Instead use swap() to deallocate vector buffer. 18016009Sserb std::vector<AtomInfo> empty; 18116009Sserb si->atomsAndOffsets.swap(empty); 18216009Sserb } 18316009Sserb // The SegmentInfo structs are BumpPtr allocated, but sections needs 18416009Sserb // to be deleted. 18516009Sserb for (SegmentInfo *sgi : _segmentInfos) { 18616009Sserb std::vector<SectionInfo*> empty2; 18716009Sserb sgi->sections.swap(empty2); 18816009Sserb } 18916009Sserb} 19016009Sserb 19116009SserbSectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) { 19216009Sserb StringRef segmentName; 19316009Sserb StringRef sectionName; 19416009Sserb SectionType sectionType; 19516009Sserb SectionAttr sectionAttrs; 19616009Sserb 19716009Sserb // Use same table used by when parsing .o files. 19816009Sserb relocatableSectionInfoForContentType(type, segmentName, sectionName, 19916009Sserb sectionType, sectionAttrs); 20016009Sserb // If we already have a SectionInfo with this name, re-use it. 20116009Sserb // This can happen if two ContentType map to the same mach-o section. 20216009Sserb for (auto sect : _sectionMap) { 20316009Sserb if (sect.second->sectionName.equals(sectionName) && 20416009Sserb sect.second->segmentName.equals(segmentName)) { 20516009Sserb return sect.second; 206 } 207 } 208 // Otherwise allocate new SectionInfo object. 209 auto *sect = new (_allocator) 210 SectionInfo(segmentName, sectionName, sectionType, _ctx, sectionAttrs); 211 _sectionInfos.push_back(sect); 212 _sectionMap[type] = sect; 213 return sect; 214} 215 216#define ENTRY(seg, sect, type, atomType) \ 217 {seg, sect, type, DefinedAtom::atomType } 218 219struct MachOFinalSectionFromAtomType { 220 StringRef segmentName; 221 StringRef sectionName; 222 SectionType sectionType; 223 DefinedAtom::ContentType atomType; 224}; 225 226const MachOFinalSectionFromAtomType sectsToAtomType[] = { 227 ENTRY("__TEXT", "__text", S_REGULAR, typeCode), 228 ENTRY("__TEXT", "__cstring", S_CSTRING_LITERALS, typeCString), 229 ENTRY("__TEXT", "__ustring", S_REGULAR, typeUTF16String), 230 ENTRY("__TEXT", "__const", S_REGULAR, typeConstant), 231 ENTRY("__TEXT", "__const", S_4BYTE_LITERALS, typeLiteral4), 232 ENTRY("__TEXT", "__const", S_8BYTE_LITERALS, typeLiteral8), 233 ENTRY("__TEXT", "__const", S_16BYTE_LITERALS, typeLiteral16), 234 ENTRY("__TEXT", "__stubs", S_SYMBOL_STUBS, typeStub), 235 ENTRY("__TEXT", "__stub_helper", S_REGULAR, typeStubHelper), 236 ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR, typeLSDA), 237 ENTRY("__TEXT", "__eh_frame", S_COALESCED, typeCFI), 238 ENTRY("__TEXT", "__unwind_info", S_REGULAR, typeProcessedUnwindInfo), 239 ENTRY("__DATA", "__data", S_REGULAR, typeData), 240 ENTRY("__DATA", "__const", S_REGULAR, typeConstData), 241 ENTRY("__DATA", "__cfstring", S_REGULAR, typeCFString), 242 ENTRY("__DATA", "__la_symbol_ptr", S_LAZY_SYMBOL_POINTERS, 243 typeLazyPointer), 244 ENTRY("__DATA", "__mod_init_func", S_MOD_INIT_FUNC_POINTERS, 245 typeInitializerPtr), 246 ENTRY("__DATA", "__mod_term_func", S_MOD_TERM_FUNC_POINTERS, 247 typeTerminatorPtr), 248 ENTRY("__DATA", "__got", S_NON_LAZY_SYMBOL_POINTERS, 249 typeGOT), 250 ENTRY("__DATA", "__thread_vars", S_THREAD_LOCAL_VARIABLES, 251 typeThunkTLV), 252 ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR, 253 typeTLVInitialData), 254 ENTRY("__DATA", "__thread_ptrs", S_THREAD_LOCAL_VARIABLE_POINTERS, 255 typeTLVInitializerPtr), 256 ENTRY("__DATA", "__thread_bss", S_THREAD_LOCAL_ZEROFILL, 257 typeTLVInitialZeroFill), 258 ENTRY("__DATA", "__bss", S_ZEROFILL, typeZeroFill), 259 ENTRY("__DATA", "__interposing", S_INTERPOSING, typeInterposingTuples), 260}; 261#undef ENTRY 262 263SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) { 264 for (auto &p : sectsToAtomType) { 265 if (p.atomType != atomType) 266 continue; 267 SectionAttr sectionAttrs = 0; 268 switch (atomType) { 269 case DefinedAtom::typeCode: 270 case DefinedAtom::typeStub: 271 case DefinedAtom::typeStubHelper: 272 sectionAttrs = S_ATTR_PURE_INSTRUCTIONS; 273 break; 274 case DefinedAtom::typeThunkTLV: 275 _hasTLVDescriptors = true; 276 break; 277 default: 278 break; 279 } 280 // If we already have a SectionInfo with this name, re-use it. 281 // This can happen if two ContentType map to the same mach-o section. 282 for (auto sect : _sectionMap) { 283 if (sect.second->sectionName.equals(p.sectionName) && 284 sect.second->segmentName.equals(p.segmentName)) { 285 return sect.second; 286 } 287 } 288 // Otherwise allocate new SectionInfo object. 289 auto *sect = new (_allocator) SectionInfo( 290 p.segmentName, p.sectionName, p.sectionType, _ctx, sectionAttrs); 291 _sectionInfos.push_back(sect); 292 _sectionMap[atomType] = sect; 293 return sect; 294 } 295 llvm_unreachable("content type not yet supported"); 296} 297 298SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) { 299 if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) { 300 // Section for this atom is derived from content type. 301 DefinedAtom::ContentType type = atom->contentType(); 302 auto pos = _sectionMap.find(type); 303 if ( pos != _sectionMap.end() ) 304 return pos->second; 305 bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); 306 return rMode ? getRelocatableSection(type) : getFinalSection(type); 307 } else { 308 // This atom needs to be in a custom section. 309 StringRef customName = atom->customSectionName(); 310 // Look to see if we have already allocated the needed custom section. 311 for(SectionInfo *sect : _customSections) { 312 const DefinedAtom *firstAtom = sect->atomsAndOffsets.front().atom; 313 if (firstAtom->customSectionName().equals(customName)) { 314 return sect; 315 } 316 } 317 // Not found, so need to create a new custom section. 318 size_t seperatorIndex = customName.find('/'); 319 assert(seperatorIndex != StringRef::npos); 320 StringRef segName = customName.slice(0, seperatorIndex); 321 StringRef sectName = customName.drop_front(seperatorIndex + 1); 322 auto *sect = 323 new (_allocator) SectionInfo(segName, sectName, S_REGULAR, _ctx); 324 _customSections.push_back(sect); 325 _sectionInfos.push_back(sect); 326 return sect; 327 } 328} 329 330void Util::appendAtom(SectionInfo *sect, const DefinedAtom *atom) { 331 // Figure out offset for atom in this section given alignment constraints. 332 uint64_t offset = sect->size; 333 DefinedAtom::Alignment atomAlign = atom->alignment(); 334 uint64_t align = atomAlign.value; 335 uint64_t requiredModulus = atomAlign.modulus; 336 uint64_t currentModulus = (offset % align); 337 if ( currentModulus != requiredModulus ) { 338 if ( requiredModulus > currentModulus ) 339 offset += requiredModulus-currentModulus; 340 else 341 offset += align+requiredModulus-currentModulus; 342 } 343 // Record max alignment of any atom in this section. 344 if (align > sect->alignment) 345 sect->alignment = atomAlign.value; 346 // Assign atom to this section with this offset. 347 AtomInfo ai = {atom, offset}; 348 sect->atomsAndOffsets.push_back(ai); 349 // Update section size to include this atom. 350 sect->size = offset + atom->size(); 351} 352 353void Util::assignAtomsToSections(const lld::File &atomFile) { 354 for (const DefinedAtom *atom : atomFile.defined()) { 355 if (atom->contentType() == DefinedAtom::typeMachHeader) 356 _machHeaderAliasAtoms.push_back(atom); 357 else 358 appendAtom(sectionForAtom(atom), atom); 359 } 360} 361 362SegmentInfo *Util::segmentForName(StringRef segName) { 363 for (SegmentInfo *si : _segmentInfos) { 364 if ( si->name.equals(segName) ) 365 return si; 366 } 367 auto *info = new (_allocator) SegmentInfo(segName); 368 if (segName.equals("__TEXT")) 369 info->access = VM_PROT_READ | VM_PROT_EXECUTE; 370 else if (segName.equals("__DATA")) 371 info->access = VM_PROT_READ | VM_PROT_WRITE; 372 else if (segName.equals("__PAGEZERO")) 373 info->access = 0; 374 _segmentInfos.push_back(info); 375 return info; 376} 377 378unsigned Util::SegmentSorter::weight(const SegmentInfo *seg) { 379 return llvm::StringSwitch<unsigned>(seg->name) 380 .Case("__PAGEZERO", 1) 381 .Case("__TEXT", 2) 382 .Case("__DATA", 3) 383 .Default(100); 384} 385 386bool Util::SegmentSorter::operator()(const SegmentInfo *left, 387 const SegmentInfo *right) { 388 return (weight(left) < weight(right)); 389} 390 391unsigned Util::TextSectionSorter::weight(const SectionInfo *sect) { 392 return llvm::StringSwitch<unsigned>(sect->sectionName) 393 .Case("__text", 1) 394 .Case("__stubs", 2) 395 .Case("__stub_helper", 3) 396 .Case("__const", 4) 397 .Case("__cstring", 5) 398 .Case("__unwind_info", 98) 399 .Case("__eh_frame", 99) 400 .Default(10); 401} 402 403bool Util::TextSectionSorter::operator()(const SectionInfo *left, 404 const SectionInfo *right) { 405 return (weight(left) < weight(right)); 406} 407 408void Util::organizeSections() { 409 // NOTE!: Keep this in sync with assignAddressesToSections. 410 switch (_ctx.outputMachOType()) { 411 case llvm::MachO::MH_EXECUTE: 412 // Main executables, need a zero-page segment 413 segmentForName("__PAGEZERO"); 414 // Fall into next case. 415 case llvm::MachO::MH_DYLIB: 416 case llvm::MachO::MH_BUNDLE: 417 // All dynamic code needs TEXT segment to hold the load commands. 418 segmentForName("__TEXT"); 419 break; 420 default: 421 break; 422 } 423 // Group sections into segments. 424 for (SectionInfo *si : _sectionInfos) { 425 SegmentInfo *seg = segmentForName(si->segmentName); 426 seg->sections.push_back(si); 427 } 428 // Sort segments. 429 std::sort(_segmentInfos.begin(), _segmentInfos.end(), SegmentSorter()); 430 431 // Sort sections within segments. 432 for (SegmentInfo *seg : _segmentInfos) { 433 if (seg->name.equals("__TEXT")) { 434 std::sort(seg->sections.begin(), seg->sections.end(), 435 TextSectionSorter()); 436 } 437 } 438 439 // Record final section indexes. 440 uint32_t segmentIndex = 0; 441 uint32_t sectionIndex = 1; 442 for (SegmentInfo *seg : _segmentInfos) { 443 seg->normalizedSegmentIndex = segmentIndex++; 444 for (SectionInfo *sect : seg->sections) 445 sect->finalSectionIndex = sectionIndex++; 446 } 447} 448 449void Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) { 450 seg->address = addr; 451 for (SectionInfo *sect : seg->sections) { 452 sect->address = llvm::RoundUpToAlignment(addr, sect->alignment); 453 addr = sect->address + sect->size; 454 } 455 seg->size = llvm::RoundUpToAlignment(addr - seg->address, _ctx.pageSize()); 456} 457 458// __TEXT segment lays out backwards so padding is at front after load commands. 459void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg, 460 uint64_t &addr) { 461 seg->address = addr; 462 // Walks sections starting at end to calculate padding for start. 463 int64_t taddr = 0; 464 for (auto it = seg->sections.rbegin(); it != seg->sections.rend(); ++it) { 465 SectionInfo *sect = *it; 466 taddr -= sect->size; 467 taddr = taddr & (0 - sect->alignment); 468 } 469 int64_t padding = taddr - hlcSize; 470 while (padding < 0) 471 padding += _ctx.pageSize(); 472 // Start assigning section address starting at padded offset. 473 addr += (padding + hlcSize); 474 for (SectionInfo *sect : seg->sections) { 475 sect->address = llvm::RoundUpToAlignment(addr, sect->alignment); 476 addr = sect->address + sect->size; 477 } 478 seg->size = llvm::RoundUpToAlignment(addr - seg->address, _ctx.pageSize()); 479} 480 481void Util::assignAddressesToSections(const NormalizedFile &file) { 482 // NOTE!: Keep this in sync with organizeSections. 483 size_t hlcSize = headerAndLoadCommandsSize(file); 484 uint64_t address = 0; 485 for (SegmentInfo *seg : _segmentInfos) { 486 if (seg->name.equals("__PAGEZERO")) { 487 seg->size = _ctx.pageZeroSize(); 488 address += seg->size; 489 } 490 else if (seg->name.equals("__TEXT")) { 491 // _ctx.baseAddress() == 0 implies it was either unspecified or 492 // pageZeroSize is also 0. In either case resetting address is safe. 493 address = _ctx.baseAddress() ? _ctx.baseAddress() : address; 494 layoutSectionsInTextSegment(hlcSize, seg, address); 495 } else 496 layoutSectionsInSegment(seg, address); 497 498 address = llvm::RoundUpToAlignment(address, _ctx.pageSize()); 499 } 500 DEBUG_WITH_TYPE("WriterMachO-norm", 501 llvm::dbgs() << "assignAddressesToSections()\n"; 502 for (SegmentInfo *sgi : _segmentInfos) { 503 llvm::dbgs() << " address=" << llvm::format("0x%08llX", sgi->address) 504 << ", size=" << llvm::format("0x%08llX", sgi->size) 505 << ", segment-name='" << sgi->name 506 << "'\n"; 507 for (SectionInfo *si : sgi->sections) { 508 llvm::dbgs()<< " addr=" << llvm::format("0x%08llX", si->address) 509 << ", size=" << llvm::format("0x%08llX", si->size) 510 << ", section-name='" << si->sectionName 511 << "\n"; 512 } 513 } 514 ); 515} 516 517void Util::copySegmentInfo(NormalizedFile &file) { 518 for (SegmentInfo *sgi : _segmentInfos) { 519 Segment seg; 520 seg.name = sgi->name; 521 seg.address = sgi->address; 522 seg.size = sgi->size; 523 seg.access = sgi->access; 524 file.segments.push_back(seg); 525 } 526} 527 528void Util::appendSection(SectionInfo *si, NormalizedFile &file) { 529 // Add new empty section to end of file.sections. 530 Section temp; 531 file.sections.push_back(std::move(temp)); 532 Section* normSect = &file.sections.back(); 533 // Copy fields to normalized section. 534 normSect->segmentName = si->segmentName; 535 normSect->sectionName = si->sectionName; 536 normSect->type = si->type; 537 normSect->attributes = si->attributes; 538 normSect->address = si->address; 539 normSect->alignment = si->alignment; 540 // Record where normalized section is. 541 si->normalizedSectionIndex = file.sections.size()-1; 542} 543 544void Util::copySectionContent(NormalizedFile &file) { 545 const bool r = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); 546 547 // Utility function for ArchHandler to find address of atom in output file. 548 auto addrForAtom = [&] (const Atom &atom) -> uint64_t { 549 auto pos = _atomToAddress.find(&atom); 550 assert(pos != _atomToAddress.end()); 551 return pos->second; 552 }; 553 554 auto sectionAddrForAtom = [&] (const Atom &atom) -> uint64_t { 555 for (const SectionInfo *sectInfo : _sectionInfos) 556 for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets) 557 if (atomInfo.atom == &atom) 558 return sectInfo->address; 559 llvm_unreachable("atom not assigned to section"); 560 }; 561 562 for (SectionInfo *si : _sectionInfos) { 563 Section *normSect = &file.sections[si->normalizedSectionIndex]; 564 if (isZeroFillSection(si->type)) { 565 const uint8_t *empty = nullptr; 566 normSect->content = llvm::makeArrayRef(empty, si->size); 567 continue; 568 } 569 // Copy content from atoms to content buffer for section. 570 uint8_t *sectionContent = file.ownedAllocations.Allocate<uint8_t>(si->size); 571 normSect->content = llvm::makeArrayRef(sectionContent, si->size); 572 for (AtomInfo &ai : si->atomsAndOffsets) { 573 uint8_t *atomContent = reinterpret_cast<uint8_t*> 574 (§ionContent[ai.offsetInSection]); 575 _archHandler.generateAtomContent(*ai.atom, r, addrForAtom, 576 sectionAddrForAtom, _ctx.baseAddress(), 577 atomContent); 578 } 579 } 580} 581 582void Util::copySectionInfo(NormalizedFile &file) { 583 file.sections.reserve(_sectionInfos.size()); 584 // Write sections grouped by segment. 585 for (SegmentInfo *sgi : _segmentInfos) { 586 for (SectionInfo *si : sgi->sections) { 587 appendSection(si, file); 588 } 589 } 590} 591 592void Util::updateSectionInfo(NormalizedFile &file) { 593 file.sections.reserve(_sectionInfos.size()); 594 // sections grouped by segment. 595 for (SegmentInfo *sgi : _segmentInfos) { 596 Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex]; 597 normSeg->address = sgi->address; 598 normSeg->size = sgi->size; 599 for (SectionInfo *si : sgi->sections) { 600 Section *normSect = &file.sections[si->normalizedSectionIndex]; 601 normSect->address = si->address; 602 } 603 } 604} 605 606void Util::copyEntryPointAddress(NormalizedFile &nFile) { 607 if (_ctx.outputTypeHasEntry()) { 608 if (_archHandler.isThumbFunction(*_entryAtom)) 609 nFile.entryAddress = (_atomToAddress[_entryAtom] | 1); 610 else 611 nFile.entryAddress = _atomToAddress[_entryAtom]; 612 } 613} 614 615void Util::buildAtomToAddressMap() { 616 DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() 617 << "assign atom addresses:\n"); 618 const bool lookForEntry = _ctx.outputTypeHasEntry(); 619 for (SectionInfo *sect : _sectionInfos) { 620 for (const AtomInfo &info : sect->atomsAndOffsets) { 621 _atomToAddress[info.atom] = sect->address + info.offsetInSection; 622 if (lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) && 623 (info.atom->size() != 0) && 624 info.atom->name() == _ctx.entrySymbolName()) { 625 _entryAtom = info.atom; 626 } 627 DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() 628 << " address=" 629 << llvm::format("0x%016X", _atomToAddress[info.atom]) 630 << llvm::format(" 0x%09lX", info.atom) 631 << ", file=#" 632 << info.atom->file().ordinal() 633 << ", atom=#" 634 << info.atom->ordinal() 635 << ", name=" 636 << info.atom->name() 637 << ", type=" 638 << info.atom->contentType() 639 << "\n"); 640 } 641 } 642 DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() 643 << "assign header alias atom addresses:\n"); 644 for (const Atom *atom : _machHeaderAliasAtoms) { 645 _atomToAddress[atom] = _ctx.baseAddress(); 646#ifndef NDEBUG 647 if (auto *definedAtom = dyn_cast<DefinedAtom>(atom)) { 648 DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() 649 << " address=" 650 << llvm::format("0x%016X", _atomToAddress[atom]) 651 << llvm::format(" 0x%09lX", atom) 652 << ", file=#" 653 << definedAtom->file().ordinal() 654 << ", atom=#" 655 << definedAtom->ordinal() 656 << ", name=" 657 << definedAtom->name() 658 << ", type=" 659 << definedAtom->contentType() 660 << "\n"); 661 } else { 662 DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs() 663 << " address=" 664 << llvm::format("0x%016X", _atomToAddress[atom]) 665 << " atom=" << atom 666 << " name=" << atom->name() << "\n"); 667 } 668#endif 669 } 670} 671 672uint16_t Util::descBits(const DefinedAtom* atom) { 673 uint16_t desc = 0; 674 switch (atom->merge()) { 675 case lld::DefinedAtom::mergeNo: 676 case lld::DefinedAtom::mergeAsTentative: 677 break; 678 case lld::DefinedAtom::mergeAsWeak: 679 case lld::DefinedAtom::mergeAsWeakAndAddressUsed: 680 desc |= N_WEAK_DEF; 681 break; 682 case lld::DefinedAtom::mergeSameNameAndSize: 683 case lld::DefinedAtom::mergeByLargestSection: 684 case lld::DefinedAtom::mergeByContent: 685 llvm_unreachable("Unsupported DefinedAtom::merge()"); 686 break; 687 } 688 if (atom->contentType() == lld::DefinedAtom::typeResolver) 689 desc |= N_SYMBOL_RESOLVER; 690 if (_archHandler.isThumbFunction(*atom)) 691 desc |= N_ARM_THUMB_DEF; 692 if (atom->deadStrip() == DefinedAtom::deadStripNever) { 693 if ((atom->contentType() != DefinedAtom::typeInitializerPtr) 694 && (atom->contentType() != DefinedAtom::typeTerminatorPtr)) 695 desc |= N_NO_DEAD_STRIP; 696 } 697 return desc; 698} 699 700bool Util::AtomSorter::operator()(const AtomAndIndex &left, 701 const AtomAndIndex &right) { 702 return (left.atom->name().compare(right.atom->name()) < 0); 703} 704 705std::error_code Util::getSymbolTableRegion(const DefinedAtom* atom, 706 bool &inGlobalsRegion, 707 SymbolScope &scope) { 708 bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); 709 switch (atom->scope()) { 710 case Atom::scopeTranslationUnit: 711 scope = 0; 712 inGlobalsRegion = false; 713 return std::error_code(); 714 case Atom::scopeLinkageUnit: 715 if ((_ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) && 716 _ctx.exportSymbolNamed(atom->name())) { 717 return make_dynamic_error_code(Twine("cannot export hidden symbol ") 718 + atom->name()); 719 } 720 if (rMode) { 721 if (_ctx.keepPrivateExterns()) { 722 // -keep_private_externs means keep in globals region as N_PEXT. 723 scope = N_PEXT | N_EXT; 724 inGlobalsRegion = true; 725 return std::error_code(); 726 } 727 } 728 // scopeLinkageUnit symbols are no longer global once linked. 729 scope = N_PEXT; 730 inGlobalsRegion = false; 731 return std::error_code(); 732 case Atom::scopeGlobal: 733 if (_ctx.exportRestrictMode()) { 734 if (_ctx.exportSymbolNamed(atom->name())) { 735 scope = N_EXT; 736 inGlobalsRegion = true; 737 return std::error_code(); 738 } else { 739 scope = N_PEXT; 740 inGlobalsRegion = false; 741 return std::error_code(); 742 } 743 } else { 744 scope = N_EXT; 745 inGlobalsRegion = true; 746 return std::error_code(); 747 } 748 break; 749 } 750 llvm_unreachable("atom->scope() unknown enum value"); 751} 752 753std::error_code Util::addSymbols(const lld::File &atomFile, 754 NormalizedFile &file) { 755 bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT); 756 // Mach-O symbol table has three regions: locals, globals, undefs. 757 758 // Add all local (non-global) symbols in address order 759 std::vector<AtomAndIndex> globals; 760 globals.reserve(512); 761 for (SectionInfo *sect : _sectionInfos) { 762 for (const AtomInfo &info : sect->atomsAndOffsets) { 763 const DefinedAtom *atom = info.atom; 764 if (!atom->name().empty()) { 765 SymbolScope symbolScope; 766 bool inGlobalsRegion; 767 if (auto ec = getSymbolTableRegion(atom, inGlobalsRegion, symbolScope)){ 768 return ec; 769 } 770 if (inGlobalsRegion) { 771 AtomAndIndex ai = { atom, sect->finalSectionIndex, symbolScope }; 772 globals.push_back(ai); 773 } else { 774 Symbol sym; 775 sym.name = atom->name(); 776 sym.type = N_SECT; 777 sym.scope = symbolScope; 778 sym.sect = sect->finalSectionIndex; 779 sym.desc = descBits(atom); 780 sym.value = _atomToAddress[atom]; 781 _atomToSymbolIndex[atom] = file.localSymbols.size(); 782 file.localSymbols.push_back(sym); 783 } 784 } else if (rMode && _archHandler.needsLocalSymbolInRelocatableFile(atom)){ 785 // Create 'Lxxx' labels for anonymous atoms if archHandler says so. 786 static unsigned tempNum = 1; 787 char tmpName[16]; 788 sprintf(tmpName, "L%04u", tempNum++); 789 StringRef tempRef(tmpName); 790 Symbol sym; 791 sym.name = tempRef.copy(file.ownedAllocations); 792 sym.type = N_SECT; 793 sym.scope = 0; 794 sym.sect = sect->finalSectionIndex; 795 sym.desc = 0; 796 sym.value = _atomToAddress[atom]; 797 _atomToSymbolIndex[atom] = file.localSymbols.size(); 798 file.localSymbols.push_back(sym); 799 } 800 } 801 } 802 803 // Sort global symbol alphabetically, then add to symbol table. 804 std::sort(globals.begin(), globals.end(), AtomSorter()); 805 const uint32_t globalStartIndex = file.localSymbols.size(); 806 for (AtomAndIndex &ai : globals) { 807 Symbol sym; 808 sym.name = ai.atom->name(); 809 sym.type = N_SECT; 810 sym.scope = ai.scope; 811 sym.sect = ai.index; 812 sym.desc = descBits(static_cast<const DefinedAtom*>(ai.atom)); 813 sym.value = _atomToAddress[ai.atom]; 814 _atomToSymbolIndex[ai.atom] = globalStartIndex + file.globalSymbols.size(); 815 file.globalSymbols.push_back(sym); 816 } 817 818 // Sort undefined symbol alphabetically, then add to symbol table. 819 std::vector<AtomAndIndex> undefs; 820 undefs.reserve(128); 821 for (const UndefinedAtom *atom : atomFile.undefined()) { 822 AtomAndIndex ai = { atom, 0, N_EXT }; 823 undefs.push_back(ai); 824 } 825 for (const SharedLibraryAtom *atom : atomFile.sharedLibrary()) { 826 AtomAndIndex ai = { atom, 0, N_EXT }; 827 undefs.push_back(ai); 828 } 829 std::sort(undefs.begin(), undefs.end(), AtomSorter()); 830 const uint32_t start = file.globalSymbols.size() + file.localSymbols.size(); 831 for (AtomAndIndex &ai : undefs) { 832 Symbol sym; 833 uint16_t desc = 0; 834 if (!rMode) { 835 uint8_t ordinal = 0; 836 if (!_ctx.useFlatNamespace()) 837 ordinal = dylibOrdinal(dyn_cast<SharedLibraryAtom>(ai.atom)); 838 llvm::MachO::SET_LIBRARY_ORDINAL(desc, ordinal); 839 } 840 sym.name = ai.atom->name(); 841 sym.type = N_UNDF; 842 sym.scope = ai.scope; 843 sym.sect = 0; 844 sym.desc = desc; 845 sym.value = 0; 846 _atomToSymbolIndex[ai.atom] = file.undefinedSymbols.size() + start; 847 file.undefinedSymbols.push_back(sym); 848 } 849 850 return std::error_code(); 851} 852 853const Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) { 854 for (const Reference *ref : *lpAtom) { 855 if (_archHandler.isLazyPointer(*ref)) { 856 return ref->target(); 857 } 858 } 859 return nullptr; 860} 861 862const Atom *Util::targetOfStub(const DefinedAtom *stubAtom) { 863 for (const Reference *ref : *stubAtom) { 864 if (const Atom *ta = ref->target()) { 865 if (const DefinedAtom *lpAtom = dyn_cast<DefinedAtom>(ta)) { 866 const Atom *target = targetOfLazyPointer(lpAtom); 867 if (target) 868 return target; 869 } 870 } 871 } 872 return nullptr; 873} 874 875void Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) { 876 for (SectionInfo *si : _sectionInfos) { 877 Section &normSect = file.sections[si->normalizedSectionIndex]; 878 switch (si->type) { 879 case llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS: 880 for (const AtomInfo &info : si->atomsAndOffsets) { 881 bool foundTarget = false; 882 for (const Reference *ref : *info.atom) { 883 const Atom *target = ref->target(); 884 if (target) { 885 if (isa<const SharedLibraryAtom>(target)) { 886 uint32_t index = _atomToSymbolIndex[target]; 887 normSect.indirectSymbols.push_back(index); 888 foundTarget = true; 889 } else { 890 normSect.indirectSymbols.push_back( 891 llvm::MachO::INDIRECT_SYMBOL_LOCAL); 892 } 893 } 894 } 895 if (!foundTarget) { 896 normSect.indirectSymbols.push_back( 897 llvm::MachO::INDIRECT_SYMBOL_ABS); 898 } 899 } 900 break; 901 case llvm::MachO::S_LAZY_SYMBOL_POINTERS: 902 for (const AtomInfo &info : si->atomsAndOffsets) { 903 const Atom *target = targetOfLazyPointer(info.atom); 904 if (target) { 905 uint32_t index = _atomToSymbolIndex[target]; 906 normSect.indirectSymbols.push_back(index); 907 } 908 } 909 break; 910 case llvm::MachO::S_SYMBOL_STUBS: 911 for (const AtomInfo &info : si->atomsAndOffsets) { 912 const Atom *target = targetOfStub(info.atom); 913 if (target) { 914 uint32_t index = _atomToSymbolIndex[target]; 915 normSect.indirectSymbols.push_back(index); 916 } 917 } 918 break; 919 default: 920 break; 921 } 922 } 923} 924 925void Util::addDependentDylibs(const lld::File &atomFile,NormalizedFile &nFile) { 926 // Scan all imported symbols and build up list of dylibs they are from. 927 int ordinal = 1; 928 for (const SharedLibraryAtom *slAtom : atomFile.sharedLibrary()) { 929 StringRef loadPath = slAtom->loadName(); 930 DylibPathToInfo::iterator pos = _dylibInfo.find(loadPath); 931 if (pos == _dylibInfo.end()) { 932 DylibInfo info; 933 bool flatNamespaceAtom = &slAtom->file() == _ctx.flatNamespaceFile(); 934 935 // If we're in -flat_namespace mode (or this atom came from the flat 936 // namespace file under -undefined dynamic_lookup) then use the flat 937 // lookup ordinal. 938 if (flatNamespaceAtom || _ctx.useFlatNamespace()) 939 info.ordinal = BIND_SPECIAL_DYLIB_FLAT_LOOKUP; 940 else 941 info.ordinal = ordinal++; 942 info.hasWeak = slAtom->canBeNullAtRuntime(); 943 info.hasNonWeak = !info.hasWeak; 944 _dylibInfo[loadPath] = info; 945 946 // Unless this was a flat_namespace atom, record the source dylib. 947 if (!flatNamespaceAtom) { 948 DependentDylib depInfo; 949 depInfo.path = loadPath; 950 depInfo.kind = llvm::MachO::LC_LOAD_DYLIB; 951 depInfo.currentVersion = _ctx.dylibCurrentVersion(loadPath); 952 depInfo.compatVersion = _ctx.dylibCompatVersion(loadPath); 953 nFile.dependentDylibs.push_back(depInfo); 954 } 955 } else { 956 if ( slAtom->canBeNullAtRuntime() ) 957 pos->second.hasWeak = true; 958 else 959 pos->second.hasNonWeak = true; 960 } 961 } 962 // Automatically weak link dylib in which all symbols are weak (canBeNull). 963 for (DependentDylib &dep : nFile.dependentDylibs) { 964 DylibInfo &info = _dylibInfo[dep.path]; 965 if (info.hasWeak && !info.hasNonWeak) 966 dep.kind = llvm::MachO::LC_LOAD_WEAK_DYLIB; 967 else if (_ctx.isUpwardDylib(dep.path)) 968 dep.kind = llvm::MachO::LC_LOAD_UPWARD_DYLIB; 969 } 970} 971 972int Util::dylibOrdinal(const SharedLibraryAtom *sa) { 973 return _dylibInfo[sa->loadName()].ordinal; 974} 975 976void Util::segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex, 977 uint64_t &segmentStartAddr) { 978 segmentIndex = 0; 979 for (const SegmentInfo *seg : _segmentInfos) { 980 if ((seg->address <= sect->address) 981 && (seg->address+seg->size >= sect->address+sect->size)) { 982 segmentStartAddr = seg->address; 983 return; 984 } 985 ++segmentIndex; 986 } 987 llvm_unreachable("section not in any segment"); 988} 989 990uint32_t Util::sectionIndexForAtom(const Atom *atom) { 991 uint64_t address = _atomToAddress[atom]; 992 for (const SectionInfo *si : _sectionInfos) { 993 if ((si->address <= address) && (address < si->address+si->size)) 994 return si->finalSectionIndex; 995 } 996 llvm_unreachable("atom not in any section"); 997} 998 999void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) { 1000 if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT) 1001 return; 1002 1003 // Utility function for ArchHandler to find symbol index for an atom. 1004 auto symIndexForAtom = [&] (const Atom &atom) -> uint32_t { 1005 auto pos = _atomToSymbolIndex.find(&atom); 1006 assert(pos != _atomToSymbolIndex.end()); 1007 return pos->second; 1008 }; 1009 1010 // Utility function for ArchHandler to find section index for an atom. 1011 auto sectIndexForAtom = [&] (const Atom &atom) -> uint32_t { 1012 return sectionIndexForAtom(&atom); 1013 }; 1014 1015 // Utility function for ArchHandler to find address of atom in output file. 1016 auto addressForAtom = [&] (const Atom &atom) -> uint64_t { 1017 auto pos = _atomToAddress.find(&atom); 1018 assert(pos != _atomToAddress.end()); 1019 return pos->second; 1020 }; 1021 1022 for (SectionInfo *si : _sectionInfos) { 1023 Section &normSect = file.sections[si->normalizedSectionIndex]; 1024 for (const AtomInfo &info : si->atomsAndOffsets) { 1025 const DefinedAtom *atom = info.atom; 1026 for (const Reference *ref : *atom) { 1027 _archHandler.appendSectionRelocations(*atom, info.offsetInSection, *ref, 1028 symIndexForAtom, 1029 sectIndexForAtom, 1030 addressForAtom, 1031 normSect.relocations); 1032 } 1033 } 1034 } 1035} 1036 1037void Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) { 1038 for (SectionInfo *si : _sectionInfos) { 1039 for (const AtomInfo &info : si->atomsAndOffsets) { 1040 // Atoms that contain data-in-code have "transition" references 1041 // which mark a point where the embedded data starts of ends. 1042 // This needs to be converted to the mach-o format which is an array 1043 // of data-in-code ranges. 1044 uint32_t startOffset = 0; 1045 DataRegionType mode = DataRegionType(0); 1046 for (const Reference *ref : *info.atom) { 1047 if (ref->kindNamespace() != Reference::KindNamespace::mach_o) 1048 continue; 1049 if (_archHandler.isDataInCodeTransition(ref->kindValue())) { 1050 DataRegionType nextMode = (DataRegionType)ref->addend(); 1051 if (mode != nextMode) { 1052 if (mode != 0) { 1053 // Found end data range, so make range entry. 1054 DataInCode entry; 1055 entry.offset = si->address + info.offsetInSection + startOffset; 1056 entry.length = ref->offsetInAtom() - startOffset; 1057 entry.kind = mode; 1058 file.dataInCode.push_back(entry); 1059 } 1060 } 1061 mode = nextMode; 1062 startOffset = ref->offsetInAtom(); 1063 } 1064 } 1065 if (mode != 0) { 1066 // Function ends with data (no end transition). 1067 DataInCode entry; 1068 entry.offset = si->address + info.offsetInSection + startOffset; 1069 entry.length = info.atom->size() - startOffset; 1070 entry.kind = mode; 1071 file.dataInCode.push_back(entry); 1072 } 1073 } 1074 } 1075} 1076 1077void Util::addRebaseAndBindingInfo(const lld::File &atomFile, 1078 NormalizedFile &nFile) { 1079 if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT) 1080 return; 1081 1082 uint8_t segmentIndex; 1083 uint64_t segmentStartAddr; 1084 for (SectionInfo *sect : _sectionInfos) { 1085 segIndexForSection(sect, segmentIndex, segmentStartAddr); 1086 for (const AtomInfo &info : sect->atomsAndOffsets) { 1087 const DefinedAtom *atom = info.atom; 1088 for (const Reference *ref : *atom) { 1089 uint64_t segmentOffset = _atomToAddress[atom] + ref->offsetInAtom() 1090 - segmentStartAddr; 1091 const Atom* targ = ref->target(); 1092 if (_archHandler.isPointer(*ref)) { 1093 // A pointer to a DefinedAtom requires rebasing. 1094 if (isa<DefinedAtom>(targ)) { 1095 RebaseLocation rebase; 1096 rebase.segIndex = segmentIndex; 1097 rebase.segOffset = segmentOffset; 1098 rebase.kind = llvm::MachO::REBASE_TYPE_POINTER; 1099 nFile.rebasingInfo.push_back(rebase); 1100 } 1101 // A pointer to an SharedLibraryAtom requires binding. 1102 if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) { 1103 BindLocation bind; 1104 bind.segIndex = segmentIndex; 1105 bind.segOffset = segmentOffset; 1106 bind.kind = llvm::MachO::BIND_TYPE_POINTER; 1107 bind.canBeNull = sa->canBeNullAtRuntime(); 1108 bind.ordinal = dylibOrdinal(sa); 1109 bind.symbolName = targ->name(); 1110 bind.addend = ref->addend(); 1111 nFile.bindingInfo.push_back(bind); 1112 } 1113 } 1114 else if (_archHandler.isLazyPointer(*ref)) { 1115 BindLocation bind; 1116 if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) { 1117 bind.ordinal = dylibOrdinal(sa); 1118 } else { 1119 bind.ordinal = llvm::MachO::BIND_SPECIAL_DYLIB_SELF; 1120 } 1121 bind.segIndex = segmentIndex; 1122 bind.segOffset = segmentOffset; 1123 bind.kind = llvm::MachO::BIND_TYPE_POINTER; 1124 bind.canBeNull = false; //sa->canBeNullAtRuntime(); 1125 bind.symbolName = targ->name(); 1126 bind.addend = ref->addend(); 1127 nFile.lazyBindingInfo.push_back(bind); 1128 } 1129 } 1130 } 1131 } 1132} 1133 1134void Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) { 1135 if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT) 1136 return; 1137 1138 for (SectionInfo *sect : _sectionInfos) { 1139 for (const AtomInfo &info : sect->atomsAndOffsets) { 1140 const DefinedAtom *atom = info.atom; 1141 if (atom->scope() != Atom::scopeGlobal) 1142 continue; 1143 if (_ctx.exportRestrictMode()) { 1144 if (!_ctx.exportSymbolNamed(atom->name())) 1145 continue; 1146 } 1147 Export exprt; 1148 exprt.name = atom->name(); 1149 exprt.offset = _atomToAddress[atom] - _ctx.baseAddress(); 1150 exprt.kind = EXPORT_SYMBOL_FLAGS_KIND_REGULAR; 1151 if (atom->merge() == DefinedAtom::mergeAsWeak) 1152 exprt.flags = EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; 1153 else 1154 exprt.flags = 0; 1155 exprt.otherOffset = 0; 1156 exprt.otherName = StringRef(); 1157 nFile.exportInfo.push_back(exprt); 1158 } 1159 } 1160} 1161 1162uint32_t Util::fileFlags() { 1163 // FIXME: these need to determined at runtime. 1164 if (_ctx.outputMachOType() == MH_OBJECT) { 1165 return MH_SUBSECTIONS_VIA_SYMBOLS; 1166 } else { 1167 uint32_t flags = MH_DYLDLINK; 1168 if (!_ctx.useFlatNamespace()) 1169 flags |= MH_TWOLEVEL | MH_NOUNDEFS; 1170 if ((_ctx.outputMachOType() == MH_EXECUTE) && _ctx.PIE()) 1171 flags |= MH_PIE; 1172 if (_hasTLVDescriptors) 1173 flags |= (MH_PIE | MH_HAS_TLV_DESCRIPTORS); 1174 return flags; 1175 } 1176} 1177 1178} // end anonymous namespace 1179 1180namespace lld { 1181namespace mach_o { 1182namespace normalized { 1183 1184/// Convert a set of Atoms into a normalized mach-o file. 1185ErrorOr<std::unique_ptr<NormalizedFile>> 1186normalizedFromAtoms(const lld::File &atomFile, 1187 const MachOLinkingContext &context) { 1188 // The util object buffers info until the normalized file can be made. 1189 Util util(context); 1190 util.assignAtomsToSections(atomFile); 1191 util.organizeSections(); 1192 1193 std::unique_ptr<NormalizedFile> f(new NormalizedFile()); 1194 NormalizedFile &normFile = *f.get(); 1195 normFile.arch = context.arch(); 1196 normFile.fileType = context.outputMachOType(); 1197 normFile.flags = util.fileFlags(); 1198 normFile.stackSize = context.stackSize(); 1199 normFile.installName = context.installName(); 1200 normFile.currentVersion = context.currentVersion(); 1201 normFile.compatVersion = context.compatibilityVersion(); 1202 normFile.pageSize = context.pageSize(); 1203 normFile.rpaths = context.rpaths(); 1204 util.addDependentDylibs(atomFile, normFile); 1205 util.copySegmentInfo(normFile); 1206 util.copySectionInfo(normFile); 1207 util.assignAddressesToSections(normFile); 1208 util.buildAtomToAddressMap(); 1209 util.updateSectionInfo(normFile); 1210 util.copySectionContent(normFile); 1211 if (auto ec = util.addSymbols(atomFile, normFile)) { 1212 return ec; 1213 } 1214 util.addIndirectSymbols(atomFile, normFile); 1215 util.addRebaseAndBindingInfo(atomFile, normFile); 1216 util.addExportInfo(atomFile, normFile); 1217 util.addSectionRelocs(atomFile, normFile); 1218 util.buildDataInCodeArray(atomFile, normFile); 1219 util.copyEntryPointAddress(normFile); 1220 1221 return std::move(f); 1222} 1223 1224} // namespace normalized 1225} // namespace mach_o 1226} // namespace lld 1227