1*2c6f75ddSDerek Schuff //===- WasmObjectFile.cpp - Wasm object file implementation -----*- C++ -*-===// 2*2c6f75ddSDerek Schuff // 3*2c6f75ddSDerek Schuff // The LLVM Compiler Infrastructure 4*2c6f75ddSDerek Schuff // 5*2c6f75ddSDerek Schuff // This file is distributed under the University of Illinois Open Source 6*2c6f75ddSDerek Schuff // License. See LICENSE.TXT for details. 7*2c6f75ddSDerek Schuff // 8*2c6f75ddSDerek Schuff //===----------------------------------------------------------------------===// 9*2c6f75ddSDerek Schuff 10*2c6f75ddSDerek Schuff #include "llvm/Object/Wasm.h" 11*2c6f75ddSDerek Schuff #include "llvm/Support/Endian.h" 12*2c6f75ddSDerek Schuff #include "llvm/Support/LEB128.h" 13*2c6f75ddSDerek Schuff 14*2c6f75ddSDerek Schuff #include <iostream> 15*2c6f75ddSDerek Schuff 16*2c6f75ddSDerek Schuff namespace llvm { 17*2c6f75ddSDerek Schuff namespace object { 18*2c6f75ddSDerek Schuff 19*2c6f75ddSDerek Schuff Expected<std::unique_ptr<WasmObjectFile>> 20*2c6f75ddSDerek Schuff ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { 21*2c6f75ddSDerek Schuff Error Err = Error::success(); 22*2c6f75ddSDerek Schuff auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err); 23*2c6f75ddSDerek Schuff if (Err) 24*2c6f75ddSDerek Schuff return std::move(Err); 25*2c6f75ddSDerek Schuff 26*2c6f75ddSDerek Schuff return std::move(ObjectFile); 27*2c6f75ddSDerek Schuff } 28*2c6f75ddSDerek Schuff 29*2c6f75ddSDerek Schuff namespace { 30*2c6f75ddSDerek Schuff 31*2c6f75ddSDerek Schuff uint32_t readUint32(const uint8_t *&Ptr) { 32*2c6f75ddSDerek Schuff uint32_t Result = support::endian::read32le(Ptr); 33*2c6f75ddSDerek Schuff Ptr += sizeof(Result); 34*2c6f75ddSDerek Schuff return Result; 35*2c6f75ddSDerek Schuff } 36*2c6f75ddSDerek Schuff 37*2c6f75ddSDerek Schuff uint64_t readULEB128(const uint8_t *&Ptr) { 38*2c6f75ddSDerek Schuff unsigned Count; 39*2c6f75ddSDerek Schuff uint64_t Result = decodeULEB128(Ptr, &Count); 40*2c6f75ddSDerek Schuff Ptr += Count; 41*2c6f75ddSDerek Schuff return Result; 42*2c6f75ddSDerek Schuff } 43*2c6f75ddSDerek Schuff 44*2c6f75ddSDerek Schuff StringRef readString(const uint8_t *&Ptr) { 45*2c6f75ddSDerek Schuff uint32_t StringLen = readULEB128(Ptr); 46*2c6f75ddSDerek Schuff StringRef Return = StringRef(reinterpret_cast<const char *>(Ptr), StringLen); 47*2c6f75ddSDerek Schuff Ptr += StringLen; 48*2c6f75ddSDerek Schuff return Return; 49*2c6f75ddSDerek Schuff } 50*2c6f75ddSDerek Schuff 51*2c6f75ddSDerek Schuff Error readSection(wasm::WasmSection &Section, const uint8_t *&Ptr, 52*2c6f75ddSDerek Schuff const uint8_t *Start) { 53*2c6f75ddSDerek Schuff // TODO(sbc): Avoid reading past EOF in the case of malformed files. 54*2c6f75ddSDerek Schuff Section.Offset = Ptr - Start; 55*2c6f75ddSDerek Schuff Section.Type = readULEB128(Ptr); 56*2c6f75ddSDerek Schuff uint32_t Size = readULEB128(Ptr); 57*2c6f75ddSDerek Schuff if (Size == 0) 58*2c6f75ddSDerek Schuff return make_error<StringError>("Zero length section", 59*2c6f75ddSDerek Schuff object_error::parse_failed); 60*2c6f75ddSDerek Schuff Section.Content = ArrayRef<uint8_t>(Ptr, Size); 61*2c6f75ddSDerek Schuff Ptr += Size; 62*2c6f75ddSDerek Schuff return Error::success(); 63*2c6f75ddSDerek Schuff } 64*2c6f75ddSDerek Schuff } 65*2c6f75ddSDerek Schuff 66*2c6f75ddSDerek Schuff WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) 67*2c6f75ddSDerek Schuff : ObjectFile(Binary::ID_Wasm, Buffer) { 68*2c6f75ddSDerek Schuff ErrorAsOutParameter ErrAsOutParam(&Err); 69*2c6f75ddSDerek Schuff Header.Magic = getData().substr(0, 4); 70*2c6f75ddSDerek Schuff if (Header.Magic != StringRef("\0asm", 4)) { 71*2c6f75ddSDerek Schuff Err = make_error<StringError>("Bad magic number", 72*2c6f75ddSDerek Schuff object_error::parse_failed); 73*2c6f75ddSDerek Schuff return; 74*2c6f75ddSDerek Schuff } 75*2c6f75ddSDerek Schuff const uint8_t *Ptr = getPtr(4); 76*2c6f75ddSDerek Schuff Header.Version = readUint32(Ptr); 77*2c6f75ddSDerek Schuff if (Header.Version != wasm::WasmVersion) { 78*2c6f75ddSDerek Schuff Err = make_error<StringError>("Bad version number", 79*2c6f75ddSDerek Schuff object_error::parse_failed); 80*2c6f75ddSDerek Schuff return; 81*2c6f75ddSDerek Schuff } 82*2c6f75ddSDerek Schuff 83*2c6f75ddSDerek Schuff const uint8_t *Eof = getPtr(getData().size()); 84*2c6f75ddSDerek Schuff wasm::WasmSection Sec; 85*2c6f75ddSDerek Schuff while (Ptr < Eof) { 86*2c6f75ddSDerek Schuff if ((Err = readSection(Sec, Ptr, getPtr(0)))) 87*2c6f75ddSDerek Schuff return; 88*2c6f75ddSDerek Schuff if (Sec.Type == wasm::WASM_SEC_USER) { 89*2c6f75ddSDerek Schuff if ((Err = parseUserSection(Sec, Sec.Content.data(), Sec.Content.size()))) 90*2c6f75ddSDerek Schuff return; 91*2c6f75ddSDerek Schuff } 92*2c6f75ddSDerek Schuff Sections.push_back(Sec); 93*2c6f75ddSDerek Schuff } 94*2c6f75ddSDerek Schuff } 95*2c6f75ddSDerek Schuff 96*2c6f75ddSDerek Schuff Error WasmObjectFile::parseUserSection(wasm::WasmSection &Sec, 97*2c6f75ddSDerek Schuff const uint8_t *Ptr, size_t Length) { 98*2c6f75ddSDerek Schuff Sec.Name = readString(Ptr); 99*2c6f75ddSDerek Schuff return Error::success(); 100*2c6f75ddSDerek Schuff } 101*2c6f75ddSDerek Schuff 102*2c6f75ddSDerek Schuff const uint8_t *WasmObjectFile::getPtr(size_t Offset) const { 103*2c6f75ddSDerek Schuff return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data()); 104*2c6f75ddSDerek Schuff } 105*2c6f75ddSDerek Schuff 106*2c6f75ddSDerek Schuff const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 107*2c6f75ddSDerek Schuff return Header; 108*2c6f75ddSDerek Schuff } 109*2c6f75ddSDerek Schuff 110*2c6f75ddSDerek Schuff void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 111*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 112*2c6f75ddSDerek Schuff } 113*2c6f75ddSDerek Schuff 114*2c6f75ddSDerek Schuff std::error_code WasmObjectFile::printSymbolName(raw_ostream &OS, 115*2c6f75ddSDerek Schuff DataRefImpl Symb) const { 116*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 117*2c6f75ddSDerek Schuff return object_error::invalid_symbol_index; 118*2c6f75ddSDerek Schuff } 119*2c6f75ddSDerek Schuff 120*2c6f75ddSDerek Schuff uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 121*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 122*2c6f75ddSDerek Schuff return 0; 123*2c6f75ddSDerek Schuff } 124*2c6f75ddSDerek Schuff 125*2c6f75ddSDerek Schuff basic_symbol_iterator WasmObjectFile::symbol_begin() const { 126*2c6f75ddSDerek Schuff return BasicSymbolRef(DataRefImpl(), this); 127*2c6f75ddSDerek Schuff } 128*2c6f75ddSDerek Schuff 129*2c6f75ddSDerek Schuff basic_symbol_iterator WasmObjectFile::symbol_end() const { 130*2c6f75ddSDerek Schuff return BasicSymbolRef(DataRefImpl(), this); 131*2c6f75ddSDerek Schuff } 132*2c6f75ddSDerek Schuff 133*2c6f75ddSDerek Schuff Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 134*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 135*2c6f75ddSDerek Schuff return errorCodeToError(object_error::invalid_symbol_index); 136*2c6f75ddSDerek Schuff } 137*2c6f75ddSDerek Schuff 138*2c6f75ddSDerek Schuff Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 139*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 140*2c6f75ddSDerek Schuff return errorCodeToError(object_error::invalid_symbol_index); 141*2c6f75ddSDerek Schuff } 142*2c6f75ddSDerek Schuff 143*2c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 144*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 145*2c6f75ddSDerek Schuff return 0; 146*2c6f75ddSDerek Schuff } 147*2c6f75ddSDerek Schuff 148*2c6f75ddSDerek Schuff uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 149*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 150*2c6f75ddSDerek Schuff return 0; 151*2c6f75ddSDerek Schuff } 152*2c6f75ddSDerek Schuff 153*2c6f75ddSDerek Schuff uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 154*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 155*2c6f75ddSDerek Schuff return 0; 156*2c6f75ddSDerek Schuff } 157*2c6f75ddSDerek Schuff 158*2c6f75ddSDerek Schuff Expected<SymbolRef::Type> 159*2c6f75ddSDerek Schuff WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 160*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 161*2c6f75ddSDerek Schuff return errorCodeToError(object_error::invalid_symbol_index); 162*2c6f75ddSDerek Schuff } 163*2c6f75ddSDerek Schuff 164*2c6f75ddSDerek Schuff Expected<section_iterator> 165*2c6f75ddSDerek Schuff WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 166*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 167*2c6f75ddSDerek Schuff return errorCodeToError(object_error::invalid_symbol_index); 168*2c6f75ddSDerek Schuff } 169*2c6f75ddSDerek Schuff 170*2c6f75ddSDerek Schuff void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 171*2c6f75ddSDerek Schuff 172*2c6f75ddSDerek Schuff std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, 173*2c6f75ddSDerek Schuff StringRef &Res) const { 174*2c6f75ddSDerek Schuff const wasm::WasmSection &S = Sections[Sec.d.a]; 175*2c6f75ddSDerek Schuff #define ECase(X) \ 176*2c6f75ddSDerek Schuff case wasm::WASM_SEC_##X: \ 177*2c6f75ddSDerek Schuff Res = #X; \ 178*2c6f75ddSDerek Schuff break 179*2c6f75ddSDerek Schuff switch (S.Type) { 180*2c6f75ddSDerek Schuff ECase(TYPE); 181*2c6f75ddSDerek Schuff ECase(IMPORT); 182*2c6f75ddSDerek Schuff ECase(FUNCTION); 183*2c6f75ddSDerek Schuff ECase(TABLE); 184*2c6f75ddSDerek Schuff ECase(MEMORY); 185*2c6f75ddSDerek Schuff ECase(GLOBAL); 186*2c6f75ddSDerek Schuff ECase(EXPORT); 187*2c6f75ddSDerek Schuff ECase(START); 188*2c6f75ddSDerek Schuff ECase(ELEM); 189*2c6f75ddSDerek Schuff ECase(CODE); 190*2c6f75ddSDerek Schuff ECase(DATA); 191*2c6f75ddSDerek Schuff case wasm::WASM_SEC_USER: 192*2c6f75ddSDerek Schuff Res = S.Name; 193*2c6f75ddSDerek Schuff break; 194*2c6f75ddSDerek Schuff default: 195*2c6f75ddSDerek Schuff return object_error::invalid_section_index; 196*2c6f75ddSDerek Schuff } 197*2c6f75ddSDerek Schuff #undef ECase 198*2c6f75ddSDerek Schuff return std::error_code(); 199*2c6f75ddSDerek Schuff } 200*2c6f75ddSDerek Schuff 201*2c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } 202*2c6f75ddSDerek Schuff 203*2c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 204*2c6f75ddSDerek Schuff const wasm::WasmSection &S = Sections[Sec.d.a]; 205*2c6f75ddSDerek Schuff return S.Content.size(); 206*2c6f75ddSDerek Schuff } 207*2c6f75ddSDerek Schuff 208*2c6f75ddSDerek Schuff std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, 209*2c6f75ddSDerek Schuff StringRef &Res) const { 210*2c6f75ddSDerek Schuff const wasm::WasmSection &S = Sections[Sec.d.a]; 211*2c6f75ddSDerek Schuff // This will never fail since wasm sections can never be empty (user-sections 212*2c6f75ddSDerek Schuff // must have a name and non-user sections each have a defined structure). 213*2c6f75ddSDerek Schuff Res = StringRef(reinterpret_cast<const char *>(S.Content.data()), 214*2c6f75ddSDerek Schuff S.Content.size()); 215*2c6f75ddSDerek Schuff return std::error_code(); 216*2c6f75ddSDerek Schuff } 217*2c6f75ddSDerek Schuff 218*2c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 219*2c6f75ddSDerek Schuff return 1; 220*2c6f75ddSDerek Schuff } 221*2c6f75ddSDerek Schuff 222*2c6f75ddSDerek Schuff bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 223*2c6f75ddSDerek Schuff return false; 224*2c6f75ddSDerek Schuff } 225*2c6f75ddSDerek Schuff 226*2c6f75ddSDerek Schuff bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 227*2c6f75ddSDerek Schuff const wasm::WasmSection &S = Sections[Sec.d.a]; 228*2c6f75ddSDerek Schuff return S.Type == wasm::WASM_SEC_CODE; 229*2c6f75ddSDerek Schuff } 230*2c6f75ddSDerek Schuff 231*2c6f75ddSDerek Schuff bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 232*2c6f75ddSDerek Schuff const wasm::WasmSection &S = Sections[Sec.d.a]; 233*2c6f75ddSDerek Schuff return S.Type == wasm::WASM_SEC_DATA; 234*2c6f75ddSDerek Schuff } 235*2c6f75ddSDerek Schuff 236*2c6f75ddSDerek Schuff bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 237*2c6f75ddSDerek Schuff 238*2c6f75ddSDerek Schuff bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 239*2c6f75ddSDerek Schuff 240*2c6f75ddSDerek Schuff bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } 241*2c6f75ddSDerek Schuff 242*2c6f75ddSDerek Schuff relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Sec) const { 243*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 244*2c6f75ddSDerek Schuff RelocationRef Rel; 245*2c6f75ddSDerek Schuff return relocation_iterator(Rel); 246*2c6f75ddSDerek Schuff } 247*2c6f75ddSDerek Schuff 248*2c6f75ddSDerek Schuff relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Sec) const { 249*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 250*2c6f75ddSDerek Schuff RelocationRef Rel; 251*2c6f75ddSDerek Schuff return relocation_iterator(Rel); 252*2c6f75ddSDerek Schuff } 253*2c6f75ddSDerek Schuff 254*2c6f75ddSDerek Schuff section_iterator WasmObjectFile::getRelocatedSection(DataRefImpl Sec) const { 255*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 256*2c6f75ddSDerek Schuff SectionRef Ref; 257*2c6f75ddSDerek Schuff return section_iterator(Ref); 258*2c6f75ddSDerek Schuff } 259*2c6f75ddSDerek Schuff 260*2c6f75ddSDerek Schuff void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 261*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 262*2c6f75ddSDerek Schuff } 263*2c6f75ddSDerek Schuff 264*2c6f75ddSDerek Schuff uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Rel) const { 265*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 266*2c6f75ddSDerek Schuff return 0; 267*2c6f75ddSDerek Schuff } 268*2c6f75ddSDerek Schuff 269*2c6f75ddSDerek Schuff symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 270*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 271*2c6f75ddSDerek Schuff SymbolRef Ref; 272*2c6f75ddSDerek Schuff return symbol_iterator(Ref); 273*2c6f75ddSDerek Schuff } 274*2c6f75ddSDerek Schuff 275*2c6f75ddSDerek Schuff uint64_t WasmObjectFile::getRelocationType(DataRefImpl Rel) const { 276*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 277*2c6f75ddSDerek Schuff return 0; 278*2c6f75ddSDerek Schuff } 279*2c6f75ddSDerek Schuff 280*2c6f75ddSDerek Schuff void WasmObjectFile::getRelocationTypeName( 281*2c6f75ddSDerek Schuff DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 282*2c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 283*2c6f75ddSDerek Schuff } 284*2c6f75ddSDerek Schuff 285*2c6f75ddSDerek Schuff section_iterator WasmObjectFile::section_begin() const { 286*2c6f75ddSDerek Schuff DataRefImpl Ref; 287*2c6f75ddSDerek Schuff Ref.d.a = 0; 288*2c6f75ddSDerek Schuff return section_iterator(SectionRef(Ref, this)); 289*2c6f75ddSDerek Schuff } 290*2c6f75ddSDerek Schuff 291*2c6f75ddSDerek Schuff section_iterator WasmObjectFile::section_end() const { 292*2c6f75ddSDerek Schuff DataRefImpl Ref; 293*2c6f75ddSDerek Schuff Ref.d.a = Sections.size(); 294*2c6f75ddSDerek Schuff return section_iterator(SectionRef(Ref, this)); 295*2c6f75ddSDerek Schuff } 296*2c6f75ddSDerek Schuff 297*2c6f75ddSDerek Schuff uint8_t WasmObjectFile::getBytesInAddress() const { return 4; } 298*2c6f75ddSDerek Schuff 299*2c6f75ddSDerek Schuff StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 300*2c6f75ddSDerek Schuff 301*2c6f75ddSDerek Schuff unsigned WasmObjectFile::getArch() const { return Triple::wasm32; } 302*2c6f75ddSDerek Schuff 303*2c6f75ddSDerek Schuff SubtargetFeatures WasmObjectFile::getFeatures() const { 304*2c6f75ddSDerek Schuff return SubtargetFeatures(); 305*2c6f75ddSDerek Schuff } 306*2c6f75ddSDerek Schuff 307*2c6f75ddSDerek Schuff bool WasmObjectFile::isRelocatableObject() const { return false; } 308*2c6f75ddSDerek Schuff 309*2c6f75ddSDerek Schuff const wasm::WasmSection * 310*2c6f75ddSDerek Schuff WasmObjectFile::getWasmSection(const SectionRef &Section) const { 311*2c6f75ddSDerek Schuff return &Sections[Section.getRawDataRefImpl().d.a]; 312*2c6f75ddSDerek Schuff } 313*2c6f75ddSDerek Schuff 314*2c6f75ddSDerek Schuff } // end namespace object 315*2c6f75ddSDerek Schuff } // end namespace llvm 316