Symbols.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. //===- Symbols.cpp --------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "Symbols.h"
  9. #include "InputFiles.h"
  10. #include "lld/Common/ErrorHandler.h"
  11. #include "lld/Common/Memory.h"
  12. #include "lld/Common/Strings.h"
  13. #include "llvm/ADT/STLExtras.h"
  14. #include "llvm/Demangle/Demangle.h"
  15. #include "llvm/Support/Debug.h"
  16. #include "llvm/Support/raw_ostream.h"
  17. using namespace llvm;
  18. using namespace llvm::object;
  19. using namespace lld::coff;
  20. namespace lld {
  21. static_assert(sizeof(SymbolUnion) <= 48,
  22. "symbols should be optimized for memory usage");
  23. // Returns a symbol name for an error message.
  24. static std::string maybeDemangleSymbol(StringRef symName) {
  25. if (config->demangle) {
  26. std::string prefix;
  27. StringRef prefixless = symName;
  28. if (prefixless.consume_front("__imp_"))
  29. prefix = "__declspec(dllimport) ";
  30. StringRef demangleInput = prefixless;
  31. if (config->machine == I386)
  32. demangleInput.consume_front("_");
  33. std::string demangled = demangle(demangleInput);
  34. if (demangled != demangleInput)
  35. return prefix + demangle(demangleInput);
  36. return (prefix + prefixless).str();
  37. }
  38. return symName;
  39. }
  40. std::string toString(coff::Symbol &b) {
  41. return maybeDemangleSymbol(b.getName());
  42. }
  43. std::string toCOFFString(const Archive::Symbol &b) {
  44. return maybeDemangleSymbol(b.getName());
  45. }
  46. namespace coff {
  47. StringRef Symbol::getName() {
  48. // COFF symbol names are read lazily for a performance reason.
  49. // Non-external symbol names are never used by the linker except for logging
  50. // or debugging. Their internal references are resolved not by name but by
  51. // symbol index. And because they are not external, no one can refer them by
  52. // name. Object files contain lots of non-external symbols, and creating
  53. // StringRefs for them (which involves lots of strlen() on the string table)
  54. // is a waste of time.
  55. if (nameData == nullptr) {
  56. auto *d = cast<DefinedCOFF>(this);
  57. StringRef nameStr;
  58. cast<ObjFile>(d->file)->getCOFFObj()->getSymbolName(d->sym, nameStr);
  59. nameData = nameStr.data();
  60. nameSize = nameStr.size();
  61. assert(nameSize == nameStr.size() && "name length truncated");
  62. }
  63. return StringRef(nameData, nameSize);
  64. }
  65. InputFile *Symbol::getFile() {
  66. if (auto *sym = dyn_cast<DefinedCOFF>(this))
  67. return sym->file;
  68. if (auto *sym = dyn_cast<LazyArchive>(this))
  69. return sym->file;
  70. if (auto *sym = dyn_cast<LazyObject>(this))
  71. return sym->file;
  72. return nullptr;
  73. }
  74. bool Symbol::isLive() const {
  75. if (auto *r = dyn_cast<DefinedRegular>(this))
  76. return r->getChunk()->live;
  77. if (auto *imp = dyn_cast<DefinedImportData>(this))
  78. return imp->file->live;
  79. if (auto *imp = dyn_cast<DefinedImportThunk>(this))
  80. return imp->wrappedSym->file->thunkLive;
  81. // Assume any other kind of symbol is live.
  82. return true;
  83. }
  84. // MinGW specific.
  85. void Symbol::replaceKeepingName(Symbol *other, size_t size) {
  86. StringRef origName = getName();
  87. memcpy(this, other, size);
  88. nameData = origName.data();
  89. nameSize = origName.size();
  90. }
  91. COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
  92. size_t symSize = cast<ObjFile>(file)->getCOFFObj()->getSymbolTableEntrySize();
  93. if (symSize == sizeof(coff_symbol16))
  94. return COFFSymbolRef(reinterpret_cast<const coff_symbol16 *>(sym));
  95. assert(symSize == sizeof(coff_symbol32));
  96. return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(sym));
  97. }
  98. uint16_t DefinedAbsolute::numOutputSections;
  99. static Chunk *makeImportThunk(DefinedImportData *s, uint16_t machine) {
  100. if (machine == AMD64)
  101. return make<ImportThunkChunkX64>(s);
  102. if (machine == I386)
  103. return make<ImportThunkChunkX86>(s);
  104. if (machine == ARM64)
  105. return make<ImportThunkChunkARM64>(s);
  106. assert(machine == ARMNT);
  107. return make<ImportThunkChunkARM>(s);
  108. }
  109. DefinedImportThunk::DefinedImportThunk(StringRef name, DefinedImportData *s,
  110. uint16_t machine)
  111. : Defined(DefinedImportThunkKind, name), wrappedSym(s),
  112. data(makeImportThunk(s, machine)) {}
  113. Defined *Undefined::getWeakAlias() {
  114. // A weak alias may be a weak alias to another symbol, so check recursively.
  115. for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias)
  116. if (auto *d = dyn_cast<Defined>(a))
  117. return d;
  118. return nullptr;
  119. }
  120. MemoryBufferRef LazyArchive::getMemberBuffer() {
  121. Archive::Child c =
  122. CHECK(sym.getMember(),
  123. "could not get the member for symbol " + toCOFFString(sym));
  124. return CHECK(c.getMemoryBufferRef(),
  125. "could not get the buffer for the member defining symbol " +
  126. toCOFFString(sym));
  127. }
  128. } // namespace coff
  129. } // namespace lld