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