1//===- InputFiles.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#include "InputFiles.h"
10#include "Config.h"
11#include "InputChunks.h"
12#include "InputElement.h"
13#include "OutputSegment.h"
14#include "SymbolTable.h"
15#include "lld/Common/CommonLinkerContext.h"
16#include "lld/Common/Reproduce.h"
17#include "llvm/BinaryFormat/Wasm.h"
18#include "llvm/Object/Binary.h"
19#include "llvm/Object/Wasm.h"
20#include "llvm/ProfileData/InstrProf.h"
21#include "llvm/Support/Path.h"
22#include "llvm/Support/TarWriter.h"
23#include "llvm/Support/raw_ostream.h"
24#include <optional>
25
26#define DEBUG_TYPE "lld"
27
28using namespace llvm;
29using namespace llvm::object;
30using namespace llvm::wasm;
31using namespace llvm::sys;
32
33namespace lld {
34
35// Returns a string in the format of "foo.o" or "foo.a(bar.o)".
36std::string toString(const wasm::InputFile *file) {
37 if (!file)
38 return "<internal>";
39
40 if (file->archiveName.empty())
41 return std::string(file->getName());
42
43 return (file->archiveName + "(" + file->getName() + ")").str();
44}
45
46namespace wasm {
47
48std::string replaceThinLTOSuffix(StringRef path) {
49 auto [suffix, repl] = ctx.arg.thinLTOObjectSuffixReplace;
50 if (path.consume_back(Suffix: suffix))
51 return (path + repl).str();
52 return std::string(path);
53}
54
55void InputFile::checkArch(Triple::ArchType arch) const {
56 bool is64 = arch == Triple::wasm64;
57 if (is64 && !ctx.arg.is64) {
58 fatal(msg: toString(file: this) +
59 ": must specify -mwasm64 to process wasm64 object files");
60 }
61 if (ctx.arg.is64.value_or(u: false) != is64) {
62 fatal(msg: toString(file: this) +
63 (is64 ? ": wasm64 object file can't be linked in wasm32 mode"
64 : ": wasm32 object file can't be linked in wasm64 mode"));
65 }
66}
67
68std::unique_ptr<llvm::TarWriter> tar;
69
70std::optional<MemoryBufferRef> readFile(StringRef path) {
71 log(msg: "Loading: " + path);
72
73 auto mbOrErr = MemoryBuffer::getFile(Filename: path);
74 if (auto ec = mbOrErr.getError()) {
75 error(msg: "cannot open " + path + ": " + ec.message());
76 return std::nullopt;
77 }
78 std::unique_ptr<MemoryBuffer> &mb = *mbOrErr;
79 MemoryBufferRef mbref = mb->getMemBufferRef();
80 make<std::unique_ptr<MemoryBuffer>>(args: std::move(mb)); // take MB ownership
81
82 if (tar)
83 tar->append(Path: relativeToRoot(path), Data: mbref.getBuffer());
84 return mbref;
85}
86
87InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName,
88 uint64_t offsetInArchive, bool lazy) {
89 file_magic magic = identify_magic(magic: mb.getBuffer());
90 if (magic == file_magic::wasm_object) {
91 std::unique_ptr<Binary> bin =
92 CHECK(createBinary(mb), mb.getBufferIdentifier());
93 auto *obj = cast<WasmObjectFile>(Val: bin.get());
94 if (obj->hasUnmodeledTypes())
95 fatal(msg: toString(s: mb.getBufferIdentifier()) +
96 " file has unmodeled reference or GC types");
97 if (obj->isSharedObject())
98 return make<SharedFile>(args&: mb);
99 return make<ObjFile>(args&: mb, args&: archiveName, args&: lazy);
100 }
101
102 assert(magic == file_magic::bitcode);
103 return make<BitcodeFile>(args&: mb, args&: archiveName, args&: offsetInArchive, args&: lazy);
104}
105
106// Relocations contain either symbol or type indices. This function takes a
107// relocation and returns relocated index (i.e. translates from the input
108// symbol/type space to the output symbol/type space).
109uint32_t ObjFile::calcNewIndex(const WasmRelocation &reloc) const {
110 if (reloc.Type == R_WASM_TYPE_INDEX_LEB) {
111 assert(typeIsUsed[reloc.Index]);
112 return typeMap[reloc.Index];
113 }
114 const Symbol *sym = symbols[reloc.Index];
115 if (auto *ss = dyn_cast<SectionSymbol>(Val: sym))
116 sym = ss->getOutputSectionSymbol();
117 return sym->getOutputSymbolIndex();
118}
119
120// Relocations can contain addend for combined sections. This function takes a
121// relocation and returns updated addend by offset in the output section.
122int64_t ObjFile::calcNewAddend(const WasmRelocation &reloc) const {
123 switch (reloc.Type) {
124 case R_WASM_MEMORY_ADDR_LEB:
125 case R_WASM_MEMORY_ADDR_LEB64:
126 case R_WASM_MEMORY_ADDR_SLEB64:
127 case R_WASM_MEMORY_ADDR_SLEB:
128 case R_WASM_MEMORY_ADDR_REL_SLEB:
129 case R_WASM_MEMORY_ADDR_REL_SLEB64:
130 case R_WASM_MEMORY_ADDR_I32:
131 case R_WASM_MEMORY_ADDR_I64:
132 case R_WASM_MEMORY_ADDR_TLS_SLEB:
133 case R_WASM_MEMORY_ADDR_TLS_SLEB64:
134 case R_WASM_FUNCTION_OFFSET_I32:
135 case R_WASM_FUNCTION_OFFSET_I64:
136 case R_WASM_MEMORY_ADDR_LOCREL_I32:
137 case R_WASM_MEMORY_ADDR_LOCREL_I64:
138 return reloc.Addend;
139 case R_WASM_SECTION_OFFSET_I32:
140 return getSectionSymbol(index: reloc.Index)->section->getOffset(offset: reloc.Addend);
141 default:
142 llvm_unreachable("unexpected relocation type");
143 }
144}
145
146// Translate from the relocation's index into the final linked output value.
147uint64_t ObjFile::calcNewValue(const WasmRelocation &reloc, uint64_t tombstone,
148 const InputChunk *chunk) const {
149 const Symbol *sym = nullptr;
150 if (reloc.Type != R_WASM_TYPE_INDEX_LEB) {
151 sym = symbols[reloc.Index];
152
153 // We can end up with relocations against non-live symbols. For example
154 // in debug sections. We return a tombstone value in debug symbol sections
155 // so this will not produce a valid range conflicting with ranges of actual
156 // code. In other sections we return reloc.Addend.
157
158 if (!isa<SectionSymbol>(Val: sym) && !sym->isLive())
159 return tombstone ? tombstone : reloc.Addend;
160 }
161
162 switch (reloc.Type) {
163 case R_WASM_TABLE_INDEX_I32:
164 case R_WASM_TABLE_INDEX_I64:
165 case R_WASM_TABLE_INDEX_SLEB:
166 case R_WASM_TABLE_INDEX_SLEB64:
167 case R_WASM_TABLE_INDEX_REL_SLEB:
168 case R_WASM_TABLE_INDEX_REL_SLEB64: {
169 if (!getFunctionSymbol(index: reloc.Index)->hasTableIndex())
170 return 0;
171 uint32_t index = getFunctionSymbol(index: reloc.Index)->getTableIndex();
172 if (reloc.Type == R_WASM_TABLE_INDEX_REL_SLEB ||
173 reloc.Type == R_WASM_TABLE_INDEX_REL_SLEB64)
174 index -= ctx.arg.tableBase;
175 return index;
176 }
177 case R_WASM_MEMORY_ADDR_LEB:
178 case R_WASM_MEMORY_ADDR_LEB64:
179 case R_WASM_MEMORY_ADDR_SLEB:
180 case R_WASM_MEMORY_ADDR_SLEB64:
181 case R_WASM_MEMORY_ADDR_REL_SLEB:
182 case R_WASM_MEMORY_ADDR_REL_SLEB64:
183 case R_WASM_MEMORY_ADDR_I32:
184 case R_WASM_MEMORY_ADDR_I64:
185 case R_WASM_MEMORY_ADDR_TLS_SLEB:
186 case R_WASM_MEMORY_ADDR_TLS_SLEB64:
187 case R_WASM_MEMORY_ADDR_LOCREL_I32:
188 case R_WASM_MEMORY_ADDR_LOCREL_I64: {
189 if (isa<UndefinedData>(Val: sym) || sym->isShared() || sym->isUndefWeak())
190 return 0;
191 auto D = cast<DefinedData>(Val: sym);
192 uint64_t value = D->getVA() + reloc.Addend;
193 if (reloc.Type == R_WASM_MEMORY_ADDR_LOCREL_I32 ||
194 reloc.Type == R_WASM_MEMORY_ADDR_LOCREL_I64) {
195 const auto *segment = cast<InputSegment>(Val: chunk);
196 uint64_t p = segment->outputSeg->startVA + segment->outputSegmentOffset +
197 reloc.Offset - segment->getInputSectionOffset();
198 value -= p;
199 }
200 return value;
201 }
202 case R_WASM_TYPE_INDEX_LEB:
203 return typeMap[reloc.Index];
204 case R_WASM_FUNCTION_INDEX_LEB:
205 case R_WASM_FUNCTION_INDEX_I32:
206 return getFunctionSymbol(index: reloc.Index)->getFunctionIndex();
207 case R_WASM_GLOBAL_INDEX_LEB:
208 case R_WASM_GLOBAL_INDEX_I32:
209 if (auto gs = dyn_cast<GlobalSymbol>(Val: sym))
210 return gs->getGlobalIndex();
211 return sym->getGOTIndex();
212 case R_WASM_TAG_INDEX_LEB:
213 return getTagSymbol(index: reloc.Index)->getTagIndex();
214 case R_WASM_FUNCTION_OFFSET_I32:
215 case R_WASM_FUNCTION_OFFSET_I64: {
216 if (isa<UndefinedFunction>(Val: sym) || sym->isShared()) {
217 return tombstone ? tombstone : reloc.Addend;
218 }
219 auto *f = cast<DefinedFunction>(Val: sym);
220 return f->function->getOffset(offset: f->function->getFunctionCodeOffset() +
221 reloc.Addend);
222 }
223 case R_WASM_SECTION_OFFSET_I32:
224 return getSectionSymbol(index: reloc.Index)->section->getOffset(offset: reloc.Addend);
225 case R_WASM_TABLE_NUMBER_LEB:
226 return getTableSymbol(index: reloc.Index)->getTableNumber();
227 default:
228 llvm_unreachable("unknown relocation type");
229 }
230}
231
232template <class T>
233static void setRelocs(const std::vector<T *> &chunks,
234 const WasmSection *section) {
235 if (!section)
236 return;
237
238 ArrayRef<WasmRelocation> relocs = section->Relocations;
239 assert(llvm::is_sorted(
240 relocs, [](const WasmRelocation &r1, const WasmRelocation &r2) {
241 return r1.Offset < r2.Offset;
242 }));
243 assert(llvm::is_sorted(chunks, [](InputChunk *c1, InputChunk *c2) {
244 return c1->getInputSectionOffset() < c2->getInputSectionOffset();
245 }));
246
247 auto relocsNext = relocs.begin();
248 auto relocsEnd = relocs.end();
249 auto relocLess = [](const WasmRelocation &r, uint32_t val) {
250 return r.Offset < val;
251 };
252 for (InputChunk *c : chunks) {
253 auto relocsStart = std::lower_bound(relocsNext, relocsEnd,
254 c->getInputSectionOffset(), relocLess);
255 relocsNext = std::lower_bound(
256 relocsStart, relocsEnd, c->getInputSectionOffset() + c->getInputSize(),
257 relocLess);
258 c->setRelocations(ArrayRef<WasmRelocation>(relocsStart, relocsNext));
259 }
260}
261
262// An object file can have two approaches to tables. With the
263// reference-types feature or call-indirect-overlong feature enabled
264// (explicitly, or implied by the reference-types feature), input files that
265// define or use tables declare the tables using symbols, and record each use
266// with a relocation. This way when the linker combines inputs, it can collate
267// the tables used by the inputs, assigning them distinct table numbers, and
268// renumber all the uses as appropriate. At the same time, the linker has
269// special logic to build the indirect function table if it is needed.
270//
271// However, MVP object files (those that target WebAssembly 1.0, the "minimum
272// viable product" version of WebAssembly) neither write table symbols nor
273// record relocations. These files can have at most one table, the indirect
274// function table used by call_indirect and which is the address space for
275// function pointers. If this table is present, it is always an import. If we
276// have a file with a table import but no table symbols, it is an MVP object
277// file. synthesizeMVPIndirectFunctionTableSymbolIfNeeded serves as a shim when
278// loading these input files, defining the missing symbol to allow the indirect
279// function table to be built.
280//
281// As indirect function table table usage in MVP objects cannot be relocated,
282// the linker must ensure that this table gets assigned index zero.
283void ObjFile::addLegacyIndirectFunctionTableIfNeeded(
284 uint32_t tableSymbolCount) {
285 uint32_t tableCount = wasmObj->getNumImportedTables() + tables.size();
286
287 // If there are symbols for all tables, then all is good.
288 if (tableCount == tableSymbolCount)
289 return;
290
291 // It's possible for an input to define tables and also use the indirect
292 // function table, but forget to compile with -mattr=+call-indirect-overlong
293 // or -mattr=+reference-types. For these newer files, we require symbols for
294 // all tables, and relocations for all of their uses.
295 if (tableSymbolCount != 0) {
296 error(msg: toString(file: this) +
297 ": expected one symbol table entry for each of the " +
298 Twine(tableCount) + " table(s) present, but got " +
299 Twine(tableSymbolCount) + " symbol(s) instead.");
300 return;
301 }
302
303 // An MVP object file can have up to one table import, for the indirect
304 // function table, but will have no table definitions.
305 if (tables.size()) {
306 error(msg: toString(file: this) +
307 ": unexpected table definition(s) without corresponding "
308 "symbol-table entries.");
309 return;
310 }
311
312 // An MVP object file can have only one table import.
313 if (tableCount != 1) {
314 error(msg: toString(file: this) +
315 ": multiple table imports, but no corresponding symbol-table "
316 "entries.");
317 return;
318 }
319
320 const WasmImport *tableImport = nullptr;
321 for (const auto &import : wasmObj->imports()) {
322 if (import.Kind == WASM_EXTERNAL_TABLE) {
323 assert(!tableImport);
324 tableImport = &import;
325 }
326 }
327 assert(tableImport);
328
329 // We can only synthesize a symtab entry for the indirect function table; if
330 // it has an unexpected name or type, assume that it's not actually the
331 // indirect function table.
332 if (tableImport->Field != functionTableName ||
333 tableImport->Table.ElemType != ValType::FUNCREF) {
334 error(msg: toString(file: this) + ": table import " + Twine(tableImport->Field) +
335 " is missing a symbol table entry.");
336 return;
337 }
338
339 WasmSymbolInfo info;
340 info.Name = tableImport->Field;
341 info.Kind = WASM_SYMBOL_TYPE_TABLE;
342 info.ImportModule = tableImport->Module;
343 info.ImportName = tableImport->Field;
344 info.Flags = WASM_SYMBOL_UNDEFINED | WASM_SYMBOL_NO_STRIP;
345 info.ElementIndex = 0;
346 LLVM_DEBUG(dbgs() << "Synthesizing symbol for table import: " << info.Name
347 << "\n");
348 const WasmGlobalType *globalType = nullptr;
349 const WasmSignature *signature = nullptr;
350 auto *wasmSym =
351 make<WasmSymbol>(args&: info, args&: globalType, args: &tableImport->Table, args&: signature);
352 Symbol *sym = createUndefined(sym: *wasmSym, isCalledDirectly: false);
353 // We're only sure it's a TableSymbol if the createUndefined succeeded.
354 if (errorCount())
355 return;
356 symbols.push_back(x: sym);
357 // Because there are no TABLE_NUMBER relocs, we can't compute accurate
358 // liveness info; instead, just mark the symbol as always live.
359 sym->markLive();
360
361 // We assume that this compilation unit has unrelocatable references to
362 // this table.
363 ctx.legacyFunctionTable = true;
364}
365
366static bool shouldMerge(const WasmSection &sec) {
367 if (ctx.arg.optimize == 0)
368 return false;
369 // Sadly we don't have section attributes yet for custom sections, so we
370 // currently go by the name alone.
371 // TODO(sbc): Add ability for wasm sections to carry flags so we don't
372 // need to use names here.
373 // For now, keep in sync with uses of wasm::WASM_SEG_FLAG_STRINGS in
374 // MCObjectFileInfo::initWasmMCObjectFileInfo which creates these custom
375 // sections.
376 return sec.Name == ".debug_str" || sec.Name == ".debug_str.dwo" ||
377 sec.Name == ".debug_line_str";
378}
379
380static bool shouldMerge(const WasmSegment &seg) {
381 // As of now we only support merging strings, and only with single byte
382 // alignment (2^0).
383 if (!(seg.Data.LinkingFlags & WASM_SEG_FLAG_STRINGS) ||
384 (seg.Data.Alignment != 0))
385 return false;
386
387 // On a regular link we don't merge sections if -O0 (default is -O1). This
388 // sometimes makes the linker significantly faster, although the output will
389 // be bigger.
390 if (ctx.arg.optimize == 0)
391 return false;
392
393 // A mergeable section with size 0 is useless because they don't have
394 // any data to merge. A mergeable string section with size 0 can be
395 // argued as invalid because it doesn't end with a null character.
396 // We'll avoid a mess by handling them as if they were non-mergeable.
397 if (seg.Data.Content.size() == 0)
398 return false;
399
400 return true;
401}
402
403void ObjFile::parseLazy() {
404 LLVM_DEBUG(dbgs() << "ObjFile::parseLazy: " << toString(this) << " "
405 << wasmObj.get() << "\n");
406 for (const SymbolRef &sym : wasmObj->symbols()) {
407 const WasmSymbol &wasmSym = wasmObj->getWasmSymbol(Symb: sym.getRawDataRefImpl());
408 if (wasmSym.isUndefined() || wasmSym.isBindingLocal())
409 continue;
410 symtab->addLazy(name: wasmSym.Info.Name, f: this);
411 // addLazy() may trigger this->extract() if an existing symbol is an
412 // undefined symbol. If that happens, this function has served its purpose,
413 // and we can exit from the loop early.
414 if (!lazy)
415 break;
416 }
417}
418
419ObjFile::ObjFile(MemoryBufferRef m, StringRef archiveName, bool lazy)
420 : WasmFileBase(ObjectKind, m) {
421 this->lazy = lazy;
422 this->archiveName = std::string(archiveName);
423
424 // Unless we are processing this as a lazy object file (e.g. part of an
425 // archive file or within `--start-lib`/`--end-lib`, it's eagerly linked, so
426 // mark it live.
427 if (!lazy)
428 markLive();
429}
430
431void SharedFile::parse() {
432 assert(wasmObj->isSharedObject());
433
434 for (const SymbolRef &sym : wasmObj->symbols()) {
435 const WasmSymbol &wasmSym = wasmObj->getWasmSymbol(Symb: sym.getRawDataRefImpl());
436 if (wasmSym.isDefined()) {
437 StringRef name = wasmSym.Info.Name;
438 // Certain shared library exports are known to be DSO-local so we
439 // don't want to add them to the symbol table.
440 // TODO(sbc): Instead of hardcoding these here perhaps we could add
441 // this as extra metadata in the `dylink` section.
442 if (name == "__wasm_apply_data_relocs" || name == "__wasm_call_ctors" ||
443 name.starts_with(Prefix: "__start_") || name.starts_with(Prefix: "__stop_"))
444 continue;
445 uint32_t flags = wasmSym.Info.Flags;
446 Symbol *s;
447 LLVM_DEBUG(dbgs() << "shared symbol: " << name << "\n");
448 switch (wasmSym.Info.Kind) {
449 case WASM_SYMBOL_TYPE_FUNCTION:
450 s = symtab->addSharedFunction(name, flags, file: this, sig: wasmSym.Signature);
451 break;
452 case WASM_SYMBOL_TYPE_DATA:
453 s = symtab->addSharedData(name, flags, file: this);
454 break;
455 case WASM_SYMBOL_TYPE_TAG:
456 s = symtab->addSharedTag(name, flags, file: this, sig: wasmSym.Signature);
457 break;
458 default:
459 continue;
460 }
461 symbols.push_back(x: s);
462 }
463 }
464}
465
466// Returns the alignment for a custom section. This is used to concatenate
467// custom sections with the same name into a single custom section.
468static uint32_t getCustomSectionAlignment(const WasmSection &sec) {
469 // TODO: Add a section attribute for alignment in the linking spec.
470 if (sec.Name == getInstrProfSectionName(IPSK: IPSK_covfun, OF: Triple::Wasm) ||
471 sec.Name == getInstrProfSectionName(IPSK: IPSK_covmap, OF: Triple::Wasm)) {
472 // llvm-cov assumes that coverage metadata sections are 8-byte aligned.
473 return 8;
474 }
475 return 1;
476}
477
478WasmFileBase::WasmFileBase(Kind k, MemoryBufferRef m) : InputFile(k, m) {
479 // Parse a memory buffer as a wasm file.
480 LLVM_DEBUG(dbgs() << "Reading object: " << toString(this) << "\n");
481 std::unique_ptr<Binary> bin = CHECK(createBinary(mb), toString(this));
482
483 auto *obj = dyn_cast<WasmObjectFile>(Val: bin.get());
484 if (!obj)
485 fatal(msg: toString(file: this) + ": not a wasm file");
486
487 bin.release();
488 wasmObj.reset(p: obj);
489
490 checkArch(arch: wasmObj->getArch());
491}
492
493void ObjFile::parse(bool ignoreComdats) {
494 // Parse a memory buffer as a wasm file.
495 LLVM_DEBUG(dbgs() << "ObjFile::parse: " << toString(this) << "\n");
496
497 if (!wasmObj->isRelocatableObject())
498 fatal(msg: toString(file: this) + ": not a relocatable wasm file");
499
500 // Build up a map of function indices to table indices for use when
501 // verifying the existing table index relocations
502 uint32_t totalFunctions =
503 wasmObj->getNumImportedFunctions() + wasmObj->functions().size();
504 tableEntriesRel.resize(new_size: totalFunctions);
505 tableEntries.resize(new_size: totalFunctions);
506 for (const WasmElemSegment &seg : wasmObj->elements()) {
507 int64_t offset;
508 if (seg.Offset.Extended)
509 fatal(msg: toString(file: this) + ": extended init exprs not supported");
510 else if (seg.Offset.Inst.Opcode == WASM_OPCODE_I32_CONST)
511 offset = seg.Offset.Inst.Value.Int32;
512 else if (seg.Offset.Inst.Opcode == WASM_OPCODE_I64_CONST)
513 offset = seg.Offset.Inst.Value.Int64;
514 else
515 fatal(msg: toString(file: this) + ": invalid table elements");
516 for (size_t index = 0; index < seg.Functions.size(); index++) {
517 auto functionIndex = seg.Functions[index];
518 tableEntriesRel[functionIndex] = index;
519 tableEntries[functionIndex] = offset + index;
520 }
521 }
522
523 ArrayRef<StringRef> comdats = wasmObj->linkingData().Comdats;
524 for (StringRef comdat : comdats) {
525 bool isNew = ignoreComdats || symtab->addComdat(name: comdat);
526 keptComdats.push_back(x: isNew);
527 }
528
529 uint32_t sectionIndex = 0;
530
531 // Bool for each symbol, true if called directly. This allows us to implement
532 // a weaker form of signature checking where undefined functions that are not
533 // called directly (i.e. only address taken) don't have to match the defined
534 // function's signature. We cannot do this for directly called functions
535 // because those signatures are checked at validation times.
536 // See https://github.com/llvm/llvm-project/issues/39758
537 std::vector<bool> isCalledDirectly(wasmObj->getNumberOfSymbols(), false);
538 for (const SectionRef &sec : wasmObj->sections()) {
539 const WasmSection &section = wasmObj->getWasmSection(Section: sec);
540 // Wasm objects can have at most one code and one data section.
541 if (section.Type == WASM_SEC_CODE) {
542 assert(!codeSection);
543 codeSection = &section;
544 } else if (section.Type == WASM_SEC_DATA) {
545 assert(!dataSection);
546 dataSection = &section;
547 } else if (section.Type == WASM_SEC_CUSTOM) {
548 InputChunk *customSec;
549 uint32_t alignment = getCustomSectionAlignment(sec: section);
550 if (shouldMerge(sec: section))
551 customSec = make<MergeInputChunk>(args: section, args: this, args&: alignment);
552 else
553 customSec = make<InputSection>(args: section, args: this, args&: alignment);
554 customSec->discarded = isExcludedByComdat(chunk: customSec);
555 customSections.emplace_back(args&: customSec);
556 customSections.back()->setRelocations(section.Relocations);
557 customSectionsByIndex[sectionIndex] = customSections.back();
558 }
559 sectionIndex++;
560 // Scans relocations to determine if a function symbol is called directly.
561 for (const WasmRelocation &reloc : section.Relocations)
562 if (reloc.Type == R_WASM_FUNCTION_INDEX_LEB)
563 isCalledDirectly[reloc.Index] = true;
564 }
565
566 typeMap.resize(new_size: getWasmObj()->types().size());
567 typeIsUsed.resize(new_size: getWasmObj()->types().size(), x: false);
568
569 // Populate `Segments`.
570 for (const WasmSegment &s : wasmObj->dataSegments()) {
571 InputChunk *seg;
572 if (shouldMerge(seg: s))
573 seg = make<MergeInputChunk>(args: s, args: this);
574 else
575 seg = make<InputSegment>(args: s, args: this);
576 seg->discarded = isExcludedByComdat(chunk: seg);
577 // Older object files did not include WASM_SEG_FLAG_TLS and instead
578 // relied on the naming convention. To maintain compat with such objects
579 // we still imply the TLS flag based on the name of the segment.
580 if (!seg->isTLS() &&
581 (seg->name.starts_with(Prefix: ".tdata") || seg->name.starts_with(Prefix: ".tbss")))
582 seg->flags |= WASM_SEG_FLAG_TLS;
583 segments.emplace_back(args&: seg);
584 }
585 setRelocs(chunks: segments, section: dataSection);
586
587 // Populate `Functions`.
588 ArrayRef<WasmFunction> funcs = wasmObj->functions();
589 ArrayRef<WasmSignature> types = wasmObj->types();
590 functions.reserve(n: funcs.size());
591
592 for (auto &f : funcs) {
593 auto *func = make<InputFunction>(args: types[f.SigIndex], args: &f, args: this);
594 func->discarded = isExcludedByComdat(chunk: func);
595 functions.emplace_back(args&: func);
596 }
597 setRelocs(chunks: functions, section: codeSection);
598
599 // Populate `Tables`.
600 for (const WasmTable &t : wasmObj->tables())
601 tables.emplace_back(args: make<InputTable>(args: t, args: this));
602
603 // Populate `Globals`.
604 for (const WasmGlobal &g : wasmObj->globals())
605 globals.emplace_back(args: make<InputGlobal>(args: g, args: this));
606
607 // Populate `Tags`.
608 for (const WasmTag &t : wasmObj->tags())
609 tags.emplace_back(args: make<InputTag>(args: types[t.SigIndex], args: t, args: this));
610
611 // Populate `Symbols` based on the symbols in the object.
612 symbols.reserve(n: wasmObj->getNumberOfSymbols());
613 uint32_t tableSymbolCount = 0;
614 for (const SymbolRef &sym : wasmObj->symbols()) {
615 const WasmSymbol &wasmSym = wasmObj->getWasmSymbol(Symb: sym.getRawDataRefImpl());
616 if (wasmSym.isTypeTable())
617 tableSymbolCount++;
618 if (wasmSym.isDefined()) {
619 // createDefined may fail if the symbol is comdat excluded in which case
620 // we fall back to creating an undefined symbol
621 if (Symbol *d = createDefined(sym: wasmSym)) {
622 symbols.push_back(x: d);
623 continue;
624 }
625 }
626 size_t idx = symbols.size();
627 symbols.push_back(x: createUndefined(sym: wasmSym, isCalledDirectly: isCalledDirectly[idx]));
628 }
629
630 addLegacyIndirectFunctionTableIfNeeded(tableSymbolCount);
631}
632
633bool ObjFile::isExcludedByComdat(const InputChunk *chunk) const {
634 uint32_t c = chunk->getComdat();
635 if (c == UINT32_MAX)
636 return false;
637 return !keptComdats[c];
638}
639
640FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t index) const {
641 return cast<FunctionSymbol>(Val: symbols[index]);
642}
643
644GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t index) const {
645 return cast<GlobalSymbol>(Val: symbols[index]);
646}
647
648TagSymbol *ObjFile::getTagSymbol(uint32_t index) const {
649 return cast<TagSymbol>(Val: symbols[index]);
650}
651
652TableSymbol *ObjFile::getTableSymbol(uint32_t index) const {
653 return cast<TableSymbol>(Val: symbols[index]);
654}
655
656SectionSymbol *ObjFile::getSectionSymbol(uint32_t index) const {
657 return cast<SectionSymbol>(Val: symbols[index]);
658}
659
660DataSymbol *ObjFile::getDataSymbol(uint32_t index) const {
661 return cast<DataSymbol>(Val: symbols[index]);
662}
663
664Symbol *ObjFile::createDefined(const WasmSymbol &sym) {
665 StringRef name = sym.Info.Name;
666 uint32_t flags = sym.Info.Flags;
667
668 switch (sym.Info.Kind) {
669 case WASM_SYMBOL_TYPE_FUNCTION: {
670 InputFunction *func =
671 functions[sym.Info.ElementIndex - wasmObj->getNumImportedFunctions()];
672 if (sym.isBindingLocal())
673 return make<DefinedFunction>(args&: name, args&: flags, args: this, args&: func);
674 if (func->discarded)
675 return nullptr;
676 return symtab->addDefinedFunction(name, flags, file: this, function: func);
677 }
678 case WASM_SYMBOL_TYPE_DATA: {
679 if ((flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_COMMON) {
680 assert(!sym.isBindingLocal());
681 auto size = sym.Info.CommonRef.Size;
682 auto alignment = sym.Info.CommonRef.Alignment;
683 return symtab->addCommon(name, flags, file: this, size, alignment);
684 }
685 InputChunk *seg = segments[sym.Info.DataRef.Segment];
686 auto offset = sym.Info.DataRef.Offset;
687 auto size = sym.Info.DataRef.Size;
688 // Support older (e.g. llvm 13) object files that pre-date the per-symbol
689 // TLS flag, and symbols were assumed to be TLS by being defined in a TLS
690 // segment.
691 if (!(flags & WASM_SYMBOL_TLS) && seg->isTLS())
692 flags |= WASM_SYMBOL_TLS;
693 if (sym.isBindingLocal())
694 return make<DefinedData>(args&: name, args&: flags, args: this, args&: seg, args&: offset, args&: size);
695 if (seg->discarded)
696 return nullptr;
697 return symtab->addDefinedData(name, flags, file: this, segment: seg, address: offset, size);
698 }
699 case WASM_SYMBOL_TYPE_GLOBAL: {
700 InputGlobal *global =
701 globals[sym.Info.ElementIndex - wasmObj->getNumImportedGlobals()];
702 if (sym.isBindingLocal())
703 return make<DefinedGlobal>(args&: name, args&: flags, args: this, args&: global);
704 return symtab->addDefinedGlobal(name, flags, file: this, g: global);
705 }
706 case WASM_SYMBOL_TYPE_SECTION: {
707 InputChunk *section = customSectionsByIndex[sym.Info.ElementIndex];
708 assert(sym.isBindingLocal());
709 // Need to return null if discarded here? data and func only do that when
710 // binding is not local.
711 if (section->discarded)
712 return nullptr;
713 return make<SectionSymbol>(args&: flags, args&: section, args: this);
714 }
715 case WASM_SYMBOL_TYPE_TAG: {
716 InputTag *tag = tags[sym.Info.ElementIndex - wasmObj->getNumImportedTags()];
717 if (sym.isBindingLocal())
718 return make<DefinedTag>(args&: name, args&: flags, args: this, args&: tag);
719 return symtab->addDefinedTag(name, flags, file: this, t: tag);
720 }
721 case WASM_SYMBOL_TYPE_TABLE: {
722 InputTable *table =
723 tables[sym.Info.ElementIndex - wasmObj->getNumImportedTables()];
724 if (sym.isBindingLocal())
725 return make<DefinedTable>(args&: name, args&: flags, args: this, args&: table);
726 return symtab->addDefinedTable(name, flags, file: this, t: table);
727 }
728 }
729 llvm_unreachable("unknown symbol kind");
730}
731
732Symbol *ObjFile::createUndefined(const WasmSymbol &sym, bool isCalledDirectly) {
733 StringRef name = sym.Info.Name;
734 uint32_t flags = sym.Info.Flags | WASM_SYMBOL_UNDEFINED;
735
736 switch (sym.Info.Kind) {
737 case WASM_SYMBOL_TYPE_FUNCTION:
738 if (sym.isBindingLocal())
739 return make<UndefinedFunction>(args&: name, args: sym.Info.ImportName,
740 args: sym.Info.ImportModule, args&: flags, args: this,
741 args: sym.Signature, args&: isCalledDirectly);
742 return symtab->addUndefinedFunction(name, importName: sym.Info.ImportName,
743 importModule: sym.Info.ImportModule, flags, file: this,
744 signature: sym.Signature, isCalledDirectly);
745 case WASM_SYMBOL_TYPE_DATA:
746 if (sym.isBindingLocal())
747 return make<UndefinedData>(args&: name, args&: flags, args: this);
748 return symtab->addUndefinedData(name, flags, file: this);
749 case WASM_SYMBOL_TYPE_GLOBAL:
750 if (sym.isBindingLocal())
751 return make<UndefinedGlobal>(args&: name, args: sym.Info.ImportName,
752 args: sym.Info.ImportModule, args&: flags, args: this,
753 args: sym.GlobalType);
754 return symtab->addUndefinedGlobal(name, importName: sym.Info.ImportName,
755 importModule: sym.Info.ImportModule, flags, file: this,
756 type: sym.GlobalType);
757 case WASM_SYMBOL_TYPE_TABLE:
758 if (sym.isBindingLocal())
759 return make<UndefinedTable>(args&: name, args: sym.Info.ImportName,
760 args: sym.Info.ImportModule, args&: flags, args: this,
761 args: sym.TableType);
762 return symtab->addUndefinedTable(name, importName: sym.Info.ImportName,
763 importModule: sym.Info.ImportModule, flags, file: this,
764 type: sym.TableType);
765 case WASM_SYMBOL_TYPE_TAG:
766 if (sym.isBindingLocal())
767 return make<UndefinedTag>(args&: name, args: sym.Info.ImportName,
768 args: sym.Info.ImportModule, args&: flags, args: this,
769 args: sym.Signature);
770 return symtab->addUndefinedTag(name, importName: sym.Info.ImportName,
771 importModule: sym.Info.ImportModule, flags, file: this,
772 sig: sym.Signature);
773 case WASM_SYMBOL_TYPE_SECTION:
774 llvm_unreachable("section symbols cannot be undefined");
775 }
776 llvm_unreachable("unknown symbol kind");
777}
778
779static StringRef strip(StringRef s) { return s.trim(Char: ' '); }
780
781void StubFile::parse() {
782 bool first = true;
783
784 SmallVector<StringRef> lines;
785 mb.getBuffer().split(A&: lines, Separator: '\n');
786 for (StringRef line : lines) {
787 line = line.trim();
788
789 // File must begin with #STUB
790 if (first) {
791 assert(line == "#STUB");
792 first = false;
793 }
794
795 // Lines starting with # are considered comments
796 if (line.starts_with(Prefix: "#") || !line.size())
797 continue;
798
799 StringRef sym;
800 StringRef rest;
801 std::tie(args&: sym, args&: rest) = line.split(Separator: ':');
802 sym = strip(s: sym);
803 rest = strip(s: rest);
804
805 symbolDependencies[sym] = {};
806
807 while (rest.size()) {
808 StringRef dep;
809 std::tie(args&: dep, args&: rest) = rest.split(Separator: ',');
810 dep = strip(s: dep);
811 symbolDependencies[sym].push_back(x: dep);
812 }
813 }
814}
815
816static uint8_t mapVisibility(GlobalValue::VisibilityTypes gvVisibility) {
817 switch (gvVisibility) {
818 case GlobalValue::DefaultVisibility:
819 return WASM_SYMBOL_VISIBILITY_DEFAULT;
820 case GlobalValue::HiddenVisibility:
821 case GlobalValue::ProtectedVisibility:
822 return WASM_SYMBOL_VISIBILITY_HIDDEN;
823 }
824 llvm_unreachable("unknown visibility");
825}
826
827static Symbol *createBitcodeSymbol(const std::vector<bool> &keptComdats,
828 const lto::InputFile::Symbol &objSym,
829 BitcodeFile &f) {
830 StringRef name = saver().save(S: objSym.getName());
831
832 uint32_t flags = objSym.isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0;
833 flags |= mapVisibility(gvVisibility: objSym.getVisibility());
834
835 int c = objSym.getComdatIndex();
836 bool excludedByComdat = c != -1 && !keptComdats[c];
837
838 if (objSym.isUndefined() || excludedByComdat) {
839 flags |= WASM_SYMBOL_UNDEFINED;
840 if (objSym.isExecutable())
841 return symtab->addUndefinedFunction(name, importName: std::nullopt, importModule: std::nullopt,
842 flags, file: &f, signature: nullptr, isCalledDirectly: true);
843 return symtab->addUndefinedData(name, flags, file: &f);
844 }
845
846 if (objSym.isExecutable())
847 return symtab->addDefinedFunction(name, flags, file: &f, function: nullptr);
848 return symtab->addDefinedData(name, flags, file: &f, segment: nullptr, address: 0, size: 0);
849}
850
851BitcodeFile::BitcodeFile(MemoryBufferRef m, StringRef archiveName,
852 uint64_t offsetInArchive, bool lazy)
853 : InputFile(BitcodeKind, m) {
854 this->lazy = lazy;
855 this->archiveName = std::string(archiveName);
856
857 std::string path = mb.getBufferIdentifier().str();
858 if (ctx.arg.thinLTOIndexOnly)
859 path = replaceThinLTOSuffix(path: mb.getBufferIdentifier());
860
861 // ThinLTO assumes that all MemoryBufferRefs given to it have a unique
862 // name. If two archives define two members with the same name, this
863 // causes a collision which result in only one of the objects being taken
864 // into consideration at LTO time (which very likely causes undefined
865 // symbols later in the link stage). So we append file offset to make
866 // filename unique.
867 StringRef name = archiveName.empty()
868 ? saver().save(S: path)
869 : saver().save(S: archiveName + "(" + path::filename(path) +
870 " at " + utostr(X: offsetInArchive) + ")");
871 MemoryBufferRef mbref(mb.getBuffer(), name);
872
873 obj = check(e: lto::InputFile::create(Object: mbref));
874
875 // If this isn't part of an archive, it's eagerly linked, so mark it live.
876 if (archiveName.empty())
877 markLive();
878}
879
880bool BitcodeFile::doneLTO = false;
881
882void BitcodeFile::parseLazy() {
883 for (auto [i, irSym] : llvm::enumerate(First: obj->symbols())) {
884 if (irSym.isUndefined())
885 continue;
886 StringRef name = saver().save(S: irSym.getName());
887 symtab->addLazy(name, f: this);
888 // addLazy() may trigger this->extract() if an existing symbol is an
889 // undefined symbol. If that happens, this function has served its purpose,
890 // and we can exit from the loop early.
891 if (!lazy)
892 break;
893 }
894}
895
896void BitcodeFile::parse(StringRef symName) {
897 if (doneLTO) {
898 error(msg: toString(file: this) + ": attempt to add bitcode file after LTO (" +
899 symName + ")");
900 return;
901 }
902
903 Triple t(obj->getTargetTriple());
904 if (!t.isWasm()) {
905 error(msg: toString(file: this) + ": machine type must be wasm32 or wasm64");
906 return;
907 }
908 checkArch(arch: t.getArch());
909 std::vector<bool> keptComdats;
910 // TODO Support nodeduplicate
911 // https://github.com/llvm/llvm-project/issues/49875
912 for (std::pair<StringRef, Comdat::SelectionKind> s : obj->getComdatTable())
913 keptComdats.push_back(x: symtab->addComdat(name: s.first));
914
915 for (const lto::InputFile::Symbol &objSym : obj->symbols())
916 symbols.push_back(x: createBitcodeSymbol(keptComdats, objSym, f&: *this));
917}
918
919} // namespace wasm
920} // namespace lld
921