1 //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===// 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 "llvm/ADT/ArrayRef.h" 10 #include "llvm/ADT/DenseSet.h" 11 #include "llvm/ADT/SmallSet.h" 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/ADT/StringSet.h" 14 #include "llvm/ADT/StringSwitch.h" 15 #include "llvm/ADT/Triple.h" 16 #include "llvm/BinaryFormat/Wasm.h" 17 #include "llvm/MC/SubtargetFeature.h" 18 #include "llvm/Object/Binary.h" 19 #include "llvm/Object/Error.h" 20 #include "llvm/Object/ObjectFile.h" 21 #include "llvm/Object/SymbolicFile.h" 22 #include "llvm/Object/Wasm.h" 23 #include "llvm/Support/Endian.h" 24 #include "llvm/Support/Error.h" 25 #include "llvm/Support/ErrorHandling.h" 26 #include "llvm/Support/LEB128.h" 27 #include "llvm/Support/ScopedPrinter.h" 28 #include <algorithm> 29 #include <cassert> 30 #include <cstdint> 31 #include <cstring> 32 33 #define DEBUG_TYPE "wasm-object" 34 35 using namespace llvm; 36 using namespace object; 37 38 void WasmSymbol::print(raw_ostream &Out) const { 39 Out << "Name=" << Info.Name 40 << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x" 41 << Twine::utohexstr(Info.Flags); 42 if (!isTypeData()) { 43 Out << ", ElemIndex=" << Info.ElementIndex; 44 } else if (isDefined()) { 45 Out << ", Segment=" << Info.DataRef.Segment; 46 Out << ", Offset=" << Info.DataRef.Offset; 47 Out << ", Size=" << Info.DataRef.Size; 48 } 49 } 50 51 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 52 LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); } 53 #endif 54 55 Expected<std::unique_ptr<WasmObjectFile>> 56 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { 57 Error Err = Error::success(); 58 auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err); 59 if (Err) 60 return std::move(Err); 61 62 return std::move(ObjectFile); 63 } 64 65 #define VARINT7_MAX ((1 << 7) - 1) 66 #define VARINT7_MIN (-(1 << 7)) 67 #define VARUINT7_MAX (1 << 7) 68 #define VARUINT1_MAX (1) 69 70 static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) { 71 if (Ctx.Ptr == Ctx.End) 72 report_fatal_error("EOF while reading uint8"); 73 return *Ctx.Ptr++; 74 } 75 76 static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) { 77 if (Ctx.Ptr + 4 > Ctx.End) 78 report_fatal_error("EOF while reading uint32"); 79 uint32_t Result = support::endian::read32le(Ctx.Ptr); 80 Ctx.Ptr += 4; 81 return Result; 82 } 83 84 static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) { 85 if (Ctx.Ptr + 4 > Ctx.End) 86 report_fatal_error("EOF while reading float64"); 87 int32_t Result = 0; 88 memcpy(&Result, Ctx.Ptr, sizeof(Result)); 89 Ctx.Ptr += sizeof(Result); 90 return Result; 91 } 92 93 static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) { 94 if (Ctx.Ptr + 8 > Ctx.End) 95 report_fatal_error("EOF while reading float64"); 96 int64_t Result = 0; 97 memcpy(&Result, Ctx.Ptr, sizeof(Result)); 98 Ctx.Ptr += sizeof(Result); 99 return Result; 100 } 101 102 static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) { 103 unsigned Count; 104 const char *Error = nullptr; 105 uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error); 106 if (Error) 107 report_fatal_error(Error); 108 Ctx.Ptr += Count; 109 return Result; 110 } 111 112 static StringRef readString(WasmObjectFile::ReadContext &Ctx) { 113 uint32_t StringLen = readULEB128(Ctx); 114 if (Ctx.Ptr + StringLen > Ctx.End) 115 report_fatal_error("EOF while reading string"); 116 StringRef Return = 117 StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen); 118 Ctx.Ptr += StringLen; 119 return Return; 120 } 121 122 static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) { 123 unsigned Count; 124 const char *Error = nullptr; 125 uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error); 126 if (Error) 127 report_fatal_error(Error); 128 Ctx.Ptr += Count; 129 return Result; 130 } 131 132 static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) { 133 int64_t Result = readLEB128(Ctx); 134 if (Result > VARUINT1_MAX || Result < 0) 135 report_fatal_error("LEB is outside Varuint1 range"); 136 return Result; 137 } 138 139 static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) { 140 int64_t Result = readLEB128(Ctx); 141 if (Result > INT32_MAX || Result < INT32_MIN) 142 report_fatal_error("LEB is outside Varint32 range"); 143 return Result; 144 } 145 146 static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) { 147 uint64_t Result = readULEB128(Ctx); 148 if (Result > UINT32_MAX) 149 report_fatal_error("LEB is outside Varuint32 range"); 150 return Result; 151 } 152 153 static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) { 154 return readLEB128(Ctx); 155 } 156 157 static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) { 158 return readULEB128(Ctx); 159 } 160 161 static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) { 162 return readUint8(Ctx); 163 } 164 165 static Error readInitExpr(wasm::WasmInitExpr &Expr, 166 WasmObjectFile::ReadContext &Ctx) { 167 Expr.Opcode = readOpcode(Ctx); 168 169 switch (Expr.Opcode) { 170 case wasm::WASM_OPCODE_I32_CONST: 171 Expr.Value.Int32 = readVarint32(Ctx); 172 break; 173 case wasm::WASM_OPCODE_I64_CONST: 174 Expr.Value.Int64 = readVarint64(Ctx); 175 break; 176 case wasm::WASM_OPCODE_F32_CONST: 177 Expr.Value.Float32 = readFloat32(Ctx); 178 break; 179 case wasm::WASM_OPCODE_F64_CONST: 180 Expr.Value.Float64 = readFloat64(Ctx); 181 break; 182 case wasm::WASM_OPCODE_GLOBAL_GET: 183 Expr.Value.Global = readULEB128(Ctx); 184 break; 185 case wasm::WASM_OPCODE_REF_NULL: { 186 wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx)); 187 if (Ty != wasm::ValType::EXTERNREF) { 188 return make_error<GenericBinaryError>("invalid type for ref.null", 189 object_error::parse_failed); 190 } 191 break; 192 } 193 default: 194 return make_error<GenericBinaryError>("invalid opcode in init_expr", 195 object_error::parse_failed); 196 } 197 198 uint8_t EndOpcode = readOpcode(Ctx); 199 if (EndOpcode != wasm::WASM_OPCODE_END) { 200 return make_error<GenericBinaryError>("invalid init_expr", 201 object_error::parse_failed); 202 } 203 return Error::success(); 204 } 205 206 static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) { 207 wasm::WasmLimits Result; 208 Result.Flags = readVaruint32(Ctx); 209 Result.Minimum = readVaruint64(Ctx); 210 if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) 211 Result.Maximum = readVaruint64(Ctx); 212 return Result; 213 } 214 215 static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) { 216 wasm::WasmTableType TableType; 217 TableType.ElemType = readUint8(Ctx); 218 TableType.Limits = readLimits(Ctx); 219 return TableType; 220 } 221 222 static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx, 223 WasmSectionOrderChecker &Checker) { 224 Section.Offset = Ctx.Ptr - Ctx.Start; 225 Section.Type = readUint8(Ctx); 226 LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n"); 227 uint32_t Size = readVaruint32(Ctx); 228 if (Size == 0) 229 return make_error<StringError>("zero length section", 230 object_error::parse_failed); 231 if (Ctx.Ptr + Size > Ctx.End) 232 return make_error<StringError>("section too large", 233 object_error::parse_failed); 234 if (Section.Type == wasm::WASM_SEC_CUSTOM) { 235 WasmObjectFile::ReadContext SectionCtx; 236 SectionCtx.Start = Ctx.Ptr; 237 SectionCtx.Ptr = Ctx.Ptr; 238 SectionCtx.End = Ctx.Ptr + Size; 239 240 Section.Name = readString(SectionCtx); 241 242 uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start; 243 Ctx.Ptr += SectionNameSize; 244 Size -= SectionNameSize; 245 } 246 247 if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) { 248 return make_error<StringError>("out of order section type: " + 249 llvm::to_string(Section.Type), 250 object_error::parse_failed); 251 } 252 253 Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size); 254 Ctx.Ptr += Size; 255 return Error::success(); 256 } 257 258 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) 259 : ObjectFile(Binary::ID_Wasm, Buffer) { 260 ErrorAsOutParameter ErrAsOutParam(&Err); 261 Header.Magic = getData().substr(0, 4); 262 if (Header.Magic != StringRef("\0asm", 4)) { 263 Err = make_error<StringError>("invalid magic number", 264 object_error::parse_failed); 265 return; 266 } 267 268 ReadContext Ctx; 269 Ctx.Start = getData().bytes_begin(); 270 Ctx.Ptr = Ctx.Start + 4; 271 Ctx.End = Ctx.Start + getData().size(); 272 273 if (Ctx.Ptr + 4 > Ctx.End) { 274 Err = make_error<StringError>("missing version number", 275 object_error::parse_failed); 276 return; 277 } 278 279 Header.Version = readUint32(Ctx); 280 if (Header.Version != wasm::WasmVersion) { 281 Err = make_error<StringError>("invalid version number: " + 282 Twine(Header.Version), 283 object_error::parse_failed); 284 return; 285 } 286 287 WasmSectionOrderChecker Checker; 288 while (Ctx.Ptr < Ctx.End) { 289 WasmSection Sec; 290 if ((Err = readSection(Sec, Ctx, Checker))) 291 return; 292 if ((Err = parseSection(Sec))) 293 return; 294 295 Sections.push_back(Sec); 296 } 297 } 298 299 Error WasmObjectFile::parseSection(WasmSection &Sec) { 300 ReadContext Ctx; 301 Ctx.Start = Sec.Content.data(); 302 Ctx.End = Ctx.Start + Sec.Content.size(); 303 Ctx.Ptr = Ctx.Start; 304 switch (Sec.Type) { 305 case wasm::WASM_SEC_CUSTOM: 306 return parseCustomSection(Sec, Ctx); 307 case wasm::WASM_SEC_TYPE: 308 return parseTypeSection(Ctx); 309 case wasm::WASM_SEC_IMPORT: 310 return parseImportSection(Ctx); 311 case wasm::WASM_SEC_FUNCTION: 312 return parseFunctionSection(Ctx); 313 case wasm::WASM_SEC_TABLE: 314 return parseTableSection(Ctx); 315 case wasm::WASM_SEC_MEMORY: 316 return parseMemorySection(Ctx); 317 case wasm::WASM_SEC_TAG: 318 return parseTagSection(Ctx); 319 case wasm::WASM_SEC_GLOBAL: 320 return parseGlobalSection(Ctx); 321 case wasm::WASM_SEC_EXPORT: 322 return parseExportSection(Ctx); 323 case wasm::WASM_SEC_START: 324 return parseStartSection(Ctx); 325 case wasm::WASM_SEC_ELEM: 326 return parseElemSection(Ctx); 327 case wasm::WASM_SEC_CODE: 328 return parseCodeSection(Ctx); 329 case wasm::WASM_SEC_DATA: 330 return parseDataSection(Ctx); 331 case wasm::WASM_SEC_DATACOUNT: 332 return parseDataCountSection(Ctx); 333 default: 334 return make_error<GenericBinaryError>( 335 "invalid section type: " + Twine(Sec.Type), object_error::parse_failed); 336 } 337 } 338 339 Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) { 340 // Legacy "dylink" section support. 341 // See parseDylink0Section for the current "dylink.0" section parsing. 342 HasDylinkSection = true; 343 DylinkInfo.MemorySize = readVaruint32(Ctx); 344 DylinkInfo.MemoryAlignment = readVaruint32(Ctx); 345 DylinkInfo.TableSize = readVaruint32(Ctx); 346 DylinkInfo.TableAlignment = readVaruint32(Ctx); 347 uint32_t Count = readVaruint32(Ctx); 348 while (Count--) { 349 DylinkInfo.Needed.push_back(readString(Ctx)); 350 } 351 352 if (Ctx.Ptr != Ctx.End) 353 return make_error<GenericBinaryError>("dylink section ended prematurely", 354 object_error::parse_failed); 355 return Error::success(); 356 } 357 358 Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) { 359 // See 360 // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md 361 HasDylinkSection = true; 362 363 const uint8_t *OrigEnd = Ctx.End; 364 while (Ctx.Ptr < OrigEnd) { 365 Ctx.End = OrigEnd; 366 uint8_t Type = readUint8(Ctx); 367 uint32_t Size = readVaruint32(Ctx); 368 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size 369 << "\n"); 370 Ctx.End = Ctx.Ptr + Size; 371 uint32_t Count; 372 switch (Type) { 373 case wasm::WASM_DYLINK_MEM_INFO: 374 DylinkInfo.MemorySize = readVaruint32(Ctx); 375 DylinkInfo.MemoryAlignment = readVaruint32(Ctx); 376 DylinkInfo.TableSize = readVaruint32(Ctx); 377 DylinkInfo.TableAlignment = readVaruint32(Ctx); 378 break; 379 case wasm::WASM_DYLINK_NEEDED: 380 Count = readVaruint32(Ctx); 381 while (Count--) { 382 DylinkInfo.Needed.push_back(readString(Ctx)); 383 } 384 break; 385 case wasm::WASM_DYLINK_EXPORT_INFO: { 386 uint32_t Count = readVaruint32(Ctx); 387 while (Count--) { 388 DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)}); 389 } 390 break; 391 } 392 case wasm::WASM_DYLINK_IMPORT_INFO: { 393 uint32_t Count = readVaruint32(Ctx); 394 while (Count--) { 395 DylinkInfo.ImportInfo.push_back( 396 {readString(Ctx), readString(Ctx), readVaruint32(Ctx)}); 397 } 398 break; 399 } 400 default: 401 LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n"); 402 Ctx.Ptr += Size; 403 break; 404 } 405 if (Ctx.Ptr != Ctx.End) { 406 return make_error<GenericBinaryError>( 407 "dylink.0 sub-section ended prematurely", object_error::parse_failed); 408 } 409 } 410 411 if (Ctx.Ptr != Ctx.End) 412 return make_error<GenericBinaryError>("dylink.0 section ended prematurely", 413 object_error::parse_failed); 414 return Error::success(); 415 } 416 417 Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { 418 llvm::DenseSet<uint64_t> SeenFunctions; 419 llvm::DenseSet<uint64_t> SeenGlobals; 420 llvm::DenseSet<uint64_t> SeenSegments; 421 if (Functions.size() && !SeenCodeSection) { 422 return make_error<GenericBinaryError>("names must come after code section", 423 object_error::parse_failed); 424 } 425 426 while (Ctx.Ptr < Ctx.End) { 427 uint8_t Type = readUint8(Ctx); 428 uint32_t Size = readVaruint32(Ctx); 429 const uint8_t *SubSectionEnd = Ctx.Ptr + Size; 430 switch (Type) { 431 case wasm::WASM_NAMES_FUNCTION: 432 case wasm::WASM_NAMES_GLOBAL: 433 case wasm::WASM_NAMES_DATA_SEGMENT: { 434 uint32_t Count = readVaruint32(Ctx); 435 while (Count--) { 436 uint32_t Index = readVaruint32(Ctx); 437 StringRef Name = readString(Ctx); 438 wasm::NameType nameType = wasm::NameType::FUNCTION; 439 if (Type == wasm::WASM_NAMES_FUNCTION) { 440 if (!SeenFunctions.insert(Index).second) 441 return make_error<GenericBinaryError>( 442 "function named more than once", object_error::parse_failed); 443 if (!isValidFunctionIndex(Index) || Name.empty()) 444 return make_error<GenericBinaryError>("invalid name entry", 445 object_error::parse_failed); 446 447 if (isDefinedFunctionIndex(Index)) 448 getDefinedFunction(Index).DebugName = Name; 449 } else if (Type == wasm::WASM_NAMES_GLOBAL) { 450 nameType = wasm::NameType::GLOBAL; 451 if (!SeenGlobals.insert(Index).second) 452 return make_error<GenericBinaryError>("global named more than once", 453 object_error::parse_failed); 454 if (!isValidGlobalIndex(Index) || Name.empty()) 455 return make_error<GenericBinaryError>("invalid name entry", 456 object_error::parse_failed); 457 } else { 458 nameType = wasm::NameType::DATA_SEGMENT; 459 if (!SeenSegments.insert(Index).second) 460 return make_error<GenericBinaryError>( 461 "segment named more than once", object_error::parse_failed); 462 if (Index > DataSegments.size()) 463 return make_error<GenericBinaryError>("invalid named data segment", 464 object_error::parse_failed); 465 } 466 DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name}); 467 } 468 break; 469 } 470 // Ignore local names for now 471 case wasm::WASM_NAMES_LOCAL: 472 default: 473 Ctx.Ptr += Size; 474 break; 475 } 476 if (Ctx.Ptr != SubSectionEnd) 477 return make_error<GenericBinaryError>( 478 "name sub-section ended prematurely", object_error::parse_failed); 479 } 480 481 if (Ctx.Ptr != Ctx.End) 482 return make_error<GenericBinaryError>("name section ended prematurely", 483 object_error::parse_failed); 484 return Error::success(); 485 } 486 487 Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) { 488 HasLinkingSection = true; 489 if (Functions.size() && !SeenCodeSection) { 490 return make_error<GenericBinaryError>( 491 "linking data must come after code section", 492 object_error::parse_failed); 493 } 494 495 LinkingData.Version = readVaruint32(Ctx); 496 if (LinkingData.Version != wasm::WasmMetadataVersion) { 497 return make_error<GenericBinaryError>( 498 "unexpected metadata version: " + Twine(LinkingData.Version) + 499 " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")", 500 object_error::parse_failed); 501 } 502 503 const uint8_t *OrigEnd = Ctx.End; 504 while (Ctx.Ptr < OrigEnd) { 505 Ctx.End = OrigEnd; 506 uint8_t Type = readUint8(Ctx); 507 uint32_t Size = readVaruint32(Ctx); 508 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size 509 << "\n"); 510 Ctx.End = Ctx.Ptr + Size; 511 switch (Type) { 512 case wasm::WASM_SYMBOL_TABLE: 513 if (Error Err = parseLinkingSectionSymtab(Ctx)) 514 return Err; 515 break; 516 case wasm::WASM_SEGMENT_INFO: { 517 uint32_t Count = readVaruint32(Ctx); 518 if (Count > DataSegments.size()) 519 return make_error<GenericBinaryError>("too many segment names", 520 object_error::parse_failed); 521 for (uint32_t I = 0; I < Count; I++) { 522 DataSegments[I].Data.Name = readString(Ctx); 523 DataSegments[I].Data.Alignment = readVaruint32(Ctx); 524 DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx); 525 } 526 break; 527 } 528 case wasm::WASM_INIT_FUNCS: { 529 uint32_t Count = readVaruint32(Ctx); 530 LinkingData.InitFunctions.reserve(Count); 531 for (uint32_t I = 0; I < Count; I++) { 532 wasm::WasmInitFunc Init; 533 Init.Priority = readVaruint32(Ctx); 534 Init.Symbol = readVaruint32(Ctx); 535 if (!isValidFunctionSymbol(Init.Symbol)) 536 return make_error<GenericBinaryError>("invalid function symbol: " + 537 Twine(Init.Symbol), 538 object_error::parse_failed); 539 LinkingData.InitFunctions.emplace_back(Init); 540 } 541 break; 542 } 543 case wasm::WASM_COMDAT_INFO: 544 if (Error Err = parseLinkingSectionComdat(Ctx)) 545 return Err; 546 break; 547 default: 548 Ctx.Ptr += Size; 549 break; 550 } 551 if (Ctx.Ptr != Ctx.End) 552 return make_error<GenericBinaryError>( 553 "linking sub-section ended prematurely", object_error::parse_failed); 554 } 555 if (Ctx.Ptr != OrigEnd) 556 return make_error<GenericBinaryError>("linking section ended prematurely", 557 object_error::parse_failed); 558 return Error::success(); 559 } 560 561 Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { 562 uint32_t Count = readVaruint32(Ctx); 563 LinkingData.SymbolTable.reserve(Count); 564 Symbols.reserve(Count); 565 StringSet<> SymbolNames; 566 567 std::vector<wasm::WasmImport *> ImportedGlobals; 568 std::vector<wasm::WasmImport *> ImportedFunctions; 569 std::vector<wasm::WasmImport *> ImportedTags; 570 std::vector<wasm::WasmImport *> ImportedTables; 571 ImportedGlobals.reserve(Imports.size()); 572 ImportedFunctions.reserve(Imports.size()); 573 ImportedTags.reserve(Imports.size()); 574 ImportedTables.reserve(Imports.size()); 575 for (auto &I : Imports) { 576 if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION) 577 ImportedFunctions.emplace_back(&I); 578 else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL) 579 ImportedGlobals.emplace_back(&I); 580 else if (I.Kind == wasm::WASM_EXTERNAL_TAG) 581 ImportedTags.emplace_back(&I); 582 else if (I.Kind == wasm::WASM_EXTERNAL_TABLE) 583 ImportedTables.emplace_back(&I); 584 } 585 586 while (Count--) { 587 wasm::WasmSymbolInfo Info; 588 const wasm::WasmSignature *Signature = nullptr; 589 const wasm::WasmGlobalType *GlobalType = nullptr; 590 const wasm::WasmTableType *TableType = nullptr; 591 592 Info.Kind = readUint8(Ctx); 593 Info.Flags = readVaruint32(Ctx); 594 bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0; 595 596 switch (Info.Kind) { 597 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 598 Info.ElementIndex = readVaruint32(Ctx); 599 if (!isValidFunctionIndex(Info.ElementIndex) || 600 IsDefined != isDefinedFunctionIndex(Info.ElementIndex)) 601 return make_error<GenericBinaryError>("invalid function symbol index", 602 object_error::parse_failed); 603 if (IsDefined) { 604 Info.Name = readString(Ctx); 605 unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; 606 wasm::WasmFunction &Function = Functions[FuncIndex]; 607 Signature = &Signatures[Function.SigIndex]; 608 if (Function.SymbolName.empty()) 609 Function.SymbolName = Info.Name; 610 } else { 611 wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; 612 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 613 Info.Name = readString(Ctx); 614 Info.ImportName = Import.Field; 615 } else { 616 Info.Name = Import.Field; 617 } 618 Signature = &Signatures[Import.SigIndex]; 619 if (!Import.Module.empty()) { 620 Info.ImportModule = Import.Module; 621 } 622 } 623 break; 624 625 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 626 Info.ElementIndex = readVaruint32(Ctx); 627 if (!isValidGlobalIndex(Info.ElementIndex) || 628 IsDefined != isDefinedGlobalIndex(Info.ElementIndex)) 629 return make_error<GenericBinaryError>("invalid global symbol index", 630 object_error::parse_failed); 631 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 632 wasm::WASM_SYMBOL_BINDING_WEAK) 633 return make_error<GenericBinaryError>("undefined weak global symbol", 634 object_error::parse_failed); 635 if (IsDefined) { 636 Info.Name = readString(Ctx); 637 unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals; 638 wasm::WasmGlobal &Global = Globals[GlobalIndex]; 639 GlobalType = &Global.Type; 640 if (Global.SymbolName.empty()) 641 Global.SymbolName = Info.Name; 642 } else { 643 wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; 644 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 645 Info.Name = readString(Ctx); 646 Info.ImportName = Import.Field; 647 } else { 648 Info.Name = Import.Field; 649 } 650 GlobalType = &Import.Global; 651 if (!Import.Module.empty()) { 652 Info.ImportModule = Import.Module; 653 } 654 } 655 break; 656 657 case wasm::WASM_SYMBOL_TYPE_TABLE: 658 Info.ElementIndex = readVaruint32(Ctx); 659 if (!isValidTableNumber(Info.ElementIndex) || 660 IsDefined != isDefinedTableNumber(Info.ElementIndex)) 661 return make_error<GenericBinaryError>("invalid table symbol index", 662 object_error::parse_failed); 663 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 664 wasm::WASM_SYMBOL_BINDING_WEAK) 665 return make_error<GenericBinaryError>("undefined weak table symbol", 666 object_error::parse_failed); 667 if (IsDefined) { 668 Info.Name = readString(Ctx); 669 unsigned TableNumber = Info.ElementIndex - NumImportedTables; 670 wasm::WasmTable &Table = Tables[TableNumber]; 671 TableType = &Table.Type; 672 if (Table.SymbolName.empty()) 673 Table.SymbolName = Info.Name; 674 } else { 675 wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex]; 676 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 677 Info.Name = readString(Ctx); 678 Info.ImportName = Import.Field; 679 } else { 680 Info.Name = Import.Field; 681 } 682 TableType = &Import.Table; 683 if (!Import.Module.empty()) { 684 Info.ImportModule = Import.Module; 685 } 686 } 687 break; 688 689 case wasm::WASM_SYMBOL_TYPE_DATA: 690 Info.Name = readString(Ctx); 691 if (IsDefined) { 692 auto Index = readVaruint32(Ctx); 693 if (Index >= DataSegments.size()) 694 return make_error<GenericBinaryError>("invalid data symbol index", 695 object_error::parse_failed); 696 auto Offset = readVaruint64(Ctx); 697 auto Size = readVaruint64(Ctx); 698 size_t SegmentSize = DataSegments[Index].Data.Content.size(); 699 if (Offset > SegmentSize) 700 return make_error<GenericBinaryError>( 701 "invalid data symbol offset: `" + Info.Name + "` (offset: " + 702 Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")", 703 object_error::parse_failed); 704 Info.DataRef = wasm::WasmDataReference{Index, Offset, Size}; 705 } 706 break; 707 708 case wasm::WASM_SYMBOL_TYPE_SECTION: { 709 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != 710 wasm::WASM_SYMBOL_BINDING_LOCAL) 711 return make_error<GenericBinaryError>( 712 "section symbols must have local binding", 713 object_error::parse_failed); 714 Info.ElementIndex = readVaruint32(Ctx); 715 // Use somewhat unique section name as symbol name. 716 StringRef SectionName = Sections[Info.ElementIndex].Name; 717 Info.Name = SectionName; 718 break; 719 } 720 721 case wasm::WASM_SYMBOL_TYPE_TAG: { 722 Info.ElementIndex = readVaruint32(Ctx); 723 if (!isValidTagIndex(Info.ElementIndex) || 724 IsDefined != isDefinedTagIndex(Info.ElementIndex)) 725 return make_error<GenericBinaryError>("invalid tag symbol index", 726 object_error::parse_failed); 727 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 728 wasm::WASM_SYMBOL_BINDING_WEAK) 729 return make_error<GenericBinaryError>("undefined weak global symbol", 730 object_error::parse_failed); 731 if (IsDefined) { 732 Info.Name = readString(Ctx); 733 unsigned TagIndex = Info.ElementIndex - NumImportedTags; 734 wasm::WasmTag &Tag = Tags[TagIndex]; 735 Signature = &Signatures[Tag.SigIndex]; 736 if (Tag.SymbolName.empty()) 737 Tag.SymbolName = Info.Name; 738 739 } else { 740 wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex]; 741 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 742 Info.Name = readString(Ctx); 743 Info.ImportName = Import.Field; 744 } else { 745 Info.Name = Import.Field; 746 } 747 Signature = &Signatures[Import.SigIndex]; 748 if (!Import.Module.empty()) { 749 Info.ImportModule = Import.Module; 750 } 751 } 752 break; 753 } 754 755 default: 756 return make_error<GenericBinaryError>("invalid symbol type: " + 757 Twine(unsigned(Info.Kind)), 758 object_error::parse_failed); 759 } 760 761 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != 762 wasm::WASM_SYMBOL_BINDING_LOCAL && 763 !SymbolNames.insert(Info.Name).second) 764 return make_error<GenericBinaryError>("duplicate symbol name " + 765 Twine(Info.Name), 766 object_error::parse_failed); 767 LinkingData.SymbolTable.emplace_back(Info); 768 Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType, 769 Signature); 770 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); 771 } 772 773 return Error::success(); 774 } 775 776 Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) { 777 uint32_t ComdatCount = readVaruint32(Ctx); 778 StringSet<> ComdatSet; 779 for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) { 780 StringRef Name = readString(Ctx); 781 if (Name.empty() || !ComdatSet.insert(Name).second) 782 return make_error<GenericBinaryError>("bad/duplicate COMDAT name " + 783 Twine(Name), 784 object_error::parse_failed); 785 LinkingData.Comdats.emplace_back(Name); 786 uint32_t Flags = readVaruint32(Ctx); 787 if (Flags != 0) 788 return make_error<GenericBinaryError>("unsupported COMDAT flags", 789 object_error::parse_failed); 790 791 uint32_t EntryCount = readVaruint32(Ctx); 792 while (EntryCount--) { 793 unsigned Kind = readVaruint32(Ctx); 794 unsigned Index = readVaruint32(Ctx); 795 switch (Kind) { 796 default: 797 return make_error<GenericBinaryError>("invalid COMDAT entry type", 798 object_error::parse_failed); 799 case wasm::WASM_COMDAT_DATA: 800 if (Index >= DataSegments.size()) 801 return make_error<GenericBinaryError>( 802 "COMDAT data index out of range", object_error::parse_failed); 803 if (DataSegments[Index].Data.Comdat != UINT32_MAX) 804 return make_error<GenericBinaryError>("data segment in two COMDATs", 805 object_error::parse_failed); 806 DataSegments[Index].Data.Comdat = ComdatIndex; 807 break; 808 case wasm::WASM_COMDAT_FUNCTION: 809 if (!isDefinedFunctionIndex(Index)) 810 return make_error<GenericBinaryError>( 811 "COMDAT function index out of range", object_error::parse_failed); 812 if (getDefinedFunction(Index).Comdat != UINT32_MAX) 813 return make_error<GenericBinaryError>("function in two COMDATs", 814 object_error::parse_failed); 815 getDefinedFunction(Index).Comdat = ComdatIndex; 816 break; 817 case wasm::WASM_COMDAT_SECTION: 818 if (Index >= Sections.size()) 819 return make_error<GenericBinaryError>( 820 "COMDAT section index out of range", object_error::parse_failed); 821 if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM) 822 return make_error<GenericBinaryError>( 823 "non-custom section in a COMDAT", object_error::parse_failed); 824 Sections[Index].Comdat = ComdatIndex; 825 break; 826 } 827 } 828 } 829 return Error::success(); 830 } 831 832 Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) { 833 llvm::SmallSet<StringRef, 3> FieldsSeen; 834 uint32_t Fields = readVaruint32(Ctx); 835 for (size_t I = 0; I < Fields; ++I) { 836 StringRef FieldName = readString(Ctx); 837 if (!FieldsSeen.insert(FieldName).second) 838 return make_error<GenericBinaryError>( 839 "producers section does not have unique fields", 840 object_error::parse_failed); 841 std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr; 842 if (FieldName == "language") { 843 ProducerVec = &ProducerInfo.Languages; 844 } else if (FieldName == "processed-by") { 845 ProducerVec = &ProducerInfo.Tools; 846 } else if (FieldName == "sdk") { 847 ProducerVec = &ProducerInfo.SDKs; 848 } else { 849 return make_error<GenericBinaryError>( 850 "producers section field is not named one of language, processed-by, " 851 "or sdk", 852 object_error::parse_failed); 853 } 854 uint32_t ValueCount = readVaruint32(Ctx); 855 llvm::SmallSet<StringRef, 8> ProducersSeen; 856 for (size_t J = 0; J < ValueCount; ++J) { 857 StringRef Name = readString(Ctx); 858 StringRef Version = readString(Ctx); 859 if (!ProducersSeen.insert(Name).second) { 860 return make_error<GenericBinaryError>( 861 "producers section contains repeated producer", 862 object_error::parse_failed); 863 } 864 ProducerVec->emplace_back(std::string(Name), std::string(Version)); 865 } 866 } 867 if (Ctx.Ptr != Ctx.End) 868 return make_error<GenericBinaryError>("producers section ended prematurely", 869 object_error::parse_failed); 870 return Error::success(); 871 } 872 873 Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) { 874 llvm::SmallSet<std::string, 8> FeaturesSeen; 875 uint32_t FeatureCount = readVaruint32(Ctx); 876 for (size_t I = 0; I < FeatureCount; ++I) { 877 wasm::WasmFeatureEntry Feature; 878 Feature.Prefix = readUint8(Ctx); 879 switch (Feature.Prefix) { 880 case wasm::WASM_FEATURE_PREFIX_USED: 881 case wasm::WASM_FEATURE_PREFIX_REQUIRED: 882 case wasm::WASM_FEATURE_PREFIX_DISALLOWED: 883 break; 884 default: 885 return make_error<GenericBinaryError>("unknown feature policy prefix", 886 object_error::parse_failed); 887 } 888 Feature.Name = std::string(readString(Ctx)); 889 if (!FeaturesSeen.insert(Feature.Name).second) 890 return make_error<GenericBinaryError>( 891 "target features section contains repeated feature \"" + 892 Feature.Name + "\"", 893 object_error::parse_failed); 894 TargetFeatures.push_back(Feature); 895 } 896 if (Ctx.Ptr != Ctx.End) 897 return make_error<GenericBinaryError>( 898 "target features section ended prematurely", 899 object_error::parse_failed); 900 return Error::success(); 901 } 902 903 Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { 904 uint32_t SectionIndex = readVaruint32(Ctx); 905 if (SectionIndex >= Sections.size()) 906 return make_error<GenericBinaryError>("invalid section index", 907 object_error::parse_failed); 908 WasmSection &Section = Sections[SectionIndex]; 909 uint32_t RelocCount = readVaruint32(Ctx); 910 uint32_t EndOffset = Section.Content.size(); 911 uint32_t PreviousOffset = 0; 912 while (RelocCount--) { 913 wasm::WasmRelocation Reloc = {}; 914 uint32_t type = readVaruint32(Ctx); 915 Reloc.Type = type; 916 Reloc.Offset = readVaruint32(Ctx); 917 if (Reloc.Offset < PreviousOffset) 918 return make_error<GenericBinaryError>("relocations not in offset order", 919 object_error::parse_failed); 920 PreviousOffset = Reloc.Offset; 921 Reloc.Index = readVaruint32(Ctx); 922 switch (type) { 923 case wasm::R_WASM_FUNCTION_INDEX_LEB: 924 case wasm::R_WASM_TABLE_INDEX_SLEB: 925 case wasm::R_WASM_TABLE_INDEX_SLEB64: 926 case wasm::R_WASM_TABLE_INDEX_I32: 927 case wasm::R_WASM_TABLE_INDEX_I64: 928 case wasm::R_WASM_TABLE_INDEX_REL_SLEB: 929 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64: 930 if (!isValidFunctionSymbol(Reloc.Index)) 931 return make_error<GenericBinaryError>( 932 "invalid relocation function index", object_error::parse_failed); 933 break; 934 case wasm::R_WASM_TABLE_NUMBER_LEB: 935 if (!isValidTableSymbol(Reloc.Index)) 936 return make_error<GenericBinaryError>("invalid relocation table index", 937 object_error::parse_failed); 938 break; 939 case wasm::R_WASM_TYPE_INDEX_LEB: 940 if (Reloc.Index >= Signatures.size()) 941 return make_error<GenericBinaryError>("invalid relocation type index", 942 object_error::parse_failed); 943 break; 944 case wasm::R_WASM_GLOBAL_INDEX_LEB: 945 // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data 946 // symbols to refer to their GOT entries. 947 if (!isValidGlobalSymbol(Reloc.Index) && 948 !isValidDataSymbol(Reloc.Index) && 949 !isValidFunctionSymbol(Reloc.Index)) 950 return make_error<GenericBinaryError>("invalid relocation global index", 951 object_error::parse_failed); 952 break; 953 case wasm::R_WASM_GLOBAL_INDEX_I32: 954 if (!isValidGlobalSymbol(Reloc.Index)) 955 return make_error<GenericBinaryError>("invalid relocation global index", 956 object_error::parse_failed); 957 break; 958 case wasm::R_WASM_TAG_INDEX_LEB: 959 if (!isValidTagSymbol(Reloc.Index)) 960 return make_error<GenericBinaryError>("invalid relocation tag index", 961 object_error::parse_failed); 962 break; 963 case wasm::R_WASM_MEMORY_ADDR_LEB: 964 case wasm::R_WASM_MEMORY_ADDR_SLEB: 965 case wasm::R_WASM_MEMORY_ADDR_I32: 966 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB: 967 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: 968 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: 969 if (!isValidDataSymbol(Reloc.Index)) 970 return make_error<GenericBinaryError>("invalid relocation data index", 971 object_error::parse_failed); 972 Reloc.Addend = readVarint32(Ctx); 973 break; 974 case wasm::R_WASM_MEMORY_ADDR_LEB64: 975 case wasm::R_WASM_MEMORY_ADDR_SLEB64: 976 case wasm::R_WASM_MEMORY_ADDR_I64: 977 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64: 978 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64: 979 if (!isValidDataSymbol(Reloc.Index)) 980 return make_error<GenericBinaryError>("invalid relocation data index", 981 object_error::parse_failed); 982 Reloc.Addend = readVarint64(Ctx); 983 break; 984 case wasm::R_WASM_FUNCTION_OFFSET_I32: 985 if (!isValidFunctionSymbol(Reloc.Index)) 986 return make_error<GenericBinaryError>( 987 "invalid relocation function index", object_error::parse_failed); 988 Reloc.Addend = readVarint32(Ctx); 989 break; 990 case wasm::R_WASM_FUNCTION_OFFSET_I64: 991 if (!isValidFunctionSymbol(Reloc.Index)) 992 return make_error<GenericBinaryError>( 993 "invalid relocation function index", object_error::parse_failed); 994 Reloc.Addend = readVarint64(Ctx); 995 break; 996 case wasm::R_WASM_SECTION_OFFSET_I32: 997 if (!isValidSectionSymbol(Reloc.Index)) 998 return make_error<GenericBinaryError>( 999 "invalid relocation section index", object_error::parse_failed); 1000 Reloc.Addend = readVarint32(Ctx); 1001 break; 1002 default: 1003 return make_error<GenericBinaryError>("invalid relocation type: " + 1004 Twine(type), 1005 object_error::parse_failed); 1006 } 1007 1008 // Relocations must fit inside the section, and must appear in order. They 1009 // also shouldn't overlap a function/element boundary, but we don't bother 1010 // to check that. 1011 uint64_t Size = 5; 1012 if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 || 1013 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 || 1014 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64) 1015 Size = 10; 1016 if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 || 1017 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 || 1018 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 || 1019 Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 || 1020 Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 || 1021 Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32) 1022 Size = 4; 1023 if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 || 1024 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 || 1025 Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64) 1026 Size = 8; 1027 if (Reloc.Offset + Size > EndOffset) 1028 return make_error<GenericBinaryError>("invalid relocation offset", 1029 object_error::parse_failed); 1030 1031 Section.Relocations.push_back(Reloc); 1032 } 1033 if (Ctx.Ptr != Ctx.End) 1034 return make_error<GenericBinaryError>("reloc section ended prematurely", 1035 object_error::parse_failed); 1036 return Error::success(); 1037 } 1038 1039 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) { 1040 if (Sec.Name == "dylink") { 1041 if (Error Err = parseDylinkSection(Ctx)) 1042 return Err; 1043 } else if (Sec.Name == "dylink.0") { 1044 if (Error Err = parseDylink0Section(Ctx)) 1045 return Err; 1046 } else if (Sec.Name == "name") { 1047 if (Error Err = parseNameSection(Ctx)) 1048 return Err; 1049 } else if (Sec.Name == "linking") { 1050 if (Error Err = parseLinkingSection(Ctx)) 1051 return Err; 1052 } else if (Sec.Name == "producers") { 1053 if (Error Err = parseProducersSection(Ctx)) 1054 return Err; 1055 } else if (Sec.Name == "target_features") { 1056 if (Error Err = parseTargetFeaturesSection(Ctx)) 1057 return Err; 1058 } else if (Sec.Name.startswith("reloc.")) { 1059 if (Error Err = parseRelocSection(Sec.Name, Ctx)) 1060 return Err; 1061 } 1062 return Error::success(); 1063 } 1064 1065 Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) { 1066 uint32_t Count = readVaruint32(Ctx); 1067 Signatures.reserve(Count); 1068 while (Count--) { 1069 wasm::WasmSignature Sig; 1070 uint8_t Form = readUint8(Ctx); 1071 if (Form != wasm::WASM_TYPE_FUNC) { 1072 return make_error<GenericBinaryError>("invalid signature type", 1073 object_error::parse_failed); 1074 } 1075 uint32_t ParamCount = readVaruint32(Ctx); 1076 Sig.Params.reserve(ParamCount); 1077 while (ParamCount--) { 1078 uint32_t ParamType = readUint8(Ctx); 1079 Sig.Params.push_back(wasm::ValType(ParamType)); 1080 } 1081 uint32_t ReturnCount = readVaruint32(Ctx); 1082 while (ReturnCount--) { 1083 uint32_t ReturnType = readUint8(Ctx); 1084 Sig.Returns.push_back(wasm::ValType(ReturnType)); 1085 } 1086 Signatures.push_back(std::move(Sig)); 1087 } 1088 if (Ctx.Ptr != Ctx.End) 1089 return make_error<GenericBinaryError>("type section ended prematurely", 1090 object_error::parse_failed); 1091 return Error::success(); 1092 } 1093 1094 Error WasmObjectFile::parseImportSection(ReadContext &Ctx) { 1095 uint32_t Count = readVaruint32(Ctx); 1096 uint32_t NumTypes = Signatures.size(); 1097 Imports.reserve(Count); 1098 for (uint32_t I = 0; I < Count; I++) { 1099 wasm::WasmImport Im; 1100 Im.Module = readString(Ctx); 1101 Im.Field = readString(Ctx); 1102 Im.Kind = readUint8(Ctx); 1103 switch (Im.Kind) { 1104 case wasm::WASM_EXTERNAL_FUNCTION: 1105 NumImportedFunctions++; 1106 Im.SigIndex = readVaruint32(Ctx); 1107 if (Im.SigIndex >= NumTypes) 1108 return make_error<GenericBinaryError>("invalid function type", 1109 object_error::parse_failed); 1110 break; 1111 case wasm::WASM_EXTERNAL_GLOBAL: 1112 NumImportedGlobals++; 1113 Im.Global.Type = readUint8(Ctx); 1114 Im.Global.Mutable = readVaruint1(Ctx); 1115 break; 1116 case wasm::WASM_EXTERNAL_MEMORY: 1117 Im.Memory = readLimits(Ctx); 1118 if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64) 1119 HasMemory64 = true; 1120 break; 1121 case wasm::WASM_EXTERNAL_TABLE: { 1122 Im.Table = readTableType(Ctx); 1123 NumImportedTables++; 1124 auto ElemType = Im.Table.ElemType; 1125 if (ElemType != wasm::WASM_TYPE_FUNCREF && 1126 ElemType != wasm::WASM_TYPE_EXTERNREF) 1127 return make_error<GenericBinaryError>("invalid table element type", 1128 object_error::parse_failed); 1129 break; 1130 } 1131 case wasm::WASM_EXTERNAL_TAG: 1132 NumImportedTags++; 1133 if (readUint8(Ctx) != 0) // Reserved 'attribute' field 1134 return make_error<GenericBinaryError>("invalid attribute", 1135 object_error::parse_failed); 1136 Im.SigIndex = readVaruint32(Ctx); 1137 if (Im.SigIndex >= NumTypes) 1138 return make_error<GenericBinaryError>("invalid tag type", 1139 object_error::parse_failed); 1140 break; 1141 default: 1142 return make_error<GenericBinaryError>("unexpected import kind", 1143 object_error::parse_failed); 1144 } 1145 Imports.push_back(Im); 1146 } 1147 if (Ctx.Ptr != Ctx.End) 1148 return make_error<GenericBinaryError>("import section ended prematurely", 1149 object_error::parse_failed); 1150 return Error::success(); 1151 } 1152 1153 Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) { 1154 uint32_t Count = readVaruint32(Ctx); 1155 Functions.reserve(Count); 1156 uint32_t NumTypes = Signatures.size(); 1157 while (Count--) { 1158 uint32_t Type = readVaruint32(Ctx); 1159 if (Type >= NumTypes) 1160 return make_error<GenericBinaryError>("invalid function type", 1161 object_error::parse_failed); 1162 wasm::WasmFunction F; 1163 F.SigIndex = Type; 1164 Functions.push_back(F); 1165 } 1166 if (Ctx.Ptr != Ctx.End) 1167 return make_error<GenericBinaryError>("function section ended prematurely", 1168 object_error::parse_failed); 1169 return Error::success(); 1170 } 1171 1172 Error WasmObjectFile::parseTableSection(ReadContext &Ctx) { 1173 TableSection = Sections.size(); 1174 uint32_t Count = readVaruint32(Ctx); 1175 Tables.reserve(Count); 1176 while (Count--) { 1177 wasm::WasmTable T; 1178 T.Type = readTableType(Ctx); 1179 T.Index = NumImportedTables + Tables.size(); 1180 Tables.push_back(T); 1181 auto ElemType = Tables.back().Type.ElemType; 1182 if (ElemType != wasm::WASM_TYPE_FUNCREF && 1183 ElemType != wasm::WASM_TYPE_EXTERNREF) { 1184 return make_error<GenericBinaryError>("invalid table element type", 1185 object_error::parse_failed); 1186 } 1187 } 1188 if (Ctx.Ptr != Ctx.End) 1189 return make_error<GenericBinaryError>("table section ended prematurely", 1190 object_error::parse_failed); 1191 return Error::success(); 1192 } 1193 1194 Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) { 1195 uint32_t Count = readVaruint32(Ctx); 1196 Memories.reserve(Count); 1197 while (Count--) { 1198 auto Limits = readLimits(Ctx); 1199 if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64) 1200 HasMemory64 = true; 1201 Memories.push_back(Limits); 1202 } 1203 if (Ctx.Ptr != Ctx.End) 1204 return make_error<GenericBinaryError>("memory section ended prematurely", 1205 object_error::parse_failed); 1206 return Error::success(); 1207 } 1208 1209 Error WasmObjectFile::parseTagSection(ReadContext &Ctx) { 1210 TagSection = Sections.size(); 1211 uint32_t Count = readVaruint32(Ctx); 1212 Tags.reserve(Count); 1213 uint32_t NumTypes = Signatures.size(); 1214 while (Count--) { 1215 if (readUint8(Ctx) != 0) // Reserved 'attribute' field 1216 return make_error<GenericBinaryError>("invalid attribute", 1217 object_error::parse_failed); 1218 uint32_t Type = readVaruint32(Ctx); 1219 if (Type >= NumTypes) 1220 return make_error<GenericBinaryError>("invalid tag type", 1221 object_error::parse_failed); 1222 wasm::WasmTag Tag; 1223 Tag.Index = NumImportedTags + Tags.size(); 1224 Tag.SigIndex = Type; 1225 Tags.push_back(Tag); 1226 } 1227 1228 if (Ctx.Ptr != Ctx.End) 1229 return make_error<GenericBinaryError>("tag section ended prematurely", 1230 object_error::parse_failed); 1231 return Error::success(); 1232 } 1233 1234 Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) { 1235 GlobalSection = Sections.size(); 1236 uint32_t Count = readVaruint32(Ctx); 1237 Globals.reserve(Count); 1238 while (Count--) { 1239 wasm::WasmGlobal Global; 1240 Global.Index = NumImportedGlobals + Globals.size(); 1241 Global.Type.Type = readUint8(Ctx); 1242 Global.Type.Mutable = readVaruint1(Ctx); 1243 if (Error Err = readInitExpr(Global.InitExpr, Ctx)) 1244 return Err; 1245 Globals.push_back(Global); 1246 } 1247 if (Ctx.Ptr != Ctx.End) 1248 return make_error<GenericBinaryError>("global section ended prematurely", 1249 object_error::parse_failed); 1250 return Error::success(); 1251 } 1252 1253 Error WasmObjectFile::parseExportSection(ReadContext &Ctx) { 1254 uint32_t Count = readVaruint32(Ctx); 1255 Exports.reserve(Count); 1256 for (uint32_t I = 0; I < Count; I++) { 1257 wasm::WasmExport Ex; 1258 Ex.Name = readString(Ctx); 1259 Ex.Kind = readUint8(Ctx); 1260 Ex.Index = readVaruint32(Ctx); 1261 switch (Ex.Kind) { 1262 case wasm::WASM_EXTERNAL_FUNCTION: 1263 1264 if (!isDefinedFunctionIndex(Ex.Index)) 1265 return make_error<GenericBinaryError>("invalid function export", 1266 object_error::parse_failed); 1267 getDefinedFunction(Ex.Index).ExportName = Ex.Name; 1268 break; 1269 case wasm::WASM_EXTERNAL_GLOBAL: 1270 if (!isValidGlobalIndex(Ex.Index)) 1271 return make_error<GenericBinaryError>("invalid global export", 1272 object_error::parse_failed); 1273 break; 1274 case wasm::WASM_EXTERNAL_TAG: 1275 if (!isValidTagIndex(Ex.Index)) 1276 return make_error<GenericBinaryError>("invalid tag export", 1277 object_error::parse_failed); 1278 break; 1279 case wasm::WASM_EXTERNAL_MEMORY: 1280 case wasm::WASM_EXTERNAL_TABLE: 1281 break; 1282 default: 1283 return make_error<GenericBinaryError>("unexpected export kind", 1284 object_error::parse_failed); 1285 } 1286 Exports.push_back(Ex); 1287 } 1288 if (Ctx.Ptr != Ctx.End) 1289 return make_error<GenericBinaryError>("export section ended prematurely", 1290 object_error::parse_failed); 1291 return Error::success(); 1292 } 1293 1294 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const { 1295 return Index < NumImportedFunctions + Functions.size(); 1296 } 1297 1298 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const { 1299 return Index >= NumImportedFunctions && isValidFunctionIndex(Index); 1300 } 1301 1302 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const { 1303 return Index < NumImportedGlobals + Globals.size(); 1304 } 1305 1306 bool WasmObjectFile::isValidTableNumber(uint32_t Index) const { 1307 return Index < NumImportedTables + Tables.size(); 1308 } 1309 1310 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const { 1311 return Index >= NumImportedGlobals && isValidGlobalIndex(Index); 1312 } 1313 1314 bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const { 1315 return Index >= NumImportedTables && isValidTableNumber(Index); 1316 } 1317 1318 bool WasmObjectFile::isValidTagIndex(uint32_t Index) const { 1319 return Index < NumImportedTags + Tags.size(); 1320 } 1321 1322 bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const { 1323 return Index >= NumImportedTags && isValidTagIndex(Index); 1324 } 1325 1326 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const { 1327 return Index < Symbols.size() && Symbols[Index].isTypeFunction(); 1328 } 1329 1330 bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const { 1331 return Index < Symbols.size() && Symbols[Index].isTypeTable(); 1332 } 1333 1334 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const { 1335 return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); 1336 } 1337 1338 bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const { 1339 return Index < Symbols.size() && Symbols[Index].isTypeTag(); 1340 } 1341 1342 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const { 1343 return Index < Symbols.size() && Symbols[Index].isTypeData(); 1344 } 1345 1346 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const { 1347 return Index < Symbols.size() && Symbols[Index].isTypeSection(); 1348 } 1349 1350 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) { 1351 assert(isDefinedFunctionIndex(Index)); 1352 return Functions[Index - NumImportedFunctions]; 1353 } 1354 1355 const wasm::WasmFunction & 1356 WasmObjectFile::getDefinedFunction(uint32_t Index) const { 1357 assert(isDefinedFunctionIndex(Index)); 1358 return Functions[Index - NumImportedFunctions]; 1359 } 1360 1361 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) { 1362 assert(isDefinedGlobalIndex(Index)); 1363 return Globals[Index - NumImportedGlobals]; 1364 } 1365 1366 wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) { 1367 assert(isDefinedTagIndex(Index)); 1368 return Tags[Index - NumImportedTags]; 1369 } 1370 1371 Error WasmObjectFile::parseStartSection(ReadContext &Ctx) { 1372 StartFunction = readVaruint32(Ctx); 1373 if (!isValidFunctionIndex(StartFunction)) 1374 return make_error<GenericBinaryError>("invalid start function", 1375 object_error::parse_failed); 1376 return Error::success(); 1377 } 1378 1379 Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) { 1380 SeenCodeSection = true; 1381 CodeSection = Sections.size(); 1382 uint32_t FunctionCount = readVaruint32(Ctx); 1383 if (FunctionCount != Functions.size()) { 1384 return make_error<GenericBinaryError>("invalid function count", 1385 object_error::parse_failed); 1386 } 1387 1388 for (uint32_t i = 0; i < FunctionCount; i++) { 1389 wasm::WasmFunction& Function = Functions[i]; 1390 const uint8_t *FunctionStart = Ctx.Ptr; 1391 uint32_t Size = readVaruint32(Ctx); 1392 const uint8_t *FunctionEnd = Ctx.Ptr + Size; 1393 1394 Function.CodeOffset = Ctx.Ptr - FunctionStart; 1395 Function.Index = NumImportedFunctions + i; 1396 Function.CodeSectionOffset = FunctionStart - Ctx.Start; 1397 Function.Size = FunctionEnd - FunctionStart; 1398 1399 uint32_t NumLocalDecls = readVaruint32(Ctx); 1400 Function.Locals.reserve(NumLocalDecls); 1401 while (NumLocalDecls--) { 1402 wasm::WasmLocalDecl Decl; 1403 Decl.Count = readVaruint32(Ctx); 1404 Decl.Type = readUint8(Ctx); 1405 Function.Locals.push_back(Decl); 1406 } 1407 1408 uint32_t BodySize = FunctionEnd - Ctx.Ptr; 1409 Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize); 1410 // This will be set later when reading in the linking metadata section. 1411 Function.Comdat = UINT32_MAX; 1412 Ctx.Ptr += BodySize; 1413 assert(Ctx.Ptr == FunctionEnd); 1414 } 1415 if (Ctx.Ptr != Ctx.End) 1416 return make_error<GenericBinaryError>("code section ended prematurely", 1417 object_error::parse_failed); 1418 return Error::success(); 1419 } 1420 1421 Error WasmObjectFile::parseElemSection(ReadContext &Ctx) { 1422 uint32_t Count = readVaruint32(Ctx); 1423 ElemSegments.reserve(Count); 1424 while (Count--) { 1425 wasm::WasmElemSegment Segment; 1426 Segment.Flags = readVaruint32(Ctx); 1427 1428 uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER | 1429 wasm::WASM_ELEM_SEGMENT_IS_PASSIVE | 1430 wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS; 1431 if (Segment.Flags & ~SupportedFlags) 1432 return make_error<GenericBinaryError>( 1433 "Unsupported flags for element segment", object_error::parse_failed); 1434 1435 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER) 1436 Segment.TableNumber = readVaruint32(Ctx); 1437 else 1438 Segment.TableNumber = 0; 1439 if (!isValidTableNumber(Segment.TableNumber)) 1440 return make_error<GenericBinaryError>("invalid TableNumber", 1441 object_error::parse_failed); 1442 1443 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) { 1444 Segment.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST; 1445 Segment.Offset.Value.Int32 = 0; 1446 } else { 1447 if (Error Err = readInitExpr(Segment.Offset, Ctx)) 1448 return Err; 1449 } 1450 1451 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) { 1452 Segment.ElemKind = readUint8(Ctx); 1453 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) { 1454 if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) && 1455 Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) { 1456 return make_error<GenericBinaryError>("invalid reference type", 1457 object_error::parse_failed); 1458 } 1459 } else { 1460 if (Segment.ElemKind != 0) 1461 return make_error<GenericBinaryError>("invalid elemtype", 1462 object_error::parse_failed); 1463 Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF); 1464 } 1465 } else { 1466 Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF); 1467 } 1468 1469 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) 1470 return make_error<GenericBinaryError>( 1471 "elem segment init expressions not yet implemented", 1472 object_error::parse_failed); 1473 1474 uint32_t NumElems = readVaruint32(Ctx); 1475 while (NumElems--) { 1476 Segment.Functions.push_back(readVaruint32(Ctx)); 1477 } 1478 ElemSegments.push_back(Segment); 1479 } 1480 if (Ctx.Ptr != Ctx.End) 1481 return make_error<GenericBinaryError>("elem section ended prematurely", 1482 object_error::parse_failed); 1483 return Error::success(); 1484 } 1485 1486 Error WasmObjectFile::parseDataSection(ReadContext &Ctx) { 1487 DataSection = Sections.size(); 1488 uint32_t Count = readVaruint32(Ctx); 1489 if (DataCount && Count != DataCount.getValue()) 1490 return make_error<GenericBinaryError>( 1491 "number of data segments does not match DataCount section"); 1492 DataSegments.reserve(Count); 1493 while (Count--) { 1494 WasmSegment Segment; 1495 Segment.Data.InitFlags = readVaruint32(Ctx); 1496 Segment.Data.MemoryIndex = 1497 (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX) 1498 ? readVaruint32(Ctx) 1499 : 0; 1500 if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) { 1501 if (Error Err = readInitExpr(Segment.Data.Offset, Ctx)) 1502 return Err; 1503 } else { 1504 Segment.Data.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST; 1505 Segment.Data.Offset.Value.Int32 = 0; 1506 } 1507 uint32_t Size = readVaruint32(Ctx); 1508 if (Size > (size_t)(Ctx.End - Ctx.Ptr)) 1509 return make_error<GenericBinaryError>("invalid segment size", 1510 object_error::parse_failed); 1511 Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size); 1512 // The rest of these Data fields are set later, when reading in the linking 1513 // metadata section. 1514 Segment.Data.Alignment = 0; 1515 Segment.Data.LinkingFlags = 0; 1516 Segment.Data.Comdat = UINT32_MAX; 1517 Segment.SectionOffset = Ctx.Ptr - Ctx.Start; 1518 Ctx.Ptr += Size; 1519 DataSegments.push_back(Segment); 1520 } 1521 if (Ctx.Ptr != Ctx.End) 1522 return make_error<GenericBinaryError>("data section ended prematurely", 1523 object_error::parse_failed); 1524 return Error::success(); 1525 } 1526 1527 Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) { 1528 DataCount = readVaruint32(Ctx); 1529 return Error::success(); 1530 } 1531 1532 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 1533 return Header; 1534 } 1535 1536 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; } 1537 1538 Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 1539 uint32_t Result = SymbolRef::SF_None; 1540 const WasmSymbol &Sym = getWasmSymbol(Symb); 1541 1542 LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n"); 1543 if (Sym.isBindingWeak()) 1544 Result |= SymbolRef::SF_Weak; 1545 if (!Sym.isBindingLocal()) 1546 Result |= SymbolRef::SF_Global; 1547 if (Sym.isHidden()) 1548 Result |= SymbolRef::SF_Hidden; 1549 if (!Sym.isDefined()) 1550 Result |= SymbolRef::SF_Undefined; 1551 if (Sym.isTypeFunction()) 1552 Result |= SymbolRef::SF_Executable; 1553 return Result; 1554 } 1555 1556 basic_symbol_iterator WasmObjectFile::symbol_begin() const { 1557 DataRefImpl Ref; 1558 Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null 1559 Ref.d.b = 0; // Symbol index 1560 return BasicSymbolRef(Ref, this); 1561 } 1562 1563 basic_symbol_iterator WasmObjectFile::symbol_end() const { 1564 DataRefImpl Ref; 1565 Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null 1566 Ref.d.b = Symbols.size(); // Symbol index 1567 return BasicSymbolRef(Ref, this); 1568 } 1569 1570 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const { 1571 return Symbols[Symb.d.b]; 1572 } 1573 1574 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const { 1575 return getWasmSymbol(Symb.getRawDataRefImpl()); 1576 } 1577 1578 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 1579 return getWasmSymbol(Symb).Info.Name; 1580 } 1581 1582 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 1583 auto &Sym = getWasmSymbol(Symb); 1584 if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION && 1585 isDefinedFunctionIndex(Sym.Info.ElementIndex)) 1586 return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset; 1587 else 1588 return getSymbolValue(Symb); 1589 } 1590 1591 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { 1592 switch (Sym.Info.Kind) { 1593 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1594 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1595 case wasm::WASM_SYMBOL_TYPE_TAG: 1596 case wasm::WASM_SYMBOL_TYPE_TABLE: 1597 return Sym.Info.ElementIndex; 1598 case wasm::WASM_SYMBOL_TYPE_DATA: { 1599 // The value of a data symbol is the segment offset, plus the symbol 1600 // offset within the segment. 1601 uint32_t SegmentIndex = Sym.Info.DataRef.Segment; 1602 const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data; 1603 if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST) { 1604 return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset; 1605 } else if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST) { 1606 return Segment.Offset.Value.Int64 + Sym.Info.DataRef.Offset; 1607 } else { 1608 llvm_unreachable("unknown init expr opcode"); 1609 } 1610 } 1611 case wasm::WASM_SYMBOL_TYPE_SECTION: 1612 return 0; 1613 } 1614 llvm_unreachable("invalid symbol type"); 1615 } 1616 1617 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 1618 return getWasmSymbolValue(getWasmSymbol(Symb)); 1619 } 1620 1621 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 1622 llvm_unreachable("not yet implemented"); 1623 return 0; 1624 } 1625 1626 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 1627 llvm_unreachable("not yet implemented"); 1628 return 0; 1629 } 1630 1631 Expected<SymbolRef::Type> 1632 WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 1633 const WasmSymbol &Sym = getWasmSymbol(Symb); 1634 1635 switch (Sym.Info.Kind) { 1636 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1637 return SymbolRef::ST_Function; 1638 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1639 return SymbolRef::ST_Other; 1640 case wasm::WASM_SYMBOL_TYPE_DATA: 1641 return SymbolRef::ST_Data; 1642 case wasm::WASM_SYMBOL_TYPE_SECTION: 1643 return SymbolRef::ST_Debug; 1644 case wasm::WASM_SYMBOL_TYPE_TAG: 1645 return SymbolRef::ST_Other; 1646 case wasm::WASM_SYMBOL_TYPE_TABLE: 1647 return SymbolRef::ST_Other; 1648 } 1649 1650 llvm_unreachable("unknown WasmSymbol::SymbolType"); 1651 return SymbolRef::ST_Other; 1652 } 1653 1654 Expected<section_iterator> 1655 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 1656 const WasmSymbol &Sym = getWasmSymbol(Symb); 1657 if (Sym.isUndefined()) 1658 return section_end(); 1659 1660 DataRefImpl Ref; 1661 Ref.d.a = getSymbolSectionIdImpl(Sym); 1662 return section_iterator(SectionRef(Ref, this)); 1663 } 1664 1665 uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const { 1666 const WasmSymbol &Sym = getWasmSymbol(Symb); 1667 return getSymbolSectionIdImpl(Sym); 1668 } 1669 1670 uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const { 1671 switch (Sym.Info.Kind) { 1672 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1673 return CodeSection; 1674 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1675 return GlobalSection; 1676 case wasm::WASM_SYMBOL_TYPE_DATA: 1677 return DataSection; 1678 case wasm::WASM_SYMBOL_TYPE_SECTION: 1679 return Sym.Info.ElementIndex; 1680 case wasm::WASM_SYMBOL_TYPE_TAG: 1681 return TagSection; 1682 case wasm::WASM_SYMBOL_TYPE_TABLE: 1683 return TableSection; 1684 default: 1685 llvm_unreachable("unknown WasmSymbol::SymbolType"); 1686 } 1687 } 1688 1689 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 1690 1691 Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const { 1692 const WasmSection &S = Sections[Sec.d.a]; 1693 #define ECase(X) \ 1694 case wasm::WASM_SEC_##X: \ 1695 return #X; 1696 switch (S.Type) { 1697 ECase(TYPE); 1698 ECase(IMPORT); 1699 ECase(FUNCTION); 1700 ECase(TABLE); 1701 ECase(MEMORY); 1702 ECase(GLOBAL); 1703 ECase(TAG); 1704 ECase(EXPORT); 1705 ECase(START); 1706 ECase(ELEM); 1707 ECase(CODE); 1708 ECase(DATA); 1709 ECase(DATACOUNT); 1710 case wasm::WASM_SEC_CUSTOM: 1711 return S.Name; 1712 default: 1713 return createStringError(object_error::invalid_section_index, ""); 1714 } 1715 #undef ECase 1716 } 1717 1718 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } 1719 1720 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const { 1721 return Sec.d.a; 1722 } 1723 1724 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 1725 const WasmSection &S = Sections[Sec.d.a]; 1726 return S.Content.size(); 1727 } 1728 1729 Expected<ArrayRef<uint8_t>> 1730 WasmObjectFile::getSectionContents(DataRefImpl Sec) const { 1731 const WasmSection &S = Sections[Sec.d.a]; 1732 // This will never fail since wasm sections can never be empty (user-sections 1733 // must have a name and non-user sections each have a defined structure). 1734 return S.Content; 1735 } 1736 1737 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 1738 return 1; 1739 } 1740 1741 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 1742 return false; 1743 } 1744 1745 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 1746 return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE; 1747 } 1748 1749 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 1750 return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA; 1751 } 1752 1753 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 1754 1755 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 1756 1757 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { 1758 DataRefImpl RelocRef; 1759 RelocRef.d.a = Ref.d.a; 1760 RelocRef.d.b = 0; 1761 return relocation_iterator(RelocationRef(RelocRef, this)); 1762 } 1763 1764 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const { 1765 const WasmSection &Sec = getWasmSection(Ref); 1766 DataRefImpl RelocRef; 1767 RelocRef.d.a = Ref.d.a; 1768 RelocRef.d.b = Sec.Relocations.size(); 1769 return relocation_iterator(RelocationRef(RelocRef, this)); 1770 } 1771 1772 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; } 1773 1774 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { 1775 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1776 return Rel.Offset; 1777 } 1778 1779 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const { 1780 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1781 if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB) 1782 return symbol_end(); 1783 DataRefImpl Sym; 1784 Sym.d.a = 1; 1785 Sym.d.b = Rel.Index; 1786 return symbol_iterator(SymbolRef(Sym, this)); 1787 } 1788 1789 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const { 1790 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1791 return Rel.Type; 1792 } 1793 1794 void WasmObjectFile::getRelocationTypeName( 1795 DataRefImpl Ref, SmallVectorImpl<char> &Result) const { 1796 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1797 StringRef Res = "Unknown"; 1798 1799 #define WASM_RELOC(name, value) \ 1800 case wasm::name: \ 1801 Res = #name; \ 1802 break; 1803 1804 switch (Rel.Type) { 1805 #include "llvm/BinaryFormat/WasmRelocs.def" 1806 } 1807 1808 #undef WASM_RELOC 1809 1810 Result.append(Res.begin(), Res.end()); 1811 } 1812 1813 section_iterator WasmObjectFile::section_begin() const { 1814 DataRefImpl Ref; 1815 Ref.d.a = 0; 1816 return section_iterator(SectionRef(Ref, this)); 1817 } 1818 1819 section_iterator WasmObjectFile::section_end() const { 1820 DataRefImpl Ref; 1821 Ref.d.a = Sections.size(); 1822 return section_iterator(SectionRef(Ref, this)); 1823 } 1824 1825 uint8_t WasmObjectFile::getBytesInAddress() const { 1826 return HasMemory64 ? 8 : 4; 1827 } 1828 1829 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 1830 1831 Triple::ArchType WasmObjectFile::getArch() const { 1832 return HasMemory64 ? Triple::wasm64 : Triple::wasm32; 1833 } 1834 1835 SubtargetFeatures WasmObjectFile::getFeatures() const { 1836 return SubtargetFeatures(); 1837 } 1838 1839 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; } 1840 1841 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; } 1842 1843 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { 1844 assert(Ref.d.a < Sections.size()); 1845 return Sections[Ref.d.a]; 1846 } 1847 1848 const WasmSection & 1849 WasmObjectFile::getWasmSection(const SectionRef &Section) const { 1850 return getWasmSection(Section.getRawDataRefImpl()); 1851 } 1852 1853 const wasm::WasmRelocation & 1854 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const { 1855 return getWasmRelocation(Ref.getRawDataRefImpl()); 1856 } 1857 1858 const wasm::WasmRelocation & 1859 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { 1860 assert(Ref.d.a < Sections.size()); 1861 const WasmSection &Sec = Sections[Ref.d.a]; 1862 assert(Ref.d.b < Sec.Relocations.size()); 1863 return Sec.Relocations[Ref.d.b]; 1864 } 1865 1866 int WasmSectionOrderChecker::getSectionOrder(unsigned ID, 1867 StringRef CustomSectionName) { 1868 switch (ID) { 1869 case wasm::WASM_SEC_CUSTOM: 1870 return StringSwitch<unsigned>(CustomSectionName) 1871 .Case("dylink", WASM_SEC_ORDER_DYLINK) 1872 .Case("dylink.0", WASM_SEC_ORDER_DYLINK) 1873 .Case("linking", WASM_SEC_ORDER_LINKING) 1874 .StartsWith("reloc.", WASM_SEC_ORDER_RELOC) 1875 .Case("name", WASM_SEC_ORDER_NAME) 1876 .Case("producers", WASM_SEC_ORDER_PRODUCERS) 1877 .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES) 1878 .Default(WASM_SEC_ORDER_NONE); 1879 case wasm::WASM_SEC_TYPE: 1880 return WASM_SEC_ORDER_TYPE; 1881 case wasm::WASM_SEC_IMPORT: 1882 return WASM_SEC_ORDER_IMPORT; 1883 case wasm::WASM_SEC_FUNCTION: 1884 return WASM_SEC_ORDER_FUNCTION; 1885 case wasm::WASM_SEC_TABLE: 1886 return WASM_SEC_ORDER_TABLE; 1887 case wasm::WASM_SEC_MEMORY: 1888 return WASM_SEC_ORDER_MEMORY; 1889 case wasm::WASM_SEC_GLOBAL: 1890 return WASM_SEC_ORDER_GLOBAL; 1891 case wasm::WASM_SEC_EXPORT: 1892 return WASM_SEC_ORDER_EXPORT; 1893 case wasm::WASM_SEC_START: 1894 return WASM_SEC_ORDER_START; 1895 case wasm::WASM_SEC_ELEM: 1896 return WASM_SEC_ORDER_ELEM; 1897 case wasm::WASM_SEC_CODE: 1898 return WASM_SEC_ORDER_CODE; 1899 case wasm::WASM_SEC_DATA: 1900 return WASM_SEC_ORDER_DATA; 1901 case wasm::WASM_SEC_DATACOUNT: 1902 return WASM_SEC_ORDER_DATACOUNT; 1903 case wasm::WASM_SEC_TAG: 1904 return WASM_SEC_ORDER_TAG; 1905 default: 1906 return WASM_SEC_ORDER_NONE; 1907 } 1908 } 1909 1910 // Represents the edges in a directed graph where any node B reachable from node 1911 // A is not allowed to appear before A in the section ordering, but may appear 1912 // afterward. 1913 int WasmSectionOrderChecker::DisallowedPredecessors 1914 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = { 1915 // WASM_SEC_ORDER_NONE 1916 {}, 1917 // WASM_SEC_ORDER_TYPE 1918 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT}, 1919 // WASM_SEC_ORDER_IMPORT 1920 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION}, 1921 // WASM_SEC_ORDER_FUNCTION 1922 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE}, 1923 // WASM_SEC_ORDER_TABLE 1924 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY}, 1925 // WASM_SEC_ORDER_MEMORY 1926 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG}, 1927 // WASM_SEC_ORDER_TAG 1928 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL}, 1929 // WASM_SEC_ORDER_GLOBAL 1930 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT}, 1931 // WASM_SEC_ORDER_EXPORT 1932 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START}, 1933 // WASM_SEC_ORDER_START 1934 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM}, 1935 // WASM_SEC_ORDER_ELEM 1936 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT}, 1937 // WASM_SEC_ORDER_DATACOUNT 1938 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE}, 1939 // WASM_SEC_ORDER_CODE 1940 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA}, 1941 // WASM_SEC_ORDER_DATA 1942 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING}, 1943 1944 // Custom Sections 1945 // WASM_SEC_ORDER_DYLINK 1946 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE}, 1947 // WASM_SEC_ORDER_LINKING 1948 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME}, 1949 // WASM_SEC_ORDER_RELOC (can be repeated) 1950 {}, 1951 // WASM_SEC_ORDER_NAME 1952 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS}, 1953 // WASM_SEC_ORDER_PRODUCERS 1954 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES}, 1955 // WASM_SEC_ORDER_TARGET_FEATURES 1956 {WASM_SEC_ORDER_TARGET_FEATURES}}; 1957 1958 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID, 1959 StringRef CustomSectionName) { 1960 int Order = getSectionOrder(ID, CustomSectionName); 1961 if (Order == WASM_SEC_ORDER_NONE) 1962 return true; 1963 1964 // Disallowed predecessors we need to check for 1965 SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList; 1966 1967 // Keep track of completed checks to avoid repeating work 1968 bool Checked[WASM_NUM_SEC_ORDERS] = {}; 1969 1970 int Curr = Order; 1971 while (true) { 1972 // Add new disallowed predecessors to work list 1973 for (size_t I = 0;; ++I) { 1974 int Next = DisallowedPredecessors[Curr][I]; 1975 if (Next == WASM_SEC_ORDER_NONE) 1976 break; 1977 if (Checked[Next]) 1978 continue; 1979 WorkList.push_back(Next); 1980 Checked[Next] = true; 1981 } 1982 1983 if (WorkList.empty()) 1984 break; 1985 1986 // Consider next disallowed predecessor 1987 Curr = WorkList.pop_back_val(); 1988 if (Seen[Curr]) 1989 return false; 1990 } 1991 1992 // Have not seen any disallowed predecessors 1993 Seen[Order] = true; 1994 return true; 1995 } 1996