comparison lld/wasm/Symbols.h @ 207:2e18cbf3894f

LLVM12
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 08 Jun 2021 06:07:14 +0900
parents 0572611fdcc8
children 5f17cb93ff66
comparison
equal deleted inserted replaced
173:0572611fdcc8 207:2e18cbf3894f
33 class InputSegment; 33 class InputSegment;
34 class InputFunction; 34 class InputFunction;
35 class InputGlobal; 35 class InputGlobal;
36 class InputEvent; 36 class InputEvent;
37 class InputSection; 37 class InputSection;
38 class InputTable;
38 class OutputSection; 39 class OutputSection;
39 40
40 #define INVALID_INDEX UINT32_MAX 41 #define INVALID_INDEX UINT32_MAX
41 42
42 // The base class for real symbol classes. 43 // The base class for real symbol classes.
45 enum Kind : uint8_t { 46 enum Kind : uint8_t {
46 DefinedFunctionKind, 47 DefinedFunctionKind,
47 DefinedDataKind, 48 DefinedDataKind,
48 DefinedGlobalKind, 49 DefinedGlobalKind,
49 DefinedEventKind, 50 DefinedEventKind,
51 DefinedTableKind,
50 SectionKind, 52 SectionKind,
51 OutputSectionKind, 53 OutputSectionKind,
52 UndefinedFunctionKind, 54 UndefinedFunctionKind,
53 UndefinedDataKind, 55 UndefinedDataKind,
54 UndefinedGlobalKind, 56 UndefinedGlobalKind,
57 UndefinedTableKind,
55 LazyKind, 58 LazyKind,
56 }; 59 };
57 60
58 Kind kind() const { return symbolKind; } 61 Kind kind() const { return symbolKind; }
59 62
60 bool isDefined() const { return !isLazy() && !isUndefined(); } 63 bool isDefined() const { return !isLazy() && !isUndefined(); }
61 64
62 bool isUndefined() const { 65 bool isUndefined() const {
63 return symbolKind == UndefinedFunctionKind || 66 return symbolKind == UndefinedFunctionKind ||
64 symbolKind == UndefinedDataKind || symbolKind == UndefinedGlobalKind; 67 symbolKind == UndefinedDataKind ||
68 symbolKind == UndefinedGlobalKind ||
69 symbolKind == UndefinedTableKind;
65 } 70 }
66 71
67 bool isLazy() const { return symbolKind == LazyKind; } 72 bool isLazy() const { return symbolKind == LazyKind; }
68 73
69 bool isLocal() const; 74 bool isLocal() const;
103 uint32_t getOutputSymbolIndex() const; 108 uint32_t getOutputSymbolIndex() const;
104 void setOutputSymbolIndex(uint32_t index); 109 void setOutputSymbolIndex(uint32_t index);
105 110
106 WasmSymbolType getWasmType() const; 111 WasmSymbolType getWasmType() const;
107 bool isExported() const; 112 bool isExported() const;
113 bool isExportedExplicit() const;
108 114
109 // Indicates that the symbol is used in an __attribute__((used)) directive 115 // Indicates that the symbol is used in an __attribute__((used)) directive
110 // or similar. 116 // or similar.
111 bool isNoStrip() const; 117 bool isNoStrip() const;
112 118
122 128
123 protected: 129 protected:
124 Symbol(StringRef name, Kind k, uint32_t flags, InputFile *f) 130 Symbol(StringRef name, Kind k, uint32_t flags, InputFile *f)
125 : name(name), file(f), symbolKind(k), referenced(!config->gcSections), 131 : name(name), file(f), symbolKind(k), referenced(!config->gcSections),
126 requiresGOT(false), isUsedInRegularObj(false), forceExport(false), 132 requiresGOT(false), isUsedInRegularObj(false), forceExport(false),
127 canInline(false), traced(false), flags(flags) {} 133 canInline(false), traced(false), isStub(false), flags(flags) {}
128 134
129 StringRef name; 135 StringRef name;
130 InputFile *file; 136 InputFile *file;
131 uint32_t outputSymbolIndex = INVALID_INDEX; 137 uint32_t outputSymbolIndex = INVALID_INDEX;
132 uint32_t gotIndex = INVALID_INDEX; 138 uint32_t gotIndex = INVALID_INDEX;
154 // doesn't know the final contents of the symbol. 160 // doesn't know the final contents of the symbol.
155 bool canInline : 1; 161 bool canInline : 1;
156 162
157 // True if this symbol is specified by --trace-symbol option. 163 // True if this symbol is specified by --trace-symbol option.
158 bool traced : 1; 164 bool traced : 1;
165
166 // True if this symbol is a linker-synthesized stub function (traps when
167 // called) and should otherwise be treated as missing/undefined. See
168 // SymbolTable::replaceWithUndefined.
169 // These stubs never appear in the table and any table index relocations
170 // against them will produce address 0 (The table index representing
171 // the null function pointer).
172 bool isStub : 1;
159 173
160 uint32_t flags; 174 uint32_t flags;
161 }; 175 };
162 176
163 class FunctionSymbol : public Symbol { 177 class FunctionSymbol : public Symbol {
215 return s->kind() == UndefinedFunctionKind; 229 return s->kind() == UndefinedFunctionKind;
216 } 230 }
217 231
218 llvm::Optional<StringRef> importName; 232 llvm::Optional<StringRef> importName;
219 llvm::Optional<StringRef> importModule; 233 llvm::Optional<StringRef> importModule;
234 DefinedFunction *stubFunction = nullptr;
220 bool isCalledDirectly; 235 bool isCalledDirectly;
221 }; 236 };
222 237
223 // Section symbols for output sections are different from those for input 238 // Section symbols for output sections are different from those for input
224 // section. These are generated by the linker and point the OutputSection 239 // section. These are generated by the linker and point the OutputSection
237 const OutputSection *section; 252 const OutputSection *section;
238 }; 253 };
239 254
240 class SectionSymbol : public Symbol { 255 class SectionSymbol : public Symbol {
241 public: 256 public:
242 SectionSymbol(uint32_t flags, const InputSection *s, InputFile *f = nullptr) 257 SectionSymbol(uint32_t flags, const InputChunk *s, InputFile *f = nullptr)
243 : Symbol("", SectionKind, flags, f), section(s) {} 258 : Symbol("", SectionKind, flags, f), section(s) {}
244 259
245 static bool classof(const Symbol *s) { return s->kind() == SectionKind; } 260 static bool classof(const Symbol *s) { return s->kind() == SectionKind; }
246 261
247 const OutputSectionSymbol *getOutputSectionSymbol() const; 262 const OutputSectionSymbol *getOutputSectionSymbol() const;
248 263
249 const InputSection *section; 264 const InputChunk *section;
250 }; 265 };
251 266
252 class DataSymbol : public Symbol { 267 class DataSymbol : public Symbol {
253 public: 268 public:
254 static bool classof(const Symbol *s) { 269 static bool classof(const Symbol *s) {
261 }; 276 };
262 277
263 class DefinedData : public DataSymbol { 278 class DefinedData : public DataSymbol {
264 public: 279 public:
265 // Constructor for regular data symbols originating from input files. 280 // Constructor for regular data symbols originating from input files.
266 DefinedData(StringRef name, uint32_t flags, InputFile *f, 281 DefinedData(StringRef name, uint32_t flags, InputFile *f, InputChunk *segment,
267 InputSegment *segment, uint32_t offset, uint32_t size) 282 uint64_t value, uint64_t size)
268 : DataSymbol(name, DefinedDataKind, flags, f), segment(segment), 283 : DataSymbol(name, DefinedDataKind, flags, f), segment(segment),
269 offset(offset), size(size) {} 284 value(value), size(size) {}
270 285
271 // Constructor for linker synthetic data symbols. 286 // Constructor for linker synthetic data symbols.
272 DefinedData(StringRef name, uint32_t flags) 287 DefinedData(StringRef name, uint32_t flags)
273 : DataSymbol(name, DefinedDataKind, flags, nullptr) {} 288 : DataSymbol(name, DefinedDataKind, flags, nullptr) {}
274 289
275 static bool classof(const Symbol *s) { return s->kind() == DefinedDataKind; } 290 static bool classof(const Symbol *s) { return s->kind() == DefinedDataKind; }
276 291
277 // Returns the output virtual address of a defined data symbol. 292 // Returns the output virtual address of a defined data symbol.
278 uint32_t getVirtualAddress() const; 293 uint64_t getVA() const;
279 void setVirtualAddress(uint32_t va); 294 void setVA(uint64_t va);
280 295
281 // Returns the offset of a defined data symbol within its OutputSegment. 296 // Returns the offset of a defined data symbol within its OutputSegment.
282 uint32_t getOutputSegmentOffset() const; 297 uint64_t getOutputSegmentOffset() const;
283 uint32_t getOutputSegmentIndex() const; 298 uint64_t getOutputSegmentIndex() const;
284 uint32_t getSize() const { return size; } 299 uint64_t getSize() const { return size; }
285 300
286 InputSegment *segment = nullptr; 301 InputChunk *segment = nullptr;
302 uint64_t value = 0;
287 303
288 protected: 304 protected:
289 uint32_t offset = 0; 305 uint64_t size = 0;
290 uint32_t size = 0;
291 }; 306 };
292 307
293 class UndefinedData : public DataSymbol { 308 class UndefinedData : public DataSymbol {
294 public: 309 public:
295 UndefinedData(StringRef name, uint32_t flags, InputFile *file = nullptr) 310 UndefinedData(StringRef name, uint32_t flags, InputFile *file = nullptr)
342 : GlobalSymbol(name, UndefinedGlobalKind, flags, file, type), 357 : GlobalSymbol(name, UndefinedGlobalKind, flags, file, type),
343 importName(importName), importModule(importModule) {} 358 importName(importName), importModule(importModule) {}
344 359
345 static bool classof(const Symbol *s) { 360 static bool classof(const Symbol *s) {
346 return s->kind() == UndefinedGlobalKind; 361 return s->kind() == UndefinedGlobalKind;
362 }
363
364 llvm::Optional<StringRef> importName;
365 llvm::Optional<StringRef> importModule;
366 };
367
368 class TableSymbol : public Symbol {
369 public:
370 static bool classof(const Symbol *s) {
371 return s->kind() == DefinedTableKind || s->kind() == UndefinedTableKind;
372 }
373
374 const WasmTableType *getTableType() const { return tableType; }
375 void setLimits(const WasmLimits &limits);
376
377 // Get/set the table number
378 uint32_t getTableNumber() const;
379 void setTableNumber(uint32_t number);
380 bool hasTableNumber() const;
381
382 protected:
383 TableSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f,
384 const WasmTableType *type)
385 : Symbol(name, k, flags, f), tableType(type) {}
386
387 const WasmTableType *tableType;
388 uint32_t tableNumber = INVALID_INDEX;
389 };
390
391 class DefinedTable : public TableSymbol {
392 public:
393 DefinedTable(StringRef name, uint32_t flags, InputFile *file,
394 InputTable *table);
395
396 static bool classof(const Symbol *s) { return s->kind() == DefinedTableKind; }
397
398 InputTable *table;
399 };
400
401 class UndefinedTable : public TableSymbol {
402 public:
403 UndefinedTable(StringRef name, llvm::Optional<StringRef> importName,
404 llvm::Optional<StringRef> importModule, uint32_t flags,
405 InputFile *file, const WasmTableType *type)
406 : TableSymbol(name, UndefinedTableKind, flags, file, type),
407 importName(importName), importModule(importModule) {}
408
409 static bool classof(const Symbol *s) {
410 return s->kind() == UndefinedTableKind;
347 } 411 }
348 412
349 llvm::Optional<StringRef> importName; 413 llvm::Optional<StringRef> importName;
350 llvm::Optional<StringRef> importModule; 414 llvm::Optional<StringRef> importModule;
351 }; 415 };
409 const llvm::object::Archive::Symbol &sym) 473 const llvm::object::Archive::Symbol &sym)
410 : Symbol(name, LazyKind, flags, file), archiveSymbol(sym) {} 474 : Symbol(name, LazyKind, flags, file), archiveSymbol(sym) {}
411 475
412 static bool classof(const Symbol *s) { return s->kind() == LazyKind; } 476 static bool classof(const Symbol *s) { return s->kind() == LazyKind; }
413 void fetch(); 477 void fetch();
478 void setWeak();
414 MemoryBufferRef getMemberBuffer(); 479 MemoryBufferRef getMemberBuffer();
415 480
416 // Lazy symbols can have a signature because they can replace an 481 // Lazy symbols can have a signature because they can replace an
417 // UndefinedFunction which which case we need to be able to preserve the 482 // UndefinedFunction which which case we need to be able to preserve the
418 // signature. 483 // signature.
468 533
469 // __wasm_call_ctors 534 // __wasm_call_ctors
470 // Function that directly calls all ctors in priority order. 535 // Function that directly calls all ctors in priority order.
471 static DefinedFunction *callCtors; 536 static DefinedFunction *callCtors;
472 537
473 // __wasm_apply_relocs 538 // __wasm_call_dtors
539 // Function that calls the libc/etc. cleanup function.
540 static DefinedFunction *callDtors;
541
542 // __wasm_apply_data_relocs
474 // Function that applies relocations to data segment post-instantiation. 543 // Function that applies relocations to data segment post-instantiation.
475 static DefinedFunction *applyRelocs; 544 static DefinedFunction *applyDataRelocs;
545
546 // __wasm_apply_global_relocs
547 // Function that applies relocations to data segment post-instantiation.
548 // Unlike __wasm_apply_data_relocs this needs to run on every thread.
549 static DefinedFunction *applyGlobalRelocs;
476 550
477 // __wasm_init_tls 551 // __wasm_init_tls
478 // Function that allocates thread-local storage and initializes it. 552 // Function that allocates thread-local storage and initializes it.
479 static DefinedFunction *initTLS; 553 static DefinedFunction *initTLS;
554
555 // Pointer to the function that is to be used in the start section.
556 // (normally an alias of initMemory, or applyGlobalRelocs).
557 static DefinedFunction *startFunction;
480 558
481 // __dso_handle 559 // __dso_handle
482 // Symbol used in calls to __cxa_atexit to determine current DLL 560 // Symbol used in calls to __cxa_atexit to determine current DLL
483 static DefinedData *dsoHandle; 561 static DefinedData *dsoHandle;
484 562
485 // __table_base 563 // __table_base
486 // Used in PIC code for offset of indirect function table 564 // Used in PIC code for offset of indirect function table
487 static UndefinedGlobal *tableBase; 565 static UndefinedGlobal *tableBase;
488 static DefinedData *definedTableBase; 566 static DefinedData *definedTableBase;
567 // 32-bit copy in wasm64 to work around init expr limitations.
568 // These can potentially be removed again once we have
569 // https://github.com/WebAssembly/extended-const
570 static UndefinedGlobal *tableBase32;
571 static DefinedData *definedTableBase32;
489 572
490 // __memory_base 573 // __memory_base
491 // Used in PIC code for offset of global data 574 // Used in PIC code for offset of global data
492 static UndefinedGlobal *memoryBase; 575 static UndefinedGlobal *memoryBase;
493 static DefinedData *definedMemoryBase; 576 static DefinedData *definedMemoryBase;
577
578 // __indirect_function_table
579 // Used as an address space for function pointers, with each function that is
580 // used as a function pointer being allocated a slot.
581 static TableSymbol *indirectFunctionTable;
494 }; 582 };
495 583
496 // A buffer class that is large enough to hold any Symbol-derived 584 // A buffer class that is large enough to hold any Symbol-derived
497 // object. We allocate memory using this class and instantiate a symbol 585 // object. We allocate memory using this class and instantiate a symbol
498 // using the placement new. 586 // using the placement new.
499 union SymbolUnion { 587 union SymbolUnion {
500 alignas(DefinedFunction) char a[sizeof(DefinedFunction)]; 588 alignas(DefinedFunction) char a[sizeof(DefinedFunction)];
501 alignas(DefinedData) char b[sizeof(DefinedData)]; 589 alignas(DefinedData) char b[sizeof(DefinedData)];
502 alignas(DefinedGlobal) char c[sizeof(DefinedGlobal)]; 590 alignas(DefinedGlobal) char c[sizeof(DefinedGlobal)];
503 alignas(DefinedEvent) char d[sizeof(DefinedEvent)]; 591 alignas(DefinedEvent) char d[sizeof(DefinedEvent)];
504 alignas(LazySymbol) char e[sizeof(LazySymbol)]; 592 alignas(DefinedTable) char e[sizeof(DefinedTable)];
505 alignas(UndefinedFunction) char f[sizeof(UndefinedFunction)]; 593 alignas(LazySymbol) char f[sizeof(LazySymbol)];
506 alignas(UndefinedData) char g[sizeof(UndefinedData)]; 594 alignas(UndefinedFunction) char g[sizeof(UndefinedFunction)];
507 alignas(UndefinedGlobal) char h[sizeof(UndefinedGlobal)]; 595 alignas(UndefinedData) char h[sizeof(UndefinedData)];
508 alignas(SectionSymbol) char i[sizeof(SectionSymbol)]; 596 alignas(UndefinedGlobal) char i[sizeof(UndefinedGlobal)];
597 alignas(UndefinedTable) char j[sizeof(UndefinedTable)];
598 alignas(SectionSymbol) char k[sizeof(SectionSymbol)];
509 }; 599 };
510 600
511 // It is important to keep the size of SymbolUnion small for performance and 601 // It is important to keep the size of SymbolUnion small for performance and
512 // memory usage reasons. 96 bytes is a soft limit based on the size of 602 // memory usage reasons. 96 bytes is a soft limit based on the size of
513 // UndefinedFunction on a 64-bit system. 603 // UndefinedFunction on a 64-bit system.
514 static_assert(sizeof(SymbolUnion) <= 112, "SymbolUnion too large"); 604 static_assert(sizeof(SymbolUnion) <= 120, "SymbolUnion too large");
515 605
516 void printTraceSymbol(Symbol *sym); 606 void printTraceSymbol(Symbol *sym);
517 void printTraceSymbolUndefined(StringRef name, const InputFile* file); 607 void printTraceSymbolUndefined(StringRef name, const InputFile* file);
518 608
519 template <typename T, typename... ArgT> 609 template <typename T, typename... ArgT>