1 //===- Writer.cpp ---------------------------------------------------------===// 2 // 3 // The LLVM Linker 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 "Writer.h" 11 #include "Config.h" 12 #include "OutputSections.h" 13 #include "SymbolTable.h" 14 #include "Target.h" 15 16 #include "llvm/Support/FileOutputBuffer.h" 17 18 using namespace llvm; 19 using namespace llvm::ELF; 20 using namespace llvm::object; 21 22 using namespace lld; 23 using namespace lld::elf2; 24 25 static const int PageSize = 4096; 26 27 // On freebsd x86_64 the first page cannot be mmaped. 28 // On linux that is controled by vm.mmap_min_addr. At least on some x86_64 29 // installs that is 65536, so the first 15 pages cannot be used. 30 // Given that, the smallest value that can be used in here is 0x10000. 31 // If using 2MB pages, the smallest page aligned address that works is 32 // 0x200000, but it looks like every OS uses 4k pages for executables. 33 // FIXME: This is architecture and OS dependent. 34 static const int VAStart = 0x10000; 35 36 namespace { 37 38 static uint32_t convertSectionFlagsToPHDRFlags(uint64_t Flags) { 39 uint32_t Ret = PF_R; 40 if (Flags & SHF_WRITE) 41 Ret |= PF_W; 42 43 if (Flags & SHF_EXECINSTR) 44 Ret |= PF_X; 45 46 return Ret; 47 } 48 49 template <bool Is64Bits> 50 class ProgramHeader { 51 public: 52 typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t; 53 typedef 54 typename std::conditional<Is64Bits, Elf64_Phdr, Elf32_Phdr>::type HeaderT; 55 56 ProgramHeader(uintX_t p_type, uintX_t p_flags) { 57 std::memset(&Header, 0, sizeof(HeaderT)); 58 Header.p_type = p_type; 59 Header.p_flags = p_flags; 60 Header.p_align = PageSize; 61 } 62 63 void setValuesFromSection(OutputSectionBase<Is64Bits> &Sec) { 64 Header.p_flags = convertSectionFlagsToPHDRFlags(Sec.getFlags()); 65 Header.p_offset = Sec.getFileOff(); 66 Header.p_vaddr = Sec.getVA(); 67 Header.p_paddr = Header.p_vaddr; 68 Header.p_filesz = Sec.getSize(); 69 Header.p_memsz = Header.p_filesz; 70 Header.p_align = Sec.getAlign(); 71 } 72 73 template <endianness E> 74 void writeHeaderTo(typename ELFFile<ELFType<E, Is64Bits>>::Elf_Phdr *PHDR) { 75 PHDR->p_type = Header.p_type; 76 PHDR->p_flags = Header.p_flags; 77 PHDR->p_offset = Header.p_offset; 78 PHDR->p_vaddr = Header.p_vaddr; 79 PHDR->p_paddr = Header.p_paddr; 80 PHDR->p_filesz = Header.p_filesz; 81 PHDR->p_memsz = Header.p_memsz; 82 PHDR->p_align = Header.p_align; 83 } 84 85 HeaderT Header; 86 bool Closed = false; 87 }; 88 89 // The writer writes a SymbolTable result to a file. 90 template <class ELFT> class Writer { 91 public: 92 typedef typename ELFFile<ELFT>::uintX_t uintX_t; 93 typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr; 94 typedef typename ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr; 95 typedef typename ELFFile<ELFT>::Elf_Phdr Elf_Phdr; 96 typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym; 97 typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range; 98 typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela; 99 Writer(SymbolTable *T) 100 : SymTabSec(*T, StrTabSec, BssSec), DynSymSec(*T, DynStrSec, BssSec), 101 RelaDynSec(DynSymSec, GotSec, T->shouldUseRela()), PltSec(GotSec), 102 HashSec(DynSymSec), DynamicSec(*T, HashSec, RelaDynSec), 103 BssSec(PltSec, GotSec, BssSec, ".bss", SHT_NOBITS, 104 SHF_ALLOC | SHF_WRITE) {} 105 void run(); 106 107 private: 108 void createSections(); 109 template <bool isRela> 110 void scanRelocs(const InputSection<ELFT> &C, 111 iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels); 112 void scanRelocs(const InputSection<ELFT> &C); 113 void assignAddresses(); 114 void openFile(StringRef OutputPath); 115 void writeHeader(); 116 void writeSections(); 117 bool needsInterpSection() const { 118 return !SymTabSec.getSymTable().getSharedFiles().empty() && 119 !Config->DynamicLinker.empty(); 120 } 121 bool needsDynamicSections() const { 122 return !SymTabSec.getSymTable().getSharedFiles().empty() || Config->Shared; 123 } 124 unsigned getVAStart() const { return Config->Shared ? 0 : VAStart; } 125 126 std::unique_ptr<llvm::FileOutputBuffer> Buffer; 127 128 llvm::SpecificBumpPtrAllocator<OutputSection<ELFT>> CAlloc; 129 std::vector<OutputSectionBase<ELFT::Is64Bits> *> OutputSections; 130 unsigned getNumSections() const { return OutputSections.size() + 1; } 131 132 llvm::BumpPtrAllocator PAlloc; 133 std::vector<ProgramHeader<ELFT::Is64Bits> *> PHDRs; 134 ProgramHeader<ELFT::Is64Bits> FileHeaderPHDR{PT_LOAD, PF_R}; 135 ProgramHeader<ELFT::Is64Bits> InterpPHDR{PT_INTERP, 0}; 136 ProgramHeader<ELFT::Is64Bits> DynamicPHDR{PT_DYNAMIC, 0}; 137 138 uintX_t FileSize; 139 uintX_t ProgramHeaderOff; 140 uintX_t SectionHeaderOff; 141 142 StringTableSection<ELFT::Is64Bits> StrTabSec = { /*dynamic=*/false }; 143 StringTableSection<ELFT::Is64Bits> DynStrSec = { /*dynamic=*/true }; 144 145 lld::elf2::SymbolTableSection<ELFT> SymTabSec; 146 lld::elf2::SymbolTableSection<ELFT> DynSymSec; 147 148 RelocationSection<ELFT> RelaDynSec; 149 150 GotSection<ELFT> GotSec; 151 PltSection<ELFT> PltSec; 152 153 HashTableSection<ELFT> HashSec; 154 155 DynamicSection<ELFT> DynamicSec; 156 157 InterpSection<ELFT::Is64Bits> InterpSec; 158 159 OutputSection<ELFT> BssSec; 160 }; 161 } // anonymous namespace 162 163 namespace lld { 164 namespace elf2 { 165 166 template <class ELFT> 167 void writeResult(SymbolTable *Symtab) { Writer<ELFT>(Symtab).run(); } 168 169 template void writeResult<ELF32LE>(SymbolTable *); 170 template void writeResult<ELF32BE>(SymbolTable *); 171 template void writeResult<ELF64LE>(SymbolTable *); 172 template void writeResult<ELF64BE>(SymbolTable *); 173 174 } // namespace elf2 175 } // namespace lld 176 177 // The main function of the writer. 178 template <class ELFT> void Writer<ELFT>::run() { 179 createSections(); 180 assignAddresses(); 181 openFile(Config->OutputFile); 182 writeHeader(); 183 writeSections(); 184 error(Buffer->commit()); 185 } 186 187 namespace { 188 template <bool Is64Bits> struct SectionKey { 189 typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t; 190 StringRef Name; 191 uint32_t sh_type; 192 uintX_t sh_flags; 193 }; 194 } 195 namespace llvm { 196 template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> { 197 static SectionKey<Is64Bits> getEmptyKey() { 198 return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0}; 199 } 200 static SectionKey<Is64Bits> getTombstoneKey() { 201 return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getTombstoneKey(), 0, 202 0}; 203 } 204 static unsigned getHashValue(const SectionKey<Is64Bits> &Val) { 205 return hash_combine(Val.Name, Val.sh_type, Val.sh_flags); 206 } 207 static bool isEqual(const SectionKey<Is64Bits> &LHS, 208 const SectionKey<Is64Bits> &RHS) { 209 return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) && 210 LHS.sh_type == RHS.sh_type && LHS.sh_flags == RHS.sh_flags; 211 } 212 }; 213 } 214 215 // The reason we have to do this early scan is as follows 216 // * To mmap the output file, we need to know the size 217 // * For that, we need to know how many dynamic relocs we will have. 218 // It might be possible to avoid this by outputting the file with write: 219 // * Write the allocated output sections, computing addresses. 220 // * Apply relocations, recording which ones require a dynamic reloc. 221 // * Write the dynamic relocations. 222 // * Write the rest of the file. 223 template <class ELFT> 224 template <bool isRela> 225 void Writer<ELFT>::scanRelocs( 226 const InputSection<ELFT> &C, 227 iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) { 228 typedef Elf_Rel_Impl<ELFT, isRela> RelType; 229 const ObjectFile<ELFT> &File = *C.getFile(); 230 bool IsMips64EL = File.getObj().isMips64EL(); 231 for (const RelType &RI : Rels) { 232 uint32_t SymIndex = RI.getSymbol(IsMips64EL); 233 SymbolBody *Body = File.getSymbolBody(SymIndex); 234 if (!Body) 235 continue; 236 uint32_t Type = RI.getType(IsMips64EL); 237 if (Target->relocNeedsPlt(Type, *Body)) { 238 if (Body->isInPlt()) 239 continue; 240 PltSec.addEntry(Body); 241 } 242 if (Target->relocNeedsGot(Type, *Body)) { 243 if (Body->isInGot()) 244 continue; 245 GotSec.addEntry(Body); 246 } else if (!isa<SharedSymbol<ELFT>>(Body)) 247 continue; 248 Body->setUsedInDynamicReloc(); 249 RelaDynSec.addReloc({C, RI}); 250 } 251 } 252 253 template <class ELFT> 254 void Writer<ELFT>::scanRelocs(const InputSection<ELFT> &C) { 255 ObjectFile<ELFT> *File = C.getFile(); 256 ELFFile<ELFT> &EObj = File->getObj(); 257 258 if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC)) 259 return; 260 261 for (const Elf_Shdr *RelSec : C.RelocSections) { 262 if (RelSec->sh_type == SHT_RELA) 263 scanRelocs(C, EObj.relas(RelSec)); 264 else 265 scanRelocs(C, EObj.rels(RelSec)); 266 } 267 } 268 269 template <class ELFT> 270 static void undefError(const SymbolTable &S, const SymbolBody &Sym) { 271 typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym; 272 typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range; 273 274 const Elf_Sym &SymE = cast<ELFSymbolBody<ELFT>>(Sym).Sym; 275 ELFFileBase *SymFile = nullptr; 276 277 for (const std::unique_ptr<ObjectFileBase> &F : S.getObjectFiles()) { 278 const auto &File = cast<ObjectFile<ELFT>>(*F); 279 Elf_Sym_Range Syms = File.getObj().symbols(File.getSymbolTable()); 280 if (&SymE > Syms.begin() && &SymE < Syms.end()) 281 SymFile = F.get(); 282 } 283 284 std::string Message = "undefined symbol: " + Sym.getName().str(); 285 if (SymFile) 286 Message += " in " + SymFile->getName().str(); 287 if (Config->NoInhibitExec) 288 warning(Message); 289 else 290 error(Message); 291 } 292 293 // Create output section objects and add them to OutputSections. 294 template <class ELFT> void Writer<ELFT>::createSections() { 295 SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSection<ELFT> *> Map; 296 297 OutputSections.push_back(&BssSec); 298 Map[{BssSec.getName(), BssSec.getType(), BssSec.getFlags()}] = &BssSec; 299 300 SymbolTable &Symtab = SymTabSec.getSymTable(); 301 for (const std::unique_ptr<ObjectFileBase> &FileB : Symtab.getObjectFiles()) { 302 auto &File = cast<ObjectFile<ELFT>>(*FileB); 303 if (!Config->DiscardAll) { 304 Elf_Sym_Range Syms = File.getLocalSymbols(); 305 for (const Elf_Sym &Sym : Syms) { 306 ErrorOr<StringRef> SymName = Sym.getName(File.getStringTable()); 307 if (SymName && shouldKeepInSymtab(*SymName)) 308 SymTabSec.addSymbol(*SymName, true); 309 } 310 } 311 for (InputSection<ELFT> *C : File.getSections()) { 312 if (!C) 313 continue; 314 const Elf_Shdr *H = C->getSectionHdr(); 315 SectionKey<ELFT::Is64Bits> Key{C->getSectionName(), H->sh_type, 316 H->sh_flags}; 317 OutputSection<ELFT> *&Sec = Map[Key]; 318 if (!Sec) { 319 Sec = new (CAlloc.Allocate()) OutputSection<ELFT>( 320 PltSec, GotSec, BssSec, Key.Name, Key.sh_type, Key.sh_flags); 321 OutputSections.push_back(Sec); 322 } 323 Sec->addSection(C); 324 scanRelocs(*C); 325 } 326 } 327 328 if (OutputSection<ELFT> *OS = 329 Map.lookup({".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC})) { 330 Symtab.addSyntheticSym<ELFT>("__init_array_start", *OS, 0); 331 Symtab.addSyntheticSym<ELFT>("__init_array_end", *OS, OS->getSize()); 332 } 333 334 // FIXME: Try to avoid the extra walk over all global symbols. 335 std::vector<DefinedCommon<ELFT> *> CommonSymbols; 336 for (auto &P : Symtab.getSymbols()) { 337 StringRef Name = P.first; 338 SymbolBody *Body = P.second->Body; 339 if (Body->isStrongUndefined()) 340 undefError<ELFT>(Symtab, *Body); 341 342 if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body)) 343 CommonSymbols.push_back(C); 344 if (!includeInSymtab(*Body)) 345 continue; 346 SymTabSec.addSymbol(Name); 347 348 if (needsDynamicSections() && includeInDynamicSymtab(*Body)) 349 HashSec.addSymbol(Body); 350 } 351 352 // Sort the common symbols by alignment as an heuristic to pack them better. 353 std::stable_sort( 354 CommonSymbols.begin(), CommonSymbols.end(), 355 [](const DefinedCommon<ELFT> *A, const DefinedCommon<ELFT> *B) { 356 return A->MaxAlignment > B->MaxAlignment; 357 }); 358 359 uintX_t Off = BssSec.getSize(); 360 for (DefinedCommon<ELFT> *C : CommonSymbols) { 361 const Elf_Sym &Sym = C->Sym; 362 uintX_t Align = C->MaxAlignment; 363 Off = RoundUpToAlignment(Off, Align); 364 C->OffsetInBSS = Off; 365 Off += Sym.st_size; 366 } 367 368 BssSec.setSize(Off); 369 370 OutputSections.push_back(&SymTabSec); 371 OutputSections.push_back(&StrTabSec); 372 373 if (needsDynamicSections()) { 374 if (needsInterpSection()) 375 OutputSections.push_back(&InterpSec); 376 OutputSections.push_back(&DynSymSec); 377 OutputSections.push_back(&HashSec); 378 OutputSections.push_back(&DynamicSec); 379 OutputSections.push_back(&DynStrSec); 380 if (RelaDynSec.hasRelocs()) 381 OutputSections.push_back(&RelaDynSec); 382 } 383 if (!GotSec.empty()) 384 OutputSections.push_back(&GotSec); 385 if (!PltSec.empty()) 386 OutputSections.push_back(&PltSec); 387 388 std::stable_sort( 389 OutputSections.begin(), OutputSections.end(), 390 [](OutputSectionBase<ELFT::Is64Bits> *A, 391 OutputSectionBase<ELFT::Is64Bits> *B) { 392 // Place SHF_ALLOC sections first. 393 return (A->getFlags() & SHF_ALLOC) && !(B->getFlags() & SHF_ALLOC); 394 }); 395 396 for (unsigned I = 0, N = OutputSections.size(); I < N; ++I) 397 OutputSections[I]->setSectionIndex(I + 1); 398 } 399 400 template <class ELFT> 401 static bool outputSectionHasPHDR(OutputSectionBase<ELFT::Is64Bits> *Sec) { 402 return Sec->getFlags() & SHF_ALLOC; 403 } 404 405 // Visits all sections to assign incremental, non-overlapping RVAs and 406 // file offsets. 407 template <class ELFT> void Writer<ELFT>::assignAddresses() { 408 assert(!OutputSections.empty() && "No output sections to layout!"); 409 uintX_t VA = getVAStart(); 410 uintX_t FileOff = 0; 411 412 FileOff += sizeof(Elf_Ehdr); 413 VA += sizeof(Elf_Ehdr); 414 415 // Reserve space for PHDRs. 416 ProgramHeaderOff = FileOff; 417 FileOff = RoundUpToAlignment(FileOff, PageSize); 418 VA = RoundUpToAlignment(VA, PageSize); 419 420 if (needsInterpSection()) 421 PHDRs.push_back(&InterpPHDR); 422 423 ProgramHeader<ELFT::Is64Bits> *LastPHDR = &FileHeaderPHDR; 424 // Create a PHDR for the file header. 425 PHDRs.push_back(&FileHeaderPHDR); 426 FileHeaderPHDR.Header.p_vaddr = getVAStart(); 427 FileHeaderPHDR.Header.p_paddr = getVAStart(); 428 FileHeaderPHDR.Header.p_align = PageSize; 429 430 for (OutputSectionBase<ELFT::Is64Bits> *Sec : OutputSections) { 431 StrTabSec.add(Sec->getName()); 432 Sec->finalize(); 433 434 if (Sec->getSize()) { 435 uintX_t Flags = convertSectionFlagsToPHDRFlags(Sec->getFlags()); 436 if (LastPHDR->Header.p_flags != Flags || 437 !outputSectionHasPHDR<ELFT>(Sec)) { 438 // Flags changed. End current PHDR and potentially create a new one. 439 if (!LastPHDR->Closed) { 440 LastPHDR->Header.p_filesz = FileOff - LastPHDR->Header.p_offset; 441 LastPHDR->Header.p_memsz = VA - LastPHDR->Header.p_vaddr; 442 LastPHDR->Closed = true; 443 } 444 445 if (outputSectionHasPHDR<ELFT>(Sec)) { 446 LastPHDR = new (PAlloc) ProgramHeader<ELFT::Is64Bits>(PT_LOAD, Flags); 447 PHDRs.push_back(LastPHDR); 448 VA = RoundUpToAlignment(VA, PageSize); 449 FileOff = RoundUpToAlignment(FileOff, PageSize); 450 LastPHDR->Header.p_offset = FileOff; 451 LastPHDR->Header.p_vaddr = VA; 452 LastPHDR->Header.p_paddr = VA; 453 } 454 } 455 } 456 457 uintX_t Align = Sec->getAlign(); 458 uintX_t Size = Sec->getSize(); 459 if (Sec->getFlags() & SHF_ALLOC) { 460 VA = RoundUpToAlignment(VA, Align); 461 Sec->setVA(VA); 462 VA += Size; 463 } 464 FileOff = RoundUpToAlignment(FileOff, Align); 465 Sec->setFileOffset(FileOff); 466 if (Sec->getType() != SHT_NOBITS) 467 FileOff += Size; 468 } 469 470 // Add a PHDR for the dynamic table. 471 if (needsDynamicSections()) 472 PHDRs.push_back(&DynamicPHDR); 473 474 FileOff += OffsetToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4); 475 476 // Add space for section headers. 477 SectionHeaderOff = FileOff; 478 FileOff += getNumSections() * sizeof(Elf_Shdr); 479 FileSize = FileOff; 480 } 481 482 template <class ELFT> void Writer<ELFT>::writeHeader() { 483 uint8_t *Buf = Buffer->getBufferStart(); 484 auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf); 485 EHdr->e_ident[EI_MAG0] = 0x7F; 486 EHdr->e_ident[EI_MAG1] = 0x45; 487 EHdr->e_ident[EI_MAG2] = 0x4C; 488 EHdr->e_ident[EI_MAG3] = 0x46; 489 EHdr->e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; 490 EHdr->e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::support::little 491 ? ELFDATA2LSB 492 : ELFDATA2MSB; 493 EHdr->e_ident[EI_VERSION] = EV_CURRENT; 494 495 const SymbolTable &Symtab = SymTabSec.getSymTable(); 496 auto &FirstObj = cast<ObjectFile<ELFT>>(*Symtab.getFirstELF()); 497 EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI(); 498 499 // FIXME: Generalize the segment construction similar to how we create 500 // output sections. 501 502 EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC; 503 EHdr->e_machine = FirstObj.getEMachine(); 504 EHdr->e_version = EV_CURRENT; 505 SymbolBody *Entry = Symtab.getEntrySym(); 506 EHdr->e_entry = 507 Entry ? getSymVA(cast<ELFSymbolBody<ELFT>>(*Entry), BssSec) : 0; 508 EHdr->e_phoff = ProgramHeaderOff; 509 EHdr->e_shoff = SectionHeaderOff; 510 EHdr->e_ehsize = sizeof(Elf_Ehdr); 511 EHdr->e_phentsize = sizeof(Elf_Phdr); 512 EHdr->e_phnum = PHDRs.size(); 513 EHdr->e_shentsize = sizeof(Elf_Shdr); 514 EHdr->e_shnum = getNumSections(); 515 EHdr->e_shstrndx = StrTabSec.getSectionIndex(); 516 517 // If nothing was merged into the file header PT_LOAD, set the size correctly. 518 if (FileHeaderPHDR.Header.p_filesz == PageSize) 519 FileHeaderPHDR.Header.p_filesz = FileHeaderPHDR.Header.p_memsz = 520 sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * PHDRs.size(); 521 522 if (needsInterpSection()) 523 InterpPHDR.setValuesFromSection(InterpSec); 524 if (needsDynamicSections()) 525 DynamicPHDR.setValuesFromSection(DynamicSec); 526 527 auto PHdrs = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff); 528 for (ProgramHeader<ELFT::Is64Bits> *PHDR : PHDRs) 529 PHDR->template writeHeaderTo<ELFT::TargetEndianness>(PHdrs++); 530 531 auto SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff); 532 // First entry is null. 533 ++SHdrs; 534 for (OutputSectionBase<ELFT::Is64Bits> *Sec : OutputSections) { 535 Sec->setNameOffset(StrTabSec.getFileOff(Sec->getName())); 536 Sec->template writeHeaderTo<ELFT::TargetEndianness>(SHdrs++); 537 } 538 } 539 540 template <class ELFT> void Writer<ELFT>::openFile(StringRef Path) { 541 ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = 542 FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable); 543 error(BufferOrErr, Twine("failed to open ") + Path); 544 Buffer = std::move(*BufferOrErr); 545 } 546 547 // Write section contents to a mmap'ed file. 548 template <class ELFT> void Writer<ELFT>::writeSections() { 549 uint8_t *Buf = Buffer->getBufferStart(); 550 for (OutputSectionBase<ELFT::Is64Bits> *Sec : OutputSections) 551 Sec->writeTo(Buf + Sec->getFileOff()); 552 } 553