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