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