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(StringRef name) { 21 auto it = symMap.find(CachedHashStringRef(name)); 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 Symbol *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 s; 56 } 57 if (!defined->isWeakDef()) { 58 error("duplicate symbol: " + name + "\n>>> defined in " + 59 toString(defined->getFile()) + "\n>>> defined in " + 60 toString(file)); 61 } 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, isWeakDef, 71 /*isExternal=*/true, isPrivateExtern); 72 defined->overridesWeakDef = overridesWeakDef; 73 return s; 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 auto 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 auto 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 if (wasInserted || isa<Undefined>(s) || 135 (isa<DylibSymbol>(s) && !isWeakDef && s->isWeakDef())) 136 replaceSymbol<DylibSymbol>(s, file, name, isWeakDef, refState, isTlv); 137 138 return s; 139 } 140 141 Symbol *SymbolTable::addLazy(StringRef name, ArchiveFile *file, 142 const object::Archive::Symbol &sym) { 143 Symbol *s; 144 bool wasInserted; 145 std::tie(s, wasInserted) = insert(name); 146 147 if (wasInserted) 148 replaceSymbol<LazySymbol>(s, file, sym); 149 else if (isa<Undefined>(s) || (isa<DylibSymbol>(s) && s->isWeakDef())) 150 file->fetch(sym); 151 return s; 152 } 153 154 Symbol *SymbolTable::addDSOHandle(const MachHeaderSection *header) { 155 Symbol *s; 156 bool wasInserted; 157 std::tie(s, wasInserted) = insert(DSOHandle::name); 158 if (!wasInserted) { 159 // FIXME: Make every symbol (including absolute symbols) contain a 160 // reference to their originating file, then add that file name to this 161 // error message. 162 if (isa<Defined>(s)) 163 error("found defined symbol with illegal name " + DSOHandle::name); 164 } 165 replaceSymbol<DSOHandle>(s, header); 166 return s; 167 } 168 169 void lld::macho::treatUndefinedSymbol(const Undefined &sym) { 170 std::string message = "undefined symbol: " + toString(sym); 171 std::string fileName = toString(sym.getFile()); 172 173 if (!fileName.empty()) 174 message += "\n>>> referenced by " + fileName; 175 switch (config->undefinedSymbolTreatment) { 176 case UndefinedSymbolTreatment::suppress: 177 break; 178 case UndefinedSymbolTreatment::error: 179 error(message); 180 break; 181 case UndefinedSymbolTreatment::warning: 182 warn(message); 183 break; 184 case UndefinedSymbolTreatment::dynamic_lookup: 185 error("dynamic_lookup unimplemented for " + message); 186 break; 187 case UndefinedSymbolTreatment::unknown: 188 llvm_unreachable("unknown -undefined TREATMENT"); 189 } 190 } 191 192 SymbolTable *macho::symtab; 193