154359Sroberto//===- Symbols.cpp --------------------------------------------------------===// 254359Sroberto// 354359Sroberto// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 454359Sroberto// See https://llvm.org/LICENSE.txt for license information. 554359Sroberto// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 682498Sroberto// 754359Sroberto//===----------------------------------------------------------------------===// 854359Sroberto 954359Sroberto#include "Symbols.h" 1054359Sroberto#include "COFFLinkerContext.h" 1154359Sroberto#include "InputFiles.h" 1254359Sroberto#include "lld/Common/ErrorHandler.h" 1354359Sroberto#include "lld/Common/Memory.h" 1454359Sroberto#include "lld/Common/Strings.h" 1554359Sroberto#include "llvm/ADT/STLExtras.h" 1654359Sroberto#include "llvm/Demangle/Demangle.h" 1754359Sroberto#include "llvm/Support/Debug.h" 1854359Sroberto#include "llvm/Support/raw_ostream.h" 1954359Sroberto 2054359Srobertousing namespace llvm; 2154359Srobertousing namespace llvm::object; 2254359Sroberto 2354359Srobertousing namespace lld::coff; 2454359Sroberto 2554359Srobertonamespace lld { 2654359Sroberto 2754359Srobertostatic_assert(sizeof(SymbolUnion) <= 48, 2854359Sroberto "symbols should be optimized for memory usage"); 2954359Sroberto 3054359Sroberto// Returns a symbol name for an error message. 3154359Srobertostatic std::string maybeDemangleSymbol(const COFFLinkerContext &ctx, 3254359Sroberto StringRef symName) { 3354359Sroberto if (ctx.config.demangle) { 3454359Sroberto std::string prefix; 3554359Sroberto StringRef prefixless = symName; 3654359Sroberto if (prefixless.consume_front("__imp_")) 3754359Sroberto prefix = "__declspec(dllimport) "; 3854359Sroberto StringRef demangleInput = prefixless; 3954359Sroberto if (ctx.config.machine == I386) 4054359Sroberto demangleInput.consume_front("_"); 4154359Sroberto std::string demangled = demangle(demangleInput); 4254359Sroberto if (demangled != demangleInput) 4354359Sroberto return prefix + demangled; 4454359Sroberto return (prefix + prefixless).str(); 4554359Sroberto } 4654359Sroberto return std::string(symName); 4754359Sroberto} 4854359Srobertostd::string toString(const COFFLinkerContext &ctx, coff::Symbol &b) { 4954359Sroberto return maybeDemangleSymbol(ctx, b.getName()); 5054359Sroberto} 5154359Srobertostd::string toCOFFString(const COFFLinkerContext &ctx, 5254359Sroberto const Archive::Symbol &b) { 5354359Sroberto return maybeDemangleSymbol(ctx, b.getName()); 5454359Sroberto} 5554359Sroberto 5654359Srobertonamespace coff { 5754359Sroberto 5854359Srobertovoid Symbol::computeName() { 5954359Sroberto assert(nameData == nullptr && 6054359Sroberto "should only compute the name once for DefinedCOFF symbols"); 6154359Sroberto auto *d = cast<DefinedCOFF>(this); 6254359Sroberto StringRef nameStr = 6354359Sroberto check(cast<ObjFile>(d->file)->getCOFFObj()->getSymbolName(d->sym)); 6454359Sroberto nameData = nameStr.data(); 6554359Sroberto nameSize = nameStr.size(); 6654359Sroberto assert(nameSize == nameStr.size() && "name length truncated"); 6754359Sroberto} 6854359Sroberto 6954359SrobertoInputFile *Symbol::getFile() { 7054359Sroberto if (auto *sym = dyn_cast<DefinedCOFF>(this)) 7154359Sroberto return sym->file; 7254359Sroberto if (auto *sym = dyn_cast<LazyArchive>(this)) 7354359Sroberto return sym->file; 7454359Sroberto if (auto *sym = dyn_cast<LazyObject>(this)) 7554359Sroberto return sym->file; 7654359Sroberto if (auto *sym = dyn_cast<LazyDLLSymbol>(this)) 7754359Sroberto return sym->file; 7854359Sroberto return nullptr; 7954359Sroberto} 8054359Sroberto 8154359Srobertobool Symbol::isLive() const { 8254359Sroberto if (auto *r = dyn_cast<DefinedRegular>(this)) 8354359Sroberto return r->getChunk()->live; 8454359Sroberto if (auto *imp = dyn_cast<DefinedImportData>(this)) 8554359Sroberto return imp->file->live; 8654359Sroberto if (auto *imp = dyn_cast<DefinedImportThunk>(this)) 8754359Sroberto return imp->wrappedSym->file->thunkLive; 8854359Sroberto // Assume any other kind of symbol is live. 8954359Sroberto return true; 9054359Sroberto} 9154359Sroberto 9254359Sroberto// MinGW specific. 9354359Srobertovoid Symbol::replaceKeepingName(Symbol *other, size_t size) { 9454359Sroberto StringRef origName = getName(); 9554359Sroberto memcpy(this, other, size); 9654359Sroberto nameData = origName.data(); 9754359Sroberto nameSize = origName.size(); 9854359Sroberto} 9954359Sroberto 10054359SrobertoCOFFSymbolRef DefinedCOFF::getCOFFSymbol() { 10154359Sroberto size_t symSize = cast<ObjFile>(file)->getCOFFObj()->getSymbolTableEntrySize(); 10254359Sroberto if (symSize == sizeof(coff_symbol16)) 10354359Sroberto return COFFSymbolRef(reinterpret_cast<const coff_symbol16 *>(sym)); 10454359Sroberto assert(symSize == sizeof(coff_symbol32)); 10554359Sroberto return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(sym)); 10654359Sroberto} 10754359Sroberto 10854359Srobertouint64_t DefinedAbsolute::getRVA() { return va - ctx.config.imageBase; } 10954359Sroberto 11054359Srobertostatic Chunk *makeImportThunk(COFFLinkerContext &ctx, DefinedImportData *s, 11154359Sroberto uint16_t machine) { 11254359Sroberto if (machine == AMD64) 11354359Sroberto return make<ImportThunkChunkX64>(ctx, s); 11454359Sroberto if (machine == I386) 11554359Sroberto return make<ImportThunkChunkX86>(ctx, s); 11654359Sroberto if (machine == ARM64) 11754359Sroberto return make<ImportThunkChunkARM64>(ctx, s); 11854359Sroberto assert(machine == ARMNT); 11954359Sroberto return make<ImportThunkChunkARM>(ctx, s); 12054359Sroberto} 12154359Sroberto 12254359SrobertoDefinedImportThunk::DefinedImportThunk(COFFLinkerContext &ctx, StringRef name, 12354359Sroberto DefinedImportData *s, uint16_t machine) 12454359Sroberto : Defined(DefinedImportThunkKind, name), wrappedSym(s), 12554359Sroberto data(makeImportThunk(ctx, s, machine)) {} 12654359Sroberto 12754359SrobertoDefined *Undefined::getWeakAlias() { 12854359Sroberto // A weak alias may be a weak alias to another symbol, so check recursively. 12954359Sroberto for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias) 13054359Sroberto if (auto *d = dyn_cast<Defined>(a)) 13154359Sroberto return d; 13254359Sroberto return nullptr; 13354359Sroberto} 13454359Sroberto 13554359SrobertoMemoryBufferRef LazyArchive::getMemberBuffer() { 13654359Sroberto Archive::Child c = 13754359Sroberto CHECK(sym.getMember(), "could not get the member for symbol " + 13854359Sroberto toCOFFString(file->ctx, sym)); 13954359Sroberto return CHECK(c.getMemoryBufferRef(), 14054359Sroberto "could not get the buffer for the member defining symbol " + 14154359Sroberto toCOFFString(file->ctx, sym)); 14254359Sroberto} 14354359Sroberto} // namespace coff 14454359Sroberto} // namespace lld 14554359Sroberto