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