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 = readUint32(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 break; 320 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: 321 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: 322 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: 323 Reloc.Addend = readVaruint32(Ptr); 324 break; 325 default: 326 return make_error<GenericBinaryError>("Bad relocation type", 327 object_error::parse_failed); 328 } 329 Section->Relocations.push_back(Reloc); 330 } 331 if (Ptr != End) 332 return make_error<GenericBinaryError>("Reloc section ended prematurely", 333 object_error::parse_failed); 334 return Error::success(); 335 } 336 337 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, 338 const uint8_t *Ptr, const uint8_t *End) { 339 Sec.Name = readString(Ptr); 340 if (Sec.Name == "name") { 341 if (Error Err = parseNameSection(Ptr, End)) 342 return Err; 343 } else if (Sec.Name.startswith("reloc.")) { 344 if (Error Err = parseRelocSection(Sec.Name, Ptr, End)) 345 return Err; 346 } 347 return Error::success(); 348 } 349 350 Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) { 351 uint32_t Count = readVaruint32(Ptr); 352 Signatures.reserve(Count); 353 while (Count--) { 354 wasm::WasmSignature Sig; 355 Sig.ReturnType = wasm::WASM_TYPE_NORESULT; 356 int8_t Form = readVarint7(Ptr); 357 if (Form != wasm::WASM_TYPE_FUNC) { 358 return make_error<GenericBinaryError>("Invalid signature type", 359 object_error::parse_failed); 360 } 361 uint32_t ParamCount = readVaruint32(Ptr); 362 Sig.ParamTypes.reserve(ParamCount); 363 while (ParamCount--) { 364 uint32_t ParamType = readVarint7(Ptr); 365 Sig.ParamTypes.push_back(ParamType); 366 } 367 uint32_t ReturnCount = readVaruint32(Ptr); 368 if (ReturnCount) { 369 if (ReturnCount != 1) { 370 return make_error<GenericBinaryError>( 371 "Multiple return types not supported", object_error::parse_failed); 372 } 373 Sig.ReturnType = readVarint7(Ptr); 374 } 375 Signatures.push_back(Sig); 376 } 377 if (Ptr != End) 378 return make_error<GenericBinaryError>("Type section ended prematurely", 379 object_error::parse_failed); 380 return Error::success(); 381 } 382 383 Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) { 384 uint32_t Count = readVaruint32(Ptr); 385 Imports.reserve(Count); 386 while (Count--) { 387 wasm::WasmImport Im; 388 Im.Module = readString(Ptr); 389 Im.Field = readString(Ptr); 390 Im.Kind = readUint8(Ptr); 391 switch (Im.Kind) { 392 case wasm::WASM_EXTERNAL_FUNCTION: 393 Im.SigIndex = readVaruint32(Ptr); 394 Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT); 395 break; 396 case wasm::WASM_EXTERNAL_GLOBAL: 397 Im.GlobalType = readVarint7(Ptr); 398 Im.GlobalMutable = readVaruint1(Ptr); 399 Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT); 400 break; 401 default: 402 // TODO(sbc): Handle other kinds of imports 403 return make_error<GenericBinaryError>( 404 "Unexpected import kind", object_error::parse_failed); 405 } 406 Imports.push_back(Im); 407 } 408 if (Ptr != End) 409 return make_error<GenericBinaryError>("Import section ended prematurely", 410 object_error::parse_failed); 411 return Error::success(); 412 } 413 414 Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) { 415 uint32_t Count = readVaruint32(Ptr); 416 FunctionTypes.reserve(Count); 417 while (Count--) { 418 FunctionTypes.push_back(readVaruint32(Ptr)); 419 } 420 if (Ptr != End) 421 return make_error<GenericBinaryError>("Function section ended prematurely", 422 object_error::parse_failed); 423 return Error::success(); 424 } 425 426 Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) { 427 uint32_t Count = readVaruint32(Ptr); 428 Tables.reserve(Count); 429 while (Count--) { 430 wasm::WasmTable Table; 431 Table.ElemType = readVarint7(Ptr); 432 if (Table.ElemType != wasm::WASM_TYPE_ANYFUNC) { 433 return make_error<GenericBinaryError>("Invalid table element type", 434 object_error::parse_failed); 435 } 436 Table.Limits = readLimits(Ptr); 437 Tables.push_back(Table); 438 } 439 if (Ptr != End) 440 return make_error<GenericBinaryError>("Table section ended prematurely", 441 object_error::parse_failed); 442 return Error::success(); 443 } 444 445 Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) { 446 uint32_t Count = readVaruint32(Ptr); 447 Memories.reserve(Count); 448 while (Count--) { 449 Memories.push_back(readLimits(Ptr)); 450 } 451 if (Ptr != End) 452 return make_error<GenericBinaryError>("Memory section ended prematurely", 453 object_error::parse_failed); 454 return Error::success(); 455 } 456 457 Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) { 458 uint32_t Count = readVaruint32(Ptr); 459 Globals.reserve(Count); 460 while (Count--) { 461 wasm::WasmGlobal Global; 462 Global.Type = readVarint7(Ptr); 463 Global.Mutable = readVaruint1(Ptr); 464 if (Error Err = readInitExpr(Global.InitExpr, Ptr)) 465 return Err; 466 Globals.push_back(Global); 467 } 468 if (Ptr != End) 469 return make_error<GenericBinaryError>("Global section ended prematurely", 470 object_error::parse_failed); 471 return Error::success(); 472 } 473 474 Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) { 475 uint32_t Count = readVaruint32(Ptr); 476 Exports.reserve(Count); 477 while (Count--) { 478 wasm::WasmExport Ex; 479 Ex.Name = readString(Ptr); 480 Ex.Kind = readUint8(Ptr); 481 Ex.Index = readVaruint32(Ptr); 482 Exports.push_back(Ex); 483 switch (Ex.Kind) { 484 case wasm::WASM_EXTERNAL_FUNCTION: 485 Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT); 486 break; 487 case wasm::WASM_EXTERNAL_GLOBAL: 488 Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT); 489 break; 490 default: 491 // TODO(sbc): Handle other kinds of exports 492 return make_error<GenericBinaryError>( 493 "Unexpected export kind", object_error::parse_failed); 494 } 495 } 496 if (Ptr != End) 497 return make_error<GenericBinaryError>("Export section ended prematurely", 498 object_error::parse_failed); 499 return Error::success(); 500 } 501 502 Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) { 503 StartFunction = readVaruint32(Ptr); 504 if (StartFunction < FunctionTypes.size()) 505 return make_error<GenericBinaryError>("Invalid start function", 506 object_error::parse_failed); 507 return Error::success(); 508 } 509 510 Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) { 511 uint32_t FunctionCount = readVaruint32(Ptr); 512 if (FunctionCount != FunctionTypes.size()) { 513 return make_error<GenericBinaryError>("Invalid function count", 514 object_error::parse_failed); 515 } 516 517 CodeSection = ArrayRef<uint8_t>(Ptr, End - Ptr); 518 519 while (FunctionCount--) { 520 wasm::WasmFunction Function; 521 uint32_t FunctionSize = readVaruint32(Ptr); 522 const uint8_t *FunctionEnd = Ptr + FunctionSize; 523 524 uint32_t NumLocalDecls = readVaruint32(Ptr); 525 Function.Locals.reserve(NumLocalDecls); 526 while (NumLocalDecls--) { 527 wasm::WasmLocalDecl Decl; 528 Decl.Count = readVaruint32(Ptr); 529 Decl.Type = readVarint7(Ptr); 530 Function.Locals.push_back(Decl); 531 } 532 533 uint32_t BodySize = FunctionEnd - Ptr; 534 Function.Body = ArrayRef<uint8_t>(Ptr, BodySize); 535 Ptr += BodySize; 536 assert(Ptr == FunctionEnd); 537 Functions.push_back(Function); 538 } 539 if (Ptr != End) 540 return make_error<GenericBinaryError>("Code section ended prematurely", 541 object_error::parse_failed); 542 return Error::success(); 543 } 544 545 Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) { 546 uint32_t Count = readVaruint32(Ptr); 547 ElemSegments.reserve(Count); 548 while (Count--) { 549 wasm::WasmElemSegment Segment; 550 Segment.TableIndex = readVaruint32(Ptr); 551 if (Segment.TableIndex != 0) { 552 return make_error<GenericBinaryError>("Invalid TableIndex", 553 object_error::parse_failed); 554 } 555 if (Error Err = readInitExpr(Segment.Offset, Ptr)) 556 return Err; 557 uint32_t NumElems = readVaruint32(Ptr); 558 while (NumElems--) { 559 Segment.Functions.push_back(readVaruint32(Ptr)); 560 } 561 ElemSegments.push_back(Segment); 562 } 563 if (Ptr != End) 564 return make_error<GenericBinaryError>("Elem section ended prematurely", 565 object_error::parse_failed); 566 return Error::success(); 567 } 568 569 Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) { 570 uint32_t Count = readVaruint32(Ptr); 571 DataSegments.reserve(Count); 572 while (Count--) { 573 wasm::WasmDataSegment Segment; 574 Segment.Index = readVaruint32(Ptr); 575 if (Error Err = readInitExpr(Segment.Offset, Ptr)) 576 return Err; 577 uint32_t Size = readVaruint32(Ptr); 578 Segment.Content = ArrayRef<uint8_t>(Ptr, Size); 579 Ptr += Size; 580 DataSegments.push_back(Segment); 581 } 582 if (Ptr != End) 583 return make_error<GenericBinaryError>("Data section ended prematurely", 584 object_error::parse_failed); 585 return Error::success(); 586 } 587 588 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const { 589 return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data()); 590 } 591 592 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 593 return Header; 594 } 595 596 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; } 597 598 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 599 const WasmSymbol &Sym = getWasmSymbol(Symb); 600 switch (Sym.Type) { 601 case WasmSymbol::SymbolType::FUNCTION_IMPORT: 602 return object::SymbolRef::SF_Undefined | SymbolRef::SF_Executable; 603 case WasmSymbol::SymbolType::FUNCTION_EXPORT: 604 return object::SymbolRef::SF_Global | SymbolRef::SF_Executable; 605 case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: 606 return object::SymbolRef::SF_Executable; 607 case WasmSymbol::SymbolType::GLOBAL_IMPORT: 608 return object::SymbolRef::SF_Undefined; 609 case WasmSymbol::SymbolType::GLOBAL_EXPORT: 610 return object::SymbolRef::SF_Global; 611 } 612 llvm_unreachable("Unknown WasmSymbol::SymbolType"); 613 } 614 615 basic_symbol_iterator WasmObjectFile::symbol_begin() const { 616 DataRefImpl Ref; 617 Ref.d.a = 0; 618 return BasicSymbolRef(Ref, this); 619 } 620 621 basic_symbol_iterator WasmObjectFile::symbol_end() const { 622 DataRefImpl Ref; 623 Ref.d.a = Symbols.size(); 624 return BasicSymbolRef(Ref, this); 625 } 626 627 const WasmSymbol &WasmObjectFile::getWasmSymbol(DataRefImpl Symb) const { 628 return Symbols[Symb.d.a]; 629 } 630 631 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 632 const WasmSymbol &Sym = getWasmSymbol(Symb); 633 return Sym.Name; 634 } 635 636 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 637 return (uint64_t)Symb.d.a; 638 } 639 640 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 641 llvm_unreachable("not yet implemented"); 642 return 0; 643 } 644 645 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 646 llvm_unreachable("not yet implemented"); 647 return 0; 648 } 649 650 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 651 llvm_unreachable("not yet implemented"); 652 return 0; 653 } 654 655 Expected<SymbolRef::Type> 656 WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 657 llvm_unreachable("not yet implemented"); 658 return errorCodeToError(object_error::invalid_symbol_index); 659 } 660 661 Expected<section_iterator> 662 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 663 llvm_unreachable("not yet implemented"); 664 return errorCodeToError(object_error::invalid_symbol_index); 665 } 666 667 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 668 669 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, 670 StringRef &Res) const { 671 const WasmSection &S = Sections[Sec.d.a]; 672 #define ECase(X) \ 673 case wasm::WASM_SEC_##X: \ 674 Res = #X; \ 675 break 676 switch (S.Type) { 677 ECase(TYPE); 678 ECase(IMPORT); 679 ECase(FUNCTION); 680 ECase(TABLE); 681 ECase(MEMORY); 682 ECase(GLOBAL); 683 ECase(EXPORT); 684 ECase(START); 685 ECase(ELEM); 686 ECase(CODE); 687 ECase(DATA); 688 case wasm::WASM_SEC_CUSTOM: 689 Res = S.Name; 690 break; 691 default: 692 return object_error::invalid_section_index; 693 } 694 #undef ECase 695 return std::error_code(); 696 } 697 698 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } 699 700 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 701 const WasmSection &S = Sections[Sec.d.a]; 702 return S.Content.size(); 703 } 704 705 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, 706 StringRef &Res) const { 707 const WasmSection &S = Sections[Sec.d.a]; 708 // This will never fail since wasm sections can never be empty (user-sections 709 // must have a name and non-user sections each have a defined structure). 710 Res = StringRef(reinterpret_cast<const char *>(S.Content.data()), 711 S.Content.size()); 712 return std::error_code(); 713 } 714 715 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 716 return 1; 717 } 718 719 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 720 return false; 721 } 722 723 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 724 return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE; 725 } 726 727 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 728 return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA; 729 } 730 731 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 732 733 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 734 735 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } 736 737 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { 738 DataRefImpl RelocRef; 739 RelocRef.d.a = Ref.d.a; 740 RelocRef.d.b = 0; 741 return relocation_iterator(RelocationRef(RelocRef, this)); 742 } 743 744 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const { 745 const WasmSection &Sec = getWasmSection(Ref); 746 DataRefImpl RelocRef; 747 RelocRef.d.a = Ref.d.a; 748 RelocRef.d.b = Sec.Relocations.size(); 749 return relocation_iterator(RelocationRef(RelocRef, this)); 750 } 751 752 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 753 Rel.d.b++; 754 } 755 756 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { 757 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 758 return Rel.Offset; 759 } 760 761 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 762 llvm_unreachable("not yet implemented"); 763 SymbolRef Ref; 764 return symbol_iterator(Ref); 765 } 766 767 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const { 768 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 769 return Rel.Type; 770 } 771 772 void WasmObjectFile::getRelocationTypeName( 773 DataRefImpl Ref, SmallVectorImpl<char> &Result) const { 774 const wasm::WasmRelocation& Rel = getWasmRelocation(Ref); 775 StringRef Res = "Unknown"; 776 777 #define WASM_RELOC(name, value) \ 778 case wasm::name: \ 779 Res = #name; \ 780 break; 781 782 switch (Rel.Type) { 783 #include "llvm/Support/WasmRelocs/WebAssembly.def" 784 } 785 786 #undef WASM_RELOC 787 788 Result.append(Res.begin(), Res.end()); 789 } 790 791 section_iterator WasmObjectFile::section_begin() const { 792 DataRefImpl Ref; 793 Ref.d.a = 0; 794 return section_iterator(SectionRef(Ref, this)); 795 } 796 797 section_iterator WasmObjectFile::section_end() const { 798 DataRefImpl Ref; 799 Ref.d.a = Sections.size(); 800 return section_iterator(SectionRef(Ref, this)); 801 } 802 803 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; } 804 805 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 806 807 unsigned WasmObjectFile::getArch() const { return Triple::wasm32; } 808 809 SubtargetFeatures WasmObjectFile::getFeatures() const { 810 return SubtargetFeatures(); 811 } 812 813 bool WasmObjectFile::isRelocatableObject() const { return false; } 814 815 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { 816 assert(Ref.d.a < Sections.size()); 817 return Sections[Ref.d.a]; 818 } 819 820 const WasmSection & 821 WasmObjectFile::getWasmSection(const SectionRef &Section) const { 822 return getWasmSection(Section.getRawDataRefImpl()); 823 } 824 825 const wasm::WasmRelocation & 826 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const { 827 return getWasmRelocation(Ref.getRawDataRefImpl()); 828 } 829 830 const wasm::WasmRelocation & 831 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { 832 assert(Ref.d.a < Sections.size()); 833 const WasmSection& Sec = Sections[Ref.d.a]; 834 assert(Ref.d.b < Sec.Relocations.size()); 835 return Sec.Relocations[Ref.d.b]; 836 } 837