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 "InputFiles.h" 11 #include "Symbols.h" 12 #include "lld/Common/ErrorHandler.h" 13 #include "lld/Common/Memory.h" 14 15 using namespace llvm; 16 using namespace lld; 17 using namespace lld::macho; 18 19 Symbol *SymbolTable::find(StringRef name) { 20 auto it = symMap.find(llvm::CachedHashStringRef(name)); 21 if (it == symMap.end()) 22 return nullptr; 23 return symVector[it->second]; 24 } 25 26 std::pair<Symbol *, bool> SymbolTable::insert(StringRef name) { 27 auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()}); 28 29 // Name already present in the symbol table. 30 if (!p.second) 31 return {symVector[p.first->second], false}; 32 33 // Name is a new symbol. 34 Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 35 symVector.push_back(sym); 36 return {sym, true}; 37 } 38 39 Symbol *SymbolTable::addDefined(StringRef name, InputSection *isec, 40 uint32_t value, bool isWeakDef) { 41 Symbol *s; 42 bool wasInserted; 43 bool overridesWeakDef = false; 44 std::tie(s, wasInserted) = insert(name); 45 46 if (!wasInserted) { 47 if (auto *defined = dyn_cast<Defined>(s)) { 48 if (isWeakDef) 49 return s; 50 if (!defined->isWeakDef()) 51 error("duplicate symbol: " + name); 52 } else if (auto *dysym = dyn_cast<DylibSymbol>(s)) { 53 overridesWeakDef = !isWeakDef && dysym->isWeakDef(); 54 } 55 // Defined symbols take priority over other types of symbols, so in case 56 // of a name conflict, we fall through to the replaceSymbol() call below. 57 } 58 59 Defined *defined = replaceSymbol<Defined>(s, name, isec, value, isWeakDef, 60 /*isExternal=*/true); 61 defined->overridesWeakDef = overridesWeakDef; 62 return s; 63 } 64 65 Symbol *SymbolTable::addUndefined(StringRef name) { 66 Symbol *s; 67 bool wasInserted; 68 std::tie(s, wasInserted) = insert(name); 69 70 if (wasInserted) 71 replaceSymbol<Undefined>(s, name); 72 else if (LazySymbol *lazy = dyn_cast<LazySymbol>(s)) 73 lazy->fetchArchiveMember(); 74 return s; 75 } 76 77 Symbol *SymbolTable::addCommon(StringRef name, InputFile *file, uint64_t size, 78 uint32_t align) { 79 Symbol *s; 80 bool wasInserted; 81 std::tie(s, wasInserted) = insert(name); 82 83 if (!wasInserted) { 84 if (auto *common = dyn_cast<CommonSymbol>(s)) { 85 if (size < common->size) 86 return s; 87 } else if (isa<Defined>(s)) { 88 return s; 89 } 90 // Common symbols take priority over all non-Defined symbols, so in case of 91 // a name conflict, we fall through to the replaceSymbol() call below. 92 } 93 94 replaceSymbol<CommonSymbol>(s, name, file, size, align); 95 return s; 96 } 97 98 Symbol *SymbolTable::addDylib(StringRef name, DylibFile *file, bool isWeakDef, 99 bool isTlv) { 100 Symbol *s; 101 bool wasInserted; 102 std::tie(s, wasInserted) = insert(name); 103 104 if (!wasInserted && isWeakDef) 105 if (auto *defined = dyn_cast<Defined>(s)) 106 if (!defined->isWeakDef()) 107 defined->overridesWeakDef = true; 108 109 if (wasInserted || isa<Undefined>(s) || 110 (isa<DylibSymbol>(s) && !isWeakDef && s->isWeakDef())) 111 replaceSymbol<DylibSymbol>(s, file, name, isWeakDef, isTlv); 112 113 return s; 114 } 115 116 Symbol *SymbolTable::addLazy(StringRef name, ArchiveFile *file, 117 const llvm::object::Archive::Symbol &sym) { 118 Symbol *s; 119 bool wasInserted; 120 std::tie(s, wasInserted) = insert(name); 121 122 if (wasInserted) 123 replaceSymbol<LazySymbol>(s, file, sym); 124 else if (isa<Undefined>(s) || (isa<DylibSymbol>(s) && s->isWeakDef())) 125 file->fetch(sym); 126 return s; 127 } 128 129 Symbol *SymbolTable::addDSOHandle(const MachHeaderSection *header) { 130 Symbol *s; 131 bool wasInserted; 132 std::tie(s, wasInserted) = insert(DSOHandle::name); 133 if (!wasInserted) { 134 // FIXME: Make every symbol (including absolute symbols) contain a 135 // reference to their originating file, then add that file name to this 136 // error message. 137 if (auto *defined = dyn_cast<Defined>(s)) 138 error("found defined symbol with illegal name " + DSOHandle::name); 139 } 140 replaceSymbol<DSOHandle>(s, header); 141 return s; 142 } 143 144 SymbolTable *macho::symtab; 145