10b57cec5SDimitry Andric //===- Symbols.cpp --------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "Symbols.h" 100b57cec5SDimitry Andric #include "InputFiles.h" 110b57cec5SDimitry Andric #include "lld/Common/ErrorHandler.h" 120b57cec5SDimitry Andric #include "lld/Common/Memory.h" 130b57cec5SDimitry Andric #include "lld/Common/Strings.h" 140b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 1585868e8aSDimitry Andric #include "llvm/Demangle/Demangle.h" 160b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 170b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric using namespace llvm; 200b57cec5SDimitry Andric using namespace llvm::object; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace lld::coff; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace lld { 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric static_assert(sizeof(SymbolUnion) <= 48, 270b57cec5SDimitry Andric "symbols should be optimized for memory usage"); 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric // Returns a symbol name for an error message. 3085868e8aSDimitry Andric static std::string maybeDemangleSymbol(StringRef symName) { 3185868e8aSDimitry Andric if (config->demangle) { 3285868e8aSDimitry Andric std::string prefix; 3385868e8aSDimitry Andric StringRef prefixless = symName; 3485868e8aSDimitry Andric if (prefixless.consume_front("__imp_")) 3585868e8aSDimitry Andric prefix = "__declspec(dllimport) "; 3685868e8aSDimitry Andric StringRef demangleInput = prefixless; 3785868e8aSDimitry Andric if (config->machine == I386) 3885868e8aSDimitry Andric demangleInput.consume_front("_"); 39*5ffd83dbSDimitry Andric std::string demangled = demangle(std::string(demangleInput)); 4085868e8aSDimitry Andric if (demangled != demangleInput) 41*5ffd83dbSDimitry Andric return prefix + demangle(std::string(demangleInput)); 4285868e8aSDimitry Andric return (prefix + prefixless).str(); 4385868e8aSDimitry Andric } 44*5ffd83dbSDimitry Andric return std::string(symName); 450b57cec5SDimitry Andric } 4685868e8aSDimitry Andric std::string toString(coff::Symbol &b) { 4785868e8aSDimitry Andric return maybeDemangleSymbol(b.getName()); 4885868e8aSDimitry Andric } 490b57cec5SDimitry Andric std::string toCOFFString(const Archive::Symbol &b) { 5085868e8aSDimitry Andric return maybeDemangleSymbol(b.getName()); 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric namespace coff { 540b57cec5SDimitry Andric 55*5ffd83dbSDimitry Andric void Symbol::computeName() { 56*5ffd83dbSDimitry Andric assert(nameData == nullptr && 57*5ffd83dbSDimitry Andric "should only compute the name once for DefinedCOFF symbols"); 580b57cec5SDimitry Andric auto *d = cast<DefinedCOFF>(this); 59*5ffd83dbSDimitry Andric StringRef nameStr = 60*5ffd83dbSDimitry Andric check(cast<ObjFile>(d->file)->getCOFFObj()->getSymbolName(d->sym)); 610b57cec5SDimitry Andric nameData = nameStr.data(); 620b57cec5SDimitry Andric nameSize = nameStr.size(); 630b57cec5SDimitry Andric assert(nameSize == nameStr.size() && "name length truncated"); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric InputFile *Symbol::getFile() { 670b57cec5SDimitry Andric if (auto *sym = dyn_cast<DefinedCOFF>(this)) 680b57cec5SDimitry Andric return sym->file; 6985868e8aSDimitry Andric if (auto *sym = dyn_cast<LazyArchive>(this)) 7085868e8aSDimitry Andric return sym->file; 7185868e8aSDimitry Andric if (auto *sym = dyn_cast<LazyObject>(this)) 720b57cec5SDimitry Andric return sym->file; 730b57cec5SDimitry Andric return nullptr; 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric bool Symbol::isLive() const { 770b57cec5SDimitry Andric if (auto *r = dyn_cast<DefinedRegular>(this)) 780b57cec5SDimitry Andric return r->getChunk()->live; 790b57cec5SDimitry Andric if (auto *imp = dyn_cast<DefinedImportData>(this)) 800b57cec5SDimitry Andric return imp->file->live; 810b57cec5SDimitry Andric if (auto *imp = dyn_cast<DefinedImportThunk>(this)) 820b57cec5SDimitry Andric return imp->wrappedSym->file->thunkLive; 830b57cec5SDimitry Andric // Assume any other kind of symbol is live. 840b57cec5SDimitry Andric return true; 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // MinGW specific. 880b57cec5SDimitry Andric void Symbol::replaceKeepingName(Symbol *other, size_t size) { 890b57cec5SDimitry Andric StringRef origName = getName(); 900b57cec5SDimitry Andric memcpy(this, other, size); 910b57cec5SDimitry Andric nameData = origName.data(); 920b57cec5SDimitry Andric nameSize = origName.size(); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric COFFSymbolRef DefinedCOFF::getCOFFSymbol() { 960b57cec5SDimitry Andric size_t symSize = cast<ObjFile>(file)->getCOFFObj()->getSymbolTableEntrySize(); 970b57cec5SDimitry Andric if (symSize == sizeof(coff_symbol16)) 980b57cec5SDimitry Andric return COFFSymbolRef(reinterpret_cast<const coff_symbol16 *>(sym)); 990b57cec5SDimitry Andric assert(symSize == sizeof(coff_symbol32)); 1000b57cec5SDimitry Andric return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(sym)); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric uint16_t DefinedAbsolute::numOutputSections; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric static Chunk *makeImportThunk(DefinedImportData *s, uint16_t machine) { 1060b57cec5SDimitry Andric if (machine == AMD64) 1070b57cec5SDimitry Andric return make<ImportThunkChunkX64>(s); 1080b57cec5SDimitry Andric if (machine == I386) 1090b57cec5SDimitry Andric return make<ImportThunkChunkX86>(s); 1100b57cec5SDimitry Andric if (machine == ARM64) 1110b57cec5SDimitry Andric return make<ImportThunkChunkARM64>(s); 1120b57cec5SDimitry Andric assert(machine == ARMNT); 1130b57cec5SDimitry Andric return make<ImportThunkChunkARM>(s); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric DefinedImportThunk::DefinedImportThunk(StringRef name, DefinedImportData *s, 1170b57cec5SDimitry Andric uint16_t machine) 1180b57cec5SDimitry Andric : Defined(DefinedImportThunkKind, name), wrappedSym(s), 1190b57cec5SDimitry Andric data(makeImportThunk(s, machine)) {} 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric Defined *Undefined::getWeakAlias() { 1220b57cec5SDimitry Andric // A weak alias may be a weak alias to another symbol, so check recursively. 1230b57cec5SDimitry Andric for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias) 1240b57cec5SDimitry Andric if (auto *d = dyn_cast<Defined>(a)) 1250b57cec5SDimitry Andric return d; 1260b57cec5SDimitry Andric return nullptr; 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 12985868e8aSDimitry Andric MemoryBufferRef LazyArchive::getMemberBuffer() { 1300b57cec5SDimitry Andric Archive::Child c = 1310b57cec5SDimitry Andric CHECK(sym.getMember(), 1320b57cec5SDimitry Andric "could not get the member for symbol " + toCOFFString(sym)); 1330b57cec5SDimitry Andric return CHECK(c.getMemoryBufferRef(), 1340b57cec5SDimitry Andric "could not get the buffer for the member defining symbol " + 1350b57cec5SDimitry Andric toCOFFString(sym)); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric } // namespace coff 1380b57cec5SDimitry Andric } // namespace lld 139