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 "COFFLinkerContext.h"
11 #include "InputFiles.h"
12 #include "lld/Common/ErrorHandler.h"
13 #include "lld/Common/Memory.h"
14 #include "lld/Common/Strings.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/Demangle/Demangle.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/raw_ostream.h"
21 using namespace llvm::object
;
23 using namespace lld::coff
;
27 static_assert(sizeof(SymbolUnion
) <= 48,
28 "symbols should be optimized for memory usage");
30 // Returns a symbol name for an error message.
31 static std::string
maybeDemangleSymbol(const COFFLinkerContext
&ctx
,
33 if (ctx
.config
.demangle
) {
35 StringRef prefixless
= symName
;
36 if (prefixless
.consume_front("__imp_"))
37 prefix
= "__declspec(dllimport) ";
38 StringRef demangleInput
= prefixless
;
39 if (ctx
.config
.machine
== I386
)
40 demangleInput
.consume_front("_");
41 std::string demangled
= demangle(demangleInput
);
42 if (demangled
!= demangleInput
)
43 return prefix
+ demangled
;
44 return (prefix
+ prefixless
).str();
46 return std::string(symName
);
48 std::string
toString(const COFFLinkerContext
&ctx
, coff::Symbol
&b
) {
49 return maybeDemangleSymbol(ctx
, b
.getName());
51 std::string
toCOFFString(const COFFLinkerContext
&ctx
,
52 const Archive::Symbol
&b
) {
53 return maybeDemangleSymbol(ctx
, b
.getName());
58 void Symbol::computeName() {
59 assert(nameData
== nullptr &&
60 "should only compute the name once for DefinedCOFF symbols");
61 auto *d
= cast
<DefinedCOFF
>(this);
63 check(cast
<ObjFile
>(d
->file
)->getCOFFObj()->getSymbolName(d
->sym
));
64 nameData
= nameStr
.data();
65 nameSize
= nameStr
.size();
66 assert(nameSize
== nameStr
.size() && "name length truncated");
69 InputFile
*Symbol::getFile() {
70 if (auto *sym
= dyn_cast
<DefinedCOFF
>(this))
72 if (auto *sym
= dyn_cast
<LazyArchive
>(this))
74 if (auto *sym
= dyn_cast
<LazyObject
>(this))
76 if (auto *sym
= dyn_cast
<LazyDLLSymbol
>(this))
81 bool Symbol::isLive() const {
82 if (auto *r
= dyn_cast
<DefinedRegular
>(this))
83 return r
->getChunk()->live
;
84 if (auto *imp
= dyn_cast
<DefinedImportData
>(this))
85 return imp
->file
->live
;
86 if (auto *imp
= dyn_cast
<DefinedImportThunk
>(this))
87 return imp
->getChunk()->live
;
88 // Assume any other kind of symbol is live.
93 void Symbol::replaceKeepingName(Symbol
*other
, size_t size
) {
94 StringRef origName
= getName();
95 memcpy(this, other
, size
);
96 nameData
= origName
.data();
97 nameSize
= origName
.size();
100 COFFSymbolRef
DefinedCOFF::getCOFFSymbol() {
101 size_t symSize
= cast
<ObjFile
>(file
)->getCOFFObj()->getSymbolTableEntrySize();
102 if (symSize
== sizeof(coff_symbol16
))
103 return COFFSymbolRef(reinterpret_cast<const coff_symbol16
*>(sym
));
104 assert(symSize
== sizeof(coff_symbol32
));
105 return COFFSymbolRef(reinterpret_cast<const coff_symbol32
*>(sym
));
108 uint64_t DefinedAbsolute::getRVA() { return va
- ctx
.config
.imageBase
; }
110 DefinedImportThunk::DefinedImportThunk(COFFLinkerContext
&ctx
, StringRef name
,
111 DefinedImportData
*s
,
112 ImportThunkChunk
*chunk
)
113 : Defined(DefinedImportThunkKind
, name
), wrappedSym(s
), data(chunk
) {}
115 Symbol
*Undefined::getWeakAlias() {
116 // A weak alias may be a weak alias to another symbol, so check recursively.
117 DenseSet
<Symbol
*> weakChain
;
118 for (Symbol
*a
= weakAlias
; a
; a
= cast
<Undefined
>(a
)->weakAlias
) {
119 // Anti-dependency symbols can't be chained.
122 if (!isa
<Undefined
>(a
))
124 if (!weakChain
.insert(a
).second
)
125 break; // We have a cycle.
130 bool Undefined::resolveWeakAlias() {
131 Defined
*d
= getDefinedWeakAlias();
135 // We want to replace Sym with D. However, we can't just blindly
136 // copy sizeof(SymbolUnion) bytes from D to Sym because D may be an
137 // internal symbol, and internal symbols are stored as "unparented"
138 // Symbols. For that reason we need to check which type of symbol we
139 // are dealing with and copy the correct number of bytes.
140 StringRef name
= getName();
141 bool wasAntiDep
= isAntiDep
;
142 if (isa
<DefinedRegular
>(d
))
143 memcpy(this, d
, sizeof(DefinedRegular
));
144 else if (isa
<DefinedAbsolute
>(d
))
145 memcpy(this, d
, sizeof(DefinedAbsolute
));
147 memcpy(this, d
, sizeof(SymbolUnion
));
149 nameData
= name
.data();
150 nameSize
= name
.size();
151 isAntiDep
= wasAntiDep
;
155 MemoryBufferRef
LazyArchive::getMemberBuffer() {
157 CHECK(sym
.getMember(), "could not get the member for symbol " +
158 toCOFFString(file
->ctx
, sym
));
159 return CHECK(c
.getMemoryBufferRef(),
160 "could not get the buffer for the member defining symbol " +
161 toCOFFString(file
->ctx
, sym
));