xref: /llvm-project/llvm/lib/Object/WasmObjectFile.cpp (revision be64ca912371ae62002aee3429de058052451d72)
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       continue;
1246     }
1247     uint32_t ReturnCount = readVaruint32(Ctx);
1248     while (ReturnCount--) {
1249       uint32_t ReturnType = readUint8(Ctx);
1250       Sig.Returns.push_back(parseValType(Ctx, ReturnType));
1251     }
1252 
1253     Signatures.push_back(std::move(Sig));
1254   }
1255   if (Ctx.Ptr != Ctx.End)
1256     return make_error<GenericBinaryError>("type section ended prematurely",
1257                                           object_error::parse_failed);
1258   return Error::success();
1259 }
1260 
1261 Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1262   uint32_t Count = readVaruint32(Ctx);
1263   uint32_t NumTypes = Signatures.size();
1264   Imports.reserve(Count);
1265   for (uint32_t I = 0; I < Count; I++) {
1266     wasm::WasmImport Im;
1267     Im.Module = readString(Ctx);
1268     Im.Field = readString(Ctx);
1269     Im.Kind = readUint8(Ctx);
1270     switch (Im.Kind) {
1271     case wasm::WASM_EXTERNAL_FUNCTION:
1272       NumImportedFunctions++;
1273       Im.SigIndex = readVaruint32(Ctx);
1274       if (Im.SigIndex >= NumTypes)
1275         return make_error<GenericBinaryError>("invalid function type",
1276                                               object_error::parse_failed);
1277       break;
1278     case wasm::WASM_EXTERNAL_GLOBAL:
1279       NumImportedGlobals++;
1280       Im.Global.Type = readUint8(Ctx);
1281       Im.Global.Mutable = readVaruint1(Ctx);
1282       break;
1283     case wasm::WASM_EXTERNAL_MEMORY:
1284       Im.Memory = readLimits(Ctx);
1285       if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1286         HasMemory64 = true;
1287       break;
1288     case wasm::WASM_EXTERNAL_TABLE: {
1289       Im.Table = readTableType(Ctx);
1290       NumImportedTables++;
1291       auto ElemType = Im.Table.ElemType;
1292       if (ElemType != wasm::ValType::FUNCREF &&
1293           ElemType != wasm::ValType::EXTERNREF &&
1294           ElemType != wasm::ValType::EXNREF &&
1295           ElemType != wasm::ValType::OTHERREF)
1296         return make_error<GenericBinaryError>("invalid table element type",
1297                                               object_error::parse_failed);
1298       break;
1299     }
1300     case wasm::WASM_EXTERNAL_TAG:
1301       NumImportedTags++;
1302       if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1303         return make_error<GenericBinaryError>("invalid attribute",
1304                                               object_error::parse_failed);
1305       Im.SigIndex = readVaruint32(Ctx);
1306       if (Im.SigIndex >= NumTypes)
1307         return make_error<GenericBinaryError>("invalid tag type",
1308                                               object_error::parse_failed);
1309       break;
1310     default:
1311       return make_error<GenericBinaryError>("unexpected import kind",
1312                                             object_error::parse_failed);
1313     }
1314     Imports.push_back(Im);
1315   }
1316   if (Ctx.Ptr != Ctx.End)
1317     return make_error<GenericBinaryError>("import section ended prematurely",
1318                                           object_error::parse_failed);
1319   return Error::success();
1320 }
1321 
1322 Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1323   uint32_t Count = readVaruint32(Ctx);
1324   Functions.reserve(Count);
1325   uint32_t NumTypes = Signatures.size();
1326   while (Count--) {
1327     uint32_t Type = readVaruint32(Ctx);
1328     if (Type >= NumTypes)
1329       return make_error<GenericBinaryError>("invalid function type",
1330                                             object_error::parse_failed);
1331     wasm::WasmFunction F;
1332     F.SigIndex = Type;
1333     Functions.push_back(F);
1334   }
1335   if (Ctx.Ptr != Ctx.End)
1336     return make_error<GenericBinaryError>("function section ended prematurely",
1337                                           object_error::parse_failed);
1338   return Error::success();
1339 }
1340 
1341 Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1342   TableSection = Sections.size();
1343   uint32_t Count = readVaruint32(Ctx);
1344   Tables.reserve(Count);
1345   while (Count--) {
1346     wasm::WasmTable T;
1347     T.Type = readTableType(Ctx);
1348     T.Index = NumImportedTables + Tables.size();
1349     Tables.push_back(T);
1350     auto ElemType = Tables.back().Type.ElemType;
1351     if (ElemType != wasm::ValType::FUNCREF &&
1352         ElemType != wasm::ValType::EXTERNREF &&
1353         ElemType != wasm::ValType::EXNREF &&
1354         ElemType != wasm::ValType::OTHERREF) {
1355       return make_error<GenericBinaryError>("invalid table element type",
1356                                             object_error::parse_failed);
1357     }
1358   }
1359   if (Ctx.Ptr != Ctx.End)
1360     return make_error<GenericBinaryError>("table section ended prematurely",
1361                                           object_error::parse_failed);
1362   return Error::success();
1363 }
1364 
1365 Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1366   uint32_t Count = readVaruint32(Ctx);
1367   Memories.reserve(Count);
1368   while (Count--) {
1369     auto Limits = readLimits(Ctx);
1370     if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1371       HasMemory64 = true;
1372     Memories.push_back(Limits);
1373   }
1374   if (Ctx.Ptr != Ctx.End)
1375     return make_error<GenericBinaryError>("memory section ended prematurely",
1376                                           object_error::parse_failed);
1377   return Error::success();
1378 }
1379 
1380 Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1381   TagSection = Sections.size();
1382   uint32_t Count = readVaruint32(Ctx);
1383   Tags.reserve(Count);
1384   uint32_t NumTypes = Signatures.size();
1385   while (Count--) {
1386     if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1387       return make_error<GenericBinaryError>("invalid attribute",
1388                                             object_error::parse_failed);
1389     uint32_t Type = readVaruint32(Ctx);
1390     if (Type >= NumTypes)
1391       return make_error<GenericBinaryError>("invalid tag type",
1392                                             object_error::parse_failed);
1393     wasm::WasmTag Tag;
1394     Tag.Index = NumImportedTags + Tags.size();
1395     Tag.SigIndex = Type;
1396     Signatures[Type].Kind = wasm::WasmSignature::Tag;
1397     Tags.push_back(Tag);
1398   }
1399 
1400   if (Ctx.Ptr != Ctx.End)
1401     return make_error<GenericBinaryError>("tag section ended prematurely",
1402                                           object_error::parse_failed);
1403   return Error::success();
1404 }
1405 
1406 Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1407   GlobalSection = Sections.size();
1408   const uint8_t *SectionStart = Ctx.Ptr;
1409   uint32_t Count = readVaruint32(Ctx);
1410   Globals.reserve(Count);
1411   while (Count--) {
1412     wasm::WasmGlobal Global;
1413     Global.Index = NumImportedGlobals + Globals.size();
1414     const uint8_t *GlobalStart = Ctx.Ptr;
1415     Global.Offset = static_cast<uint32_t>(GlobalStart - SectionStart);
1416     auto GlobalOpcode = readVaruint32(Ctx);
1417     Global.Type.Type = (uint8_t)parseValType(Ctx, GlobalOpcode);
1418     Global.Type.Mutable = readVaruint1(Ctx);
1419     if (Error Err = readInitExpr(Global.InitExpr, Ctx))
1420       return Err;
1421     Global.Size = static_cast<uint32_t>(Ctx.Ptr - GlobalStart);
1422     Globals.push_back(Global);
1423   }
1424   if (Ctx.Ptr != Ctx.End)
1425     return make_error<GenericBinaryError>("global section ended prematurely",
1426                                           object_error::parse_failed);
1427   return Error::success();
1428 }
1429 
1430 Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1431   uint32_t Count = readVaruint32(Ctx);
1432   Exports.reserve(Count);
1433   Symbols.reserve(Count);
1434   for (uint32_t I = 0; I < Count; I++) {
1435     wasm::WasmExport Ex;
1436     Ex.Name = readString(Ctx);
1437     Ex.Kind = readUint8(Ctx);
1438     Ex.Index = readVaruint32(Ctx);
1439     const wasm::WasmSignature *Signature = nullptr;
1440     const wasm::WasmGlobalType *GlobalType = nullptr;
1441     const wasm::WasmTableType *TableType = nullptr;
1442     wasm::WasmSymbolInfo Info;
1443     Info.Name = Ex.Name;
1444     Info.Flags = 0;
1445     switch (Ex.Kind) {
1446     case wasm::WASM_EXTERNAL_FUNCTION: {
1447       if (!isDefinedFunctionIndex(Ex.Index))
1448         return make_error<GenericBinaryError>("invalid function export",
1449                                               object_error::parse_failed);
1450       getDefinedFunction(Ex.Index).ExportName = Ex.Name;
1451       Info.Kind = wasm::WASM_SYMBOL_TYPE_FUNCTION;
1452       Info.ElementIndex = Ex.Index;
1453       unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
1454       wasm::WasmFunction &Function = Functions[FuncIndex];
1455       Signature = &Signatures[Function.SigIndex];
1456       break;
1457     }
1458     case wasm::WASM_EXTERNAL_GLOBAL: {
1459       if (!isValidGlobalIndex(Ex.Index))
1460         return make_error<GenericBinaryError>("invalid global export",
1461                                               object_error::parse_failed);
1462       Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA;
1463       uint64_t Offset = 0;
1464       if (isDefinedGlobalIndex(Ex.Index)) {
1465         auto Global = getDefinedGlobal(Ex.Index);
1466         if (!Global.InitExpr.Extended) {
1467           auto Inst = Global.InitExpr.Inst;
1468           if (Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1469             Offset = Inst.Value.Int32;
1470           } else if (Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1471             Offset = Inst.Value.Int64;
1472           }
1473         }
1474       }
1475       Info.DataRef = wasm::WasmDataReference{0, Offset, 0};
1476       break;
1477     }
1478     case wasm::WASM_EXTERNAL_TAG:
1479       if (!isValidTagIndex(Ex.Index))
1480         return make_error<GenericBinaryError>("invalid tag export",
1481                                               object_error::parse_failed);
1482       Info.Kind = wasm::WASM_SYMBOL_TYPE_TAG;
1483       Info.ElementIndex = Ex.Index;
1484       break;
1485     case wasm::WASM_EXTERNAL_MEMORY:
1486       break;
1487     case wasm::WASM_EXTERNAL_TABLE:
1488       Info.Kind = wasm::WASM_SYMBOL_TYPE_TABLE;
1489       Info.ElementIndex = Ex.Index;
1490       break;
1491     default:
1492       return make_error<GenericBinaryError>("unexpected export kind",
1493                                             object_error::parse_failed);
1494     }
1495     Exports.push_back(Ex);
1496     if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) {
1497       Symbols.emplace_back(Info, GlobalType, TableType, Signature);
1498       LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
1499     }
1500   }
1501   if (Ctx.Ptr != Ctx.End)
1502     return make_error<GenericBinaryError>("export section ended prematurely",
1503                                           object_error::parse_failed);
1504   return Error::success();
1505 }
1506 
1507 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1508   return Index < NumImportedFunctions + Functions.size();
1509 }
1510 
1511 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1512   return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1513 }
1514 
1515 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1516   return Index < NumImportedGlobals + Globals.size();
1517 }
1518 
1519 bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1520   return Index < NumImportedTables + Tables.size();
1521 }
1522 
1523 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1524   return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1525 }
1526 
1527 bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1528   return Index >= NumImportedTables && isValidTableNumber(Index);
1529 }
1530 
1531 bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1532   return Index < NumImportedTags + Tags.size();
1533 }
1534 
1535 bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1536   return Index >= NumImportedTags && isValidTagIndex(Index);
1537 }
1538 
1539 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1540   return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1541 }
1542 
1543 bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1544   return Index < Symbols.size() && Symbols[Index].isTypeTable();
1545 }
1546 
1547 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1548   return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1549 }
1550 
1551 bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1552   return Index < Symbols.size() && Symbols[Index].isTypeTag();
1553 }
1554 
1555 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1556   return Index < Symbols.size() && Symbols[Index].isTypeData();
1557 }
1558 
1559 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1560   return Index < Symbols.size() && Symbols[Index].isTypeSection();
1561 }
1562 
1563 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1564   assert(isDefinedFunctionIndex(Index));
1565   return Functions[Index - NumImportedFunctions];
1566 }
1567 
1568 const wasm::WasmFunction &
1569 WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1570   assert(isDefinedFunctionIndex(Index));
1571   return Functions[Index - NumImportedFunctions];
1572 }
1573 
1574 const wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) const {
1575   assert(isDefinedGlobalIndex(Index));
1576   return Globals[Index - NumImportedGlobals];
1577 }
1578 
1579 wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1580   assert(isDefinedTagIndex(Index));
1581   return Tags[Index - NumImportedTags];
1582 }
1583 
1584 Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1585   StartFunction = readVaruint32(Ctx);
1586   if (!isValidFunctionIndex(StartFunction))
1587     return make_error<GenericBinaryError>("invalid start function",
1588                                           object_error::parse_failed);
1589   return Error::success();
1590 }
1591 
1592 Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1593   CodeSection = Sections.size();
1594   uint32_t FunctionCount = readVaruint32(Ctx);
1595   if (FunctionCount != Functions.size()) {
1596     return make_error<GenericBinaryError>("invalid function count",
1597                                           object_error::parse_failed);
1598   }
1599 
1600   for (uint32_t i = 0; i < FunctionCount; i++) {
1601     wasm::WasmFunction& Function = Functions[i];
1602     const uint8_t *FunctionStart = Ctx.Ptr;
1603     uint32_t Size = readVaruint32(Ctx);
1604     const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1605 
1606     Function.CodeOffset = Ctx.Ptr - FunctionStart;
1607     Function.Index = NumImportedFunctions + i;
1608     Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1609     Function.Size = FunctionEnd - FunctionStart;
1610 
1611     uint32_t NumLocalDecls = readVaruint32(Ctx);
1612     Function.Locals.reserve(NumLocalDecls);
1613     while (NumLocalDecls--) {
1614       wasm::WasmLocalDecl Decl;
1615       Decl.Count = readVaruint32(Ctx);
1616       Decl.Type = readUint8(Ctx);
1617       Function.Locals.push_back(Decl);
1618     }
1619 
1620     uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1621     // Ensure that Function is within Ctx's buffer.
1622     if (Ctx.Ptr + BodySize > Ctx.End) {
1623       return make_error<GenericBinaryError>("Function extends beyond buffer",
1624                                             object_error::parse_failed);
1625     }
1626     Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1627     // This will be set later when reading in the linking metadata section.
1628     Function.Comdat = UINT32_MAX;
1629     Ctx.Ptr += BodySize;
1630     assert(Ctx.Ptr == FunctionEnd);
1631   }
1632   if (Ctx.Ptr != Ctx.End)
1633     return make_error<GenericBinaryError>("code section ended prematurely",
1634                                           object_error::parse_failed);
1635   return Error::success();
1636 }
1637 
1638 Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1639   uint32_t Count = readVaruint32(Ctx);
1640   ElemSegments.reserve(Count);
1641   while (Count--) {
1642     wasm::WasmElemSegment Segment;
1643     Segment.Flags = readVaruint32(Ctx);
1644 
1645     uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
1646                               wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |
1647                               wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;
1648     if (Segment.Flags & ~SupportedFlags)
1649       return make_error<GenericBinaryError>(
1650           "Unsupported flags for element segment", object_error::parse_failed);
1651 
1652     bool IsPassive = (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) != 0;
1653     bool IsDeclarative =
1654         IsPassive && (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE);
1655     bool HasTableNumber =
1656         !IsPassive &&
1657         (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER);
1658     bool HasInitExprs =
1659         (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS);
1660     bool HasElemKind =
1661         (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) &&
1662         !HasInitExprs;
1663 
1664     if (HasTableNumber)
1665       Segment.TableNumber = readVaruint32(Ctx);
1666     else
1667       Segment.TableNumber = 0;
1668 
1669     if (!isValidTableNumber(Segment.TableNumber))
1670       return make_error<GenericBinaryError>("invalid TableNumber",
1671                                             object_error::parse_failed);
1672 
1673     if (IsPassive || IsDeclarative) {
1674       Segment.Offset.Extended = false;
1675       Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1676       Segment.Offset.Inst.Value.Int32 = 0;
1677     } else {
1678       if (Error Err = readInitExpr(Segment.Offset, Ctx))
1679         return Err;
1680     }
1681 
1682     if (HasElemKind) {
1683       auto ElemKind = readVaruint32(Ctx);
1684       if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
1685         Segment.ElemKind = parseValType(Ctx, ElemKind);
1686         if (Segment.ElemKind != wasm::ValType::FUNCREF &&
1687             Segment.ElemKind != wasm::ValType::EXTERNREF &&
1688             Segment.ElemKind != wasm::ValType::EXNREF &&
1689             Segment.ElemKind != wasm::ValType::OTHERREF) {
1690           return make_error<GenericBinaryError>("invalid elem type",
1691                                                 object_error::parse_failed);
1692         }
1693       } else {
1694         if (ElemKind != 0)
1695           return make_error<GenericBinaryError>("invalid elem type",
1696                                                 object_error::parse_failed);
1697         Segment.ElemKind = wasm::ValType::FUNCREF;
1698       }
1699     } else if (HasInitExprs) {
1700       auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
1701       Segment.ElemKind = ElemType;
1702     } else {
1703       Segment.ElemKind = wasm::ValType::FUNCREF;
1704     }
1705 
1706     uint32_t NumElems = readVaruint32(Ctx);
1707 
1708     if (HasInitExprs) {
1709       while (NumElems--) {
1710         wasm::WasmInitExpr Expr;
1711         if (Error Err = readInitExpr(Expr, Ctx))
1712           return Err;
1713       }
1714     } else {
1715       while (NumElems--) {
1716         Segment.Functions.push_back(readVaruint32(Ctx));
1717       }
1718     }
1719     ElemSegments.push_back(Segment);
1720   }
1721   if (Ctx.Ptr != Ctx.End)
1722     return make_error<GenericBinaryError>("elem section ended prematurely",
1723                                           object_error::parse_failed);
1724   return Error::success();
1725 }
1726 
1727 Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1728   DataSection = Sections.size();
1729   uint32_t Count = readVaruint32(Ctx);
1730   if (DataCount && Count != *DataCount)
1731     return make_error<GenericBinaryError>(
1732         "number of data segments does not match DataCount section");
1733   DataSegments.reserve(Count);
1734   while (Count--) {
1735     WasmSegment Segment;
1736     Segment.Data.InitFlags = readVaruint32(Ctx);
1737     Segment.Data.MemoryIndex =
1738         (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1739             ? readVaruint32(Ctx)
1740             : 0;
1741     if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1742       if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1743         return Err;
1744     } else {
1745       Segment.Data.Offset.Extended = false;
1746       Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1747       Segment.Data.Offset.Inst.Value.Int32 = 0;
1748     }
1749     uint32_t Size = readVaruint32(Ctx);
1750     if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1751       return make_error<GenericBinaryError>("invalid segment size",
1752                                             object_error::parse_failed);
1753     Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1754     // The rest of these Data fields are set later, when reading in the linking
1755     // metadata section.
1756     Segment.Data.Alignment = 0;
1757     Segment.Data.LinkingFlags = 0;
1758     Segment.Data.Comdat = UINT32_MAX;
1759     Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1760     Ctx.Ptr += Size;
1761     DataSegments.push_back(Segment);
1762   }
1763   if (Ctx.Ptr != Ctx.End)
1764     return make_error<GenericBinaryError>("data section ended prematurely",
1765                                           object_error::parse_failed);
1766   return Error::success();
1767 }
1768 
1769 Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1770   DataCount = readVaruint32(Ctx);
1771   return Error::success();
1772 }
1773 
1774 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1775   return Header;
1776 }
1777 
1778 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1779 
1780 Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1781   uint32_t Result = SymbolRef::SF_None;
1782   const WasmSymbol &Sym = getWasmSymbol(Symb);
1783 
1784   LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1785   if (Sym.isBindingWeak())
1786     Result |= SymbolRef::SF_Weak;
1787   if (!Sym.isBindingLocal())
1788     Result |= SymbolRef::SF_Global;
1789   if (Sym.isHidden())
1790     Result |= SymbolRef::SF_Hidden;
1791   if (!Sym.isDefined())
1792     Result |= SymbolRef::SF_Undefined;
1793   if (Sym.isTypeFunction())
1794     Result |= SymbolRef::SF_Executable;
1795   return Result;
1796 }
1797 
1798 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1799   DataRefImpl Ref;
1800   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1801   Ref.d.b = 0; // Symbol index
1802   return BasicSymbolRef(Ref, this);
1803 }
1804 
1805 basic_symbol_iterator WasmObjectFile::symbol_end() const {
1806   DataRefImpl Ref;
1807   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1808   Ref.d.b = Symbols.size(); // Symbol index
1809   return BasicSymbolRef(Ref, this);
1810 }
1811 
1812 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1813   return Symbols[Symb.d.b];
1814 }
1815 
1816 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1817   return getWasmSymbol(Symb.getRawDataRefImpl());
1818 }
1819 
1820 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1821   return getWasmSymbol(Symb).Info.Name;
1822 }
1823 
1824 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1825   auto &Sym = getWasmSymbol(Symb);
1826   if (!Sym.isDefined())
1827     return 0;
1828   Expected<section_iterator> Sec = getSymbolSection(Symb);
1829   if (!Sec)
1830     return Sec.takeError();
1831   uint32_t SectionAddress = getSectionAddress(Sec.get()->getRawDataRefImpl());
1832   if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1833       isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
1834     return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
1835            SectionAddress;
1836   }
1837   if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL &&
1838       isDefinedGlobalIndex(Sym.Info.ElementIndex)) {
1839     return getDefinedGlobal(Sym.Info.ElementIndex).Offset + SectionAddress;
1840   }
1841 
1842   return getSymbolValue(Symb);
1843 }
1844 
1845 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1846   switch (Sym.Info.Kind) {
1847   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1848   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1849   case wasm::WASM_SYMBOL_TYPE_TAG:
1850   case wasm::WASM_SYMBOL_TYPE_TABLE:
1851     return Sym.Info.ElementIndex;
1852   case wasm::WASM_SYMBOL_TYPE_DATA: {
1853     // The value of a data symbol is the segment offset, plus the symbol
1854     // offset within the segment.
1855     uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1856     const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1857     if (Segment.Offset.Extended) {
1858       llvm_unreachable("extended init exprs not supported");
1859     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1860       return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
1861     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1862       return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
1863     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {
1864       return Sym.Info.DataRef.Offset;
1865     } else {
1866       llvm_unreachable("unknown init expr opcode");
1867     }
1868   }
1869   case wasm::WASM_SYMBOL_TYPE_SECTION:
1870     return 0;
1871   }
1872   llvm_unreachable("invalid symbol type");
1873 }
1874 
1875 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1876   return getWasmSymbolValue(getWasmSymbol(Symb));
1877 }
1878 
1879 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1880   llvm_unreachable("not yet implemented");
1881   return 0;
1882 }
1883 
1884 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1885   llvm_unreachable("not yet implemented");
1886   return 0;
1887 }
1888 
1889 Expected<SymbolRef::Type>
1890 WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1891   const WasmSymbol &Sym = getWasmSymbol(Symb);
1892 
1893   switch (Sym.Info.Kind) {
1894   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1895     return SymbolRef::ST_Function;
1896   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1897     return SymbolRef::ST_Other;
1898   case wasm::WASM_SYMBOL_TYPE_DATA:
1899     return SymbolRef::ST_Data;
1900   case wasm::WASM_SYMBOL_TYPE_SECTION:
1901     return SymbolRef::ST_Debug;
1902   case wasm::WASM_SYMBOL_TYPE_TAG:
1903     return SymbolRef::ST_Other;
1904   case wasm::WASM_SYMBOL_TYPE_TABLE:
1905     return SymbolRef::ST_Other;
1906   }
1907 
1908   llvm_unreachable("unknown WasmSymbol::SymbolType");
1909   return SymbolRef::ST_Other;
1910 }
1911 
1912 Expected<section_iterator>
1913 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1914   const WasmSymbol &Sym = getWasmSymbol(Symb);
1915   if (Sym.isUndefined())
1916     return section_end();
1917 
1918   DataRefImpl Ref;
1919   Ref.d.a = getSymbolSectionIdImpl(Sym);
1920   return section_iterator(SectionRef(Ref, this));
1921 }
1922 
1923 uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
1924   const WasmSymbol &Sym = getWasmSymbol(Symb);
1925   return getSymbolSectionIdImpl(Sym);
1926 }
1927 
1928 uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
1929   switch (Sym.Info.Kind) {
1930   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1931     return CodeSection;
1932   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1933     return GlobalSection;
1934   case wasm::WASM_SYMBOL_TYPE_DATA:
1935     return DataSection;
1936   case wasm::WASM_SYMBOL_TYPE_SECTION:
1937     return Sym.Info.ElementIndex;
1938   case wasm::WASM_SYMBOL_TYPE_TAG:
1939     return TagSection;
1940   case wasm::WASM_SYMBOL_TYPE_TABLE:
1941     return TableSection;
1942   default:
1943     llvm_unreachable("unknown WasmSymbol::SymbolType");
1944   }
1945 }
1946 
1947 uint32_t WasmObjectFile::getSymbolSize(SymbolRef Symb) const {
1948   const WasmSymbol &Sym = getWasmSymbol(Symb);
1949   if (!Sym.isDefined())
1950     return 0;
1951   if (Sym.isTypeGlobal())
1952     return getDefinedGlobal(Sym.Info.ElementIndex).Size;
1953   if (Sym.isTypeData())
1954     return Sym.Info.DataRef.Size;
1955   if (Sym.isTypeFunction())
1956     return functions()[Sym.Info.ElementIndex - getNumImportedFunctions()].Size;
1957   // Currently symbol size is only tracked for data segments and functions. In
1958   // principle we could also track size (e.g. binary size) for tables, globals
1959   // and element segments etc too.
1960   return 0;
1961 }
1962 
1963 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1964 
1965 Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
1966   const WasmSection &S = Sections[Sec.d.a];
1967   if (S.Type == wasm::WASM_SEC_CUSTOM)
1968     return S.Name;
1969   if (S.Type > wasm::WASM_SEC_LAST_KNOWN)
1970     return createStringError(object_error::invalid_section_index, "");
1971   return wasm::sectionTypeToString(S.Type);
1972 }
1973 
1974 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const {
1975   // For object files, use 0 for section addresses, and section offsets for
1976   // symbol addresses. For linked files, use file offsets.
1977   // See also getSymbolAddress.
1978   return isRelocatableObject() || isSharedObject() ? 0
1979                                                    : Sections[Sec.d.a].Offset;
1980 }
1981 
1982 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1983   return Sec.d.a;
1984 }
1985 
1986 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1987   const WasmSection &S = Sections[Sec.d.a];
1988   return S.Content.size();
1989 }
1990 
1991 Expected<ArrayRef<uint8_t>>
1992 WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
1993   const WasmSection &S = Sections[Sec.d.a];
1994   // This will never fail since wasm sections can never be empty (user-sections
1995   // must have a name and non-user sections each have a defined structure).
1996   return S.Content;
1997 }
1998 
1999 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
2000   return 1;
2001 }
2002 
2003 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
2004   return false;
2005 }
2006 
2007 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
2008   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
2009 }
2010 
2011 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
2012   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
2013 }
2014 
2015 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
2016 
2017 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
2018 
2019 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
2020   DataRefImpl RelocRef;
2021   RelocRef.d.a = Ref.d.a;
2022   RelocRef.d.b = 0;
2023   return relocation_iterator(RelocationRef(RelocRef, this));
2024 }
2025 
2026 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
2027   const WasmSection &Sec = getWasmSection(Ref);
2028   DataRefImpl RelocRef;
2029   RelocRef.d.a = Ref.d.a;
2030   RelocRef.d.b = Sec.Relocations.size();
2031   return relocation_iterator(RelocationRef(RelocRef, this));
2032 }
2033 
2034 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
2035 
2036 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
2037   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
2038   return Rel.Offset;
2039 }
2040 
2041 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
2042   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
2043   if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
2044     return symbol_end();
2045   DataRefImpl Sym;
2046   Sym.d.a = 1;
2047   Sym.d.b = Rel.Index;
2048   return symbol_iterator(SymbolRef(Sym, this));
2049 }
2050 
2051 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
2052   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
2053   return Rel.Type;
2054 }
2055 
2056 void WasmObjectFile::getRelocationTypeName(
2057     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
2058   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
2059   StringRef Res = "Unknown";
2060 
2061 #define WASM_RELOC(name, value)                                                \
2062   case wasm::name:                                                             \
2063     Res = #name;                                                               \
2064     break;
2065 
2066   switch (Rel.Type) {
2067 #include "llvm/BinaryFormat/WasmRelocs.def"
2068   }
2069 
2070 #undef WASM_RELOC
2071 
2072   Result.append(Res.begin(), Res.end());
2073 }
2074 
2075 section_iterator WasmObjectFile::section_begin() const {
2076   DataRefImpl Ref;
2077   Ref.d.a = 0;
2078   return section_iterator(SectionRef(Ref, this));
2079 }
2080 
2081 section_iterator WasmObjectFile::section_end() const {
2082   DataRefImpl Ref;
2083   Ref.d.a = Sections.size();
2084   return section_iterator(SectionRef(Ref, this));
2085 }
2086 
2087 uint8_t WasmObjectFile::getBytesInAddress() const {
2088   return HasMemory64 ? 8 : 4;
2089 }
2090 
2091 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
2092 
2093 Triple::ArchType WasmObjectFile::getArch() const {
2094   return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
2095 }
2096 
2097 Expected<SubtargetFeatures> WasmObjectFile::getFeatures() const {
2098   return SubtargetFeatures();
2099 }
2100 
2101 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
2102 
2103 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
2104 
2105 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
2106   assert(Ref.d.a < Sections.size());
2107   return Sections[Ref.d.a];
2108 }
2109 
2110 const WasmSection &
2111 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
2112   return getWasmSection(Section.getRawDataRefImpl());
2113 }
2114 
2115 const wasm::WasmRelocation &
2116 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
2117   return getWasmRelocation(Ref.getRawDataRefImpl());
2118 }
2119 
2120 const wasm::WasmRelocation &
2121 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
2122   assert(Ref.d.a < Sections.size());
2123   const WasmSection &Sec = Sections[Ref.d.a];
2124   assert(Ref.d.b < Sec.Relocations.size());
2125   return Sec.Relocations[Ref.d.b];
2126 }
2127 
2128 int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
2129                                              StringRef CustomSectionName) {
2130   switch (ID) {
2131   case wasm::WASM_SEC_CUSTOM:
2132     return StringSwitch<unsigned>(CustomSectionName)
2133         .Case("dylink", WASM_SEC_ORDER_DYLINK)
2134         .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
2135         .Case("linking", WASM_SEC_ORDER_LINKING)
2136         .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
2137         .Case("name", WASM_SEC_ORDER_NAME)
2138         .Case("producers", WASM_SEC_ORDER_PRODUCERS)
2139         .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
2140         .Default(WASM_SEC_ORDER_NONE);
2141   case wasm::WASM_SEC_TYPE:
2142     return WASM_SEC_ORDER_TYPE;
2143   case wasm::WASM_SEC_IMPORT:
2144     return WASM_SEC_ORDER_IMPORT;
2145   case wasm::WASM_SEC_FUNCTION:
2146     return WASM_SEC_ORDER_FUNCTION;
2147   case wasm::WASM_SEC_TABLE:
2148     return WASM_SEC_ORDER_TABLE;
2149   case wasm::WASM_SEC_MEMORY:
2150     return WASM_SEC_ORDER_MEMORY;
2151   case wasm::WASM_SEC_GLOBAL:
2152     return WASM_SEC_ORDER_GLOBAL;
2153   case wasm::WASM_SEC_EXPORT:
2154     return WASM_SEC_ORDER_EXPORT;
2155   case wasm::WASM_SEC_START:
2156     return WASM_SEC_ORDER_START;
2157   case wasm::WASM_SEC_ELEM:
2158     return WASM_SEC_ORDER_ELEM;
2159   case wasm::WASM_SEC_CODE:
2160     return WASM_SEC_ORDER_CODE;
2161   case wasm::WASM_SEC_DATA:
2162     return WASM_SEC_ORDER_DATA;
2163   case wasm::WASM_SEC_DATACOUNT:
2164     return WASM_SEC_ORDER_DATACOUNT;
2165   case wasm::WASM_SEC_TAG:
2166     return WASM_SEC_ORDER_TAG;
2167   default:
2168     return WASM_SEC_ORDER_NONE;
2169   }
2170 }
2171 
2172 // Represents the edges in a directed graph where any node B reachable from node
2173 // A is not allowed to appear before A in the section ordering, but may appear
2174 // afterward.
2175 int WasmSectionOrderChecker::DisallowedPredecessors
2176     [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2177         // WASM_SEC_ORDER_NONE
2178         {},
2179         // WASM_SEC_ORDER_TYPE
2180         {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2181         // WASM_SEC_ORDER_IMPORT
2182         {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2183         // WASM_SEC_ORDER_FUNCTION
2184         {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2185         // WASM_SEC_ORDER_TABLE
2186         {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2187         // WASM_SEC_ORDER_MEMORY
2188         {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2189         // WASM_SEC_ORDER_TAG
2190         {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2191         // WASM_SEC_ORDER_GLOBAL
2192         {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2193         // WASM_SEC_ORDER_EXPORT
2194         {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2195         // WASM_SEC_ORDER_START
2196         {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2197         // WASM_SEC_ORDER_ELEM
2198         {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2199         // WASM_SEC_ORDER_DATACOUNT
2200         {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2201         // WASM_SEC_ORDER_CODE
2202         {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2203         // WASM_SEC_ORDER_DATA
2204         {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2205 
2206         // Custom Sections
2207         // WASM_SEC_ORDER_DYLINK
2208         {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2209         // WASM_SEC_ORDER_LINKING
2210         {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2211         // WASM_SEC_ORDER_RELOC (can be repeated)
2212         {},
2213         // WASM_SEC_ORDER_NAME
2214         {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2215         // WASM_SEC_ORDER_PRODUCERS
2216         {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2217         // WASM_SEC_ORDER_TARGET_FEATURES
2218         {WASM_SEC_ORDER_TARGET_FEATURES}};
2219 
2220 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
2221                                                   StringRef CustomSectionName) {
2222   int Order = getSectionOrder(ID, CustomSectionName);
2223   if (Order == WASM_SEC_ORDER_NONE)
2224     return true;
2225 
2226   // Disallowed predecessors we need to check for
2227   SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
2228 
2229   // Keep track of completed checks to avoid repeating work
2230   bool Checked[WASM_NUM_SEC_ORDERS] = {};
2231 
2232   int Curr = Order;
2233   while (true) {
2234     // Add new disallowed predecessors to work list
2235     for (size_t I = 0;; ++I) {
2236       int Next = DisallowedPredecessors[Curr][I];
2237       if (Next == WASM_SEC_ORDER_NONE)
2238         break;
2239       if (Checked[Next])
2240         continue;
2241       WorkList.push_back(Next);
2242       Checked[Next] = true;
2243     }
2244 
2245     if (WorkList.empty())
2246       break;
2247 
2248     // Consider next disallowed predecessor
2249     Curr = WorkList.pop_back_val();
2250     if (Seen[Curr])
2251       return false;
2252   }
2253 
2254   // Have not seen any disallowed predecessors
2255   Seen[Order] = true;
2256   return true;
2257 }
2258