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 namespace lld {
26 namespace wasm {
27 
28 OutStruct 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   if (sym->hasGOTIndex())
107     return;
108   LLVM_DEBUG(dbgs() << "addGOTEntry: " << toString(*sym) << "\n");
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 = config->tableBase + 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 = config->tableBase + out.elemSec->numEntries();
216 
217   raw_ostream &os = bodyOutputStream;
218   writeUleb128(os, 1, "table count");
219   WasmLimits limits;
220   if (config->growableTable)
221     limits = {0, tableSize, 0};
222   else
223     limits = {WASM_LIMITS_FLAG_HAS_MAX, tableSize, tableSize};
224   writeTableType(os, WasmTable{WASM_TYPE_FUNCREF, limits});
225 }
226 
227 void MemorySection::writeBody() {
228   raw_ostream &os = bodyOutputStream;
229 
230   bool hasMax = maxMemoryPages != 0 || config->sharedMemory;
231   writeUleb128(os, 1, "memory count");
232   unsigned flags = 0;
233   if (hasMax)
234     flags |= WASM_LIMITS_FLAG_HAS_MAX;
235   if (config->sharedMemory)
236     flags |= WASM_LIMITS_FLAG_IS_SHARED;
237   writeUleb128(os, flags, "memory limits flags");
238   writeUleb128(os, numMemoryPages, "initial pages");
239   if (hasMax)
240     writeUleb128(os, maxMemoryPages, "max pages");
241 }
242 
243 void GlobalSection::assignIndexes() {
244   uint32_t globalIndex = out.importSec->getNumImportedGlobals();
245   for (InputGlobal *g : inputGlobals)
246     g->setGlobalIndex(globalIndex++);
247   for (Symbol *sym : staticGotSymbols)
248     sym->setGOTIndex(globalIndex++);
249   isSealed = true;
250 }
251 
252 void GlobalSection::addStaticGOTEntry(Symbol *sym) {
253   assert(!isSealed);
254   if (sym->requiresGOT)
255     return;
256   LLVM_DEBUG(dbgs() << "addStaticGOTEntry: " << sym->getName() << " "
257                     << toString(sym->kind()) << "\n");
258   sym->requiresGOT = true;
259   if (auto *F = dyn_cast<FunctionSymbol>(sym))
260     out.elemSec->addEntry(F);
261   staticGotSymbols.push_back(sym);
262 }
263 
264 void GlobalSection::writeBody() {
265   raw_ostream &os = bodyOutputStream;
266 
267   writeUleb128(os, numGlobals(), "global count");
268   for (InputGlobal *g : inputGlobals)
269     writeGlobal(os, g->global);
270   for (const Symbol *sym : staticGotSymbols) {
271     WasmGlobal global;
272     global.Type = {WASM_TYPE_I32, false};
273     global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
274     if (auto *d = dyn_cast<DefinedData>(sym))
275       global.InitExpr.Value.Int32 = d->getVirtualAddress();
276     else if (auto *f = dyn_cast<FunctionSymbol>(sym))
277       global.InitExpr.Value.Int32 = f->getTableIndex();
278     else {
279       assert(isa<UndefinedData>(sym));
280       global.InitExpr.Value.Int32 = 0;
281     }
282     writeGlobal(os, global);
283   }
284   for (const DefinedData *sym : dataAddressGlobals) {
285     WasmGlobal global;
286     global.Type = {WASM_TYPE_I32, false};
287     global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
288     global.InitExpr.Value.Int32 = sym->getVirtualAddress();
289     writeGlobal(os, global);
290   }
291 }
292 
293 void GlobalSection::addGlobal(InputGlobal *global) {
294   assert(!isSealed);
295   if (!global->live)
296     return;
297   inputGlobals.push_back(global);
298 }
299 
300 void EventSection::writeBody() {
301   raw_ostream &os = bodyOutputStream;
302 
303   writeUleb128(os, inputEvents.size(), "event count");
304   for (InputEvent *e : inputEvents) {
305     e->event.Type.SigIndex = out.typeSec->lookupType(e->signature);
306     writeEvent(os, e->event);
307   }
308 }
309 
310 void EventSection::addEvent(InputEvent *event) {
311   if (!event->live)
312     return;
313   uint32_t eventIndex =
314       out.importSec->getNumImportedEvents() + inputEvents.size();
315   LLVM_DEBUG(dbgs() << "addEvent: " << eventIndex << "\n");
316   event->setEventIndex(eventIndex);
317   inputEvents.push_back(event);
318 }
319 
320 void ExportSection::writeBody() {
321   raw_ostream &os = bodyOutputStream;
322 
323   writeUleb128(os, exports.size(), "export count");
324   for (const WasmExport &export_ : exports)
325     writeExport(os, export_);
326 }
327 
328 bool StartSection::isNeeded() const {
329   return !config->relocatable && numSegments && config->sharedMemory;
330 }
331 
332 void StartSection::writeBody() {
333   raw_ostream &os = bodyOutputStream;
334   writeUleb128(os, WasmSym::initMemory->getFunctionIndex(), "function index");
335 }
336 
337 void ElemSection::addEntry(FunctionSymbol *sym) {
338   if (sym->hasTableIndex())
339     return;
340   sym->setTableIndex(config->tableBase + indirectFunctions.size());
341   indirectFunctions.emplace_back(sym);
342 }
343 
344 void ElemSection::writeBody() {
345   raw_ostream &os = bodyOutputStream;
346 
347   writeUleb128(os, 1, "segment count");
348   writeUleb128(os, 0, "table index");
349   WasmInitExpr initExpr;
350   if (config->isPic) {
351     initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
352     initExpr.Value.Global = WasmSym::tableBase->getGlobalIndex();
353   } else {
354     initExpr.Opcode = WASM_OPCODE_I32_CONST;
355     initExpr.Value.Int32 = config->tableBase;
356   }
357   writeInitExpr(os, initExpr);
358   writeUleb128(os, indirectFunctions.size(), "elem count");
359 
360   uint32_t tableIndex = config->tableBase;
361   for (const FunctionSymbol *sym : indirectFunctions) {
362     assert(sym->getTableIndex() == tableIndex);
363     writeUleb128(os, sym->getFunctionIndex(), "function index");
364     ++tableIndex;
365   }
366 }
367 
368 DataCountSection::DataCountSection(ArrayRef<OutputSegment *> segments)
369     : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT),
370       numSegments(std::count_if(
371           segments.begin(), segments.end(),
372           [](OutputSegment *const segment) { return !segment->isBss; })) {}
373 
374 void DataCountSection::writeBody() {
375   writeUleb128(bodyOutputStream, numSegments, "data count");
376 }
377 
378 bool DataCountSection::isNeeded() const {
379   return numSegments && config->sharedMemory;
380 }
381 
382 void LinkingSection::writeBody() {
383   raw_ostream &os = bodyOutputStream;
384 
385   writeUleb128(os, WasmMetadataVersion, "Version");
386 
387   if (!symtabEntries.empty()) {
388     SubSection sub(WASM_SYMBOL_TABLE);
389     writeUleb128(sub.os, symtabEntries.size(), "num symbols");
390 
391     for (const Symbol *sym : symtabEntries) {
392       assert(sym->isDefined() || sym->isUndefined());
393       WasmSymbolType kind = sym->getWasmType();
394       uint32_t flags = sym->getFlags();
395 
396       writeU8(sub.os, kind, "sym kind");
397       writeUleb128(sub.os, flags, "sym flags");
398 
399       if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
400         writeUleb128(sub.os, f->getFunctionIndex(), "index");
401         if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
402           writeStr(sub.os, sym->getName(), "sym name");
403       } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) {
404         writeUleb128(sub.os, g->getGlobalIndex(), "index");
405         if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
406           writeStr(sub.os, sym->getName(), "sym name");
407       } else if (auto *e = dyn_cast<EventSymbol>(sym)) {
408         writeUleb128(sub.os, e->getEventIndex(), "index");
409         if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
410           writeStr(sub.os, sym->getName(), "sym name");
411       } else if (isa<DataSymbol>(sym)) {
412         writeStr(sub.os, sym->getName(), "sym name");
413         if (auto *dataSym = dyn_cast<DefinedData>(sym)) {
414           writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");
415           writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),
416                        "data offset");
417           writeUleb128(sub.os, dataSym->getSize(), "data size");
418         }
419       } else {
420         auto *s = cast<OutputSectionSymbol>(sym);
421         writeUleb128(sub.os, s->section->sectionIndex, "sym section index");
422       }
423     }
424 
425     sub.writeTo(os);
426   }
427 
428   if (dataSegments.size()) {
429     SubSection sub(WASM_SEGMENT_INFO);
430     writeUleb128(sub.os, dataSegments.size(), "num data segments");
431     for (const OutputSegment *s : dataSegments) {
432       writeStr(sub.os, s->name, "segment name");
433       writeUleb128(sub.os, s->alignment, "alignment");
434       writeUleb128(sub.os, 0, "flags");
435     }
436     sub.writeTo(os);
437   }
438 
439   if (!initFunctions.empty()) {
440     SubSection sub(WASM_INIT_FUNCS);
441     writeUleb128(sub.os, initFunctions.size(), "num init functions");
442     for (const WasmInitEntry &f : initFunctions) {
443       writeUleb128(sub.os, f.priority, "priority");
444       writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index");
445     }
446     sub.writeTo(os);
447   }
448 
449   struct ComdatEntry {
450     unsigned kind;
451     uint32_t index;
452   };
453   std::map<StringRef, std::vector<ComdatEntry>> comdats;
454 
455   for (const InputFunction *f : out.functionSec->inputFunctions) {
456     StringRef comdat = f->getComdatName();
457     if (!comdat.empty())
458       comdats[comdat].emplace_back(
459           ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()});
460   }
461   for (uint32_t i = 0; i < dataSegments.size(); ++i) {
462     const auto &inputSegments = dataSegments[i]->inputSegments;
463     if (inputSegments.empty())
464       continue;
465     StringRef comdat = inputSegments[0]->getComdatName();
466 #ifndef NDEBUG
467     for (const InputSegment *isec : inputSegments)
468       assert(isec->getComdatName() == comdat);
469 #endif
470     if (!comdat.empty())
471       comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i});
472   }
473 
474   if (!comdats.empty()) {
475     SubSection sub(WASM_COMDAT_INFO);
476     writeUleb128(sub.os, comdats.size(), "num comdats");
477     for (const auto &c : comdats) {
478       writeStr(sub.os, c.first, "comdat name");
479       writeUleb128(sub.os, 0, "comdat flags"); // flags for future use
480       writeUleb128(sub.os, c.second.size(), "num entries");
481       for (const ComdatEntry &entry : c.second) {
482         writeU8(sub.os, entry.kind, "entry kind");
483         writeUleb128(sub.os, entry.index, "entry index");
484       }
485     }
486     sub.writeTo(os);
487   }
488 }
489 
490 void LinkingSection::addToSymtab(Symbol *sym) {
491   sym->setOutputSymbolIndex(symtabEntries.size());
492   symtabEntries.emplace_back(sym);
493 }
494 
495 unsigned NameSection::numNames() const {
496   unsigned numNames = out.importSec->getNumImportedFunctions();
497   for (const InputFunction *f : out.functionSec->inputFunctions)
498     if (!f->getName().empty() || !f->getDebugName().empty())
499       ++numNames;
500 
501   return numNames;
502 }
503 
504 // Create the custom "name" section containing debug symbol names.
505 void NameSection::writeBody() {
506   SubSection sub(WASM_NAMES_FUNCTION);
507   writeUleb128(sub.os, numNames(), "name count");
508 
509   // Names must appear in function index order.  As it happens importedSymbols
510   // and inputFunctions are numbered in order with imported functions coming
511   // first.
512   for (const Symbol *s : out.importSec->importedSymbols) {
513     if (auto *f = dyn_cast<FunctionSymbol>(s)) {
514       writeUleb128(sub.os, f->getFunctionIndex(), "func index");
515       writeStr(sub.os, toString(*s), "symbol name");
516     }
517   }
518   for (const InputFunction *f : out.functionSec->inputFunctions) {
519     if (!f->getName().empty()) {
520       writeUleb128(sub.os, f->getFunctionIndex(), "func index");
521       if (!f->getDebugName().empty()) {
522         writeStr(sub.os, f->getDebugName(), "symbol name");
523       } else {
524         writeStr(sub.os, maybeDemangleSymbol(f->getName()), "symbol name");
525       }
526     }
527   }
528 
529   sub.writeTo(bodyOutputStream);
530 }
531 
532 void ProducersSection::addInfo(const WasmProducerInfo &info) {
533   for (auto &producers :
534        {std::make_pair(&info.Languages, &languages),
535         std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)})
536     for (auto &producer : *producers.first)
537       if (producers.second->end() ==
538           llvm::find_if(*producers.second,
539                         [&](std::pair<std::string, std::string> seen) {
540                           return seen.first == producer.first;
541                         }))
542         producers.second->push_back(producer);
543 }
544 
545 void ProducersSection::writeBody() {
546   auto &os = bodyOutputStream;
547   writeUleb128(os, fieldCount(), "field count");
548   for (auto &field :
549        {std::make_pair("language", languages),
550         std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) {
551     if (field.second.empty())
552       continue;
553     writeStr(os, field.first, "field name");
554     writeUleb128(os, field.second.size(), "number of entries");
555     for (auto &entry : field.second) {
556       writeStr(os, entry.first, "producer name");
557       writeStr(os, entry.second, "producer version");
558     }
559   }
560 }
561 
562 void TargetFeaturesSection::writeBody() {
563   SmallVector<std::string, 8> emitted(features.begin(), features.end());
564   llvm::sort(emitted);
565   auto &os = bodyOutputStream;
566   writeUleb128(os, emitted.size(), "feature count");
567   for (auto &feature : emitted) {
568     writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix");
569     writeStr(os, feature, "feature name");
570   }
571 }
572 
573 void RelocSection::writeBody() {
574   uint32_t count = sec->getNumRelocations();
575   assert(sec->sectionIndex != UINT32_MAX);
576   writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section");
577   writeUleb128(bodyOutputStream, count, "reloc count");
578   sec->writeRelocations(bodyOutputStream);
579 }
580 
581 } // namespace wasm
582 } // namespace lld
583