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