xref: /llvm-project-15.0.7/lld/COFF/Writer.cpp (revision 8692a4d1)
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     Symbol *Sym = Symtab->find("__delayLoadHelper2");
252     Defined *Helper = cast<Defined>(Sym->Body);
253     DelayIdata.create(Helper);
254     OutputSection *Sec = createSection(".didat");
255     for (Chunk *C : DelayIdata.getChunks())
256       Sec->addChunk(C);
257     Sec = createSection(".data");
258     for (Chunk *C : DelayIdata.getDataChunks())
259       Sec->addChunk(C);
260     Sec = createSection(".text");
261     for (std::unique_ptr<Chunk> &C : DelayIdata.getCodeChunks())
262       Sec->addChunk(C.get());
263   }
264 }
265 
266 void Writer::createExportTable() {
267   if (Config->Exports.empty())
268     return;
269   OutputSection *Sec = createSection(".edata");
270   for (std::unique_ptr<Chunk> &C : Edata.Chunks)
271     Sec->addChunk(C.get());
272 }
273 
274 // The Windows loader doesn't seem to like empty sections,
275 // so we remove them if any.
276 void Writer::removeEmptySections() {
277   auto IsEmpty = [](OutputSection *S) { return S->getVirtualSize() == 0; };
278   OutputSections.erase(
279       std::remove_if(OutputSections.begin(), OutputSections.end(), IsEmpty),
280       OutputSections.end());
281   uint32_t Idx = 1;
282   for (OutputSection *Sec : OutputSections)
283     Sec->SectionIndex = Idx++;
284 }
285 
286 size_t Writer::addEntryToStringTable(StringRef Str) {
287   assert(Str.size() > COFF::NameSize);
288   size_t OffsetOfEntry = Strtab.size() + 4; // +4 for the size field
289   Strtab.insert(Strtab.end(), Str.begin(), Str.end());
290   Strtab.push_back('\0');
291   return OffsetOfEntry;
292 }
293 
294 void Writer::createSymbolAndStringTable() {
295   if (!Config->Debug)
296     return;
297   // Name field in the section table is 8 byte long. Longer names need
298   // to be written to the string table. First, construct string table.
299   for (OutputSection *Sec : OutputSections) {
300     StringRef Name = Sec->getName();
301     if (Name.size() <= COFF::NameSize)
302       continue;
303     Sec->setStringTableOff(addEntryToStringTable(Name));
304   }
305   for (ObjectFile *File : Symtab->ObjectFiles) {
306     for (SymbolBody *B : File->getSymbols()) {
307       auto *D = dyn_cast<DefinedRegular>(B);
308       if (!D || !D->isLive())
309         continue;
310       uint64_t RVA = D->getRVA();
311       OutputSection *SymSec = nullptr;
312       for (OutputSection *Sec : OutputSections) {
313         if (Sec->getRVA() > RVA)
314           break;
315         SymSec = Sec;
316       }
317       uint64_t SectionRVA = SymSec->getRVA();
318       uint64_t SymbolValue = RVA - SectionRVA;
319 
320       StringRef Name = D->getName();
321       coff_symbol16 Sym;
322       if (Name.size() > COFF::NameSize) {
323         Sym.Name.Offset.Zeroes = 0;
324         Sym.Name.Offset.Offset = addEntryToStringTable(Name);
325       } else {
326         memset(Sym.Name.ShortName, 0, COFF::NameSize);
327         memcpy(Sym.Name.ShortName, Name.data(), Name.size());
328       }
329 
330       COFFSymbolRef DSymRef= D->getCOFFSymbol();
331       Sym.Value = SymbolValue;
332       Sym.SectionNumber = SymSec->SectionIndex;
333       Sym.Type = DSymRef.getType();
334       Sym.StorageClass = DSymRef.getStorageClass();
335       Sym.NumberOfAuxSymbols = 0;
336       OutputSymtab.push_back(Sym);
337     }
338   }
339   OutputSection *LastSection = OutputSections.back();
340   // We position the symbol table to be adjacent to the end of the last section.
341   uint64_t FileOff =
342       LastSection->getFileOff() +
343       RoundUpToAlignment(LastSection->getRawSize(), FileAlignment);
344   if (!OutputSymtab.empty()) {
345     PointerToSymbolTable = FileOff;
346     FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
347   }
348   if (!Strtab.empty())
349     FileOff += Strtab.size() + 4;
350   FileSize = SizeOfHeaders +
351              RoundUpToAlignment(FileOff - SizeOfHeaders, FileAlignment);
352 }
353 
354 // Visits all sections to assign incremental, non-overlapping RVAs and
355 // file offsets.
356 void Writer::assignAddresses() {
357   SizeOfHeaders = DOSStubSize + sizeof(PEMagic) + sizeof(coff_file_header) +
358                   sizeof(data_directory) * NumberfOfDataDirectory +
359                   sizeof(coff_section) * OutputSections.size();
360   SizeOfHeaders +=
361       Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
362   SizeOfHeaders = RoundUpToAlignment(SizeOfHeaders, PageSize);
363   uint64_t RVA = 0x1000; // The first page is kept unmapped.
364   uint64_t FileOff = SizeOfHeaders;
365   for (OutputSection *Sec : OutputSections) {
366     if (Sec->getName() == ".reloc")
367       addBaserels(Sec);
368     Sec->setRVA(RVA);
369     Sec->setFileOffset(FileOff);
370     RVA += RoundUpToAlignment(Sec->getVirtualSize(), PageSize);
371     FileOff += RoundUpToAlignment(Sec->getRawSize(), FileAlignment);
372   }
373   SizeOfImage = SizeOfHeaders + RoundUpToAlignment(RVA - 0x1000, PageSize);
374   FileSize = SizeOfHeaders +
375              RoundUpToAlignment(FileOff - SizeOfHeaders, FileAlignment);
376 }
377 
378 template <typename PEHeaderTy> void Writer::writeHeader() {
379   // Write DOS stub
380   uint8_t *Buf = Buffer->getBufferStart();
381   auto *DOS = reinterpret_cast<dos_header *>(Buf);
382   Buf += DOSStubSize;
383   DOS->Magic[0] = 'M';
384   DOS->Magic[1] = 'Z';
385   DOS->AddressOfRelocationTable = sizeof(dos_header);
386   DOS->AddressOfNewExeHeader = DOSStubSize;
387 
388   // Write PE magic
389   memcpy(Buf, PEMagic, sizeof(PEMagic));
390   Buf += sizeof(PEMagic);
391 
392   // Write COFF header
393   auto *COFF = reinterpret_cast<coff_file_header *>(Buf);
394   Buf += sizeof(*COFF);
395   COFF->Machine = Config->MachineType;
396   COFF->NumberOfSections = OutputSections.size();
397   COFF->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
398   if (Config->is64()) {
399     COFF->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
400   } else {
401     COFF->Characteristics |= IMAGE_FILE_32BIT_MACHINE;
402   }
403   if (Config->DLL)
404     COFF->Characteristics |= IMAGE_FILE_DLL;
405   if (!Config->Relocatable)
406     COFF->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
407   COFF->SizeOfOptionalHeader =
408       sizeof(PEHeaderTy) + sizeof(data_directory) * NumberfOfDataDirectory;
409 
410   // Write PE header
411   auto *PE = reinterpret_cast<PEHeaderTy *>(Buf);
412   Buf += sizeof(*PE);
413   PE->Magic = Config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32;
414   PE->ImageBase = Config->ImageBase;
415   PE->SectionAlignment = SectionAlignment;
416   PE->FileAlignment = FileAlignment;
417   PE->MajorImageVersion = Config->MajorImageVersion;
418   PE->MinorImageVersion = Config->MinorImageVersion;
419   PE->MajorOperatingSystemVersion = Config->MajorOSVersion;
420   PE->MinorOperatingSystemVersion = Config->MinorOSVersion;
421   PE->MajorSubsystemVersion = Config->MajorOSVersion;
422   PE->MinorSubsystemVersion = Config->MinorOSVersion;
423   PE->Subsystem = Config->Subsystem;
424   PE->SizeOfImage = SizeOfImage;
425   PE->SizeOfHeaders = SizeOfHeaders;
426   if (!Config->NoEntry) {
427     Defined *Entry = cast<Defined>(Config->Entry->repl());
428     PE->AddressOfEntryPoint = Entry->getRVA();
429   }
430   PE->SizeOfStackReserve = Config->StackReserve;
431   PE->SizeOfStackCommit = Config->StackCommit;
432   PE->SizeOfHeapReserve = Config->HeapReserve;
433   PE->SizeOfHeapCommit = Config->HeapCommit;
434   if (Config->DynamicBase)
435     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
436   if (Config->HighEntropyVA)
437     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA;
438   if (!Config->AllowBind)
439     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND;
440   if (Config->NxCompat)
441     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
442   if (!Config->AllowIsolation)
443     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;
444   if (Config->TerminalServerAware)
445     PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
446   PE->NumberOfRvaAndSize = NumberfOfDataDirectory;
447   if (OutputSection *Text = findSection(".text")) {
448     PE->BaseOfCode = Text->getRVA();
449     PE->SizeOfCode = Text->getRawSize();
450   }
451   PE->SizeOfInitializedData = getSizeOfInitializedData();
452 
453   // Write data directory
454   auto *Dir = reinterpret_cast<data_directory *>(Buf);
455   Buf += sizeof(*Dir) * NumberfOfDataDirectory;
456   if (OutputSection *Sec = findSection(".edata")) {
457     Dir[EXPORT_TABLE].RelativeVirtualAddress = Sec->getRVA();
458     Dir[EXPORT_TABLE].Size = Sec->getVirtualSize();
459   }
460   if (!Idata.empty()) {
461     Dir[IMPORT_TABLE].RelativeVirtualAddress = Idata.getDirRVA();
462     Dir[IMPORT_TABLE].Size = Idata.getDirSize();
463     Dir[IAT].RelativeVirtualAddress = Idata.getIATRVA();
464     Dir[IAT].Size = Idata.getIATSize();
465   }
466   if (!DelayIdata.empty()) {
467     Dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress =
468         DelayIdata.getDirRVA();
469     Dir[DELAY_IMPORT_DESCRIPTOR].Size = DelayIdata.getDirSize();
470   }
471   if (OutputSection *Sec = findSection(".rsrc")) {
472     Dir[RESOURCE_TABLE].RelativeVirtualAddress = Sec->getRVA();
473     Dir[RESOURCE_TABLE].Size = Sec->getVirtualSize();
474   }
475   if (OutputSection *Sec = findSection(".reloc")) {
476     Dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = Sec->getRVA();
477     Dir[BASE_RELOCATION_TABLE].Size = Sec->getVirtualSize();
478   }
479   if (OutputSection *Sec = findSection(".pdata")) {
480     Dir[EXCEPTION_TABLE].RelativeVirtualAddress = Sec->getRVA();
481     Dir[EXCEPTION_TABLE].Size = Sec->getVirtualSize();
482   }
483   if (Symbol *Sym = Symtab->find("_tls_used")) {
484     if (Defined *B = dyn_cast<Defined>(Sym->Body)) {
485       Dir[TLS_TABLE].RelativeVirtualAddress = B->getRVA();
486       Dir[TLS_TABLE].Size = 40;
487     }
488   }
489 
490   // Write section table
491   for (OutputSection *Sec : OutputSections) {
492     Sec->writeHeaderTo(Buf);
493     Buf += sizeof(coff_section);
494   }
495 
496   if (OutputSymtab.empty())
497     return;
498 
499   COFF->PointerToSymbolTable = PointerToSymbolTable;
500   uint32_t NumberOfSymbols = OutputSymtab.size();
501   COFF->NumberOfSymbols = NumberOfSymbols;
502   auto *SymbolTable = reinterpret_cast<coff_symbol16 *>(
503       Buffer->getBufferStart() + COFF->PointerToSymbolTable);
504   for (size_t I = 0; I != NumberOfSymbols; ++I)
505     SymbolTable[I] = OutputSymtab[I];
506   // Create the string table, it follows immediately after the symbol table.
507   // The first 4 bytes is length including itself.
508   Buf = reinterpret_cast<uint8_t *>(&SymbolTable[NumberOfSymbols]);
509   write32le(Buf, Strtab.size() + 4);
510   memcpy(Buf + 4, Strtab.data(), Strtab.size());
511 }
512 
513 std::error_code Writer::openFile(StringRef Path) {
514   if (auto EC = FileOutputBuffer::create(Path, FileSize, Buffer,
515                                          FileOutputBuffer::F_executable)) {
516     llvm::errs() << "failed to open " << Path << ": " << EC.message() << "\n";
517     return EC;
518   }
519   return std::error_code();
520 }
521 
522 // Write section contents to a mmap'ed file.
523 void Writer::writeSections() {
524   uint8_t *Buf = Buffer->getBufferStart();
525   for (OutputSection *Sec : OutputSections) {
526     // Fill gaps between functions in .text with INT3 instructions
527     // instead of leaving as NUL bytes (which can be interpreted as
528     // ADD instructions).
529     if (Sec->getPermissions() & IMAGE_SCN_CNT_CODE)
530       memset(Buf + Sec->getFileOff(), 0xCC, Sec->getRawSize());
531     for (Chunk *C : Sec->getChunks())
532       C->writeTo(Buf);
533   }
534 }
535 
536 // Sort .pdata section contents according to PE/COFF spec 5.5.
537 void Writer::sortExceptionTable() {
538   if (auto *Sec = findSection(".pdata")) {
539     // We assume .pdata contains function table entries only.
540     struct Entry { ulittle32_t Begin, End, Unwind; };
541     uint8_t *Buf = Buffer->getBufferStart() + Sec->getFileOff();
542     std::sort(reinterpret_cast<Entry *>(Buf),
543               reinterpret_cast<Entry *>(Buf + Sec->getVirtualSize()),
544               [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });
545   }
546 }
547 
548 OutputSection *Writer::findSection(StringRef Name) {
549   for (OutputSection *Sec : OutputSections)
550     if (Sec->getName() == Name)
551       return Sec;
552   return nullptr;
553 }
554 
555 uint32_t Writer::getSizeOfInitializedData() {
556   uint32_t Res = 0;
557   for (OutputSection *S : OutputSections)
558     if (S->getPermissions() & IMAGE_SCN_CNT_INITIALIZED_DATA)
559       Res += S->getRawSize();
560   return Res;
561 }
562 
563 // Returns an existing section or create a new one if not found.
564 OutputSection *Writer::createSection(StringRef Name) {
565   if (auto *Sec = findSection(Name))
566     return Sec;
567   const auto DATA = IMAGE_SCN_CNT_INITIALIZED_DATA;
568   const auto BSS = IMAGE_SCN_CNT_UNINITIALIZED_DATA;
569   const auto CODE = IMAGE_SCN_CNT_CODE;
570   const auto DISCARDABLE = IMAGE_SCN_MEM_DISCARDABLE;
571   const auto R = IMAGE_SCN_MEM_READ;
572   const auto W = IMAGE_SCN_MEM_WRITE;
573   const auto X = IMAGE_SCN_MEM_EXECUTE;
574   uint32_t Perms = StringSwitch<uint32_t>(Name)
575                        .Case(".bss", BSS | R | W)
576                        .Case(".data", DATA | R | W)
577                        .Case(".didat", DATA | R)
578                        .Case(".edata", DATA | R)
579                        .Case(".idata", DATA | R)
580                        .Case(".rdata", DATA | R)
581                        .Case(".reloc", DATA | DISCARDABLE | R)
582                        .Case(".text", CODE | R | X)
583                        .Default(0);
584   if (!Perms)
585     llvm_unreachable("unknown section name");
586   auto Sec = new (CAlloc.Allocate()) OutputSection(Name);
587   Sec->addPermissions(Perms);
588   OutputSections.push_back(Sec);
589   return Sec;
590 }
591 
592 // Dest is .reloc section. Add contents to that section.
593 void Writer::addBaserels(OutputSection *Dest) {
594   std::vector<uint32_t> V;
595   StringRef Name = Config->is64() ? "__ImageBase" : "___ImageBase";
596   Defined *ImageBase = cast<Defined>(Symtab->find(Name)->Body);
597   for (OutputSection *Sec : OutputSections) {
598     if (Sec == Dest)
599       continue;
600     // Collect all locations for base relocations.
601     for (Chunk *C : Sec->getChunks())
602       C->getBaserels(&V, ImageBase);
603     // Add the addresses to .reloc section.
604     if (!V.empty())
605       addBaserelBlocks(Dest, V);
606     V.clear();
607   }
608 }
609 
610 // Add addresses to .reloc section. Note that addresses are grouped by page.
611 void Writer::addBaserelBlocks(OutputSection *Dest, std::vector<uint32_t> &V) {
612   const uint32_t Mask = ~uint32_t(PageSize - 1);
613   uint32_t Page = V[0] & Mask;
614   size_t I = 0, J = 1;
615   for (size_t E = V.size(); J < E; ++J) {
616     uint32_t P = V[J] & Mask;
617     if (P == Page)
618       continue;
619     BaserelChunk *Buf = BAlloc.Allocate();
620     Dest->addChunk(new (Buf) BaserelChunk(Page, &V[I], &V[0] + J));
621     I = J;
622     Page = P;
623   }
624   if (I == J)
625     return;
626   BaserelChunk *Buf = BAlloc.Allocate();
627   Dest->addChunk(new (Buf) BaserelChunk(Page, &V[I], &V[0] + J));
628 }
629 
630 } // namespace coff
631 } // namespace lld
632