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::getNumImports() 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   LLVM_DEBUG(dbgs() << "addGOTEntry: " << toString(*sym) << "\n");
107   if (sym->hasGOTIndex())
108     return;
109   sym->setGOTIndex(numImportedGlobals++);
110   gotSymbols.push_back(sym);
111 }
112 
113 void ImportSection::addImport(Symbol *sym) {
114   assert(!isSealed);
115   importedSymbols.emplace_back(sym);
116   if (auto *f = dyn_cast<FunctionSymbol>(sym))
117     f->setFunctionIndex(numImportedFunctions++);
118   else if (auto *g = dyn_cast<GlobalSymbol>(sym))
119     g->setGlobalIndex(numImportedGlobals++);
120   else
121     cast<EventSymbol>(sym)->setEventIndex(numImportedEvents++);
122 }
123 
124 void ImportSection::writeBody() {
125   raw_ostream &os = bodyOutputStream;
126 
127   writeUleb128(os, getNumImports(), "import count");
128 
129   if (config->importMemory) {
130     WasmImport import;
131     import.Module = defaultModule;
132     import.Field = "memory";
133     import.Kind = WASM_EXTERNAL_MEMORY;
134     import.Memory.Flags = 0;
135     import.Memory.Initial = out.memorySec->numMemoryPages;
136     if (out.memorySec->maxMemoryPages != 0 || config->sharedMemory) {
137       import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
138       import.Memory.Maximum = out.memorySec->maxMemoryPages;
139     }
140     if (config->sharedMemory)
141       import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED;
142     writeImport(os, import);
143   }
144 
145   if (config->importTable) {
146     uint32_t tableSize = out.elemSec->elemOffset + out.elemSec->numEntries();
147     WasmImport import;
148     import.Module = defaultModule;
149     import.Field = functionTableName;
150     import.Kind = WASM_EXTERNAL_TABLE;
151     import.Table.ElemType = WASM_TYPE_FUNCREF;
152     import.Table.Limits = {0, tableSize, 0};
153     writeImport(os, import);
154   }
155 
156   for (const Symbol *sym : importedSymbols) {
157     WasmImport import;
158     if (auto *f = dyn_cast<UndefinedFunction>(sym)) {
159       import.Field = f->importName;
160       import.Module = f->importModule;
161     } else if (auto *g = dyn_cast<UndefinedGlobal>(sym)) {
162       import.Field = g->importName;
163       import.Module = g->importModule;
164     } else {
165       import.Field = sym->getName();
166       import.Module = defaultModule;
167     }
168 
169     if (auto *functionSym = dyn_cast<FunctionSymbol>(sym)) {
170       import.Kind = WASM_EXTERNAL_FUNCTION;
171       import.SigIndex = out.typeSec->lookupType(*functionSym->signature);
172     } else if (auto *globalSym = dyn_cast<GlobalSymbol>(sym)) {
173       import.Kind = WASM_EXTERNAL_GLOBAL;
174       import.Global = *globalSym->getGlobalType();
175     } else {
176       auto *eventSym = cast<EventSymbol>(sym);
177       import.Kind = WASM_EXTERNAL_EVENT;
178       import.Event.Attribute = eventSym->getEventType()->Attribute;
179       import.Event.SigIndex = out.typeSec->lookupType(*eventSym->signature);
180     }
181     writeImport(os, import);
182   }
183 
184   for (const Symbol *sym : gotSymbols) {
185     WasmImport import;
186     import.Kind = WASM_EXTERNAL_GLOBAL;
187     import.Global = {WASM_TYPE_I32, true};
188     if (isa<DataSymbol>(sym))
189       import.Module = "GOT.mem";
190     else
191       import.Module = "GOT.func";
192     import.Field = sym->getName();
193     writeImport(os, import);
194   }
195 }
196 
197 void FunctionSection::writeBody() {
198   raw_ostream &os = bodyOutputStream;
199 
200   writeUleb128(os, inputFunctions.size(), "function count");
201   for (const InputFunction *func : inputFunctions)
202     writeUleb128(os, out.typeSec->lookupType(func->signature), "sig index");
203 }
204 
205 void FunctionSection::addFunction(InputFunction *func) {
206   if (!func->live)
207     return;
208   uint32_t functionIndex =
209       out.importSec->getNumImportedFunctions() + inputFunctions.size();
210   inputFunctions.emplace_back(func);
211   func->setFunctionIndex(functionIndex);
212 }
213 
214 void TableSection::writeBody() {
215   uint32_t tableSize = out.elemSec->elemOffset + out.elemSec->numEntries();
216 
217   raw_ostream &os = bodyOutputStream;
218   writeUleb128(os, 1, "table count");
219   WasmLimits limits = {WASM_LIMITS_FLAG_HAS_MAX, tableSize, tableSize};
220   writeTableType(os, WasmTable{WASM_TYPE_FUNCREF, limits});
221 }
222 
223 void MemorySection::writeBody() {
224   raw_ostream &os = bodyOutputStream;
225 
226   bool hasMax = maxMemoryPages != 0 || config->sharedMemory;
227   writeUleb128(os, 1, "memory count");
228   unsigned flags = 0;
229   if (hasMax)
230     flags |= WASM_LIMITS_FLAG_HAS_MAX;
231   if (config->sharedMemory)
232     flags |= WASM_LIMITS_FLAG_IS_SHARED;
233   writeUleb128(os, flags, "memory limits flags");
234   writeUleb128(os, numMemoryPages, "initial pages");
235   if (hasMax)
236     writeUleb128(os, maxMemoryPages, "max pages");
237 }
238 
239 void GlobalSection::assignIndexes() {
240   uint32_t globalIndex = out.importSec->getNumImportedGlobals();
241   for (InputGlobal *g : inputGlobals)
242     g->setGlobalIndex(globalIndex++);
243   for (Symbol *sym : gotSymbols)
244     sym->setGOTIndex(globalIndex++);
245 }
246 
247 void GlobalSection::addDummyGOTEntry(Symbol *sym) {
248   LLVM_DEBUG(dbgs() << "addDummyGOTEntry: " << toString(*sym) << "\n");
249   if (sym->hasGOTIndex())
250     return;
251   gotSymbols.push_back(sym);
252 }
253 
254 void GlobalSection::writeBody() {
255   raw_ostream &os = bodyOutputStream;
256 
257   writeUleb128(os, numGlobals(), "global count");
258   for (InputGlobal *g : inputGlobals)
259     writeGlobal(os, g->global);
260   for (const DefinedData *sym : definedFakeGlobals) {
261     WasmGlobal global;
262     global.Type = {WASM_TYPE_I32, false};
263     global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
264     global.InitExpr.Value.Int32 = sym->getVirtualAddress();
265     writeGlobal(os, global);
266   }
267   for (const Symbol *sym : gotSymbols) {
268     WasmGlobal global;
269     global.Type = {WASM_TYPE_I32, false};
270     global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
271     if (auto *d = dyn_cast<DefinedData>(sym))
272       global.InitExpr.Value.Int32 = d->getVirtualAddress();
273     else if (auto *f = cast<DefinedFunction>(sym))
274       global.InitExpr.Value.Int32 = f->getTableIndex();
275     writeGlobal(os, global);
276   }
277 }
278 
279 void GlobalSection::addGlobal(InputGlobal *global) {
280   if (!global->live)
281     return;
282   inputGlobals.push_back(global);
283 }
284 
285 void EventSection::writeBody() {
286   raw_ostream &os = bodyOutputStream;
287 
288   writeUleb128(os, inputEvents.size(), "event count");
289   for (InputEvent *e : inputEvents) {
290     e->event.Type.SigIndex = out.typeSec->lookupType(e->signature);
291     writeEvent(os, e->event);
292   }
293 }
294 
295 void EventSection::addEvent(InputEvent *event) {
296   if (!event->live)
297     return;
298   uint32_t eventIndex =
299       out.importSec->getNumImportedEvents() + inputEvents.size();
300   LLVM_DEBUG(dbgs() << "addEvent: " << eventIndex << "\n");
301   event->setEventIndex(eventIndex);
302   inputEvents.push_back(event);
303 }
304 
305 void ExportSection::writeBody() {
306   raw_ostream &os = bodyOutputStream;
307 
308   writeUleb128(os, exports.size(), "export count");
309   for (const WasmExport &export_ : exports)
310     writeExport(os, export_);
311 }
312 
313 void ElemSection::addEntry(FunctionSymbol *sym) {
314   if (sym->hasTableIndex())
315     return;
316   sym->setTableIndex(elemOffset + indirectFunctions.size());
317   indirectFunctions.emplace_back(sym);
318 }
319 
320 void ElemSection::writeBody() {
321   raw_ostream &os = bodyOutputStream;
322 
323   writeUleb128(os, 1, "segment count");
324   writeUleb128(os, 0, "table index");
325   WasmInitExpr initExpr;
326   if (config->isPic) {
327     initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
328     initExpr.Value.Global = WasmSym::tableBase->getGlobalIndex();
329   } else {
330     initExpr.Opcode = WASM_OPCODE_I32_CONST;
331     initExpr.Value.Int32 = elemOffset;
332   }
333   writeInitExpr(os, initExpr);
334   writeUleb128(os, indirectFunctions.size(), "elem count");
335 
336   uint32_t tableIndex = elemOffset;
337   for (const FunctionSymbol *sym : indirectFunctions) {
338     assert(sym->getTableIndex() == tableIndex);
339     writeUleb128(os, sym->getFunctionIndex(), "function index");
340     ++tableIndex;
341   }
342 }
343 
344 void DataCountSection::writeBody() {
345   writeUleb128(bodyOutputStream, numSegments, "data count");
346 }
347 
348 bool DataCountSection::isNeeded() const {
349   return numSegments && config->passiveSegments;
350 }
351 
352 static uint32_t getWasmFlags(const Symbol *sym) {
353   uint32_t flags = 0;
354   if (sym->isLocal())
355     flags |= WASM_SYMBOL_BINDING_LOCAL;
356   if (sym->isWeak())
357     flags |= WASM_SYMBOL_BINDING_WEAK;
358   if (sym->isHidden())
359     flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
360   if (sym->isUndefined())
361     flags |= WASM_SYMBOL_UNDEFINED;
362   if (auto *f = dyn_cast<UndefinedFunction>(sym)) {
363     if (f->getName() != f->importName)
364       flags |= WASM_SYMBOL_EXPLICIT_NAME;
365   } else if (auto *g = dyn_cast<UndefinedGlobal>(sym)) {
366     if (g->getName() != g->importName)
367       flags |= WASM_SYMBOL_EXPLICIT_NAME;
368   }
369   return flags;
370 }
371 
372 void LinkingSection::writeBody() {
373   raw_ostream &os = bodyOutputStream;
374 
375   writeUleb128(os, WasmMetadataVersion, "Version");
376 
377   if (!symtabEntries.empty()) {
378     SubSection sub(WASM_SYMBOL_TABLE);
379     writeUleb128(sub.os, symtabEntries.size(), "num symbols");
380 
381     for (const Symbol *sym : symtabEntries) {
382       assert(sym->isDefined() || sym->isUndefined());
383       WasmSymbolType kind = sym->getWasmType();
384       uint32_t flags = getWasmFlags(sym);
385 
386       writeU8(sub.os, kind, "sym kind");
387       writeUleb128(sub.os, flags, "sym flags");
388 
389       if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
390         writeUleb128(sub.os, f->getFunctionIndex(), "index");
391         if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
392           writeStr(sub.os, sym->getName(), "sym name");
393       } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) {
394         writeUleb128(sub.os, g->getGlobalIndex(), "index");
395         if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
396           writeStr(sub.os, sym->getName(), "sym name");
397       } else if (auto *e = dyn_cast<EventSymbol>(sym)) {
398         writeUleb128(sub.os, e->getEventIndex(), "index");
399         if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
400           writeStr(sub.os, sym->getName(), "sym name");
401       } else if (isa<DataSymbol>(sym)) {
402         writeStr(sub.os, sym->getName(), "sym name");
403         if (auto *dataSym = dyn_cast<DefinedData>(sym)) {
404           writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");
405           writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),
406                        "data offset");
407           writeUleb128(sub.os, dataSym->getSize(), "data size");
408         }
409       } else {
410         auto *s = cast<OutputSectionSymbol>(sym);
411         writeUleb128(sub.os, s->section->sectionIndex, "sym section index");
412       }
413     }
414 
415     sub.writeTo(os);
416   }
417 
418   if (dataSegments.size()) {
419     SubSection sub(WASM_SEGMENT_INFO);
420     writeUleb128(sub.os, dataSegments.size(), "num data segments");
421     for (const OutputSegment *s : dataSegments) {
422       writeStr(sub.os, s->name, "segment name");
423       writeUleb128(sub.os, s->alignment, "alignment");
424       writeUleb128(sub.os, 0, "flags");
425     }
426     sub.writeTo(os);
427   }
428 
429   if (!initFunctions.empty()) {
430     SubSection sub(WASM_INIT_FUNCS);
431     writeUleb128(sub.os, initFunctions.size(), "num init functions");
432     for (const WasmInitEntry &f : initFunctions) {
433       writeUleb128(sub.os, f.priority, "priority");
434       writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index");
435     }
436     sub.writeTo(os);
437   }
438 
439   struct ComdatEntry {
440     unsigned kind;
441     uint32_t index;
442   };
443   std::map<StringRef, std::vector<ComdatEntry>> comdats;
444 
445   for (const InputFunction *f : out.functionSec->inputFunctions) {
446     StringRef comdat = f->getComdatName();
447     if (!comdat.empty())
448       comdats[comdat].emplace_back(
449           ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()});
450   }
451   for (uint32_t i = 0; i < dataSegments.size(); ++i) {
452     const auto &inputSegments = dataSegments[i]->inputSegments;
453     if (inputSegments.empty())
454       continue;
455     StringRef comdat = inputSegments[0]->getComdatName();
456 #ifndef NDEBUG
457     for (const InputSegment *isec : inputSegments)
458       assert(isec->getComdatName() == comdat);
459 #endif
460     if (!comdat.empty())
461       comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i});
462   }
463 
464   if (!comdats.empty()) {
465     SubSection sub(WASM_COMDAT_INFO);
466     writeUleb128(sub.os, comdats.size(), "num comdats");
467     for (const auto &c : comdats) {
468       writeStr(sub.os, c.first, "comdat name");
469       writeUleb128(sub.os, 0, "comdat flags"); // flags for future use
470       writeUleb128(sub.os, c.second.size(), "num entries");
471       for (const ComdatEntry &entry : c.second) {
472         writeU8(sub.os, entry.kind, "entry kind");
473         writeUleb128(sub.os, entry.index, "entry index");
474       }
475     }
476     sub.writeTo(os);
477   }
478 }
479 
480 void LinkingSection::addToSymtab(Symbol *sym) {
481   sym->setOutputSymbolIndex(symtabEntries.size());
482   symtabEntries.emplace_back(sym);
483 }
484 
485 unsigned NameSection::numNames() const {
486   unsigned numNames = out.importSec->getNumImportedFunctions();
487   for (const InputFunction *f : out.functionSec->inputFunctions)
488     if (!f->getName().empty() || !f->getDebugName().empty())
489       ++numNames;
490 
491   return numNames;
492 }
493 
494 // Create the custom "name" section containing debug symbol names.
495 void NameSection::writeBody() {
496   SubSection sub(WASM_NAMES_FUNCTION);
497   writeUleb128(sub.os, numNames(), "name count");
498 
499   // Names must appear in function index order.  As it happens importedSymbols
500   // and inputFunctions are numbered in order with imported functions coming
501   // first.
502   for (const Symbol *s : out.importSec->importedSymbols) {
503     if (auto *f = dyn_cast<FunctionSymbol>(s)) {
504       writeUleb128(sub.os, f->getFunctionIndex(), "func index");
505       writeStr(sub.os, toString(*s), "symbol name");
506     }
507   }
508   for (const InputFunction *f : out.functionSec->inputFunctions) {
509     if (!f->getName().empty()) {
510       writeUleb128(sub.os, f->getFunctionIndex(), "func index");
511       if (!f->getDebugName().empty()) {
512         writeStr(sub.os, f->getDebugName(), "symbol name");
513       } else {
514         writeStr(sub.os, maybeDemangleSymbol(f->getName()), "symbol name");
515       }
516     }
517   }
518 
519   sub.writeTo(bodyOutputStream);
520 }
521 
522 void ProducersSection::addInfo(const WasmProducerInfo &info) {
523   for (auto &producers :
524        {std::make_pair(&info.Languages, &languages),
525         std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)})
526     for (auto &producer : *producers.first)
527       if (producers.second->end() ==
528           llvm::find_if(*producers.second,
529                         [&](std::pair<std::string, std::string> seen) {
530                           return seen.first == producer.first;
531                         }))
532         producers.second->push_back(producer);
533 }
534 
535 void ProducersSection::writeBody() {
536   auto &os = bodyOutputStream;
537   writeUleb128(os, fieldCount(), "field count");
538   for (auto &field :
539        {std::make_pair("language", languages),
540         std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) {
541     if (field.second.empty())
542       continue;
543     writeStr(os, field.first, "field name");
544     writeUleb128(os, field.second.size(), "number of entries");
545     for (auto &entry : field.second) {
546       writeStr(os, entry.first, "producer name");
547       writeStr(os, entry.second, "producer version");
548     }
549   }
550 }
551 
552 void TargetFeaturesSection::writeBody() {
553   SmallVector<std::string, 8> emitted(features.begin(), features.end());
554   llvm::sort(emitted);
555   auto &os = bodyOutputStream;
556   writeUleb128(os, emitted.size(), "feature count");
557   for (auto &feature : emitted) {
558     writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix");
559     writeStr(os, feature, "feature name");
560   }
561 }
562 
563 void RelocSection::writeBody() {
564   uint32_t count = sec->getNumRelocations();
565   assert(sec->sectionIndex != UINT32_MAX);
566   writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section");
567   writeUleb128(bodyOutputStream, count, "reloc count");
568   sec->writeRelocations(bodyOutputStream);
569 }
570