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, InputSection *isec, 41 uint32_t value, bool isWeakDef, 42 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); 59 } else if (auto *dysym = dyn_cast<DylibSymbol>(s)) { 60 overridesWeakDef = !isWeakDef && dysym->isWeakDef(); 61 } 62 // Defined symbols take priority over other types of symbols, so in case 63 // of a name conflict, we fall through to the replaceSymbol() call below. 64 } 65 66 Defined *defined = 67 replaceSymbol<Defined>(s, name, isec, value, isWeakDef, 68 /*isExternal=*/true, isPrivateExtern); 69 defined->overridesWeakDef = overridesWeakDef; 70 return s; 71 } 72 73 Symbol *SymbolTable::addUndefined(StringRef name, bool isWeakRef) { 74 Symbol *s; 75 bool wasInserted; 76 std::tie(s, wasInserted) = insert(name); 77 78 auto refState = isWeakRef ? RefState::Weak : RefState::Strong; 79 80 if (wasInserted) 81 replaceSymbol<Undefined>(s, name, refState); 82 else if (auto *lazy = dyn_cast<LazySymbol>(s)) 83 lazy->fetchArchiveMember(); 84 else if (auto *dynsym = dyn_cast<DylibSymbol>(s)) 85 dynsym->refState = std::max(dynsym->refState, refState); 86 else if (auto *undefined = dyn_cast<Undefined>(s)) 87 undefined->refState = std::max(undefined->refState, refState); 88 return s; 89 } 90 91 Symbol *SymbolTable::addCommon(StringRef name, InputFile *file, uint64_t size, 92 uint32_t align, bool isPrivateExtern) { 93 Symbol *s; 94 bool wasInserted; 95 std::tie(s, wasInserted) = insert(name); 96 97 if (!wasInserted) { 98 if (auto *common = dyn_cast<CommonSymbol>(s)) { 99 if (size < common->size) 100 return s; 101 } else if (isa<Defined>(s)) { 102 return s; 103 } 104 // Common symbols take priority over all non-Defined symbols, so in case of 105 // a name conflict, we fall through to the replaceSymbol() call below. 106 } 107 108 replaceSymbol<CommonSymbol>(s, name, file, size, align, isPrivateExtern); 109 return s; 110 } 111 112 Symbol *SymbolTable::addDylib(StringRef name, DylibFile *file, bool isWeakDef, 113 bool isTlv) { 114 Symbol *s; 115 bool wasInserted; 116 std::tie(s, wasInserted) = insert(name); 117 118 auto refState = RefState::Unreferenced; 119 if (!wasInserted) { 120 if (auto *defined = dyn_cast<Defined>(s)) { 121 if (isWeakDef && !defined->isWeakDef()) 122 defined->overridesWeakDef = true; 123 } else if (auto *undefined = dyn_cast<Undefined>(s)) { 124 refState = undefined->refState; 125 } else if (auto *dysym = dyn_cast<DylibSymbol>(s)) { 126 refState = dysym->refState; 127 } 128 } 129 130 if (wasInserted || isa<Undefined>(s) || 131 (isa<DylibSymbol>(s) && !isWeakDef && s->isWeakDef())) 132 replaceSymbol<DylibSymbol>(s, file, name, isWeakDef, refState, isTlv); 133 134 return s; 135 } 136 137 Symbol *SymbolTable::addLazy(StringRef name, ArchiveFile *file, 138 const object::Archive::Symbol &sym) { 139 Symbol *s; 140 bool wasInserted; 141 std::tie(s, wasInserted) = insert(name); 142 143 if (wasInserted) 144 replaceSymbol<LazySymbol>(s, file, sym); 145 else if (isa<Undefined>(s) || (isa<DylibSymbol>(s) && s->isWeakDef())) 146 file->fetch(sym); 147 return s; 148 } 149 150 Symbol *SymbolTable::addDSOHandle(const MachHeaderSection *header) { 151 Symbol *s; 152 bool wasInserted; 153 std::tie(s, wasInserted) = insert(DSOHandle::name); 154 if (!wasInserted) { 155 // FIXME: Make every symbol (including absolute symbols) contain a 156 // reference to their originating file, then add that file name to this 157 // error message. 158 if (isa<Defined>(s)) 159 error("found defined symbol with illegal name " + DSOHandle::name); 160 } 161 replaceSymbol<DSOHandle>(s, header); 162 return s; 163 } 164 165 void lld::macho::treatUndefinedSymbol(StringRef symbolName, 166 StringRef fileName) { 167 std::string message = ("undefined symbol: " + symbolName).str(); 168 if (!fileName.empty()) 169 message += ("\n>>> referenced by " + fileName).str(); 170 switch (config->undefinedSymbolTreatment) { 171 case UndefinedSymbolTreatment::suppress: 172 break; 173 case UndefinedSymbolTreatment::error: 174 error(message); 175 break; 176 case UndefinedSymbolTreatment::warning: 177 warn(message); 178 break; 179 case UndefinedSymbolTreatment::dynamic_lookup: 180 error("dynamic_lookup unimplemented for " + message); 181 break; 182 case UndefinedSymbolTreatment::unknown: 183 llvm_unreachable("unknown -undefined TREATMENT"); 184 } 185 } 186 187 SymbolTable *macho::symtab; 188