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