1 //===- Writer.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 "Writer.h" 10 #include "Config.h" 11 #include "InputChunks.h" 12 #include "InputEvent.h" 13 #include "InputGlobal.h" 14 #include "OutputSections.h" 15 #include "OutputSegment.h" 16 #include "Relocations.h" 17 #include "SymbolTable.h" 18 #include "SyntheticSections.h" 19 #include "WriterUtils.h" 20 #include "lld/Common/ErrorHandler.h" 21 #include "lld/Common/Memory.h" 22 #include "lld/Common/Strings.h" 23 #include "llvm/ADT/DenseSet.h" 24 #include "llvm/ADT/SmallSet.h" 25 #include "llvm/ADT/SmallVector.h" 26 #include "llvm/ADT/StringMap.h" 27 #include "llvm/BinaryFormat/Wasm.h" 28 #include "llvm/Object/WasmTraits.h" 29 #include "llvm/Support/FileOutputBuffer.h" 30 #include "llvm/Support/Format.h" 31 #include "llvm/Support/FormatVariadic.h" 32 #include "llvm/Support/LEB128.h" 33 #include "llvm/Support/Parallel.h" 34 35 #include <cstdarg> 36 #include <map> 37 38 #define DEBUG_TYPE "lld" 39 40 using namespace llvm; 41 using namespace llvm::wasm; 42 43 namespace lld { 44 namespace wasm { 45 static constexpr int stackAlignment = 16; 46 47 namespace { 48 49 // The writer writes a SymbolTable result to a file. 50 class Writer { 51 public: 52 void run(); 53 54 private: 55 void openFile(); 56 57 bool needsPassiveInitialization(const OutputSegment *segment); 58 bool hasPassiveInitializedSegments(); 59 60 void createInitMemoryFunction(); 61 void createApplyRelocationsFunction(); 62 void createCallCtorsFunction(); 63 void createInitTLSFunction(); 64 65 void assignIndexes(); 66 void populateSymtab(); 67 void populateProducers(); 68 void populateTargetFeatures(); 69 void calculateInitFunctions(); 70 void calculateImports(); 71 void calculateExports(); 72 void calculateCustomSections(); 73 void calculateTypes(); 74 void createOutputSegments(); 75 void layoutMemory(); 76 void createHeader(); 77 78 void addSection(OutputSection *sec); 79 80 void addSections(); 81 82 void createCustomSections(); 83 void createSyntheticSections(); 84 void finalizeSections(); 85 86 // Custom sections 87 void createRelocSections(); 88 89 void writeHeader(); 90 void writeSections(); 91 92 uint64_t fileSize = 0; 93 94 std::vector<WasmInitEntry> initFunctions; 95 llvm::StringMap<std::vector<InputSection *>> customSectionMapping; 96 97 // Elements that are used to construct the final output 98 std::string header; 99 std::vector<OutputSection *> outputSections; 100 101 std::unique_ptr<FileOutputBuffer> buffer; 102 103 std::vector<OutputSegment *> segments; 104 llvm::SmallDenseMap<StringRef, OutputSegment *> segmentMap; 105 }; 106 107 } // anonymous namespace 108 109 void Writer::calculateCustomSections() { 110 log("calculateCustomSections"); 111 bool stripDebug = config->stripDebug || config->stripAll; 112 for (ObjFile *file : symtab->objectFiles) { 113 for (InputSection *section : file->customSections) { 114 StringRef name = section->getName(); 115 // These custom sections are known the linker and synthesized rather than 116 // blindly copied. 117 if (name == "linking" || name == "name" || name == "producers" || 118 name == "target_features" || name.startswith("reloc.")) 119 continue; 120 // These custom sections are generated by `clang -fembed-bitcode`. 121 // These are used by the rust toolchain to ship LTO data along with 122 // compiled object code, but they don't want this included in the linker 123 // output. 124 if (name == ".llvmbc" || name == ".llvmcmd") 125 continue; 126 // Strip debug section in that option was specified. 127 if (stripDebug && name.startswith(".debug_")) 128 continue; 129 // Otherwise include custom sections by default and concatenate their 130 // contents. 131 customSectionMapping[name].push_back(section); 132 } 133 } 134 } 135 136 void Writer::createCustomSections() { 137 log("createCustomSections"); 138 for (auto &pair : customSectionMapping) { 139 StringRef name = pair.first(); 140 LLVM_DEBUG(dbgs() << "createCustomSection: " << name << "\n"); 141 142 OutputSection *sec = make<CustomSection>(std::string(name), pair.second); 143 if (config->relocatable || config->emitRelocs) { 144 auto *sym = make<OutputSectionSymbol>(sec); 145 out.linkingSec->addToSymtab(sym); 146 sec->sectionSym = sym; 147 } 148 addSection(sec); 149 } 150 } 151 152 // Create relocations sections in the final output. 153 // These are only created when relocatable output is requested. 154 void Writer::createRelocSections() { 155 log("createRelocSections"); 156 // Don't use iterator here since we are adding to OutputSection 157 size_t origSize = outputSections.size(); 158 for (size_t i = 0; i < origSize; i++) { 159 LLVM_DEBUG(dbgs() << "check section " << i << "\n"); 160 OutputSection *sec = outputSections[i]; 161 162 // Count the number of needed sections. 163 uint32_t count = sec->getNumRelocations(); 164 if (!count) 165 continue; 166 167 StringRef name; 168 if (sec->type == WASM_SEC_DATA) 169 name = "reloc.DATA"; 170 else if (sec->type == WASM_SEC_CODE) 171 name = "reloc.CODE"; 172 else if (sec->type == WASM_SEC_CUSTOM) 173 name = saver.save("reloc." + sec->name); 174 else 175 llvm_unreachable( 176 "relocations only supported for code, data, or custom sections"); 177 178 addSection(make<RelocSection>(name, sec)); 179 } 180 } 181 182 void Writer::populateProducers() { 183 for (ObjFile *file : symtab->objectFiles) { 184 const WasmProducerInfo &info = file->getWasmObj()->getProducerInfo(); 185 out.producersSec->addInfo(info); 186 } 187 } 188 189 void Writer::writeHeader() { 190 memcpy(buffer->getBufferStart(), header.data(), header.size()); 191 } 192 193 void Writer::writeSections() { 194 uint8_t *buf = buffer->getBufferStart(); 195 parallelForEach(outputSections, [buf](OutputSection *s) { 196 assert(s->isNeeded()); 197 s->writeTo(buf); 198 }); 199 } 200 201 // Fix the memory layout of the output binary. This assigns memory offsets 202 // to each of the input data sections as well as the explicit stack region. 203 // The default memory layout is as follows, from low to high. 204 // 205 // - initialized data (starting at Config->globalBase) 206 // - BSS data (not currently implemented in llvm) 207 // - explicit stack (Config->ZStackSize) 208 // - heap start / unallocated 209 // 210 // The --stack-first option means that stack is placed before any static data. 211 // This can be useful since it means that stack overflow traps immediately 212 // rather than overwriting global data, but also increases code size since all 213 // static data loads and stores requires larger offsets. 214 void Writer::layoutMemory() { 215 uint64_t memoryPtr = 0; 216 217 auto placeStack = [&]() { 218 if (config->relocatable || config->isPic) 219 return; 220 memoryPtr = alignTo(memoryPtr, stackAlignment); 221 if (config->zStackSize != alignTo(config->zStackSize, stackAlignment)) 222 error("stack size must be " + Twine(stackAlignment) + "-byte aligned"); 223 log("mem: stack size = " + Twine(config->zStackSize)); 224 log("mem: stack base = " + Twine(memoryPtr)); 225 memoryPtr += config->zStackSize; 226 auto *sp = cast<DefinedGlobal>(WasmSym::stackPointer); 227 switch (sp->global->global.InitExpr.Opcode) { 228 case WASM_OPCODE_I32_CONST: 229 sp->global->global.InitExpr.Value.Int32 = memoryPtr; 230 break; 231 case WASM_OPCODE_I64_CONST: 232 sp->global->global.InitExpr.Value.Int64 = memoryPtr; 233 break; 234 default: 235 llvm_unreachable("init expr must be i32/i64.const"); 236 } 237 log("mem: stack top = " + Twine(memoryPtr)); 238 }; 239 240 if (config->stackFirst) { 241 placeStack(); 242 } else { 243 memoryPtr = config->globalBase; 244 log("mem: global base = " + Twine(config->globalBase)); 245 } 246 247 if (WasmSym::globalBase) 248 WasmSym::globalBase->setVirtualAddress(memoryPtr); 249 250 uint64_t dataStart = memoryPtr; 251 252 // Arbitrarily set __dso_handle handle to point to the start of the data 253 // segments. 254 if (WasmSym::dsoHandle) 255 WasmSym::dsoHandle->setVirtualAddress(dataStart); 256 257 out.dylinkSec->memAlign = 0; 258 for (OutputSegment *seg : segments) { 259 out.dylinkSec->memAlign = std::max(out.dylinkSec->memAlign, seg->alignment); 260 memoryPtr = alignTo(memoryPtr, 1ULL << seg->alignment); 261 seg->startVA = memoryPtr; 262 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", seg->name, 263 memoryPtr, seg->size, seg->alignment)); 264 memoryPtr += seg->size; 265 266 if (WasmSym::tlsSize && seg->name == ".tdata") { 267 auto *tlsSize = cast<DefinedGlobal>(WasmSym::tlsSize); 268 assert(tlsSize->global->global.InitExpr.Opcode == WASM_OPCODE_I32_CONST); 269 tlsSize->global->global.InitExpr.Value.Int32 = seg->size; 270 271 auto *tlsAlign = cast<DefinedGlobal>(WasmSym::tlsAlign); 272 assert(tlsAlign->global->global.InitExpr.Opcode == WASM_OPCODE_I32_CONST); 273 tlsAlign->global->global.InitExpr.Value.Int32 = int64_t{1} 274 << seg->alignment; 275 } 276 } 277 278 // Make space for the memory initialization flag 279 if (WasmSym::initMemoryFlag) { 280 memoryPtr = alignTo(memoryPtr, 4); 281 WasmSym::initMemoryFlag->setVirtualAddress(memoryPtr); 282 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", 283 "__wasm_init_memory_flag", memoryPtr, 4, 4)); 284 memoryPtr += 4; 285 } 286 287 if (WasmSym::dataEnd) 288 WasmSym::dataEnd->setVirtualAddress(memoryPtr); 289 290 log("mem: static data = " + Twine(memoryPtr - dataStart)); 291 292 if (config->shared) { 293 out.dylinkSec->memSize = memoryPtr; 294 return; 295 } 296 297 if (!config->stackFirst) 298 placeStack(); 299 300 // Set `__heap_base` to directly follow the end of the stack or global data. 301 // The fact that this comes last means that a malloc/brk implementation 302 // can grow the heap at runtime. 303 log("mem: heap base = " + Twine(memoryPtr)); 304 if (WasmSym::heapBase) 305 WasmSym::heapBase->setVirtualAddress(memoryPtr); 306 307 uint64_t maxMemorySetting = 1ULL << (config->is64 ? 48 : 32); 308 309 if (config->initialMemory != 0) { 310 if (config->initialMemory != alignTo(config->initialMemory, WasmPageSize)) 311 error("initial memory must be " + Twine(WasmPageSize) + "-byte aligned"); 312 if (memoryPtr > config->initialMemory) 313 error("initial memory too small, " + Twine(memoryPtr) + " bytes needed"); 314 if (config->initialMemory > maxMemorySetting) 315 error("initial memory too large, cannot be greater than " + 316 Twine(maxMemorySetting)); 317 memoryPtr = config->initialMemory; 318 } 319 out.dylinkSec->memSize = memoryPtr; 320 out.memorySec->numMemoryPages = 321 alignTo(memoryPtr, WasmPageSize) / WasmPageSize; 322 log("mem: total pages = " + Twine(out.memorySec->numMemoryPages)); 323 324 // Check max if explicitly supplied or required by shared memory 325 if (config->maxMemory != 0 || config->sharedMemory) { 326 if (config->maxMemory != alignTo(config->maxMemory, WasmPageSize)) 327 error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned"); 328 if (memoryPtr > config->maxMemory) 329 error("maximum memory too small, " + Twine(memoryPtr) + " bytes needed"); 330 if (config->maxMemory > maxMemorySetting) 331 error("maximum memory too large, cannot be greater than " + 332 Twine(maxMemorySetting)); 333 out.memorySec->maxMemoryPages = config->maxMemory / WasmPageSize; 334 log("mem: max pages = " + Twine(out.memorySec->maxMemoryPages)); 335 } 336 } 337 338 void Writer::addSection(OutputSection *sec) { 339 if (!sec->isNeeded()) 340 return; 341 log("addSection: " + toString(*sec)); 342 sec->sectionIndex = outputSections.size(); 343 outputSections.push_back(sec); 344 } 345 346 // If a section name is valid as a C identifier (which is rare because of 347 // the leading '.'), linkers are expected to define __start_<secname> and 348 // __stop_<secname> symbols. They are at beginning and end of the section, 349 // respectively. This is not requested by the ELF standard, but GNU ld and 350 // gold provide the feature, and used by many programs. 351 static void addStartStopSymbols(const OutputSegment *seg) { 352 StringRef name = seg->name; 353 if (!isValidCIdentifier(name)) 354 return; 355 LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << name << "\n"); 356 uint32_t start = seg->startVA; 357 uint32_t stop = start + seg->size; 358 symtab->addOptionalDataSymbol(saver.save("__start_" + name), start); 359 symtab->addOptionalDataSymbol(saver.save("__stop_" + name), stop); 360 } 361 362 void Writer::addSections() { 363 addSection(out.dylinkSec); 364 addSection(out.typeSec); 365 addSection(out.importSec); 366 addSection(out.functionSec); 367 addSection(out.tableSec); 368 addSection(out.memorySec); 369 addSection(out.eventSec); 370 addSection(out.globalSec); 371 addSection(out.exportSec); 372 addSection(out.startSec); 373 addSection(out.elemSec); 374 addSection(out.dataCountSec); 375 376 addSection(make<CodeSection>(out.functionSec->inputFunctions)); 377 addSection(make<DataSection>(segments)); 378 379 createCustomSections(); 380 381 addSection(out.linkingSec); 382 if (config->emitRelocs || config->relocatable) { 383 createRelocSections(); 384 } 385 386 addSection(out.nameSec); 387 addSection(out.producersSec); 388 addSection(out.targetFeaturesSec); 389 } 390 391 void Writer::finalizeSections() { 392 for (OutputSection *s : outputSections) { 393 s->setOffset(fileSize); 394 s->finalizeContents(); 395 fileSize += s->getSize(); 396 } 397 } 398 399 void Writer::populateTargetFeatures() { 400 StringMap<std::string> used; 401 StringMap<std::string> required; 402 StringMap<std::string> disallowed; 403 SmallSet<std::string, 8> &allowed = out.targetFeaturesSec->features; 404 bool tlsUsed = false; 405 406 // Only infer used features if user did not specify features 407 bool inferFeatures = !config->features.hasValue(); 408 409 if (!inferFeatures) { 410 auto &explicitFeatures = config->features.getValue(); 411 allowed.insert(explicitFeatures.begin(), explicitFeatures.end()); 412 if (!config->checkFeatures) 413 return; 414 } 415 416 // Find the sets of used, required, and disallowed features 417 for (ObjFile *file : symtab->objectFiles) { 418 StringRef fileName(file->getName()); 419 for (auto &feature : file->getWasmObj()->getTargetFeatures()) { 420 switch (feature.Prefix) { 421 case WASM_FEATURE_PREFIX_USED: 422 used.insert({feature.Name, std::string(fileName)}); 423 break; 424 case WASM_FEATURE_PREFIX_REQUIRED: 425 used.insert({feature.Name, std::string(fileName)}); 426 required.insert({feature.Name, std::string(fileName)}); 427 break; 428 case WASM_FEATURE_PREFIX_DISALLOWED: 429 disallowed.insert({feature.Name, std::string(fileName)}); 430 break; 431 default: 432 error("Unrecognized feature policy prefix " + 433 std::to_string(feature.Prefix)); 434 } 435 } 436 437 // Find TLS data segments 438 auto isTLS = [](InputSegment *segment) { 439 StringRef name = segment->getName(); 440 return segment->live && 441 (name.startswith(".tdata") || name.startswith(".tbss")); 442 }; 443 tlsUsed = tlsUsed || 444 std::any_of(file->segments.begin(), file->segments.end(), isTLS); 445 } 446 447 if (inferFeatures) 448 for (const auto &key : used.keys()) 449 allowed.insert(std::string(key)); 450 451 if (!config->relocatable && allowed.count("atomics") && 452 !config->sharedMemory) { 453 if (inferFeatures) 454 error(Twine("'atomics' feature is used by ") + used["atomics"] + 455 ", so --shared-memory must be used"); 456 else 457 error("'atomics' feature is used, so --shared-memory must be used"); 458 } 459 460 if (!config->checkFeatures) 461 return; 462 463 if (config->sharedMemory) { 464 if (disallowed.count("shared-mem")) 465 error("--shared-memory is disallowed by " + disallowed["shared-mem"] + 466 " because it was not compiled with 'atomics' or 'bulk-memory' " 467 "features."); 468 469 for (auto feature : {"atomics", "bulk-memory"}) 470 if (!allowed.count(feature)) 471 error(StringRef("'") + feature + 472 "' feature must be used in order to use shared memory"); 473 } 474 475 if (tlsUsed) { 476 for (auto feature : {"atomics", "bulk-memory"}) 477 if (!allowed.count(feature)) 478 error(StringRef("'") + feature + 479 "' feature must be used in order to use thread-local storage"); 480 } 481 482 // Validate that used features are allowed in output 483 if (!inferFeatures) { 484 for (auto &feature : used.keys()) { 485 if (!allowed.count(std::string(feature))) 486 error(Twine("Target feature '") + feature + "' used by " + 487 used[feature] + " is not allowed."); 488 } 489 } 490 491 // Validate the required and disallowed constraints for each file 492 for (ObjFile *file : symtab->objectFiles) { 493 StringRef fileName(file->getName()); 494 SmallSet<std::string, 8> objectFeatures; 495 for (auto &feature : file->getWasmObj()->getTargetFeatures()) { 496 if (feature.Prefix == WASM_FEATURE_PREFIX_DISALLOWED) 497 continue; 498 objectFeatures.insert(feature.Name); 499 if (disallowed.count(feature.Name)) 500 error(Twine("Target feature '") + feature.Name + "' used in " + 501 fileName + " is disallowed by " + disallowed[feature.Name] + 502 ". Use --no-check-features to suppress."); 503 } 504 for (auto &feature : required.keys()) { 505 if (!objectFeatures.count(std::string(feature))) 506 error(Twine("Missing target feature '") + feature + "' in " + fileName + 507 ", required by " + required[feature] + 508 ". Use --no-check-features to suppress."); 509 } 510 } 511 } 512 513 void Writer::calculateImports() { 514 for (Symbol *sym : symtab->getSymbols()) { 515 if (!sym->isUndefined()) 516 continue; 517 if (sym->isWeak() && !config->relocatable) 518 continue; 519 if (!sym->isLive()) 520 continue; 521 if (!sym->isUsedInRegularObj) 522 continue; 523 // We don't generate imports for data symbols. They however can be imported 524 // as GOT entries. 525 if (isa<DataSymbol>(sym)) 526 continue; 527 528 LLVM_DEBUG(dbgs() << "import: " << sym->getName() << "\n"); 529 out.importSec->addImport(sym); 530 } 531 } 532 533 void Writer::calculateExports() { 534 if (config->relocatable) 535 return; 536 537 if (!config->relocatable && !config->importMemory) 538 out.exportSec->exports.push_back( 539 WasmExport{"memory", WASM_EXTERNAL_MEMORY, 0}); 540 541 if (!config->relocatable && config->exportTable) 542 out.exportSec->exports.push_back( 543 WasmExport{functionTableName, WASM_EXTERNAL_TABLE, 0}); 544 545 unsigned globalIndex = 546 out.importSec->getNumImportedGlobals() + out.globalSec->numGlobals(); 547 548 for (Symbol *sym : symtab->getSymbols()) { 549 if (!sym->isExported()) 550 continue; 551 if (!sym->isLive()) 552 continue; 553 554 StringRef name = sym->getName(); 555 WasmExport export_; 556 if (auto *f = dyn_cast<DefinedFunction>(sym)) { 557 if (Optional<StringRef> exportName = f->function->getExportName()) { 558 name = *exportName; 559 } 560 export_ = {name, WASM_EXTERNAL_FUNCTION, f->getFunctionIndex()}; 561 } else if (auto *g = dyn_cast<DefinedGlobal>(sym)) { 562 // TODO(sbc): Remove this check once to mutable global proposal is 563 // implement in all major browsers. 564 // See: https://github.com/WebAssembly/mutable-global 565 if (g->getGlobalType()->Mutable) { 566 // Only __stack_pointer and __tls_base should ever be create as mutable. 567 assert(g == WasmSym::stackPointer || g == WasmSym::tlsBase); 568 continue; 569 } 570 export_ = {name, WASM_EXTERNAL_GLOBAL, g->getGlobalIndex()}; 571 } else if (auto *e = dyn_cast<DefinedEvent>(sym)) { 572 export_ = {name, WASM_EXTERNAL_EVENT, e->getEventIndex()}; 573 } else { 574 auto *d = cast<DefinedData>(sym); 575 out.globalSec->dataAddressGlobals.push_back(d); 576 export_ = {name, WASM_EXTERNAL_GLOBAL, globalIndex++}; 577 } 578 579 LLVM_DEBUG(dbgs() << "Export: " << name << "\n"); 580 out.exportSec->exports.push_back(export_); 581 } 582 } 583 584 void Writer::populateSymtab() { 585 if (!config->relocatable && !config->emitRelocs) 586 return; 587 588 for (Symbol *sym : symtab->getSymbols()) 589 if (sym->isUsedInRegularObj && sym->isLive()) 590 out.linkingSec->addToSymtab(sym); 591 592 for (ObjFile *file : symtab->objectFiles) { 593 LLVM_DEBUG(dbgs() << "Local symtab entries: " << file->getName() << "\n"); 594 for (Symbol *sym : file->getSymbols()) 595 if (sym->isLocal() && !isa<SectionSymbol>(sym) && sym->isLive()) 596 out.linkingSec->addToSymtab(sym); 597 } 598 } 599 600 void Writer::calculateTypes() { 601 // The output type section is the union of the following sets: 602 // 1. Any signature used in the TYPE relocation 603 // 2. The signatures of all imported functions 604 // 3. The signatures of all defined functions 605 // 4. The signatures of all imported events 606 // 5. The signatures of all defined events 607 608 for (ObjFile *file : symtab->objectFiles) { 609 ArrayRef<WasmSignature> types = file->getWasmObj()->types(); 610 for (uint32_t i = 0; i < types.size(); i++) 611 if (file->typeIsUsed[i]) 612 file->typeMap[i] = out.typeSec->registerType(types[i]); 613 } 614 615 for (const Symbol *sym : out.importSec->importedSymbols) { 616 if (auto *f = dyn_cast<FunctionSymbol>(sym)) 617 out.typeSec->registerType(*f->signature); 618 else if (auto *e = dyn_cast<EventSymbol>(sym)) 619 out.typeSec->registerType(*e->signature); 620 } 621 622 for (const InputFunction *f : out.functionSec->inputFunctions) 623 out.typeSec->registerType(f->signature); 624 625 for (const InputEvent *e : out.eventSec->inputEvents) 626 out.typeSec->registerType(e->signature); 627 } 628 629 static void scanRelocations() { 630 for (ObjFile *file : symtab->objectFiles) { 631 LLVM_DEBUG(dbgs() << "scanRelocations: " << file->getName() << "\n"); 632 for (InputChunk *chunk : file->functions) 633 scanRelocations(chunk); 634 for (InputChunk *chunk : file->segments) 635 scanRelocations(chunk); 636 for (auto &p : file->customSections) 637 scanRelocations(p); 638 } 639 } 640 641 void Writer::assignIndexes() { 642 // Seal the import section, since other index spaces such as function and 643 // global are effected by the number of imports. 644 out.importSec->seal(); 645 646 for (InputFunction *func : symtab->syntheticFunctions) 647 out.functionSec->addFunction(func); 648 649 for (ObjFile *file : symtab->objectFiles) { 650 LLVM_DEBUG(dbgs() << "Functions: " << file->getName() << "\n"); 651 for (InputFunction *func : file->functions) 652 out.functionSec->addFunction(func); 653 } 654 655 for (InputGlobal *global : symtab->syntheticGlobals) 656 out.globalSec->addGlobal(global); 657 658 for (ObjFile *file : symtab->objectFiles) { 659 LLVM_DEBUG(dbgs() << "Globals: " << file->getName() << "\n"); 660 for (InputGlobal *global : file->globals) 661 out.globalSec->addGlobal(global); 662 } 663 664 for (ObjFile *file : symtab->objectFiles) { 665 LLVM_DEBUG(dbgs() << "Events: " << file->getName() << "\n"); 666 for (InputEvent *event : file->events) 667 out.eventSec->addEvent(event); 668 } 669 670 out.globalSec->assignIndexes(); 671 } 672 673 static StringRef getOutputDataSegmentName(StringRef name) { 674 // With PIC code we currently only support a single data segment since 675 // we only have a single __memory_base to use as our base address. 676 if (config->isPic) 677 return ".data"; 678 // We only support one thread-local segment, so we must merge the segments 679 // despite --no-merge-data-segments. 680 // We also need to merge .tbss into .tdata so they share the same offsets. 681 if (name.startswith(".tdata") || name.startswith(".tbss")) 682 return ".tdata"; 683 if (!config->mergeDataSegments) 684 return name; 685 if (name.startswith(".text.")) 686 return ".text"; 687 if (name.startswith(".data.")) 688 return ".data"; 689 if (name.startswith(".bss.")) 690 return ".bss"; 691 if (name.startswith(".rodata.")) 692 return ".rodata"; 693 return name; 694 } 695 696 void Writer::createOutputSegments() { 697 for (ObjFile *file : symtab->objectFiles) { 698 for (InputSegment *segment : file->segments) { 699 if (!segment->live) 700 continue; 701 StringRef name = getOutputDataSegmentName(segment->getName()); 702 OutputSegment *&s = segmentMap[name]; 703 if (s == nullptr) { 704 LLVM_DEBUG(dbgs() << "new segment: " << name << "\n"); 705 s = make<OutputSegment>(name); 706 if (config->sharedMemory || name == ".tdata") 707 s->initFlags = WASM_SEGMENT_IS_PASSIVE; 708 // Exported memories are guaranteed to be zero-initialized, so no need 709 // to emit data segments for bss sections. 710 // TODO: consider initializing bss sections with memory.fill 711 // instructions when memory is imported and bulk-memory is available. 712 if (!config->importMemory && !config->relocatable && 713 name.startswith(".bss")) 714 s->isBss = true; 715 segments.push_back(s); 716 } 717 s->addInputSegment(segment); 718 LLVM_DEBUG(dbgs() << "added data: " << name << ": " << s->size << "\n"); 719 } 720 } 721 722 // Sort segments by type, placing .bss last 723 std::stable_sort(segments.begin(), segments.end(), 724 [](const OutputSegment *a, const OutputSegment *b) { 725 auto order = [](StringRef name) { 726 return StringSwitch<int>(name) 727 .StartsWith(".rodata", 0) 728 .StartsWith(".data", 1) 729 .StartsWith(".tdata", 2) 730 .StartsWith(".bss", 4) 731 .Default(3); 732 }; 733 return order(a->name) < order(b->name); 734 }); 735 736 for (size_t i = 0; i < segments.size(); ++i) 737 segments[i]->index = i; 738 } 739 740 static void createFunction(DefinedFunction *func, StringRef bodyContent) { 741 std::string functionBody; 742 { 743 raw_string_ostream os(functionBody); 744 writeUleb128(os, bodyContent.size(), "function size"); 745 os << bodyContent; 746 } 747 ArrayRef<uint8_t> body = arrayRefFromStringRef(saver.save(functionBody)); 748 cast<SyntheticFunction>(func->function)->setBody(body); 749 } 750 751 bool Writer::needsPassiveInitialization(const OutputSegment *segment) { 752 return segment->initFlags & WASM_SEGMENT_IS_PASSIVE && 753 segment->name != ".tdata" && !segment->isBss; 754 } 755 756 bool Writer::hasPassiveInitializedSegments() { 757 return std::find_if(segments.begin(), segments.end(), 758 [this](const OutputSegment *s) { 759 return this->needsPassiveInitialization(s); 760 }) != segments.end(); 761 } 762 763 void Writer::createInitMemoryFunction() { 764 LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n"); 765 assert(WasmSym::initMemoryFlag); 766 uint32_t flagAddress = WasmSym::initMemoryFlag->getVirtualAddress(); 767 std::string bodyContent; 768 { 769 raw_string_ostream os(bodyContent); 770 writeUleb128(os, 0, "num locals"); 771 772 if (hasPassiveInitializedSegments()) { 773 // Initialize memory in a thread-safe manner. The thread that successfully 774 // increments the flag from 0 to 1 is is responsible for performing the 775 // memory initialization. Other threads go sleep on the flag until the 776 // first thread finishing initializing memory, increments the flag to 2, 777 // and wakes all the other threads. Once the flag has been set to 2, 778 // subsequently started threads will skip the sleep. All threads 779 // unconditionally drop their passive data segments once memory has been 780 // initialized. The generated code is as follows: 781 // 782 // (func $__wasm_init_memory 783 // (if 784 // (i32.atomic.rmw.cmpxchg align=2 offset=0 785 // (i32.const $__init_memory_flag) 786 // (i32.const 0) 787 // (i32.const 1) 788 // ) 789 // (then 790 // (drop 791 // (i32.atomic.wait align=2 offset=0 792 // (i32.const $__init_memory_flag) 793 // (i32.const 1) 794 // (i32.const -1) 795 // ) 796 // ) 797 // ) 798 // (else 799 // ( ... initialize data segments ... ) 800 // (i32.atomic.store align=2 offset=0 801 // (i32.const $__init_memory_flag) 802 // (i32.const 2) 803 // ) 804 // (drop 805 // (i32.atomic.notify align=2 offset=0 806 // (i32.const $__init_memory_flag) 807 // (i32.const -1u) 808 // ) 809 // ) 810 // ) 811 // ) 812 // ( ... drop data segments ... ) 813 // ) 814 815 // Atomically check whether this is the main thread. 816 writeI32Const(os, flagAddress, "flag address"); 817 writeI32Const(os, 0, "expected flag value"); 818 writeI32Const(os, 1, "flag value"); 819 writeU8(os, WASM_OPCODE_ATOMICS_PREFIX, "atomics prefix"); 820 writeUleb128(os, WASM_OPCODE_I32_RMW_CMPXCHG, "i32.atomic.rmw.cmpxchg"); 821 writeMemArg(os, 2, 0); 822 writeU8(os, WASM_OPCODE_IF, "IF"); 823 writeU8(os, WASM_TYPE_NORESULT, "blocktype"); 824 825 // Did not increment 0, so wait for main thread to initialize memory 826 writeI32Const(os, flagAddress, "flag address"); 827 writeI32Const(os, 1, "expected flag value"); 828 writeI64Const(os, -1, "timeout"); 829 writeU8(os, WASM_OPCODE_ATOMICS_PREFIX, "atomics prefix"); 830 writeUleb128(os, WASM_OPCODE_I32_ATOMIC_WAIT, "i32.atomic.wait"); 831 writeMemArg(os, 2, 0); 832 writeU8(os, WASM_OPCODE_DROP, "drop"); 833 834 writeU8(os, WASM_OPCODE_ELSE, "ELSE"); 835 836 // Did increment 0, so conditionally initialize passive data segments 837 for (const OutputSegment *s : segments) { 838 if (needsPassiveInitialization(s)) { 839 // destination address 840 writeI32Const(os, s->startVA, "destination address"); 841 // source segment offset 842 writeI32Const(os, 0, "segment offset"); 843 // memory region size 844 writeI32Const(os, s->size, "memory region size"); 845 // memory.init instruction 846 writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix"); 847 writeUleb128(os, WASM_OPCODE_MEMORY_INIT, "memory.init"); 848 writeUleb128(os, s->index, "segment index immediate"); 849 writeU8(os, 0, "memory index immediate"); 850 } 851 } 852 853 // Set flag to 2 to mark end of initialization 854 writeI32Const(os, flagAddress, "flag address"); 855 writeI32Const(os, 2, "flag value"); 856 writeU8(os, WASM_OPCODE_ATOMICS_PREFIX, "atomics prefix"); 857 writeUleb128(os, WASM_OPCODE_I32_ATOMIC_STORE, "i32.atomic.store"); 858 writeMemArg(os, 2, 0); 859 860 // Notify any waiters that memory initialization is complete 861 writeI32Const(os, flagAddress, "flag address"); 862 writeI32Const(os, -1, "number of waiters"); 863 writeU8(os, WASM_OPCODE_ATOMICS_PREFIX, "atomics prefix"); 864 writeUleb128(os, WASM_OPCODE_ATOMIC_NOTIFY, "atomic.notify"); 865 writeMemArg(os, 2, 0); 866 writeU8(os, WASM_OPCODE_DROP, "drop"); 867 868 writeU8(os, WASM_OPCODE_END, "END"); 869 870 // Unconditionally drop passive data segments 871 for (const OutputSegment *s : segments) { 872 if (needsPassiveInitialization(s)) { 873 // data.drop instruction 874 writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix"); 875 writeUleb128(os, WASM_OPCODE_DATA_DROP, "data.drop"); 876 writeUleb128(os, s->index, "segment index immediate"); 877 } 878 } 879 } 880 writeU8(os, WASM_OPCODE_END, "END"); 881 } 882 883 createFunction(WasmSym::initMemory, bodyContent); 884 } 885 886 // For -shared (PIC) output, we create create a synthetic function which will 887 // apply any relocations to the data segments on startup. This function is 888 // called __wasm_apply_relocs and is added at the beginning of __wasm_call_ctors 889 // before any of the constructors run. 890 void Writer::createApplyRelocationsFunction() { 891 LLVM_DEBUG(dbgs() << "createApplyRelocationsFunction\n"); 892 // First write the body's contents to a string. 893 std::string bodyContent; 894 { 895 raw_string_ostream os(bodyContent); 896 writeUleb128(os, 0, "num locals"); 897 for (const OutputSegment *seg : segments) 898 for (const InputSegment *inSeg : seg->inputSegments) 899 inSeg->generateRelocationCode(os); 900 writeU8(os, WASM_OPCODE_END, "END"); 901 } 902 903 createFunction(WasmSym::applyRelocs, bodyContent); 904 } 905 906 // Create synthetic "__wasm_call_ctors" function based on ctor functions 907 // in input object. 908 void Writer::createCallCtorsFunction() { 909 if (!WasmSym::callCtors->isLive()) 910 return; 911 912 // First write the body's contents to a string. 913 std::string bodyContent; 914 { 915 raw_string_ostream os(bodyContent); 916 writeUleb128(os, 0, "num locals"); 917 918 if (config->isPic) { 919 writeU8(os, WASM_OPCODE_CALL, "CALL"); 920 writeUleb128(os, WasmSym::applyRelocs->getFunctionIndex(), 921 "function index"); 922 } 923 924 // Call constructors 925 for (const WasmInitEntry &f : initFunctions) { 926 writeU8(os, WASM_OPCODE_CALL, "CALL"); 927 writeUleb128(os, f.sym->getFunctionIndex(), "function index"); 928 for (size_t i = 0; i < f.sym->signature->Returns.size(); i++) { 929 writeU8(os, WASM_OPCODE_DROP, "DROP"); 930 } 931 } 932 writeU8(os, WASM_OPCODE_END, "END"); 933 } 934 935 createFunction(WasmSym::callCtors, bodyContent); 936 } 937 938 void Writer::createInitTLSFunction() { 939 if (!WasmSym::initTLS->isLive()) 940 return; 941 942 std::string bodyContent; 943 { 944 raw_string_ostream os(bodyContent); 945 946 OutputSegment *tlsSeg = nullptr; 947 for (auto *seg : segments) { 948 if (seg->name == ".tdata") { 949 tlsSeg = seg; 950 break; 951 } 952 } 953 954 writeUleb128(os, 0, "num locals"); 955 if (tlsSeg) { 956 writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get"); 957 writeUleb128(os, 0, "local index"); 958 959 writeU8(os, WASM_OPCODE_GLOBAL_SET, "global.set"); 960 writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(), "global index"); 961 962 writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get"); 963 writeUleb128(os, 0, "local index"); 964 965 writeI32Const(os, 0, "segment offset"); 966 967 writeI32Const(os, tlsSeg->size, "memory region size"); 968 969 writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix"); 970 writeUleb128(os, WASM_OPCODE_MEMORY_INIT, "MEMORY.INIT"); 971 writeUleb128(os, tlsSeg->index, "segment index immediate"); 972 writeU8(os, 0, "memory index immediate"); 973 } 974 writeU8(os, WASM_OPCODE_END, "end function"); 975 } 976 977 createFunction(WasmSym::initTLS, bodyContent); 978 } 979 980 // Populate InitFunctions vector with init functions from all input objects. 981 // This is then used either when creating the output linking section or to 982 // synthesize the "__wasm_call_ctors" function. 983 void Writer::calculateInitFunctions() { 984 if (!config->relocatable && !WasmSym::callCtors->isLive()) 985 return; 986 987 for (ObjFile *file : symtab->objectFiles) { 988 const WasmLinkingData &l = file->getWasmObj()->linkingData(); 989 for (const WasmInitFunc &f : l.InitFunctions) { 990 FunctionSymbol *sym = file->getFunctionSymbol(f.Symbol); 991 // comdat exclusions can cause init functions be discarded. 992 if (sym->isDiscarded()) 993 continue; 994 assert(sym->isLive()); 995 if (sym->signature->Params.size() != 0) 996 error("constructor functions cannot take arguments: " + toString(*sym)); 997 LLVM_DEBUG(dbgs() << "initFunctions: " << toString(*sym) << "\n"); 998 initFunctions.emplace_back(WasmInitEntry{sym, f.Priority}); 999 } 1000 } 1001 1002 // Sort in order of priority (lowest first) so that they are called 1003 // in the correct order. 1004 llvm::stable_sort(initFunctions, 1005 [](const WasmInitEntry &l, const WasmInitEntry &r) { 1006 return l.priority < r.priority; 1007 }); 1008 } 1009 1010 void Writer::createSyntheticSections() { 1011 out.dylinkSec = make<DylinkSection>(); 1012 out.typeSec = make<TypeSection>(); 1013 out.importSec = make<ImportSection>(); 1014 out.functionSec = make<FunctionSection>(); 1015 out.tableSec = make<TableSection>(); 1016 out.memorySec = make<MemorySection>(); 1017 out.eventSec = make<EventSection>(); 1018 out.globalSec = make<GlobalSection>(); 1019 out.exportSec = make<ExportSection>(); 1020 out.startSec = make<StartSection>(hasPassiveInitializedSegments()); 1021 out.elemSec = make<ElemSection>(); 1022 out.dataCountSec = make<DataCountSection>(segments); 1023 out.linkingSec = make<LinkingSection>(initFunctions, segments); 1024 out.nameSec = make<NameSection>(); 1025 out.producersSec = make<ProducersSection>(); 1026 out.targetFeaturesSec = make<TargetFeaturesSection>(); 1027 } 1028 1029 void Writer::run() { 1030 if (config->relocatable || config->isPic) 1031 config->globalBase = 0; 1032 1033 // For PIC code the table base is assigned dynamically by the loader. 1034 // For non-PIC, we start at 1 so that accessing table index 0 always traps. 1035 if (!config->isPic) { 1036 config->tableBase = 1; 1037 if (WasmSym::definedTableBase) 1038 WasmSym::definedTableBase->setVirtualAddress(config->tableBase); 1039 } 1040 1041 log("-- createOutputSegments"); 1042 createOutputSegments(); 1043 log("-- createSyntheticSections"); 1044 createSyntheticSections(); 1045 log("-- populateProducers"); 1046 populateProducers(); 1047 log("-- populateTargetFeatures"); 1048 populateTargetFeatures(); 1049 log("-- calculateImports"); 1050 calculateImports(); 1051 log("-- layoutMemory"); 1052 layoutMemory(); 1053 1054 if (!config->relocatable) { 1055 // Create linker synthesized __start_SECNAME/__stop_SECNAME symbols 1056 // This has to be done after memory layout is performed. 1057 for (const OutputSegment *seg : segments) 1058 addStartStopSymbols(seg); 1059 } 1060 1061 log("-- scanRelocations"); 1062 scanRelocations(); 1063 log("-- assignIndexes"); 1064 assignIndexes(); 1065 log("-- calculateInitFunctions"); 1066 calculateInitFunctions(); 1067 1068 if (!config->relocatable) { 1069 // Create linker synthesized functions 1070 if (config->sharedMemory) 1071 createInitMemoryFunction(); 1072 if (config->isPic) 1073 createApplyRelocationsFunction(); 1074 createCallCtorsFunction(); 1075 } 1076 1077 if (!config->relocatable && config->sharedMemory && !config->shared) 1078 createInitTLSFunction(); 1079 1080 if (errorCount()) 1081 return; 1082 1083 log("-- calculateTypes"); 1084 calculateTypes(); 1085 log("-- calculateExports"); 1086 calculateExports(); 1087 log("-- calculateCustomSections"); 1088 calculateCustomSections(); 1089 log("-- populateSymtab"); 1090 populateSymtab(); 1091 log("-- addSections"); 1092 addSections(); 1093 1094 if (errorHandler().verbose) { 1095 log("Defined Functions: " + Twine(out.functionSec->inputFunctions.size())); 1096 log("Defined Globals : " + Twine(out.globalSec->numGlobals())); 1097 log("Defined Events : " + Twine(out.eventSec->inputEvents.size())); 1098 log("Function Imports : " + 1099 Twine(out.importSec->getNumImportedFunctions())); 1100 log("Global Imports : " + Twine(out.importSec->getNumImportedGlobals())); 1101 log("Event Imports : " + Twine(out.importSec->getNumImportedEvents())); 1102 for (ObjFile *file : symtab->objectFiles) 1103 file->dumpInfo(); 1104 } 1105 1106 createHeader(); 1107 log("-- finalizeSections"); 1108 finalizeSections(); 1109 1110 log("-- openFile"); 1111 openFile(); 1112 if (errorCount()) 1113 return; 1114 1115 writeHeader(); 1116 1117 log("-- writeSections"); 1118 writeSections(); 1119 if (errorCount()) 1120 return; 1121 1122 if (Error e = buffer->commit()) 1123 fatal("failed to write the output file: " + toString(std::move(e))); 1124 } 1125 1126 // Open a result file. 1127 void Writer::openFile() { 1128 log("writing: " + config->outputFile); 1129 1130 Expected<std::unique_ptr<FileOutputBuffer>> bufferOrErr = 1131 FileOutputBuffer::create(config->outputFile, fileSize, 1132 FileOutputBuffer::F_executable); 1133 1134 if (!bufferOrErr) 1135 error("failed to open " + config->outputFile + ": " + 1136 toString(bufferOrErr.takeError())); 1137 else 1138 buffer = std::move(*bufferOrErr); 1139 } 1140 1141 void Writer::createHeader() { 1142 raw_string_ostream os(header); 1143 writeBytes(os, WasmMagic, sizeof(WasmMagic), "wasm magic"); 1144 writeU32(os, WasmVersion, "wasm version"); 1145 os.flush(); 1146 fileSize += header.size(); 1147 } 1148 1149 void writeResult() { Writer().run(); } 1150 1151 } // namespace wasm 1152 } // namespace lld 1153