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/ErrorHandler.h"
21 #include "lld/Common/Memory.h"
22 #include "lld/Common/Strings.h"
23 #include "llvm/ADT/DenseSet.h"
24 #include "llvm/ADT/SmallSet.h"
25 #include "llvm/ADT/SmallVector.h"
26 #include "llvm/ADT/StringMap.h"
27 #include "llvm/BinaryFormat/Wasm.h"
28 #include "llvm/BinaryFormat/WasmTraits.h"
29 #include "llvm/Support/FileOutputBuffer.h"
30 #include "llvm/Support/Format.h"
31 #include "llvm/Support/FormatVariadic.h"
32 #include "llvm/Support/LEB128.h"
33 #include "llvm/Support/Parallel.h"
38 #define DEBUG_TYPE "lld"
41 using namespace llvm::wasm
;
45 static constexpr int stackAlignment
= 16;
46 static constexpr int heapAlignment
= 16;
50 // The writer writes a SymbolTable result to a file.
58 bool needsPassiveInitialization(const OutputSegment
*segment
);
59 bool hasPassiveInitializedSegments();
61 void createSyntheticInitFunctions();
62 void createInitMemoryFunction();
63 void createStartFunction();
64 void createApplyDataRelocationsFunction();
65 void createApplyGlobalRelocationsFunction();
66 void createCallCtorsFunction();
67 void createInitTLSFunction();
68 void createCommandExportWrappers();
69 void createCommandExportWrapper(uint32_t functionIndex
, DefinedFunction
*f
);
72 void populateSymtab();
73 void populateProducers();
74 void populateTargetFeatures();
75 void calculateInitFunctions();
76 void calculateImports();
77 void calculateExports();
78 void calculateCustomSections();
79 void calculateTypes();
80 void createOutputSegments();
81 OutputSegment
*createOutputSegment(StringRef name
);
82 void combineOutputSegments();
86 void addSection(OutputSection
*sec
);
90 void createCustomSections();
91 void createSyntheticSections();
92 void createSyntheticSectionsPostLayout();
93 void finalizeSections();
96 void createRelocSections();
101 uint64_t fileSize
= 0;
103 std::vector
<WasmInitEntry
> initFunctions
;
104 llvm::StringMap
<std::vector
<InputChunk
*>> customSectionMapping
;
106 // Stable storage for command export wrapper function name strings.
107 std::list
<std::string
> commandExportWrapperNames
;
109 // Elements that are used to construct the final output
111 std::vector
<OutputSection
*> outputSections
;
113 std::unique_ptr
<FileOutputBuffer
> buffer
;
115 std::vector
<OutputSegment
*> segments
;
116 llvm::SmallDenseMap
<StringRef
, OutputSegment
*> segmentMap
;
119 } // anonymous namespace
121 void Writer::calculateCustomSections() {
122 log("calculateCustomSections");
123 bool stripDebug
= config
->stripDebug
|| config
->stripAll
;
124 for (ObjFile
*file
: symtab
->objectFiles
) {
125 for (InputChunk
*section
: file
->customSections
) {
126 // Exclude COMDAT sections that are not selected for inclusion
127 if (section
->discarded
)
129 StringRef name
= section
->getName();
130 // These custom sections are known the linker and synthesized rather than
132 if (name
== "linking" || name
== "name" || name
== "producers" ||
133 name
== "target_features" || name
.startswith("reloc."))
135 // These custom sections are generated by `clang -fembed-bitcode`.
136 // These are used by the rust toolchain to ship LTO data along with
137 // compiled object code, but they don't want this included in the linker
139 if (name
== ".llvmbc" || name
== ".llvmcmd")
141 // Strip debug section in that option was specified.
142 if (stripDebug
&& name
.startswith(".debug_"))
144 // Otherwise include custom sections by default and concatenate their
146 customSectionMapping
[name
].push_back(section
);
151 void Writer::createCustomSections() {
152 log("createCustomSections");
153 for (auto &pair
: customSectionMapping
) {
154 StringRef name
= pair
.first();
155 LLVM_DEBUG(dbgs() << "createCustomSection: " << name
<< "\n");
157 OutputSection
*sec
= make
<CustomSection
>(std::string(name
), pair
.second
);
158 if (config
->relocatable
|| config
->emitRelocs
) {
159 auto *sym
= make
<OutputSectionSymbol
>(sec
);
160 out
.linkingSec
->addToSymtab(sym
);
161 sec
->sectionSym
= sym
;
167 // Create relocations sections in the final output.
168 // These are only created when relocatable output is requested.
169 void Writer::createRelocSections() {
170 log("createRelocSections");
171 // Don't use iterator here since we are adding to OutputSection
172 size_t origSize
= outputSections
.size();
173 for (size_t i
= 0; i
< origSize
; i
++) {
174 LLVM_DEBUG(dbgs() << "check section " << i
<< "\n");
175 OutputSection
*sec
= outputSections
[i
];
177 // Count the number of needed sections.
178 uint32_t count
= sec
->getNumRelocations();
183 if (sec
->type
== WASM_SEC_DATA
)
185 else if (sec
->type
== WASM_SEC_CODE
)
187 else if (sec
->type
== WASM_SEC_CUSTOM
)
188 name
= saver
.save("reloc." + sec
->name
);
191 "relocations only supported for code, data, or custom sections");
193 addSection(make
<RelocSection
>(name
, sec
));
197 void Writer::populateProducers() {
198 for (ObjFile
*file
: symtab
->objectFiles
) {
199 const WasmProducerInfo
&info
= file
->getWasmObj()->getProducerInfo();
200 out
.producersSec
->addInfo(info
);
204 void Writer::writeHeader() {
205 memcpy(buffer
->getBufferStart(), header
.data(), header
.size());
208 void Writer::writeSections() {
209 uint8_t *buf
= buffer
->getBufferStart();
210 parallelForEach(outputSections
, [buf
](OutputSection
*s
) {
211 assert(s
->isNeeded());
216 static void setGlobalPtr(DefinedGlobal
*g
, uint64_t memoryPtr
) {
217 g
->global
->setPointerValue(memoryPtr
);
220 // Fix the memory layout of the output binary. This assigns memory offsets
221 // to each of the input data sections as well as the explicit stack region.
222 // The default memory layout is as follows, from low to high.
224 // - initialized data (starting at Config->globalBase)
225 // - BSS data (not currently implemented in llvm)
226 // - explicit stack (Config->ZStackSize)
227 // - heap start / unallocated
229 // The --stack-first option means that stack is placed before any static data.
230 // This can be useful since it means that stack overflow traps immediately
231 // rather than overwriting global data, but also increases code size since all
232 // static data loads and stores requires larger offsets.
233 void Writer::layoutMemory() {
234 uint64_t memoryPtr
= 0;
236 auto placeStack
= [&]() {
237 if (config
->relocatable
|| config
->isPic
)
239 memoryPtr
= alignTo(memoryPtr
, stackAlignment
);
240 if (config
->zStackSize
!= alignTo(config
->zStackSize
, stackAlignment
))
241 error("stack size must be " + Twine(stackAlignment
) + "-byte aligned");
242 log("mem: stack size = " + Twine(config
->zStackSize
));
243 log("mem: stack base = " + Twine(memoryPtr
));
244 memoryPtr
+= config
->zStackSize
;
245 setGlobalPtr(cast
<DefinedGlobal
>(WasmSym::stackPointer
), memoryPtr
);
246 log("mem: stack top = " + Twine(memoryPtr
));
249 if (config
->stackFirst
) {
252 memoryPtr
= config
->globalBase
;
253 log("mem: global base = " + Twine(config
->globalBase
));
256 if (WasmSym::globalBase
)
257 WasmSym::globalBase
->setVA(memoryPtr
);
259 uint64_t dataStart
= memoryPtr
;
261 // Arbitrarily set __dso_handle handle to point to the start of the data
263 if (WasmSym::dsoHandle
)
264 WasmSym::dsoHandle
->setVA(dataStart
);
266 out
.dylinkSec
->memAlign
= 0;
267 for (OutputSegment
*seg
: segments
) {
268 out
.dylinkSec
->memAlign
= std::max(out
.dylinkSec
->memAlign
, seg
->alignment
);
269 memoryPtr
= alignTo(memoryPtr
, 1ULL << seg
->alignment
);
270 seg
->startVA
= memoryPtr
;
271 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", seg
->name
,
272 memoryPtr
, seg
->size
, seg
->alignment
));
274 if (!config
->relocatable
&& seg
->isTLS()) {
275 if (config
->sharedMemory
) {
276 auto *tlsSize
= cast
<DefinedGlobal
>(WasmSym::tlsSize
);
277 setGlobalPtr(tlsSize
, seg
->size
);
279 auto *tlsAlign
= cast
<DefinedGlobal
>(WasmSym::tlsAlign
);
280 setGlobalPtr(tlsAlign
, int64_t{1} << seg
->alignment
);
282 auto *tlsBase
= cast
<DefinedGlobal
>(WasmSym::tlsBase
);
283 setGlobalPtr(tlsBase
, memoryPtr
);
287 memoryPtr
+= seg
->size
;
290 // Make space for the memory initialization flag
291 if (config
->sharedMemory
&& hasPassiveInitializedSegments()) {
292 memoryPtr
= alignTo(memoryPtr
, 4);
293 WasmSym::initMemoryFlag
= symtab
->addSyntheticDataSymbol(
294 "__wasm_init_memory_flag", WASM_SYMBOL_VISIBILITY_HIDDEN
);
295 WasmSym::initMemoryFlag
->markLive();
296 WasmSym::initMemoryFlag
->setVA(memoryPtr
);
297 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}",
298 "__wasm_init_memory_flag", memoryPtr
, 4, 4));
302 if (WasmSym::dataEnd
)
303 WasmSym::dataEnd
->setVA(memoryPtr
);
305 uint64_t staticDataSize
= memoryPtr
- dataStart
;
306 log("mem: static data = " + Twine(staticDataSize
));
308 out
.dylinkSec
->memSize
= staticDataSize
;
310 if (!config
->stackFirst
)
313 if (WasmSym::heapBase
) {
314 // Set `__heap_base` to follow the end of the stack or global data. The
315 // fact that this comes last means that a malloc/brk implementation can
316 // grow the heap at runtime.
317 // We'll align the heap base here because memory allocators might expect
318 // __heap_base to be aligned already.
319 memoryPtr
= alignTo(memoryPtr
, heapAlignment
);
320 log("mem: heap base = " + Twine(memoryPtr
));
321 WasmSym::heapBase
->setVA(memoryPtr
);
324 uint64_t maxMemorySetting
= 1ULL
325 << (config
->is64
.getValueOr(false) ? 48 : 32);
327 if (config
->initialMemory
!= 0) {
328 if (config
->initialMemory
!= alignTo(config
->initialMemory
, WasmPageSize
))
329 error("initial memory must be " + Twine(WasmPageSize
) + "-byte aligned");
330 if (memoryPtr
> config
->initialMemory
)
331 error("initial memory too small, " + Twine(memoryPtr
) + " bytes needed");
332 if (config
->initialMemory
> maxMemorySetting
)
333 error("initial memory too large, cannot be greater than " +
334 Twine(maxMemorySetting
));
335 memoryPtr
= config
->initialMemory
;
337 out
.memorySec
->numMemoryPages
=
338 alignTo(memoryPtr
, WasmPageSize
) / WasmPageSize
;
339 log("mem: total pages = " + Twine(out
.memorySec
->numMemoryPages
));
341 if (config
->maxMemory
!= 0) {
342 if (config
->maxMemory
!= alignTo(config
->maxMemory
, WasmPageSize
))
343 error("maximum memory must be " + Twine(WasmPageSize
) + "-byte aligned");
344 if (memoryPtr
> config
->maxMemory
)
345 error("maximum memory too small, " + Twine(memoryPtr
) + " bytes needed");
346 if (config
->maxMemory
> maxMemorySetting
)
347 error("maximum memory too large, cannot be greater than " +
348 Twine(maxMemorySetting
));
351 // Check max if explicitly supplied or required by shared memory
352 if (config
->maxMemory
!= 0 || config
->sharedMemory
) {
353 uint64_t max
= config
->maxMemory
;
355 // If no maxMemory config was supplied but we are building with
356 // shared memory, we need to pick a sensible upper limit.
358 max
= maxMemorySetting
;
360 max
= alignTo(memoryPtr
, WasmPageSize
);
362 out
.memorySec
->maxMemoryPages
= max
/ WasmPageSize
;
363 log("mem: max pages = " + Twine(out
.memorySec
->maxMemoryPages
));
367 void Writer::addSection(OutputSection
*sec
) {
368 if (!sec
->isNeeded())
370 log("addSection: " + toString(*sec
));
371 sec
->sectionIndex
= outputSections
.size();
372 outputSections
.push_back(sec
);
375 // If a section name is valid as a C identifier (which is rare because of
376 // the leading '.'), linkers are expected to define __start_<secname> and
377 // __stop_<secname> symbols. They are at beginning and end of the section,
378 // respectively. This is not requested by the ELF standard, but GNU ld and
379 // gold provide the feature, and used by many programs.
380 static void addStartStopSymbols(const OutputSegment
*seg
) {
381 StringRef name
= seg
->name
;
382 if (!isValidCIdentifier(name
))
384 LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << name
<< "\n");
385 uint64_t start
= seg
->startVA
;
386 uint64_t stop
= start
+ seg
->size
;
387 symtab
->addOptionalDataSymbol(saver
.save("__start_" + name
), start
);
388 symtab
->addOptionalDataSymbol(saver
.save("__stop_" + name
), stop
);
391 void Writer::addSections() {
392 addSection(out
.dylinkSec
);
393 addSection(out
.typeSec
);
394 addSection(out
.importSec
);
395 addSection(out
.functionSec
);
396 addSection(out
.tableSec
);
397 addSection(out
.memorySec
);
398 addSection(out
.tagSec
);
399 addSection(out
.globalSec
);
400 addSection(out
.exportSec
);
401 addSection(out
.startSec
);
402 addSection(out
.elemSec
);
403 addSection(out
.dataCountSec
);
405 addSection(make
<CodeSection
>(out
.functionSec
->inputFunctions
));
406 addSection(make
<DataSection
>(segments
));
408 createCustomSections();
410 addSection(out
.linkingSec
);
411 if (config
->emitRelocs
|| config
->relocatable
) {
412 createRelocSections();
415 addSection(out
.nameSec
);
416 addSection(out
.producersSec
);
417 addSection(out
.targetFeaturesSec
);
420 void Writer::finalizeSections() {
421 for (OutputSection
*s
: outputSections
) {
422 s
->setOffset(fileSize
);
423 s
->finalizeContents();
424 fileSize
+= s
->getSize();
428 void Writer::populateTargetFeatures() {
429 StringMap
<std::string
> used
;
430 StringMap
<std::string
> required
;
431 StringMap
<std::string
> disallowed
;
432 SmallSet
<std::string
, 8> &allowed
= out
.targetFeaturesSec
->features
;
433 bool tlsUsed
= false;
435 // Only infer used features if user did not specify features
436 bool inferFeatures
= !config
->features
.hasValue();
438 if (!inferFeatures
) {
439 auto &explicitFeatures
= config
->features
.getValue();
440 allowed
.insert(explicitFeatures
.begin(), explicitFeatures
.end());
441 if (!config
->checkFeatures
)
445 // Find the sets of used, required, and disallowed features
446 for (ObjFile
*file
: symtab
->objectFiles
) {
447 StringRef
fileName(file
->getName());
448 for (auto &feature
: file
->getWasmObj()->getTargetFeatures()) {
449 switch (feature
.Prefix
) {
450 case WASM_FEATURE_PREFIX_USED
:
451 used
.insert({feature
.Name
, std::string(fileName
)});
453 case WASM_FEATURE_PREFIX_REQUIRED
:
454 used
.insert({feature
.Name
, std::string(fileName
)});
455 required
.insert({feature
.Name
, std::string(fileName
)});
457 case WASM_FEATURE_PREFIX_DISALLOWED
:
458 disallowed
.insert({feature
.Name
, std::string(fileName
)});
461 error("Unrecognized feature policy prefix " +
462 std::to_string(feature
.Prefix
));
466 // Find TLS data segments
467 auto isTLS
= [](InputChunk
*segment
) {
468 return segment
->live
&& segment
->isTLS();
471 std::any_of(file
->segments
.begin(), file
->segments
.end(), isTLS
);
475 for (const auto &key
: used
.keys())
476 allowed
.insert(std::string(key
));
478 if (!config
->checkFeatures
)
481 if (!config
->relocatable
&& allowed
.count("mutable-globals") == 0) {
482 for (const Symbol
*sym
: out
.importSec
->importedSymbols
) {
483 if (auto *global
= dyn_cast
<GlobalSymbol
>(sym
)) {
484 if (global
->getGlobalType()->Mutable
) {
485 error(Twine("mutable global imported but 'mutable-globals' feature "
486 "not present in inputs: `") +
487 toString(*sym
) + "`. Use --no-check-features to suppress.");
491 for (const Symbol
*sym
: out
.exportSec
->exportedSymbols
) {
492 if (isa
<GlobalSymbol
>(sym
)) {
493 error(Twine("mutable global exported but 'mutable-globals' feature "
494 "not present in inputs: `") +
495 toString(*sym
) + "`. Use --no-check-features to suppress.");
500 if (config
->sharedMemory
) {
501 if (disallowed
.count("shared-mem"))
502 error("--shared-memory is disallowed by " + disallowed
["shared-mem"] +
503 " because it was not compiled with 'atomics' or 'bulk-memory' "
506 for (auto feature
: {"atomics", "bulk-memory"})
507 if (!allowed
.count(feature
))
508 error(StringRef("'") + feature
+
509 "' feature must be used in order to use shared memory");
513 for (auto feature
: {"atomics", "bulk-memory"})
514 if (!allowed
.count(feature
))
515 error(StringRef("'") + feature
+
516 "' feature must be used in order to use thread-local storage");
519 // Validate that used features are allowed in output
520 if (!inferFeatures
) {
521 for (auto &feature
: used
.keys()) {
522 if (!allowed
.count(std::string(feature
)))
523 error(Twine("Target feature '") + feature
+ "' used by " +
524 used
[feature
] + " is not allowed.");
528 // Validate the required and disallowed constraints for each file
529 for (ObjFile
*file
: symtab
->objectFiles
) {
530 StringRef
fileName(file
->getName());
531 SmallSet
<std::string
, 8> objectFeatures
;
532 for (auto &feature
: file
->getWasmObj()->getTargetFeatures()) {
533 if (feature
.Prefix
== WASM_FEATURE_PREFIX_DISALLOWED
)
535 objectFeatures
.insert(feature
.Name
);
536 if (disallowed
.count(feature
.Name
))
537 error(Twine("Target feature '") + feature
.Name
+ "' used in " +
538 fileName
+ " is disallowed by " + disallowed
[feature
.Name
] +
539 ". Use --no-check-features to suppress.");
541 for (auto &feature
: required
.keys()) {
542 if (!objectFeatures
.count(std::string(feature
)))
543 error(Twine("Missing target feature '") + feature
+ "' in " + fileName
+
544 ", required by " + required
[feature
] +
545 ". Use --no-check-features to suppress.");
550 static bool shouldImport(Symbol
*sym
) {
551 // We don't generate imports for data symbols. They however can be imported
553 if (isa
<DataSymbol
>(sym
))
557 if (!sym
->isUsedInRegularObj
)
560 // When a symbol is weakly defined in a shared library we need to allow
561 // it to be overridden by another module so need to both import
562 // and export the symbol.
563 if (config
->shared
&& sym
->isDefined() && sym
->isWeak())
565 if (!sym
->isUndefined())
567 if (sym
->isWeak() && !config
->relocatable
&& !config
->isPic
)
570 // In PIC mode we only need to import functions when they are called directly.
571 // Indirect usage all goes via GOT imports.
573 if (auto *f
= dyn_cast
<UndefinedFunction
>(sym
))
574 if (!f
->isCalledDirectly
)
578 if (config
->isPic
|| config
->relocatable
|| config
->importUndefined
)
580 if (config
->allowUndefinedSymbols
.count(sym
->getName()) != 0)
583 return sym
->importName
.hasValue();
586 void Writer::calculateImports() {
587 // Some inputs require that the indirect function table be assigned to table
588 // number 0, so if it is present and is an import, allocate it before any
590 if (WasmSym::indirectFunctionTable
&&
591 shouldImport(WasmSym::indirectFunctionTable
))
592 out
.importSec
->addImport(WasmSym::indirectFunctionTable
);
594 for (Symbol
*sym
: symtab
->getSymbols()) {
595 if (!shouldImport(sym
))
597 if (sym
== WasmSym::indirectFunctionTable
)
599 LLVM_DEBUG(dbgs() << "import: " << sym
->getName() << "\n");
600 out
.importSec
->addImport(sym
);
604 void Writer::calculateExports() {
605 if (config
->relocatable
)
608 if (!config
->relocatable
&& !config
->importMemory
)
609 out
.exportSec
->exports
.push_back(
610 WasmExport
{"memory", WASM_EXTERNAL_MEMORY
, 0});
612 unsigned globalIndex
=
613 out
.importSec
->getNumImportedGlobals() + out
.globalSec
->numGlobals();
615 for (Symbol
*sym
: symtab
->getSymbols()) {
616 if (!sym
->isExported())
621 StringRef name
= sym
->getName();
623 if (auto *f
= dyn_cast
<DefinedFunction
>(sym
)) {
624 if (Optional
<StringRef
> exportName
= f
->function
->getExportName()) {
627 export_
= {name
, WASM_EXTERNAL_FUNCTION
, f
->getExportedFunctionIndex()};
628 } else if (auto *g
= dyn_cast
<DefinedGlobal
>(sym
)) {
629 if (g
->getGlobalType()->Mutable
&& !g
->getFile() && !g
->forceExport
) {
630 // Avoid exporting mutable globals are linker synthesized (e.g.
631 // __stack_pointer or __tls_base) unless they are explicitly exported
632 // from the command line.
633 // Without this check `--export-all` would cause any program using the
634 // stack pointer to export a mutable global even if none of the input
635 // files were built with the `mutable-globals` feature.
638 export_
= {name
, WASM_EXTERNAL_GLOBAL
, g
->getGlobalIndex()};
639 } else if (auto *t
= dyn_cast
<DefinedTag
>(sym
)) {
640 export_
= {name
, WASM_EXTERNAL_TAG
, t
->getTagIndex()};
641 } else if (auto *d
= dyn_cast
<DefinedData
>(sym
)) {
642 if (d
->segment
&& d
->segment
->isTLS()) {
643 // We can't currenly export TLS data symbols.
644 if (sym
->isExportedExplicit())
645 error("TLS symbols cannot yet be exported: `" + toString(*sym
) + "`");
648 out
.globalSec
->dataAddressGlobals
.push_back(d
);
649 export_
= {name
, WASM_EXTERNAL_GLOBAL
, globalIndex
++};
651 auto *t
= cast
<DefinedTable
>(sym
);
652 export_
= {name
, WASM_EXTERNAL_TABLE
, t
->getTableNumber()};
655 LLVM_DEBUG(dbgs() << "Export: " << name
<< "\n");
656 out
.exportSec
->exports
.push_back(export_
);
657 out
.exportSec
->exportedSymbols
.push_back(sym
);
661 void Writer::populateSymtab() {
662 if (!config
->relocatable
&& !config
->emitRelocs
)
665 for (Symbol
*sym
: symtab
->getSymbols())
666 if (sym
->isUsedInRegularObj
&& sym
->isLive())
667 out
.linkingSec
->addToSymtab(sym
);
669 for (ObjFile
*file
: symtab
->objectFiles
) {
670 LLVM_DEBUG(dbgs() << "Local symtab entries: " << file
->getName() << "\n");
671 for (Symbol
*sym
: file
->getSymbols())
672 if (sym
->isLocal() && !isa
<SectionSymbol
>(sym
) && sym
->isLive())
673 out
.linkingSec
->addToSymtab(sym
);
677 void Writer::calculateTypes() {
678 // The output type section is the union of the following sets:
679 // 1. Any signature used in the TYPE relocation
680 // 2. The signatures of all imported functions
681 // 3. The signatures of all defined functions
682 // 4. The signatures of all imported tags
683 // 5. The signatures of all defined tags
685 for (ObjFile
*file
: symtab
->objectFiles
) {
686 ArrayRef
<WasmSignature
> types
= file
->getWasmObj()->types();
687 for (uint32_t i
= 0; i
< types
.size(); i
++)
688 if (file
->typeIsUsed
[i
])
689 file
->typeMap
[i
] = out
.typeSec
->registerType(types
[i
]);
692 for (const Symbol
*sym
: out
.importSec
->importedSymbols
) {
693 if (auto *f
= dyn_cast
<FunctionSymbol
>(sym
))
694 out
.typeSec
->registerType(*f
->signature
);
695 else if (auto *t
= dyn_cast
<TagSymbol
>(sym
))
696 out
.typeSec
->registerType(*t
->signature
);
699 for (const InputFunction
*f
: out
.functionSec
->inputFunctions
)
700 out
.typeSec
->registerType(f
->signature
);
702 for (const InputTag
*t
: out
.tagSec
->inputTags
)
703 out
.typeSec
->registerType(t
->signature
);
706 // In a command-style link, create a wrapper for each exported symbol
707 // which calls the constructors and destructors.
708 void Writer::createCommandExportWrappers() {
709 // This logic doesn't currently support Emscripten-style PIC mode.
710 assert(!config
->isPic
);
712 // If there are no ctors and there's no libc `__wasm_call_dtors` to
713 // call, don't wrap the exports.
714 if (initFunctions
.empty() && WasmSym::callDtors
== NULL
)
717 std::vector
<DefinedFunction
*> toWrap
;
719 for (Symbol
*sym
: symtab
->getSymbols())
720 if (sym
->isExported())
721 if (auto *f
= dyn_cast
<DefinedFunction
>(sym
))
724 for (auto *f
: toWrap
) {
725 auto funcNameStr
= (f
->getName() + ".command_export").str();
726 commandExportWrapperNames
.push_back(funcNameStr
);
727 const std::string
&funcName
= commandExportWrapperNames
.back();
729 auto func
= make
<SyntheticFunction
>(*f
->getSignature(), funcName
);
730 if (f
->function
->getExportName().hasValue())
731 func
->setExportName(f
->function
->getExportName()->str());
733 func
->setExportName(f
->getName().str());
735 DefinedFunction
*def
=
736 symtab
->addSyntheticFunction(funcName
, f
->flags
, func
);
739 def
->flags
|= WASM_SYMBOL_EXPORTED
;
740 def
->flags
&= ~WASM_SYMBOL_VISIBILITY_HIDDEN
;
741 def
->forceExport
= f
->forceExport
;
743 f
->flags
|= WASM_SYMBOL_VISIBILITY_HIDDEN
;
744 f
->flags
&= ~WASM_SYMBOL_EXPORTED
;
745 f
->forceExport
= false;
747 out
.functionSec
->addFunction(func
);
749 createCommandExportWrapper(f
->getFunctionIndex(), def
);
753 static void finalizeIndirectFunctionTable() {
754 if (!WasmSym::indirectFunctionTable
)
757 if (shouldImport(WasmSym::indirectFunctionTable
) &&
758 !WasmSym::indirectFunctionTable
->hasTableNumber()) {
759 // Processing -Bsymbolic relocations resulted in a late requirement that the
760 // indirect function table be present, and we are running in --import-table
761 // mode. Add the table now to the imports section. Otherwise it will be
762 // added to the tables section later in assignIndexes.
763 out
.importSec
->addImport(WasmSym::indirectFunctionTable
);
766 uint32_t tableSize
= config
->tableBase
+ out
.elemSec
->numEntries();
767 WasmLimits limits
= {0, tableSize
, 0};
768 if (WasmSym::indirectFunctionTable
->isDefined() && !config
->growableTable
) {
769 limits
.Flags
|= WASM_LIMITS_FLAG_HAS_MAX
;
770 limits
.Maximum
= limits
.Minimum
;
772 WasmSym::indirectFunctionTable
->setLimits(limits
);
775 static void scanRelocations() {
776 for (ObjFile
*file
: symtab
->objectFiles
) {
777 LLVM_DEBUG(dbgs() << "scanRelocations: " << file
->getName() << "\n");
778 for (InputChunk
*chunk
: file
->functions
)
779 scanRelocations(chunk
);
780 for (InputChunk
*chunk
: file
->segments
)
781 scanRelocations(chunk
);
782 for (auto &p
: file
->customSections
)
787 void Writer::assignIndexes() {
788 // Seal the import section, since other index spaces such as function and
789 // global are effected by the number of imports.
790 out
.importSec
->seal();
792 for (InputFunction
*func
: symtab
->syntheticFunctions
)
793 out
.functionSec
->addFunction(func
);
795 for (ObjFile
*file
: symtab
->objectFiles
) {
796 LLVM_DEBUG(dbgs() << "Functions: " << file
->getName() << "\n");
797 for (InputFunction
*func
: file
->functions
)
798 out
.functionSec
->addFunction(func
);
801 for (InputGlobal
*global
: symtab
->syntheticGlobals
)
802 out
.globalSec
->addGlobal(global
);
804 for (ObjFile
*file
: symtab
->objectFiles
) {
805 LLVM_DEBUG(dbgs() << "Globals: " << file
->getName() << "\n");
806 for (InputGlobal
*global
: file
->globals
)
807 out
.globalSec
->addGlobal(global
);
810 for (ObjFile
*file
: symtab
->objectFiles
) {
811 LLVM_DEBUG(dbgs() << "Tags: " << file
->getName() << "\n");
812 for (InputTag
*tag
: file
->tags
)
813 out
.tagSec
->addTag(tag
);
816 for (ObjFile
*file
: symtab
->objectFiles
) {
817 LLVM_DEBUG(dbgs() << "Tables: " << file
->getName() << "\n");
818 for (InputTable
*table
: file
->tables
)
819 out
.tableSec
->addTable(table
);
822 for (InputTable
*table
: symtab
->syntheticTables
)
823 out
.tableSec
->addTable(table
);
825 out
.globalSec
->assignIndexes();
826 out
.tableSec
->assignIndexes();
829 static StringRef
getOutputDataSegmentName(const InputChunk
&seg
) {
830 // We always merge .tbss and .tdata into a single TLS segment so all TLS
831 // symbols are be relative to single __tls_base.
834 StringRef name
= seg
.getName();
835 if (!config
->mergeDataSegments
)
837 if (name
.startswith(".text."))
839 if (name
.startswith(".data."))
841 if (name
.startswith(".bss."))
843 if (name
.startswith(".rodata."))
848 OutputSegment
*Writer::createOutputSegment(StringRef name
) {
849 LLVM_DEBUG(dbgs() << "new segment: " << name
<< "\n");
850 OutputSegment
*s
= make
<OutputSegment
>(name
);
851 if (config
->sharedMemory
)
852 s
->initFlags
= WASM_DATA_SEGMENT_IS_PASSIVE
;
853 // Exported memories are guaranteed to be zero-initialized, so no need
854 // to emit data segments for bss sections.
855 // TODO: consider initializing bss sections with memory.fill
856 // instructions when memory is imported and bulk-memory is available.
857 if (!config
->importMemory
&& !config
->relocatable
&& name
.startswith(".bss"))
859 segments
.push_back(s
);
863 void Writer::createOutputSegments() {
864 for (ObjFile
*file
: symtab
->objectFiles
) {
865 for (InputChunk
*segment
: file
->segments
) {
868 StringRef name
= getOutputDataSegmentName(*segment
);
869 OutputSegment
*s
= nullptr;
870 // When running in relocatable mode we can't merge segments that are part
871 // of comdat groups since the ultimate linker needs to be able exclude or
872 // include them individually.
873 if (config
->relocatable
&& !segment
->getComdatName().empty()) {
874 s
= createOutputSegment(name
);
876 if (segmentMap
.count(name
) == 0)
877 segmentMap
[name
] = createOutputSegment(name
);
878 s
= segmentMap
[name
];
880 s
->addInputSegment(segment
);
884 // Sort segments by type, placing .bss last
885 std::stable_sort(segments
.begin(), segments
.end(),
886 [](const OutputSegment
*a
, const OutputSegment
*b
) {
887 auto order
= [](StringRef name
) {
888 return StringSwitch
<int>(name
)
889 .StartsWith(".tdata", 0)
890 .StartsWith(".rodata", 1)
891 .StartsWith(".data", 2)
892 .StartsWith(".bss", 4)
895 return order(a
->name
) < order(b
->name
);
898 for (size_t i
= 0; i
< segments
.size(); ++i
)
899 segments
[i
]->index
= i
;
901 // Merge MergeInputSections into a single MergeSyntheticSection.
902 LLVM_DEBUG(dbgs() << "-- finalize input semgments\n");
903 for (OutputSegment
*seg
: segments
)
904 seg
->finalizeInputSegments();
907 void Writer::combineOutputSegments() {
908 // With PIC code we currently only support a single active data segment since
909 // we only have a single __memory_base to use as our base address. This pass
910 // combines all data segments into a single .data segment.
911 // This restructions can be relaxed once we have extended constant
912 // expressions available:
913 // https://github.com/WebAssembly/extended-const
914 assert(config
->isPic
&& !config
->sharedMemory
);
915 if (segments
.size() <= 1)
917 OutputSegment
*combined
= make
<OutputSegment
>(".data");
918 combined
->startVA
= segments
[0]->startVA
;
919 for (OutputSegment
*s
: segments
) {
921 for (InputChunk
*inSeg
: s
->inputSegments
) {
923 inSeg
->alignment
= std::max(inSeg
->alignment
, s
->alignment
);
926 uint64_t oldVA
= inSeg
->getVA();
928 combined
->addInputSegment(inSeg
);
930 uint64_t newVA
= inSeg
->getVA();
931 LLVM_DEBUG(dbgs() << "added input segment. name=" << inSeg
->getName()
932 << " oldVA=" << oldVA
<< " newVA=" << newVA
<< "\n");
933 assert(oldVA
== newVA
);
938 segments
= {combined
};
941 static void createFunction(DefinedFunction
*func
, StringRef bodyContent
) {
942 std::string functionBody
;
944 raw_string_ostream
os(functionBody
);
945 writeUleb128(os
, bodyContent
.size(), "function size");
948 ArrayRef
<uint8_t> body
= arrayRefFromStringRef(saver
.save(functionBody
));
949 cast
<SyntheticFunction
>(func
->function
)->setBody(body
);
952 bool Writer::needsPassiveInitialization(const OutputSegment
*segment
) {
953 return segment
->initFlags
& WASM_DATA_SEGMENT_IS_PASSIVE
&&
954 !segment
->isTLS() && !segment
->isBss
;
957 bool Writer::hasPassiveInitializedSegments() {
958 return std::find_if(segments
.begin(), segments
.end(),
959 [this](const OutputSegment
*s
) {
960 return this->needsPassiveInitialization(s
);
961 }) != segments
.end();
964 void Writer::createSyntheticInitFunctions() {
965 if (config
->relocatable
)
968 static WasmSignature nullSignature
= {{}, {}};
970 // Passive segments are used to avoid memory being reinitialized on each
971 // thread's instantiation. These passive segments are initialized and
972 // dropped in __wasm_init_memory, which is registered as the start function
973 if (config
->sharedMemory
&& hasPassiveInitializedSegments()) {
974 WasmSym::initMemory
= symtab
->addSyntheticFunction(
975 "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN
,
976 make
<SyntheticFunction
>(nullSignature
, "__wasm_init_memory"));
977 WasmSym::initMemory
->markLive();
981 // For PIC code we create synthetic functions that apply relocations.
982 // These get called from __wasm_call_ctors before the user-level
984 WasmSym::applyDataRelocs
= symtab
->addSyntheticFunction(
985 "__wasm_apply_data_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN
,
986 make
<SyntheticFunction
>(nullSignature
, "__wasm_apply_data_relocs"));
987 WasmSym::applyDataRelocs
->markLive();
989 if (out
.globalSec
->needsRelocations()) {
990 WasmSym::applyGlobalRelocs
= symtab
->addSyntheticFunction(
991 "__wasm_apply_global_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN
,
992 make
<SyntheticFunction
>(nullSignature
, "__wasm_apply_global_relocs"));
993 WasmSym::applyGlobalRelocs
->markLive();
997 if (WasmSym::applyGlobalRelocs
&& WasmSym::initMemory
) {
998 WasmSym::startFunction
= symtab
->addSyntheticFunction(
999 "__wasm_start", WASM_SYMBOL_VISIBILITY_HIDDEN
,
1000 make
<SyntheticFunction
>(nullSignature
, "__wasm_start"));
1001 WasmSym::startFunction
->markLive();
1005 void Writer::createInitMemoryFunction() {
1006 LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n");
1007 assert(WasmSym::initMemory
);
1008 assert(WasmSym::initMemoryFlag
);
1009 assert(hasPassiveInitializedSegments());
1010 uint64_t flagAddress
= WasmSym::initMemoryFlag
->getVA();
1011 bool is64
= config
->is64
.getValueOr(false);
1012 std::string bodyContent
;
1014 raw_string_ostream
os(bodyContent
);
1015 // Initialize memory in a thread-safe manner. The thread that successfully
1016 // increments the flag from 0 to 1 is is responsible for performing the
1017 // memory initialization. Other threads go sleep on the flag until the
1018 // first thread finishing initializing memory, increments the flag to 2,
1019 // and wakes all the other threads. Once the flag has been set to 2,
1020 // subsequently started threads will skip the sleep. All threads
1021 // unconditionally drop their passive data segments once memory has been
1022 // initialized. The generated code is as follows:
1024 // (func $__wasm_init_memory
1026 // (i32.atomic.rmw.cmpxchg align=2 offset=0
1027 // (i32.const $__init_memory_flag)
1033 // (i32.atomic.wait align=2 offset=0
1034 // (i32.const $__init_memory_flag)
1041 // ( ... initialize data segments ... )
1042 // (i32.atomic.store align=2 offset=0
1043 // (i32.const $__init_memory_flag)
1047 // (i32.atomic.notify align=2 offset=0
1048 // (i32.const $__init_memory_flag)
1054 // ( ... drop data segments ... )
1057 // When we are building with PIC, calculate the flag location using:
1059 // (global.get $__memory_base)
1060 // (i32.const $__init_memory_flag)
1063 // With PIC code we cache the flag address in local 0
1064 if (config
->isPic
) {
1065 writeUleb128(os
, 1, "num local decls");
1066 writeUleb128(os
, 1, "local count");
1067 writeU8(os
, is64
? WASM_TYPE_I64
: WASM_TYPE_I32
, "address type");
1068 writeU8(os
, WASM_OPCODE_GLOBAL_GET
, "GLOBAL_GET");
1069 writeUleb128(os
, WasmSym::memoryBase
->getGlobalIndex(), "memory_base");
1070 writePtrConst(os
, flagAddress
, is64
, "flag address");
1071 writeU8(os
, is64
? WASM_OPCODE_I64_ADD
: WASM_OPCODE_I32_ADD
, "add");
1072 writeU8(os
, WASM_OPCODE_LOCAL_SET
, "local.set");
1073 writeUleb128(os
, 0, "local 0");
1075 writeUleb128(os
, 0, "num locals");
1078 auto writeGetFlagAddress
= [&]() {
1079 if (config
->isPic
) {
1080 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1081 writeUleb128(os
, 0, "local 0");
1083 writePtrConst(os
, flagAddress
, is64
, "flag address");
1087 // Atomically check whether this is the main thread.
1088 writeGetFlagAddress();
1089 writeI32Const(os
, 0, "expected flag value");
1090 writeI32Const(os
, 1, "flag value");
1091 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1092 writeUleb128(os
, WASM_OPCODE_I32_RMW_CMPXCHG
, "i32.atomic.rmw.cmpxchg");
1093 writeMemArg(os
, 2, 0);
1094 writeU8(os
, WASM_OPCODE_IF
, "IF");
1095 writeU8(os
, WASM_TYPE_NORESULT
, "blocktype");
1097 // Did not increment 0, so wait for main thread to initialize memory
1098 writeGetFlagAddress();
1099 writeI32Const(os
, 1, "expected flag value");
1100 writeI64Const(os
, -1, "timeout");
1102 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1103 writeUleb128(os
, WASM_OPCODE_I32_ATOMIC_WAIT
, "i32.atomic.wait");
1104 writeMemArg(os
, 2, 0);
1105 writeU8(os
, WASM_OPCODE_DROP
, "drop");
1107 writeU8(os
, WASM_OPCODE_ELSE
, "ELSE");
1109 // Did increment 0, so conditionally initialize passive data segments
1110 for (const OutputSegment
*s
: segments
) {
1111 if (needsPassiveInitialization(s
)) {
1112 // destination address
1113 writePtrConst(os
, s
->startVA
, is64
, "destination address");
1114 if (config
->isPic
) {
1115 writeU8(os
, WASM_OPCODE_GLOBAL_GET
, "GLOBAL_GET");
1116 writeUleb128(os
, WasmSym::memoryBase
->getGlobalIndex(),
1118 writeU8(os
, is64
? WASM_OPCODE_I64_ADD
: WASM_OPCODE_I32_ADD
,
1121 // source segment offset
1122 writeI32Const(os
, 0, "segment offset");
1123 // memory region size
1124 writeI32Const(os
, s
->size
, "memory region size");
1125 // memory.init instruction
1126 writeU8(os
, WASM_OPCODE_MISC_PREFIX
, "bulk-memory prefix");
1127 writeUleb128(os
, WASM_OPCODE_MEMORY_INIT
, "memory.init");
1128 writeUleb128(os
, s
->index
, "segment index immediate");
1129 writeU8(os
, 0, "memory index immediate");
1133 // Set flag to 2 to mark end of initialization
1134 writeGetFlagAddress();
1135 writeI32Const(os
, 2, "flag value");
1136 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1137 writeUleb128(os
, WASM_OPCODE_I32_ATOMIC_STORE
, "i32.atomic.store");
1138 writeMemArg(os
, 2, 0);
1140 // Notify any waiters that memory initialization is complete
1141 writeGetFlagAddress();
1142 writeI32Const(os
, -1, "number of waiters");
1143 writeU8(os
, WASM_OPCODE_ATOMICS_PREFIX
, "atomics prefix");
1144 writeUleb128(os
, WASM_OPCODE_ATOMIC_NOTIFY
, "atomic.notify");
1145 writeMemArg(os
, 2, 0);
1146 writeU8(os
, WASM_OPCODE_DROP
, "drop");
1148 writeU8(os
, WASM_OPCODE_END
, "END");
1150 // Unconditionally drop passive data segments
1151 for (const OutputSegment
*s
: segments
) {
1152 if (needsPassiveInitialization(s
)) {
1153 // data.drop instruction
1154 writeU8(os
, WASM_OPCODE_MISC_PREFIX
, "bulk-memory prefix");
1155 writeUleb128(os
, WASM_OPCODE_DATA_DROP
, "data.drop");
1156 writeUleb128(os
, s
->index
, "segment index immediate");
1159 writeU8(os
, WASM_OPCODE_END
, "END");
1162 createFunction(WasmSym::initMemory
, bodyContent
);
1165 void Writer::createStartFunction() {
1166 if (WasmSym::startFunction
) {
1167 std::string bodyContent
;
1169 raw_string_ostream
os(bodyContent
);
1170 writeUleb128(os
, 0, "num locals");
1171 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1172 writeUleb128(os
, WasmSym::initMemory
->getFunctionIndex(),
1174 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1175 writeUleb128(os
, WasmSym::applyGlobalRelocs
->getFunctionIndex(),
1177 writeU8(os
, WASM_OPCODE_END
, "END");
1179 createFunction(WasmSym::startFunction
, bodyContent
);
1180 } else if (WasmSym::initMemory
) {
1181 WasmSym::startFunction
= WasmSym::initMemory
;
1182 } else if (WasmSym::applyGlobalRelocs
) {
1183 WasmSym::startFunction
= WasmSym::applyGlobalRelocs
;
1187 // For -shared (PIC) output, we create create a synthetic function which will
1188 // apply any relocations to the data segments on startup. This function is
1189 // called `__wasm_apply_data_relocs` and is added at the beginning of
1190 // `__wasm_call_ctors` before any of the constructors run.
1191 void Writer::createApplyDataRelocationsFunction() {
1192 LLVM_DEBUG(dbgs() << "createApplyDataRelocationsFunction\n");
1193 // First write the body's contents to a string.
1194 std::string bodyContent
;
1196 raw_string_ostream
os(bodyContent
);
1197 writeUleb128(os
, 0, "num locals");
1198 for (const OutputSegment
*seg
: segments
)
1199 for (const InputChunk
*inSeg
: seg
->inputSegments
)
1200 inSeg
->generateRelocationCode(os
);
1202 writeU8(os
, WASM_OPCODE_END
, "END");
1205 createFunction(WasmSym::applyDataRelocs
, bodyContent
);
1208 // Similar to createApplyDataRelocationsFunction but generates relocation code
1209 // fro WebAssembly globals. Because these globals are not shared between threads
1210 // these relocation need to run on every thread.
1211 void Writer::createApplyGlobalRelocationsFunction() {
1212 // First write the body's contents to a string.
1213 std::string bodyContent
;
1215 raw_string_ostream
os(bodyContent
);
1216 writeUleb128(os
, 0, "num locals");
1217 out
.globalSec
->generateRelocationCode(os
);
1218 writeU8(os
, WASM_OPCODE_END
, "END");
1221 createFunction(WasmSym::applyGlobalRelocs
, bodyContent
);
1224 // Create synthetic "__wasm_call_ctors" function based on ctor functions
1226 void Writer::createCallCtorsFunction() {
1227 // If __wasm_call_ctors isn't referenced, there aren't any ctors, and we
1228 // aren't calling `__wasm_apply_data_relocs` for Emscripten-style PIC, don't
1229 // define the `__wasm_call_ctors` function.
1230 if (!WasmSym::callCtors
->isLive() && !WasmSym::applyDataRelocs
&&
1231 initFunctions
.empty())
1234 // First write the body's contents to a string.
1235 std::string bodyContent
;
1237 raw_string_ostream
os(bodyContent
);
1238 writeUleb128(os
, 0, "num locals");
1240 if (WasmSym::applyDataRelocs
) {
1241 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1242 writeUleb128(os
, WasmSym::applyDataRelocs
->getFunctionIndex(),
1246 // Call constructors
1247 for (const WasmInitEntry
&f
: initFunctions
) {
1248 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1249 writeUleb128(os
, f
.sym
->getFunctionIndex(), "function index");
1250 for (size_t i
= 0; i
< f
.sym
->signature
->Returns
.size(); i
++) {
1251 writeU8(os
, WASM_OPCODE_DROP
, "DROP");
1255 writeU8(os
, WASM_OPCODE_END
, "END");
1258 createFunction(WasmSym::callCtors
, bodyContent
);
1261 // Create a wrapper around a function export which calls the
1262 // static constructors and destructors.
1263 void Writer::createCommandExportWrapper(uint32_t functionIndex
,
1264 DefinedFunction
*f
) {
1265 // First write the body's contents to a string.
1266 std::string bodyContent
;
1268 raw_string_ostream
os(bodyContent
);
1269 writeUleb128(os
, 0, "num locals");
1271 // Call `__wasm_call_ctors` which call static constructors (and
1272 // applies any runtime relocations in Emscripten-style PIC mode)
1273 if (WasmSym::callCtors
->isLive()) {
1274 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1275 writeUleb128(os
, WasmSym::callCtors
->getFunctionIndex(),
1279 // Call the user's code, leaving any return values on the operand stack.
1280 for (size_t i
= 0; i
< f
->signature
->Params
.size(); ++i
) {
1281 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1282 writeUleb128(os
, i
, "local index");
1284 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1285 writeUleb128(os
, functionIndex
, "function index");
1287 // Call the function that calls the destructors.
1288 if (DefinedFunction
*callDtors
= WasmSym::callDtors
) {
1289 writeU8(os
, WASM_OPCODE_CALL
, "CALL");
1290 writeUleb128(os
, callDtors
->getFunctionIndex(), "function index");
1293 // End the function, returning the return values from the user's code.
1294 writeU8(os
, WASM_OPCODE_END
, "END");
1297 createFunction(f
, bodyContent
);
1300 void Writer::createInitTLSFunction() {
1301 std::string bodyContent
;
1303 raw_string_ostream
os(bodyContent
);
1305 OutputSegment
*tlsSeg
= nullptr;
1306 for (auto *seg
: segments
) {
1307 if (seg
->name
== ".tdata") {
1313 writeUleb128(os
, 0, "num locals");
1315 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1316 writeUleb128(os
, 0, "local index");
1318 writeU8(os
, WASM_OPCODE_GLOBAL_SET
, "global.set");
1319 writeUleb128(os
, WasmSym::tlsBase
->getGlobalIndex(), "global index");
1321 // FIXME(wvo): this local needs to be I64 in wasm64, or we need an extend op.
1322 writeU8(os
, WASM_OPCODE_LOCAL_GET
, "local.get");
1323 writeUleb128(os
, 0, "local index");
1325 writeI32Const(os
, 0, "segment offset");
1327 writeI32Const(os
, tlsSeg
->size
, "memory region size");
1329 writeU8(os
, WASM_OPCODE_MISC_PREFIX
, "bulk-memory prefix");
1330 writeUleb128(os
, WASM_OPCODE_MEMORY_INIT
, "MEMORY.INIT");
1331 writeUleb128(os
, tlsSeg
->index
, "segment index immediate");
1332 writeU8(os
, 0, "memory index immediate");
1334 writeU8(os
, WASM_OPCODE_END
, "end function");
1337 createFunction(WasmSym::initTLS
, bodyContent
);
1340 // Populate InitFunctions vector with init functions from all input objects.
1341 // This is then used either when creating the output linking section or to
1342 // synthesize the "__wasm_call_ctors" function.
1343 void Writer::calculateInitFunctions() {
1344 if (!config
->relocatable
&& !WasmSym::callCtors
->isLive())
1347 for (ObjFile
*file
: symtab
->objectFiles
) {
1348 const WasmLinkingData
&l
= file
->getWasmObj()->linkingData();
1349 for (const WasmInitFunc
&f
: l
.InitFunctions
) {
1350 FunctionSymbol
*sym
= file
->getFunctionSymbol(f
.Symbol
);
1351 // comdat exclusions can cause init functions be discarded.
1352 if (sym
->isDiscarded() || !sym
->isLive())
1354 if (sym
->signature
->Params
.size() != 0)
1355 error("constructor functions cannot take arguments: " + toString(*sym
));
1356 LLVM_DEBUG(dbgs() << "initFunctions: " << toString(*sym
) << "\n");
1357 initFunctions
.emplace_back(WasmInitEntry
{sym
, f
.Priority
});
1361 // Sort in order of priority (lowest first) so that they are called
1362 // in the correct order.
1363 llvm::stable_sort(initFunctions
,
1364 [](const WasmInitEntry
&l
, const WasmInitEntry
&r
) {
1365 return l
.priority
< r
.priority
;
1369 void Writer::createSyntheticSections() {
1370 out
.dylinkSec
= make
<DylinkSection
>();
1371 out
.typeSec
= make
<TypeSection
>();
1372 out
.importSec
= make
<ImportSection
>();
1373 out
.functionSec
= make
<FunctionSection
>();
1374 out
.tableSec
= make
<TableSection
>();
1375 out
.memorySec
= make
<MemorySection
>();
1376 out
.tagSec
= make
<TagSection
>();
1377 out
.globalSec
= make
<GlobalSection
>();
1378 out
.exportSec
= make
<ExportSection
>();
1379 out
.startSec
= make
<StartSection
>();
1380 out
.elemSec
= make
<ElemSection
>();
1381 out
.producersSec
= make
<ProducersSection
>();
1382 out
.targetFeaturesSec
= make
<TargetFeaturesSection
>();
1385 void Writer::createSyntheticSectionsPostLayout() {
1386 out
.dataCountSec
= make
<DataCountSection
>(segments
);
1387 out
.linkingSec
= make
<LinkingSection
>(initFunctions
, segments
);
1388 out
.nameSec
= make
<NameSection
>(segments
);
1391 void Writer::run() {
1392 if (config
->relocatable
|| config
->isPic
)
1393 config
->globalBase
= 0;
1395 // For PIC code the table base is assigned dynamically by the loader.
1396 // For non-PIC, we start at 1 so that accessing table index 0 always traps.
1397 if (!config
->isPic
) {
1398 config
->tableBase
= 1;
1399 if (WasmSym::definedTableBase
)
1400 WasmSym::definedTableBase
->setVA(config
->tableBase
);
1401 if (WasmSym::definedTableBase32
)
1402 WasmSym::definedTableBase32
->setVA(config
->tableBase
);
1405 log("-- createOutputSegments");
1406 createOutputSegments();
1407 log("-- createSyntheticSections");
1408 createSyntheticSections();
1409 log("-- layoutMemory");
1412 if (!config
->relocatable
) {
1413 // Create linker synthesized __start_SECNAME/__stop_SECNAME symbols
1414 // This has to be done after memory layout is performed.
1415 for (const OutputSegment
*seg
: segments
) {
1416 addStartStopSymbols(seg
);
1420 for (auto &pair
: config
->exportedSymbols
) {
1421 Symbol
*sym
= symtab
->find(pair
.first());
1422 if (sym
&& sym
->isDefined())
1423 sym
->forceExport
= true;
1426 // Delay reporting error about explict exports until after addStartStopSymbols
1427 // which can create optional symbols.
1428 for (auto &name
: config
->requiredExports
) {
1429 Symbol
*sym
= symtab
->find(name
);
1430 if (!sym
|| !sym
->isDefined()) {
1431 if (config
->unresolvedSymbols
== UnresolvedPolicy::ReportError
)
1432 error(Twine("symbol exported via --export not found: ") + name
);
1433 if (config
->unresolvedSymbols
== UnresolvedPolicy::Warn
)
1434 warn(Twine("symbol exported via --export not found: ") + name
);
1438 if (config
->isPic
&& !config
->sharedMemory
) {
1439 // In shared memory mode all data segments are passive and initilized
1440 // via __wasm_init_memory.
1441 log("-- combineOutputSegments");
1442 combineOutputSegments();
1445 log("-- createSyntheticSectionsPostLayout");
1446 createSyntheticSectionsPostLayout();
1447 log("-- populateProducers");
1448 populateProducers();
1449 log("-- calculateImports");
1451 log("-- scanRelocations");
1453 log("-- finalizeIndirectFunctionTable");
1454 finalizeIndirectFunctionTable();
1455 log("-- createSyntheticInitFunctions");
1456 createSyntheticInitFunctions();
1457 log("-- assignIndexes");
1459 log("-- calculateInitFunctions");
1460 calculateInitFunctions();
1462 if (!config
->relocatable
) {
1463 // Create linker synthesized functions
1464 if (WasmSym::applyDataRelocs
)
1465 createApplyDataRelocationsFunction();
1466 if (WasmSym::applyGlobalRelocs
)
1467 createApplyGlobalRelocationsFunction();
1468 if (WasmSym::initMemory
)
1469 createInitMemoryFunction();
1470 createStartFunction();
1472 createCallCtorsFunction();
1474 // Create export wrappers for commands if needed.
1476 // If the input contains a call to `__wasm_call_ctors`, either in one of
1477 // the input objects or an explicit export from the command-line, we
1478 // assume ctors and dtors are taken care of already.
1479 if (!config
->relocatable
&& !config
->isPic
&&
1480 !WasmSym::callCtors
->isUsedInRegularObj
&&
1481 !WasmSym::callCtors
->isExported()) {
1482 log("-- createCommandExportWrappers");
1483 createCommandExportWrappers();
1487 if (WasmSym::initTLS
&& WasmSym::initTLS
->isLive())
1488 createInitTLSFunction();
1493 log("-- calculateTypes");
1495 log("-- calculateExports");
1497 log("-- calculateCustomSections");
1498 calculateCustomSections();
1499 log("-- populateSymtab");
1501 log("-- populateTargetFeatures");
1502 populateTargetFeatures();
1503 log("-- addSections");
1506 if (errorHandler().verbose
) {
1507 log("Defined Functions: " + Twine(out
.functionSec
->inputFunctions
.size()));
1508 log("Defined Globals : " + Twine(out
.globalSec
->numGlobals()));
1509 log("Defined Tags : " + Twine(out
.tagSec
->inputTags
.size()));
1510 log("Defined Tables : " + Twine(out
.tableSec
->inputTables
.size()));
1511 log("Function Imports : " +
1512 Twine(out
.importSec
->getNumImportedFunctions()));
1513 log("Global Imports : " + Twine(out
.importSec
->getNumImportedGlobals()));
1514 log("Tag Imports : " + Twine(out
.importSec
->getNumImportedTags()));
1515 log("Table Imports : " + Twine(out
.importSec
->getNumImportedTables()));
1516 for (ObjFile
*file
: symtab
->objectFiles
)
1521 log("-- finalizeSections");
1524 log("-- writeMapFile");
1525 writeMapFile(outputSections
);
1534 log("-- writeSections");
1539 if (Error e
= buffer
->commit())
1540 fatal("failed to write the output file: " + toString(std::move(e
)));
1543 // Open a result file.
1544 void Writer::openFile() {
1545 log("writing: " + config
->outputFile
);
1547 Expected
<std::unique_ptr
<FileOutputBuffer
>> bufferOrErr
=
1548 FileOutputBuffer::create(config
->outputFile
, fileSize
,
1549 FileOutputBuffer::F_executable
);
1552 error("failed to open " + config
->outputFile
+ ": " +
1553 toString(bufferOrErr
.takeError()));
1555 buffer
= std::move(*bufferOrErr
);
1558 void Writer::createHeader() {
1559 raw_string_ostream
os(header
);
1560 writeBytes(os
, WasmMagic
, sizeof(WasmMagic
), "wasm magic");
1561 writeU32(os
, WasmVersion
, "wasm version");
1563 fileSize
+= header
.size();
1566 void writeResult() { Writer().run(); }