12c6f75ddSDerek Schuff //===- WasmObjectFile.cpp - Wasm object file implementation -----*- C++ -*-===// 22c6f75ddSDerek Schuff // 32c6f75ddSDerek Schuff // The LLVM Compiler Infrastructure 42c6f75ddSDerek Schuff // 52c6f75ddSDerek Schuff // This file is distributed under the University of Illinois Open Source 62c6f75ddSDerek Schuff // License. See LICENSE.TXT for details. 72c6f75ddSDerek Schuff // 82c6f75ddSDerek Schuff //===----------------------------------------------------------------------===// 92c6f75ddSDerek Schuff 102c6f75ddSDerek Schuff #include "llvm/Object/Wasm.h" 112c6f75ddSDerek Schuff #include "llvm/Support/Endian.h" 122c6f75ddSDerek Schuff #include "llvm/Support/LEB128.h" 132c6f75ddSDerek Schuff 142c6f75ddSDerek Schuff namespace llvm { 152c6f75ddSDerek Schuff namespace object { 162c6f75ddSDerek Schuff 172c6f75ddSDerek Schuff Expected<std::unique_ptr<WasmObjectFile>> 182c6f75ddSDerek Schuff ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { 192c6f75ddSDerek Schuff Error Err = Error::success(); 202c6f75ddSDerek Schuff auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err); 212c6f75ddSDerek Schuff if (Err) 222c6f75ddSDerek Schuff return std::move(Err); 232c6f75ddSDerek Schuff 242c6f75ddSDerek Schuff return std::move(ObjectFile); 252c6f75ddSDerek Schuff } 262c6f75ddSDerek Schuff 272c6f75ddSDerek Schuff namespace { 282c6f75ddSDerek Schuff 292c6f75ddSDerek Schuff uint32_t readUint32(const uint8_t *&Ptr) { 302c6f75ddSDerek Schuff uint32_t Result = support::endian::read32le(Ptr); 312c6f75ddSDerek Schuff Ptr += sizeof(Result); 322c6f75ddSDerek Schuff return Result; 332c6f75ddSDerek Schuff } 342c6f75ddSDerek Schuff 352c6f75ddSDerek Schuff uint64_t readULEB128(const uint8_t *&Ptr) { 362c6f75ddSDerek Schuff unsigned Count; 372c6f75ddSDerek Schuff uint64_t Result = decodeULEB128(Ptr, &Count); 382c6f75ddSDerek Schuff Ptr += Count; 392c6f75ddSDerek Schuff return Result; 402c6f75ddSDerek Schuff } 412c6f75ddSDerek Schuff 422c6f75ddSDerek Schuff StringRef readString(const uint8_t *&Ptr) { 432c6f75ddSDerek Schuff uint32_t StringLen = readULEB128(Ptr); 442c6f75ddSDerek Schuff StringRef Return = StringRef(reinterpret_cast<const char *>(Ptr), StringLen); 452c6f75ddSDerek Schuff Ptr += StringLen; 462c6f75ddSDerek Schuff return Return; 472c6f75ddSDerek Schuff } 482c6f75ddSDerek Schuff 492c6f75ddSDerek Schuff Error readSection(wasm::WasmSection &Section, const uint8_t *&Ptr, 502c6f75ddSDerek Schuff const uint8_t *Start) { 512c6f75ddSDerek Schuff // TODO(sbc): Avoid reading past EOF in the case of malformed files. 522c6f75ddSDerek Schuff Section.Offset = Ptr - Start; 532c6f75ddSDerek Schuff Section.Type = readULEB128(Ptr); 542c6f75ddSDerek Schuff uint32_t Size = readULEB128(Ptr); 552c6f75ddSDerek Schuff if (Size == 0) 562c6f75ddSDerek Schuff return make_error<StringError>("Zero length section", 572c6f75ddSDerek Schuff object_error::parse_failed); 582c6f75ddSDerek Schuff Section.Content = ArrayRef<uint8_t>(Ptr, Size); 592c6f75ddSDerek Schuff Ptr += Size; 602c6f75ddSDerek Schuff return Error::success(); 612c6f75ddSDerek Schuff } 622c6f75ddSDerek Schuff } 632c6f75ddSDerek Schuff 642c6f75ddSDerek Schuff WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) 652c6f75ddSDerek Schuff : ObjectFile(Binary::ID_Wasm, Buffer) { 662c6f75ddSDerek Schuff ErrorAsOutParameter ErrAsOutParam(&Err); 672c6f75ddSDerek Schuff Header.Magic = getData().substr(0, 4); 682c6f75ddSDerek Schuff if (Header.Magic != StringRef("\0asm", 4)) { 692c6f75ddSDerek Schuff Err = make_error<StringError>("Bad magic number", 702c6f75ddSDerek Schuff object_error::parse_failed); 712c6f75ddSDerek Schuff return; 722c6f75ddSDerek Schuff } 732c6f75ddSDerek Schuff const uint8_t *Ptr = getPtr(4); 742c6f75ddSDerek Schuff Header.Version = readUint32(Ptr); 752c6f75ddSDerek Schuff if (Header.Version != wasm::WasmVersion) { 762c6f75ddSDerek Schuff Err = make_error<StringError>("Bad version number", 772c6f75ddSDerek Schuff object_error::parse_failed); 782c6f75ddSDerek Schuff return; 792c6f75ddSDerek Schuff } 802c6f75ddSDerek Schuff 812c6f75ddSDerek Schuff const uint8_t *Eof = getPtr(getData().size()); 822c6f75ddSDerek Schuff wasm::WasmSection Sec; 832c6f75ddSDerek Schuff while (Ptr < Eof) { 842c6f75ddSDerek Schuff if ((Err = readSection(Sec, Ptr, getPtr(0)))) 852c6f75ddSDerek Schuff return; 86*6d76b7b4SDerek Schuff if (Sec.Type == wasm::WASM_SEC_CUSTOM) { 87*6d76b7b4SDerek Schuff if ((Err = 88*6d76b7b4SDerek Schuff parseCustomSection(Sec, Sec.Content.data(), Sec.Content.size()))) 892c6f75ddSDerek Schuff return; 902c6f75ddSDerek Schuff } 912c6f75ddSDerek Schuff Sections.push_back(Sec); 922c6f75ddSDerek Schuff } 932c6f75ddSDerek Schuff } 942c6f75ddSDerek Schuff 95*6d76b7b4SDerek Schuff Error WasmObjectFile::parseCustomSection(wasm::WasmSection &Sec, 962c6f75ddSDerek Schuff const uint8_t *Ptr, size_t Length) { 972c6f75ddSDerek Schuff Sec.Name = readString(Ptr); 982c6f75ddSDerek Schuff return Error::success(); 992c6f75ddSDerek Schuff } 1002c6f75ddSDerek Schuff 1012c6f75ddSDerek Schuff const uint8_t *WasmObjectFile::getPtr(size_t Offset) const { 1022c6f75ddSDerek Schuff return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data()); 1032c6f75ddSDerek Schuff } 1042c6f75ddSDerek Schuff 1052c6f75ddSDerek Schuff const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 1062c6f75ddSDerek Schuff return Header; 1072c6f75ddSDerek Schuff } 1082c6f75ddSDerek Schuff 1092c6f75ddSDerek Schuff void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 1102c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 1112c6f75ddSDerek Schuff } 1122c6f75ddSDerek Schuff 1132c6f75ddSDerek Schuff std::error_code WasmObjectFile::printSymbolName(raw_ostream &OS, 1142c6f75ddSDerek Schuff DataRefImpl Symb) const { 1152c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 1162c6f75ddSDerek Schuff return object_error::invalid_symbol_index; 1172c6f75ddSDerek Schuff } 1182c6f75ddSDerek Schuff 1192c6f75ddSDerek Schuff uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 1202c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 1212c6f75ddSDerek Schuff return 0; 1222c6f75ddSDerek Schuff } 1232c6f75ddSDerek Schuff 1242c6f75ddSDerek Schuff basic_symbol_iterator WasmObjectFile::symbol_begin() const { 1252c6f75ddSDerek Schuff return BasicSymbolRef(DataRefImpl(), this); 1262c6f75ddSDerek Schuff } 1272c6f75ddSDerek Schuff 1282c6f75ddSDerek Schuff basic_symbol_iterator WasmObjectFile::symbol_end() const { 1292c6f75ddSDerek Schuff return BasicSymbolRef(DataRefImpl(), this); 1302c6f75ddSDerek Schuff } 1312c6f75ddSDerek Schuff 1322c6f75ddSDerek Schuff Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 1332c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 1342c6f75ddSDerek Schuff return errorCodeToError(object_error::invalid_symbol_index); 1352c6f75ddSDerek Schuff } 1362c6f75ddSDerek Schuff 1372c6f75ddSDerek Schuff Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 1382c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 1392c6f75ddSDerek Schuff return errorCodeToError(object_error::invalid_symbol_index); 1402c6f75ddSDerek Schuff } 1412c6f75ddSDerek Schuff 1422c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 1432c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 1442c6f75ddSDerek Schuff return 0; 1452c6f75ddSDerek Schuff } 1462c6f75ddSDerek Schuff 1472c6f75ddSDerek Schuff uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 1482c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 1492c6f75ddSDerek Schuff return 0; 1502c6f75ddSDerek Schuff } 1512c6f75ddSDerek Schuff 1522c6f75ddSDerek Schuff uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 1532c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 1542c6f75ddSDerek Schuff return 0; 1552c6f75ddSDerek Schuff } 1562c6f75ddSDerek Schuff 1572c6f75ddSDerek Schuff Expected<SymbolRef::Type> 1582c6f75ddSDerek Schuff WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 1592c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 1602c6f75ddSDerek Schuff return errorCodeToError(object_error::invalid_symbol_index); 1612c6f75ddSDerek Schuff } 1622c6f75ddSDerek Schuff 1632c6f75ddSDerek Schuff Expected<section_iterator> 1642c6f75ddSDerek Schuff WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 1652c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 1662c6f75ddSDerek Schuff return errorCodeToError(object_error::invalid_symbol_index); 1672c6f75ddSDerek Schuff } 1682c6f75ddSDerek Schuff 1692c6f75ddSDerek Schuff void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 1702c6f75ddSDerek Schuff 1712c6f75ddSDerek Schuff std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, 1722c6f75ddSDerek Schuff StringRef &Res) const { 1732c6f75ddSDerek Schuff const wasm::WasmSection &S = Sections[Sec.d.a]; 1742c6f75ddSDerek Schuff #define ECase(X) \ 1752c6f75ddSDerek Schuff case wasm::WASM_SEC_##X: \ 1762c6f75ddSDerek Schuff Res = #X; \ 1772c6f75ddSDerek Schuff break 1782c6f75ddSDerek Schuff switch (S.Type) { 1792c6f75ddSDerek Schuff ECase(TYPE); 1802c6f75ddSDerek Schuff ECase(IMPORT); 1812c6f75ddSDerek Schuff ECase(FUNCTION); 1822c6f75ddSDerek Schuff ECase(TABLE); 1832c6f75ddSDerek Schuff ECase(MEMORY); 1842c6f75ddSDerek Schuff ECase(GLOBAL); 1852c6f75ddSDerek Schuff ECase(EXPORT); 1862c6f75ddSDerek Schuff ECase(START); 1872c6f75ddSDerek Schuff ECase(ELEM); 1882c6f75ddSDerek Schuff ECase(CODE); 1892c6f75ddSDerek Schuff ECase(DATA); 190*6d76b7b4SDerek Schuff case wasm::WASM_SEC_CUSTOM: 1912c6f75ddSDerek Schuff Res = S.Name; 1922c6f75ddSDerek Schuff break; 1932c6f75ddSDerek Schuff default: 1942c6f75ddSDerek Schuff return object_error::invalid_section_index; 1952c6f75ddSDerek Schuff } 1962c6f75ddSDerek Schuff #undef ECase 1972c6f75ddSDerek Schuff return std::error_code(); 1982c6f75ddSDerek Schuff } 1992c6f75ddSDerek Schuff 2002c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } 2012c6f75ddSDerek Schuff 2022c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 2032c6f75ddSDerek Schuff const wasm::WasmSection &S = Sections[Sec.d.a]; 2042c6f75ddSDerek Schuff return S.Content.size(); 2052c6f75ddSDerek Schuff } 2062c6f75ddSDerek Schuff 2072c6f75ddSDerek Schuff std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, 2082c6f75ddSDerek Schuff StringRef &Res) const { 2092c6f75ddSDerek Schuff const wasm::WasmSection &S = Sections[Sec.d.a]; 2102c6f75ddSDerek Schuff // This will never fail since wasm sections can never be empty (user-sections 2112c6f75ddSDerek Schuff // must have a name and non-user sections each have a defined structure). 2122c6f75ddSDerek Schuff Res = StringRef(reinterpret_cast<const char *>(S.Content.data()), 2132c6f75ddSDerek Schuff S.Content.size()); 2142c6f75ddSDerek Schuff return std::error_code(); 2152c6f75ddSDerek Schuff } 2162c6f75ddSDerek Schuff 2172c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 2182c6f75ddSDerek Schuff return 1; 2192c6f75ddSDerek Schuff } 2202c6f75ddSDerek Schuff 2212c6f75ddSDerek Schuff bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 2222c6f75ddSDerek Schuff return false; 2232c6f75ddSDerek Schuff } 2242c6f75ddSDerek Schuff 2252c6f75ddSDerek Schuff bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 2262c6f75ddSDerek Schuff const wasm::WasmSection &S = Sections[Sec.d.a]; 2272c6f75ddSDerek Schuff return S.Type == wasm::WASM_SEC_CODE; 2282c6f75ddSDerek Schuff } 2292c6f75ddSDerek Schuff 2302c6f75ddSDerek Schuff bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 2312c6f75ddSDerek Schuff const wasm::WasmSection &S = Sections[Sec.d.a]; 2322c6f75ddSDerek Schuff return S.Type == wasm::WASM_SEC_DATA; 2332c6f75ddSDerek Schuff } 2342c6f75ddSDerek Schuff 2352c6f75ddSDerek Schuff bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 2362c6f75ddSDerek Schuff 2372c6f75ddSDerek Schuff bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 2382c6f75ddSDerek Schuff 2392c6f75ddSDerek Schuff bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } 2402c6f75ddSDerek Schuff 2412c6f75ddSDerek Schuff relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Sec) const { 2422c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 2432c6f75ddSDerek Schuff RelocationRef Rel; 2442c6f75ddSDerek Schuff return relocation_iterator(Rel); 2452c6f75ddSDerek Schuff } 2462c6f75ddSDerek Schuff 2472c6f75ddSDerek Schuff relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Sec) const { 2482c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 2492c6f75ddSDerek Schuff RelocationRef Rel; 2502c6f75ddSDerek Schuff return relocation_iterator(Rel); 2512c6f75ddSDerek Schuff } 2522c6f75ddSDerek Schuff 2532c6f75ddSDerek Schuff section_iterator WasmObjectFile::getRelocatedSection(DataRefImpl Sec) const { 2542c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 2552c6f75ddSDerek Schuff SectionRef Ref; 2562c6f75ddSDerek Schuff return section_iterator(Ref); 2572c6f75ddSDerek Schuff } 2582c6f75ddSDerek Schuff 2592c6f75ddSDerek Schuff void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 2602c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 2612c6f75ddSDerek Schuff } 2622c6f75ddSDerek Schuff 2632c6f75ddSDerek Schuff uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Rel) const { 2642c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 2652c6f75ddSDerek Schuff return 0; 2662c6f75ddSDerek Schuff } 2672c6f75ddSDerek Schuff 2682c6f75ddSDerek Schuff symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 2692c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 2702c6f75ddSDerek Schuff SymbolRef Ref; 2712c6f75ddSDerek Schuff return symbol_iterator(Ref); 2722c6f75ddSDerek Schuff } 2732c6f75ddSDerek Schuff 2742c6f75ddSDerek Schuff uint64_t WasmObjectFile::getRelocationType(DataRefImpl Rel) const { 2752c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 2762c6f75ddSDerek Schuff return 0; 2772c6f75ddSDerek Schuff } 2782c6f75ddSDerek Schuff 2792c6f75ddSDerek Schuff void WasmObjectFile::getRelocationTypeName( 2802c6f75ddSDerek Schuff DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 2812c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 2822c6f75ddSDerek Schuff } 2832c6f75ddSDerek Schuff 2842c6f75ddSDerek Schuff section_iterator WasmObjectFile::section_begin() const { 2852c6f75ddSDerek Schuff DataRefImpl Ref; 2862c6f75ddSDerek Schuff Ref.d.a = 0; 2872c6f75ddSDerek Schuff return section_iterator(SectionRef(Ref, this)); 2882c6f75ddSDerek Schuff } 2892c6f75ddSDerek Schuff 2902c6f75ddSDerek Schuff section_iterator WasmObjectFile::section_end() const { 2912c6f75ddSDerek Schuff DataRefImpl Ref; 2922c6f75ddSDerek Schuff Ref.d.a = Sections.size(); 2932c6f75ddSDerek Schuff return section_iterator(SectionRef(Ref, this)); 2942c6f75ddSDerek Schuff } 2952c6f75ddSDerek Schuff 2962c6f75ddSDerek Schuff uint8_t WasmObjectFile::getBytesInAddress() const { return 4; } 2972c6f75ddSDerek Schuff 2982c6f75ddSDerek Schuff StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 2992c6f75ddSDerek Schuff 3002c6f75ddSDerek Schuff unsigned WasmObjectFile::getArch() const { return Triple::wasm32; } 3012c6f75ddSDerek Schuff 3022c6f75ddSDerek Schuff SubtargetFeatures WasmObjectFile::getFeatures() const { 3032c6f75ddSDerek Schuff return SubtargetFeatures(); 3042c6f75ddSDerek Schuff } 3052c6f75ddSDerek Schuff 3062c6f75ddSDerek Schuff bool WasmObjectFile::isRelocatableObject() const { return false; } 3072c6f75ddSDerek Schuff 3082c6f75ddSDerek Schuff const wasm::WasmSection * 3092c6f75ddSDerek Schuff WasmObjectFile::getWasmSection(const SectionRef &Section) const { 3102c6f75ddSDerek Schuff return &Sections[Section.getRawDataRefImpl().d.a]; 3112c6f75ddSDerek Schuff } 3122c6f75ddSDerek Schuff 3132c6f75ddSDerek Schuff } // end namespace object 3142c6f75ddSDerek Schuff } // end namespace llvm 315