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
: ctx
.objectFiles
) {
137 for (InputChunk
*section
: file
->customSections
) {
138 // Exclude COMDAT sections that are not selected for inclusion
139 if (section
->discarded
)
141 // Ignore empty custom sections. In particular objcopy/strip will
142 // sometimes replace stripped sections with empty custom sections to
143 // avoid section re-numbering.
144 if (section
->getSize() == 0)
146 StringRef name
= section
->name
;
147 // These custom sections are known the linker and synthesized rather than
149 if (name
== "linking" || name
== "name" || name
== "producers" ||
150 name
== "target_features" || name
.starts_with("reloc."))
152 // These custom sections are generated by `clang -fembed-bitcode`.
153 // These are used by the rust toolchain to ship LTO data along with
154 // compiled object code, but they don't want this included in the linker
156 if (name
== ".llvmbc" || name
== ".llvmcmd")
158 // Strip debug section in that option was specified.
159 if (stripDebug
&& name
.starts_with(".debug_"))
161 // Otherwise include custom sections by default and concatenate their
163 customSectionMapping
[name
].push_back(section
);
168 void Writer::createCustomSections() {
169 log("createCustomSections");
170 for (auto &pair
: customSectionMapping
) {
171 StringRef name
= pair
.first
;
172 LLVM_DEBUG(dbgs() << "createCustomSection: " << name
<< "\n");
174 OutputSection
*sec
= make
<CustomSection
>(std::string(name
), pair
.second
);
175 if (config
->relocatable
|| config
->emitRelocs
) {
176 auto *sym
= make
<OutputSectionSymbol
>(sec
);
177 out
.linkingSec
->addToSymtab(sym
);
178 sec
->sectionSym
= sym
;
184 // Create relocations sections in the final output.
185 // These are only created when relocatable output is requested.
186 void Writer::createRelocSections() {
187 log("createRelocSections");
188 // Don't use iterator here since we are adding to OutputSection
189 size_t origSize
= outputSections
.size();
190 for (size_t i
= 0; i
< origSize
; i
++) {
191 LLVM_DEBUG(dbgs() << "check section " << i
<< "\n");
192 OutputSection
*sec
= outputSections
[i
];
194 // Count the number of needed sections.
195 uint32_t count
= sec
->getNumRelocations();
200 if (sec
->type
== WASM_SEC_DATA
)
202 else if (sec
->type
== WASM_SEC_CODE
)
204 else if (sec
->type
== WASM_SEC_CUSTOM
)
205 name
= saver().save("reloc." + sec
->name
);
208 "relocations only supported for code, data, or custom sections");
210 addSection(make
<RelocSection
>(name
, sec
));
214 void Writer::populateProducers() {
215 for (ObjFile
*file
: ctx
.objectFiles
) {
216 const WasmProducerInfo
&info
= file
->getWasmObj()->getProducerInfo();
217 out
.producersSec
->addInfo(info
);
221 void Writer::writeHeader() {
222 memcpy(buffer
->getBufferStart(), header
.data(), header
.size());
225 void Writer::writeSections() {
226 uint8_t *buf
= buffer
->getBufferStart();
227 parallelForEach(outputSections
, [buf
](OutputSection
*s
) {
228 assert(s
->isNeeded());
233 // Computes a hash value of Data using a given hash function.
234 // In order to utilize multiple cores, we first split data into 1MB
235 // chunks, compute a hash for each chunk, and then compute a hash value
236 // of the hash values.
239 computeHash(llvm::MutableArrayRef
<uint8_t> hashBuf
,
240 llvm::ArrayRef
<uint8_t> data
,
241 std::function
<void(uint8_t *dest
, ArrayRef
<uint8_t> arr
)> hashFn
) {
242 std::vector
<ArrayRef
<uint8_t>> chunks
= split(data
, 1024 * 1024);
243 std::vector
<uint8_t> hashes(chunks
.size() * hashBuf
.size());
245 // Compute hash values.
246 parallelFor(0, chunks
.size(), [&](size_t i
) {
247 hashFn(hashes
.data() + i
* hashBuf
.size(), chunks
[i
]);
250 // Write to the final output buffer.
251 hashFn(hashBuf
.data(), hashes
);
254 static void makeUUID(unsigned version
, llvm::ArrayRef
<uint8_t> fileHash
,
255 llvm::MutableArrayRef
<uint8_t> output
) {
256 assert((version
== 4 || version
== 5) && "Unknown UUID version");
257 assert(output
.size() == 16 && "Wrong size for UUID output");
259 // Build a valid v5 UUID from a hardcoded (randomly-generated) namespace
260 // UUID, and the computed hash of the output.
261 std::array
<uint8_t, 16> namespaceUUID
{0xA1, 0xFA, 0x48, 0x2D, 0x0E, 0x22,
262 0x03, 0x8D, 0x33, 0x8B, 0x52, 0x1C,
263 0xD6, 0xD2, 0x12, 0xB2};
265 sha
.update(namespaceUUID
);
266 sha
.update(fileHash
);
267 auto s
= sha
.final();
268 std::copy(s
.data(), &s
.data()[output
.size()], output
.data());
269 } else if (version
== 4) {
270 if (auto ec
= llvm::getRandomBytes(output
.data(), output
.size()))
271 error("entropy source failure: " + ec
.message());
273 // Set the UUID version and variant fields.
274 // The version is the upper nibble of byte 6 (0b0101xxxx or 0b0100xxxx)
275 output
[6] = (static_cast<uint8_t>(version
) << 4) | (output
[6] & 0xF);
277 // The variant is DCE 1.1/ISO 11578 (0b10xxxxxx)
282 void Writer::writeBuildId() {
283 if (!out
.buildIdSec
->isNeeded())
285 if (config
->buildId
== BuildIdKind::Hexstring
) {
286 out
.buildIdSec
->writeBuildId(config
->buildIdVector
);
290 // Compute a hash of all sections of the output file.
291 size_t hashSize
= out
.buildIdSec
->hashSize
;
292 std::vector
<uint8_t> buildId(hashSize
);
293 llvm::ArrayRef
<uint8_t> buf
{buffer
->getBufferStart(), size_t(fileSize
)};
295 switch (config
->buildId
) {
296 case BuildIdKind::Fast
: {
297 std::vector
<uint8_t> fileHash(8);
298 computeHash(fileHash
, buf
, [](uint8_t *dest
, ArrayRef
<uint8_t> arr
) {
299 support::endian::write64le(dest
, xxh3_64bits(arr
));
301 makeUUID(5, fileHash
, buildId
);
304 case BuildIdKind::Sha1
:
305 computeHash(buildId
, buf
, [&](uint8_t *dest
, ArrayRef
<uint8_t> arr
) {
306 memcpy(dest
, SHA1::hash(arr
).data(), hashSize
);
309 case BuildIdKind::Uuid
:
310 makeUUID(4, {}, buildId
);
313 llvm_unreachable("unknown BuildIdKind");
315 out
.buildIdSec
->writeBuildId(buildId
);
318 static void setGlobalPtr(DefinedGlobal
*g
, uint64_t memoryPtr
) {
319 LLVM_DEBUG(dbgs() << "setGlobalPtr " << g
->getName() << " -> " << memoryPtr
<< "\n");
320 g
->global
->setPointerValue(memoryPtr
);
323 // Fix the memory layout of the output binary. This assigns memory offsets
324 // to each of the input data sections as well as the explicit stack region.
325 // The default memory layout is as follows, from low to high.
327 // - initialized data (starting at config->globalBase)
328 // - BSS data (not currently implemented in llvm)
329 // - explicit stack (config->ZStackSize)
330 // - heap start / unallocated
332 // The --stack-first option means that stack is placed before any static data.
333 // This can be useful since it means that stack overflow traps immediately
334 // rather than overwriting global data, but also increases code size since all
335 // static data loads and stores requires larger offsets.
336 void Writer::layoutMemory() {
337 uint64_t memoryPtr
= 0;
339 auto placeStack
= [&]() {
340 if (config
->relocatable
|| ctx
.isPic
)
342 memoryPtr
= alignTo(memoryPtr
, stackAlignment
);
343 if (WasmSym::stackLow
)
344 WasmSym::stackLow
->setVA(memoryPtr
);
345 if (config
->zStackSize
!= alignTo(config
->zStackSize
, stackAlignment
))
346 error("stack size must be " + Twine(stackAlignment
) + "-byte aligned");
347 log("mem: stack size = " + Twine(config
->zStackSize
));
348 log("mem: stack base = " + Twine(memoryPtr
));
349 memoryPtr
+= config
->zStackSize
;
350 setGlobalPtr(cast
<DefinedGlobal
>(WasmSym::stackPointer
), memoryPtr
);
351 if (WasmSym::stackHigh
)
352 WasmSym::stackHigh
->setVA(memoryPtr
);
353 log("mem: stack top = " + Twine(memoryPtr
));
356 if (config
->stackFirst
) {
358 if (config
->globalBase
) {
359 if (config
->globalBase
< memoryPtr
) {
360 error("--global-base cannot be less than stack size when --stack-first is used");
363 memoryPtr
= config
->globalBase
;
366 memoryPtr
= config
->globalBase
;
369 log("mem: global base = " + Twine(memoryPtr
));
370 if (WasmSym::globalBase
)
371 WasmSym::globalBase
->setVA(memoryPtr
);
373 uint64_t dataStart
= memoryPtr
;
375 // Arbitrarily set __dso_handle handle to point to the start of the data
377 if (WasmSym::dsoHandle
)
378 WasmSym::dsoHandle
->setVA(dataStart
);
380 out
.dylinkSec
->memAlign
= 0;
381 for (OutputSegment
*seg
: segments
) {
382 out
.dylinkSec
->memAlign
= std::max(out
.dylinkSec
->memAlign
, seg
->alignment
);
383 memoryPtr
= alignTo(memoryPtr
, 1ULL << seg
->alignment
);
384 seg
->startVA
= memoryPtr
;
385 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", seg
->name
,
386 memoryPtr
, seg
->size
, seg
->alignment
));
388 if (!config
->relocatable
&& seg
->isTLS()) {
389 if (WasmSym::tlsSize
) {
390 auto *tlsSize
= cast
<DefinedGlobal
>(WasmSym::tlsSize
);
391 setGlobalPtr(tlsSize
, seg
->size
);
393 if (WasmSym::tlsAlign
) {
394 auto *tlsAlign
= cast
<DefinedGlobal
>(WasmSym::tlsAlign
);
395 setGlobalPtr(tlsAlign
, int64_t{1} << seg
->alignment
);
397 if (!config
->sharedMemory
&& WasmSym::tlsBase
) {
398 auto *tlsBase
= cast
<DefinedGlobal
>(WasmSym::tlsBase
);
399 setGlobalPtr(tlsBase
, memoryPtr
);
403 memoryPtr
+= seg
->size
;
406 // Make space for the memory initialization flag
407 if (config
->sharedMemory
&& hasPassiveInitializedSegments()) {
408 memoryPtr
= alignTo(memoryPtr
, 4);
409 WasmSym::initMemoryFlag
= symtab
->addSyntheticDataSymbol(
410 "__wasm_init_memory_flag", WASM_SYMBOL_VISIBILITY_HIDDEN
);
411 WasmSym::initMemoryFlag
->markLive();
412 WasmSym::initMemoryFlag
->setVA(memoryPtr
);
413 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}",
414 "__wasm_init_memory_flag", memoryPtr
, 4, 4));
418 if (WasmSym::dataEnd
)
419 WasmSym::dataEnd
->setVA(memoryPtr
);
421 uint64_t staticDataSize
= memoryPtr
- dataStart
;
422 log("mem: static data = " + Twine(staticDataSize
));
424 out
.dylinkSec
->memSize
= staticDataSize
;
426 if (!config
->stackFirst
)
429 if (WasmSym::heapBase
) {
430 // Set `__heap_base` to follow the end of the stack or global data. The
431 // fact that this comes last means that a malloc/brk implementation can
432 // grow the heap at runtime.
433 // We'll align the heap base here because memory allocators might expect
434 // __heap_base to be aligned already.
435 memoryPtr
= alignTo(memoryPtr
, heapAlignment
);
436 log("mem: heap base = " + Twine(memoryPtr
));
437 WasmSym::heapBase
->setVA(memoryPtr
);
440 uint64_t maxMemorySetting
= 1ULL << 32;
441 if (config
->is64
.value_or(false)) {
442 // TODO: Update once we decide on a reasonable limit here:
443 // https://github.com/WebAssembly/memory64/issues/33
444 maxMemorySetting
= 1ULL << 34;
447 if (config
->initialHeap
!= 0) {
448 if (config
->initialHeap
!= alignTo(config
->initialHeap
, WasmPageSize
))
449 error("initial heap must be " + Twine(WasmPageSize
) + "-byte aligned");
450 uint64_t maxInitialHeap
= maxMemorySetting
- memoryPtr
;
451 if (config
->initialHeap
> maxInitialHeap
)
452 error("initial heap too large, cannot be greater than " +
453 Twine(maxInitialHeap
));
454 memoryPtr
+= config
->initialHeap
;
457 if (config
->initialMemory
!= 0) {
458 if (config
->initialMemory
!= alignTo(config
->initialMemory
, WasmPageSize
))
459 error("initial memory must be " + Twine(WasmPageSize
) + "-byte aligned");
460 if (memoryPtr
> config
->initialMemory
)
461 error("initial memory too small, " + Twine(memoryPtr
) + " bytes needed");
462 if (config
->initialMemory
> maxMemorySetting
)
463 error("initial memory too large, cannot be greater than " +
464 Twine(maxMemorySetting
));
465 memoryPtr
= config
->initialMemory
;
468 memoryPtr
= alignTo(memoryPtr
, WasmPageSize
);
470 out
.memorySec
->numMemoryPages
= memoryPtr
/ WasmPageSize
;
471 log("mem: total pages = " + Twine(out
.memorySec
->numMemoryPages
));
473 if (WasmSym::heapEnd
) {
474 // Set `__heap_end` to follow the end of the statically allocated linear
475 // memory. The fact that this comes last means that a malloc/brk
476 // implementation can grow the heap at runtime.
477 log("mem: heap end = " + Twine(memoryPtr
));
478 WasmSym::heapEnd
->setVA(memoryPtr
);
481 uint64_t maxMemory
= 0;
482 if (config
->maxMemory
!= 0) {
483 if (config
->maxMemory
!= alignTo(config
->maxMemory
, WasmPageSize
))
484 error("maximum memory must be " + Twine(WasmPageSize
) + "-byte aligned");
485 if (memoryPtr
> config
->maxMemory
)
486 error("maximum memory too small, " + Twine(memoryPtr
) + " bytes needed");
487 if (config
->maxMemory
> maxMemorySetting
)
488 error("maximum memory too large, cannot be greater than " +
489 Twine(maxMemorySetting
));
491 maxMemory
= config
->maxMemory
;
492 } else if (config
->noGrowableMemory
) {
493 maxMemory
= memoryPtr
;
496 // If no maxMemory config was supplied but we are building with
497 // shared memory, we need to pick a sensible upper limit.
498 if (config
->sharedMemory
&& maxMemory
== 0) {
500 maxMemory
= maxMemorySetting
;
502 maxMemory
= memoryPtr
;
505 if (maxMemory
!= 0) {
506 out
.memorySec
->maxMemoryPages
= maxMemory
/ WasmPageSize
;
507 log("mem: max pages = " + Twine(out
.memorySec
->maxMemoryPages
));
511 void Writer::addSection(OutputSection
*sec
) {
512 if (!sec
->isNeeded())
514 log("addSection: " + toString(*sec
));
515 sec
->sectionIndex
= outputSections
.size();
516 outputSections
.push_back(sec
);
519 // If a section name is valid as a C identifier (which is rare because of
520 // the leading '.'), linkers are expected to define __start_<secname> and
521 // __stop_<secname> symbols. They are at beginning and end of the section,
522 // respectively. This is not requested by the ELF standard, but GNU ld and
523 // gold provide the feature, and used by many programs.
524 static void addStartStopSymbols(const OutputSegment
*seg
) {
525 StringRef name
= seg
->name
;
526 if (!isValidCIdentifier(name
))
528 LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << name
<< "\n");
529 uint64_t start
= seg
->startVA
;
530 uint64_t stop
= start
+ seg
->size
;
531 symtab
->addOptionalDataSymbol(saver().save("__start_" + name
), start
);
532 symtab
->addOptionalDataSymbol(saver().save("__stop_" + name
), stop
);
535 void Writer::addSections() {
536 addSection(out
.dylinkSec
);
537 addSection(out
.typeSec
);
538 addSection(out
.importSec
);
539 addSection(out
.functionSec
);
540 addSection(out
.tableSec
);
541 addSection(out
.memorySec
);
542 addSection(out
.tagSec
);
543 addSection(out
.globalSec
);
544 addSection(out
.exportSec
);
545 addSection(out
.startSec
);
546 addSection(out
.elemSec
);
547 addSection(out
.dataCountSec
);
549 addSection(make
<CodeSection
>(out
.functionSec
->inputFunctions
));
550 addSection(make
<DataSection
>(segments
));
552 createCustomSections();
554 addSection(out
.linkingSec
);
555 if (config
->emitRelocs
|| config
->relocatable
) {
556 createRelocSections();
559 addSection(out
.nameSec
);
560 addSection(out
.producersSec
);
561 addSection(out
.targetFeaturesSec
);
562 addSection(out
.buildIdSec
);
565 void Writer::finalizeSections() {
566 for (OutputSection
*s
: outputSections
) {
567 s
->setOffset(fileSize
);
568 s
->finalizeContents();
569 fileSize
+= s
->getSize();
573 void Writer::populateTargetFeatures() {
574 StringMap
<std::string
> used
;
575 StringMap
<std::string
> disallowed
;
576 SmallSet
<std::string
, 8> &allowed
= out
.targetFeaturesSec
->features
;
577 bool tlsUsed
= false;
580 // This should not be necessary because all PIC objects should
581 // contain the mutable-globals feature.
582 // TODO (https://github.com/llvm/llvm-project/issues/51681)
583 allowed
.insert("mutable-globals");
586 if (config
->extraFeatures
.has_value()) {
587 auto &extraFeatures
= *config
->extraFeatures
;
588 allowed
.insert(extraFeatures
.begin(), extraFeatures
.end());
591 // Only infer used features if user did not specify features
592 bool inferFeatures
= !config
->features
.has_value();
594 if (!inferFeatures
) {
595 auto &explicitFeatures
= *config
->features
;
596 allowed
.insert(explicitFeatures
.begin(), explicitFeatures
.end());
597 if (!config
->checkFeatures
)
601 // Find the sets of used and disallowed features
602 for (ObjFile
*file
: ctx
.objectFiles
) {
603 StringRef
fileName(file
->getName());
604 for (auto &feature
: file
->getWasmObj()->getTargetFeatures()) {
605 switch (feature
.Prefix
) {
606 case WASM_FEATURE_PREFIX_USED
:
607 used
.insert({feature
.Name
, std::string(fileName
)});
609 case WASM_FEATURE_PREFIX_DISALLOWED
:
610 disallowed
.insert({feature
.Name
, std::string(fileName
)});
613 error("Unrecognized feature policy prefix " +
614 std::to_string(feature
.Prefix
));
618 // Find TLS data segments
619 auto isTLS
= [](InputChunk
*segment
) {
620 return segment
->live
&& segment
->isTLS();
622 tlsUsed
= tlsUsed
|| llvm::any_of(file
->segments
, isTLS
);
626 for (const auto &key
: used
.keys())
627 allowed
.insert(std::string(key
));
629 if (!config
->checkFeatures
)
632 if (config
->sharedMemory
) {
633 if (disallowed
.count("shared-mem"))
634 error("--shared-memory is disallowed by " + disallowed
["shared-mem"] +
635 " because it was not compiled with 'atomics' or 'bulk-memory' "
638 for (auto feature
: {"atomics", "bulk-memory"})
639 if (!allowed
.count(feature
))
640 error(StringRef("'") + feature
+
641 "' feature must be used in order to use shared memory");
645 for (auto feature
: {"atomics", "bulk-memory"})
646 if (!allowed
.count(feature
))
647 error(StringRef("'") + feature
+
648 "' feature must be used in order to use thread-local storage");
651 // Validate that used features are allowed in output
652 if (!inferFeatures
) {
653 for (const auto &feature
: used
.keys()) {
654 if (!allowed
.count(std::string(feature
)))
655 error(Twine("Target feature '") + feature
+ "' used by " +
656 used
[feature
] + " is not allowed.");
660 // Validate the disallowed constraints for each file
661 for (ObjFile
*file
: ctx
.objectFiles
) {
662 StringRef
fileName(file
->getName());
663 SmallSet
<std::string
, 8> objectFeatures
;
664 for (const auto &feature
: file
->getWasmObj()->getTargetFeatures()) {
665 if (feature
.Prefix
== WASM_FEATURE_PREFIX_DISALLOWED
)
667 objectFeatures
.insert(feature
.Name
);
668 if (disallowed
.count(feature
.Name
))
669 error(Twine("Target feature '") + feature
.Name
+ "' used in " +
670 fileName
+ " is disallowed by " + disallowed
[feature
.Name
] +
671 ". Use --no-check-features to suppress.");
676 // Normally we don't include bss segments in the binary. In particular if
677 // memory is not being imported then we can assume its zero initialized.
678 // In the case the memory is imported, and we can use the memory.fill
679 // instruction, then we can also avoid including the segments.
680 // Finally, if we are emitting relocations, they may refer to locations within
681 // the bss segments, so these segments need to exist in the binary.
682 if (config
->emitRelocs
||
683 (config
->memoryImport
.has_value() && !allowed
.count("bulk-memory")))
684 ctx
.emitBssSegments
= true;
686 if (allowed
.count("extended-const"))
687 config
->extendedConst
= true;
689 for (auto &feature
: allowed
)
690 log("Allowed feature: " + feature
);
693 void Writer::checkImportExportTargetFeatures() {
694 if (config
->relocatable
|| !config
->checkFeatures
)
697 if (out
.targetFeaturesSec
->features
.count("mutable-globals") == 0) {
698 for (const Symbol
*sym
: out
.importSec
->importedSymbols
) {
699 if (auto *global
= dyn_cast
<GlobalSymbol
>(sym
)) {
700 if (global
->getGlobalType()->Mutable
) {
701 error(Twine("mutable global imported but 'mutable-globals' feature "
702 "not present in inputs: `") +
703 toString(*sym
) + "`. Use --no-check-features to suppress.");
707 for (const Symbol
*sym
: out
.exportSec
->exportedSymbols
) {
708 if (isa
<GlobalSymbol
>(sym
)) {
709 error(Twine("mutable global exported but 'mutable-globals' feature "
710 "not present in inputs: `") +
711 toString(*sym
) + "`. Use --no-check-features to suppress.");
717 static bool shouldImport(Symbol
*sym
) {
718 // We don't generate imports for data symbols. They however can be imported
720 if (isa
<DataSymbol
>(sym
))
724 if (!sym
->isUsedInRegularObj
)
727 // When a symbol is weakly defined in a shared library we need to allow
728 // it to be overridden by another module so need to both import
729 // and export the symbol.
730 if (config
->shared
&& sym
->isWeak() && !sym
->isUndefined() &&
735 if (!sym
->isUndefined())
737 if (sym
->isWeak() && !config
->relocatable
&& !ctx
.isPic
)
740 // In PIC mode we only need to import functions when they are called directly.
741 // Indirect usage all goes via GOT imports.
743 if (auto *f
= dyn_cast
<UndefinedFunction
>(sym
))
744 if (!f
->isCalledDirectly
)
748 if (ctx
.isPic
|| config
->relocatable
|| config
->importUndefined
||
749 config
->unresolvedSymbols
== UnresolvedPolicy::ImportDynamic
)
751 if (config
->allowUndefinedSymbols
.count(sym
->getName()) != 0)
754 return sym
->isImported();
757 void Writer::calculateImports() {
758 // Some inputs require that the indirect function table be assigned to table
759 // number 0, so if it is present and is an import, allocate it before any
761 if (WasmSym::indirectFunctionTable
&&
762 shouldImport(WasmSym::indirectFunctionTable
))
763 out
.importSec
->addImport(WasmSym::indirectFunctionTable
);
765 for (Symbol
*sym
: symtab
->symbols()) {
766 if (!shouldImport(sym
))
768 if (sym
== WasmSym::indirectFunctionTable
)
770 LLVM_DEBUG(dbgs() << "import: " << sym
->getName() << "\n");
771 out
.importSec
->addImport(sym
);
775 void Writer::calculateExports() {
776 if (config
->relocatable
)
779 if (!config
->relocatable
&& config
->memoryExport
.has_value()) {
780 out
.exportSec
->exports
.push_back(
781 WasmExport
{*config
->memoryExport
, WASM_EXTERNAL_MEMORY
, 0});
784 unsigned globalIndex
=
785 out
.importSec
->getNumImportedGlobals() + out
.globalSec
->numGlobals();
787 for (Symbol
*sym
: symtab
->symbols()) {
788 if (!sym
->isExported())
792 if (isa
<SharedFunctionSymbol
>(sym
) || sym
->isShared())
795 StringRef name
= sym
->getName();
796 LLVM_DEBUG(dbgs() << "Export: " << name
<< "\n");
798 if (auto *f
= dyn_cast
<DefinedFunction
>(sym
)) {
799 if (std::optional
<StringRef
> exportName
= f
->function
->getExportName()) {
802 export_
= {name
, WASM_EXTERNAL_FUNCTION
, f
->getExportedFunctionIndex()};
803 } else if (auto *g
= dyn_cast
<DefinedGlobal
>(sym
)) {
804 if (g
->getGlobalType()->Mutable
&& !g
->getFile() && !g
->forceExport
) {
805 // Avoid exporting mutable globals are linker synthesized (e.g.
806 // __stack_pointer or __tls_base) unless they are explicitly exported
807 // from the command line.
808 // Without this check `--export-all` would cause any program using the
809 // stack pointer to export a mutable global even if none of the input
810 // files were built with the `mutable-globals` feature.
813 export_
= {name
, WASM_EXTERNAL_GLOBAL
, g
->getGlobalIndex()};
814 } else if (auto *t
= dyn_cast
<DefinedTag
>(sym
)) {
815 export_
= {name
, WASM_EXTERNAL_TAG
, t
->getTagIndex()};
816 } else if (auto *d
= dyn_cast
<DefinedData
>(sym
)) {
817 out
.globalSec
->dataAddressGlobals
.push_back(d
);
818 export_
= {name
, WASM_EXTERNAL_GLOBAL
, globalIndex
++};
820 auto *t
= cast
<DefinedTable
>(sym
);
821 export_
= {name
, WASM_EXTERNAL_TABLE
, t
->getTableNumber()};
824 out
.exportSec
->exports
.push_back(export_
);
825 out
.exportSec
->exportedSymbols
.push_back(sym
);
829 void Writer::populateSymtab() {
830 if (!config
->relocatable
&& !config
->emitRelocs
)
833 for (Symbol
*sym
: symtab
->symbols())
834 if (sym
->isUsedInRegularObj
&& sym
->isLive() && !sym
->isShared())
835 out
.linkingSec
->addToSymtab(sym
);
837 for (ObjFile
*file
: ctx
.objectFiles
) {
838 LLVM_DEBUG(dbgs() << "Local symtab entries: " << file
->getName() << "\n");
839 for (Symbol
*sym
: file
->getSymbols())
840 if (sym
->isLocal() && !isa
<SectionSymbol
>(sym
) && sym
->isLive())
841 out
.linkingSec
->addToSymtab(sym
);
845 void Writer::calculateTypes() {
846 // The output type section is the union of the following sets:
847 // 1. Any signature used in the TYPE relocation
848 // 2. The signatures of all imported functions
849 // 3. The signatures of all defined functions
850 // 4. The signatures of all imported tags
851 // 5. The signatures of all defined tags
853 for (ObjFile
*file
: ctx
.objectFiles
) {
854 ArrayRef
<WasmSignature
> types
= file
->getWasmObj()->types();
855 for (uint32_t i
= 0; i
< types
.size(); i
++)
856 if (file
->typeIsUsed
[i
])
857 file
->typeMap
[i
] = out
.typeSec
->registerType(types
[i
]);
860 for (const Symbol
*sym
: out
.importSec
->importedSymbols
) {
861 if (auto *f
= dyn_cast
<FunctionSymbol
>(sym
))
862 out
.typeSec
->registerType(*f
->signature
);
863 else if (auto *t
= dyn_cast
<TagSymbol
>(sym
))
864 out
.typeSec
->registerType(*t
->signature
);
867 for (const InputFunction
*f
: out
.functionSec
->inputFunctions
)
868 out
.typeSec
->registerType(f
->signature
);
870 for (const InputTag
*t
: out
.tagSec
->inputTags
)
871 out
.typeSec
->registerType(t
->signature
);
874 // In a command-style link, create a wrapper for each exported symbol
875 // which calls the constructors and destructors.
876 void Writer::createCommandExportWrappers() {
877 // This logic doesn't currently support Emscripten-style PIC mode.
880 // If there are no ctors and there's no libc `__wasm_call_dtors` to
881 // call, don't wrap the exports.
882 if (initFunctions
.empty() && WasmSym::callDtors
== nullptr)
885 std::vector
<DefinedFunction
*> toWrap
;
887 for (Symbol
*sym
: symtab
->symbols())
888 if (sym
->isExported())
889 if (auto *f
= dyn_cast
<DefinedFunction
>(sym
))
892 for (auto *f
: toWrap
) {
893 auto funcNameStr
= (f
->getName() + ".command_export").str();
894 commandExportWrapperNames
.push_back(funcNameStr
);
895 const std::string
&funcName
= commandExportWrapperNames
.back();
897 auto func
= make
<SyntheticFunction
>(*f
->getSignature(), funcName
);
898 if (f
->function
->getExportName())
899 func
->setExportName(f
->function
->getExportName()->str());
901 func
->setExportName(f
->getName().str());
903 DefinedFunction
*def
=
904 symtab
->addSyntheticFunction(funcName
, f
->flags
, func
);
907 def
->flags
|= WASM_SYMBOL_EXPORTED
;
908 def
->flags
&= ~WASM_SYMBOL_VISIBILITY_HIDDEN
;
909 def
->forceExport
= f
->forceExport
;
911 f
->flags
|= WASM_SYMBOL_VISIBILITY_HIDDEN
;
912 f
->flags
&= ~WASM_SYMBOL_EXPORTED
;
913 f
->forceExport
= false;
915 out
.functionSec
->addFunction(func
);
917 createCommandExportWrapper(f
->getFunctionIndex(), def
);
921 static void finalizeIndirectFunctionTable() {
922 if (!WasmSym::indirectFunctionTable
)
925 if (shouldImport(WasmSym::indirectFunctionTable
) &&
926 !WasmSym::indirectFunctionTable
->hasTableNumber()) {
927 // Processing -Bsymbolic relocations resulted in a late requirement that the
928 // indirect function table be present, and we are running in --import-table
929 // mode. Add the table now to the imports section. Otherwise it will be
930 // added to the tables section later in assignIndexes.
931 out
.importSec
->addImport(WasmSym::indirectFunctionTable
);
934 uint32_t tableSize
= config
->tableBase
+ out
.elemSec
->numEntries();
935 WasmLimits limits
= {0, tableSize
, 0};
936 if (WasmSym::indirectFunctionTable
->isDefined() && !config
->growableTable
) {
937 limits
.Flags
|= WASM_LIMITS_FLAG_HAS_MAX
;
938 limits
.Maximum
= limits
.Minimum
;
940 if (config
->is64
.value_or(false))
941 limits
.Flags
|= WASM_LIMITS_FLAG_IS_64
;
942 WasmSym::indirectFunctionTable
->setLimits(limits
);
945 static void scanRelocations() {
946 for (ObjFile
*file
: ctx
.objectFiles
) {
947 LLVM_DEBUG(dbgs() << "scanRelocations: " << file
->getName() << "\n");
948 for (InputChunk
*chunk
: file
->functions
)
949 scanRelocations(chunk
);
950 for (InputChunk
*chunk
: file
->segments
)
951 scanRelocations(chunk
);
952 for (auto &p
: file
->customSections
)
957 void Writer::assignIndexes() {
958 // Seal the import section, since other index spaces such as function and
959 // global are effected by the number of imports.
960 out
.importSec
->seal();
962 for (InputFunction
*func
: ctx
.syntheticFunctions
)
963 out
.functionSec
->addFunction(func
);
965 for (ObjFile
*file
: ctx
.objectFiles
) {
966 LLVM_DEBUG(dbgs() << "Functions: " << file
->getName() << "\n");
967 for (InputFunction
*func
: file
->functions
)
968 out
.functionSec
->addFunction(func
);
971 for (InputGlobal
*global
: ctx
.syntheticGlobals
)
972 out
.globalSec
->addGlobal(global
);
974 for (ObjFile
*file
: ctx
.objectFiles
) {
975 LLVM_DEBUG(dbgs() << "Globals: " << file
->getName() << "\n");
976 for (InputGlobal
*global
: file
->globals
)
977 out
.globalSec
->addGlobal(global
);
980 for (ObjFile
*file
: ctx
.objectFiles
) {
981 LLVM_DEBUG(dbgs() << "Tags: " << file
->getName() << "\n");
982 for (InputTag
*tag
: file
->tags
)
983 out
.tagSec
->addTag(tag
);
986 for (ObjFile
*file
: ctx
.objectFiles
) {
987 LLVM_DEBUG(dbgs() << "Tables: " << file
->getName() << "\n");
988 for (InputTable
*table
: file
->tables
)
989 out
.tableSec
->addTable(table
);
992 for (InputTable
*table
: ctx
.syntheticTables
)
993 out
.tableSec
->addTable(table
);
995 out
.globalSec
->assignIndexes();
996 out
.tableSec
->assignIndexes();
999 static StringRef
getOutputDataSegmentName(const InputChunk
&seg
) {
1000 // We always merge .tbss and .tdata into a single TLS segment so all TLS
1001 // symbols are be relative to single __tls_base.
1004 if (!config
->mergeDataSegments
)
1006 if (seg
.name
.starts_with(".text."))
1008 if (seg
.name
.starts_with(".data."))
1010 if (seg
.name
.starts_with(".bss."))
1012 if (seg
.name
.starts_with(".rodata."))
1017 OutputSegment
*Writer::createOutputSegment(StringRef name
) {
1018 LLVM_DEBUG(dbgs() << "new segment: " << name
<< "\n");
1019 OutputSegment
*s
= make
<OutputSegment
>(name
);
1020 if (config
->sharedMemory
)
1021 s
->initFlags
= WASM_DATA_SEGMENT_IS_PASSIVE
;
1022 if (!config
->relocatable
&& name
.starts_with(".bss"))
1024 segments
.push_back(s
);
1028 void Writer::createOutputSegments() {
1029 for (ObjFile
*file
: ctx
.objectFiles
) {
1030 for (InputChunk
*segment
: file
->segments
) {
1033 StringRef name
= getOutputDataSegmentName(*segment
);
1034 OutputSegment
*s
= nullptr;
1035 // When running in relocatable mode we can't merge segments that are part
1036 // of comdat groups since the ultimate linker needs to be able exclude or
1037 // include them individually.
1038 if (config
->relocatable
&& !segment
->getComdatName().empty()) {
1039 s
= createOutputSegment(name
);
1041 if (segmentMap
.count(name
) == 0)
1042 segmentMap
[name
] = createOutputSegment(name
);
1043 s
= segmentMap
[name
];
1045 s
->addInputSegment(segment
);
1049 // Sort segments by type, placing .bss last
1050 std::stable_sort(segments
.begin(), segments
.end(),
1051 [](const OutputSegment
*a
, const OutputSegment
*b
) {
1052 auto order
= [](StringRef name
) {
1053 return StringSwitch
<int>(name
)
1054 .StartsWith(".tdata", 0)
1055 .StartsWith(".rodata", 1)
1056 .StartsWith(".data", 2)
1057 .StartsWith(".bss", 4)
1060 return order(a
->name
) < order(b
->name
);
1063 for (size_t i
= 0; i
< segments
.size(); ++i
)
1064 segments
[i
]->index
= i
;
1066 // Merge MergeInputSections into a single MergeSyntheticSection.
1067 LLVM_DEBUG(dbgs() << "-- finalize input semgments\n");
1068 for (OutputSegment
*seg
: segments
)
1069 seg
->finalizeInputSegments();
1072 void Writer::combineOutputSegments() {
1073 // With PIC code we currently only support a single active data segment since
1074 // we only have a single __memory_base to use as our base address. This pass
1075 // combines all data segments into a single .data segment.
1076 // This restriction does not apply when the extended const extension is
1077 // available: https://github.com/WebAssembly/extended-const
1078 assert(!config
->extendedConst
);
1079 assert(ctx
.isPic
&& !config
->sharedMemory
);
1080 if (segments
.size() <= 1)
1082 OutputSegment
*combined
= make
<OutputSegment
>(".data");
1083 combined
->startVA
= segments
[0]->startVA
;
1084 for (OutputSegment
*s
: segments
) {
1086 for (InputChunk
*inSeg
: s
->inputSegments
) {
1088 inSeg
->alignment
= std::max(inSeg
->alignment
, s
->alignment
);
1091 uint64_t oldVA
= inSeg
->getVA();
1093 combined
->addInputSegment(inSeg
);
1095 uint64_t newVA
= inSeg
->getVA();
1096 LLVM_DEBUG(dbgs() << "added input segment. name=" << inSeg
->name
1097 << " oldVA=" << oldVA
<< " newVA=" << newVA
<< "\n");
1098 assert(oldVA
== newVA
);
1103 segments
= {combined
};
1106 static void createFunction(DefinedFunction
*func
, StringRef bodyContent
) {
1107 std::string functionBody
;
1109 raw_string_ostream
os(functionBody
);
1110 writeUleb128(os
, bodyContent
.size(), "function size");
1113 ArrayRef
<uint8_t> body
= arrayRefFromStringRef(saver().save(functionBody
));
1114 cast
<SyntheticFunction
>(func
->function
)->setBody(body
);
1117 bool Writer::needsPassiveInitialization(const OutputSegment
*segment
) {
1118 // If bulk memory features is supported then we can perform bss initialization
1119 // (via memory.fill) during `__wasm_init_memory`.
1120 if (config
->memoryImport
.has_value() && !segment
->requiredInBinary())
1122 return segment
->initFlags
& WASM_DATA_SEGMENT_IS_PASSIVE
;
1125 bool Writer::hasPassiveInitializedSegments() {
1126 return llvm::any_of(segments
, [this](const OutputSegment
*s
) {
1127 return this->needsPassiveInitialization(s
);
1131 void Writer::createSyntheticInitFunctions() {
1132 if (config
->relocatable
)
1135 static WasmSignature nullSignature
= {{}, {}};
1137 createApplyDataRelocationsFunction();
1139 // Passive segments are used to avoid memory being reinitialized on each
1140 // thread's instantiation. These passive segments are initialized and
1141 // dropped in __wasm_init_memory, which is registered as the start function
1142 // We also initialize bss segments (using memory.fill) as part of this
1144 if (hasPassiveInitializedSegments()) {
1145 WasmSym::initMemory
= symtab
->addSyntheticFunction(
1146 "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN
,
1147 make
<SyntheticFunction
>(nullSignature
, "__wasm_init_memory"));
1148 WasmSym::initMemory
->markLive();
1149 if (config
->sharedMemory
) {
1150 // This global is assigned during __wasm_init_memory in the shared memory
1152 WasmSym::tlsBase
->markLive();
1156 if (config
->sharedMemory
) {
1157 if (out
.globalSec
->needsTLSRelocations()) {
1158 WasmSym::applyGlobalTLSRelocs
= symtab
->addSyntheticFunction(
1159 "__wasm_apply_global_tls_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN
,
1160 make
<SyntheticFunction
>(nullSignature
,
1161 "__wasm_apply_global_tls_relocs"));
1162 WasmSym::applyGlobalTLSRelocs
->markLive();
1163 // TLS relocations depend on the __tls_base symbols
1164 WasmSym::tlsBase
->markLive();
1167 auto hasTLSRelocs
= [](const OutputSegment
*segment
) {
1168 if (segment
->isTLS())
1169 for (const auto* is
: segment
->inputSegments
)
1170 if (is
->getRelocations().size())
1174 if (llvm::any_of(segments
, hasTLSRelocs
)) {
1175 WasmSym::applyTLSRelocs
= symtab
->addSyntheticFunction(
1176 "__wasm_apply_tls_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN
,
1177 make
<SyntheticFunction
>(nullSignature
,
1178 "__wasm_apply_tls_relocs"));
1179 WasmSym::applyTLSRelocs
->markLive();
1183 if (ctx
.isPic
&& out
.globalSec
->needsRelocations()) {
1184 WasmSym::applyGlobalRelocs
= symtab
->addSyntheticFunction(
1185 "__wasm_apply_global_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN
,
1186 make
<SyntheticFunction
>(nullSignature
, "__wasm_apply_global_relocs"));
1187 WasmSym::applyGlobalRelocs
->markLive();
1190 // If there is only one start function we can just use that function
1191 // itself as the Wasm start function, otherwise we need to synthesize
1192 // a new function to call them in sequence.
1193 if (WasmSym::applyGlobalRelocs
&& WasmSym::initMemory
) {
1194 WasmSym::startFunction
= symtab
->addSyntheticFunction(
1195 "__wasm_start", WASM_SYMBOL_VISIBILITY_HIDDEN
,
1196 make
<SyntheticFunction
>(nullSignature
, "__wasm_start"));
1197 WasmSym::startFunction
->markLive();
1201 void Writer::createInitMemoryFunction() {
1202 LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n");
1203 assert(WasmSym::initMemory
);
1204 assert(hasPassiveInitializedSegments());
1205 uint64_t flagAddress
;
1206 if (config
->sharedMemory
) {
1207 assert(WasmSym::initMemoryFlag
);
1208 flagAddress
= WasmSym::initMemoryFlag
->getVA();
1210 bool is64
= config
->is64
.value_or(false);
1211 std::string bodyContent
;
1213 raw_string_ostream
os(bodyContent
);
1214 // Initialize memory in a thread-safe manner. The thread that successfully
1215 // increments the flag from 0 to 1 is responsible for performing the memory
1216 // initialization. Other threads go sleep on the flag until the first thread
1217 // finishing initializing memory, increments the flag to 2, and wakes all
1218 // the other threads. Once the flag has been set to 2, subsequently started
1219 // threads will skip the sleep. All threads unconditionally drop their
1220 // passive data segments once memory has been initialized. The generated
1221 // code is as follows:
1223 // (func $__wasm_init_memory
1227 // (br_table $init $wait $drop
1228 // (i32.atomic.rmw.cmpxchg align=2 offset=0
1229 // (i32.const $__init_memory_flag)
1235 // ( ... initialize data segments ... )
1236 // (i32.atomic.store align=2 offset=0
1237 // (i32.const $__init_memory_flag)
1241 // (i32.atomic.notify align=2 offset=0
1242 // (i32.const $__init_memory_flag)
1249 // (i32.atomic.wait align=2 offset=0
1250 // (i32.const $__init_memory_flag)
1256 // ( ... drop data segments ... )
1259 // When we are building with PIC, calculate the flag location using:
1261 // (global.get $__memory_base)
1262 // (i32.const $__init_memory_flag)
1265 auto writeGetFlagAddress
= [&]() {
1267 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1268 writeUleb128(os
, 0, "local 0");
1270 writePtrConst(os
, flagAddress
, is64
, "flag address");
1274 if (config
->sharedMemory
) {
1275 // With PIC code we cache the flag address in local 0
1277 writeUleb128(os
, 1, "num local decls");
1278 writeUleb128(os
, 2, "local count");
1279 writeU8(os
, is64
? WASM_TYPE_I64
: WASM_TYPE_I32
, "address type");
1280 writeU8(os
, WASM_OPCODE_GLOBAL_GET
, "GLOBAL_GET");
1281 writeUleb128(os
, WasmSym::memoryBase
->getGlobalIndex(), "memory_base");
1282 writePtrConst(os
, flagAddress
, is64
, "flag address");
1283 writeU8(os
, is64
? WASM_OPCODE_I64_ADD
: WASM_OPCODE_I32_ADD
, "add");
1284 writeU8(os
, WASM_OPCODE_LOCAL_SET
, "local.set");
1285 writeUleb128(os
, 0, "local 0");
1287 writeUleb128(os
, 0, "num locals");
1290 // Set up destination blocks
1291 writeU8(os
, WASM_OPCODE_BLOCK
, "block $drop");
1292 writeU8(os
, WASM_TYPE_NORESULT
, "block type");
1293 writeU8(os
, WASM_OPCODE_BLOCK
, "block $wait");
1294 writeU8(os
, WASM_TYPE_NORESULT
, "block type");
1295 writeU8(os
, WASM_OPCODE_BLOCK
, "block $init");
1296 writeU8(os
, WASM_TYPE_NORESULT
, "block type");
1298 // Atomically check whether we win the race.
1299 writeGetFlagAddress();
1300 writeI32Const(os
, 0, "expected flag value");
1301 writeI32Const(os
, 1, "new flag value");
1302 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1303 writeUleb128(os
, WASM_OPCODE_I32_RMW_CMPXCHG
, "i32.atomic.rmw.cmpxchg");
1304 writeMemArg(os
, 2, 0);
1306 // Based on the value, decide what to do next.
1307 writeU8(os
, WASM_OPCODE_BR_TABLE
, "br_table");
1308 writeUleb128(os
, 2, "label vector length");
1309 writeUleb128(os
, 0, "label $init");
1310 writeUleb128(os
, 1, "label $wait");
1311 writeUleb128(os
, 2, "default label $drop");
1313 // Initialize passive data segments
1314 writeU8(os
, WASM_OPCODE_END
, "end $init");
1316 writeUleb128(os
, 0, "num local decls");
1319 for (const OutputSegment
*s
: segments
) {
1320 if (needsPassiveInitialization(s
)) {
1321 // For passive BSS segments we can simple issue a memory.fill(0).
1322 // For non-BSS segments we do a memory.init. Both these
1323 // instructions take as their first argument the destination
1325 writePtrConst(os
, s
->startVA
, is64
, "destination address");
1327 writeU8(os
, WASM_OPCODE_GLOBAL_GET
, "GLOBAL_GET");
1328 writeUleb128(os
, WasmSym::memoryBase
->getGlobalIndex(),
1330 writeU8(os
, is64
? WASM_OPCODE_I64_ADD
: WASM_OPCODE_I32_ADD
,
1334 // When we initialize the TLS segment we also set the `__tls_base`
1335 // global. This allows the runtime to use this static copy of the
1336 // TLS data for the first/main thread.
1337 if (config
->sharedMemory
&& s
->isTLS()) {
1339 // Cache the result of the addionion in local 0
1340 writeU8(os
, WASM_OPCODE_LOCAL_TEE
, "local.tee");
1341 writeUleb128(os
, 1, "local 1");
1343 writePtrConst(os
, s
->startVA
, is64
, "destination address");
1345 writeU8(os
, WASM_OPCODE_GLOBAL_SET
, "GLOBAL_SET");
1346 writeUleb128(os
, WasmSym::tlsBase
->getGlobalIndex(),
1349 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.tee");
1350 writeUleb128(os
, 1, "local 1");
1355 writeI32Const(os
, 0, "fill value");
1356 writePtrConst(os
, s
->size
, is64
, "memory region size");
1357 writeU8(os
, WASM_OPCODE_MISC_PREFIX
, "bulk-memory prefix");
1358 writeUleb128(os
, WASM_OPCODE_MEMORY_FILL
, "memory.fill");
1359 writeU8(os
, 0, "memory index immediate");
1361 writeI32Const(os
, 0, "source segment offset");
1362 writeI32Const(os
, s
->size
, "memory region size");
1363 writeU8(os
, WASM_OPCODE_MISC_PREFIX
, "bulk-memory prefix");
1364 writeUleb128(os
, WASM_OPCODE_MEMORY_INIT
, "memory.init");
1365 writeUleb128(os
, s
->index
, "segment index immediate");
1366 writeU8(os
, 0, "memory index immediate");
1371 if (config
->sharedMemory
) {
1372 // Set flag to 2 to mark end of initialization
1373 writeGetFlagAddress();
1374 writeI32Const(os
, 2, "flag value");
1375 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1376 writeUleb128(os
, WASM_OPCODE_I32_ATOMIC_STORE
, "i32.atomic.store");
1377 writeMemArg(os
, 2, 0);
1379 // Notify any waiters that memory initialization is complete
1380 writeGetFlagAddress();
1381 writeI32Const(os
, -1, "number of waiters");
1382 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1383 writeUleb128(os
, WASM_OPCODE_ATOMIC_NOTIFY
, "atomic.notify");
1384 writeMemArg(os
, 2, 0);
1385 writeU8(os
, WASM_OPCODE_DROP
, "drop");
1387 // Branch to drop the segments
1388 writeU8(os
, WASM_OPCODE_BR
, "br");
1389 writeUleb128(os
, 1, "label $drop");
1391 // Wait for the winning thread to initialize memory
1392 writeU8(os
, WASM_OPCODE_END
, "end $wait");
1393 writeGetFlagAddress();
1394 writeI32Const(os
, 1, "expected flag value");
1395 writeI64Const(os
, -1, "timeout");
1397 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1398 writeUleb128(os
, WASM_OPCODE_I32_ATOMIC_WAIT
, "i32.atomic.wait");
1399 writeMemArg(os
, 2, 0);
1400 writeU8(os
, WASM_OPCODE_DROP
, "drop");
1402 // Unconditionally drop passive data segments
1403 writeU8(os
, WASM_OPCODE_END
, "end $drop");
1406 for (const OutputSegment
*s
: segments
) {
1407 if (needsPassiveInitialization(s
) && !s
->isBss
) {
1408 // The TLS region should not be dropped since its is needed
1409 // during the initialization of each thread (__wasm_init_tls).
1410 if (config
->sharedMemory
&& s
->isTLS())
1412 // data.drop instruction
1413 writeU8(os
, WASM_OPCODE_MISC_PREFIX
, "bulk-memory prefix");
1414 writeUleb128(os
, WASM_OPCODE_DATA_DROP
, "data.drop");
1415 writeUleb128(os
, s
->index
, "segment index immediate");
1420 writeU8(os
, WASM_OPCODE_END
, "END");
1423 createFunction(WasmSym::initMemory
, bodyContent
);
1426 void Writer::createStartFunction() {
1427 // If the start function exists when we have more than one function to call.
1428 if (WasmSym::initMemory
&& WasmSym::applyGlobalRelocs
) {
1429 assert(WasmSym::startFunction
);
1430 std::string bodyContent
;
1432 raw_string_ostream
os(bodyContent
);
1433 writeUleb128(os
, 0, "num locals");
1434 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1435 writeUleb128(os
, WasmSym::applyGlobalRelocs
->getFunctionIndex(),
1437 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1438 writeUleb128(os
, WasmSym::initMemory
->getFunctionIndex(),
1440 writeU8(os
, WASM_OPCODE_END
, "END");
1442 createFunction(WasmSym::startFunction
, bodyContent
);
1443 } else if (WasmSym::initMemory
) {
1444 WasmSym::startFunction
= WasmSym::initMemory
;
1445 } else if (WasmSym::applyGlobalRelocs
) {
1446 WasmSym::startFunction
= WasmSym::applyGlobalRelocs
;
1450 // For -shared (PIC) output, we create create a synthetic function which will
1451 // apply any relocations to the data segments on startup. This function is
1452 // called `__wasm_apply_data_relocs` and is expected to be called before
1453 // any user code (i.e. before `__wasm_call_ctors`).
1454 void Writer::createApplyDataRelocationsFunction() {
1455 LLVM_DEBUG(dbgs() << "createApplyDataRelocationsFunction\n");
1456 // First write the body's contents to a string.
1457 std::string bodyContent
;
1459 raw_string_ostream
os(bodyContent
);
1460 writeUleb128(os
, 0, "num locals");
1461 bool generated
= false;
1462 for (const OutputSegment
*seg
: segments
)
1463 if (!config
->sharedMemory
|| !seg
->isTLS())
1464 for (const InputChunk
*inSeg
: seg
->inputSegments
)
1465 generated
|= inSeg
->generateRelocationCode(os
);
1468 LLVM_DEBUG(dbgs() << "skipping empty __wasm_apply_data_relocs\n");
1471 writeU8(os
, WASM_OPCODE_END
, "END");
1474 // __wasm_apply_data_relocs
1475 // Function that applies relocations to data segment post-instantiation.
1476 static WasmSignature nullSignature
= {{}, {}};
1477 auto def
= symtab
->addSyntheticFunction(
1478 "__wasm_apply_data_relocs",
1479 WASM_SYMBOL_VISIBILITY_DEFAULT
| WASM_SYMBOL_EXPORTED
,
1480 make
<SyntheticFunction
>(nullSignature
, "__wasm_apply_data_relocs"));
1483 createFunction(def
, bodyContent
);
1486 void Writer::createApplyTLSRelocationsFunction() {
1487 LLVM_DEBUG(dbgs() << "createApplyTLSRelocationsFunction\n");
1488 std::string bodyContent
;
1490 raw_string_ostream
os(bodyContent
);
1491 writeUleb128(os
, 0, "num locals");
1492 for (const OutputSegment
*seg
: segments
)
1494 for (const InputChunk
*inSeg
: seg
->inputSegments
)
1495 inSeg
->generateRelocationCode(os
);
1497 writeU8(os
, WASM_OPCODE_END
, "END");
1500 createFunction(WasmSym::applyTLSRelocs
, bodyContent
);
1503 // Similar to createApplyDataRelocationsFunction but generates relocation code
1504 // for WebAssembly globals. Because these globals are not shared between threads
1505 // these relocation need to run on every thread.
1506 void Writer::createApplyGlobalRelocationsFunction() {
1507 // First write the body's contents to a string.
1508 std::string bodyContent
;
1510 raw_string_ostream
os(bodyContent
);
1511 writeUleb128(os
, 0, "num locals");
1512 out
.globalSec
->generateRelocationCode(os
, false);
1513 writeU8(os
, WASM_OPCODE_END
, "END");
1516 createFunction(WasmSym::applyGlobalRelocs
, bodyContent
);
1519 // Similar to createApplyGlobalRelocationsFunction but for
1520 // TLS symbols. This cannot be run during the start function
1521 // but must be delayed until __wasm_init_tls is called.
1522 void Writer::createApplyGlobalTLSRelocationsFunction() {
1523 // First write the body's contents to a string.
1524 std::string bodyContent
;
1526 raw_string_ostream
os(bodyContent
);
1527 writeUleb128(os
, 0, "num locals");
1528 out
.globalSec
->generateRelocationCode(os
, true);
1529 writeU8(os
, WASM_OPCODE_END
, "END");
1532 createFunction(WasmSym::applyGlobalTLSRelocs
, bodyContent
);
1535 // Create synthetic "__wasm_call_ctors" function based on ctor functions
1537 void Writer::createCallCtorsFunction() {
1538 // If __wasm_call_ctors isn't referenced, there aren't any ctors, don't
1539 // define the `__wasm_call_ctors` function.
1540 if (!WasmSym::callCtors
->isLive() && initFunctions
.empty())
1543 // First write the body's contents to a string.
1544 std::string bodyContent
;
1546 raw_string_ostream
os(bodyContent
);
1547 writeUleb128(os
, 0, "num locals");
1549 // Call constructors
1550 for (const WasmInitEntry
&f
: initFunctions
) {
1551 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1552 writeUleb128(os
, f
.sym
->getFunctionIndex(), "function index");
1553 for (size_t i
= 0; i
< f
.sym
->signature
->Returns
.size(); i
++) {
1554 writeU8(os
, WASM_OPCODE_DROP
, "DROP");
1558 writeU8(os
, WASM_OPCODE_END
, "END");
1561 createFunction(WasmSym::callCtors
, bodyContent
);
1564 // Create a wrapper around a function export which calls the
1565 // static constructors and destructors.
1566 void Writer::createCommandExportWrapper(uint32_t functionIndex
,
1567 DefinedFunction
*f
) {
1568 // First write the body's contents to a string.
1569 std::string bodyContent
;
1571 raw_string_ostream
os(bodyContent
);
1572 writeUleb128(os
, 0, "num locals");
1574 // Call `__wasm_call_ctors` which call static constructors (and
1575 // applies any runtime relocations in Emscripten-style PIC mode)
1576 if (WasmSym::callCtors
->isLive()) {
1577 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1578 writeUleb128(os
, WasmSym::callCtors
->getFunctionIndex(),
1582 // Call the user's code, leaving any return values on the operand stack.
1583 for (size_t i
= 0; i
< f
->signature
->Params
.size(); ++i
) {
1584 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1585 writeUleb128(os
, i
, "local index");
1587 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1588 writeUleb128(os
, functionIndex
, "function index");
1590 // Call the function that calls the destructors.
1591 if (DefinedFunction
*callDtors
= WasmSym::callDtors
) {
1592 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1593 writeUleb128(os
, callDtors
->getFunctionIndex(), "function index");
1596 // End the function, returning the return values from the user's code.
1597 writeU8(os
, WASM_OPCODE_END
, "END");
1600 createFunction(f
, bodyContent
);
1603 void Writer::createInitTLSFunction() {
1604 std::string bodyContent
;
1606 raw_string_ostream
os(bodyContent
);
1608 OutputSegment
*tlsSeg
= nullptr;
1609 for (auto *seg
: segments
) {
1610 if (seg
->name
== ".tdata") {
1616 writeUleb128(os
, 0, "num locals");
1618 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1619 writeUleb128(os
, 0, "local index");
1621 writeU8(os
, WASM_OPCODE_GLOBAL_SET
, "global.set");
1622 writeUleb128(os
, WasmSym::tlsBase
->getGlobalIndex(), "global index");
1624 // FIXME(wvo): this local needs to be I64 in wasm64, or we need an extend op.
1625 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1626 writeUleb128(os
, 0, "local index");
1628 writeI32Const(os
, 0, "segment offset");
1630 writeI32Const(os
, tlsSeg
->size
, "memory region size");
1632 writeU8(os
, WASM_OPCODE_MISC_PREFIX
, "bulk-memory prefix");
1633 writeUleb128(os
, WASM_OPCODE_MEMORY_INIT
, "MEMORY.INIT");
1634 writeUleb128(os
, tlsSeg
->index
, "segment index immediate");
1635 writeU8(os
, 0, "memory index immediate");
1638 if (WasmSym::applyTLSRelocs
) {
1639 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1640 writeUleb128(os
, WasmSym::applyTLSRelocs
->getFunctionIndex(),
1644 if (WasmSym::applyGlobalTLSRelocs
) {
1645 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1646 writeUleb128(os
, WasmSym::applyGlobalTLSRelocs
->getFunctionIndex(),
1649 writeU8(os
, WASM_OPCODE_END
, "end function");
1652 createFunction(WasmSym::initTLS
, bodyContent
);
1655 // Populate InitFunctions vector with init functions from all input objects.
1656 // This is then used either when creating the output linking section or to
1657 // synthesize the "__wasm_call_ctors" function.
1658 void Writer::calculateInitFunctions() {
1659 if (!config
->relocatable
&& !WasmSym::callCtors
->isLive())
1662 for (ObjFile
*file
: ctx
.objectFiles
) {
1663 const WasmLinkingData
&l
= file
->getWasmObj()->linkingData();
1664 for (const WasmInitFunc
&f
: l
.InitFunctions
) {
1665 FunctionSymbol
*sym
= file
->getFunctionSymbol(f
.Symbol
);
1666 // comdat exclusions can cause init functions be discarded.
1667 if (sym
->isDiscarded() || !sym
->isLive())
1669 if (sym
->signature
->Params
.size() != 0)
1670 error("constructor functions cannot take arguments: " + toString(*sym
));
1671 LLVM_DEBUG(dbgs() << "initFunctions: " << toString(*sym
) << "\n");
1672 initFunctions
.emplace_back(WasmInitEntry
{sym
, f
.Priority
});
1676 // Sort in order of priority (lowest first) so that they are called
1677 // in the correct order.
1678 llvm::stable_sort(initFunctions
,
1679 [](const WasmInitEntry
&l
, const WasmInitEntry
&r
) {
1680 return l
.priority
< r
.priority
;
1684 void Writer::createSyntheticSections() {
1685 out
.dylinkSec
= make
<DylinkSection
>();
1686 out
.typeSec
= make
<TypeSection
>();
1687 out
.importSec
= make
<ImportSection
>();
1688 out
.functionSec
= make
<FunctionSection
>();
1689 out
.tableSec
= make
<TableSection
>();
1690 out
.memorySec
= make
<MemorySection
>();
1691 out
.tagSec
= make
<TagSection
>();
1692 out
.globalSec
= make
<GlobalSection
>();
1693 out
.exportSec
= make
<ExportSection
>();
1694 out
.startSec
= make
<StartSection
>();
1695 out
.elemSec
= make
<ElemSection
>();
1696 out
.producersSec
= make
<ProducersSection
>();
1697 out
.targetFeaturesSec
= make
<TargetFeaturesSection
>();
1698 out
.buildIdSec
= make
<BuildIdSection
>();
1701 void Writer::createSyntheticSectionsPostLayout() {
1702 out
.dataCountSec
= make
<DataCountSection
>(segments
);
1703 out
.linkingSec
= make
<LinkingSection
>(initFunctions
, segments
);
1704 out
.nameSec
= make
<NameSection
>(segments
);
1707 void Writer::run() {
1708 // For PIC code the table base is assigned dynamically by the loader.
1709 // For non-PIC, we start at 1 so that accessing table index 0 always traps.
1710 if (!ctx
.isPic
&& WasmSym::definedTableBase
)
1711 WasmSym::definedTableBase
->setVA(config
->tableBase
);
1713 log("-- createOutputSegments");
1714 createOutputSegments();
1715 log("-- createSyntheticSections");
1716 createSyntheticSections();
1717 log("-- layoutMemory");
1720 if (!config
->relocatable
) {
1721 // Create linker synthesized __start_SECNAME/__stop_SECNAME symbols
1722 // This has to be done after memory layout is performed.
1723 for (const OutputSegment
*seg
: segments
) {
1724 addStartStopSymbols(seg
);
1728 for (auto &pair
: config
->exportedSymbols
) {
1729 Symbol
*sym
= symtab
->find(pair
.first());
1730 if (sym
&& sym
->isDefined())
1731 sym
->forceExport
= true;
1734 // Delay reporting errors about explicit exports until after
1735 // addStartStopSymbols which can create optional symbols.
1736 for (auto &name
: config
->requiredExports
) {
1737 Symbol
*sym
= symtab
->find(name
);
1738 if (!sym
|| !sym
->isDefined()) {
1739 if (config
->unresolvedSymbols
== UnresolvedPolicy::ReportError
)
1740 error(Twine("symbol exported via --export not found: ") + name
);
1741 if (config
->unresolvedSymbols
== UnresolvedPolicy::Warn
)
1742 warn(Twine("symbol exported via --export not found: ") + name
);
1746 log("-- populateTargetFeatures");
1747 populateTargetFeatures();
1749 // When outputting PIC code each segment lives at at fixes offset from the
1750 // `__memory_base` import. Unless we support the extended const expression we
1751 // can't do addition inside the constant expression, so we much combine the
1752 // segments into a single one that can live at `__memory_base`.
1753 if (ctx
.isPic
&& !config
->extendedConst
&& !config
->sharedMemory
) {
1754 // In shared memory mode all data segments are passive and initialized
1755 // via __wasm_init_memory.
1756 log("-- combineOutputSegments");
1757 combineOutputSegments();
1760 log("-- createSyntheticSectionsPostLayout");
1761 createSyntheticSectionsPostLayout();
1762 log("-- populateProducers");
1763 populateProducers();
1764 log("-- calculateImports");
1766 log("-- scanRelocations");
1768 log("-- finalizeIndirectFunctionTable");
1769 finalizeIndirectFunctionTable();
1770 log("-- createSyntheticInitFunctions");
1771 createSyntheticInitFunctions();
1772 log("-- assignIndexes");
1774 log("-- calculateInitFunctions");
1775 calculateInitFunctions();
1777 if (!config
->relocatable
) {
1778 // Create linker synthesized functions
1779 if (WasmSym::applyGlobalRelocs
)
1780 createApplyGlobalRelocationsFunction();
1781 if (WasmSym::applyTLSRelocs
)
1782 createApplyTLSRelocationsFunction();
1783 if (WasmSym::applyGlobalTLSRelocs
)
1784 createApplyGlobalTLSRelocationsFunction();
1785 if (WasmSym::initMemory
)
1786 createInitMemoryFunction();
1787 createStartFunction();
1789 createCallCtorsFunction();
1791 // Create export wrappers for commands if needed.
1793 // If the input contains a call to `__wasm_call_ctors`, either in one of
1794 // the input objects or an explicit export from the command-line, we
1795 // assume ctors and dtors are taken care of already.
1796 if (!config
->relocatable
&& !ctx
.isPic
&&
1797 !WasmSym::callCtors
->isUsedInRegularObj
&&
1798 !WasmSym::callCtors
->isExported()) {
1799 log("-- createCommandExportWrappers");
1800 createCommandExportWrappers();
1804 if (WasmSym::initTLS
&& WasmSym::initTLS
->isLive()) {
1805 log("-- createInitTLSFunction");
1806 createInitTLSFunction();
1812 log("-- calculateTypes");
1814 log("-- calculateExports");
1816 log("-- calculateCustomSections");
1817 calculateCustomSections();
1818 log("-- populateSymtab");
1820 log("-- checkImportExportTargetFeatures");
1821 checkImportExportTargetFeatures();
1822 log("-- addSections");
1825 if (errorHandler().verbose
) {
1826 log("Defined Functions: " + Twine(out
.functionSec
->inputFunctions
.size()));
1827 log("Defined Globals : " + Twine(out
.globalSec
->numGlobals()));
1828 log("Defined Tags : " + Twine(out
.tagSec
->inputTags
.size()));
1829 log("Defined Tables : " + Twine(out
.tableSec
->inputTables
.size()));
1830 log("Function Imports : " +
1831 Twine(out
.importSec
->getNumImportedFunctions()));
1832 log("Global Imports : " + Twine(out
.importSec
->getNumImportedGlobals()));
1833 log("Tag Imports : " + Twine(out
.importSec
->getNumImportedTags()));
1834 log("Table Imports : " + Twine(out
.importSec
->getNumImportedTables()));
1838 log("-- finalizeSections");
1841 log("-- writeMapFile");
1842 writeMapFile(outputSections
);
1851 log("-- writeSections");
1857 if (Error e
= buffer
->commit())
1858 fatal("failed to write output '" + buffer
->getPath() +
1859 "': " + toString(std::move(e
)));
1862 // Open a result file.
1863 void Writer::openFile() {
1864 log("writing: " + config
->outputFile
);
1866 Expected
<std::unique_ptr
<FileOutputBuffer
>> bufferOrErr
=
1867 FileOutputBuffer::create(config
->outputFile
, fileSize
,
1868 FileOutputBuffer::F_executable
);
1871 error("failed to open " + config
->outputFile
+ ": " +
1872 toString(bufferOrErr
.takeError()));
1874 buffer
= std::move(*bufferOrErr
);
1877 void Writer::createHeader() {
1878 raw_string_ostream
os(header
);
1879 writeBytes(os
, WasmMagic
, sizeof(WasmMagic
), "wasm magic");
1880 writeU32(os
, WasmVersion
, "wasm version");
1881 fileSize
+= header
.size();
1884 void writeResult() { Writer().run(); }
1886 } // namespace wasm::lld