namespace llvm {
namespace object {
+class WasmSymbol {
+public:
+ enum class SymbolType {
+ FUNCTION_IMPORT,
+ FUNCTION_EXPORT,
+ GLOBAL_IMPORT,
+ GLOBAL_EXPORT,
+ DEBUG_FUNCTION_NAME,
+ };
+
+ WasmSymbol(StringRef Name, SymbolType Type) : Name(Name), Type(Type) {}
+
+ StringRef Name;
+ SymbolType Type;
+};
+
+class WasmSection {
+public:
+ WasmSection() : Type(0), Offset(0) {}
+
+ uint32_t Type; // Section type (See below)
+ uint32_t Offset; // Offset with in the file
+ StringRef Name; // Section name (User-defined sections only)
+ ArrayRef<uint8_t> Content; // Section content
+ std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
+};
+
class WasmObjectFile : public ObjectFile {
public:
WasmObjectFile(MemoryBufferRef Object, Error &Err);
const wasm::WasmObjectHeader &getHeader() const;
- const wasm::WasmSection *getWasmSection(const SectionRef &Section) const;
+ const WasmSymbol &getWasmSymbol(DataRefImpl Symb) const;
+ const WasmSection &getWasmSection(const SectionRef &Section) const;
+ const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const;
static bool classof(const Binary *v) { return v->isWasm(); }
+ const std::vector<wasm::WasmSignature>& types() const { return Signatures; }
+ const std::vector<uint32_t>& functionTypes() const { return FunctionTypes; }
+ const std::vector<wasm::WasmImport>& imports() const { return Imports; }
+ const std::vector<wasm::WasmTable>& tables() const { return Tables; }
+ const std::vector<wasm::WasmLimits>& memories() const { return Memories; }
+ const std::vector<wasm::WasmGlobal>& globals() const { return Globals; }
+ const std::vector<wasm::WasmExport>& exports() const { return Exports; }
+ const std::vector<wasm::WasmElemSegment>& elements() const {
+ return ElemSegments;
+ }
+ const std::vector<wasm::WasmDataSegment>& dataSegments() const {
+ return DataSegments;
+ }
+ const std::vector<wasm::WasmFunction>& functions() const { return Functions; }
+ const ArrayRef<uint8_t>& code() const { return CodeSection; }
+ uint32_t startFunction() const { return StartFunction; }
+
protected:
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() 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;
// Overrides from RelocationRef.
void moveRelocationNext(DataRefImpl &Rel) const override;
bool isRelocatableObject() const override;
private:
+ const WasmSection &getWasmSection(DataRefImpl Ref) const;
+ const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
+
+ WasmSection* findCustomSectionByName(StringRef Name);
+ WasmSection* findSectionByType(uint32_t Type);
+
const uint8_t *getPtr(size_t Offset) const;
- Error parseCustomSection(wasm::WasmSection &Sec, const uint8_t *Ptr,
- size_t Length);
+ Error parseSection(WasmSection &Sec);
+ Error parseCustomSection(WasmSection &Sec, const uint8_t *Ptr,
+ const uint8_t *End);
+
+ // Standard section types
+ Error parseTypeSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseImportSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseFunctionSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseTableSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseMemorySection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseGlobalSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseExportSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseStartSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseElemSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseCodeSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseDataSection(const uint8_t *Ptr, const uint8_t *End);
+
+ // Custom section types
+ Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
+ Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
+ const uint8_t *End);
wasm::WasmObjectHeader Header;
- std::vector<wasm::WasmSection> Sections;
+ std::vector<WasmSection> Sections;
+ std::vector<wasm::WasmSignature> Signatures;
+ std::vector<uint32_t> FunctionTypes;
+ std::vector<wasm::WasmTable> Tables;
+ std::vector<wasm::WasmLimits> Memories;
+ std::vector<wasm::WasmGlobal> Globals;
+ std::vector<wasm::WasmImport> Imports;
+ std::vector<wasm::WasmExport> Exports;
+ std::vector<wasm::WasmElemSegment> ElemSegments;
+ std::vector<wasm::WasmDataSegment> DataSegments;
+ std::vector<WasmSymbol> Symbols;
+ std::vector<wasm::WasmFunction> Functions;
+ ArrayRef<uint8_t> CodeSection;
+ uint32_t StartFunction;
};
} // end namespace object
#ifndef LLVM_OBJECTYAML_OBJECTYAML_H
#define LLVM_OBJECTYAML_OBJECTYAML_H
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/ObjectYAML/ELFYAML.h"
#include "llvm/ObjectYAML/COFFYAML.h"
+#include "llvm/ObjectYAML/ELFYAML.h"
#include "llvm/ObjectYAML/MachOYAML.h"
+#include "llvm/ObjectYAML/WasmYAML.h"
+#include "llvm/Support/YAMLTraits.h"
namespace llvm {
namespace yaml {
std::unique_ptr<COFFYAML::Object> Coff;
std::unique_ptr<MachOYAML::Object> MachO;
std::unique_ptr<MachOYAML::UniversalBinary> FatMachO;
+ std::unique_ptr<WasmYAML::Object> Wasm;
};
template <> struct MappingTraits<YamlObjectFile> {
--- /dev/null
+//===- 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"
+#include "llvm/Support/Wasm.h"
+
+namespace llvm {
+namespace WasmYAML {
+
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionType)
+LLVM_YAML_STRONG_TYPEDEF(int32_t, ValueType)
+LLVM_YAML_STRONG_TYPEDEF(int32_t, TableType)
+LLVM_YAML_STRONG_TYPEDEF(int32_t, SignatureForm)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportKind)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, Opcode)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, RelocType)
+
+struct FileHeader {
+ yaml::Hex32 Version;
+};
+
+struct Import {
+ StringRef Module;
+ StringRef Field;
+ ExportKind Kind;
+ union {
+ uint32_t SigIndex;
+ ValueType GlobalType;
+ };
+ bool GlobalMutable;
+};
+
+struct Limits {
+ yaml::Hex32 Flags;
+ yaml::Hex32 Initial;
+ yaml::Hex32 Maximum;
+};
+
+struct Table {
+ TableType ElemType;
+ Limits TableLimits;
+};
+
+struct Export {
+ StringRef Name;
+ ExportKind Kind;
+ uint32_t Index;
+};
+
+struct ElemSegment {
+ uint32_t TableIndex;
+ wasm::WasmInitExpr Offset;
+ std::vector<uint32_t> Functions;
+};
+
+struct Global {
+ ValueType Type;
+ bool Mutable;
+ wasm::WasmInitExpr InitExpr;
+};
+
+struct LocalDecl {
+ ValueType Type;
+ uint32_t Count;
+};
+
+struct Function {
+ std::vector<LocalDecl> Locals;
+ yaml::BinaryRef Body;
+};
+
+struct Relocation {
+ RelocType Type;
+ uint32_t Index;
+ yaml::Hex32 Offset;
+ yaml::Hex32 Addend;
+};
+
+struct DataSegment {
+ uint32_t Index;
+ wasm::WasmInitExpr Offset;
+ yaml::BinaryRef Content;
+};
+
+struct Signature {
+ Signature() : Form(wasm::WASM_TYPE_FUNC) {}
+
+ uint32_t Index;
+ SignatureForm Form;
+ std::vector<ValueType> ParamTypes;
+ ValueType ReturnType;
+};
+
+struct Section {
+ Section(SectionType SecType) : Type(SecType) {}
+
+ SectionType Type;
+ std::vector<Relocation> Relocations;
+};
+
+struct CustomSection : Section {
+ CustomSection() : Section(wasm::WASM_SEC_CUSTOM) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_CUSTOM;
+ }
+
+ StringRef Name;
+ yaml::BinaryRef Payload;
+};
+
+struct TypeSection : Section {
+ TypeSection() : Section(wasm::WASM_SEC_TYPE) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_TYPE;
+ }
+
+ std::vector<Signature> Signatures;
+};
+
+struct ImportSection : Section {
+ ImportSection() : Section(wasm::WASM_SEC_IMPORT) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_IMPORT;
+ }
+
+ std::vector<Import> Imports;
+};
+
+struct FunctionSection : Section {
+ FunctionSection() : Section(wasm::WASM_SEC_FUNCTION) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_FUNCTION;
+ }
+
+ std::vector<uint32_t> FunctionTypes;
+};
+
+struct TableSection : Section {
+ TableSection() : Section(wasm::WASM_SEC_TABLE) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_TABLE;
+ }
+
+ std::vector<Table> Tables;
+};
+
+struct MemorySection : Section {
+ MemorySection() : Section(wasm::WASM_SEC_MEMORY) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_MEMORY;
+ }
+
+ std::vector<Limits> Memories;
+};
+
+struct GlobalSection : Section {
+ GlobalSection() : Section(wasm::WASM_SEC_GLOBAL) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_GLOBAL;
+ }
+
+ std::vector<Global> Globals;
+};
+
+struct ExportSection : Section {
+ ExportSection() : Section(wasm::WASM_SEC_EXPORT) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_EXPORT;
+ }
+
+ std::vector<Export> Exports;
+};
+
+struct StartSection : Section {
+ StartSection() : Section(wasm::WASM_SEC_START) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_START;
+ }
+
+ uint32_t StartFunction;
+};
+
+struct ElemSection : Section {
+ ElemSection() : Section(wasm::WASM_SEC_ELEM) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_ELEM;
+ }
+
+ std::vector<ElemSegment> Segments;
+};
+
+struct CodeSection : Section {
+ CodeSection() : Section(wasm::WASM_SEC_CODE) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_CODE;
+ }
+
+ std::vector<Function> Functions;
+};
+
+struct DataSection : Section {
+ DataSection() : Section(wasm::WASM_SEC_DATA) {}
+ static bool classof(const Section *S) {
+ return S->Type == wasm::WASM_SEC_DATA;
+ }
+
+ std::vector<DataSegment> Segments;
+};
+
+struct Object {
+ FileHeader Header;
+ std::vector<std::unique_ptr<Section>> Sections;
+};
+
+} // end namespace WasmYAML
+} // end namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::WasmYAML::Section>)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Signature)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ValueType)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Table)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Import)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Export)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ElemSegment)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Limits)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DataSegment)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Global)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Function)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
+LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<WasmYAML::FileHeader> {
+ static void mapping(IO &IO, WasmYAML::FileHeader &FileHdr);
+};
+
+template <> struct MappingTraits<std::unique_ptr<WasmYAML::Section>> {
+ static void mapping(IO &IO, std::unique_ptr<WasmYAML::Section> &Section);
+};
+
+template <> struct MappingTraits<WasmYAML::Object> {
+ static void mapping(IO &IO, WasmYAML::Object &Object);
+};
+
+template <> struct MappingTraits<WasmYAML::Import> {
+ static void mapping(IO &IO, WasmYAML::Import &Import);
+};
+
+template <> struct MappingTraits<WasmYAML::Export> {
+ static void mapping(IO &IO, WasmYAML::Export &Export);
+};
+
+template <> struct MappingTraits<WasmYAML::Global> {
+ static void mapping(IO &IO, WasmYAML::Global &Global);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::SectionType> {
+ static void enumeration(IO &IO, WasmYAML::SectionType &Type);
+};
+
+template <> struct MappingTraits<WasmYAML::Signature> {
+ static void mapping(IO &IO, WasmYAML::Signature &Signature);
+};
+
+template <> struct MappingTraits<WasmYAML::Table> {
+ static void mapping(IO &IO, WasmYAML::Table &Table);
+};
+
+template <> struct MappingTraits<WasmYAML::Limits> {
+ static void mapping(IO &IO, WasmYAML::Limits &Limits);
+};
+
+template <> struct MappingTraits<WasmYAML::Function> {
+ static void mapping(IO &IO, WasmYAML::Function &Function);
+};
+
+template <> struct MappingTraits<WasmYAML::Relocation> {
+ static void mapping(IO &IO, WasmYAML::Relocation &Relocation);
+};
+
+template <> struct MappingTraits<WasmYAML::LocalDecl> {
+ static void mapping(IO &IO, WasmYAML::LocalDecl &LocalDecl);
+};
+
+template <> struct MappingTraits<wasm::WasmInitExpr> {
+ static void mapping(IO &IO, wasm::WasmInitExpr &Expr);
+};
+
+template <> struct MappingTraits<WasmYAML::DataSegment> {
+ static void mapping(IO &IO, WasmYAML::DataSegment &Segment);
+};
+
+template <> struct MappingTraits<WasmYAML::ElemSegment> {
+ static void mapping(IO &IO, WasmYAML::ElemSegment &Segment);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> {
+ static void enumeration(IO &IO, WasmYAML::ValueType &Type);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::ExportKind> {
+ static void enumeration(IO &IO, WasmYAML::ExportKind &Kind);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::TableType> {
+ static void enumeration(IO &IO, WasmYAML::TableType &Type);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::Opcode> {
+ static void enumeration(IO &IO, WasmYAML::Opcode &Opcode);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::RelocType> {
+ static void enumeration(IO &IO, WasmYAML::RelocType &Kind);
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+#endif
uint32_t Version;
};
-struct WasmSection {
- uint32_t Type; // Section type (See below)
- uint32_t Offset; // Offset with in the file
- StringRef Name; // Section name (User-defined sections only)
- ArrayRef<uint8_t> Content; // Section content
+struct WasmSignature {
+ std::vector<int32_t> ParamTypes;
+ int32_t ReturnType;
+};
+
+struct WasmImport {
+ StringRef Module;
+ StringRef Field;
+ uint32_t Kind;
+ union {
+ uint32_t SigIndex;
+ int32_t GlobalType;
+ };
+ bool GlobalMutable;
+};
+
+struct WasmExport {
+ StringRef Name;
+ uint32_t Kind;
+ uint32_t Index;
+};
+
+struct WasmLimits {
+ uint32_t Flags;
+ uint32_t Initial;
+ uint32_t Maximum;
+};
+
+struct WasmTable {
+ int32_t ElemType;
+ WasmLimits Limits;
+};
+
+struct WasmInitExpr {
+ uint8_t Opcode;
+ union {
+ int32_t Int32;
+ int64_t Int64;
+ int32_t Float32;
+ int64_t Float64;
+ uint32_t Global;
+ } Value;
+};
+
+struct WasmGlobal {
+ int32_t Type;
+ bool Mutable;
+ WasmInitExpr InitExpr;
+};
+
+struct WasmLocalDecl {
+ int32_t Type;
+ uint32_t Count;
+};
+
+struct WasmFunction {
+ std::vector<WasmLocalDecl> Locals;
+ ArrayRef<uint8_t> Body;
+};
+
+struct WasmDataSegment {
+ uint32_t Index;
+ WasmInitExpr Offset;
+ ArrayRef<uint8_t> Content;
+};
+
+struct WasmElemSegment {
+ uint32_t TableIndex;
+ WasmInitExpr Offset;
+ std::vector<uint32_t> Functions;
+};
+
+struct WasmRelocation {
+ uint32_t Type; // The type of the relocation.
+ int32_t Index; // Index into function to global index space.
+ uint64_t Offset; // Offset from the start of the section.
+ uint64_t Addend; // A value to add to the symbol.
};
enum : unsigned {
WASM_NAMES_LOCAL = 0x2,
};
+enum : unsigned {
+ WASM_LIMITS_FLAG_HAS_MAX = 0x1,
+};
+
// Subset of types that a value can have
enum class ValType {
I32 = WASM_TYPE_I32,
#include "WasmRelocs/WebAssembly.def"
};
+#undef WASM_RELOC
+
} // end namespace wasm
} // end namespace llvm
return std::move(ObjectFile);
}
+#define VARINT7_MAX ((1<<7)-1)
+#define VARINT7_MIN (-(1<<7))
+#define VARUINT7_MAX (1<<7)
+#define VARUINT1_MAX (1)
+
+static uint8_t readUint8(const uint8_t *&Ptr) { return *Ptr++; }
+
static uint32_t readUint32(const uint8_t *&Ptr) {
uint32_t Result = support::endian::read32le(Ptr);
Ptr += sizeof(Result);
return Result;
}
+static int32_t readFloat32(const uint8_t *&Ptr) {
+ int32_t Result = 0;
+ memcpy(&Result, Ptr, sizeof(Result));
+ Ptr += sizeof(Result);
+ return Result;
+}
+
+static int64_t readFloat64(const uint8_t *&Ptr) {
+ int64_t Result = 0;
+ memcpy(&Result, Ptr, sizeof(Result));
+ Ptr += sizeof(Result);
+ return Result;
+}
+
static uint64_t readULEB128(const uint8_t *&Ptr) {
unsigned Count;
uint64_t Result = decodeULEB128(Ptr, &Count);
return Return;
}
-static Error readSection(wasm::WasmSection &Section, const uint8_t *&Ptr,
+static int64_t readLEB128(const uint8_t *&Ptr) {
+ unsigned Count;
+ uint64_t Result = decodeSLEB128(Ptr, &Count);
+ Ptr += Count;
+ return Result;
+}
+
+static uint8_t readVaruint1(const uint8_t *&Ptr) {
+ int64_t result = readLEB128(Ptr);
+ assert(result <= VARUINT1_MAX && result >= 0);
+ return result;
+}
+
+static int8_t readVarint7(const uint8_t *&Ptr) {
+ int64_t result = readLEB128(Ptr);
+ assert(result <= VARINT7_MAX && result >= VARINT7_MIN);
+ return result;
+}
+
+static uint8_t readVaruint7(const uint8_t *&Ptr) {
+ uint64_t result = readULEB128(Ptr);
+ assert(result <= VARUINT7_MAX && result >= 0);
+ return result;
+}
+
+static int32_t readVarint32(const uint8_t *&Ptr) {
+ int64_t result = readLEB128(Ptr);
+ assert(result <= INT32_MAX && result >= INT32_MIN);
+ return result;
+}
+
+static uint32_t readVaruint32(const uint8_t *&Ptr) {
+ uint64_t result = readULEB128(Ptr);
+ assert(result <= UINT32_MAX && result >= 0);
+ return result;
+}
+
+static int64_t readVarint64(const uint8_t *&Ptr) {
+ return readLEB128(Ptr);
+}
+
+static uint8_t readOpcode(const uint8_t *&Ptr) {
+ return readUint8(Ptr);
+}
+
+static Error readInitExpr(wasm::WasmInitExpr &Expr, const uint8_t *&Ptr) {
+ Expr.Opcode = readOpcode(Ptr);
+
+ switch (Expr.Opcode) {
+ case wasm::WASM_OPCODE_I32_CONST:
+ Expr.Value.Int32 = readVarint32(Ptr);
+ break;
+ case wasm::WASM_OPCODE_I64_CONST:
+ Expr.Value.Int64 = readVarint64(Ptr);
+ break;
+ case wasm::WASM_OPCODE_F32_CONST:
+ Expr.Value.Float32 = readFloat32(Ptr);
+ break;
+ case wasm::WASM_OPCODE_F64_CONST:
+ Expr.Value.Float64 = readFloat64(Ptr);
+ break;
+ case wasm::WASM_OPCODE_GET_GLOBAL:
+ Expr.Value.Global = readUint32(Ptr);
+ break;
+ default:
+ return make_error<GenericBinaryError>("Invalid opcode in init_expr",
+ object_error::parse_failed);
+ }
+
+ uint8_t EndOpcode = readOpcode(Ptr);
+ if (EndOpcode != wasm::WASM_OPCODE_END) {
+ return make_error<GenericBinaryError>("Invalid init_expr",
+ object_error::parse_failed);
+ }
+ return Error::success();
+}
+
+static wasm::WasmLimits readLimits(const uint8_t *&Ptr) {
+ wasm::WasmLimits Result;
+ Result.Flags = readVaruint1(Ptr);
+ Result.Initial = readVaruint32(Ptr);
+ if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
+ Result.Maximum = readVaruint32(Ptr);
+ return Result;
+}
+
+static Error readSection(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);
+ Section.Type = readVaruint7(Ptr);
+ uint32_t Size = readVaruint32(Ptr);
if (Size == 0)
return make_error<StringError>("Zero length section",
object_error::parse_failed);
}
WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
- : ObjectFile(Binary::ID_Wasm, Buffer) {
+ : ObjectFile(Binary::ID_Wasm, Buffer), StartFunction(-1) {
ErrorAsOutParameter ErrAsOutParam(&Err);
Header.Magic = getData().substr(0, 4);
if (Header.Magic != StringRef("\0asm", 4)) {
}
const uint8_t *Eof = getPtr(getData().size());
- wasm::WasmSection Sec;
+ WasmSection Sec;
while (Ptr < Eof) {
if ((Err = readSection(Sec, Ptr, getPtr(0))))
return;
- if (Sec.Type == wasm::WASM_SEC_CUSTOM) {
- if ((Err =
- parseCustomSection(Sec, Sec.Content.data(), Sec.Content.size())))
- return;
- }
+ if ((Err = parseSection(Sec)))
+ return;
+
Sections.push_back(Sec);
}
}
-Error WasmObjectFile::parseCustomSection(wasm::WasmSection &Sec,
- const uint8_t *Ptr, size_t Length) {
+Error WasmObjectFile::parseSection(WasmSection &Sec) {
+ const uint8_t* Start = Sec.Content.data();
+ const uint8_t* End = Start + Sec.Content.size();
+ switch (Sec.Type) {
+ case wasm::WASM_SEC_CUSTOM:
+ return parseCustomSection(Sec, Start, End);
+ case wasm::WASM_SEC_TYPE:
+ return parseTypeSection(Start, End);
+ case wasm::WASM_SEC_IMPORT:
+ return parseImportSection(Start, End);
+ case wasm::WASM_SEC_FUNCTION:
+ return parseFunctionSection(Start, End);
+ case wasm::WASM_SEC_TABLE:
+ return parseTableSection(Start, End);
+ case wasm::WASM_SEC_MEMORY:
+ return parseMemorySection(Start, End);
+ case wasm::WASM_SEC_GLOBAL:
+ return parseGlobalSection(Start, End);
+ case wasm::WASM_SEC_EXPORT:
+ return parseExportSection(Start, End);
+ case wasm::WASM_SEC_START:
+ return parseStartSection(Start, End);
+ case wasm::WASM_SEC_ELEM:
+ return parseElemSection(Start, End);
+ case wasm::WASM_SEC_CODE:
+ return parseCodeSection(Start, End);
+ case wasm::WASM_SEC_DATA:
+ return parseDataSection(Start, End);
+ default:
+ return make_error<GenericBinaryError>("Bad section type",
+ object_error::parse_failed);
+ }
+}
+
+Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
+ while (Ptr < End) {
+ uint8_t Type = readVarint7(Ptr);
+ uint32_t Size = readVaruint32(Ptr);
+ switch (Type) {
+ case wasm::WASM_NAMES_FUNCTION: {
+ uint32_t Count = readVaruint32(Ptr);
+ while (Count--) {
+ /*uint32_t Index =*/readVaruint32(Ptr);
+ StringRef Name = readString(Ptr);
+ if (Name.size())
+ Symbols.emplace_back(Name,
+ WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME);
+ }
+ break;
+ }
+ // Ignore local names for now
+ case wasm::WASM_NAMES_LOCAL:
+ default:
+ Ptr += Size;
+ break;
+ }
+ }
+
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Name section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) {
+ for (WasmSection& Section : Sections) {
+ if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name)
+ return &Section;
+ }
+ return nullptr;
+}
+
+WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) {
+ assert(Type != wasm::WASM_SEC_CUSTOM);
+ for (WasmSection& Section : Sections) {
+ if (Section.Type == Type)
+ return &Section;
+ }
+ return nullptr;
+}
+
+Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
+ const uint8_t *End) {
+ uint8_t SectionCode = readVarint7(Ptr);
+ WasmSection* Section = nullptr;
+ if (SectionCode == wasm::WASM_SEC_CUSTOM) {
+ StringRef Name = readString(Ptr);
+ Section = findCustomSectionByName(Name);
+ } else {
+ Section = findSectionByType(SectionCode);
+ }
+ if (!Section)
+ return make_error<GenericBinaryError>("Invalid section code",
+ object_error::parse_failed);
+ uint32_t RelocCount = readVaruint32(Ptr);
+ while (RelocCount--) {
+ wasm::WasmRelocation Reloc;
+ memset(&Reloc, 0, sizeof(Reloc));
+ Reloc.Type = readVaruint32(Ptr);
+ Reloc.Offset = readVaruint32(Ptr);
+ Reloc.Index = readVaruint32(Ptr);
+ switch (Reloc.Type) {
+ case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+ case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
+ break;
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ Reloc.Addend = readVaruint32(Ptr);
+ break;
+ default:
+ return make_error<GenericBinaryError>("Bad relocation type",
+ object_error::parse_failed);
+ }
+ Section->Relocations.push_back(Reloc);
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Reloc section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+Error WasmObjectFile::parseCustomSection(WasmSection &Sec,
+ const uint8_t *Ptr, const uint8_t *End) {
Sec.Name = readString(Ptr);
+ if (Sec.Name == "name") {
+ if (Error Err = parseNameSection(Ptr, End))
+ return Err;
+ } else if (Sec.Name.startswith("reloc.")) {
+ if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
+ return Err;
+ }
+ return Error::success();
+}
+
+Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) {
+ uint32_t Count = readVaruint32(Ptr);
+ Signatures.reserve(Count);
+ while (Count--) {
+ wasm::WasmSignature Sig;
+ Sig.ReturnType = wasm::WASM_TYPE_NORESULT;
+ int8_t Form = readVarint7(Ptr);
+ if (Form != wasm::WASM_TYPE_FUNC) {
+ return make_error<GenericBinaryError>("Invalid signature type",
+ object_error::parse_failed);
+ }
+ uint32_t ParamCount = readVaruint32(Ptr);
+ Sig.ParamTypes.reserve(ParamCount);
+ while (ParamCount--) {
+ uint32_t ParamType = readVarint7(Ptr);
+ Sig.ParamTypes.push_back(ParamType);
+ }
+ uint32_t ReturnCount = readVaruint32(Ptr);
+ if (ReturnCount) {
+ if (ReturnCount != 1) {
+ return make_error<GenericBinaryError>(
+ "Multiple return types not supported", object_error::parse_failed);
+ }
+ Sig.ReturnType = readVarint7(Ptr);
+ }
+ Signatures.push_back(Sig);
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Type section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) {
+ uint32_t Count = readVaruint32(Ptr);
+ Imports.reserve(Count);
+ while (Count--) {
+ wasm::WasmImport Im;
+ Im.Module = readString(Ptr);
+ Im.Field = readString(Ptr);
+ Im.Kind = readUint8(Ptr);
+ switch (Im.Kind) {
+ case wasm::WASM_EXTERNAL_FUNCTION:
+ Im.SigIndex = readVaruint32(Ptr);
+ Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT);
+ break;
+ case wasm::WASM_EXTERNAL_GLOBAL:
+ Im.GlobalType = readVarint7(Ptr);
+ Im.GlobalMutable = readVaruint1(Ptr);
+ Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT);
+ break;
+ default:
+ // TODO(sbc): Handle other kinds of imports
+ return make_error<GenericBinaryError>(
+ "Unexpected import kind", object_error::parse_failed);
+ }
+ Imports.push_back(Im);
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Import section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) {
+ uint32_t Count = readVaruint32(Ptr);
+ FunctionTypes.reserve(Count);
+ while (Count--) {
+ FunctionTypes.push_back(readVaruint32(Ptr));
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Function section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) {
+ uint32_t Count = readVaruint32(Ptr);
+ Tables.reserve(Count);
+ while (Count--) {
+ wasm::WasmTable Table;
+ Table.ElemType = readVarint7(Ptr);
+ if (Table.ElemType != wasm::WASM_TYPE_ANYFUNC) {
+ return make_error<GenericBinaryError>("Invalid table element type",
+ object_error::parse_failed);
+ }
+ Table.Limits = readLimits(Ptr);
+ Tables.push_back(Table);
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Table section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) {
+ uint32_t Count = readVaruint32(Ptr);
+ Memories.reserve(Count);
+ while (Count--) {
+ Memories.push_back(readLimits(Ptr));
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Memory section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) {
+ uint32_t Count = readVaruint32(Ptr);
+ Globals.reserve(Count);
+ while (Count--) {
+ wasm::WasmGlobal Global;
+ Global.Type = readVarint7(Ptr);
+ Global.Mutable = readVaruint1(Ptr);
+ size_t offset = Ptr - getPtr(0);
+ if (Error Err = readInitExpr(Global.InitExpr, Ptr)) {
+ offset = Ptr - getPtr(0);
+ return Err;
+ }
+ Globals.push_back(Global);
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Global section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) {
+ uint32_t Count = readVaruint32(Ptr);
+ Exports.reserve(Count);
+ while (Count--) {
+ wasm::WasmExport Ex;
+ Ex.Name = readString(Ptr);
+ Ex.Kind = readUint8(Ptr);
+ Ex.Index = readVaruint32(Ptr);
+ Exports.push_back(Ex);
+ switch (Ex.Kind) {
+ case wasm::WASM_EXTERNAL_FUNCTION:
+ Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT);
+ break;
+ case wasm::WASM_EXTERNAL_GLOBAL:
+ Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT);
+ break;
+ default:
+ // TODO(sbc): Handle other kinds of exports
+ return make_error<GenericBinaryError>(
+ "Unexpected export kind", object_error::parse_failed);
+ }
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Export section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
+ StartFunction = readVaruint32(Ptr);
+ if (StartFunction < FunctionTypes.size())
+ return make_error<GenericBinaryError>("Invalid start function",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) {
+ uint32_t FunctionCount = readVaruint32(Ptr);
+ if (FunctionCount != FunctionTypes.size()) {
+ return make_error<GenericBinaryError>("Invalid function count",
+ object_error::parse_failed);
+ }
+
+ CodeSection = ArrayRef<uint8_t>(Ptr, End - Ptr);
+
+ while (FunctionCount--) {
+ wasm::WasmFunction Function;
+ uint32_t FunctionSize = readVaruint32(Ptr);
+ const uint8_t *FunctionEnd = Ptr + FunctionSize;
+
+ uint32_t NumLocalDecls = readVaruint32(Ptr);
+ Function.Locals.reserve(NumLocalDecls);
+ while (NumLocalDecls--) {
+ wasm::WasmLocalDecl Decl;
+ Decl.Count = readVaruint32(Ptr);
+ Decl.Type = readVarint7(Ptr);
+ Function.Locals.push_back(Decl);
+ }
+
+ uint32_t BodySize = FunctionEnd - Ptr;
+ Function.Body = ArrayRef<uint8_t>(Ptr, BodySize);
+ Ptr += BodySize;
+ assert(Ptr == FunctionEnd);
+ Functions.push_back(Function);
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Code section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) {
+ uint32_t Count = readVaruint32(Ptr);
+ ElemSegments.reserve(Count);
+ while (Count--) {
+ wasm::WasmElemSegment Segment;
+ Segment.TableIndex = readVaruint32(Ptr);
+ if (Segment.TableIndex != 0) {
+ return make_error<GenericBinaryError>("Invalid TableIndex",
+ object_error::parse_failed);
+ }
+ if (Error Err = readInitExpr(Segment.Offset, Ptr))
+ return Err;
+ uint32_t NumElems = readVaruint32(Ptr);
+ while (NumElems--) {
+ Segment.Functions.push_back(readVaruint32(Ptr));
+ }
+ ElemSegments.push_back(Segment);
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Elem section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
+Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) {
+ uint32_t Count = readVaruint32(Ptr);
+ DataSegments.reserve(Count);
+ while (Count--) {
+ wasm::WasmDataSegment Segment;
+ Segment.Index = readVaruint32(Ptr);
+ if (Error Err = readInitExpr(Segment.Offset, Ptr))
+ return Err;
+ uint32_t Size = readVaruint32(Ptr);
+ Segment.Content = ArrayRef<uint8_t>(Ptr, Size);
+ Ptr += Size;
+ DataSegments.push_back(Segment);
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Data section ended prematurely",
+ object_error::parse_failed);
return Error::success();
}
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;
-}
+void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
- llvm_unreachable("not yet implemented");
- return 0;
+ const WasmSymbol &Sym = getWasmSymbol(Symb);
+ switch (Sym.Type) {
+ case WasmSymbol::SymbolType::FUNCTION_IMPORT:
+ return object::SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
+ case WasmSymbol::SymbolType::FUNCTION_EXPORT:
+ return object::SymbolRef::SF_Global | SymbolRef::SF_Executable;
+ case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
+ return object::SymbolRef::SF_Executable;
+ case WasmSymbol::SymbolType::GLOBAL_IMPORT:
+ return object::SymbolRef::SF_Undefined;
+ case WasmSymbol::SymbolType::GLOBAL_EXPORT:
+ return object::SymbolRef::SF_Global;
+ }
}
basic_symbol_iterator WasmObjectFile::symbol_begin() const {
- return BasicSymbolRef(DataRefImpl(), this);
+ DataRefImpl Ref;
+ Ref.d.a = 0;
+ return BasicSymbolRef(Ref, this);
}
basic_symbol_iterator WasmObjectFile::symbol_end() const {
- return BasicSymbolRef(DataRefImpl(), this);
+ DataRefImpl Ref;
+ Ref.d.a = Symbols.size();
+ return BasicSymbolRef(Ref, this);
+}
+
+const WasmSymbol &WasmObjectFile::getWasmSymbol(DataRefImpl Symb) const {
+ return Symbols[Symb.d.a];
}
Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
- llvm_unreachable("not yet implemented");
- return errorCodeToError(object_error::invalid_symbol_index);
+ const WasmSymbol &Sym = getWasmSymbol(Symb);
+ return Sym.Name;
}
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
- llvm_unreachable("not yet implemented");
- return errorCodeToError(object_error::invalid_symbol_index);
+ return (uint64_t)Symb.d.a;
}
uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
StringRef &Res) const {
- const wasm::WasmSection &S = Sections[Sec.d.a];
+ const WasmSection &S = Sections[Sec.d.a];
#define ECase(X) \
case wasm::WASM_SEC_##X: \
Res = #X; \
uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
- const wasm::WasmSection &S = Sections[Sec.d.a];
+ const 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];
+ const 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()),
}
bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
- const wasm::WasmSection &S = Sections[Sec.d.a];
- return S.Type == wasm::WASM_SEC_CODE;
+ return getWasmSection(Sec).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;
+ return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
}
bool WasmObjectFile::isSectionBSS(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);
+relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
+ DataRefImpl RelocRef;
+ RelocRef.d.a = Ref.d.a;
+ RelocRef.d.b = 0;
+ return relocation_iterator(RelocationRef(RelocRef, this));
}
-section_iterator WasmObjectFile::getRelocatedSection(DataRefImpl Sec) const {
- llvm_unreachable("not yet implemented");
- SectionRef Ref;
- return section_iterator(Ref);
+relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
+ const WasmSection &Sec = getWasmSection(Ref);
+ DataRefImpl RelocRef;
+ RelocRef.d.a = Ref.d.a;
+ RelocRef.d.b = Sec.Relocations.size();
+ return relocation_iterator(RelocationRef(RelocRef, this));
}
void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
- llvm_unreachable("not yet implemented");
+ Rel.d.b++;
}
-uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Rel) const {
- llvm_unreachable("not yet implemented");
- return 0;
+uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
+ const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
+ return Rel.Offset;
}
symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
return symbol_iterator(Ref);
}
-uint64_t WasmObjectFile::getRelocationType(DataRefImpl Rel) const {
- llvm_unreachable("not yet implemented");
- return 0;
+uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
+ const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
+ return Rel.Type;
}
void WasmObjectFile::getRelocationTypeName(
- DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
- llvm_unreachable("not yet implemented");
+ DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
+ const wasm::WasmRelocation& Rel = getWasmRelocation(Ref);
+ StringRef Res = "Unknown";
+
+#define WASM_RELOC(name, value) \
+ case wasm::name: \
+ Res = #name; \
+ break;
+
+ switch (Rel.Type) {
+#include "llvm/Support/WasmRelocs/WebAssembly.def"
+ }
+
+#undef WASM_RELOC
+
+ Result.append(Res.begin(), Res.end());
}
section_iterator WasmObjectFile::section_begin() const {
bool WasmObjectFile::isRelocatableObject() const { return false; }
-const wasm::WasmSection *
+const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
+ assert(Ref.d.a >= 0 && Ref.d.a < Sections.size());
+ return Sections[Ref.d.a];
+}
+
+const WasmSection &
WasmObjectFile::getWasmSection(const SectionRef &Section) const {
- return &Sections[Section.getRawDataRefImpl().d.a];
+ return getWasmSection(Section.getRawDataRefImpl());
+}
+
+const wasm::WasmRelocation &
+WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
+ return getWasmRelocation(Ref.getRawDataRefImpl());
+}
+
+const wasm::WasmRelocation &
+WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
+ assert(Ref.d.a >= 0 && Ref.d.a < Sections.size());
+ const WasmSection& Sec = Sections[Ref.d.a];
+ assert(Ref.d.b >= 0 && Ref.d.b < Sec.Relocations.size());
+ return Sec.Relocations[Ref.d.b];
}
ELFYAML.cpp
MachOYAML.cpp
ObjectYAML.cpp
+ WasmYAML.cpp
YAML.cpp
)
ObjectFile.FatMachO.reset(new MachOYAML::UniversalBinary());
MappingTraits<MachOYAML::UniversalBinary>::mapping(IO,
*ObjectFile.FatMachO);
+ } else if (IO.mapTag("!WASM")) {
+ ObjectFile.Wasm.reset(new WasmYAML::Object());
+ MappingTraits<WasmYAML::Object>::mapping(IO, *ObjectFile.Wasm);
} else {
Input &In = (Input &)IO;
std::string Tag = In.getCurrentNode()->getRawTag();
--- /dev/null
+//===- 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/Object/Wasm.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/MipsABIFlags.h"
+
+namespace llvm {
+namespace yaml {
+
+void MappingTraits<WasmYAML::FileHeader>::mapping(
+ IO &IO, WasmYAML::FileHeader &FileHdr) {
+ IO.mapRequired("Version", FileHdr.Version);
+}
+
+void MappingTraits<WasmYAML::Object>::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);
+}
+
+static void commonSectionMapping(IO &IO, WasmYAML::Section &Section) {
+ IO.mapRequired("Type", Section.Type);
+ IO.mapOptional("Relocations", Section.Relocations);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapRequired("Name", Section.Name);
+ IO.mapRequired("Payload", Section.Payload);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::TypeSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapOptional("Signatures", Section.Signatures);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::ImportSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapOptional("Imports", Section.Imports);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::FunctionSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapOptional("FunctionTypes", Section.FunctionTypes);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::TableSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapOptional("Tables", Section.Tables);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::MemorySection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapOptional("Memories", Section.Memories);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::GlobalSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapOptional("Globals", Section.Globals);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::ExportSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapOptional("Exports", Section.Exports);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::StartSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapOptional("StartFunction", Section.StartFunction);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::ElemSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapOptional("Segments", Section.Segments);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::CodeSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapRequired("Functions", Section.Functions);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::DataSection &Section) {
+ commonSectionMapping(IO, Section);
+ IO.mapRequired("Segments", Section.Segments);
+}
+
+void MappingTraits<std::unique_ptr<WasmYAML::Section>>::mapping(
+ IO &IO, std::unique_ptr<WasmYAML::Section> &Section) {
+ WasmYAML::SectionType SectionType;
+ if (IO.outputting())
+ SectionType = Section->Type;
+ else
+ IO.mapRequired("Type", SectionType);
+
+ switch (SectionType) {
+ case wasm::WASM_SEC_CUSTOM:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::CustomSection());
+ sectionMapping(IO, *cast<WasmYAML::CustomSection>(Section.get()));
+ break;
+ case wasm::WASM_SEC_TYPE:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::TypeSection());
+ sectionMapping(IO, *cast<WasmYAML::TypeSection>(Section.get()));
+ break;
+ case wasm::WASM_SEC_IMPORT:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::ImportSection());
+ sectionMapping(IO, *cast<WasmYAML::ImportSection>(Section.get()));
+ break;
+ case wasm::WASM_SEC_FUNCTION:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::FunctionSection());
+ sectionMapping(IO, *cast<WasmYAML::FunctionSection>(Section.get()));
+ break;
+ case wasm::WASM_SEC_TABLE:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::TableSection());
+ sectionMapping(IO, *cast<WasmYAML::TableSection>(Section.get()));
+ break;
+ case wasm::WASM_SEC_MEMORY:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::MemorySection());
+ sectionMapping(IO, *cast<WasmYAML::MemorySection>(Section.get()));
+ break;
+ case wasm::WASM_SEC_GLOBAL:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::GlobalSection());
+ sectionMapping(IO, *cast<WasmYAML::GlobalSection>(Section.get()));
+ break;
+ case wasm::WASM_SEC_EXPORT:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::ExportSection());
+ sectionMapping(IO, *cast<WasmYAML::ExportSection>(Section.get()));
+ break;
+ case wasm::WASM_SEC_START:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::StartSection());
+ sectionMapping(IO, *cast<WasmYAML::StartSection>(Section.get()));
+ break;
+ case wasm::WASM_SEC_ELEM:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::ElemSection());
+ sectionMapping(IO, *cast<WasmYAML::ElemSection>(Section.get()));
+ break;
+ case wasm::WASM_SEC_CODE:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::CodeSection());
+ sectionMapping(IO, *cast<WasmYAML::CodeSection>(Section.get()));
+ break;
+ case wasm::WASM_SEC_DATA:
+ if (!IO.outputting())
+ Section.reset(new WasmYAML::DataSection());
+ sectionMapping(IO, *cast<WasmYAML::DataSection>(Section.get()));
+ break;
+ default:
+ llvm_unreachable("Unknown section type");
+ }
+}
+
+void ScalarEnumerationTraits<WasmYAML::SectionType>::enumeration(
+ IO &IO, WasmYAML::SectionType &Type) {
+#define ECase(X) IO.enumCase(Type, #X, wasm::WASM_SEC_##X);
+ ECase(CUSTOM);
+ ECase(TYPE);
+ ECase(IMPORT);
+ ECase(FUNCTION);
+ ECase(TABLE);
+ ECase(MEMORY);
+ ECase(GLOBAL);
+ ECase(EXPORT);
+ ECase(START);
+ ECase(ELEM);
+ ECase(CODE);
+ ECase(DATA);
+#undef ECase
+}
+
+void MappingTraits<WasmYAML::Signature>::mapping(
+ IO &IO, WasmYAML::Signature &Signature) {
+ IO.mapOptional("Index", Signature.Index);
+ IO.mapRequired("ReturnType", Signature.ReturnType);
+ IO.mapRequired("ParamTypes", Signature.ParamTypes);
+}
+
+void MappingTraits<WasmYAML::Table>::mapping(IO &IO, WasmYAML::Table &Table) {
+ IO.mapRequired("ElemType", Table.ElemType);
+ IO.mapRequired("Limits", Table.TableLimits);
+}
+
+void MappingTraits<WasmYAML::Function>::mapping(IO &IO,
+ WasmYAML::Function &Function) {
+ IO.mapRequired("Locals", Function.Locals);
+ IO.mapRequired("Body", Function.Body);
+}
+
+void MappingTraits<WasmYAML::Relocation>::mapping(
+ IO &IO, WasmYAML::Relocation &Relocation) {
+ IO.mapRequired("Type", Relocation.Type);
+ IO.mapRequired("Index", Relocation.Index);
+ IO.mapRequired("Offset", Relocation.Offset);
+ IO.mapRequired("Addend", Relocation.Addend);
+}
+
+void MappingTraits<WasmYAML::LocalDecl>::mapping(
+ IO &IO, WasmYAML::LocalDecl &LocalDecl) {
+ IO.mapRequired("Type", LocalDecl.Type);
+ IO.mapRequired("Count", LocalDecl.Count);
+}
+
+void MappingTraits<WasmYAML::Limits>::mapping(IO &IO,
+ WasmYAML::Limits &Limits) {
+ if (!IO.outputting() || Limits.Flags)
+ IO.mapOptional("Flags", Limits.Flags);
+ IO.mapRequired("Initial", Limits.Initial);
+ if (!IO.outputting() || Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
+ IO.mapOptional("Maximum", Limits.Maximum);
+}
+
+void MappingTraits<WasmYAML::ElemSegment>::mapping(
+ IO &IO, WasmYAML::ElemSegment &Segment) {
+ IO.mapRequired("Offset", Segment.Offset);
+ IO.mapRequired("Functions", Segment.Functions);
+}
+
+void MappingTraits<WasmYAML::Import>::mapping(IO &IO,
+ WasmYAML::Import &Import) {
+ IO.mapRequired("Module", Import.Module);
+ IO.mapRequired("Field", Import.Field);
+ IO.mapRequired("Kind", Import.Kind);
+ if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
+ IO.mapRequired("SigIndex", Import.SigIndex);
+ } else if (Import.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
+ IO.mapRequired("GlobalType", Import.GlobalType);
+ IO.mapRequired("GlobalMutable", Import.GlobalMutable);
+ } else {
+ llvm_unreachable("unhandled import type");
+ }
+}
+
+void MappingTraits<WasmYAML::Export>::mapping(IO &IO,
+ WasmYAML::Export &Export) {
+ IO.mapRequired("Name", Export.Name);
+ IO.mapRequired("Kind", Export.Kind);
+ IO.mapRequired("Index", Export.Index);
+}
+
+void MappingTraits<WasmYAML::Global>::mapping(IO &IO,
+ WasmYAML::Global &Global) {
+ IO.mapRequired("Type", Global.Type);
+ IO.mapRequired("Mutable", Global.Mutable);
+ IO.mapRequired("InitExpr", Global.InitExpr);
+}
+
+void MappingTraits<wasm::WasmInitExpr>::mapping(IO &IO,
+ wasm::WasmInitExpr &Expr) {
+ WasmYAML::Opcode Op = Expr.Opcode;
+ IO.mapRequired("Opcode", Op);
+ Expr.Opcode = Op;
+ switch (Expr.Opcode) {
+ case wasm::WASM_OPCODE_I32_CONST:
+ IO.mapRequired("Value", Expr.Value.Int32);
+ break;
+ case wasm::WASM_OPCODE_I64_CONST:
+ IO.mapRequired("Value", Expr.Value.Int64);
+ break;
+ case wasm::WASM_OPCODE_F32_CONST:
+ IO.mapRequired("Value", Expr.Value.Float32);
+ break;
+ case wasm::WASM_OPCODE_F64_CONST:
+ IO.mapRequired("Value", Expr.Value.Float64);
+ break;
+ }
+}
+
+void MappingTraits<WasmYAML::DataSegment>::mapping(
+ IO &IO, WasmYAML::DataSegment &Segment) {
+ IO.mapRequired("Index", Segment.Index);
+ IO.mapRequired("Offset", Segment.Offset);
+ IO.mapRequired("Content", Segment.Content);
+}
+
+void ScalarEnumerationTraits<WasmYAML::ValueType>::enumeration(
+ IO &IO, WasmYAML::ValueType &Type) {
+#define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
+ ECase(I32);
+ ECase(I64);
+ ECase(F32);
+ ECase(F64);
+ ECase(ANYFUNC);
+ ECase(FUNC);
+ ECase(NORESULT);
+#undef ECase
+}
+
+void ScalarEnumerationTraits<WasmYAML::ExportKind>::enumeration(
+ IO &IO, WasmYAML::ExportKind &Kind) {
+#define ECase(X) IO.enumCase(Kind, #X, wasm::WASM_EXTERNAL_##X);
+ ECase(FUNCTION);
+ ECase(TABLE);
+ ECase(MEMORY);
+ ECase(GLOBAL);
+#undef ECase
+}
+
+void ScalarEnumerationTraits<WasmYAML::Opcode>::enumeration(
+ IO &IO, WasmYAML::Opcode &Code) {
+#define ECase(X) IO.enumCase(Code, #X, wasm::WASM_OPCODE_##X);
+ ECase(END);
+ ECase(I32_CONST);
+ ECase(I64_CONST);
+ ECase(F64_CONST);
+ ECase(F32_CONST);
+ ECase(GET_GLOBAL);
+#undef ECase
+}
+
+void ScalarEnumerationTraits<WasmYAML::TableType>::enumeration(
+ IO &IO, WasmYAML::TableType &Type) {
+#define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
+ ECase(ANYFUNC);
+#undef ECase
+}
+
+void ScalarEnumerationTraits<WasmYAML::RelocType>::enumeration(
+ IO &IO, WasmYAML::RelocType &Type) {
+#define WASM_RELOC(name, value) IO.enumCase(Type, #name, wasm::name);
+#include "llvm/Support/WasmRelocs/WebAssembly.def"
+#undef WASM_RELOC
+}
+
+} // end namespace yaml
+} // end namespace llvm
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: TYPE
+ Signatures:
+ - ReturnType: F32
+ ParamTypes:
+ - I32
+ - ReturnType: NORESULT
+ ParamTypes:
+ - I32
+ - I64
+ - Type: FUNCTION
+ FunctionTypes:
+ - 0
+ - 1
+ - Type: CODE
+ Relocations:
+ - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
+ Index: 0
+ Offset: 0x00000006
+ Addend: 0x00000000
+ - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB
+ Index: 1
+ Offset: 0x00000025
+ Addend: 0x00000000
+ Functions:
+ - Locals:
+ - Type: I32
+ Count: 3
+ Body: 418080808000210020002101200111808080800000210220020F0B
+ - Locals:
+ - Type: I32
+ Count: 1
+ Body: 108180808000210020000F0B
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: TYPE
+# CHECK: Signatures:
+# CHECK: - Index: 0
+# CHECK: ReturnType: F32
+# CHECK: ParamTypes:
+# CHECK: - I32
+# CHECK: - Index: 1
+# CHECK: ReturnType: NORESULT
+# CHECK: ParamTypes:
+# CHECK: - I32
+# CHECK: - I64
+# CHECK: - Type: CODE
+# CHECK: Relocations:
+# CHECK: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
+# CHECK: Index: 0
+# CHECK: Offset: 0x00000006
+# CHECK: Addend: 0x00000000
+# CHECK: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB
+# CHECK: Index: 1
+# CHECK: Offset: 0x00000025
+# CHECK: Addend: 0x00000000
+# CHECK: Functions:
+# CHECK: - Locals:
+# CHECK: - Type: I32
+# CHECK: Count: 3
+# CHECK: Body: 418080808000210020002101200111808080800000210220020F0B
+# CHECK: - Locals:
+# CHECK: - Type: I32
+# CHECK: Count: 1
+# CHECK: Body: 108180808000210020000F0B
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: CUSTOM
+ Name: foo
+ Payload: 03666F6F0401020304
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: CUSTOM
+# CHECK: Name: foo
+# CHECK: Payload: 03666F6F0401020304
+# CHECK: ...
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: MEMORY
+ Memories:
+ - Initial: 0x00000003
+ - Type: DATA
+ Segments:
+ - Index: 0
+ Offset:
+ Opcode: I32_CONST
+ Value: 4
+ Content: '10001000'
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: DATA
+# CHECK: Segments:
+# CHECK: - Index: 0
+# CHECK: Offset:
+# CHECK: Opcode: I32_CONST
+# CHECK: Value: 4
+# CHECK: Content: '10001000'
+# CHECK: ...
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: TABLE
+ Tables:
+ - ElemType: ANYFUNC
+ Limits:
+ Flags: 0x00000001
+ Initial: 0x00000010
+ Maximum: 0x00000011
+ - Type: ELEM
+ Segments:
+ - Offset:
+ Opcode: I32_CONST
+ Value: 3
+ Functions:
+ - 1
+ - Offset:
+ Opcode: I32_CONST
+ Value: 5
+ Functions:
+ - 4
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: ELEM
+# CHECK: Segments:
+# CHECK: - Offset:
+# CHECK: Opcode: I32_CONST
+# CHECK: Value: 3
+# CHECK: Functions:
+# CHECK: - 1
+# CHECK: - Offset:
+# CHECK: Opcode: I32_CONST
+# CHECK: Value: 5
+# CHECK: Functions:
+# CHECK: - 4
+# CHECK: ...
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: EXPORT
+ Exports:
+ - Name: foo
+ Kind: FUNCTION
+ Index: 0
+ - Name: bar
+ Kind: FUNCTION
+ Index: 1
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: EXPORT
+# CHECK: Exports:
+# CHECK: - Name: foo
+# CHECK: Kind: FUNCTION
+# CHECK: Index: 0
+# CHECK: - Name: bar
+# CHECK: Kind: FUNCTION
+# CHECK: Index: 1
+# CHECK: ...
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: FUNCTION
+ FunctionTypes:
+ - 1
+ - 0
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: FUNCTION
+# CHECK: FunctionTypes:
+# CHECK: - 1
+# CHECK: - 0
+# CHECK: ...
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: GLOBAL
+ Globals:
+ - Type: I32
+ Mutable: false
+ InitExpr:
+ Opcode: I64_CONST
+ Value: -5
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: GLOBAL
+# CHECK: Globals:
+# CHECK: - Type: I32
+# CHECK: Mutable: false
+# CHECK: InitExpr:
+# CHECK: Opcode: I64_CONST
+# CHECK: Value: -5
+# CHECK: ...
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: ...
--- /dev/null
+# RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s
+
+--- !WASM
+FileHeader:
+ Version: 0x00000002
+...
+
+# CHECK: Error: 'Invalid data was encountered while parsing the file'
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: TYPE
+ Signatures:
+ - ReturnType: I32
+ ParamTypes:
+ - I32
+ - Type: IMPORT
+ Imports:
+ - Module: foo
+ Field: bar
+ Kind: FUNCTION
+ SigIndex: 0
+ - Module: fiz
+ Field: baz
+ Kind: GLOBAL
+ GlobalType: I32
+ GlobalMutable: false
+ - Type: FUNCTION
+ FunctionTypes:
+ - 0
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: IMPORT
+# CHECK: Imports:
+# CHECK: - Module: foo
+# CHECK: Field: bar
+# CHECK: Kind: FUNCTION
+# CHECK: SigIndex: 0
+# CHECK: - Module: fiz
+# CHECK: Field: baz
+# CHECK: Kind: GLOBAL
+# CHECK: GlobalType: I32
+# CHECK: GlobalMutable: false
+# CHECK: ...
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: MEMORY
+ Memories:
+ - Flags: 0x00000001
+ Initial: 0x00000002
+ Maximum: 0x000000FF
+ - Initial: 0x00000003
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: MEMORY
+# CHECK: Memories:
+# CHECK: - Flags: 0x00000001
+# CHECK: Initial: 0x00000002
+# CHECK: Maximum: 0x000000FF
+# CHECK: - Initial: 0x00000003
+# CHECK: ...
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: START
+ StartFunction: 1
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: START
+# CHECK: StartFunction: 1
+# CHECK: ...
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: TABLE
+ Tables:
+ - ElemType: ANYFUNC
+ Limits:
+ Flags: 0x00000001
+ Initial: 0x00000010
+ Maximum: 0x00000011
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: TABLE
+# CHECK: Tables:
+# CHECK: - ElemType: ANYFUNC
+# CHECK: Limits:
+# CHECK: Flags: 0x00000001
+# CHECK: Initial: 0x00000010
+# CHECK: Maximum: 0x00000011
+# CHECK: ...
--- /dev/null
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+ Version: 0x00000001
+Sections:
+ - Type: TYPE
+ Signatures:
+ - ReturnType: I32
+ ParamTypes:
+ - F32
+ - F32
+ - ReturnType: I64
+ ParamTypes:
+ - F64
+ - F64
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK: Version: 0x00000001
+# CHECK: Sections:
+# CHECK: - Type: TYPE
+# CHECK: Signatures:
+# CHECK: - Index: 0
+# CHECK: ReturnType: I32
+# CHECK: ParamTypes:
+# CHECK: - F32
+# CHECK: - F32
+# CHECK: - Index: 1
+# CHECK: ReturnType: I64
+# CHECK: ParamTypes:
+# CHECK: - F64
+# CHECK: - F64
+# CHECK: ...
# CHECK: 4 EXPORT 0000000e 0000000000000000
# CHECK: 5 ELEM 00000007 0000000000000000
# CHECK: 6 CODE 0000002a 0000000000000000 TEXT
-# CHECK: 7 name 0000002c 0000000000000000
+# CHECK: 7 name 0000003c 0000000000000000
# RUN: llvm-objdump -p %p/Inputs/test.wasm | FileCheck %s -check-prefix CHECK-HEADER
WASM-NEXT: }
WASM-NEXT: Section {
WASM-NEXT: Type: CUSTOM (0x0)
-WASM-NEXT: Size: 44
+WASM-NEXT: Size: 60
WASM-NEXT: Offset: 119
WASM-NEXT: Name: name
WASM-NEXT: }
void printSections() override {
ListScope Group(W, "Sections");
for (const SectionRef &Section : Obj->sections()) {
- const wasm::WasmSection *WasmSec = Obj->getWasmSection(Section);
+ const WasmSection &WasmSec = Obj->getWasmSection(Section);
DictScope SectionD(W, "Section");
- const char *Type = wasmSectionTypeToString(WasmSec->Type);
- W.printHex("Type", Type, WasmSec->Type);
- W.printNumber("Size", (uint64_t)WasmSec->Content.size());
- W.printNumber("Offset", WasmSec->Offset);
- if (WasmSec->Type == wasm::WASM_SEC_CUSTOM) {
- W.printString("Name", WasmSec->Name);
+ const char *Type = wasmSectionTypeToString(WasmSec.Type);
+ W.printHex("Type", Type, WasmSec.Type);
+ W.printNumber("Size", (uint64_t)WasmSec.Content.size());
+ W.printNumber("Offset", WasmSec.Offset);
+ if (WasmSec.Type == wasm::WASM_SEC_CUSTOM) {
+ W.printString("Name", WasmSec.Name);
}
}
}
dwarf2yaml.cpp
elf2yaml.cpp
macho2yaml.cpp
+ wasm2yaml.cpp
Error.cpp
)
return coff2yaml(outs(), cast<COFFObjectFile>(Obj));
if (Obj.isELF())
return elf2yaml(outs(), Obj);
+ if (Obj.isWasm())
+ return wasm2yaml(outs(), cast<WasmObjectFile>(Obj));
return obj2yaml_error::unsupported_obj_file_format;
}
#define LLVM_TOOLS_OBJ2YAML_OBJ2YAML_H
#include "llvm/Object/COFF.h"
+#include "llvm/Object/Wasm.h"
#include "llvm/Support/raw_ostream.h"
#include <system_error>
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);
// Forward decls for dwarf2yaml
namespace llvm {
--- /dev/null
+//===------ 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<WasmYAML::Object *> dump();
+};
+
+ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
+ auto Y = make_unique<WasmYAML::Object>();
+
+ // Dump header
+ Y->Header.Version = Obj.getHeader().Version;
+
+ // Dump sections
+ for (const auto &Sec : Obj.sections()) {
+ const object::WasmSection &WasmSec = Obj.getWasmSection(Sec);
+ std::unique_ptr<WasmYAML::Section> S;
+ switch (WasmSec.Type) {
+ case wasm::WASM_SEC_CUSTOM: {
+ if (WasmSec.Name.startswith("reloc.")) {
+ // Relocations are attached the sections they apply to rather than
+ // being represented as a custom section in the YAML output.
+ continue;
+ }
+ auto CustomSec = make_unique<WasmYAML::CustomSection>();
+ CustomSec->Name = WasmSec.Name;
+ CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
+ S = std::move(CustomSec);
+ break;
+ }
+ case wasm::WASM_SEC_TYPE: {
+ auto TypeSec = make_unique<WasmYAML::TypeSection>();
+ uint32_t Index = 0;
+ for (const auto &FunctionSig : Obj.types()) {
+ WasmYAML::Signature Sig;
+ Sig.Index = Index++;
+ Sig.ReturnType = FunctionSig.ReturnType;
+ for (const auto &ParamType : FunctionSig.ParamTypes)
+ Sig.ParamTypes.push_back(ParamType);
+ TypeSec->Signatures.push_back(Sig);
+ }
+ S = std::move(TypeSec);
+ break;
+ }
+ case wasm::WASM_SEC_IMPORT: {
+ auto ImportSec = make_unique<WasmYAML::ImportSection>();
+ for (auto &Import : Obj.imports()) {
+ WasmYAML::Import Ex;
+ Ex.Module = Import.Module;
+ Ex.Field = Import.Field;
+ Ex.Kind = Import.Kind;
+ if (Ex.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
+ Ex.SigIndex = Import.SigIndex;
+ } else if (Ex.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
+ Ex.GlobalType = Import.GlobalType;
+ Ex.GlobalMutable = Import.GlobalMutable;
+ }
+ ImportSec->Imports.push_back(Ex);
+ }
+ S = std::move(ImportSec);
+ break;
+ }
+ case wasm::WASM_SEC_FUNCTION: {
+ auto FuncSec = make_unique<WasmYAML::FunctionSection>();
+ for (const auto &Func : Obj.functionTypes()) {
+ FuncSec->FunctionTypes.push_back(Func);
+ }
+ S = std::move(FuncSec);
+ break;
+ }
+ case wasm::WASM_SEC_TABLE: {
+ auto TableSec = make_unique<WasmYAML::TableSection>();
+ for (auto &Table : Obj.tables()) {
+ WasmYAML::Table T;
+ T.ElemType = Table.ElemType;
+ T.TableLimits.Flags = Table.Limits.Flags;
+ T.TableLimits.Initial = Table.Limits.Initial;
+ T.TableLimits.Maximum = Table.Limits.Maximum;
+ TableSec->Tables.push_back(T);
+ }
+ S = std::move(TableSec);
+ break;
+ }
+ case wasm::WASM_SEC_MEMORY: {
+ auto MemorySec = make_unique<WasmYAML::MemorySection>();
+ for (auto &Memory : Obj.memories()) {
+ WasmYAML::Limits L;
+ L.Flags = Memory.Flags;
+ L.Initial = Memory.Initial;
+ L.Maximum = Memory.Maximum;
+ MemorySec->Memories.push_back(L);
+ }
+ S = std::move(MemorySec);
+ break;
+ }
+ case wasm::WASM_SEC_GLOBAL: {
+ auto GlobalSec = make_unique<WasmYAML::GlobalSection>();
+ for (auto &Global : Obj.globals()) {
+ WasmYAML::Global G;
+ G.Type = Global.Type;
+ G.Mutable = Global.Mutable;
+ G.InitExpr = Global.InitExpr;
+ GlobalSec->Globals.push_back(G);
+ }
+ S = std::move(GlobalSec);
+ break;
+ }
+ case wasm::WASM_SEC_START: {
+ auto StartSec = make_unique<WasmYAML::StartSection>();
+ StartSec->StartFunction = Obj.startFunction();
+ S = std::move(StartSec);
+ break;
+ }
+ case wasm::WASM_SEC_EXPORT: {
+ auto ExportSec = make_unique<WasmYAML::ExportSection>();
+ for (auto &Export : Obj.exports()) {
+ WasmYAML::Export Ex;
+ Ex.Name = Export.Name;
+ Ex.Kind = Export.Kind;
+ Ex.Index = Export.Index;
+ ExportSec->Exports.push_back(Ex);
+ }
+ S = std::move(ExportSec);
+ break;
+ }
+ case wasm::WASM_SEC_ELEM: {
+ auto ElemSec = make_unique<WasmYAML::ElemSection>();
+ for (auto &Segment : Obj.elements()) {
+ WasmYAML::ElemSegment Seg;
+ Seg.TableIndex = Segment.TableIndex;
+ Seg.Offset = Segment.Offset;
+ for (auto &Func : Segment.Functions) {
+ Seg.Functions.push_back(Func);
+ }
+ ElemSec->Segments.push_back(Seg);
+ }
+ S = std::move(ElemSec);
+ break;
+ }
+ case wasm::WASM_SEC_CODE: {
+ auto CodeSec = make_unique<WasmYAML::CodeSection>();
+ for (auto &Func : Obj.functions()) {
+ WasmYAML::Function Function;
+ for (auto &Local : Func.Locals) {
+ WasmYAML::LocalDecl LocalDecl;
+ LocalDecl.Type = Local.Type;
+ LocalDecl.Count = Local.Count;
+ Function.Locals.push_back(LocalDecl);
+ }
+ Function.Body = yaml::BinaryRef(Func.Body);
+ CodeSec->Functions.push_back(Function);
+ }
+ S = std::move(CodeSec);
+ break;
+ }
+ case wasm::WASM_SEC_DATA: {
+ auto DataSec = make_unique<WasmYAML::DataSection>();
+ for (auto &Segment : Obj.dataSegments()) {
+ WasmYAML::DataSegment Seg;
+ Seg.Index = Segment.Index;
+ Seg.Offset = Segment.Offset;
+ Seg.Content = yaml::BinaryRef(Segment.Content);
+ DataSec->Segments.push_back(Seg);
+ }
+ S = std::move(DataSec);
+ break;
+ }
+ default:
+ llvm_unreachable("Unknown section type");
+ break;
+ }
+ for (const wasm::WasmRelocation &Reloc: WasmSec.Relocations) {
+ WasmYAML::Relocation R;
+ R.Type = Reloc.Type;
+ R.Index = Reloc.Index;
+ R.Offset = Reloc.Offset;
+ R.Addend = Reloc.Addend;
+ S->Relocations.push_back(R);
+ }
+ Y->Sections.push_back(std::move(S));
+ }
+
+ return Y.release();
+}
+
+} // namespace
+
+std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) {
+ WasmDumper Dumper(Obj);
+ ErrorOr<WasmYAML::Object *> YAMLOrErr = Dumper.dump();
+ if (std::error_code EC = YAMLOrErr.getError())
+ return EC;
+
+ std::unique_ptr<WasmYAML::Object> YAML(YAMLOrErr.get());
+ yaml::Output Yout(Out);
+ Yout << *YAML;
+
+ return std::error_code();
+}
yaml2coff.cpp
yaml2elf.cpp
yaml2macho.cpp
+ yaml2wasm.cpp
)
return yaml2coff(*Doc.Coff, Out);
if (Doc.MachO || Doc.FatMachO)
return yaml2macho(Doc, Out);
+ if (Doc.Wasm)
+ return yaml2wasm(*Doc.Wasm, Out);
errs() << "yaml2obj: Unknown document type!\n";
return 1;
}
struct Object;
}
+namespace WasmYAML {
+struct Object;
+}
+
namespace yaml {
class Input;
struct YamlObjectFile;
int yaml2coff(llvm::COFFYAML::Object &Doc, llvm::raw_ostream &Out);
int yaml2elf(llvm::ELFYAML::Object &Doc, llvm::raw_ostream &Out);
int yaml2macho(llvm::yaml::YamlObjectFile &Doc, llvm::raw_ostream &Out);
+int yaml2wasm(llvm::WasmYAML::Object &Doc, llvm::raw_ostream &Out);
#endif
--- /dev/null
+//===- yaml2wasm - Convert YAML to a Wasm object file --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief The Wasm component of yaml2obj.
+///
+//===----------------------------------------------------------------------===//
+//
+#include "yaml2obj.h"
+#include "llvm/Object/Wasm.h"
+#include "llvm/ObjectYAML/ObjectYAML.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/LEB128.h"
+
+using namespace llvm;
+
+/// This parses a yaml stream that represents a Wasm object file.
+/// See docs/yaml2obj for the yaml scheema.
+class WasmWriter {
+public:
+ WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
+ int writeWasm(raw_ostream &OS);
+ int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
+ int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
+
+private:
+ WasmYAML::Object &Obj;
+};
+
+static int writeUint64(raw_ostream &OS, uint64_t Value) {
+ char Data[sizeof(Value)];
+ support::endian::write64le(Data, Value);
+ OS.write(Data, sizeof(Data));
+ return 0;
+}
+
+static int writeUint32(raw_ostream &OS, uint32_t Value) {
+ char Data[sizeof(Value)];
+ support::endian::write32le(Data, Value);
+ OS.write(Data, sizeof(Data));
+ return 0;
+}
+
+static int writeUint8(raw_ostream &OS, uint8_t Value) {
+ char Data[sizeof(Value)];
+ memcpy(Data, &Value, sizeof(Data));
+ OS.write(Data, sizeof(Data));
+ return 0;
+}
+
+static int writeStringRef(StringRef &Str, raw_ostream &OS) {
+ encodeULEB128(Str.size(), OS);
+ OS << Str;
+ return 0;
+}
+
+static int writeLimits(WasmYAML::Limits Lim, raw_ostream &OS) {
+ encodeULEB128(Lim.Flags, OS);
+ encodeULEB128(Lim.Initial, OS);
+ if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
+ encodeULEB128(Lim.Maximum, OS);
+ return 0;
+}
+
+static int writeInitExpr(wasm::WasmInitExpr InitExpr, raw_ostream &OS) {
+ writeUint8(OS, InitExpr.Opcode);
+ switch (InitExpr.Opcode) {
+ case wasm::WASM_OPCODE_I32_CONST:
+ encodeSLEB128(InitExpr.Value.Int32, OS);
+ break;
+ case wasm::WASM_OPCODE_I64_CONST:
+ encodeSLEB128(InitExpr.Value.Int64, OS);
+ break;
+ case wasm::WASM_OPCODE_F32_CONST:
+ writeUint32(OS, InitExpr.Value.Float32);
+ break;
+ case wasm::WASM_OPCODE_F64_CONST:
+ writeUint64(OS, InitExpr.Value.Float64);
+ break;
+ case wasm::WASM_OPCODE_GET_GLOBAL:
+ encodeULEB128(InitExpr.Value.Global, OS);
+ break;
+ default:
+ errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode;
+ return 1;
+ }
+ writeUint8(OS, wasm::WASM_OPCODE_END);
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::CustomSection &Section) {
+ // writeStringRef(Section.Name, OS);
+ // encodeULEB128(Section.Payload.binary_size(), OS);
+ Section.Payload.writeAsBinary(OS);
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::TypeSection &Section) {
+ encodeULEB128(Section.Signatures.size(), OS);
+ for (auto &Sig : Section.Signatures) {
+ encodeSLEB128(Sig.Form, OS);
+ encodeULEB128(Sig.ParamTypes.size(), OS);
+ for (auto ParamType : Sig.ParamTypes)
+ encodeSLEB128(ParamType, OS);
+ if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
+ encodeSLEB128(0, OS);
+ } else {
+ encodeULEB128(1, OS);
+ encodeSLEB128(Sig.ReturnType, OS);
+ }
+ }
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::ImportSection &Section) {
+ encodeULEB128(Section.Imports.size(), OS);
+ for (auto &Import : Section.Imports) {
+ writeStringRef(Import.Module, OS);
+ writeStringRef(Import.Field, OS);
+ encodeULEB128(Import.Kind, OS);
+ switch (Import.Kind) {
+ case wasm::WASM_EXTERNAL_FUNCTION:
+ encodeULEB128(Import.SigIndex, OS);
+ break;
+ case wasm::WASM_EXTERNAL_GLOBAL:
+ encodeSLEB128(Import.GlobalType, OS);
+ writeUint8(OS, Import.GlobalMutable);
+ break;
+ default:
+ errs() << "Unknown import type: " << Import.Kind;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::FunctionSection &Section) {
+ encodeULEB128(Section.FunctionTypes.size(), OS);
+ for (uint32_t FuncType : Section.FunctionTypes) {
+ encodeULEB128(FuncType, OS);
+ }
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::ExportSection &Section) {
+ encodeULEB128(Section.Exports.size(), OS);
+ for (auto &Export : Section.Exports) {
+ writeStringRef(Export.Name, OS);
+ encodeULEB128(Export.Kind, OS);
+ encodeULEB128(Export.Index, OS);
+ }
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::StartSection &Section) {
+ encodeULEB128(Section.StartFunction, OS);
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::TableSection &Section) {
+ encodeULEB128(Section.Tables.size(), OS);
+ for (auto &Table : Section.Tables) {
+ encodeSLEB128(Table.ElemType, OS);
+ writeLimits(Table.TableLimits, OS);
+ }
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::MemorySection &Section) {
+ encodeULEB128(Section.Memories.size(), OS);
+ for (auto &Mem : Section.Memories) {
+ writeLimits(Mem, OS);
+ }
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::GlobalSection &Section) {
+ encodeULEB128(Section.Globals.size(), OS);
+ for (auto &Global : Section.Globals) {
+ encodeSLEB128(Global.Type, OS);
+ writeUint8(OS, Global.Mutable);
+ writeInitExpr(Global.InitExpr, OS);
+ }
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::ElemSection &Section) {
+ encodeULEB128(Section.Segments.size(), OS);
+ for (auto &Segment : Section.Segments) {
+ encodeULEB128(Segment.TableIndex, OS);
+ writeInitExpr(Segment.Offset, OS);
+
+ encodeULEB128(Segment.Functions.size(), OS);
+ for (auto &Function : Segment.Functions) {
+ encodeULEB128(Function, OS);
+ }
+ }
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::CodeSection &Section) {
+ encodeULEB128(Section.Functions.size(), OS);
+ for (auto &Func : Section.Functions) {
+ std::string OutString;
+ raw_string_ostream StringStream(OutString);
+
+ encodeULEB128(Func.Locals.size(), StringStream);
+ for (auto &LocalDecl : Func.Locals) {
+ encodeULEB128(LocalDecl.Count, StringStream);
+ encodeSLEB128(LocalDecl.Type, StringStream);
+ }
+
+ Func.Body.writeAsBinary(StringStream);
+
+ // Write the section size followed by the content
+ StringStream.flush();
+ encodeULEB128(OutString.size(), OS);
+ OS << OutString;
+ }
+ return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+ WasmYAML::DataSection &Section) {
+ encodeULEB128(Section.Segments.size(), OS);
+ for (auto &Segment : Section.Segments) {
+ encodeULEB128(Segment.Index, OS);
+ writeInitExpr(Segment.Offset, OS);
+ encodeULEB128(Segment.Content.binary_size(), OS);
+ Segment.Content.writeAsBinary(OS);
+ }
+ return 0;
+}
+
+int WasmWriter::writeRelocSection(raw_ostream &OS,
+ WasmYAML::Section &Sec) {
+ StringRef Name;
+ switch (Sec.Type) {
+ case wasm::WASM_SEC_CODE:
+ Name = "reloc.CODE";
+ break;
+ case wasm::WASM_SEC_DATA:
+ Name = "reloc.DATA";
+ break;
+ default:
+ llvm_unreachable("not yet implemented");
+ return 1;
+ }
+
+ writeStringRef(Name, OS);
+ encodeULEB128(Sec.Type, OS);
+ encodeULEB128(Sec.Relocations.size(), OS);
+
+ for (auto Reloc: Sec.Relocations) {
+ encodeULEB128(Reloc.Type, OS);
+ encodeULEB128(Reloc.Offset, OS);
+ encodeULEB128(Reloc.Index, OS);
+ switch (Reloc.Type) {
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ encodeULEB128(Reloc.Addend, OS);
+ }
+ }
+ return 0;
+}
+
+
+int WasmWriter::writeWasm(raw_ostream &OS) {
+ // Write headers
+ OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
+ writeUint32(OS, Obj.Header.Version);
+
+ // Write each section
+ for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
+ encodeULEB128(Sec->Type, OS);
+
+ std::string OutString;
+ raw_string_ostream StringStream(OutString);
+ if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
+ if (auto Err = writeSectionContent(StringStream, *S))
+ return Err;
+ } else {
+ errs() << "Unknown section type: " << Sec->Type << "\n";
+ return 1;
+ }
+ StringStream.flush();
+
+ // Write the section size followed by the content
+ encodeULEB128(OutString.size(), OS);
+ OS << OutString;
+ }
+
+ // write reloc sections for any section that have relocations
+ for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
+ if (Sec->Relocations.empty())
+ continue;
+
+ encodeULEB128(wasm::WASM_SEC_CUSTOM, OS);
+ std::string OutString;
+ raw_string_ostream StringStream(OutString);
+ writeRelocSection(StringStream, *Sec);
+ StringStream.flush();
+
+ encodeULEB128(OutString.size(), OS);
+ OS << OutString;
+ }
+
+ return 0;
+}
+
+int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
+ WasmWriter Writer(Doc);
+
+ return Writer.writeWasm(Out);
+}