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