Index: include/llvm/Object/Binary.h =================================================================== --- include/llvm/Object/Binary.h +++ include/llvm/Object/Binary.h @@ -59,6 +59,8 @@ ID_MachO64L, // MachO 64-bit, little endian ID_MachO64B, // MachO 64-bit, big endian + ID_WASM, + ID_EndObjects }; @@ -115,6 +117,10 @@ return TypeID == ID_COFF; } + bool isWasm() const { + return TypeID == ID_WASM; + } + bool isCOFFImportFile() const { return TypeID == ID_COFFImportFile; } Index: include/llvm/Object/ObjectFile.h =================================================================== --- include/llvm/Object/ObjectFile.h +++ include/llvm/Object/ObjectFile.h @@ -29,6 +29,7 @@ class ObjectFile; class COFFObjectFile; class MachOObjectFile; +class WasmObjectFile; class SymbolRef; class symbol_iterator; @@ -302,6 +303,8 @@ static Expected> createMachOObjectFile(MemoryBufferRef Object); + static Expected> + createWasmObjectFile(MemoryBufferRef Object); }; // Inline function definitions. Index: include/llvm/Object/Wasm.h =================================================================== --- /dev/null +++ include/llvm/Object/Wasm.h @@ -0,0 +1,110 @@ +//===- Wasm.h - 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. +// +//===----------------------------------------------------------------------===// +// +// This file declares the WasmObjectFile class, which implement the ObjectFile +// interface for Wasm files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_WASM_H +#define LLVM_OBJECT_WASM_H + +#include "llvm/Object/ObjectFile.h" + +namespace llvm { +namespace object { + +struct WasmObjectHeader { + StringRef Magic; + uint32_t Version; +}; + +struct WasmSection { + uint32_t Offset; + uint32_t Kind; + uint32_t Size; + const uint8_t* Start; +}; + +class WasmObjectFile : public ObjectFile { +public: + WasmObjectFile(MemoryBufferRef Object, Error &Err); + const WasmObjectHeader &getHeader() const; + const WasmSection *getWasmSection(const SectionRef &Section) const; + +protected: + WasmObjectHeader Header; + std::vector Sections; + + const uint8_t *getPtr(size_t Offset) const; + + void moveSymbolNext(DataRefImpl &Symb) const override; + + std::error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const override; + + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + + basic_symbol_iterator symbol_begin_impl() const override; + + basic_symbol_iterator symbol_end_impl() const override; + Expected getSymbolName(DataRefImpl Symb) const override; + + //std::error_code printSymbolName(raw_ostream &OS, + //DataRefImpl Symb) const override; + Expected getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + uint32_t getSymbolAlignment(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; + Expected getSymbolType(DataRefImpl Symb) const override; + Expected + getSymbolSection(DataRefImpl Symb) const override; + + // Same as above for SectionRef. + friend class SectionRef; + void moveSectionNext(DataRefImpl &Sec) const override; + std::error_code getSectionName(DataRefImpl Sec, + StringRef &Res) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; + std::error_code getSectionContents(DataRefImpl Sec, + StringRef &Res) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool isSectionBitcode(DataRefImpl Sec) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + section_iterator getRelocatedSection(DataRefImpl Sec) const override; + + // Same as above for RelocationRef. + friend class RelocationRef; + void moveRelocationNext(DataRefImpl &Rel) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const override; + + section_iterator section_begin() const override; + section_iterator section_end() const override; + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + unsigned getArch() const override; + SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } + bool isRelocatableObject() const override; +}; + +} +} + +#endif Index: include/llvm/ObjectYAML/WasmYAML.h =================================================================== --- /dev/null +++ include/llvm/ObjectYAML/WasmYAML.h @@ -0,0 +1,68 @@ +//===- WasmYAML.h - Wasm YAMLIO implementation ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file declares classes for handling the YAML representation +/// of wasm binaries. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECTYAML_WASMYAML_H +#define LLVM_OBJECTYAML_WASMYAML_H + +#include "llvm/ObjectYAML/YAML.h" + +namespace llvm { +namespace WasmYAML { + +struct FileHeader { + StringRef Magic; + llvm::yaml::Hex32 Version; +}; + +struct Section { + uint32_t Kind; + llvm::yaml::Hex32 Offset; + llvm::yaml::Hex32 Size; + yaml::BinaryRef Content; +}; + +struct Object { + FileHeader Header; + std::vector> Sections; +}; + +} // namespace llvm::MachOYAML +} // namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr) + +namespace llvm { +namespace yaml { + +template <> +struct MappingTraits { + static void mapping(IO &IO, WasmYAML::FileHeader &FileHdr); +}; + +template <> +struct MappingTraits> { + static void mapping(IO &IO, std::unique_ptr &Section); + //static StringRef validate(IO &io, std::unique_ptr &Section); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, WasmYAML::Object &Object); +}; + +} // end namespace yaml +} // end namespace llvm + +#endif Index: include/llvm/Support/FileSystem.h =================================================================== --- include/llvm/Support/FileSystem.h +++ include/llvm/Support/FileSystem.h @@ -261,7 +261,8 @@ coff_object, ///< COFF object file coff_import_library, ///< COFF import library pecoff_executable, ///< PECOFF executable file - windows_resource ///< Windows compiled resource file (.rc) + windows_resource, ///< Windows compiled resource file (.rc) + wasm_object ///< WebAssembly Object file }; bool is_object() const { Index: lib/Object/Binary.cpp =================================================================== --- lib/Object/Binary.cpp +++ lib/Object/Binary.cpp @@ -63,6 +63,7 @@ case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: case sys::fs::file_magic::bitcode: + case sys::fs::file_magic::wasm_object: return ObjectFile::createSymbolicFile(Buffer, Type, Context); case sys::fs::file_magic::macho_universal_binary: return MachOUniversalBinary::create(Buffer); Index: lib/Object/CMakeLists.txt =================================================================== --- lib/Object/CMakeLists.txt +++ lib/Object/CMakeLists.txt @@ -15,6 +15,7 @@ RecordStreamer.cpp SymbolicFile.cpp SymbolSize.cpp + WasmObjectFile.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/Object Index: lib/Object/ObjectFile.cpp =================================================================== --- lib/Object/ObjectFile.cpp +++ lib/Object/ObjectFile.cpp @@ -13,6 +13,7 @@ #include "llvm/Object/COFF.h" #include "llvm/Object/MachO.h" +#include "llvm/Object/Wasm.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" @@ -104,6 +105,8 @@ case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: return errorOrToExpected(createCOFFObjectFile(Object)); + case sys::fs::file_magic::wasm_object: + return createWasmObjectFile(Object); } llvm_unreachable("Unexpected Object File Type"); } Index: lib/Object/SymbolicFile.cpp =================================================================== --- lib/Object/SymbolicFile.cpp +++ lib/Object/SymbolicFile.cpp @@ -57,6 +57,7 @@ case sys::fs::file_magic::macho_dsym_companion: case sys::fs::file_magic::macho_kext_bundle: case sys::fs::file_magic::pecoff_executable: + case sys::fs::file_magic::wasm_object: return ObjectFile::createObjectFile(Object, Type); case sys::fs::file_magic::coff_import_library: return std::unique_ptr(new COFFImportFile(Object)); Index: lib/Object/WasmObjectFile.cpp =================================================================== --- /dev/null +++ lib/Object/WasmObjectFile.cpp @@ -0,0 +1,280 @@ +//===- 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/LEB128.h" +#include "llvm/Support/Host.h" + +#include + +namespace llvm { +namespace object { + +Expected> +ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { + Error Err; + std::unique_ptr R; + + R.reset(new WasmObjectFile(Buffer, Err)); + if (Err) + std::move(Err); + + return std::move(R); +} + +uint32_t readUint32(const uint8_t *Ptr) { + uint32_t Result = 0; + memcpy(&Result, Ptr, sizeof(Result)); + if (!sys::IsLittleEndianHost) + sys::swapByteOrder(Result); + return Result; +} + +uint64_t readULEB128(const uint8_t *&Ptr) { + unsigned Count; + uint64_t Result = decodeULEB128(Ptr, &Count); + Ptr += Count; + return Result; +} + +void readSection(WasmSection &Section, const uint8_t *&Ptr, const uint8_t *Start) { + Section.Offset = Ptr - Start; + Section.Kind = readULEB128(Ptr); + Section.Size = readULEB128(Ptr); + Section.Start = Ptr; + Ptr += Section.Size; +} + +WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) + : ObjectFile(Binary::ID_WASM, Buffer) { + Header.Magic = getData().substr(0, 4); + Header.Version = readUint32(getPtr(4)); + if (Header.Magic != StringRef("\0asm", 4)) { + Err = make_error("Bad magic number", + object_error::invalid_file_type); + } + const uint8_t* Ptr = getPtr(8); + const uint8_t* Eof = getPtr(getData().size()); + WasmSection Sec; + while (Ptr < Eof) { + readSection(Sec, Ptr, getPtr(0)); + Sections.push_back(Sec); + } +} + +const uint8_t *WasmObjectFile::getPtr(size_t Offset) const { + return (const uint8_t*)getData().substr(Offset, 1).data(); +} + +const WasmObjectHeader& WasmObjectFile::getHeader() const { + return Header; +} + +void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { + assert(0); +} + +std::error_code WasmObjectFile::printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const { + assert(0); + return object_error::invalid_file_type; +} + +uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { + assert(0); + return 0; +} + +basic_symbol_iterator WasmObjectFile::symbol_begin_impl() const { + assert(0); + return BasicSymbolRef(DataRefImpl(), this); +} + +basic_symbol_iterator WasmObjectFile::symbol_end_impl() const { + assert(0); + return BasicSymbolRef(DataRefImpl(), this); +} + +Expected WasmObjectFile::getSymbolName(DataRefImpl Symb) const { + assert(0); + return errorCodeToError(object_error::invalid_file_type); +} + +Expected WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { + assert(0); + return errorCodeToError(object_error::invalid_file_type); +} + +uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { + assert(0); + return 0; +} + +uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { + assert(0); + return 0; +} + +uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { + assert(0); + return 0; +} + +Expected WasmObjectFile::getSymbolType(DataRefImpl Symb) const { + assert(0); + return errorCodeToError(object_error::invalid_file_type); +} + +Expected WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { + assert(0); + return errorCodeToError(object_error::invalid_file_type); +} + +void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { + Sec.d.a++; +} + +std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, + StringRef &Res) const { + assert(0); + return object_error::invalid_file_type; +} + +uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { + assert(0); + return 0; +} + +uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { + assert(0); + return 0; +} + +std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Res) const { + assert(0); + return object_error::invalid_file_type; +} + +uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { + assert(0); + return 1; +} + +bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { + assert(0); + return false; +} + +bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { + assert(0); + return false; +} + +bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { + assert(0); + return false; +} + +bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { + assert(0); + return false; +} + +bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { + assert(0); + return false; +} + +bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { + assert(0); + return false; +} + +relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Sec) const { + assert(0); + RelocationRef Rel; + return relocation_iterator(Rel); +} + +relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Sec) const { + assert(0); + RelocationRef Rel; + return relocation_iterator(Rel); +} + +section_iterator WasmObjectFile::getRelocatedSection(DataRefImpl Sec) const { + assert(0); + SectionRef Ref; + return section_iterator(Ref); +} + +void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { + assert(0); +} + +uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Rel) const { + assert(0); + return 0; +} + +symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const { + assert(0); + SymbolRef Ref; + return symbol_iterator(Ref); +} + +uint64_t WasmObjectFile::getRelocationType(DataRefImpl Rel) const { + assert(0); + return 0; +} + +void WasmObjectFile::getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const { + assert(0); +} + +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 { + assert(0); + return 0; +} + +StringRef WasmObjectFile::getFileFormatName() const { + assert(0); + return "wasm32"; +} + +unsigned WasmObjectFile::getArch() const { + assert(0); + return Triple::UnknownArch; +} + +bool WasmObjectFile::isRelocatableObject() const { + assert(0); + return false; +} + +const WasmSection *WasmObjectFile::getWasmSection(const SectionRef &Section) const { + return &Sections[Section.getRawDataRefImpl().d.a]; +} + +} // end namespace object +} // end namespace llvm Index: lib/ObjectYAML/CMakeLists.txt =================================================================== --- lib/ObjectYAML/CMakeLists.txt +++ lib/ObjectYAML/CMakeLists.txt @@ -4,4 +4,5 @@ ELFYAML.cpp MachOYAML.cpp ObjectYAML.cpp + WasmYAML.cpp ) Index: lib/ObjectYAML/WasmYAML.cpp =================================================================== --- /dev/null +++ lib/ObjectYAML/WasmYAML.cpp @@ -0,0 +1,46 @@ +//===- WasmYAML.cpp - Wasm YAMLIO implementation --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines classes for handling the YAML representation of wasm. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ObjectYAML/WasmYAML.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/MipsABIFlags.h" + +namespace llvm { +namespace yaml { + +void MappingTraits::mapping(IO &IO, + WasmYAML::FileHeader &FileHdr) { + IO.mapRequired("Magic", FileHdr.Magic); + IO.mapRequired("Version", FileHdr.Version); +} + +void MappingTraits::mapping(IO &IO, + WasmYAML::Object &Object) { + IO.setContext(&Object); + IO.mapTag("!WASM", true); + IO.mapRequired("FileHeader", Object.Header); + IO.mapOptional("Sections", Object.Sections); + IO.setContext(nullptr); +} + +void MappingTraits>::mapping( + IO &IO, + std::unique_ptr &Section) { + IO.mapRequired("Kind", Section->Kind); + IO.mapRequired("Offset", Section->Offset); + IO.mapRequired("Size", Section->Size); + IO.mapRequired("Content", Section->Content); +} + +} // end namespace yaml +} // end namespace llvm Index: lib/Support/Path.cpp =================================================================== --- lib/Support/Path.cpp +++ lib/Support/Path.cpp @@ -1008,6 +1008,8 @@ // 0x0000 = COFF unknown machine type if (Magic[1] == 0) return file_magic::coff_object; + if (Magic[1] == 'a' && Magic[2] == 's' && Magic[3] == 'm') + return file_magic::wasm_object; break; } case 0xDE: // 0x0B17C0DE = BC wraper Index: tools/obj2yaml/CMakeLists.txt =================================================================== --- tools/obj2yaml/CMakeLists.txt +++ tools/obj2yaml/CMakeLists.txt @@ -9,5 +9,6 @@ coff2yaml.cpp elf2yaml.cpp macho2yaml.cpp + wasm2yaml.cpp Error.cpp ) Index: tools/obj2yaml/coff2yaml.cpp =================================================================== --- tools/obj2yaml/coff2yaml.cpp +++ tools/obj2yaml/coff2yaml.cpp @@ -1,4 +1,4 @@ -//===------ utils/obj2yaml.cpp - obj2yaml conversion tool -------*- C++ -*-===// +//===------ utils/coff2yaml.cpp - obj2yaml conversion tool ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // Index: tools/obj2yaml/obj2yaml.h =================================================================== --- tools/obj2yaml/obj2yaml.h +++ tools/obj2yaml/obj2yaml.h @@ -14,6 +14,7 @@ #define LLVM_TOOLS_OBJ2YAML_OBJ2YAML_H #include "llvm/Object/COFF.h" +#include "llvm/Object/Wasm.h" #include "llvm/Support/raw_ostream.h" #include @@ -23,5 +24,7 @@ const llvm::object::ObjectFile &Obj); std::error_code macho2yaml(llvm::raw_ostream &Out, const llvm::object::Binary &Obj); +std::error_code wasm2yaml(llvm::raw_ostream &Out, + const llvm::object::WasmObjectFile &Obj); #endif Index: tools/obj2yaml/obj2yaml.cpp =================================================================== --- tools/obj2yaml/obj2yaml.cpp +++ tools/obj2yaml/obj2yaml.cpp @@ -24,6 +24,8 @@ return coff2yaml(outs(), cast(Obj)); if (Obj.isELF()) return elf2yaml(outs(), Obj); + if (Obj.isWasm()) + return wasm2yaml(outs(), cast(Obj)); return obj2yaml_error::unsupported_obj_file_format; } Index: tools/obj2yaml/wasm2yaml.cpp =================================================================== --- /dev/null +++ tools/obj2yaml/wasm2yaml.cpp @@ -0,0 +1,63 @@ +//===------ utils/wasm2yaml.cpp - obj2yaml conversion tool ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "obj2yaml.h" +#include "llvm/Object/COFF.h" +#include "llvm/ObjectYAML/WasmYAML.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/YAMLTraits.h" + +using namespace llvm; + +namespace { + +class WasmDumper { + const object::WasmObjectFile &Obj; + +public: + WasmDumper(const object::WasmObjectFile &O) : Obj(O) {} + ErrorOr dump(); +}; + +ErrorOr WasmDumper::dump() { + auto Y = make_unique(); + + // Dump header + Y->Header.Magic = Obj.getHeader().Magic; + Y->Header.Version = Obj.getHeader().Version; + + // Dump sections + for (const auto &Sec : Obj.sections()) { + const object::WasmSection* WasmSec = Obj.getWasmSection(Sec); + WasmYAML::Section* S = new WasmYAML::Section; + S->Kind = WasmSec->Kind; + S->Offset = WasmSec->Offset; + S->Size = WasmSec->Size; + ArrayRef Content(WasmSec->Start, WasmSec->Size); + S->Content = yaml::BinaryRef(Content); + Y->Sections.push_back(std::unique_ptr(S)); + } + + return Y.release(); +} + +} + +std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) { + WasmDumper Dumper(Obj); + ErrorOr YAMLOrErr = Dumper.dump(); + if (std::error_code EC = YAMLOrErr.getError()) + return EC; + + std::unique_ptr YAML(YAMLOrErr.get()); + yaml::Output Yout(Out); + Yout << *YAML; + + return std::error_code(); +}