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 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());
56 const COFFSyncStream
&
57 coff::operator<<(const COFFSyncStream
&s
,
58 const llvm::object::Archive::Symbol
*sym
) {
59 s
<< maybeDemangleSymbol(s
.ctx
, sym
->getName());
63 const COFFSyncStream
&coff::operator<<(const COFFSyncStream
&s
, Symbol
*sym
) {
64 return s
<< maybeDemangleSymbol(s
.ctx
, sym
->getName());
69 void Symbol::computeName() {
70 assert(nameData
== nullptr &&
71 "should only compute the name once for DefinedCOFF symbols");
72 auto *d
= cast
<DefinedCOFF
>(this);
74 check(cast
<ObjFile
>(d
->file
)->getCOFFObj()->getSymbolName(d
->sym
));
75 nameData
= nameStr
.data();
76 nameSize
= nameStr
.size();
77 assert(nameSize
== nameStr
.size() && "name length truncated");
80 InputFile
*Symbol::getFile() {
81 if (auto *sym
= dyn_cast
<DefinedCOFF
>(this))
83 if (auto *sym
= dyn_cast
<LazyArchive
>(this))
85 if (auto *sym
= dyn_cast
<LazyObject
>(this))
87 if (auto *sym
= dyn_cast
<LazyDLLSymbol
>(this))
92 bool Symbol::isLive() const {
93 if (auto *r
= dyn_cast
<DefinedRegular
>(this))
94 return r
->getChunk()->live
;
95 if (auto *imp
= dyn_cast
<DefinedImportData
>(this))
96 return imp
->file
->live
;
97 if (auto *imp
= dyn_cast
<DefinedImportThunk
>(this))
98 return imp
->getChunk()->live
;
99 // Assume any other kind of symbol is live.
104 void Symbol::replaceKeepingName(Symbol
*other
, size_t size
) {
105 StringRef origName
= getName();
106 memcpy(this, other
, size
);
107 nameData
= origName
.data();
108 nameSize
= origName
.size();
111 COFFSymbolRef
DefinedCOFF::getCOFFSymbol() {
112 size_t symSize
= cast
<ObjFile
>(file
)->getCOFFObj()->getSymbolTableEntrySize();
113 if (symSize
== sizeof(coff_symbol16
))
114 return COFFSymbolRef(reinterpret_cast<const coff_symbol16
*>(sym
));
115 assert(symSize
== sizeof(coff_symbol32
));
116 return COFFSymbolRef(reinterpret_cast<const coff_symbol32
*>(sym
));
119 uint64_t DefinedAbsolute::getRVA() { return va
- ctx
.config
.imageBase
; }
121 DefinedImportThunk::DefinedImportThunk(COFFLinkerContext
&ctx
, StringRef name
,
122 DefinedImportData
*s
,
123 ImportThunkChunk
*chunk
)
124 : Defined(DefinedImportThunkKind
, name
), wrappedSym(s
), data(chunk
) {}
126 Symbol
*Undefined::getWeakAlias() {
127 // A weak alias may be a weak alias to another symbol, so check recursively.
128 DenseSet
<Symbol
*> weakChain
;
129 for (Symbol
*a
= weakAlias
; a
; a
= cast
<Undefined
>(a
)->weakAlias
) {
130 // Anti-dependency symbols can't be chained.
133 if (!isa
<Undefined
>(a
))
135 if (!weakChain
.insert(a
).second
)
136 break; // We have a cycle.
141 bool Undefined::resolveWeakAlias() {
142 Defined
*d
= getDefinedWeakAlias();
146 // We want to replace Sym with D. However, we can't just blindly
147 // copy sizeof(SymbolUnion) bytes from D to Sym because D may be an
148 // internal symbol, and internal symbols are stored as "unparented"
149 // Symbols. For that reason we need to check which type of symbol we
150 // are dealing with and copy the correct number of bytes.
151 StringRef name
= getName();
152 bool wasAntiDep
= isAntiDep
;
153 if (isa
<DefinedRegular
>(d
))
154 memcpy(this, d
, sizeof(DefinedRegular
));
155 else if (isa
<DefinedAbsolute
>(d
))
156 memcpy(this, d
, sizeof(DefinedAbsolute
));
158 memcpy(this, d
, sizeof(SymbolUnion
));
160 nameData
= name
.data();
161 nameSize
= name
.size();
162 isAntiDep
= wasAntiDep
;
166 MemoryBufferRef
LazyArchive::getMemberBuffer() {
168 CHECK(sym
.getMember(), "could not get the member for symbol " +
169 toCOFFString(file
->symtab
.ctx
, sym
));
170 return CHECK(c
.getMemoryBufferRef(),
171 "could not get the buffer for the member defining symbol " +
172 toCOFFString(file
->symtab
.ctx
, sym
));