xref: /llvm-project-15.0.7/lld/COFF/Writer.cpp (revision e993a16d)
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 "Config.h"
11 #include "Writer.h"
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/StringSwitch.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/Support/Debug.h"
16 #include "llvm/Support/Endian.h"
17 #include "llvm/Support/FileOutputBuffer.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include <algorithm>
20 #include <cstdio>
21 #include <functional>
22 #include <map>
23 #include <unordered_set>
24 #include <utility>
25 
26 using namespace llvm;
27 using namespace llvm::COFF;
28 using namespace llvm::object;
29 using namespace llvm::support;
30 using namespace llvm::support::endian;
31 
32 static const int PageSize = 4096;
33 static const int FileAlignment = 512;
34 static const int SectionAlignment = 4096;
35 static const int DOSStubSize = 64;
36 static const int NumberfOfDataDirectory = 16;
37 
38 namespace lld {
39 namespace coff {
40 
41 // The main function of the writer.
42 std::error_code Writer::write(StringRef OutputPath) {
43   markLive();
44   dedupCOMDATs();
45   createSections();
46   createMiscChunks();
47   createImportTables();
48   createExportTable();
49   if (Config->Relocatable)
50     createSection(".reloc");
51   assignAddresses();
52   removeEmptySections();
53   createSymbolAndStringTable();
54   if (auto EC = openFile(OutputPath))
55     return EC;
56   if (Config->is64()) {
57     writeHeader<pe32plus_header>();
58   } else {
59     writeHeader<pe32_header>();
60   }
61   writeSections();
62   sortExceptionTable();
63   return Buffer->commit();
64 }
65 
66 void OutputSection::setRVA(uint64_t RVA) {
67   Header.VirtualAddress = RVA;
68   for (Chunk *C : Chunks)
69     C->setRVA(C->getRVA() + RVA);
70 }
71 
72 void OutputSection::setFileOffset(uint64_t Off) {
73   // If a section has no actual data (i.e. BSS section), we want to
74   // set 0 to its PointerToRawData. Otherwise the output is rejected
75   // by the loader.
76   if (Header.SizeOfRawData == 0)
77     return;
78   Header.PointerToRawData = Off;
79   for (Chunk *C : Chunks)
80     C->setFileOff(C->getFileOff() + Off);
81 }
82 
83 void OutputSection::addChunk(Chunk *C) {
84   Chunks.push_back(C);
85   C->setOutputSection(this);
86   uint64_t Off = Header.VirtualSize;
87   Off = RoundUpToAlignment(Off, C->getAlign());
88   C->setRVA(Off);
89   C->setFileOff(Off);
90   Off += C->getSize();
91   Header.VirtualSize = Off;
92   if (C->hasData())
93     Header.SizeOfRawData = RoundUpToAlignment(Off, FileAlignment);
94 }
95 
96 void OutputSection::addPermissions(uint32_t C) {
97   Header.Characteristics |= C & PermMask;
98 }
99 
100 // Write the section header to a given buffer.
101 void OutputSection::writeHeaderTo(uint8_t *Buf) {
102   auto *Hdr = reinterpret_cast<coff_section *>(Buf);
103   *Hdr = Header;
104   if (StringTableOff) {
105     // If name is too long, write offset into the string table as a name.
106     sprintf(Hdr->Name, "/%d", StringTableOff);
107   } else {
108     assert(!Config->Debug || Name.size() <= COFF::NameSize);
109     strncpy(Hdr->Name, Name.data(),
110             std::min(Name.size(), (size_t)COFF::NameSize));
111   }
112 }
113 
114 // Set live bit on for each reachable chunk. Unmarked (unreachable)
115 // COMDAT chunks will be ignored in the next step, so that they don't
116 // come to the final output file.
117 void Writer::markLive() {
118   if (!Config->DoGC)
119     return;
120 
121   // We build up a worklist of sections which have been marked as live. We only
122   // push into the worklist when we discover an unmarked section, and we mark
123   // as we push, so sections never appear twice in the list.
124   SmallVector<SectionChunk *, 256> Worklist;
125 
126   for (Undefined *U : Config->GCRoot) {
127     auto *D = dyn_cast<DefinedRegular>(U->repl());
128     if (!D || D->isLive())
129       continue;
130     D->markLive();
131     Worklist.push_back(D->getChunk());
132   }
133   for (Chunk *C : Symtab->getChunks()) {
134     auto *SC = dyn_cast<SectionChunk>(C);
135     if (!SC || !SC->isRoot() || SC->isLive())
136       continue;
137     SC->markLive();
138     Worklist.push_back(SC);
139   }
140   while (!Worklist.empty()) {
141     SectionChunk *SC = Worklist.pop_back_val();
142     assert(SC->isLive() && "We mark as live when pushing onto the worklist!");
143 
144     // Mark all symbols listed in the relocation table for this section.
145     for (SymbolBody *S : SC->symbols())
146       if (auto *D = dyn_cast<DefinedRegular>(S->repl()))
147         if (!D->isLive()) {
148           D->markLive();
149           Worklist.push_back(D->getChunk());
150         }
151 
152     // Mark associative sections if any.
153     for (SectionChunk *ChildSC : SC->children())
154       if (!ChildSC->isLive()) {
155         ChildSC->markLive();
156         Worklist.push_back(ChildSC);
157       }
158   }
159 }
160 
161 // Merge identical COMDAT sections.
162 void Writer::dedupCOMDATs() {
163   if (Config->ICF)
164     doICF(Symtab->getChunks());
165 }
166 
167 static StringRef getOutputSection(StringRef Name) {
168   StringRef S = Name.split('$').first;
169   if (Config->Debug)
170     return S;
171   auto It = Config->Merge.find(S);
172   if (It == Config->Merge.end())
173     return S;
174   return It->second;
175 }
176 
177 // Create output section objects and add them to OutputSections.
178 void Writer::createSections() {
179   // First, bin chunks by name.
180   std::map<StringRef, std::vector<Chunk *>> Map;
181   for (Chunk *C : Symtab->getChunks()) {
182     if (Config->DoGC) {
183       auto *SC = dyn_cast<SectionChunk>(C);
184       if (SC && !SC->isLive()) {
185         if (Config->Verbose)
186           SC->printDiscardedMessage();
187         continue;
188       }
189     }
190     Map[C->getSectionName()].push_back(C);
191   }
192 
193   // Then create an OutputSection for each section.
194   // '$' and all following characters in input section names are
195   // discarded when determining output section. So, .text$foo
196   // contributes to .text, for example. See PE/COFF spec 3.2.
197   std::map<StringRef, OutputSection *> Sections;
198   for (auto Pair : Map) {
199     StringRef Name = getOutputSection(Pair.first);
200     OutputSection *&Sec = Sections[Name];
201     if (!Sec) {
202       Sec = new (CAlloc.Allocate()) OutputSection(Name);
203       OutputSections.push_back(Sec);
204     }
205     std::vector<Chunk *> &Chunks = Pair.second;
206     for (Chunk *C : Chunks) {
207       Sec->addChunk(C);
208       Sec->addPermissions(C->getPermissions());
209     }
210   }
211 }
212 
213 void Writer::createMiscChunks() {
214   if (Symtab->LocalImportChunks.empty())
215     return;
216   OutputSection *Sec = createSection(".rdata");
217   for (Chunk *C : Symtab->LocalImportChunks)
218     Sec->addChunk(C);
219 }
220 
221 // Create .idata section for the DLL-imported symbol table.
222 // The format of this section is inherently Windows-specific.
223 // IdataContents class abstracted away the details for us,
224 // so we just let it create chunks and add them to the section.
225 void Writer::createImportTables() {
226   if (Symtab->ImportFiles.empty())
227     return;
228   OutputSection *Text = createSection(".text");
229   for (ImportFile *File : Symtab->ImportFiles) {
230     for (SymbolBody *B : File->getSymbols()) {
231       auto *Import = dyn_cast<DefinedImportData>(B);
232       if (!Import) {
233         // Linker-created function thunks for DLL symbols are added to
234         // .text section.
235         Text->addChunk(cast<DefinedImportThunk>(B)->getChunk());
236         continue;
237       }
238       if (Config->DelayLoads.count(Import->getDLLName().lower())) {
239         DelayIdata.add(Import);
240       } else {
241         Idata.add(Import);
242       }
243     }
244   }
245   if (!Idata.empty()) {
246     OutputSection *Sec = createSection(".idata");
247     for (Chunk *C : Idata.getChunks())
248       Sec->addChunk(C);
249   }
250   if (!DelayIdata.empty()) {
251     Defined *Helper = cast<Defined>(Config->DelayLoadHelper->repl());
252     DelayIdata.create(Helper);
253     OutputSection *Sec = createSection(".didat");
254     for (Chunk *C : DelayIdata.getChunks())
255       Sec->addChunk(C);
256     Sec = createSection(".data");
257     for (Chunk *C : DelayIdata.getDataChunks())
258       Sec->addChunk(C);
259     Sec = createSection(".text");
260     for (std::unique_ptr<Chunk> &C : DelayIdata.getCodeChunks())
261       Sec->addChunk(C.get());
262   }
263 }
264 
265 void Writer::createExportTable() {
266   if (Config->Exports.empty())
267     return;
268   OutputSection *Sec = createSection(".edata");
269   for (std::unique_ptr<Chunk> &C : Edata.Chunks)
270     Sec->addChunk(C.get());
271 }
272 
273 // The Windows loader doesn't seem to like empty sections,
274 // so we remove them if any.
275 void Writer::removeEmptySections() {
276   auto IsEmpty = [](OutputSection *S) { return S->getVirtualSize() == 0; };
277   OutputSections.erase(
278       std::remove_if(OutputSections.begin(), OutputSections.end(), IsEmpty),
279       OutputSections.end());
280   uint32_t Idx = 1;
281   for (OutputSection *Sec : OutputSections)
282     Sec->SectionIndex = Idx++;
283 }
284 
285 size_t Writer::addEntryToStringTable(StringRef Str) {
286   assert(Str.size() > COFF::NameSize);
287   size_t OffsetOfEntry = Strtab.size() + 4; // +4 for the size field
288   Strtab.insert(Strtab.end(), Str.begin(), Str.end());
289   Strtab.push_back('\0');
290   return OffsetOfEntry;
291 }
292 
293 coff_symbol16 Writer::createSymbol(DefinedRegular *D) {
294   uint64_t RVA = D->getRVA();
295   OutputSection *Sec = nullptr;
296   for (OutputSection *S : OutputSections) {
297     if (S->getRVA() > RVA)
298       break;
299     Sec = S;
300   }
301 
302   coff_symbol16 Sym;
303   StringRef Name = D->getName();
304   if (Name.size() > COFF::NameSize) {
305     Sym.Name.Offset.Zeroes = 0;
306     Sym.Name.Offset.Offset = addEntryToStringTable(Name);
307   } else {
308     memset(Sym.Name.ShortName, 0, COFF::NameSize);
309     memcpy(Sym.Name.ShortName, Name.data(), Name.size());
310   }
311   COFFSymbolRef DSymRef = D->getCOFFSymbol();
312   Sym.Value = RVA - Sec->getRVA();
313   Sym.SectionNumber = Sec->SectionIndex;
314   Sym.Type = DSymRef.getType();
315   Sym.StorageClass = DSymRef.getStorageClass();
316   Sym.NumberOfAuxSymbols = 0;
317   return Sym;
318 }
319 
320 void Writer::createSymbolAndStringTable() {
321   if (!Config->Debug)
322     return;
323   // Name field in the section table is 8 byte long. Longer names need
324   // to be written to the string table. First, construct string table.
325   for (OutputSection *Sec : OutputSections) {
326     StringRef Name = Sec->getName();
327     if (Name.size() <= COFF::NameSize)
328       continue;
329     Sec->setStringTableOff(addEntryToStringTable(Name));
330   }
331 
332   for (ObjectFile *File : Symtab->ObjectFiles)
333     for (SymbolBody *B : File->getSymbols())
334       if (auto *D = dyn_cast<DefinedRegular>(B))
335         if (D->isLive())
336           OutputSymtab.push_back(createSymbol(D));
337 
338   OutputSection *LastSection = OutputSections.back();
339   // We position the symbol table to be adjacent to the end of the last section.
340   uint64_t FileOff =
341       LastSection->getFileOff() +
342       RoundUpToAlignment(LastSection->getRawSize(), FileAlignment);
343   if (!OutputSymtab.empty()) {
344     PointerToSymbolTable = FileOff;
345     FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
346   }
347   if (!Strtab.empty())
348     FileOff += Strtab.size() + 4;
349   FileSize = SizeOfHeaders +
350              RoundUpToAlignment(FileOff - SizeOfHeaders, FileAlignment);
351 }
352 
353 // Visits all sections to assign incremental, non-overlapping RVAs and
354 // file offsets.
355 void Writer::assignAddresses() {
356   SizeOfHeaders = DOSStubSize + sizeof(PEMagic) + sizeof(coff_file_header) +
357                   sizeof(data_directory) * NumberfOfDataDirectory +
358                   sizeof(coff_section) * OutputSections.size();
359   SizeOfHeaders +=
360       Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
361   SizeOfHeaders = RoundUpToAlignment(SizeOfHeaders, PageSize);
362   uint64_t RVA = 0x1000; // The first page is kept unmapped.
363   uint64_t FileOff = SizeOfHeaders;
364   for (OutputSection *Sec : OutputSections) {
365     if (Sec->getName() == ".reloc")
366       addBaserels(Sec);
367     Sec->setRVA(RVA);
368     Sec->setFileOffset(FileOff);
369     RVA += RoundUpToAlignment(Sec->getVirtualSize(), PageSize);
370     FileOff += RoundUpToAlignment(Sec->getRawSize(), FileAlignment);
371   }
372   SizeOfImage = SizeOfHeaders + RoundUpToAlignment(RVA - 0x1000, PageSize);
373   FileSize = SizeOfHeaders +
374              RoundUpToAlignment(FileOff - SizeOfHeaders, FileAlignment);
375 }
376 
377 template <typename PEHeaderTy> void Writer::writeHeader() {
378   // Write DOS stub
379   uint8_t *Buf = Buffer->getBufferStart();
380   auto *DOS = reinterpret_cast<dos_header *>(Buf);
381   Buf += DOSStubSize;
382   DOS->Magic[0] = 'M';
383   DOS->Magic[1] = 'Z';
384   DOS->AddressOfRelocationTable = sizeof(dos_header);
385   DOS->AddressOfNewExeHeader = DOSStubSize;
386 
387   // Write PE magic
388   memcpy(Buf, PEMagic, sizeof(PEMagic));
389   Buf += sizeof(PEMagic);
390 
391   // Write COFF header
392   auto *COFF = reinterpret_cast<coff_file_header *>(Buf);
393   Buf += sizeof(*COFF);
394   COFF->Machine = Config->MachineType;
395   COFF->NumberOfSections = OutputSections.size();
396   COFF->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
397   if (Config->is64()) {
398     COFF->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
399   } else {
400     COFF->Characteristics |= IMAGE_FILE_32BIT_MACHINE;
401   }
402   if (Config->DLL)
403     COFF->Characteristics |= IMAGE_FILE_DLL;
404   if (!Config->Relocatable)
405     COFF->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
406   COFF->SizeOfOptionalHeader =
407       sizeof(PEHeaderTy) + sizeof(data_directory) * NumberfOfDataDirectory;
408 
409   // Write PE header
410   auto *PE = reinterpret_cast<PEHeaderTy *>(Buf);
411   Buf += sizeof(*PE);
412   PE->Magic = Config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32;
413   PE->ImageBase = Config->ImageBase;
414   PE->SectionAlignment = SectionAlignment;
415   PE->FileAlignment = FileAlignment;
416   PE->MajorImageVersion = Config->MajorImageVersion;
417   PE->MinorImageVersion = Config->MinorImageVersion;
418   PE->MajorOperatingSystemVersion = Config->MajorOSVersion;
419   PE->MinorOperatingSystemVersion = Config->MinorOSVersion;
420   PE->MajorSubsystemVersion = Config->MajorOSVersion;
421   PE->MinorSubsystemVersion = Config->MinorOSVersion;
422   PE->Subsystem = Config->Subsystem;
423   PE->SizeOfImage = SizeOfImage;
424   PE->SizeOfHeaders = SizeOfHeaders;
425   if (!Config->NoEntry) {
426     Defined *Entry = cast<Defined>(Config->Entry->repl());
427     PE->AddressOfEntryPoint = Entry->getRVA();
428   }
429   PE->SizeOfStackReserve = Config->StackReserve;
430   PE->SizeOfStackCommit = Config->StackCommit;
431   PE->SizeOfHeapReserve = Config->HeapReserve;
432   PE->SizeOfHeapCommit = Config->HeapCommit;
433   if (Config->DynamicBase)
434     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
435   if (Config->HighEntropyVA)
436     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA;
437   if (!Config->AllowBind)
438     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND;
439   if (Config->NxCompat)
440     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
441   if (!Config->AllowIsolation)
442     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;
443   if (Config->TerminalServerAware)
444     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
445   PE->NumberOfRvaAndSize = NumberfOfDataDirectory;
446   if (OutputSection *Text = findSection(".text")) {
447     PE->BaseOfCode = Text->getRVA();
448     PE->SizeOfCode = Text->getRawSize();
449   }
450   PE->SizeOfInitializedData = getSizeOfInitializedData();
451 
452   // Write data directory
453   auto *Dir = reinterpret_cast<data_directory *>(Buf);
454   Buf += sizeof(*Dir) * NumberfOfDataDirectory;
455   if (OutputSection *Sec = findSection(".edata")) {
456     Dir[EXPORT_TABLE].RelativeVirtualAddress = Sec->getRVA();
457     Dir[EXPORT_TABLE].Size = Sec->getVirtualSize();
458   }
459   if (!Idata.empty()) {
460     Dir[IMPORT_TABLE].RelativeVirtualAddress = Idata.getDirRVA();
461     Dir[IMPORT_TABLE].Size = Idata.getDirSize();
462     Dir[IAT].RelativeVirtualAddress = Idata.getIATRVA();
463     Dir[IAT].Size = Idata.getIATSize();
464   }
465   if (!DelayIdata.empty()) {
466     Dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress =
467         DelayIdata.getDirRVA();
468     Dir[DELAY_IMPORT_DESCRIPTOR].Size = DelayIdata.getDirSize();
469   }
470   if (OutputSection *Sec = findSection(".rsrc")) {
471     Dir[RESOURCE_TABLE].RelativeVirtualAddress = Sec->getRVA();
472     Dir[RESOURCE_TABLE].Size = Sec->getVirtualSize();
473   }
474   if (OutputSection *Sec = findSection(".reloc")) {
475     Dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = Sec->getRVA();
476     Dir[BASE_RELOCATION_TABLE].Size = Sec->getVirtualSize();
477   }
478   if (OutputSection *Sec = findSection(".pdata")) {
479     Dir[EXCEPTION_TABLE].RelativeVirtualAddress = Sec->getRVA();
480     Dir[EXCEPTION_TABLE].Size = Sec->getVirtualSize();
481   }
482   if (Symbol *Sym = Symtab->find("_tls_used")) {
483     if (Defined *B = dyn_cast<Defined>(Sym->Body)) {
484       Dir[TLS_TABLE].RelativeVirtualAddress = B->getRVA();
485       Dir[TLS_TABLE].Size = 40;
486     }
487   }
488 
489   // Write section table
490   for (OutputSection *Sec : OutputSections) {
491     Sec->writeHeaderTo(Buf);
492     Buf += sizeof(coff_section);
493   }
494 
495   if (OutputSymtab.empty())
496     return;
497 
498   COFF->PointerToSymbolTable = PointerToSymbolTable;
499   uint32_t NumberOfSymbols = OutputSymtab.size();
500   COFF->NumberOfSymbols = NumberOfSymbols;
501   auto *SymbolTable = reinterpret_cast<coff_symbol16 *>(
502       Buffer->getBufferStart() + COFF->PointerToSymbolTable);
503   for (size_t I = 0; I != NumberOfSymbols; ++I)
504     SymbolTable[I] = OutputSymtab[I];
505   // Create the string table, it follows immediately after the symbol table.
506   // The first 4 bytes is length including itself.
507   Buf = reinterpret_cast<uint8_t *>(&SymbolTable[NumberOfSymbols]);
508   write32le(Buf, Strtab.size() + 4);
509   memcpy(Buf + 4, Strtab.data(), Strtab.size());
510 }
511 
512 std::error_code Writer::openFile(StringRef Path) {
513   if (auto EC = FileOutputBuffer::create(Path, FileSize, Buffer,
514                                          FileOutputBuffer::F_executable)) {
515     llvm::errs() << "failed to open " << Path << ": " << EC.message() << "\n";
516     return EC;
517   }
518   return std::error_code();
519 }
520 
521 // Write section contents to a mmap'ed file.
522 void Writer::writeSections() {
523   uint8_t *Buf = Buffer->getBufferStart();
524   for (OutputSection *Sec : OutputSections) {
525     // Fill gaps between functions in .text with INT3 instructions
526     // instead of leaving as NUL bytes (which can be interpreted as
527     // ADD instructions).
528     if (Sec->getPermissions() & IMAGE_SCN_CNT_CODE)
529       memset(Buf + Sec->getFileOff(), 0xCC, Sec->getRawSize());
530     for (Chunk *C : Sec->getChunks())
531       C->writeTo(Buf);
532   }
533 }
534 
535 // Sort .pdata section contents according to PE/COFF spec 5.5.
536 void Writer::sortExceptionTable() {
537   if (auto *Sec = findSection(".pdata")) {
538     // We assume .pdata contains function table entries only.
539     struct Entry { ulittle32_t Begin, End, Unwind; };
540     uint8_t *Buf = Buffer->getBufferStart() + Sec->getFileOff();
541     std::sort(reinterpret_cast<Entry *>(Buf),
542               reinterpret_cast<Entry *>(Buf + Sec->getVirtualSize()),
543               [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });
544   }
545 }
546 
547 OutputSection *Writer::findSection(StringRef Name) {
548   for (OutputSection *Sec : OutputSections)
549     if (Sec->getName() == Name)
550       return Sec;
551   return nullptr;
552 }
553 
554 uint32_t Writer::getSizeOfInitializedData() {
555   uint32_t Res = 0;
556   for (OutputSection *S : OutputSections)
557     if (S->getPermissions() & IMAGE_SCN_CNT_INITIALIZED_DATA)
558       Res += S->getRawSize();
559   return Res;
560 }
561 
562 // Returns an existing section or create a new one if not found.
563 OutputSection *Writer::createSection(StringRef Name) {
564   if (auto *Sec = findSection(Name))
565     return Sec;
566   const auto DATA = IMAGE_SCN_CNT_INITIALIZED_DATA;
567   const auto BSS = IMAGE_SCN_CNT_UNINITIALIZED_DATA;
568   const auto CODE = IMAGE_SCN_CNT_CODE;
569   const auto DISCARDABLE = IMAGE_SCN_MEM_DISCARDABLE;
570   const auto R = IMAGE_SCN_MEM_READ;
571   const auto W = IMAGE_SCN_MEM_WRITE;
572   const auto X = IMAGE_SCN_MEM_EXECUTE;
573   uint32_t Perms = StringSwitch<uint32_t>(Name)
574                        .Case(".bss", BSS | R | W)
575                        .Case(".data", DATA | R | W)
576                        .Case(".didat", DATA | R)
577                        .Case(".edata", DATA | R)
578                        .Case(".idata", DATA | R)
579                        .Case(".rdata", DATA | R)
580                        .Case(".reloc", DATA | DISCARDABLE | R)
581                        .Case(".text", CODE | R | X)
582                        .Default(0);
583   if (!Perms)
584     llvm_unreachable("unknown section name");
585   auto Sec = new (CAlloc.Allocate()) OutputSection(Name);
586   Sec->addPermissions(Perms);
587   OutputSections.push_back(Sec);
588   return Sec;
589 }
590 
591 // Dest is .reloc section. Add contents to that section.
592 void Writer::addBaserels(OutputSection *Dest) {
593   std::vector<uint32_t> V;
594   StringRef Name = Config->is64() ? "__ImageBase" : "___ImageBase";
595   Defined *ImageBase = cast<Defined>(Symtab->find(Name)->Body);
596   for (OutputSection *Sec : OutputSections) {
597     if (Sec == Dest)
598       continue;
599     // Collect all locations for base relocations.
600     for (Chunk *C : Sec->getChunks())
601       C->getBaserels(&V, ImageBase);
602     // Add the addresses to .reloc section.
603     if (!V.empty())
604       addBaserelBlocks(Dest, V);
605     V.clear();
606   }
607 }
608 
609 // Add addresses to .reloc section. Note that addresses are grouped by page.
610 void Writer::addBaserelBlocks(OutputSection *Dest, std::vector<uint32_t> &V) {
611   const uint32_t Mask = ~uint32_t(PageSize - 1);
612   uint32_t Page = V[0] & Mask;
613   size_t I = 0, J = 1;
614   for (size_t E = V.size(); J < E; ++J) {
615     uint32_t P = V[J] & Mask;
616     if (P == Page)
617       continue;
618     BaserelChunk *Buf = BAlloc.Allocate();
619     Dest->addChunk(new (Buf) BaserelChunk(Page, &V[I], &V[0] + J));
620     I = J;
621     Page = P;
622   }
623   if (I == J)
624     return;
625   BaserelChunk *Buf = BAlloc.Allocate();
626   Dest->addChunk(new (Buf) BaserelChunk(Page, &V[I], &V[0] + J));
627 }
628 
629 } // namespace coff
630 } // namespace lld
631