Mercurial > hg > CbC > CbC_llvm
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; |