xref: /llvm-project/lld/wasm/Symbols.h (revision 3792b36234b6c87d728f0a905543e284bf961460)
1 //===- Symbols.h ------------------------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLD_WASM_SYMBOLS_H
10 #define LLD_WASM_SYMBOLS_H
11 
12 #include "Config.h"
13 #include "lld/Common/LLVM.h"
14 #include "llvm/Object/Archive.h"
15 #include "llvm/Object/Wasm.h"
16 #include <optional>
17 
18 namespace lld {
19 namespace wasm {
20 
21 // Shared string constants
22 
23 // The default module name to use for symbol imports.
24 extern const char *defaultModule;
25 
26 // The name under which to import or export the wasm table.
27 extern const char *functionTableName;
28 
29 // The name under which to import or export the wasm memory.
30 extern const char *memoryName;
31 
32 using llvm::wasm::WasmSymbolType;
33 
34 class InputFile;
35 class InputChunk;
36 class InputSegment;
37 class InputFunction;
38 class InputGlobal;
39 class InputTag;
40 class InputSection;
41 class InputTable;
42 class OutputSection;
43 
44 #define INVALID_INDEX UINT32_MAX
45 
46 // The base class for real symbol classes.
47 class Symbol {
48 public:
49   enum Kind : uint8_t {
50     DefinedFunctionKind,
51     DefinedDataKind,
52     DefinedGlobalKind,
53     DefinedTagKind,
54     DefinedTableKind,
55     SectionKind,
56     OutputSectionKind,
57     UndefinedFunctionKind,
58     UndefinedDataKind,
59     UndefinedGlobalKind,
60     UndefinedTableKind,
61     UndefinedTagKind,
62     LazyKind,
63     SharedFunctionKind,
64     SharedDataKind,
65   };
66 
67   Kind kind() const { return symbolKind; }
68 
69   bool isDefined() const { return !isLazy() && !isUndefined(); }
70 
71   bool isUndefined() const {
72     return symbolKind == UndefinedFunctionKind ||
73            symbolKind == UndefinedDataKind ||
74            symbolKind == UndefinedGlobalKind ||
75            symbolKind == UndefinedTableKind || symbolKind == UndefinedTagKind;
76   }
77 
78   bool isLazy() const { return symbolKind == LazyKind; }
79   bool isShared() const {
80     return symbolKind == SharedFunctionKind || symbolKind == SharedDataKind;
81   }
82 
83   bool isLocal() const;
84   bool isWeak() const;
85   bool isHidden() const;
86   bool isTLS() const;
87 
88   // Returns true if this symbol exists in a discarded (due to COMDAT) section
89   bool isDiscarded() const;
90 
91   // True if this is an undefined weak symbol. This only works once
92   // all input files have been added.
93   bool isUndefWeak() const {
94     // See comment on lazy symbols for details.
95     return isWeak() && (isUndefined() || isLazy());
96   }
97 
98   // Returns the symbol name.
99   StringRef getName() const { return name; }
100 
101   // Returns the file from which this symbol was created.
102   InputFile *getFile() const { return file; }
103 
104   InputChunk *getChunk() const;
105 
106   // Indicates that the section or import for this symbol will be included in
107   // the final image.
108   bool isLive() const;
109 
110   // Marks the symbol's InputChunk as Live, so that it will be included in the
111   // final image.
112   void markLive();
113 
114   void setHidden(bool isHidden);
115 
116   // Get/set the index in the output symbol table.  This is only used for
117   // relocatable output.
118   uint32_t getOutputSymbolIndex() const;
119   void setOutputSymbolIndex(uint32_t index);
120 
121   WasmSymbolType getWasmType() const;
122   bool isImported() const;
123   bool isExported() const;
124   bool isExportedExplicit() const;
125 
126   // Indicates that the symbol is used in an __attribute__((used)) directive
127   // or similar.
128   bool isNoStrip() const;
129 
130   const WasmSignature* getSignature() const;
131 
132   uint32_t getGOTIndex() const {
133     assert(gotIndex != INVALID_INDEX);
134     return gotIndex;
135   }
136 
137   void setGOTIndex(uint32_t index);
138   bool hasGOTIndex() const { return gotIndex != INVALID_INDEX; }
139 
140 protected:
141   Symbol(StringRef name, Kind k, uint32_t flags, InputFile *f)
142       : name(name), file(f), symbolKind(k), referenced(!ctx.arg.gcSections),
143         requiresGOT(false), isUsedInRegularObj(false), forceExport(false),
144         forceImport(false), canInline(false), traced(false), isStub(false),
145         flags(flags) {}
146 
147   StringRef name;
148   InputFile *file;
149   uint32_t outputSymbolIndex = INVALID_INDEX;
150   uint32_t gotIndex = INVALID_INDEX;
151   Kind symbolKind;
152 
153 public:
154   bool referenced : 1;
155 
156   // True for data symbols that needs a dummy GOT entry.  Used for static
157   // linking of GOT accesses.
158   bool requiresGOT : 1;
159 
160   // True if the symbol was used for linking and thus need to be added to the
161   // output file's symbol table. This is true for all symbols except for
162   // unreferenced DSO symbols, lazy (archive) symbols, and bitcode symbols that
163   // are unreferenced except by other bitcode objects.
164   bool isUsedInRegularObj : 1;
165 
166   // True if this symbol is explicitly marked for export (i.e. via the
167   // -e/--export command line flag)
168   bool forceExport : 1;
169 
170   bool forceImport : 1;
171 
172   // False if LTO shouldn't inline whatever this symbol points to. If a symbol
173   // is overwritten after LTO, LTO shouldn't inline the symbol because it
174   // doesn't know the final contents of the symbol.
175   bool canInline : 1;
176 
177   // True if this symbol is specified by --trace-symbol option.
178   bool traced : 1;
179 
180   // True if this symbol is a linker-synthesized stub function (traps when
181   // called) and should otherwise be treated as missing/undefined.  See
182   // SymbolTable::replaceWithUndefined.
183   // These stubs never appear in the table and any table index relocations
184   // against them will produce address 0 (The table index representing
185   // the null function pointer).
186   bool isStub : 1;
187 
188   uint32_t flags;
189 
190   std::optional<StringRef> importName;
191   std::optional<StringRef> importModule;
192 };
193 
194 class FunctionSymbol : public Symbol {
195 public:
196   static bool classof(const Symbol *s) {
197     return s->kind() == DefinedFunctionKind ||
198            s->kind() == SharedFunctionKind ||
199            s->kind() == UndefinedFunctionKind;
200   }
201 
202   // Get/set the table index
203   void setTableIndex(uint32_t index);
204   uint32_t getTableIndex() const;
205   bool hasTableIndex() const;
206 
207   // Get/set the function index
208   uint32_t getFunctionIndex() const;
209   void setFunctionIndex(uint32_t index);
210   bool hasFunctionIndex() const;
211 
212   const WasmSignature *signature;
213 
214 protected:
215   FunctionSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f,
216                  const WasmSignature *sig)
217       : Symbol(name, k, flags, f), signature(sig) {}
218 
219   uint32_t tableIndex = INVALID_INDEX;
220   uint32_t functionIndex = INVALID_INDEX;
221 };
222 
223 class DefinedFunction : public FunctionSymbol {
224 public:
225   DefinedFunction(StringRef name, uint32_t flags, InputFile *f,
226                   InputFunction *function);
227 
228   static bool classof(const Symbol *s) {
229     return s->kind() == DefinedFunctionKind;
230   }
231 
232   // Get the function index to be used when exporting.  This only applies to
233   // defined functions and can be differ from the regular function index for
234   // weakly defined functions (that are imported and used via one index but
235   // defined and exported via another).
236   uint32_t getExportedFunctionIndex() const;
237 
238   InputFunction *function;
239 };
240 
241 class UndefinedFunction : public FunctionSymbol {
242 public:
243   UndefinedFunction(StringRef name, std::optional<StringRef> importName,
244                     std::optional<StringRef> importModule, uint32_t flags,
245                     InputFile *file = nullptr,
246                     const WasmSignature *type = nullptr,
247                     bool isCalledDirectly = true)
248       : FunctionSymbol(name, UndefinedFunctionKind, flags, file, type),
249         isCalledDirectly(isCalledDirectly) {
250     this->importName = importName;
251     this->importModule = importModule;
252   }
253 
254   static bool classof(const Symbol *s) {
255     return s->kind() == UndefinedFunctionKind;
256   }
257 
258   DefinedFunction *stubFunction = nullptr;
259   bool isCalledDirectly;
260 };
261 
262 // Section symbols for output sections are different from those for input
263 // section.  These are generated by the linker and point the OutputSection
264 // rather than an InputSection.
265 class OutputSectionSymbol : public Symbol {
266 public:
267   OutputSectionSymbol(const OutputSection *s)
268       : Symbol("", OutputSectionKind, llvm::wasm::WASM_SYMBOL_BINDING_LOCAL,
269                nullptr),
270         section(s) {}
271 
272   static bool classof(const Symbol *s) {
273     return s->kind() == OutputSectionKind;
274   }
275 
276   const OutputSection *section;
277 };
278 
279 class SectionSymbol : public Symbol {
280 public:
281   SectionSymbol(uint32_t flags, const InputChunk *s, InputFile *f = nullptr)
282       : Symbol("", SectionKind, flags, f), section(s) {}
283 
284   static bool classof(const Symbol *s) { return s->kind() == SectionKind; }
285 
286   const OutputSectionSymbol *getOutputSectionSymbol() const;
287 
288   const InputChunk *section;
289 };
290 
291 class DataSymbol : public Symbol {
292 public:
293   static bool classof(const Symbol *s) {
294     return s->kind() == DefinedDataKind || s->kind() == UndefinedDataKind ||
295            s->kind() == SharedDataKind;
296   }
297 
298 protected:
299   DataSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f)
300       : Symbol(name, k, flags, f) {}
301 };
302 
303 class DefinedData : public DataSymbol {
304 public:
305   // Constructor for regular data symbols originating from input files.
306   DefinedData(StringRef name, uint32_t flags, InputFile *f, InputChunk *segment,
307               uint64_t value, uint64_t size)
308       : DataSymbol(name, DefinedDataKind, flags, f), segment(segment),
309         value(value), size(size) {}
310 
311   // Constructor for linker synthetic data symbols.
312   DefinedData(StringRef name, uint32_t flags)
313       : DataSymbol(name, DefinedDataKind, flags, nullptr) {}
314 
315   static bool classof(const Symbol *s) { return s->kind() == DefinedDataKind; }
316 
317   // Returns the output virtual address of a defined data symbol.
318   // For TLS symbols, by default (unless absolute is set), this returns an
319   // address relative the `__tls_base`.
320   uint64_t getVA(bool absolute = false) const;
321   void setVA(uint64_t va);
322 
323   // Returns the offset of a defined data symbol within its OutputSegment.
324   uint64_t getOutputSegmentOffset() const;
325   uint64_t getOutputSegmentIndex() const;
326   uint64_t getSize() const { return size; }
327 
328   InputChunk *segment = nullptr;
329   uint64_t value = 0;
330 
331 protected:
332   uint64_t size = 0;
333 };
334 
335 class SharedData : public DataSymbol {
336 public:
337   SharedData(StringRef name, uint32_t flags, InputFile *f)
338       : DataSymbol(name, SharedDataKind, flags, f) {}
339 };
340 
341 class UndefinedData : public DataSymbol {
342 public:
343   UndefinedData(StringRef name, uint32_t flags, InputFile *file = nullptr)
344       : DataSymbol(name, UndefinedDataKind, flags, file) {}
345   static bool classof(const Symbol *s) {
346     return s->kind() == UndefinedDataKind;
347   }
348 };
349 
350 class GlobalSymbol : public Symbol {
351 public:
352   static bool classof(const Symbol *s) {
353     return s->kind() == DefinedGlobalKind || s->kind() == UndefinedGlobalKind;
354   }
355 
356   const WasmGlobalType *getGlobalType() const { return globalType; }
357 
358   // Get/set the global index
359   uint32_t getGlobalIndex() const;
360   void setGlobalIndex(uint32_t index);
361   bool hasGlobalIndex() const;
362 
363 protected:
364   GlobalSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f,
365                const WasmGlobalType *globalType)
366       : Symbol(name, k, flags, f), globalType(globalType) {}
367 
368   const WasmGlobalType *globalType;
369   uint32_t globalIndex = INVALID_INDEX;
370 };
371 
372 class DefinedGlobal : public GlobalSymbol {
373 public:
374   DefinedGlobal(StringRef name, uint32_t flags, InputFile *file,
375                 InputGlobal *global);
376 
377   static bool classof(const Symbol *s) {
378     return s->kind() == DefinedGlobalKind;
379   }
380 
381   InputGlobal *global;
382 };
383 
384 class UndefinedGlobal : public GlobalSymbol {
385 public:
386   UndefinedGlobal(StringRef name, std::optional<StringRef> importName,
387                   std::optional<StringRef> importModule, uint32_t flags,
388                   InputFile *file = nullptr,
389                   const WasmGlobalType *type = nullptr)
390       : GlobalSymbol(name, UndefinedGlobalKind, flags, file, type) {
391     this->importName = importName;
392     this->importModule = importModule;
393   }
394 
395   static bool classof(const Symbol *s) {
396     return s->kind() == UndefinedGlobalKind;
397   }
398 };
399 
400 class TableSymbol : public Symbol {
401 public:
402   static bool classof(const Symbol *s) {
403     return s->kind() == DefinedTableKind || s->kind() == UndefinedTableKind;
404   }
405 
406   const WasmTableType *getTableType() const { return tableType; }
407   void setLimits(const WasmLimits &limits);
408 
409   // Get/set the table number
410   uint32_t getTableNumber() const;
411   void setTableNumber(uint32_t number);
412   bool hasTableNumber() const;
413 
414 protected:
415   TableSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f,
416               const WasmTableType *type)
417       : Symbol(name, k, flags, f), tableType(type) {}
418 
419   const WasmTableType *tableType;
420   uint32_t tableNumber = INVALID_INDEX;
421 };
422 
423 class DefinedTable : public TableSymbol {
424 public:
425   DefinedTable(StringRef name, uint32_t flags, InputFile *file,
426                InputTable *table);
427 
428   static bool classof(const Symbol *s) { return s->kind() == DefinedTableKind; }
429 
430   InputTable *table;
431 };
432 
433 class UndefinedTable : public TableSymbol {
434 public:
435   UndefinedTable(StringRef name, std::optional<StringRef> importName,
436                  std::optional<StringRef> importModule, uint32_t flags,
437                  InputFile *file, const WasmTableType *type)
438       : TableSymbol(name, UndefinedTableKind, flags, file, type) {
439     this->importName = importName;
440     this->importModule = importModule;
441   }
442 
443   static bool classof(const Symbol *s) {
444     return s->kind() == UndefinedTableKind;
445   }
446 };
447 
448 // A tag is a general format to distinguish typed entities. Each tag has an
449 // attribute and a type. Currently the attribute can only specify that the tag
450 // is for an exception tag.
451 //
452 // In exception handling, tags are used to distinguish different kinds of
453 // exceptions. For example, they can be used to distinguish different language's
454 // exceptions, e.g., all C++ exceptions have the same tag and Java exceptions
455 // would have a distinct tag. Wasm can filter the exceptions it catches based on
456 // their tag.
457 //
458 // A single TagSymbol object represents a single tag. The C++ exception symbol
459 // is a weak symbol generated in every object file in which exceptions are used,
460 // and is named '__cpp_exception' for linking.
461 class TagSymbol : public Symbol {
462 public:
463   static bool classof(const Symbol *s) {
464     return s->kind() == DefinedTagKind || s->kind() == UndefinedTagKind;
465   }
466 
467   // Get/set the tag index
468   uint32_t getTagIndex() const;
469   void setTagIndex(uint32_t index);
470   bool hasTagIndex() const;
471 
472   const WasmSignature *signature;
473 
474 protected:
475   TagSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f,
476             const WasmSignature *sig)
477       : Symbol(name, k, flags, f), signature(sig) {}
478 
479   uint32_t tagIndex = INVALID_INDEX;
480 };
481 
482 class DefinedTag : public TagSymbol {
483 public:
484   DefinedTag(StringRef name, uint32_t flags, InputFile *file, InputTag *tag);
485 
486   static bool classof(const Symbol *s) { return s->kind() == DefinedTagKind; }
487 
488   InputTag *tag;
489 };
490 
491 class UndefinedTag : public TagSymbol {
492 public:
493   UndefinedTag(StringRef name, std::optional<StringRef> importName,
494                std::optional<StringRef> importModule, uint32_t flags,
495                InputFile *file = nullptr, const WasmSignature *sig = nullptr)
496       : TagSymbol(name, UndefinedTagKind, flags, file, sig) {
497     this->importName = importName;
498     this->importModule = importModule;
499   }
500 
501   static bool classof(const Symbol *s) { return s->kind() == UndefinedTagKind; }
502 };
503 
504 class SharedFunctionSymbol : public FunctionSymbol {
505 public:
506   SharedFunctionSymbol(StringRef name, uint32_t flags, InputFile *file,
507                        const WasmSignature *sig)
508       : FunctionSymbol(name, SharedFunctionKind, flags, file, sig) {}
509   static bool classof(const Symbol *s) {
510     return s->kind() == SharedFunctionKind;
511   }
512 };
513 
514 // LazySymbol symbols represent symbols in object files between --start-lib and
515 // --end-lib options. LLD also handles traditional archives as if all the files
516 // in the archive are surrounded by --start-lib and --end-lib.
517 //
518 // A special complication is the handling of weak undefined symbols. They should
519 // not load a file, but we have to remember we have seen both the weak undefined
520 // and the lazy. We represent that with a lazy symbol with a weak binding. This
521 // means that code looking for undefined symbols normally also has to take lazy
522 // symbols into consideration.
523 class LazySymbol : public Symbol {
524 public:
525   LazySymbol(StringRef name, uint32_t flags, InputFile *file)
526       : Symbol(name, LazyKind, flags, file) {}
527 
528   static bool classof(const Symbol *s) { return s->kind() == LazyKind; }
529   void extract();
530   void setWeak();
531 
532   // Lazy symbols can have a signature because they can replace an
533   // UndefinedFunction in which case we need to be able to preserve the
534   // signature.
535   // TODO(sbc): This repetition of the signature field is inelegant.  Revisit
536   // the use of class hierarchy to represent symbol taxonomy.
537   const WasmSignature *signature = nullptr;
538 };
539 
540 // linker-generated symbols
541 struct WasmSym {
542   // __global_base
543   // Symbol marking the start of the global section.
544   static DefinedData *globalBase;
545 
546   // __stack_pointer/__stack_low/__stack_high
547   // Global that holds current value of stack pointer and data symbols marking
548   // the start and end of the stack region.  stackPointer is initialized to
549   // stackHigh and grows downwards towards stackLow
550   static GlobalSymbol *stackPointer;
551   static DefinedData *stackLow;
552   static DefinedData *stackHigh;
553 
554   // __tls_base
555   // Global that holds the address of the base of the current thread's
556   // TLS block.
557   static GlobalSymbol *tlsBase;
558 
559   // __tls_size
560   // Symbol whose value is the size of the TLS block.
561   static GlobalSymbol *tlsSize;
562 
563   // __tls_size
564   // Symbol whose value is the alignment of the TLS block.
565   static GlobalSymbol *tlsAlign;
566 
567   // __data_end
568   // Symbol marking the end of the data and bss.
569   static DefinedData *dataEnd;
570 
571   // __heap_base/__heap_end
572   // Symbols marking the beginning and end of the "heap". It starts at the end
573   // of the data, bss and explicit stack, and extends to the end of the linear
574   // memory allocated by wasm-ld. This region of memory is not used by the
575   // linked code, so it may be used as a backing store for `sbrk` or `malloc`
576   // implementations.
577   static DefinedData *heapBase;
578   static DefinedData *heapEnd;
579 
580   // __wasm_init_memory_flag
581   // Symbol whose contents are nonzero iff memory has already been initialized.
582   static DefinedData *initMemoryFlag;
583 
584   // __wasm_init_memory
585   // Function that initializes passive data segments during instantiation.
586   static DefinedFunction *initMemory;
587 
588   // __wasm_call_ctors
589   // Function that directly calls all ctors in priority order.
590   static DefinedFunction *callCtors;
591 
592   // __wasm_call_dtors
593   // Function that calls the libc/etc. cleanup function.
594   static DefinedFunction *callDtors;
595 
596   // __wasm_apply_global_relocs
597   // Function that applies relocations to wasm globals post-instantiation.
598   // Unlike __wasm_apply_data_relocs this needs to run on every thread.
599   static DefinedFunction *applyGlobalRelocs;
600 
601   // __wasm_apply_tls_relocs
602   // Like __wasm_apply_data_relocs but for TLS section.  These must be
603   // delayed until __wasm_init_tls.
604   static DefinedFunction *applyTLSRelocs;
605 
606   // __wasm_apply_global_tls_relocs
607   // Like applyGlobalRelocs but for globals that hold TLS addresses.  These
608   // must be delayed until __wasm_init_tls.
609   static DefinedFunction *applyGlobalTLSRelocs;
610 
611   // __wasm_init_tls
612   // Function that allocates thread-local storage and initializes it.
613   static DefinedFunction *initTLS;
614 
615   // Pointer to the function that is to be used in the start section.
616   // (normally an alias of initMemory, or applyGlobalRelocs).
617   static DefinedFunction *startFunction;
618 
619   // __dso_handle
620   // Symbol used in calls to __cxa_atexit to determine current DLL
621   static DefinedData *dsoHandle;
622 
623   // __table_base
624   // Used in PIC code for offset of indirect function table
625   static UndefinedGlobal *tableBase;
626   static DefinedData *definedTableBase;
627 
628   // __memory_base
629   // Used in PIC code for offset of global data
630   static UndefinedGlobal *memoryBase;
631   static DefinedData *definedMemoryBase;
632 
633   // __indirect_function_table
634   // Used as an address space for function pointers, with each function that is
635   // used as a function pointer being allocated a slot.
636   static TableSymbol *indirectFunctionTable;
637 };
638 
639 // A buffer class that is large enough to hold any Symbol-derived
640 // object. We allocate memory using this class and instantiate a symbol
641 // using the placement new.
642 union SymbolUnion {
643   alignas(DefinedFunction) char a[sizeof(DefinedFunction)];
644   alignas(DefinedData) char b[sizeof(DefinedData)];
645   alignas(DefinedGlobal) char c[sizeof(DefinedGlobal)];
646   alignas(DefinedTag) char d[sizeof(DefinedTag)];
647   alignas(DefinedTable) char e[sizeof(DefinedTable)];
648   alignas(LazySymbol) char f[sizeof(LazySymbol)];
649   alignas(UndefinedFunction) char g[sizeof(UndefinedFunction)];
650   alignas(UndefinedData) char h[sizeof(UndefinedData)];
651   alignas(UndefinedGlobal) char i[sizeof(UndefinedGlobal)];
652   alignas(UndefinedTable) char j[sizeof(UndefinedTable)];
653   alignas(SectionSymbol) char k[sizeof(SectionSymbol)];
654   alignas(SharedFunctionSymbol) char l[sizeof(SharedFunctionSymbol)];
655 };
656 
657 // It is important to keep the size of SymbolUnion small for performance and
658 // memory usage reasons. 96 bytes is a soft limit based on the size of
659 // UndefinedFunction on a 64-bit system.
660 static_assert(sizeof(SymbolUnion) <= 120, "SymbolUnion too large");
661 
662 void printTraceSymbol(Symbol *sym);
663 void printTraceSymbolUndefined(StringRef name, const InputFile* file);
664 
665 template <typename T, typename... ArgT>
666 T *replaceSymbol(Symbol *s, ArgT &&... arg) {
667   static_assert(std::is_trivially_destructible<T>(),
668                 "Symbol types must be trivially destructible");
669   static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
670   static_assert(alignof(T) <= alignof(SymbolUnion),
671                 "SymbolUnion not aligned enough");
672   assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
673          "Not a Symbol");
674 
675   Symbol symCopy = *s;
676 
677   T *s2 = new (s) T(std::forward<ArgT>(arg)...);
678   s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
679   s2->forceExport = symCopy.forceExport;
680   s2->forceImport = symCopy.forceImport;
681   s2->canInline = symCopy.canInline;
682   s2->traced = symCopy.traced;
683   s2->referenced = symCopy.referenced;
684 
685   // Print out a log message if --trace-symbol was specified.
686   // This is for debugging.
687   if (s2->traced)
688     printTraceSymbol(s2);
689 
690   return s2;
691 }
692 
693 } // namespace wasm
694 
695 // Returns a symbol name for an error message.
696 std::string toString(const wasm::Symbol &sym);
697 std::string toString(wasm::Symbol::Kind kind);
698 std::string maybeDemangleSymbol(StringRef name);
699 
700 } // namespace lld
701 
702 #endif
703