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