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
->wrappedSym
->file
->thunkLive
;
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 static Chunk
*makeImportThunk(COFFLinkerContext
&ctx
, DefinedImportData
*s
,
112 if (machine
== AMD64
)
113 return make
<ImportThunkChunkX64
>(ctx
, s
);
115 return make
<ImportThunkChunkX86
>(ctx
, s
);
116 if (machine
== ARM64
)
117 return make
<ImportThunkChunkARM64
>(ctx
, s
);
118 assert(machine
== ARMNT
);
119 return make
<ImportThunkChunkARM
>(ctx
, s
);
122 DefinedImportThunk::DefinedImportThunk(COFFLinkerContext
&ctx
, StringRef name
,
123 DefinedImportData
*s
, uint16_t machine
)
124 : Defined(DefinedImportThunkKind
, name
), wrappedSym(s
),
125 data(makeImportThunk(ctx
, s
, machine
)) {}
127 Defined
*Undefined::getWeakAlias() {
128 // A weak alias may be a weak alias to another symbol, so check recursively.
129 for (Symbol
*a
= weakAlias
; a
; a
= cast
<Undefined
>(a
)->weakAlias
)
130 if (auto *d
= dyn_cast
<Defined
>(a
))
135 MemoryBufferRef
LazyArchive::getMemberBuffer() {
137 CHECK(sym
.getMember(), "could not get the member for symbol " +
138 toCOFFString(file
->ctx
, sym
));
139 return CHECK(c
.getMemoryBufferRef(),
140 "could not get the buffer for the member defining symbol " +
141 toCOFFString(file
->ctx
, sym
));