diff options
Diffstat (limited to 'contrib/llvm/lib/Object/WasmObjectFile.cpp')
| -rw-r--r-- | contrib/llvm/lib/Object/WasmObjectFile.cpp | 723 | 
1 files changed, 646 insertions, 77 deletions
diff --git a/contrib/llvm/lib/Object/WasmObjectFile.cpp b/contrib/llvm/lib/Object/WasmObjectFile.cpp index 2b61a8a034f6..058686e4db9e 100644 --- a/contrib/llvm/lib/Object/WasmObjectFile.cpp +++ b/contrib/llvm/lib/Object/WasmObjectFile.cpp @@ -1,4 +1,4 @@ -//===- WasmObjectFile.cpp - Wasm object file implementation -----*- C++ -*-===// +//===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//  //  //                     The LLVM Compiler Infrastructure  // @@ -7,12 +7,29 @@  //  //===----------------------------------------------------------------------===// +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/Error.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h"  #include "llvm/Object/Wasm.h"  #include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/LEB128.h" +#include "llvm/Support/Wasm.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <cstring> +#include <system_error> -namespace llvm { -namespace object { +using namespace llvm; +using namespace object;  Expected<std::unique_ptr<WasmObjectFile>>  ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { @@ -24,34 +41,146 @@ ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {    return std::move(ObjectFile);  } -namespace { +#define VARINT7_MAX ((1<<7)-1) +#define VARINT7_MIN (-(1<<7)) +#define VARUINT7_MAX (1<<7) +#define VARUINT1_MAX (1) -uint32_t readUint32(const uint8_t *&Ptr) { +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;  } -uint64_t readULEB128(const uint8_t *&Ptr) { +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);    Ptr += Count;    return Result;  } -StringRef readString(const uint8_t *&Ptr) { +static StringRef readString(const uint8_t *&Ptr) {    uint32_t StringLen = readULEB128(Ptr);    StringRef Return = StringRef(reinterpret_cast<const char *>(Ptr), StringLen);    Ptr += StringLen;    return Return;  } -Error readSection(wasm::WasmSection &Section, const uint8_t *&Ptr, -                  const uint8_t *Start) { +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); +  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); +  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 = readULEB128(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 wasm::WasmTable readTable(const uint8_t *&Ptr) { +  wasm::WasmTable Table; +  Table.ElemType = readVarint7(Ptr); +  Table.Limits = readLimits(Ptr); +  return Table; +} + +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); @@ -59,7 +188,6 @@ Error readSection(wasm::WasmSection &Section, const uint8_t *&Ptr,    Ptr += Size;    return Error::success();  } -}  WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)      : ObjectFile(Binary::ID_Wasm, Buffer) { @@ -79,21 +207,402 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)    }    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_USER) { -      if ((Err = parseUserSection(Sec, Sec.Content.data(), Sec.Content.size()))) -        return; -    } +    if ((Err = parseSection(Sec))) +      return; +      Sections.push_back(Sec);    }  } -Error WasmObjectFile::parseUserSection(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.empty()) +          Symbols.emplace_back(Name, +                               WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME, +                               Sections.size(), Index); +      } +      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: +    case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: +      break; +    case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: +    case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: +    case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: +      Reloc.Addend = readVarint32(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); +  for (uint32_t i = 0; i < Count; i++) { +    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, +                           Sections.size(), i); +      break; +    case wasm::WASM_EXTERNAL_GLOBAL: +      Im.Global.Type = readVarint7(Ptr); +      Im.Global.Mutable = readVaruint1(Ptr); +      Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT, +                           Sections.size(), i); +      break; +    case wasm::WASM_EXTERNAL_MEMORY: +      Im.Memory = readLimits(Ptr); +      break; +    case wasm::WASM_EXTERNAL_TABLE: +      Im.Table = readTable(Ptr); +      if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) { +        return make_error<GenericBinaryError>("Invalid table element type", +                                              object_error::parse_failed); +      } +      break; +    default: +      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--) { +    Tables.push_back(readTable(Ptr)); +    if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) { +      return make_error<GenericBinaryError>("Invalid table element type", +                                            object_error::parse_failed); +    } +  } +  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); +    if (Error Err = readInitExpr(Global.InitExpr, Ptr)) +      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); +  for (uint32_t i = 0; i < Count; i++) { +    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, +                           Sections.size(), i); +      break; +    case wasm::WASM_EXTERNAL_GLOBAL: +      Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT, +                           Sections.size(), i); +      break; +    case wasm::WASM_EXTERNAL_MEMORY: +    case wasm::WASM_EXTERNAL_TABLE: +      break; +    default: +      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();  } @@ -105,42 +614,65 @@ const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {    return Header;  } -void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { -  llvm_unreachable("not yet implemented"); -} - -std::error_code WasmObjectFile::printSymbolName(raw_ostream &OS, -                                                DataRefImpl Symb) const { -  llvm_unreachable("not yet implemented"); -  return object_error::invalid_symbol_index; -} +void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }  uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { -  llvm_unreachable("not yet implemented"); -  return 0; +  uint32_t Result = SymbolRef::SF_None; +  const WasmSymbol &Sym = getWasmSymbol(Symb); + +  switch (Sym.Type) { +  case WasmSymbol::SymbolType::FUNCTION_IMPORT: +    Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable; +    break; +  case WasmSymbol::SymbolType::FUNCTION_EXPORT: +    Result |= SymbolRef::SF_Global | SymbolRef::SF_Executable; +    break; +  case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: +    Result |= SymbolRef::SF_Executable; +    break; +  case WasmSymbol::SymbolType::GLOBAL_IMPORT: +    Result |= SymbolRef::SF_Undefined; +    break; +  case WasmSymbol::SymbolType::GLOBAL_EXPORT: +    Result |= SymbolRef::SF_Global; +    break; +  } + +  return Result;  }  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(const DataRefImpl &Symb) const { +  return Symbols[Symb.d.a]; +} + +const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const { +  return getWasmSymbol(Symb.getRawDataRefImpl());  }  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 getSymbolValue(Symb);  }  uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { -  llvm_unreachable("not yet implemented"); -  return 0; +  const WasmSymbol &Sym = getWasmSymbol(Symb); +  return Sym.ElementIndex;  }  uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { @@ -155,21 +687,34 @@ uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {  Expected<SymbolRef::Type>  WasmObjectFile::getSymbolType(DataRefImpl Symb) const { -  llvm_unreachable("not yet implemented"); -  return errorCodeToError(object_error::invalid_symbol_index); +  const WasmSymbol &Sym = getWasmSymbol(Symb); + +  switch (Sym.Type) { +  case WasmSymbol::SymbolType::FUNCTION_IMPORT: +  case WasmSymbol::SymbolType::FUNCTION_EXPORT: +  case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: +    return SymbolRef::ST_Function; +  case WasmSymbol::SymbolType::GLOBAL_IMPORT: +  case WasmSymbol::SymbolType::GLOBAL_EXPORT: +    return SymbolRef::ST_Data; +  } + +  llvm_unreachable("Unknown WasmSymbol::SymbolType"); +  return SymbolRef::ST_Other;  }  Expected<section_iterator>  WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { -  llvm_unreachable("not yet implemented"); -  return errorCodeToError(object_error::invalid_symbol_index); +  DataRefImpl Ref; +  Ref.d.a = getWasmSymbol(Symb).Section; +  return section_iterator(SectionRef(Ref, this));  }  void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }  std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,                                                 StringRef &Res) const { -  const wasm::WasmSection &S = Sections[Sec.d.a]; +  const WasmSection &S = Sections[Sec.d.a];  #define ECase(X)                                                               \    case wasm::WASM_SEC_##X:                                                     \      Res = #X;                                                                  \ @@ -186,7 +731,7 @@ std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,      ECase(ELEM);      ECase(CODE);      ECase(DATA); -  case wasm::WASM_SEC_USER: +  case wasm::WASM_SEC_CUSTOM:      Res = S.Name;      break;    default: @@ -199,13 +744,13 @@ std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,  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()), @@ -222,13 +767,11 @@ bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {  }  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; } @@ -237,31 +780,28 @@ bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }  bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } -relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Sec) const { -  llvm_unreachable("not yet implemented"); -  RelocationRef Rel; -  return relocation_iterator(Rel); -} - -relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Sec) const { -  llvm_unreachable("not yet implemented"); -  RelocationRef Rel; -  return relocation_iterator(Rel); +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 { @@ -270,14 +810,28 @@ 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 { @@ -304,10 +858,25 @@ SubtargetFeatures WasmObjectFile::getFeatures() const {  bool WasmObjectFile::isRelocatableObject() const { return false; } -const wasm::WasmSection * +const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { +  assert(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());  } -} // end namespace object -} // end namespace llvm +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 < Sections.size()); +  const WasmSection& Sec = Sections[Ref.d.a]; +  assert(Ref.d.b < Sec.Relocations.size()); +  return Sec.Relocations[Ref.d.b]; +}  | 
