1 //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/ADT/ArrayRef.h" 11 #include "llvm/ADT/DenseSet.h" 12 #include "llvm/ADT/STLExtras.h" 13 #include "llvm/ADT/StringRef.h" 14 #include "llvm/ADT/StringSet.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 <algorithm> 28 #include <cassert> 29 #include <cstdint> 30 #include <cstring> 31 #include <system_error> 32 33 #define DEBUG_TYPE "wasm-object" 34 35 using namespace llvm; 36 using namespace object; 37 38 Expected<std::unique_ptr<WasmObjectFile>> 39 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { 40 Error Err = Error::success(); 41 auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err); 42 if (Err) 43 return std::move(Err); 44 45 return std::move(ObjectFile); 46 } 47 48 #define VARINT7_MAX ((1<<7)-1) 49 #define VARINT7_MIN (-(1<<7)) 50 #define VARUINT7_MAX (1<<7) 51 #define VARUINT1_MAX (1) 52 53 static uint8_t readUint8(const uint8_t *&Ptr) { return *Ptr++; } 54 55 static uint32_t readUint32(const uint8_t *&Ptr) { 56 uint32_t Result = support::endian::read32le(Ptr); 57 Ptr += sizeof(Result); 58 return Result; 59 } 60 61 static int32_t readFloat32(const uint8_t *&Ptr) { 62 int32_t Result = 0; 63 memcpy(&Result, Ptr, sizeof(Result)); 64 Ptr += sizeof(Result); 65 return Result; 66 } 67 68 static int64_t readFloat64(const uint8_t *&Ptr) { 69 int64_t Result = 0; 70 memcpy(&Result, Ptr, sizeof(Result)); 71 Ptr += sizeof(Result); 72 return Result; 73 } 74 75 static uint64_t readULEB128(const uint8_t *&Ptr) { 76 unsigned Count; 77 uint64_t Result = decodeULEB128(Ptr, &Count); 78 Ptr += Count; 79 return Result; 80 } 81 82 static StringRef readString(const uint8_t *&Ptr) { 83 uint32_t StringLen = readULEB128(Ptr); 84 StringRef Return = StringRef(reinterpret_cast<const char *>(Ptr), StringLen); 85 Ptr += StringLen; 86 return Return; 87 } 88 89 static int64_t readLEB128(const uint8_t *&Ptr) { 90 unsigned Count; 91 uint64_t Result = decodeSLEB128(Ptr, &Count); 92 Ptr += Count; 93 return Result; 94 } 95 96 static uint8_t readVaruint1(const uint8_t *&Ptr) { 97 int64_t result = readLEB128(Ptr); 98 assert(result <= VARUINT1_MAX && result >= 0); 99 return result; 100 } 101 102 static int32_t readVarint32(const uint8_t *&Ptr) { 103 int64_t result = readLEB128(Ptr); 104 assert(result <= INT32_MAX && result >= INT32_MIN); 105 return result; 106 } 107 108 static uint32_t readVaruint32(const uint8_t *&Ptr) { 109 uint64_t result = readULEB128(Ptr); 110 assert(result <= UINT32_MAX); 111 return result; 112 } 113 114 static int64_t readVarint64(const uint8_t *&Ptr) { 115 return readLEB128(Ptr); 116 } 117 118 static uint8_t readOpcode(const uint8_t *&Ptr) { 119 return readUint8(Ptr); 120 } 121 122 static Error readInitExpr(wasm::WasmInitExpr &Expr, const uint8_t *&Ptr) { 123 Expr.Opcode = readOpcode(Ptr); 124 125 switch (Expr.Opcode) { 126 case wasm::WASM_OPCODE_I32_CONST: 127 Expr.Value.Int32 = readVarint32(Ptr); 128 break; 129 case wasm::WASM_OPCODE_I64_CONST: 130 Expr.Value.Int64 = readVarint64(Ptr); 131 break; 132 case wasm::WASM_OPCODE_F32_CONST: 133 Expr.Value.Float32 = readFloat32(Ptr); 134 break; 135 case wasm::WASM_OPCODE_F64_CONST: 136 Expr.Value.Float64 = readFloat64(Ptr); 137 break; 138 case wasm::WASM_OPCODE_GET_GLOBAL: 139 Expr.Value.Global = readULEB128(Ptr); 140 break; 141 default: 142 return make_error<GenericBinaryError>("Invalid opcode in init_expr", 143 object_error::parse_failed); 144 } 145 146 uint8_t EndOpcode = readOpcode(Ptr); 147 if (EndOpcode != wasm::WASM_OPCODE_END) { 148 return make_error<GenericBinaryError>("Invalid init_expr", 149 object_error::parse_failed); 150 } 151 return Error::success(); 152 } 153 154 static wasm::WasmLimits readLimits(const uint8_t *&Ptr) { 155 wasm::WasmLimits Result; 156 Result.Flags = readVaruint1(Ptr); 157 Result.Initial = readVaruint32(Ptr); 158 if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) 159 Result.Maximum = readVaruint32(Ptr); 160 return Result; 161 } 162 163 static wasm::WasmTable readTable(const uint8_t *&Ptr) { 164 wasm::WasmTable Table; 165 Table.ElemType = readUint8(Ptr); 166 Table.Limits = readLimits(Ptr); 167 return Table; 168 } 169 170 static Error readSection(WasmSection &Section, const uint8_t *&Ptr, 171 const uint8_t *Start, const uint8_t *Eof) { 172 Section.Offset = Ptr - Start; 173 Section.Type = readUint8(Ptr); 174 uint32_t Size = readVaruint32(Ptr); 175 if (Size == 0) 176 return make_error<StringError>("Zero length section", 177 object_error::parse_failed); 178 if (Ptr + Size > Eof) 179 return make_error<StringError>("Section too large", 180 object_error::parse_failed); 181 Section.Content = ArrayRef<uint8_t>(Ptr, Size); 182 Ptr += Size; 183 return Error::success(); 184 } 185 186 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) 187 : ObjectFile(Binary::ID_Wasm, Buffer) { 188 ErrorAsOutParameter ErrAsOutParam(&Err); 189 Header.Magic = getData().substr(0, 4); 190 if (Header.Magic != StringRef("\0asm", 4)) { 191 Err = make_error<StringError>("Bad magic number", 192 object_error::parse_failed); 193 return; 194 } 195 196 const uint8_t *Eof = getPtr(getData().size()); 197 const uint8_t *Ptr = getPtr(4); 198 199 if (Ptr + 4 > Eof) { 200 Err = make_error<StringError>("Missing version number", 201 object_error::parse_failed); 202 return; 203 } 204 205 Header.Version = readUint32(Ptr); 206 if (Header.Version != wasm::WasmVersion) { 207 Err = make_error<StringError>("Bad version number", 208 object_error::parse_failed); 209 return; 210 } 211 212 WasmSection Sec; 213 while (Ptr < Eof) { 214 if ((Err = readSection(Sec, Ptr, getPtr(0), Eof))) 215 return; 216 if ((Err = parseSection(Sec))) 217 return; 218 219 Sections.push_back(Sec); 220 } 221 } 222 223 Error WasmObjectFile::parseSection(WasmSection &Sec) { 224 const uint8_t* Start = Sec.Content.data(); 225 const uint8_t* End = Start + Sec.Content.size(); 226 switch (Sec.Type) { 227 case wasm::WASM_SEC_CUSTOM: 228 return parseCustomSection(Sec, Start, End); 229 case wasm::WASM_SEC_TYPE: 230 return parseTypeSection(Start, End); 231 case wasm::WASM_SEC_IMPORT: 232 return parseImportSection(Start, End); 233 case wasm::WASM_SEC_FUNCTION: 234 return parseFunctionSection(Start, End); 235 case wasm::WASM_SEC_TABLE: 236 return parseTableSection(Start, End); 237 case wasm::WASM_SEC_MEMORY: 238 return parseMemorySection(Start, End); 239 case wasm::WASM_SEC_GLOBAL: 240 return parseGlobalSection(Start, End); 241 case wasm::WASM_SEC_EXPORT: 242 return parseExportSection(Start, End); 243 case wasm::WASM_SEC_START: 244 return parseStartSection(Start, End); 245 case wasm::WASM_SEC_ELEM: 246 return parseElemSection(Start, End); 247 case wasm::WASM_SEC_CODE: 248 return parseCodeSection(Start, End); 249 case wasm::WASM_SEC_DATA: 250 return parseDataSection(Start, End); 251 default: 252 return make_error<GenericBinaryError>("Bad section type", 253 object_error::parse_failed); 254 } 255 } 256 257 Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) { 258 llvm::DenseSet<uint64_t> Seen; 259 if (Functions.size() != FunctionTypes.size()) { 260 return make_error<GenericBinaryError>("Names must come after code section", 261 object_error::parse_failed); 262 } 263 264 while (Ptr < End) { 265 uint8_t Type = readUint8(Ptr); 266 uint32_t Size = readVaruint32(Ptr); 267 const uint8_t *SubSectionEnd = Ptr + Size; 268 switch (Type) { 269 case wasm::WASM_NAMES_FUNCTION: { 270 uint32_t Count = readVaruint32(Ptr); 271 while (Count--) { 272 uint32_t Index = readVaruint32(Ptr); 273 if (!Seen.insert(Index).second) 274 return make_error<GenericBinaryError>("Function named more than once", 275 object_error::parse_failed); 276 StringRef Name = readString(Ptr); 277 if (!isValidFunctionIndex(Index) || Name.empty()) 278 return make_error<GenericBinaryError>("Invalid name entry", 279 object_error::parse_failed); 280 DebugNames.push_back(wasm::WasmFunctionName{Index, Name}); 281 if (isDefinedFunctionIndex(Index)) { 282 // Override any existing name; the name specified by the "names" 283 // section is the Function's canonical name. 284 getDefinedFunction(Index).Name = Name; 285 } 286 } 287 break; 288 } 289 // Ignore local names for now 290 case wasm::WASM_NAMES_LOCAL: 291 default: 292 Ptr += Size; 293 break; 294 } 295 if (Ptr != SubSectionEnd) 296 return make_error<GenericBinaryError>("Name sub-section ended prematurely", 297 object_error::parse_failed); 298 } 299 300 if (Ptr != End) 301 return make_error<GenericBinaryError>("Name section ended prematurely", 302 object_error::parse_failed); 303 return Error::success(); 304 } 305 306 Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr, 307 const uint8_t *End) { 308 HasLinkingSection = true; 309 if (Functions.size() != FunctionTypes.size()) { 310 return make_error<GenericBinaryError>( 311 "Linking data must come after code section", object_error::parse_failed); 312 } 313 314 while (Ptr < End) { 315 uint8_t Type = readUint8(Ptr); 316 uint32_t Size = readVaruint32(Ptr); 317 const uint8_t *SubSectionEnd = Ptr + Size; 318 switch (Type) { 319 case wasm::WASM_SYMBOL_TABLE: 320 if (Error Err = parseLinkingSectionSymtab(Ptr, SubSectionEnd)) 321 return Err; 322 break; 323 case wasm::WASM_SEGMENT_INFO: { 324 uint32_t Count = readVaruint32(Ptr); 325 if (Count > DataSegments.size()) 326 return make_error<GenericBinaryError>("Too many segment names", 327 object_error::parse_failed); 328 for (uint32_t i = 0; i < Count; i++) { 329 DataSegments[i].Data.Name = readString(Ptr); 330 DataSegments[i].Data.Alignment = readVaruint32(Ptr); 331 DataSegments[i].Data.Flags = readVaruint32(Ptr); 332 } 333 break; 334 } 335 case wasm::WASM_INIT_FUNCS: { 336 uint32_t Count = readVaruint32(Ptr); 337 LinkingData.InitFunctions.reserve(Count); 338 for (uint32_t i = 0; i < Count; i++) { 339 wasm::WasmInitFunc Init; 340 Init.Priority = readVaruint32(Ptr); 341 Init.Symbol = readVaruint32(Ptr); 342 if (!isValidFunctionSymbol(Init.Symbol)) 343 return make_error<GenericBinaryError>("Invalid function symbol: " + 344 Twine(Init.Symbol), 345 object_error::parse_failed); 346 LinkingData.InitFunctions.emplace_back(Init); 347 } 348 break; 349 } 350 case wasm::WASM_COMDAT_INFO: 351 if (Error Err = parseLinkingSectionComdat(Ptr, SubSectionEnd)) 352 return Err; 353 break; 354 default: 355 Ptr += Size; 356 break; 357 } 358 if (Ptr != SubSectionEnd) 359 return make_error<GenericBinaryError>( 360 "Linking sub-section ended prematurely", object_error::parse_failed); 361 } 362 if (Ptr != End) 363 return make_error<GenericBinaryError>("Linking section ended prematurely", 364 object_error::parse_failed); 365 return Error::success(); 366 } 367 368 Error WasmObjectFile::parseLinkingSectionSymtab(const uint8_t *&Ptr, 369 const uint8_t *End) { 370 uint32_t Count = readVaruint32(Ptr); 371 LinkingData.SymbolTable.reserve(Count); 372 Symbols.reserve(Count); 373 StringSet<> SymbolNames; 374 375 std::vector<wasm::WasmImport *> ImportedGlobals; 376 std::vector<wasm::WasmImport *> ImportedFunctions; 377 ImportedGlobals.reserve(Imports.size()); 378 ImportedFunctions.reserve(Imports.size()); 379 for (auto &I : Imports) { 380 if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION) 381 ImportedFunctions.emplace_back(&I); 382 else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL) 383 ImportedGlobals.emplace_back(&I); 384 } 385 386 while (Count--) { 387 wasm::WasmSymbolInfo Info; 388 const wasm::WasmSignature *FunctionType = nullptr; 389 const wasm::WasmGlobalType *GlobalType = nullptr; 390 391 Info.Kind = readUint8(Ptr); 392 Info.Flags = readVaruint32(Ptr); 393 bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0; 394 395 switch (Info.Kind) { 396 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 397 Info.ElementIndex = readVaruint32(Ptr); 398 if (!isValidFunctionIndex(Info.ElementIndex) || 399 IsDefined != isDefinedFunctionIndex(Info.ElementIndex)) 400 return make_error<GenericBinaryError>("invalid function symbol index", 401 object_error::parse_failed); 402 if (IsDefined) { 403 Info.Name = readString(Ptr); 404 unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; 405 FunctionType = &Signatures[FunctionTypes[FuncIndex]]; 406 wasm::WasmFunction &Function = Functions[FuncIndex]; 407 if (Function.Name.empty()) { 408 // Use the symbol's name to set a name for the Function, but only if 409 // one hasn't already been set. 410 Function.Name = Info.Name; 411 } 412 } else { 413 wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; 414 FunctionType = &Signatures[Import.SigIndex]; 415 Info.Name = Import.Field; 416 } 417 break; 418 419 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 420 Info.ElementIndex = readVaruint32(Ptr); 421 if (!isValidGlobalIndex(Info.ElementIndex) || 422 IsDefined != isDefinedGlobalIndex(Info.ElementIndex)) 423 return make_error<GenericBinaryError>("invalid global symbol index", 424 object_error::parse_failed); 425 if (IsDefined) { 426 Info.Name = readString(Ptr); 427 unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals; 428 wasm::WasmGlobal &Global = Globals[GlobalIndex]; 429 GlobalType = &Global.Type; 430 if (Global.Name.empty()) { 431 // Use the symbol's name to set a name for the Global, but only if 432 // one hasn't already been set. 433 Global.Name = Info.Name; 434 } 435 } else { 436 wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; 437 Info.Name = Import.Field; 438 GlobalType = &Import.Global; 439 } 440 break; 441 442 case wasm::WASM_SYMBOL_TYPE_DATA: 443 Info.Name = readString(Ptr); 444 if (IsDefined) { 445 uint32_t Index = readVaruint32(Ptr); 446 if (Index >= DataSegments.size()) 447 return make_error<GenericBinaryError>("invalid data symbol index", 448 object_error::parse_failed); 449 uint32_t Offset = readVaruint32(Ptr); 450 uint32_t Size = readVaruint32(Ptr); 451 if (Offset + Size > DataSegments[Index].Data.Content.size()) 452 return make_error<GenericBinaryError>("invalid data symbol offset", 453 object_error::parse_failed); 454 Info.DataRef = wasm::WasmDataReference{Index, Offset, Size}; 455 } 456 break; 457 458 default: 459 return make_error<GenericBinaryError>("Invalid symbol type", 460 object_error::parse_failed); 461 } 462 463 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != 464 wasm::WASM_SYMBOL_BINDING_LOCAL && 465 !SymbolNames.insert(Info.Name).second) 466 return make_error<GenericBinaryError>("Duplicate symbol name " + 467 Twine(Info.Name), 468 object_error::parse_failed); 469 LinkingData.SymbolTable.emplace_back(Info); 470 Symbols.emplace_back(LinkingData.SymbolTable.back(), FunctionType, 471 GlobalType); 472 DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); 473 } 474 475 return Error::success(); 476 } 477 478 Error WasmObjectFile::parseLinkingSectionComdat(const uint8_t *&Ptr, 479 const uint8_t *End) 480 { 481 uint32_t ComdatCount = readVaruint32(Ptr); 482 StringSet<> ComdatSet; 483 while (ComdatCount--) { 484 StringRef Name = readString(Ptr); 485 if (Name.empty() || !ComdatSet.insert(Name).second) 486 return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " + Twine(Name), 487 object_error::parse_failed); 488 Comdats.emplace_back(Name); 489 uint32_t Flags = readVaruint32(Ptr); 490 if (Flags != 0) 491 return make_error<GenericBinaryError>("Unsupported COMDAT flags", 492 object_error::parse_failed); 493 494 uint32_t EntryCount = readVaruint32(Ptr); 495 while (EntryCount--) { 496 unsigned Kind = readVaruint32(Ptr); 497 unsigned Index = readVaruint32(Ptr); 498 switch (Kind) { 499 default: 500 return make_error<GenericBinaryError>("Invalid COMDAT entry type", 501 object_error::parse_failed); 502 case wasm::WASM_COMDAT_DATA: 503 if (Index >= DataSegments.size()) 504 return make_error<GenericBinaryError>("COMDAT data index out of range", 505 object_error::parse_failed); 506 if (!DataSegments[Index].Data.Comdat.empty()) 507 return make_error<GenericBinaryError>("Data segment in two COMDATs", 508 object_error::parse_failed); 509 DataSegments[Index].Data.Comdat = Name; 510 break; 511 case wasm::WASM_COMDAT_FUNCTION: 512 if (!isDefinedFunctionIndex(Index)) 513 return make_error<GenericBinaryError>("COMDAT function index out of range", 514 object_error::parse_failed); 515 if (!getDefinedFunction(Index).Comdat.empty()) 516 return make_error<GenericBinaryError>("Function in two COMDATs", 517 object_error::parse_failed); 518 getDefinedFunction(Index).Comdat = Name; 519 break; 520 } 521 } 522 } 523 return Error::success(); 524 } 525 526 WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) { 527 for (WasmSection& Section : Sections) { 528 if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name) 529 return &Section; 530 } 531 return nullptr; 532 } 533 534 WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) { 535 assert(Type != wasm::WASM_SEC_CUSTOM); 536 for (WasmSection& Section : Sections) { 537 if (Section.Type == Type) 538 return &Section; 539 } 540 return nullptr; 541 } 542 543 Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr, 544 const uint8_t *End) { 545 uint8_t SectionCode = readUint8(Ptr); 546 WasmSection* Section = nullptr; 547 if (SectionCode == wasm::WASM_SEC_CUSTOM) { 548 StringRef Name = readString(Ptr); 549 Section = findCustomSectionByName(Name); 550 } else { 551 Section = findSectionByType(SectionCode); 552 } 553 if (!Section) 554 return make_error<GenericBinaryError>("Invalid section code", 555 object_error::parse_failed); 556 uint32_t RelocCount = readVaruint32(Ptr); 557 uint32_t EndOffset = Section->Content.size(); 558 while (RelocCount--) { 559 wasm::WasmRelocation Reloc = {}; 560 Reloc.Type = readVaruint32(Ptr); 561 Reloc.Offset = readVaruint32(Ptr); 562 Reloc.Index = readVaruint32(Ptr); 563 switch (Reloc.Type) { 564 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: 565 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: 566 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: 567 if (!isValidFunctionSymbol(Reloc.Index)) 568 return make_error<GenericBinaryError>("Bad relocation function index", 569 object_error::parse_failed); 570 break; 571 case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: 572 if (Reloc.Index >= Signatures.size()) 573 return make_error<GenericBinaryError>("Bad relocation type index", 574 object_error::parse_failed); 575 break; 576 case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: 577 if (!isValidGlobalSymbol(Reloc.Index)) 578 return make_error<GenericBinaryError>("Bad relocation global index", 579 object_error::parse_failed); 580 break; 581 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: 582 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: 583 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: 584 if (!isValidDataSymbol(Reloc.Index)) 585 return make_error<GenericBinaryError>("Bad relocation data index", 586 object_error::parse_failed); 587 Reloc.Addend = readVarint32(Ptr); 588 break; 589 default: 590 return make_error<GenericBinaryError>("Bad relocation type: " + 591 Twine(Reloc.Type), 592 object_error::parse_failed); 593 } 594 595 // Relocations must fit inside the section, and must appear in order. They 596 // also shouldn't overlap a function/element boundary, but we don't bother 597 // to check that. 598 uint64_t Size = 5; 599 if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 || 600 Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32) 601 Size = 4; 602 if (Reloc.Offset + Size > EndOffset) 603 return make_error<GenericBinaryError>("Bad relocation offset", 604 object_error::parse_failed); 605 606 Section->Relocations.push_back(Reloc); 607 } 608 if (Ptr != End) 609 return make_error<GenericBinaryError>("Reloc section ended prematurely", 610 object_error::parse_failed); 611 return Error::success(); 612 } 613 614 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, 615 const uint8_t *Ptr, const uint8_t *End) { 616 Sec.Name = readString(Ptr); 617 if (Sec.Name == "name") { 618 if (Error Err = parseNameSection(Ptr, End)) 619 return Err; 620 } else if (Sec.Name == "linking") { 621 if (Error Err = parseLinkingSection(Ptr, End)) 622 return Err; 623 } else if (Sec.Name.startswith("reloc.")) { 624 if (Error Err = parseRelocSection(Sec.Name, Ptr, End)) 625 return Err; 626 } 627 return Error::success(); 628 } 629 630 Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) { 631 uint32_t Count = readVaruint32(Ptr); 632 Signatures.reserve(Count); 633 while (Count--) { 634 wasm::WasmSignature Sig; 635 Sig.ReturnType = wasm::WASM_TYPE_NORESULT; 636 uint8_t Form = readUint8(Ptr); 637 if (Form != wasm::WASM_TYPE_FUNC) { 638 return make_error<GenericBinaryError>("Invalid signature type", 639 object_error::parse_failed); 640 } 641 uint32_t ParamCount = readVaruint32(Ptr); 642 Sig.ParamTypes.reserve(ParamCount); 643 while (ParamCount--) { 644 uint32_t ParamType = readUint8(Ptr); 645 Sig.ParamTypes.push_back(ParamType); 646 } 647 uint32_t ReturnCount = readVaruint32(Ptr); 648 if (ReturnCount) { 649 if (ReturnCount != 1) { 650 return make_error<GenericBinaryError>( 651 "Multiple return types not supported", object_error::parse_failed); 652 } 653 Sig.ReturnType = readUint8(Ptr); 654 } 655 Signatures.push_back(Sig); 656 } 657 if (Ptr != End) 658 return make_error<GenericBinaryError>("Type section ended prematurely", 659 object_error::parse_failed); 660 return Error::success(); 661 } 662 663 Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) { 664 uint32_t Count = readVaruint32(Ptr); 665 Imports.reserve(Count); 666 for (uint32_t i = 0; i < Count; i++) { 667 wasm::WasmImport Im; 668 Im.Module = readString(Ptr); 669 Im.Field = readString(Ptr); 670 Im.Kind = readUint8(Ptr); 671 switch (Im.Kind) { 672 case wasm::WASM_EXTERNAL_FUNCTION: 673 NumImportedFunctions++; 674 Im.SigIndex = readVaruint32(Ptr); 675 break; 676 case wasm::WASM_EXTERNAL_GLOBAL: 677 NumImportedGlobals++; 678 Im.Global.Type = readUint8(Ptr); 679 Im.Global.Mutable = readVaruint1(Ptr); 680 break; 681 case wasm::WASM_EXTERNAL_MEMORY: 682 Im.Memory = readLimits(Ptr); 683 break; 684 case wasm::WASM_EXTERNAL_TABLE: 685 Im.Table = readTable(Ptr); 686 if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) 687 return make_error<GenericBinaryError>("Invalid table element type", 688 object_error::parse_failed); 689 break; 690 default: 691 return make_error<GenericBinaryError>( 692 "Unexpected import kind", object_error::parse_failed); 693 } 694 Imports.push_back(Im); 695 } 696 if (Ptr != End) 697 return make_error<GenericBinaryError>("Import section ended prematurely", 698 object_error::parse_failed); 699 return Error::success(); 700 } 701 702 Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) { 703 uint32_t Count = readVaruint32(Ptr); 704 FunctionTypes.reserve(Count); 705 uint32_t NumTypes = Signatures.size(); 706 while (Count--) { 707 uint32_t Type = readVaruint32(Ptr); 708 if (Type >= NumTypes) 709 return make_error<GenericBinaryError>("Invalid function type", 710 object_error::parse_failed); 711 FunctionTypes.push_back(Type); 712 } 713 if (Ptr != End) 714 return make_error<GenericBinaryError>("Function section ended prematurely", 715 object_error::parse_failed); 716 return Error::success(); 717 } 718 719 Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) { 720 uint32_t Count = readVaruint32(Ptr); 721 Tables.reserve(Count); 722 while (Count--) { 723 Tables.push_back(readTable(Ptr)); 724 if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) { 725 return make_error<GenericBinaryError>("Invalid table element type", 726 object_error::parse_failed); 727 } 728 } 729 if (Ptr != End) 730 return make_error<GenericBinaryError>("Table section ended prematurely", 731 object_error::parse_failed); 732 return Error::success(); 733 } 734 735 Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) { 736 uint32_t Count = readVaruint32(Ptr); 737 Memories.reserve(Count); 738 while (Count--) { 739 Memories.push_back(readLimits(Ptr)); 740 } 741 if (Ptr != End) 742 return make_error<GenericBinaryError>("Memory section ended prematurely", 743 object_error::parse_failed); 744 return Error::success(); 745 } 746 747 Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) { 748 GlobalSection = Sections.size(); 749 uint32_t Count = readVaruint32(Ptr); 750 Globals.reserve(Count); 751 while (Count--) { 752 wasm::WasmGlobal Global; 753 Global.Index = NumImportedGlobals + Globals.size(); 754 Global.Type.Type = readUint8(Ptr); 755 Global.Type.Mutable = readVaruint1(Ptr); 756 if (Error Err = readInitExpr(Global.InitExpr, Ptr)) 757 return Err; 758 Globals.push_back(Global); 759 } 760 if (Ptr != End) 761 return make_error<GenericBinaryError>("Global section ended prematurely", 762 object_error::parse_failed); 763 return Error::success(); 764 } 765 766 Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) { 767 uint32_t Count = readVaruint32(Ptr); 768 Exports.reserve(Count); 769 for (uint32_t i = 0; i < Count; i++) { 770 wasm::WasmExport Ex; 771 Ex.Name = readString(Ptr); 772 Ex.Kind = readUint8(Ptr); 773 Ex.Index = readVaruint32(Ptr); 774 switch (Ex.Kind) { 775 case wasm::WASM_EXTERNAL_FUNCTION: 776 if (!isValidFunctionIndex(Ex.Index)) 777 return make_error<GenericBinaryError>("Invalid function export", 778 object_error::parse_failed); 779 break; 780 case wasm::WASM_EXTERNAL_GLOBAL: 781 if (!isValidGlobalIndex(Ex.Index)) 782 return make_error<GenericBinaryError>("Invalid global export", 783 object_error::parse_failed); 784 break; 785 case wasm::WASM_EXTERNAL_MEMORY: 786 case wasm::WASM_EXTERNAL_TABLE: 787 break; 788 default: 789 return make_error<GenericBinaryError>( 790 "Unexpected export kind", object_error::parse_failed); 791 } 792 Exports.push_back(Ex); 793 } 794 if (Ptr != End) 795 return make_error<GenericBinaryError>("Export section ended prematurely", 796 object_error::parse_failed); 797 return Error::success(); 798 } 799 800 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const { 801 return Index < NumImportedFunctions + FunctionTypes.size(); 802 } 803 804 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const { 805 return Index >= NumImportedFunctions && isValidFunctionIndex(Index); 806 } 807 808 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const { 809 return Index < NumImportedGlobals + Globals.size(); 810 } 811 812 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const { 813 return Index >= NumImportedGlobals && isValidGlobalIndex(Index); 814 } 815 816 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const { 817 return Index < Symbols.size() && Symbols[Index].isTypeFunction(); 818 } 819 820 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const { 821 return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); 822 } 823 824 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const { 825 return Index < Symbols.size() && Symbols[Index].isTypeData(); 826 } 827 828 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) { 829 assert(isDefinedFunctionIndex(Index)); 830 return Functions[Index - NumImportedFunctions]; 831 } 832 833 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) { 834 assert(isDefinedGlobalIndex(Index)); 835 return Globals[Index - NumImportedGlobals]; 836 } 837 838 Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) { 839 StartFunction = readVaruint32(Ptr); 840 if (!isValidFunctionIndex(StartFunction)) 841 return make_error<GenericBinaryError>("Invalid start function", 842 object_error::parse_failed); 843 return Error::success(); 844 } 845 846 Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) { 847 CodeSection = Sections.size(); 848 const uint8_t *CodeSectionStart = Ptr; 849 uint32_t FunctionCount = readVaruint32(Ptr); 850 if (FunctionCount != FunctionTypes.size()) { 851 return make_error<GenericBinaryError>("Invalid function count", 852 object_error::parse_failed); 853 } 854 855 while (FunctionCount--) { 856 wasm::WasmFunction Function; 857 const uint8_t *FunctionStart = Ptr; 858 uint32_t Size = readVaruint32(Ptr); 859 const uint8_t *FunctionEnd = Ptr + Size; 860 861 Function.Index = NumImportedFunctions + Functions.size(); 862 Function.CodeSectionOffset = FunctionStart - CodeSectionStart; 863 Function.Size = FunctionEnd - FunctionStart; 864 865 uint32_t NumLocalDecls = readVaruint32(Ptr); 866 Function.Locals.reserve(NumLocalDecls); 867 while (NumLocalDecls--) { 868 wasm::WasmLocalDecl Decl; 869 Decl.Count = readVaruint32(Ptr); 870 Decl.Type = readUint8(Ptr); 871 Function.Locals.push_back(Decl); 872 } 873 874 uint32_t BodySize = FunctionEnd - Ptr; 875 Function.Body = ArrayRef<uint8_t>(Ptr, BodySize); 876 Ptr += BodySize; 877 assert(Ptr == FunctionEnd); 878 Functions.push_back(Function); 879 } 880 if (Ptr != End) 881 return make_error<GenericBinaryError>("Code section ended prematurely", 882 object_error::parse_failed); 883 return Error::success(); 884 } 885 886 Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) { 887 uint32_t Count = readVaruint32(Ptr); 888 ElemSegments.reserve(Count); 889 while (Count--) { 890 wasm::WasmElemSegment Segment; 891 Segment.TableIndex = readVaruint32(Ptr); 892 if (Segment.TableIndex != 0) { 893 return make_error<GenericBinaryError>("Invalid TableIndex", 894 object_error::parse_failed); 895 } 896 if (Error Err = readInitExpr(Segment.Offset, Ptr)) 897 return Err; 898 uint32_t NumElems = readVaruint32(Ptr); 899 while (NumElems--) { 900 Segment.Functions.push_back(readVaruint32(Ptr)); 901 } 902 ElemSegments.push_back(Segment); 903 } 904 if (Ptr != End) 905 return make_error<GenericBinaryError>("Elem section ended prematurely", 906 object_error::parse_failed); 907 return Error::success(); 908 } 909 910 Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) { 911 DataSection = Sections.size(); 912 const uint8_t *Start = Ptr; 913 uint32_t Count = readVaruint32(Ptr); 914 DataSegments.reserve(Count); 915 while (Count--) { 916 WasmSegment Segment; 917 Segment.Data.MemoryIndex = readVaruint32(Ptr); 918 if (Error Err = readInitExpr(Segment.Data.Offset, Ptr)) 919 return Err; 920 uint32_t Size = readVaruint32(Ptr); 921 Segment.Data.Content = ArrayRef<uint8_t>(Ptr, Size); 922 Segment.Data.Alignment = 0; 923 Segment.Data.Flags = 0; 924 Segment.SectionOffset = Ptr - Start; 925 Ptr += Size; 926 DataSegments.push_back(Segment); 927 } 928 if (Ptr != End) 929 return make_error<GenericBinaryError>("Data section ended prematurely", 930 object_error::parse_failed); 931 return Error::success(); 932 } 933 934 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const { 935 return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data()); 936 } 937 938 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 939 return Header; 940 } 941 942 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; } 943 944 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 945 uint32_t Result = SymbolRef::SF_None; 946 const WasmSymbol &Sym = getWasmSymbol(Symb); 947 948 DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n"); 949 if (Sym.isBindingWeak()) 950 Result |= SymbolRef::SF_Weak; 951 if (!Sym.isBindingLocal()) 952 Result |= SymbolRef::SF_Global; 953 if (Sym.isHidden()) 954 Result |= SymbolRef::SF_Hidden; 955 if (!Sym.isDefined()) 956 Result |= SymbolRef::SF_Undefined; 957 if (Sym.isTypeFunction()) 958 Result |= SymbolRef::SF_Executable; 959 return Result; 960 } 961 962 basic_symbol_iterator WasmObjectFile::symbol_begin() const { 963 DataRefImpl Ref; 964 Ref.d.a = 0; 965 return BasicSymbolRef(Ref, this); 966 } 967 968 basic_symbol_iterator WasmObjectFile::symbol_end() const { 969 DataRefImpl Ref; 970 Ref.d.a = Symbols.size(); 971 return BasicSymbolRef(Ref, this); 972 } 973 974 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const { 975 return Symbols[Symb.d.a]; 976 } 977 978 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const { 979 return getWasmSymbol(Symb.getRawDataRefImpl()); 980 } 981 982 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 983 return getWasmSymbol(Symb).Info.Name; 984 } 985 986 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 987 return getSymbolValue(Symb); 988 } 989 990 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const { 991 switch (Sym.Info.Kind) { 992 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 993 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 994 return Sym.Info.ElementIndex; 995 case wasm::WASM_SYMBOL_TYPE_DATA: { 996 // The value of a data symbol is the segment offset, plus the symbol 997 // offset within the segment. 998 uint32_t SegmentIndex = Sym.Info.DataRef.Segment; 999 const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data; 1000 assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST); 1001 return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset; 1002 } 1003 } 1004 llvm_unreachable("invalid symbol type"); 1005 } 1006 1007 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 1008 return getWasmSymbolValue(getWasmSymbol(Symb)); 1009 } 1010 1011 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 1012 llvm_unreachable("not yet implemented"); 1013 return 0; 1014 } 1015 1016 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 1017 llvm_unreachable("not yet implemented"); 1018 return 0; 1019 } 1020 1021 Expected<SymbolRef::Type> 1022 WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 1023 const WasmSymbol &Sym = getWasmSymbol(Symb); 1024 1025 switch (Sym.Info.Kind) { 1026 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1027 return SymbolRef::ST_Function; 1028 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1029 return SymbolRef::ST_Other; 1030 case wasm::WASM_SYMBOL_TYPE_DATA: 1031 return SymbolRef::ST_Data; 1032 } 1033 1034 llvm_unreachable("Unknown WasmSymbol::SymbolType"); 1035 return SymbolRef::ST_Other; 1036 } 1037 1038 Expected<section_iterator> 1039 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 1040 const WasmSymbol& Sym = getWasmSymbol(Symb); 1041 if (Sym.isUndefined()) 1042 return section_end(); 1043 1044 DataRefImpl Ref; 1045 switch (Sym.Info.Kind) { 1046 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1047 Ref.d.a = CodeSection; 1048 break; 1049 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1050 Ref.d.a = GlobalSection; 1051 break; 1052 case wasm::WASM_SYMBOL_TYPE_DATA: 1053 Ref.d.a = DataSection; 1054 break; 1055 default: 1056 llvm_unreachable("Unknown WasmSymbol::SymbolType"); 1057 } 1058 return section_iterator(SectionRef(Ref, this)); 1059 } 1060 1061 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 1062 1063 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, 1064 StringRef &Res) const { 1065 const WasmSection &S = Sections[Sec.d.a]; 1066 #define ECase(X) \ 1067 case wasm::WASM_SEC_##X: \ 1068 Res = #X; \ 1069 break 1070 switch (S.Type) { 1071 ECase(TYPE); 1072 ECase(IMPORT); 1073 ECase(FUNCTION); 1074 ECase(TABLE); 1075 ECase(MEMORY); 1076 ECase(GLOBAL); 1077 ECase(EXPORT); 1078 ECase(START); 1079 ECase(ELEM); 1080 ECase(CODE); 1081 ECase(DATA); 1082 case wasm::WASM_SEC_CUSTOM: 1083 Res = S.Name; 1084 break; 1085 default: 1086 return object_error::invalid_section_index; 1087 } 1088 #undef ECase 1089 return std::error_code(); 1090 } 1091 1092 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } 1093 1094 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const { 1095 return Sec.d.a; 1096 } 1097 1098 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 1099 const WasmSection &S = Sections[Sec.d.a]; 1100 return S.Content.size(); 1101 } 1102 1103 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, 1104 StringRef &Res) const { 1105 const WasmSection &S = Sections[Sec.d.a]; 1106 // This will never fail since wasm sections can never be empty (user-sections 1107 // must have a name and non-user sections each have a defined structure). 1108 Res = StringRef(reinterpret_cast<const char *>(S.Content.data()), 1109 S.Content.size()); 1110 return std::error_code(); 1111 } 1112 1113 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 1114 return 1; 1115 } 1116 1117 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 1118 return false; 1119 } 1120 1121 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 1122 return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE; 1123 } 1124 1125 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 1126 return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA; 1127 } 1128 1129 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 1130 1131 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 1132 1133 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } 1134 1135 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { 1136 DataRefImpl RelocRef; 1137 RelocRef.d.a = Ref.d.a; 1138 RelocRef.d.b = 0; 1139 return relocation_iterator(RelocationRef(RelocRef, this)); 1140 } 1141 1142 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const { 1143 const WasmSection &Sec = getWasmSection(Ref); 1144 DataRefImpl RelocRef; 1145 RelocRef.d.a = Ref.d.a; 1146 RelocRef.d.b = Sec.Relocations.size(); 1147 return relocation_iterator(RelocationRef(RelocRef, this)); 1148 } 1149 1150 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1151 Rel.d.b++; 1152 } 1153 1154 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { 1155 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1156 return Rel.Offset; 1157 } 1158 1159 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1160 llvm_unreachable("not yet implemented"); 1161 SymbolRef Ref; 1162 return symbol_iterator(Ref); 1163 } 1164 1165 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const { 1166 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1167 return Rel.Type; 1168 } 1169 1170 void WasmObjectFile::getRelocationTypeName( 1171 DataRefImpl Ref, SmallVectorImpl<char> &Result) const { 1172 const wasm::WasmRelocation& Rel = getWasmRelocation(Ref); 1173 StringRef Res = "Unknown"; 1174 1175 #define WASM_RELOC(name, value) \ 1176 case wasm::name: \ 1177 Res = #name; \ 1178 break; 1179 1180 switch (Rel.Type) { 1181 #include "llvm/BinaryFormat/WasmRelocs.def" 1182 } 1183 1184 #undef WASM_RELOC 1185 1186 Result.append(Res.begin(), Res.end()); 1187 } 1188 1189 section_iterator WasmObjectFile::section_begin() const { 1190 DataRefImpl Ref; 1191 Ref.d.a = 0; 1192 return section_iterator(SectionRef(Ref, this)); 1193 } 1194 1195 section_iterator WasmObjectFile::section_end() const { 1196 DataRefImpl Ref; 1197 Ref.d.a = Sections.size(); 1198 return section_iterator(SectionRef(Ref, this)); 1199 } 1200 1201 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; } 1202 1203 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 1204 1205 Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; } 1206 1207 SubtargetFeatures WasmObjectFile::getFeatures() const { 1208 return SubtargetFeatures(); 1209 } 1210 1211 bool WasmObjectFile::isRelocatableObject() const { 1212 return HasLinkingSection; 1213 } 1214 1215 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { 1216 assert(Ref.d.a < Sections.size()); 1217 return Sections[Ref.d.a]; 1218 } 1219 1220 const WasmSection & 1221 WasmObjectFile::getWasmSection(const SectionRef &Section) const { 1222 return getWasmSection(Section.getRawDataRefImpl()); 1223 } 1224 1225 const wasm::WasmRelocation & 1226 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const { 1227 return getWasmRelocation(Ref.getRawDataRefImpl()); 1228 } 1229 1230 const wasm::WasmRelocation & 1231 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { 1232 assert(Ref.d.a < Sections.size()); 1233 const WasmSection& Sec = Sections[Ref.d.a]; 1234 assert(Ref.d.b < Sec.Relocations.size()); 1235 return Sec.Relocations[Ref.d.b]; 1236 } 1237