1 //===- lib/MC/MachObjectWriter.cpp - Mach-O File Writer -------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/MC/MCMachObjectWriter.h" 11 #include "llvm/ADT/OwningPtr.h" 12 #include "llvm/ADT/StringMap.h" 13 #include "llvm/ADT/Twine.h" 14 #include "llvm/MC/MCAssembler.h" 15 #include "llvm/MC/MCAsmLayout.h" 16 #include "llvm/MC/MCExpr.h" 17 #include "llvm/MC/MCObjectWriter.h" 18 #include "llvm/MC/MCSectionMachO.h" 19 #include "llvm/MC/MCSymbol.h" 20 #include "llvm/MC/MCMachOSymbolFlags.h" 21 #include "llvm/MC/MCValue.h" 22 #include "llvm/Object/MachOFormat.h" 23 #include "llvm/Support/ErrorHandling.h" 24 #include "llvm/Target/TargetAsmBackend.h" 25 26 #include <vector> 27 using namespace llvm; 28 using namespace llvm::object; 29 30 bool MachObjectWriter:: 31 doesSymbolRequireExternRelocation(const MCSymbolData *SD) { 32 // Undefined symbols are always extern. 33 if (SD->Symbol->isUndefined()) 34 return true; 35 36 // References to weak definitions require external relocation entries; the 37 // definition may not always be the one in the same object file. 38 if (SD->getFlags() & SF_WeakDefinition) 39 return true; 40 41 // Otherwise, we can use an internal relocation. 42 return false; 43 } 44 45 bool MachObjectWriter:: 46 MachSymbolData::operator<(const MachSymbolData &RHS) const { 47 return SymbolData->getSymbol().getName() < 48 RHS.SymbolData->getSymbol().getName(); 49 } 50 51 bool MachObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { 52 const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo( 53 (MCFixupKind) Kind); 54 55 return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; 56 } 57 58 uint64_t MachObjectWriter::getFragmentAddress(const MCFragment *Fragment, 59 const MCAsmLayout &Layout) const { 60 return getSectionAddress(Fragment->getParent()) + 61 Layout.getFragmentOffset(Fragment); 62 } 63 64 uint64_t MachObjectWriter::getSymbolAddress(const MCSymbolData* SD, 65 const MCAsmLayout &Layout) const { 66 const MCSymbol &S = SD->getSymbol(); 67 68 // If this is a variable, then recursively evaluate now. 69 if (S.isVariable()) { 70 MCValue Target; 71 if (!S.getVariableValue()->EvaluateAsRelocatable(Target, Layout)) 72 report_fatal_error("unable to evaluate offset for variable '" + 73 S.getName() + "'"); 74 75 // Verify that any used symbols are defined. 76 if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined()) 77 report_fatal_error("unable to evaluate offset to undefined symbol '" + 78 Target.getSymA()->getSymbol().getName() + "'"); 79 if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined()) 80 report_fatal_error("unable to evaluate offset to undefined symbol '" + 81 Target.getSymB()->getSymbol().getName() + "'"); 82 83 uint64_t Address = Target.getConstant(); 84 if (Target.getSymA()) 85 Address += getSymbolAddress(&Layout.getAssembler().getSymbolData( 86 Target.getSymA()->getSymbol()), Layout); 87 if (Target.getSymB()) 88 Address += getSymbolAddress(&Layout.getAssembler().getSymbolData( 89 Target.getSymB()->getSymbol()), Layout); 90 return Address; 91 } 92 93 return getSectionAddress(SD->getFragment()->getParent()) + 94 Layout.getSymbolOffset(SD); 95 } 96 97 uint64_t MachObjectWriter::getPaddingSize(const MCSectionData *SD, 98 const MCAsmLayout &Layout) const { 99 uint64_t EndAddr = getSectionAddress(SD) + Layout.getSectionAddressSize(SD); 100 unsigned Next = SD->getLayoutOrder() + 1; 101 if (Next >= Layout.getSectionOrder().size()) 102 return 0; 103 104 const MCSectionData &NextSD = *Layout.getSectionOrder()[Next]; 105 if (NextSD.getSection().isVirtualSection()) 106 return 0; 107 return OffsetToAlignment(EndAddr, NextSD.getAlignment()); 108 } 109 110 void MachObjectWriter::WriteHeader(unsigned NumLoadCommands, 111 unsigned LoadCommandsSize, 112 bool SubsectionsViaSymbols) { 113 uint32_t Flags = 0; 114 115 if (SubsectionsViaSymbols) 116 Flags |= macho::HF_SubsectionsViaSymbols; 117 118 // struct mach_header (28 bytes) or 119 // struct mach_header_64 (32 bytes) 120 121 uint64_t Start = OS.tell(); 122 (void) Start; 123 124 Write32(is64Bit() ? macho::HM_Object64 : macho::HM_Object32); 125 126 Write32(TargetObjectWriter->getCPUType()); 127 Write32(TargetObjectWriter->getCPUSubtype()); 128 129 Write32(macho::HFT_Object); 130 Write32(NumLoadCommands); 131 Write32(LoadCommandsSize); 132 Write32(Flags); 133 if (is64Bit()) 134 Write32(0); // reserved 135 136 assert(OS.tell() - Start == 137 (is64Bit() ? macho::Header64Size : macho::Header32Size)); 138 } 139 140 /// WriteSegmentLoadCommand - Write a segment load command. 141 /// 142 /// \arg NumSections - The number of sections in this segment. 143 /// \arg SectionDataSize - The total size of the sections. 144 void MachObjectWriter::WriteSegmentLoadCommand(unsigned NumSections, 145 uint64_t VMSize, 146 uint64_t SectionDataStartOffset, 147 uint64_t SectionDataSize) { 148 // struct segment_command (56 bytes) or 149 // struct segment_command_64 (72 bytes) 150 151 uint64_t Start = OS.tell(); 152 (void) Start; 153 154 unsigned SegmentLoadCommandSize = 155 is64Bit() ? macho::SegmentLoadCommand64Size: 156 macho::SegmentLoadCommand32Size; 157 Write32(is64Bit() ? macho::LCT_Segment64 : macho::LCT_Segment); 158 Write32(SegmentLoadCommandSize + 159 NumSections * (is64Bit() ? macho::Section64Size : 160 macho::Section32Size)); 161 162 WriteBytes("", 16); 163 if (is64Bit()) { 164 Write64(0); // vmaddr 165 Write64(VMSize); // vmsize 166 Write64(SectionDataStartOffset); // file offset 167 Write64(SectionDataSize); // file size 168 } else { 169 Write32(0); // vmaddr 170 Write32(VMSize); // vmsize 171 Write32(SectionDataStartOffset); // file offset 172 Write32(SectionDataSize); // file size 173 } 174 Write32(0x7); // maxprot 175 Write32(0x7); // initprot 176 Write32(NumSections); 177 Write32(0); // flags 178 179 assert(OS.tell() - Start == SegmentLoadCommandSize); 180 } 181 182 void MachObjectWriter::WriteSection(const MCAssembler &Asm, 183 const MCAsmLayout &Layout, 184 const MCSectionData &SD, 185 uint64_t FileOffset, 186 uint64_t RelocationsStart, 187 unsigned NumRelocations) { 188 uint64_t SectionSize = Layout.getSectionAddressSize(&SD); 189 190 // The offset is unused for virtual sections. 191 if (SD.getSection().isVirtualSection()) { 192 assert(Layout.getSectionFileSize(&SD) == 0 && "Invalid file size!"); 193 FileOffset = 0; 194 } 195 196 // struct section (68 bytes) or 197 // struct section_64 (80 bytes) 198 199 uint64_t Start = OS.tell(); 200 (void) Start; 201 202 const MCSectionMachO &Section = cast<MCSectionMachO>(SD.getSection()); 203 WriteBytes(Section.getSectionName(), 16); 204 WriteBytes(Section.getSegmentName(), 16); 205 if (is64Bit()) { 206 Write64(getSectionAddress(&SD)); // address 207 Write64(SectionSize); // size 208 } else { 209 Write32(getSectionAddress(&SD)); // address 210 Write32(SectionSize); // size 211 } 212 Write32(FileOffset); 213 214 unsigned Flags = Section.getTypeAndAttributes(); 215 if (SD.hasInstructions()) 216 Flags |= MCSectionMachO::S_ATTR_SOME_INSTRUCTIONS; 217 218 assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!"); 219 Write32(Log2_32(SD.getAlignment())); 220 Write32(NumRelocations ? RelocationsStart : 0); 221 Write32(NumRelocations); 222 Write32(Flags); 223 Write32(IndirectSymBase.lookup(&SD)); // reserved1 224 Write32(Section.getStubSize()); // reserved2 225 if (is64Bit()) 226 Write32(0); // reserved3 227 228 assert(OS.tell() - Start == (is64Bit() ? macho::Section64Size : 229 macho::Section32Size)); 230 } 231 232 void MachObjectWriter::WriteSymtabLoadCommand(uint32_t SymbolOffset, 233 uint32_t NumSymbols, 234 uint32_t StringTableOffset, 235 uint32_t StringTableSize) { 236 // struct symtab_command (24 bytes) 237 238 uint64_t Start = OS.tell(); 239 (void) Start; 240 241 Write32(macho::LCT_Symtab); 242 Write32(macho::SymtabLoadCommandSize); 243 Write32(SymbolOffset); 244 Write32(NumSymbols); 245 Write32(StringTableOffset); 246 Write32(StringTableSize); 247 248 assert(OS.tell() - Start == macho::SymtabLoadCommandSize); 249 } 250 251 void MachObjectWriter::WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, 252 uint32_t NumLocalSymbols, 253 uint32_t FirstExternalSymbol, 254 uint32_t NumExternalSymbols, 255 uint32_t FirstUndefinedSymbol, 256 uint32_t NumUndefinedSymbols, 257 uint32_t IndirectSymbolOffset, 258 uint32_t NumIndirectSymbols) { 259 // struct dysymtab_command (80 bytes) 260 261 uint64_t Start = OS.tell(); 262 (void) Start; 263 264 Write32(macho::LCT_Dysymtab); 265 Write32(macho::DysymtabLoadCommandSize); 266 Write32(FirstLocalSymbol); 267 Write32(NumLocalSymbols); 268 Write32(FirstExternalSymbol); 269 Write32(NumExternalSymbols); 270 Write32(FirstUndefinedSymbol); 271 Write32(NumUndefinedSymbols); 272 Write32(0); // tocoff 273 Write32(0); // ntoc 274 Write32(0); // modtaboff 275 Write32(0); // nmodtab 276 Write32(0); // extrefsymoff 277 Write32(0); // nextrefsyms 278 Write32(IndirectSymbolOffset); 279 Write32(NumIndirectSymbols); 280 Write32(0); // extreloff 281 Write32(0); // nextrel 282 Write32(0); // locreloff 283 Write32(0); // nlocrel 284 285 assert(OS.tell() - Start == macho::DysymtabLoadCommandSize); 286 } 287 288 void MachObjectWriter::WriteNlist(MachSymbolData &MSD, 289 const MCAsmLayout &Layout) { 290 MCSymbolData &Data = *MSD.SymbolData; 291 const MCSymbol &Symbol = Data.getSymbol(); 292 uint8_t Type = 0; 293 uint16_t Flags = Data.getFlags(); 294 uint32_t Address = 0; 295 296 // Set the N_TYPE bits. See <mach-o/nlist.h>. 297 // 298 // FIXME: Are the prebound or indirect fields possible here? 299 if (Symbol.isUndefined()) 300 Type = macho::STT_Undefined; 301 else if (Symbol.isAbsolute()) 302 Type = macho::STT_Absolute; 303 else 304 Type = macho::STT_Section; 305 306 // FIXME: Set STAB bits. 307 308 if (Data.isPrivateExtern()) 309 Type |= macho::STF_PrivateExtern; 310 311 // Set external bit. 312 if (Data.isExternal() || Symbol.isUndefined()) 313 Type |= macho::STF_External; 314 315 // Compute the symbol address. 316 if (Symbol.isDefined()) { 317 if (Symbol.isAbsolute()) { 318 Address = cast<MCConstantExpr>(Symbol.getVariableValue())->getValue(); 319 } else { 320 Address = getSymbolAddress(&Data, Layout); 321 } 322 } else if (Data.isCommon()) { 323 // Common symbols are encoded with the size in the address 324 // field, and their alignment in the flags. 325 Address = Data.getCommonSize(); 326 327 // Common alignment is packed into the 'desc' bits. 328 if (unsigned Align = Data.getCommonAlignment()) { 329 unsigned Log2Size = Log2_32(Align); 330 assert((1U << Log2Size) == Align && "Invalid 'common' alignment!"); 331 if (Log2Size > 15) 332 report_fatal_error("invalid 'common' alignment '" + 333 Twine(Align) + "'"); 334 // FIXME: Keep this mask with the SymbolFlags enumeration. 335 Flags = (Flags & 0xF0FF) | (Log2Size << 8); 336 } 337 } 338 339 // struct nlist (12 bytes) 340 341 Write32(MSD.StringIndex); 342 Write8(Type); 343 Write8(MSD.SectionIndex); 344 345 // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc' 346 // value. 347 Write16(Flags); 348 if (is64Bit()) 349 Write64(Address); 350 else 351 Write32(Address); 352 } 353 354 void MachObjectWriter::RecordRelocation(const MCAssembler &Asm, 355 const MCAsmLayout &Layout, 356 const MCFragment *Fragment, 357 const MCFixup &Fixup, 358 MCValue Target, 359 uint64_t &FixedValue) { 360 TargetObjectWriter->RecordRelocation(this, Asm, Layout, Fragment, Fixup, 361 Target, FixedValue); 362 } 363 364 void MachObjectWriter::BindIndirectSymbols(MCAssembler &Asm) { 365 // This is the point where 'as' creates actual symbols for indirect symbols 366 // (in the following two passes). It would be easier for us to do this sooner 367 // when we see the attribute, but that makes getting the order in the symbol 368 // table much more complicated than it is worth. 369 // 370 // FIXME: Revisit this when the dust settles. 371 372 // Bind non lazy symbol pointers first. 373 unsigned IndirectIndex = 0; 374 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), 375 ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) { 376 const MCSectionMachO &Section = 377 cast<MCSectionMachO>(it->SectionData->getSection()); 378 379 if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) 380 continue; 381 382 // Initialize the section indirect symbol base, if necessary. 383 if (!IndirectSymBase.count(it->SectionData)) 384 IndirectSymBase[it->SectionData] = IndirectIndex; 385 386 Asm.getOrCreateSymbolData(*it->Symbol); 387 } 388 389 // Then lazy symbol pointers and symbol stubs. 390 IndirectIndex = 0; 391 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), 392 ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) { 393 const MCSectionMachO &Section = 394 cast<MCSectionMachO>(it->SectionData->getSection()); 395 396 if (Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS && 397 Section.getType() != MCSectionMachO::S_SYMBOL_STUBS) 398 continue; 399 400 // Initialize the section indirect symbol base, if necessary. 401 if (!IndirectSymBase.count(it->SectionData)) 402 IndirectSymBase[it->SectionData] = IndirectIndex; 403 404 // Set the symbol type to undefined lazy, but only on construction. 405 // 406 // FIXME: Do not hardcode. 407 bool Created; 408 MCSymbolData &Entry = Asm.getOrCreateSymbolData(*it->Symbol, &Created); 409 if (Created) 410 Entry.setFlags(Entry.getFlags() | 0x0001); 411 } 412 } 413 414 /// ComputeSymbolTable - Compute the symbol table data 415 /// 416 /// \param StringTable [out] - The string table data. 417 /// \param StringIndexMap [out] - Map from symbol names to offsets in the 418 /// string table. 419 void MachObjectWriter:: 420 ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, 421 std::vector<MachSymbolData> &LocalSymbolData, 422 std::vector<MachSymbolData> &ExternalSymbolData, 423 std::vector<MachSymbolData> &UndefinedSymbolData) { 424 // Build section lookup table. 425 DenseMap<const MCSection*, uint8_t> SectionIndexMap; 426 unsigned Index = 1; 427 for (MCAssembler::iterator it = Asm.begin(), 428 ie = Asm.end(); it != ie; ++it, ++Index) 429 SectionIndexMap[&it->getSection()] = Index; 430 assert(Index <= 256 && "Too many sections!"); 431 432 // Index 0 is always the empty string. 433 StringMap<uint64_t> StringIndexMap; 434 StringTable += '\x00'; 435 436 // Build the symbol arrays and the string table, but only for non-local 437 // symbols. 438 // 439 // The particular order that we collect the symbols and create the string 440 // table, then sort the symbols is chosen to match 'as'. Even though it 441 // doesn't matter for correctness, this is important for letting us diff .o 442 // files. 443 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), 444 ie = Asm.symbol_end(); it != ie; ++it) { 445 const MCSymbol &Symbol = it->getSymbol(); 446 447 // Ignore non-linker visible symbols. 448 if (!Asm.isSymbolLinkerVisible(it->getSymbol())) 449 continue; 450 451 if (!it->isExternal() && !Symbol.isUndefined()) 452 continue; 453 454 uint64_t &Entry = StringIndexMap[Symbol.getName()]; 455 if (!Entry) { 456 Entry = StringTable.size(); 457 StringTable += Symbol.getName(); 458 StringTable += '\x00'; 459 } 460 461 MachSymbolData MSD; 462 MSD.SymbolData = it; 463 MSD.StringIndex = Entry; 464 465 if (Symbol.isUndefined()) { 466 MSD.SectionIndex = 0; 467 UndefinedSymbolData.push_back(MSD); 468 } else if (Symbol.isAbsolute()) { 469 MSD.SectionIndex = 0; 470 ExternalSymbolData.push_back(MSD); 471 } else { 472 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); 473 assert(MSD.SectionIndex && "Invalid section index!"); 474 ExternalSymbolData.push_back(MSD); 475 } 476 } 477 478 // Now add the data for local symbols. 479 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), 480 ie = Asm.symbol_end(); it != ie; ++it) { 481 const MCSymbol &Symbol = it->getSymbol(); 482 483 // Ignore non-linker visible symbols. 484 if (!Asm.isSymbolLinkerVisible(it->getSymbol())) 485 continue; 486 487 if (it->isExternal() || Symbol.isUndefined()) 488 continue; 489 490 uint64_t &Entry = StringIndexMap[Symbol.getName()]; 491 if (!Entry) { 492 Entry = StringTable.size(); 493 StringTable += Symbol.getName(); 494 StringTable += '\x00'; 495 } 496 497 MachSymbolData MSD; 498 MSD.SymbolData = it; 499 MSD.StringIndex = Entry; 500 501 if (Symbol.isAbsolute()) { 502 MSD.SectionIndex = 0; 503 LocalSymbolData.push_back(MSD); 504 } else { 505 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); 506 assert(MSD.SectionIndex && "Invalid section index!"); 507 LocalSymbolData.push_back(MSD); 508 } 509 } 510 511 // External and undefined symbols are required to be in lexicographic order. 512 std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); 513 std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end()); 514 515 // Set the symbol indices. 516 Index = 0; 517 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) 518 LocalSymbolData[i].SymbolData->setIndex(Index++); 519 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) 520 ExternalSymbolData[i].SymbolData->setIndex(Index++); 521 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) 522 UndefinedSymbolData[i].SymbolData->setIndex(Index++); 523 524 // The string table is padded to a multiple of 4. 525 while (StringTable.size() % 4) 526 StringTable += '\x00'; 527 } 528 529 void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm, 530 const MCAsmLayout &Layout) { 531 uint64_t StartAddress = 0; 532 const SmallVectorImpl<MCSectionData*> &Order = Layout.getSectionOrder(); 533 for (int i = 0, n = Order.size(); i != n ; ++i) { 534 const MCSectionData *SD = Order[i]; 535 StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment()); 536 SectionAddress[SD] = StartAddress; 537 StartAddress += Layout.getSectionAddressSize(SD); 538 539 // Explicitly pad the section to match the alignment requirements of the 540 // following one. This is for 'gas' compatibility, it shouldn't 541 /// strictly be necessary. 542 StartAddress += getPaddingSize(SD, Layout); 543 } 544 } 545 546 void MachObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, 547 const MCAsmLayout &Layout) { 548 computeSectionAddresses(Asm, Layout); 549 550 // Create symbol data for any indirect symbols. 551 BindIndirectSymbols(Asm); 552 553 // Compute symbol table information and bind symbol indices. 554 ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData, 555 UndefinedSymbolData); 556 } 557 558 bool MachObjectWriter:: 559 IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, 560 const MCSymbolData &DataA, 561 const MCFragment &FB, 562 bool InSet, 563 bool IsPCRel) const { 564 if (InSet) 565 return true; 566 567 // The effective address is 568 // addr(atom(A)) + offset(A) 569 // - addr(atom(B)) - offset(B) 570 // and the offsets are not relocatable, so the fixup is fully resolved when 571 // addr(atom(A)) - addr(atom(B)) == 0. 572 const MCSymbolData *A_Base = 0, *B_Base = 0; 573 574 const MCSymbol &SA = DataA.getSymbol().AliasedSymbol(); 575 const MCSection &SecA = SA.getSection(); 576 const MCSection &SecB = FB.getParent()->getSection(); 577 578 if (IsPCRel) { 579 // The simple (Darwin, except on x86_64) way of dealing with this was to 580 // assume that any reference to a temporary symbol *must* be a temporary 581 // symbol in the same atom, unless the sections differ. Therefore, any PCrel 582 // relocation to a temporary symbol (in the same section) is fully 583 // resolved. This also works in conjunction with absolutized .set, which 584 // requires the compiler to use .set to absolutize the differences between 585 // symbols which the compiler knows to be assembly time constants, so we 586 // don't need to worry about considering symbol differences fully resolved. 587 588 if (!Asm.getBackend().hasReliableSymbolDifference()) { 589 if (!SA.isTemporary() || !SA.isInSection() || &SecA != &SecB) 590 return false; 591 return true; 592 } 593 } else { 594 if (!TargetObjectWriter->useAggressiveSymbolFolding()) 595 return false; 596 } 597 598 const MCFragment &FA = *Asm.getSymbolData(SA).getFragment(); 599 600 A_Base = FA.getAtom(); 601 if (!A_Base) 602 return false; 603 604 B_Base = FB.getAtom(); 605 if (!B_Base) 606 return false; 607 608 // If the atoms are the same, they are guaranteed to have the same address. 609 if (A_Base == B_Base) 610 return true; 611 612 // Otherwise, we can't prove this is fully resolved. 613 return false; 614 } 615 616 void MachObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { 617 unsigned NumSections = Asm.size(); 618 619 // The section data starts after the header, the segment load command (and 620 // section headers) and the symbol table. 621 unsigned NumLoadCommands = 1; 622 uint64_t LoadCommandsSize = is64Bit() ? 623 macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size : 624 macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size; 625 626 // Add the symbol table load command sizes, if used. 627 unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() + 628 UndefinedSymbolData.size(); 629 if (NumSymbols) { 630 NumLoadCommands += 2; 631 LoadCommandsSize += (macho::SymtabLoadCommandSize + 632 macho::DysymtabLoadCommandSize); 633 } 634 635 // Compute the total size of the section data, as well as its file size and vm 636 // size. 637 uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size : 638 macho::Header32Size) + LoadCommandsSize; 639 uint64_t SectionDataSize = 0; 640 uint64_t SectionDataFileSize = 0; 641 uint64_t VMSize = 0; 642 for (MCAssembler::const_iterator it = Asm.begin(), 643 ie = Asm.end(); it != ie; ++it) { 644 const MCSectionData &SD = *it; 645 uint64_t Address = getSectionAddress(&SD); 646 uint64_t Size = Layout.getSectionAddressSize(&SD); 647 uint64_t FileSize = Layout.getSectionFileSize(&SD); 648 FileSize += getPaddingSize(&SD, Layout); 649 650 VMSize = std::max(VMSize, Address + Size); 651 652 if (SD.getSection().isVirtualSection()) 653 continue; 654 655 SectionDataSize = std::max(SectionDataSize, Address + Size); 656 SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize); 657 } 658 659 // The section data is padded to 4 bytes. 660 // 661 // FIXME: Is this machine dependent? 662 unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4); 663 SectionDataFileSize += SectionDataPadding; 664 665 // Write the prolog, starting with the header and load command... 666 WriteHeader(NumLoadCommands, LoadCommandsSize, 667 Asm.getSubsectionsViaSymbols()); 668 WriteSegmentLoadCommand(NumSections, VMSize, 669 SectionDataStart, SectionDataSize); 670 671 // ... and then the section headers. 672 uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; 673 for (MCAssembler::const_iterator it = Asm.begin(), 674 ie = Asm.end(); it != ie; ++it) { 675 std::vector<macho::RelocationEntry> &Relocs = Relocations[it]; 676 unsigned NumRelocs = Relocs.size(); 677 uint64_t SectionStart = SectionDataStart + getSectionAddress(it); 678 WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs); 679 RelocTableEnd += NumRelocs * macho::RelocationInfoSize; 680 } 681 682 // Write the symbol table load command, if used. 683 if (NumSymbols) { 684 unsigned FirstLocalSymbol = 0; 685 unsigned NumLocalSymbols = LocalSymbolData.size(); 686 unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols; 687 unsigned NumExternalSymbols = ExternalSymbolData.size(); 688 unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols; 689 unsigned NumUndefinedSymbols = UndefinedSymbolData.size(); 690 unsigned NumIndirectSymbols = Asm.indirect_symbol_size(); 691 unsigned NumSymTabSymbols = 692 NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols; 693 uint64_t IndirectSymbolSize = NumIndirectSymbols * 4; 694 uint64_t IndirectSymbolOffset = 0; 695 696 // If used, the indirect symbols are written after the section data. 697 if (NumIndirectSymbols) 698 IndirectSymbolOffset = RelocTableEnd; 699 700 // The symbol table is written after the indirect symbol data. 701 uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize; 702 703 // The string table is written after symbol table. 704 uint64_t StringTableOffset = 705 SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? macho::Nlist64Size : 706 macho::Nlist32Size); 707 WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, 708 StringTableOffset, StringTable.size()); 709 710 WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols, 711 FirstExternalSymbol, NumExternalSymbols, 712 FirstUndefinedSymbol, NumUndefinedSymbols, 713 IndirectSymbolOffset, NumIndirectSymbols); 714 } 715 716 // Write the actual section data. 717 for (MCAssembler::const_iterator it = Asm.begin(), 718 ie = Asm.end(); it != ie; ++it) { 719 Asm.WriteSectionData(it, Layout); 720 721 uint64_t Pad = getPaddingSize(it, Layout); 722 for (unsigned int i = 0; i < Pad; ++i) 723 Write8(0); 724 } 725 726 // Write the extra padding. 727 WriteZeros(SectionDataPadding); 728 729 // Write the relocation entries. 730 for (MCAssembler::const_iterator it = Asm.begin(), 731 ie = Asm.end(); it != ie; ++it) { 732 // Write the section relocation entries, in reverse order to match 'as' 733 // (approximately, the exact algorithm is more complicated than this). 734 std::vector<macho::RelocationEntry> &Relocs = Relocations[it]; 735 for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { 736 Write32(Relocs[e - i - 1].Word0); 737 Write32(Relocs[e - i - 1].Word1); 738 } 739 } 740 741 // Write the symbol table data, if used. 742 if (NumSymbols) { 743 // Write the indirect symbol entries. 744 for (MCAssembler::const_indirect_symbol_iterator 745 it = Asm.indirect_symbol_begin(), 746 ie = Asm.indirect_symbol_end(); it != ie; ++it) { 747 // Indirect symbols in the non lazy symbol pointer section have some 748 // special handling. 749 const MCSectionMachO &Section = 750 static_cast<const MCSectionMachO&>(it->SectionData->getSection()); 751 if (Section.getType() == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) { 752 // If this symbol is defined and internal, mark it as such. 753 if (it->Symbol->isDefined() && 754 !Asm.getSymbolData(*it->Symbol).isExternal()) { 755 uint32_t Flags = macho::ISF_Local; 756 if (it->Symbol->isAbsolute()) 757 Flags |= macho::ISF_Absolute; 758 Write32(Flags); 759 continue; 760 } 761 } 762 763 Write32(Asm.getSymbolData(*it->Symbol).getIndex()); 764 } 765 766 // FIXME: Check that offsets match computed ones. 767 768 // Write the symbol table entries. 769 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) 770 WriteNlist(LocalSymbolData[i], Layout); 771 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) 772 WriteNlist(ExternalSymbolData[i], Layout); 773 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) 774 WriteNlist(UndefinedSymbolData[i], Layout); 775 776 // Write the string table. 777 OS << StringTable.str(); 778 } 779 } 780 781 MCObjectWriter *llvm::createMachObjectWriter(MCMachObjectTargetWriter *MOTW, 782 raw_ostream &OS, 783 bool IsLittleEndian) { 784 return new MachObjectWriter(MOTW, OS, IsLittleEndian); 785 } 786