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