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