1 //===- SyntheticSections.cpp ----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains linker-synthesized sections. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "SyntheticSections.h" 14 15 #include "InputChunks.h" 16 #include "InputEvent.h" 17 #include "InputGlobal.h" 18 #include "OutputSegment.h" 19 #include "SymbolTable.h" 20 #include "llvm/Support/Path.h" 21 22 using namespace llvm; 23 using namespace llvm::wasm; 24 25 namespace lld { 26 namespace wasm { 27 28 OutStruct out; 29 30 namespace { 31 32 // Some synthetic sections (e.g. "name" and "linking") have subsections. 33 // Just like the synthetic sections themselves these need to be created before 34 // they can be written out (since they are preceded by their length). This 35 // class is used to create subsections and then write them into the stream 36 // of the parent section. 37 class SubSection { 38 public: 39 explicit SubSection(uint32_t type) : type(type) {} 40 41 void writeTo(raw_ostream &to) { 42 os.flush(); 43 writeUleb128(to, type, "subsection type"); 44 writeUleb128(to, body.size(), "subsection size"); 45 to.write(body.data(), body.size()); 46 } 47 48 private: 49 uint32_t type; 50 std::string body; 51 52 public: 53 raw_string_ostream os{body}; 54 }; 55 56 } // namespace 57 58 void DylinkSection::writeBody() { 59 raw_ostream &os = bodyOutputStream; 60 61 writeUleb128(os, memSize, "MemSize"); 62 writeUleb128(os, memAlign, "MemAlign"); 63 writeUleb128(os, out.elemSec->numEntries(), "TableSize"); 64 writeUleb128(os, 0, "TableAlign"); 65 writeUleb128(os, symtab->sharedFiles.size(), "Needed"); 66 for (auto *so : symtab->sharedFiles) 67 writeStr(os, llvm::sys::path::filename(so->getName()), "so name"); 68 } 69 70 uint32_t TypeSection::registerType(const WasmSignature &sig) { 71 auto pair = typeIndices.insert(std::make_pair(sig, types.size())); 72 if (pair.second) { 73 LLVM_DEBUG(llvm::dbgs() << "type " << toString(sig) << "\n"); 74 types.push_back(&sig); 75 } 76 return pair.first->second; 77 } 78 79 uint32_t TypeSection::lookupType(const WasmSignature &sig) { 80 auto it = typeIndices.find(sig); 81 if (it == typeIndices.end()) { 82 error("type not found: " + toString(sig)); 83 return 0; 84 } 85 return it->second; 86 } 87 88 void TypeSection::writeBody() { 89 writeUleb128(bodyOutputStream, types.size(), "type count"); 90 for (const WasmSignature *sig : types) 91 writeSig(bodyOutputStream, *sig); 92 } 93 94 uint32_t ImportSection::getNumImports() const { 95 assert(isSealed); 96 uint32_t numImports = importedSymbols.size() + gotSymbols.size(); 97 if (config->importMemory) 98 ++numImports; 99 if (config->importTable) 100 ++numImports; 101 return numImports; 102 } 103 104 void ImportSection::addGOTEntry(Symbol *sym) { 105 assert(!isSealed); 106 if (sym->hasGOTIndex()) 107 return; 108 LLVM_DEBUG(dbgs() << "addGOTEntry: " << toString(*sym) << "\n"); 109 sym->setGOTIndex(numImportedGlobals++); 110 gotSymbols.push_back(sym); 111 } 112 113 void ImportSection::addImport(Symbol *sym) { 114 assert(!isSealed); 115 importedSymbols.emplace_back(sym); 116 if (auto *f = dyn_cast<FunctionSymbol>(sym)) 117 f->setFunctionIndex(numImportedFunctions++); 118 else if (auto *g = dyn_cast<GlobalSymbol>(sym)) 119 g->setGlobalIndex(numImportedGlobals++); 120 else 121 cast<EventSymbol>(sym)->setEventIndex(numImportedEvents++); 122 } 123 124 void ImportSection::writeBody() { 125 raw_ostream &os = bodyOutputStream; 126 127 writeUleb128(os, getNumImports(), "import count"); 128 129 if (config->importMemory) { 130 WasmImport import; 131 import.Module = defaultModule; 132 import.Field = "memory"; 133 import.Kind = WASM_EXTERNAL_MEMORY; 134 import.Memory.Flags = 0; 135 import.Memory.Initial = out.memorySec->numMemoryPages; 136 if (out.memorySec->maxMemoryPages != 0 || config->sharedMemory) { 137 import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX; 138 import.Memory.Maximum = out.memorySec->maxMemoryPages; 139 } 140 if (config->sharedMemory) 141 import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED; 142 writeImport(os, import); 143 } 144 145 if (config->importTable) { 146 uint32_t tableSize = config->tableBase + out.elemSec->numEntries(); 147 WasmImport import; 148 import.Module = defaultModule; 149 import.Field = functionTableName; 150 import.Kind = WASM_EXTERNAL_TABLE; 151 import.Table.ElemType = WASM_TYPE_FUNCREF; 152 import.Table.Limits = {0, tableSize, 0}; 153 writeImport(os, import); 154 } 155 156 for (const Symbol *sym : importedSymbols) { 157 WasmImport import; 158 if (auto *f = dyn_cast<UndefinedFunction>(sym)) { 159 import.Field = f->importName; 160 import.Module = f->importModule; 161 } else if (auto *g = dyn_cast<UndefinedGlobal>(sym)) { 162 import.Field = g->importName; 163 import.Module = g->importModule; 164 } else { 165 import.Field = sym->getName(); 166 import.Module = defaultModule; 167 } 168 169 if (auto *functionSym = dyn_cast<FunctionSymbol>(sym)) { 170 import.Kind = WASM_EXTERNAL_FUNCTION; 171 import.SigIndex = out.typeSec->lookupType(*functionSym->signature); 172 } else if (auto *globalSym = dyn_cast<GlobalSymbol>(sym)) { 173 import.Kind = WASM_EXTERNAL_GLOBAL; 174 import.Global = *globalSym->getGlobalType(); 175 } else { 176 auto *eventSym = cast<EventSymbol>(sym); 177 import.Kind = WASM_EXTERNAL_EVENT; 178 import.Event.Attribute = eventSym->getEventType()->Attribute; 179 import.Event.SigIndex = out.typeSec->lookupType(*eventSym->signature); 180 } 181 writeImport(os, import); 182 } 183 184 for (const Symbol *sym : gotSymbols) { 185 WasmImport import; 186 import.Kind = WASM_EXTERNAL_GLOBAL; 187 import.Global = {WASM_TYPE_I32, true}; 188 if (isa<DataSymbol>(sym)) 189 import.Module = "GOT.mem"; 190 else 191 import.Module = "GOT.func"; 192 import.Field = sym->getName(); 193 writeImport(os, import); 194 } 195 } 196 197 void FunctionSection::writeBody() { 198 raw_ostream &os = bodyOutputStream; 199 200 writeUleb128(os, inputFunctions.size(), "function count"); 201 for (const InputFunction *func : inputFunctions) 202 writeUleb128(os, out.typeSec->lookupType(func->signature), "sig index"); 203 } 204 205 void FunctionSection::addFunction(InputFunction *func) { 206 if (!func->live) 207 return; 208 uint32_t functionIndex = 209 out.importSec->getNumImportedFunctions() + inputFunctions.size(); 210 inputFunctions.emplace_back(func); 211 func->setFunctionIndex(functionIndex); 212 } 213 214 void TableSection::writeBody() { 215 uint32_t tableSize = config->tableBase + out.elemSec->numEntries(); 216 217 raw_ostream &os = bodyOutputStream; 218 writeUleb128(os, 1, "table count"); 219 WasmLimits limits; 220 if (config->growableTable) 221 limits = {0, tableSize, 0}; 222 else 223 limits = {WASM_LIMITS_FLAG_HAS_MAX, tableSize, tableSize}; 224 writeTableType(os, WasmTable{WASM_TYPE_FUNCREF, limits}); 225 } 226 227 void MemorySection::writeBody() { 228 raw_ostream &os = bodyOutputStream; 229 230 bool hasMax = maxMemoryPages != 0 || config->sharedMemory; 231 writeUleb128(os, 1, "memory count"); 232 unsigned flags = 0; 233 if (hasMax) 234 flags |= WASM_LIMITS_FLAG_HAS_MAX; 235 if (config->sharedMemory) 236 flags |= WASM_LIMITS_FLAG_IS_SHARED; 237 writeUleb128(os, flags, "memory limits flags"); 238 writeUleb128(os, numMemoryPages, "initial pages"); 239 if (hasMax) 240 writeUleb128(os, maxMemoryPages, "max pages"); 241 } 242 243 void GlobalSection::assignIndexes() { 244 uint32_t globalIndex = out.importSec->getNumImportedGlobals(); 245 for (InputGlobal *g : inputGlobals) 246 g->setGlobalIndex(globalIndex++); 247 for (Symbol *sym : staticGotSymbols) 248 sym->setGOTIndex(globalIndex++); 249 isSealed = true; 250 } 251 252 void GlobalSection::addStaticGOTEntry(Symbol *sym) { 253 assert(!isSealed); 254 if (sym->requiresGOT) 255 return; 256 LLVM_DEBUG(dbgs() << "addStaticGOTEntry: " << sym->getName() << " " 257 << toString(sym->kind()) << "\n"); 258 sym->requiresGOT = true; 259 if (auto *F = dyn_cast<FunctionSymbol>(sym)) 260 out.elemSec->addEntry(F); 261 staticGotSymbols.push_back(sym); 262 } 263 264 void GlobalSection::writeBody() { 265 raw_ostream &os = bodyOutputStream; 266 267 writeUleb128(os, numGlobals(), "global count"); 268 for (InputGlobal *g : inputGlobals) 269 writeGlobal(os, g->global); 270 for (const Symbol *sym : staticGotSymbols) { 271 WasmGlobal global; 272 global.Type = {WASM_TYPE_I32, false}; 273 global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; 274 if (auto *d = dyn_cast<DefinedData>(sym)) 275 global.InitExpr.Value.Int32 = d->getVirtualAddress(); 276 else if (auto *f = dyn_cast<FunctionSymbol>(sym)) 277 global.InitExpr.Value.Int32 = f->getTableIndex(); 278 else { 279 assert(isa<UndefinedData>(sym)); 280 global.InitExpr.Value.Int32 = 0; 281 } 282 writeGlobal(os, global); 283 } 284 for (const DefinedData *sym : dataAddressGlobals) { 285 WasmGlobal global; 286 global.Type = {WASM_TYPE_I32, false}; 287 global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; 288 global.InitExpr.Value.Int32 = sym->getVirtualAddress(); 289 writeGlobal(os, global); 290 } 291 } 292 293 void GlobalSection::addGlobal(InputGlobal *global) { 294 assert(!isSealed); 295 if (!global->live) 296 return; 297 inputGlobals.push_back(global); 298 } 299 300 void EventSection::writeBody() { 301 raw_ostream &os = bodyOutputStream; 302 303 writeUleb128(os, inputEvents.size(), "event count"); 304 for (InputEvent *e : inputEvents) { 305 e->event.Type.SigIndex = out.typeSec->lookupType(e->signature); 306 writeEvent(os, e->event); 307 } 308 } 309 310 void EventSection::addEvent(InputEvent *event) { 311 if (!event->live) 312 return; 313 uint32_t eventIndex = 314 out.importSec->getNumImportedEvents() + inputEvents.size(); 315 LLVM_DEBUG(dbgs() << "addEvent: " << eventIndex << "\n"); 316 event->setEventIndex(eventIndex); 317 inputEvents.push_back(event); 318 } 319 320 void ExportSection::writeBody() { 321 raw_ostream &os = bodyOutputStream; 322 323 writeUleb128(os, exports.size(), "export count"); 324 for (const WasmExport &export_ : exports) 325 writeExport(os, export_); 326 } 327 328 bool StartSection::isNeeded() const { 329 return !config->relocatable && numSegments && config->sharedMemory; 330 } 331 332 void StartSection::writeBody() { 333 raw_ostream &os = bodyOutputStream; 334 writeUleb128(os, WasmSym::initMemory->getFunctionIndex(), "function index"); 335 } 336 337 void ElemSection::addEntry(FunctionSymbol *sym) { 338 if (sym->hasTableIndex()) 339 return; 340 sym->setTableIndex(config->tableBase + indirectFunctions.size()); 341 indirectFunctions.emplace_back(sym); 342 } 343 344 void ElemSection::writeBody() { 345 raw_ostream &os = bodyOutputStream; 346 347 writeUleb128(os, 1, "segment count"); 348 writeUleb128(os, 0, "table index"); 349 WasmInitExpr initExpr; 350 if (config->isPic) { 351 initExpr.Opcode = WASM_OPCODE_GLOBAL_GET; 352 initExpr.Value.Global = WasmSym::tableBase->getGlobalIndex(); 353 } else { 354 initExpr.Opcode = WASM_OPCODE_I32_CONST; 355 initExpr.Value.Int32 = config->tableBase; 356 } 357 writeInitExpr(os, initExpr); 358 writeUleb128(os, indirectFunctions.size(), "elem count"); 359 360 uint32_t tableIndex = config->tableBase; 361 for (const FunctionSymbol *sym : indirectFunctions) { 362 assert(sym->getTableIndex() == tableIndex); 363 writeUleb128(os, sym->getFunctionIndex(), "function index"); 364 ++tableIndex; 365 } 366 } 367 368 DataCountSection::DataCountSection(ArrayRef<OutputSegment *> segments) 369 : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT), 370 numSegments(std::count_if( 371 segments.begin(), segments.end(), 372 [](OutputSegment *const segment) { return !segment->isBss; })) {} 373 374 void DataCountSection::writeBody() { 375 writeUleb128(bodyOutputStream, numSegments, "data count"); 376 } 377 378 bool DataCountSection::isNeeded() const { 379 return numSegments && config->sharedMemory; 380 } 381 382 void LinkingSection::writeBody() { 383 raw_ostream &os = bodyOutputStream; 384 385 writeUleb128(os, WasmMetadataVersion, "Version"); 386 387 if (!symtabEntries.empty()) { 388 SubSection sub(WASM_SYMBOL_TABLE); 389 writeUleb128(sub.os, symtabEntries.size(), "num symbols"); 390 391 for (const Symbol *sym : symtabEntries) { 392 assert(sym->isDefined() || sym->isUndefined()); 393 WasmSymbolType kind = sym->getWasmType(); 394 uint32_t flags = sym->getFlags(); 395 396 writeU8(sub.os, kind, "sym kind"); 397 writeUleb128(sub.os, flags, "sym flags"); 398 399 if (auto *f = dyn_cast<FunctionSymbol>(sym)) { 400 writeUleb128(sub.os, f->getFunctionIndex(), "index"); 401 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 402 writeStr(sub.os, sym->getName(), "sym name"); 403 } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) { 404 writeUleb128(sub.os, g->getGlobalIndex(), "index"); 405 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 406 writeStr(sub.os, sym->getName(), "sym name"); 407 } else if (auto *e = dyn_cast<EventSymbol>(sym)) { 408 writeUleb128(sub.os, e->getEventIndex(), "index"); 409 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 410 writeStr(sub.os, sym->getName(), "sym name"); 411 } else if (isa<DataSymbol>(sym)) { 412 writeStr(sub.os, sym->getName(), "sym name"); 413 if (auto *dataSym = dyn_cast<DefinedData>(sym)) { 414 writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index"); 415 writeUleb128(sub.os, dataSym->getOutputSegmentOffset(), 416 "data offset"); 417 writeUleb128(sub.os, dataSym->getSize(), "data size"); 418 } 419 } else { 420 auto *s = cast<OutputSectionSymbol>(sym); 421 writeUleb128(sub.os, s->section->sectionIndex, "sym section index"); 422 } 423 } 424 425 sub.writeTo(os); 426 } 427 428 if (dataSegments.size()) { 429 SubSection sub(WASM_SEGMENT_INFO); 430 writeUleb128(sub.os, dataSegments.size(), "num data segments"); 431 for (const OutputSegment *s : dataSegments) { 432 writeStr(sub.os, s->name, "segment name"); 433 writeUleb128(sub.os, s->alignment, "alignment"); 434 writeUleb128(sub.os, 0, "flags"); 435 } 436 sub.writeTo(os); 437 } 438 439 if (!initFunctions.empty()) { 440 SubSection sub(WASM_INIT_FUNCS); 441 writeUleb128(sub.os, initFunctions.size(), "num init functions"); 442 for (const WasmInitEntry &f : initFunctions) { 443 writeUleb128(sub.os, f.priority, "priority"); 444 writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index"); 445 } 446 sub.writeTo(os); 447 } 448 449 struct ComdatEntry { 450 unsigned kind; 451 uint32_t index; 452 }; 453 std::map<StringRef, std::vector<ComdatEntry>> comdats; 454 455 for (const InputFunction *f : out.functionSec->inputFunctions) { 456 StringRef comdat = f->getComdatName(); 457 if (!comdat.empty()) 458 comdats[comdat].emplace_back( 459 ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()}); 460 } 461 for (uint32_t i = 0; i < dataSegments.size(); ++i) { 462 const auto &inputSegments = dataSegments[i]->inputSegments; 463 if (inputSegments.empty()) 464 continue; 465 StringRef comdat = inputSegments[0]->getComdatName(); 466 #ifndef NDEBUG 467 for (const InputSegment *isec : inputSegments) 468 assert(isec->getComdatName() == comdat); 469 #endif 470 if (!comdat.empty()) 471 comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i}); 472 } 473 474 if (!comdats.empty()) { 475 SubSection sub(WASM_COMDAT_INFO); 476 writeUleb128(sub.os, comdats.size(), "num comdats"); 477 for (const auto &c : comdats) { 478 writeStr(sub.os, c.first, "comdat name"); 479 writeUleb128(sub.os, 0, "comdat flags"); // flags for future use 480 writeUleb128(sub.os, c.second.size(), "num entries"); 481 for (const ComdatEntry &entry : c.second) { 482 writeU8(sub.os, entry.kind, "entry kind"); 483 writeUleb128(sub.os, entry.index, "entry index"); 484 } 485 } 486 sub.writeTo(os); 487 } 488 } 489 490 void LinkingSection::addToSymtab(Symbol *sym) { 491 sym->setOutputSymbolIndex(symtabEntries.size()); 492 symtabEntries.emplace_back(sym); 493 } 494 495 unsigned NameSection::numNames() const { 496 unsigned numNames = out.importSec->getNumImportedFunctions(); 497 for (const InputFunction *f : out.functionSec->inputFunctions) 498 if (!f->getName().empty() || !f->getDebugName().empty()) 499 ++numNames; 500 501 return numNames; 502 } 503 504 // Create the custom "name" section containing debug symbol names. 505 void NameSection::writeBody() { 506 SubSection sub(WASM_NAMES_FUNCTION); 507 writeUleb128(sub.os, numNames(), "name count"); 508 509 // Names must appear in function index order. As it happens importedSymbols 510 // and inputFunctions are numbered in order with imported functions coming 511 // first. 512 for (const Symbol *s : out.importSec->importedSymbols) { 513 if (auto *f = dyn_cast<FunctionSymbol>(s)) { 514 writeUleb128(sub.os, f->getFunctionIndex(), "func index"); 515 writeStr(sub.os, toString(*s), "symbol name"); 516 } 517 } 518 for (const InputFunction *f : out.functionSec->inputFunctions) { 519 if (!f->getName().empty()) { 520 writeUleb128(sub.os, f->getFunctionIndex(), "func index"); 521 if (!f->getDebugName().empty()) { 522 writeStr(sub.os, f->getDebugName(), "symbol name"); 523 } else { 524 writeStr(sub.os, maybeDemangleSymbol(f->getName()), "symbol name"); 525 } 526 } 527 } 528 529 sub.writeTo(bodyOutputStream); 530 } 531 532 void ProducersSection::addInfo(const WasmProducerInfo &info) { 533 for (auto &producers : 534 {std::make_pair(&info.Languages, &languages), 535 std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)}) 536 for (auto &producer : *producers.first) 537 if (producers.second->end() == 538 llvm::find_if(*producers.second, 539 [&](std::pair<std::string, std::string> seen) { 540 return seen.first == producer.first; 541 })) 542 producers.second->push_back(producer); 543 } 544 545 void ProducersSection::writeBody() { 546 auto &os = bodyOutputStream; 547 writeUleb128(os, fieldCount(), "field count"); 548 for (auto &field : 549 {std::make_pair("language", languages), 550 std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) { 551 if (field.second.empty()) 552 continue; 553 writeStr(os, field.first, "field name"); 554 writeUleb128(os, field.second.size(), "number of entries"); 555 for (auto &entry : field.second) { 556 writeStr(os, entry.first, "producer name"); 557 writeStr(os, entry.second, "producer version"); 558 } 559 } 560 } 561 562 void TargetFeaturesSection::writeBody() { 563 SmallVector<std::string, 8> emitted(features.begin(), features.end()); 564 llvm::sort(emitted); 565 auto &os = bodyOutputStream; 566 writeUleb128(os, emitted.size(), "feature count"); 567 for (auto &feature : emitted) { 568 writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix"); 569 writeStr(os, feature, "feature name"); 570 } 571 } 572 573 void RelocSection::writeBody() { 574 uint32_t count = sec->getNumRelocations(); 575 assert(sec->sectionIndex != UINT32_MAX); 576 writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section"); 577 writeUleb128(bodyOutputStream, count, "reloc count"); 578 sec->writeRelocations(bodyOutputStream); 579 } 580 581 } // namespace wasm 582 } // namespace lld 583