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