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