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