1 //===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===// 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 Wasm object file writer information. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ADT/STLExtras.h" 14 #include "llvm/ADT/SmallPtrSet.h" 15 #include "llvm/BinaryFormat/Wasm.h" 16 #include "llvm/BinaryFormat/WasmTraits.h" 17 #include "llvm/Config/llvm-config.h" 18 #include "llvm/MC/MCAsmBackend.h" 19 #include "llvm/MC/MCAsmLayout.h" 20 #include "llvm/MC/MCAssembler.h" 21 #include "llvm/MC/MCContext.h" 22 #include "llvm/MC/MCExpr.h" 23 #include "llvm/MC/MCFixupKindInfo.h" 24 #include "llvm/MC/MCObjectWriter.h" 25 #include "llvm/MC/MCSectionWasm.h" 26 #include "llvm/MC/MCSymbolWasm.h" 27 #include "llvm/MC/MCValue.h" 28 #include "llvm/MC/MCWasmObjectWriter.h" 29 #include "llvm/Support/Casting.h" 30 #include "llvm/Support/Debug.h" 31 #include "llvm/Support/EndianStream.h" 32 #include "llvm/Support/ErrorHandling.h" 33 #include "llvm/Support/LEB128.h" 34 #include "llvm/Support/StringSaver.h" 35 #include <vector> 36 37 using namespace llvm; 38 39 #define DEBUG_TYPE "mc" 40 41 namespace { 42 43 // When we create the indirect function table we start at 1, so that there is 44 // and empty slot at 0 and therefore calling a null function pointer will trap. 45 static const uint32_t InitialTableOffset = 1; 46 47 // For patching purposes, we need to remember where each section starts, both 48 // for patching up the section size field, and for patching up references to 49 // locations within the section. 50 struct SectionBookkeeping { 51 // Where the size of the section is written. 52 uint64_t SizeOffset; 53 // Where the section header ends (without custom section name). 54 uint64_t PayloadOffset; 55 // Where the contents of the section starts. 56 uint64_t ContentsOffset; 57 uint32_t Index; 58 }; 59 60 // A wasm data segment. A wasm binary contains only a single data section 61 // but that can contain many segments, each with their own virtual location 62 // in memory. Each MCSection data created by llvm is modeled as its own 63 // wasm data segment. 64 struct WasmDataSegment { 65 MCSectionWasm *Section; 66 StringRef Name; 67 uint32_t InitFlags; 68 uint64_t Offset; 69 uint32_t Alignment; 70 uint32_t LinkingFlags; 71 SmallVector<char, 4> Data; 72 }; 73 74 // A wasm function to be written into the function section. 75 struct WasmFunction { 76 uint32_t SigIndex; 77 const MCSymbolWasm *Sym; 78 }; 79 80 // A wasm global to be written into the global section. 81 struct WasmGlobal { 82 wasm::WasmGlobalType Type; 83 uint64_t InitialValue; 84 }; 85 86 // Information about a single item which is part of a COMDAT. For each data 87 // segment or function which is in the COMDAT, there is a corresponding 88 // WasmComdatEntry. 89 struct WasmComdatEntry { 90 unsigned Kind; 91 uint32_t Index; 92 }; 93 94 // Information about a single relocation. 95 struct WasmRelocationEntry { 96 uint64_t Offset; // Where is the relocation. 97 const MCSymbolWasm *Symbol; // The symbol to relocate with. 98 int64_t Addend; // A value to add to the symbol. 99 unsigned Type; // The type of the relocation. 100 const MCSectionWasm *FixupSection; // The section the relocation is targeting. 101 102 WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol, 103 int64_t Addend, unsigned Type, 104 const MCSectionWasm *FixupSection) 105 : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type), 106 FixupSection(FixupSection) {} 107 108 bool hasAddend() const { return wasm::relocTypeHasAddend(Type); } 109 110 void print(raw_ostream &Out) const { 111 Out << wasm::relocTypetoString(Type) << " Off=" << Offset 112 << ", Sym=" << *Symbol << ", Addend=" << Addend 113 << ", FixupSection=" << FixupSection->getName(); 114 } 115 116 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 117 LLVM_DUMP_METHOD void dump() const { print(dbgs()); } 118 #endif 119 }; 120 121 static const uint32_t InvalidIndex = -1; 122 123 struct WasmCustomSection { 124 125 StringRef Name; 126 MCSectionWasm *Section; 127 128 uint32_t OutputContentsOffset = 0; 129 uint32_t OutputIndex = InvalidIndex; 130 131 WasmCustomSection(StringRef Name, MCSectionWasm *Section) 132 : Name(Name), Section(Section) {} 133 }; 134 135 #if !defined(NDEBUG) 136 raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) { 137 Rel.print(OS); 138 return OS; 139 } 140 #endif 141 142 // Write X as an (unsigned) LEB value at offset Offset in Stream, padded 143 // to allow patching. 144 template <int W> 145 void writePatchableLEB(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) { 146 uint8_t Buffer[W]; 147 unsigned SizeLen = encodeULEB128(X, Buffer, W); 148 assert(SizeLen == W); 149 Stream.pwrite((char *)Buffer, SizeLen, Offset); 150 } 151 152 // Write X as an signed LEB value at offset Offset in Stream, padded 153 // to allow patching. 154 template <int W> 155 void writePatchableSLEB(raw_pwrite_stream &Stream, int64_t X, uint64_t Offset) { 156 uint8_t Buffer[W]; 157 unsigned SizeLen = encodeSLEB128(X, Buffer, W); 158 assert(SizeLen == W); 159 Stream.pwrite((char *)Buffer, SizeLen, Offset); 160 } 161 162 // Write X as a plain integer value at offset Offset in Stream. 163 static void patchI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) { 164 uint8_t Buffer[4]; 165 support::endian::write32le(Buffer, X); 166 Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset); 167 } 168 169 static void patchI64(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) { 170 uint8_t Buffer[8]; 171 support::endian::write64le(Buffer, X); 172 Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset); 173 } 174 175 bool isDwoSection(const MCSection &Sec) { 176 return Sec.getName().endswith(".dwo"); 177 } 178 179 class WasmObjectWriter : public MCObjectWriter { 180 support::endian::Writer *W; 181 182 /// The target specific Wasm writer instance. 183 std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter; 184 185 // Relocations for fixing up references in the code section. 186 std::vector<WasmRelocationEntry> CodeRelocations; 187 // Relocations for fixing up references in the data section. 188 std::vector<WasmRelocationEntry> DataRelocations; 189 190 // Index values to use for fixing up call_indirect type indices. 191 // Maps function symbols to the index of the type of the function 192 DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices; 193 // Maps function symbols to the table element index space. Used 194 // for TABLE_INDEX relocation types (i.e. address taken functions). 195 DenseMap<const MCSymbolWasm *, uint32_t> TableIndices; 196 // Maps function/global/table symbols to the 197 // function/global/table/tag/section index space. 198 DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices; 199 DenseMap<const MCSymbolWasm *, uint32_t> GOTIndices; 200 // Maps data symbols to the Wasm segment and offset/size with the segment. 201 DenseMap<const MCSymbolWasm *, wasm::WasmDataReference> DataLocations; 202 203 // Stores output data (index, relocations, content offset) for custom 204 // section. 205 std::vector<WasmCustomSection> CustomSections; 206 std::unique_ptr<WasmCustomSection> ProducersSection; 207 std::unique_ptr<WasmCustomSection> TargetFeaturesSection; 208 // Relocations for fixing up references in the custom sections. 209 DenseMap<const MCSectionWasm *, std::vector<WasmRelocationEntry>> 210 CustomSectionsRelocations; 211 212 // Map from section to defining function symbol. 213 DenseMap<const MCSection *, const MCSymbol *> SectionFunctions; 214 215 DenseMap<wasm::WasmSignature, uint32_t> SignatureIndices; 216 SmallVector<wasm::WasmSignature, 4> Signatures; 217 SmallVector<WasmDataSegment, 4> DataSegments; 218 unsigned NumFunctionImports = 0; 219 unsigned NumGlobalImports = 0; 220 unsigned NumTableImports = 0; 221 unsigned NumTagImports = 0; 222 uint32_t SectionCount = 0; 223 224 enum class DwoMode { 225 AllSections, 226 NonDwoOnly, 227 DwoOnly, 228 }; 229 bool IsSplitDwarf = false; 230 raw_pwrite_stream *OS = nullptr; 231 raw_pwrite_stream *DwoOS = nullptr; 232 233 // TargetObjectWriter wranppers. 234 bool is64Bit() const { return TargetObjectWriter->is64Bit(); } 235 bool isEmscripten() const { return TargetObjectWriter->isEmscripten(); } 236 237 void startSection(SectionBookkeeping &Section, unsigned SectionId); 238 void startCustomSection(SectionBookkeeping &Section, StringRef Name); 239 void endSection(SectionBookkeeping &Section); 240 241 public: 242 WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, 243 raw_pwrite_stream &OS_) 244 : TargetObjectWriter(std::move(MOTW)), OS(&OS_) {} 245 246 WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, 247 raw_pwrite_stream &OS_, raw_pwrite_stream &DwoOS_) 248 : TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(true), OS(&OS_), 249 DwoOS(&DwoOS_) {} 250 251 private: 252 void reset() override { 253 CodeRelocations.clear(); 254 DataRelocations.clear(); 255 TypeIndices.clear(); 256 WasmIndices.clear(); 257 GOTIndices.clear(); 258 TableIndices.clear(); 259 DataLocations.clear(); 260 CustomSections.clear(); 261 ProducersSection.reset(); 262 TargetFeaturesSection.reset(); 263 CustomSectionsRelocations.clear(); 264 SignatureIndices.clear(); 265 Signatures.clear(); 266 DataSegments.clear(); 267 SectionFunctions.clear(); 268 NumFunctionImports = 0; 269 NumGlobalImports = 0; 270 NumTableImports = 0; 271 MCObjectWriter::reset(); 272 } 273 274 void writeHeader(const MCAssembler &Asm); 275 276 void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, 277 const MCFragment *Fragment, const MCFixup &Fixup, 278 MCValue Target, uint64_t &FixedValue) override; 279 280 void executePostLayoutBinding(MCAssembler &Asm, 281 const MCAsmLayout &Layout) override; 282 void prepareImports(SmallVectorImpl<wasm::WasmImport> &Imports, 283 MCAssembler &Asm, const MCAsmLayout &Layout); 284 uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; 285 286 uint64_t writeOneObject(MCAssembler &Asm, const MCAsmLayout &Layout, 287 DwoMode Mode); 288 289 void writeString(const StringRef Str) { 290 encodeULEB128(Str.size(), W->OS); 291 W->OS << Str; 292 } 293 294 void writeStringWithAlignment(const StringRef Str, unsigned Alignment); 295 296 void writeI32(int32_t val) { 297 char Buffer[4]; 298 support::endian::write32le(Buffer, val); 299 W->OS.write(Buffer, sizeof(Buffer)); 300 } 301 302 void writeI64(int64_t val) { 303 char Buffer[8]; 304 support::endian::write64le(Buffer, val); 305 W->OS.write(Buffer, sizeof(Buffer)); 306 } 307 308 void writeValueType(wasm::ValType Ty) { W->OS << static_cast<char>(Ty); } 309 310 void writeTypeSection(ArrayRef<wasm::WasmSignature> Signatures); 311 void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint64_t DataSize, 312 uint32_t NumElements); 313 void writeFunctionSection(ArrayRef<WasmFunction> Functions); 314 void writeExportSection(ArrayRef<wasm::WasmExport> Exports); 315 void writeElemSection(const MCSymbolWasm *IndirectFunctionTable, 316 ArrayRef<uint32_t> TableElems); 317 void writeDataCountSection(); 318 uint32_t writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout, 319 ArrayRef<WasmFunction> Functions); 320 uint32_t writeDataSection(const MCAsmLayout &Layout); 321 void writeTagSection(ArrayRef<uint32_t> TagTypes); 322 void writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals); 323 void writeTableSection(ArrayRef<wasm::WasmTable> Tables); 324 void writeRelocSection(uint32_t SectionIndex, StringRef Name, 325 std::vector<WasmRelocationEntry> &Relocations); 326 void writeLinkingMetaDataSection( 327 ArrayRef<wasm::WasmSymbolInfo> SymbolInfos, 328 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs, 329 const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats); 330 void writeCustomSection(WasmCustomSection &CustomSection, 331 const MCAssembler &Asm, const MCAsmLayout &Layout); 332 void writeCustomRelocSections(); 333 334 uint64_t getProvisionalValue(const WasmRelocationEntry &RelEntry, 335 const MCAsmLayout &Layout); 336 void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations, 337 uint64_t ContentsOffset, const MCAsmLayout &Layout); 338 339 uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry); 340 uint32_t getFunctionType(const MCSymbolWasm &Symbol); 341 uint32_t getTagType(const MCSymbolWasm &Symbol); 342 void registerFunctionType(const MCSymbolWasm &Symbol); 343 void registerTagType(const MCSymbolWasm &Symbol); 344 }; 345 346 } // end anonymous namespace 347 348 // Write out a section header and a patchable section size field. 349 void WasmObjectWriter::startSection(SectionBookkeeping &Section, 350 unsigned SectionId) { 351 LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n"); 352 W->OS << char(SectionId); 353 354 Section.SizeOffset = W->OS.tell(); 355 356 // The section size. We don't know the size yet, so reserve enough space 357 // for any 32-bit value; we'll patch it later. 358 encodeULEB128(0, W->OS, 5); 359 360 // The position where the section starts, for measuring its size. 361 Section.ContentsOffset = W->OS.tell(); 362 Section.PayloadOffset = W->OS.tell(); 363 Section.Index = SectionCount++; 364 } 365 366 // Write a string with extra paddings for trailing alignment 367 // TODO: support alignment at asm and llvm level? 368 void WasmObjectWriter::writeStringWithAlignment(const StringRef Str, 369 unsigned Alignment) { 370 371 // Calculate the encoded size of str length and add pads based on it and 372 // alignment. 373 raw_null_ostream NullOS; 374 uint64_t StrSizeLength = encodeULEB128(Str.size(), NullOS); 375 uint64_t Offset = W->OS.tell() + StrSizeLength + Str.size(); 376 uint64_t Paddings = offsetToAlignment(Offset, Align(Alignment)); 377 Offset += Paddings; 378 379 // LEB128 greater than 5 bytes is invalid 380 assert((StrSizeLength + Paddings) <= 5 && "too long string to align"); 381 382 encodeSLEB128(Str.size(), W->OS, StrSizeLength + Paddings); 383 W->OS << Str; 384 385 assert(W->OS.tell() == Offset && "invalid padding"); 386 } 387 388 void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section, 389 StringRef Name) { 390 LLVM_DEBUG(dbgs() << "startCustomSection " << Name << "\n"); 391 startSection(Section, wasm::WASM_SEC_CUSTOM); 392 393 // The position where the section header ends, for measuring its size. 394 Section.PayloadOffset = W->OS.tell(); 395 396 // Custom sections in wasm also have a string identifier. 397 if (Name != "__clangast") { 398 writeString(Name); 399 } else { 400 // The on-disk hashtable in clangast needs to be aligned by 4 bytes. 401 writeStringWithAlignment(Name, 4); 402 } 403 404 // The position where the custom section starts. 405 Section.ContentsOffset = W->OS.tell(); 406 } 407 408 // Now that the section is complete and we know how big it is, patch up the 409 // section size field at the start of the section. 410 void WasmObjectWriter::endSection(SectionBookkeeping &Section) { 411 uint64_t Size = W->OS.tell(); 412 // /dev/null doesn't support seek/tell and can report offset of 0. 413 // Simply skip this patching in that case. 414 if (!Size) 415 return; 416 417 Size -= Section.PayloadOffset; 418 if (uint32_t(Size) != Size) 419 report_fatal_error("section size does not fit in a uint32_t"); 420 421 LLVM_DEBUG(dbgs() << "endSection size=" << Size << "\n"); 422 423 // Write the final section size to the payload_len field, which follows 424 // the section id byte. 425 writePatchableLEB<5>(static_cast<raw_pwrite_stream &>(W->OS), Size, 426 Section.SizeOffset); 427 } 428 429 // Emit the Wasm header. 430 void WasmObjectWriter::writeHeader(const MCAssembler &Asm) { 431 W->OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic)); 432 W->write<uint32_t>(wasm::WasmVersion); 433 } 434 435 void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm, 436 const MCAsmLayout &Layout) { 437 // Some compilation units require the indirect function table to be present 438 // but don't explicitly reference it. This is the case for call_indirect 439 // without the reference-types feature, and also function bitcasts in all 440 // cases. In those cases the __indirect_function_table has the 441 // WASM_SYMBOL_NO_STRIP attribute. Here we make sure this symbol makes it to 442 // the assembler, if needed. 443 if (auto *Sym = Asm.getContext().lookupSymbol("__indirect_function_table")) { 444 const auto *WasmSym = static_cast<const MCSymbolWasm *>(Sym); 445 if (WasmSym->isNoStrip()) 446 Asm.registerSymbol(*Sym); 447 } 448 449 // Build a map of sections to the function that defines them, for use 450 // in recordRelocation. 451 for (const MCSymbol &S : Asm.symbols()) { 452 const auto &WS = static_cast<const MCSymbolWasm &>(S); 453 if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) { 454 const auto &Sec = static_cast<const MCSectionWasm &>(S.getSection()); 455 auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S)); 456 if (!Pair.second) 457 report_fatal_error("section already has a defining function: " + 458 Sec.getName()); 459 } 460 } 461 } 462 463 void WasmObjectWriter::recordRelocation(MCAssembler &Asm, 464 const MCAsmLayout &Layout, 465 const MCFragment *Fragment, 466 const MCFixup &Fixup, MCValue Target, 467 uint64_t &FixedValue) { 468 // The WebAssembly backend should never generate FKF_IsPCRel fixups 469 assert(!(Asm.getBackend().getFixupKindInfo(Fixup.getKind()).Flags & 470 MCFixupKindInfo::FKF_IsPCRel)); 471 472 const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent()); 473 uint64_t C = Target.getConstant(); 474 uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); 475 MCContext &Ctx = Asm.getContext(); 476 bool IsLocRel = false; 477 478 if (const MCSymbolRefExpr *RefB = Target.getSymB()) { 479 480 const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol()); 481 482 if (FixupSection.getKind().isText()) { 483 Ctx.reportError(Fixup.getLoc(), 484 Twine("symbol '") + SymB.getName() + 485 "' unsupported subtraction expression used in " 486 "relocation in code section."); 487 return; 488 } 489 490 if (SymB.isUndefined()) { 491 Ctx.reportError(Fixup.getLoc(), 492 Twine("symbol '") + SymB.getName() + 493 "' can not be undefined in a subtraction expression"); 494 return; 495 } 496 const MCSection &SecB = SymB.getSection(); 497 if (&SecB != &FixupSection) { 498 Ctx.reportError(Fixup.getLoc(), 499 Twine("symbol '") + SymB.getName() + 500 "' can not be placed in a different section"); 501 return; 502 } 503 IsLocRel = true; 504 C += FixupOffset - Layout.getSymbolOffset(SymB); 505 } 506 507 // We either rejected the fixup or folded B into C at this point. 508 const MCSymbolRefExpr *RefA = Target.getSymA(); 509 const auto *SymA = cast<MCSymbolWasm>(&RefA->getSymbol()); 510 511 // The .init_array isn't translated as data, so don't do relocations in it. 512 if (FixupSection.getName().startswith(".init_array")) { 513 SymA->setUsedInInitArray(); 514 return; 515 } 516 517 if (SymA->isVariable()) { 518 const MCExpr *Expr = SymA->getVariableValue(); 519 if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) 520 if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) 521 llvm_unreachable("weakref used in reloc not yet implemented"); 522 } 523 524 // Put any constant offset in an addend. Offsets can be negative, and 525 // LLVM expects wrapping, in contrast to wasm's immediates which can't 526 // be negative and don't wrap. 527 FixedValue = 0; 528 529 unsigned Type = 530 TargetObjectWriter->getRelocType(Target, Fixup, FixupSection, IsLocRel); 531 532 // Absolute offset within a section or a function. 533 // Currently only supported for for metadata sections. 534 // See: test/MC/WebAssembly/blockaddress.ll 535 if ((Type == wasm::R_WASM_FUNCTION_OFFSET_I32 || 536 Type == wasm::R_WASM_FUNCTION_OFFSET_I64 || 537 Type == wasm::R_WASM_SECTION_OFFSET_I32) && 538 SymA->isDefined()) { 539 // SymA can be a temp data symbol that represents a function (in which case 540 // it needs to be replaced by the section symbol), [XXX and it apparently 541 // later gets changed again to a func symbol?] or it can be a real 542 // function symbol, in which case it can be left as-is. 543 544 if (!FixupSection.getKind().isMetadata()) 545 report_fatal_error("relocations for function or section offsets are " 546 "only supported in metadata sections"); 547 548 const MCSymbol *SectionSymbol = nullptr; 549 const MCSection &SecA = SymA->getSection(); 550 if (SecA.getKind().isText()) { 551 auto SecSymIt = SectionFunctions.find(&SecA); 552 if (SecSymIt == SectionFunctions.end()) 553 report_fatal_error("section doesn\'t have defining symbol"); 554 SectionSymbol = SecSymIt->second; 555 } else { 556 SectionSymbol = SecA.getBeginSymbol(); 557 } 558 if (!SectionSymbol) 559 report_fatal_error("section symbol is required for relocation"); 560 561 C += Layout.getSymbolOffset(*SymA); 562 SymA = cast<MCSymbolWasm>(SectionSymbol); 563 } 564 565 if (Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB || 566 Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64 || 567 Type == wasm::R_WASM_TABLE_INDEX_SLEB || 568 Type == wasm::R_WASM_TABLE_INDEX_SLEB64 || 569 Type == wasm::R_WASM_TABLE_INDEX_I32 || 570 Type == wasm::R_WASM_TABLE_INDEX_I64) { 571 // TABLE_INDEX relocs implicitly use the default indirect function table. 572 // We require the function table to have already been defined. 573 auto TableName = "__indirect_function_table"; 574 MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(TableName)); 575 if (!Sym) { 576 report_fatal_error("missing indirect function table symbol"); 577 } else { 578 if (!Sym->isFunctionTable()) 579 report_fatal_error("__indirect_function_table symbol has wrong type"); 580 // Ensure that __indirect_function_table reaches the output. 581 Sym->setNoStrip(); 582 Asm.registerSymbol(*Sym); 583 } 584 } 585 586 // Relocation other than R_WASM_TYPE_INDEX_LEB are required to be 587 // against a named symbol. 588 if (Type != wasm::R_WASM_TYPE_INDEX_LEB) { 589 if (SymA->getName().empty()) 590 report_fatal_error("relocations against un-named temporaries are not yet " 591 "supported by wasm"); 592 593 SymA->setUsedInReloc(); 594 } 595 596 switch (RefA->getKind()) { 597 case MCSymbolRefExpr::VK_GOT: 598 case MCSymbolRefExpr::VK_WASM_GOT_TLS: 599 SymA->setUsedInGOT(); 600 break; 601 default: 602 break; 603 } 604 605 WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection); 606 LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n"); 607 608 if (FixupSection.isWasmData()) { 609 DataRelocations.push_back(Rec); 610 } else if (FixupSection.getKind().isText()) { 611 CodeRelocations.push_back(Rec); 612 } else if (FixupSection.getKind().isMetadata()) { 613 CustomSectionsRelocations[&FixupSection].push_back(Rec); 614 } else { 615 llvm_unreachable("unexpected section type"); 616 } 617 } 618 619 // Compute a value to write into the code at the location covered 620 // by RelEntry. This value isn't used by the static linker; it just serves 621 // to make the object format more readable and more likely to be directly 622 // useable. 623 uint64_t 624 WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry, 625 const MCAsmLayout &Layout) { 626 if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB || 627 RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) && 628 !RelEntry.Symbol->isGlobal()) { 629 assert(GOTIndices.count(RelEntry.Symbol) > 0 && "symbol not found in GOT index space"); 630 return GOTIndices[RelEntry.Symbol]; 631 } 632 633 switch (RelEntry.Type) { 634 case wasm::R_WASM_TABLE_INDEX_REL_SLEB: 635 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64: 636 case wasm::R_WASM_TABLE_INDEX_SLEB: 637 case wasm::R_WASM_TABLE_INDEX_SLEB64: 638 case wasm::R_WASM_TABLE_INDEX_I32: 639 case wasm::R_WASM_TABLE_INDEX_I64: { 640 // Provisional value is table address of the resolved symbol itself 641 const MCSymbolWasm *Base = 642 cast<MCSymbolWasm>(Layout.getBaseSymbol(*RelEntry.Symbol)); 643 assert(Base->isFunction()); 644 if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB || 645 RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64) 646 return TableIndices[Base] - InitialTableOffset; 647 else 648 return TableIndices[Base]; 649 } 650 case wasm::R_WASM_TYPE_INDEX_LEB: 651 // Provisional value is same as the index 652 return getRelocationIndexValue(RelEntry); 653 case wasm::R_WASM_FUNCTION_INDEX_LEB: 654 case wasm::R_WASM_GLOBAL_INDEX_LEB: 655 case wasm::R_WASM_GLOBAL_INDEX_I32: 656 case wasm::R_WASM_TAG_INDEX_LEB: 657 case wasm::R_WASM_TABLE_NUMBER_LEB: 658 // Provisional value is function/global/tag Wasm index 659 assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space"); 660 return WasmIndices[RelEntry.Symbol]; 661 case wasm::R_WASM_FUNCTION_OFFSET_I32: 662 case wasm::R_WASM_FUNCTION_OFFSET_I64: 663 case wasm::R_WASM_SECTION_OFFSET_I32: { 664 if (!RelEntry.Symbol->isDefined()) 665 return 0; 666 const auto &Section = 667 static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection()); 668 return Section.getSectionOffset() + RelEntry.Addend; 669 } 670 case wasm::R_WASM_MEMORY_ADDR_LEB: 671 case wasm::R_WASM_MEMORY_ADDR_LEB64: 672 case wasm::R_WASM_MEMORY_ADDR_SLEB: 673 case wasm::R_WASM_MEMORY_ADDR_SLEB64: 674 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB: 675 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64: 676 case wasm::R_WASM_MEMORY_ADDR_I32: 677 case wasm::R_WASM_MEMORY_ADDR_I64: 678 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: 679 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64: 680 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: { 681 // Provisional value is address of the global plus the offset 682 // For undefined symbols, use zero 683 if (!RelEntry.Symbol->isDefined()) 684 return 0; 685 const wasm::WasmDataReference &SymRef = DataLocations[RelEntry.Symbol]; 686 const WasmDataSegment &Segment = DataSegments[SymRef.Segment]; 687 // Ignore overflow. LLVM allows address arithmetic to silently wrap. 688 return Segment.Offset + SymRef.Offset + RelEntry.Addend; 689 } 690 default: 691 llvm_unreachable("invalid relocation type"); 692 } 693 } 694 695 static void addData(SmallVectorImpl<char> &DataBytes, 696 MCSectionWasm &DataSection) { 697 LLVM_DEBUG(errs() << "addData: " << DataSection.getName() << "\n"); 698 699 DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment())); 700 701 for (const MCFragment &Frag : DataSection) { 702 if (Frag.hasInstructions()) 703 report_fatal_error("only data supported in data sections"); 704 705 if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) { 706 if (Align->getValueSize() != 1) 707 report_fatal_error("only byte values supported for alignment"); 708 // If nops are requested, use zeros, as this is the data section. 709 uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue(); 710 uint64_t Size = 711 std::min<uint64_t>(alignTo(DataBytes.size(), Align->getAlignment()), 712 DataBytes.size() + Align->getMaxBytesToEmit()); 713 DataBytes.resize(Size, Value); 714 } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) { 715 int64_t NumValues; 716 if (!Fill->getNumValues().evaluateAsAbsolute(NumValues)) 717 llvm_unreachable("The fill should be an assembler constant"); 718 DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues, 719 Fill->getValue()); 720 } else if (auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) { 721 const SmallVectorImpl<char> &Contents = LEB->getContents(); 722 llvm::append_range(DataBytes, Contents); 723 } else { 724 const auto &DataFrag = cast<MCDataFragment>(Frag); 725 const SmallVectorImpl<char> &Contents = DataFrag.getContents(); 726 llvm::append_range(DataBytes, Contents); 727 } 728 } 729 730 LLVM_DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n"); 731 } 732 733 uint32_t 734 WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) { 735 if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) { 736 if (!TypeIndices.count(RelEntry.Symbol)) 737 report_fatal_error("symbol not found in type index space: " + 738 RelEntry.Symbol->getName()); 739 return TypeIndices[RelEntry.Symbol]; 740 } 741 742 return RelEntry.Symbol->getIndex(); 743 } 744 745 // Apply the portions of the relocation records that we can handle ourselves 746 // directly. 747 void WasmObjectWriter::applyRelocations( 748 ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset, 749 const MCAsmLayout &Layout) { 750 auto &Stream = static_cast<raw_pwrite_stream &>(W->OS); 751 for (const WasmRelocationEntry &RelEntry : Relocations) { 752 uint64_t Offset = ContentsOffset + 753 RelEntry.FixupSection->getSectionOffset() + 754 RelEntry.Offset; 755 756 LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n"); 757 auto Value = getProvisionalValue(RelEntry, Layout); 758 759 switch (RelEntry.Type) { 760 case wasm::R_WASM_FUNCTION_INDEX_LEB: 761 case wasm::R_WASM_TYPE_INDEX_LEB: 762 case wasm::R_WASM_GLOBAL_INDEX_LEB: 763 case wasm::R_WASM_MEMORY_ADDR_LEB: 764 case wasm::R_WASM_TAG_INDEX_LEB: 765 case wasm::R_WASM_TABLE_NUMBER_LEB: 766 writePatchableLEB<5>(Stream, Value, Offset); 767 break; 768 case wasm::R_WASM_MEMORY_ADDR_LEB64: 769 writePatchableLEB<10>(Stream, Value, Offset); 770 break; 771 case wasm::R_WASM_TABLE_INDEX_I32: 772 case wasm::R_WASM_MEMORY_ADDR_I32: 773 case wasm::R_WASM_FUNCTION_OFFSET_I32: 774 case wasm::R_WASM_SECTION_OFFSET_I32: 775 case wasm::R_WASM_GLOBAL_INDEX_I32: 776 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: 777 patchI32(Stream, Value, Offset); 778 break; 779 case wasm::R_WASM_TABLE_INDEX_I64: 780 case wasm::R_WASM_MEMORY_ADDR_I64: 781 case wasm::R_WASM_FUNCTION_OFFSET_I64: 782 patchI64(Stream, Value, Offset); 783 break; 784 case wasm::R_WASM_TABLE_INDEX_SLEB: 785 case wasm::R_WASM_TABLE_INDEX_REL_SLEB: 786 case wasm::R_WASM_MEMORY_ADDR_SLEB: 787 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB: 788 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: 789 writePatchableSLEB<5>(Stream, Value, Offset); 790 break; 791 case wasm::R_WASM_TABLE_INDEX_SLEB64: 792 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64: 793 case wasm::R_WASM_MEMORY_ADDR_SLEB64: 794 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64: 795 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64: 796 writePatchableSLEB<10>(Stream, Value, Offset); 797 break; 798 default: 799 llvm_unreachable("invalid relocation type"); 800 } 801 } 802 } 803 804 void WasmObjectWriter::writeTypeSection( 805 ArrayRef<wasm::WasmSignature> Signatures) { 806 if (Signatures.empty()) 807 return; 808 809 SectionBookkeeping Section; 810 startSection(Section, wasm::WASM_SEC_TYPE); 811 812 encodeULEB128(Signatures.size(), W->OS); 813 814 for (const wasm::WasmSignature &Sig : Signatures) { 815 W->OS << char(wasm::WASM_TYPE_FUNC); 816 encodeULEB128(Sig.Params.size(), W->OS); 817 for (wasm::ValType Ty : Sig.Params) 818 writeValueType(Ty); 819 encodeULEB128(Sig.Returns.size(), W->OS); 820 for (wasm::ValType Ty : Sig.Returns) 821 writeValueType(Ty); 822 } 823 824 endSection(Section); 825 } 826 827 void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports, 828 uint64_t DataSize, 829 uint32_t NumElements) { 830 if (Imports.empty()) 831 return; 832 833 uint64_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize; 834 835 SectionBookkeeping Section; 836 startSection(Section, wasm::WASM_SEC_IMPORT); 837 838 encodeULEB128(Imports.size(), W->OS); 839 for (const wasm::WasmImport &Import : Imports) { 840 writeString(Import.Module); 841 writeString(Import.Field); 842 W->OS << char(Import.Kind); 843 844 switch (Import.Kind) { 845 case wasm::WASM_EXTERNAL_FUNCTION: 846 encodeULEB128(Import.SigIndex, W->OS); 847 break; 848 case wasm::WASM_EXTERNAL_GLOBAL: 849 W->OS << char(Import.Global.Type); 850 W->OS << char(Import.Global.Mutable ? 1 : 0); 851 break; 852 case wasm::WASM_EXTERNAL_MEMORY: 853 encodeULEB128(Import.Memory.Flags, W->OS); 854 encodeULEB128(NumPages, W->OS); // initial 855 break; 856 case wasm::WASM_EXTERNAL_TABLE: 857 W->OS << char(Import.Table.ElemType); 858 encodeULEB128(0, W->OS); // flags 859 encodeULEB128(NumElements, W->OS); // initial 860 break; 861 case wasm::WASM_EXTERNAL_TAG: 862 W->OS << char(0); // Reserved 'attribute' field 863 encodeULEB128(Import.SigIndex, W->OS); 864 break; 865 default: 866 llvm_unreachable("unsupported import kind"); 867 } 868 } 869 870 endSection(Section); 871 } 872 873 void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) { 874 if (Functions.empty()) 875 return; 876 877 SectionBookkeeping Section; 878 startSection(Section, wasm::WASM_SEC_FUNCTION); 879 880 encodeULEB128(Functions.size(), W->OS); 881 for (const WasmFunction &Func : Functions) 882 encodeULEB128(Func.SigIndex, W->OS); 883 884 endSection(Section); 885 } 886 887 void WasmObjectWriter::writeTagSection(ArrayRef<uint32_t> TagTypes) { 888 if (TagTypes.empty()) 889 return; 890 891 SectionBookkeeping Section; 892 startSection(Section, wasm::WASM_SEC_TAG); 893 894 encodeULEB128(TagTypes.size(), W->OS); 895 for (uint32_t Index : TagTypes) { 896 W->OS << char(0); // Reserved 'attribute' field 897 encodeULEB128(Index, W->OS); 898 } 899 900 endSection(Section); 901 } 902 903 void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) { 904 if (Globals.empty()) 905 return; 906 907 SectionBookkeeping Section; 908 startSection(Section, wasm::WASM_SEC_GLOBAL); 909 910 encodeULEB128(Globals.size(), W->OS); 911 for (const wasm::WasmGlobal &Global : Globals) { 912 encodeULEB128(Global.Type.Type, W->OS); 913 W->OS << char(Global.Type.Mutable); 914 W->OS << char(Global.InitExpr.Opcode); 915 switch (Global.Type.Type) { 916 case wasm::WASM_TYPE_I32: 917 encodeSLEB128(0, W->OS); 918 break; 919 case wasm::WASM_TYPE_I64: 920 encodeSLEB128(0, W->OS); 921 break; 922 case wasm::WASM_TYPE_F32: 923 writeI32(0); 924 break; 925 case wasm::WASM_TYPE_F64: 926 writeI64(0); 927 break; 928 case wasm::WASM_TYPE_EXTERNREF: 929 writeValueType(wasm::ValType::EXTERNREF); 930 break; 931 default: 932 llvm_unreachable("unexpected type"); 933 } 934 W->OS << char(wasm::WASM_OPCODE_END); 935 } 936 937 endSection(Section); 938 } 939 940 void WasmObjectWriter::writeTableSection(ArrayRef<wasm::WasmTable> Tables) { 941 if (Tables.empty()) 942 return; 943 944 SectionBookkeeping Section; 945 startSection(Section, wasm::WASM_SEC_TABLE); 946 947 encodeULEB128(Tables.size(), W->OS); 948 for (const wasm::WasmTable &Table : Tables) { 949 encodeULEB128(Table.Type.ElemType, W->OS); 950 encodeULEB128(Table.Type.Limits.Flags, W->OS); 951 encodeULEB128(Table.Type.Limits.Minimum, W->OS); 952 if (Table.Type.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) 953 encodeULEB128(Table.Type.Limits.Maximum, W->OS); 954 } 955 endSection(Section); 956 } 957 958 void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) { 959 if (Exports.empty()) 960 return; 961 962 SectionBookkeeping Section; 963 startSection(Section, wasm::WASM_SEC_EXPORT); 964 965 encodeULEB128(Exports.size(), W->OS); 966 for (const wasm::WasmExport &Export : Exports) { 967 writeString(Export.Name); 968 W->OS << char(Export.Kind); 969 encodeULEB128(Export.Index, W->OS); 970 } 971 972 endSection(Section); 973 } 974 975 void WasmObjectWriter::writeElemSection( 976 const MCSymbolWasm *IndirectFunctionTable, ArrayRef<uint32_t> TableElems) { 977 if (TableElems.empty()) 978 return; 979 980 assert(IndirectFunctionTable); 981 982 SectionBookkeeping Section; 983 startSection(Section, wasm::WASM_SEC_ELEM); 984 985 encodeULEB128(1, W->OS); // number of "segments" 986 987 assert(WasmIndices.count(IndirectFunctionTable)); 988 uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second; 989 uint32_t Flags = 0; 990 if (TableNumber) 991 Flags |= wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER; 992 encodeULEB128(Flags, W->OS); 993 if (Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER) 994 encodeULEB128(TableNumber, W->OS); // the table number 995 996 // init expr for starting offset 997 W->OS << char(wasm::WASM_OPCODE_I32_CONST); 998 encodeSLEB128(InitialTableOffset, W->OS); 999 W->OS << char(wasm::WASM_OPCODE_END); 1000 1001 if (Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) { 1002 // We only write active function table initializers, for which the elem kind 1003 // is specified to be written as 0x00 and interpreted to mean "funcref". 1004 const uint8_t ElemKind = 0; 1005 W->OS << ElemKind; 1006 } 1007 1008 encodeULEB128(TableElems.size(), W->OS); 1009 for (uint32_t Elem : TableElems) 1010 encodeULEB128(Elem, W->OS); 1011 1012 endSection(Section); 1013 } 1014 1015 void WasmObjectWriter::writeDataCountSection() { 1016 if (DataSegments.empty()) 1017 return; 1018 1019 SectionBookkeeping Section; 1020 startSection(Section, wasm::WASM_SEC_DATACOUNT); 1021 encodeULEB128(DataSegments.size(), W->OS); 1022 endSection(Section); 1023 } 1024 1025 uint32_t WasmObjectWriter::writeCodeSection(const MCAssembler &Asm, 1026 const MCAsmLayout &Layout, 1027 ArrayRef<WasmFunction> Functions) { 1028 if (Functions.empty()) 1029 return 0; 1030 1031 SectionBookkeeping Section; 1032 startSection(Section, wasm::WASM_SEC_CODE); 1033 1034 encodeULEB128(Functions.size(), W->OS); 1035 1036 for (const WasmFunction &Func : Functions) { 1037 auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection()); 1038 1039 int64_t Size = 0; 1040 if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout)) 1041 report_fatal_error(".size expression must be evaluatable"); 1042 1043 encodeULEB128(Size, W->OS); 1044 FuncSection.setSectionOffset(W->OS.tell() - Section.ContentsOffset); 1045 Asm.writeSectionData(W->OS, &FuncSection, Layout); 1046 } 1047 1048 // Apply fixups. 1049 applyRelocations(CodeRelocations, Section.ContentsOffset, Layout); 1050 1051 endSection(Section); 1052 return Section.Index; 1053 } 1054 1055 uint32_t WasmObjectWriter::writeDataSection(const MCAsmLayout &Layout) { 1056 if (DataSegments.empty()) 1057 return 0; 1058 1059 SectionBookkeeping Section; 1060 startSection(Section, wasm::WASM_SEC_DATA); 1061 1062 encodeULEB128(DataSegments.size(), W->OS); // count 1063 1064 for (const WasmDataSegment &Segment : DataSegments) { 1065 encodeULEB128(Segment.InitFlags, W->OS); // flags 1066 if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX) 1067 encodeULEB128(0, W->OS); // memory index 1068 if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) { 1069 W->OS << char(is64Bit() ? wasm::WASM_OPCODE_I64_CONST 1070 : wasm::WASM_OPCODE_I32_CONST); 1071 encodeSLEB128(Segment.Offset, W->OS); // offset 1072 W->OS << char(wasm::WASM_OPCODE_END); 1073 } 1074 encodeULEB128(Segment.Data.size(), W->OS); // size 1075 Segment.Section->setSectionOffset(W->OS.tell() - Section.ContentsOffset); 1076 W->OS << Segment.Data; // data 1077 } 1078 1079 // Apply fixups. 1080 applyRelocations(DataRelocations, Section.ContentsOffset, Layout); 1081 1082 endSection(Section); 1083 return Section.Index; 1084 } 1085 1086 void WasmObjectWriter::writeRelocSection( 1087 uint32_t SectionIndex, StringRef Name, 1088 std::vector<WasmRelocationEntry> &Relocs) { 1089 // See: https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md 1090 // for descriptions of the reloc sections. 1091 1092 if (Relocs.empty()) 1093 return; 1094 1095 // First, ensure the relocations are sorted in offset order. In general they 1096 // should already be sorted since `recordRelocation` is called in offset 1097 // order, but for the code section we combine many MC sections into single 1098 // wasm section, and this order is determined by the order of Asm.Symbols() 1099 // not the sections order. 1100 llvm::stable_sort( 1101 Relocs, [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) { 1102 return (A.Offset + A.FixupSection->getSectionOffset()) < 1103 (B.Offset + B.FixupSection->getSectionOffset()); 1104 }); 1105 1106 SectionBookkeeping Section; 1107 startCustomSection(Section, std::string("reloc.") + Name.str()); 1108 1109 encodeULEB128(SectionIndex, W->OS); 1110 encodeULEB128(Relocs.size(), W->OS); 1111 for (const WasmRelocationEntry &RelEntry : Relocs) { 1112 uint64_t Offset = 1113 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset(); 1114 uint32_t Index = getRelocationIndexValue(RelEntry); 1115 1116 W->OS << char(RelEntry.Type); 1117 encodeULEB128(Offset, W->OS); 1118 encodeULEB128(Index, W->OS); 1119 if (RelEntry.hasAddend()) 1120 encodeSLEB128(RelEntry.Addend, W->OS); 1121 } 1122 1123 endSection(Section); 1124 } 1125 1126 void WasmObjectWriter::writeCustomRelocSections() { 1127 for (const auto &Sec : CustomSections) { 1128 auto &Relocations = CustomSectionsRelocations[Sec.Section]; 1129 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations); 1130 } 1131 } 1132 1133 void WasmObjectWriter::writeLinkingMetaDataSection( 1134 ArrayRef<wasm::WasmSymbolInfo> SymbolInfos, 1135 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs, 1136 const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) { 1137 SectionBookkeeping Section; 1138 startCustomSection(Section, "linking"); 1139 encodeULEB128(wasm::WasmMetadataVersion, W->OS); 1140 1141 SectionBookkeeping SubSection; 1142 if (SymbolInfos.size() != 0) { 1143 startSection(SubSection, wasm::WASM_SYMBOL_TABLE); 1144 encodeULEB128(SymbolInfos.size(), W->OS); 1145 for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) { 1146 encodeULEB128(Sym.Kind, W->OS); 1147 encodeULEB128(Sym.Flags, W->OS); 1148 switch (Sym.Kind) { 1149 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1150 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1151 case wasm::WASM_SYMBOL_TYPE_TAG: 1152 case wasm::WASM_SYMBOL_TYPE_TABLE: 1153 encodeULEB128(Sym.ElementIndex, W->OS); 1154 if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 || 1155 (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) 1156 writeString(Sym.Name); 1157 break; 1158 case wasm::WASM_SYMBOL_TYPE_DATA: 1159 writeString(Sym.Name); 1160 if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) { 1161 encodeULEB128(Sym.DataRef.Segment, W->OS); 1162 encodeULEB128(Sym.DataRef.Offset, W->OS); 1163 encodeULEB128(Sym.DataRef.Size, W->OS); 1164 } 1165 break; 1166 case wasm::WASM_SYMBOL_TYPE_SECTION: { 1167 const uint32_t SectionIndex = 1168 CustomSections[Sym.ElementIndex].OutputIndex; 1169 encodeULEB128(SectionIndex, W->OS); 1170 break; 1171 } 1172 default: 1173 llvm_unreachable("unexpected kind"); 1174 } 1175 } 1176 endSection(SubSection); 1177 } 1178 1179 if (DataSegments.size()) { 1180 startSection(SubSection, wasm::WASM_SEGMENT_INFO); 1181 encodeULEB128(DataSegments.size(), W->OS); 1182 for (const WasmDataSegment &Segment : DataSegments) { 1183 writeString(Segment.Name); 1184 encodeULEB128(Segment.Alignment, W->OS); 1185 encodeULEB128(Segment.LinkingFlags, W->OS); 1186 } 1187 endSection(SubSection); 1188 } 1189 1190 if (!InitFuncs.empty()) { 1191 startSection(SubSection, wasm::WASM_INIT_FUNCS); 1192 encodeULEB128(InitFuncs.size(), W->OS); 1193 for (auto &StartFunc : InitFuncs) { 1194 encodeULEB128(StartFunc.first, W->OS); // priority 1195 encodeULEB128(StartFunc.second, W->OS); // function index 1196 } 1197 endSection(SubSection); 1198 } 1199 1200 if (Comdats.size()) { 1201 startSection(SubSection, wasm::WASM_COMDAT_INFO); 1202 encodeULEB128(Comdats.size(), W->OS); 1203 for (const auto &C : Comdats) { 1204 writeString(C.first); 1205 encodeULEB128(0, W->OS); // flags for future use 1206 encodeULEB128(C.second.size(), W->OS); 1207 for (const WasmComdatEntry &Entry : C.second) { 1208 encodeULEB128(Entry.Kind, W->OS); 1209 encodeULEB128(Entry.Index, W->OS); 1210 } 1211 } 1212 endSection(SubSection); 1213 } 1214 1215 endSection(Section); 1216 } 1217 1218 void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection, 1219 const MCAssembler &Asm, 1220 const MCAsmLayout &Layout) { 1221 SectionBookkeeping Section; 1222 auto *Sec = CustomSection.Section; 1223 startCustomSection(Section, CustomSection.Name); 1224 1225 Sec->setSectionOffset(W->OS.tell() - Section.ContentsOffset); 1226 Asm.writeSectionData(W->OS, Sec, Layout); 1227 1228 CustomSection.OutputContentsOffset = Section.ContentsOffset; 1229 CustomSection.OutputIndex = Section.Index; 1230 1231 endSection(Section); 1232 1233 // Apply fixups. 1234 auto &Relocations = CustomSectionsRelocations[CustomSection.Section]; 1235 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout); 1236 } 1237 1238 uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) { 1239 assert(Symbol.isFunction()); 1240 assert(TypeIndices.count(&Symbol)); 1241 return TypeIndices[&Symbol]; 1242 } 1243 1244 uint32_t WasmObjectWriter::getTagType(const MCSymbolWasm &Symbol) { 1245 assert(Symbol.isTag()); 1246 assert(TypeIndices.count(&Symbol)); 1247 return TypeIndices[&Symbol]; 1248 } 1249 1250 void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) { 1251 assert(Symbol.isFunction()); 1252 1253 wasm::WasmSignature S; 1254 1255 if (auto *Sig = Symbol.getSignature()) { 1256 S.Returns = Sig->Returns; 1257 S.Params = Sig->Params; 1258 } 1259 1260 auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size())); 1261 if (Pair.second) 1262 Signatures.push_back(S); 1263 TypeIndices[&Symbol] = Pair.first->second; 1264 1265 LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol 1266 << " new:" << Pair.second << "\n"); 1267 LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n"); 1268 } 1269 1270 void WasmObjectWriter::registerTagType(const MCSymbolWasm &Symbol) { 1271 assert(Symbol.isTag()); 1272 1273 // TODO Currently we don't generate imported exceptions, but if we do, we 1274 // should have a way of infering types of imported exceptions. 1275 wasm::WasmSignature S; 1276 if (auto *Sig = Symbol.getSignature()) { 1277 S.Returns = Sig->Returns; 1278 S.Params = Sig->Params; 1279 } 1280 1281 auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size())); 1282 if (Pair.second) 1283 Signatures.push_back(S); 1284 TypeIndices[&Symbol] = Pair.first->second; 1285 1286 LLVM_DEBUG(dbgs() << "registerTagType: " << Symbol << " new:" << Pair.second 1287 << "\n"); 1288 LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n"); 1289 } 1290 1291 static bool isInSymtab(const MCSymbolWasm &Sym) { 1292 if (Sym.isUsedInReloc() || Sym.isUsedInInitArray()) 1293 return true; 1294 1295 if (Sym.isComdat() && !Sym.isDefined()) 1296 return false; 1297 1298 if (Sym.isTemporary()) 1299 return false; 1300 1301 if (Sym.isSection()) 1302 return false; 1303 1304 if (Sym.omitFromLinkingSection()) 1305 return false; 1306 1307 return true; 1308 } 1309 1310 void WasmObjectWriter::prepareImports( 1311 SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm, 1312 const MCAsmLayout &Layout) { 1313 // For now, always emit the memory import, since loads and stores are not 1314 // valid without it. In the future, we could perhaps be more clever and omit 1315 // it if there are no loads or stores. 1316 wasm::WasmImport MemImport; 1317 MemImport.Module = "env"; 1318 MemImport.Field = "__linear_memory"; 1319 MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY; 1320 MemImport.Memory.Flags = is64Bit() ? wasm::WASM_LIMITS_FLAG_IS_64 1321 : wasm::WASM_LIMITS_FLAG_NONE; 1322 Imports.push_back(MemImport); 1323 1324 // Populate SignatureIndices, and Imports and WasmIndices for undefined 1325 // symbols. This must be done before populating WasmIndices for defined 1326 // symbols. 1327 for (const MCSymbol &S : Asm.symbols()) { 1328 const auto &WS = static_cast<const MCSymbolWasm &>(S); 1329 1330 // Register types for all functions, including those with private linkage 1331 // (because wasm always needs a type signature). 1332 if (WS.isFunction()) { 1333 const auto *BS = Layout.getBaseSymbol(S); 1334 if (!BS) 1335 report_fatal_error(Twine(S.getName()) + 1336 ": absolute addressing not supported!"); 1337 registerFunctionType(*cast<MCSymbolWasm>(BS)); 1338 } 1339 1340 if (WS.isTag()) 1341 registerTagType(WS); 1342 1343 if (WS.isTemporary()) 1344 continue; 1345 1346 // If the symbol is not defined in this translation unit, import it. 1347 if (!WS.isDefined() && !WS.isComdat()) { 1348 if (WS.isFunction()) { 1349 wasm::WasmImport Import; 1350 Import.Module = WS.getImportModule(); 1351 Import.Field = WS.getImportName(); 1352 Import.Kind = wasm::WASM_EXTERNAL_FUNCTION; 1353 Import.SigIndex = getFunctionType(WS); 1354 Imports.push_back(Import); 1355 assert(WasmIndices.count(&WS) == 0); 1356 WasmIndices[&WS] = NumFunctionImports++; 1357 } else if (WS.isGlobal()) { 1358 if (WS.isWeak()) 1359 report_fatal_error("undefined global symbol cannot be weak"); 1360 1361 wasm::WasmImport Import; 1362 Import.Field = WS.getImportName(); 1363 Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; 1364 Import.Module = WS.getImportModule(); 1365 Import.Global = WS.getGlobalType(); 1366 Imports.push_back(Import); 1367 assert(WasmIndices.count(&WS) == 0); 1368 WasmIndices[&WS] = NumGlobalImports++; 1369 } else if (WS.isTag()) { 1370 if (WS.isWeak()) 1371 report_fatal_error("undefined tag symbol cannot be weak"); 1372 1373 wasm::WasmImport Import; 1374 Import.Module = WS.getImportModule(); 1375 Import.Field = WS.getImportName(); 1376 Import.Kind = wasm::WASM_EXTERNAL_TAG; 1377 Import.SigIndex = getTagType(WS); 1378 Imports.push_back(Import); 1379 assert(WasmIndices.count(&WS) == 0); 1380 WasmIndices[&WS] = NumTagImports++; 1381 } else if (WS.isTable()) { 1382 if (WS.isWeak()) 1383 report_fatal_error("undefined table symbol cannot be weak"); 1384 1385 wasm::WasmImport Import; 1386 Import.Module = WS.getImportModule(); 1387 Import.Field = WS.getImportName(); 1388 Import.Kind = wasm::WASM_EXTERNAL_TABLE; 1389 Import.Table = WS.getTableType(); 1390 Imports.push_back(Import); 1391 assert(WasmIndices.count(&WS) == 0); 1392 WasmIndices[&WS] = NumTableImports++; 1393 } 1394 } 1395 } 1396 1397 // Add imports for GOT globals 1398 for (const MCSymbol &S : Asm.symbols()) { 1399 const auto &WS = static_cast<const MCSymbolWasm &>(S); 1400 if (WS.isUsedInGOT()) { 1401 wasm::WasmImport Import; 1402 if (WS.isFunction()) 1403 Import.Module = "GOT.func"; 1404 else 1405 Import.Module = "GOT.mem"; 1406 Import.Field = WS.getName(); 1407 Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; 1408 Import.Global = {wasm::WASM_TYPE_I32, true}; 1409 Imports.push_back(Import); 1410 assert(GOTIndices.count(&WS) == 0); 1411 GOTIndices[&WS] = NumGlobalImports++; 1412 } 1413 } 1414 } 1415 1416 uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, 1417 const MCAsmLayout &Layout) { 1418 support::endian::Writer MainWriter(*OS, support::little); 1419 W = &MainWriter; 1420 if (IsSplitDwarf) { 1421 uint64_t TotalSize = writeOneObject(Asm, Layout, DwoMode::NonDwoOnly); 1422 assert(DwoOS); 1423 support::endian::Writer DwoWriter(*DwoOS, support::little); 1424 W = &DwoWriter; 1425 return TotalSize + writeOneObject(Asm, Layout, DwoMode::DwoOnly); 1426 } else { 1427 return writeOneObject(Asm, Layout, DwoMode::AllSections); 1428 } 1429 } 1430 1431 uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, 1432 const MCAsmLayout &Layout, 1433 DwoMode Mode) { 1434 uint64_t StartOffset = W->OS.tell(); 1435 SectionCount = 0; 1436 CustomSections.clear(); 1437 1438 LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n"); 1439 1440 // Collect information from the available symbols. 1441 SmallVector<WasmFunction, 4> Functions; 1442 SmallVector<uint32_t, 4> TableElems; 1443 SmallVector<wasm::WasmImport, 4> Imports; 1444 SmallVector<wasm::WasmExport, 4> Exports; 1445 SmallVector<uint32_t, 2> TagTypes; 1446 SmallVector<wasm::WasmGlobal, 1> Globals; 1447 SmallVector<wasm::WasmTable, 1> Tables; 1448 SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos; 1449 SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs; 1450 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats; 1451 uint64_t DataSize = 0; 1452 if (Mode != DwoMode::DwoOnly) { 1453 prepareImports(Imports, Asm, Layout); 1454 } 1455 1456 // Populate DataSegments and CustomSections, which must be done before 1457 // populating DataLocations. 1458 for (MCSection &Sec : Asm) { 1459 auto &Section = static_cast<MCSectionWasm &>(Sec); 1460 StringRef SectionName = Section.getName(); 1461 1462 if (Mode == DwoMode::NonDwoOnly && isDwoSection(Sec)) 1463 continue; 1464 if (Mode == DwoMode::DwoOnly && !isDwoSection(Sec)) 1465 continue; 1466 1467 LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << " group " 1468 << Section.getGroup() << "\n";); 1469 1470 // .init_array sections are handled specially elsewhere. 1471 if (SectionName.startswith(".init_array")) 1472 continue; 1473 1474 // Code is handled separately 1475 if (Section.getKind().isText()) 1476 continue; 1477 1478 if (Section.isWasmData()) { 1479 uint32_t SegmentIndex = DataSegments.size(); 1480 DataSize = alignTo(DataSize, Section.getAlignment()); 1481 DataSegments.emplace_back(); 1482 WasmDataSegment &Segment = DataSegments.back(); 1483 Segment.Name = SectionName; 1484 Segment.InitFlags = Section.getPassive() 1485 ? (uint32_t)wasm::WASM_DATA_SEGMENT_IS_PASSIVE 1486 : 0; 1487 Segment.Offset = DataSize; 1488 Segment.Section = &Section; 1489 addData(Segment.Data, Section); 1490 Segment.Alignment = Log2_32(Section.getAlignment()); 1491 Segment.LinkingFlags = Section.getSegmentFlags(); 1492 DataSize += Segment.Data.size(); 1493 Section.setSegmentIndex(SegmentIndex); 1494 1495 if (const MCSymbolWasm *C = Section.getGroup()) { 1496 Comdats[C->getName()].emplace_back( 1497 WasmComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex}); 1498 } 1499 } else { 1500 // Create custom sections 1501 assert(Sec.getKind().isMetadata()); 1502 1503 StringRef Name = SectionName; 1504 1505 // For user-defined custom sections, strip the prefix 1506 if (Name.startswith(".custom_section.")) 1507 Name = Name.substr(strlen(".custom_section.")); 1508 1509 MCSymbol *Begin = Sec.getBeginSymbol(); 1510 if (Begin) { 1511 assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0); 1512 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size(); 1513 } 1514 1515 // Separate out the producers and target features sections 1516 if (Name == "producers") { 1517 ProducersSection = std::make_unique<WasmCustomSection>(Name, &Section); 1518 continue; 1519 } 1520 if (Name == "target_features") { 1521 TargetFeaturesSection = 1522 std::make_unique<WasmCustomSection>(Name, &Section); 1523 continue; 1524 } 1525 1526 // Custom sections can also belong to COMDAT groups. In this case the 1527 // decriptor's "index" field is the section index (in the final object 1528 // file), but that is not known until after layout, so it must be fixed up 1529 // later 1530 if (const MCSymbolWasm *C = Section.getGroup()) { 1531 Comdats[C->getName()].emplace_back( 1532 WasmComdatEntry{wasm::WASM_COMDAT_SECTION, 1533 static_cast<uint32_t>(CustomSections.size())}); 1534 } 1535 1536 CustomSections.emplace_back(Name, &Section); 1537 } 1538 } 1539 1540 if (Mode != DwoMode::DwoOnly) { 1541 // Populate WasmIndices and DataLocations for defined symbols. 1542 for (const MCSymbol &S : Asm.symbols()) { 1543 // Ignore unnamed temporary symbols, which aren't ever exported, imported, 1544 // or used in relocations. 1545 if (S.isTemporary() && S.getName().empty()) 1546 continue; 1547 1548 const auto &WS = static_cast<const MCSymbolWasm &>(S); 1549 LLVM_DEBUG(dbgs() 1550 << "MCSymbol: " 1551 << toString(WS.getType().getValueOr(wasm::WASM_SYMBOL_TYPE_DATA)) 1552 << " '" << S << "'" 1553 << " isDefined=" << S.isDefined() << " isExternal=" 1554 << S.isExternal() << " isTemporary=" << S.isTemporary() 1555 << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden() 1556 << " isVariable=" << WS.isVariable() << "\n"); 1557 1558 if (WS.isVariable()) 1559 continue; 1560 if (WS.isComdat() && !WS.isDefined()) 1561 continue; 1562 1563 if (WS.isFunction()) { 1564 unsigned Index; 1565 if (WS.isDefined()) { 1566 if (WS.getOffset() != 0) 1567 report_fatal_error( 1568 "function sections must contain one function each"); 1569 1570 if (WS.getSize() == nullptr) 1571 report_fatal_error( 1572 "function symbols must have a size set with .size"); 1573 1574 // A definition. Write out the function body. 1575 Index = NumFunctionImports + Functions.size(); 1576 WasmFunction Func; 1577 Func.SigIndex = getFunctionType(WS); 1578 Func.Sym = &WS; 1579 assert(WasmIndices.count(&WS) == 0); 1580 WasmIndices[&WS] = Index; 1581 Functions.push_back(Func); 1582 1583 auto &Section = static_cast<MCSectionWasm &>(WS.getSection()); 1584 if (const MCSymbolWasm *C = Section.getGroup()) { 1585 Comdats[C->getName()].emplace_back( 1586 WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index}); 1587 } 1588 1589 if (WS.hasExportName()) { 1590 wasm::WasmExport Export; 1591 Export.Name = WS.getExportName(); 1592 Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; 1593 Export.Index = Index; 1594 Exports.push_back(Export); 1595 } 1596 } else { 1597 // An import; the index was assigned above. 1598 Index = WasmIndices.find(&WS)->second; 1599 } 1600 1601 LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n"); 1602 1603 } else if (WS.isData()) { 1604 if (!isInSymtab(WS)) 1605 continue; 1606 1607 if (!WS.isDefined()) { 1608 LLVM_DEBUG(dbgs() << " -> segment index: -1" 1609 << "\n"); 1610 continue; 1611 } 1612 1613 if (!WS.getSize()) 1614 report_fatal_error("data symbols must have a size set with .size: " + 1615 WS.getName()); 1616 1617 int64_t Size = 0; 1618 if (!WS.getSize()->evaluateAsAbsolute(Size, Layout)) 1619 report_fatal_error(".size expression must be evaluatable"); 1620 1621 auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection()); 1622 if (!DataSection.isWasmData()) 1623 report_fatal_error("data symbols must live in a data section: " + 1624 WS.getName()); 1625 1626 // For each data symbol, export it in the symtab as a reference to the 1627 // corresponding Wasm data segment. 1628 wasm::WasmDataReference Ref = wasm::WasmDataReference{ 1629 DataSection.getSegmentIndex(), Layout.getSymbolOffset(WS), 1630 static_cast<uint64_t>(Size)}; 1631 assert(DataLocations.count(&WS) == 0); 1632 DataLocations[&WS] = Ref; 1633 LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n"); 1634 1635 } else if (WS.isGlobal()) { 1636 // A "true" Wasm global (currently just __stack_pointer) 1637 if (WS.isDefined()) { 1638 wasm::WasmGlobal Global; 1639 Global.Type = WS.getGlobalType(); 1640 Global.Index = NumGlobalImports + Globals.size(); 1641 switch (Global.Type.Type) { 1642 case wasm::WASM_TYPE_I32: 1643 Global.InitExpr.Opcode = wasm::WASM_OPCODE_I32_CONST; 1644 break; 1645 case wasm::WASM_TYPE_I64: 1646 Global.InitExpr.Opcode = wasm::WASM_OPCODE_I64_CONST; 1647 break; 1648 case wasm::WASM_TYPE_F32: 1649 Global.InitExpr.Opcode = wasm::WASM_OPCODE_F32_CONST; 1650 break; 1651 case wasm::WASM_TYPE_F64: 1652 Global.InitExpr.Opcode = wasm::WASM_OPCODE_F64_CONST; 1653 break; 1654 case wasm::WASM_TYPE_EXTERNREF: 1655 Global.InitExpr.Opcode = wasm::WASM_OPCODE_REF_NULL; 1656 break; 1657 default: 1658 llvm_unreachable("unexpected type"); 1659 } 1660 assert(WasmIndices.count(&WS) == 0); 1661 WasmIndices[&WS] = Global.Index; 1662 Globals.push_back(Global); 1663 } else { 1664 // An import; the index was assigned above 1665 LLVM_DEBUG(dbgs() << " -> global index: " 1666 << WasmIndices.find(&WS)->second << "\n"); 1667 } 1668 } else if (WS.isTable()) { 1669 if (WS.isDefined()) { 1670 wasm::WasmTable Table; 1671 Table.Index = NumTableImports + Tables.size(); 1672 Table.Type = WS.getTableType(); 1673 assert(WasmIndices.count(&WS) == 0); 1674 WasmIndices[&WS] = Table.Index; 1675 Tables.push_back(Table); 1676 } 1677 LLVM_DEBUG(dbgs() << " -> table index: " 1678 << WasmIndices.find(&WS)->second << "\n"); 1679 } else if (WS.isTag()) { 1680 // C++ exception symbol (__cpp_exception) or longjmp symbol 1681 // (__c_longjmp) 1682 unsigned Index; 1683 if (WS.isDefined()) { 1684 Index = NumTagImports + TagTypes.size(); 1685 uint32_t SigIndex = getTagType(WS); 1686 assert(WasmIndices.count(&WS) == 0); 1687 WasmIndices[&WS] = Index; 1688 TagTypes.push_back(SigIndex); 1689 } else { 1690 // An import; the index was assigned above. 1691 assert(WasmIndices.count(&WS) > 0); 1692 } 1693 LLVM_DEBUG(dbgs() << " -> tag index: " << WasmIndices.find(&WS)->second 1694 << "\n"); 1695 1696 } else { 1697 assert(WS.isSection()); 1698 } 1699 } 1700 1701 // Populate WasmIndices and DataLocations for aliased symbols. We need to 1702 // process these in a separate pass because we need to have processed the 1703 // target of the alias before the alias itself and the symbols are not 1704 // necessarily ordered in this way. 1705 for (const MCSymbol &S : Asm.symbols()) { 1706 if (!S.isVariable()) 1707 continue; 1708 1709 assert(S.isDefined()); 1710 1711 const auto *BS = Layout.getBaseSymbol(S); 1712 if (!BS) 1713 report_fatal_error(Twine(S.getName()) + 1714 ": absolute addressing not supported!"); 1715 const MCSymbolWasm *Base = cast<MCSymbolWasm>(BS); 1716 1717 // Find the target symbol of this weak alias and export that index 1718 const auto &WS = static_cast<const MCSymbolWasm &>(S); 1719 LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *Base 1720 << "'\n"); 1721 1722 if (Base->isFunction()) { 1723 assert(WasmIndices.count(Base) > 0); 1724 uint32_t WasmIndex = WasmIndices.find(Base)->second; 1725 assert(WasmIndices.count(&WS) == 0); 1726 WasmIndices[&WS] = WasmIndex; 1727 LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n"); 1728 } else if (Base->isData()) { 1729 auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection()); 1730 uint64_t Offset = Layout.getSymbolOffset(S); 1731 int64_t Size = 0; 1732 // For data symbol alias we use the size of the base symbol as the 1733 // size of the alias. When an offset from the base is involved this 1734 // can result in a offset + size goes past the end of the data section 1735 // which out object format doesn't support. So we must clamp it. 1736 if (!Base->getSize()->evaluateAsAbsolute(Size, Layout)) 1737 report_fatal_error(".size expression must be evaluatable"); 1738 const WasmDataSegment &Segment = 1739 DataSegments[DataSection.getSegmentIndex()]; 1740 Size = 1741 std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset); 1742 wasm::WasmDataReference Ref = wasm::WasmDataReference{ 1743 DataSection.getSegmentIndex(), 1744 static_cast<uint32_t>(Layout.getSymbolOffset(S)), 1745 static_cast<uint32_t>(Size)}; 1746 DataLocations[&WS] = Ref; 1747 LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n"); 1748 } else { 1749 report_fatal_error("don't yet support global/tag aliases"); 1750 } 1751 } 1752 } 1753 1754 // Finally, populate the symbol table itself, in its "natural" order. 1755 for (const MCSymbol &S : Asm.symbols()) { 1756 const auto &WS = static_cast<const MCSymbolWasm &>(S); 1757 if (!isInSymtab(WS)) { 1758 WS.setIndex(InvalidIndex); 1759 continue; 1760 } 1761 LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n"); 1762 1763 uint32_t Flags = 0; 1764 if (WS.isWeak()) 1765 Flags |= wasm::WASM_SYMBOL_BINDING_WEAK; 1766 if (WS.isHidden()) 1767 Flags |= wasm::WASM_SYMBOL_VISIBILITY_HIDDEN; 1768 if (!WS.isExternal() && WS.isDefined()) 1769 Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL; 1770 if (WS.isUndefined()) 1771 Flags |= wasm::WASM_SYMBOL_UNDEFINED; 1772 if (WS.isNoStrip()) { 1773 Flags |= wasm::WASM_SYMBOL_NO_STRIP; 1774 if (isEmscripten()) { 1775 Flags |= wasm::WASM_SYMBOL_EXPORTED; 1776 } 1777 } 1778 if (WS.hasImportName()) 1779 Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME; 1780 if (WS.hasExportName()) 1781 Flags |= wasm::WASM_SYMBOL_EXPORTED; 1782 if (WS.isTLS()) 1783 Flags |= wasm::WASM_SYMBOL_TLS; 1784 1785 wasm::WasmSymbolInfo Info; 1786 Info.Name = WS.getName(); 1787 Info.Kind = WS.getType().getValueOr(wasm::WASM_SYMBOL_TYPE_DATA); 1788 Info.Flags = Flags; 1789 if (!WS.isData()) { 1790 assert(WasmIndices.count(&WS) > 0); 1791 Info.ElementIndex = WasmIndices.find(&WS)->second; 1792 } else if (WS.isDefined()) { 1793 assert(DataLocations.count(&WS) > 0); 1794 Info.DataRef = DataLocations.find(&WS)->second; 1795 } 1796 WS.setIndex(SymbolInfos.size()); 1797 SymbolInfos.emplace_back(Info); 1798 } 1799 1800 { 1801 auto HandleReloc = [&](const WasmRelocationEntry &Rel) { 1802 // Functions referenced by a relocation need to put in the table. This is 1803 // purely to make the object file's provisional values readable, and is 1804 // ignored by the linker, which re-calculates the relocations itself. 1805 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 && 1806 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 && 1807 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB && 1808 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 && 1809 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB && 1810 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64) 1811 return; 1812 assert(Rel.Symbol->isFunction()); 1813 const MCSymbolWasm *Base = 1814 cast<MCSymbolWasm>(Layout.getBaseSymbol(*Rel.Symbol)); 1815 uint32_t FunctionIndex = WasmIndices.find(Base)->second; 1816 uint32_t TableIndex = TableElems.size() + InitialTableOffset; 1817 if (TableIndices.try_emplace(Base, TableIndex).second) { 1818 LLVM_DEBUG(dbgs() << " -> adding " << Base->getName() 1819 << " to table: " << TableIndex << "\n"); 1820 TableElems.push_back(FunctionIndex); 1821 registerFunctionType(*Base); 1822 } 1823 }; 1824 1825 for (const WasmRelocationEntry &RelEntry : CodeRelocations) 1826 HandleReloc(RelEntry); 1827 for (const WasmRelocationEntry &RelEntry : DataRelocations) 1828 HandleReloc(RelEntry); 1829 } 1830 1831 // Translate .init_array section contents into start functions. 1832 for (const MCSection &S : Asm) { 1833 const auto &WS = static_cast<const MCSectionWasm &>(S); 1834 if (WS.getName().startswith(".fini_array")) 1835 report_fatal_error(".fini_array sections are unsupported"); 1836 if (!WS.getName().startswith(".init_array")) 1837 continue; 1838 if (WS.getFragmentList().empty()) 1839 continue; 1840 1841 // init_array is expected to contain a single non-empty data fragment 1842 if (WS.getFragmentList().size() != 3) 1843 report_fatal_error("only one .init_array section fragment supported"); 1844 1845 auto IT = WS.begin(); 1846 const MCFragment &EmptyFrag = *IT; 1847 if (EmptyFrag.getKind() != MCFragment::FT_Data) 1848 report_fatal_error(".init_array section should be aligned"); 1849 1850 IT = std::next(IT); 1851 const MCFragment &AlignFrag = *IT; 1852 if (AlignFrag.getKind() != MCFragment::FT_Align) 1853 report_fatal_error(".init_array section should be aligned"); 1854 if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4)) 1855 report_fatal_error(".init_array section should be aligned for pointers"); 1856 1857 const MCFragment &Frag = *std::next(IT); 1858 if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) 1859 report_fatal_error("only data supported in .init_array section"); 1860 1861 uint16_t Priority = UINT16_MAX; 1862 unsigned PrefixLength = strlen(".init_array"); 1863 if (WS.getName().size() > PrefixLength) { 1864 if (WS.getName()[PrefixLength] != '.') 1865 report_fatal_error( 1866 ".init_array section priority should start with '.'"); 1867 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority)) 1868 report_fatal_error("invalid .init_array section priority"); 1869 } 1870 const auto &DataFrag = cast<MCDataFragment>(Frag); 1871 const SmallVectorImpl<char> &Contents = DataFrag.getContents(); 1872 for (const uint8_t * 1873 P = (const uint8_t *)Contents.data(), 1874 *End = (const uint8_t *)Contents.data() + Contents.size(); 1875 P != End; ++P) { 1876 if (*P != 0) 1877 report_fatal_error("non-symbolic data in .init_array section"); 1878 } 1879 for (const MCFixup &Fixup : DataFrag.getFixups()) { 1880 assert(Fixup.getKind() == 1881 MCFixup::getKindForSize(is64Bit() ? 8 : 4, false)); 1882 const MCExpr *Expr = Fixup.getValue(); 1883 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr); 1884 if (!SymRef) 1885 report_fatal_error("fixups in .init_array should be symbol references"); 1886 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol()); 1887 if (TargetSym.getIndex() == InvalidIndex) 1888 report_fatal_error("symbols in .init_array should exist in symtab"); 1889 if (!TargetSym.isFunction()) 1890 report_fatal_error("symbols in .init_array should be for functions"); 1891 InitFuncs.push_back( 1892 std::make_pair(Priority, TargetSym.getIndex())); 1893 } 1894 } 1895 1896 // Write out the Wasm header. 1897 writeHeader(Asm); 1898 1899 uint32_t CodeSectionIndex, DataSectionIndex; 1900 if (Mode != DwoMode::DwoOnly) { 1901 writeTypeSection(Signatures); 1902 writeImportSection(Imports, DataSize, TableElems.size()); 1903 writeFunctionSection(Functions); 1904 writeTableSection(Tables); 1905 // Skip the "memory" section; we import the memory instead. 1906 writeTagSection(TagTypes); 1907 writeGlobalSection(Globals); 1908 writeExportSection(Exports); 1909 const MCSymbol *IndirectFunctionTable = 1910 Asm.getContext().lookupSymbol("__indirect_function_table"); 1911 writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable), 1912 TableElems); 1913 writeDataCountSection(); 1914 1915 CodeSectionIndex = writeCodeSection(Asm, Layout, Functions); 1916 DataSectionIndex = writeDataSection(Layout); 1917 } 1918 1919 // The Sections in the COMDAT list have placeholder indices (their index among 1920 // custom sections, rather than among all sections). Fix them up here. 1921 for (auto &Group : Comdats) { 1922 for (auto &Entry : Group.second) { 1923 if (Entry.Kind == wasm::WASM_COMDAT_SECTION) { 1924 Entry.Index += SectionCount; 1925 } 1926 } 1927 } 1928 for (auto &CustomSection : CustomSections) 1929 writeCustomSection(CustomSection, Asm, Layout); 1930 1931 if (Mode != DwoMode::DwoOnly) { 1932 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats); 1933 1934 writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations); 1935 writeRelocSection(DataSectionIndex, "DATA", DataRelocations); 1936 } 1937 writeCustomRelocSections(); 1938 if (ProducersSection) 1939 writeCustomSection(*ProducersSection, Asm, Layout); 1940 if (TargetFeaturesSection) 1941 writeCustomSection(*TargetFeaturesSection, Asm, Layout); 1942 1943 // TODO: Translate the .comment section to the output. 1944 return W->OS.tell() - StartOffset; 1945 } 1946 1947 std::unique_ptr<MCObjectWriter> 1948 llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, 1949 raw_pwrite_stream &OS) { 1950 return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS); 1951 } 1952 1953 std::unique_ptr<MCObjectWriter> 1954 llvm::createWasmDwoObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, 1955 raw_pwrite_stream &OS, 1956 raw_pwrite_stream &DwoOS) { 1957 return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS, DwoOS); 1958 } 1959