xref: /freebsd/contrib/llvm-project/lld/COFF/Symbols.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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