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