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/STLExtras.h" 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/ADT/Triple.h" 14 #include "llvm/MC/SubtargetFeature.h" 15 #include "llvm/Object/Binary.h" 16 #include "llvm/Object/Error.h" 17 #include "llvm/Object/ObjectFile.h" 18 #include "llvm/Object/SymbolicFile.h" 19 #include "llvm/Object/Wasm.h" 20 #include "llvm/Support/Endian.h" 21 #include "llvm/Support/Error.h" 22 #include "llvm/Support/ErrorHandling.h" 23 #include "llvm/Support/LEB128.h" 24 #include "llvm/Support/Wasm.h" 25 #include <algorithm> 26 #include <cassert> 27 #include <cstdint> 28 #include <cstring> 29 #include <system_error> 30 31 using namespace llvm; 32 using namespace object; 33 34 Expected<std::unique_ptr<WasmObjectFile>> 35 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { 36 Error Err = Error::success(); 37 auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err); 38 if (Err) 39 return std::move(Err); 40 41 return std::move(ObjectFile); 42 } 43 44 #define VARINT7_MAX ((1<<7)-1) 45 #define VARINT7_MIN (-(1<<7)) 46 #define VARUINT7_MAX (1<<7) 47 #define VARUINT1_MAX (1) 48 49 static uint8_t readUint8(const uint8_t *&Ptr) { return *Ptr++; } 50 51 static uint32_t readUint32(const uint8_t *&Ptr) { 52 uint32_t Result = support::endian::read32le(Ptr); 53 Ptr += sizeof(Result); 54 return Result; 55 } 56 57 static int32_t readFloat32(const uint8_t *&Ptr) { 58 int32_t Result = 0; 59 memcpy(&Result, Ptr, sizeof(Result)); 60 Ptr += sizeof(Result); 61 return Result; 62 } 63 64 static int64_t readFloat64(const uint8_t *&Ptr) { 65 int64_t Result = 0; 66 memcpy(&Result, Ptr, sizeof(Result)); 67 Ptr += sizeof(Result); 68 return Result; 69 } 70 71 static uint64_t readULEB128(const uint8_t *&Ptr) { 72 unsigned Count; 73 uint64_t Result = decodeULEB128(Ptr, &Count); 74 Ptr += Count; 75 return Result; 76 } 77 78 static StringRef readString(const uint8_t *&Ptr) { 79 uint32_t StringLen = readULEB128(Ptr); 80 StringRef Return = StringRef(reinterpret_cast<const char *>(Ptr), StringLen); 81 Ptr += StringLen; 82 return Return; 83 } 84 85 static int64_t readLEB128(const uint8_t *&Ptr) { 86 unsigned Count; 87 uint64_t Result = decodeSLEB128(Ptr, &Count); 88 Ptr += Count; 89 return Result; 90 } 91 92 static uint8_t readVaruint1(const uint8_t *&Ptr) { 93 int64_t result = readLEB128(Ptr); 94 assert(result <= VARUINT1_MAX && result >= 0); 95 return result; 96 } 97 98 static int8_t readVarint7(const uint8_t *&Ptr) { 99 int64_t result = readLEB128(Ptr); 100 assert(result <= VARINT7_MAX && result >= VARINT7_MIN); 101 return result; 102 } 103 104 static uint8_t readVaruint7(const uint8_t *&Ptr) { 105 uint64_t result = readULEB128(Ptr); 106 assert(result <= VARUINT7_MAX); 107 return result; 108 } 109 110 static int32_t readVarint32(const uint8_t *&Ptr) { 111 int64_t result = readLEB128(Ptr); 112 assert(result <= INT32_MAX && result >= INT32_MIN); 113 return result; 114 } 115 116 static uint32_t readVaruint32(const uint8_t *&Ptr) { 117 uint64_t result = readULEB128(Ptr); 118 assert(result <= UINT32_MAX); 119 return result; 120 } 121 122 static int64_t readVarint64(const uint8_t *&Ptr) { 123 return readLEB128(Ptr); 124 } 125 126 static uint8_t readOpcode(const uint8_t *&Ptr) { 127 return readUint8(Ptr); 128 } 129 130 static Error readInitExpr(wasm::WasmInitExpr &Expr, const uint8_t *&Ptr) { 131 Expr.Opcode = readOpcode(Ptr); 132 133 switch (Expr.Opcode) { 134 case wasm::WASM_OPCODE_I32_CONST: 135 Expr.Value.Int32 = readVarint32(Ptr); 136 break; 137 case wasm::WASM_OPCODE_I64_CONST: 138 Expr.Value.Int64 = readVarint64(Ptr); 139 break; 140 case wasm::WASM_OPCODE_F32_CONST: 141 Expr.Value.Float32 = readFloat32(Ptr); 142 break; 143 case wasm::WASM_OPCODE_F64_CONST: 144 Expr.Value.Float64 = readFloat64(Ptr); 145 break; 146 case wasm::WASM_OPCODE_GET_GLOBAL: 147 Expr.Value.Global = readULEB128(Ptr); 148 break; 149 default: 150 return make_error<GenericBinaryError>("Invalid opcode in init_expr", 151 object_error::parse_failed); 152 } 153 154 uint8_t EndOpcode = readOpcode(Ptr); 155 if (EndOpcode != wasm::WASM_OPCODE_END) { 156 return make_error<GenericBinaryError>("Invalid init_expr", 157 object_error::parse_failed); 158 } 159 return Error::success(); 160 } 161 162 static wasm::WasmLimits readLimits(const uint8_t *&Ptr) { 163 wasm::WasmLimits Result; 164 Result.Flags = readVaruint1(Ptr); 165 Result.Initial = readVaruint32(Ptr); 166 if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) 167 Result.Maximum = readVaruint32(Ptr); 168 return Result; 169 } 170 171 static Error readSection(WasmSection &Section, const uint8_t *&Ptr, 172 const uint8_t *Start) { 173 // TODO(sbc): Avoid reading past EOF in the case of malformed files. 174 Section.Offset = Ptr - Start; 175 Section.Type = readVaruint7(Ptr); 176 uint32_t Size = readVaruint32(Ptr); 177 if (Size == 0) 178 return make_error<StringError>("Zero length section", 179 object_error::parse_failed); 180 Section.Content = ArrayRef<uint8_t>(Ptr, Size); 181 Ptr += Size; 182 return Error::success(); 183 } 184 185 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) 186 : ObjectFile(Binary::ID_Wasm, Buffer) { 187 ErrorAsOutParameter ErrAsOutParam(&Err); 188 Header.Magic = getData().substr(0, 4); 189 if (Header.Magic != StringRef("\0asm", 4)) { 190 Err = make_error<StringError>("Bad magic number", 191 object_error::parse_failed); 192 return; 193 } 194 const uint8_t *Ptr = getPtr(4); 195 Header.Version = readUint32(Ptr); 196 if (Header.Version != wasm::WasmVersion) { 197 Err = make_error<StringError>("Bad version number", 198 object_error::parse_failed); 199 return; 200 } 201 202 const uint8_t *Eof = getPtr(getData().size()); 203 WasmSection Sec; 204 while (Ptr < Eof) { 205 if ((Err = readSection(Sec, Ptr, getPtr(0)))) 206 return; 207 if ((Err = parseSection(Sec))) 208 return; 209 210 Sections.push_back(Sec); 211 } 212 } 213 214 Error WasmObjectFile::parseSection(WasmSection &Sec) { 215 const uint8_t* Start = Sec.Content.data(); 216 const uint8_t* End = Start + Sec.Content.size(); 217 switch (Sec.Type) { 218 case wasm::WASM_SEC_CUSTOM: 219 return parseCustomSection(Sec, Start, End); 220 case wasm::WASM_SEC_TYPE: 221 return parseTypeSection(Start, End); 222 case wasm::WASM_SEC_IMPORT: 223 return parseImportSection(Start, End); 224 case wasm::WASM_SEC_FUNCTION: 225 return parseFunctionSection(Start, End); 226 case wasm::WASM_SEC_TABLE: 227 return parseTableSection(Start, End); 228 case wasm::WASM_SEC_MEMORY: 229 return parseMemorySection(Start, End); 230 case wasm::WASM_SEC_GLOBAL: 231 return parseGlobalSection(Start, End); 232 case wasm::WASM_SEC_EXPORT: 233 return parseExportSection(Start, End); 234 case wasm::WASM_SEC_START: 235 return parseStartSection(Start, End); 236 case wasm::WASM_SEC_ELEM: 237 return parseElemSection(Start, End); 238 case wasm::WASM_SEC_CODE: 239 return parseCodeSection(Start, End); 240 case wasm::WASM_SEC_DATA: 241 return parseDataSection(Start, End); 242 default: 243 return make_error<GenericBinaryError>("Bad section type", 244 object_error::parse_failed); 245 } 246 } 247 248 Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) { 249 while (Ptr < End) { 250 uint8_t Type = readVarint7(Ptr); 251 uint32_t Size = readVaruint32(Ptr); 252 switch (Type) { 253 case wasm::WASM_NAMES_FUNCTION: { 254 uint32_t Count = readVaruint32(Ptr); 255 while (Count--) { 256 /*uint32_t Index =*/readVaruint32(Ptr); 257 StringRef Name = readString(Ptr); 258 if (!Name.empty()) 259 Symbols.emplace_back(Name, 260 WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME); 261 } 262 break; 263 } 264 // Ignore local names for now 265 case wasm::WASM_NAMES_LOCAL: 266 default: 267 Ptr += Size; 268 break; 269 } 270 } 271 272 if (Ptr != End) 273 return make_error<GenericBinaryError>("Name section ended prematurely", 274 object_error::parse_failed); 275 return Error::success(); 276 } 277 278 WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) { 279 for (WasmSection& Section : Sections) { 280 if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name) 281 return &Section; 282 } 283 return nullptr; 284 } 285 286 WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) { 287 assert(Type != wasm::WASM_SEC_CUSTOM); 288 for (WasmSection& Section : Sections) { 289 if (Section.Type == Type) 290 return &Section; 291 } 292 return nullptr; 293 } 294 295 Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr, 296 const uint8_t *End) { 297 uint8_t SectionCode = readVarint7(Ptr); 298 WasmSection* Section = nullptr; 299 if (SectionCode == wasm::WASM_SEC_CUSTOM) { 300 StringRef Name = readString(Ptr); 301 Section = findCustomSectionByName(Name); 302 } else { 303 Section = findSectionByType(SectionCode); 304 } 305 if (!Section) 306 return make_error<GenericBinaryError>("Invalid section code", 307 object_error::parse_failed); 308 uint32_t RelocCount = readVaruint32(Ptr); 309 while (RelocCount--) { 310 wasm::WasmRelocation Reloc; 311 memset(&Reloc, 0, sizeof(Reloc)); 312 Reloc.Type = readVaruint32(Ptr); 313 Reloc.Offset = readVaruint32(Ptr); 314 Reloc.Index = readVaruint32(Ptr); 315 switch (Reloc.Type) { 316 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: 317 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: 318 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: 319 case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: 320 break; 321 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: 322 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: 323 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: 324 Reloc.Addend = readVarint32(Ptr); 325 break; 326 default: 327 return make_error<GenericBinaryError>("Bad relocation type", 328 object_error::parse_failed); 329 } 330 Section->Relocations.push_back(Reloc); 331 } 332 if (Ptr != End) 333 return make_error<GenericBinaryError>("Reloc section ended prematurely", 334 object_error::parse_failed); 335 return Error::success(); 336 } 337 338 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, 339 const uint8_t *Ptr, const uint8_t *End) { 340 Sec.Name = readString(Ptr); 341 if (Sec.Name == "name") { 342 if (Error Err = parseNameSection(Ptr, End)) 343 return Err; 344 } else if (Sec.Name.startswith("reloc.")) { 345 if (Error Err = parseRelocSection(Sec.Name, Ptr, End)) 346 return Err; 347 } 348 return Error::success(); 349 } 350 351 Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) { 352 uint32_t Count = readVaruint32(Ptr); 353 Signatures.reserve(Count); 354 while (Count--) { 355 wasm::WasmSignature Sig; 356 Sig.ReturnType = wasm::WASM_TYPE_NORESULT; 357 int8_t Form = readVarint7(Ptr); 358 if (Form != wasm::WASM_TYPE_FUNC) { 359 return make_error<GenericBinaryError>("Invalid signature type", 360 object_error::parse_failed); 361 } 362 uint32_t ParamCount = readVaruint32(Ptr); 363 Sig.ParamTypes.reserve(ParamCount); 364 while (ParamCount--) { 365 uint32_t ParamType = readVarint7(Ptr); 366 Sig.ParamTypes.push_back(ParamType); 367 } 368 uint32_t ReturnCount = readVaruint32(Ptr); 369 if (ReturnCount) { 370 if (ReturnCount != 1) { 371 return make_error<GenericBinaryError>( 372 "Multiple return types not supported", object_error::parse_failed); 373 } 374 Sig.ReturnType = readVarint7(Ptr); 375 } 376 Signatures.push_back(Sig); 377 } 378 if (Ptr != End) 379 return make_error<GenericBinaryError>("Type section ended prematurely", 380 object_error::parse_failed); 381 return Error::success(); 382 } 383 384 Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) { 385 uint32_t Count = readVaruint32(Ptr); 386 Imports.reserve(Count); 387 while (Count--) { 388 wasm::WasmImport Im; 389 Im.Module = readString(Ptr); 390 Im.Field = readString(Ptr); 391 Im.Kind = readUint8(Ptr); 392 switch (Im.Kind) { 393 case wasm::WASM_EXTERNAL_FUNCTION: 394 Im.SigIndex = readVaruint32(Ptr); 395 Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT); 396 break; 397 case wasm::WASM_EXTERNAL_GLOBAL: 398 Im.GlobalType = readVarint7(Ptr); 399 Im.GlobalMutable = readVaruint1(Ptr); 400 Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT); 401 break; 402 default: 403 // TODO(sbc): Handle other kinds of imports 404 return make_error<GenericBinaryError>( 405 "Unexpected import kind", object_error::parse_failed); 406 } 407 Imports.push_back(Im); 408 } 409 if (Ptr != End) 410 return make_error<GenericBinaryError>("Import section ended prematurely", 411 object_error::parse_failed); 412 return Error::success(); 413 } 414 415 Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) { 416 uint32_t Count = readVaruint32(Ptr); 417 FunctionTypes.reserve(Count); 418 while (Count--) { 419 FunctionTypes.push_back(readVaruint32(Ptr)); 420 } 421 if (Ptr != End) 422 return make_error<GenericBinaryError>("Function section ended prematurely", 423 object_error::parse_failed); 424 return Error::success(); 425 } 426 427 Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) { 428 uint32_t Count = readVaruint32(Ptr); 429 Tables.reserve(Count); 430 while (Count--) { 431 wasm::WasmTable Table; 432 Table.ElemType = readVarint7(Ptr); 433 if (Table.ElemType != wasm::WASM_TYPE_ANYFUNC) { 434 return make_error<GenericBinaryError>("Invalid table element type", 435 object_error::parse_failed); 436 } 437 Table.Limits = readLimits(Ptr); 438 Tables.push_back(Table); 439 } 440 if (Ptr != End) 441 return make_error<GenericBinaryError>("Table section ended prematurely", 442 object_error::parse_failed); 443 return Error::success(); 444 } 445 446 Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) { 447 uint32_t Count = readVaruint32(Ptr); 448 Memories.reserve(Count); 449 while (Count--) { 450 Memories.push_back(readLimits(Ptr)); 451 } 452 if (Ptr != End) 453 return make_error<GenericBinaryError>("Memory section ended prematurely", 454 object_error::parse_failed); 455 return Error::success(); 456 } 457 458 Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) { 459 uint32_t Count = readVaruint32(Ptr); 460 Globals.reserve(Count); 461 while (Count--) { 462 wasm::WasmGlobal Global; 463 Global.Type = readVarint7(Ptr); 464 Global.Mutable = readVaruint1(Ptr); 465 if (Error Err = readInitExpr(Global.InitExpr, Ptr)) 466 return Err; 467 Globals.push_back(Global); 468 } 469 if (Ptr != End) 470 return make_error<GenericBinaryError>("Global section ended prematurely", 471 object_error::parse_failed); 472 return Error::success(); 473 } 474 475 Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) { 476 uint32_t Count = readVaruint32(Ptr); 477 Exports.reserve(Count); 478 while (Count--) { 479 wasm::WasmExport Ex; 480 Ex.Name = readString(Ptr); 481 Ex.Kind = readUint8(Ptr); 482 Ex.Index = readVaruint32(Ptr); 483 Exports.push_back(Ex); 484 switch (Ex.Kind) { 485 case wasm::WASM_EXTERNAL_FUNCTION: 486 Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT); 487 break; 488 case wasm::WASM_EXTERNAL_GLOBAL: 489 Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT); 490 break; 491 default: 492 // TODO(sbc): Handle other kinds of exports 493 return make_error<GenericBinaryError>( 494 "Unexpected export kind", object_error::parse_failed); 495 } 496 } 497 if (Ptr != End) 498 return make_error<GenericBinaryError>("Export section ended prematurely", 499 object_error::parse_failed); 500 return Error::success(); 501 } 502 503 Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) { 504 StartFunction = readVaruint32(Ptr); 505 if (StartFunction < FunctionTypes.size()) 506 return make_error<GenericBinaryError>("Invalid start function", 507 object_error::parse_failed); 508 return Error::success(); 509 } 510 511 Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) { 512 uint32_t FunctionCount = readVaruint32(Ptr); 513 if (FunctionCount != FunctionTypes.size()) { 514 return make_error<GenericBinaryError>("Invalid function count", 515 object_error::parse_failed); 516 } 517 518 CodeSection = ArrayRef<uint8_t>(Ptr, End - Ptr); 519 520 while (FunctionCount--) { 521 wasm::WasmFunction Function; 522 uint32_t FunctionSize = readVaruint32(Ptr); 523 const uint8_t *FunctionEnd = Ptr + FunctionSize; 524 525 uint32_t NumLocalDecls = readVaruint32(Ptr); 526 Function.Locals.reserve(NumLocalDecls); 527 while (NumLocalDecls--) { 528 wasm::WasmLocalDecl Decl; 529 Decl.Count = readVaruint32(Ptr); 530 Decl.Type = readVarint7(Ptr); 531 Function.Locals.push_back(Decl); 532 } 533 534 uint32_t BodySize = FunctionEnd - Ptr; 535 Function.Body = ArrayRef<uint8_t>(Ptr, BodySize); 536 Ptr += BodySize; 537 assert(Ptr == FunctionEnd); 538 Functions.push_back(Function); 539 } 540 if (Ptr != End) 541 return make_error<GenericBinaryError>("Code section ended prematurely", 542 object_error::parse_failed); 543 return Error::success(); 544 } 545 546 Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) { 547 uint32_t Count = readVaruint32(Ptr); 548 ElemSegments.reserve(Count); 549 while (Count--) { 550 wasm::WasmElemSegment Segment; 551 Segment.TableIndex = readVaruint32(Ptr); 552 if (Segment.TableIndex != 0) { 553 return make_error<GenericBinaryError>("Invalid TableIndex", 554 object_error::parse_failed); 555 } 556 if (Error Err = readInitExpr(Segment.Offset, Ptr)) 557 return Err; 558 uint32_t NumElems = readVaruint32(Ptr); 559 while (NumElems--) { 560 Segment.Functions.push_back(readVaruint32(Ptr)); 561 } 562 ElemSegments.push_back(Segment); 563 } 564 if (Ptr != End) 565 return make_error<GenericBinaryError>("Elem section ended prematurely", 566 object_error::parse_failed); 567 return Error::success(); 568 } 569 570 Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) { 571 uint32_t Count = readVaruint32(Ptr); 572 DataSegments.reserve(Count); 573 while (Count--) { 574 wasm::WasmDataSegment Segment; 575 Segment.Index = readVaruint32(Ptr); 576 if (Error Err = readInitExpr(Segment.Offset, Ptr)) 577 return Err; 578 uint32_t Size = readVaruint32(Ptr); 579 Segment.Content = ArrayRef<uint8_t>(Ptr, Size); 580 Ptr += Size; 581 DataSegments.push_back(Segment); 582 } 583 if (Ptr != End) 584 return make_error<GenericBinaryError>("Data section ended prematurely", 585 object_error::parse_failed); 586 return Error::success(); 587 } 588 589 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const { 590 return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data()); 591 } 592 593 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 594 return Header; 595 } 596 597 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; } 598 599 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 600 const WasmSymbol &Sym = getWasmSymbol(Symb); 601 switch (Sym.Type) { 602 case WasmSymbol::SymbolType::FUNCTION_IMPORT: 603 return object::SymbolRef::SF_Undefined | SymbolRef::SF_Executable; 604 case WasmSymbol::SymbolType::FUNCTION_EXPORT: 605 return object::SymbolRef::SF_Global | SymbolRef::SF_Executable; 606 case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: 607 return object::SymbolRef::SF_Executable; 608 case WasmSymbol::SymbolType::GLOBAL_IMPORT: 609 return object::SymbolRef::SF_Undefined; 610 case WasmSymbol::SymbolType::GLOBAL_EXPORT: 611 return object::SymbolRef::SF_Global; 612 } 613 llvm_unreachable("Unknown WasmSymbol::SymbolType"); 614 } 615 616 basic_symbol_iterator WasmObjectFile::symbol_begin() const { 617 DataRefImpl Ref; 618 Ref.d.a = 0; 619 return BasicSymbolRef(Ref, this); 620 } 621 622 basic_symbol_iterator WasmObjectFile::symbol_end() const { 623 DataRefImpl Ref; 624 Ref.d.a = Symbols.size(); 625 return BasicSymbolRef(Ref, this); 626 } 627 628 const WasmSymbol &WasmObjectFile::getWasmSymbol(DataRefImpl Symb) const { 629 return Symbols[Symb.d.a]; 630 } 631 632 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 633 const WasmSymbol &Sym = getWasmSymbol(Symb); 634 return Sym.Name; 635 } 636 637 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 638 return (uint64_t)Symb.d.a; 639 } 640 641 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 642 llvm_unreachable("not yet implemented"); 643 return 0; 644 } 645 646 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 647 llvm_unreachable("not yet implemented"); 648 return 0; 649 } 650 651 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 652 llvm_unreachable("not yet implemented"); 653 return 0; 654 } 655 656 Expected<SymbolRef::Type> 657 WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 658 llvm_unreachable("not yet implemented"); 659 return errorCodeToError(object_error::invalid_symbol_index); 660 } 661 662 Expected<section_iterator> 663 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 664 llvm_unreachable("not yet implemented"); 665 return errorCodeToError(object_error::invalid_symbol_index); 666 } 667 668 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 669 670 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, 671 StringRef &Res) const { 672 const WasmSection &S = Sections[Sec.d.a]; 673 #define ECase(X) \ 674 case wasm::WASM_SEC_##X: \ 675 Res = #X; \ 676 break 677 switch (S.Type) { 678 ECase(TYPE); 679 ECase(IMPORT); 680 ECase(FUNCTION); 681 ECase(TABLE); 682 ECase(MEMORY); 683 ECase(GLOBAL); 684 ECase(EXPORT); 685 ECase(START); 686 ECase(ELEM); 687 ECase(CODE); 688 ECase(DATA); 689 case wasm::WASM_SEC_CUSTOM: 690 Res = S.Name; 691 break; 692 default: 693 return object_error::invalid_section_index; 694 } 695 #undef ECase 696 return std::error_code(); 697 } 698 699 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } 700 701 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 702 const WasmSection &S = Sections[Sec.d.a]; 703 return S.Content.size(); 704 } 705 706 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, 707 StringRef &Res) const { 708 const WasmSection &S = Sections[Sec.d.a]; 709 // This will never fail since wasm sections can never be empty (user-sections 710 // must have a name and non-user sections each have a defined structure). 711 Res = StringRef(reinterpret_cast<const char *>(S.Content.data()), 712 S.Content.size()); 713 return std::error_code(); 714 } 715 716 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 717 return 1; 718 } 719 720 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 721 return false; 722 } 723 724 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 725 return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE; 726 } 727 728 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 729 return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA; 730 } 731 732 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 733 734 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 735 736 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } 737 738 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { 739 DataRefImpl RelocRef; 740 RelocRef.d.a = Ref.d.a; 741 RelocRef.d.b = 0; 742 return relocation_iterator(RelocationRef(RelocRef, this)); 743 } 744 745 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const { 746 const WasmSection &Sec = getWasmSection(Ref); 747 DataRefImpl RelocRef; 748 RelocRef.d.a = Ref.d.a; 749 RelocRef.d.b = Sec.Relocations.size(); 750 return relocation_iterator(RelocationRef(RelocRef, this)); 751 } 752 753 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 754 Rel.d.b++; 755 } 756 757 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { 758 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 759 return Rel.Offset; 760 } 761 762 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 763 llvm_unreachable("not yet implemented"); 764 SymbolRef Ref; 765 return symbol_iterator(Ref); 766 } 767 768 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const { 769 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 770 return Rel.Type; 771 } 772 773 void WasmObjectFile::getRelocationTypeName( 774 DataRefImpl Ref, SmallVectorImpl<char> &Result) const { 775 const wasm::WasmRelocation& Rel = getWasmRelocation(Ref); 776 StringRef Res = "Unknown"; 777 778 #define WASM_RELOC(name, value) \ 779 case wasm::name: \ 780 Res = #name; \ 781 break; 782 783 switch (Rel.Type) { 784 #include "llvm/Support/WasmRelocs/WebAssembly.def" 785 } 786 787 #undef WASM_RELOC 788 789 Result.append(Res.begin(), Res.end()); 790 } 791 792 section_iterator WasmObjectFile::section_begin() const { 793 DataRefImpl Ref; 794 Ref.d.a = 0; 795 return section_iterator(SectionRef(Ref, this)); 796 } 797 798 section_iterator WasmObjectFile::section_end() const { 799 DataRefImpl Ref; 800 Ref.d.a = Sections.size(); 801 return section_iterator(SectionRef(Ref, this)); 802 } 803 804 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; } 805 806 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 807 808 unsigned WasmObjectFile::getArch() const { return Triple::wasm32; } 809 810 SubtargetFeatures WasmObjectFile::getFeatures() const { 811 return SubtargetFeatures(); 812 } 813 814 bool WasmObjectFile::isRelocatableObject() const { return false; } 815 816 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { 817 assert(Ref.d.a < Sections.size()); 818 return Sections[Ref.d.a]; 819 } 820 821 const WasmSection & 822 WasmObjectFile::getWasmSection(const SectionRef &Section) const { 823 return getWasmSection(Section.getRawDataRefImpl()); 824 } 825 826 const wasm::WasmRelocation & 827 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const { 828 return getWasmRelocation(Ref.getRawDataRefImpl()); 829 } 830 831 const wasm::WasmRelocation & 832 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { 833 assert(Ref.d.a < Sections.size()); 834 const WasmSection& Sec = Sections[Ref.d.a]; 835 assert(Ref.d.b < Sec.Relocations.size()); 836 return Sec.Relocations[Ref.d.b]; 837 } 838