blob: 002c6945c47b3ebdc996e7c1628123b07dbfd5f4 [file] [log] [blame]
Rui Ueyama411c63602015-05-28 19:09:301//===- Symbols.cpp --------------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:563// 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
Rui Ueyama411c63602015-05-28 19:09:306//
7//===----------------------------------------------------------------------===//
8
Rui Ueyamaa45d45e2016-12-07 23:17:029#include "Symbols.h"
Amy Huang5a58b192023-01-10 04:37:2810#include "COFFLinkerContext.h"
Rui Ueyama411c63602015-05-28 19:09:3011#include "InputFiles.h"
Bob Haarmanb8a59c82017-10-25 22:28:3812#include "lld/Common/ErrorHandler.h"
Rui Ueyama2017d522017-11-28 20:39:1713#include "lld/Common/Memory.h"
Rui Ueyamaee173712018-02-28 17:38:1914#include "lld/Common/Strings.h"
Rui Ueyama411c63602015-05-28 19:09:3015#include "llvm/ADT/STLExtras.h"
Martin Storsjobf6f4e92019-09-27 12:23:4516#include "llvm/Demangle/Demangle.h"
Rui Ueyama411c63602015-05-28 19:09:3017#include "llvm/Support/Debug.h"
18#include "llvm/Support/raw_ostream.h"
19
Rui Ueyamaa45d45e2016-12-07 23:17:0220using namespace llvm;
Rui Ueyama411c63602015-05-28 19:09:3021using namespace llvm::object;
Rui Ueyama411c63602015-05-28 19:09:3022
Nico Weber020d92c2019-03-11 23:02:1823using namespace lld::coff;
24
Nico Webercb2c5002019-07-19 13:29:1025namespace lld {
26
Reid Klecknera30920c2019-04-19 22:51:4927static_assert(sizeof(SymbolUnion) <= 48,
28 "symbols should be optimized for memory usage");
29
Rui Ueyama7a8ff132017-01-06 10:15:4730// Returns a symbol name for an error message.
Nico Weberd73ef972024-12-14 00:35:5131std::string maybeDemangleSymbol(const COFFLinkerContext &ctx,
32 StringRef symName) {
Amy Huang5a58b192023-01-10 04:37:2833 if (ctx.config.demangle) {
Martin Storsjobf6f4e92019-09-27 12:23:4534 std::string prefix;
Martin Storsjo9809ed62019-10-04 19:47:5935 StringRef prefixless = symName;
36 if (prefixless.consume_front("__imp_"))
Martin Storsjobf6f4e92019-09-27 12:23:4537 prefix = "__declspec(dllimport) ";
Martin Storsjo9809ed62019-10-04 19:47:5938 StringRef demangleInput = prefixless;
Amy Huang5a58b192023-01-10 04:37:2839 if (ctx.config.machine == I386)
Martin Storsjobf6f4e92019-09-27 12:23:4540 demangleInput.consume_front("_");
Nick Desaulniers8abbc172023-06-05 21:59:4641 std::string demangled = demangle(demangleInput);
Martin Storsjobf6f4e92019-09-27 12:23:4542 if (demangled != demangleInput)
Nick Desaulniers8abbc172023-06-05 21:59:4643 return prefix + demangled;
Martin Storsjo9809ed62019-10-04 19:47:5944 return (prefix + prefixless).str();
Martin Storsjoa66fc1c92019-09-02 13:25:4645 }
Benjamin Krameradcd0262020-01-28 19:23:4646 return std::string(symName);
Rui Ueyama7a8ff132017-01-06 10:15:4747}
Amy Huang5a58b192023-01-10 04:37:2848std::string toString(const COFFLinkerContext &ctx, coff::Symbol &b) {
49 return maybeDemangleSymbol(ctx, b.getName());
Martin Storsjobf6f4e92019-09-27 12:23:4550}
Amy Huang5a58b192023-01-10 04:37:2851std::string toCOFFString(const COFFLinkerContext &ctx,
52 const Archive::Symbol &b) {
53 return maybeDemangleSymbol(ctx, b.getName());
Nico Weber9c0716f2019-07-23 19:00:0154}
Rui Ueyama7a8ff132017-01-06 10:15:4755
Fangrui Song982575fd2024-12-04 04:51:5056const COFFSyncStream &
57coff::operator<<(const COFFSyncStream &s,
58 const llvm::object::Archive::Symbol *sym) {
59 s << maybeDemangleSymbol(s.ctx, sym->getName());
60 return s;
61}
62
Rui Ueyama411c63602015-05-28 19:09:3063namespace coff {
64
Reid Kleckner9b7f6142020-05-03 02:53:4965void Symbol::computeName() {
66 assert(nameData == nullptr &&
67 "should only compute the name once for DefinedCOFF symbols");
68 auto *d = cast<DefinedCOFF>(this);
Reid Kleckner77ecf902020-05-08 17:41:0569 StringRef nameStr =
70 check(cast<ObjFile>(d->file)->getCOFFObj()->getSymbolName(d->sym));
Reid Kleckner9b7f6142020-05-03 02:53:4971 nameData = nameStr.data();
72 nameSize = nameStr.size();
73 assert(nameSize == nameStr.size() && "name length truncated");
Rui Ueyama57fe78d2015-06-08 19:43:5974}
75
Rui Ueyamaf52496e2017-11-03 21:21:4776InputFile *Symbol::getFile() {
Rui Ueyama136d27a2019-07-11 05:40:3077 if (auto *sym = dyn_cast<DefinedCOFF>(this))
78 return sym->file;
Bob Haarman7dc5e7a02019-09-03 20:32:1679 if (auto *sym = dyn_cast<LazyArchive>(this))
80 return sym->file;
81 if (auto *sym = dyn_cast<LazyObject>(this))
Rui Ueyama136d27a2019-07-11 05:40:3082 return sym->file;
Martin Storsjöa9ff1ce2021-06-16 13:59:4683 if (auto *sym = dyn_cast<LazyDLLSymbol>(this))
84 return sym->file;
Rui Ueyamaa45d45e2016-12-07 23:17:0285 return nullptr;
86}
87
Rui Ueyamaf52496e2017-11-03 21:21:4788bool Symbol::isLive() const {
Rui Ueyama136d27a2019-07-11 05:40:3089 if (auto *r = dyn_cast<DefinedRegular>(this))
90 return r->getChunk()->live;
91 if (auto *imp = dyn_cast<DefinedImportData>(this))
92 return imp->file->live;
93 if (auto *imp = dyn_cast<DefinedImportThunk>(this))
Jacek Caban6be9be52024-09-13 13:42:0594 return imp->getChunk()->live;
Reid Klecknereacdf042017-07-27 18:25:5995 // Assume any other kind of symbol is live.
96 return true;
97}
98
Rui Ueyama136d27a2019-07-11 05:40:3099void Symbol::replaceKeepingName(Symbol *other, size_t size) {
100 StringRef origName = getName();
101 memcpy(this, other, size);
102 nameData = origName.data();
103 nameSize = origName.size();
Martin Storsjoeac1b052018-08-27 08:43:31104}
105
David Majnemer3a62d3d2015-07-09 17:43:50106COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
Rui Ueyama136d27a2019-07-11 05:40:30107 size_t symSize = cast<ObjFile>(file)->getCOFFObj()->getSymbolTableEntrySize();
108 if (symSize == sizeof(coff_symbol16))
109 return COFFSymbolRef(reinterpret_cast<const coff_symbol16 *>(sym));
110 assert(symSize == sizeof(coff_symbol32));
111 return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(sym));
David Majnemer3a62d3d2015-07-09 17:43:50112}
113
Amy Huang5a58b192023-01-10 04:37:28114uint64_t DefinedAbsolute::getRVA() { return va - ctx.config.imageBase; }
Reid Kleckner84564112017-06-22 23:33:04115
Amy Huang5a58b192023-01-10 04:37:28116DefinedImportThunk::DefinedImportThunk(COFFLinkerContext &ctx, StringRef name,
Jacek Caban7e0008d2024-09-11 10:22:36117 DefinedImportData *s,
118 ImportThunkChunk *chunk)
119 : Defined(DefinedImportThunkKind, name), wrappedSym(s), data(chunk) {}
Rui Ueyama28df0422015-07-25 01:16:06120
Jacek Cabanba898db2024-10-15 20:58:13121Symbol *Undefined::getWeakAlias() {
Peter Collingbourne2612a322015-07-04 05:28:41122 // A weak alias may be a weak alias to another symbol, so check recursively.
Jacek Caban513e0af2024-08-20 08:21:00123 DenseSet<Symbol *> weakChain;
124 for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias) {
Jacek Cabanf1ba8942024-10-21 09:44:31125 // Anti-dependency symbols can't be chained.
126 if (a->isAntiDep)
127 break;
Jacek Cabanba898db2024-10-15 20:58:13128 if (!isa<Undefined>(a))
129 return a;
Jacek Caban513e0af2024-08-20 08:21:00130 if (!weakChain.insert(a).second)
131 break; // We have a cycle.
132 }
Peter Collingbourne2612a322015-07-04 05:28:41133 return nullptr;
134}
Amy Huanga1c022c2019-08-22 19:40:07135
Jacek Cabanec4d5a62024-08-26 17:20:18136bool Undefined::resolveWeakAlias() {
Jacek Cabanba898db2024-10-15 20:58:13137 Defined *d = getDefinedWeakAlias();
Jacek Cabanec4d5a62024-08-26 17:20:18138 if (!d)
139 return false;
140
141 // We want to replace Sym with D. However, we can't just blindly
142 // copy sizeof(SymbolUnion) bytes from D to Sym because D may be an
143 // internal symbol, and internal symbols are stored as "unparented"
144 // Symbols. For that reason we need to check which type of symbol we
145 // are dealing with and copy the correct number of bytes.
146 StringRef name = getName();
Jacek Cabanf1ba8942024-10-21 09:44:31147 bool wasAntiDep = isAntiDep;
Jacek Cabanec4d5a62024-08-26 17:20:18148 if (isa<DefinedRegular>(d))
149 memcpy(this, d, sizeof(DefinedRegular));
150 else if (isa<DefinedAbsolute>(d))
151 memcpy(this, d, sizeof(DefinedAbsolute));
152 else
153 memcpy(this, d, sizeof(SymbolUnion));
154
155 nameData = name.data();
156 nameSize = name.size();
Jacek Cabanf1ba8942024-10-21 09:44:31157 isAntiDep = wasAntiDep;
Jacek Cabanec4d5a62024-08-26 17:20:18158 return true;
159}
160
Bob Haarman7dc5e7a02019-09-03 20:32:16161MemoryBufferRef LazyArchive::getMemberBuffer() {
Amy Huanga1c022c2019-08-22 19:40:07162 Archive::Child c =
Amy Huang5a58b192023-01-10 04:37:28163 CHECK(sym.getMember(), "could not get the member for symbol " +
Jacek Caban6b493ba2024-12-15 11:45:34164 toCOFFString(file->symtab.ctx, sym));
Amy Huanga1c022c2019-08-22 19:40:07165 return CHECK(c.getMemoryBufferRef(),
Amy Huang5a58b192023-01-10 04:37:28166 "could not get the buffer for the member defining symbol " +
Jacek Caban6b493ba2024-12-15 11:45:34167 toCOFFString(file->symtab.ctx, sym));
Amy Huanga1c022c2019-08-22 19:40:07168}
Rui Ueyamace039262017-01-06 10:04:08169} // namespace coff
Rui Ueyama411c63602015-05-28 19:09:30170} // namespace lld