brintos

brintos / llvm-project-archived public Read only

0
0
Text · 81.0 KiB · ee7a306 Raw
2280 lines · cpp
1//===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/ArrayRef.h"10#include "llvm/ADT/DenseSet.h"11#include "llvm/ADT/SmallSet.h"12#include "llvm/ADT/StringRef.h"13#include "llvm/ADT/StringSet.h"14#include "llvm/ADT/StringSwitch.h"15#include "llvm/BinaryFormat/Wasm.h"16#include "llvm/Object/Binary.h"17#include "llvm/Object/Error.h"18#include "llvm/Object/ObjectFile.h"19#include "llvm/Object/SymbolicFile.h"20#include "llvm/Object/Wasm.h"21#include "llvm/Support/Endian.h"22#include "llvm/Support/Error.h"23#include "llvm/Support/ErrorHandling.h"24#include "llvm/Support/LEB128.h"25#include "llvm/Support/ScopedPrinter.h"26#include "llvm/TargetParser/SubtargetFeature.h"27#include "llvm/TargetParser/Triple.h"28#include <cassert>29#include <cstdint>30#include <cstring>31 32#define DEBUG_TYPE "wasm-object"33 34using namespace llvm;35using namespace object;36 37void WasmSymbol::print(raw_ostream &Out) const {38  Out << "Name=" << Info.Name39      << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"40      << Twine::utohexstr(Info.Flags) << " [";41  switch (getBinding()) {42    case wasm::WASM_SYMBOL_BINDING_GLOBAL: Out << "global"; break;43    case wasm::WASM_SYMBOL_BINDING_LOCAL: Out << "local"; break;44    case wasm::WASM_SYMBOL_BINDING_WEAK: Out << "weak"; break;45  }46  if (isHidden()) {47    Out << ", hidden";48  } else {49    Out << ", default";50  }51  Out << "]";52  if (!isTypeData()) {53    Out << ", ElemIndex=" << Info.ElementIndex;54  } else if (isDefined()) {55    Out << ", Segment=" << Info.DataRef.Segment;56    Out << ", Offset=" << Info.DataRef.Offset;57    Out << ", Size=" << Info.DataRef.Size;58  }59}60 61#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)62LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }63#endif64 65Expected<std::unique_ptr<WasmObjectFile>>66ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {67  Error Err = Error::success();68  auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);69  if (Err)70    return std::move(Err);71 72  return std::move(ObjectFile);73}74 75#define VARINT7_MAX ((1 << 7) - 1)76#define VARINT7_MIN (-(1 << 7))77#define VARUINT7_MAX (1 << 7)78#define VARUINT1_MAX (1)79 80static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {81  if (Ctx.Ptr == Ctx.End)82    report_fatal_error("EOF while reading uint8");83  return *Ctx.Ptr++;84}85 86static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {87  if (Ctx.Ptr + 4 > Ctx.End)88    report_fatal_error("EOF while reading uint32");89  uint32_t Result = support::endian::read32le(Ctx.Ptr);90  Ctx.Ptr += 4;91  return Result;92}93 94static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {95  if (Ctx.Ptr + 4 > Ctx.End)96    report_fatal_error("EOF while reading float64");97  int32_t Result = 0;98  memcpy(&Result, Ctx.Ptr, sizeof(Result));99  Ctx.Ptr += sizeof(Result);100  return Result;101}102 103static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {104  if (Ctx.Ptr + 8 > Ctx.End)105    report_fatal_error("EOF while reading float64");106  int64_t Result = 0;107  memcpy(&Result, Ctx.Ptr, sizeof(Result));108  Ctx.Ptr += sizeof(Result);109  return Result;110}111 112static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {113  unsigned Count;114  const char *Error = nullptr;115  uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);116  if (Error)117    report_fatal_error(Error);118  Ctx.Ptr += Count;119  return Result;120}121 122static StringRef readString(WasmObjectFile::ReadContext &Ctx) {123  uint32_t StringLen = readULEB128(Ctx);124  if (Ctx.Ptr + StringLen > Ctx.End)125    report_fatal_error("EOF while reading string");126  StringRef Return =127      StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);128  Ctx.Ptr += StringLen;129  return Return;130}131 132static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {133  unsigned Count;134  const char *Error = nullptr;135  uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);136  if (Error)137    report_fatal_error(Error);138  Ctx.Ptr += Count;139  return Result;140}141 142static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {143  int64_t Result = readLEB128(Ctx);144  if (Result > VARUINT1_MAX || Result < 0)145    report_fatal_error("LEB is outside Varuint1 range");146  return Result;147}148 149static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {150  int64_t Result = readLEB128(Ctx);151  if (Result > INT32_MAX || Result < INT32_MIN)152    report_fatal_error("LEB is outside Varint32 range");153  return Result;154}155 156static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {157  uint64_t Result = readULEB128(Ctx);158  if (Result > UINT32_MAX)159    report_fatal_error("LEB is outside Varuint32 range");160  return Result;161}162 163static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {164  return readLEB128(Ctx);165}166 167static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {168  return readULEB128(Ctx);169}170 171static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {172  return readUint8(Ctx);173}174 175static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx,176                                  uint32_t Code) {177  // only directly encoded FUNCREF/EXTERNREF/EXNREF are supported178  // (not ref null func, ref null extern, or ref null exn)179  switch (Code) {180  case wasm::WASM_TYPE_I32:181  case wasm::WASM_TYPE_I64:182  case wasm::WASM_TYPE_F32:183  case wasm::WASM_TYPE_F64:184  case wasm::WASM_TYPE_V128:185  case wasm::WASM_TYPE_FUNCREF:186  case wasm::WASM_TYPE_EXTERNREF:187  case wasm::WASM_TYPE_EXNREF:188    return wasm::ValType(Code);189  }190  if (Code == wasm::WASM_TYPE_NULLABLE || Code == wasm::WASM_TYPE_NONNULLABLE) {191    /* Discard HeapType */ readVarint64(Ctx);192  }193  return wasm::ValType(wasm::ValType::OTHERREF);194}195 196static Error readInitExpr(wasm::WasmInitExpr &Expr,197                          WasmObjectFile::ReadContext &Ctx) {198  auto Start = Ctx.Ptr;199 200  Expr.Extended = false;201  Expr.Inst.Opcode = readOpcode(Ctx);202  switch (Expr.Inst.Opcode) {203  case wasm::WASM_OPCODE_I32_CONST:204    Expr.Inst.Value.Int32 = readVarint32(Ctx);205    break;206  case wasm::WASM_OPCODE_I64_CONST:207    Expr.Inst.Value.Int64 = readVarint64(Ctx);208    break;209  case wasm::WASM_OPCODE_F32_CONST:210    Expr.Inst.Value.Float32 = readFloat32(Ctx);211    break;212  case wasm::WASM_OPCODE_F64_CONST:213    Expr.Inst.Value.Float64 = readFloat64(Ctx);214    break;215  case wasm::WASM_OPCODE_GLOBAL_GET:216    Expr.Inst.Value.Global = readULEB128(Ctx);217    break;218  case wasm::WASM_OPCODE_REF_NULL: {219    /* Discard type */ parseValType(Ctx, readVaruint32(Ctx));220    break;221  }222  default:223    Expr.Extended = true;224  }225 226  if (!Expr.Extended) {227    uint8_t EndOpcode = readOpcode(Ctx);228    if (EndOpcode != wasm::WASM_OPCODE_END)229      Expr.Extended = true;230  }231 232  if (Expr.Extended) {233    Ctx.Ptr = Start;234    while (true) {235      uint8_t Opcode = readOpcode(Ctx);236      switch (Opcode) {237      case wasm::WASM_OPCODE_I32_CONST:238      case wasm::WASM_OPCODE_GLOBAL_GET:239      case wasm::WASM_OPCODE_REF_NULL:240      case wasm::WASM_OPCODE_REF_FUNC:241      case wasm::WASM_OPCODE_I64_CONST:242        readULEB128(Ctx);243        break;244      case wasm::WASM_OPCODE_F32_CONST:245        readFloat32(Ctx);246        break;247      case wasm::WASM_OPCODE_F64_CONST:248        readFloat64(Ctx);249        break;250      case wasm::WASM_OPCODE_I32_ADD:251      case wasm::WASM_OPCODE_I32_SUB:252      case wasm::WASM_OPCODE_I32_MUL:253      case wasm::WASM_OPCODE_I64_ADD:254      case wasm::WASM_OPCODE_I64_SUB:255      case wasm::WASM_OPCODE_I64_MUL:256        break;257      case wasm::WASM_OPCODE_GC_PREFIX:258        break;259      // The GC opcodes are in a separate (prefixed space). This flat switch260      // structure works as long as there is no overlap between the GC and261      // general opcodes used in init exprs.262      case wasm::WASM_OPCODE_STRUCT_NEW:263      case wasm::WASM_OPCODE_STRUCT_NEW_DEFAULT:264      case wasm::WASM_OPCODE_ARRAY_NEW:265      case wasm::WASM_OPCODE_ARRAY_NEW_DEFAULT:266        readULEB128(Ctx); // heap type index267        break;268      case wasm::WASM_OPCODE_ARRAY_NEW_FIXED:269        readULEB128(Ctx); // heap type index270        readULEB128(Ctx); // array size271        break;272      case wasm::WASM_OPCODE_REF_I31:273        break;274      case wasm::WASM_OPCODE_END:275        Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);276        return Error::success();277      default:278        return make_error<GenericBinaryError>(279            Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)),280            object_error::parse_failed);281      }282    }283  }284 285  return Error::success();286}287 288static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {289  wasm::WasmLimits Result;290  Result.Flags = readVaruint32(Ctx);291  Result.Minimum = readVaruint64(Ctx);292  if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)293    Result.Maximum = readVaruint64(Ctx);294  if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_PAGE_SIZE) {295    uint32_t PageSizeLog2 = readVaruint32(Ctx);296    if (PageSizeLog2 >= 32)297      report_fatal_error("log2(wasm page size) too large");298    Result.PageSize = 1 << PageSizeLog2;299  }300  return Result;301}302 303static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {304  wasm::WasmTableType TableType;305  auto ElemType = parseValType(Ctx, readVaruint32(Ctx));306  TableType.ElemType = ElemType;307  TableType.Limits = readLimits(Ctx);308  return TableType;309}310 311static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,312                         WasmSectionOrderChecker &Checker) {313  Section.Type = readUint8(Ctx);314  LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");315  // When reading the section's size, store the size of the LEB used to encode316  // it. This allows objcopy/strip to reproduce the binary identically.317  const uint8_t *PreSizePtr = Ctx.Ptr;318  uint32_t Size = readVaruint32(Ctx);319  Section.HeaderSecSizeEncodingLen = Ctx.Ptr - PreSizePtr;320  Section.Offset = Ctx.Ptr - Ctx.Start;321  if (Size == 0)322    return make_error<StringError>("zero length section",323                                   object_error::parse_failed);324  if (Ctx.Ptr + Size > Ctx.End)325    return make_error<StringError>("section too large",326                                   object_error::parse_failed);327  if (Section.Type == wasm::WASM_SEC_CUSTOM) {328    WasmObjectFile::ReadContext SectionCtx;329    SectionCtx.Start = Ctx.Ptr;330    SectionCtx.Ptr = Ctx.Ptr;331    SectionCtx.End = Ctx.Ptr + Size;332 333    Section.Name = readString(SectionCtx);334 335    uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;336    Ctx.Ptr += SectionNameSize;337    Size -= SectionNameSize;338  }339 340  if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {341    return make_error<StringError>("out of order section type: " +342                                       llvm::to_string(Section.Type),343                                   object_error::parse_failed);344  }345 346  Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);347  Ctx.Ptr += Size;348  return Error::success();349}350 351WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)352    : ObjectFile(Binary::ID_Wasm, Buffer) {353  ErrorAsOutParameter ErrAsOutParam(Err);354  Header.Magic = getData().substr(0, 4);355  if (Header.Magic != StringRef("\0asm", 4)) {356    Err = make_error<StringError>("invalid magic number",357                                  object_error::parse_failed);358    return;359  }360 361  ReadContext Ctx;362  Ctx.Start = getData().bytes_begin();363  Ctx.Ptr = Ctx.Start + 4;364  Ctx.End = Ctx.Start + getData().size();365 366  if (Ctx.Ptr + 4 > Ctx.End) {367    Err = make_error<StringError>("missing version number",368                                  object_error::parse_failed);369    return;370  }371 372  Header.Version = readUint32(Ctx);373  if (Header.Version != wasm::WasmVersion) {374    Err = make_error<StringError>("invalid version number: " +375                                      Twine(Header.Version),376                                  object_error::parse_failed);377    return;378  }379 380  WasmSectionOrderChecker Checker;381  while (Ctx.Ptr < Ctx.End) {382    WasmSection Sec;383    if ((Err = readSection(Sec, Ctx, Checker)))384      return;385    if ((Err = parseSection(Sec)))386      return;387 388    Sections.push_back(Sec);389  }390}391 392Error WasmObjectFile::parseSection(WasmSection &Sec) {393  ReadContext Ctx;394  Ctx.Start = Sec.Content.data();395  Ctx.End = Ctx.Start + Sec.Content.size();396  Ctx.Ptr = Ctx.Start;397  switch (Sec.Type) {398  case wasm::WASM_SEC_CUSTOM:399    return parseCustomSection(Sec, Ctx);400  case wasm::WASM_SEC_TYPE:401    return parseTypeSection(Ctx);402  case wasm::WASM_SEC_IMPORT:403    return parseImportSection(Ctx);404  case wasm::WASM_SEC_FUNCTION:405    return parseFunctionSection(Ctx);406  case wasm::WASM_SEC_TABLE:407    return parseTableSection(Ctx);408  case wasm::WASM_SEC_MEMORY:409    return parseMemorySection(Ctx);410  case wasm::WASM_SEC_TAG:411    return parseTagSection(Ctx);412  case wasm::WASM_SEC_GLOBAL:413    return parseGlobalSection(Ctx);414  case wasm::WASM_SEC_EXPORT:415    return parseExportSection(Ctx);416  case wasm::WASM_SEC_START:417    return parseStartSection(Ctx);418  case wasm::WASM_SEC_ELEM:419    return parseElemSection(Ctx);420  case wasm::WASM_SEC_CODE:421    return parseCodeSection(Ctx);422  case wasm::WASM_SEC_DATA:423    return parseDataSection(Ctx);424  case wasm::WASM_SEC_DATACOUNT:425    return parseDataCountSection(Ctx);426  default:427    return make_error<GenericBinaryError>(428        "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);429  }430}431 432Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {433  // Legacy "dylink" section support.434  // See parseDylink0Section for the current "dylink.0" section parsing.435  HasDylinkSection = true;436  DylinkInfo.MemorySize = readVaruint32(Ctx);437  DylinkInfo.MemoryAlignment = readVaruint32(Ctx);438  DylinkInfo.TableSize = readVaruint32(Ctx);439  DylinkInfo.TableAlignment = readVaruint32(Ctx);440  uint32_t Count = readVaruint32(Ctx);441  while (Count--) {442    DylinkInfo.Needed.push_back(readString(Ctx));443  }444 445  if (Ctx.Ptr != Ctx.End)446    return make_error<GenericBinaryError>("dylink section ended prematurely",447                                          object_error::parse_failed);448  return Error::success();449}450 451Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {452  // See453  // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md454  HasDylinkSection = true;455 456  const uint8_t *OrigEnd = Ctx.End;457  while (Ctx.Ptr < OrigEnd) {458    Ctx.End = OrigEnd;459    uint8_t Type = readUint8(Ctx);460    uint32_t Size = readVaruint32(Ctx);461    LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size462                      << "\n");463    Ctx.End = Ctx.Ptr + Size;464    uint32_t Count;465    switch (Type) {466    case wasm::WASM_DYLINK_MEM_INFO:467      DylinkInfo.MemorySize = readVaruint32(Ctx);468      DylinkInfo.MemoryAlignment = readVaruint32(Ctx);469      DylinkInfo.TableSize = readVaruint32(Ctx);470      DylinkInfo.TableAlignment = readVaruint32(Ctx);471      break;472    case wasm::WASM_DYLINK_NEEDED:473      Count = readVaruint32(Ctx);474      while (Count--) {475        DylinkInfo.Needed.push_back(readString(Ctx));476      }477      break;478    case wasm::WASM_DYLINK_EXPORT_INFO: {479      uint32_t Count = readVaruint32(Ctx);480      while (Count--) {481        DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)});482      }483      break;484    }485    case wasm::WASM_DYLINK_IMPORT_INFO: {486      uint32_t Count = readVaruint32(Ctx);487      while (Count--) {488        DylinkInfo.ImportInfo.push_back(489            {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});490      }491      break;492    }493    case wasm::WASM_DYLINK_RUNTIME_PATH: {494      Count = readVaruint32(Ctx);495      while (Count--) {496        DylinkInfo.RuntimePath.push_back(readString(Ctx));497      }498      break;499    }500    default:501      LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");502      Ctx.Ptr += Size;503      break;504    }505    if (Ctx.Ptr != Ctx.End) {506      return make_error<GenericBinaryError>(507          "dylink.0 sub-section ended prematurely", object_error::parse_failed);508    }509  }510 511  if (Ctx.Ptr != Ctx.End)512    return make_error<GenericBinaryError>("dylink.0 section ended prematurely",513                                          object_error::parse_failed);514  return Error::success();515}516 517Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {518  llvm::DenseSet<uint64_t> SeenFunctions;519  llvm::DenseSet<uint64_t> SeenGlobals;520  llvm::DenseSet<uint64_t> SeenSegments;521 522  // If we have linking section (symbol table) or if we are parsing a DSO523  // then we don't use the name section for symbol information.524  bool PopulateSymbolTable = !HasLinkingSection && !HasDylinkSection;525 526  // If we are using the name section for symbol information then it will527  // supersede any symbols created by the export section.528  if (PopulateSymbolTable)529    Symbols.clear();530 531  while (Ctx.Ptr < Ctx.End) {532    uint8_t Type = readUint8(Ctx);533    uint32_t Size = readVaruint32(Ctx);534    const uint8_t *SubSectionEnd = Ctx.Ptr + Size;535 536    switch (Type) {537    case wasm::WASM_NAMES_FUNCTION:538    case wasm::WASM_NAMES_GLOBAL:539    case wasm::WASM_NAMES_DATA_SEGMENT: {540      uint32_t Count = readVaruint32(Ctx);541      while (Count--) {542        uint32_t Index = readVaruint32(Ctx);543        StringRef Name = readString(Ctx);544        wasm::NameType nameType = wasm::NameType::FUNCTION;545        wasm::WasmSymbolInfo Info{Name,546                                  /*Kind */ wasm::WASM_SYMBOL_TYPE_FUNCTION,547                                  /* Flags */ 0,548                                  /* ImportModule */ std::nullopt,549                                  /* ImportName */ std::nullopt,550                                  /* ExportName */ std::nullopt,551                                  {/* ElementIndex */ Index}};552        const wasm::WasmSignature *Signature = nullptr;553        const wasm::WasmGlobalType *GlobalType = nullptr;554        const wasm::WasmTableType *TableType = nullptr;555        if (Type == wasm::WASM_NAMES_FUNCTION) {556          if (!SeenFunctions.insert(Index).second)557            return make_error<GenericBinaryError>(558                "function named more than once", object_error::parse_failed);559          if (!isValidFunctionIndex(Index) || Name.empty())560            return make_error<GenericBinaryError>("invalid function name entry",561                                                  object_error::parse_failed);562 563          if (isDefinedFunctionIndex(Index)) {564            wasm::WasmFunction &F = getDefinedFunction(Index);565            F.DebugName = Name;566            Signature = &Signatures[F.SigIndex];567            if (F.ExportName) {568              Info.ExportName = F.ExportName;569              Info.Flags |= wasm::WASM_SYMBOL_BINDING_GLOBAL;570            } else {571              Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;572            }573          } else {574            Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED;575          }576        } else if (Type == wasm::WASM_NAMES_GLOBAL) {577          if (!SeenGlobals.insert(Index).second)578            return make_error<GenericBinaryError>("global named more than once",579                                                  object_error::parse_failed);580          if (!isValidGlobalIndex(Index) || Name.empty())581            return make_error<GenericBinaryError>("invalid global name entry",582                                                  object_error::parse_failed);583          nameType = wasm::NameType::GLOBAL;584          Info.Kind = wasm::WASM_SYMBOL_TYPE_GLOBAL;585          if (isDefinedGlobalIndex(Index)) {586            GlobalType = &getDefinedGlobal(Index).Type;587          } else {588            Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED;589          }590        } else {591          if (!SeenSegments.insert(Index).second)592            return make_error<GenericBinaryError>(593                "segment named more than once", object_error::parse_failed);594          if (Index > DataSegments.size())595            return make_error<GenericBinaryError>("invalid data segment name entry",596                                                  object_error::parse_failed);597          nameType = wasm::NameType::DATA_SEGMENT;598          Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA;599          Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;600          assert(Index < DataSegments.size());601          Info.DataRef = wasm::WasmDataReference{602              Index, 0, DataSegments[Index].Data.Content.size()};603        }604        DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});605        if (PopulateSymbolTable)606          Symbols.emplace_back(Info, GlobalType, TableType, Signature);607      }608      break;609    }610    // Ignore local names for now611    case wasm::WASM_NAMES_LOCAL:612    default:613      Ctx.Ptr += Size;614      break;615    }616    if (Ctx.Ptr != SubSectionEnd)617      return make_error<GenericBinaryError>(618          "name sub-section ended prematurely", object_error::parse_failed);619  }620 621  if (Ctx.Ptr != Ctx.End)622    return make_error<GenericBinaryError>("name section ended prematurely",623                                          object_error::parse_failed);624  return Error::success();625}626 627Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {628  HasLinkingSection = true;629 630  LinkingData.Version = readVaruint32(Ctx);631  if (LinkingData.Version != wasm::WasmMetadataVersion) {632    return make_error<GenericBinaryError>(633        "unexpected metadata version: " + Twine(LinkingData.Version) +634            " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",635        object_error::parse_failed);636  }637 638  const uint8_t *OrigEnd = Ctx.End;639  while (Ctx.Ptr < OrigEnd) {640    Ctx.End = OrigEnd;641    uint8_t Type = readUint8(Ctx);642    uint32_t Size = readVaruint32(Ctx);643    LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size644                      << "\n");645    Ctx.End = Ctx.Ptr + Size;646    switch (Type) {647    case wasm::WASM_SYMBOL_TABLE:648      if (Error Err = parseLinkingSectionSymtab(Ctx))649        return Err;650      break;651    case wasm::WASM_SEGMENT_INFO: {652      uint32_t Count = readVaruint32(Ctx);653      if (Count > DataSegments.size())654        return make_error<GenericBinaryError>("too many segment names",655                                              object_error::parse_failed);656      for (uint32_t I = 0; I < Count; I++) {657        DataSegments[I].Data.Name = readString(Ctx);658        DataSegments[I].Data.Alignment = readVaruint32(Ctx);659        DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);660      }661      break;662    }663    case wasm::WASM_INIT_FUNCS: {664      uint32_t Count = readVaruint32(Ctx);665      LinkingData.InitFunctions.reserve(Count);666      for (uint32_t I = 0; I < Count; I++) {667        wasm::WasmInitFunc Init;668        Init.Priority = readVaruint32(Ctx);669        Init.Symbol = readVaruint32(Ctx);670        if (!isValidFunctionSymbol(Init.Symbol))671          return make_error<GenericBinaryError>("invalid function symbol: " +672                                                    Twine(Init.Symbol),673                                                object_error::parse_failed);674        LinkingData.InitFunctions.emplace_back(Init);675      }676      break;677    }678    case wasm::WASM_COMDAT_INFO:679      if (Error Err = parseLinkingSectionComdat(Ctx))680        return Err;681      break;682    default:683      Ctx.Ptr += Size;684      break;685    }686    if (Ctx.Ptr != Ctx.End)687      return make_error<GenericBinaryError>(688          "linking sub-section ended prematurely", object_error::parse_failed);689  }690  if (Ctx.Ptr != OrigEnd)691    return make_error<GenericBinaryError>("linking section ended prematurely",692                                          object_error::parse_failed);693  return Error::success();694}695 696Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {697  uint32_t Count = readVaruint32(Ctx);698  // Clear out any symbol information that was derived from the exports699  // section.700  Symbols.clear();701  Symbols.reserve(Count);702  StringSet<> SymbolNames;703 704  std::vector<wasm::WasmImport *> ImportedGlobals;705  std::vector<wasm::WasmImport *> ImportedFunctions;706  std::vector<wasm::WasmImport *> ImportedTags;707  std::vector<wasm::WasmImport *> ImportedTables;708  ImportedGlobals.reserve(Imports.size());709  ImportedFunctions.reserve(Imports.size());710  ImportedTags.reserve(Imports.size());711  ImportedTables.reserve(Imports.size());712  for (auto &I : Imports) {713    if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)714      ImportedFunctions.emplace_back(&I);715    else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)716      ImportedGlobals.emplace_back(&I);717    else if (I.Kind == wasm::WASM_EXTERNAL_TAG)718      ImportedTags.emplace_back(&I);719    else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)720      ImportedTables.emplace_back(&I);721  }722 723  while (Count--) {724    wasm::WasmSymbolInfo Info;725    const wasm::WasmSignature *Signature = nullptr;726    const wasm::WasmGlobalType *GlobalType = nullptr;727    const wasm::WasmTableType *TableType = nullptr;728 729    Info.Kind = readUint8(Ctx);730    Info.Flags = readVaruint32(Ctx);731    bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;732 733    switch (Info.Kind) {734    case wasm::WASM_SYMBOL_TYPE_FUNCTION:735      Info.ElementIndex = readVaruint32(Ctx);736      if (!isValidFunctionIndex(Info.ElementIndex) ||737          IsDefined != isDefinedFunctionIndex(Info.ElementIndex))738        return make_error<GenericBinaryError>("invalid function symbol index",739                                              object_error::parse_failed);740      if (IsDefined) {741        Info.Name = readString(Ctx);742        unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;743        wasm::WasmFunction &Function = Functions[FuncIndex];744        Signature = &Signatures[Function.SigIndex];745        if (Function.SymbolName.empty())746          Function.SymbolName = Info.Name;747      } else {748        wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];749        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {750          Info.Name = readString(Ctx);751          Info.ImportName = Import.Field;752        } else {753          Info.Name = Import.Field;754        }755        Signature = &Signatures[Import.SigIndex];756        Info.ImportModule = Import.Module;757      }758      break;759 760    case wasm::WASM_SYMBOL_TYPE_GLOBAL:761      Info.ElementIndex = readVaruint32(Ctx);762      if (!isValidGlobalIndex(Info.ElementIndex) ||763          IsDefined != isDefinedGlobalIndex(Info.ElementIndex))764        return make_error<GenericBinaryError>("invalid global symbol index",765                                              object_error::parse_failed);766      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==767                            wasm::WASM_SYMBOL_BINDING_WEAK)768        return make_error<GenericBinaryError>("undefined weak global symbol",769                                              object_error::parse_failed);770      if (IsDefined) {771        Info.Name = readString(Ctx);772        unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;773        wasm::WasmGlobal &Global = Globals[GlobalIndex];774        GlobalType = &Global.Type;775        if (Global.SymbolName.empty())776          Global.SymbolName = Info.Name;777      } else {778        wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];779        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {780          Info.Name = readString(Ctx);781          Info.ImportName = Import.Field;782        } else {783          Info.Name = Import.Field;784        }785        GlobalType = &Import.Global;786        Info.ImportModule = Import.Module;787      }788      break;789 790    case wasm::WASM_SYMBOL_TYPE_TABLE:791      Info.ElementIndex = readVaruint32(Ctx);792      if (!isValidTableNumber(Info.ElementIndex) ||793          IsDefined != isDefinedTableNumber(Info.ElementIndex))794        return make_error<GenericBinaryError>("invalid table symbol index",795                                              object_error::parse_failed);796      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==797                            wasm::WASM_SYMBOL_BINDING_WEAK)798        return make_error<GenericBinaryError>("undefined weak table symbol",799                                              object_error::parse_failed);800      if (IsDefined) {801        Info.Name = readString(Ctx);802        unsigned TableNumber = Info.ElementIndex - NumImportedTables;803        wasm::WasmTable &Table = Tables[TableNumber];804        TableType = &Table.Type;805        if (Table.SymbolName.empty())806          Table.SymbolName = Info.Name;807      } else {808        wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];809        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {810          Info.Name = readString(Ctx);811          Info.ImportName = Import.Field;812        } else {813          Info.Name = Import.Field;814        }815        TableType = &Import.Table;816        Info.ImportModule = Import.Module;817      }818      break;819 820    case wasm::WASM_SYMBOL_TYPE_DATA:821      Info.Name = readString(Ctx);822      if (IsDefined) {823        auto Index = readVaruint32(Ctx);824        auto Offset = readVaruint64(Ctx);825        auto Size = readVaruint64(Ctx);826        if (!(Info.Flags & wasm::WASM_SYMBOL_ABSOLUTE)) {827          if (static_cast<size_t>(Index) >= DataSegments.size())828            return make_error<GenericBinaryError>(829                "invalid data segment index: " + Twine(Index),830                object_error::parse_failed);831          size_t SegmentSize = DataSegments[Index].Data.Content.size();832          if (Offset > SegmentSize)833            return make_error<GenericBinaryError>(834                "invalid data symbol offset: `" + Info.Name +835                    "` (offset: " + Twine(Offset) +836                    " segment size: " + Twine(SegmentSize) + ")",837                object_error::parse_failed);838        }839        Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};840      }841      break;842 843    case wasm::WASM_SYMBOL_TYPE_SECTION: {844      if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=845          wasm::WASM_SYMBOL_BINDING_LOCAL)846        return make_error<GenericBinaryError>(847            "section symbols must have local binding",848            object_error::parse_failed);849      Info.ElementIndex = readVaruint32(Ctx);850      // Use somewhat unique section name as symbol name.851      StringRef SectionName = Sections[Info.ElementIndex].Name;852      Info.Name = SectionName;853      break;854    }855 856    case wasm::WASM_SYMBOL_TYPE_TAG: {857      Info.ElementIndex = readVaruint32(Ctx);858      if (!isValidTagIndex(Info.ElementIndex) ||859          IsDefined != isDefinedTagIndex(Info.ElementIndex))860        return make_error<GenericBinaryError>("invalid tag symbol index",861                                              object_error::parse_failed);862      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==863                            wasm::WASM_SYMBOL_BINDING_WEAK)864        return make_error<GenericBinaryError>("undefined weak global symbol",865                                              object_error::parse_failed);866      if (IsDefined) {867        Info.Name = readString(Ctx);868        unsigned TagIndex = Info.ElementIndex - NumImportedTags;869        wasm::WasmTag &Tag = Tags[TagIndex];870        Signature = &Signatures[Tag.SigIndex];871        if (Tag.SymbolName.empty())872          Tag.SymbolName = Info.Name;873 874      } else {875        wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];876        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {877          Info.Name = readString(Ctx);878          Info.ImportName = Import.Field;879        } else {880          Info.Name = Import.Field;881        }882        Signature = &Signatures[Import.SigIndex];883        Info.ImportModule = Import.Module;884      }885      break;886    }887 888    default:889      return make_error<GenericBinaryError>("invalid symbol type: " +890                                                Twine(unsigned(Info.Kind)),891                                            object_error::parse_failed);892    }893 894    if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=895            wasm::WASM_SYMBOL_BINDING_LOCAL &&896        !SymbolNames.insert(Info.Name).second)897      return make_error<GenericBinaryError>("duplicate symbol name " +898                                                Twine(Info.Name),899                                            object_error::parse_failed);900    Symbols.emplace_back(Info, GlobalType, TableType, Signature);901    LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");902  }903 904  return Error::success();905}906 907Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {908  uint32_t ComdatCount = readVaruint32(Ctx);909  StringSet<> ComdatSet;910  for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {911    StringRef Name = readString(Ctx);912    if (Name.empty() || !ComdatSet.insert(Name).second)913      return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +914                                                Twine(Name),915                                            object_error::parse_failed);916    LinkingData.Comdats.emplace_back(Name);917    uint32_t Flags = readVaruint32(Ctx);918    if (Flags != 0)919      return make_error<GenericBinaryError>("unsupported COMDAT flags",920                                            object_error::parse_failed);921 922    uint32_t EntryCount = readVaruint32(Ctx);923    while (EntryCount--) {924      unsigned Kind = readVaruint32(Ctx);925      unsigned Index = readVaruint32(Ctx);926      switch (Kind) {927      default:928        return make_error<GenericBinaryError>("invalid COMDAT entry type",929                                              object_error::parse_failed);930      case wasm::WASM_COMDAT_DATA:931        if (Index >= DataSegments.size())932          return make_error<GenericBinaryError>(933              "COMDAT data index out of range", object_error::parse_failed);934        if (DataSegments[Index].Data.Comdat != UINT32_MAX)935          return make_error<GenericBinaryError>("data segment in two COMDATs",936                                                object_error::parse_failed);937        DataSegments[Index].Data.Comdat = ComdatIndex;938        break;939      case wasm::WASM_COMDAT_FUNCTION:940        if (!isDefinedFunctionIndex(Index))941          return make_error<GenericBinaryError>(942              "COMDAT function index out of range", object_error::parse_failed);943        if (getDefinedFunction(Index).Comdat != UINT32_MAX)944          return make_error<GenericBinaryError>("function in two COMDATs",945                                                object_error::parse_failed);946        getDefinedFunction(Index).Comdat = ComdatIndex;947        break;948      case wasm::WASM_COMDAT_SECTION:949        if (Index >= Sections.size())950          return make_error<GenericBinaryError>(951              "COMDAT section index out of range", object_error::parse_failed);952        if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)953          return make_error<GenericBinaryError>(954              "non-custom section in a COMDAT", object_error::parse_failed);955        Sections[Index].Comdat = ComdatIndex;956        break;957      }958    }959  }960  return Error::success();961}962 963Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {964  llvm::SmallSet<StringRef, 3> FieldsSeen;965  uint32_t Fields = readVaruint32(Ctx);966  for (size_t I = 0; I < Fields; ++I) {967    StringRef FieldName = readString(Ctx);968    if (!FieldsSeen.insert(FieldName).second)969      return make_error<GenericBinaryError>(970          "producers section does not have unique fields",971          object_error::parse_failed);972    std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;973    if (FieldName == "language") {974      ProducerVec = &ProducerInfo.Languages;975    } else if (FieldName == "processed-by") {976      ProducerVec = &ProducerInfo.Tools;977    } else if (FieldName == "sdk") {978      ProducerVec = &ProducerInfo.SDKs;979    } else {980      return make_error<GenericBinaryError>(981          "producers section field is not named one of language, processed-by, "982          "or sdk",983          object_error::parse_failed);984    }985    uint32_t ValueCount = readVaruint32(Ctx);986    llvm::SmallSet<StringRef, 8> ProducersSeen;987    for (size_t J = 0; J < ValueCount; ++J) {988      StringRef Name = readString(Ctx);989      StringRef Version = readString(Ctx);990      if (!ProducersSeen.insert(Name).second) {991        return make_error<GenericBinaryError>(992            "producers section contains repeated producer",993            object_error::parse_failed);994      }995      ProducerVec->emplace_back(std::string(Name), std::string(Version));996    }997  }998  if (Ctx.Ptr != Ctx.End)999    return make_error<GenericBinaryError>("producers section ended prematurely",1000                                          object_error::parse_failed);1001  return Error::success();1002}1003 1004Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {1005  llvm::SmallSet<std::string, 8> FeaturesSeen;1006  uint32_t FeatureCount = readVaruint32(Ctx);1007  for (size_t I = 0; I < FeatureCount; ++I) {1008    wasm::WasmFeatureEntry Feature;1009    Feature.Prefix = readUint8(Ctx);1010    switch (Feature.Prefix) {1011    case wasm::WASM_FEATURE_PREFIX_USED:1012    case wasm::WASM_FEATURE_PREFIX_DISALLOWED:1013      break;1014    default:1015      return make_error<GenericBinaryError>("unknown feature policy prefix",1016                                            object_error::parse_failed);1017    }1018    Feature.Name = std::string(readString(Ctx));1019    if (!FeaturesSeen.insert(Feature.Name).second)1020      return make_error<GenericBinaryError>(1021          "target features section contains repeated feature \"" +1022              Feature.Name + "\"",1023          object_error::parse_failed);1024    TargetFeatures.push_back(Feature);1025  }1026  if (Ctx.Ptr != Ctx.End)1027    return make_error<GenericBinaryError>(1028        "target features section ended prematurely",1029        object_error::parse_failed);1030  return Error::success();1031}1032 1033Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {1034  uint32_t SectionIndex = readVaruint32(Ctx);1035  if (SectionIndex >= Sections.size())1036    return make_error<GenericBinaryError>("invalid section index",1037                                          object_error::parse_failed);1038  WasmSection &Section = Sections[SectionIndex];1039  uint32_t RelocCount = readVaruint32(Ctx);1040  uint32_t EndOffset = Section.Content.size();1041  uint32_t PreviousOffset = 0;1042  while (RelocCount--) {1043    wasm::WasmRelocation Reloc = {};1044    uint32_t type = readVaruint32(Ctx);1045    Reloc.Type = type;1046    Reloc.Offset = readVaruint32(Ctx);1047    if (Reloc.Offset < PreviousOffset)1048      return make_error<GenericBinaryError>("relocations not in offset order",1049                                            object_error::parse_failed);1050 1051    auto badReloc = [&](StringRef msg) {1052      return make_error<GenericBinaryError>(1053          msg + ": " + Twine(Symbols[Reloc.Index].Info.Name),1054          object_error::parse_failed);1055    };1056 1057    PreviousOffset = Reloc.Offset;1058    Reloc.Index = readVaruint32(Ctx);1059    switch (type) {1060    case wasm::R_WASM_FUNCTION_INDEX_LEB:1061    case wasm::R_WASM_FUNCTION_INDEX_I32:1062    case wasm::R_WASM_TABLE_INDEX_SLEB:1063    case wasm::R_WASM_TABLE_INDEX_SLEB64:1064    case wasm::R_WASM_TABLE_INDEX_I32:1065    case wasm::R_WASM_TABLE_INDEX_I64:1066    case wasm::R_WASM_TABLE_INDEX_REL_SLEB:1067    case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:1068      if (!isValidFunctionSymbol(Reloc.Index))1069        return badReloc("invalid function relocation");1070      break;1071    case wasm::R_WASM_TABLE_NUMBER_LEB:1072      if (!isValidTableSymbol(Reloc.Index))1073        return badReloc("invalid table relocation");1074      break;1075    case wasm::R_WASM_TYPE_INDEX_LEB:1076      if (Reloc.Index >= Signatures.size())1077        return badReloc("invalid relocation type index");1078      break;1079    case wasm::R_WASM_GLOBAL_INDEX_LEB:1080      // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data1081      // symbols to refer to their GOT entries.1082      if (!isValidGlobalSymbol(Reloc.Index) &&1083          !isValidDataSymbol(Reloc.Index) &&1084          !isValidFunctionSymbol(Reloc.Index))1085        return badReloc("invalid global relocation");1086      break;1087    case wasm::R_WASM_GLOBAL_INDEX_I32:1088      if (!isValidGlobalSymbol(Reloc.Index))1089        return badReloc("invalid global relocation");1090      break;1091    case wasm::R_WASM_TAG_INDEX_LEB:1092      if (!isValidTagSymbol(Reloc.Index))1093        return badReloc("invalid tag relocation");1094      break;1095    case wasm::R_WASM_MEMORY_ADDR_LEB:1096    case wasm::R_WASM_MEMORY_ADDR_SLEB:1097    case wasm::R_WASM_MEMORY_ADDR_I32:1098    case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:1099    case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:1100    case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:1101      if (!isValidDataSymbol(Reloc.Index))1102        return badReloc("invalid data relocation");1103      Reloc.Addend = readVarint32(Ctx);1104      break;1105    case wasm::R_WASM_MEMORY_ADDR_LEB64:1106    case wasm::R_WASM_MEMORY_ADDR_SLEB64:1107    case wasm::R_WASM_MEMORY_ADDR_I64:1108    case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:1109    case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:1110      if (!isValidDataSymbol(Reloc.Index))1111        return badReloc("invalid data relocation");1112      Reloc.Addend = readVarint64(Ctx);1113      break;1114    case wasm::R_WASM_FUNCTION_OFFSET_I32:1115      if (!isValidFunctionSymbol(Reloc.Index))1116        return badReloc("invalid function relocation");1117      Reloc.Addend = readVarint32(Ctx);1118      break;1119    case wasm::R_WASM_FUNCTION_OFFSET_I64:1120      if (!isValidFunctionSymbol(Reloc.Index))1121        return badReloc("invalid function relocation");1122      Reloc.Addend = readVarint64(Ctx);1123      break;1124    case wasm::R_WASM_SECTION_OFFSET_I32:1125      if (!isValidSectionSymbol(Reloc.Index))1126        return badReloc("invalid section relocation");1127      Reloc.Addend = readVarint32(Ctx);1128      break;1129    default:1130      return make_error<GenericBinaryError>("invalid relocation type: " +1131                                                Twine(type),1132                                            object_error::parse_failed);1133    }1134 1135    // Relocations must fit inside the section, and must appear in order.  They1136    // also shouldn't overlap a function/element boundary, but we don't bother1137    // to check that.1138    uint64_t Size = 5;1139    if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||1140        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||1141        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)1142      Size = 10;1143    if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||1144        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||1145        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||1146        Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||1147        Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||1148        Reloc.Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||1149        Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)1150      Size = 4;1151    if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||1152        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||1153        Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)1154      Size = 8;1155    if (Reloc.Offset + Size > EndOffset)1156      return make_error<GenericBinaryError>("invalid relocation offset",1157                                            object_error::parse_failed);1158 1159    Section.Relocations.push_back(Reloc);1160  }1161  if (Ctx.Ptr != Ctx.End)1162    return make_error<GenericBinaryError>("reloc section ended prematurely",1163                                          object_error::parse_failed);1164  return Error::success();1165}1166 1167Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {1168  if (Sec.Name == "dylink") {1169    if (Error Err = parseDylinkSection(Ctx))1170      return Err;1171  } else if (Sec.Name == "dylink.0") {1172    if (Error Err = parseDylink0Section(Ctx))1173      return Err;1174  } else if (Sec.Name == "name") {1175    if (Error Err = parseNameSection(Ctx))1176      return Err;1177  } else if (Sec.Name == "linking") {1178    if (Error Err = parseLinkingSection(Ctx))1179      return Err;1180  } else if (Sec.Name == "producers") {1181    if (Error Err = parseProducersSection(Ctx))1182      return Err;1183  } else if (Sec.Name == "target_features") {1184    if (Error Err = parseTargetFeaturesSection(Ctx))1185      return Err;1186  } else if (Sec.Name.starts_with("reloc.")) {1187    if (Error Err = parseRelocSection(Sec.Name, Ctx))1188      return Err;1189  }1190  return Error::success();1191}1192 1193Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {1194  auto parseFieldDef = [&]() {1195    uint32_t TypeCode = readVaruint32((Ctx));1196    /* Discard StorageType */ parseValType(Ctx, TypeCode);1197    /* Discard Mutability */ readVaruint32(Ctx);1198  };1199 1200  uint32_t Count = readVaruint32(Ctx);1201  Signatures.reserve(Count);1202  while (Count--) {1203    wasm::WasmSignature Sig;1204    uint8_t Form = readUint8(Ctx);1205    if (Form == wasm::WASM_TYPE_REC) {1206      // Rec groups expand the type index space (beyond what was declared at1207      // the top of the section, and also consume one element in that space.1208      uint32_t RecSize = readVaruint32(Ctx);1209      if (RecSize == 0)1210        return make_error<GenericBinaryError>("Rec group size cannot be 0",1211                                              object_error::parse_failed);1212      Signatures.reserve(Signatures.size() + RecSize);1213      Count += RecSize;1214      Sig.Kind = wasm::WasmSignature::Placeholder;1215      Signatures.push_back(std::move(Sig));1216      HasUnmodeledTypes = true;1217      continue;1218    }1219    if (Form != wasm::WASM_TYPE_FUNC) {1220      // Currently LLVM only models function types, and not other composite1221      // types. Here we parse the type declarations just enough to skip past1222      // them in the binary.1223      if (Form == wasm::WASM_TYPE_SUB || Form == wasm::WASM_TYPE_SUB_FINAL) {1224        uint32_t Supers = readVaruint32(Ctx);1225        if (Supers > 0) {1226          if (Supers != 1)1227            return make_error<GenericBinaryError>(1228                "Invalid number of supertypes", object_error::parse_failed);1229          /* Discard SuperIndex */ readVaruint32(Ctx);1230        }1231        Form = readVaruint32(Ctx);1232      }1233      if (Form == wasm::WASM_TYPE_STRUCT) {1234        uint32_t FieldCount = readVaruint32(Ctx);1235        while (FieldCount--) {1236          parseFieldDef();1237        }1238      } else if (Form == wasm::WASM_TYPE_ARRAY) {1239        parseFieldDef();1240      } else {1241        return make_error<GenericBinaryError>("bad form",1242                                              object_error::parse_failed);1243      }1244      Sig.Kind = wasm::WasmSignature::Placeholder;1245      Signatures.push_back(std::move(Sig));1246      HasUnmodeledTypes = true;1247      continue;1248    }1249 1250    uint32_t ParamCount = readVaruint32(Ctx);1251    Sig.Params.reserve(ParamCount);1252    while (ParamCount--) {1253      uint32_t ParamType = readUint8(Ctx);1254      Sig.Params.push_back(parseValType(Ctx, ParamType));1255    }1256    uint32_t ReturnCount = readVaruint32(Ctx);1257    while (ReturnCount--) {1258      uint32_t ReturnType = readUint8(Ctx);1259      Sig.Returns.push_back(parseValType(Ctx, ReturnType));1260    }1261 1262    Signatures.push_back(std::move(Sig));1263  }1264  if (Ctx.Ptr != Ctx.End)1265    return make_error<GenericBinaryError>("type section ended prematurely",1266                                          object_error::parse_failed);1267  return Error::success();1268}1269 1270Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {1271  uint32_t Count = readVaruint32(Ctx);1272  uint32_t NumTypes = Signatures.size();1273  Imports.reserve(Count);1274  for (uint32_t I = 0; I < Count; I++) {1275    wasm::WasmImport Im;1276    Im.Module = readString(Ctx);1277    Im.Field = readString(Ctx);1278    Im.Kind = readUint8(Ctx);1279    switch (Im.Kind) {1280    case wasm::WASM_EXTERNAL_FUNCTION:1281      NumImportedFunctions++;1282      Im.SigIndex = readVaruint32(Ctx);1283      if (Im.SigIndex >= NumTypes)1284        return make_error<GenericBinaryError>("invalid function type",1285                                              object_error::parse_failed);1286      break;1287    case wasm::WASM_EXTERNAL_GLOBAL:1288      NumImportedGlobals++;1289      Im.Global.Type = readUint8(Ctx);1290      Im.Global.Mutable = readVaruint1(Ctx);1291      break;1292    case wasm::WASM_EXTERNAL_MEMORY:1293      Im.Memory = readLimits(Ctx);1294      if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)1295        HasMemory64 = true;1296      break;1297    case wasm::WASM_EXTERNAL_TABLE: {1298      Im.Table = readTableType(Ctx);1299      NumImportedTables++;1300      auto ElemType = Im.Table.ElemType;1301      if (ElemType != wasm::ValType::FUNCREF &&1302          ElemType != wasm::ValType::EXTERNREF &&1303          ElemType != wasm::ValType::EXNREF &&1304          ElemType != wasm::ValType::OTHERREF)1305        return make_error<GenericBinaryError>("invalid table element type",1306                                              object_error::parse_failed);1307      break;1308    }1309    case wasm::WASM_EXTERNAL_TAG:1310      NumImportedTags++;1311      if (readUint8(Ctx) != 0) // Reserved 'attribute' field1312        return make_error<GenericBinaryError>("invalid attribute",1313                                              object_error::parse_failed);1314      Im.SigIndex = readVaruint32(Ctx);1315      if (Im.SigIndex >= NumTypes)1316        return make_error<GenericBinaryError>("invalid tag type",1317                                              object_error::parse_failed);1318      break;1319    default:1320      return make_error<GenericBinaryError>("unexpected import kind",1321                                            object_error::parse_failed);1322    }1323    Imports.push_back(Im);1324  }1325  if (Ctx.Ptr != Ctx.End)1326    return make_error<GenericBinaryError>("import section ended prematurely",1327                                          object_error::parse_failed);1328  return Error::success();1329}1330 1331Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {1332  uint32_t Count = readVaruint32(Ctx);1333  Functions.reserve(Count);1334  uint32_t NumTypes = Signatures.size();1335  while (Count--) {1336    uint32_t Type = readVaruint32(Ctx);1337    if (Type >= NumTypes)1338      return make_error<GenericBinaryError>("invalid function type",1339                                            object_error::parse_failed);1340    wasm::WasmFunction F;1341    F.SigIndex = Type;1342    Functions.push_back(F);1343  }1344  if (Ctx.Ptr != Ctx.End)1345    return make_error<GenericBinaryError>("function section ended prematurely",1346                                          object_error::parse_failed);1347  return Error::success();1348}1349 1350Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {1351  TableSection = Sections.size();1352  uint32_t Count = readVaruint32(Ctx);1353  Tables.reserve(Count);1354  while (Count--) {1355    wasm::WasmTable T;1356    T.Type = readTableType(Ctx);1357    T.Index = NumImportedTables + Tables.size();1358    Tables.push_back(T);1359    auto ElemType = Tables.back().Type.ElemType;1360    if (ElemType != wasm::ValType::FUNCREF &&1361        ElemType != wasm::ValType::EXTERNREF &&1362        ElemType != wasm::ValType::EXNREF &&1363        ElemType != wasm::ValType::OTHERREF) {1364      return make_error<GenericBinaryError>("invalid table element type",1365                                            object_error::parse_failed);1366    }1367  }1368  if (Ctx.Ptr != Ctx.End)1369    return make_error<GenericBinaryError>("table section ended prematurely",1370                                          object_error::parse_failed);1371  return Error::success();1372}1373 1374Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {1375  uint32_t Count = readVaruint32(Ctx);1376  Memories.reserve(Count);1377  while (Count--) {1378    auto Limits = readLimits(Ctx);1379    if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)1380      HasMemory64 = true;1381    Memories.push_back(Limits);1382  }1383  if (Ctx.Ptr != Ctx.End)1384    return make_error<GenericBinaryError>("memory section ended prematurely",1385                                          object_error::parse_failed);1386  return Error::success();1387}1388 1389Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {1390  TagSection = Sections.size();1391  uint32_t Count = readVaruint32(Ctx);1392  Tags.reserve(Count);1393  uint32_t NumTypes = Signatures.size();1394  while (Count--) {1395    if (readUint8(Ctx) != 0) // Reserved 'attribute' field1396      return make_error<GenericBinaryError>("invalid attribute",1397                                            object_error::parse_failed);1398    uint32_t Type = readVaruint32(Ctx);1399    if (Type >= NumTypes)1400      return make_error<GenericBinaryError>("invalid tag type",1401                                            object_error::parse_failed);1402    wasm::WasmTag Tag;1403    Tag.Index = NumImportedTags + Tags.size();1404    Tag.SigIndex = Type;1405    Signatures[Type].Kind = wasm::WasmSignature::Tag;1406    Tags.push_back(Tag);1407  }1408 1409  if (Ctx.Ptr != Ctx.End)1410    return make_error<GenericBinaryError>("tag section ended prematurely",1411                                          object_error::parse_failed);1412  return Error::success();1413}1414 1415Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {1416  GlobalSection = Sections.size();1417  const uint8_t *SectionStart = Ctx.Ptr;1418  uint32_t Count = readVaruint32(Ctx);1419  Globals.reserve(Count);1420  while (Count--) {1421    wasm::WasmGlobal Global;1422    Global.Index = NumImportedGlobals + Globals.size();1423    const uint8_t *GlobalStart = Ctx.Ptr;1424    Global.Offset = static_cast<uint32_t>(GlobalStart - SectionStart);1425    auto GlobalOpcode = readVaruint32(Ctx);1426    Global.Type.Type = (uint8_t)parseValType(Ctx, GlobalOpcode);1427    Global.Type.Mutable = readVaruint1(Ctx);1428    if (Error Err = readInitExpr(Global.InitExpr, Ctx))1429      return Err;1430    Global.Size = static_cast<uint32_t>(Ctx.Ptr - GlobalStart);1431    Globals.push_back(Global);1432  }1433  if (Ctx.Ptr != Ctx.End)1434    return make_error<GenericBinaryError>("global section ended prematurely",1435                                          object_error::parse_failed);1436  return Error::success();1437}1438 1439Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {1440  uint32_t Count = readVaruint32(Ctx);1441  Exports.reserve(Count);1442  Symbols.reserve(Count);1443  for (uint32_t I = 0; I < Count; I++) {1444    wasm::WasmExport Ex;1445    Ex.Name = readString(Ctx);1446    Ex.Kind = readUint8(Ctx);1447    Ex.Index = readVaruint32(Ctx);1448    const wasm::WasmSignature *Signature = nullptr;1449    const wasm::WasmGlobalType *GlobalType = nullptr;1450    const wasm::WasmTableType *TableType = nullptr;1451    wasm::WasmSymbolInfo Info;1452    Info.Name = Ex.Name;1453    Info.Flags = 0;1454    switch (Ex.Kind) {1455    case wasm::WASM_EXTERNAL_FUNCTION: {1456      if (!isValidFunctionIndex(Ex.Index))1457        return make_error<GenericBinaryError>("invalid function export",1458                                              object_error::parse_failed);1459      Info.Kind = wasm::WASM_SYMBOL_TYPE_FUNCTION;1460      Info.ElementIndex = Ex.Index;1461      if (isDefinedFunctionIndex(Ex.Index)) {1462        getDefinedFunction(Ex.Index).ExportName = Ex.Name;1463        unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;1464        wasm::WasmFunction &Function = Functions[FuncIndex];1465        Signature = &Signatures[Function.SigIndex];1466      }1467      // Else the function is imported. LLVM object files don't use this1468      // pattern and we still treat this as an undefined symbol, but we want to1469      // parse it without crashing.1470      break;1471    }1472    case wasm::WASM_EXTERNAL_GLOBAL: {1473      if (!isValidGlobalIndex(Ex.Index))1474        return make_error<GenericBinaryError>("invalid global export",1475                                              object_error::parse_failed);1476      Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA;1477      uint64_t Offset = 0;1478      if (isDefinedGlobalIndex(Ex.Index)) {1479        auto Global = getDefinedGlobal(Ex.Index);1480        if (!Global.InitExpr.Extended) {1481          auto Inst = Global.InitExpr.Inst;1482          if (Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {1483            Offset = Inst.Value.Int32;1484          } else if (Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {1485            Offset = Inst.Value.Int64;1486          }1487        }1488      }1489      Info.DataRef = wasm::WasmDataReference{0, Offset, 0};1490      break;1491    }1492    case wasm::WASM_EXTERNAL_TAG:1493      if (!isValidTagIndex(Ex.Index))1494        return make_error<GenericBinaryError>("invalid tag export",1495                                              object_error::parse_failed);1496      Info.Kind = wasm::WASM_SYMBOL_TYPE_TAG;1497      Info.ElementIndex = Ex.Index;1498      break;1499    case wasm::WASM_EXTERNAL_MEMORY:1500      break;1501    case wasm::WASM_EXTERNAL_TABLE:1502      Info.Kind = wasm::WASM_SYMBOL_TYPE_TABLE;1503      Info.ElementIndex = Ex.Index;1504      break;1505    default:1506      return make_error<GenericBinaryError>("unexpected export kind",1507                                            object_error::parse_failed);1508    }1509    Exports.push_back(Ex);1510    if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) {1511      Symbols.emplace_back(Info, GlobalType, TableType, Signature);1512      LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");1513    }1514  }1515  if (Ctx.Ptr != Ctx.End)1516    return make_error<GenericBinaryError>("export section ended prematurely",1517                                          object_error::parse_failed);1518  return Error::success();1519}1520 1521bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {1522  return Index < NumImportedFunctions + Functions.size();1523}1524 1525bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {1526  return Index >= NumImportedFunctions && isValidFunctionIndex(Index);1527}1528 1529bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {1530  return Index < NumImportedGlobals + Globals.size();1531}1532 1533bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {1534  return Index < NumImportedTables + Tables.size();1535}1536 1537bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {1538  return Index >= NumImportedGlobals && isValidGlobalIndex(Index);1539}1540 1541bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {1542  return Index >= NumImportedTables && isValidTableNumber(Index);1543}1544 1545bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {1546  return Index < NumImportedTags + Tags.size();1547}1548 1549bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {1550  return Index >= NumImportedTags && isValidTagIndex(Index);1551}1552 1553bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {1554  return Index < Symbols.size() && Symbols[Index].isTypeFunction();1555}1556 1557bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {1558  return Index < Symbols.size() && Symbols[Index].isTypeTable();1559}1560 1561bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {1562  return Index < Symbols.size() && Symbols[Index].isTypeGlobal();1563}1564 1565bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {1566  return Index < Symbols.size() && Symbols[Index].isTypeTag();1567}1568 1569bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {1570  return Index < Symbols.size() && Symbols[Index].isTypeData();1571}1572 1573bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {1574  return Index < Symbols.size() && Symbols[Index].isTypeSection();1575}1576 1577wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {1578  assert(isDefinedFunctionIndex(Index));1579  return Functions[Index - NumImportedFunctions];1580}1581 1582const wasm::WasmFunction &1583WasmObjectFile::getDefinedFunction(uint32_t Index) const {1584  assert(isDefinedFunctionIndex(Index));1585  return Functions[Index - NumImportedFunctions];1586}1587 1588const wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) const {1589  assert(isDefinedGlobalIndex(Index));1590  return Globals[Index - NumImportedGlobals];1591}1592 1593wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {1594  assert(isDefinedTagIndex(Index));1595  return Tags[Index - NumImportedTags];1596}1597 1598Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {1599  StartFunction = readVaruint32(Ctx);1600  if (!isValidFunctionIndex(StartFunction))1601    return make_error<GenericBinaryError>("invalid start function",1602                                          object_error::parse_failed);1603  return Error::success();1604}1605 1606Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {1607  CodeSection = Sections.size();1608  uint32_t FunctionCount = readVaruint32(Ctx);1609  if (FunctionCount != Functions.size()) {1610    return make_error<GenericBinaryError>("invalid function count",1611                                          object_error::parse_failed);1612  }1613 1614  for (uint32_t i = 0; i < FunctionCount; i++) {1615    wasm::WasmFunction& Function = Functions[i];1616    const uint8_t *FunctionStart = Ctx.Ptr;1617    uint32_t Size = readVaruint32(Ctx);1618    const uint8_t *FunctionEnd = Ctx.Ptr + Size;1619 1620    Function.CodeOffset = Ctx.Ptr - FunctionStart;1621    Function.Index = NumImportedFunctions + i;1622    Function.CodeSectionOffset = FunctionStart - Ctx.Start;1623    Function.Size = FunctionEnd - FunctionStart;1624 1625    uint32_t NumLocalDecls = readVaruint32(Ctx);1626    Function.Locals.reserve(NumLocalDecls);1627    while (NumLocalDecls--) {1628      wasm::WasmLocalDecl Decl;1629      Decl.Count = readVaruint32(Ctx);1630      Decl.Type = readUint8(Ctx);1631      Function.Locals.push_back(Decl);1632    }1633 1634    uint32_t BodySize = FunctionEnd - Ctx.Ptr;1635    // Ensure that Function is within Ctx's buffer.1636    if (Ctx.Ptr + BodySize > Ctx.End) {1637      return make_error<GenericBinaryError>("Function extends beyond buffer",1638                                            object_error::parse_failed);1639    }1640    Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);1641    // This will be set later when reading in the linking metadata section.1642    Function.Comdat = UINT32_MAX;1643    Ctx.Ptr += BodySize;1644    assert(Ctx.Ptr == FunctionEnd);1645  }1646  if (Ctx.Ptr != Ctx.End)1647    return make_error<GenericBinaryError>("code section ended prematurely",1648                                          object_error::parse_failed);1649  return Error::success();1650}1651 1652Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {1653  uint32_t Count = readVaruint32(Ctx);1654  ElemSegments.reserve(Count);1655  while (Count--) {1656    wasm::WasmElemSegment Segment;1657    Segment.Flags = readVaruint32(Ctx);1658 1659    uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |1660                              wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |1661                              wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;1662    if (Segment.Flags & ~SupportedFlags)1663      return make_error<GenericBinaryError>(1664          "Unsupported flags for element segment", object_error::parse_failed);1665 1666    wasm::ElemSegmentMode Mode;1667    if ((Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) == 0) {1668      Mode = wasm::ElemSegmentMode::Active;1669    } else if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE) {1670      Mode = wasm::ElemSegmentMode::Declarative;1671    } else {1672      Mode = wasm::ElemSegmentMode::Passive;1673    }1674    bool HasTableNumber =1675        Mode == wasm::ElemSegmentMode::Active &&1676        (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER);1677    bool HasElemKind =1678        (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC) &&1679        !(Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS);1680    bool HasElemType =1681        (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC) &&1682        (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS);1683    bool HasInitExprs =1684        (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS);1685 1686    if (HasTableNumber)1687      Segment.TableNumber = readVaruint32(Ctx);1688    else1689      Segment.TableNumber = 0;1690 1691    if (!isValidTableNumber(Segment.TableNumber))1692      return make_error<GenericBinaryError>("invalid TableNumber",1693                                            object_error::parse_failed);1694 1695    if (Mode != wasm::ElemSegmentMode::Active) {1696      Segment.Offset.Extended = false;1697      Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;1698      Segment.Offset.Inst.Value.Int32 = 0;1699    } else {1700      if (Error Err = readInitExpr(Segment.Offset, Ctx))1701        return Err;1702    }1703 1704    if (HasElemKind) {1705      auto ElemKind = readVaruint32(Ctx);1706      if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {1707        Segment.ElemKind = parseValType(Ctx, ElemKind);1708        if (Segment.ElemKind != wasm::ValType::FUNCREF &&1709            Segment.ElemKind != wasm::ValType::EXTERNREF &&1710            Segment.ElemKind != wasm::ValType::EXNREF &&1711            Segment.ElemKind != wasm::ValType::OTHERREF) {1712          return make_error<GenericBinaryError>("invalid elem type",1713                                                object_error::parse_failed);1714        }1715      } else {1716        if (ElemKind != 0)1717          return make_error<GenericBinaryError>("invalid elem type",1718                                                object_error::parse_failed);1719        Segment.ElemKind = wasm::ValType::FUNCREF;1720      }1721    } else if (HasElemType) {1722      auto ElemType = parseValType(Ctx, readVaruint32(Ctx));1723      Segment.ElemKind = ElemType;1724    } else {1725      Segment.ElemKind = wasm::ValType::FUNCREF;1726    }1727 1728    uint32_t NumElems = readVaruint32(Ctx);1729 1730    if (HasInitExprs) {1731      while (NumElems--) {1732        wasm::WasmInitExpr Expr;1733        if (Error Err = readInitExpr(Expr, Ctx))1734          return Err;1735      }1736    } else {1737      while (NumElems--) {1738        Segment.Functions.push_back(readVaruint32(Ctx));1739      }1740    }1741    ElemSegments.push_back(Segment);1742  }1743  if (Ctx.Ptr != Ctx.End)1744    return make_error<GenericBinaryError>("elem section ended prematurely",1745                                          object_error::parse_failed);1746  return Error::success();1747}1748 1749Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {1750  DataSection = Sections.size();1751  uint32_t Count = readVaruint32(Ctx);1752  if (DataCount && Count != *DataCount)1753    return make_error<GenericBinaryError>(1754        "number of data segments does not match DataCount section");1755  DataSegments.reserve(Count);1756  while (Count--) {1757    WasmSegment Segment;1758    Segment.Data.InitFlags = readVaruint32(Ctx);1759    Segment.Data.MemoryIndex =1760        (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)1761            ? readVaruint32(Ctx)1762            : 0;1763    if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {1764      if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))1765        return Err;1766    } else {1767      Segment.Data.Offset.Extended = false;1768      Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;1769      Segment.Data.Offset.Inst.Value.Int32 = 0;1770    }1771    uint32_t Size = readVaruint32(Ctx);1772    if (Size > (size_t)(Ctx.End - Ctx.Ptr))1773      return make_error<GenericBinaryError>("invalid segment size",1774                                            object_error::parse_failed);1775    Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);1776    // The rest of these Data fields are set later, when reading in the linking1777    // metadata section.1778    Segment.Data.Alignment = 0;1779    Segment.Data.LinkingFlags = 0;1780    Segment.Data.Comdat = UINT32_MAX;1781    Segment.SectionOffset = Ctx.Ptr - Ctx.Start;1782    Ctx.Ptr += Size;1783    DataSegments.push_back(Segment);1784  }1785  if (Ctx.Ptr != Ctx.End)1786    return make_error<GenericBinaryError>("data section ended prematurely",1787                                          object_error::parse_failed);1788  return Error::success();1789}1790 1791Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {1792  DataCount = readVaruint32(Ctx);1793  return Error::success();1794}1795 1796const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {1797  return Header;1798}1799 1800void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }1801 1802Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {1803  uint32_t Result = SymbolRef::SF_None;1804  const WasmSymbol &Sym = getWasmSymbol(Symb);1805 1806  LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");1807  if (Sym.isBindingWeak())1808    Result |= SymbolRef::SF_Weak;1809  if (!Sym.isBindingLocal())1810    Result |= SymbolRef::SF_Global;1811  if (Sym.isHidden())1812    Result |= SymbolRef::SF_Hidden;1813  if (!Sym.isDefined())1814    Result |= SymbolRef::SF_Undefined;1815  if (Sym.isTypeFunction())1816    Result |= SymbolRef::SF_Executable;1817  return Result;1818}1819 1820basic_symbol_iterator WasmObjectFile::symbol_begin() const {1821  DataRefImpl Ref;1822  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null1823  Ref.d.b = 0; // Symbol index1824  return BasicSymbolRef(Ref, this);1825}1826 1827basic_symbol_iterator WasmObjectFile::symbol_end() const {1828  DataRefImpl Ref;1829  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null1830  Ref.d.b = Symbols.size(); // Symbol index1831  return BasicSymbolRef(Ref, this);1832}1833 1834const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {1835  return Symbols[Symb.d.b];1836}1837 1838const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {1839  return getWasmSymbol(Symb.getRawDataRefImpl());1840}1841 1842Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {1843  return getWasmSymbol(Symb).Info.Name;1844}1845 1846Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {1847  auto &Sym = getWasmSymbol(Symb);1848  if (!Sym.isDefined())1849    return 0;1850  Expected<section_iterator> Sec = getSymbolSection(Symb);1851  if (!Sec)1852    return Sec.takeError();1853  uint32_t SectionAddress = getSectionAddress(Sec.get()->getRawDataRefImpl());1854  if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&1855      isDefinedFunctionIndex(Sym.Info.ElementIndex)) {1856    return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +1857           SectionAddress;1858  }1859  if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL &&1860      isDefinedGlobalIndex(Sym.Info.ElementIndex)) {1861    return getDefinedGlobal(Sym.Info.ElementIndex).Offset + SectionAddress;1862  }1863 1864  return getSymbolValue(Symb);1865}1866 1867uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {1868  switch (Sym.Info.Kind) {1869  case wasm::WASM_SYMBOL_TYPE_FUNCTION:1870  case wasm::WASM_SYMBOL_TYPE_GLOBAL:1871  case wasm::WASM_SYMBOL_TYPE_TAG:1872  case wasm::WASM_SYMBOL_TYPE_TABLE:1873    return Sym.Info.ElementIndex;1874  case wasm::WASM_SYMBOL_TYPE_DATA: {1875    // The value of a data symbol is the segment offset, plus the symbol1876    // offset within the segment.1877    uint32_t SegmentIndex = Sym.Info.DataRef.Segment;1878    const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;1879    if (Segment.Offset.Extended) {1880      llvm_unreachable("extended init exprs not supported");1881    } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {1882      return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;1883    } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {1884      return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;1885    } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {1886      return Sym.Info.DataRef.Offset;1887    } else {1888      llvm_unreachable("unknown init expr opcode");1889    }1890  }1891  case wasm::WASM_SYMBOL_TYPE_SECTION:1892    return 0;1893  }1894  llvm_unreachable("invalid symbol type");1895}1896 1897uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {1898  return getWasmSymbolValue(getWasmSymbol(Symb));1899}1900 1901uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {1902  llvm_unreachable("not yet implemented");1903  return 0;1904}1905 1906uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {1907  llvm_unreachable("not yet implemented");1908  return 0;1909}1910 1911Expected<SymbolRef::Type>1912WasmObjectFile::getSymbolType(DataRefImpl Symb) const {1913  const WasmSymbol &Sym = getWasmSymbol(Symb);1914 1915  switch (Sym.Info.Kind) {1916  case wasm::WASM_SYMBOL_TYPE_FUNCTION:1917    return SymbolRef::ST_Function;1918  case wasm::WASM_SYMBOL_TYPE_GLOBAL:1919    return SymbolRef::ST_Other;1920  case wasm::WASM_SYMBOL_TYPE_DATA:1921    return SymbolRef::ST_Data;1922  case wasm::WASM_SYMBOL_TYPE_SECTION:1923    return SymbolRef::ST_Debug;1924  case wasm::WASM_SYMBOL_TYPE_TAG:1925    return SymbolRef::ST_Other;1926  case wasm::WASM_SYMBOL_TYPE_TABLE:1927    return SymbolRef::ST_Other;1928  }1929 1930  llvm_unreachable("unknown WasmSymbol::SymbolType");1931  return SymbolRef::ST_Other;1932}1933 1934Expected<section_iterator>1935WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {1936  const WasmSymbol &Sym = getWasmSymbol(Symb);1937  if (Sym.isUndefined())1938    return section_end();1939 1940  DataRefImpl Ref;1941  Ref.d.a = getSymbolSectionIdImpl(Sym);1942  return section_iterator(SectionRef(Ref, this));1943}1944 1945uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {1946  const WasmSymbol &Sym = getWasmSymbol(Symb);1947  return getSymbolSectionIdImpl(Sym);1948}1949 1950uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {1951  switch (Sym.Info.Kind) {1952  case wasm::WASM_SYMBOL_TYPE_FUNCTION:1953    return CodeSection;1954  case wasm::WASM_SYMBOL_TYPE_GLOBAL:1955    return GlobalSection;1956  case wasm::WASM_SYMBOL_TYPE_DATA:1957    return DataSection;1958  case wasm::WASM_SYMBOL_TYPE_SECTION:1959    return Sym.Info.ElementIndex;1960  case wasm::WASM_SYMBOL_TYPE_TAG:1961    return TagSection;1962  case wasm::WASM_SYMBOL_TYPE_TABLE:1963    return TableSection;1964  default:1965    llvm_unreachable("unknown WasmSymbol::SymbolType");1966  }1967}1968 1969uint32_t WasmObjectFile::getSymbolSize(SymbolRef Symb) const {1970  const WasmSymbol &Sym = getWasmSymbol(Symb);1971  if (!Sym.isDefined())1972    return 0;1973  if (Sym.isTypeGlobal())1974    return getDefinedGlobal(Sym.Info.ElementIndex).Size;1975  if (Sym.isTypeData())1976    return Sym.Info.DataRef.Size;1977  if (Sym.isTypeFunction())1978    return functions()[Sym.Info.ElementIndex - getNumImportedFunctions()].Size;1979  // Currently symbol size is only tracked for data segments and functions. In1980  // principle we could also track size (e.g. binary size) for tables, globals1981  // and element segments etc too.1982  return 0;1983}1984 1985void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }1986 1987Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {1988  const WasmSection &S = Sections[Sec.d.a];1989  if (S.Type == wasm::WASM_SEC_CUSTOM)1990    return S.Name;1991  if (S.Type > wasm::WASM_SEC_LAST_KNOWN)1992    return createStringError(object_error::invalid_section_index, "");1993  return wasm::sectionTypeToString(S.Type);1994}1995 1996uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const {1997  // For object files, use 0 for section addresses, and section offsets for1998  // symbol addresses. For linked files, use file offsets.1999  // See also getSymbolAddress.2000  return isRelocatableObject() || isSharedObject() ? 02001                                                   : Sections[Sec.d.a].Offset;2002}2003 2004uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {2005  return Sec.d.a;2006}2007 2008uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {2009  const WasmSection &S = Sections[Sec.d.a];2010  return S.Content.size();2011}2012 2013Expected<ArrayRef<uint8_t>>2014WasmObjectFile::getSectionContents(DataRefImpl Sec) const {2015  const WasmSection &S = Sections[Sec.d.a];2016  // This will never fail since wasm sections can never be empty (user-sections2017  // must have a name and non-user sections each have a defined structure).2018  return S.Content;2019}2020 2021uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {2022  return 1;2023}2024 2025bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {2026  return false;2027}2028 2029bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {2030  return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;2031}2032 2033bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {2034  return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;2035}2036 2037bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }2038 2039bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }2040 2041relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {2042  DataRefImpl RelocRef;2043  RelocRef.d.a = Ref.d.a;2044  RelocRef.d.b = 0;2045  return relocation_iterator(RelocationRef(RelocRef, this));2046}2047 2048relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {2049  const WasmSection &Sec = getWasmSection(Ref);2050  DataRefImpl RelocRef;2051  RelocRef.d.a = Ref.d.a;2052  RelocRef.d.b = Sec.Relocations.size();2053  return relocation_iterator(RelocationRef(RelocRef, this));2054}2055 2056void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }2057 2058uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {2059  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);2060  return Rel.Offset;2061}2062 2063symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {2064  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);2065  if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)2066    return symbol_end();2067  DataRefImpl Sym;2068  Sym.d.a = 1;2069  Sym.d.b = Rel.Index;2070  return symbol_iterator(SymbolRef(Sym, this));2071}2072 2073uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {2074  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);2075  return Rel.Type;2076}2077 2078void WasmObjectFile::getRelocationTypeName(2079    DataRefImpl Ref, SmallVectorImpl<char> &Result) const {2080  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);2081  StringRef Res = "Unknown";2082 2083#define WASM_RELOC(name, value)                                                \2084  case wasm::name:                                                             \2085    Res = #name;                                                               \2086    break;2087 2088  switch (Rel.Type) {2089#include "llvm/BinaryFormat/WasmRelocs.def"2090  }2091 2092#undef WASM_RELOC2093 2094  Result.append(Res.begin(), Res.end());2095}2096 2097section_iterator WasmObjectFile::section_begin() const {2098  DataRefImpl Ref;2099  Ref.d.a = 0;2100  return section_iterator(SectionRef(Ref, this));2101}2102 2103section_iterator WasmObjectFile::section_end() const {2104  DataRefImpl Ref;2105  Ref.d.a = Sections.size();2106  return section_iterator(SectionRef(Ref, this));2107}2108 2109uint8_t WasmObjectFile::getBytesInAddress() const {2110  return HasMemory64 ? 8 : 4;2111}2112 2113StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }2114 2115Triple::ArchType WasmObjectFile::getArch() const {2116  return HasMemory64 ? Triple::wasm64 : Triple::wasm32;2117}2118 2119Expected<SubtargetFeatures> WasmObjectFile::getFeatures() const {2120  return SubtargetFeatures();2121}2122 2123bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }2124 2125bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }2126 2127const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {2128  assert(Ref.d.a < Sections.size());2129  return Sections[Ref.d.a];2130}2131 2132const WasmSection &2133WasmObjectFile::getWasmSection(const SectionRef &Section) const {2134  return getWasmSection(Section.getRawDataRefImpl());2135}2136 2137const wasm::WasmRelocation &2138WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {2139  return getWasmRelocation(Ref.getRawDataRefImpl());2140}2141 2142const wasm::WasmRelocation &2143WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {2144  assert(Ref.d.a < Sections.size());2145  const WasmSection &Sec = Sections[Ref.d.a];2146  assert(Ref.d.b < Sec.Relocations.size());2147  return Sec.Relocations[Ref.d.b];2148}2149 2150int WasmSectionOrderChecker::getSectionOrder(unsigned ID,2151                                             StringRef CustomSectionName) {2152  switch (ID) {2153  case wasm::WASM_SEC_CUSTOM:2154    return StringSwitch<unsigned>(CustomSectionName)2155        .Case("dylink", WASM_SEC_ORDER_DYLINK)2156        .Case("dylink.0", WASM_SEC_ORDER_DYLINK)2157        .Case("linking", WASM_SEC_ORDER_LINKING)2158        .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)2159        .Case("name", WASM_SEC_ORDER_NAME)2160        .Case("producers", WASM_SEC_ORDER_PRODUCERS)2161        .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)2162        .Default(WASM_SEC_ORDER_NONE);2163  case wasm::WASM_SEC_TYPE:2164    return WASM_SEC_ORDER_TYPE;2165  case wasm::WASM_SEC_IMPORT:2166    return WASM_SEC_ORDER_IMPORT;2167  case wasm::WASM_SEC_FUNCTION:2168    return WASM_SEC_ORDER_FUNCTION;2169  case wasm::WASM_SEC_TABLE:2170    return WASM_SEC_ORDER_TABLE;2171  case wasm::WASM_SEC_MEMORY:2172    return WASM_SEC_ORDER_MEMORY;2173  case wasm::WASM_SEC_GLOBAL:2174    return WASM_SEC_ORDER_GLOBAL;2175  case wasm::WASM_SEC_EXPORT:2176    return WASM_SEC_ORDER_EXPORT;2177  case wasm::WASM_SEC_START:2178    return WASM_SEC_ORDER_START;2179  case wasm::WASM_SEC_ELEM:2180    return WASM_SEC_ORDER_ELEM;2181  case wasm::WASM_SEC_CODE:2182    return WASM_SEC_ORDER_CODE;2183  case wasm::WASM_SEC_DATA:2184    return WASM_SEC_ORDER_DATA;2185  case wasm::WASM_SEC_DATACOUNT:2186    return WASM_SEC_ORDER_DATACOUNT;2187  case wasm::WASM_SEC_TAG:2188    return WASM_SEC_ORDER_TAG;2189  default:2190    return WASM_SEC_ORDER_NONE;2191  }2192}2193 2194// Represents the edges in a directed graph where any node B reachable from node2195// A is not allowed to appear before A in the section ordering, but may appear2196// afterward.2197int WasmSectionOrderChecker::DisallowedPredecessors2198    [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {2199        // WASM_SEC_ORDER_NONE2200        {},2201        // WASM_SEC_ORDER_TYPE2202        {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},2203        // WASM_SEC_ORDER_IMPORT2204        {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},2205        // WASM_SEC_ORDER_FUNCTION2206        {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},2207        // WASM_SEC_ORDER_TABLE2208        {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},2209        // WASM_SEC_ORDER_MEMORY2210        {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},2211        // WASM_SEC_ORDER_TAG2212        {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},2213        // WASM_SEC_ORDER_GLOBAL2214        {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},2215        // WASM_SEC_ORDER_EXPORT2216        {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},2217        // WASM_SEC_ORDER_START2218        {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},2219        // WASM_SEC_ORDER_ELEM2220        {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},2221        // WASM_SEC_ORDER_DATACOUNT2222        {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},2223        // WASM_SEC_ORDER_CODE2224        {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},2225        // WASM_SEC_ORDER_DATA2226        {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},2227 2228        // Custom Sections2229        // WASM_SEC_ORDER_DYLINK2230        {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},2231        // WASM_SEC_ORDER_LINKING2232        {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},2233        // WASM_SEC_ORDER_RELOC (can be repeated)2234        {},2235        // WASM_SEC_ORDER_NAME2236        {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},2237        // WASM_SEC_ORDER_PRODUCERS2238        {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},2239        // WASM_SEC_ORDER_TARGET_FEATURES2240        {WASM_SEC_ORDER_TARGET_FEATURES}};2241 2242bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,2243                                                  StringRef CustomSectionName) {2244  int Order = getSectionOrder(ID, CustomSectionName);2245  if (Order == WASM_SEC_ORDER_NONE)2246    return true;2247 2248  // Disallowed predecessors we need to check for2249  SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;2250 2251  // Keep track of completed checks to avoid repeating work2252  bool Checked[WASM_NUM_SEC_ORDERS] = {};2253 2254  int Curr = Order;2255  while (true) {2256    // Add new disallowed predecessors to work list2257    for (size_t I = 0;; ++I) {2258      int Next = DisallowedPredecessors[Curr][I];2259      if (Next == WASM_SEC_ORDER_NONE)2260        break;2261      if (Checked[Next])2262        continue;2263      WorkList.push_back(Next);2264      Checked[Next] = true;2265    }2266 2267    if (WorkList.empty())2268      break;2269 2270    // Consider next disallowed predecessor2271    Curr = WorkList.pop_back_val();2272    if (Seen[Curr])2273      return false;2274  }2275 2276  // Have not seen any disallowed predecessors2277  Seen[Order] = true;2278  return true;2279}2280