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.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 427 wasm::WASM_SYMBOL_BINDING_WEAK) 428 return make_error<GenericBinaryError>("undefined weak global symbol", 429 object_error::parse_failed); 430 if (IsDefined) { 431 Info.Name = readString(Ptr); 432 unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals; 433 wasm::WasmGlobal &Global = Globals[GlobalIndex]; 434 GlobalType = &Global.Type; 435 if (Global.Name.empty()) { 436 // Use the symbol's name to set a name for the Global, but only if 437 // one hasn't already been set. 438 Global.Name = Info.Name; 439 } 440 } else { 441 wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; 442 Info.Name = Import.Field; 443 GlobalType = &Import.Global; 444 } 445 break; 446 447 case wasm::WASM_SYMBOL_TYPE_DATA: 448 Info.Name = readString(Ptr); 449 if (IsDefined) { 450 uint32_t Index = readVaruint32(Ptr); 451 if (Index >= DataSegments.size()) 452 return make_error<GenericBinaryError>("invalid data symbol index", 453 object_error::parse_failed); 454 uint32_t Offset = readVaruint32(Ptr); 455 uint32_t Size = readVaruint32(Ptr); 456 if (Offset + Size > DataSegments[Index].Data.Content.size()) 457 return make_error<GenericBinaryError>("invalid data symbol offset", 458 object_error::parse_failed); 459 Info.DataRef = wasm::WasmDataReference{Index, Offset, Size}; 460 } 461 break; 462 463 default: 464 return make_error<GenericBinaryError>("Invalid symbol type", 465 object_error::parse_failed); 466 } 467 468 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != 469 wasm::WASM_SYMBOL_BINDING_LOCAL && 470 !SymbolNames.insert(Info.Name).second) 471 return make_error<GenericBinaryError>("Duplicate symbol name " + 472 Twine(Info.Name), 473 object_error::parse_failed); 474 LinkingData.SymbolTable.emplace_back(Info); 475 Symbols.emplace_back(LinkingData.SymbolTable.back(), FunctionType, 476 GlobalType); 477 DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); 478 } 479 480 return Error::success(); 481 } 482 483 Error WasmObjectFile::parseLinkingSectionComdat(const uint8_t *&Ptr, 484 const uint8_t *End) 485 { 486 uint32_t ComdatCount = readVaruint32(Ptr); 487 StringSet<> ComdatSet; 488 for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) { 489 StringRef Name = readString(Ptr); 490 if (Name.empty() || !ComdatSet.insert(Name).second) 491 return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " + Twine(Name), 492 object_error::parse_failed); 493 LinkingData.Comdats.emplace_back(Name); 494 uint32_t Flags = readVaruint32(Ptr); 495 if (Flags != 0) 496 return make_error<GenericBinaryError>("Unsupported COMDAT flags", 497 object_error::parse_failed); 498 499 uint32_t EntryCount = readVaruint32(Ptr); 500 while (EntryCount--) { 501 unsigned Kind = readVaruint32(Ptr); 502 unsigned Index = readVaruint32(Ptr); 503 switch (Kind) { 504 default: 505 return make_error<GenericBinaryError>("Invalid COMDAT entry type", 506 object_error::parse_failed); 507 case wasm::WASM_COMDAT_DATA: 508 if (Index >= DataSegments.size()) 509 return make_error<GenericBinaryError>("COMDAT data index out of range", 510 object_error::parse_failed); 511 if (DataSegments[Index].Data.Comdat != UINT32_MAX) 512 return make_error<GenericBinaryError>("Data segment in two COMDATs", 513 object_error::parse_failed); 514 DataSegments[Index].Data.Comdat = ComdatIndex; 515 break; 516 case wasm::WASM_COMDAT_FUNCTION: 517 if (!isDefinedFunctionIndex(Index)) 518 return make_error<GenericBinaryError>("COMDAT function index out of range", 519 object_error::parse_failed); 520 if (getDefinedFunction(Index).Comdat != UINT32_MAX) 521 return make_error<GenericBinaryError>("Function in two COMDATs", 522 object_error::parse_failed); 523 getDefinedFunction(Index).Comdat = ComdatIndex; 524 break; 525 } 526 } 527 } 528 return Error::success(); 529 } 530 531 WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) { 532 for (WasmSection& Section : Sections) { 533 if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name) 534 return &Section; 535 } 536 return nullptr; 537 } 538 539 WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) { 540 assert(Type != wasm::WASM_SEC_CUSTOM); 541 for (WasmSection& Section : Sections) { 542 if (Section.Type == Type) 543 return &Section; 544 } 545 return nullptr; 546 } 547 548 Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr, 549 const uint8_t *End) { 550 uint8_t SectionCode = readUint8(Ptr); 551 WasmSection* Section = nullptr; 552 if (SectionCode == wasm::WASM_SEC_CUSTOM) { 553 StringRef Name = readString(Ptr); 554 Section = findCustomSectionByName(Name); 555 } else { 556 Section = findSectionByType(SectionCode); 557 } 558 if (!Section) 559 return make_error<GenericBinaryError>("Invalid section code", 560 object_error::parse_failed); 561 uint32_t RelocCount = readVaruint32(Ptr); 562 uint32_t EndOffset = Section->Content.size(); 563 while (RelocCount--) { 564 wasm::WasmRelocation Reloc = {}; 565 Reloc.Type = readVaruint32(Ptr); 566 Reloc.Offset = readVaruint32(Ptr); 567 Reloc.Index = readVaruint32(Ptr); 568 switch (Reloc.Type) { 569 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: 570 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: 571 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: 572 if (!isValidFunctionSymbol(Reloc.Index)) 573 return make_error<GenericBinaryError>("Bad relocation function index", 574 object_error::parse_failed); 575 break; 576 case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: 577 if (Reloc.Index >= Signatures.size()) 578 return make_error<GenericBinaryError>("Bad relocation type index", 579 object_error::parse_failed); 580 break; 581 case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: 582 if (!isValidGlobalSymbol(Reloc.Index)) 583 return make_error<GenericBinaryError>("Bad relocation global index", 584 object_error::parse_failed); 585 break; 586 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: 587 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: 588 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: 589 if (!isValidDataSymbol(Reloc.Index)) 590 return make_error<GenericBinaryError>("Bad relocation data index", 591 object_error::parse_failed); 592 Reloc.Addend = readVarint32(Ptr); 593 break; 594 default: 595 return make_error<GenericBinaryError>("Bad relocation type: " + 596 Twine(Reloc.Type), 597 object_error::parse_failed); 598 } 599 600 // Relocations must fit inside the section, and must appear in order. They 601 // also shouldn't overlap a function/element boundary, but we don't bother 602 // to check that. 603 uint64_t Size = 5; 604 if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 || 605 Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32) 606 Size = 4; 607 if (Reloc.Offset + Size > EndOffset) 608 return make_error<GenericBinaryError>("Bad relocation offset", 609 object_error::parse_failed); 610 611 Section->Relocations.push_back(Reloc); 612 } 613 if (Ptr != End) 614 return make_error<GenericBinaryError>("Reloc section ended prematurely", 615 object_error::parse_failed); 616 return Error::success(); 617 } 618 619 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, 620 const uint8_t *Ptr, const uint8_t *End) { 621 Sec.Name = readString(Ptr); 622 if (Sec.Name == "name") { 623 if (Error Err = parseNameSection(Ptr, End)) 624 return Err; 625 } else if (Sec.Name == "linking") { 626 if (Error Err = parseLinkingSection(Ptr, End)) 627 return Err; 628 } else if (Sec.Name.startswith("reloc.")) { 629 if (Error Err = parseRelocSection(Sec.Name, Ptr, End)) 630 return Err; 631 } 632 return Error::success(); 633 } 634 635 Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) { 636 uint32_t Count = readVaruint32(Ptr); 637 Signatures.reserve(Count); 638 while (Count--) { 639 wasm::WasmSignature Sig; 640 Sig.ReturnType = wasm::WASM_TYPE_NORESULT; 641 uint8_t Form = readUint8(Ptr); 642 if (Form != wasm::WASM_TYPE_FUNC) { 643 return make_error<GenericBinaryError>("Invalid signature type", 644 object_error::parse_failed); 645 } 646 uint32_t ParamCount = readVaruint32(Ptr); 647 Sig.ParamTypes.reserve(ParamCount); 648 while (ParamCount--) { 649 uint32_t ParamType = readUint8(Ptr); 650 Sig.ParamTypes.push_back(ParamType); 651 } 652 uint32_t ReturnCount = readVaruint32(Ptr); 653 if (ReturnCount) { 654 if (ReturnCount != 1) { 655 return make_error<GenericBinaryError>( 656 "Multiple return types not supported", object_error::parse_failed); 657 } 658 Sig.ReturnType = readUint8(Ptr); 659 } 660 Signatures.push_back(Sig); 661 } 662 if (Ptr != End) 663 return make_error<GenericBinaryError>("Type section ended prematurely", 664 object_error::parse_failed); 665 return Error::success(); 666 } 667 668 Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) { 669 uint32_t Count = readVaruint32(Ptr); 670 Imports.reserve(Count); 671 for (uint32_t i = 0; i < Count; i++) { 672 wasm::WasmImport Im; 673 Im.Module = readString(Ptr); 674 Im.Field = readString(Ptr); 675 Im.Kind = readUint8(Ptr); 676 switch (Im.Kind) { 677 case wasm::WASM_EXTERNAL_FUNCTION: 678 NumImportedFunctions++; 679 Im.SigIndex = readVaruint32(Ptr); 680 break; 681 case wasm::WASM_EXTERNAL_GLOBAL: 682 NumImportedGlobals++; 683 Im.Global.Type = readUint8(Ptr); 684 Im.Global.Mutable = readVaruint1(Ptr); 685 break; 686 case wasm::WASM_EXTERNAL_MEMORY: 687 Im.Memory = readLimits(Ptr); 688 break; 689 case wasm::WASM_EXTERNAL_TABLE: 690 Im.Table = readTable(Ptr); 691 if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) 692 return make_error<GenericBinaryError>("Invalid table element type", 693 object_error::parse_failed); 694 break; 695 default: 696 return make_error<GenericBinaryError>( 697 "Unexpected import kind", object_error::parse_failed); 698 } 699 Imports.push_back(Im); 700 } 701 if (Ptr != End) 702 return make_error<GenericBinaryError>("Import section ended prematurely", 703 object_error::parse_failed); 704 return Error::success(); 705 } 706 707 Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) { 708 uint32_t Count = readVaruint32(Ptr); 709 FunctionTypes.reserve(Count); 710 uint32_t NumTypes = Signatures.size(); 711 while (Count--) { 712 uint32_t Type = readVaruint32(Ptr); 713 if (Type >= NumTypes) 714 return make_error<GenericBinaryError>("Invalid function type", 715 object_error::parse_failed); 716 FunctionTypes.push_back(Type); 717 } 718 if (Ptr != End) 719 return make_error<GenericBinaryError>("Function section ended prematurely", 720 object_error::parse_failed); 721 return Error::success(); 722 } 723 724 Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) { 725 uint32_t Count = readVaruint32(Ptr); 726 Tables.reserve(Count); 727 while (Count--) { 728 Tables.push_back(readTable(Ptr)); 729 if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) { 730 return make_error<GenericBinaryError>("Invalid table element type", 731 object_error::parse_failed); 732 } 733 } 734 if (Ptr != End) 735 return make_error<GenericBinaryError>("Table section ended prematurely", 736 object_error::parse_failed); 737 return Error::success(); 738 } 739 740 Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) { 741 uint32_t Count = readVaruint32(Ptr); 742 Memories.reserve(Count); 743 while (Count--) { 744 Memories.push_back(readLimits(Ptr)); 745 } 746 if (Ptr != End) 747 return make_error<GenericBinaryError>("Memory section ended prematurely", 748 object_error::parse_failed); 749 return Error::success(); 750 } 751 752 Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) { 753 GlobalSection = Sections.size(); 754 uint32_t Count = readVaruint32(Ptr); 755 Globals.reserve(Count); 756 while (Count--) { 757 wasm::WasmGlobal Global; 758 Global.Index = NumImportedGlobals + Globals.size(); 759 Global.Type.Type = readUint8(Ptr); 760 Global.Type.Mutable = readVaruint1(Ptr); 761 if (Error Err = readInitExpr(Global.InitExpr, Ptr)) 762 return Err; 763 Globals.push_back(Global); 764 } 765 if (Ptr != End) 766 return make_error<GenericBinaryError>("Global section ended prematurely", 767 object_error::parse_failed); 768 return Error::success(); 769 } 770 771 Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) { 772 uint32_t Count = readVaruint32(Ptr); 773 Exports.reserve(Count); 774 for (uint32_t i = 0; i < Count; i++) { 775 wasm::WasmExport Ex; 776 Ex.Name = readString(Ptr); 777 Ex.Kind = readUint8(Ptr); 778 Ex.Index = readVaruint32(Ptr); 779 switch (Ex.Kind) { 780 case wasm::WASM_EXTERNAL_FUNCTION: 781 if (!isValidFunctionIndex(Ex.Index)) 782 return make_error<GenericBinaryError>("Invalid function export", 783 object_error::parse_failed); 784 break; 785 case wasm::WASM_EXTERNAL_GLOBAL: 786 if (!isValidGlobalIndex(Ex.Index)) 787 return make_error<GenericBinaryError>("Invalid global export", 788 object_error::parse_failed); 789 break; 790 case wasm::WASM_EXTERNAL_MEMORY: 791 case wasm::WASM_EXTERNAL_TABLE: 792 break; 793 default: 794 return make_error<GenericBinaryError>( 795 "Unexpected export kind", object_error::parse_failed); 796 } 797 Exports.push_back(Ex); 798 } 799 if (Ptr != End) 800 return make_error<GenericBinaryError>("Export section ended prematurely", 801 object_error::parse_failed); 802 return Error::success(); 803 } 804 805 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const { 806 return Index < NumImportedFunctions + FunctionTypes.size(); 807 } 808 809 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const { 810 return Index >= NumImportedFunctions && isValidFunctionIndex(Index); 811 } 812 813 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const { 814 return Index < NumImportedGlobals + Globals.size(); 815 } 816 817 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const { 818 return Index >= NumImportedGlobals && isValidGlobalIndex(Index); 819 } 820 821 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const { 822 return Index < Symbols.size() && Symbols[Index].isTypeFunction(); 823 } 824 825 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const { 826 return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); 827 } 828 829 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const { 830 return Index < Symbols.size() && Symbols[Index].isTypeData(); 831 } 832 833 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) { 834 assert(isDefinedFunctionIndex(Index)); 835 return Functions[Index - NumImportedFunctions]; 836 } 837 838 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) { 839 assert(isDefinedGlobalIndex(Index)); 840 return Globals[Index - NumImportedGlobals]; 841 } 842 843 Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) { 844 StartFunction = readVaruint32(Ptr); 845 if (!isValidFunctionIndex(StartFunction)) 846 return make_error<GenericBinaryError>("Invalid start function", 847 object_error::parse_failed); 848 return Error::success(); 849 } 850 851 Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) { 852 CodeSection = Sections.size(); 853 const uint8_t *CodeSectionStart = Ptr; 854 uint32_t FunctionCount = readVaruint32(Ptr); 855 if (FunctionCount != FunctionTypes.size()) { 856 return make_error<GenericBinaryError>("Invalid function count", 857 object_error::parse_failed); 858 } 859 860 while (FunctionCount--) { 861 wasm::WasmFunction Function; 862 const uint8_t *FunctionStart = Ptr; 863 uint32_t Size = readVaruint32(Ptr); 864 const uint8_t *FunctionEnd = Ptr + Size; 865 866 Function.Index = NumImportedFunctions + Functions.size(); 867 Function.CodeSectionOffset = FunctionStart - CodeSectionStart; 868 Function.Size = FunctionEnd - FunctionStart; 869 870 uint32_t NumLocalDecls = readVaruint32(Ptr); 871 Function.Locals.reserve(NumLocalDecls); 872 while (NumLocalDecls--) { 873 wasm::WasmLocalDecl Decl; 874 Decl.Count = readVaruint32(Ptr); 875 Decl.Type = readUint8(Ptr); 876 Function.Locals.push_back(Decl); 877 } 878 879 uint32_t BodySize = FunctionEnd - Ptr; 880 Function.Body = ArrayRef<uint8_t>(Ptr, BodySize); 881 // This will be set later when reading in the linking metadata section. 882 Function.Comdat = UINT32_MAX; 883 Ptr += BodySize; 884 assert(Ptr == FunctionEnd); 885 Functions.push_back(Function); 886 } 887 if (Ptr != End) 888 return make_error<GenericBinaryError>("Code section ended prematurely", 889 object_error::parse_failed); 890 return Error::success(); 891 } 892 893 Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) { 894 uint32_t Count = readVaruint32(Ptr); 895 ElemSegments.reserve(Count); 896 while (Count--) { 897 wasm::WasmElemSegment Segment; 898 Segment.TableIndex = readVaruint32(Ptr); 899 if (Segment.TableIndex != 0) { 900 return make_error<GenericBinaryError>("Invalid TableIndex", 901 object_error::parse_failed); 902 } 903 if (Error Err = readInitExpr(Segment.Offset, Ptr)) 904 return Err; 905 uint32_t NumElems = readVaruint32(Ptr); 906 while (NumElems--) { 907 Segment.Functions.push_back(readVaruint32(Ptr)); 908 } 909 ElemSegments.push_back(Segment); 910 } 911 if (Ptr != End) 912 return make_error<GenericBinaryError>("Elem section ended prematurely", 913 object_error::parse_failed); 914 return Error::success(); 915 } 916 917 Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) { 918 DataSection = Sections.size(); 919 const uint8_t *Start = Ptr; 920 uint32_t Count = readVaruint32(Ptr); 921 DataSegments.reserve(Count); 922 while (Count--) { 923 WasmSegment Segment; 924 Segment.Data.MemoryIndex = readVaruint32(Ptr); 925 if (Error Err = readInitExpr(Segment.Data.Offset, Ptr)) 926 return Err; 927 uint32_t Size = readVaruint32(Ptr); 928 Segment.Data.Content = ArrayRef<uint8_t>(Ptr, Size); 929 // The rest of these Data fields are set later, when reading in the linking 930 // metadata section. 931 Segment.Data.Alignment = 0; 932 Segment.Data.Flags = 0; 933 Segment.Data.Comdat = UINT32_MAX; 934 Segment.SectionOffset = Ptr - Start; 935 Ptr += Size; 936 DataSegments.push_back(Segment); 937 } 938 if (Ptr != End) 939 return make_error<GenericBinaryError>("Data section ended prematurely", 940 object_error::parse_failed); 941 return Error::success(); 942 } 943 944 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const { 945 return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data()); 946 } 947 948 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 949 return Header; 950 } 951 952 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; } 953 954 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 955 uint32_t Result = SymbolRef::SF_None; 956 const WasmSymbol &Sym = getWasmSymbol(Symb); 957 958 DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n"); 959 if (Sym.isBindingWeak()) 960 Result |= SymbolRef::SF_Weak; 961 if (!Sym.isBindingLocal()) 962 Result |= SymbolRef::SF_Global; 963 if (Sym.isHidden()) 964 Result |= SymbolRef::SF_Hidden; 965 if (!Sym.isDefined()) 966 Result |= SymbolRef::SF_Undefined; 967 if (Sym.isTypeFunction()) 968 Result |= SymbolRef::SF_Executable; 969 return Result; 970 } 971 972 basic_symbol_iterator WasmObjectFile::symbol_begin() const { 973 DataRefImpl Ref; 974 Ref.d.a = 0; 975 return BasicSymbolRef(Ref, this); 976 } 977 978 basic_symbol_iterator WasmObjectFile::symbol_end() const { 979 DataRefImpl Ref; 980 Ref.d.a = Symbols.size(); 981 return BasicSymbolRef(Ref, this); 982 } 983 984 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const { 985 return Symbols[Symb.d.a]; 986 } 987 988 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const { 989 return getWasmSymbol(Symb.getRawDataRefImpl()); 990 } 991 992 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 993 return getWasmSymbol(Symb).Info.Name; 994 } 995 996 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 997 return getSymbolValue(Symb); 998 } 999 1000 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const { 1001 switch (Sym.Info.Kind) { 1002 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1003 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1004 return Sym.Info.ElementIndex; 1005 case wasm::WASM_SYMBOL_TYPE_DATA: { 1006 // The value of a data symbol is the segment offset, plus the symbol 1007 // offset within the segment. 1008 uint32_t SegmentIndex = Sym.Info.DataRef.Segment; 1009 const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data; 1010 assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST); 1011 return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset; 1012 } 1013 } 1014 llvm_unreachable("invalid symbol type"); 1015 } 1016 1017 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 1018 return getWasmSymbolValue(getWasmSymbol(Symb)); 1019 } 1020 1021 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 1022 llvm_unreachable("not yet implemented"); 1023 return 0; 1024 } 1025 1026 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 1027 llvm_unreachable("not yet implemented"); 1028 return 0; 1029 } 1030 1031 Expected<SymbolRef::Type> 1032 WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 1033 const WasmSymbol &Sym = getWasmSymbol(Symb); 1034 1035 switch (Sym.Info.Kind) { 1036 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1037 return SymbolRef::ST_Function; 1038 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1039 return SymbolRef::ST_Other; 1040 case wasm::WASM_SYMBOL_TYPE_DATA: 1041 return SymbolRef::ST_Data; 1042 } 1043 1044 llvm_unreachable("Unknown WasmSymbol::SymbolType"); 1045 return SymbolRef::ST_Other; 1046 } 1047 1048 Expected<section_iterator> 1049 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 1050 const WasmSymbol& Sym = getWasmSymbol(Symb); 1051 if (Sym.isUndefined()) 1052 return section_end(); 1053 1054 DataRefImpl Ref; 1055 switch (Sym.Info.Kind) { 1056 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1057 Ref.d.a = CodeSection; 1058 break; 1059 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1060 Ref.d.a = GlobalSection; 1061 break; 1062 case wasm::WASM_SYMBOL_TYPE_DATA: 1063 Ref.d.a = DataSection; 1064 break; 1065 default: 1066 llvm_unreachable("Unknown WasmSymbol::SymbolType"); 1067 } 1068 return section_iterator(SectionRef(Ref, this)); 1069 } 1070 1071 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 1072 1073 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, 1074 StringRef &Res) const { 1075 const WasmSection &S = Sections[Sec.d.a]; 1076 #define ECase(X) \ 1077 case wasm::WASM_SEC_##X: \ 1078 Res = #X; \ 1079 break 1080 switch (S.Type) { 1081 ECase(TYPE); 1082 ECase(IMPORT); 1083 ECase(FUNCTION); 1084 ECase(TABLE); 1085 ECase(MEMORY); 1086 ECase(GLOBAL); 1087 ECase(EXPORT); 1088 ECase(START); 1089 ECase(ELEM); 1090 ECase(CODE); 1091 ECase(DATA); 1092 case wasm::WASM_SEC_CUSTOM: 1093 Res = S.Name; 1094 break; 1095 default: 1096 return object_error::invalid_section_index; 1097 } 1098 #undef ECase 1099 return std::error_code(); 1100 } 1101 1102 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } 1103 1104 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const { 1105 return Sec.d.a; 1106 } 1107 1108 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 1109 const WasmSection &S = Sections[Sec.d.a]; 1110 return S.Content.size(); 1111 } 1112 1113 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, 1114 StringRef &Res) const { 1115 const WasmSection &S = Sections[Sec.d.a]; 1116 // This will never fail since wasm sections can never be empty (user-sections 1117 // must have a name and non-user sections each have a defined structure). 1118 Res = StringRef(reinterpret_cast<const char *>(S.Content.data()), 1119 S.Content.size()); 1120 return std::error_code(); 1121 } 1122 1123 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 1124 return 1; 1125 } 1126 1127 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 1128 return false; 1129 } 1130 1131 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 1132 return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE; 1133 } 1134 1135 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 1136 return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA; 1137 } 1138 1139 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 1140 1141 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 1142 1143 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } 1144 1145 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { 1146 DataRefImpl RelocRef; 1147 RelocRef.d.a = Ref.d.a; 1148 RelocRef.d.b = 0; 1149 return relocation_iterator(RelocationRef(RelocRef, this)); 1150 } 1151 1152 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const { 1153 const WasmSection &Sec = getWasmSection(Ref); 1154 DataRefImpl RelocRef; 1155 RelocRef.d.a = Ref.d.a; 1156 RelocRef.d.b = Sec.Relocations.size(); 1157 return relocation_iterator(RelocationRef(RelocRef, this)); 1158 } 1159 1160 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1161 Rel.d.b++; 1162 } 1163 1164 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { 1165 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1166 return Rel.Offset; 1167 } 1168 1169 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1170 llvm_unreachable("not yet implemented"); 1171 SymbolRef Ref; 1172 return symbol_iterator(Ref); 1173 } 1174 1175 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const { 1176 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1177 return Rel.Type; 1178 } 1179 1180 void WasmObjectFile::getRelocationTypeName( 1181 DataRefImpl Ref, SmallVectorImpl<char> &Result) const { 1182 const wasm::WasmRelocation& Rel = getWasmRelocation(Ref); 1183 StringRef Res = "Unknown"; 1184 1185 #define WASM_RELOC(name, value) \ 1186 case wasm::name: \ 1187 Res = #name; \ 1188 break; 1189 1190 switch (Rel.Type) { 1191 #include "llvm/BinaryFormat/WasmRelocs.def" 1192 } 1193 1194 #undef WASM_RELOC 1195 1196 Result.append(Res.begin(), Res.end()); 1197 } 1198 1199 section_iterator WasmObjectFile::section_begin() const { 1200 DataRefImpl Ref; 1201 Ref.d.a = 0; 1202 return section_iterator(SectionRef(Ref, this)); 1203 } 1204 1205 section_iterator WasmObjectFile::section_end() const { 1206 DataRefImpl Ref; 1207 Ref.d.a = Sections.size(); 1208 return section_iterator(SectionRef(Ref, this)); 1209 } 1210 1211 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; } 1212 1213 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 1214 1215 Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; } 1216 1217 SubtargetFeatures WasmObjectFile::getFeatures() const { 1218 return SubtargetFeatures(); 1219 } 1220 1221 bool WasmObjectFile::isRelocatableObject() const { 1222 return HasLinkingSection; 1223 } 1224 1225 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { 1226 assert(Ref.d.a < Sections.size()); 1227 return Sections[Ref.d.a]; 1228 } 1229 1230 const WasmSection & 1231 WasmObjectFile::getWasmSection(const SectionRef &Section) const { 1232 return getWasmSection(Section.getRawDataRefImpl()); 1233 } 1234 1235 const wasm::WasmRelocation & 1236 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const { 1237 return getWasmRelocation(Ref.getRawDataRefImpl()); 1238 } 1239 1240 const wasm::WasmRelocation & 1241 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { 1242 assert(Ref.d.a < Sections.size()); 1243 const WasmSection& Sec = Sections[Ref.d.a]; 1244 assert(Ref.d.b < Sec.Relocations.size()); 1245 return Sec.Relocations[Ref.d.b]; 1246 } 1247