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