1 //===- SyntheticSection.h ---------------------------------------*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
9 // Synthetic sections represent chunks of linker-created data. If you
10 // need to create a chunk of data that to be included in some section
11 // in the result, you probably want to create that as a synthetic section.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLD_WASM_SYNTHETIC_SECTIONS_H
16 #define LLD_WASM_SYNTHETIC_SECTIONS_H
18 #include "OutputSections.h"
20 #include "llvm/ADT/SmallSet.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/BinaryFormat/WasmTraits.h"
25 #define DEBUG_TYPE "lld"
29 // An init entry to be written to either the synthetic init func or the
31 struct WasmInitEntry
{
32 const FunctionSymbol
*sym
;
36 class SyntheticSection
: public OutputSection
{
38 SyntheticSection(uint32_t type
, std::string name
= "")
39 : OutputSection(type
, name
), bodyOutputStream(body
) {
41 writeStr(bodyOutputStream
, name
, "section name");
44 void writeTo(uint8_t *buf
) override
{
46 log("writing " + toString(*this));
47 memcpy(buf
+ offset
, header
.data(), header
.size());
48 memcpy(buf
+ offset
+ header
.size(), body
.data(), body
.size());
51 size_t getSize() const override
{ return header
.size() + body
.size(); }
53 virtual void writeBody() {}
55 virtual void assignIndexes() {}
57 void finalizeContents() override
{
59 createHeader(body
.size());
62 raw_ostream
&getStream() { return bodyOutputStream
; }
67 llvm::raw_string_ostream bodyOutputStream
;
70 // Create the custom "dylink" section containing information for the dynamic
73 // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
74 class DylinkSection
: public SyntheticSection
{
76 DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, "dylink.0") {}
77 bool isNeeded() const override
;
78 void writeBody() override
;
80 uint32_t memAlign
= 0;
84 class TypeSection
: public SyntheticSection
{
86 TypeSection() : SyntheticSection(llvm::wasm::WASM_SEC_TYPE
) {}
88 bool isNeeded() const override
{ return types
.size() > 0; };
89 void writeBody() override
;
90 uint32_t registerType(const WasmSignature
&sig
);
91 uint32_t lookupType(const WasmSignature
&sig
);
94 std::vector
<const WasmSignature
*> types
;
95 llvm::DenseMap
<WasmSignature
, int32_t> typeIndices
;
99 * A key for some kind of imported entity of type `T`.
101 * Used when de-duplicating imports.
103 template <typename T
> struct ImportKey
{
105 enum class State
{ Plain
, Empty
, Tombstone
};
109 std::optional
<StringRef
> importModule
;
110 std::optional
<StringRef
> importName
;
114 ImportKey(T type
) : type(type
), state(State::Plain
) {}
115 ImportKey(T type
, State state
) : type(type
), state(state
) {}
116 ImportKey(T type
, std::optional
<StringRef
> importModule
,
117 std::optional
<StringRef
> importName
)
118 : type(type
), importModule(importModule
), importName(importName
),
119 state(State::Plain
) {}
122 template <typename T
>
123 inline bool operator==(const ImportKey
<T
> &lhs
, const ImportKey
<T
> &rhs
) {
124 return lhs
.state
== rhs
.state
&& lhs
.importModule
== rhs
.importModule
&&
125 lhs
.importName
== rhs
.importName
&& lhs
.type
== rhs
.type
;
128 } // namespace wasm::lld
130 // `ImportKey<T>` can be used as a key in a `DenseMap` if `T` can be used as a
131 // key in a `DenseMap`.
133 template <typename T
> struct DenseMapInfo
<lld::wasm::ImportKey
<T
>> {
134 static lld::wasm::ImportKey
<T
> getEmptyKey() {
135 typename
lld::wasm::ImportKey
<T
> key(llvm::DenseMapInfo
<T
>::getEmptyKey());
136 key
.state
= lld::wasm::ImportKey
<T
>::State::Empty
;
139 static lld::wasm::ImportKey
<T
> getTombstoneKey() {
140 typename
lld::wasm::ImportKey
<T
> key(llvm::DenseMapInfo
<T
>::getEmptyKey());
141 key
.state
= lld::wasm::ImportKey
<T
>::State::Tombstone
;
144 static unsigned getHashValue(const lld::wasm::ImportKey
<T
> &key
) {
145 uintptr_t hash
= hash_value(key
.importModule
);
146 hash
= hash_combine(hash
, key
.importName
);
147 hash
= hash_combine(hash
, llvm::DenseMapInfo
<T
>::getHashValue(key
.type
));
148 hash
= hash_combine(hash
, key
.state
);
151 static bool isEqual(const lld::wasm::ImportKey
<T
> &lhs
,
152 const lld::wasm::ImportKey
<T
> &rhs
) {
156 } // end namespace llvm
161 class ImportSection
: public SyntheticSection
{
163 ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT
) {}
164 bool isNeeded() const override
{ return getNumImports() > 0; }
165 void writeBody() override
;
166 void addImport(Symbol
*sym
);
167 void addGOTEntry(Symbol
*sym
);
168 void seal() { isSealed
= true; }
169 uint32_t getNumImports() const;
170 uint32_t getNumImportedGlobals() const {
172 return numImportedGlobals
;
174 uint32_t getNumImportedFunctions() const {
176 return numImportedFunctions
;
178 uint32_t getNumImportedTags() const {
180 return numImportedTags
;
182 uint32_t getNumImportedTables() const {
184 return numImportedTables
;
187 std::vector
<const Symbol
*> importedSymbols
;
188 std::vector
<const Symbol
*> gotSymbols
;
191 bool isSealed
= false;
192 unsigned numImportedGlobals
= 0;
193 unsigned numImportedFunctions
= 0;
194 unsigned numImportedTags
= 0;
195 unsigned numImportedTables
= 0;
196 llvm::DenseMap
<ImportKey
<WasmGlobalType
>, uint32_t> importedGlobals
;
197 llvm::DenseMap
<ImportKey
<WasmSignature
>, uint32_t> importedFunctions
;
198 llvm::DenseMap
<ImportKey
<WasmTableType
>, uint32_t> importedTables
;
199 llvm::DenseMap
<ImportKey
<WasmSignature
>, uint32_t> importedTags
;
202 class FunctionSection
: public SyntheticSection
{
204 FunctionSection() : SyntheticSection(llvm::wasm::WASM_SEC_FUNCTION
) {}
206 bool isNeeded() const override
{ return inputFunctions
.size() > 0; };
207 void writeBody() override
;
208 void addFunction(InputFunction
*func
);
210 std::vector
<InputFunction
*> inputFunctions
;
215 class TableSection
: public SyntheticSection
{
217 TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE
) {}
219 bool isNeeded() const override
{ return inputTables
.size() > 0; };
220 void assignIndexes() override
;
221 void writeBody() override
;
222 void addTable(InputTable
*table
);
224 std::vector
<InputTable
*> inputTables
;
227 class MemorySection
: public SyntheticSection
{
229 MemorySection() : SyntheticSection(llvm::wasm::WASM_SEC_MEMORY
) {}
231 bool isNeeded() const override
{ return !config
->memoryImport
.has_value(); }
232 void writeBody() override
;
234 uint64_t numMemoryPages
= 0;
235 uint64_t maxMemoryPages
= 0;
238 // The tag section contains a list of declared wasm tags associated with the
239 // module. Currently the only supported tag kind is exceptions. All C++
240 // exceptions are represented by a single tag. A tag entry in this section
241 // contains information on what kind of tag it is (e.g. exception) and the type
242 // of values associated with the tag. (In Wasm, a tag can contain multiple
243 // values of primitive types. But for C++ exceptions, we just throw a pointer
244 // which is an i32 value (for wasm32 architecture), so the signature of C++
245 // exception is (i32)->(void), because all exception tag types are assumed to
246 // have void return type to share WasmSignature with functions.)
247 class TagSection
: public SyntheticSection
{
249 TagSection() : SyntheticSection(llvm::wasm::WASM_SEC_TAG
) {}
250 void writeBody() override
;
251 bool isNeeded() const override
{ return inputTags
.size() > 0; }
252 void addTag(InputTag
*tag
);
254 std::vector
<InputTag
*> inputTags
;
257 class GlobalSection
: public SyntheticSection
{
259 GlobalSection() : SyntheticSection(llvm::wasm::WASM_SEC_GLOBAL
) {}
261 static bool classof(const OutputSection
*sec
) {
262 return sec
->type
== llvm::wasm::WASM_SEC_GLOBAL
;
265 uint32_t numGlobals() const {
267 return inputGlobals
.size() + dataAddressGlobals
.size() +
268 internalGotSymbols
.size();
270 bool isNeeded() const override
{ return numGlobals() > 0; }
271 void assignIndexes() override
;
272 void writeBody() override
;
273 void addGlobal(InputGlobal
*global
);
275 // Add an internal GOT entry global that corresponds to the given symbol.
276 // Normally GOT entries are imported and assigned by the external dynamic
277 // linker. However, when linking PIC code statically or when linking with
278 // -Bsymbolic we can internalize GOT entries by declaring globals the hold
281 // For the static linking case these internal globals can be completely
282 // eliminated by a post-link optimizer such as wasm-opt.
284 // TODO(sbc): Another approach to optimizing these away could be to use
285 // specific relocation types combined with linker relaxation which could
286 // transform a `global.get` to an `i32.const`.
287 void addInternalGOTEntry(Symbol
*sym
);
288 bool needsRelocations() {
289 if (config
->extendedConst
)
291 return llvm::any_of(internalGotSymbols
,
292 [=](Symbol
*sym
) { return !sym
->isTLS(); });
294 bool needsTLSRelocations() {
295 return llvm::any_of(internalGotSymbols
,
296 [=](Symbol
*sym
) { return sym
->isTLS(); });
298 void generateRelocationCode(raw_ostream
&os
, bool TLS
) const;
300 std::vector
<DefinedData
*> dataAddressGlobals
;
301 std::vector
<InputGlobal
*> inputGlobals
;
302 std::vector
<Symbol
*> internalGotSymbols
;
305 bool isSealed
= false;
308 class ExportSection
: public SyntheticSection
{
310 ExportSection() : SyntheticSection(llvm::wasm::WASM_SEC_EXPORT
) {}
311 bool isNeeded() const override
{ return exports
.size() > 0; }
312 void writeBody() override
;
314 std::vector
<llvm::wasm::WasmExport
> exports
;
315 std::vector
<const Symbol
*> exportedSymbols
;
318 class StartSection
: public SyntheticSection
{
320 StartSection() : SyntheticSection(llvm::wasm::WASM_SEC_START
) {}
321 bool isNeeded() const override
;
322 void writeBody() override
;
325 class ElemSection
: public SyntheticSection
{
328 : SyntheticSection(llvm::wasm::WASM_SEC_ELEM
) {}
329 bool isNeeded() const override
{ return indirectFunctions
.size() > 0; };
330 void writeBody() override
;
331 void addEntry(FunctionSymbol
*sym
);
332 uint32_t numEntries() const { return indirectFunctions
.size(); }
335 std::vector
<const FunctionSymbol
*> indirectFunctions
;
338 class DataCountSection
: public SyntheticSection
{
340 DataCountSection(ArrayRef
<OutputSegment
*> segments
);
341 bool isNeeded() const override
;
342 void writeBody() override
;
345 uint32_t numSegments
;
348 // Create the custom "linking" section containing linker metadata.
349 // This is only created when relocatable output is requested.
350 class LinkingSection
: public SyntheticSection
{
352 LinkingSection(const std::vector
<WasmInitEntry
> &initFunctions
,
353 const std::vector
<OutputSegment
*> &dataSegments
)
354 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, "linking"),
355 initFunctions(initFunctions
), dataSegments(dataSegments
) {}
356 bool isNeeded() const override
{
357 return config
->relocatable
|| config
->emitRelocs
;
359 void writeBody() override
;
360 void addToSymtab(Symbol
*sym
);
363 std::vector
<const Symbol
*> symtabEntries
;
364 llvm::StringMap
<uint32_t> sectionSymbolIndices
;
365 const std::vector
<WasmInitEntry
> &initFunctions
;
366 const std::vector
<OutputSegment
*> &dataSegments
;
369 // Create the custom "name" section containing debug symbol names.
370 class NameSection
: public SyntheticSection
{
372 NameSection(ArrayRef
<OutputSegment
*> segments
)
373 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, "name"),
374 segments(segments
) {}
375 bool isNeeded() const override
{
376 if (config
->stripAll
&& !config
->keepSections
.count(name
))
378 return numNames() > 0;
380 void writeBody() override
;
381 unsigned numNames() const {
382 // We always write at least one name which is the name of the
384 return 1 + numNamedGlobals() + numNamedFunctions();
386 unsigned numNamedGlobals() const;
387 unsigned numNamedFunctions() const;
388 unsigned numNamedDataSegments() const;
391 ArrayRef
<OutputSegment
*> segments
;
394 class ProducersSection
: public SyntheticSection
{
397 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, "producers") {}
398 bool isNeeded() const override
{
399 if (config
->stripAll
&& !config
->keepSections
.count(name
))
401 return fieldCount() > 0;
403 void writeBody() override
;
404 void addInfo(const llvm::wasm::WasmProducerInfo
&info
);
407 int fieldCount() const {
408 return int(!languages
.empty()) + int(!tools
.empty()) + int(!sDKs
.empty());
410 SmallVector
<std::pair
<std::string
, std::string
>, 8> languages
;
411 SmallVector
<std::pair
<std::string
, std::string
>, 8> tools
;
412 SmallVector
<std::pair
<std::string
, std::string
>, 8> sDKs
;
415 class TargetFeaturesSection
: public SyntheticSection
{
417 TargetFeaturesSection()
418 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, "target_features") {}
419 bool isNeeded() const override
{
420 if (config
->stripAll
&& !config
->keepSections
.count(name
))
422 return features
.size() > 0;
424 void writeBody() override
;
426 llvm::SmallSet
<std::string
, 8> features
;
429 class RelocSection
: public SyntheticSection
{
431 RelocSection(StringRef name
, OutputSection
*sec
)
432 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, std::string(name
)),
434 void writeBody() override
;
435 bool isNeeded() const override
{ return sec
->getNumRelocations() > 0; };
441 class BuildIdSection
: public SyntheticSection
{
444 void writeBody() override
;
445 bool isNeeded() const override
{
446 return config
->buildId
!= BuildIdKind::None
;
448 void writeBuildId(llvm::ArrayRef
<uint8_t> buf
);
449 void writeTo(uint8_t *buf
) override
{
450 LLVM_DEBUG(llvm::dbgs()
451 << "BuildId writeto buf " << buf
<< " offset " << offset
452 << " headersize " << header
.size() << '\n');
453 // The actual build ID is derived from a hash of all of the output
454 // sections, so it can't be calculated until they are written. Here
455 // we write the section leaving zeros in place of the hash.
456 SyntheticSection::writeTo(buf
);
457 // Calculate and store the location where the hash will be written.
458 hashPlaceholderPtr
= buf
+ offset
+ header
.size() +
459 +sizeof(buildIdSectionName
) /*name string*/ +
463 const uint32_t hashSize
;
466 static constexpr char buildIdSectionName
[] = "build_id";
467 uint8_t *hashPlaceholderPtr
= nullptr;
470 // Linker generated output sections
472 DylinkSection
*dylinkSec
;
473 TypeSection
*typeSec
;
474 FunctionSection
*functionSec
;
475 ImportSection
*importSec
;
476 TableSection
*tableSec
;
477 MemorySection
*memorySec
;
478 GlobalSection
*globalSec
;
480 ExportSection
*exportSec
;
481 StartSection
*startSec
;
482 ElemSection
*elemSec
;
483 DataCountSection
*dataCountSec
;
484 LinkingSection
*linkingSec
;
485 NameSection
*nameSec
;
486 ProducersSection
*producersSec
;
487 TargetFeaturesSection
*targetFeaturesSec
;
488 BuildIdSection
*buildIdSec
;
491 extern OutStruct out
;