blob: 002c6945c47b3ebdc996e7c1628123b07dbfd5f4 [file] [log] [blame]
Rui Ueyama411c63602015-05-28 19:09:30 +00001//===- Symbols.cpp --------------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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:30 +00006//
7//===----------------------------------------------------------------------===//
8
Rui Ueyamaa45d45e2016-12-07 23:17:02 +00009#include "Symbols.h"
Amy Huang5a58b192023-01-09 23:37:28 -050010#include "COFFLinkerContext.h"
Rui Ueyama411c63602015-05-28 19:09:30 +000011#include "InputFiles.h"
Bob Haarmanb8a59c82017-10-25 22:28:38 +000012#include "lld/Common/ErrorHandler.h"
Rui Ueyama2017d522017-11-28 20:39:17 +000013#include "lld/Common/Memory.h"
Rui Ueyamaee173712018-02-28 17:38:19 +000014#include "lld/Common/Strings.h"
Rui Ueyama411c63602015-05-28 19:09:30 +000015#include "llvm/ADT/STLExtras.h"
Martin Storsjobf6f4e92019-09-27 12:23:45 +000016#include "llvm/Demangle/Demangle.h"
Rui Ueyama411c63602015-05-28 19:09:30 +000017#include "llvm/Support/Debug.h"
18#include "llvm/Support/raw_ostream.h"
19
Rui Ueyamaa45d45e2016-12-07 23:17:02 +000020using namespace llvm;
Rui Ueyama411c63602015-05-28 19:09:30 +000021using namespace llvm::object;
Rui Ueyama411c63602015-05-28 19:09:30 +000022
Nico Weber020d92c2019-03-11 23:02:18 +000023using namespace lld::coff;
24
Nico Webercb2c5002019-07-19 13:29:10 +000025namespace lld {
26
Reid Klecknera30920c2019-04-19 22:51:49 +000027static_assert(sizeof(SymbolUnion) <= 48,
28 "symbols should be optimized for memory usage");
29
Rui Ueyama7a8ff132017-01-06 10:15:47 +000030// Returns a symbol name for an error message.
Nico Weberd73ef972024-12-13 19:35:51 -050031std::string maybeDemangleSymbol(const COFFLinkerContext &ctx,
32 StringRef symName) {
Amy Huang5a58b192023-01-09 23:37:28 -050033 if (ctx.config.demangle) {
Martin Storsjobf6f4e92019-09-27 12:23:45 +000034 std::string prefix;
Martin Storsjo9809ed62019-10-04 19:47:59 +000035 StringRef prefixless = symName;
36 if (prefixless.consume_front("__imp_"))
Martin Storsjobf6f4e92019-09-27 12:23:45 +000037 prefix = "__declspec(dllimport) ";
Martin Storsjo9809ed62019-10-04 19:47:59 +000038 StringRef demangleInput = prefixless;
Amy Huang5a58b192023-01-09 23:37:28 -050039 if (ctx.config.machine == I386)
Martin Storsjobf6f4e92019-09-27 12:23:45 +000040 demangleInput.consume_front("_");
Nick Desaulniers8abbc172023-06-05 14:59:46 -070041 std::string demangled = demangle(demangleInput);
Martin Storsjobf6f4e92019-09-27 12:23:45 +000042 if (demangled != demangleInput)
Nick Desaulniers8abbc172023-06-05 14:59:46 -070043 return prefix + demangled;
Martin Storsjo9809ed62019-10-04 19:47:59 +000044 return (prefix + prefixless).str();
Martin Storsjoa66fc1c92019-09-02 13:25:46 +000045 }
Benjamin Krameradcd0262020-01-28 20:23:46 +010046 return std::string(symName);
Rui Ueyama7a8ff132017-01-06 10:15:47 +000047}
Amy Huang5a58b192023-01-09 23:37:28 -050048std::string toString(const COFFLinkerContext &ctx, coff::Symbol &b) {
49 return maybeDemangleSymbol(ctx, b.getName());
Martin Storsjobf6f4e92019-09-27 12:23:45 +000050}
Amy Huang5a58b192023-01-09 23:37:28 -050051std::string toCOFFString(const COFFLinkerContext &ctx,
52 const Archive::Symbol &b) {
53 return maybeDemangleSymbol(ctx, b.getName());
Nico Weber9c0716f2019-07-23 19:00:01 +000054}
Rui Ueyama7a8ff132017-01-06 10:15:47 +000055
Fangrui Song982575fd2024-12-03 20:51:50 -080056const 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:30 +000063namespace coff {
64
Reid Kleckner9b7f6142020-05-02 19:53:49 -070065void 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 10:41:05 -070069 StringRef nameStr =
70 check(cast<ObjFile>(d->file)->getCOFFObj()->getSymbolName(d->sym));
Reid Kleckner9b7f6142020-05-02 19:53:49 -070071 nameData = nameStr.data();
72 nameSize = nameStr.size();
73 assert(nameSize == nameStr.size() && "name length truncated");
Rui Ueyama57fe78d2015-06-08 19:43:59 +000074}
75
Rui Ueyamaf52496e2017-11-03 21:21:47 +000076InputFile *Symbol::getFile() {
Rui Ueyama136d27a2019-07-11 05:40:30 +000077 if (auto *sym = dyn_cast<DefinedCOFF>(this))
78 return sym->file;
Bob Haarman7dc5e7a02019-09-03 20:32:16 +000079 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:30 +000082 return sym->file;
Martin Storsjöa9ff1ce2021-06-16 16:59:46 +030083 if (auto *sym = dyn_cast<LazyDLLSymbol>(this))
84 return sym->file;
Rui Ueyamaa45d45e2016-12-07 23:17:02 +000085 return nullptr;
86}
87
Rui Ueyamaf52496e2017-11-03 21:21:47 +000088bool Symbol::isLive() const {
Rui Ueyama136d27a2019-07-11 05:40:30 +000089 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 15:42:05 +020094 return imp->getChunk()->live;
Reid Klecknereacdf042017-07-27 18:25:59 +000095 // Assume any other kind of symbol is live.
96 return true;
97}
98
Rui Ueyama136d27a2019-07-11 05:40:30 +000099void 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:31 +0000104}
105
David Majnemer3a62d3d2015-07-09 17:43:50 +0000106COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
Rui Ueyama136d27a2019-07-11 05:40:30 +0000107 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:50 +0000112}
113
Amy Huang5a58b192023-01-09 23:37:28 -0500114uint64_t DefinedAbsolute::getRVA() { return va - ctx.config.imageBase; }
Reid Kleckner84564112017-06-22 23:33:04 +0000115
Amy Huang5a58b192023-01-09 23:37:28 -0500116DefinedImportThunk::DefinedImportThunk(COFFLinkerContext &ctx, StringRef name,
Jacek Caban7e0008d2024-09-11 12:22:36 +0200117 DefinedImportData *s,
118 ImportThunkChunk *chunk)
119 : Defined(DefinedImportThunkKind, name), wrappedSym(s), data(chunk) {}
Rui Ueyama28df0422015-07-25 01:16:06 +0000120
Jacek Cabanba898db2024-10-15 22:58:13 +0200121Symbol *Undefined::getWeakAlias() {
Peter Collingbourne2612a322015-07-04 05:28:41 +0000122 // A weak alias may be a weak alias to another symbol, so check recursively.
Jacek Caban513e0af2024-08-20 10:21:00 +0200123 DenseSet<Symbol *> weakChain;
124 for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias) {
Jacek Cabanf1ba8942024-10-21 11:44:31 +0200125 // Anti-dependency symbols can't be chained.
126 if (a->isAntiDep)
127 break;
Jacek Cabanba898db2024-10-15 22:58:13 +0200128 if (!isa<Undefined>(a))
129 return a;
Jacek Caban513e0af2024-08-20 10:21:00 +0200130 if (!weakChain.insert(a).second)
131 break; // We have a cycle.
132 }
Peter Collingbourne2612a322015-07-04 05:28:41 +0000133 return nullptr;
134}
Amy Huanga1c022c2019-08-22 19:40:07 +0000135
Jacek Cabanec4d5a62024-08-26 19:20:18 +0200136bool Undefined::resolveWeakAlias() {
Jacek Cabanba898db2024-10-15 22:58:13 +0200137 Defined *d = getDefinedWeakAlias();
Jacek Cabanec4d5a62024-08-26 19:20:18 +0200138 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 11:44:31 +0200147 bool wasAntiDep = isAntiDep;
Jacek Cabanec4d5a62024-08-26 19:20:18 +0200148 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 11:44:31 +0200157 isAntiDep = wasAntiDep;
Jacek Cabanec4d5a62024-08-26 19:20:18 +0200158 return true;
159}
160
Bob Haarman7dc5e7a02019-09-03 20:32:16 +0000161MemoryBufferRef LazyArchive::getMemberBuffer() {
Amy Huanga1c022c2019-08-22 19:40:07 +0000162 Archive::Child c =
Amy Huang5a58b192023-01-09 23:37:28 -0500163 CHECK(sym.getMember(), "could not get the member for symbol " +
Jacek Caban6b493ba2024-12-15 12:45:34 +0100164 toCOFFString(file->symtab.ctx, sym));
Amy Huanga1c022c2019-08-22 19:40:07 +0000165 return CHECK(c.getMemoryBufferRef(),
Amy Huang5a58b192023-01-09 23:37:28 -0500166 "could not get the buffer for the member defining symbol " +
Jacek Caban6b493ba2024-12-15 12:45:34 +0100167 toCOFFString(file->symtab.ctx, sym));
Amy Huanga1c022c2019-08-22 19:40:07 +0000168}
Rui Ueyamace039262017-01-06 10:04:08 +0000169} // namespace coff
Rui Ueyama411c63602015-05-28 19:09:30 +0000170} // namespace lld