15ffd83dbSDimitry Andric //===- SymbolTable.cpp ----------------------------------------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #include "SymbolTable.h" 10*e8d8bef9SDimitry Andric #include "Config.h" 115ffd83dbSDimitry Andric #include "InputFiles.h" 125ffd83dbSDimitry Andric #include "Symbols.h" 135ffd83dbSDimitry Andric #include "lld/Common/ErrorHandler.h" 145ffd83dbSDimitry Andric #include "lld/Common/Memory.h" 155ffd83dbSDimitry Andric 165ffd83dbSDimitry Andric using namespace llvm; 175ffd83dbSDimitry Andric using namespace lld; 185ffd83dbSDimitry Andric using namespace lld::macho; 195ffd83dbSDimitry Andric 205ffd83dbSDimitry Andric Symbol *SymbolTable::find(StringRef name) { 21*e8d8bef9SDimitry Andric auto it = symMap.find(CachedHashStringRef(name)); 225ffd83dbSDimitry Andric if (it == symMap.end()) 235ffd83dbSDimitry Andric return nullptr; 245ffd83dbSDimitry Andric return symVector[it->second]; 255ffd83dbSDimitry Andric } 265ffd83dbSDimitry Andric 275ffd83dbSDimitry Andric std::pair<Symbol *, bool> SymbolTable::insert(StringRef name) { 285ffd83dbSDimitry Andric auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()}); 295ffd83dbSDimitry Andric 305ffd83dbSDimitry Andric // Name already present in the symbol table. 315ffd83dbSDimitry Andric if (!p.second) 325ffd83dbSDimitry Andric return {symVector[p.first->second], false}; 335ffd83dbSDimitry Andric 345ffd83dbSDimitry Andric // Name is a new symbol. 355ffd83dbSDimitry Andric Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 365ffd83dbSDimitry Andric symVector.push_back(sym); 375ffd83dbSDimitry Andric return {sym, true}; 385ffd83dbSDimitry Andric } 395ffd83dbSDimitry Andric 405ffd83dbSDimitry Andric Symbol *SymbolTable::addDefined(StringRef name, InputSection *isec, 41*e8d8bef9SDimitry Andric uint32_t value, bool isWeakDef, 42*e8d8bef9SDimitry Andric bool isPrivateExtern) { 435ffd83dbSDimitry Andric Symbol *s; 445ffd83dbSDimitry Andric bool wasInserted; 45*e8d8bef9SDimitry Andric bool overridesWeakDef = false; 465ffd83dbSDimitry Andric std::tie(s, wasInserted) = insert(name); 475ffd83dbSDimitry Andric 48*e8d8bef9SDimitry Andric if (!wasInserted) { 49*e8d8bef9SDimitry Andric if (auto *defined = dyn_cast<Defined>(s)) { 50*e8d8bef9SDimitry Andric if (isWeakDef) { 51*e8d8bef9SDimitry Andric // Both old and new symbol weak (e.g. inline function in two TUs): 52*e8d8bef9SDimitry Andric // If one of them isn't private extern, the merged symbol isn't. 53*e8d8bef9SDimitry Andric if (defined->isWeakDef()) 54*e8d8bef9SDimitry Andric defined->privateExtern &= isPrivateExtern; 55*e8d8bef9SDimitry Andric return s; 56*e8d8bef9SDimitry Andric } 57*e8d8bef9SDimitry Andric if (!defined->isWeakDef()) 585ffd83dbSDimitry Andric error("duplicate symbol: " + name); 59*e8d8bef9SDimitry Andric } else if (auto *dysym = dyn_cast<DylibSymbol>(s)) { 60*e8d8bef9SDimitry Andric overridesWeakDef = !isWeakDef && dysym->isWeakDef(); 61*e8d8bef9SDimitry Andric } 62*e8d8bef9SDimitry Andric // Defined symbols take priority over other types of symbols, so in case 63*e8d8bef9SDimitry Andric // of a name conflict, we fall through to the replaceSymbol() call below. 64*e8d8bef9SDimitry Andric } 655ffd83dbSDimitry Andric 66*e8d8bef9SDimitry Andric Defined *defined = 67*e8d8bef9SDimitry Andric replaceSymbol<Defined>(s, name, isec, value, isWeakDef, 68*e8d8bef9SDimitry Andric /*isExternal=*/true, isPrivateExtern); 69*e8d8bef9SDimitry Andric defined->overridesWeakDef = overridesWeakDef; 705ffd83dbSDimitry Andric return s; 715ffd83dbSDimitry Andric } 725ffd83dbSDimitry Andric 73*e8d8bef9SDimitry Andric Symbol *SymbolTable::addUndefined(StringRef name, bool isWeakRef) { 745ffd83dbSDimitry Andric Symbol *s; 755ffd83dbSDimitry Andric bool wasInserted; 765ffd83dbSDimitry Andric std::tie(s, wasInserted) = insert(name); 775ffd83dbSDimitry Andric 78*e8d8bef9SDimitry Andric auto refState = isWeakRef ? RefState::Weak : RefState::Strong; 79*e8d8bef9SDimitry Andric 805ffd83dbSDimitry Andric if (wasInserted) 81*e8d8bef9SDimitry Andric replaceSymbol<Undefined>(s, name, refState); 82*e8d8bef9SDimitry Andric else if (auto *lazy = dyn_cast<LazySymbol>(s)) 835ffd83dbSDimitry Andric lazy->fetchArchiveMember(); 84*e8d8bef9SDimitry Andric else if (auto *dynsym = dyn_cast<DylibSymbol>(s)) 85*e8d8bef9SDimitry Andric dynsym->refState = std::max(dynsym->refState, refState); 86*e8d8bef9SDimitry Andric else if (auto *undefined = dyn_cast<Undefined>(s)) 87*e8d8bef9SDimitry Andric undefined->refState = std::max(undefined->refState, refState); 885ffd83dbSDimitry Andric return s; 895ffd83dbSDimitry Andric } 905ffd83dbSDimitry Andric 91*e8d8bef9SDimitry Andric Symbol *SymbolTable::addCommon(StringRef name, InputFile *file, uint64_t size, 92*e8d8bef9SDimitry Andric uint32_t align, bool isPrivateExtern) { 935ffd83dbSDimitry Andric Symbol *s; 945ffd83dbSDimitry Andric bool wasInserted; 955ffd83dbSDimitry Andric std::tie(s, wasInserted) = insert(name); 965ffd83dbSDimitry Andric 97*e8d8bef9SDimitry Andric if (!wasInserted) { 98*e8d8bef9SDimitry Andric if (auto *common = dyn_cast<CommonSymbol>(s)) { 99*e8d8bef9SDimitry Andric if (size < common->size) 100*e8d8bef9SDimitry Andric return s; 101*e8d8bef9SDimitry Andric } else if (isa<Defined>(s)) { 102*e8d8bef9SDimitry Andric return s; 103*e8d8bef9SDimitry Andric } 104*e8d8bef9SDimitry Andric // Common symbols take priority over all non-Defined symbols, so in case of 105*e8d8bef9SDimitry Andric // a name conflict, we fall through to the replaceSymbol() call below. 106*e8d8bef9SDimitry Andric } 107*e8d8bef9SDimitry Andric 108*e8d8bef9SDimitry Andric replaceSymbol<CommonSymbol>(s, name, file, size, align, isPrivateExtern); 109*e8d8bef9SDimitry Andric return s; 110*e8d8bef9SDimitry Andric } 111*e8d8bef9SDimitry Andric 112*e8d8bef9SDimitry Andric Symbol *SymbolTable::addDylib(StringRef name, DylibFile *file, bool isWeakDef, 113*e8d8bef9SDimitry Andric bool isTlv) { 114*e8d8bef9SDimitry Andric Symbol *s; 115*e8d8bef9SDimitry Andric bool wasInserted; 116*e8d8bef9SDimitry Andric std::tie(s, wasInserted) = insert(name); 117*e8d8bef9SDimitry Andric 118*e8d8bef9SDimitry Andric auto refState = RefState::Unreferenced; 119*e8d8bef9SDimitry Andric if (!wasInserted) { 120*e8d8bef9SDimitry Andric if (auto *defined = dyn_cast<Defined>(s)) { 121*e8d8bef9SDimitry Andric if (isWeakDef && !defined->isWeakDef()) 122*e8d8bef9SDimitry Andric defined->overridesWeakDef = true; 123*e8d8bef9SDimitry Andric } else if (auto *undefined = dyn_cast<Undefined>(s)) { 124*e8d8bef9SDimitry Andric refState = undefined->refState; 125*e8d8bef9SDimitry Andric } else if (auto *dysym = dyn_cast<DylibSymbol>(s)) { 126*e8d8bef9SDimitry Andric refState = dysym->refState; 127*e8d8bef9SDimitry Andric } 128*e8d8bef9SDimitry Andric } 129*e8d8bef9SDimitry Andric 130*e8d8bef9SDimitry Andric if (wasInserted || isa<Undefined>(s) || 131*e8d8bef9SDimitry Andric (isa<DylibSymbol>(s) && !isWeakDef && s->isWeakDef())) 132*e8d8bef9SDimitry Andric replaceSymbol<DylibSymbol>(s, file, name, isWeakDef, refState, isTlv); 133*e8d8bef9SDimitry Andric 1345ffd83dbSDimitry Andric return s; 1355ffd83dbSDimitry Andric } 1365ffd83dbSDimitry Andric 1375ffd83dbSDimitry Andric Symbol *SymbolTable::addLazy(StringRef name, ArchiveFile *file, 138*e8d8bef9SDimitry Andric const object::Archive::Symbol &sym) { 1395ffd83dbSDimitry Andric Symbol *s; 1405ffd83dbSDimitry Andric bool wasInserted; 1415ffd83dbSDimitry Andric std::tie(s, wasInserted) = insert(name); 1425ffd83dbSDimitry Andric 1435ffd83dbSDimitry Andric if (wasInserted) 1445ffd83dbSDimitry Andric replaceSymbol<LazySymbol>(s, file, sym); 145*e8d8bef9SDimitry Andric else if (isa<Undefined>(s) || (isa<DylibSymbol>(s) && s->isWeakDef())) 1465ffd83dbSDimitry Andric file->fetch(sym); 1475ffd83dbSDimitry Andric return s; 1485ffd83dbSDimitry Andric } 1495ffd83dbSDimitry Andric 150*e8d8bef9SDimitry Andric Symbol *SymbolTable::addDSOHandle(const MachHeaderSection *header) { 151*e8d8bef9SDimitry Andric Symbol *s; 152*e8d8bef9SDimitry Andric bool wasInserted; 153*e8d8bef9SDimitry Andric std::tie(s, wasInserted) = insert(DSOHandle::name); 154*e8d8bef9SDimitry Andric if (!wasInserted) { 155*e8d8bef9SDimitry Andric // FIXME: Make every symbol (including absolute symbols) contain a 156*e8d8bef9SDimitry Andric // reference to their originating file, then add that file name to this 157*e8d8bef9SDimitry Andric // error message. 158*e8d8bef9SDimitry Andric if (isa<Defined>(s)) 159*e8d8bef9SDimitry Andric error("found defined symbol with illegal name " + DSOHandle::name); 160*e8d8bef9SDimitry Andric } 161*e8d8bef9SDimitry Andric replaceSymbol<DSOHandle>(s, header); 162*e8d8bef9SDimitry Andric return s; 163*e8d8bef9SDimitry Andric } 164*e8d8bef9SDimitry Andric 165*e8d8bef9SDimitry Andric void lld::macho::treatUndefinedSymbol(StringRef symbolName, 166*e8d8bef9SDimitry Andric StringRef fileName) { 167*e8d8bef9SDimitry Andric std::string message = ("undefined symbol: " + symbolName).str(); 168*e8d8bef9SDimitry Andric if (!fileName.empty()) 169*e8d8bef9SDimitry Andric message += ("\n>>> referenced by " + fileName).str(); 170*e8d8bef9SDimitry Andric switch (config->undefinedSymbolTreatment) { 171*e8d8bef9SDimitry Andric case UndefinedSymbolTreatment::suppress: 172*e8d8bef9SDimitry Andric break; 173*e8d8bef9SDimitry Andric case UndefinedSymbolTreatment::error: 174*e8d8bef9SDimitry Andric error(message); 175*e8d8bef9SDimitry Andric break; 176*e8d8bef9SDimitry Andric case UndefinedSymbolTreatment::warning: 177*e8d8bef9SDimitry Andric warn(message); 178*e8d8bef9SDimitry Andric break; 179*e8d8bef9SDimitry Andric case UndefinedSymbolTreatment::dynamic_lookup: 180*e8d8bef9SDimitry Andric error("dynamic_lookup unimplemented for " + message); 181*e8d8bef9SDimitry Andric break; 182*e8d8bef9SDimitry Andric case UndefinedSymbolTreatment::unknown: 183*e8d8bef9SDimitry Andric llvm_unreachable("unknown -undefined TREATMENT"); 184*e8d8bef9SDimitry Andric } 185*e8d8bef9SDimitry Andric } 186*e8d8bef9SDimitry Andric 1875ffd83dbSDimitry Andric SymbolTable *macho::symtab; 188