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