Bug Summary

File:build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lld/COFF/Symbols.h
Warning:line 230, column 30
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name MapFile.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -isystem /usr/include/libxml2 -D LLD_VENDOR="Debian" -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/lld/COFF -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lld/COFF -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lld/include -I tools/lld/include -I include -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-16/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm=build-llvm -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm=build-llvm -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -O3 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm=build-llvm -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-09-04-125545-48738-1 -x c++ /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lld/COFF/MapFile.cpp

/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lld/COFF/MapFile.cpp

1//===- MapFile.cpp --------------------------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the /map option in the same format as link.exe
10// (based on observations)
11//
12// Header (program name, timestamp info, preferred load address)
13//
14// Section list (Start = Section index:Base address):
15// Start Length Name Class
16// 0001:00001000 00000015H .text CODE
17//
18// Symbols list:
19// Address Publics by Value Rva + Base Lib:Object
20// 0001:00001000 main 0000000140001000 main.obj
21// 0001:00001300 ?__scrt_common_main@@YAHXZ 0000000140001300 libcmt:exe_main.obj
22//
23// entry point at 0001:00000360
24//
25// Static symbols
26//
27// 0000:00000000 __guard_fids__ 0000000140000000 libcmt : exe_main.obj
28//===----------------------------------------------------------------------===//
29
30#include "MapFile.h"
31#include "COFFLinkerContext.h"
32#include "SymbolTable.h"
33#include "Symbols.h"
34#include "Writer.h"
35#include "lld/Common/ErrorHandler.h"
36#include "lld/Common/Timer.h"
37#include "llvm/Support/Parallel.h"
38#include "llvm/Support/Path.h"
39#include "llvm/Support/raw_ostream.h"
40
41using namespace llvm;
42using namespace llvm::object;
43using namespace lld;
44using namespace lld::coff;
45
46// Print out the first two columns of a line.
47static void writeHeader(raw_ostream &os, uint32_t sec, uint64_t addr) {
48 os << format(" %04x:%08llx", sec, addr);
49}
50
51// Write the time stamp with the format used by link.exe
52// It seems identical to strftime with "%c" on msvc build, but we need a
53// locale-agnostic version.
54static void writeFormattedTimestamp(raw_ostream &os, time_t tds) {
55 constexpr const char *const days[7] = {"Sun", "Mon", "Tue", "Wed",
56 "Thu", "Fri", "Sat"};
57 constexpr const char *const months[12] = {"Jan", "Feb", "Mar", "Apr",
58 "May", "Jun", "Jul", "Aug",
59 "Sep", "Oct", "Nov", "Dec"};
60 tm *time = localtime(&tds);
61 os << format("%s %s %2d %02d:%02d:%02d %d", days[time->tm_wday],
62 months[time->tm_mon], time->tm_mday, time->tm_hour, time->tm_min,
63 time->tm_sec, time->tm_year + 1900);
64}
65
66static void sortUniqueSymbols(std::vector<Defined *> &syms) {
67 // Build helper vector
68 using SortEntry = std::pair<Defined *, size_t>;
69 std::vector<SortEntry> v;
70 v.resize(syms.size());
71 for (size_t i = 0, e = syms.size(); i < e; ++i)
72 v[i] = SortEntry(syms[i], i);
73
74 // Remove duplicate symbol pointers
75 parallelSort(v, std::less<SortEntry>());
76 auto end = std::unique(v.begin(), v.end(),
77 [](const SortEntry &a, const SortEntry &b) {
78 return a.first == b.first;
79 });
80 v.erase(end, v.end());
81
82 // Sort by RVA then original order
83 parallelSort(v, [](const SortEntry &a, const SortEntry &b) {
84 // Add config->imageBase to avoid comparing "negative" RVAs.
85 // This can happen with symbols of Absolute kind
86 uint64_t rvaa = config->imageBase + a.first->getRVA();
87 uint64_t rvab = config->imageBase + b.first->getRVA();
88 return rvaa < rvab || (rvaa == rvab && a.second < b.second);
89 });
90
91 syms.resize(v.size());
92 for (size_t i = 0, e = v.size(); i < e; ++i)
93 syms[i] = v[i].first;
94}
95
96// Returns the lists of all symbols that we want to print out.
97static void getSymbols(const COFFLinkerContext &ctx,
98 std::vector<Defined *> &syms,
99 std::vector<Defined *> &staticSyms) {
100
101 for (ObjFile *file : ctx.objFileInstances)
102 for (Symbol *b : file->getSymbols()) {
103 if (!b || !b->isLive())
104 continue;
105 if (auto *sym = dyn_cast<DefinedCOFF>(b)) {
106 COFFSymbolRef symRef = sym->getCOFFSymbol();
107 if (!symRef.isSectionDefinition() &&
108 symRef.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL) {
109 if (symRef.getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC)
110 staticSyms.push_back(sym);
111 else
112 syms.push_back(sym);
113 }
114 } else if (auto *sym = dyn_cast<Defined>(b)) {
115 syms.push_back(sym);
116 }
117 }
118
119 for (ImportFile *file : ctx.importFileInstances) {
120 if (!file->live)
121 continue;
122
123 if (!file->thunkSym)
124 continue;
125
126 if (!file->thunkLive)
127 continue;
128
129 if (auto *thunkSym = dyn_cast<Defined>(file->thunkSym))
130 syms.push_back(thunkSym);
131
132 if (auto *impSym = dyn_cast_or_null<Defined>(file->impSym))
133 syms.push_back(impSym);
134 }
135
136 sortUniqueSymbols(syms);
137 sortUniqueSymbols(staticSyms);
138}
139
140// Construct a map from symbols to their stringified representations.
141static DenseMap<Defined *, std::string>
142getSymbolStrings(const COFFLinkerContext &ctx, ArrayRef<Defined *> syms) {
143 std::vector<std::string> str(syms.size());
144 parallelFor((size_t)0, syms.size(), [&](size_t i) {
145 raw_string_ostream os(str[i]);
146 Defined *sym = syms[i];
147
148 uint16_t sectionIdx = 0;
149 uint64_t address = 0;
150 SmallString<128> fileDescr;
151
152 if (auto *absSym
1.1
'absSym' is null
1.1
'absSym' is null
= dyn_cast<DefinedAbsolute>(sym)) {
1
Assuming 'sym' is not a 'CastReturnType'
2
Taking false branch
153 address = absSym->getVA();
154 fileDescr = "<absolute>";
155 } else if (isa<DefinedSynthetic>(sym)) {
3
Assuming 'sym' is not a 'DefinedSynthetic'
4
Taking false branch
156 fileDescr = "<linker-defined>";
157 } else if (isa<DefinedCommon>(sym)) {
5
Assuming 'sym' is not a 'DefinedCommon'
6
Taking false branch
158 fileDescr = "<common>";
159 } else if (Chunk *chunk = sym->getChunk()) {
7
Assuming 'chunk' is null
8
Taking false branch
160 address = sym->getRVA();
161 if (OutputSection *sec = ctx.getOutputSection(chunk))
162 address -= sec->header.VirtualAddress;
163
164 sectionIdx = chunk->getOutputSectionIdx();
165
166 InputFile *file;
167 if (auto *impSym = dyn_cast<DefinedImportData>(sym))
168 file = impSym->file;
169 else if (auto *thunkSym = dyn_cast<DefinedImportThunk>(sym))
170 file = thunkSym->wrappedSym->file;
171 else
172 file = sym->getFile();
173
174 if (file) {
175 if (!file->parentName.empty()) {
176 fileDescr = sys::path::filename(file->parentName);
177 sys::path::replace_extension(fileDescr, "");
178 fileDescr += ":";
179 }
180 fileDescr += sys::path::filename(file->getName());
181 }
182 }
183 writeHeader(os, sectionIdx, address);
184 os << " ";
185 os << left_justify(sym->getName(), 26);
186 os << " ";
187 os << format_hex_no_prefix((config->imageBase + sym->getRVA()), 16);
9
Calling 'Defined::getRVA'
188 if (!fileDescr.empty()) {
189 os << " "; // FIXME : Handle "f" and "i" flags sometimes generated
190 // by link.exe in those spaces
191 os << fileDescr;
192 }
193 });
194
195 DenseMap<Defined *, std::string> ret;
196 for (size_t i = 0, e = syms.size(); i < e; ++i)
197 ret[syms[i]] = std::move(str[i]);
198 return ret;
199}
200
201void lld::coff::writeMapFile(COFFLinkerContext &ctx) {
202 if (config->mapFile.empty())
203 return;
204
205 std::error_code ec;
206 raw_fd_ostream os(config->mapFile, ec, sys::fs::OF_None);
207 if (ec)
208 fatal("cannot open " + config->mapFile + ": " + ec.message());
209
210 ScopedTimer t1(ctx.totalMapTimer);
211
212 // Collect symbol info that we want to print out.
213 ScopedTimer t2(ctx.symbolGatherTimer);
214 std::vector<Defined *> syms;
215 std::vector<Defined *> staticSyms;
216 getSymbols(ctx, syms, staticSyms);
217 t2.stop();
218
219 ScopedTimer t3(ctx.symbolStringsTimer);
220 DenseMap<Defined *, std::string> symStr = getSymbolStrings(ctx, syms);
221 DenseMap<Defined *, std::string> staticSymStr =
222 getSymbolStrings(ctx, staticSyms);
223 t3.stop();
224
225 ScopedTimer t4(ctx.writeTimer);
226 SmallString<128> AppName = sys::path::filename(config->outputFile);
227 sys::path::replace_extension(AppName, "");
228
229 // Print out the file header
230 os << " " << AppName << "\n";
231 os << "\n";
232
233 os << " Timestamp is " << format_hex_no_prefix(config->timestamp, 8) << " (";
234 if (config->repro) {
235 os << "Repro mode";
236 } else {
237 writeFormattedTimestamp(os, config->timestamp);
238 }
239 os << ")\n";
240
241 os << "\n";
242 os << " Preferred load address is "
243 << format_hex_no_prefix(config->imageBase, 16) << "\n";
244 os << "\n";
245
246 // Print out section table.
247 os << " Start Length Name Class\n";
248
249 for (OutputSection *sec : ctx.outputSections) {
250 // Merge display of chunks with same sectionName
251 std::vector<std::pair<SectionChunk *, SectionChunk *>> ChunkRanges;
252 for (Chunk *c : sec->chunks) {
253 auto *sc = dyn_cast<SectionChunk>(c);
254 if (!sc)
255 continue;
256
257 if (ChunkRanges.empty() ||
258 c->getSectionName() != ChunkRanges.back().first->getSectionName()) {
259 ChunkRanges.emplace_back(sc, sc);
260 } else {
261 ChunkRanges.back().second = sc;
262 }
263 }
264
265 const bool isCodeSection =
266 (sec->header.Characteristics & COFF::IMAGE_SCN_CNT_CODE) &&
267 (sec->header.Characteristics & COFF::IMAGE_SCN_MEM_READ) &&
268 (sec->header.Characteristics & COFF::IMAGE_SCN_MEM_EXECUTE);
269 StringRef SectionClass = (isCodeSection ? "CODE" : "DATA");
270
271 for (auto &cr : ChunkRanges) {
272 size_t size =
273 cr.second->getRVA() + cr.second->getSize() - cr.first->getRVA();
274
275 auto address = cr.first->getRVA() - sec->header.VirtualAddress;
276 writeHeader(os, sec->sectionIndex, address);
277 os << " " << format_hex_no_prefix(size, 8) << "H";
278 os << " " << left_justify(cr.first->getSectionName(), 23);
279 os << " " << SectionClass;
280 os << '\n';
281 }
282 }
283
284 // Print out the symbols table (without static symbols)
285 os << "\n";
286 os << " Address Publics by Value Rva+Base"
287 " Lib:Object\n";
288 os << "\n";
289 for (Defined *sym : syms)
290 os << symStr[sym] << '\n';
291
292 // Print out the entry point.
293 os << "\n";
294
295 uint16_t entrySecIndex = 0;
296 uint64_t entryAddress = 0;
297
298 if (!config->noEntry) {
299 Defined *entry = dyn_cast_or_null<Defined>(config->entry);
300 if (entry) {
301 Chunk *chunk = entry->getChunk();
302 entrySecIndex = chunk->getOutputSectionIdx();
303 entryAddress =
304 entry->getRVA() - ctx.getOutputSection(chunk)->header.VirtualAddress;
305 }
306 }
307 os << " entry point at ";
308 os << format("%04x:%08llx", entrySecIndex, entryAddress);
309 os << "\n";
310
311 // Print out the static symbols
312 os << "\n";
313 os << " Static symbols\n";
314 os << "\n";
315 for (Defined *sym : staticSyms)
316 os << staticSymStr[sym] << '\n';
317
318 t4.stop();
319 t1.stop();
320}

/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lld/COFF/Symbols.h

1//===- Symbols.h ------------------------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_COFF_SYMBOLS_H
10#define LLD_COFF_SYMBOLS_H
11
12#include "Chunks.h"
13#include "Config.h"
14#include "lld/Common/LLVM.h"
15#include "lld/Common/Memory.h"
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/Object/Archive.h"
18#include "llvm/Object/COFF.h"
19#include <atomic>
20#include <memory>
21#include <vector>
22
23namespace lld {
24
25std::string toString(coff::Symbol &b);
26
27// There are two different ways to convert an Archive::Symbol to a string:
28// One for Microsoft name mangling and one for Itanium name mangling.
29// Call the functions toCOFFString and toELFString, not just toString.
30std::string toCOFFString(const coff::Archive::Symbol &b);
31
32namespace coff {
33
34using llvm::object::Archive;
35using llvm::object::COFFSymbolRef;
36using llvm::object::coff_import_header;
37using llvm::object::coff_symbol_generic;
38
39class ArchiveFile;
40class InputFile;
41class ObjFile;
42class SymbolTable;
43
44// The base class for real symbol classes.
45class Symbol {
46public:
47 enum Kind {
48 // The order of these is significant. We start with the regular defined
49 // symbols as those are the most prevalent and the zero tag is the cheapest
50 // to set. Among the defined kinds, the lower the kind is preferred over
51 // the higher kind when testing whether one symbol should take precedence
52 // over another.
53 DefinedRegularKind = 0,
54 DefinedCommonKind,
55 DefinedLocalImportKind,
56 DefinedImportThunkKind,
57 DefinedImportDataKind,
58 DefinedAbsoluteKind,
59 DefinedSyntheticKind,
60
61 UndefinedKind,
62 LazyArchiveKind,
63 LazyObjectKind,
64 LazyDLLSymbolKind,
65
66 LastDefinedCOFFKind = DefinedCommonKind,
67 LastDefinedKind = DefinedSyntheticKind,
68 };
69
70 Kind kind() const { return static_cast<Kind>(symbolKind); }
71
72 // Returns the symbol name.
73 StringRef getName() {
74 // COFF symbol names are read lazily for a performance reason.
75 // Non-external symbol names are never used by the linker except for logging
76 // or debugging. Their internal references are resolved not by name but by
77 // symbol index. And because they are not external, no one can refer them by
78 // name. Object files contain lots of non-external symbols, and creating
79 // StringRefs for them (which involves lots of strlen() on the string table)
80 // is a waste of time.
81 if (nameData == nullptr)
82 computeName();
83 return StringRef(nameData, nameSize);
84 }
85
86 void replaceKeepingName(Symbol *other, size_t size);
87
88 // Returns the file from which this symbol was created.
89 InputFile *getFile();
90
91 // Indicates that this symbol will be included in the final image. Only valid
92 // after calling markLive.
93 bool isLive() const;
94
95 bool isLazy() const {
96 return symbolKind == LazyArchiveKind || symbolKind == LazyObjectKind ||
97 symbolKind == LazyDLLSymbolKind;
98 }
99
100private:
101 void computeName();
102
103protected:
104 friend SymbolTable;
105 explicit Symbol(Kind k, StringRef n = "")
106 : symbolKind(k), isExternal(true), isCOMDAT(false),
107 writtenToSymtab(false), pendingArchiveLoad(false), isGCRoot(false),
108 isRuntimePseudoReloc(false), deferUndefined(false), canInline(true),
109 nameSize(n.size()), nameData(n.empty() ? nullptr : n.data()) {}
110
111 const unsigned symbolKind : 8;
112 unsigned isExternal : 1;
113
114public:
115 // This bit is used by the \c DefinedRegular subclass.
116 unsigned isCOMDAT : 1;
117
118 // This bit is used by Writer::createSymbolAndStringTable() to prevent
119 // symbols from being written to the symbol table more than once.
120 unsigned writtenToSymtab : 1;
121
122 // True if this symbol was referenced by a regular (non-bitcode) object.
123 unsigned isUsedInRegularObj : 1;
124
125 // True if we've seen both a lazy and an undefined symbol with this symbol
126 // name, which means that we have enqueued an archive member load and should
127 // not load any more archive members to resolve the same symbol.
128 unsigned pendingArchiveLoad : 1;
129
130 /// True if we've already added this symbol to the list of GC roots.
131 unsigned isGCRoot : 1;
132
133 unsigned isRuntimePseudoReloc : 1;
134
135 // True if we want to allow this symbol to be undefined in the early
136 // undefined check pass in SymbolTable::reportUnresolvable(), as it
137 // might be fixed up later.
138 unsigned deferUndefined : 1;
139
140 // False if LTO shouldn't inline whatever this symbol points to. If a symbol
141 // is overwritten after LTO, LTO shouldn't inline the symbol because it
142 // doesn't know the final contents of the symbol.
143 unsigned canInline : 1;
144
145protected:
146 // Symbol name length. Assume symbol lengths fit in a 32-bit integer.
147 uint32_t nameSize;
148
149 const char *nameData;
150};
151
152// The base class for any defined symbols, including absolute symbols,
153// etc.
154class Defined : public Symbol {
155public:
156 Defined(Kind k, StringRef n) : Symbol(k, n) {}
157
158 static bool classof(const Symbol *s) { return s->kind() <= LastDefinedKind; }
159
160 // Returns the RVA (relative virtual address) of this symbol. The
161 // writer sets and uses RVAs.
162 uint64_t getRVA();
163
164 // Returns the chunk containing this symbol. Absolute symbols and __ImageBase
165 // do not have chunks, so this may return null.
166 Chunk *getChunk();
167};
168
169// Symbols defined via a COFF object file or bitcode file. For COFF files, this
170// stores a coff_symbol_generic*, and names of internal symbols are lazily
171// loaded through that. For bitcode files, Sym is nullptr and the name is stored
172// as a decomposed StringRef.
173class DefinedCOFF : public Defined {
174 friend Symbol;
175
176public:
177 DefinedCOFF(Kind k, InputFile *f, StringRef n, const coff_symbol_generic *s)
178 : Defined(k, n), file(f), sym(s) {}
179
180 static bool classof(const Symbol *s) {
181 return s->kind() <= LastDefinedCOFFKind;
182 }
183
184 InputFile *getFile() { return file; }
185
186 COFFSymbolRef getCOFFSymbol();
187
188 InputFile *file;
189
190protected:
191 const coff_symbol_generic *sym;
192};
193
194// Regular defined symbols read from object file symbol tables.
195class DefinedRegular : public DefinedCOFF {
196public:
197 DefinedRegular(InputFile *f, StringRef n, bool isCOMDAT,
198 bool isExternal = false,
199 const coff_symbol_generic *s = nullptr,
200 SectionChunk *c = nullptr)
201 : DefinedCOFF(DefinedRegularKind, f, n, s), data(c ? &c->repl : nullptr) {
202 this->isExternal = isExternal;
203 this->isCOMDAT = isCOMDAT;
204 }
205
206 static bool classof(const Symbol *s) {
207 return s->kind() == DefinedRegularKind;
208 }
209
210 uint64_t getRVA() const { return (*data)->getRVA() + sym->Value; }
211 SectionChunk *getChunk() const { return *data; }
212 uint32_t getValue() const { return sym->Value; }
213
214 SectionChunk **data;
215};
216
217class DefinedCommon : public DefinedCOFF {
218public:
219 DefinedCommon(InputFile *f, StringRef n, uint64_t size,
220 const coff_symbol_generic *s = nullptr,
221 CommonChunk *c = nullptr)
222 : DefinedCOFF(DefinedCommonKind, f, n, s), data(c), size(size) {
223 this->isExternal = true;
224 }
225
226 static bool classof(const Symbol *s) {
227 return s->kind() == DefinedCommonKind;
228 }
229
230 uint64_t getRVA() { return data->getRVA(); }
13
Called C++ object pointer is null
231 CommonChunk *getChunk() { return data; }
232
233private:
234 friend SymbolTable;
235 uint64_t getSize() const { return size; }
236 CommonChunk *data;
237 uint64_t size;
238};
239
240// Absolute symbols.
241class DefinedAbsolute : public Defined {
242public:
243 DefinedAbsolute(StringRef n, COFFSymbolRef s)
244 : Defined(DefinedAbsoluteKind, n), va(s.getValue()) {
245 isExternal = s.isExternal();
246 }
247
248 DefinedAbsolute(StringRef n, uint64_t v)
249 : Defined(DefinedAbsoluteKind, n), va(v) {}
250
251 static bool classof(const Symbol *s) {
252 return s->kind() == DefinedAbsoluteKind;
253 }
254
255 uint64_t getRVA() { return va - config->imageBase; }
256 void setVA(uint64_t v) { va = v; }
257 uint64_t getVA() const { return va; }
258
259 // Section index relocations against absolute symbols resolve to
260 // this 16 bit number, and it is the largest valid section index
261 // plus one. This variable keeps it.
262 static uint16_t numOutputSections;
263
264private:
265 uint64_t va;
266};
267
268// This symbol is used for linker-synthesized symbols like __ImageBase and
269// __safe_se_handler_table.
270class DefinedSynthetic : public Defined {
271public:
272 explicit DefinedSynthetic(StringRef name, Chunk *c)
273 : Defined(DefinedSyntheticKind, name), c(c) {}
274
275 static bool classof(const Symbol *s) {
276 return s->kind() == DefinedSyntheticKind;
277 }
278
279 // A null chunk indicates that this is __ImageBase. Otherwise, this is some
280 // other synthesized chunk, like SEHTableChunk.
281 uint32_t getRVA() { return c ? c->getRVA() : 0; }
282 Chunk *getChunk() { return c; }
283
284private:
285 Chunk *c;
286};
287
288// This class represents a symbol defined in an archive file. It is
289// created from an archive file header, and it knows how to load an
290// object file from an archive to replace itself with a defined
291// symbol. If the resolver finds both Undefined and LazyArchive for
292// the same name, it will ask the LazyArchive to load a file.
293class LazyArchive : public Symbol {
294public:
295 LazyArchive(ArchiveFile *f, const Archive::Symbol s)
296 : Symbol(LazyArchiveKind, s.getName()), file(f), sym(s) {}
297
298 static bool classof(const Symbol *s) { return s->kind() == LazyArchiveKind; }
299
300 MemoryBufferRef getMemberBuffer();
301
302 ArchiveFile *file;
303 const Archive::Symbol sym;
304};
305
306class LazyObject : public Symbol {
307public:
308 LazyObject(InputFile *f, StringRef n) : Symbol(LazyObjectKind, n), file(f) {}
309 static bool classof(const Symbol *s) { return s->kind() == LazyObjectKind; }
310 InputFile *file;
311};
312
313// MinGW only.
314class LazyDLLSymbol : public Symbol {
315public:
316 LazyDLLSymbol(DLLFile *f, DLLFile::Symbol *s, StringRef n)
317 : Symbol(LazyDLLSymbolKind, n), file(f), sym(s) {}
318 static bool classof(const Symbol *s) {
319 return s->kind() == LazyDLLSymbolKind;
320 }
321
322 DLLFile *file;
323 DLLFile::Symbol *sym;
324};
325
326// Undefined symbols.
327class Undefined : public Symbol {
328public:
329 explicit Undefined(StringRef n) : Symbol(UndefinedKind, n) {}
330
331 static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; }
332
333 // An undefined symbol can have a fallback symbol which gives an
334 // undefined symbol a second chance if it would remain undefined.
335 // If it remains undefined, it'll be replaced with whatever the
336 // Alias pointer points to.
337 Symbol *weakAlias = nullptr;
338
339 // If this symbol is external weak, try to resolve it to a defined
340 // symbol by searching the chain of fallback symbols. Returns the symbol if
341 // successful, otherwise returns null.
342 Defined *getWeakAlias();
343};
344
345// Windows-specific classes.
346
347// This class represents a symbol imported from a DLL. This has two
348// names for internal use and external use. The former is used for
349// name resolution, and the latter is used for the import descriptor
350// table in an output. The former has "__imp_" prefix.
351class DefinedImportData : public Defined {
352public:
353 DefinedImportData(StringRef n, ImportFile *f)
354 : Defined(DefinedImportDataKind, n), file(f) {
355 }
356
357 static bool classof(const Symbol *s) {
358 return s->kind() == DefinedImportDataKind;
359 }
360
361 uint64_t getRVA() { return file->location->getRVA(); }
362 Chunk *getChunk() { return file->location; }
363 void setLocation(Chunk *addressTable) { file->location = addressTable; }
364
365 StringRef getDLLName() { return file->dllName; }
366 StringRef getExternalName() { return file->externalName; }
367 uint16_t getOrdinal() { return file->hdr->OrdinalHint; }
368
369 ImportFile *file;
370
371 // This is a pointer to the synthetic symbol associated with the load thunk
372 // for this symbol that will be called if the DLL is delay-loaded. This is
373 // needed for Control Flow Guard because if this DefinedImportData symbol is a
374 // valid call target, the corresponding load thunk must also be marked as a
375 // valid call target.
376 DefinedSynthetic *loadThunkSym = nullptr;
377};
378
379// This class represents a symbol for a jump table entry which jumps
380// to a function in a DLL. Linker are supposed to create such symbols
381// without "__imp_" prefix for all function symbols exported from
382// DLLs, so that you can call DLL functions as regular functions with
383// a regular name. A function pointer is given as a DefinedImportData.
384class DefinedImportThunk : public Defined {
385public:
386 DefinedImportThunk(StringRef name, DefinedImportData *s, uint16_t machine);
387
388 static bool classof(const Symbol *s) {
389 return s->kind() == DefinedImportThunkKind;
390 }
391
392 uint64_t getRVA() { return data->getRVA(); }
393 Chunk *getChunk() { return data; }
394
395 DefinedImportData *wrappedSym;
396
397private:
398 Chunk *data;
399};
400
401// If you have a symbol "foo" in your object file, a symbol name
402// "__imp_foo" becomes automatically available as a pointer to "foo".
403// This class is for such automatically-created symbols.
404// Yes, this is an odd feature. We didn't intend to implement that.
405// This is here just for compatibility with MSVC.
406class DefinedLocalImport : public Defined {
407public:
408 DefinedLocalImport(StringRef n, Defined *s)
409 : Defined(DefinedLocalImportKind, n), data(make<LocalImportChunk>(s)) {}
410
411 static bool classof(const Symbol *s) {
412 return s->kind() == DefinedLocalImportKind;
413 }
414
415 uint64_t getRVA() { return data->getRVA(); }
416 Chunk *getChunk() { return data; }
417
418private:
419 LocalImportChunk *data;
420};
421
422inline uint64_t Defined::getRVA() {
423 switch (kind()) {
10
Control jumps to 'case DefinedCommonKind:' at line 434
424 case DefinedAbsoluteKind:
425 return cast<DefinedAbsolute>(this)->getRVA();
426 case DefinedSyntheticKind:
427 return cast<DefinedSynthetic>(this)->getRVA();
428 case DefinedImportDataKind:
429 return cast<DefinedImportData>(this)->getRVA();
430 case DefinedImportThunkKind:
431 return cast<DefinedImportThunk>(this)->getRVA();
432 case DefinedLocalImportKind:
433 return cast<DefinedLocalImport>(this)->getRVA();
434 case DefinedCommonKind:
435 return cast<DefinedCommon>(this)->getRVA();
11
The object is a 'DefinedCommon'
12
Calling 'DefinedCommon::getRVA'
436 case DefinedRegularKind:
437 return cast<DefinedRegular>(this)->getRVA();
438 case LazyArchiveKind:
439 case LazyObjectKind:
440 case LazyDLLSymbolKind:
441 case UndefinedKind:
442 llvm_unreachable("Cannot get the address for an undefined symbol.")::llvm::llvm_unreachable_internal("Cannot get the address for an undefined symbol."
, "lld/COFF/Symbols.h", 442)
;
443 }
444 llvm_unreachable("unknown symbol kind")::llvm::llvm_unreachable_internal("unknown symbol kind", "lld/COFF/Symbols.h"
, 444)
;
445}
446
447inline Chunk *Defined::getChunk() {
448 switch (kind()) {
449 case DefinedRegularKind:
450 return cast<DefinedRegular>(this)->getChunk();
451 case DefinedAbsoluteKind:
452 return nullptr;
453 case DefinedSyntheticKind:
454 return cast<DefinedSynthetic>(this)->getChunk();
455 case DefinedImportDataKind:
456 return cast<DefinedImportData>(this)->getChunk();
457 case DefinedImportThunkKind:
458 return cast<DefinedImportThunk>(this)->getChunk();
459 case DefinedLocalImportKind:
460 return cast<DefinedLocalImport>(this)->getChunk();
461 case DefinedCommonKind:
462 return cast<DefinedCommon>(this)->getChunk();
463 case LazyArchiveKind:
464 case LazyObjectKind:
465 case LazyDLLSymbolKind:
466 case UndefinedKind:
467 llvm_unreachable("Cannot get the chunk of an undefined symbol.")::llvm::llvm_unreachable_internal("Cannot get the chunk of an undefined symbol."
, "lld/COFF/Symbols.h", 467)
;
468 }
469 llvm_unreachable("unknown symbol kind")::llvm::llvm_unreachable_internal("unknown symbol kind", "lld/COFF/Symbols.h"
, 469)
;
470}
471
472// A buffer class that is large enough to hold any Symbol-derived
473// object. We allocate memory using this class and instantiate a symbol
474// using the placement new.
475union SymbolUnion {
476 alignas(DefinedRegular) char a[sizeof(DefinedRegular)];
477 alignas(DefinedCommon) char b[sizeof(DefinedCommon)];
478 alignas(DefinedAbsolute) char c[sizeof(DefinedAbsolute)];
479 alignas(DefinedSynthetic) char d[sizeof(DefinedSynthetic)];
480 alignas(LazyArchive) char e[sizeof(LazyArchive)];
481 alignas(Undefined) char f[sizeof(Undefined)];
482 alignas(DefinedImportData) char g[sizeof(DefinedImportData)];
483 alignas(DefinedImportThunk) char h[sizeof(DefinedImportThunk)];
484 alignas(DefinedLocalImport) char i[sizeof(DefinedLocalImport)];
485 alignas(LazyObject) char j[sizeof(LazyObject)];
486 alignas(LazyDLLSymbol) char k[sizeof(LazyDLLSymbol)];
487};
488
489template <typename T, typename... ArgT>
490void replaceSymbol(Symbol *s, ArgT &&... arg) {
491 static_assert(std::is_trivially_destructible<T>(),
492 "Symbol types must be trivially destructible");
493 static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");
494 static_assert(alignof(T) <= alignof(SymbolUnion),
495 "SymbolUnion not aligned enough");
496 assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&(static_cast <bool> (static_cast<Symbol *>(static_cast
<T *>(nullptr)) == nullptr && "Not a Symbol") ?
void (0) : __assert_fail ("static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr && \"Not a Symbol\""
, "lld/COFF/Symbols.h", 497, __extension__ __PRETTY_FUNCTION__
))
497 "Not a Symbol")(static_cast <bool> (static_cast<Symbol *>(static_cast
<T *>(nullptr)) == nullptr && "Not a Symbol") ?
void (0) : __assert_fail ("static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr && \"Not a Symbol\""
, "lld/COFF/Symbols.h", 497, __extension__ __PRETTY_FUNCTION__
))
;
498 bool canInline = s->canInline;
499 new (s) T(std::forward<ArgT>(arg)...);
500 s->canInline = canInline;
501}
502} // namespace coff
503
504} // namespace lld
505
506#endif