1 //===- Symbols.cpp --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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/Demangle/Demangle.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/raw_ostream.h"
20 using namespace llvm::object
;
22 using namespace lld::coff
;
26 static_assert(sizeof(SymbolUnion
) <= 48,
27 "symbols should be optimized for memory usage");
29 // Returns a symbol name for an error message.
30 static std::string
maybeDemangleSymbol(StringRef symName
) {
31 if (config
->demangle
) {
33 StringRef prefixless
= symName
;
34 if (prefixless
.consume_front("__imp_"))
35 prefix
= "__declspec(dllimport) ";
36 StringRef demangleInput
= prefixless
;
37 if (config
->machine
== I386
)
38 demangleInput
.consume_front("_");
39 std::string demangled
= demangle(std::string(demangleInput
));
40 if (demangled
!= demangleInput
)
41 return prefix
+ demangle(std::string(demangleInput
));
42 return (prefix
+ prefixless
).str();
44 return std::string(symName
);
46 std::string
toString(coff::Symbol
&b
) {
47 return maybeDemangleSymbol(b
.getName());
49 std::string
toCOFFString(const Archive::Symbol
&b
) {
50 return maybeDemangleSymbol(b
.getName());
55 void Symbol::computeName() {
56 assert(nameData
== nullptr &&
57 "should only compute the name once for DefinedCOFF symbols");
58 auto *d
= cast
<DefinedCOFF
>(this);
60 check(cast
<ObjFile
>(d
->file
)->getCOFFObj()->getSymbolName(d
->sym
));
61 nameData
= nameStr
.data();
62 nameSize
= nameStr
.size();
63 assert(nameSize
== nameStr
.size() && "name length truncated");
66 InputFile
*Symbol::getFile() {
67 if (auto *sym
= dyn_cast
<DefinedCOFF
>(this))
69 if (auto *sym
= dyn_cast
<LazyArchive
>(this))
71 if (auto *sym
= dyn_cast
<LazyObject
>(this))
73 if (auto *sym
= dyn_cast
<LazyDLLSymbol
>(this))
78 bool Symbol::isLive() const {
79 if (auto *r
= dyn_cast
<DefinedRegular
>(this))
80 return r
->getChunk()->live
;
81 if (auto *imp
= dyn_cast
<DefinedImportData
>(this))
82 return imp
->file
->live
;
83 if (auto *imp
= dyn_cast
<DefinedImportThunk
>(this))
84 return imp
->wrappedSym
->file
->thunkLive
;
85 // Assume any other kind of symbol is live.
90 void Symbol::replaceKeepingName(Symbol
*other
, size_t size
) {
91 StringRef origName
= getName();
92 memcpy(this, other
, size
);
93 nameData
= origName
.data();
94 nameSize
= origName
.size();
97 COFFSymbolRef
DefinedCOFF::getCOFFSymbol() {
98 size_t symSize
= cast
<ObjFile
>(file
)->getCOFFObj()->getSymbolTableEntrySize();
99 if (symSize
== sizeof(coff_symbol16
))
100 return COFFSymbolRef(reinterpret_cast<const coff_symbol16
*>(sym
));
101 assert(symSize
== sizeof(coff_symbol32
));
102 return COFFSymbolRef(reinterpret_cast<const coff_symbol32
*>(sym
));
105 uint16_t DefinedAbsolute::numOutputSections
;
107 static Chunk
*makeImportThunk(DefinedImportData
*s
, uint16_t machine
) {
108 if (machine
== AMD64
)
109 return make
<ImportThunkChunkX64
>(s
);
111 return make
<ImportThunkChunkX86
>(s
);
112 if (machine
== ARM64
)
113 return make
<ImportThunkChunkARM64
>(s
);
114 assert(machine
== ARMNT
);
115 return make
<ImportThunkChunkARM
>(s
);
118 DefinedImportThunk::DefinedImportThunk(StringRef name
, DefinedImportData
*s
,
120 : Defined(DefinedImportThunkKind
, name
), wrappedSym(s
),
121 data(makeImportThunk(s
, machine
)) {}
123 Defined
*Undefined::getWeakAlias() {
124 // A weak alias may be a weak alias to another symbol, so check recursively.
125 for (Symbol
*a
= weakAlias
; a
; a
= cast
<Undefined
>(a
)->weakAlias
)
126 if (auto *d
= dyn_cast
<Defined
>(a
))
131 MemoryBufferRef
LazyArchive::getMemberBuffer() {
133 CHECK(sym
.getMember(),
134 "could not get the member for symbol " + toCOFFString(sym
));
135 return CHECK(c
.getMemoryBufferRef(),
136 "could not get the buffer for the member defining symbol " +