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