1//===- Writer.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#include "Writer.h"
10#include "Config.h"
11#include "InputChunks.h"
12#include "InputElement.h"
13#include "MapFile.h"
14#include "OutputSections.h"
15#include "OutputSegment.h"
16#include "Relocations.h"
17#include "SymbolTable.h"
18#include "SyntheticSections.h"
19#include "WriterUtils.h"
20#include "lld/Common/Arrays.h"
21#include "lld/Common/CommonLinkerContext.h"
22#include "lld/Common/Strings.h"
23#include "llvm/ADT/ArrayRef.h"
24#include "llvm/ADT/MapVector.h"
25#include "llvm/ADT/SmallSet.h"
26#include "llvm/ADT/SmallVector.h"
27#include "llvm/ADT/StringMap.h"
28#include "llvm/BinaryFormat/Wasm.h"
29#include "llvm/Support/FileOutputBuffer.h"
30#include "llvm/Support/FormatVariadic.h"
31#include "llvm/Support/Parallel.h"
32#include "llvm/Support/RandomNumberGenerator.h"
33#include "llvm/Support/SHA1.h"
34#include "llvm/Support/xxhash.h"
35
36#include <cstdarg>
37#include <optional>
38
39#define DEBUG_TYPE "lld"
40
41using namespace llvm;
42using namespace llvm::wasm;
43
44namespace lld::wasm {
45static constexpr int stackAlignment = 16;
46static constexpr int heapAlignment = 16;
47
48namespace {
49
50// The writer writes a SymbolTable result to a file.
51class Writer {
52public:
53 void run();
54
55private:
56 void openFile();
57
58 bool needsPassiveInitialization(const OutputSegment *segment);
59 bool hasPassiveInitializedSegments();
60
61 void createSyntheticInitFunctions();
62 void createInitMemoryFunction();
63 void createStartFunction();
64 void createApplyDataRelocationsFunction();
65 void createApplyGlobalRelocationsFunction();
66 void createApplyTLSRelocationsFunction();
67 void createApplyGlobalTLSRelocationsFunction();
68 void createCallCtorsFunction();
69 void createInitTLSFunction();
70 void createCommandExportWrappers();
71 void createCommandExportWrapper(uint32_t functionIndex, DefinedFunction *f);
72
73 void assignIndexes();
74 void populateSymtab();
75 void populateProducers();
76 void populateTargetFeatures();
77 // populateTargetFeatures happens early on so some checks are delayed
78 // until imports and exports are finalized. There are run unstead
79 // in checkImportExportTargetFeatures
80 void checkImportExportTargetFeatures();
81 void calculateInitFunctions();
82 void calculateImports();
83 void calculateExports();
84 void calculateCustomSections();
85 void calculateTypes();
86 void createOutputSegments();
87 OutputSegment *createOutputSegment(StringRef name);
88 void combineOutputSegments();
89 void layoutMemory();
90 void createHeader();
91
92 void addSection(OutputSection *sec);
93
94 void addSections();
95
96 void createCustomSections();
97 void createSyntheticSections();
98 void createSyntheticSectionsPostLayout();
99 void finalizeSections();
100
101 // Custom sections
102 void createRelocSections();
103
104 void writeHeader();
105 void writeSections();
106 void writeBuildId();
107
108 uint64_t fileSize = 0;
109
110 std::vector<WasmInitEntry> initFunctions;
111 llvm::MapVector<StringRef, std::vector<InputChunk *>> customSectionMapping;
112
113 // Stable storage for command export wrapper function name strings.
114 std::list<std::string> commandExportWrapperNames;
115
116 // Elements that are used to construct the final output
117 std::string header;
118 std::vector<OutputSection *> outputSections;
119
120 std::unique_ptr<FileOutputBuffer> buffer;
121
122 std::vector<OutputSegment *> segments;
123 llvm::SmallDenseMap<StringRef, OutputSegment *> segmentMap;
124};
125
126} // anonymous namespace
127
128void Writer::calculateCustomSections() {
129 log(msg: "calculateCustomSections");
130 bool stripDebug = ctx.arg.stripDebug || ctx.arg.stripAll;
131 for (ObjFile *file : ctx.objectFiles) {
132 for (InputChunk *section : file->customSections) {
133 // Exclude COMDAT sections that are not selected for inclusion
134 if (section->discarded)
135 continue;
136 // Ignore empty custom sections. In particular objcopy/strip will
137 // sometimes replace stripped sections with empty custom sections to
138 // avoid section re-numbering.
139 if (section->getSize() == 0)
140 continue;
141 StringRef name = section->name;
142 // These custom sections are known the linker and synthesized rather than
143 // blindly copied.
144 if (name == "linking" || name == "name" || name == "producers" ||
145 name == "target_features" || name.starts_with(Prefix: "reloc."))
146 continue;
147 // These custom sections are generated by `clang -fembed-bitcode`.
148 // These are used by the rust toolchain to ship LTO data along with
149 // compiled object code, but they don't want this included in the linker
150 // output.
151 if (name == ".llvmbc" || name == ".llvmcmd")
152 continue;
153 // Strip debug section in that option was specified.
154 if (stripDebug && name.starts_with(Prefix: ".debug_"))
155 continue;
156 // Otherwise include custom sections by default and concatenate their
157 // contents.
158 customSectionMapping[name].push_back(x: section);
159 }
160 }
161}
162
163void Writer::createCustomSections() {
164 log(msg: "createCustomSections");
165 for (auto &pair : customSectionMapping) {
166 StringRef name = pair.first;
167 LLVM_DEBUG(dbgs() << "createCustomSection: " << name << "\n");
168
169 OutputSection *sec = make<CustomSection>(args: std::string(name), args&: pair.second);
170 if (ctx.arg.relocatable || ctx.arg.emitRelocs) {
171 auto *sym = make<OutputSectionSymbol>(args&: sec);
172 out.linkingSec->addToSymtab(sym);
173 sec->sectionSym = sym;
174 }
175 addSection(sec);
176 }
177}
178
179// Create relocations sections in the final output.
180// These are only created when relocatable output is requested.
181void Writer::createRelocSections() {
182 log(msg: "createRelocSections");
183 // Don't use iterator here since we are adding to OutputSection
184 size_t origSize = outputSections.size();
185 for (size_t i = 0; i < origSize; i++) {
186 LLVM_DEBUG(dbgs() << "check section " << i << "\n");
187 OutputSection *sec = outputSections[i];
188
189 // Count the number of needed sections.
190 uint32_t count = sec->getNumRelocations();
191 if (!count)
192 continue;
193
194 StringRef name;
195 if (sec->type == WASM_SEC_DATA)
196 name = "reloc.DATA";
197 else if (sec->type == WASM_SEC_CODE)
198 name = "reloc.CODE";
199 else if (sec->type == WASM_SEC_CUSTOM)
200 name = saver().save(S: "reloc." + sec->name);
201 else
202 llvm_unreachable(
203 "relocations only supported for code, data, or custom sections");
204
205 addSection(sec: make<RelocSection>(args&: name, args&: sec));
206 }
207}
208
209void Writer::populateProducers() {
210 for (ObjFile *file : ctx.objectFiles) {
211 const WasmProducerInfo &info = file->getWasmObj()->getProducerInfo();
212 out.producersSec->addInfo(info);
213 }
214}
215
216void Writer::writeHeader() {
217 memcpy(dest: buffer->getBufferStart(), src: header.data(), n: header.size());
218}
219
220void Writer::writeSections() {
221 uint8_t *buf = buffer->getBufferStart();
222 parallelForEach(R&: outputSections, Fn: [buf](OutputSection *s) {
223 assert(s->isNeeded());
224 s->writeTo(buf);
225 });
226}
227
228// Computes a hash value of Data using a given hash function.
229// In order to utilize multiple cores, we first split data into 1MB
230// chunks, compute a hash for each chunk, and then compute a hash value
231// of the hash values.
232
233static void
234computeHash(llvm::MutableArrayRef<uint8_t> hashBuf,
235 llvm::ArrayRef<uint8_t> data,
236 std::function<void(uint8_t *dest, ArrayRef<uint8_t> arr)> hashFn) {
237 std::vector<ArrayRef<uint8_t>> chunks = split(arr: data, chunkSize: 1024 * 1024);
238 std::vector<uint8_t> hashes(chunks.size() * hashBuf.size());
239
240 // Compute hash values.
241 parallelFor(Begin: 0, End: chunks.size(), Fn: [&](size_t i) {
242 hashFn(hashes.data() + i * hashBuf.size(), chunks[i]);
243 });
244
245 // Write to the final output buffer.
246 hashFn(hashBuf.data(), hashes);
247}
248
249static void makeUUID(unsigned version, llvm::ArrayRef<uint8_t> fileHash,
250 llvm::MutableArrayRef<uint8_t> output) {
251 assert((version == 4 || version == 5) && "Unknown UUID version");
252 assert(output.size() == 16 && "Wrong size for UUID output");
253 if (version == 5) {
254 // Build a valid v5 UUID from a hardcoded (randomly-generated) namespace
255 // UUID, and the computed hash of the output.
256 std::array<uint8_t, 16> namespaceUUID{0xA1, 0xFA, 0x48, 0x2D, 0x0E, 0x22,
257 0x03, 0x8D, 0x33, 0x8B, 0x52, 0x1C,
258 0xD6, 0xD2, 0x12, 0xB2};
259 SHA1 sha;
260 sha.update(Data: namespaceUUID);
261 sha.update(Data: fileHash);
262 auto s = sha.final();
263 std::copy(first: s.data(), last: &s.data()[output.size()], result: output.data());
264 } else if (version == 4) {
265 if (auto ec = llvm::getRandomBytes(Buffer: output.data(), Size: output.size()))
266 error(msg: "entropy source failure: " + ec.message());
267 }
268 // Set the UUID version and variant fields.
269 // The version is the upper nibble of byte 6 (0b0101xxxx or 0b0100xxxx)
270 output[6] = (static_cast<uint8_t>(version) << 4) | (output[6] & 0xF);
271
272 // The variant is DCE 1.1/ISO 11578 (0b10xxxxxx)
273 output[8] &= 0xBF;
274 output[8] |= 0x80;
275}
276
277void Writer::writeBuildId() {
278 if (!out.buildIdSec->isNeeded())
279 return;
280 if (ctx.arg.buildId == BuildIdKind::Hexstring) {
281 out.buildIdSec->writeBuildId(buf: ctx.arg.buildIdVector);
282 return;
283 }
284
285 // Compute a hash of all sections of the output file.
286 size_t hashSize = out.buildIdSec->hashSize;
287 std::vector<uint8_t> buildId(hashSize);
288 llvm::ArrayRef<uint8_t> buf{buffer->getBufferStart(), size_t(fileSize)};
289
290 switch (ctx.arg.buildId) {
291 case BuildIdKind::Fast: {
292 std::vector<uint8_t> fileHash(8);
293 computeHash(hashBuf: fileHash, data: buf, hashFn: [](uint8_t *dest, ArrayRef<uint8_t> arr) {
294 support::endian::write64le(P: dest, V: xxh3_64bits(data: arr));
295 });
296 makeUUID(version: 5, fileHash, output: buildId);
297 break;
298 }
299 case BuildIdKind::Sha1:
300 computeHash(hashBuf: buildId, data: buf, hashFn: [&](uint8_t *dest, ArrayRef<uint8_t> arr) {
301 memcpy(dest: dest, src: SHA1::hash(Data: arr).data(), n: hashSize);
302 });
303 break;
304 case BuildIdKind::Uuid:
305 makeUUID(version: 4, fileHash: {}, output: buildId);
306 break;
307 default:
308 llvm_unreachable("unknown BuildIdKind");
309 }
310 out.buildIdSec->writeBuildId(buf: buildId);
311}
312
313static void setGlobalPtr(DefinedGlobal *g, uint64_t memoryPtr) {
314 LLVM_DEBUG(dbgs() << "setGlobalPtr " << g->getName() << " -> " << memoryPtr
315 << "\n");
316 g->global->setPointerValue(memoryPtr);
317}
318
319static void checkPageAligned(StringRef name, uint64_t value) {
320 if (value != alignTo(Value: value, Align: ctx.arg.pageSize))
321 error(msg: name + " must be aligned to the page size (" +
322 Twine(ctx.arg.pageSize) + " bytes)");
323}
324
325// Fix the memory layout of the output binary. This assigns memory offsets
326// to each of the input data sections as well as the explicit stack region.
327// The default memory layout is as follows, from low to high.
328//
329// - initialized data (starting at ctx.arg.globalBase)
330// - BSS data (not currently implemented in llvm)
331// - explicit stack (ctx.arg.ZStackSize)
332// - heap start / unallocated
333//
334// The --stack-first option means that stack is placed before any static data.
335// This can be useful since it means that stack overflow traps immediately
336// rather than overwriting global data, but also increases code size since all
337// static data loads and stores requires larger offsets.
338void Writer::layoutMemory() {
339 uint64_t memoryPtr = 0;
340
341 auto placeStack = [&]() {
342 if (ctx.arg.relocatable || ctx.isPic)
343 return;
344 memoryPtr = alignTo(Value: memoryPtr, Align: stackAlignment);
345 if (ctx.sym.stackLow)
346 ctx.sym.stackLow->setVA(memoryPtr);
347 if (ctx.arg.zStackSize != alignTo(Value: ctx.arg.zStackSize, Align: stackAlignment))
348 error(msg: "stack size must be " + Twine(stackAlignment) + "-byte aligned");
349 log(msg: "mem: stack size = " + Twine(ctx.arg.zStackSize));
350 log(msg: "mem: stack base = " + Twine(memoryPtr));
351 memoryPtr += ctx.arg.zStackSize;
352 setGlobalPtr(g: cast<DefinedGlobal>(Val: ctx.sym.stackPointer), memoryPtr);
353 if (ctx.sym.stackHigh)
354 ctx.sym.stackHigh->setVA(memoryPtr);
355 log(msg: "mem: stack top = " + Twine(memoryPtr));
356 };
357
358 if (ctx.arg.stackFirst) {
359 placeStack();
360 if (ctx.arg.globalBase) {
361 if (ctx.arg.globalBase < memoryPtr) {
362 error(msg: "--global-base cannot be less than stack size when --stack-first "
363 "is used");
364 return;
365 }
366 memoryPtr = ctx.arg.globalBase;
367 }
368 } else {
369 memoryPtr = ctx.arg.globalBase;
370 }
371
372 log(msg: "mem: global base = " + Twine(memoryPtr));
373 if (ctx.sym.globalBase)
374 ctx.sym.globalBase->setVA(memoryPtr);
375
376 uint64_t dataStart = memoryPtr;
377
378 // Arbitrarily set __dso_handle handle to point to the start of the data
379 // segments.
380 if (ctx.sym.dsoHandle)
381 ctx.sym.dsoHandle->setVA(dataStart);
382
383 out.dylinkSec->memAlign = 0;
384 for (OutputSegment *seg : segments) {
385 out.dylinkSec->memAlign = std::max(a: out.dylinkSec->memAlign, b: seg->alignment);
386 memoryPtr = alignTo(Value: memoryPtr, Align: 1ULL << seg->alignment);
387 seg->startVA = memoryPtr;
388 log(msg: formatv(Fmt: "mem: {0,-15} offset={1,-8} size={2,-8} align={3}", Vals&: seg->name,
389 Vals&: memoryPtr, Vals&: seg->size, Vals&: seg->alignment));
390
391 if (!ctx.arg.relocatable && seg->isTLS()) {
392 if (ctx.sym.tlsSize) {
393 auto *tlsSize = cast<DefinedGlobal>(Val: ctx.sym.tlsSize);
394 setGlobalPtr(g: tlsSize, memoryPtr: seg->size);
395 }
396 if (ctx.sym.tlsAlign) {
397 auto *tlsAlign = cast<DefinedGlobal>(Val: ctx.sym.tlsAlign);
398 setGlobalPtr(g: tlsAlign, memoryPtr: int64_t{1} << seg->alignment);
399 }
400 if (!ctx.arg.sharedMemory && ctx.sym.tlsBase) {
401 auto *tlsBase = cast<DefinedGlobal>(Val: ctx.sym.tlsBase);
402 setGlobalPtr(g: tlsBase, memoryPtr);
403 }
404 }
405
406 if (ctx.sym.rodataStart && seg->name.starts_with(Prefix: ".rodata") &&
407 !ctx.sym.rodataStart->getVA())
408 ctx.sym.rodataStart->setVA(memoryPtr);
409
410 memoryPtr += seg->size;
411
412 // Might get set more than once if segment merging is not enabled.
413 if (ctx.sym.rodataEnd && seg->name.starts_with(Prefix: ".rodata"))
414 ctx.sym.rodataEnd->setVA(memoryPtr);
415 }
416
417 // Make space for the memory initialization flag
418 if (ctx.arg.sharedMemory && hasPassiveInitializedSegments()) {
419 memoryPtr = alignTo(Value: memoryPtr, Align: 4);
420 ctx.sym.initMemoryFlag = symtab->addSyntheticDataSymbol(
421 name: "__wasm_init_memory_flag", flags: WASM_SYMBOL_VISIBILITY_HIDDEN);
422 ctx.sym.initMemoryFlag->markLive();
423 ctx.sym.initMemoryFlag->setVA(memoryPtr);
424 log(msg: formatv(Fmt: "mem: {0,-15} offset={1,-8} size={2,-8} align={3}",
425 Vals: "__wasm_init_memory_flag", Vals&: memoryPtr, Vals: 4, Vals: 4));
426 memoryPtr += 4;
427 }
428
429 if (ctx.sym.dataEnd)
430 ctx.sym.dataEnd->setVA(memoryPtr);
431
432 uint64_t staticDataSize = memoryPtr - dataStart;
433 log(msg: "mem: static data = " + Twine(staticDataSize));
434 if (ctx.isPic)
435 out.dylinkSec->memSize = staticDataSize;
436
437 if (!ctx.arg.stackFirst)
438 placeStack();
439
440 if (ctx.sym.heapBase) {
441 // Set `__heap_base` to follow the end of the stack or global data. The
442 // fact that this comes last means that a malloc/brk implementation can
443 // grow the heap at runtime.
444 // We'll align the heap base here because memory allocators might expect
445 // __heap_base to be aligned already.
446 memoryPtr = alignTo(Value: memoryPtr, Align: heapAlignment);
447 log(msg: "mem: heap base = " + Twine(memoryPtr));
448 ctx.sym.heapBase->setVA(memoryPtr);
449 }
450
451 uint64_t maxMemorySetting = 1ULL << 32;
452 if (ctx.arg.is64.value_or(u: false)) {
453 // TODO: Update once we decide on a reasonable limit here:
454 // https://github.com/WebAssembly/memory64/issues/33
455 maxMemorySetting = 1ULL << 34;
456 }
457
458 if (ctx.arg.initialHeap != 0) {
459 checkPageAligned(name: "initial heap", value: ctx.arg.initialHeap);
460 uint64_t maxInitialHeap = maxMemorySetting - memoryPtr;
461 if (ctx.arg.initialHeap > maxInitialHeap)
462 error(msg: "initial heap too large, cannot be greater than " +
463 Twine(maxInitialHeap));
464 memoryPtr += ctx.arg.initialHeap;
465 }
466
467 if (ctx.arg.initialMemory != 0) {
468 checkPageAligned(name: "initial memory", value: ctx.arg.initialMemory);
469 if (memoryPtr > ctx.arg.initialMemory)
470 error(msg: "initial memory too small, " + Twine(memoryPtr) + " bytes needed");
471 if (ctx.arg.initialMemory > maxMemorySetting)
472 error(msg: "initial memory too large, cannot be greater than " +
473 Twine(maxMemorySetting));
474 memoryPtr = ctx.arg.initialMemory;
475 }
476
477 memoryPtr = alignTo(Value: memoryPtr, Align: ctx.arg.pageSize);
478
479 out.memorySec->numMemoryPages = memoryPtr / ctx.arg.pageSize;
480 log(msg: "mem: total pages = " + Twine(out.memorySec->numMemoryPages));
481
482 if (ctx.sym.heapEnd) {
483 // Set `__heap_end` to follow the end of the statically allocated linear
484 // memory. The fact that this comes last means that a malloc/brk
485 // implementation can grow the heap at runtime.
486 log(msg: "mem: heap end = " + Twine(memoryPtr));
487 ctx.sym.heapEnd->setVA(memoryPtr);
488 }
489
490 uint64_t maxMemory = 0;
491 if (ctx.arg.maxMemory != 0) {
492 checkPageAligned(name: "maximum memory", value: ctx.arg.maxMemory);
493 if (memoryPtr > ctx.arg.maxMemory)
494 error(msg: "maximum memory too small, " + Twine(memoryPtr) + " bytes needed");
495 if (ctx.arg.maxMemory > maxMemorySetting)
496 error(msg: "maximum memory too large, cannot be greater than " +
497 Twine(maxMemorySetting));
498
499 maxMemory = ctx.arg.maxMemory;
500 } else if (ctx.arg.noGrowableMemory) {
501 maxMemory = memoryPtr;
502 }
503
504 // If no maxMemory config was supplied but we are building with
505 // shared memory, we need to pick a sensible upper limit.
506 if (ctx.arg.sharedMemory && maxMemory == 0) {
507 if (ctx.isPic)
508 maxMemory = maxMemorySetting;
509 else
510 maxMemory = memoryPtr;
511 }
512
513 if (maxMemory != 0) {
514 out.memorySec->maxMemoryPages = maxMemory / ctx.arg.pageSize;
515 log(msg: "mem: max pages = " + Twine(out.memorySec->maxMemoryPages));
516 }
517}
518
519void Writer::addSection(OutputSection *sec) {
520 if (!sec->isNeeded())
521 return;
522 log(msg: "addSection: " + toString(section: *sec));
523 sec->sectionIndex = outputSections.size();
524 outputSections.push_back(x: sec);
525}
526
527// If a section name is valid as a C identifier (which is rare because of
528// the leading '.'), linkers are expected to define __start_<secname> and
529// __stop_<secname> symbols. They are at beginning and end of the section,
530// respectively. This is not requested by the ELF standard, but GNU ld and
531// gold provide the feature, and used by many programs.
532static void addStartStopSymbols(const OutputSegment *seg) {
533 StringRef name = seg->name;
534 if (!isValidCIdentifier(s: name))
535 return;
536 LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << name << "\n");
537 uint64_t start = seg->startVA;
538 uint64_t stop = start + seg->size;
539 symtab->addOptionalDataSymbol(name: saver().save(S: "__start_" + name), value: start);
540 symtab->addOptionalDataSymbol(name: saver().save(S: "__stop_" + name), value: stop);
541}
542
543void Writer::addSections() {
544 addSection(sec: out.dylinkSec);
545 addSection(sec: out.typeSec);
546 addSection(sec: out.importSec);
547 addSection(sec: out.functionSec);
548 addSection(sec: out.tableSec);
549 addSection(sec: out.memorySec);
550 addSection(sec: out.tagSec);
551 addSection(sec: out.globalSec);
552 addSection(sec: out.exportSec);
553 addSection(sec: out.startSec);
554 addSection(sec: out.elemSec);
555 addSection(sec: out.dataCountSec);
556
557 addSection(sec: make<CodeSection>(args&: out.functionSec->inputFunctions));
558 addSection(sec: make<DataSection>(args&: segments));
559
560 createCustomSections();
561
562 addSection(sec: out.linkingSec);
563 if (ctx.arg.emitRelocs || ctx.arg.relocatable) {
564 createRelocSections();
565 }
566
567 addSection(sec: out.nameSec);
568 addSection(sec: out.producersSec);
569 addSection(sec: out.targetFeaturesSec);
570 addSection(sec: out.buildIdSec);
571}
572
573void Writer::finalizeSections() {
574 for (OutputSection *s : outputSections) {
575 s->setOffset(fileSize);
576 s->finalizeContents();
577 fileSize += s->getSize();
578 }
579}
580
581void Writer::populateTargetFeatures() {
582 StringMap<std::string> used;
583 StringMap<std::string> disallowed;
584 SmallSet<std::string, 8> &allowed = out.targetFeaturesSec->features;
585 bool tlsUsed = false;
586
587 if (ctx.isPic) {
588 // This should not be necessary because all PIC objects should
589 // contain the `mutable-globals` feature.
590 // TODO (https://github.com/llvm/llvm-project/issues/51681)
591 allowed.insert(V: "mutable-globals");
592 }
593
594 if (ctx.arg.extraFeatures.has_value()) {
595 auto &extraFeatures = *ctx.arg.extraFeatures;
596 allowed.insert_range(R&: extraFeatures);
597 }
598
599 // Only infer used features if user did not specify features
600 bool inferFeatures = !ctx.arg.features.has_value();
601
602 if (!inferFeatures) {
603 auto &explicitFeatures = *ctx.arg.features;
604 allowed.insert_range(R&: explicitFeatures);
605 if (!ctx.arg.checkFeatures)
606 goto done;
607 }
608
609 // Find the sets of used and disallowed features
610 for (ObjFile *file : ctx.objectFiles) {
611 StringRef fileName(file->getName());
612 for (auto &feature : file->getWasmObj()->getTargetFeatures()) {
613 switch (feature.Prefix) {
614 case WASM_FEATURE_PREFIX_USED:
615 used.insert(KV: {feature.Name, std::string(fileName)});
616 break;
617 case WASM_FEATURE_PREFIX_DISALLOWED:
618 disallowed.insert(KV: {feature.Name, std::string(fileName)});
619 break;
620 default:
621 error(msg: "Unrecognized feature policy prefix " +
622 std::to_string(val: feature.Prefix));
623 }
624 }
625
626 // Find TLS data segments
627 auto isTLS = [](InputChunk *segment) {
628 return segment->live && segment->isTLS();
629 };
630 tlsUsed = tlsUsed || llvm::any_of(Range&: file->segments, P: isTLS);
631 }
632
633 if (inferFeatures)
634 for (const auto &key : used.keys())
635 allowed.insert(V: std::string(key));
636
637 if (!ctx.arg.checkFeatures)
638 goto done;
639
640 if (ctx.arg.sharedMemory) {
641 if (disallowed.contains(Key: "shared-mem"))
642 error(msg: "--shared-memory is disallowed by " + disallowed["shared-mem"] +
643 " because it was not compiled with 'atomics' or 'bulk-memory' "
644 "features.");
645
646 for (auto feature : {"atomics", "bulk-memory"})
647 if (!allowed.contains(V: feature))
648 error(msg: StringRef("'") + feature +
649 "' feature must be used in order to use shared memory");
650 }
651
652 if (tlsUsed) {
653 for (auto feature : {"atomics", "bulk-memory"})
654 if (!allowed.contains(V: feature))
655 error(msg: StringRef("'") + feature +
656 "' feature must be used in order to use thread-local storage");
657 }
658
659 // Validate that used features are allowed in output
660 if (!inferFeatures) {
661 for (const auto &feature : used.keys()) {
662 if (!allowed.contains(V: std::string(feature)))
663 error(msg: Twine("Target feature '") + feature + "' used by " +
664 used[feature] + " is not allowed.");
665 }
666 }
667
668 // Validate the disallowed constraints for each file
669 for (ObjFile *file : ctx.objectFiles) {
670 StringRef fileName(file->getName());
671 SmallSet<std::string, 8> objectFeatures;
672 for (const auto &feature : file->getWasmObj()->getTargetFeatures()) {
673 if (feature.Prefix == WASM_FEATURE_PREFIX_DISALLOWED)
674 continue;
675 objectFeatures.insert(V: feature.Name);
676 if (disallowed.contains(Key: feature.Name))
677 error(msg: Twine("Target feature '") + feature.Name + "' used in " +
678 fileName + " is disallowed by " + disallowed[feature.Name] +
679 ". Use --no-check-features to suppress.");
680 }
681 }
682
683done:
684 // Normally we don't include bss segments in the binary. In particular if
685 // memory is not being imported then we can assume its zero initialized.
686 // In the case the memory is imported, and we can use the memory.fill
687 // instruction, then we can also avoid including the segments.
688 // Finally, if we are emitting relocations, they may refer to locations within
689 // the bss segments, so these segments need to exist in the binary.
690 if (ctx.arg.emitRelocs ||
691 (ctx.arg.memoryImport.has_value() && !allowed.contains(V: "bulk-memory")))
692 ctx.emitBssSegments = true;
693
694 if (allowed.contains(V: "extended-const"))
695 ctx.arg.extendedConst = true;
696
697 for (auto &feature : allowed)
698 log(msg: "Allowed feature: " + feature);
699}
700
701void Writer::checkImportExportTargetFeatures() {
702 if (ctx.arg.relocatable || !ctx.arg.checkFeatures)
703 return;
704
705 if (!out.targetFeaturesSec->features.contains(V: "mutable-globals")) {
706 for (const Symbol *sym : out.importSec->importedSymbols) {
707 if (auto *global = dyn_cast<GlobalSymbol>(Val: sym)) {
708 if (global->getGlobalType()->Mutable) {
709 error(msg: Twine("mutable global imported but 'mutable-globals' feature "
710 "not present in inputs: `") +
711 toString(sym: *sym) + "`. Use --no-check-features to suppress.");
712 }
713 }
714 }
715 for (const Symbol *sym : out.exportSec->exportedSymbols) {
716 if (auto *global = dyn_cast<GlobalSymbol>(Val: sym)) {
717 if (global->getGlobalType()->Mutable) {
718 error(msg: Twine("mutable global exported but 'mutable-globals' feature "
719 "not present in inputs: `") +
720 toString(sym: *sym) + "`. Use --no-check-features to suppress.");
721 }
722 }
723 }
724 }
725}
726
727static bool shouldImport(Symbol *sym) {
728 // We don't generate imports for data symbols. They however can be imported
729 // as GOT entries.
730 if (isa<DataSymbol>(Val: sym))
731 return false;
732 if (!sym->isLive())
733 return false;
734 if (!sym->isUsedInRegularObj)
735 return false;
736
737 // When a symbol is weakly defined in a shared library we need to allow
738 // it to be overridden by another module so need to both import
739 // and export the symbol.
740 if (ctx.arg.shared && sym->isWeak() && !sym->isUndefined() &&
741 !sym->isHidden())
742 return true;
743 if (sym->isShared())
744 return true;
745 if (!sym->isUndefined())
746 return false;
747 if (sym->isWeak() && !ctx.arg.relocatable && !ctx.isPic)
748 return false;
749
750 // In PIC mode we only need to import functions when they are called directly.
751 // Indirect usage all goes via GOT imports.
752 if (ctx.isPic) {
753 if (auto *f = dyn_cast<UndefinedFunction>(Val: sym))
754 if (!f->isCalledDirectly)
755 return false;
756 }
757
758 if (ctx.isPic || ctx.arg.relocatable || ctx.arg.importUndefined ||
759 ctx.arg.unresolvedSymbols == UnresolvedPolicy::ImportDynamic)
760 return true;
761 if (ctx.arg.allowUndefinedSymbols.contains(key: sym->getName()))
762 return true;
763
764 return sym->isImported();
765}
766
767void Writer::calculateImports() {
768 // Some inputs require that the indirect function table be assigned to table
769 // number 0, so if it is present and is an import, allocate it before any
770 // other tables.
771 if (ctx.sym.indirectFunctionTable &&
772 shouldImport(sym: ctx.sym.indirectFunctionTable))
773 out.importSec->addImport(sym: ctx.sym.indirectFunctionTable);
774
775 for (Symbol *sym : symtab->symbols()) {
776 if (!shouldImport(sym))
777 continue;
778 if (sym == ctx.sym.indirectFunctionTable)
779 continue;
780 LLVM_DEBUG(dbgs() << "import: " << sym->getName() << "\n");
781 out.importSec->addImport(sym);
782 }
783}
784
785void Writer::calculateExports() {
786 if (ctx.arg.relocatable)
787 return;
788
789 if (!ctx.arg.relocatable && ctx.arg.memoryExport.has_value()) {
790 out.exportSec->exports.push_back(
791 x: WasmExport{.Name: *ctx.arg.memoryExport, .Kind: WASM_EXTERNAL_MEMORY, .Index: 0});
792 }
793
794 unsigned globalIndex =
795 out.importSec->getNumImportedGlobals() + out.globalSec->numGlobals();
796
797 bool hasMutableGlobals =
798 out.targetFeaturesSec->features.contains(V: "mutable-globals");
799
800 for (Symbol *sym : symtab->symbols()) {
801 if (!sym->isExported())
802 continue;
803 if (!sym->isLive())
804 continue;
805 if (isa<SharedFunctionSymbol>(Val: sym) || sym->isShared())
806 continue;
807
808 StringRef name = sym->getName();
809 LLVM_DEBUG(dbgs() << "Export: " << name << "\n");
810 WasmExport export_;
811 if (auto *f = dyn_cast<DefinedFunction>(Val: sym)) {
812 if (std::optional<StringRef> exportName = f->function->getExportName()) {
813 name = *exportName;
814 }
815 export_ = {.Name: name, .Kind: WASM_EXTERNAL_FUNCTION, .Index: f->getExportedFunctionIndex()};
816 } else if (auto *g = dyn_cast<DefinedGlobal>(Val: sym)) {
817 if (!hasMutableGlobals && g->getGlobalType()->Mutable && !g->getFile() &&
818 !g->isExportedExplicit()) {
819 // Avoid exporting mutable globals are linker synthesized (e.g.
820 // __stack_pointer or __tls_base) unless they are explicitly exported
821 // from the command line.
822 // Without this check `--export-all` would cause any program using the
823 // stack pointer to export a mutable global even if none of the input
824 // files were built with the `mutable-globals` feature.
825 continue;
826 }
827 export_ = {.Name: name, .Kind: WASM_EXTERNAL_GLOBAL, .Index: g->getGlobalIndex()};
828 } else if (auto *t = dyn_cast<DefinedTag>(Val: sym)) {
829 export_ = {.Name: name, .Kind: WASM_EXTERNAL_TAG, .Index: t->getTagIndex()};
830 } else if (auto *d = dyn_cast<DefinedData>(Val: sym)) {
831 out.globalSec->dataAddressGlobals.push_back(x: d);
832 export_ = {.Name: name, .Kind: WASM_EXTERNAL_GLOBAL, .Index: globalIndex++};
833 } else {
834 auto *t = cast<DefinedTable>(Val: sym);
835 export_ = {.Name: name, .Kind: WASM_EXTERNAL_TABLE, .Index: t->getTableNumber()};
836 }
837
838 out.exportSec->exports.push_back(x: export_);
839 out.exportSec->exportedSymbols.push_back(x: sym);
840 }
841}
842
843void Writer::populateSymtab() {
844 if (!ctx.arg.relocatable && !ctx.arg.emitRelocs)
845 return;
846
847 for (Symbol *sym : symtab->symbols())
848 if (sym->isUsedInRegularObj && sym->isLive() && !sym->isShared())
849 out.linkingSec->addToSymtab(sym);
850
851 for (ObjFile *file : ctx.objectFiles) {
852 LLVM_DEBUG(dbgs() << "Local symtab entries: " << file->getName() << "\n");
853 for (Symbol *sym : file->getSymbols())
854 if (sym->isLocal() && !isa<SectionSymbol>(Val: sym) && sym->isLive())
855 out.linkingSec->addToSymtab(sym);
856 }
857}
858
859void Writer::calculateTypes() {
860 // The output type section is the union of the following sets:
861 // 1. Any signature used in the TYPE relocation
862 // 2. The signatures of all imported functions
863 // 3. The signatures of all defined functions
864 // 4. The signatures of all imported tags
865 // 5. The signatures of all defined tags
866
867 for (ObjFile *file : ctx.objectFiles) {
868 ArrayRef<WasmSignature> types = file->getWasmObj()->types();
869 for (uint32_t i = 0; i < types.size(); i++)
870 if (file->typeIsUsed[i])
871 file->typeMap[i] = out.typeSec->registerType(sig: types[i]);
872 }
873
874 for (const Symbol *sym : out.importSec->importedSymbols) {
875 if (auto *f = dyn_cast<FunctionSymbol>(Val: sym))
876 out.typeSec->registerType(sig: *f->signature);
877 else if (auto *t = dyn_cast<TagSymbol>(Val: sym))
878 out.typeSec->registerType(sig: *t->signature);
879 }
880
881 for (const InputFunction *f : out.functionSec->inputFunctions)
882 out.typeSec->registerType(sig: f->signature);
883
884 for (const InputTag *t : out.tagSec->inputTags)
885 out.typeSec->registerType(sig: t->signature);
886}
887
888// In a command-style link, create a wrapper for each exported symbol
889// which calls the constructors and destructors.
890void Writer::createCommandExportWrappers() {
891 // This logic doesn't currently support Emscripten-style PIC mode.
892 assert(!ctx.isPic);
893
894 // If there are no ctors and there's no libc `__wasm_call_dtors` to
895 // call, don't wrap the exports.
896 if (initFunctions.empty() && ctx.sym.callDtors == nullptr)
897 return;
898
899 std::vector<DefinedFunction *> toWrap;
900
901 for (Symbol *sym : symtab->symbols())
902 if (sym->isExported())
903 if (auto *f = dyn_cast<DefinedFunction>(Val: sym))
904 toWrap.push_back(x: f);
905
906 for (auto *f : toWrap) {
907 auto funcNameStr = (f->getName() + ".command_export").str();
908 commandExportWrapperNames.push_back(x: funcNameStr);
909 const std::string &funcName = commandExportWrapperNames.back();
910
911 auto func = make<SyntheticFunction>(args: *f->getSignature(), args: funcName);
912 if (f->function->getExportName())
913 func->setExportName(f->function->getExportName()->str());
914 else
915 func->setExportName(f->getName().str());
916
917 DefinedFunction *def =
918 symtab->addSyntheticFunction(name: funcName, flags: f->flags, function: func);
919 def->markLive();
920
921 def->flags |= WASM_SYMBOL_EXPORTED;
922 def->flags &= ~WASM_SYMBOL_VISIBILITY_HIDDEN;
923 def->forceExport = f->forceExport;
924
925 f->flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
926 f->flags &= ~WASM_SYMBOL_EXPORTED;
927 f->forceExport = false;
928
929 out.functionSec->addFunction(func);
930
931 createCommandExportWrapper(functionIndex: f->getFunctionIndex(), f: def);
932 }
933}
934
935static void finalizeIndirectFunctionTable() {
936 if (!ctx.sym.indirectFunctionTable)
937 return;
938
939 if (shouldImport(sym: ctx.sym.indirectFunctionTable) &&
940 !ctx.sym.indirectFunctionTable->hasTableNumber()) {
941 // Processing -Bsymbolic relocations resulted in a late requirement that the
942 // indirect function table be present, and we are running in --import-table
943 // mode. Add the table now to the imports section. Otherwise it will be
944 // added to the tables section later in assignIndexes.
945 out.importSec->addImport(sym: ctx.sym.indirectFunctionTable);
946 }
947
948 uint32_t tableSize = ctx.arg.tableBase + out.elemSec->numEntries();
949 WasmLimits limits = {.Flags: 0, .Minimum: tableSize, .Maximum: 0, .PageSize: 0};
950 if (ctx.sym.indirectFunctionTable->isDefined() && !ctx.arg.growableTable) {
951 limits.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
952 limits.Maximum = limits.Minimum;
953 }
954 if (ctx.arg.is64.value_or(u: false))
955 limits.Flags |= WASM_LIMITS_FLAG_IS_64;
956 ctx.sym.indirectFunctionTable->setLimits(limits);
957}
958
959static void scanRelocations() {
960 for (ObjFile *file : ctx.objectFiles) {
961 LLVM_DEBUG(dbgs() << "scanRelocations: " << file->getName() << "\n");
962 for (InputChunk *chunk : file->functions)
963 scanRelocations(chunk);
964 for (InputChunk *chunk : file->segments)
965 scanRelocations(chunk);
966 for (auto &p : file->customSections)
967 scanRelocations(chunk: p);
968 }
969}
970
971void Writer::assignIndexes() {
972 // Seal the import section, since other index spaces such as function and
973 // global are effected by the number of imports.
974 out.importSec->seal();
975
976 for (InputFunction *func : ctx.syntheticFunctions)
977 out.functionSec->addFunction(func);
978
979 for (ObjFile *file : ctx.objectFiles) {
980 LLVM_DEBUG(dbgs() << "Functions: " << file->getName() << "\n");
981 for (InputFunction *func : file->functions)
982 out.functionSec->addFunction(func);
983 }
984
985 for (InputGlobal *global : ctx.syntheticGlobals)
986 out.globalSec->addGlobal(global);
987
988 for (ObjFile *file : ctx.objectFiles) {
989 LLVM_DEBUG(dbgs() << "Globals: " << file->getName() << "\n");
990 for (InputGlobal *global : file->globals)
991 out.globalSec->addGlobal(global);
992 }
993
994 for (ObjFile *file : ctx.objectFiles) {
995 LLVM_DEBUG(dbgs() << "Tags: " << file->getName() << "\n");
996 for (InputTag *tag : file->tags)
997 out.tagSec->addTag(tag);
998 }
999
1000 for (ObjFile *file : ctx.objectFiles) {
1001 LLVM_DEBUG(dbgs() << "Tables: " << file->getName() << "\n");
1002 for (InputTable *table : file->tables)
1003 out.tableSec->addTable(table);
1004 }
1005
1006 for (InputTable *table : ctx.syntheticTables)
1007 out.tableSec->addTable(table);
1008
1009 out.globalSec->assignIndexes();
1010 out.tableSec->assignIndexes();
1011}
1012
1013static StringRef getOutputDataSegmentName(const InputChunk &seg) {
1014 // We always merge .tbss and .tdata into a single TLS segment so all TLS
1015 // symbols are be relative to single __tls_base.
1016 if (seg.isTLS())
1017 return ".tdata";
1018 if (!ctx.arg.mergeDataSegments)
1019 return seg.name;
1020 if (seg.name.starts_with(Prefix: ".text."))
1021 return ".text";
1022 if (seg.name.starts_with(Prefix: ".data."))
1023 return ".data";
1024 if (seg.name.starts_with(Prefix: ".bss."))
1025 return ".bss";
1026 if (seg.name.starts_with(Prefix: ".rodata."))
1027 return ".rodata";
1028 return seg.name;
1029}
1030
1031OutputSegment *Writer::createOutputSegment(StringRef name) {
1032 LLVM_DEBUG(dbgs() << "new segment: " << name << "\n");
1033 OutputSegment *s = make<OutputSegment>(args&: name);
1034 if (ctx.arg.sharedMemory)
1035 s->initFlags = WASM_DATA_SEGMENT_IS_PASSIVE;
1036 if (!ctx.arg.relocatable && name.starts_with(Prefix: ".bss"))
1037 s->isBss = true;
1038 segments.push_back(x: s);
1039 return s;
1040}
1041
1042void Writer::createOutputSegments() {
1043 for (ObjFile *file : ctx.objectFiles) {
1044 for (InputChunk *segment : file->segments) {
1045 if (!segment->live)
1046 continue;
1047 StringRef name = getOutputDataSegmentName(seg: *segment);
1048 OutputSegment *s = nullptr;
1049 // When running in relocatable mode we can't merge segments that are part
1050 // of comdat groups since the ultimate linker needs to be able exclude or
1051 // include them individually.
1052 if (ctx.arg.relocatable && !segment->getComdatName().empty()) {
1053 s = createOutputSegment(name);
1054 } else {
1055 if (!segmentMap.contains(Val: name))
1056 segmentMap[name] = createOutputSegment(name);
1057 s = segmentMap[name];
1058 }
1059 s->addInputSegment(inSeg: segment);
1060 }
1061 }
1062
1063 // Sort segments by type, placing .bss last
1064 llvm::stable_sort(Range&: segments,
1065 C: [](const OutputSegment *a, const OutputSegment *b) {
1066 auto order = [](StringRef name) {
1067 return StringSwitch<int>(name)
1068 .StartsWith(S: ".tdata", Value: 0)
1069 .StartsWith(S: ".rodata", Value: 1)
1070 .StartsWith(S: ".data", Value: 2)
1071 .StartsWith(S: ".bss", Value: 4)
1072 .Default(Value: 3);
1073 };
1074 return order(a->name) < order(b->name);
1075 });
1076
1077 for (size_t i = 0; i < segments.size(); ++i)
1078 segments[i]->index = i;
1079
1080 // Merge MergeInputSections into a single MergeSyntheticSection.
1081 LLVM_DEBUG(dbgs() << "-- finalize input semgments\n");
1082 for (OutputSegment *seg : segments)
1083 seg->finalizeInputSegments();
1084}
1085
1086void Writer::combineOutputSegments() {
1087 // With PIC code we currently only support a single active data segment since
1088 // we only have a single __memory_base to use as our base address. This pass
1089 // combines all data segments into a single .data segment.
1090 // This restriction does not apply when the extended const extension is
1091 // available: https://github.com/WebAssembly/extended-const
1092 assert(!ctx.arg.extendedConst);
1093 assert(ctx.isPic && !ctx.arg.sharedMemory);
1094 if (segments.size() <= 1)
1095 return;
1096 OutputSegment *combined = make<OutputSegment>(args: ".data");
1097 combined->startVA = segments[0]->startVA;
1098 std::vector<OutputSegment *> newSegments = {combined};
1099 for (OutputSegment *s : segments) {
1100 if (!s->requiredInBinary()) {
1101 newSegments.push_back(x: s);
1102 continue;
1103 }
1104 bool first = true;
1105 for (InputChunk *inSeg : s->inputSegments) {
1106 if (first)
1107 inSeg->alignment = std::max(a: inSeg->alignment, b: s->alignment);
1108 first = false;
1109#ifndef NDEBUG
1110 uint64_t oldVA = inSeg->getVA();
1111#endif
1112 combined->addInputSegment(inSeg);
1113#ifndef NDEBUG
1114 uint64_t newVA = inSeg->getVA();
1115 LLVM_DEBUG(dbgs() << "added input segment. name=" << inSeg->name
1116 << " oldVA=" << oldVA << " newVA=" << newVA << "\n");
1117 assert(oldVA == newVA);
1118#endif
1119 }
1120 }
1121
1122 segments = std::move(newSegments);
1123}
1124
1125static void createFunction(DefinedFunction *func, StringRef bodyContent) {
1126 std::string functionBody;
1127 {
1128 raw_string_ostream os(functionBody);
1129 writeUleb128(os, number: bodyContent.size(), msg: "function size");
1130 os << bodyContent;
1131 }
1132 ArrayRef<uint8_t> body = arrayRefFromStringRef(Input: saver().save(S: functionBody));
1133 cast<SyntheticFunction>(Val: func->function)->setBody(body);
1134}
1135
1136bool Writer::needsPassiveInitialization(const OutputSegment *segment) {
1137 // If bulk memory features is supported then we can perform bss initialization
1138 // (via memory.fill) during `__wasm_init_memory`.
1139 if (ctx.arg.memoryImport.has_value() && !segment->requiredInBinary())
1140 return true;
1141 return segment->initFlags & WASM_DATA_SEGMENT_IS_PASSIVE;
1142}
1143
1144bool Writer::hasPassiveInitializedSegments() {
1145 return llvm::any_of(Range&: segments, P: [this](const OutputSegment *s) {
1146 return this->needsPassiveInitialization(segment: s);
1147 });
1148}
1149
1150void Writer::createSyntheticInitFunctions() {
1151 if (ctx.arg.relocatable)
1152 return;
1153
1154 static WasmSignature nullSignature = {{}, {}};
1155
1156 createApplyDataRelocationsFunction();
1157
1158 // Passive segments are used to avoid memory being reinitialized on each
1159 // thread's instantiation. These passive segments are initialized and
1160 // dropped in __wasm_init_memory, which is registered as the start function
1161 // We also initialize bss segments (using memory.fill) as part of this
1162 // function.
1163 if (hasPassiveInitializedSegments()) {
1164 ctx.sym.initMemory = symtab->addSyntheticFunction(
1165 name: "__wasm_init_memory", flags: WASM_SYMBOL_VISIBILITY_HIDDEN,
1166 function: make<SyntheticFunction>(args&: nullSignature, args: "__wasm_init_memory"));
1167 ctx.sym.initMemory->markLive();
1168 if (ctx.arg.sharedMemory) {
1169 // This global is assigned during __wasm_init_memory in the shared memory
1170 // case.
1171 ctx.sym.tlsBase->markLive();
1172 }
1173 }
1174
1175 if (ctx.arg.sharedMemory) {
1176 if (out.globalSec->needsTLSRelocations()) {
1177 ctx.sym.applyGlobalTLSRelocs = symtab->addSyntheticFunction(
1178 name: "__wasm_apply_global_tls_relocs", flags: WASM_SYMBOL_VISIBILITY_HIDDEN,
1179 function: make<SyntheticFunction>(args&: nullSignature,
1180 args: "__wasm_apply_global_tls_relocs"));
1181 ctx.sym.applyGlobalTLSRelocs->markLive();
1182 // TLS relocations depend on the __tls_base symbols
1183 ctx.sym.tlsBase->markLive();
1184 }
1185
1186 auto hasTLSRelocs = [](const OutputSegment *segment) {
1187 if (segment->isTLS())
1188 for (const auto *is : segment->inputSegments)
1189 if (is->getRelocations().size())
1190 return true;
1191 return false;
1192 };
1193 if (llvm::any_of(Range&: segments, P: hasTLSRelocs)) {
1194 ctx.sym.applyTLSRelocs = symtab->addSyntheticFunction(
1195 name: "__wasm_apply_tls_relocs", flags: WASM_SYMBOL_VISIBILITY_HIDDEN,
1196 function: make<SyntheticFunction>(args&: nullSignature, args: "__wasm_apply_tls_relocs"));
1197 ctx.sym.applyTLSRelocs->markLive();
1198 }
1199 }
1200
1201 if (ctx.isPic && out.globalSec->needsRelocations()) {
1202 ctx.sym.applyGlobalRelocs = symtab->addSyntheticFunction(
1203 name: "__wasm_apply_global_relocs", flags: WASM_SYMBOL_VISIBILITY_HIDDEN,
1204 function: make<SyntheticFunction>(args&: nullSignature, args: "__wasm_apply_global_relocs"));
1205 ctx.sym.applyGlobalRelocs->markLive();
1206 }
1207
1208 // If there is only one start function we can just use that function
1209 // itself as the Wasm start function, otherwise we need to synthesize
1210 // a new function to call them in sequence.
1211 if (ctx.sym.applyGlobalRelocs && ctx.sym.initMemory) {
1212 ctx.sym.startFunction = symtab->addSyntheticFunction(
1213 name: "__wasm_start", flags: WASM_SYMBOL_VISIBILITY_HIDDEN,
1214 function: make<SyntheticFunction>(args&: nullSignature, args: "__wasm_start"));
1215 ctx.sym.startFunction->markLive();
1216 }
1217}
1218
1219void Writer::createInitMemoryFunction() {
1220 LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n");
1221 assert(ctx.sym.initMemory);
1222 assert(hasPassiveInitializedSegments());
1223 uint64_t flagAddress;
1224 if (ctx.arg.sharedMemory) {
1225 assert(ctx.sym.initMemoryFlag);
1226 flagAddress = ctx.sym.initMemoryFlag->getVA();
1227 }
1228 bool is64 = ctx.arg.is64.value_or(u: false);
1229 std::string bodyContent;
1230 {
1231 raw_string_ostream os(bodyContent);
1232 // Initialize memory in a thread-safe manner. The thread that successfully
1233 // increments the flag from 0 to 1 is responsible for performing the memory
1234 // initialization. Other threads go sleep on the flag until the first thread
1235 // finishing initializing memory, increments the flag to 2, and wakes all
1236 // the other threads. Once the flag has been set to 2, subsequently started
1237 // threads will skip the sleep. All threads unconditionally drop their
1238 // passive data segments once memory has been initialized. The generated
1239 // code is as follows:
1240 //
1241 // (func $__wasm_init_memory
1242 // (block $drop
1243 // (block $wait
1244 // (block $init
1245 // (br_table $init $wait $drop
1246 // (i32.atomic.rmw.cmpxchg align=2 offset=0
1247 // (i32.const $__init_memory_flag)
1248 // (i32.const 0)
1249 // (i32.const 1)
1250 // )
1251 // )
1252 // ) ;; $init
1253 // ( ... initialize data segments ... )
1254 // (i32.atomic.store align=2 offset=0
1255 // (i32.const $__init_memory_flag)
1256 // (i32.const 2)
1257 // )
1258 // (drop
1259 // (i32.atomic.notify align=2 offset=0
1260 // (i32.const $__init_memory_flag)
1261 // (i32.const -1u)
1262 // )
1263 // )
1264 // (br $drop)
1265 // ) ;; $wait
1266 // (drop
1267 // (i32.atomic.wait align=2 offset=0
1268 // (i32.const $__init_memory_flag)
1269 // (i32.const 1)
1270 // (i32.const -1)
1271 // )
1272 // )
1273 // ) ;; $drop
1274 // ( ... drop data segments ... )
1275 // )
1276 //
1277 // When we are building with PIC, calculate the flag location using:
1278 //
1279 // (global.get $__memory_base)
1280 // (i32.const $__init_memory_flag)
1281 // (i32.const 1)
1282
1283 auto writeGetFlagAddress = [&]() {
1284 if (ctx.isPic) {
1285 writeU8(os, byte: WASM_OPCODE_LOCAL_GET, msg: "local.get");
1286 writeUleb128(os, number: 0, msg: "local 0");
1287 } else {
1288 writePtrConst(os, number: flagAddress, is64, msg: "flag address");
1289 }
1290 };
1291
1292 if (ctx.arg.sharedMemory) {
1293 // With PIC code we cache the flag address in local 0
1294 if (ctx.isPic) {
1295 writeUleb128(os, number: 1, msg: "num local decls");
1296 writeUleb128(os, number: 2, msg: "local count");
1297 writeU8(os, byte: is64 ? WASM_TYPE_I64 : WASM_TYPE_I32, msg: "address type");
1298 writeU8(os, byte: WASM_OPCODE_GLOBAL_GET, msg: "GLOBAL_GET");
1299 writeUleb128(os, number: ctx.sym.memoryBase->getGlobalIndex(), msg: "memory_base");
1300 writePtrConst(os, number: flagAddress, is64, msg: "flag address");
1301 writeU8(os, byte: is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD, msg: "add");
1302 writeU8(os, byte: WASM_OPCODE_LOCAL_SET, msg: "local.set");
1303 writeUleb128(os, number: 0, msg: "local 0");
1304 } else {
1305 writeUleb128(os, number: 0, msg: "num locals");
1306 }
1307
1308 // Set up destination blocks
1309 writeU8(os, byte: WASM_OPCODE_BLOCK, msg: "block $drop");
1310 writeU8(os, byte: WASM_TYPE_NORESULT, msg: "block type");
1311 writeU8(os, byte: WASM_OPCODE_BLOCK, msg: "block $wait");
1312 writeU8(os, byte: WASM_TYPE_NORESULT, msg: "block type");
1313 writeU8(os, byte: WASM_OPCODE_BLOCK, msg: "block $init");
1314 writeU8(os, byte: WASM_TYPE_NORESULT, msg: "block type");
1315
1316 // Atomically check whether we win the race.
1317 writeGetFlagAddress();
1318 writeI32Const(os, number: 0, msg: "expected flag value");
1319 writeI32Const(os, number: 1, msg: "new flag value");
1320 writeU8(os, byte: WASM_OPCODE_ATOMICS_PREFIX, msg: "atomics prefix");
1321 writeUleb128(os, number: WASM_OPCODE_I32_RMW_CMPXCHG, msg: "i32.atomic.rmw.cmpxchg");
1322 writeMemArg(os, alignment: 2, offset: 0);
1323
1324 // Based on the value, decide what to do next.
1325 writeU8(os, byte: WASM_OPCODE_BR_TABLE, msg: "br_table");
1326 writeUleb128(os, number: 2, msg: "label vector length");
1327 writeUleb128(os, number: 0, msg: "label $init");
1328 writeUleb128(os, number: 1, msg: "label $wait");
1329 writeUleb128(os, number: 2, msg: "default label $drop");
1330
1331 // Initialize passive data segments
1332 writeU8(os, byte: WASM_OPCODE_END, msg: "end $init");
1333 } else {
1334 writeUleb128(os, number: 0, msg: "num local decls");
1335 }
1336
1337 for (const OutputSegment *s : segments) {
1338 if (needsPassiveInitialization(segment: s)) {
1339 // For passive BSS segments we can simple issue a memory.fill(0).
1340 // For non-BSS segments we do a memory.init. Both these
1341 // instructions take as their first argument the destination
1342 // address.
1343 writePtrConst(os, number: s->startVA, is64, msg: "destination address");
1344 if (ctx.isPic) {
1345 writeU8(os, byte: WASM_OPCODE_GLOBAL_GET, msg: "GLOBAL_GET");
1346 writeUleb128(os, number: ctx.sym.memoryBase->getGlobalIndex(),
1347 msg: "__memory_base");
1348 writeU8(os, byte: is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD,
1349 msg: "i32.add");
1350 }
1351
1352 // When we initialize the TLS segment we also set the `__tls_base`
1353 // global. This allows the runtime to use this static copy of the
1354 // TLS data for the first/main thread.
1355 if (ctx.arg.sharedMemory && s->isTLS()) {
1356 if (ctx.isPic) {
1357 // Cache the result of the addionion in local 0
1358 writeU8(os, byte: WASM_OPCODE_LOCAL_TEE, msg: "local.tee");
1359 writeUleb128(os, number: 1, msg: "local 1");
1360 } else {
1361 writePtrConst(os, number: s->startVA, is64, msg: "destination address");
1362 }
1363 writeU8(os, byte: WASM_OPCODE_GLOBAL_SET, msg: "GLOBAL_SET");
1364 writeUleb128(os, number: ctx.sym.tlsBase->getGlobalIndex(), msg: "__tls_base");
1365 if (ctx.isPic) {
1366 writeU8(os, byte: WASM_OPCODE_LOCAL_GET, msg: "local.tee");
1367 writeUleb128(os, number: 1, msg: "local 1");
1368 }
1369 }
1370
1371 if (s->isBss) {
1372 writeI32Const(os, number: 0, msg: "fill value");
1373 writePtrConst(os, number: s->size, is64, msg: "memory region size");
1374 writeU8(os, byte: WASM_OPCODE_MISC_PREFIX, msg: "bulk-memory prefix");
1375 writeUleb128(os, number: WASM_OPCODE_MEMORY_FILL, msg: "memory.fill");
1376 writeU8(os, byte: 0, msg: "memory index immediate");
1377 } else {
1378 writeI32Const(os, number: 0, msg: "source segment offset");
1379 writeI32Const(os, number: s->size, msg: "memory region size");
1380 writeU8(os, byte: WASM_OPCODE_MISC_PREFIX, msg: "bulk-memory prefix");
1381 writeUleb128(os, number: WASM_OPCODE_MEMORY_INIT, msg: "memory.init");
1382 writeUleb128(os, number: s->index, msg: "segment index immediate");
1383 writeU8(os, byte: 0, msg: "memory index immediate");
1384 }
1385 }
1386 }
1387
1388 if (ctx.arg.sharedMemory) {
1389 // Set flag to 2 to mark end of initialization
1390 writeGetFlagAddress();
1391 writeI32Const(os, number: 2, msg: "flag value");
1392 writeU8(os, byte: WASM_OPCODE_ATOMICS_PREFIX, msg: "atomics prefix");
1393 writeUleb128(os, number: WASM_OPCODE_I32_ATOMIC_STORE, msg: "i32.atomic.store");
1394 writeMemArg(os, alignment: 2, offset: 0);
1395
1396 // Notify any waiters that memory initialization is complete
1397 writeGetFlagAddress();
1398 writeI32Const(os, number: -1, msg: "number of waiters");
1399 writeU8(os, byte: WASM_OPCODE_ATOMICS_PREFIX, msg: "atomics prefix");
1400 writeUleb128(os, number: WASM_OPCODE_ATOMIC_NOTIFY, msg: "atomic.notify");
1401 writeMemArg(os, alignment: 2, offset: 0);
1402 writeU8(os, byte: WASM_OPCODE_DROP, msg: "drop");
1403
1404 // Branch to drop the segments
1405 writeU8(os, byte: WASM_OPCODE_BR, msg: "br");
1406 writeUleb128(os, number: 1, msg: "label $drop");
1407
1408 // Wait for the winning thread to initialize memory
1409 writeU8(os, byte: WASM_OPCODE_END, msg: "end $wait");
1410 writeGetFlagAddress();
1411 writeI32Const(os, number: 1, msg: "expected flag value");
1412 writeI64Const(os, number: -1, msg: "timeout");
1413
1414 writeU8(os, byte: WASM_OPCODE_ATOMICS_PREFIX, msg: "atomics prefix");
1415 writeUleb128(os, number: WASM_OPCODE_I32_ATOMIC_WAIT, msg: "i32.atomic.wait");
1416 writeMemArg(os, alignment: 2, offset: 0);
1417 writeU8(os, byte: WASM_OPCODE_DROP, msg: "drop");
1418
1419 // Unconditionally drop passive data segments
1420 writeU8(os, byte: WASM_OPCODE_END, msg: "end $drop");
1421 }
1422
1423 for (const OutputSegment *s : segments) {
1424 if (needsPassiveInitialization(segment: s) && !s->isBss) {
1425 // The TLS region should not be dropped since its is needed
1426 // during the initialization of each thread (__wasm_init_tls).
1427 if (ctx.arg.sharedMemory && s->isTLS())
1428 continue;
1429 // data.drop instruction
1430 writeU8(os, byte: WASM_OPCODE_MISC_PREFIX, msg: "bulk-memory prefix");
1431 writeUleb128(os, number: WASM_OPCODE_DATA_DROP, msg: "data.drop");
1432 writeUleb128(os, number: s->index, msg: "segment index immediate");
1433 }
1434 }
1435
1436 // End the function
1437 writeU8(os, byte: WASM_OPCODE_END, msg: "END");
1438 }
1439
1440 createFunction(func: ctx.sym.initMemory, bodyContent);
1441}
1442
1443void Writer::createStartFunction() {
1444 // If the start function exists when we have more than one function to call.
1445 if (ctx.sym.initMemory && ctx.sym.applyGlobalRelocs) {
1446 assert(ctx.sym.startFunction);
1447 std::string bodyContent;
1448 {
1449 raw_string_ostream os(bodyContent);
1450 writeUleb128(os, number: 0, msg: "num locals");
1451 writeU8(os, byte: WASM_OPCODE_CALL, msg: "CALL");
1452 writeUleb128(os, number: ctx.sym.applyGlobalRelocs->getFunctionIndex(),
1453 msg: "function index");
1454 writeU8(os, byte: WASM_OPCODE_CALL, msg: "CALL");
1455 writeUleb128(os, number: ctx.sym.initMemory->getFunctionIndex(),
1456 msg: "function index");
1457 writeU8(os, byte: WASM_OPCODE_END, msg: "END");
1458 }
1459 createFunction(func: ctx.sym.startFunction, bodyContent);
1460 } else if (ctx.sym.initMemory) {
1461 ctx.sym.startFunction = ctx.sym.initMemory;
1462 } else if (ctx.sym.applyGlobalRelocs) {
1463 ctx.sym.startFunction = ctx.sym.applyGlobalRelocs;
1464 }
1465}
1466
1467// For -shared (PIC) output, we create create a synthetic function which will
1468// apply any relocations to the data segments on startup. This function is
1469// called `__wasm_apply_data_relocs` and is expected to be called before
1470// any user code (i.e. before `__wasm_call_ctors`).
1471void Writer::createApplyDataRelocationsFunction() {
1472 LLVM_DEBUG(dbgs() << "createApplyDataRelocationsFunction\n");
1473 // First write the body's contents to a string.
1474 std::string bodyContent;
1475 {
1476 raw_string_ostream os(bodyContent);
1477 writeUleb128(os, number: 0, msg: "num locals");
1478 bool generated = false;
1479 for (const OutputSegment *seg : segments)
1480 if (!ctx.arg.sharedMemory || !seg->isTLS())
1481 for (const InputChunk *inSeg : seg->inputSegments)
1482 generated |= inSeg->generateRelocationCode(os);
1483
1484 if (!generated) {
1485 LLVM_DEBUG(dbgs() << "skipping empty __wasm_apply_data_relocs\n");
1486 return;
1487 }
1488 writeU8(os, byte: WASM_OPCODE_END, msg: "END");
1489 }
1490
1491 // __wasm_apply_data_relocs
1492 // Function that applies relocations to data segment post-instantiation.
1493 static WasmSignature nullSignature = {{}, {}};
1494 auto def = symtab->addSyntheticFunction(
1495 name: "__wasm_apply_data_relocs",
1496 flags: WASM_SYMBOL_VISIBILITY_DEFAULT | WASM_SYMBOL_EXPORTED,
1497 function: make<SyntheticFunction>(args&: nullSignature, args: "__wasm_apply_data_relocs"));
1498 def->markLive();
1499
1500 createFunction(func: def, bodyContent);
1501}
1502
1503void Writer::createApplyTLSRelocationsFunction() {
1504 LLVM_DEBUG(dbgs() << "createApplyTLSRelocationsFunction\n");
1505 std::string bodyContent;
1506 {
1507 raw_string_ostream os(bodyContent);
1508 writeUleb128(os, number: 0, msg: "num locals");
1509 for (const OutputSegment *seg : segments)
1510 if (seg->isTLS())
1511 for (const InputChunk *inSeg : seg->inputSegments)
1512 inSeg->generateRelocationCode(os);
1513
1514 writeU8(os, byte: WASM_OPCODE_END, msg: "END");
1515 }
1516
1517 createFunction(func: ctx.sym.applyTLSRelocs, bodyContent);
1518}
1519
1520// Similar to createApplyDataRelocationsFunction but generates relocation code
1521// for WebAssembly globals. Because these globals are not shared between threads
1522// these relocation need to run on every thread.
1523void Writer::createApplyGlobalRelocationsFunction() {
1524 // First write the body's contents to a string.
1525 std::string bodyContent;
1526 {
1527 raw_string_ostream os(bodyContent);
1528 writeUleb128(os, number: 0, msg: "num locals");
1529 out.globalSec->generateRelocationCode(os, TLS: false);
1530 writeU8(os, byte: WASM_OPCODE_END, msg: "END");
1531 }
1532
1533 createFunction(func: ctx.sym.applyGlobalRelocs, bodyContent);
1534}
1535
1536// Similar to createApplyGlobalRelocationsFunction but for
1537// TLS symbols. This cannot be run during the start function
1538// but must be delayed until __wasm_init_tls is called.
1539void Writer::createApplyGlobalTLSRelocationsFunction() {
1540 // First write the body's contents to a string.
1541 std::string bodyContent;
1542 {
1543 raw_string_ostream os(bodyContent);
1544 writeUleb128(os, number: 0, msg: "num locals");
1545 out.globalSec->generateRelocationCode(os, TLS: true);
1546 writeU8(os, byte: WASM_OPCODE_END, msg: "END");
1547 }
1548
1549 createFunction(func: ctx.sym.applyGlobalTLSRelocs, bodyContent);
1550}
1551
1552// Create synthetic "__wasm_call_ctors" function based on ctor functions
1553// in input object.
1554void Writer::createCallCtorsFunction() {
1555 // If __wasm_call_ctors isn't referenced, there aren't any ctors, don't
1556 // define the `__wasm_call_ctors` function.
1557 if (!ctx.sym.callCtors->isLive() && initFunctions.empty())
1558 return;
1559
1560 // First write the body's contents to a string.
1561 std::string bodyContent;
1562 {
1563 raw_string_ostream os(bodyContent);
1564 writeUleb128(os, number: 0, msg: "num locals");
1565
1566 // Call constructors
1567 for (const WasmInitEntry &f : initFunctions) {
1568 writeU8(os, byte: WASM_OPCODE_CALL, msg: "CALL");
1569 writeUleb128(os, number: f.sym->getFunctionIndex(), msg: "function index");
1570 for (size_t i = 0; i < f.sym->signature->Returns.size(); i++) {
1571 writeU8(os, byte: WASM_OPCODE_DROP, msg: "DROP");
1572 }
1573 }
1574
1575 writeU8(os, byte: WASM_OPCODE_END, msg: "END");
1576 }
1577
1578 createFunction(func: ctx.sym.callCtors, bodyContent);
1579}
1580
1581// Create a wrapper around a function export which calls the
1582// static constructors and destructors.
1583void Writer::createCommandExportWrapper(uint32_t functionIndex,
1584 DefinedFunction *f) {
1585 // First write the body's contents to a string.
1586 std::string bodyContent;
1587 {
1588 raw_string_ostream os(bodyContent);
1589 writeUleb128(os, number: 0, msg: "num locals");
1590
1591 // Call `__wasm_call_ctors` which call static constructors (and
1592 // applies any runtime relocations in Emscripten-style PIC mode)
1593 if (ctx.sym.callCtors->isLive()) {
1594 writeU8(os, byte: WASM_OPCODE_CALL, msg: "CALL");
1595 writeUleb128(os, number: ctx.sym.callCtors->getFunctionIndex(), msg: "function index");
1596 }
1597
1598 // Call the user's code, leaving any return values on the operand stack.
1599 for (size_t i = 0; i < f->signature->Params.size(); ++i) {
1600 writeU8(os, byte: WASM_OPCODE_LOCAL_GET, msg: "local.get");
1601 writeUleb128(os, number: i, msg: "local index");
1602 }
1603 writeU8(os, byte: WASM_OPCODE_CALL, msg: "CALL");
1604 writeUleb128(os, number: functionIndex, msg: "function index");
1605
1606 // Call the function that calls the destructors.
1607 if (DefinedFunction *callDtors = ctx.sym.callDtors) {
1608 writeU8(os, byte: WASM_OPCODE_CALL, msg: "CALL");
1609 writeUleb128(os, number: callDtors->getFunctionIndex(), msg: "function index");
1610 }
1611
1612 // End the function, returning the return values from the user's code.
1613 writeU8(os, byte: WASM_OPCODE_END, msg: "END");
1614 }
1615
1616 createFunction(func: f, bodyContent);
1617}
1618
1619void Writer::createInitTLSFunction() {
1620 std::string bodyContent;
1621 {
1622 raw_string_ostream os(bodyContent);
1623
1624 OutputSegment *tlsSeg = nullptr;
1625 for (auto *seg : segments) {
1626 if (seg->name == ".tdata") {
1627 tlsSeg = seg;
1628 break;
1629 }
1630 }
1631
1632 writeUleb128(os, number: 0, msg: "num locals");
1633 if (tlsSeg) {
1634 writeU8(os, byte: WASM_OPCODE_LOCAL_GET, msg: "local.get");
1635 writeUleb128(os, number: 0, msg: "local index");
1636
1637 writeU8(os, byte: WASM_OPCODE_GLOBAL_SET, msg: "global.set");
1638 writeUleb128(os, number: ctx.sym.tlsBase->getGlobalIndex(), msg: "global index");
1639
1640 // FIXME(wvo): this local needs to be I64 in wasm64, or we need an extend
1641 // op.
1642 writeU8(os, byte: WASM_OPCODE_LOCAL_GET, msg: "local.get");
1643 writeUleb128(os, number: 0, msg: "local index");
1644
1645 writeI32Const(os, number: 0, msg: "segment offset");
1646
1647 writeI32Const(os, number: tlsSeg->size, msg: "memory region size");
1648
1649 writeU8(os, byte: WASM_OPCODE_MISC_PREFIX, msg: "bulk-memory prefix");
1650 writeUleb128(os, number: WASM_OPCODE_MEMORY_INIT, msg: "MEMORY.INIT");
1651 writeUleb128(os, number: tlsSeg->index, msg: "segment index immediate");
1652 writeU8(os, byte: 0, msg: "memory index immediate");
1653 }
1654
1655 if (ctx.sym.applyTLSRelocs) {
1656 writeU8(os, byte: WASM_OPCODE_CALL, msg: "CALL");
1657 writeUleb128(os, number: ctx.sym.applyTLSRelocs->getFunctionIndex(),
1658 msg: "function index");
1659 }
1660
1661 if (ctx.sym.applyGlobalTLSRelocs) {
1662 writeU8(os, byte: WASM_OPCODE_CALL, msg: "CALL");
1663 writeUleb128(os, number: ctx.sym.applyGlobalTLSRelocs->getFunctionIndex(),
1664 msg: "function index");
1665 }
1666 writeU8(os, byte: WASM_OPCODE_END, msg: "end function");
1667 }
1668
1669 createFunction(func: ctx.sym.initTLS, bodyContent);
1670}
1671
1672// Populate InitFunctions vector with init functions from all input objects.
1673// This is then used either when creating the output linking section or to
1674// synthesize the "__wasm_call_ctors" function.
1675void Writer::calculateInitFunctions() {
1676 if (!ctx.arg.relocatable && !ctx.sym.callCtors->isLive())
1677 return;
1678
1679 for (ObjFile *file : ctx.objectFiles) {
1680 const WasmLinkingData &l = file->getWasmObj()->linkingData();
1681 for (const WasmInitFunc &f : l.InitFunctions) {
1682 FunctionSymbol *sym = file->getFunctionSymbol(index: f.Symbol);
1683 // comdat exclusions can cause init functions be discarded.
1684 if (sym->isDiscarded() || !sym->isLive())
1685 continue;
1686 if (sym->signature->Params.size() != 0)
1687 error(msg: "constructor functions cannot take arguments: " + toString(sym: *sym));
1688 LLVM_DEBUG(dbgs() << "initFunctions: " << toString(*sym) << "\n");
1689 initFunctions.emplace_back(args: WasmInitEntry{.sym: sym, .priority: f.Priority});
1690 }
1691 }
1692
1693 // Sort in order of priority (lowest first) so that they are called
1694 // in the correct order.
1695 llvm::stable_sort(Range&: initFunctions,
1696 C: [](const WasmInitEntry &l, const WasmInitEntry &r) {
1697 return l.priority < r.priority;
1698 });
1699}
1700
1701void Writer::createSyntheticSections() {
1702 out.dylinkSec = make<DylinkSection>();
1703 out.typeSec = make<TypeSection>();
1704 out.importSec = make<ImportSection>();
1705 out.functionSec = make<FunctionSection>();
1706 out.tableSec = make<TableSection>();
1707 out.memorySec = make<MemorySection>();
1708 out.tagSec = make<TagSection>();
1709 out.globalSec = make<GlobalSection>();
1710 out.exportSec = make<ExportSection>();
1711 out.startSec = make<StartSection>();
1712 out.elemSec = make<ElemSection>();
1713 out.producersSec = make<ProducersSection>();
1714 out.targetFeaturesSec = make<TargetFeaturesSection>();
1715 out.buildIdSec = make<BuildIdSection>();
1716}
1717
1718void Writer::createSyntheticSectionsPostLayout() {
1719 out.dataCountSec = make<DataCountSection>(args&: segments);
1720 out.linkingSec = make<LinkingSection>(args&: initFunctions, args&: segments);
1721 out.nameSec = make<NameSection>(args&: segments);
1722}
1723
1724void Writer::run() {
1725 // For PIC code the table base is assigned dynamically by the loader.
1726 // For non-PIC, we start at 1 so that accessing table index 0 always traps.
1727 if (!ctx.isPic && ctx.sym.tableBase)
1728 setGlobalPtr(g: cast<DefinedGlobal>(Val: ctx.sym.tableBase), memoryPtr: ctx.arg.tableBase);
1729
1730 log(msg: "-- createOutputSegments");
1731 createOutputSegments();
1732 log(msg: "-- createSyntheticSections");
1733 createSyntheticSections();
1734 log(msg: "-- layoutMemory");
1735 layoutMemory();
1736
1737 if (!ctx.arg.relocatable) {
1738 // Create linker synthesized __start_SECNAME/__stop_SECNAME symbols
1739 // This has to be done after memory layout is performed.
1740 for (const OutputSegment *seg : segments) {
1741 addStartStopSymbols(seg);
1742 }
1743 }
1744
1745 for (auto &pair : ctx.arg.exportedSymbols) {
1746 Symbol *sym = symtab->find(name: pair.first());
1747 if (sym && sym->isDefined())
1748 sym->forceExport = true;
1749 }
1750
1751 // Delay reporting errors about explicit exports until after
1752 // addStartStopSymbols which can create optional symbols.
1753 for (auto &name : ctx.arg.requiredExports) {
1754 Symbol *sym = symtab->find(name);
1755 if (!sym || !sym->isDefined()) {
1756 if (ctx.arg.unresolvedSymbols == UnresolvedPolicy::ReportError)
1757 error(msg: Twine("symbol exported via --export not found: ") + name);
1758 if (ctx.arg.unresolvedSymbols == UnresolvedPolicy::Warn)
1759 warn(msg: Twine("symbol exported via --export not found: ") + name);
1760 }
1761 }
1762
1763 log(msg: "-- populateTargetFeatures");
1764 populateTargetFeatures();
1765
1766 // When outputting PIC code each segment lives at at fixes offset from the
1767 // `__memory_base` import. Unless we support the extended const expression we
1768 // can't do addition inside the constant expression, so we much combine the
1769 // segments into a single one that can live at `__memory_base`.
1770 if (ctx.isPic && !ctx.arg.extendedConst && !ctx.arg.sharedMemory) {
1771 // In shared memory mode all data segments are passive and initialized
1772 // via __wasm_init_memory.
1773 log(msg: "-- combineOutputSegments");
1774 combineOutputSegments();
1775 }
1776
1777 log(msg: "-- createSyntheticSectionsPostLayout");
1778 createSyntheticSectionsPostLayout();
1779 log(msg: "-- populateProducers");
1780 populateProducers();
1781 log(msg: "-- calculateImports");
1782 calculateImports();
1783 log(msg: "-- scanRelocations");
1784 scanRelocations();
1785 log(msg: "-- finalizeIndirectFunctionTable");
1786 finalizeIndirectFunctionTable();
1787 log(msg: "-- createSyntheticInitFunctions");
1788 createSyntheticInitFunctions();
1789 log(msg: "-- assignIndexes");
1790 assignIndexes();
1791 log(msg: "-- calculateInitFunctions");
1792 calculateInitFunctions();
1793
1794 if (!ctx.arg.relocatable) {
1795 // Create linker synthesized functions
1796 if (ctx.sym.applyGlobalRelocs) {
1797 createApplyGlobalRelocationsFunction();
1798 }
1799 if (ctx.sym.applyTLSRelocs) {
1800 createApplyTLSRelocationsFunction();
1801 }
1802 if (ctx.sym.applyGlobalTLSRelocs) {
1803 createApplyGlobalTLSRelocationsFunction();
1804 }
1805 if (ctx.sym.initMemory) {
1806 createInitMemoryFunction();
1807 }
1808 createStartFunction();
1809
1810 createCallCtorsFunction();
1811
1812 // Create export wrappers for commands if needed.
1813 //
1814 // If the input contains a call to `__wasm_call_ctors`, either in one of
1815 // the input objects or an explicit export from the command-line, we
1816 // assume ctors and dtors are taken care of already.
1817 if (!ctx.arg.relocatable && !ctx.isPic &&
1818 !ctx.sym.callCtors->isUsedInRegularObj &&
1819 !ctx.sym.callCtors->isExported()) {
1820 log(msg: "-- createCommandExportWrappers");
1821 createCommandExportWrappers();
1822 }
1823 }
1824
1825 if (ctx.sym.initTLS && ctx.sym.initTLS->isLive()) {
1826 log(msg: "-- createInitTLSFunction");
1827 createInitTLSFunction();
1828 }
1829
1830 if (errorCount())
1831 return;
1832
1833 log(msg: "-- calculateTypes");
1834 calculateTypes();
1835 log(msg: "-- calculateExports");
1836 calculateExports();
1837 log(msg: "-- calculateCustomSections");
1838 calculateCustomSections();
1839 log(msg: "-- populateSymtab");
1840 populateSymtab();
1841 log(msg: "-- checkImportExportTargetFeatures");
1842 checkImportExportTargetFeatures();
1843 log(msg: "-- addSections");
1844 addSections();
1845
1846 if (errorHandler().verbose) {
1847 log(msg: "Defined Functions: " + Twine(out.functionSec->inputFunctions.size()));
1848 log(msg: "Defined Globals : " + Twine(out.globalSec->numGlobals()));
1849 log(msg: "Defined Tags : " + Twine(out.tagSec->inputTags.size()));
1850 log(msg: "Defined Tables : " + Twine(out.tableSec->inputTables.size()));
1851 log(msg: "Function Imports : " +
1852 Twine(out.importSec->getNumImportedFunctions()));
1853 log(msg: "Global Imports : " + Twine(out.importSec->getNumImportedGlobals()));
1854 log(msg: "Tag Imports : " + Twine(out.importSec->getNumImportedTags()));
1855 log(msg: "Table Imports : " + Twine(out.importSec->getNumImportedTables()));
1856 }
1857
1858 createHeader();
1859 log(msg: "-- finalizeSections");
1860 finalizeSections();
1861
1862 log(msg: "-- writeMapFile");
1863 writeMapFile(outputSections);
1864
1865 log(msg: "-- openFile");
1866 openFile();
1867 if (errorCount())
1868 return;
1869
1870 writeHeader();
1871
1872 log(msg: "-- writeSections");
1873 writeSections();
1874 writeBuildId();
1875 if (errorCount())
1876 return;
1877
1878 if (Error e = buffer->commit())
1879 fatal(msg: "failed to write output '" + buffer->getPath() +
1880 "': " + toString(E: std::move(e)));
1881}
1882
1883// Open a result file.
1884void Writer::openFile() {
1885 log(msg: "writing: " + ctx.arg.outputFile);
1886
1887 Expected<std::unique_ptr<FileOutputBuffer>> bufferOrErr =
1888 FileOutputBuffer::create(FilePath: ctx.arg.outputFile, Size: fileSize,
1889 Flags: FileOutputBuffer::F_executable);
1890
1891 if (!bufferOrErr)
1892 error(msg: "failed to open " + ctx.arg.outputFile + ": " +
1893 toString(E: bufferOrErr.takeError()));
1894 else
1895 buffer = std::move(*bufferOrErr);
1896}
1897
1898void Writer::createHeader() {
1899 raw_string_ostream os(header);
1900 writeBytes(os, bytes: WasmMagic, count: sizeof(WasmMagic), msg: "wasm magic");
1901 writeU32(os, number: WasmVersion, msg: "wasm version");
1902 fileSize += header.size();
1903}
1904
1905void writeResult() { Writer().run(); }
1906
1907} // namespace lld::wasm
1908