xref: /llvm-project-15.0.7/lld/ELF/Writer.cpp (revision b4e2e7a2)
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