xref: /freebsd/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp (revision c8c62548bffb83f3d25e062929c45d66fea755f1)
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-exception
6  //
7  //===----------------------------------------------------------------------===//
8  
9  #include "llvm/ADT/ArrayRef.h"
10  #include "llvm/ADT/DenseSet.h"
11  #include "llvm/ADT/STLExtras.h"
12  #include "llvm/ADT/SmallSet.h"
13  #include "llvm/ADT/StringRef.h"
14  #include "llvm/ADT/StringSet.h"
15  #include "llvm/ADT/StringSwitch.h"
16  #include "llvm/ADT/Triple.h"
17  #include "llvm/BinaryFormat/Wasm.h"
18  #include "llvm/MC/SubtargetFeature.h"
19  #include "llvm/Object/Binary.h"
20  #include "llvm/Object/Error.h"
21  #include "llvm/Object/ObjectFile.h"
22  #include "llvm/Object/SymbolicFile.h"
23  #include "llvm/Object/Wasm.h"
24  #include "llvm/Support/Endian.h"
25  #include "llvm/Support/Error.h"
26  #include "llvm/Support/ErrorHandling.h"
27  #include "llvm/Support/LEB128.h"
28  #include "llvm/Support/ScopedPrinter.h"
29  #include <algorithm>
30  #include <cassert>
31  #include <cstdint>
32  #include <cstring>
33  #include <system_error>
34  
35  #define DEBUG_TYPE "wasm-object"
36  
37  using namespace llvm;
38  using namespace object;
39  
40  void WasmSymbol::print(raw_ostream &Out) const {
41    Out << "Name=" << Info.Name
42        << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
43        << ", Flags=" << Info.Flags;
44    if (!isTypeData()) {
45      Out << ", ElemIndex=" << Info.ElementIndex;
46    } else if (isDefined()) {
47      Out << ", Segment=" << Info.DataRef.Segment;
48      Out << ", Offset=" << Info.DataRef.Offset;
49      Out << ", Size=" << Info.DataRef.Size;
50    }
51  }
52  
53  #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
54  LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
55  #endif
56  
57  Expected<std::unique_ptr<WasmObjectFile>>
58  ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
59    Error Err = Error::success();
60    auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
61    if (Err)
62      return std::move(Err);
63  
64    return std::move(ObjectFile);
65  }
66  
67  #define VARINT7_MAX ((1 << 7) - 1)
68  #define VARINT7_MIN (-(1 << 7))
69  #define VARUINT7_MAX (1 << 7)
70  #define VARUINT1_MAX (1)
71  
72  static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
73    if (Ctx.Ptr == Ctx.End)
74      report_fatal_error("EOF while reading uint8");
75    return *Ctx.Ptr++;
76  }
77  
78  static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
79    if (Ctx.Ptr + 4 > Ctx.End)
80      report_fatal_error("EOF while reading uint32");
81    uint32_t Result = support::endian::read32le(Ctx.Ptr);
82    Ctx.Ptr += 4;
83    return Result;
84  }
85  
86  static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
87    if (Ctx.Ptr + 4 > Ctx.End)
88      report_fatal_error("EOF while reading float64");
89    int32_t Result = 0;
90    memcpy(&Result, Ctx.Ptr, sizeof(Result));
91    Ctx.Ptr += sizeof(Result);
92    return Result;
93  }
94  
95  static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
96    if (Ctx.Ptr + 8 > Ctx.End)
97      report_fatal_error("EOF while reading float64");
98    int64_t Result = 0;
99    memcpy(&Result, Ctx.Ptr, sizeof(Result));
100    Ctx.Ptr += sizeof(Result);
101    return Result;
102  }
103  
104  static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
105    unsigned Count;
106    const char *Error = nullptr;
107    uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
108    if (Error)
109      report_fatal_error(Error);
110    Ctx.Ptr += Count;
111    return Result;
112  }
113  
114  static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
115    uint32_t StringLen = readULEB128(Ctx);
116    if (Ctx.Ptr + StringLen > Ctx.End)
117      report_fatal_error("EOF while reading string");
118    StringRef Return =
119        StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
120    Ctx.Ptr += StringLen;
121    return Return;
122  }
123  
124  static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
125    unsigned Count;
126    const char *Error = nullptr;
127    uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
128    if (Error)
129      report_fatal_error(Error);
130    Ctx.Ptr += Count;
131    return Result;
132  }
133  
134  static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
135    int64_t Result = readLEB128(Ctx);
136    if (Result > VARUINT1_MAX || Result < 0)
137      report_fatal_error("LEB is outside Varuint1 range");
138    return Result;
139  }
140  
141  static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
142    int64_t Result = readLEB128(Ctx);
143    if (Result > INT32_MAX || Result < INT32_MIN)
144      report_fatal_error("LEB is outside Varint32 range");
145    return Result;
146  }
147  
148  static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
149    uint64_t Result = readULEB128(Ctx);
150    if (Result > UINT32_MAX)
151      report_fatal_error("LEB is outside Varuint32 range");
152    return Result;
153  }
154  
155  static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
156    return readLEB128(Ctx);
157  }
158  
159  static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
160    return readULEB128(Ctx);
161  }
162  
163  static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
164    return readUint8(Ctx);
165  }
166  
167  static Error readInitExpr(wasm::WasmInitExpr &Expr,
168                            WasmObjectFile::ReadContext &Ctx) {
169    Expr.Opcode = readOpcode(Ctx);
170  
171    switch (Expr.Opcode) {
172    case wasm::WASM_OPCODE_I32_CONST:
173      Expr.Value.Int32 = readVarint32(Ctx);
174      break;
175    case wasm::WASM_OPCODE_I64_CONST:
176      Expr.Value.Int64 = readVarint64(Ctx);
177      break;
178    case wasm::WASM_OPCODE_F32_CONST:
179      Expr.Value.Float32 = readFloat32(Ctx);
180      break;
181    case wasm::WASM_OPCODE_F64_CONST:
182      Expr.Value.Float64 = readFloat64(Ctx);
183      break;
184    case wasm::WASM_OPCODE_GLOBAL_GET:
185      Expr.Value.Global = readULEB128(Ctx);
186      break;
187    case wasm::WASM_OPCODE_REF_NULL: {
188      wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
189      if (Ty != wasm::ValType::EXTERNREF) {
190        return make_error<GenericBinaryError>("Invalid type for ref.null",
191                                              object_error::parse_failed);
192      }
193      break;
194    }
195    default:
196      return make_error<GenericBinaryError>("Invalid opcode in init_expr",
197                                            object_error::parse_failed);
198    }
199  
200    uint8_t EndOpcode = readOpcode(Ctx);
201    if (EndOpcode != wasm::WASM_OPCODE_END) {
202      return make_error<GenericBinaryError>("Invalid init_expr",
203                                            object_error::parse_failed);
204    }
205    return Error::success();
206  }
207  
208  static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
209    wasm::WasmLimits Result;
210    Result.Flags = readVaruint32(Ctx);
211    Result.Initial = readVaruint64(Ctx);
212    if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
213      Result.Maximum = readVaruint64(Ctx);
214    return Result;
215  }
216  
217  static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
218    wasm::WasmTable Table;
219    Table.ElemType = readUint8(Ctx);
220    Table.Limits = readLimits(Ctx);
221    return Table;
222  }
223  
224  static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
225                           WasmSectionOrderChecker &Checker) {
226    Section.Offset = Ctx.Ptr - Ctx.Start;
227    Section.Type = readUint8(Ctx);
228    LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
229    uint32_t Size = readVaruint32(Ctx);
230    if (Size == 0)
231      return make_error<StringError>("Zero length section",
232                                     object_error::parse_failed);
233    if (Ctx.Ptr + Size > Ctx.End)
234      return make_error<StringError>("Section too large",
235                                     object_error::parse_failed);
236    if (Section.Type == wasm::WASM_SEC_CUSTOM) {
237      WasmObjectFile::ReadContext SectionCtx;
238      SectionCtx.Start = Ctx.Ptr;
239      SectionCtx.Ptr = Ctx.Ptr;
240      SectionCtx.End = Ctx.Ptr + Size;
241  
242      Section.Name = readString(SectionCtx);
243  
244      uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
245      Ctx.Ptr += SectionNameSize;
246      Size -= SectionNameSize;
247    }
248  
249    if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
250      return make_error<StringError>("Out of order section type: " +
251                                         llvm::to_string(Section.Type),
252                                     object_error::parse_failed);
253    }
254  
255    Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
256    Ctx.Ptr += Size;
257    return Error::success();
258  }
259  
260  WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
261      : ObjectFile(Binary::ID_Wasm, Buffer) {
262    ErrorAsOutParameter ErrAsOutParam(&Err);
263    Header.Magic = getData().substr(0, 4);
264    if (Header.Magic != StringRef("\0asm", 4)) {
265      Err =
266          make_error<StringError>("Bad magic number", object_error::parse_failed);
267      return;
268    }
269  
270    ReadContext Ctx;
271    Ctx.Start = getData().bytes_begin();
272    Ctx.Ptr = Ctx.Start + 4;
273    Ctx.End = Ctx.Start + getData().size();
274  
275    if (Ctx.Ptr + 4 > Ctx.End) {
276      Err = make_error<StringError>("Missing version number",
277                                    object_error::parse_failed);
278      return;
279    }
280  
281    Header.Version = readUint32(Ctx);
282    if (Header.Version != wasm::WasmVersion) {
283      Err = make_error<StringError>("Bad version number",
284                                    object_error::parse_failed);
285      return;
286    }
287  
288    WasmSection Sec;
289    WasmSectionOrderChecker Checker;
290    while (Ctx.Ptr < Ctx.End) {
291      if ((Err = readSection(Sec, Ctx, Checker)))
292        return;
293      if ((Err = parseSection(Sec)))
294        return;
295  
296      Sections.push_back(Sec);
297    }
298  }
299  
300  Error WasmObjectFile::parseSection(WasmSection &Sec) {
301    ReadContext Ctx;
302    Ctx.Start = Sec.Content.data();
303    Ctx.End = Ctx.Start + Sec.Content.size();
304    Ctx.Ptr = Ctx.Start;
305    switch (Sec.Type) {
306    case wasm::WASM_SEC_CUSTOM:
307      return parseCustomSection(Sec, Ctx);
308    case wasm::WASM_SEC_TYPE:
309      return parseTypeSection(Ctx);
310    case wasm::WASM_SEC_IMPORT:
311      return parseImportSection(Ctx);
312    case wasm::WASM_SEC_FUNCTION:
313      return parseFunctionSection(Ctx);
314    case wasm::WASM_SEC_TABLE:
315      return parseTableSection(Ctx);
316    case wasm::WASM_SEC_MEMORY:
317      return parseMemorySection(Ctx);
318    case wasm::WASM_SEC_EVENT:
319      return parseEventSection(Ctx);
320    case wasm::WASM_SEC_GLOBAL:
321      return parseGlobalSection(Ctx);
322    case wasm::WASM_SEC_EXPORT:
323      return parseExportSection(Ctx);
324    case wasm::WASM_SEC_START:
325      return parseStartSection(Ctx);
326    case wasm::WASM_SEC_ELEM:
327      return parseElemSection(Ctx);
328    case wasm::WASM_SEC_CODE:
329      return parseCodeSection(Ctx);
330    case wasm::WASM_SEC_DATA:
331      return parseDataSection(Ctx);
332    case wasm::WASM_SEC_DATACOUNT:
333      return parseDataCountSection(Ctx);
334    default:
335      return make_error<GenericBinaryError>(
336          "Invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
337    }
338  }
339  
340  Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
341    // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
342    HasDylinkSection = true;
343    DylinkInfo.MemorySize = readVaruint32(Ctx);
344    DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
345    DylinkInfo.TableSize = readVaruint32(Ctx);
346    DylinkInfo.TableAlignment = readVaruint32(Ctx);
347    uint32_t Count = readVaruint32(Ctx);
348    while (Count--) {
349      DylinkInfo.Needed.push_back(readString(Ctx));
350    }
351    if (Ctx.Ptr != Ctx.End)
352      return make_error<GenericBinaryError>("dylink section ended prematurely",
353                                            object_error::parse_failed);
354    return Error::success();
355  }
356  
357  Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
358    llvm::DenseSet<uint64_t> Seen;
359    if (FunctionTypes.size() && !SeenCodeSection) {
360      return make_error<GenericBinaryError>("Names must come after code section",
361                                            object_error::parse_failed);
362    }
363  
364    while (Ctx.Ptr < Ctx.End) {
365      uint8_t Type = readUint8(Ctx);
366      uint32_t Size = readVaruint32(Ctx);
367      const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
368      switch (Type) {
369      case wasm::WASM_NAMES_FUNCTION: {
370        uint32_t Count = readVaruint32(Ctx);
371        while (Count--) {
372          uint32_t Index = readVaruint32(Ctx);
373          if (!Seen.insert(Index).second)
374            return make_error<GenericBinaryError>("Function named more than once",
375                                                  object_error::parse_failed);
376          StringRef Name = readString(Ctx);
377          if (!isValidFunctionIndex(Index) || Name.empty())
378            return make_error<GenericBinaryError>("Invalid name entry",
379                                                  object_error::parse_failed);
380          DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
381          if (isDefinedFunctionIndex(Index))
382            getDefinedFunction(Index).DebugName = Name;
383        }
384        break;
385      }
386      // Ignore local names for now
387      case wasm::WASM_NAMES_LOCAL:
388      default:
389        Ctx.Ptr += Size;
390        break;
391      }
392      if (Ctx.Ptr != SubSectionEnd)
393        return make_error<GenericBinaryError>(
394            "Name sub-section ended prematurely", object_error::parse_failed);
395    }
396  
397    if (Ctx.Ptr != Ctx.End)
398      return make_error<GenericBinaryError>("Name section ended prematurely",
399                                            object_error::parse_failed);
400    return Error::success();
401  }
402  
403  Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
404    HasLinkingSection = true;
405    if (FunctionTypes.size() && !SeenCodeSection) {
406      return make_error<GenericBinaryError>(
407          "Linking data must come after code section",
408          object_error::parse_failed);
409    }
410  
411    LinkingData.Version = readVaruint32(Ctx);
412    if (LinkingData.Version != wasm::WasmMetadataVersion) {
413      return make_error<GenericBinaryError>(
414          "Unexpected metadata version: " + Twine(LinkingData.Version) +
415              " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
416          object_error::parse_failed);
417    }
418  
419    const uint8_t *OrigEnd = Ctx.End;
420    while (Ctx.Ptr < OrigEnd) {
421      Ctx.End = OrigEnd;
422      uint8_t Type = readUint8(Ctx);
423      uint32_t Size = readVaruint32(Ctx);
424      LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
425                        << "\n");
426      Ctx.End = Ctx.Ptr + Size;
427      switch (Type) {
428      case wasm::WASM_SYMBOL_TABLE:
429        if (Error Err = parseLinkingSectionSymtab(Ctx))
430          return Err;
431        break;
432      case wasm::WASM_SEGMENT_INFO: {
433        uint32_t Count = readVaruint32(Ctx);
434        if (Count > DataSegments.size())
435          return make_error<GenericBinaryError>("Too many segment names",
436                                                object_error::parse_failed);
437        for (uint32_t I = 0; I < Count; I++) {
438          DataSegments[I].Data.Name = readString(Ctx);
439          DataSegments[I].Data.Alignment = readVaruint32(Ctx);
440          DataSegments[I].Data.LinkerFlags = readVaruint32(Ctx);
441        }
442        break;
443      }
444      case wasm::WASM_INIT_FUNCS: {
445        uint32_t Count = readVaruint32(Ctx);
446        LinkingData.InitFunctions.reserve(Count);
447        for (uint32_t I = 0; I < Count; I++) {
448          wasm::WasmInitFunc Init;
449          Init.Priority = readVaruint32(Ctx);
450          Init.Symbol = readVaruint32(Ctx);
451          if (!isValidFunctionSymbol(Init.Symbol))
452            return make_error<GenericBinaryError>("Invalid function symbol: " +
453                                                      Twine(Init.Symbol),
454                                                  object_error::parse_failed);
455          LinkingData.InitFunctions.emplace_back(Init);
456        }
457        break;
458      }
459      case wasm::WASM_COMDAT_INFO:
460        if (Error Err = parseLinkingSectionComdat(Ctx))
461          return Err;
462        break;
463      default:
464        Ctx.Ptr += Size;
465        break;
466      }
467      if (Ctx.Ptr != Ctx.End)
468        return make_error<GenericBinaryError>(
469            "Linking sub-section ended prematurely", object_error::parse_failed);
470    }
471    if (Ctx.Ptr != OrigEnd)
472      return make_error<GenericBinaryError>("Linking section ended prematurely",
473                                            object_error::parse_failed);
474    return Error::success();
475  }
476  
477  Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
478    uint32_t Count = readVaruint32(Ctx);
479    LinkingData.SymbolTable.reserve(Count);
480    Symbols.reserve(Count);
481    StringSet<> SymbolNames;
482  
483    std::vector<wasm::WasmImport *> ImportedGlobals;
484    std::vector<wasm::WasmImport *> ImportedFunctions;
485    std::vector<wasm::WasmImport *> ImportedEvents;
486    ImportedGlobals.reserve(Imports.size());
487    ImportedFunctions.reserve(Imports.size());
488    ImportedEvents.reserve(Imports.size());
489    for (auto &I : Imports) {
490      if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
491        ImportedFunctions.emplace_back(&I);
492      else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
493        ImportedGlobals.emplace_back(&I);
494      else if (I.Kind == wasm::WASM_EXTERNAL_EVENT)
495        ImportedEvents.emplace_back(&I);
496    }
497  
498    while (Count--) {
499      wasm::WasmSymbolInfo Info;
500      const wasm::WasmSignature *Signature = nullptr;
501      const wasm::WasmGlobalType *GlobalType = nullptr;
502      const wasm::WasmEventType *EventType = nullptr;
503  
504      Info.Kind = readUint8(Ctx);
505      Info.Flags = readVaruint32(Ctx);
506      bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
507  
508      switch (Info.Kind) {
509      case wasm::WASM_SYMBOL_TYPE_FUNCTION:
510        Info.ElementIndex = readVaruint32(Ctx);
511        if (!isValidFunctionIndex(Info.ElementIndex) ||
512            IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
513          return make_error<GenericBinaryError>("invalid function symbol index",
514                                                object_error::parse_failed);
515        if (IsDefined) {
516          Info.Name = readString(Ctx);
517          unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
518          Signature = &Signatures[FunctionTypes[FuncIndex]];
519          wasm::WasmFunction &Function = Functions[FuncIndex];
520          if (Function.SymbolName.empty())
521            Function.SymbolName = Info.Name;
522        } else {
523          wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
524          if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
525            Info.Name = readString(Ctx);
526            Info.ImportName = Import.Field;
527          } else {
528            Info.Name = Import.Field;
529          }
530          Signature = &Signatures[Import.SigIndex];
531          if (!Import.Module.empty()) {
532            Info.ImportModule = Import.Module;
533          }
534        }
535        break;
536  
537      case wasm::WASM_SYMBOL_TYPE_GLOBAL:
538        Info.ElementIndex = readVaruint32(Ctx);
539        if (!isValidGlobalIndex(Info.ElementIndex) ||
540            IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
541          return make_error<GenericBinaryError>("invalid global symbol index",
542                                                object_error::parse_failed);
543        if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
544                              wasm::WASM_SYMBOL_BINDING_WEAK)
545          return make_error<GenericBinaryError>("undefined weak global symbol",
546                                                object_error::parse_failed);
547        if (IsDefined) {
548          Info.Name = readString(Ctx);
549          unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
550          wasm::WasmGlobal &Global = Globals[GlobalIndex];
551          GlobalType = &Global.Type;
552          if (Global.SymbolName.empty())
553            Global.SymbolName = Info.Name;
554        } else {
555          wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
556          if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
557            Info.Name = readString(Ctx);
558            Info.ImportName = Import.Field;
559          } else {
560            Info.Name = Import.Field;
561          }
562          GlobalType = &Import.Global;
563          Info.ImportName = Import.Field;
564          if (!Import.Module.empty()) {
565            Info.ImportModule = Import.Module;
566          }
567        }
568        break;
569  
570      case wasm::WASM_SYMBOL_TYPE_DATA:
571        Info.Name = readString(Ctx);
572        if (IsDefined) {
573          auto Index = readVaruint32(Ctx);
574          if (Index >= DataSegments.size())
575            return make_error<GenericBinaryError>("invalid data symbol index",
576                                                  object_error::parse_failed);
577          auto Offset = readVaruint64(Ctx);
578          auto Size = readVaruint64(Ctx);
579          if (Offset + Size > DataSegments[Index].Data.Content.size())
580            return make_error<GenericBinaryError>("invalid data symbol offset",
581                                                  object_error::parse_failed);
582          Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
583        }
584        break;
585  
586      case wasm::WASM_SYMBOL_TYPE_SECTION: {
587        if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
588            wasm::WASM_SYMBOL_BINDING_LOCAL)
589          return make_error<GenericBinaryError>(
590              "Section symbols must have local binding",
591              object_error::parse_failed);
592        Info.ElementIndex = readVaruint32(Ctx);
593        // Use somewhat unique section name as symbol name.
594        StringRef SectionName = Sections[Info.ElementIndex].Name;
595        Info.Name = SectionName;
596        break;
597      }
598  
599      case wasm::WASM_SYMBOL_TYPE_EVENT: {
600        Info.ElementIndex = readVaruint32(Ctx);
601        if (!isValidEventIndex(Info.ElementIndex) ||
602            IsDefined != isDefinedEventIndex(Info.ElementIndex))
603          return make_error<GenericBinaryError>("invalid event symbol index",
604                                                object_error::parse_failed);
605        if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
606                              wasm::WASM_SYMBOL_BINDING_WEAK)
607          return make_error<GenericBinaryError>("undefined weak global symbol",
608                                                object_error::parse_failed);
609        if (IsDefined) {
610          Info.Name = readString(Ctx);
611          unsigned EventIndex = Info.ElementIndex - NumImportedEvents;
612          wasm::WasmEvent &Event = Events[EventIndex];
613          Signature = &Signatures[Event.Type.SigIndex];
614          EventType = &Event.Type;
615          if (Event.SymbolName.empty())
616            Event.SymbolName = Info.Name;
617  
618        } else {
619          wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
620          if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
621            Info.Name = readString(Ctx);
622            Info.ImportName = Import.Field;
623          } else {
624            Info.Name = Import.Field;
625          }
626          EventType = &Import.Event;
627          Signature = &Signatures[EventType->SigIndex];
628          if (!Import.Module.empty()) {
629            Info.ImportModule = Import.Module;
630          }
631        }
632        break;
633      }
634  
635      default:
636        return make_error<GenericBinaryError>("Invalid symbol type",
637                                              object_error::parse_failed);
638      }
639  
640      if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
641              wasm::WASM_SYMBOL_BINDING_LOCAL &&
642          !SymbolNames.insert(Info.Name).second)
643        return make_error<GenericBinaryError>("Duplicate symbol name " +
644                                                  Twine(Info.Name),
645                                              object_error::parse_failed);
646      LinkingData.SymbolTable.emplace_back(Info);
647      Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, EventType,
648                           Signature);
649      LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
650    }
651  
652    return Error::success();
653  }
654  
655  Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
656    uint32_t ComdatCount = readVaruint32(Ctx);
657    StringSet<> ComdatSet;
658    for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
659      StringRef Name = readString(Ctx);
660      if (Name.empty() || !ComdatSet.insert(Name).second)
661        return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
662                                                  Twine(Name),
663                                              object_error::parse_failed);
664      LinkingData.Comdats.emplace_back(Name);
665      uint32_t Flags = readVaruint32(Ctx);
666      if (Flags != 0)
667        return make_error<GenericBinaryError>("Unsupported COMDAT flags",
668                                              object_error::parse_failed);
669  
670      uint32_t EntryCount = readVaruint32(Ctx);
671      while (EntryCount--) {
672        unsigned Kind = readVaruint32(Ctx);
673        unsigned Index = readVaruint32(Ctx);
674        switch (Kind) {
675        default:
676          return make_error<GenericBinaryError>("Invalid COMDAT entry type",
677                                                object_error::parse_failed);
678        case wasm::WASM_COMDAT_DATA:
679          if (Index >= DataSegments.size())
680            return make_error<GenericBinaryError>(
681                "COMDAT data index out of range", object_error::parse_failed);
682          if (DataSegments[Index].Data.Comdat != UINT32_MAX)
683            return make_error<GenericBinaryError>("Data segment in two COMDATs",
684                                                  object_error::parse_failed);
685          DataSegments[Index].Data.Comdat = ComdatIndex;
686          break;
687        case wasm::WASM_COMDAT_FUNCTION:
688          if (!isDefinedFunctionIndex(Index))
689            return make_error<GenericBinaryError>(
690                "COMDAT function index out of range", object_error::parse_failed);
691          if (getDefinedFunction(Index).Comdat != UINT32_MAX)
692            return make_error<GenericBinaryError>("Function in two COMDATs",
693                                                  object_error::parse_failed);
694          getDefinedFunction(Index).Comdat = ComdatIndex;
695          break;
696        }
697      }
698    }
699    return Error::success();
700  }
701  
702  Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
703    llvm::SmallSet<StringRef, 3> FieldsSeen;
704    uint32_t Fields = readVaruint32(Ctx);
705    for (size_t I = 0; I < Fields; ++I) {
706      StringRef FieldName = readString(Ctx);
707      if (!FieldsSeen.insert(FieldName).second)
708        return make_error<GenericBinaryError>(
709            "Producers section does not have unique fields",
710            object_error::parse_failed);
711      std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
712      if (FieldName == "language") {
713        ProducerVec = &ProducerInfo.Languages;
714      } else if (FieldName == "processed-by") {
715        ProducerVec = &ProducerInfo.Tools;
716      } else if (FieldName == "sdk") {
717        ProducerVec = &ProducerInfo.SDKs;
718      } else {
719        return make_error<GenericBinaryError>(
720            "Producers section field is not named one of language, processed-by, "
721            "or sdk",
722            object_error::parse_failed);
723      }
724      uint32_t ValueCount = readVaruint32(Ctx);
725      llvm::SmallSet<StringRef, 8> ProducersSeen;
726      for (size_t J = 0; J < ValueCount; ++J) {
727        StringRef Name = readString(Ctx);
728        StringRef Version = readString(Ctx);
729        if (!ProducersSeen.insert(Name).second) {
730          return make_error<GenericBinaryError>(
731              "Producers section contains repeated producer",
732              object_error::parse_failed);
733        }
734        ProducerVec->emplace_back(std::string(Name), std::string(Version));
735      }
736    }
737    if (Ctx.Ptr != Ctx.End)
738      return make_error<GenericBinaryError>("Producers section ended prematurely",
739                                            object_error::parse_failed);
740    return Error::success();
741  }
742  
743  Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
744    llvm::SmallSet<std::string, 8> FeaturesSeen;
745    uint32_t FeatureCount = readVaruint32(Ctx);
746    for (size_t I = 0; I < FeatureCount; ++I) {
747      wasm::WasmFeatureEntry Feature;
748      Feature.Prefix = readUint8(Ctx);
749      switch (Feature.Prefix) {
750      case wasm::WASM_FEATURE_PREFIX_USED:
751      case wasm::WASM_FEATURE_PREFIX_REQUIRED:
752      case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
753        break;
754      default:
755        return make_error<GenericBinaryError>("Unknown feature policy prefix",
756                                              object_error::parse_failed);
757      }
758      Feature.Name = std::string(readString(Ctx));
759      if (!FeaturesSeen.insert(Feature.Name).second)
760        return make_error<GenericBinaryError>(
761            "Target features section contains repeated feature \"" +
762                Feature.Name + "\"",
763            object_error::parse_failed);
764      TargetFeatures.push_back(Feature);
765    }
766    if (Ctx.Ptr != Ctx.End)
767      return make_error<GenericBinaryError>(
768          "Target features section ended prematurely",
769          object_error::parse_failed);
770    return Error::success();
771  }
772  
773  Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
774    uint32_t SectionIndex = readVaruint32(Ctx);
775    if (SectionIndex >= Sections.size())
776      return make_error<GenericBinaryError>("Invalid section index",
777                                            object_error::parse_failed);
778    WasmSection &Section = Sections[SectionIndex];
779    uint32_t RelocCount = readVaruint32(Ctx);
780    uint32_t EndOffset = Section.Content.size();
781    uint32_t PreviousOffset = 0;
782    while (RelocCount--) {
783      wasm::WasmRelocation Reloc = {};
784      Reloc.Type = readVaruint32(Ctx);
785      Reloc.Offset = readVaruint32(Ctx);
786      if (Reloc.Offset < PreviousOffset)
787        return make_error<GenericBinaryError>("Relocations not in offset order",
788                                              object_error::parse_failed);
789      PreviousOffset = Reloc.Offset;
790      Reloc.Index = readVaruint32(Ctx);
791      switch (Reloc.Type) {
792      case wasm::R_WASM_FUNCTION_INDEX_LEB:
793      case wasm::R_WASM_TABLE_INDEX_SLEB:
794      case wasm::R_WASM_TABLE_INDEX_I32:
795      case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
796        if (!isValidFunctionSymbol(Reloc.Index))
797          return make_error<GenericBinaryError>("Bad relocation function index",
798                                                object_error::parse_failed);
799        break;
800      case wasm::R_WASM_TYPE_INDEX_LEB:
801        if (Reloc.Index >= Signatures.size())
802          return make_error<GenericBinaryError>("Bad relocation type index",
803                                                object_error::parse_failed);
804        break;
805      case wasm::R_WASM_GLOBAL_INDEX_LEB:
806        // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
807        // symbols to refer to their GOT entries.
808        if (!isValidGlobalSymbol(Reloc.Index) &&
809            !isValidDataSymbol(Reloc.Index) &&
810            !isValidFunctionSymbol(Reloc.Index))
811          return make_error<GenericBinaryError>("Bad relocation global index",
812                                                object_error::parse_failed);
813        break;
814      case wasm::R_WASM_GLOBAL_INDEX_I32:
815        if (!isValidGlobalSymbol(Reloc.Index))
816          return make_error<GenericBinaryError>("Bad relocation global index",
817                                                object_error::parse_failed);
818        break;
819      case wasm::R_WASM_EVENT_INDEX_LEB:
820        if (!isValidEventSymbol(Reloc.Index))
821          return make_error<GenericBinaryError>("Bad relocation event index",
822                                                object_error::parse_failed);
823        break;
824      case wasm::R_WASM_MEMORY_ADDR_LEB:
825      case wasm::R_WASM_MEMORY_ADDR_SLEB:
826      case wasm::R_WASM_MEMORY_ADDR_I32:
827      case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
828        if (!isValidDataSymbol(Reloc.Index))
829          return make_error<GenericBinaryError>("Bad relocation data index",
830                                                object_error::parse_failed);
831        Reloc.Addend = readVarint32(Ctx);
832        break;
833      case wasm::R_WASM_MEMORY_ADDR_LEB64:
834      case wasm::R_WASM_MEMORY_ADDR_SLEB64:
835      case wasm::R_WASM_MEMORY_ADDR_I64:
836      case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
837        if (!isValidDataSymbol(Reloc.Index))
838          return make_error<GenericBinaryError>("Bad relocation data index",
839                                                object_error::parse_failed);
840        Reloc.Addend = readVarint64(Ctx);
841        break;
842      case wasm::R_WASM_FUNCTION_OFFSET_I32:
843        if (!isValidFunctionSymbol(Reloc.Index))
844          return make_error<GenericBinaryError>("Bad relocation function index",
845                                                object_error::parse_failed);
846        Reloc.Addend = readVarint32(Ctx);
847        break;
848      case wasm::R_WASM_SECTION_OFFSET_I32:
849        if (!isValidSectionSymbol(Reloc.Index))
850          return make_error<GenericBinaryError>("Bad relocation section index",
851                                                object_error::parse_failed);
852        Reloc.Addend = readVarint32(Ctx);
853        break;
854      default:
855        return make_error<GenericBinaryError>("Bad relocation type: " +
856                                                  Twine(Reloc.Type),
857                                              object_error::parse_failed);
858      }
859  
860      // Relocations must fit inside the section, and must appear in order.  They
861      // also shouldn't overlap a function/element boundary, but we don't bother
862      // to check that.
863      uint64_t Size = 5;
864      if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
865          Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
866          Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
867        Size = 10;
868      if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
869          Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
870          Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
871          Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
872          Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
873        Size = 4;
874      if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64)
875        Size = 8;
876      if (Reloc.Offset + Size > EndOffset)
877        return make_error<GenericBinaryError>("Bad relocation offset",
878                                              object_error::parse_failed);
879  
880      Section.Relocations.push_back(Reloc);
881    }
882    if (Ctx.Ptr != Ctx.End)
883      return make_error<GenericBinaryError>("Reloc section ended prematurely",
884                                            object_error::parse_failed);
885    return Error::success();
886  }
887  
888  Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
889    if (Sec.Name == "dylink") {
890      if (Error Err = parseDylinkSection(Ctx))
891        return Err;
892    } else if (Sec.Name == "name") {
893      if (Error Err = parseNameSection(Ctx))
894        return Err;
895    } else if (Sec.Name == "linking") {
896      if (Error Err = parseLinkingSection(Ctx))
897        return Err;
898    } else if (Sec.Name == "producers") {
899      if (Error Err = parseProducersSection(Ctx))
900        return Err;
901    } else if (Sec.Name == "target_features") {
902      if (Error Err = parseTargetFeaturesSection(Ctx))
903        return Err;
904    } else if (Sec.Name.startswith("reloc.")) {
905      if (Error Err = parseRelocSection(Sec.Name, Ctx))
906        return Err;
907    }
908    return Error::success();
909  }
910  
911  Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
912    uint32_t Count = readVaruint32(Ctx);
913    Signatures.reserve(Count);
914    while (Count--) {
915      wasm::WasmSignature Sig;
916      uint8_t Form = readUint8(Ctx);
917      if (Form != wasm::WASM_TYPE_FUNC) {
918        return make_error<GenericBinaryError>("Invalid signature type",
919                                              object_error::parse_failed);
920      }
921      uint32_t ParamCount = readVaruint32(Ctx);
922      Sig.Params.reserve(ParamCount);
923      while (ParamCount--) {
924        uint32_t ParamType = readUint8(Ctx);
925        Sig.Params.push_back(wasm::ValType(ParamType));
926      }
927      uint32_t ReturnCount = readVaruint32(Ctx);
928      while (ReturnCount--) {
929        uint32_t ReturnType = readUint8(Ctx);
930        Sig.Returns.push_back(wasm::ValType(ReturnType));
931      }
932      Signatures.push_back(std::move(Sig));
933    }
934    if (Ctx.Ptr != Ctx.End)
935      return make_error<GenericBinaryError>("Type section ended prematurely",
936                                            object_error::parse_failed);
937    return Error::success();
938  }
939  
940  Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
941    uint32_t Count = readVaruint32(Ctx);
942    Imports.reserve(Count);
943    for (uint32_t I = 0; I < Count; I++) {
944      wasm::WasmImport Im;
945      Im.Module = readString(Ctx);
946      Im.Field = readString(Ctx);
947      Im.Kind = readUint8(Ctx);
948      switch (Im.Kind) {
949      case wasm::WASM_EXTERNAL_FUNCTION:
950        NumImportedFunctions++;
951        Im.SigIndex = readVaruint32(Ctx);
952        break;
953      case wasm::WASM_EXTERNAL_GLOBAL:
954        NumImportedGlobals++;
955        Im.Global.Type = readUint8(Ctx);
956        Im.Global.Mutable = readVaruint1(Ctx);
957        break;
958      case wasm::WASM_EXTERNAL_MEMORY:
959        Im.Memory = readLimits(Ctx);
960        break;
961      case wasm::WASM_EXTERNAL_TABLE:
962        Im.Table = readTable(Ctx);
963        if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF)
964          return make_error<GenericBinaryError>("Invalid table element type",
965                                                object_error::parse_failed);
966        break;
967      case wasm::WASM_EXTERNAL_EVENT:
968        NumImportedEvents++;
969        Im.Event.Attribute = readVarint32(Ctx);
970        Im.Event.SigIndex = readVarint32(Ctx);
971        break;
972      default:
973        return make_error<GenericBinaryError>("Unexpected import kind",
974                                              object_error::parse_failed);
975      }
976      Imports.push_back(Im);
977    }
978    if (Ctx.Ptr != Ctx.End)
979      return make_error<GenericBinaryError>("Import section ended prematurely",
980                                            object_error::parse_failed);
981    return Error::success();
982  }
983  
984  Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
985    uint32_t Count = readVaruint32(Ctx);
986    FunctionTypes.reserve(Count);
987    Functions.resize(Count);
988    uint32_t NumTypes = Signatures.size();
989    while (Count--) {
990      uint32_t Type = readVaruint32(Ctx);
991      if (Type >= NumTypes)
992        return make_error<GenericBinaryError>("Invalid function type",
993                                              object_error::parse_failed);
994      FunctionTypes.push_back(Type);
995    }
996    if (Ctx.Ptr != Ctx.End)
997      return make_error<GenericBinaryError>("Function section ended prematurely",
998                                            object_error::parse_failed);
999    return Error::success();
1000  }
1001  
1002  Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1003    uint32_t Count = readVaruint32(Ctx);
1004    Tables.reserve(Count);
1005    while (Count--) {
1006      Tables.push_back(readTable(Ctx));
1007      if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) {
1008        return make_error<GenericBinaryError>("Invalid table element type",
1009                                              object_error::parse_failed);
1010      }
1011    }
1012    if (Ctx.Ptr != Ctx.End)
1013      return make_error<GenericBinaryError>("Table section ended prematurely",
1014                                            object_error::parse_failed);
1015    return Error::success();
1016  }
1017  
1018  Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1019    uint32_t Count = readVaruint32(Ctx);
1020    Memories.reserve(Count);
1021    while (Count--) {
1022      Memories.push_back(readLimits(Ctx));
1023    }
1024    if (Ctx.Ptr != Ctx.End)
1025      return make_error<GenericBinaryError>("Memory section ended prematurely",
1026                                            object_error::parse_failed);
1027    return Error::success();
1028  }
1029  
1030  Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
1031    EventSection = Sections.size();
1032    uint32_t Count = readVarint32(Ctx);
1033    Events.reserve(Count);
1034    while (Count--) {
1035      wasm::WasmEvent Event;
1036      Event.Index = NumImportedEvents + Events.size();
1037      Event.Type.Attribute = readVaruint32(Ctx);
1038      Event.Type.SigIndex = readVarint32(Ctx);
1039      Events.push_back(Event);
1040    }
1041  
1042    if (Ctx.Ptr != Ctx.End)
1043      return make_error<GenericBinaryError>("Event section ended prematurely",
1044                                            object_error::parse_failed);
1045    return Error::success();
1046  }
1047  
1048  Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1049    GlobalSection = Sections.size();
1050    uint32_t Count = readVaruint32(Ctx);
1051    Globals.reserve(Count);
1052    while (Count--) {
1053      wasm::WasmGlobal Global;
1054      Global.Index = NumImportedGlobals + Globals.size();
1055      Global.Type.Type = readUint8(Ctx);
1056      Global.Type.Mutable = readVaruint1(Ctx);
1057      if (Error Err = readInitExpr(Global.InitExpr, Ctx))
1058        return Err;
1059      Globals.push_back(Global);
1060    }
1061    if (Ctx.Ptr != Ctx.End)
1062      return make_error<GenericBinaryError>("Global section ended prematurely",
1063                                            object_error::parse_failed);
1064    return Error::success();
1065  }
1066  
1067  Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1068    uint32_t Count = readVaruint32(Ctx);
1069    Exports.reserve(Count);
1070    for (uint32_t I = 0; I < Count; I++) {
1071      wasm::WasmExport Ex;
1072      Ex.Name = readString(Ctx);
1073      Ex.Kind = readUint8(Ctx);
1074      Ex.Index = readVaruint32(Ctx);
1075      switch (Ex.Kind) {
1076      case wasm::WASM_EXTERNAL_FUNCTION:
1077  
1078        if (!isDefinedFunctionIndex(Ex.Index))
1079          return make_error<GenericBinaryError>("Invalid function export",
1080                                                object_error::parse_failed);
1081        getDefinedFunction(Ex.Index).ExportName = Ex.Name;
1082        break;
1083      case wasm::WASM_EXTERNAL_GLOBAL:
1084        if (!isValidGlobalIndex(Ex.Index))
1085          return make_error<GenericBinaryError>("Invalid global export",
1086                                                object_error::parse_failed);
1087        break;
1088      case wasm::WASM_EXTERNAL_EVENT:
1089        if (!isValidEventIndex(Ex.Index))
1090          return make_error<GenericBinaryError>("Invalid event export",
1091                                                object_error::parse_failed);
1092        break;
1093      case wasm::WASM_EXTERNAL_MEMORY:
1094      case wasm::WASM_EXTERNAL_TABLE:
1095        break;
1096      default:
1097        return make_error<GenericBinaryError>("Unexpected export kind",
1098                                              object_error::parse_failed);
1099      }
1100      Exports.push_back(Ex);
1101    }
1102    if (Ctx.Ptr != Ctx.End)
1103      return make_error<GenericBinaryError>("Export section ended prematurely",
1104                                            object_error::parse_failed);
1105    return Error::success();
1106  }
1107  
1108  bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1109    return Index < NumImportedFunctions + FunctionTypes.size();
1110  }
1111  
1112  bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1113    return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1114  }
1115  
1116  bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1117    return Index < NumImportedGlobals + Globals.size();
1118  }
1119  
1120  bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1121    return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1122  }
1123  
1124  bool WasmObjectFile::isValidEventIndex(uint32_t Index) const {
1125    return Index < NumImportedEvents + Events.size();
1126  }
1127  
1128  bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const {
1129    return Index >= NumImportedEvents && isValidEventIndex(Index);
1130  }
1131  
1132  bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1133    return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1134  }
1135  
1136  bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1137    return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1138  }
1139  
1140  bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const {
1141    return Index < Symbols.size() && Symbols[Index].isTypeEvent();
1142  }
1143  
1144  bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1145    return Index < Symbols.size() && Symbols[Index].isTypeData();
1146  }
1147  
1148  bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1149    return Index < Symbols.size() && Symbols[Index].isTypeSection();
1150  }
1151  
1152  wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1153    assert(isDefinedFunctionIndex(Index));
1154    return Functions[Index - NumImportedFunctions];
1155  }
1156  
1157  const wasm::WasmFunction &
1158  WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1159    assert(isDefinedFunctionIndex(Index));
1160    return Functions[Index - NumImportedFunctions];
1161  }
1162  
1163  wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
1164    assert(isDefinedGlobalIndex(Index));
1165    return Globals[Index - NumImportedGlobals];
1166  }
1167  
1168  wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) {
1169    assert(isDefinedEventIndex(Index));
1170    return Events[Index - NumImportedEvents];
1171  }
1172  
1173  Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1174    StartFunction = readVaruint32(Ctx);
1175    if (!isValidFunctionIndex(StartFunction))
1176      return make_error<GenericBinaryError>("Invalid start function",
1177                                            object_error::parse_failed);
1178    return Error::success();
1179  }
1180  
1181  Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1182    SeenCodeSection = true;
1183    CodeSection = Sections.size();
1184    uint32_t FunctionCount = readVaruint32(Ctx);
1185    if (FunctionCount != FunctionTypes.size()) {
1186      return make_error<GenericBinaryError>("Invalid function count",
1187                                            object_error::parse_failed);
1188    }
1189  
1190    for (uint32_t i = 0; i < FunctionCount; i++) {
1191      wasm::WasmFunction& Function = Functions[i];
1192      const uint8_t *FunctionStart = Ctx.Ptr;
1193      uint32_t Size = readVaruint32(Ctx);
1194      const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1195  
1196      Function.CodeOffset = Ctx.Ptr - FunctionStart;
1197      Function.Index = NumImportedFunctions + i;
1198      Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1199      Function.Size = FunctionEnd - FunctionStart;
1200  
1201      uint32_t NumLocalDecls = readVaruint32(Ctx);
1202      Function.Locals.reserve(NumLocalDecls);
1203      while (NumLocalDecls--) {
1204        wasm::WasmLocalDecl Decl;
1205        Decl.Count = readVaruint32(Ctx);
1206        Decl.Type = readUint8(Ctx);
1207        Function.Locals.push_back(Decl);
1208      }
1209  
1210      uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1211      Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1212      // This will be set later when reading in the linking metadata section.
1213      Function.Comdat = UINT32_MAX;
1214      Ctx.Ptr += BodySize;
1215      assert(Ctx.Ptr == FunctionEnd);
1216    }
1217    if (Ctx.Ptr != Ctx.End)
1218      return make_error<GenericBinaryError>("Code section ended prematurely",
1219                                            object_error::parse_failed);
1220    return Error::success();
1221  }
1222  
1223  Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1224    uint32_t Count = readVaruint32(Ctx);
1225    ElemSegments.reserve(Count);
1226    while (Count--) {
1227      wasm::WasmElemSegment Segment;
1228      Segment.TableIndex = readVaruint32(Ctx);
1229      if (Segment.TableIndex != 0) {
1230        return make_error<GenericBinaryError>("Invalid TableIndex",
1231                                              object_error::parse_failed);
1232      }
1233      if (Error Err = readInitExpr(Segment.Offset, Ctx))
1234        return Err;
1235      uint32_t NumElems = readVaruint32(Ctx);
1236      while (NumElems--) {
1237        Segment.Functions.push_back(readVaruint32(Ctx));
1238      }
1239      ElemSegments.push_back(Segment);
1240    }
1241    if (Ctx.Ptr != Ctx.End)
1242      return make_error<GenericBinaryError>("Elem section ended prematurely",
1243                                            object_error::parse_failed);
1244    return Error::success();
1245  }
1246  
1247  Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1248    DataSection = Sections.size();
1249    uint32_t Count = readVaruint32(Ctx);
1250    if (DataCount && Count != DataCount.getValue())
1251      return make_error<GenericBinaryError>(
1252          "Number of data segments does not match DataCount section");
1253    DataSegments.reserve(Count);
1254    while (Count--) {
1255      WasmSegment Segment;
1256      Segment.Data.InitFlags = readVaruint32(Ctx);
1257      Segment.Data.MemoryIndex = (Segment.Data.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
1258                                 ? readVaruint32(Ctx) : 0;
1259      if ((Segment.Data.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) {
1260        if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1261          return Err;
1262      } else {
1263        Segment.Data.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST;
1264        Segment.Data.Offset.Value.Int32 = 0;
1265      }
1266      uint32_t Size = readVaruint32(Ctx);
1267      if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1268        return make_error<GenericBinaryError>("Invalid segment size",
1269                                              object_error::parse_failed);
1270      Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1271      // The rest of these Data fields are set later, when reading in the linking
1272      // metadata section.
1273      Segment.Data.Alignment = 0;
1274      Segment.Data.LinkerFlags = 0;
1275      Segment.Data.Comdat = UINT32_MAX;
1276      Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1277      Ctx.Ptr += Size;
1278      DataSegments.push_back(Segment);
1279    }
1280    if (Ctx.Ptr != Ctx.End)
1281      return make_error<GenericBinaryError>("Data section ended prematurely",
1282                                            object_error::parse_failed);
1283    return Error::success();
1284  }
1285  
1286  Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1287    DataCount = readVaruint32(Ctx);
1288    return Error::success();
1289  }
1290  
1291  const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1292    return Header;
1293  }
1294  
1295  void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1296  
1297  Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1298    uint32_t Result = SymbolRef::SF_None;
1299    const WasmSymbol &Sym = getWasmSymbol(Symb);
1300  
1301    LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1302    if (Sym.isBindingWeak())
1303      Result |= SymbolRef::SF_Weak;
1304    if (!Sym.isBindingLocal())
1305      Result |= SymbolRef::SF_Global;
1306    if (Sym.isHidden())
1307      Result |= SymbolRef::SF_Hidden;
1308    if (!Sym.isDefined())
1309      Result |= SymbolRef::SF_Undefined;
1310    if (Sym.isTypeFunction())
1311      Result |= SymbolRef::SF_Executable;
1312    return Result;
1313  }
1314  
1315  basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1316    DataRefImpl Ref;
1317    Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1318    Ref.d.b = 0; // Symbol index
1319    return BasicSymbolRef(Ref, this);
1320  }
1321  
1322  basic_symbol_iterator WasmObjectFile::symbol_end() const {
1323    DataRefImpl Ref;
1324    Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1325    Ref.d.b = Symbols.size(); // Symbol index
1326    return BasicSymbolRef(Ref, this);
1327  }
1328  
1329  const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1330    return Symbols[Symb.d.b];
1331  }
1332  
1333  const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1334    return getWasmSymbol(Symb.getRawDataRefImpl());
1335  }
1336  
1337  Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1338    return getWasmSymbol(Symb).Info.Name;
1339  }
1340  
1341  Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1342    auto &Sym = getWasmSymbol(Symb);
1343    if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1344        isDefinedFunctionIndex(Sym.Info.ElementIndex))
1345      return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
1346    else
1347      return getSymbolValue(Symb);
1348  }
1349  
1350  uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1351    switch (Sym.Info.Kind) {
1352    case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1353    case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1354    case wasm::WASM_SYMBOL_TYPE_EVENT:
1355      return Sym.Info.ElementIndex;
1356    case wasm::WASM_SYMBOL_TYPE_DATA: {
1357      // The value of a data symbol is the segment offset, plus the symbol
1358      // offset within the segment.
1359      uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1360      const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1361      if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1362        return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
1363      } else if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1364        return Segment.Offset.Value.Int64 + Sym.Info.DataRef.Offset;
1365      } else {
1366        llvm_unreachable("unknown init expr opcode");
1367      }
1368    }
1369    case wasm::WASM_SYMBOL_TYPE_SECTION:
1370      return 0;
1371    }
1372    llvm_unreachable("invalid symbol type");
1373  }
1374  
1375  uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1376    return getWasmSymbolValue(getWasmSymbol(Symb));
1377  }
1378  
1379  uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1380    llvm_unreachable("not yet implemented");
1381    return 0;
1382  }
1383  
1384  uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1385    llvm_unreachable("not yet implemented");
1386    return 0;
1387  }
1388  
1389  Expected<SymbolRef::Type>
1390  WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1391    const WasmSymbol &Sym = getWasmSymbol(Symb);
1392  
1393    switch (Sym.Info.Kind) {
1394    case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1395      return SymbolRef::ST_Function;
1396    case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1397      return SymbolRef::ST_Other;
1398    case wasm::WASM_SYMBOL_TYPE_DATA:
1399      return SymbolRef::ST_Data;
1400    case wasm::WASM_SYMBOL_TYPE_SECTION:
1401      return SymbolRef::ST_Debug;
1402    case wasm::WASM_SYMBOL_TYPE_EVENT:
1403      return SymbolRef::ST_Other;
1404    }
1405  
1406    llvm_unreachable("Unknown WasmSymbol::SymbolType");
1407    return SymbolRef::ST_Other;
1408  }
1409  
1410  Expected<section_iterator>
1411  WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1412    const WasmSymbol &Sym = getWasmSymbol(Symb);
1413    if (Sym.isUndefined())
1414      return section_end();
1415  
1416    DataRefImpl Ref;
1417    Ref.d.a = getSymbolSectionIdImpl(Sym);
1418    return section_iterator(SectionRef(Ref, this));
1419  }
1420  
1421  uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
1422    const WasmSymbol &Sym = getWasmSymbol(Symb);
1423    return getSymbolSectionIdImpl(Sym);
1424  }
1425  
1426  uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
1427    switch (Sym.Info.Kind) {
1428    case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1429      return CodeSection;
1430    case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1431      return GlobalSection;
1432    case wasm::WASM_SYMBOL_TYPE_DATA:
1433      return DataSection;
1434    case wasm::WASM_SYMBOL_TYPE_SECTION:
1435      return Sym.Info.ElementIndex;
1436    case wasm::WASM_SYMBOL_TYPE_EVENT:
1437      return EventSection;
1438    default:
1439      llvm_unreachable("Unknown WasmSymbol::SymbolType");
1440    }
1441  }
1442  
1443  void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1444  
1445  Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
1446    const WasmSection &S = Sections[Sec.d.a];
1447  #define ECase(X)                                                               \
1448    case wasm::WASM_SEC_##X:                                                     \
1449      return #X;
1450    switch (S.Type) {
1451      ECase(TYPE);
1452      ECase(IMPORT);
1453      ECase(FUNCTION);
1454      ECase(TABLE);
1455      ECase(MEMORY);
1456      ECase(GLOBAL);
1457      ECase(EVENT);
1458      ECase(EXPORT);
1459      ECase(START);
1460      ECase(ELEM);
1461      ECase(CODE);
1462      ECase(DATA);
1463      ECase(DATACOUNT);
1464    case wasm::WASM_SEC_CUSTOM:
1465      return S.Name;
1466    default:
1467      return createStringError(object_error::invalid_section_index, "");
1468    }
1469  #undef ECase
1470  }
1471  
1472  uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1473  
1474  uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1475    return Sec.d.a;
1476  }
1477  
1478  uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1479    const WasmSection &S = Sections[Sec.d.a];
1480    return S.Content.size();
1481  }
1482  
1483  Expected<ArrayRef<uint8_t>>
1484  WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
1485    const WasmSection &S = Sections[Sec.d.a];
1486    // This will never fail since wasm sections can never be empty (user-sections
1487    // must have a name and non-user sections each have a defined structure).
1488    return S.Content;
1489  }
1490  
1491  uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1492    return 1;
1493  }
1494  
1495  bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1496    return false;
1497  }
1498  
1499  bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1500    return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1501  }
1502  
1503  bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1504    return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1505  }
1506  
1507  bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1508  
1509  bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1510  
1511  relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1512    DataRefImpl RelocRef;
1513    RelocRef.d.a = Ref.d.a;
1514    RelocRef.d.b = 0;
1515    return relocation_iterator(RelocationRef(RelocRef, this));
1516  }
1517  
1518  relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1519    const WasmSection &Sec = getWasmSection(Ref);
1520    DataRefImpl RelocRef;
1521    RelocRef.d.a = Ref.d.a;
1522    RelocRef.d.b = Sec.Relocations.size();
1523    return relocation_iterator(RelocationRef(RelocRef, this));
1524  }
1525  
1526  void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1527  
1528  uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1529    const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1530    return Rel.Offset;
1531  }
1532  
1533  symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1534    const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1535    if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
1536      return symbol_end();
1537    DataRefImpl Sym;
1538    Sym.d.a = 1;
1539    Sym.d.b = Rel.Index;
1540    return symbol_iterator(SymbolRef(Sym, this));
1541  }
1542  
1543  uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1544    const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1545    return Rel.Type;
1546  }
1547  
1548  void WasmObjectFile::getRelocationTypeName(
1549      DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1550    const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1551    StringRef Res = "Unknown";
1552  
1553  #define WASM_RELOC(name, value)                                                \
1554    case wasm::name:                                                             \
1555      Res = #name;                                                               \
1556      break;
1557  
1558    switch (Rel.Type) {
1559  #include "llvm/BinaryFormat/WasmRelocs.def"
1560    }
1561  
1562  #undef WASM_RELOC
1563  
1564    Result.append(Res.begin(), Res.end());
1565  }
1566  
1567  section_iterator WasmObjectFile::section_begin() const {
1568    DataRefImpl Ref;
1569    Ref.d.a = 0;
1570    return section_iterator(SectionRef(Ref, this));
1571  }
1572  
1573  section_iterator WasmObjectFile::section_end() const {
1574    DataRefImpl Ref;
1575    Ref.d.a = Sections.size();
1576    return section_iterator(SectionRef(Ref, this));
1577  }
1578  
1579  uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1580  
1581  StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1582  
1583  Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
1584  
1585  SubtargetFeatures WasmObjectFile::getFeatures() const {
1586    return SubtargetFeatures();
1587  }
1588  
1589  bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1590  
1591  bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1592  
1593  const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1594    assert(Ref.d.a < Sections.size());
1595    return Sections[Ref.d.a];
1596  }
1597  
1598  const WasmSection &
1599  WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1600    return getWasmSection(Section.getRawDataRefImpl());
1601  }
1602  
1603  const wasm::WasmRelocation &
1604  WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1605    return getWasmRelocation(Ref.getRawDataRefImpl());
1606  }
1607  
1608  const wasm::WasmRelocation &
1609  WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1610    assert(Ref.d.a < Sections.size());
1611    const WasmSection &Sec = Sections[Ref.d.a];
1612    assert(Ref.d.b < Sec.Relocations.size());
1613    return Sec.Relocations[Ref.d.b];
1614  }
1615  
1616  int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1617                                               StringRef CustomSectionName) {
1618    switch (ID) {
1619    case wasm::WASM_SEC_CUSTOM:
1620      return StringSwitch<unsigned>(CustomSectionName)
1621          .Case("dylink", WASM_SEC_ORDER_DYLINK)
1622          .Case("linking", WASM_SEC_ORDER_LINKING)
1623          .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1624          .Case("name", WASM_SEC_ORDER_NAME)
1625          .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1626          .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
1627          .Default(WASM_SEC_ORDER_NONE);
1628    case wasm::WASM_SEC_TYPE:
1629      return WASM_SEC_ORDER_TYPE;
1630    case wasm::WASM_SEC_IMPORT:
1631      return WASM_SEC_ORDER_IMPORT;
1632    case wasm::WASM_SEC_FUNCTION:
1633      return WASM_SEC_ORDER_FUNCTION;
1634    case wasm::WASM_SEC_TABLE:
1635      return WASM_SEC_ORDER_TABLE;
1636    case wasm::WASM_SEC_MEMORY:
1637      return WASM_SEC_ORDER_MEMORY;
1638    case wasm::WASM_SEC_GLOBAL:
1639      return WASM_SEC_ORDER_GLOBAL;
1640    case wasm::WASM_SEC_EXPORT:
1641      return WASM_SEC_ORDER_EXPORT;
1642    case wasm::WASM_SEC_START:
1643      return WASM_SEC_ORDER_START;
1644    case wasm::WASM_SEC_ELEM:
1645      return WASM_SEC_ORDER_ELEM;
1646    case wasm::WASM_SEC_CODE:
1647      return WASM_SEC_ORDER_CODE;
1648    case wasm::WASM_SEC_DATA:
1649      return WASM_SEC_ORDER_DATA;
1650    case wasm::WASM_SEC_DATACOUNT:
1651      return WASM_SEC_ORDER_DATACOUNT;
1652    case wasm::WASM_SEC_EVENT:
1653      return WASM_SEC_ORDER_EVENT;
1654    default:
1655      return WASM_SEC_ORDER_NONE;
1656    }
1657  }
1658  
1659  // Represents the edges in a directed graph where any node B reachable from node
1660  // A is not allowed to appear before A in the section ordering, but may appear
1661  // afterward.
1662  int WasmSectionOrderChecker::DisallowedPredecessors
1663      [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
1664          // WASM_SEC_ORDER_NONE
1665          {},
1666          // WASM_SEC_ORDER_TYPE
1667          {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
1668          // WASM_SEC_ORDER_IMPORT
1669          {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
1670          // WASM_SEC_ORDER_FUNCTION
1671          {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
1672          // WASM_SEC_ORDER_TABLE
1673          {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
1674          // WASM_SEC_ORDER_MEMORY
1675          {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_EVENT},
1676          // WASM_SEC_ORDER_EVENT
1677          {WASM_SEC_ORDER_EVENT, WASM_SEC_ORDER_GLOBAL},
1678          // WASM_SEC_ORDER_GLOBAL
1679          {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
1680          // WASM_SEC_ORDER_EXPORT
1681          {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
1682          // WASM_SEC_ORDER_START
1683          {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
1684          // WASM_SEC_ORDER_ELEM
1685          {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
1686          // WASM_SEC_ORDER_DATACOUNT
1687          {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
1688          // WASM_SEC_ORDER_CODE
1689          {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
1690          // WASM_SEC_ORDER_DATA
1691          {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
1692  
1693          // Custom Sections
1694          // WASM_SEC_ORDER_DYLINK
1695          {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
1696          // WASM_SEC_ORDER_LINKING
1697          {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
1698          // WASM_SEC_ORDER_RELOC (can be repeated)
1699          {},
1700          // WASM_SEC_ORDER_NAME
1701          {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
1702          // WASM_SEC_ORDER_PRODUCERS
1703          {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
1704          // WASM_SEC_ORDER_TARGET_FEATURES
1705          {WASM_SEC_ORDER_TARGET_FEATURES}};
1706  
1707  bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
1708                                                    StringRef CustomSectionName) {
1709    int Order = getSectionOrder(ID, CustomSectionName);
1710    if (Order == WASM_SEC_ORDER_NONE)
1711      return true;
1712  
1713    // Disallowed predecessors we need to check for
1714    SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
1715  
1716    // Keep track of completed checks to avoid repeating work
1717    bool Checked[WASM_NUM_SEC_ORDERS] = {};
1718  
1719    int Curr = Order;
1720    while (true) {
1721      // Add new disallowed predecessors to work list
1722      for (size_t I = 0;; ++I) {
1723        int Next = DisallowedPredecessors[Curr][I];
1724        if (Next == WASM_SEC_ORDER_NONE)
1725          break;
1726        if (Checked[Next])
1727          continue;
1728        WorkList.push_back(Next);
1729        Checked[Next] = true;
1730      }
1731  
1732      if (WorkList.empty())
1733        break;
1734  
1735      // Consider next disallowed predecessor
1736      Curr = WorkList.pop_back_val();
1737      if (Seen[Curr])
1738        return false;
1739    }
1740  
1741    // Have not seen any disallowed predecessors
1742    Seen[Order] = true;
1743    return true;
1744  }
1745