1 //===- Symbols.h ------------------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef LLD_WASM_SYMBOLS_H
11 #define LLD_WASM_SYMBOLS_H
12
13 #include "Config.h"
14 #include "lld/Common/LLVM.h"
15 #include "llvm/Object/Archive.h"
16 #include "llvm/Object/Wasm.h"
17
18 namespace lld {
19 namespace wasm {
20
21 using llvm::wasm::WasmSymbolType;
22
23 class InputFile;
24 class InputChunk;
25 class InputSegment;
26 class InputFunction;
27 class InputGlobal;
28 class InputEvent;
29 class InputSection;
30
31 #define INVALID_INDEX UINT32_MAX
32
33 // The base class for real symbol classes.
34 class Symbol {
35 public:
36 enum Kind {
37 DefinedFunctionKind,
38 DefinedDataKind,
39 DefinedGlobalKind,
40 DefinedEventKind,
41 SectionKind,
42 UndefinedFunctionKind,
43 UndefinedDataKind,
44 UndefinedGlobalKind,
45 LazyKind,
46 };
47
kind()48 Kind kind() const { return SymbolKind; }
49
isDefined()50 bool isDefined() const {
51 return SymbolKind == DefinedFunctionKind || SymbolKind == DefinedDataKind ||
52 SymbolKind == DefinedGlobalKind || SymbolKind == DefinedEventKind ||
53 SymbolKind == SectionKind;
54 }
55
isUndefined()56 bool isUndefined() const {
57 return SymbolKind == UndefinedFunctionKind ||
58 SymbolKind == UndefinedDataKind || SymbolKind == UndefinedGlobalKind;
59 }
60
isLazy()61 bool isLazy() const { return SymbolKind == LazyKind; }
62
63 bool isLocal() const;
64 bool isWeak() const;
65 bool isHidden() const;
66
67 // Returns the symbol name.
getName()68 StringRef getName() const { return Name; }
69
70 // Returns the file from which this symbol was created.
getFile()71 InputFile *getFile() const { return File; }
72
73 InputChunk *getChunk() const;
74
75 // Indicates that the section or import for this symbol will be included in
76 // the final image.
77 bool isLive() const;
78
79 // Marks the symbol's InputChunk as Live, so that it will be included in the
80 // final image.
81 void markLive();
82
83 void setHidden(bool IsHidden);
84
85 // Get/set the index in the output symbol table. This is only used for
86 // relocatable output.
87 uint32_t getOutputSymbolIndex() const;
88 void setOutputSymbolIndex(uint32_t Index);
89
90 WasmSymbolType getWasmType() const;
91 bool isExported() const;
92
93 // True if this symbol was referenced by a regular (non-bitcode) object.
94 unsigned IsUsedInRegularObj : 1;
95 unsigned ForceExport : 1;
96
97 protected:
Symbol(StringRef Name,Kind K,uint32_t Flags,InputFile * F)98 Symbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F)
99 : IsUsedInRegularObj(false), ForceExport(false), Name(Name),
100 SymbolKind(K), Flags(Flags), File(F), Referenced(!Config->GcSections) {}
101
102 StringRef Name;
103 Kind SymbolKind;
104 uint32_t Flags;
105 InputFile *File;
106 uint32_t OutputSymbolIndex = INVALID_INDEX;
107 bool Referenced;
108 };
109
110 class FunctionSymbol : public Symbol {
111 public:
classof(const Symbol * S)112 static bool classof(const Symbol *S) {
113 return S->kind() == DefinedFunctionKind ||
114 S->kind() == UndefinedFunctionKind;
115 }
116
117 // Get/set the table index
118 void setTableIndex(uint32_t Index);
119 uint32_t getTableIndex() const;
120 bool hasTableIndex() const;
121
122 // Get/set the function index
123 uint32_t getFunctionIndex() const;
124 void setFunctionIndex(uint32_t Index);
125 bool hasFunctionIndex() const;
126
127 const WasmSignature *Signature;
128
129 protected:
FunctionSymbol(StringRef Name,Kind K,uint32_t Flags,InputFile * F,const WasmSignature * Sig)130 FunctionSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,
131 const WasmSignature *Sig)
132 : Symbol(Name, K, Flags, F), Signature(Sig) {}
133
134 uint32_t TableIndex = INVALID_INDEX;
135 uint32_t FunctionIndex = INVALID_INDEX;
136 };
137
138 class DefinedFunction : public FunctionSymbol {
139 public:
140 DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F,
141 InputFunction *Function);
142
classof(const Symbol * S)143 static bool classof(const Symbol *S) {
144 return S->kind() == DefinedFunctionKind;
145 }
146
147 InputFunction *Function;
148 };
149
150 class UndefinedFunction : public FunctionSymbol {
151 public:
152 UndefinedFunction(StringRef Name, StringRef ImportName,
153 StringRef ImportModule, uint32_t Flags,
154 InputFile *File = nullptr,
155 const WasmSignature *Type = nullptr)
FunctionSymbol(Name,UndefinedFunctionKind,Flags,File,Type)156 : FunctionSymbol(Name, UndefinedFunctionKind, Flags, File, Type),
157 ImportName(ImportName), ImportModule(ImportModule) {}
158
classof(const Symbol * S)159 static bool classof(const Symbol *S) {
160 return S->kind() == UndefinedFunctionKind;
161 }
162
163 StringRef ImportName;
164 StringRef ImportModule;
165 };
166
167 class SectionSymbol : public Symbol {
168 public:
classof(const Symbol * S)169 static bool classof(const Symbol *S) { return S->kind() == SectionKind; }
170
171 SectionSymbol(StringRef Name, uint32_t Flags, const InputSection *S,
172 InputFile *F = nullptr)
Symbol(Name,SectionKind,Flags,F)173 : Symbol(Name, SectionKind, Flags, F), Section(S) {}
174
175 const InputSection *Section;
176
177 uint32_t getOutputSectionIndex() const;
178 void setOutputSectionIndex(uint32_t Index);
179
180 protected:
181 uint32_t OutputSectionIndex = INVALID_INDEX;
182 };
183
184 class DataSymbol : public Symbol {
185 public:
classof(const Symbol * S)186 static bool classof(const Symbol *S) {
187 return S->kind() == DefinedDataKind || S->kind() == UndefinedDataKind;
188 }
189
190 protected:
DataSymbol(StringRef Name,Kind K,uint32_t Flags,InputFile * F)191 DataSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F)
192 : Symbol(Name, K, Flags, F) {}
193 };
194
195 class DefinedData : public DataSymbol {
196 public:
197 // Constructor for regular data symbols originating from input files.
DefinedData(StringRef Name,uint32_t Flags,InputFile * F,InputSegment * Segment,uint32_t Offset,uint32_t Size)198 DefinedData(StringRef Name, uint32_t Flags, InputFile *F,
199 InputSegment *Segment, uint32_t Offset, uint32_t Size)
200 : DataSymbol(Name, DefinedDataKind, Flags, F), Segment(Segment),
201 Offset(Offset), Size(Size) {}
202
203 // Constructor for linker synthetic data symbols.
DefinedData(StringRef Name,uint32_t Flags)204 DefinedData(StringRef Name, uint32_t Flags)
205 : DataSymbol(Name, DefinedDataKind, Flags, nullptr) {}
206
classof(const Symbol * S)207 static bool classof(const Symbol *S) { return S->kind() == DefinedDataKind; }
208
209 // Returns the output virtual address of a defined data symbol.
210 uint32_t getVirtualAddress() const;
211 void setVirtualAddress(uint32_t VA);
212
213 // Returns the offset of a defined data symbol within its OutputSegment.
214 uint32_t getOutputSegmentOffset() const;
215 uint32_t getOutputSegmentIndex() const;
getSize()216 uint32_t getSize() const { return Size; }
217
218 InputSegment *Segment = nullptr;
219
220 protected:
221 uint32_t Offset = 0;
222 uint32_t Size = 0;
223 };
224
225 class UndefinedData : public DataSymbol {
226 public:
227 UndefinedData(StringRef Name, uint32_t Flags, InputFile *File = nullptr)
DataSymbol(Name,UndefinedDataKind,Flags,File)228 : DataSymbol(Name, UndefinedDataKind, Flags, File) {}
classof(const Symbol * S)229 static bool classof(const Symbol *S) {
230 return S->kind() == UndefinedDataKind;
231 }
232 };
233
234 class GlobalSymbol : public Symbol {
235 public:
classof(const Symbol * S)236 static bool classof(const Symbol *S) {
237 return S->kind() == DefinedGlobalKind || S->kind() == UndefinedGlobalKind;
238 }
239
getGlobalType()240 const WasmGlobalType *getGlobalType() const { return GlobalType; }
241
242 // Get/set the global index
243 uint32_t getGlobalIndex() const;
244 void setGlobalIndex(uint32_t Index);
245 bool hasGlobalIndex() const;
246
247 protected:
GlobalSymbol(StringRef Name,Kind K,uint32_t Flags,InputFile * F,const WasmGlobalType * GlobalType)248 GlobalSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,
249 const WasmGlobalType *GlobalType)
250 : Symbol(Name, K, Flags, F), GlobalType(GlobalType) {}
251
252 const WasmGlobalType *GlobalType;
253 uint32_t GlobalIndex = INVALID_INDEX;
254 };
255
256 class DefinedGlobal : public GlobalSymbol {
257 public:
258 DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File,
259 InputGlobal *Global);
260
classof(const Symbol * S)261 static bool classof(const Symbol *S) {
262 return S->kind() == DefinedGlobalKind;
263 }
264
265 InputGlobal *Global;
266 };
267
268 class UndefinedGlobal : public GlobalSymbol {
269 public:
270 UndefinedGlobal(StringRef Name, StringRef ImportName, StringRef ImportModule,
271 uint32_t Flags, InputFile *File = nullptr,
272 const WasmGlobalType *Type = nullptr)
GlobalSymbol(Name,UndefinedGlobalKind,Flags,File,Type)273 : GlobalSymbol(Name, UndefinedGlobalKind, Flags, File, Type),
274 ImportName(ImportName), ImportModule(ImportModule) {}
275
classof(const Symbol * S)276 static bool classof(const Symbol *S) {
277 return S->kind() == UndefinedGlobalKind;
278 }
279
280 StringRef ImportName;
281 StringRef ImportModule;
282 };
283
284 // Wasm events are features that suspend the current execution and transfer the
285 // control flow to a corresponding handler. Currently the only supported event
286 // kind is exceptions.
287 //
288 // Event tags are values to distinguish different events. For exceptions, they
289 // can be used to distinguish different language's exceptions, i.e., all C++
290 // exceptions have the same tag. Wasm can generate code capable of doing
291 // different handling actions based on the tag of caught exceptions.
292 //
293 // A single EventSymbol object represents a single tag. C++ exception event
294 // symbol is a weak symbol generated in every object file in which exceptions
295 // are used, and has name '__cpp_exception' for linking.
296 class EventSymbol : public Symbol {
297 public:
classof(const Symbol * S)298 static bool classof(const Symbol *S) { return S->kind() == DefinedEventKind; }
299
getEventType()300 const WasmEventType *getEventType() const { return EventType; }
301
302 // Get/set the event index
303 uint32_t getEventIndex() const;
304 void setEventIndex(uint32_t Index);
305 bool hasEventIndex() const;
306
307 const WasmSignature *Signature;
308
309 protected:
EventSymbol(StringRef Name,Kind K,uint32_t Flags,InputFile * F,const WasmEventType * EventType,const WasmSignature * Sig)310 EventSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,
311 const WasmEventType *EventType, const WasmSignature *Sig)
312 : Symbol(Name, K, Flags, F), Signature(Sig), EventType(EventType) {}
313
314 const WasmEventType *EventType;
315 uint32_t EventIndex = INVALID_INDEX;
316 };
317
318 class DefinedEvent : public EventSymbol {
319 public:
320 DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File,
321 InputEvent *Event);
322
classof(const Symbol * S)323 static bool classof(const Symbol *S) { return S->kind() == DefinedEventKind; }
324
325 InputEvent *Event;
326 };
327
328 class LazySymbol : public Symbol {
329 public:
LazySymbol(StringRef Name,InputFile * File,const llvm::object::Archive::Symbol & Sym)330 LazySymbol(StringRef Name, InputFile *File,
331 const llvm::object::Archive::Symbol &Sym)
332 : Symbol(Name, LazyKind, 0, File), ArchiveSymbol(Sym) {}
333
classof(const Symbol * S)334 static bool classof(const Symbol *S) { return S->kind() == LazyKind; }
335 void fetch();
336
337 private:
338 llvm::object::Archive::Symbol ArchiveSymbol;
339 };
340
341 // linker-generated symbols
342 struct WasmSym {
343 // __stack_pointer
344 // Global that holds the address of the top of the explicit value stack in
345 // linear memory.
346 static GlobalSymbol *StackPointer;
347
348 // __data_end
349 // Symbol marking the end of the data and bss.
350 static DefinedData *DataEnd;
351
352 // __heap_base
353 // Symbol marking the end of the data, bss and explicit stack. Any linear
354 // memory following this address is not used by the linked code and can
355 // therefore be used as a backing store for brk()/malloc() implementations.
356 static DefinedData *HeapBase;
357
358 // __wasm_call_ctors
359 // Function that directly calls all ctors in priority order.
360 static DefinedFunction *CallCtors;
361
362 // __dso_handle
363 // Symbol used in calls to __cxa_atexit to determine current DLL
364 static DefinedData *DsoHandle;
365
366 // __table_base
367 // Used in PIC code for offset of indirect function table
368 static UndefinedGlobal *TableBase;
369
370 // __memory_base
371 // Used in PIC code for offset of global data
372 static UndefinedGlobal *MemoryBase;
373 };
374
375 // A buffer class that is large enough to hold any Symbol-derived
376 // object. We allocate memory using this class and instantiate a symbol
377 // using the placement new.
378 union SymbolUnion {
379 alignas(DefinedFunction) char A[sizeof(DefinedFunction)];
380 alignas(DefinedData) char B[sizeof(DefinedData)];
381 alignas(DefinedGlobal) char C[sizeof(DefinedGlobal)];
382 alignas(DefinedEvent) char D[sizeof(DefinedEvent)];
383 alignas(LazySymbol) char E[sizeof(LazySymbol)];
384 alignas(UndefinedFunction) char F[sizeof(UndefinedFunction)];
385 alignas(UndefinedData) char G[sizeof(UndefinedData)];
386 alignas(UndefinedGlobal) char H[sizeof(UndefinedGlobal)];
387 alignas(SectionSymbol) char I[sizeof(SectionSymbol)];
388 };
389
390 template <typename T, typename... ArgT>
replaceSymbol(Symbol * S,ArgT &&...Arg)391 T *replaceSymbol(Symbol *S, ArgT &&... Arg) {
392 static_assert(std::is_trivially_destructible<T>(),
393 "Symbol types must be trivially destructible");
394 static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
395 static_assert(alignof(T) <= alignof(SymbolUnion),
396 "SymbolUnion not aligned enough");
397 assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
398 "Not a Symbol");
399
400 Symbol SymCopy = *S;
401
402 T *S2 = new (S) T(std::forward<ArgT>(Arg)...);
403 S2->IsUsedInRegularObj = SymCopy.IsUsedInRegularObj;
404 S2->ForceExport = SymCopy.ForceExport;
405 return S2;
406 }
407
408 } // namespace wasm
409
410 // Returns a symbol name for an error message.
411 std::string toString(const wasm::Symbol &Sym);
412 std::string toString(wasm::Symbol::Kind Kind);
413 std::string maybeDemangleSymbol(StringRef Name);
414
415 } // namespace lld
416
417 #endif
418