1 //===- Writer.cpp ---------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
11 #include "InputChunks.h"
12 #include "InputElement.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/DenseSet.h"
25 #include "llvm/ADT/MapVector.h"
26 #include "llvm/ADT/SmallSet.h"
27 #include "llvm/ADT/SmallVector.h"
28 #include "llvm/ADT/StringMap.h"
29 #include "llvm/BinaryFormat/Wasm.h"
30 #include "llvm/BinaryFormat/WasmTraits.h"
31 #include "llvm/Support/FileOutputBuffer.h"
32 #include "llvm/Support/Format.h"
33 #include "llvm/Support/FormatVariadic.h"
34 #include "llvm/Support/LEB128.h"
35 #include "llvm/Support/Parallel.h"
36 #include "llvm/Support/RandomNumberGenerator.h"
37 #include "llvm/Support/SHA1.h"
38 #include "llvm/Support/xxhash.h"
44 #define DEBUG_TYPE "lld"
47 using namespace llvm::wasm
;
50 static constexpr int stackAlignment
= 16;
51 static constexpr int heapAlignment
= 16;
55 // The writer writes a SymbolTable result to a file.
63 bool needsPassiveInitialization(const OutputSegment
*segment
);
64 bool hasPassiveInitializedSegments();
66 void createSyntheticInitFunctions();
67 void createInitMemoryFunction();
68 void createStartFunction();
69 void createApplyDataRelocationsFunction();
70 void createApplyGlobalRelocationsFunction();
71 void createApplyTLSRelocationsFunction();
72 void createApplyGlobalTLSRelocationsFunction();
73 void createCallCtorsFunction();
74 void createInitTLSFunction();
75 void createCommandExportWrappers();
76 void createCommandExportWrapper(uint32_t functionIndex
, DefinedFunction
*f
);
79 void populateSymtab();
80 void populateProducers();
81 void populateTargetFeatures();
82 // populateTargetFeatures happens early on so some checks are delayed
83 // until imports and exports are finalized. There are run unstead
84 // in checkImportExportTargetFeatures
85 void checkImportExportTargetFeatures();
86 void calculateInitFunctions();
87 void calculateImports();
88 void calculateExports();
89 void calculateCustomSections();
90 void calculateTypes();
91 void createOutputSegments();
92 OutputSegment
*createOutputSegment(StringRef name
);
93 void combineOutputSegments();
97 void addSection(OutputSection
*sec
);
101 void createCustomSections();
102 void createSyntheticSections();
103 void createSyntheticSectionsPostLayout();
104 void finalizeSections();
107 void createRelocSections();
110 void writeSections();
113 uint64_t fileSize
= 0;
115 std::vector
<WasmInitEntry
> initFunctions
;
116 llvm::MapVector
<StringRef
, std::vector
<InputChunk
*>> customSectionMapping
;
118 // Stable storage for command export wrapper function name strings.
119 std::list
<std::string
> commandExportWrapperNames
;
121 // Elements that are used to construct the final output
123 std::vector
<OutputSection
*> outputSections
;
125 std::unique_ptr
<FileOutputBuffer
> buffer
;
127 std::vector
<OutputSegment
*> segments
;
128 llvm::SmallDenseMap
<StringRef
, OutputSegment
*> segmentMap
;
131 } // anonymous namespace
133 void Writer::calculateCustomSections() {
134 log("calculateCustomSections");
135 bool stripDebug
= config
->stripDebug
|| config
->stripAll
;
136 for (ObjFile
*file
: symtab
->objectFiles
) {
137 for (InputChunk
*section
: file
->customSections
) {
138 // Exclude COMDAT sections that are not selected for inclusion
139 if (section
->discarded
)
141 StringRef name
= section
->name
;
142 // These custom sections are known the linker and synthesized rather than
144 if (name
== "linking" || name
== "name" || name
== "producers" ||
145 name
== "target_features" || name
.starts_with("reloc."))
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
151 if (name
== ".llvmbc" || name
== ".llvmcmd")
153 // Strip debug section in that option was specified.
154 if (stripDebug
&& name
.starts_with(".debug_"))
156 // Otherwise include custom sections by default and concatenate their
158 customSectionMapping
[name
].push_back(section
);
163 void Writer::createCustomSections() {
164 log("createCustomSections");
165 for (auto &pair
: customSectionMapping
) {
166 StringRef name
= pair
.first
;
167 LLVM_DEBUG(dbgs() << "createCustomSection: " << name
<< "\n");
169 OutputSection
*sec
= make
<CustomSection
>(std::string(name
), pair
.second
);
170 if (config
->relocatable
|| config
->emitRelocs
) {
171 auto *sym
= make
<OutputSectionSymbol
>(sec
);
172 out
.linkingSec
->addToSymtab(sym
);
173 sec
->sectionSym
= sym
;
179 // Create relocations sections in the final output.
180 // These are only created when relocatable output is requested.
181 void Writer::createRelocSections() {
182 log("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
];
189 // Count the number of needed sections.
190 uint32_t count
= sec
->getNumRelocations();
195 if (sec
->type
== WASM_SEC_DATA
)
197 else if (sec
->type
== WASM_SEC_CODE
)
199 else if (sec
->type
== WASM_SEC_CUSTOM
)
200 name
= saver().save("reloc." + sec
->name
);
203 "relocations only supported for code, data, or custom sections");
205 addSection(make
<RelocSection
>(name
, sec
));
209 void Writer::populateProducers() {
210 for (ObjFile
*file
: symtab
->objectFiles
) {
211 const WasmProducerInfo
&info
= file
->getWasmObj()->getProducerInfo();
212 out
.producersSec
->addInfo(info
);
216 void Writer::writeHeader() {
217 memcpy(buffer
->getBufferStart(), header
.data(), header
.size());
220 void Writer::writeSections() {
221 uint8_t *buf
= buffer
->getBufferStart();
222 parallelForEach(outputSections
, [buf
](OutputSection
*s
) {
223 assert(s
->isNeeded());
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.
234 computeHash(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(data
, 1024 * 1024);
238 std::vector
<uint8_t> hashes(chunks
.size() * hashBuf
.size());
240 // Compute hash values.
241 parallelFor(0, chunks
.size(), [&](size_t i
) {
242 hashFn(hashes
.data() + i
* hashBuf
.size(), chunks
[i
]);
245 // Write to the final output buffer.
246 hashFn(hashBuf
.data(), hashes
);
249 static 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");
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};
260 sha
.update(namespaceUUID
);
261 sha
.update(fileHash
);
262 auto s
= sha
.final();
263 std::copy(s
.data(), &s
.data()[output
.size()], output
.data());
264 } else if (version
== 4) {
265 if (auto ec
= llvm::getRandomBytes(output
.data(), output
.size()))
266 error("entropy source failure: " + ec
.message());
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);
272 // The variant is DCE 1.1/ISO 11578 (0b10xxxxxx)
277 void Writer::writeBuildId() {
278 if (!out
.buildIdSec
->isNeeded())
280 if (config
->buildId
== BuildIdKind::Hexstring
) {
281 out
.buildIdSec
->writeBuildId(config
->buildIdVector
);
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
)};
290 switch (config
->buildId
) {
291 case BuildIdKind::Fast
: {
292 std::vector
<uint8_t> fileHash(8);
293 computeHash(fileHash
, buf
, [](uint8_t *dest
, ArrayRef
<uint8_t> arr
) {
294 support::endian::write64le(dest
, xxh3_64bits(arr
));
296 makeUUID(5, fileHash
, buildId
);
299 case BuildIdKind::Sha1
:
300 computeHash(buildId
, buf
, [&](uint8_t *dest
, ArrayRef
<uint8_t> arr
) {
301 memcpy(dest
, SHA1::hash(arr
).data(), hashSize
);
304 case BuildIdKind::Uuid
:
305 makeUUID(4, {}, buildId
);
308 llvm_unreachable("unknown BuildIdKind");
310 out
.buildIdSec
->writeBuildId(buildId
);
313 static void setGlobalPtr(DefinedGlobal
*g
, uint64_t memoryPtr
) {
314 LLVM_DEBUG(dbgs() << "setGlobalPtr " << g
->getName() << " -> " << memoryPtr
<< "\n");
315 g
->global
->setPointerValue(memoryPtr
);
318 // Fix the memory layout of the output binary. This assigns memory offsets
319 // to each of the input data sections as well as the explicit stack region.
320 // The default memory layout is as follows, from low to high.
322 // - initialized data (starting at config->globalBase)
323 // - BSS data (not currently implemented in llvm)
324 // - explicit stack (config->ZStackSize)
325 // - heap start / unallocated
327 // The --stack-first option means that stack is placed before any static data.
328 // This can be useful since it means that stack overflow traps immediately
329 // rather than overwriting global data, but also increases code size since all
330 // static data loads and stores requires larger offsets.
331 void Writer::layoutMemory() {
332 uint64_t memoryPtr
= 0;
334 auto placeStack
= [&]() {
335 if (config
->relocatable
|| config
->isPic
)
337 memoryPtr
= alignTo(memoryPtr
, stackAlignment
);
338 if (WasmSym::stackLow
)
339 WasmSym::stackLow
->setVA(memoryPtr
);
340 if (config
->zStackSize
!= alignTo(config
->zStackSize
, stackAlignment
))
341 error("stack size must be " + Twine(stackAlignment
) + "-byte aligned");
342 log("mem: stack size = " + Twine(config
->zStackSize
));
343 log("mem: stack base = " + Twine(memoryPtr
));
344 memoryPtr
+= config
->zStackSize
;
345 setGlobalPtr(cast
<DefinedGlobal
>(WasmSym::stackPointer
), memoryPtr
);
346 if (WasmSym::stackHigh
)
347 WasmSym::stackHigh
->setVA(memoryPtr
);
348 log("mem: stack top = " + Twine(memoryPtr
));
351 if (config
->stackFirst
) {
353 if (config
->globalBase
) {
354 if (config
->globalBase
< memoryPtr
) {
355 error("--global-base cannot be less than stack size when --stack-first is used");
358 memoryPtr
= config
->globalBase
;
361 memoryPtr
= config
->globalBase
;
364 log("mem: global base = " + Twine(memoryPtr
));
365 if (WasmSym::globalBase
)
366 WasmSym::globalBase
->setVA(memoryPtr
);
368 uint64_t dataStart
= memoryPtr
;
370 // Arbitrarily set __dso_handle handle to point to the start of the data
372 if (WasmSym::dsoHandle
)
373 WasmSym::dsoHandle
->setVA(dataStart
);
375 out
.dylinkSec
->memAlign
= 0;
376 for (OutputSegment
*seg
: segments
) {
377 out
.dylinkSec
->memAlign
= std::max(out
.dylinkSec
->memAlign
, seg
->alignment
);
378 memoryPtr
= alignTo(memoryPtr
, 1ULL << seg
->alignment
);
379 seg
->startVA
= memoryPtr
;
380 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", seg
->name
,
381 memoryPtr
, seg
->size
, seg
->alignment
));
383 if (!config
->relocatable
&& seg
->isTLS()) {
384 if (WasmSym::tlsSize
) {
385 auto *tlsSize
= cast
<DefinedGlobal
>(WasmSym::tlsSize
);
386 setGlobalPtr(tlsSize
, seg
->size
);
388 if (WasmSym::tlsAlign
) {
389 auto *tlsAlign
= cast
<DefinedGlobal
>(WasmSym::tlsAlign
);
390 setGlobalPtr(tlsAlign
, int64_t{1} << seg
->alignment
);
392 if (!config
->sharedMemory
&& WasmSym::tlsBase
) {
393 auto *tlsBase
= cast
<DefinedGlobal
>(WasmSym::tlsBase
);
394 setGlobalPtr(tlsBase
, memoryPtr
);
398 memoryPtr
+= seg
->size
;
401 // Make space for the memory initialization flag
402 if (config
->sharedMemory
&& hasPassiveInitializedSegments()) {
403 memoryPtr
= alignTo(memoryPtr
, 4);
404 WasmSym::initMemoryFlag
= symtab
->addSyntheticDataSymbol(
405 "__wasm_init_memory_flag", WASM_SYMBOL_VISIBILITY_HIDDEN
);
406 WasmSym::initMemoryFlag
->markLive();
407 WasmSym::initMemoryFlag
->setVA(memoryPtr
);
408 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}",
409 "__wasm_init_memory_flag", memoryPtr
, 4, 4));
413 if (WasmSym::dataEnd
)
414 WasmSym::dataEnd
->setVA(memoryPtr
);
416 uint64_t staticDataSize
= memoryPtr
- dataStart
;
417 log("mem: static data = " + Twine(staticDataSize
));
419 out
.dylinkSec
->memSize
= staticDataSize
;
421 if (!config
->stackFirst
)
424 if (WasmSym::heapBase
) {
425 // Set `__heap_base` to follow the end of the stack or global data. The
426 // fact that this comes last means that a malloc/brk implementation can
427 // grow the heap at runtime.
428 // We'll align the heap base here because memory allocators might expect
429 // __heap_base to be aligned already.
430 memoryPtr
= alignTo(memoryPtr
, heapAlignment
);
431 log("mem: heap base = " + Twine(memoryPtr
));
432 WasmSym::heapBase
->setVA(memoryPtr
);
435 uint64_t maxMemorySetting
= 1ULL << 32;
436 if (config
->is64
.value_or(false)) {
437 // TODO: Update once we decide on a reasonable limit here:
438 // https://github.com/WebAssembly/memory64/issues/33
439 maxMemorySetting
= 1ULL << 34;
442 if (config
->initialMemory
!= 0) {
443 if (config
->initialMemory
!= alignTo(config
->initialMemory
, WasmPageSize
))
444 error("initial memory must be " + Twine(WasmPageSize
) + "-byte aligned");
445 if (memoryPtr
> config
->initialMemory
)
446 error("initial memory too small, " + Twine(memoryPtr
) + " bytes needed");
447 if (config
->initialMemory
> maxMemorySetting
)
448 error("initial memory too large, cannot be greater than " +
449 Twine(maxMemorySetting
));
450 memoryPtr
= config
->initialMemory
;
453 memoryPtr
= alignTo(memoryPtr
, WasmPageSize
);
455 out
.memorySec
->numMemoryPages
= memoryPtr
/ WasmPageSize
;
456 log("mem: total pages = " + Twine(out
.memorySec
->numMemoryPages
));
458 if (WasmSym::heapEnd
) {
459 // Set `__heap_end` to follow the end of the statically allocated linear
460 // memory. The fact that this comes last means that a malloc/brk
461 // implementation can grow the heap at runtime.
462 log("mem: heap end = " + Twine(memoryPtr
));
463 WasmSym::heapEnd
->setVA(memoryPtr
);
466 if (config
->maxMemory
!= 0) {
467 if (config
->maxMemory
!= alignTo(config
->maxMemory
, WasmPageSize
))
468 error("maximum memory must be " + Twine(WasmPageSize
) + "-byte aligned");
469 if (memoryPtr
> config
->maxMemory
)
470 error("maximum memory too small, " + Twine(memoryPtr
) + " bytes needed");
471 if (config
->maxMemory
> maxMemorySetting
)
472 error("maximum memory too large, cannot be greater than " +
473 Twine(maxMemorySetting
));
476 // Check max if explicitly supplied or required by shared memory
477 if (config
->maxMemory
!= 0 || config
->sharedMemory
) {
478 uint64_t max
= config
->maxMemory
;
480 // If no maxMemory config was supplied but we are building with
481 // shared memory, we need to pick a sensible upper limit.
483 max
= maxMemorySetting
;
487 out
.memorySec
->maxMemoryPages
= max
/ WasmPageSize
;
488 log("mem: max pages = " + Twine(out
.memorySec
->maxMemoryPages
));
492 void Writer::addSection(OutputSection
*sec
) {
493 if (!sec
->isNeeded())
495 log("addSection: " + toString(*sec
));
496 sec
->sectionIndex
= outputSections
.size();
497 outputSections
.push_back(sec
);
500 // If a section name is valid as a C identifier (which is rare because of
501 // the leading '.'), linkers are expected to define __start_<secname> and
502 // __stop_<secname> symbols. They are at beginning and end of the section,
503 // respectively. This is not requested by the ELF standard, but GNU ld and
504 // gold provide the feature, and used by many programs.
505 static void addStartStopSymbols(const OutputSegment
*seg
) {
506 StringRef name
= seg
->name
;
507 if (!isValidCIdentifier(name
))
509 LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << name
<< "\n");
510 uint64_t start
= seg
->startVA
;
511 uint64_t stop
= start
+ seg
->size
;
512 symtab
->addOptionalDataSymbol(saver().save("__start_" + name
), start
);
513 symtab
->addOptionalDataSymbol(saver().save("__stop_" + name
), stop
);
516 void Writer::addSections() {
517 addSection(out
.dylinkSec
);
518 addSection(out
.typeSec
);
519 addSection(out
.importSec
);
520 addSection(out
.functionSec
);
521 addSection(out
.tableSec
);
522 addSection(out
.memorySec
);
523 addSection(out
.tagSec
);
524 addSection(out
.globalSec
);
525 addSection(out
.exportSec
);
526 addSection(out
.startSec
);
527 addSection(out
.elemSec
);
528 addSection(out
.dataCountSec
);
530 addSection(make
<CodeSection
>(out
.functionSec
->inputFunctions
));
531 addSection(make
<DataSection
>(segments
));
533 createCustomSections();
535 addSection(out
.linkingSec
);
536 if (config
->emitRelocs
|| config
->relocatable
) {
537 createRelocSections();
540 addSection(out
.nameSec
);
541 addSection(out
.producersSec
);
542 addSection(out
.targetFeaturesSec
);
543 addSection(out
.buildIdSec
);
546 void Writer::finalizeSections() {
547 for (OutputSection
*s
: outputSections
) {
548 s
->setOffset(fileSize
);
549 s
->finalizeContents();
550 fileSize
+= s
->getSize();
554 void Writer::populateTargetFeatures() {
555 StringMap
<std::string
> used
;
556 StringMap
<std::string
> required
;
557 StringMap
<std::string
> disallowed
;
558 SmallSet
<std::string
, 8> &allowed
= out
.targetFeaturesSec
->features
;
559 bool tlsUsed
= false;
562 // This should not be necessary because all PIC objects should
563 // contain the mutable-globals feature.
564 // TODO (https://github.com/llvm/llvm-project/issues/51681)
565 allowed
.insert("mutable-globals");
568 if (config
->extraFeatures
.has_value()) {
569 auto &extraFeatures
= *config
->extraFeatures
;
570 allowed
.insert(extraFeatures
.begin(), extraFeatures
.end());
573 // Only infer used features if user did not specify features
574 bool inferFeatures
= !config
->features
.has_value();
576 if (!inferFeatures
) {
577 auto &explicitFeatures
= *config
->features
;
578 allowed
.insert(explicitFeatures
.begin(), explicitFeatures
.end());
579 if (!config
->checkFeatures
)
583 // Find the sets of used, required, and disallowed features
584 for (ObjFile
*file
: symtab
->objectFiles
) {
585 StringRef
fileName(file
->getName());
586 for (auto &feature
: file
->getWasmObj()->getTargetFeatures()) {
587 switch (feature
.Prefix
) {
588 case WASM_FEATURE_PREFIX_USED
:
589 used
.insert({feature
.Name
, std::string(fileName
)});
591 case WASM_FEATURE_PREFIX_REQUIRED
:
592 used
.insert({feature
.Name
, std::string(fileName
)});
593 required
.insert({feature
.Name
, std::string(fileName
)});
595 case WASM_FEATURE_PREFIX_DISALLOWED
:
596 disallowed
.insert({feature
.Name
, std::string(fileName
)});
599 error("Unrecognized feature policy prefix " +
600 std::to_string(feature
.Prefix
));
604 // Find TLS data segments
605 auto isTLS
= [](InputChunk
*segment
) {
606 return segment
->live
&& segment
->isTLS();
608 tlsUsed
= tlsUsed
|| llvm::any_of(file
->segments
, isTLS
);
612 for (const auto &key
: used
.keys())
613 allowed
.insert(std::string(key
));
615 if (!config
->checkFeatures
)
618 if (config
->sharedMemory
) {
619 if (disallowed
.count("shared-mem"))
620 error("--shared-memory is disallowed by " + disallowed
["shared-mem"] +
621 " because it was not compiled with 'atomics' or 'bulk-memory' "
624 for (auto feature
: {"atomics", "bulk-memory"})
625 if (!allowed
.count(feature
))
626 error(StringRef("'") + feature
+
627 "' feature must be used in order to use shared memory");
631 for (auto feature
: {"atomics", "bulk-memory"})
632 if (!allowed
.count(feature
))
633 error(StringRef("'") + feature
+
634 "' feature must be used in order to use thread-local storage");
637 // Validate that used features are allowed in output
638 if (!inferFeatures
) {
639 for (const auto &feature
: used
.keys()) {
640 if (!allowed
.count(std::string(feature
)))
641 error(Twine("Target feature '") + feature
+ "' used by " +
642 used
[feature
] + " is not allowed.");
646 // Validate the required and disallowed constraints for each file
647 for (ObjFile
*file
: symtab
->objectFiles
) {
648 StringRef
fileName(file
->getName());
649 SmallSet
<std::string
, 8> objectFeatures
;
650 for (const auto &feature
: file
->getWasmObj()->getTargetFeatures()) {
651 if (feature
.Prefix
== WASM_FEATURE_PREFIX_DISALLOWED
)
653 objectFeatures
.insert(feature
.Name
);
654 if (disallowed
.count(feature
.Name
))
655 error(Twine("Target feature '") + feature
.Name
+ "' used in " +
656 fileName
+ " is disallowed by " + disallowed
[feature
.Name
] +
657 ". Use --no-check-features to suppress.");
659 for (const auto &feature
: required
.keys()) {
660 if (!objectFeatures
.count(std::string(feature
)))
661 error(Twine("Missing target feature '") + feature
+ "' in " + fileName
+
662 ", required by " + required
[feature
] +
663 ". Use --no-check-features to suppress.");
668 // Normally we don't include bss segments in the binary. In particular if
669 // memory is not being imported then we can assume its zero initialized.
670 // In the case the memory is imported, and we can use the memory.fill
671 // instruction, then we can also avoid including the segments.
672 // Finally, if we are emitting relocations, they may refer to locations within
673 // the bss segments, so these segments need to exist in the binary.
674 if (config
->emitRelocs
||
675 (config
->memoryImport
.has_value() && !allowed
.count("bulk-memory")))
676 config
->emitBssSegments
= true;
678 if (allowed
.count("extended-const"))
679 config
->extendedConst
= true;
681 for (auto &feature
: allowed
)
682 log("Allowed feature: " + feature
);
685 void Writer::checkImportExportTargetFeatures() {
686 if (config
->relocatable
|| !config
->checkFeatures
)
689 if (out
.targetFeaturesSec
->features
.count("mutable-globals") == 0) {
690 for (const Symbol
*sym
: out
.importSec
->importedSymbols
) {
691 if (auto *global
= dyn_cast
<GlobalSymbol
>(sym
)) {
692 if (global
->getGlobalType()->Mutable
) {
693 error(Twine("mutable global imported but 'mutable-globals' feature "
694 "not present in inputs: `") +
695 toString(*sym
) + "`. Use --no-check-features to suppress.");
699 for (const Symbol
*sym
: out
.exportSec
->exportedSymbols
) {
700 if (isa
<GlobalSymbol
>(sym
)) {
701 error(Twine("mutable global exported but 'mutable-globals' feature "
702 "not present in inputs: `") +
703 toString(*sym
) + "`. Use --no-check-features to suppress.");
709 static bool shouldImport(Symbol
*sym
) {
710 // We don't generate imports for data symbols. They however can be imported
712 if (isa
<DataSymbol
>(sym
))
716 if (!sym
->isUsedInRegularObj
)
719 // When a symbol is weakly defined in a shared library we need to allow
720 // it to be overridden by another module so need to both import
721 // and export the symbol.
722 if (config
->shared
&& sym
->isWeak() && !sym
->isUndefined() &&
725 if (!sym
->isUndefined())
727 if (sym
->isWeak() && !config
->relocatable
&& !config
->isPic
)
730 // In PIC mode we only need to import functions when they are called directly.
731 // Indirect usage all goes via GOT imports.
733 if (auto *f
= dyn_cast
<UndefinedFunction
>(sym
))
734 if (!f
->isCalledDirectly
)
738 if (config
->isPic
|| config
->relocatable
|| config
->importUndefined
||
739 config
->unresolvedSymbols
== UnresolvedPolicy::ImportDynamic
)
741 if (config
->allowUndefinedSymbols
.count(sym
->getName()) != 0)
744 return sym
->isImported();
747 void Writer::calculateImports() {
748 // Some inputs require that the indirect function table be assigned to table
749 // number 0, so if it is present and is an import, allocate it before any
751 if (WasmSym::indirectFunctionTable
&&
752 shouldImport(WasmSym::indirectFunctionTable
))
753 out
.importSec
->addImport(WasmSym::indirectFunctionTable
);
755 for (Symbol
*sym
: symtab
->symbols()) {
756 if (!shouldImport(sym
))
758 if (sym
== WasmSym::indirectFunctionTable
)
760 LLVM_DEBUG(dbgs() << "import: " << sym
->getName() << "\n");
761 out
.importSec
->addImport(sym
);
765 void Writer::calculateExports() {
766 if (config
->relocatable
)
769 if (!config
->relocatable
&& config
->memoryExport
.has_value()) {
770 out
.exportSec
->exports
.push_back(
771 WasmExport
{*config
->memoryExport
, WASM_EXTERNAL_MEMORY
, 0});
774 unsigned globalIndex
=
775 out
.importSec
->getNumImportedGlobals() + out
.globalSec
->numGlobals();
777 for (Symbol
*sym
: symtab
->symbols()) {
778 if (!sym
->isExported())
783 StringRef name
= sym
->getName();
785 if (auto *f
= dyn_cast
<DefinedFunction
>(sym
)) {
786 if (std::optional
<StringRef
> exportName
= f
->function
->getExportName()) {
789 export_
= {name
, WASM_EXTERNAL_FUNCTION
, f
->getExportedFunctionIndex()};
790 } else if (auto *g
= dyn_cast
<DefinedGlobal
>(sym
)) {
791 if (g
->getGlobalType()->Mutable
&& !g
->getFile() && !g
->forceExport
) {
792 // Avoid exporting mutable globals are linker synthesized (e.g.
793 // __stack_pointer or __tls_base) unless they are explicitly exported
794 // from the command line.
795 // Without this check `--export-all` would cause any program using the
796 // stack pointer to export a mutable global even if none of the input
797 // files were built with the `mutable-globals` feature.
800 export_
= {name
, WASM_EXTERNAL_GLOBAL
, g
->getGlobalIndex()};
801 } else if (auto *t
= dyn_cast
<DefinedTag
>(sym
)) {
802 export_
= {name
, WASM_EXTERNAL_TAG
, t
->getTagIndex()};
803 } else if (auto *d
= dyn_cast
<DefinedData
>(sym
)) {
804 out
.globalSec
->dataAddressGlobals
.push_back(d
);
805 export_
= {name
, WASM_EXTERNAL_GLOBAL
, globalIndex
++};
807 auto *t
= cast
<DefinedTable
>(sym
);
808 export_
= {name
, WASM_EXTERNAL_TABLE
, t
->getTableNumber()};
811 LLVM_DEBUG(dbgs() << "Export: " << name
<< "\n");
812 out
.exportSec
->exports
.push_back(export_
);
813 out
.exportSec
->exportedSymbols
.push_back(sym
);
817 void Writer::populateSymtab() {
818 if (!config
->relocatable
&& !config
->emitRelocs
)
821 for (Symbol
*sym
: symtab
->symbols())
822 if (sym
->isUsedInRegularObj
&& sym
->isLive())
823 out
.linkingSec
->addToSymtab(sym
);
825 for (ObjFile
*file
: symtab
->objectFiles
) {
826 LLVM_DEBUG(dbgs() << "Local symtab entries: " << file
->getName() << "\n");
827 for (Symbol
*sym
: file
->getSymbols())
828 if (sym
->isLocal() && !isa
<SectionSymbol
>(sym
) && sym
->isLive())
829 out
.linkingSec
->addToSymtab(sym
);
833 void Writer::calculateTypes() {
834 // The output type section is the union of the following sets:
835 // 1. Any signature used in the TYPE relocation
836 // 2. The signatures of all imported functions
837 // 3. The signatures of all defined functions
838 // 4. The signatures of all imported tags
839 // 5. The signatures of all defined tags
841 for (ObjFile
*file
: symtab
->objectFiles
) {
842 ArrayRef
<WasmSignature
> types
= file
->getWasmObj()->types();
843 for (uint32_t i
= 0; i
< types
.size(); i
++)
844 if (file
->typeIsUsed
[i
])
845 file
->typeMap
[i
] = out
.typeSec
->registerType(types
[i
]);
848 for (const Symbol
*sym
: out
.importSec
->importedSymbols
) {
849 if (auto *f
= dyn_cast
<FunctionSymbol
>(sym
))
850 out
.typeSec
->registerType(*f
->signature
);
851 else if (auto *t
= dyn_cast
<TagSymbol
>(sym
))
852 out
.typeSec
->registerType(*t
->signature
);
855 for (const InputFunction
*f
: out
.functionSec
->inputFunctions
)
856 out
.typeSec
->registerType(f
->signature
);
858 for (const InputTag
*t
: out
.tagSec
->inputTags
)
859 out
.typeSec
->registerType(t
->signature
);
862 // In a command-style link, create a wrapper for each exported symbol
863 // which calls the constructors and destructors.
864 void Writer::createCommandExportWrappers() {
865 // This logic doesn't currently support Emscripten-style PIC mode.
866 assert(!config
->isPic
);
868 // If there are no ctors and there's no libc `__wasm_call_dtors` to
869 // call, don't wrap the exports.
870 if (initFunctions
.empty() && WasmSym::callDtors
== nullptr)
873 std::vector
<DefinedFunction
*> toWrap
;
875 for (Symbol
*sym
: symtab
->symbols())
876 if (sym
->isExported())
877 if (auto *f
= dyn_cast
<DefinedFunction
>(sym
))
880 for (auto *f
: toWrap
) {
881 auto funcNameStr
= (f
->getName() + ".command_export").str();
882 commandExportWrapperNames
.push_back(funcNameStr
);
883 const std::string
&funcName
= commandExportWrapperNames
.back();
885 auto func
= make
<SyntheticFunction
>(*f
->getSignature(), funcName
);
886 if (f
->function
->getExportName())
887 func
->setExportName(f
->function
->getExportName()->str());
889 func
->setExportName(f
->getName().str());
891 DefinedFunction
*def
=
892 symtab
->addSyntheticFunction(funcName
, f
->flags
, func
);
895 def
->flags
|= WASM_SYMBOL_EXPORTED
;
896 def
->flags
&= ~WASM_SYMBOL_VISIBILITY_HIDDEN
;
897 def
->forceExport
= f
->forceExport
;
899 f
->flags
|= WASM_SYMBOL_VISIBILITY_HIDDEN
;
900 f
->flags
&= ~WASM_SYMBOL_EXPORTED
;
901 f
->forceExport
= false;
903 out
.functionSec
->addFunction(func
);
905 createCommandExportWrapper(f
->getFunctionIndex(), def
);
909 static void finalizeIndirectFunctionTable() {
910 if (!WasmSym::indirectFunctionTable
)
913 if (shouldImport(WasmSym::indirectFunctionTable
) &&
914 !WasmSym::indirectFunctionTable
->hasTableNumber()) {
915 // Processing -Bsymbolic relocations resulted in a late requirement that the
916 // indirect function table be present, and we are running in --import-table
917 // mode. Add the table now to the imports section. Otherwise it will be
918 // added to the tables section later in assignIndexes.
919 out
.importSec
->addImport(WasmSym::indirectFunctionTable
);
922 uint32_t tableSize
= config
->tableBase
+ out
.elemSec
->numEntries();
923 WasmLimits limits
= {0, tableSize
, 0};
924 if (WasmSym::indirectFunctionTable
->isDefined() && !config
->growableTable
) {
925 limits
.Flags
|= WASM_LIMITS_FLAG_HAS_MAX
;
926 limits
.Maximum
= limits
.Minimum
;
928 WasmSym::indirectFunctionTable
->setLimits(limits
);
931 static void scanRelocations() {
932 for (ObjFile
*file
: symtab
->objectFiles
) {
933 LLVM_DEBUG(dbgs() << "scanRelocations: " << file
->getName() << "\n");
934 for (InputChunk
*chunk
: file
->functions
)
935 scanRelocations(chunk
);
936 for (InputChunk
*chunk
: file
->segments
)
937 scanRelocations(chunk
);
938 for (auto &p
: file
->customSections
)
943 void Writer::assignIndexes() {
944 // Seal the import section, since other index spaces such as function and
945 // global are effected by the number of imports.
946 out
.importSec
->seal();
948 for (InputFunction
*func
: symtab
->syntheticFunctions
)
949 out
.functionSec
->addFunction(func
);
951 for (ObjFile
*file
: symtab
->objectFiles
) {
952 LLVM_DEBUG(dbgs() << "Functions: " << file
->getName() << "\n");
953 for (InputFunction
*func
: file
->functions
)
954 out
.functionSec
->addFunction(func
);
957 for (InputGlobal
*global
: symtab
->syntheticGlobals
)
958 out
.globalSec
->addGlobal(global
);
960 for (ObjFile
*file
: symtab
->objectFiles
) {
961 LLVM_DEBUG(dbgs() << "Globals: " << file
->getName() << "\n");
962 for (InputGlobal
*global
: file
->globals
)
963 out
.globalSec
->addGlobal(global
);
966 for (ObjFile
*file
: symtab
->objectFiles
) {
967 LLVM_DEBUG(dbgs() << "Tags: " << file
->getName() << "\n");
968 for (InputTag
*tag
: file
->tags
)
969 out
.tagSec
->addTag(tag
);
972 for (ObjFile
*file
: symtab
->objectFiles
) {
973 LLVM_DEBUG(dbgs() << "Tables: " << file
->getName() << "\n");
974 for (InputTable
*table
: file
->tables
)
975 out
.tableSec
->addTable(table
);
978 for (InputTable
*table
: symtab
->syntheticTables
)
979 out
.tableSec
->addTable(table
);
981 out
.globalSec
->assignIndexes();
982 out
.tableSec
->assignIndexes();
985 static StringRef
getOutputDataSegmentName(const InputChunk
&seg
) {
986 // We always merge .tbss and .tdata into a single TLS segment so all TLS
987 // symbols are be relative to single __tls_base.
990 if (!config
->mergeDataSegments
)
992 if (seg
.name
.starts_with(".text."))
994 if (seg
.name
.starts_with(".data."))
996 if (seg
.name
.starts_with(".bss."))
998 if (seg
.name
.starts_with(".rodata."))
1003 OutputSegment
*Writer::createOutputSegment(StringRef name
) {
1004 LLVM_DEBUG(dbgs() << "new segment: " << name
<< "\n");
1005 OutputSegment
*s
= make
<OutputSegment
>(name
);
1006 if (config
->sharedMemory
)
1007 s
->initFlags
= WASM_DATA_SEGMENT_IS_PASSIVE
;
1008 if (!config
->relocatable
&& name
.starts_with(".bss"))
1010 segments
.push_back(s
);
1014 void Writer::createOutputSegments() {
1015 for (ObjFile
*file
: symtab
->objectFiles
) {
1016 for (InputChunk
*segment
: file
->segments
) {
1019 StringRef name
= getOutputDataSegmentName(*segment
);
1020 OutputSegment
*s
= nullptr;
1021 // When running in relocatable mode we can't merge segments that are part
1022 // of comdat groups since the ultimate linker needs to be able exclude or
1023 // include them individually.
1024 if (config
->relocatable
&& !segment
->getComdatName().empty()) {
1025 s
= createOutputSegment(name
);
1027 if (segmentMap
.count(name
) == 0)
1028 segmentMap
[name
] = createOutputSegment(name
);
1029 s
= segmentMap
[name
];
1031 s
->addInputSegment(segment
);
1035 // Sort segments by type, placing .bss last
1036 std::stable_sort(segments
.begin(), segments
.end(),
1037 [](const OutputSegment
*a
, const OutputSegment
*b
) {
1038 auto order
= [](StringRef name
) {
1039 return StringSwitch
<int>(name
)
1040 .StartsWith(".tdata", 0)
1041 .StartsWith(".rodata", 1)
1042 .StartsWith(".data", 2)
1043 .StartsWith(".bss", 4)
1046 return order(a
->name
) < order(b
->name
);
1049 for (size_t i
= 0; i
< segments
.size(); ++i
)
1050 segments
[i
]->index
= i
;
1052 // Merge MergeInputSections into a single MergeSyntheticSection.
1053 LLVM_DEBUG(dbgs() << "-- finalize input semgments\n");
1054 for (OutputSegment
*seg
: segments
)
1055 seg
->finalizeInputSegments();
1058 void Writer::combineOutputSegments() {
1059 // With PIC code we currently only support a single active data segment since
1060 // we only have a single __memory_base to use as our base address. This pass
1061 // combines all data segments into a single .data segment.
1062 // This restriction does not apply when the extended const extension is
1063 // available: https://github.com/WebAssembly/extended-const
1064 assert(!config
->extendedConst
);
1065 assert(config
->isPic
&& !config
->sharedMemory
);
1066 if (segments
.size() <= 1)
1068 OutputSegment
*combined
= make
<OutputSegment
>(".data");
1069 combined
->startVA
= segments
[0]->startVA
;
1070 for (OutputSegment
*s
: segments
) {
1072 for (InputChunk
*inSeg
: s
->inputSegments
) {
1074 inSeg
->alignment
= std::max(inSeg
->alignment
, s
->alignment
);
1077 uint64_t oldVA
= inSeg
->getVA();
1079 combined
->addInputSegment(inSeg
);
1081 uint64_t newVA
= inSeg
->getVA();
1082 LLVM_DEBUG(dbgs() << "added input segment. name=" << inSeg
->name
1083 << " oldVA=" << oldVA
<< " newVA=" << newVA
<< "\n");
1084 assert(oldVA
== newVA
);
1089 segments
= {combined
};
1092 static void createFunction(DefinedFunction
*func
, StringRef bodyContent
) {
1093 std::string functionBody
;
1095 raw_string_ostream
os(functionBody
);
1096 writeUleb128(os
, bodyContent
.size(), "function size");
1099 ArrayRef
<uint8_t> body
= arrayRefFromStringRef(saver().save(functionBody
));
1100 cast
<SyntheticFunction
>(func
->function
)->setBody(body
);
1103 bool Writer::needsPassiveInitialization(const OutputSegment
*segment
) {
1104 // If bulk memory features is supported then we can perform bss initialization
1105 // (via memory.fill) during `__wasm_init_memory`.
1106 if (config
->memoryImport
.has_value() && !segment
->requiredInBinary())
1108 return segment
->initFlags
& WASM_DATA_SEGMENT_IS_PASSIVE
;
1111 bool Writer::hasPassiveInitializedSegments() {
1112 return llvm::any_of(segments
, [this](const OutputSegment
*s
) {
1113 return this->needsPassiveInitialization(s
);
1117 void Writer::createSyntheticInitFunctions() {
1118 if (config
->relocatable
)
1121 static WasmSignature nullSignature
= {{}, {}};
1123 // Passive segments are used to avoid memory being reinitialized on each
1124 // thread's instantiation. These passive segments are initialized and
1125 // dropped in __wasm_init_memory, which is registered as the start function
1126 // We also initialize bss segments (using memory.fill) as part of this
1128 if (hasPassiveInitializedSegments()) {
1129 WasmSym::initMemory
= symtab
->addSyntheticFunction(
1130 "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN
,
1131 make
<SyntheticFunction
>(nullSignature
, "__wasm_init_memory"));
1132 WasmSym::initMemory
->markLive();
1133 if (config
->sharedMemory
) {
1134 // This global is assigned during __wasm_init_memory in the shared memory
1136 WasmSym::tlsBase
->markLive();
1140 if (config
->sharedMemory
) {
1141 if (out
.globalSec
->needsTLSRelocations()) {
1142 WasmSym::applyGlobalTLSRelocs
= symtab
->addSyntheticFunction(
1143 "__wasm_apply_global_tls_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN
,
1144 make
<SyntheticFunction
>(nullSignature
,
1145 "__wasm_apply_global_tls_relocs"));
1146 WasmSym::applyGlobalTLSRelocs
->markLive();
1147 // TLS relocations depend on the __tls_base symbols
1148 WasmSym::tlsBase
->markLive();
1151 auto hasTLSRelocs
= [](const OutputSegment
*segment
) {
1152 if (segment
->isTLS())
1153 for (const auto* is
: segment
->inputSegments
)
1154 if (is
->getRelocations().size())
1158 if (llvm::any_of(segments
, hasTLSRelocs
)) {
1159 WasmSym::applyTLSRelocs
= symtab
->addSyntheticFunction(
1160 "__wasm_apply_tls_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN
,
1161 make
<SyntheticFunction
>(nullSignature
,
1162 "__wasm_apply_tls_relocs"));
1163 WasmSym::applyTLSRelocs
->markLive();
1167 if (config
->isPic
&& out
.globalSec
->needsRelocations()) {
1168 WasmSym::applyGlobalRelocs
= symtab
->addSyntheticFunction(
1169 "__wasm_apply_global_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN
,
1170 make
<SyntheticFunction
>(nullSignature
, "__wasm_apply_global_relocs"));
1171 WasmSym::applyGlobalRelocs
->markLive();
1174 // If there is only one start function we can just use that function
1175 // itself as the Wasm start function, otherwise we need to synthesize
1176 // a new function to call them in sequence.
1177 if (WasmSym::applyGlobalRelocs
&& WasmSym::initMemory
) {
1178 WasmSym::startFunction
= symtab
->addSyntheticFunction(
1179 "__wasm_start", WASM_SYMBOL_VISIBILITY_HIDDEN
,
1180 make
<SyntheticFunction
>(nullSignature
, "__wasm_start"));
1181 WasmSym::startFunction
->markLive();
1185 void Writer::createInitMemoryFunction() {
1186 LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n");
1187 assert(WasmSym::initMemory
);
1188 assert(hasPassiveInitializedSegments());
1189 uint64_t flagAddress
;
1190 if (config
->sharedMemory
) {
1191 assert(WasmSym::initMemoryFlag
);
1192 flagAddress
= WasmSym::initMemoryFlag
->getVA();
1194 bool is64
= config
->is64
.value_or(false);
1195 std::string bodyContent
;
1197 raw_string_ostream
os(bodyContent
);
1198 // Initialize memory in a thread-safe manner. The thread that successfully
1199 // increments the flag from 0 to 1 is responsible for performing the memory
1200 // initialization. Other threads go sleep on the flag until the first thread
1201 // finishing initializing memory, increments the flag to 2, and wakes all
1202 // the other threads. Once the flag has been set to 2, subsequently started
1203 // threads will skip the sleep. All threads unconditionally drop their
1204 // passive data segments once memory has been initialized. The generated
1205 // code is as follows:
1207 // (func $__wasm_init_memory
1211 // (br_table $init $wait $drop
1212 // (i32.atomic.rmw.cmpxchg align=2 offset=0
1213 // (i32.const $__init_memory_flag)
1219 // ( ... initialize data segments ... )
1220 // (i32.atomic.store align=2 offset=0
1221 // (i32.const $__init_memory_flag)
1225 // (i32.atomic.notify align=2 offset=0
1226 // (i32.const $__init_memory_flag)
1233 // (i32.atomic.wait align=2 offset=0
1234 // (i32.const $__init_memory_flag)
1240 // ( ... drop data segments ... )
1243 // When we are building with PIC, calculate the flag location using:
1245 // (global.get $__memory_base)
1246 // (i32.const $__init_memory_flag)
1249 auto writeGetFlagAddress
= [&]() {
1250 if (config
->isPic
) {
1251 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1252 writeUleb128(os
, 0, "local 0");
1254 writePtrConst(os
, flagAddress
, is64
, "flag address");
1258 if (config
->sharedMemory
) {
1259 // With PIC code we cache the flag address in local 0
1260 if (config
->isPic
) {
1261 writeUleb128(os
, 1, "num local decls");
1262 writeUleb128(os
, 2, "local count");
1263 writeU8(os
, is64
? WASM_TYPE_I64
: WASM_TYPE_I32
, "address type");
1264 writeU8(os
, WASM_OPCODE_GLOBAL_GET
, "GLOBAL_GET");
1265 writeUleb128(os
, WasmSym::memoryBase
->getGlobalIndex(), "memory_base");
1266 writePtrConst(os
, flagAddress
, is64
, "flag address");
1267 writeU8(os
, is64
? WASM_OPCODE_I64_ADD
: WASM_OPCODE_I32_ADD
, "add");
1268 writeU8(os
, WASM_OPCODE_LOCAL_SET
, "local.set");
1269 writeUleb128(os
, 0, "local 0");
1271 writeUleb128(os
, 0, "num locals");
1274 // Set up destination blocks
1275 writeU8(os
, WASM_OPCODE_BLOCK
, "block $drop");
1276 writeU8(os
, WASM_TYPE_NORESULT
, "block type");
1277 writeU8(os
, WASM_OPCODE_BLOCK
, "block $wait");
1278 writeU8(os
, WASM_TYPE_NORESULT
, "block type");
1279 writeU8(os
, WASM_OPCODE_BLOCK
, "block $init");
1280 writeU8(os
, WASM_TYPE_NORESULT
, "block type");
1282 // Atomically check whether we win the race.
1283 writeGetFlagAddress();
1284 writeI32Const(os
, 0, "expected flag value");
1285 writeI32Const(os
, 1, "new flag value");
1286 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1287 writeUleb128(os
, WASM_OPCODE_I32_RMW_CMPXCHG
, "i32.atomic.rmw.cmpxchg");
1288 writeMemArg(os
, 2, 0);
1290 // Based on the value, decide what to do next.
1291 writeU8(os
, WASM_OPCODE_BR_TABLE
, "br_table");
1292 writeUleb128(os
, 2, "label vector length");
1293 writeUleb128(os
, 0, "label $init");
1294 writeUleb128(os
, 1, "label $wait");
1295 writeUleb128(os
, 2, "default label $drop");
1297 // Initialize passive data segments
1298 writeU8(os
, WASM_OPCODE_END
, "end $init");
1300 writeUleb128(os
, 0, "num local decls");
1303 for (const OutputSegment
*s
: segments
) {
1304 if (needsPassiveInitialization(s
)) {
1305 // For passive BSS segments we can simple issue a memory.fill(0).
1306 // For non-BSS segments we do a memory.init. Both these
1307 // instructions take as their first argument the destination
1309 writePtrConst(os
, s
->startVA
, is64
, "destination address");
1310 if (config
->isPic
) {
1311 writeU8(os
, WASM_OPCODE_GLOBAL_GET
, "GLOBAL_GET");
1312 writeUleb128(os
, WasmSym::memoryBase
->getGlobalIndex(),
1314 writeU8(os
, is64
? WASM_OPCODE_I64_ADD
: WASM_OPCODE_I32_ADD
,
1318 // When we initialize the TLS segment we also set the `__tls_base`
1319 // global. This allows the runtime to use this static copy of the
1320 // TLS data for the first/main thread.
1321 if (config
->sharedMemory
&& s
->isTLS()) {
1322 if (config
->isPic
) {
1323 // Cache the result of the addionion in local 0
1324 writeU8(os
, WASM_OPCODE_LOCAL_TEE
, "local.tee");
1325 writeUleb128(os
, 1, "local 1");
1327 writePtrConst(os
, s
->startVA
, is64
, "destination address");
1329 writeU8(os
, WASM_OPCODE_GLOBAL_SET
, "GLOBAL_SET");
1330 writeUleb128(os
, WasmSym::tlsBase
->getGlobalIndex(),
1332 if (config
->isPic
) {
1333 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.tee");
1334 writeUleb128(os
, 1, "local 1");
1339 writeI32Const(os
, 0, "fill value");
1340 writePtrConst(os
, s
->size
, is64
, "memory region size");
1341 writeU8(os
, WASM_OPCODE_MISC_PREFIX
, "bulk-memory prefix");
1342 writeUleb128(os
, WASM_OPCODE_MEMORY_FILL
, "memory.fill");
1343 writeU8(os
, 0, "memory index immediate");
1345 writeI32Const(os
, 0, "source segment offset");
1346 writeI32Const(os
, s
->size
, "memory region size");
1347 writeU8(os
, WASM_OPCODE_MISC_PREFIX
, "bulk-memory prefix");
1348 writeUleb128(os
, WASM_OPCODE_MEMORY_INIT
, "memory.init");
1349 writeUleb128(os
, s
->index
, "segment index immediate");
1350 writeU8(os
, 0, "memory index immediate");
1355 if (config
->sharedMemory
) {
1356 // Set flag to 2 to mark end of initialization
1357 writeGetFlagAddress();
1358 writeI32Const(os
, 2, "flag value");
1359 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1360 writeUleb128(os
, WASM_OPCODE_I32_ATOMIC_STORE
, "i32.atomic.store");
1361 writeMemArg(os
, 2, 0);
1363 // Notify any waiters that memory initialization is complete
1364 writeGetFlagAddress();
1365 writeI32Const(os
, -1, "number of waiters");
1366 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1367 writeUleb128(os
, WASM_OPCODE_ATOMIC_NOTIFY
, "atomic.notify");
1368 writeMemArg(os
, 2, 0);
1369 writeU8(os
, WASM_OPCODE_DROP
, "drop");
1371 // Branch to drop the segments
1372 writeU8(os
, WASM_OPCODE_BR
, "br");
1373 writeUleb128(os
, 1, "label $drop");
1375 // Wait for the winning thread to initialize memory
1376 writeU8(os
, WASM_OPCODE_END
, "end $wait");
1377 writeGetFlagAddress();
1378 writeI32Const(os
, 1, "expected flag value");
1379 writeI64Const(os
, -1, "timeout");
1381 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1382 writeUleb128(os
, WASM_OPCODE_I32_ATOMIC_WAIT
, "i32.atomic.wait");
1383 writeMemArg(os
, 2, 0);
1384 writeU8(os
, WASM_OPCODE_DROP
, "drop");
1386 // Unconditionally drop passive data segments
1387 writeU8(os
, WASM_OPCODE_END
, "end $drop");
1390 for (const OutputSegment
*s
: segments
) {
1391 if (needsPassiveInitialization(s
) && !s
->isBss
) {
1392 // The TLS region should not be dropped since its is needed
1393 // during the initialization of each thread (__wasm_init_tls).
1394 if (config
->sharedMemory
&& s
->isTLS())
1396 // data.drop instruction
1397 writeU8(os
, WASM_OPCODE_MISC_PREFIX
, "bulk-memory prefix");
1398 writeUleb128(os
, WASM_OPCODE_DATA_DROP
, "data.drop");
1399 writeUleb128(os
, s
->index
, "segment index immediate");
1404 writeU8(os
, WASM_OPCODE_END
, "END");
1407 createFunction(WasmSym::initMemory
, bodyContent
);
1410 void Writer::createStartFunction() {
1411 // If the start function exists when we have more than one function to call.
1412 if (WasmSym::initMemory
&& WasmSym::applyGlobalRelocs
) {
1413 assert(WasmSym::startFunction
);
1414 std::string bodyContent
;
1416 raw_string_ostream
os(bodyContent
);
1417 writeUleb128(os
, 0, "num locals");
1418 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1419 writeUleb128(os
, WasmSym::applyGlobalRelocs
->getFunctionIndex(),
1421 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1422 writeUleb128(os
, WasmSym::initMemory
->getFunctionIndex(),
1424 writeU8(os
, WASM_OPCODE_END
, "END");
1426 createFunction(WasmSym::startFunction
, bodyContent
);
1427 } else if (WasmSym::initMemory
) {
1428 WasmSym::startFunction
= WasmSym::initMemory
;
1429 } else if (WasmSym::applyGlobalRelocs
) {
1430 WasmSym::startFunction
= WasmSym::applyGlobalRelocs
;
1434 // For -shared (PIC) output, we create create a synthetic function which will
1435 // apply any relocations to the data segments on startup. This function is
1436 // called `__wasm_apply_data_relocs` and is expected to be called before
1437 // any user code (i.e. before `__wasm_call_ctors`).
1438 void Writer::createApplyDataRelocationsFunction() {
1439 LLVM_DEBUG(dbgs() << "createApplyDataRelocationsFunction\n");
1440 // First write the body's contents to a string.
1441 std::string bodyContent
;
1443 raw_string_ostream
os(bodyContent
);
1444 writeUleb128(os
, 0, "num locals");
1445 for (const OutputSegment
*seg
: segments
)
1446 if (!config
->sharedMemory
|| !seg
->isTLS())
1447 for (const InputChunk
*inSeg
: seg
->inputSegments
)
1448 inSeg
->generateRelocationCode(os
);
1450 writeU8(os
, WASM_OPCODE_END
, "END");
1453 createFunction(WasmSym::applyDataRelocs
, bodyContent
);
1456 void Writer::createApplyTLSRelocationsFunction() {
1457 LLVM_DEBUG(dbgs() << "createApplyTLSRelocationsFunction\n");
1458 std::string bodyContent
;
1460 raw_string_ostream
os(bodyContent
);
1461 writeUleb128(os
, 0, "num locals");
1462 for (const OutputSegment
*seg
: segments
)
1464 for (const InputChunk
*inSeg
: seg
->inputSegments
)
1465 inSeg
->generateRelocationCode(os
);
1467 writeU8(os
, WASM_OPCODE_END
, "END");
1470 createFunction(WasmSym::applyTLSRelocs
, bodyContent
);
1473 // Similar to createApplyDataRelocationsFunction but generates relocation code
1474 // for WebAssembly globals. Because these globals are not shared between threads
1475 // these relocation need to run on every thread.
1476 void Writer::createApplyGlobalRelocationsFunction() {
1477 // First write the body's contents to a string.
1478 std::string bodyContent
;
1480 raw_string_ostream
os(bodyContent
);
1481 writeUleb128(os
, 0, "num locals");
1482 out
.globalSec
->generateRelocationCode(os
, false);
1483 writeU8(os
, WASM_OPCODE_END
, "END");
1486 createFunction(WasmSym::applyGlobalRelocs
, bodyContent
);
1489 // Similar to createApplyGlobalRelocationsFunction but for
1490 // TLS symbols. This cannot be run during the start function
1491 // but must be delayed until __wasm_init_tls is called.
1492 void Writer::createApplyGlobalTLSRelocationsFunction() {
1493 // First write the body's contents to a string.
1494 std::string bodyContent
;
1496 raw_string_ostream
os(bodyContent
);
1497 writeUleb128(os
, 0, "num locals");
1498 out
.globalSec
->generateRelocationCode(os
, true);
1499 writeU8(os
, WASM_OPCODE_END
, "END");
1502 createFunction(WasmSym::applyGlobalTLSRelocs
, bodyContent
);
1505 // Create synthetic "__wasm_call_ctors" function based on ctor functions
1507 void Writer::createCallCtorsFunction() {
1508 // If __wasm_call_ctors isn't referenced, there aren't any ctors, don't
1509 // define the `__wasm_call_ctors` function.
1510 if (!WasmSym::callCtors
->isLive() && initFunctions
.empty())
1513 // First write the body's contents to a string.
1514 std::string bodyContent
;
1516 raw_string_ostream
os(bodyContent
);
1517 writeUleb128(os
, 0, "num locals");
1519 // Call constructors
1520 for (const WasmInitEntry
&f
: initFunctions
) {
1521 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1522 writeUleb128(os
, f
.sym
->getFunctionIndex(), "function index");
1523 for (size_t i
= 0; i
< f
.sym
->signature
->Returns
.size(); i
++) {
1524 writeU8(os
, WASM_OPCODE_DROP
, "DROP");
1528 writeU8(os
, WASM_OPCODE_END
, "END");
1531 createFunction(WasmSym::callCtors
, bodyContent
);
1534 // Create a wrapper around a function export which calls the
1535 // static constructors and destructors.
1536 void Writer::createCommandExportWrapper(uint32_t functionIndex
,
1537 DefinedFunction
*f
) {
1538 // First write the body's contents to a string.
1539 std::string bodyContent
;
1541 raw_string_ostream
os(bodyContent
);
1542 writeUleb128(os
, 0, "num locals");
1544 // Call `__wasm_call_ctors` which call static constructors (and
1545 // applies any runtime relocations in Emscripten-style PIC mode)
1546 if (WasmSym::callCtors
->isLive()) {
1547 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1548 writeUleb128(os
, WasmSym::callCtors
->getFunctionIndex(),
1552 // Call the user's code, leaving any return values on the operand stack.
1553 for (size_t i
= 0; i
< f
->signature
->Params
.size(); ++i
) {
1554 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1555 writeUleb128(os
, i
, "local index");
1557 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1558 writeUleb128(os
, functionIndex
, "function index");
1560 // Call the function that calls the destructors.
1561 if (DefinedFunction
*callDtors
= WasmSym::callDtors
) {
1562 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1563 writeUleb128(os
, callDtors
->getFunctionIndex(), "function index");
1566 // End the function, returning the return values from the user's code.
1567 writeU8(os
, WASM_OPCODE_END
, "END");
1570 createFunction(f
, bodyContent
);
1573 void Writer::createInitTLSFunction() {
1574 std::string bodyContent
;
1576 raw_string_ostream
os(bodyContent
);
1578 OutputSegment
*tlsSeg
= nullptr;
1579 for (auto *seg
: segments
) {
1580 if (seg
->name
== ".tdata") {
1586 writeUleb128(os
, 0, "num locals");
1588 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1589 writeUleb128(os
, 0, "local index");
1591 writeU8(os
, WASM_OPCODE_GLOBAL_SET
, "global.set");
1592 writeUleb128(os
, WasmSym::tlsBase
->getGlobalIndex(), "global index");
1594 // FIXME(wvo): this local needs to be I64 in wasm64, or we need an extend op.
1595 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1596 writeUleb128(os
, 0, "local index");
1598 writeI32Const(os
, 0, "segment offset");
1600 writeI32Const(os
, tlsSeg
->size
, "memory region size");
1602 writeU8(os
, WASM_OPCODE_MISC_PREFIX
, "bulk-memory prefix");
1603 writeUleb128(os
, WASM_OPCODE_MEMORY_INIT
, "MEMORY.INIT");
1604 writeUleb128(os
, tlsSeg
->index
, "segment index immediate");
1605 writeU8(os
, 0, "memory index immediate");
1608 if (WasmSym::applyTLSRelocs
) {
1609 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1610 writeUleb128(os
, WasmSym::applyTLSRelocs
->getFunctionIndex(),
1614 if (WasmSym::applyGlobalTLSRelocs
) {
1615 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1616 writeUleb128(os
, WasmSym::applyGlobalTLSRelocs
->getFunctionIndex(),
1619 writeU8(os
, WASM_OPCODE_END
, "end function");
1622 createFunction(WasmSym::initTLS
, bodyContent
);
1625 // Populate InitFunctions vector with init functions from all input objects.
1626 // This is then used either when creating the output linking section or to
1627 // synthesize the "__wasm_call_ctors" function.
1628 void Writer::calculateInitFunctions() {
1629 if (!config
->relocatable
&& !WasmSym::callCtors
->isLive())
1632 for (ObjFile
*file
: symtab
->objectFiles
) {
1633 const WasmLinkingData
&l
= file
->getWasmObj()->linkingData();
1634 for (const WasmInitFunc
&f
: l
.InitFunctions
) {
1635 FunctionSymbol
*sym
= file
->getFunctionSymbol(f
.Symbol
);
1636 // comdat exclusions can cause init functions be discarded.
1637 if (sym
->isDiscarded() || !sym
->isLive())
1639 if (sym
->signature
->Params
.size() != 0)
1640 error("constructor functions cannot take arguments: " + toString(*sym
));
1641 LLVM_DEBUG(dbgs() << "initFunctions: " << toString(*sym
) << "\n");
1642 initFunctions
.emplace_back(WasmInitEntry
{sym
, f
.Priority
});
1646 // Sort in order of priority (lowest first) so that they are called
1647 // in the correct order.
1648 llvm::stable_sort(initFunctions
,
1649 [](const WasmInitEntry
&l
, const WasmInitEntry
&r
) {
1650 return l
.priority
< r
.priority
;
1654 void Writer::createSyntheticSections() {
1655 out
.dylinkSec
= make
<DylinkSection
>();
1656 out
.typeSec
= make
<TypeSection
>();
1657 out
.importSec
= make
<ImportSection
>();
1658 out
.functionSec
= make
<FunctionSection
>();
1659 out
.tableSec
= make
<TableSection
>();
1660 out
.memorySec
= make
<MemorySection
>();
1661 out
.tagSec
= make
<TagSection
>();
1662 out
.globalSec
= make
<GlobalSection
>();
1663 out
.exportSec
= make
<ExportSection
>();
1664 out
.startSec
= make
<StartSection
>();
1665 out
.elemSec
= make
<ElemSection
>();
1666 out
.producersSec
= make
<ProducersSection
>();
1667 out
.targetFeaturesSec
= make
<TargetFeaturesSection
>();
1668 out
.buildIdSec
= make
<BuildIdSection
>();
1671 void Writer::createSyntheticSectionsPostLayout() {
1672 out
.dataCountSec
= make
<DataCountSection
>(segments
);
1673 out
.linkingSec
= make
<LinkingSection
>(initFunctions
, segments
);
1674 out
.nameSec
= make
<NameSection
>(segments
);
1677 void Writer::run() {
1678 // For PIC code the table base is assigned dynamically by the loader.
1679 // For non-PIC, we start at 1 so that accessing table index 0 always traps.
1680 if (!config
->isPic
) {
1681 if (WasmSym::definedTableBase
)
1682 WasmSym::definedTableBase
->setVA(config
->tableBase
);
1683 if (WasmSym::definedTableBase32
)
1684 WasmSym::definedTableBase32
->setVA(config
->tableBase
);
1687 log("-- createOutputSegments");
1688 createOutputSegments();
1689 log("-- createSyntheticSections");
1690 createSyntheticSections();
1691 log("-- layoutMemory");
1694 if (!config
->relocatable
) {
1695 // Create linker synthesized __start_SECNAME/__stop_SECNAME symbols
1696 // This has to be done after memory layout is performed.
1697 for (const OutputSegment
*seg
: segments
) {
1698 addStartStopSymbols(seg
);
1702 for (auto &pair
: config
->exportedSymbols
) {
1703 Symbol
*sym
= symtab
->find(pair
.first());
1704 if (sym
&& sym
->isDefined())
1705 sym
->forceExport
= true;
1708 // Delay reporting errors about explicit exports until after
1709 // addStartStopSymbols which can create optional symbols.
1710 for (auto &name
: config
->requiredExports
) {
1711 Symbol
*sym
= symtab
->find(name
);
1712 if (!sym
|| !sym
->isDefined()) {
1713 if (config
->unresolvedSymbols
== UnresolvedPolicy::ReportError
)
1714 error(Twine("symbol exported via --export not found: ") + name
);
1715 if (config
->unresolvedSymbols
== UnresolvedPolicy::Warn
)
1716 warn(Twine("symbol exported via --export not found: ") + name
);
1720 log("-- populateTargetFeatures");
1721 populateTargetFeatures();
1723 // When outputting PIC code each segment lives at at fixes offset from the
1724 // `__memory_base` import. Unless we support the extended const expression we
1725 // can't do addition inside the constant expression, so we much combine the
1726 // segments into a single one that can live at `__memory_base`.
1727 if (config
->isPic
&& !config
->extendedConst
&& !config
->sharedMemory
) {
1728 // In shared memory mode all data segments are passive and initialized
1729 // via __wasm_init_memory.
1730 log("-- combineOutputSegments");
1731 combineOutputSegments();
1734 log("-- createSyntheticSectionsPostLayout");
1735 createSyntheticSectionsPostLayout();
1736 log("-- populateProducers");
1737 populateProducers();
1738 log("-- calculateImports");
1740 log("-- scanRelocations");
1742 log("-- finalizeIndirectFunctionTable");
1743 finalizeIndirectFunctionTable();
1744 log("-- createSyntheticInitFunctions");
1745 createSyntheticInitFunctions();
1746 log("-- assignIndexes");
1748 log("-- calculateInitFunctions");
1749 calculateInitFunctions();
1751 if (!config
->relocatable
) {
1752 // Create linker synthesized functions
1753 if (WasmSym::applyDataRelocs
)
1754 createApplyDataRelocationsFunction();
1755 if (WasmSym::applyGlobalRelocs
)
1756 createApplyGlobalRelocationsFunction();
1757 if (WasmSym::applyTLSRelocs
)
1758 createApplyTLSRelocationsFunction();
1759 if (WasmSym::applyGlobalTLSRelocs
)
1760 createApplyGlobalTLSRelocationsFunction();
1761 if (WasmSym::initMemory
)
1762 createInitMemoryFunction();
1763 createStartFunction();
1765 createCallCtorsFunction();
1767 // Create export wrappers for commands if needed.
1769 // If the input contains a call to `__wasm_call_ctors`, either in one of
1770 // the input objects or an explicit export from the command-line, we
1771 // assume ctors and dtors are taken care of already.
1772 if (!config
->relocatable
&& !config
->isPic
&&
1773 !WasmSym::callCtors
->isUsedInRegularObj
&&
1774 !WasmSym::callCtors
->isExported()) {
1775 log("-- createCommandExportWrappers");
1776 createCommandExportWrappers();
1780 if (WasmSym::initTLS
&& WasmSym::initTLS
->isLive()) {
1781 log("-- createInitTLSFunction");
1782 createInitTLSFunction();
1788 log("-- calculateTypes");
1790 log("-- calculateExports");
1792 log("-- calculateCustomSections");
1793 calculateCustomSections();
1794 log("-- populateSymtab");
1796 log("-- checkImportExportTargetFeatures");
1797 checkImportExportTargetFeatures();
1798 log("-- addSections");
1801 if (errorHandler().verbose
) {
1802 log("Defined Functions: " + Twine(out
.functionSec
->inputFunctions
.size()));
1803 log("Defined Globals : " + Twine(out
.globalSec
->numGlobals()));
1804 log("Defined Tags : " + Twine(out
.tagSec
->inputTags
.size()));
1805 log("Defined Tables : " + Twine(out
.tableSec
->inputTables
.size()));
1806 log("Function Imports : " +
1807 Twine(out
.importSec
->getNumImportedFunctions()));
1808 log("Global Imports : " + Twine(out
.importSec
->getNumImportedGlobals()));
1809 log("Tag Imports : " + Twine(out
.importSec
->getNumImportedTags()));
1810 log("Table Imports : " + Twine(out
.importSec
->getNumImportedTables()));
1814 log("-- finalizeSections");
1817 log("-- writeMapFile");
1818 writeMapFile(outputSections
);
1827 log("-- writeSections");
1833 if (Error e
= buffer
->commit())
1834 fatal("failed to write output '" + buffer
->getPath() +
1835 "': " + toString(std::move(e
)));
1838 // Open a result file.
1839 void Writer::openFile() {
1840 log("writing: " + config
->outputFile
);
1842 Expected
<std::unique_ptr
<FileOutputBuffer
>> bufferOrErr
=
1843 FileOutputBuffer::create(config
->outputFile
, fileSize
,
1844 FileOutputBuffer::F_executable
);
1847 error("failed to open " + config
->outputFile
+ ": " +
1848 toString(bufferOrErr
.takeError()));
1850 buffer
= std::move(*bufferOrErr
);
1853 void Writer::createHeader() {
1854 raw_string_ostream
os(header
);
1855 writeBytes(os
, WasmMagic
, sizeof(WasmMagic
), "wasm magic");
1856 writeU32(os
, WasmVersion
, "wasm version");
1858 fileSize
+= header
.size();
1861 void writeResult() { Writer().run(); }
1863 } // namespace wasm::lld