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 bodyOutputStream
.flush();
60 createHeader(body
.size());
63 raw_ostream
&getStream() { return bodyOutputStream
; }
68 llvm::raw_string_ostream bodyOutputStream
;
71 // Create the custom "dylink" section containing information for the dynamic
74 // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
75 class DylinkSection
: public SyntheticSection
{
77 DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, "dylink.0") {}
78 bool isNeeded() const override
;
79 void writeBody() override
;
81 uint32_t memAlign
= 0;
85 class TypeSection
: public SyntheticSection
{
87 TypeSection() : SyntheticSection(llvm::wasm::WASM_SEC_TYPE
) {}
89 bool isNeeded() const override
{ return types
.size() > 0; };
90 void writeBody() override
;
91 uint32_t registerType(const WasmSignature
&sig
);
92 uint32_t lookupType(const WasmSignature
&sig
);
95 std::vector
<const WasmSignature
*> types
;
96 llvm::DenseMap
<WasmSignature
, int32_t> typeIndices
;
100 * A key for some kind of imported entity of type `T`.
102 * Used when de-duplicating imports.
104 template <typename T
> struct ImportKey
{
106 enum class State
{ Plain
, Empty
, Tombstone
};
110 std::optional
<StringRef
> importModule
;
111 std::optional
<StringRef
> importName
;
115 ImportKey(T type
) : type(type
), state(State::Plain
) {}
116 ImportKey(T type
, State state
) : type(type
), state(state
) {}
117 ImportKey(T type
, std::optional
<StringRef
> importModule
,
118 std::optional
<StringRef
> importName
)
119 : type(type
), importModule(importModule
), importName(importName
),
120 state(State::Plain
) {}
123 template <typename T
>
124 inline bool operator==(const ImportKey
<T
> &lhs
, const ImportKey
<T
> &rhs
) {
125 return lhs
.state
== rhs
.state
&& lhs
.importModule
== rhs
.importModule
&&
126 lhs
.importName
== rhs
.importName
&& lhs
.type
== rhs
.type
;
129 } // namespace wasm::lld
131 // `ImportKey<T>` can be used as a key in a `DenseMap` if `T` can be used as a
132 // key in a `DenseMap`.
134 template <typename T
> struct DenseMapInfo
<lld::wasm::ImportKey
<T
>> {
135 static lld::wasm::ImportKey
<T
> getEmptyKey() {
136 typename
lld::wasm::ImportKey
<T
> key(llvm::DenseMapInfo
<T
>::getEmptyKey());
137 key
.state
= lld::wasm::ImportKey
<T
>::State::Empty
;
140 static lld::wasm::ImportKey
<T
> getTombstoneKey() {
141 typename
lld::wasm::ImportKey
<T
> key(llvm::DenseMapInfo
<T
>::getEmptyKey());
142 key
.state
= lld::wasm::ImportKey
<T
>::State::Tombstone
;
145 static unsigned getHashValue(const lld::wasm::ImportKey
<T
> &key
) {
146 uintptr_t hash
= hash_value(key
.importModule
);
147 hash
= hash_combine(hash
, key
.importName
);
148 hash
= hash_combine(hash
, llvm::DenseMapInfo
<T
>::getHashValue(key
.type
));
149 hash
= hash_combine(hash
, key
.state
);
152 static bool isEqual(const lld::wasm::ImportKey
<T
> &lhs
,
153 const lld::wasm::ImportKey
<T
> &rhs
) {
157 } // end namespace llvm
162 class ImportSection
: public SyntheticSection
{
164 ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT
) {}
165 bool isNeeded() const override
{ return getNumImports() > 0; }
166 void writeBody() override
;
167 void addImport(Symbol
*sym
);
168 void addGOTEntry(Symbol
*sym
);
169 void seal() { isSealed
= true; }
170 uint32_t getNumImports() const;
171 uint32_t getNumImportedGlobals() const {
173 return numImportedGlobals
;
175 uint32_t getNumImportedFunctions() const {
177 return numImportedFunctions
;
179 uint32_t getNumImportedTags() const {
181 return numImportedTags
;
183 uint32_t getNumImportedTables() const {
185 return numImportedTables
;
188 std::vector
<const Symbol
*> importedSymbols
;
189 std::vector
<const Symbol
*> gotSymbols
;
192 bool isSealed
= false;
193 unsigned numImportedGlobals
= 0;
194 unsigned numImportedFunctions
= 0;
195 unsigned numImportedTags
= 0;
196 unsigned numImportedTables
= 0;
197 llvm::DenseMap
<ImportKey
<WasmGlobalType
>, uint32_t> importedGlobals
;
198 llvm::DenseMap
<ImportKey
<WasmSignature
>, uint32_t> importedFunctions
;
199 llvm::DenseMap
<ImportKey
<WasmTableType
>, uint32_t> importedTables
;
200 llvm::DenseMap
<ImportKey
<WasmSignature
>, uint32_t> importedTags
;
203 class FunctionSection
: public SyntheticSection
{
205 FunctionSection() : SyntheticSection(llvm::wasm::WASM_SEC_FUNCTION
) {}
207 bool isNeeded() const override
{ return inputFunctions
.size() > 0; };
208 void writeBody() override
;
209 void addFunction(InputFunction
*func
);
211 std::vector
<InputFunction
*> inputFunctions
;
216 class TableSection
: public SyntheticSection
{
218 TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE
) {}
220 bool isNeeded() const override
{ return inputTables
.size() > 0; };
221 void assignIndexes() override
;
222 void writeBody() override
;
223 void addTable(InputTable
*table
);
225 std::vector
<InputTable
*> inputTables
;
228 class MemorySection
: public SyntheticSection
{
230 MemorySection() : SyntheticSection(llvm::wasm::WASM_SEC_MEMORY
) {}
232 bool isNeeded() const override
{ return !config
->memoryImport
.has_value(); }
233 void writeBody() override
;
235 uint64_t numMemoryPages
= 0;
236 uint64_t maxMemoryPages
= 0;
239 // The tag section contains a list of declared wasm tags associated with the
240 // module. Currently the only supported tag kind is exceptions. All C++
241 // exceptions are represented by a single tag. A tag entry in this section
242 // contains information on what kind of tag it is (e.g. exception) and the type
243 // of values associated with the tag. (In Wasm, a tag can contain multiple
244 // values of primitive types. But for C++ exceptions, we just throw a pointer
245 // which is an i32 value (for wasm32 architecture), so the signature of C++
246 // exception is (i32)->(void), because all exception tag types are assumed to
247 // have void return type to share WasmSignature with functions.)
248 class TagSection
: public SyntheticSection
{
250 TagSection() : SyntheticSection(llvm::wasm::WASM_SEC_TAG
) {}
251 void writeBody() override
;
252 bool isNeeded() const override
{ return inputTags
.size() > 0; }
253 void addTag(InputTag
*tag
);
255 std::vector
<InputTag
*> inputTags
;
258 class GlobalSection
: public SyntheticSection
{
260 GlobalSection() : SyntheticSection(llvm::wasm::WASM_SEC_GLOBAL
) {}
262 static bool classof(const OutputSection
*sec
) {
263 return sec
->type
== llvm::wasm::WASM_SEC_GLOBAL
;
266 uint32_t numGlobals() const {
268 return inputGlobals
.size() + dataAddressGlobals
.size() +
269 internalGotSymbols
.size();
271 bool isNeeded() const override
{ return numGlobals() > 0; }
272 void assignIndexes() override
;
273 void writeBody() override
;
274 void addGlobal(InputGlobal
*global
);
276 // Add an internal GOT entry global that corresponds to the given symbol.
277 // Normally GOT entries are imported and assigned by the external dynamic
278 // linker. However, when linking PIC code statically or when linking with
279 // -Bsymbolic we can internalize GOT entries by declaring globals the hold
282 // For the static linking case these internal globals can be completely
283 // eliminated by a post-link optimizer such as wasm-opt.
285 // TODO(sbc): Another approach to optimizing these away could be to use
286 // specific relocation types combined with linker relaxation which could
287 // transform a `global.get` to an `i32.const`.
288 void addInternalGOTEntry(Symbol
*sym
);
289 bool needsRelocations() {
290 if (config
->extendedConst
)
292 return llvm::any_of(internalGotSymbols
,
293 [=](Symbol
*sym
) { return !sym
->isTLS(); });
295 bool needsTLSRelocations() {
296 return llvm::any_of(internalGotSymbols
,
297 [=](Symbol
*sym
) { return sym
->isTLS(); });
299 void generateRelocationCode(raw_ostream
&os
, bool TLS
) const;
301 std::vector
<DefinedData
*> dataAddressGlobals
;
302 std::vector
<InputGlobal
*> inputGlobals
;
303 std::vector
<Symbol
*> internalGotSymbols
;
306 bool isSealed
= false;
309 class ExportSection
: public SyntheticSection
{
311 ExportSection() : SyntheticSection(llvm::wasm::WASM_SEC_EXPORT
) {}
312 bool isNeeded() const override
{ return exports
.size() > 0; }
313 void writeBody() override
;
315 std::vector
<llvm::wasm::WasmExport
> exports
;
316 std::vector
<const Symbol
*> exportedSymbols
;
319 class StartSection
: public SyntheticSection
{
321 StartSection() : SyntheticSection(llvm::wasm::WASM_SEC_START
) {}
322 bool isNeeded() const override
;
323 void writeBody() override
;
326 class ElemSection
: public SyntheticSection
{
329 : SyntheticSection(llvm::wasm::WASM_SEC_ELEM
) {}
330 bool isNeeded() const override
{ return indirectFunctions
.size() > 0; };
331 void writeBody() override
;
332 void addEntry(FunctionSymbol
*sym
);
333 uint32_t numEntries() const { return indirectFunctions
.size(); }
336 std::vector
<const FunctionSymbol
*> indirectFunctions
;
339 class DataCountSection
: public SyntheticSection
{
341 DataCountSection(ArrayRef
<OutputSegment
*> segments
);
342 bool isNeeded() const override
;
343 void writeBody() override
;
346 uint32_t numSegments
;
349 // Create the custom "linking" section containing linker metadata.
350 // This is only created when relocatable output is requested.
351 class LinkingSection
: public SyntheticSection
{
353 LinkingSection(const std::vector
<WasmInitEntry
> &initFunctions
,
354 const std::vector
<OutputSegment
*> &dataSegments
)
355 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, "linking"),
356 initFunctions(initFunctions
), dataSegments(dataSegments
) {}
357 bool isNeeded() const override
{
358 return config
->relocatable
|| config
->emitRelocs
;
360 void writeBody() override
;
361 void addToSymtab(Symbol
*sym
);
364 std::vector
<const Symbol
*> symtabEntries
;
365 llvm::StringMap
<uint32_t> sectionSymbolIndices
;
366 const std::vector
<WasmInitEntry
> &initFunctions
;
367 const std::vector
<OutputSegment
*> &dataSegments
;
370 // Create the custom "name" section containing debug symbol names.
371 class NameSection
: public SyntheticSection
{
373 NameSection(ArrayRef
<OutputSegment
*> segments
)
374 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, "name"),
375 segments(segments
) {}
376 bool isNeeded() const override
{ return !config
->stripAll
&& numNames() > 0; }
377 void writeBody() override
;
378 unsigned numNames() const {
379 // We always write at least one name which is the name of the
381 return 1 + numNamedGlobals() + numNamedFunctions();
383 unsigned numNamedGlobals() const;
384 unsigned numNamedFunctions() const;
385 unsigned numNamedDataSegments() const;
388 ArrayRef
<OutputSegment
*> segments
;
391 class ProducersSection
: public SyntheticSection
{
394 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, "producers") {}
395 bool isNeeded() const override
{
396 return !config
->stripAll
&& fieldCount() > 0;
398 void writeBody() override
;
399 void addInfo(const llvm::wasm::WasmProducerInfo
&info
);
402 int fieldCount() const {
403 return int(!languages
.empty()) + int(!tools
.empty()) + int(!sDKs
.empty());
405 SmallVector
<std::pair
<std::string
, std::string
>, 8> languages
;
406 SmallVector
<std::pair
<std::string
, std::string
>, 8> tools
;
407 SmallVector
<std::pair
<std::string
, std::string
>, 8> sDKs
;
410 class TargetFeaturesSection
: public SyntheticSection
{
412 TargetFeaturesSection()
413 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, "target_features") {}
414 bool isNeeded() const override
{
415 return !config
->stripAll
&& features
.size() > 0;
417 void writeBody() override
;
419 llvm::SmallSet
<std::string
, 8> features
;
422 class RelocSection
: public SyntheticSection
{
424 RelocSection(StringRef name
, OutputSection
*sec
)
425 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, std::string(name
)),
427 void writeBody() override
;
428 bool isNeeded() const override
{ return sec
->getNumRelocations() > 0; };
434 class BuildIdSection
: public SyntheticSection
{
437 void writeBody() override
;
438 bool isNeeded() const override
{
439 return config
->buildId
!= BuildIdKind::None
;
441 void writeBuildId(llvm::ArrayRef
<uint8_t> buf
);
442 void writeTo(uint8_t *buf
) override
{
443 LLVM_DEBUG(llvm::dbgs()
444 << "BuildId writeto buf " << buf
<< " offset " << offset
445 << " headersize " << header
.size() << '\n');
446 // The actual build ID is derived from a hash of all of the output
447 // sections, so it can't be calculated until they are written. Here
448 // we write the section leaving zeros in place of the hash.
449 SyntheticSection::writeTo(buf
);
450 // Calculate and store the location where the hash will be written.
451 hashPlaceholderPtr
= buf
+ offset
+ header
.size() +
452 +sizeof(buildIdSectionName
) /*name string*/ +
456 const uint32_t hashSize
;
459 static constexpr char buildIdSectionName
[] = "build_id";
460 uint8_t *hashPlaceholderPtr
= nullptr;
463 // Linker generated output sections
465 DylinkSection
*dylinkSec
;
466 TypeSection
*typeSec
;
467 FunctionSection
*functionSec
;
468 ImportSection
*importSec
;
469 TableSection
*tableSec
;
470 MemorySection
*memorySec
;
471 GlobalSection
*globalSec
;
473 ExportSection
*exportSec
;
474 StartSection
*startSec
;
475 ElemSection
*elemSec
;
476 DataCountSection
*dataCountSec
;
477 LinkingSection
*linkingSec
;
478 NameSection
*nameSec
;
479 ProducersSection
*producersSec
;
480 TargetFeaturesSection
*targetFeaturesSec
;
481 BuildIdSection
*buildIdSec
;
484 extern OutStruct out
;