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