comparison lld/MachO/SymbolTable.cpp @ 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
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 // 6 //
7 //===----------------------------------------------------------------------===// 7 //===----------------------------------------------------------------------===//
8 8
9 #include "SymbolTable.h" 9 #include "SymbolTable.h"
10 #include "Config.h"
10 #include "InputFiles.h" 11 #include "InputFiles.h"
11 #include "Symbols.h" 12 #include "Symbols.h"
12 #include "lld/Common/ErrorHandler.h" 13 #include "lld/Common/ErrorHandler.h"
13 #include "lld/Common/Memory.h" 14 #include "lld/Common/Memory.h"
14 15
15 using namespace llvm; 16 using namespace llvm;
16 using namespace lld; 17 using namespace lld;
17 using namespace lld::macho; 18 using namespace lld::macho;
18 19
19 Symbol *SymbolTable::find(StringRef name) { 20 Symbol *SymbolTable::find(CachedHashStringRef cachedName) {
20 auto it = symMap.find(llvm::CachedHashStringRef(name)); 21 auto it = symMap.find(cachedName);
21 if (it == symMap.end()) 22 if (it == symMap.end())
22 return nullptr; 23 return nullptr;
23 return symVector[it->second]; 24 return symVector[it->second];
24 } 25 }
25 26
26 std::pair<Symbol *, bool> SymbolTable::insert(StringRef name) { 27 std::pair<Symbol *, bool> SymbolTable::insert(StringRef name,
28 const InputFile *file) {
27 auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()}); 29 auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()});
28 30
29 // Name already present in the symbol table. 31 Symbol *sym;
30 if (!p.second) 32 if (!p.second) {
31 return {symVector[p.first->second], false}; 33 // Name already present in the symbol table.
32 34 sym = symVector[p.first->second];
33 // Name is a new symbol. 35 } else {
34 Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 36 // Name is a new symbol.
35 symVector.push_back(sym); 37 sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
36 return {sym, true}; 38 symVector.push_back(sym);
37 } 39 }
38 40
39 Symbol *SymbolTable::addDefined(StringRef name, InputSection *isec, 41 sym->isUsedInRegularObj |= !file || isa<ObjFile>(file);
40 uint32_t value) { 42 return {sym, p.second};
41 Symbol *s; 43 }
42 bool wasInserted; 44
43 std::tie(s, wasInserted) = insert(name); 45 Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
44 46 InputSection *isec, uint64_t value,
45 if (!wasInserted && isa<Defined>(s)) 47 uint64_t size, bool isWeakDef,
46 error("duplicate symbol: " + name); 48 bool isPrivateExtern, bool isThumb,
47 49 bool isReferencedDynamically,
48 replaceSymbol<Defined>(s, name, isec, value); 50 bool noDeadStrip) {
49 return s; 51 Symbol *s;
50 } 52 bool wasInserted;
51 53 bool overridesWeakDef = false;
52 Symbol *SymbolTable::addUndefined(StringRef name) { 54 std::tie(s, wasInserted) = insert(name, file);
53 Symbol *s; 55
54 bool wasInserted; 56 assert(!isWeakDef || (isa<BitcodeFile>(file) && !isec) ||
55 std::tie(s, wasInserted) = insert(name); 57 (isa<ObjFile>(file) && file == isec->file));
58
59 if (!wasInserted) {
60 if (auto *defined = dyn_cast<Defined>(s)) {
61 if (isWeakDef) {
62 if (defined->isWeakDef()) {
63 // Both old and new symbol weak (e.g. inline function in two TUs):
64 // If one of them isn't private extern, the merged symbol isn't.
65 defined->privateExtern &= isPrivateExtern;
66 defined->referencedDynamically |= isReferencedDynamically;
67 defined->noDeadStrip |= noDeadStrip;
68
69 // FIXME: Handle this for bitcode files.
70 // FIXME: We currently only do this if both symbols are weak.
71 // We could do this if either is weak (but getting the
72 // case where !isWeakDef && defined->isWeakDef() right
73 // requires some care and testing).
74 if (isec)
75 isec->wasCoalesced = true;
76 }
77
78 return defined;
79 }
80 if (!defined->isWeakDef())
81 error("duplicate symbol: " + name + "\n>>> defined in " +
82 toString(defined->getFile()) + "\n>>> defined in " +
83 toString(file));
84 } else if (auto *dysym = dyn_cast<DylibSymbol>(s)) {
85 overridesWeakDef = !isWeakDef && dysym->isWeakDef();
86 dysym->unreference();
87 }
88 // Defined symbols take priority over other types of symbols, so in case
89 // of a name conflict, we fall through to the replaceSymbol() call below.
90 }
91
92 Defined *defined = replaceSymbol<Defined>(
93 s, name, file, isec, value, size, isWeakDef, /*isExternal=*/true,
94 isPrivateExtern, isThumb, isReferencedDynamically, noDeadStrip);
95 defined->overridesWeakDef = overridesWeakDef;
96 return defined;
97 }
98
99 Symbol *SymbolTable::addUndefined(StringRef name, InputFile *file,
100 bool isWeakRef) {
101 Symbol *s;
102 bool wasInserted;
103 std::tie(s, wasInserted) = insert(name, file);
104
105 RefState refState = isWeakRef ? RefState::Weak : RefState::Strong;
56 106
57 if (wasInserted) 107 if (wasInserted)
58 replaceSymbol<Undefined>(s, name); 108 replaceSymbol<Undefined>(s, name, file, refState);
59 else if (LazySymbol *lazy = dyn_cast<LazySymbol>(s)) 109 else if (auto *lazy = dyn_cast<LazySymbol>(s))
60 lazy->fetchArchiveMember(); 110 lazy->fetchArchiveMember();
61 return s; 111 else if (auto *dynsym = dyn_cast<DylibSymbol>(s))
62 } 112 dynsym->reference(refState);
63 113 else if (auto *undefined = dyn_cast<Undefined>(s))
64 Symbol *SymbolTable::addDylib(StringRef name, DylibFile *file) { 114 undefined->refState = std::max(undefined->refState, refState);
65 Symbol *s; 115 return s;
66 bool wasInserted; 116 }
67 std::tie(s, wasInserted) = insert(name); 117
68 118 Symbol *SymbolTable::addCommon(StringRef name, InputFile *file, uint64_t size,
69 if (wasInserted || isa<Undefined>(s)) 119 uint32_t align, bool isPrivateExtern) {
70 replaceSymbol<DylibSymbol>(s, file, name); 120 Symbol *s;
71 return s; 121 bool wasInserted;
122 std::tie(s, wasInserted) = insert(name, file);
123
124 if (!wasInserted) {
125 if (auto *common = dyn_cast<CommonSymbol>(s)) {
126 if (size < common->size)
127 return s;
128 } else if (isa<Defined>(s)) {
129 return s;
130 }
131 // Common symbols take priority over all non-Defined symbols, so in case of
132 // a name conflict, we fall through to the replaceSymbol() call below.
133 }
134
135 replaceSymbol<CommonSymbol>(s, name, file, size, align, isPrivateExtern);
136 return s;
137 }
138
139 Symbol *SymbolTable::addDylib(StringRef name, DylibFile *file, bool isWeakDef,
140 bool isTlv) {
141 Symbol *s;
142 bool wasInserted;
143 std::tie(s, wasInserted) = insert(name, file);
144
145 RefState refState = RefState::Unreferenced;
146 if (!wasInserted) {
147 if (auto *defined = dyn_cast<Defined>(s)) {
148 if (isWeakDef && !defined->isWeakDef())
149 defined->overridesWeakDef = true;
150 } else if (auto *undefined = dyn_cast<Undefined>(s)) {
151 refState = undefined->refState;
152 } else if (auto *dysym = dyn_cast<DylibSymbol>(s)) {
153 refState = dysym->getRefState();
154 }
155 }
156
157 bool isDynamicLookup = file == nullptr;
158 if (wasInserted || isa<Undefined>(s) ||
159 (isa<DylibSymbol>(s) &&
160 ((!isWeakDef && s->isWeakDef()) ||
161 (!isDynamicLookup && cast<DylibSymbol>(s)->isDynamicLookup())))) {
162 if (auto *dynsym = dyn_cast<DylibSymbol>(s))
163 dynsym->unreference();
164 replaceSymbol<DylibSymbol>(s, file, name, isWeakDef, refState, isTlv);
165 }
166
167 return s;
168 }
169
170 Symbol *SymbolTable::addDynamicLookup(StringRef name) {
171 return addDylib(name, /*file=*/nullptr, /*isWeakDef=*/false, /*isTlv=*/false);
72 } 172 }
73 173
74 Symbol *SymbolTable::addLazy(StringRef name, ArchiveFile *file, 174 Symbol *SymbolTable::addLazy(StringRef name, ArchiveFile *file,
75 const llvm::object::Archive::Symbol &sym) { 175 const object::Archive::Symbol &sym) {
76 Symbol *s; 176 Symbol *s;
77 bool wasInserted; 177 bool wasInserted;
78 std::tie(s, wasInserted) = insert(name); 178 std::tie(s, wasInserted) = insert(name, file);
79 179
80 if (wasInserted) 180 if (wasInserted)
81 replaceSymbol<LazySymbol>(s, file, sym); 181 replaceSymbol<LazySymbol>(s, file, sym);
82 else if (isa<Undefined>(s)) 182 else if (isa<Undefined>(s) || (isa<DylibSymbol>(s) && s->isWeakDef()))
83 file->fetch(sym); 183 file->fetch(sym);
84 return s; 184 return s;
85 } 185 }
86 186
187 Defined *SymbolTable::addSynthetic(StringRef name, InputSection *isec,
188 uint64_t value, bool isPrivateExtern,
189 bool includeInSymtab,
190 bool referencedDynamically) {
191 Defined *s = addDefined(name, nullptr, isec, value, /*size=*/0,
192 /*isWeakDef=*/false, isPrivateExtern,
193 /*isThumb=*/false, referencedDynamically,
194 /*noDeadStrip=*/false);
195 s->includeInSymtab = includeInSymtab;
196 return s;
197 }
198
199 void lld::macho::treatUndefinedSymbol(const Undefined &sym, StringRef source) {
200 auto message = [source, &sym]() {
201 std::string message = "undefined symbol: " + toString(sym);
202 if (!source.empty())
203 message += "\n>>> referenced by " + source.str();
204 else
205 message += "\n>>> referenced by " + toString(sym.getFile());
206 return message;
207 };
208 switch (config->undefinedSymbolTreatment) {
209 case UndefinedSymbolTreatment::error:
210 error(message());
211 break;
212 case UndefinedSymbolTreatment::warning:
213 warn(message());
214 LLVM_FALLTHROUGH;
215 case UndefinedSymbolTreatment::dynamic_lookup:
216 case UndefinedSymbolTreatment::suppress:
217 symtab->addDynamicLookup(sym.getName());
218 break;
219 case UndefinedSymbolTreatment::unknown:
220 llvm_unreachable("unknown -undefined TREATMENT");
221 }
222 }
223
87 SymbolTable *macho::symtab; 224 SymbolTable *macho::symtab;