1 //===- SyntheticSections.cpp ----------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains linker-synthesized sections.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "SyntheticSections.h"
14 
15 #include "InputChunks.h"
16 #include "InputEvent.h"
17 #include "InputGlobal.h"
18 #include "OutputSegment.h"
19 #include "SymbolTable.h"
20 #include "llvm/Support/Path.h"
21 
22 using namespace llvm;
23 using namespace llvm::wasm;
24 
25 using namespace lld;
26 using namespace lld::wasm;
27 
28 OutStruct lld::wasm::Out;
29 
30 namespace {
31 
32 // Some synthetic sections (e.g. "name" and "linking") have subsections.
33 // Just like the synthetic sections themselves these need to be created before
34 // they can be written out (since they are preceded by their length). This
35 // class is used to create subsections and then write them into the stream
36 // of the parent section.
37 class SubSection {
38 public:
39   explicit SubSection(uint32_t Type) : Type(Type) {}
40 
41   void writeTo(raw_ostream &To) {
42     OS.flush();
43     writeUleb128(To, Type, "subsection type");
44     writeUleb128(To, Body.size(), "subsection size");
45     To.write(Body.data(), Body.size());
46   }
47 
48 private:
49   uint32_t Type;
50   std::string Body;
51 
52 public:
53   raw_string_ostream OS{Body};
54 };
55 
56 } // namespace
57 
58 void DylinkSection::writeBody() {
59   raw_ostream &OS = BodyOutputStream;
60 
61   writeUleb128(OS, MemSize, "MemSize");
62   writeUleb128(OS, MemAlign, "MemAlign");
63   writeUleb128(OS, Out.ElemSec->numEntries(), "TableSize");
64   writeUleb128(OS, 0, "TableAlign");
65   writeUleb128(OS, Symtab->SharedFiles.size(), "Needed");
66   for (auto *SO : Symtab->SharedFiles)
67     writeStr(OS, llvm::sys::path::filename(SO->getName()), "so name");
68 }
69 
70 uint32_t TypeSection::registerType(const WasmSignature &Sig) {
71   auto Pair = TypeIndices.insert(std::make_pair(Sig, Types.size()));
72   if (Pair.second) {
73     LLVM_DEBUG(llvm::dbgs() << "type " << toString(Sig) << "\n");
74     Types.push_back(&Sig);
75   }
76   return Pair.first->second;
77 }
78 
79 uint32_t TypeSection::lookupType(const WasmSignature &Sig) {
80   auto It = TypeIndices.find(Sig);
81   if (It == TypeIndices.end()) {
82     error("type not found: " + toString(Sig));
83     return 0;
84   }
85   return It->second;
86 }
87 
88 void TypeSection::writeBody() {
89   writeUleb128(BodyOutputStream, Types.size(), "type count");
90   for (const WasmSignature *Sig : Types)
91     writeSig(BodyOutputStream, *Sig);
92 }
93 
94 uint32_t ImportSection::numImports() const {
95   assert(IsSealed);
96   uint32_t NumImports = ImportedSymbols.size() + GOTSymbols.size();
97   if (Config->ImportMemory)
98     ++NumImports;
99   if (Config->ImportTable)
100     ++NumImports;
101   return NumImports;
102 }
103 
104 void ImportSection::addGOTEntry(Symbol *Sym) {
105   assert(!IsSealed);
106   if (Sym->hasGOTIndex())
107     return;
108   Sym->setGOTIndex(NumImportedGlobals++);
109   GOTSymbols.push_back(Sym);
110 }
111 
112 void ImportSection::addImport(Symbol *Sym) {
113   assert(!IsSealed);
114   ImportedSymbols.emplace_back(Sym);
115   if (auto *F = dyn_cast<FunctionSymbol>(Sym))
116     F->setFunctionIndex(NumImportedFunctions++);
117   else if (auto *G = dyn_cast<GlobalSymbol>(Sym))
118     G->setGlobalIndex(NumImportedGlobals++);
119   else
120     cast<EventSymbol>(Sym)->setEventIndex(NumImportedEvents++);
121 }
122 
123 void ImportSection::writeBody() {
124   raw_ostream &OS = BodyOutputStream;
125 
126   writeUleb128(OS, numImports(), "import count");
127 
128   if (Config->ImportMemory) {
129     WasmImport Import;
130     Import.Module = DefaultModule;
131     Import.Field = "memory";
132     Import.Kind = WASM_EXTERNAL_MEMORY;
133     Import.Memory.Flags = 0;
134     Import.Memory.Initial = Out.MemorySec->NumMemoryPages;
135     if (Out.MemorySec->MaxMemoryPages != 0 || Config->SharedMemory) {
136       Import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
137       Import.Memory.Maximum = Out.MemorySec->MaxMemoryPages;
138     }
139     if (Config->SharedMemory)
140       Import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED;
141     writeImport(OS, Import);
142   }
143 
144   if (Config->ImportTable) {
145     uint32_t TableSize = Out.ElemSec->ElemOffset + Out.ElemSec->numEntries();
146     WasmImport Import;
147     Import.Module = DefaultModule;
148     Import.Field = FunctionTableName;
149     Import.Kind = WASM_EXTERNAL_TABLE;
150     Import.Table.ElemType = WASM_TYPE_FUNCREF;
151     Import.Table.Limits = {0, TableSize, 0};
152     writeImport(OS, Import);
153   }
154 
155   for (const Symbol *Sym : ImportedSymbols) {
156     WasmImport Import;
157     if (auto *F = dyn_cast<UndefinedFunction>(Sym)) {
158       Import.Field = F->ImportName;
159       Import.Module = F->ImportModule;
160     } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) {
161       Import.Field = G->ImportName;
162       Import.Module = G->ImportModule;
163     } else {
164       Import.Field = Sym->getName();
165       Import.Module = DefaultModule;
166     }
167 
168     if (auto *FunctionSym = dyn_cast<FunctionSymbol>(Sym)) {
169       Import.Kind = WASM_EXTERNAL_FUNCTION;
170       Import.SigIndex = Out.TypeSec->lookupType(*FunctionSym->Signature);
171     } else if (auto *GlobalSym = dyn_cast<GlobalSymbol>(Sym)) {
172       Import.Kind = WASM_EXTERNAL_GLOBAL;
173       Import.Global = *GlobalSym->getGlobalType();
174     } else {
175       auto *EventSym = cast<EventSymbol>(Sym);
176       Import.Kind = WASM_EXTERNAL_EVENT;
177       Import.Event.Attribute = EventSym->getEventType()->Attribute;
178       Import.Event.SigIndex = Out.TypeSec->lookupType(*EventSym->Signature);
179     }
180     writeImport(OS, Import);
181   }
182 
183   for (const Symbol *Sym : GOTSymbols) {
184     WasmImport Import;
185     Import.Kind = WASM_EXTERNAL_GLOBAL;
186     Import.Global = {WASM_TYPE_I32, true};
187     if (isa<DataSymbol>(Sym))
188       Import.Module = "GOT.mem";
189     else
190       Import.Module = "GOT.func";
191     Import.Field = Sym->getName();
192     writeImport(OS, Import);
193   }
194 }
195 
196 void FunctionSection::writeBody() {
197   raw_ostream &OS = BodyOutputStream;
198 
199   writeUleb128(OS, InputFunctions.size(), "function count");
200   for (const InputFunction *Func : InputFunctions)
201     writeUleb128(OS, Out.TypeSec->lookupType(Func->Signature), "sig index");
202 }
203 
204 void FunctionSection::addFunction(InputFunction *Func) {
205   if (!Func->Live)
206     return;
207   uint32_t FunctionIndex =
208       Out.ImportSec->numImportedFunctions() + InputFunctions.size();
209   InputFunctions.emplace_back(Func);
210   Func->setFunctionIndex(FunctionIndex);
211 }
212 
213 void TableSection::writeBody() {
214   uint32_t TableSize = Out.ElemSec->ElemOffset + Out.ElemSec->numEntries();
215 
216   raw_ostream &OS = BodyOutputStream;
217   writeUleb128(OS, 1, "table count");
218   WasmLimits Limits = {WASM_LIMITS_FLAG_HAS_MAX, TableSize, TableSize};
219   writeTableType(OS, WasmTable{WASM_TYPE_FUNCREF, Limits});
220 }
221 
222 void MemorySection::writeBody() {
223   raw_ostream &OS = BodyOutputStream;
224 
225   bool HasMax = MaxMemoryPages != 0 || Config->SharedMemory;
226   writeUleb128(OS, 1, "memory count");
227   unsigned Flags = 0;
228   if (HasMax)
229     Flags |= WASM_LIMITS_FLAG_HAS_MAX;
230   if (Config->SharedMemory)
231     Flags |= WASM_LIMITS_FLAG_IS_SHARED;
232   writeUleb128(OS, Flags, "memory limits flags");
233   writeUleb128(OS, NumMemoryPages, "initial pages");
234   if (HasMax)
235     writeUleb128(OS, MaxMemoryPages, "max pages");
236 }
237 
238 void GlobalSection::writeBody() {
239   raw_ostream &OS = BodyOutputStream;
240 
241   writeUleb128(OS, numGlobals(), "global count");
242   for (const InputGlobal *G : InputGlobals)
243     writeGlobal(OS, G->Global);
244   for (const DefinedData *Sym : DefinedFakeGlobals) {
245     WasmGlobal Global;
246     Global.Type = {WASM_TYPE_I32, false};
247     Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
248     Global.InitExpr.Value.Int32 = Sym->getVirtualAddress();
249     writeGlobal(OS, Global);
250   }
251 }
252 
253 void GlobalSection::addGlobal(InputGlobal *Global) {
254   if (!Global->Live)
255     return;
256   uint32_t GlobalIndex =
257       Out.ImportSec->numImportedGlobals() + InputGlobals.size();
258   LLVM_DEBUG(dbgs() << "addGlobal: " << GlobalIndex << "\n");
259   Global->setGlobalIndex(GlobalIndex);
260   Out.GlobalSec->InputGlobals.push_back(Global);
261 }
262 
263 void EventSection::writeBody() {
264   raw_ostream &OS = BodyOutputStream;
265 
266   writeUleb128(OS, InputEvents.size(), "event count");
267   for (InputEvent *E : InputEvents) {
268     E->Event.Type.SigIndex = Out.TypeSec->lookupType(E->Signature);
269     writeEvent(OS, E->Event);
270   }
271 }
272 
273 void EventSection::addEvent(InputEvent *Event) {
274   if (!Event->Live)
275     return;
276   uint32_t EventIndex = Out.ImportSec->numImportedEvents() + InputEvents.size();
277   LLVM_DEBUG(dbgs() << "addEvent: " << EventIndex << "\n");
278   Event->setEventIndex(EventIndex);
279   InputEvents.push_back(Event);
280 }
281 
282 void ExportSection::writeBody() {
283   raw_ostream &OS = BodyOutputStream;
284 
285   writeUleb128(OS, Exports.size(), "export count");
286   for (const WasmExport &Export : Exports)
287     writeExport(OS, Export);
288 }
289 
290 void ElemSection::addEntry(FunctionSymbol *Sym) {
291   if (Sym->hasTableIndex())
292     return;
293   Sym->setTableIndex(ElemOffset + IndirectFunctions.size());
294   IndirectFunctions.emplace_back(Sym);
295 }
296 
297 void ElemSection::writeBody() {
298   raw_ostream &OS = BodyOutputStream;
299 
300   writeUleb128(OS, 1, "segment count");
301   writeUleb128(OS, 0, "table index");
302   WasmInitExpr InitExpr;
303   if (Config->Pic) {
304     InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
305     InitExpr.Value.Global = WasmSym::TableBase->getGlobalIndex();
306   } else {
307     InitExpr.Opcode = WASM_OPCODE_I32_CONST;
308     InitExpr.Value.Int32 = ElemOffset;
309   }
310   writeInitExpr(OS, InitExpr);
311   writeUleb128(OS, IndirectFunctions.size(), "elem count");
312 
313   uint32_t TableIndex = ElemOffset;
314   for (const FunctionSymbol *Sym : IndirectFunctions) {
315     assert(Sym->getTableIndex() == TableIndex);
316     writeUleb128(OS, Sym->getFunctionIndex(), "function index");
317     ++TableIndex;
318   }
319 }
320 
321 void DataCountSection::writeBody() {
322   writeUleb128(BodyOutputStream, NumSegments, "data count");
323 }
324 
325 bool DataCountSection::isNeeded() const {
326   return NumSegments && Out.TargetFeaturesSec->Features.count("bulk-memory");
327 }
328 
329 static uint32_t getWasmFlags(const Symbol *Sym) {
330   uint32_t Flags = 0;
331   if (Sym->isLocal())
332     Flags |= WASM_SYMBOL_BINDING_LOCAL;
333   if (Sym->isWeak())
334     Flags |= WASM_SYMBOL_BINDING_WEAK;
335   if (Sym->isHidden())
336     Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
337   if (Sym->isUndefined())
338     Flags |= WASM_SYMBOL_UNDEFINED;
339   if (auto *F = dyn_cast<UndefinedFunction>(Sym)) {
340     if (F->getName() != F->ImportName)
341       Flags |= WASM_SYMBOL_EXPLICIT_NAME;
342   } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) {
343     if (G->getName() != G->ImportName)
344       Flags |= WASM_SYMBOL_EXPLICIT_NAME;
345   }
346   return Flags;
347 }
348 
349 void LinkingSection::writeBody() {
350   raw_ostream &OS = BodyOutputStream;
351 
352   writeUleb128(OS, WasmMetadataVersion, "Version");
353 
354   if (!SymtabEntries.empty()) {
355     SubSection Sub(WASM_SYMBOL_TABLE);
356     writeUleb128(Sub.OS, SymtabEntries.size(), "num symbols");
357 
358     for (const Symbol *Sym : SymtabEntries) {
359       assert(Sym->isDefined() || Sym->isUndefined());
360       WasmSymbolType Kind = Sym->getWasmType();
361       uint32_t Flags = getWasmFlags(Sym);
362 
363       writeU8(Sub.OS, Kind, "sym kind");
364       writeUleb128(Sub.OS, Flags, "sym flags");
365 
366       if (auto *F = dyn_cast<FunctionSymbol>(Sym)) {
367         writeUleb128(Sub.OS, F->getFunctionIndex(), "index");
368         if (Sym->isDefined() || (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
369           writeStr(Sub.OS, Sym->getName(), "sym name");
370       } else if (auto *G = dyn_cast<GlobalSymbol>(Sym)) {
371         writeUleb128(Sub.OS, G->getGlobalIndex(), "index");
372         if (Sym->isDefined() || (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
373           writeStr(Sub.OS, Sym->getName(), "sym name");
374       } else if (auto *E = dyn_cast<EventSymbol>(Sym)) {
375         writeUleb128(Sub.OS, E->getEventIndex(), "index");
376         if (Sym->isDefined() || (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
377           writeStr(Sub.OS, Sym->getName(), "sym name");
378       } else if (isa<DataSymbol>(Sym)) {
379         writeStr(Sub.OS, Sym->getName(), "sym name");
380         if (auto *DataSym = dyn_cast<DefinedData>(Sym)) {
381           writeUleb128(Sub.OS, DataSym->getOutputSegmentIndex(), "index");
382           writeUleb128(Sub.OS, DataSym->getOutputSegmentOffset(),
383                        "data offset");
384           writeUleb128(Sub.OS, DataSym->getSize(), "data size");
385         }
386       } else {
387         auto *S = cast<OutputSectionSymbol>(Sym);
388         writeUleb128(Sub.OS, S->Section->SectionIndex, "sym section index");
389       }
390     }
391 
392     Sub.writeTo(OS);
393   }
394 
395   if (DataSegments.size()) {
396     SubSection Sub(WASM_SEGMENT_INFO);
397     writeUleb128(Sub.OS, DataSegments.size(), "num data segments");
398     for (const OutputSegment *S : DataSegments) {
399       writeStr(Sub.OS, S->Name, "segment name");
400       writeUleb128(Sub.OS, S->Alignment, "alignment");
401       writeUleb128(Sub.OS, 0, "flags");
402     }
403     Sub.writeTo(OS);
404   }
405 
406   if (!InitFunctions.empty()) {
407     SubSection Sub(WASM_INIT_FUNCS);
408     writeUleb128(Sub.OS, InitFunctions.size(), "num init functions");
409     for (const WasmInitEntry &F : InitFunctions) {
410       writeUleb128(Sub.OS, F.Priority, "priority");
411       writeUleb128(Sub.OS, F.Sym->getOutputSymbolIndex(), "function index");
412     }
413     Sub.writeTo(OS);
414   }
415 
416   struct ComdatEntry {
417     unsigned Kind;
418     uint32_t Index;
419   };
420   std::map<StringRef, std::vector<ComdatEntry>> Comdats;
421 
422   for (const InputFunction *F : Out.FunctionSec->InputFunctions) {
423     StringRef Comdat = F->getComdatName();
424     if (!Comdat.empty())
425       Comdats[Comdat].emplace_back(
426           ComdatEntry{WASM_COMDAT_FUNCTION, F->getFunctionIndex()});
427   }
428   for (uint32_t I = 0; I < DataSegments.size(); ++I) {
429     const auto &InputSegments = DataSegments[I]->InputSegments;
430     if (InputSegments.empty())
431       continue;
432     StringRef Comdat = InputSegments[0]->getComdatName();
433 #ifndef NDEBUG
434     for (const InputSegment *IS : InputSegments)
435       assert(IS->getComdatName() == Comdat);
436 #endif
437     if (!Comdat.empty())
438       Comdats[Comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, I});
439   }
440 
441   if (!Comdats.empty()) {
442     SubSection Sub(WASM_COMDAT_INFO);
443     writeUleb128(Sub.OS, Comdats.size(), "num comdats");
444     for (const auto &C : Comdats) {
445       writeStr(Sub.OS, C.first, "comdat name");
446       writeUleb128(Sub.OS, 0, "comdat flags"); // flags for future use
447       writeUleb128(Sub.OS, C.second.size(), "num entries");
448       for (const ComdatEntry &Entry : C.second) {
449         writeU8(Sub.OS, Entry.Kind, "entry kind");
450         writeUleb128(Sub.OS, Entry.Index, "entry index");
451       }
452     }
453     Sub.writeTo(OS);
454   }
455 }
456 
457 void LinkingSection::addToSymtab(Symbol *Sym) {
458   Sym->setOutputSymbolIndex(SymtabEntries.size());
459   SymtabEntries.emplace_back(Sym);
460 }
461 
462 unsigned NameSection::numNames() const {
463   unsigned NumNames = Out.ImportSec->numImportedFunctions();
464   for (const InputFunction *F : Out.FunctionSec->InputFunctions)
465     if (!F->getName().empty() || !F->getDebugName().empty())
466       ++NumNames;
467 
468   return NumNames;
469 }
470 
471 // Create the custom "name" section containing debug symbol names.
472 void NameSection::writeBody() {
473   SubSection Sub(WASM_NAMES_FUNCTION);
474   writeUleb128(Sub.OS, numNames(), "name count");
475 
476   // Names must appear in function index order.  As it happens ImportedSymbols
477   // and InputFunctions are numbered in order with imported functions coming
478   // first.
479   for (const Symbol *S : Out.ImportSec->ImportedSymbols) {
480     if (auto *F = dyn_cast<FunctionSymbol>(S)) {
481       writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
482       writeStr(Sub.OS, toString(*S), "symbol name");
483     }
484   }
485   for (const InputFunction *F : Out.FunctionSec->InputFunctions) {
486     if (!F->getName().empty()) {
487       writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
488       if (!F->getDebugName().empty()) {
489         writeStr(Sub.OS, F->getDebugName(), "symbol name");
490       } else {
491         writeStr(Sub.OS, maybeDemangleSymbol(F->getName()), "symbol name");
492       }
493     }
494   }
495 
496   Sub.writeTo(BodyOutputStream);
497 }
498 
499 void ProducersSection::addInfo(const WasmProducerInfo &Info) {
500   for (auto &Producers :
501        {std::make_pair(&Info.Languages, &Languages),
502         std::make_pair(&Info.Tools, &Tools), std::make_pair(&Info.SDKs, &SDKs)})
503     for (auto &Producer : *Producers.first)
504       if (Producers.second->end() ==
505           llvm::find_if(*Producers.second,
506                         [&](std::pair<std::string, std::string> Seen) {
507                           return Seen.first == Producer.first;
508                         }))
509         Producers.second->push_back(Producer);
510 }
511 
512 void ProducersSection::writeBody() {
513   auto &OS = BodyOutputStream;
514   writeUleb128(OS, fieldCount(), "field count");
515   for (auto &Field :
516        {std::make_pair("language", Languages),
517         std::make_pair("processed-by", Tools), std::make_pair("sdk", SDKs)}) {
518     if (Field.second.empty())
519       continue;
520     writeStr(OS, Field.first, "field name");
521     writeUleb128(OS, Field.second.size(), "number of entries");
522     for (auto &Entry : Field.second) {
523       writeStr(OS, Entry.first, "producer name");
524       writeStr(OS, Entry.second, "producer version");
525     }
526   }
527 }
528 
529 void TargetFeaturesSection::writeBody() {
530   SmallVector<std::string, 8> Emitted(Features.begin(), Features.end());
531   llvm::sort(Emitted);
532   auto &OS = BodyOutputStream;
533   writeUleb128(OS, Emitted.size(), "feature count");
534   for (auto &Feature : Emitted) {
535     writeU8(OS, WASM_FEATURE_PREFIX_USED, "feature used prefix");
536     writeStr(OS, Feature, "feature name");
537   }
538 }
539 
540 void RelocSection::writeBody() {
541   uint32_t Count = Sec->numRelocations();
542   assert(Sec->SectionIndex != UINT32_MAX);
543   writeUleb128(BodyOutputStream, Sec->SectionIndex, "reloc section");
544   writeUleb128(BodyOutputStream, Count, "reloc count");
545   Sec->writeRelocations(BodyOutputStream);
546 }
547