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