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