173
|
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_MACHO_SYMBOLS_H
|
|
10 #define LLD_MACHO_SYMBOLS_H
|
|
11
|
|
12 #include "InputSection.h"
|
|
13 #include "Target.h"
|
|
14 #include "lld/Common/Strings.h"
|
|
15 #include "llvm/Object/Archive.h"
|
|
16
|
|
17 namespace lld {
|
|
18 namespace macho {
|
|
19
|
|
20 class InputSection;
|
|
21 class DylibFile;
|
|
22 class ArchiveFile;
|
|
23
|
|
24 struct StringRefZ {
|
|
25 StringRefZ(const char *s) : data(s), size(-1) {}
|
|
26 StringRefZ(StringRef s) : data(s.data()), size(s.size()) {}
|
|
27
|
|
28 const char *data;
|
|
29 const uint32_t size;
|
|
30 };
|
|
31
|
|
32 class Symbol {
|
|
33 public:
|
|
34 enum Kind {
|
|
35 DefinedKind,
|
|
36 UndefinedKind,
|
|
37 DylibKind,
|
|
38 LazyKind,
|
|
39 };
|
|
40
|
|
41 Kind kind() const { return static_cast<Kind>(symbolKind); }
|
|
42
|
|
43 StringRef getName() const { return {name.data, name.size}; }
|
|
44
|
|
45 uint64_t getVA() const;
|
|
46
|
|
47 protected:
|
|
48 Symbol(Kind k, StringRefZ name) : symbolKind(k), name(name) {}
|
|
49
|
|
50 Kind symbolKind;
|
|
51 StringRefZ name;
|
|
52 };
|
|
53
|
|
54 class Defined : public Symbol {
|
|
55 public:
|
|
56 Defined(StringRefZ name, InputSection *isec, uint32_t value)
|
|
57 : Symbol(DefinedKind, name), isec(isec), value(value) {}
|
|
58
|
|
59 InputSection *isec;
|
|
60 uint32_t value;
|
|
61
|
|
62 static bool classof(const Symbol *s) { return s->kind() == DefinedKind; }
|
|
63 };
|
|
64
|
|
65 class Undefined : public Symbol {
|
|
66 public:
|
|
67 Undefined(StringRefZ name) : Symbol(UndefinedKind, name) {}
|
|
68
|
|
69 static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; }
|
|
70 };
|
|
71
|
|
72 class DylibSymbol : public Symbol {
|
|
73 public:
|
|
74 DylibSymbol(DylibFile *file, StringRefZ name)
|
|
75 : Symbol(DylibKind, name), file(file) {}
|
|
76
|
|
77 static bool classof(const Symbol *s) { return s->kind() == DylibKind; }
|
|
78
|
|
79 DylibFile *file;
|
|
80 uint32_t gotIndex = UINT32_MAX;
|
|
81 uint32_t stubsIndex = UINT32_MAX;
|
|
82 uint32_t lazyBindOffset = UINT32_MAX;
|
|
83 };
|
|
84
|
|
85 class LazySymbol : public Symbol {
|
|
86 public:
|
|
87 LazySymbol(ArchiveFile *file, const llvm::object::Archive::Symbol &sym)
|
|
88 : Symbol(LazyKind, sym.getName()), file(file), sym(sym) {}
|
|
89
|
|
90 static bool classof(const Symbol *s) { return s->kind() == LazyKind; }
|
|
91
|
|
92 void fetchArchiveMember();
|
|
93
|
|
94 private:
|
|
95 ArchiveFile *file;
|
|
96 const llvm::object::Archive::Symbol sym;
|
|
97 };
|
|
98
|
|
99 inline uint64_t Symbol::getVA() const {
|
|
100 if (auto *d = dyn_cast<Defined>(this))
|
|
101 return d->isec->getVA() + d->value;
|
|
102 return 0;
|
|
103 }
|
|
104
|
|
105 union SymbolUnion {
|
|
106 alignas(Defined) char a[sizeof(Defined)];
|
|
107 alignas(Undefined) char b[sizeof(Undefined)];
|
|
108 alignas(DylibSymbol) char c[sizeof(DylibSymbol)];
|
|
109 alignas(LazySymbol) char d[sizeof(LazySymbol)];
|
|
110 };
|
|
111
|
|
112 template <typename T, typename... ArgT>
|
|
113 void replaceSymbol(Symbol *s, ArgT &&... arg) {
|
|
114 static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
|
|
115 static_assert(alignof(T) <= alignof(SymbolUnion),
|
|
116 "SymbolUnion not aligned enough");
|
|
117 assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
|
|
118 "Not a Symbol");
|
|
119
|
|
120 new (s) T(std::forward<ArgT>(arg)...);
|
|
121 }
|
|
122
|
|
123 } // namespace macho
|
|
124
|
|
125 std::string toString(const macho::Symbol &);
|
|
126 } // namespace lld
|
|
127
|
|
128 #endif
|