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   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, getNumImports(), "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->getNumImportedFunctions() + 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->getNumImportedGlobals() + 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 =
277       out.importSec->getNumImportedEvents() + inputEvents.size();
278   LLVM_DEBUG(dbgs() << "addEvent: " << eventIndex << "\n");
279   event->setEventIndex(eventIndex);
280   inputEvents.push_back(event);
281 }
282 
283 void ExportSection::writeBody() {
284   raw_ostream &os = bodyOutputStream;
285 
286   writeUleb128(os, exports.size(), "export count");
287   for (const WasmExport &export_ : exports)
288     writeExport(os, export_);
289 }
290 
291 void ElemSection::addEntry(FunctionSymbol *sym) {
292   if (sym->hasTableIndex())
293     return;
294   sym->setTableIndex(elemOffset + indirectFunctions.size());
295   indirectFunctions.emplace_back(sym);
296 }
297 
298 void ElemSection::writeBody() {
299   raw_ostream &os = bodyOutputStream;
300 
301   writeUleb128(os, 1, "segment count");
302   writeUleb128(os, 0, "table index");
303   WasmInitExpr initExpr;
304   if (config->isPic) {
305     initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
306     initExpr.Value.Global = WasmSym::tableBase->getGlobalIndex();
307   } else {
308     initExpr.Opcode = WASM_OPCODE_I32_CONST;
309     initExpr.Value.Int32 = elemOffset;
310   }
311   writeInitExpr(os, initExpr);
312   writeUleb128(os, indirectFunctions.size(), "elem count");
313 
314   uint32_t tableIndex = elemOffset;
315   for (const FunctionSymbol *sym : indirectFunctions) {
316     assert(sym->getTableIndex() == tableIndex);
317     writeUleb128(os, sym->getFunctionIndex(), "function index");
318     ++tableIndex;
319   }
320 }
321 
322 void DataCountSection::writeBody() {
323   writeUleb128(bodyOutputStream, numSegments, "data count");
324 }
325 
326 bool DataCountSection::isNeeded() const {
327   return numSegments && config->passiveSegments;
328 }
329 
330 static uint32_t getWasmFlags(const Symbol *sym) {
331   uint32_t flags = 0;
332   if (sym->isLocal())
333     flags |= WASM_SYMBOL_BINDING_LOCAL;
334   if (sym->isWeak())
335     flags |= WASM_SYMBOL_BINDING_WEAK;
336   if (sym->isHidden())
337     flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
338   if (sym->isUndefined())
339     flags |= WASM_SYMBOL_UNDEFINED;
340   if (auto *f = dyn_cast<UndefinedFunction>(sym)) {
341     if (f->getName() != f->importName)
342       flags |= WASM_SYMBOL_EXPLICIT_NAME;
343   } else if (auto *g = dyn_cast<UndefinedGlobal>(sym)) {
344     if (g->getName() != g->importName)
345       flags |= WASM_SYMBOL_EXPLICIT_NAME;
346   }
347   return flags;
348 }
349 
350 void LinkingSection::writeBody() {
351   raw_ostream &os = bodyOutputStream;
352 
353   writeUleb128(os, WasmMetadataVersion, "Version");
354 
355   if (!symtabEntries.empty()) {
356     SubSection sub(WASM_SYMBOL_TABLE);
357     writeUleb128(sub.os, symtabEntries.size(), "num symbols");
358 
359     for (const Symbol *sym : symtabEntries) {
360       assert(sym->isDefined() || sym->isUndefined());
361       WasmSymbolType kind = sym->getWasmType();
362       uint32_t flags = getWasmFlags(sym);
363 
364       writeU8(sub.os, kind, "sym kind");
365       writeUleb128(sub.os, flags, "sym flags");
366 
367       if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
368         writeUleb128(sub.os, f->getFunctionIndex(), "index");
369         if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
370           writeStr(sub.os, sym->getName(), "sym name");
371       } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) {
372         writeUleb128(sub.os, g->getGlobalIndex(), "index");
373         if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
374           writeStr(sub.os, sym->getName(), "sym name");
375       } else if (auto *e = dyn_cast<EventSymbol>(sym)) {
376         writeUleb128(sub.os, e->getEventIndex(), "index");
377         if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
378           writeStr(sub.os, sym->getName(), "sym name");
379       } else if (isa<DataSymbol>(sym)) {
380         writeStr(sub.os, sym->getName(), "sym name");
381         if (auto *dataSym = dyn_cast<DefinedData>(sym)) {
382           writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");
383           writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),
384                        "data offset");
385           writeUleb128(sub.os, dataSym->getSize(), "data size");
386         }
387       } else {
388         auto *s = cast<OutputSectionSymbol>(sym);
389         writeUleb128(sub.os, s->section->sectionIndex, "sym section index");
390       }
391     }
392 
393     sub.writeTo(os);
394   }
395 
396   if (dataSegments.size()) {
397     SubSection sub(WASM_SEGMENT_INFO);
398     writeUleb128(sub.os, dataSegments.size(), "num data segments");
399     for (const OutputSegment *s : dataSegments) {
400       writeStr(sub.os, s->name, "segment name");
401       writeUleb128(sub.os, s->alignment, "alignment");
402       writeUleb128(sub.os, 0, "flags");
403     }
404     sub.writeTo(os);
405   }
406 
407   if (!initFunctions.empty()) {
408     SubSection sub(WASM_INIT_FUNCS);
409     writeUleb128(sub.os, initFunctions.size(), "num init functions");
410     for (const WasmInitEntry &f : initFunctions) {
411       writeUleb128(sub.os, f.priority, "priority");
412       writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index");
413     }
414     sub.writeTo(os);
415   }
416 
417   struct ComdatEntry {
418     unsigned kind;
419     uint32_t index;
420   };
421   std::map<StringRef, std::vector<ComdatEntry>> comdats;
422 
423   for (const InputFunction *f : out.functionSec->inputFunctions) {
424     StringRef comdat = f->getComdatName();
425     if (!comdat.empty())
426       comdats[comdat].emplace_back(
427           ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()});
428   }
429   for (uint32_t i = 0; i < dataSegments.size(); ++i) {
430     const auto &inputSegments = dataSegments[i]->inputSegments;
431     if (inputSegments.empty())
432       continue;
433     StringRef comdat = inputSegments[0]->getComdatName();
434 #ifndef NDEBUG
435     for (const InputSegment *isec : inputSegments)
436       assert(isec->getComdatName() == comdat);
437 #endif
438     if (!comdat.empty())
439       comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i});
440   }
441 
442   if (!comdats.empty()) {
443     SubSection sub(WASM_COMDAT_INFO);
444     writeUleb128(sub.os, comdats.size(), "num comdats");
445     for (const auto &c : comdats) {
446       writeStr(sub.os, c.first, "comdat name");
447       writeUleb128(sub.os, 0, "comdat flags"); // flags for future use
448       writeUleb128(sub.os, c.second.size(), "num entries");
449       for (const ComdatEntry &entry : c.second) {
450         writeU8(sub.os, entry.kind, "entry kind");
451         writeUleb128(sub.os, entry.index, "entry index");
452       }
453     }
454     sub.writeTo(os);
455   }
456 }
457 
458 void LinkingSection::addToSymtab(Symbol *sym) {
459   sym->setOutputSymbolIndex(symtabEntries.size());
460   symtabEntries.emplace_back(sym);
461 }
462 
463 unsigned NameSection::numNames() const {
464   unsigned numNames = out.importSec->getNumImportedFunctions();
465   for (const InputFunction *f : out.functionSec->inputFunctions)
466     if (!f->getName().empty() || !f->getDebugName().empty())
467       ++numNames;
468 
469   return numNames;
470 }
471 
472 // Create the custom "name" section containing debug symbol names.
473 void NameSection::writeBody() {
474   SubSection sub(WASM_NAMES_FUNCTION);
475   writeUleb128(sub.os, numNames(), "name count");
476 
477   // Names must appear in function index order.  As it happens importedSymbols
478   // and inputFunctions are numbered in order with imported functions coming
479   // first.
480   for (const Symbol *s : out.importSec->importedSymbols) {
481     if (auto *f = dyn_cast<FunctionSymbol>(s)) {
482       writeUleb128(sub.os, f->getFunctionIndex(), "func index");
483       writeStr(sub.os, toString(*s), "symbol name");
484     }
485   }
486   for (const InputFunction *f : out.functionSec->inputFunctions) {
487     if (!f->getName().empty()) {
488       writeUleb128(sub.os, f->getFunctionIndex(), "func index");
489       if (!f->getDebugName().empty()) {
490         writeStr(sub.os, f->getDebugName(), "symbol name");
491       } else {
492         writeStr(sub.os, maybeDemangleSymbol(f->getName()), "symbol name");
493       }
494     }
495   }
496 
497   sub.writeTo(bodyOutputStream);
498 }
499 
500 void ProducersSection::addInfo(const WasmProducerInfo &info) {
501   for (auto &producers :
502        {std::make_pair(&info.Languages, &languages),
503         std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)})
504     for (auto &producer : *producers.first)
505       if (producers.second->end() ==
506           llvm::find_if(*producers.second,
507                         [&](std::pair<std::string, std::string> seen) {
508                           return seen.first == producer.first;
509                         }))
510         producers.second->push_back(producer);
511 }
512 
513 void ProducersSection::writeBody() {
514   auto &os = bodyOutputStream;
515   writeUleb128(os, fieldCount(), "field count");
516   for (auto &field :
517        {std::make_pair("language", languages),
518         std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) {
519     if (field.second.empty())
520       continue;
521     writeStr(os, field.first, "field name");
522     writeUleb128(os, field.second.size(), "number of entries");
523     for (auto &entry : field.second) {
524       writeStr(os, entry.first, "producer name");
525       writeStr(os, entry.second, "producer version");
526     }
527   }
528 }
529 
530 void TargetFeaturesSection::writeBody() {
531   SmallVector<std::string, 8> emitted(features.begin(), features.end());
532   llvm::sort(emitted);
533   auto &os = bodyOutputStream;
534   writeUleb128(os, emitted.size(), "feature count");
535   for (auto &feature : emitted) {
536     writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix");
537     writeStr(os, feature, "feature name");
538   }
539 }
540 
541 void RelocSection::writeBody() {
542   uint32_t count = sec->getNumRelocations();
543   assert(sec->sectionIndex != UINT32_MAX);
544   writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section");
545   writeUleb128(bodyOutputStream, count, "reloc count");
546   sec->writeRelocations(bodyOutputStream);
547 }
548