1ece8a530Spatrick //===- SyntheticSections.cpp ----------------------------------------------===//
2ece8a530Spatrick //
3ece8a530Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ece8a530Spatrick // See https://llvm.org/LICENSE.txt for license information.
5ece8a530Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ece8a530Spatrick //
7ece8a530Spatrick //===----------------------------------------------------------------------===//
8ece8a530Spatrick //
9ece8a530Spatrick // This file contains linker-synthesized sections.
10ece8a530Spatrick //
11ece8a530Spatrick //===----------------------------------------------------------------------===//
12ece8a530Spatrick
13ece8a530Spatrick #include "SyntheticSections.h"
14ece8a530Spatrick
15ece8a530Spatrick #include "InputChunks.h"
161cf9926bSpatrick #include "InputElement.h"
17ece8a530Spatrick #include "OutputSegment.h"
18ece8a530Spatrick #include "SymbolTable.h"
19ece8a530Spatrick #include "llvm/Support/Path.h"
20*dfe94b16Srobert #include <optional>
21ece8a530Spatrick
22ece8a530Spatrick using namespace llvm;
23ece8a530Spatrick using namespace llvm::wasm;
24ece8a530Spatrick
25ece8a530Spatrick namespace lld {
26ece8a530Spatrick namespace wasm {
27ece8a530Spatrick
28ece8a530Spatrick OutStruct out;
29ece8a530Spatrick
30ece8a530Spatrick namespace {
31ece8a530Spatrick
32ece8a530Spatrick // Some synthetic sections (e.g. "name" and "linking") have subsections.
33ece8a530Spatrick // Just like the synthetic sections themselves these need to be created before
34ece8a530Spatrick // they can be written out (since they are preceded by their length). This
35ece8a530Spatrick // class is used to create subsections and then write them into the stream
36ece8a530Spatrick // of the parent section.
37ece8a530Spatrick class SubSection {
38ece8a530Spatrick public:
SubSection(uint32_t type)39ece8a530Spatrick explicit SubSection(uint32_t type) : type(type) {}
40ece8a530Spatrick
writeTo(raw_ostream & to)41ece8a530Spatrick void writeTo(raw_ostream &to) {
42ece8a530Spatrick os.flush();
43ece8a530Spatrick writeUleb128(to, type, "subsection type");
44ece8a530Spatrick writeUleb128(to, body.size(), "subsection size");
45ece8a530Spatrick to.write(body.data(), body.size());
46ece8a530Spatrick }
47ece8a530Spatrick
48ece8a530Spatrick private:
49ece8a530Spatrick uint32_t type;
50ece8a530Spatrick std::string body;
51ece8a530Spatrick
52ece8a530Spatrick public:
53ece8a530Spatrick raw_string_ostream os{body};
54ece8a530Spatrick };
55ece8a530Spatrick
56ece8a530Spatrick } // namespace
57ece8a530Spatrick
isNeeded() const58*dfe94b16Srobert bool DylinkSection::isNeeded() const {
59*dfe94b16Srobert return config->isPic ||
60*dfe94b16Srobert config->unresolvedSymbols == UnresolvedPolicy::ImportDynamic ||
61*dfe94b16Srobert !symtab->sharedFiles.empty();
62*dfe94b16Srobert }
63*dfe94b16Srobert
writeBody()64ece8a530Spatrick void DylinkSection::writeBody() {
65ece8a530Spatrick raw_ostream &os = bodyOutputStream;
66ece8a530Spatrick
67*dfe94b16Srobert {
68*dfe94b16Srobert SubSection sub(WASM_DYLINK_MEM_INFO);
69*dfe94b16Srobert writeUleb128(sub.os, memSize, "MemSize");
70*dfe94b16Srobert writeUleb128(sub.os, memAlign, "MemAlign");
71*dfe94b16Srobert writeUleb128(sub.os, out.elemSec->numEntries(), "TableSize");
72*dfe94b16Srobert writeUleb128(sub.os, 0, "TableAlign");
73*dfe94b16Srobert sub.writeTo(os);
74*dfe94b16Srobert }
75*dfe94b16Srobert
76*dfe94b16Srobert if (symtab->sharedFiles.size()) {
77*dfe94b16Srobert SubSection sub(WASM_DYLINK_NEEDED);
78*dfe94b16Srobert writeUleb128(sub.os, symtab->sharedFiles.size(), "Needed");
79ece8a530Spatrick for (auto *so : symtab->sharedFiles)
80*dfe94b16Srobert writeStr(sub.os, llvm::sys::path::filename(so->getName()), "so name");
81*dfe94b16Srobert sub.writeTo(os);
82*dfe94b16Srobert }
83*dfe94b16Srobert
84*dfe94b16Srobert // Under certain circumstances we need to include extra information about our
85*dfe94b16Srobert // exports and/or imports to the dynamic linker.
86*dfe94b16Srobert // For exports we need to notify the linker when an export is TLS since the
87*dfe94b16Srobert // exported value is relative to __tls_base rather than __memory_base.
88*dfe94b16Srobert // For imports we need to notify the dynamic linker when an import is weak
89*dfe94b16Srobert // so that knows not to report an error for such symbols.
90*dfe94b16Srobert std::vector<const Symbol *> importInfo;
91*dfe94b16Srobert std::vector<const Symbol *> exportInfo;
92*dfe94b16Srobert for (const Symbol *sym : symtab->symbols()) {
93*dfe94b16Srobert if (sym->isLive()) {
94*dfe94b16Srobert if (sym->isExported() && sym->isTLS() && isa<DefinedData>(sym)) {
95*dfe94b16Srobert exportInfo.push_back(sym);
96*dfe94b16Srobert }
97*dfe94b16Srobert if (sym->isUndefWeak()) {
98*dfe94b16Srobert importInfo.push_back(sym);
99*dfe94b16Srobert }
100*dfe94b16Srobert }
101*dfe94b16Srobert }
102*dfe94b16Srobert
103*dfe94b16Srobert if (!exportInfo.empty()) {
104*dfe94b16Srobert SubSection sub(WASM_DYLINK_EXPORT_INFO);
105*dfe94b16Srobert writeUleb128(sub.os, exportInfo.size(), "num exports");
106*dfe94b16Srobert
107*dfe94b16Srobert for (const Symbol *sym : exportInfo) {
108*dfe94b16Srobert LLVM_DEBUG(llvm::dbgs() << "export info: " << toString(*sym) << "\n");
109*dfe94b16Srobert StringRef name = sym->getName();
110*dfe94b16Srobert if (auto *f = dyn_cast<DefinedFunction>(sym)) {
111*dfe94b16Srobert if (std::optional<StringRef> exportName =
112*dfe94b16Srobert f->function->getExportName()) {
113*dfe94b16Srobert name = *exportName;
114*dfe94b16Srobert }
115*dfe94b16Srobert }
116*dfe94b16Srobert writeStr(sub.os, name, "sym name");
117*dfe94b16Srobert writeUleb128(sub.os, sym->flags, "sym flags");
118*dfe94b16Srobert }
119*dfe94b16Srobert
120*dfe94b16Srobert sub.writeTo(os);
121*dfe94b16Srobert }
122*dfe94b16Srobert
123*dfe94b16Srobert if (!importInfo.empty()) {
124*dfe94b16Srobert SubSection sub(WASM_DYLINK_IMPORT_INFO);
125*dfe94b16Srobert writeUleb128(sub.os, importInfo.size(), "num imports");
126*dfe94b16Srobert
127*dfe94b16Srobert for (const Symbol *sym : importInfo) {
128*dfe94b16Srobert LLVM_DEBUG(llvm::dbgs() << "imports info: " << toString(*sym) << "\n");
129*dfe94b16Srobert StringRef module = sym->importModule.value_or(defaultModule);
130*dfe94b16Srobert StringRef name = sym->importName.value_or(sym->getName());
131*dfe94b16Srobert writeStr(sub.os, module, "import module");
132*dfe94b16Srobert writeStr(sub.os, name, "import name");
133*dfe94b16Srobert writeUleb128(sub.os, sym->flags, "sym flags");
134*dfe94b16Srobert }
135*dfe94b16Srobert
136*dfe94b16Srobert sub.writeTo(os);
137*dfe94b16Srobert }
138ece8a530Spatrick }
139ece8a530Spatrick
registerType(const WasmSignature & sig)140ece8a530Spatrick uint32_t TypeSection::registerType(const WasmSignature &sig) {
141ece8a530Spatrick auto pair = typeIndices.insert(std::make_pair(sig, types.size()));
142ece8a530Spatrick if (pair.second) {
143ece8a530Spatrick LLVM_DEBUG(llvm::dbgs() << "type " << toString(sig) << "\n");
144ece8a530Spatrick types.push_back(&sig);
145ece8a530Spatrick }
146ece8a530Spatrick return pair.first->second;
147ece8a530Spatrick }
148ece8a530Spatrick
lookupType(const WasmSignature & sig)149ece8a530Spatrick uint32_t TypeSection::lookupType(const WasmSignature &sig) {
150ece8a530Spatrick auto it = typeIndices.find(sig);
151ece8a530Spatrick if (it == typeIndices.end()) {
152ece8a530Spatrick error("type not found: " + toString(sig));
153ece8a530Spatrick return 0;
154ece8a530Spatrick }
155ece8a530Spatrick return it->second;
156ece8a530Spatrick }
157ece8a530Spatrick
writeBody()158ece8a530Spatrick void TypeSection::writeBody() {
159ece8a530Spatrick writeUleb128(bodyOutputStream, types.size(), "type count");
160ece8a530Spatrick for (const WasmSignature *sig : types)
161ece8a530Spatrick writeSig(bodyOutputStream, *sig);
162ece8a530Spatrick }
163ece8a530Spatrick
getNumImports() const164ece8a530Spatrick uint32_t ImportSection::getNumImports() const {
165ece8a530Spatrick assert(isSealed);
166ece8a530Spatrick uint32_t numImports = importedSymbols.size() + gotSymbols.size();
167*dfe94b16Srobert if (config->memoryImport.has_value())
168ece8a530Spatrick ++numImports;
169ece8a530Spatrick return numImports;
170ece8a530Spatrick }
171ece8a530Spatrick
addGOTEntry(Symbol * sym)172ece8a530Spatrick void ImportSection::addGOTEntry(Symbol *sym) {
173ece8a530Spatrick assert(!isSealed);
174ece8a530Spatrick if (sym->hasGOTIndex())
175ece8a530Spatrick return;
176ece8a530Spatrick LLVM_DEBUG(dbgs() << "addGOTEntry: " << toString(*sym) << "\n");
177ece8a530Spatrick sym->setGOTIndex(numImportedGlobals++);
178*dfe94b16Srobert if (config->isPic) {
179*dfe94b16Srobert // Any symbol that is assigned an normal GOT entry must be exported
180*dfe94b16Srobert // otherwise the dynamic linker won't be able create the entry that contains
181*dfe94b16Srobert // it.
182*dfe94b16Srobert sym->forceExport = true;
183*dfe94b16Srobert }
184ece8a530Spatrick gotSymbols.push_back(sym);
185ece8a530Spatrick }
186ece8a530Spatrick
addImport(Symbol * sym)187ece8a530Spatrick void ImportSection::addImport(Symbol *sym) {
188ece8a530Spatrick assert(!isSealed);
189*dfe94b16Srobert StringRef module = sym->importModule.value_or(defaultModule);
190*dfe94b16Srobert StringRef name = sym->importName.value_or(sym->getName());
1911cf9926bSpatrick if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
1921cf9926bSpatrick ImportKey<WasmSignature> key(*(f->getSignature()), module, name);
1931cf9926bSpatrick auto entry = importedFunctions.try_emplace(key, numImportedFunctions);
1941cf9926bSpatrick if (entry.second) {
195ece8a530Spatrick importedSymbols.emplace_back(sym);
196ece8a530Spatrick f->setFunctionIndex(numImportedFunctions++);
1971cf9926bSpatrick } else {
1981cf9926bSpatrick f->setFunctionIndex(entry.first->second);
1991cf9926bSpatrick }
2001cf9926bSpatrick } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) {
2011cf9926bSpatrick ImportKey<WasmGlobalType> key(*(g->getGlobalType()), module, name);
2021cf9926bSpatrick auto entry = importedGlobals.try_emplace(key, numImportedGlobals);
2031cf9926bSpatrick if (entry.second) {
2041cf9926bSpatrick importedSymbols.emplace_back(sym);
205ece8a530Spatrick g->setGlobalIndex(numImportedGlobals++);
2061cf9926bSpatrick } else {
2071cf9926bSpatrick g->setGlobalIndex(entry.first->second);
2081cf9926bSpatrick }
2091cf9926bSpatrick } else if (auto *t = dyn_cast<TagSymbol>(sym)) {
210*dfe94b16Srobert ImportKey<WasmSignature> key(*(t->getSignature()), module, name);
211*dfe94b16Srobert auto entry = importedTags.try_emplace(key, numImportedTags);
212*dfe94b16Srobert if (entry.second) {
2131cf9926bSpatrick importedSymbols.emplace_back(sym);
2141cf9926bSpatrick t->setTagIndex(numImportedTags++);
2151cf9926bSpatrick } else {
216*dfe94b16Srobert t->setTagIndex(entry.first->second);
217*dfe94b16Srobert }
218*dfe94b16Srobert } else {
2191cf9926bSpatrick assert(TableSymbol::classof(sym));
2201cf9926bSpatrick auto *table = cast<TableSymbol>(sym);
2211cf9926bSpatrick ImportKey<WasmTableType> key(*(table->getTableType()), module, name);
2221cf9926bSpatrick auto entry = importedTables.try_emplace(key, numImportedTables);
2231cf9926bSpatrick if (entry.second) {
2241cf9926bSpatrick importedSymbols.emplace_back(sym);
2251cf9926bSpatrick table->setTableNumber(numImportedTables++);
2261cf9926bSpatrick } else {
2271cf9926bSpatrick table->setTableNumber(entry.first->second);
2281cf9926bSpatrick }
2291cf9926bSpatrick }
230ece8a530Spatrick }
231ece8a530Spatrick
writeBody()232ece8a530Spatrick void ImportSection::writeBody() {
233ece8a530Spatrick raw_ostream &os = bodyOutputStream;
234ece8a530Spatrick
235ece8a530Spatrick writeUleb128(os, getNumImports(), "import count");
236ece8a530Spatrick
237*dfe94b16Srobert bool is64 = config->is64.value_or(false);
2381cf9926bSpatrick
239*dfe94b16Srobert if (config->memoryImport) {
240ece8a530Spatrick WasmImport import;
241*dfe94b16Srobert import.Module = config->memoryImport->first;
242*dfe94b16Srobert import.Field = config->memoryImport->second;
243ece8a530Spatrick import.Kind = WASM_EXTERNAL_MEMORY;
244ece8a530Spatrick import.Memory.Flags = 0;
2451cf9926bSpatrick import.Memory.Minimum = out.memorySec->numMemoryPages;
246ece8a530Spatrick if (out.memorySec->maxMemoryPages != 0 || config->sharedMemory) {
247ece8a530Spatrick import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
248ece8a530Spatrick import.Memory.Maximum = out.memorySec->maxMemoryPages;
249ece8a530Spatrick }
250ece8a530Spatrick if (config->sharedMemory)
251ece8a530Spatrick import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED;
2521cf9926bSpatrick if (is64)
253bb684c34Spatrick import.Memory.Flags |= WASM_LIMITS_FLAG_IS_64;
254ece8a530Spatrick writeImport(os, import);
255ece8a530Spatrick }
256ece8a530Spatrick
257ece8a530Spatrick for (const Symbol *sym : importedSymbols) {
258ece8a530Spatrick WasmImport import;
259*dfe94b16Srobert import.Field = sym->importName.value_or(sym->getName());
260*dfe94b16Srobert import.Module = sym->importModule.value_or(defaultModule);
261ece8a530Spatrick
262ece8a530Spatrick if (auto *functionSym = dyn_cast<FunctionSymbol>(sym)) {
263ece8a530Spatrick import.Kind = WASM_EXTERNAL_FUNCTION;
264ece8a530Spatrick import.SigIndex = out.typeSec->lookupType(*functionSym->signature);
265ece8a530Spatrick } else if (auto *globalSym = dyn_cast<GlobalSymbol>(sym)) {
266ece8a530Spatrick import.Kind = WASM_EXTERNAL_GLOBAL;
267ece8a530Spatrick import.Global = *globalSym->getGlobalType();
2681cf9926bSpatrick } else if (auto *tagSym = dyn_cast<TagSymbol>(sym)) {
2691cf9926bSpatrick import.Kind = WASM_EXTERNAL_TAG;
270*dfe94b16Srobert import.SigIndex = out.typeSec->lookupType(*tagSym->signature);
271ece8a530Spatrick } else {
2721cf9926bSpatrick auto *tableSym = cast<TableSymbol>(sym);
2731cf9926bSpatrick import.Kind = WASM_EXTERNAL_TABLE;
2741cf9926bSpatrick import.Table = *tableSym->getTableType();
275ece8a530Spatrick }
276ece8a530Spatrick writeImport(os, import);
277ece8a530Spatrick }
278ece8a530Spatrick
279ece8a530Spatrick for (const Symbol *sym : gotSymbols) {
280ece8a530Spatrick WasmImport import;
281ece8a530Spatrick import.Kind = WASM_EXTERNAL_GLOBAL;
2821cf9926bSpatrick auto ptrType = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32;
2831cf9926bSpatrick import.Global = {static_cast<uint8_t>(ptrType), true};
284ece8a530Spatrick if (isa<DataSymbol>(sym))
285ece8a530Spatrick import.Module = "GOT.mem";
286ece8a530Spatrick else
287ece8a530Spatrick import.Module = "GOT.func";
288ece8a530Spatrick import.Field = sym->getName();
289ece8a530Spatrick writeImport(os, import);
290ece8a530Spatrick }
291ece8a530Spatrick }
292ece8a530Spatrick
writeBody()293ece8a530Spatrick void FunctionSection::writeBody() {
294ece8a530Spatrick raw_ostream &os = bodyOutputStream;
295ece8a530Spatrick
296ece8a530Spatrick writeUleb128(os, inputFunctions.size(), "function count");
297ece8a530Spatrick for (const InputFunction *func : inputFunctions)
298ece8a530Spatrick writeUleb128(os, out.typeSec->lookupType(func->signature), "sig index");
299ece8a530Spatrick }
300ece8a530Spatrick
addFunction(InputFunction * func)301ece8a530Spatrick void FunctionSection::addFunction(InputFunction *func) {
302ece8a530Spatrick if (!func->live)
303ece8a530Spatrick return;
304ece8a530Spatrick uint32_t functionIndex =
305ece8a530Spatrick out.importSec->getNumImportedFunctions() + inputFunctions.size();
306ece8a530Spatrick inputFunctions.emplace_back(func);
307ece8a530Spatrick func->setFunctionIndex(functionIndex);
308ece8a530Spatrick }
309ece8a530Spatrick
writeBody()310ece8a530Spatrick void TableSection::writeBody() {
311ece8a530Spatrick raw_ostream &os = bodyOutputStream;
3121cf9926bSpatrick
3131cf9926bSpatrick writeUleb128(os, inputTables.size(), "table count");
3141cf9926bSpatrick for (const InputTable *table : inputTables)
3151cf9926bSpatrick writeTableType(os, table->getType());
3161cf9926bSpatrick }
3171cf9926bSpatrick
addTable(InputTable * table)3181cf9926bSpatrick void TableSection::addTable(InputTable *table) {
3191cf9926bSpatrick if (!table->live)
3201cf9926bSpatrick return;
3211cf9926bSpatrick // Some inputs require that the indirect function table be assigned to table
3221cf9926bSpatrick // number 0.
3231cf9926bSpatrick if (config->legacyFunctionTable &&
3241cf9926bSpatrick isa<DefinedTable>(WasmSym::indirectFunctionTable) &&
3251cf9926bSpatrick cast<DefinedTable>(WasmSym::indirectFunctionTable)->table == table) {
3261cf9926bSpatrick if (out.importSec->getNumImportedTables()) {
3271cf9926bSpatrick // Alack! Some other input imported a table, meaning that we are unable
3281cf9926bSpatrick // to assign table number 0 to the indirect function table.
3291cf9926bSpatrick for (const auto *culprit : out.importSec->importedSymbols) {
3301cf9926bSpatrick if (isa<UndefinedTable>(culprit)) {
3311cf9926bSpatrick error("object file not built with 'reference-types' feature "
3321cf9926bSpatrick "conflicts with import of table " +
3331cf9926bSpatrick culprit->getName() + " by file " +
3341cf9926bSpatrick toString(culprit->getFile()));
3351cf9926bSpatrick return;
3361cf9926bSpatrick }
3371cf9926bSpatrick }
3381cf9926bSpatrick llvm_unreachable("failed to find conflicting table import");
3391cf9926bSpatrick }
3401cf9926bSpatrick inputTables.insert(inputTables.begin(), table);
3411cf9926bSpatrick return;
3421cf9926bSpatrick }
3431cf9926bSpatrick inputTables.push_back(table);
3441cf9926bSpatrick }
3451cf9926bSpatrick
assignIndexes()3461cf9926bSpatrick void TableSection::assignIndexes() {
3471cf9926bSpatrick uint32_t tableNumber = out.importSec->getNumImportedTables();
3481cf9926bSpatrick for (InputTable *t : inputTables)
3491cf9926bSpatrick t->assignIndex(tableNumber++);
350ece8a530Spatrick }
351ece8a530Spatrick
writeBody()352ece8a530Spatrick void MemorySection::writeBody() {
353ece8a530Spatrick raw_ostream &os = bodyOutputStream;
354ece8a530Spatrick
355ece8a530Spatrick bool hasMax = maxMemoryPages != 0 || config->sharedMemory;
356ece8a530Spatrick writeUleb128(os, 1, "memory count");
357ece8a530Spatrick unsigned flags = 0;
358ece8a530Spatrick if (hasMax)
359ece8a530Spatrick flags |= WASM_LIMITS_FLAG_HAS_MAX;
360ece8a530Spatrick if (config->sharedMemory)
361ece8a530Spatrick flags |= WASM_LIMITS_FLAG_IS_SHARED;
362*dfe94b16Srobert if (config->is64.value_or(false))
363bb684c34Spatrick flags |= WASM_LIMITS_FLAG_IS_64;
364ece8a530Spatrick writeUleb128(os, flags, "memory limits flags");
365ece8a530Spatrick writeUleb128(os, numMemoryPages, "initial pages");
366ece8a530Spatrick if (hasMax)
367ece8a530Spatrick writeUleb128(os, maxMemoryPages, "max pages");
368ece8a530Spatrick }
369ece8a530Spatrick
writeBody()3701cf9926bSpatrick void TagSection::writeBody() {
371bb684c34Spatrick raw_ostream &os = bodyOutputStream;
372bb684c34Spatrick
3731cf9926bSpatrick writeUleb128(os, inputTags.size(), "tag count");
3741cf9926bSpatrick for (InputTag *t : inputTags) {
375*dfe94b16Srobert writeUleb128(os, 0, "tag attribute"); // Reserved "attribute" field
376*dfe94b16Srobert writeUleb128(os, out.typeSec->lookupType(t->signature), "sig index");
377bb684c34Spatrick }
378bb684c34Spatrick }
379bb684c34Spatrick
addTag(InputTag * tag)3801cf9926bSpatrick void TagSection::addTag(InputTag *tag) {
3811cf9926bSpatrick if (!tag->live)
382bb684c34Spatrick return;
3831cf9926bSpatrick uint32_t tagIndex = out.importSec->getNumImportedTags() + inputTags.size();
3841cf9926bSpatrick LLVM_DEBUG(dbgs() << "addTag: " << tagIndex << "\n");
3851cf9926bSpatrick tag->assignIndex(tagIndex);
3861cf9926bSpatrick inputTags.push_back(tag);
387bb684c34Spatrick }
388bb684c34Spatrick
assignIndexes()389ece8a530Spatrick void GlobalSection::assignIndexes() {
390ece8a530Spatrick uint32_t globalIndex = out.importSec->getNumImportedGlobals();
391ece8a530Spatrick for (InputGlobal *g : inputGlobals)
3921cf9926bSpatrick g->assignIndex(globalIndex++);
3931cf9926bSpatrick for (Symbol *sym : internalGotSymbols)
394ece8a530Spatrick sym->setGOTIndex(globalIndex++);
395ece8a530Spatrick isSealed = true;
396ece8a530Spatrick }
397ece8a530Spatrick
ensureIndirectFunctionTable()3981cf9926bSpatrick static void ensureIndirectFunctionTable() {
3991cf9926bSpatrick if (!WasmSym::indirectFunctionTable)
4001cf9926bSpatrick WasmSym::indirectFunctionTable =
4011cf9926bSpatrick symtab->resolveIndirectFunctionTable(/*required =*/true);
4021cf9926bSpatrick }
4031cf9926bSpatrick
addInternalGOTEntry(Symbol * sym)4041cf9926bSpatrick void GlobalSection::addInternalGOTEntry(Symbol *sym) {
405ece8a530Spatrick assert(!isSealed);
406ece8a530Spatrick if (sym->requiresGOT)
407ece8a530Spatrick return;
4081cf9926bSpatrick LLVM_DEBUG(dbgs() << "addInternalGOTEntry: " << sym->getName() << " "
409ece8a530Spatrick << toString(sym->kind()) << "\n");
410ece8a530Spatrick sym->requiresGOT = true;
4111cf9926bSpatrick if (auto *F = dyn_cast<FunctionSymbol>(sym)) {
4121cf9926bSpatrick ensureIndirectFunctionTable();
413ece8a530Spatrick out.elemSec->addEntry(F);
4141cf9926bSpatrick }
4151cf9926bSpatrick internalGotSymbols.push_back(sym);
4161cf9926bSpatrick }
4171cf9926bSpatrick
generateRelocationCode(raw_ostream & os,bool TLS) const418*dfe94b16Srobert void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
419*dfe94b16Srobert assert(!config->extendedConst);
420*dfe94b16Srobert bool is64 = config->is64.value_or(false);
4211cf9926bSpatrick unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST
4221cf9926bSpatrick : WASM_OPCODE_I32_CONST;
4231cf9926bSpatrick unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD
4241cf9926bSpatrick : WASM_OPCODE_I32_ADD;
4251cf9926bSpatrick
4261cf9926bSpatrick for (const Symbol *sym : internalGotSymbols) {
427*dfe94b16Srobert if (TLS != sym->isTLS())
428*dfe94b16Srobert continue;
429*dfe94b16Srobert
4301cf9926bSpatrick if (auto *d = dyn_cast<DefinedData>(sym)) {
4311cf9926bSpatrick // Get __memory_base
4321cf9926bSpatrick writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
433*dfe94b16Srobert if (sym->isTLS())
434*dfe94b16Srobert writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(), "__tls_base");
435*dfe94b16Srobert else
436*dfe94b16Srobert writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(),
437*dfe94b16Srobert "__memory_base");
4381cf9926bSpatrick
4391cf9926bSpatrick // Add the virtual address of the data symbol
4401cf9926bSpatrick writeU8(os, opcode_ptr_const, "CONST");
4411cf9926bSpatrick writeSleb128(os, d->getVA(), "offset");
4421cf9926bSpatrick } else if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
4431cf9926bSpatrick if (f->isStub)
4441cf9926bSpatrick continue;
4451cf9926bSpatrick // Get __table_base
4461cf9926bSpatrick writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
4471cf9926bSpatrick writeUleb128(os, WasmSym::tableBase->getGlobalIndex(), "__table_base");
4481cf9926bSpatrick
4491cf9926bSpatrick // Add the table index to __table_base
4501cf9926bSpatrick writeU8(os, opcode_ptr_const, "CONST");
4511cf9926bSpatrick writeSleb128(os, f->getTableIndex(), "offset");
4521cf9926bSpatrick } else {
4531cf9926bSpatrick assert(isa<UndefinedData>(sym));
4541cf9926bSpatrick continue;
4551cf9926bSpatrick }
4561cf9926bSpatrick writeU8(os, opcode_ptr_add, "ADD");
4571cf9926bSpatrick writeU8(os, WASM_OPCODE_GLOBAL_SET, "GLOBAL_SET");
4581cf9926bSpatrick writeUleb128(os, sym->getGOTIndex(), "got_entry");
4591cf9926bSpatrick }
460ece8a530Spatrick }
461ece8a530Spatrick
writeBody()462ece8a530Spatrick void GlobalSection::writeBody() {
463ece8a530Spatrick raw_ostream &os = bodyOutputStream;
464ece8a530Spatrick
465ece8a530Spatrick writeUleb128(os, numGlobals(), "global count");
4661cf9926bSpatrick for (InputGlobal *g : inputGlobals) {
4671cf9926bSpatrick writeGlobalType(os, g->getType());
4681cf9926bSpatrick writeInitExpr(os, g->getInitExpr());
4691cf9926bSpatrick }
470*dfe94b16Srobert bool is64 = config->is64.value_or(false);
4711cf9926bSpatrick uint8_t itype = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32;
4721cf9926bSpatrick for (const Symbol *sym : internalGotSymbols) {
473*dfe94b16Srobert bool mutable_ = false;
474*dfe94b16Srobert if (!sym->isStub) {
475*dfe94b16Srobert // In the case of dynamic linking, unless we have 'extended-const'
476*dfe94b16Srobert // available, these global must to be mutable since they get updated to
477*dfe94b16Srobert // the correct runtime value during `__wasm_apply_global_relocs`.
478*dfe94b16Srobert if (!config->extendedConst && config->isPic && !sym->isTLS())
479*dfe94b16Srobert mutable_ = true;
480*dfe94b16Srobert // With multi-theadeding any TLS globals must be mutable since they get
481*dfe94b16Srobert // set during `__wasm_apply_global_tls_relocs`
482*dfe94b16Srobert if (config->sharedMemory && sym->isTLS())
483*dfe94b16Srobert mutable_ = true;
484*dfe94b16Srobert }
4851cf9926bSpatrick WasmGlobalType type{itype, mutable_};
486*dfe94b16Srobert writeGlobalType(os, type);
487*dfe94b16Srobert
488*dfe94b16Srobert if (config->extendedConst && config->isPic && !sym->isTLS() &&
489*dfe94b16Srobert isa<DefinedData>(sym)) {
490*dfe94b16Srobert // We can use an extended init expression to add a constant
491*dfe94b16Srobert // offset of __memory_base.
492*dfe94b16Srobert auto *d = cast<DefinedData>(sym);
493*dfe94b16Srobert writeU8(os, WASM_OPCODE_GLOBAL_GET, "global get");
494*dfe94b16Srobert writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(),
495*dfe94b16Srobert "literal (global index)");
496*dfe94b16Srobert if (d->getVA()) {
497*dfe94b16Srobert writePtrConst(os, d->getVA(), is64, "offset");
498*dfe94b16Srobert writeU8(os, is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD, "add");
499*dfe94b16Srobert }
500*dfe94b16Srobert writeU8(os, WASM_OPCODE_END, "opcode:end");
501*dfe94b16Srobert } else {
5021cf9926bSpatrick WasmInitExpr initExpr;
503ece8a530Spatrick if (auto *d = dyn_cast<DefinedData>(sym))
5041cf9926bSpatrick initExpr = intConst(d->getVA(), is64);
505ece8a530Spatrick else if (auto *f = dyn_cast<FunctionSymbol>(sym))
5061cf9926bSpatrick initExpr = intConst(f->isStub ? 0 : f->getTableIndex(), is64);
507ece8a530Spatrick else {
508ece8a530Spatrick assert(isa<UndefinedData>(sym));
5091cf9926bSpatrick initExpr = intConst(0, is64);
510ece8a530Spatrick }
5111cf9926bSpatrick writeInitExpr(os, initExpr);
512ece8a530Spatrick }
513*dfe94b16Srobert }
514ece8a530Spatrick for (const DefinedData *sym : dataAddressGlobals) {
5151cf9926bSpatrick WasmGlobalType type{itype, false};
5161cf9926bSpatrick writeGlobalType(os, type);
5171cf9926bSpatrick writeInitExpr(os, intConst(sym->getVA(), is64));
518ece8a530Spatrick }
519ece8a530Spatrick }
520ece8a530Spatrick
addGlobal(InputGlobal * global)521ece8a530Spatrick void GlobalSection::addGlobal(InputGlobal *global) {
522ece8a530Spatrick assert(!isSealed);
523ece8a530Spatrick if (!global->live)
524ece8a530Spatrick return;
525ece8a530Spatrick inputGlobals.push_back(global);
526ece8a530Spatrick }
527ece8a530Spatrick
writeBody()528ece8a530Spatrick void ExportSection::writeBody() {
529ece8a530Spatrick raw_ostream &os = bodyOutputStream;
530ece8a530Spatrick
531ece8a530Spatrick writeUleb128(os, exports.size(), "export count");
532ece8a530Spatrick for (const WasmExport &export_ : exports)
533ece8a530Spatrick writeExport(os, export_);
534ece8a530Spatrick }
535ece8a530Spatrick
isNeeded() const536ece8a530Spatrick bool StartSection::isNeeded() const {
5371cf9926bSpatrick return WasmSym::startFunction != nullptr;
538ece8a530Spatrick }
539ece8a530Spatrick
writeBody()540ece8a530Spatrick void StartSection::writeBody() {
541ece8a530Spatrick raw_ostream &os = bodyOutputStream;
5421cf9926bSpatrick writeUleb128(os, WasmSym::startFunction->getFunctionIndex(),
5431cf9926bSpatrick "function index");
544ece8a530Spatrick }
545ece8a530Spatrick
addEntry(FunctionSymbol * sym)546ece8a530Spatrick void ElemSection::addEntry(FunctionSymbol *sym) {
5471cf9926bSpatrick // Don't add stub functions to the wasm table. The address of all stub
5481cf9926bSpatrick // functions should be zero and they should they don't appear in the table.
5491cf9926bSpatrick // They only exist so that the calls to missing functions can validate.
5501cf9926bSpatrick if (sym->hasTableIndex() || sym->isStub)
551ece8a530Spatrick return;
552ece8a530Spatrick sym->setTableIndex(config->tableBase + indirectFunctions.size());
553ece8a530Spatrick indirectFunctions.emplace_back(sym);
554ece8a530Spatrick }
555ece8a530Spatrick
writeBody()556ece8a530Spatrick void ElemSection::writeBody() {
557ece8a530Spatrick raw_ostream &os = bodyOutputStream;
558ece8a530Spatrick
5591cf9926bSpatrick assert(WasmSym::indirectFunctionTable);
560ece8a530Spatrick writeUleb128(os, 1, "segment count");
5611cf9926bSpatrick uint32_t tableNumber = WasmSym::indirectFunctionTable->getTableNumber();
5621cf9926bSpatrick uint32_t flags = 0;
5631cf9926bSpatrick if (tableNumber)
5641cf9926bSpatrick flags |= WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER;
5651cf9926bSpatrick writeUleb128(os, flags, "elem segment flags");
5661cf9926bSpatrick if (flags & WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
5671cf9926bSpatrick writeUleb128(os, tableNumber, "table number");
5681cf9926bSpatrick
569ece8a530Spatrick WasmInitExpr initExpr;
570*dfe94b16Srobert initExpr.Extended = false;
571ece8a530Spatrick if (config->isPic) {
572*dfe94b16Srobert initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
573*dfe94b16Srobert initExpr.Inst.Value.Global =
574*dfe94b16Srobert (config->is64.value_or(false) ? WasmSym::tableBase32
5751cf9926bSpatrick : WasmSym::tableBase)
5761cf9926bSpatrick ->getGlobalIndex();
577ece8a530Spatrick } else {
578*dfe94b16Srobert initExpr.Inst.Opcode = WASM_OPCODE_I32_CONST;
579*dfe94b16Srobert initExpr.Inst.Value.Int32 = config->tableBase;
580ece8a530Spatrick }
581ece8a530Spatrick writeInitExpr(os, initExpr);
582ece8a530Spatrick
5831cf9926bSpatrick if (flags & WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
5841cf9926bSpatrick // We only write active function table initializers, for which the elem kind
5851cf9926bSpatrick // is specified to be written as 0x00 and interpreted to mean "funcref".
5861cf9926bSpatrick const uint8_t elemKind = 0;
5871cf9926bSpatrick writeU8(os, elemKind, "elem kind");
5881cf9926bSpatrick }
5891cf9926bSpatrick
5901cf9926bSpatrick writeUleb128(os, indirectFunctions.size(), "elem count");
591ece8a530Spatrick uint32_t tableIndex = config->tableBase;
592ece8a530Spatrick for (const FunctionSymbol *sym : indirectFunctions) {
593ece8a530Spatrick assert(sym->getTableIndex() == tableIndex);
594*dfe94b16Srobert (void) tableIndex;
595ece8a530Spatrick writeUleb128(os, sym->getFunctionIndex(), "function index");
596ece8a530Spatrick ++tableIndex;
597ece8a530Spatrick }
598ece8a530Spatrick }
599ece8a530Spatrick
DataCountSection(ArrayRef<OutputSegment * > segments)600ece8a530Spatrick DataCountSection::DataCountSection(ArrayRef<OutputSegment *> segments)
601ece8a530Spatrick : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT),
602*dfe94b16Srobert numSegments(llvm::count_if(segments, [](OutputSegment *const segment) {
603*dfe94b16Srobert return segment->requiredInBinary();
604*dfe94b16Srobert })) {}
605ece8a530Spatrick
writeBody()606ece8a530Spatrick void DataCountSection::writeBody() {
607ece8a530Spatrick writeUleb128(bodyOutputStream, numSegments, "data count");
608ece8a530Spatrick }
609ece8a530Spatrick
isNeeded() const610ece8a530Spatrick bool DataCountSection::isNeeded() const {
611ece8a530Spatrick return numSegments && config->sharedMemory;
612ece8a530Spatrick }
613ece8a530Spatrick
writeBody()614ece8a530Spatrick void LinkingSection::writeBody() {
615ece8a530Spatrick raw_ostream &os = bodyOutputStream;
616ece8a530Spatrick
617ece8a530Spatrick writeUleb128(os, WasmMetadataVersion, "Version");
618ece8a530Spatrick
619ece8a530Spatrick if (!symtabEntries.empty()) {
620ece8a530Spatrick SubSection sub(WASM_SYMBOL_TABLE);
621ece8a530Spatrick writeUleb128(sub.os, symtabEntries.size(), "num symbols");
622ece8a530Spatrick
623ece8a530Spatrick for (const Symbol *sym : symtabEntries) {
624ece8a530Spatrick assert(sym->isDefined() || sym->isUndefined());
625ece8a530Spatrick WasmSymbolType kind = sym->getWasmType();
626bb684c34Spatrick uint32_t flags = sym->flags;
627ece8a530Spatrick
628ece8a530Spatrick writeU8(sub.os, kind, "sym kind");
629ece8a530Spatrick writeUleb128(sub.os, flags, "sym flags");
630ece8a530Spatrick
631ece8a530Spatrick if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
632*dfe94b16Srobert if (auto *d = dyn_cast<DefinedFunction>(sym)) {
633*dfe94b16Srobert writeUleb128(sub.os, d->getExportedFunctionIndex(), "index");
634*dfe94b16Srobert } else {
635ece8a530Spatrick writeUleb128(sub.os, f->getFunctionIndex(), "index");
636*dfe94b16Srobert }
637ece8a530Spatrick if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
638ece8a530Spatrick writeStr(sub.os, sym->getName(), "sym name");
639ece8a530Spatrick } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) {
640ece8a530Spatrick writeUleb128(sub.os, g->getGlobalIndex(), "index");
641ece8a530Spatrick if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
642ece8a530Spatrick writeStr(sub.os, sym->getName(), "sym name");
6431cf9926bSpatrick } else if (auto *t = dyn_cast<TagSymbol>(sym)) {
6441cf9926bSpatrick writeUleb128(sub.os, t->getTagIndex(), "index");
6451cf9926bSpatrick if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
6461cf9926bSpatrick writeStr(sub.os, sym->getName(), "sym name");
6471cf9926bSpatrick } else if (auto *t = dyn_cast<TableSymbol>(sym)) {
6481cf9926bSpatrick writeUleb128(sub.os, t->getTableNumber(), "table number");
649ece8a530Spatrick if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
650ece8a530Spatrick writeStr(sub.os, sym->getName(), "sym name");
651ece8a530Spatrick } else if (isa<DataSymbol>(sym)) {
652ece8a530Spatrick writeStr(sub.os, sym->getName(), "sym name");
653ece8a530Spatrick if (auto *dataSym = dyn_cast<DefinedData>(sym)) {
654ece8a530Spatrick writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");
655ece8a530Spatrick writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),
656ece8a530Spatrick "data offset");
657ece8a530Spatrick writeUleb128(sub.os, dataSym->getSize(), "data size");
658ece8a530Spatrick }
659ece8a530Spatrick } else {
660ece8a530Spatrick auto *s = cast<OutputSectionSymbol>(sym);
661ece8a530Spatrick writeUleb128(sub.os, s->section->sectionIndex, "sym section index");
662ece8a530Spatrick }
663ece8a530Spatrick }
664ece8a530Spatrick
665ece8a530Spatrick sub.writeTo(os);
666ece8a530Spatrick }
667ece8a530Spatrick
668ece8a530Spatrick if (dataSegments.size()) {
669ece8a530Spatrick SubSection sub(WASM_SEGMENT_INFO);
670ece8a530Spatrick writeUleb128(sub.os, dataSegments.size(), "num data segments");
671ece8a530Spatrick for (const OutputSegment *s : dataSegments) {
672ece8a530Spatrick writeStr(sub.os, s->name, "segment name");
673ece8a530Spatrick writeUleb128(sub.os, s->alignment, "alignment");
6741cf9926bSpatrick writeUleb128(sub.os, s->linkingFlags, "flags");
675ece8a530Spatrick }
676ece8a530Spatrick sub.writeTo(os);
677ece8a530Spatrick }
678ece8a530Spatrick
679ece8a530Spatrick if (!initFunctions.empty()) {
680ece8a530Spatrick SubSection sub(WASM_INIT_FUNCS);
681ece8a530Spatrick writeUleb128(sub.os, initFunctions.size(), "num init functions");
682ece8a530Spatrick for (const WasmInitEntry &f : initFunctions) {
683ece8a530Spatrick writeUleb128(sub.os, f.priority, "priority");
684ece8a530Spatrick writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index");
685ece8a530Spatrick }
686ece8a530Spatrick sub.writeTo(os);
687ece8a530Spatrick }
688ece8a530Spatrick
689ece8a530Spatrick struct ComdatEntry {
690ece8a530Spatrick unsigned kind;
691ece8a530Spatrick uint32_t index;
692ece8a530Spatrick };
693ece8a530Spatrick std::map<StringRef, std::vector<ComdatEntry>> comdats;
694ece8a530Spatrick
695ece8a530Spatrick for (const InputFunction *f : out.functionSec->inputFunctions) {
696ece8a530Spatrick StringRef comdat = f->getComdatName();
697ece8a530Spatrick if (!comdat.empty())
698ece8a530Spatrick comdats[comdat].emplace_back(
699ece8a530Spatrick ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()});
700ece8a530Spatrick }
701ece8a530Spatrick for (uint32_t i = 0; i < dataSegments.size(); ++i) {
702ece8a530Spatrick const auto &inputSegments = dataSegments[i]->inputSegments;
703ece8a530Spatrick if (inputSegments.empty())
704ece8a530Spatrick continue;
705ece8a530Spatrick StringRef comdat = inputSegments[0]->getComdatName();
706ece8a530Spatrick #ifndef NDEBUG
7071cf9926bSpatrick for (const InputChunk *isec : inputSegments)
708ece8a530Spatrick assert(isec->getComdatName() == comdat);
709ece8a530Spatrick #endif
710ece8a530Spatrick if (!comdat.empty())
711ece8a530Spatrick comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i});
712ece8a530Spatrick }
713ece8a530Spatrick
714ece8a530Spatrick if (!comdats.empty()) {
715ece8a530Spatrick SubSection sub(WASM_COMDAT_INFO);
716ece8a530Spatrick writeUleb128(sub.os, comdats.size(), "num comdats");
717ece8a530Spatrick for (const auto &c : comdats) {
718ece8a530Spatrick writeStr(sub.os, c.first, "comdat name");
719ece8a530Spatrick writeUleb128(sub.os, 0, "comdat flags"); // flags for future use
720ece8a530Spatrick writeUleb128(sub.os, c.second.size(), "num entries");
721ece8a530Spatrick for (const ComdatEntry &entry : c.second) {
722ece8a530Spatrick writeU8(sub.os, entry.kind, "entry kind");
723ece8a530Spatrick writeUleb128(sub.os, entry.index, "entry index");
724ece8a530Spatrick }
725ece8a530Spatrick }
726ece8a530Spatrick sub.writeTo(os);
727ece8a530Spatrick }
728ece8a530Spatrick }
729ece8a530Spatrick
addToSymtab(Symbol * sym)730ece8a530Spatrick void LinkingSection::addToSymtab(Symbol *sym) {
731ece8a530Spatrick sym->setOutputSymbolIndex(symtabEntries.size());
732ece8a530Spatrick symtabEntries.emplace_back(sym);
733ece8a530Spatrick }
734ece8a530Spatrick
numNamedFunctions() const7351cf9926bSpatrick unsigned NameSection::numNamedFunctions() const {
736ece8a530Spatrick unsigned numNames = out.importSec->getNumImportedFunctions();
7371cf9926bSpatrick
738ece8a530Spatrick for (const InputFunction *f : out.functionSec->inputFunctions)
739*dfe94b16Srobert if (!f->name.empty() || !f->debugName.empty())
740ece8a530Spatrick ++numNames;
741ece8a530Spatrick
742ece8a530Spatrick return numNames;
743ece8a530Spatrick }
744ece8a530Spatrick
numNamedGlobals() const7451cf9926bSpatrick unsigned NameSection::numNamedGlobals() const {
7461cf9926bSpatrick unsigned numNames = out.importSec->getNumImportedGlobals();
7471cf9926bSpatrick
7481cf9926bSpatrick for (const InputGlobal *g : out.globalSec->inputGlobals)
7491cf9926bSpatrick if (!g->getName().empty())
7501cf9926bSpatrick ++numNames;
7511cf9926bSpatrick
7521cf9926bSpatrick numNames += out.globalSec->internalGotSymbols.size();
7531cf9926bSpatrick return numNames;
7541cf9926bSpatrick }
7551cf9926bSpatrick
numNamedDataSegments() const7561cf9926bSpatrick unsigned NameSection::numNamedDataSegments() const {
7571cf9926bSpatrick unsigned numNames = 0;
7581cf9926bSpatrick
7591cf9926bSpatrick for (const OutputSegment *s : segments)
760*dfe94b16Srobert if (!s->name.empty() && s->requiredInBinary())
7611cf9926bSpatrick ++numNames;
7621cf9926bSpatrick
7631cf9926bSpatrick return numNames;
7641cf9926bSpatrick }
7651cf9926bSpatrick
766ece8a530Spatrick // Create the custom "name" section containing debug symbol names.
writeBody()767ece8a530Spatrick void NameSection::writeBody() {
7681cf9926bSpatrick unsigned count = numNamedFunctions();
7691cf9926bSpatrick if (count) {
770ece8a530Spatrick SubSection sub(WASM_NAMES_FUNCTION);
7711cf9926bSpatrick writeUleb128(sub.os, count, "name count");
772ece8a530Spatrick
7731cf9926bSpatrick // Function names appear in function index order. As it happens
7741cf9926bSpatrick // importedSymbols and inputFunctions are numbered in order with imported
7751cf9926bSpatrick // functions coming first.
776ece8a530Spatrick for (const Symbol *s : out.importSec->importedSymbols) {
777ece8a530Spatrick if (auto *f = dyn_cast<FunctionSymbol>(s)) {
778ece8a530Spatrick writeUleb128(sub.os, f->getFunctionIndex(), "func index");
779ece8a530Spatrick writeStr(sub.os, toString(*s), "symbol name");
780ece8a530Spatrick }
781ece8a530Spatrick }
782ece8a530Spatrick for (const InputFunction *f : out.functionSec->inputFunctions) {
783*dfe94b16Srobert if (!f->name.empty()) {
784ece8a530Spatrick writeUleb128(sub.os, f->getFunctionIndex(), "func index");
785*dfe94b16Srobert if (!f->debugName.empty()) {
786*dfe94b16Srobert writeStr(sub.os, f->debugName, "symbol name");
787ece8a530Spatrick } else {
788*dfe94b16Srobert writeStr(sub.os, maybeDemangleSymbol(f->name), "symbol name");
789ece8a530Spatrick }
790ece8a530Spatrick }
791ece8a530Spatrick }
7921cf9926bSpatrick sub.writeTo(bodyOutputStream);
7931cf9926bSpatrick }
7941cf9926bSpatrick
7951cf9926bSpatrick count = numNamedGlobals();
7961cf9926bSpatrick if (count) {
7971cf9926bSpatrick SubSection sub(WASM_NAMES_GLOBAL);
7981cf9926bSpatrick writeUleb128(sub.os, count, "name count");
7991cf9926bSpatrick
8001cf9926bSpatrick for (const Symbol *s : out.importSec->importedSymbols) {
8011cf9926bSpatrick if (auto *g = dyn_cast<GlobalSymbol>(s)) {
8021cf9926bSpatrick writeUleb128(sub.os, g->getGlobalIndex(), "global index");
8031cf9926bSpatrick writeStr(sub.os, toString(*s), "symbol name");
8041cf9926bSpatrick }
8051cf9926bSpatrick }
8061cf9926bSpatrick for (const Symbol *s : out.importSec->gotSymbols) {
8071cf9926bSpatrick writeUleb128(sub.os, s->getGOTIndex(), "global index");
8081cf9926bSpatrick writeStr(sub.os, toString(*s), "symbol name");
8091cf9926bSpatrick }
8101cf9926bSpatrick for (const InputGlobal *g : out.globalSec->inputGlobals) {
8111cf9926bSpatrick if (!g->getName().empty()) {
8121cf9926bSpatrick writeUleb128(sub.os, g->getAssignedIndex(), "global index");
8131cf9926bSpatrick writeStr(sub.os, maybeDemangleSymbol(g->getName()), "symbol name");
8141cf9926bSpatrick }
8151cf9926bSpatrick }
8161cf9926bSpatrick for (Symbol *s : out.globalSec->internalGotSymbols) {
8171cf9926bSpatrick writeUleb128(sub.os, s->getGOTIndex(), "global index");
8181cf9926bSpatrick if (isa<FunctionSymbol>(s))
8191cf9926bSpatrick writeStr(sub.os, "GOT.func.internal." + toString(*s), "symbol name");
8201cf9926bSpatrick else
8211cf9926bSpatrick writeStr(sub.os, "GOT.data.internal." + toString(*s), "symbol name");
8221cf9926bSpatrick }
823ece8a530Spatrick
824ece8a530Spatrick sub.writeTo(bodyOutputStream);
825ece8a530Spatrick }
826ece8a530Spatrick
8271cf9926bSpatrick count = numNamedDataSegments();
8281cf9926bSpatrick if (count) {
8291cf9926bSpatrick SubSection sub(WASM_NAMES_DATA_SEGMENT);
8301cf9926bSpatrick writeUleb128(sub.os, count, "name count");
8311cf9926bSpatrick
8321cf9926bSpatrick for (OutputSegment *s : segments) {
833*dfe94b16Srobert if (!s->name.empty() && s->requiredInBinary()) {
8341cf9926bSpatrick writeUleb128(sub.os, s->index, "global index");
8351cf9926bSpatrick writeStr(sub.os, s->name, "segment name");
8361cf9926bSpatrick }
8371cf9926bSpatrick }
8381cf9926bSpatrick
8391cf9926bSpatrick sub.writeTo(bodyOutputStream);
8401cf9926bSpatrick }
8411cf9926bSpatrick }
8421cf9926bSpatrick
addInfo(const WasmProducerInfo & info)843ece8a530Spatrick void ProducersSection::addInfo(const WasmProducerInfo &info) {
844ece8a530Spatrick for (auto &producers :
845ece8a530Spatrick {std::make_pair(&info.Languages, &languages),
846ece8a530Spatrick std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)})
847ece8a530Spatrick for (auto &producer : *producers.first)
848*dfe94b16Srobert if (llvm::none_of(*producers.second,
849ece8a530Spatrick [&](std::pair<std::string, std::string> seen) {
850ece8a530Spatrick return seen.first == producer.first;
851ece8a530Spatrick }))
852ece8a530Spatrick producers.second->push_back(producer);
853ece8a530Spatrick }
854ece8a530Spatrick
writeBody()855ece8a530Spatrick void ProducersSection::writeBody() {
856ece8a530Spatrick auto &os = bodyOutputStream;
857ece8a530Spatrick writeUleb128(os, fieldCount(), "field count");
858ece8a530Spatrick for (auto &field :
859ece8a530Spatrick {std::make_pair("language", languages),
860ece8a530Spatrick std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) {
861ece8a530Spatrick if (field.second.empty())
862ece8a530Spatrick continue;
863ece8a530Spatrick writeStr(os, field.first, "field name");
864ece8a530Spatrick writeUleb128(os, field.second.size(), "number of entries");
865ece8a530Spatrick for (auto &entry : field.second) {
866ece8a530Spatrick writeStr(os, entry.first, "producer name");
867ece8a530Spatrick writeStr(os, entry.second, "producer version");
868ece8a530Spatrick }
869ece8a530Spatrick }
870ece8a530Spatrick }
871ece8a530Spatrick
writeBody()872ece8a530Spatrick void TargetFeaturesSection::writeBody() {
873ece8a530Spatrick SmallVector<std::string, 8> emitted(features.begin(), features.end());
874ece8a530Spatrick llvm::sort(emitted);
875ece8a530Spatrick auto &os = bodyOutputStream;
876ece8a530Spatrick writeUleb128(os, emitted.size(), "feature count");
877ece8a530Spatrick for (auto &feature : emitted) {
878ece8a530Spatrick writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix");
879ece8a530Spatrick writeStr(os, feature, "feature name");
880ece8a530Spatrick }
881ece8a530Spatrick }
882ece8a530Spatrick
writeBody()883ece8a530Spatrick void RelocSection::writeBody() {
884ece8a530Spatrick uint32_t count = sec->getNumRelocations();
885ece8a530Spatrick assert(sec->sectionIndex != UINT32_MAX);
886ece8a530Spatrick writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section");
887ece8a530Spatrick writeUleb128(bodyOutputStream, count, "reloc count");
888ece8a530Spatrick sec->writeRelocations(bodyOutputStream);
889ece8a530Spatrick }
890ece8a530Spatrick
891ece8a530Spatrick } // namespace wasm
892ece8a530Spatrick } // namespace lld
893