1 //===- Symbols.cpp --------------------------------------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "Symbols.h" 11 #include "Error.h" 12 #include "InputFiles.h" 13 #include "Strings.h" 14 #include "lld/Support/Memory.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/Support/Debug.h" 17 #include "llvm/Support/raw_ostream.h" 18 19 using namespace llvm; 20 using namespace llvm::object; 21 22 namespace lld { 23 namespace coff { 24 25 StringRef SymbolBody::getName() { 26 // DefinedCOFF names are read lazily for a performance reason. 27 // Non-external symbol names are never used by the linker except for logging 28 // or debugging. Their internal references are resolved not by name but by 29 // symbol index. And because they are not external, no one can refer them by 30 // name. Object files contain lots of non-external symbols, and creating 31 // StringRefs for them (which involves lots of strlen() on the string table) 32 // is a waste of time. 33 if (Name.empty()) { 34 auto *D = cast<DefinedCOFF>(this); 35 D->File->getCOFFObj()->getSymbolName(D->Sym, Name); 36 } 37 return Name; 38 } 39 40 InputFile *SymbolBody::getFile() { 41 if (auto *Sym = dyn_cast<DefinedCOFF>(this)) 42 return Sym->File; 43 if (auto *Sym = dyn_cast<DefinedBitcode>(this)) 44 return Sym->File; 45 if (auto *Sym = dyn_cast<Lazy>(this)) 46 return Sym->File; 47 return nullptr; 48 } 49 50 COFFSymbolRef DefinedCOFF::getCOFFSymbol() { 51 size_t SymSize = File->getCOFFObj()->getSymbolTableEntrySize(); 52 if (SymSize == sizeof(coff_symbol16)) 53 return COFFSymbolRef(reinterpret_cast<const coff_symbol16 *>(Sym)); 54 assert(SymSize == sizeof(coff_symbol32)); 55 return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym)); 56 } 57 58 DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S, 59 uint16_t Machine) 60 : Defined(DefinedImportThunkKind, Name) { 61 switch (Machine) { 62 case AMD64: Data.reset(new ImportThunkChunkX64(S)); return; 63 case I386: Data.reset(new ImportThunkChunkX86(S)); return; 64 case ARMNT: Data.reset(new ImportThunkChunkARM(S)); return; 65 default: llvm_unreachable("unknown machine type"); 66 } 67 } 68 69 Defined *Undefined::getWeakAlias() { 70 // A weak alias may be a weak alias to another symbol, so check recursively. 71 for (SymbolBody *A = WeakAlias; A; A = cast<Undefined>(A)->WeakAlias) 72 if (auto *D = dyn_cast<Defined>(A)) 73 return D; 74 return nullptr; 75 } 76 77 // Returns a symbol name for an error message. 78 std::string toString(SymbolBody &B) { 79 if (Optional<std::string> S = demangle(B.getName())) 80 return ("\"" + *S + "\" (" + B.getName() + ")").str(); 81 return B.getName(); 82 } 83 84 } // namespace coff 85 } // namespace lld 86