diff options
Diffstat (limited to 'contrib/llvm/lib/Object/WasmObjectFile.cpp')
-rw-r--r-- | contrib/llvm/lib/Object/WasmObjectFile.cpp | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Object/WasmObjectFile.cpp b/contrib/llvm/lib/Object/WasmObjectFile.cpp new file mode 100644 index 0000000..2b61a8a0 --- /dev/null +++ b/contrib/llvm/lib/Object/WasmObjectFile.cpp @@ -0,0 +1,313 @@ +//===- WasmObjectFile.cpp - Wasm object file implementation -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/Wasm.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/LEB128.h" + +namespace llvm { +namespace object { + +Expected<std::unique_ptr<WasmObjectFile>> +ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { + Error Err = Error::success(); + auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err); + if (Err) + return std::move(Err); + + return std::move(ObjectFile); +} + +namespace { + +uint32_t readUint32(const uint8_t *&Ptr) { + uint32_t Result = support::endian::read32le(Ptr); + Ptr += sizeof(Result); + return Result; +} + +uint64_t readULEB128(const uint8_t *&Ptr) { + unsigned Count; + uint64_t Result = decodeULEB128(Ptr, &Count); + Ptr += Count; + return Result; +} + +StringRef readString(const uint8_t *&Ptr) { + uint32_t StringLen = readULEB128(Ptr); + StringRef Return = StringRef(reinterpret_cast<const char *>(Ptr), StringLen); + Ptr += StringLen; + return Return; +} + +Error readSection(wasm::WasmSection &Section, const uint8_t *&Ptr, + const uint8_t *Start) { + // TODO(sbc): Avoid reading past EOF in the case of malformed files. + Section.Offset = Ptr - Start; + Section.Type = readULEB128(Ptr); + uint32_t Size = readULEB128(Ptr); + if (Size == 0) + return make_error<StringError>("Zero length section", + object_error::parse_failed); + Section.Content = ArrayRef<uint8_t>(Ptr, Size); + Ptr += Size; + return Error::success(); +} +} + +WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) + : ObjectFile(Binary::ID_Wasm, Buffer) { + ErrorAsOutParameter ErrAsOutParam(&Err); + Header.Magic = getData().substr(0, 4); + if (Header.Magic != StringRef("\0asm", 4)) { + Err = make_error<StringError>("Bad magic number", + object_error::parse_failed); + return; + } + const uint8_t *Ptr = getPtr(4); + Header.Version = readUint32(Ptr); + if (Header.Version != wasm::WasmVersion) { + Err = make_error<StringError>("Bad version number", + object_error::parse_failed); + return; + } + + const uint8_t *Eof = getPtr(getData().size()); + wasm::WasmSection Sec; + while (Ptr < Eof) { + if ((Err = readSection(Sec, Ptr, getPtr(0)))) + return; + if (Sec.Type == wasm::WASM_SEC_USER) { + if ((Err = parseUserSection(Sec, Sec.Content.data(), Sec.Content.size()))) + return; + } + Sections.push_back(Sec); + } +} + +Error WasmObjectFile::parseUserSection(wasm::WasmSection &Sec, + const uint8_t *Ptr, size_t Length) { + Sec.Name = readString(Ptr); + return Error::success(); +} + +const uint8_t *WasmObjectFile::getPtr(size_t Offset) const { + return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data()); +} + +const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { + return Header; +} + +void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { + llvm_unreachable("not yet implemented"); +} + +std::error_code WasmObjectFile::printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const { + llvm_unreachable("not yet implemented"); + return object_error::invalid_symbol_index; +} + +uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { + llvm_unreachable("not yet implemented"); + return 0; +} + +basic_symbol_iterator WasmObjectFile::symbol_begin() const { + return BasicSymbolRef(DataRefImpl(), this); +} + +basic_symbol_iterator WasmObjectFile::symbol_end() const { + return BasicSymbolRef(DataRefImpl(), this); +} + +Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { + llvm_unreachable("not yet implemented"); + return errorCodeToError(object_error::invalid_symbol_index); +} + +Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { + llvm_unreachable("not yet implemented"); + return errorCodeToError(object_error::invalid_symbol_index); +} + +uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { + llvm_unreachable("not yet implemented"); + return 0; +} + +uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { + llvm_unreachable("not yet implemented"); + return 0; +} + +uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { + llvm_unreachable("not yet implemented"); + return 0; +} + +Expected<SymbolRef::Type> +WasmObjectFile::getSymbolType(DataRefImpl Symb) const { + llvm_unreachable("not yet implemented"); + return errorCodeToError(object_error::invalid_symbol_index); +} + +Expected<section_iterator> +WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { + llvm_unreachable("not yet implemented"); + return errorCodeToError(object_error::invalid_symbol_index); +} + +void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } + +std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, + StringRef &Res) const { + const wasm::WasmSection &S = Sections[Sec.d.a]; +#define ECase(X) \ + case wasm::WASM_SEC_##X: \ + Res = #X; \ + break + switch (S.Type) { + ECase(TYPE); + ECase(IMPORT); + ECase(FUNCTION); + ECase(TABLE); + ECase(MEMORY); + ECase(GLOBAL); + ECase(EXPORT); + ECase(START); + ECase(ELEM); + ECase(CODE); + ECase(DATA); + case wasm::WASM_SEC_USER: + Res = S.Name; + break; + default: + return object_error::invalid_section_index; + } +#undef ECase + return std::error_code(); +} + +uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } + +uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { + const wasm::WasmSection &S = Sections[Sec.d.a]; + return S.Content.size(); +} + +std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Res) const { + const wasm::WasmSection &S = Sections[Sec.d.a]; + // This will never fail since wasm sections can never be empty (user-sections + // must have a name and non-user sections each have a defined structure). + Res = StringRef(reinterpret_cast<const char *>(S.Content.data()), + S.Content.size()); + return std::error_code(); +} + +uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { + return 1; +} + +bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { + return false; +} + +bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { + const wasm::WasmSection &S = Sections[Sec.d.a]; + return S.Type == wasm::WASM_SEC_CODE; +} + +bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { + const wasm::WasmSection &S = Sections[Sec.d.a]; + return S.Type == wasm::WASM_SEC_DATA; +} + +bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } + +bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } + +bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } + +relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Sec) const { + llvm_unreachable("not yet implemented"); + RelocationRef Rel; + return relocation_iterator(Rel); +} + +relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Sec) const { + llvm_unreachable("not yet implemented"); + RelocationRef Rel; + return relocation_iterator(Rel); +} + +section_iterator WasmObjectFile::getRelocatedSection(DataRefImpl Sec) const { + llvm_unreachable("not yet implemented"); + SectionRef Ref; + return section_iterator(Ref); +} + +void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { + llvm_unreachable("not yet implemented"); +} + +uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Rel) const { + llvm_unreachable("not yet implemented"); + return 0; +} + +symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const { + llvm_unreachable("not yet implemented"); + SymbolRef Ref; + return symbol_iterator(Ref); +} + +uint64_t WasmObjectFile::getRelocationType(DataRefImpl Rel) const { + llvm_unreachable("not yet implemented"); + return 0; +} + +void WasmObjectFile::getRelocationTypeName( + DataRefImpl Rel, SmallVectorImpl<char> &Result) const { + llvm_unreachable("not yet implemented"); +} + +section_iterator WasmObjectFile::section_begin() const { + DataRefImpl Ref; + Ref.d.a = 0; + return section_iterator(SectionRef(Ref, this)); +} + +section_iterator WasmObjectFile::section_end() const { + DataRefImpl Ref; + Ref.d.a = Sections.size(); + return section_iterator(SectionRef(Ref, this)); +} + +uint8_t WasmObjectFile::getBytesInAddress() const { return 4; } + +StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } + +unsigned WasmObjectFile::getArch() const { return Triple::wasm32; } + +SubtargetFeatures WasmObjectFile::getFeatures() const { + return SubtargetFeatures(); +} + +bool WasmObjectFile::isRelocatableObject() const { return false; } + +const wasm::WasmSection * +WasmObjectFile::getWasmSection(const SectionRef &Section) const { + return &Sections[Section.getRawDataRefImpl().d.a]; +} + +} // end namespace object +} // end namespace llvm |