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