xref: /llvm-project/llvm/lib/Object/WasmObjectFile.cpp (revision 2481adb59cb63c90879f4537ad36339da3ad61a6)
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 (1) {
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   if (Functions.size() && !SeenCodeSection) {
455     return make_error<GenericBinaryError>("names must come after code section",
456                                           object_error::parse_failed);
457   }
458 
459   while (Ctx.Ptr < Ctx.End) {
460     uint8_t Type = readUint8(Ctx);
461     uint32_t Size = readVaruint32(Ctx);
462     const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
463     switch (Type) {
464     case wasm::WASM_NAMES_FUNCTION:
465     case wasm::WASM_NAMES_GLOBAL:
466     case wasm::WASM_NAMES_DATA_SEGMENT: {
467       uint32_t Count = readVaruint32(Ctx);
468       while (Count--) {
469         uint32_t Index = readVaruint32(Ctx);
470         StringRef Name = readString(Ctx);
471         wasm::NameType nameType = wasm::NameType::FUNCTION;
472         if (Type == wasm::WASM_NAMES_FUNCTION) {
473           if (!SeenFunctions.insert(Index).second)
474             return make_error<GenericBinaryError>(
475                 "function named more than once", object_error::parse_failed);
476           if (!isValidFunctionIndex(Index) || Name.empty())
477             return make_error<GenericBinaryError>("invalid name entry",
478                                                   object_error::parse_failed);
479 
480           if (isDefinedFunctionIndex(Index))
481             getDefinedFunction(Index).DebugName = Name;
482         } else if (Type == wasm::WASM_NAMES_GLOBAL) {
483           nameType = wasm::NameType::GLOBAL;
484           if (!SeenGlobals.insert(Index).second)
485             return make_error<GenericBinaryError>("global named more than once",
486                                                   object_error::parse_failed);
487           if (!isValidGlobalIndex(Index) || Name.empty())
488             return make_error<GenericBinaryError>("invalid name entry",
489                                                   object_error::parse_failed);
490         } else {
491           nameType = wasm::NameType::DATA_SEGMENT;
492           if (!SeenSegments.insert(Index).second)
493             return make_error<GenericBinaryError>(
494                 "segment named more than once", object_error::parse_failed);
495           if (Index > DataSegments.size())
496             return make_error<GenericBinaryError>("invalid named data segment",
497                                                   object_error::parse_failed);
498         }
499         DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
500       }
501       break;
502     }
503     // Ignore local names for now
504     case wasm::WASM_NAMES_LOCAL:
505     default:
506       Ctx.Ptr += Size;
507       break;
508     }
509     if (Ctx.Ptr != SubSectionEnd)
510       return make_error<GenericBinaryError>(
511           "name sub-section ended prematurely", object_error::parse_failed);
512   }
513 
514   if (Ctx.Ptr != Ctx.End)
515     return make_error<GenericBinaryError>("name section ended prematurely",
516                                           object_error::parse_failed);
517   return Error::success();
518 }
519 
520 Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
521   HasLinkingSection = true;
522   if (Functions.size() && !SeenCodeSection) {
523     return make_error<GenericBinaryError>(
524         "linking data must come after code section",
525         object_error::parse_failed);
526   }
527 
528   LinkingData.Version = readVaruint32(Ctx);
529   if (LinkingData.Version != wasm::WasmMetadataVersion) {
530     return make_error<GenericBinaryError>(
531         "unexpected metadata version: " + Twine(LinkingData.Version) +
532             " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
533         object_error::parse_failed);
534   }
535 
536   const uint8_t *OrigEnd = Ctx.End;
537   while (Ctx.Ptr < OrigEnd) {
538     Ctx.End = OrigEnd;
539     uint8_t Type = readUint8(Ctx);
540     uint32_t Size = readVaruint32(Ctx);
541     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
542                       << "\n");
543     Ctx.End = Ctx.Ptr + Size;
544     switch (Type) {
545     case wasm::WASM_SYMBOL_TABLE:
546       if (Error Err = parseLinkingSectionSymtab(Ctx))
547         return Err;
548       break;
549     case wasm::WASM_SEGMENT_INFO: {
550       uint32_t Count = readVaruint32(Ctx);
551       if (Count > DataSegments.size())
552         return make_error<GenericBinaryError>("too many segment names",
553                                               object_error::parse_failed);
554       for (uint32_t I = 0; I < Count; I++) {
555         DataSegments[I].Data.Name = readString(Ctx);
556         DataSegments[I].Data.Alignment = readVaruint32(Ctx);
557         DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
558       }
559       break;
560     }
561     case wasm::WASM_INIT_FUNCS: {
562       uint32_t Count = readVaruint32(Ctx);
563       LinkingData.InitFunctions.reserve(Count);
564       for (uint32_t I = 0; I < Count; I++) {
565         wasm::WasmInitFunc Init;
566         Init.Priority = readVaruint32(Ctx);
567         Init.Symbol = readVaruint32(Ctx);
568         if (!isValidFunctionSymbol(Init.Symbol))
569           return make_error<GenericBinaryError>("invalid function symbol: " +
570                                                     Twine(Init.Symbol),
571                                                 object_error::parse_failed);
572         LinkingData.InitFunctions.emplace_back(Init);
573       }
574       break;
575     }
576     case wasm::WASM_COMDAT_INFO:
577       if (Error Err = parseLinkingSectionComdat(Ctx))
578         return Err;
579       break;
580     default:
581       Ctx.Ptr += Size;
582       break;
583     }
584     if (Ctx.Ptr != Ctx.End)
585       return make_error<GenericBinaryError>(
586           "linking sub-section ended prematurely", object_error::parse_failed);
587   }
588   if (Ctx.Ptr != OrigEnd)
589     return make_error<GenericBinaryError>("linking section ended prematurely",
590                                           object_error::parse_failed);
591   return Error::success();
592 }
593 
594 Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
595   uint32_t Count = readVaruint32(Ctx);
596   LinkingData.SymbolTable.reserve(Count);
597   Symbols.reserve(Count);
598   StringSet<> SymbolNames;
599 
600   std::vector<wasm::WasmImport *> ImportedGlobals;
601   std::vector<wasm::WasmImport *> ImportedFunctions;
602   std::vector<wasm::WasmImport *> ImportedTags;
603   std::vector<wasm::WasmImport *> ImportedTables;
604   ImportedGlobals.reserve(Imports.size());
605   ImportedFunctions.reserve(Imports.size());
606   ImportedTags.reserve(Imports.size());
607   ImportedTables.reserve(Imports.size());
608   for (auto &I : Imports) {
609     if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
610       ImportedFunctions.emplace_back(&I);
611     else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
612       ImportedGlobals.emplace_back(&I);
613     else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
614       ImportedTags.emplace_back(&I);
615     else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
616       ImportedTables.emplace_back(&I);
617   }
618 
619   while (Count--) {
620     wasm::WasmSymbolInfo Info;
621     const wasm::WasmSignature *Signature = nullptr;
622     const wasm::WasmGlobalType *GlobalType = nullptr;
623     const wasm::WasmTableType *TableType = nullptr;
624 
625     Info.Kind = readUint8(Ctx);
626     Info.Flags = readVaruint32(Ctx);
627     bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
628 
629     switch (Info.Kind) {
630     case wasm::WASM_SYMBOL_TYPE_FUNCTION:
631       Info.ElementIndex = readVaruint32(Ctx);
632       if (!isValidFunctionIndex(Info.ElementIndex) ||
633           IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
634         return make_error<GenericBinaryError>("invalid function symbol index",
635                                               object_error::parse_failed);
636       if (IsDefined) {
637         Info.Name = readString(Ctx);
638         unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
639         wasm::WasmFunction &Function = Functions[FuncIndex];
640         Signature = &Signatures[Function.SigIndex];
641         if (Function.SymbolName.empty())
642           Function.SymbolName = Info.Name;
643       } else {
644         wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
645         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
646           Info.Name = readString(Ctx);
647           Info.ImportName = Import.Field;
648         } else {
649           Info.Name = Import.Field;
650         }
651         Signature = &Signatures[Import.SigIndex];
652         if (!Import.Module.empty()) {
653           Info.ImportModule = Import.Module;
654         }
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         if (!Import.Module.empty()) {
685           Info.ImportModule = Import.Module;
686         }
687       }
688       break;
689 
690     case wasm::WASM_SYMBOL_TYPE_TABLE:
691       Info.ElementIndex = readVaruint32(Ctx);
692       if (!isValidTableNumber(Info.ElementIndex) ||
693           IsDefined != isDefinedTableNumber(Info.ElementIndex))
694         return make_error<GenericBinaryError>("invalid table symbol index",
695                                               object_error::parse_failed);
696       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
697                             wasm::WASM_SYMBOL_BINDING_WEAK)
698         return make_error<GenericBinaryError>("undefined weak table symbol",
699                                               object_error::parse_failed);
700       if (IsDefined) {
701         Info.Name = readString(Ctx);
702         unsigned TableNumber = Info.ElementIndex - NumImportedTables;
703         wasm::WasmTable &Table = Tables[TableNumber];
704         TableType = &Table.Type;
705         if (Table.SymbolName.empty())
706           Table.SymbolName = Info.Name;
707       } else {
708         wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
709         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
710           Info.Name = readString(Ctx);
711           Info.ImportName = Import.Field;
712         } else {
713           Info.Name = Import.Field;
714         }
715         TableType = &Import.Table;
716         if (!Import.Module.empty()) {
717           Info.ImportModule = Import.Module;
718         }
719       }
720       break;
721 
722     case wasm::WASM_SYMBOL_TYPE_DATA:
723       Info.Name = readString(Ctx);
724       if (IsDefined) {
725         auto Index = readVaruint32(Ctx);
726         if (Index >= DataSegments.size())
727           return make_error<GenericBinaryError>("invalid data symbol index",
728                                                 object_error::parse_failed);
729         auto Offset = readVaruint64(Ctx);
730         auto Size = readVaruint64(Ctx);
731         size_t SegmentSize = DataSegments[Index].Data.Content.size();
732         if (Offset > SegmentSize)
733           return make_error<GenericBinaryError>(
734               "invalid data symbol offset: `" + Info.Name + "` (offset: " +
735                   Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")",
736               object_error::parse_failed);
737         Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
738       }
739       break;
740 
741     case wasm::WASM_SYMBOL_TYPE_SECTION: {
742       if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
743           wasm::WASM_SYMBOL_BINDING_LOCAL)
744         return make_error<GenericBinaryError>(
745             "section symbols must have local binding",
746             object_error::parse_failed);
747       Info.ElementIndex = readVaruint32(Ctx);
748       // Use somewhat unique section name as symbol name.
749       StringRef SectionName = Sections[Info.ElementIndex].Name;
750       Info.Name = SectionName;
751       break;
752     }
753 
754     case wasm::WASM_SYMBOL_TYPE_TAG: {
755       Info.ElementIndex = readVaruint32(Ctx);
756       if (!isValidTagIndex(Info.ElementIndex) ||
757           IsDefined != isDefinedTagIndex(Info.ElementIndex))
758         return make_error<GenericBinaryError>("invalid tag symbol index",
759                                               object_error::parse_failed);
760       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
761                             wasm::WASM_SYMBOL_BINDING_WEAK)
762         return make_error<GenericBinaryError>("undefined weak global symbol",
763                                               object_error::parse_failed);
764       if (IsDefined) {
765         Info.Name = readString(Ctx);
766         unsigned TagIndex = Info.ElementIndex - NumImportedTags;
767         wasm::WasmTag &Tag = Tags[TagIndex];
768         Signature = &Signatures[Tag.SigIndex];
769         if (Tag.SymbolName.empty())
770           Tag.SymbolName = Info.Name;
771 
772       } else {
773         wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
774         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
775           Info.Name = readString(Ctx);
776           Info.ImportName = Import.Field;
777         } else {
778           Info.Name = Import.Field;
779         }
780         Signature = &Signatures[Import.SigIndex];
781         if (!Import.Module.empty()) {
782           Info.ImportModule = Import.Module;
783         }
784       }
785       break;
786     }
787 
788     default:
789       return make_error<GenericBinaryError>("invalid symbol type: " +
790                                                 Twine(unsigned(Info.Kind)),
791                                             object_error::parse_failed);
792     }
793 
794     if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
795             wasm::WASM_SYMBOL_BINDING_LOCAL &&
796         !SymbolNames.insert(Info.Name).second)
797       return make_error<GenericBinaryError>("duplicate symbol name " +
798                                                 Twine(Info.Name),
799                                             object_error::parse_failed);
800     LinkingData.SymbolTable.emplace_back(Info);
801     Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
802                          Signature);
803     LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
804   }
805 
806   return Error::success();
807 }
808 
809 Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
810   uint32_t ComdatCount = readVaruint32(Ctx);
811   StringSet<> ComdatSet;
812   for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
813     StringRef Name = readString(Ctx);
814     if (Name.empty() || !ComdatSet.insert(Name).second)
815       return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
816                                                 Twine(Name),
817                                             object_error::parse_failed);
818     LinkingData.Comdats.emplace_back(Name);
819     uint32_t Flags = readVaruint32(Ctx);
820     if (Flags != 0)
821       return make_error<GenericBinaryError>("unsupported COMDAT flags",
822                                             object_error::parse_failed);
823 
824     uint32_t EntryCount = readVaruint32(Ctx);
825     while (EntryCount--) {
826       unsigned Kind = readVaruint32(Ctx);
827       unsigned Index = readVaruint32(Ctx);
828       switch (Kind) {
829       default:
830         return make_error<GenericBinaryError>("invalid COMDAT entry type",
831                                               object_error::parse_failed);
832       case wasm::WASM_COMDAT_DATA:
833         if (Index >= DataSegments.size())
834           return make_error<GenericBinaryError>(
835               "COMDAT data index out of range", object_error::parse_failed);
836         if (DataSegments[Index].Data.Comdat != UINT32_MAX)
837           return make_error<GenericBinaryError>("data segment in two COMDATs",
838                                                 object_error::parse_failed);
839         DataSegments[Index].Data.Comdat = ComdatIndex;
840         break;
841       case wasm::WASM_COMDAT_FUNCTION:
842         if (!isDefinedFunctionIndex(Index))
843           return make_error<GenericBinaryError>(
844               "COMDAT function index out of range", object_error::parse_failed);
845         if (getDefinedFunction(Index).Comdat != UINT32_MAX)
846           return make_error<GenericBinaryError>("function in two COMDATs",
847                                                 object_error::parse_failed);
848         getDefinedFunction(Index).Comdat = ComdatIndex;
849         break;
850       case wasm::WASM_COMDAT_SECTION:
851         if (Index >= Sections.size())
852           return make_error<GenericBinaryError>(
853               "COMDAT section index out of range", object_error::parse_failed);
854         if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
855           return make_error<GenericBinaryError>(
856               "non-custom section in a COMDAT", object_error::parse_failed);
857         Sections[Index].Comdat = ComdatIndex;
858         break;
859       }
860     }
861   }
862   return Error::success();
863 }
864 
865 Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
866   llvm::SmallSet<StringRef, 3> FieldsSeen;
867   uint32_t Fields = readVaruint32(Ctx);
868   for (size_t I = 0; I < Fields; ++I) {
869     StringRef FieldName = readString(Ctx);
870     if (!FieldsSeen.insert(FieldName).second)
871       return make_error<GenericBinaryError>(
872           "producers section does not have unique fields",
873           object_error::parse_failed);
874     std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
875     if (FieldName == "language") {
876       ProducerVec = &ProducerInfo.Languages;
877     } else if (FieldName == "processed-by") {
878       ProducerVec = &ProducerInfo.Tools;
879     } else if (FieldName == "sdk") {
880       ProducerVec = &ProducerInfo.SDKs;
881     } else {
882       return make_error<GenericBinaryError>(
883           "producers section field is not named one of language, processed-by, "
884           "or sdk",
885           object_error::parse_failed);
886     }
887     uint32_t ValueCount = readVaruint32(Ctx);
888     llvm::SmallSet<StringRef, 8> ProducersSeen;
889     for (size_t J = 0; J < ValueCount; ++J) {
890       StringRef Name = readString(Ctx);
891       StringRef Version = readString(Ctx);
892       if (!ProducersSeen.insert(Name).second) {
893         return make_error<GenericBinaryError>(
894             "producers section contains repeated producer",
895             object_error::parse_failed);
896       }
897       ProducerVec->emplace_back(std::string(Name), std::string(Version));
898     }
899   }
900   if (Ctx.Ptr != Ctx.End)
901     return make_error<GenericBinaryError>("producers section ended prematurely",
902                                           object_error::parse_failed);
903   return Error::success();
904 }
905 
906 Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
907   llvm::SmallSet<std::string, 8> FeaturesSeen;
908   uint32_t FeatureCount = readVaruint32(Ctx);
909   for (size_t I = 0; I < FeatureCount; ++I) {
910     wasm::WasmFeatureEntry Feature;
911     Feature.Prefix = readUint8(Ctx);
912     switch (Feature.Prefix) {
913     case wasm::WASM_FEATURE_PREFIX_USED:
914     case wasm::WASM_FEATURE_PREFIX_REQUIRED:
915     case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
916       break;
917     default:
918       return make_error<GenericBinaryError>("unknown feature policy prefix",
919                                             object_error::parse_failed);
920     }
921     Feature.Name = std::string(readString(Ctx));
922     if (!FeaturesSeen.insert(Feature.Name).second)
923       return make_error<GenericBinaryError>(
924           "target features section contains repeated feature \"" +
925               Feature.Name + "\"",
926           object_error::parse_failed);
927     TargetFeatures.push_back(Feature);
928   }
929   if (Ctx.Ptr != Ctx.End)
930     return make_error<GenericBinaryError>(
931         "target features section ended prematurely",
932         object_error::parse_failed);
933   return Error::success();
934 }
935 
936 Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
937   uint32_t SectionIndex = readVaruint32(Ctx);
938   if (SectionIndex >= Sections.size())
939     return make_error<GenericBinaryError>("invalid section index",
940                                           object_error::parse_failed);
941   WasmSection &Section = Sections[SectionIndex];
942   uint32_t RelocCount = readVaruint32(Ctx);
943   uint32_t EndOffset = Section.Content.size();
944   uint32_t PreviousOffset = 0;
945   while (RelocCount--) {
946     wasm::WasmRelocation Reloc = {};
947     uint32_t type = readVaruint32(Ctx);
948     Reloc.Type = type;
949     Reloc.Offset = readVaruint32(Ctx);
950     if (Reloc.Offset < PreviousOffset)
951       return make_error<GenericBinaryError>("relocations not in offset order",
952                                             object_error::parse_failed);
953     PreviousOffset = Reloc.Offset;
954     Reloc.Index = readVaruint32(Ctx);
955     switch (type) {
956     case wasm::R_WASM_FUNCTION_INDEX_LEB:
957     case wasm::R_WASM_TABLE_INDEX_SLEB:
958     case wasm::R_WASM_TABLE_INDEX_SLEB64:
959     case wasm::R_WASM_TABLE_INDEX_I32:
960     case wasm::R_WASM_TABLE_INDEX_I64:
961     case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
962     case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
963       if (!isValidFunctionSymbol(Reloc.Index))
964         return make_error<GenericBinaryError>(
965             "invalid relocation function index", object_error::parse_failed);
966       break;
967     case wasm::R_WASM_TABLE_NUMBER_LEB:
968       if (!isValidTableSymbol(Reloc.Index))
969         return make_error<GenericBinaryError>("invalid relocation table index",
970                                               object_error::parse_failed);
971       break;
972     case wasm::R_WASM_TYPE_INDEX_LEB:
973       if (Reloc.Index >= Signatures.size())
974         return make_error<GenericBinaryError>("invalid relocation type index",
975                                               object_error::parse_failed);
976       break;
977     case wasm::R_WASM_GLOBAL_INDEX_LEB:
978       // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
979       // symbols to refer to their GOT entries.
980       if (!isValidGlobalSymbol(Reloc.Index) &&
981           !isValidDataSymbol(Reloc.Index) &&
982           !isValidFunctionSymbol(Reloc.Index))
983         return make_error<GenericBinaryError>("invalid relocation global index",
984                                               object_error::parse_failed);
985       break;
986     case wasm::R_WASM_GLOBAL_INDEX_I32:
987       if (!isValidGlobalSymbol(Reloc.Index))
988         return make_error<GenericBinaryError>("invalid relocation global index",
989                                               object_error::parse_failed);
990       break;
991     case wasm::R_WASM_TAG_INDEX_LEB:
992       if (!isValidTagSymbol(Reloc.Index))
993         return make_error<GenericBinaryError>("invalid relocation tag index",
994                                               object_error::parse_failed);
995       break;
996     case wasm::R_WASM_MEMORY_ADDR_LEB:
997     case wasm::R_WASM_MEMORY_ADDR_SLEB:
998     case wasm::R_WASM_MEMORY_ADDR_I32:
999     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1000     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1001     case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1002       if (!isValidDataSymbol(Reloc.Index))
1003         return make_error<GenericBinaryError>("invalid relocation data index",
1004                                               object_error::parse_failed);
1005       Reloc.Addend = readVarint32(Ctx);
1006       break;
1007     case wasm::R_WASM_MEMORY_ADDR_LEB64:
1008     case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1009     case wasm::R_WASM_MEMORY_ADDR_I64:
1010     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1011     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1012       if (!isValidDataSymbol(Reloc.Index))
1013         return make_error<GenericBinaryError>("invalid relocation data index",
1014                                               object_error::parse_failed);
1015       Reloc.Addend = readVarint64(Ctx);
1016       break;
1017     case wasm::R_WASM_FUNCTION_OFFSET_I32:
1018       if (!isValidFunctionSymbol(Reloc.Index))
1019         return make_error<GenericBinaryError>(
1020             "invalid relocation function index", object_error::parse_failed);
1021       Reloc.Addend = readVarint32(Ctx);
1022       break;
1023     case wasm::R_WASM_FUNCTION_OFFSET_I64:
1024       if (!isValidFunctionSymbol(Reloc.Index))
1025         return make_error<GenericBinaryError>(
1026             "invalid relocation function index", object_error::parse_failed);
1027       Reloc.Addend = readVarint64(Ctx);
1028       break;
1029     case wasm::R_WASM_SECTION_OFFSET_I32:
1030       if (!isValidSectionSymbol(Reloc.Index))
1031         return make_error<GenericBinaryError>(
1032             "invalid relocation section index", object_error::parse_failed);
1033       Reloc.Addend = readVarint32(Ctx);
1034       break;
1035     default:
1036       return make_error<GenericBinaryError>("invalid relocation type: " +
1037                                                 Twine(type),
1038                                             object_error::parse_failed);
1039     }
1040 
1041     // Relocations must fit inside the section, and must appear in order.  They
1042     // also shouldn't overlap a function/element boundary, but we don't bother
1043     // to check that.
1044     uint64_t Size = 5;
1045     if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1046         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1047         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1048       Size = 10;
1049     if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1050         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1051         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1052         Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1053         Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1054         Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1055       Size = 4;
1056     if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1057         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1058         Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1059       Size = 8;
1060     if (Reloc.Offset + Size > EndOffset)
1061       return make_error<GenericBinaryError>("invalid relocation offset",
1062                                             object_error::parse_failed);
1063 
1064     Section.Relocations.push_back(Reloc);
1065   }
1066   if (Ctx.Ptr != Ctx.End)
1067     return make_error<GenericBinaryError>("reloc section ended prematurely",
1068                                           object_error::parse_failed);
1069   return Error::success();
1070 }
1071 
1072 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
1073   if (Sec.Name == "dylink") {
1074     if (Error Err = parseDylinkSection(Ctx))
1075       return Err;
1076   } else if (Sec.Name == "dylink.0") {
1077     if (Error Err = parseDylink0Section(Ctx))
1078       return Err;
1079   } else if (Sec.Name == "name") {
1080     if (Error Err = parseNameSection(Ctx))
1081       return Err;
1082   } else if (Sec.Name == "linking") {
1083     if (Error Err = parseLinkingSection(Ctx))
1084       return Err;
1085   } else if (Sec.Name == "producers") {
1086     if (Error Err = parseProducersSection(Ctx))
1087       return Err;
1088   } else if (Sec.Name == "target_features") {
1089     if (Error Err = parseTargetFeaturesSection(Ctx))
1090       return Err;
1091   } else if (Sec.Name.startswith("reloc.")) {
1092     if (Error Err = parseRelocSection(Sec.Name, Ctx))
1093       return Err;
1094   }
1095   return Error::success();
1096 }
1097 
1098 Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1099   uint32_t Count = readVaruint32(Ctx);
1100   Signatures.reserve(Count);
1101   while (Count--) {
1102     wasm::WasmSignature Sig;
1103     uint8_t Form = readUint8(Ctx);
1104     if (Form != wasm::WASM_TYPE_FUNC) {
1105       return make_error<GenericBinaryError>("invalid signature type",
1106                                             object_error::parse_failed);
1107     }
1108     uint32_t ParamCount = readVaruint32(Ctx);
1109     Sig.Params.reserve(ParamCount);
1110     while (ParamCount--) {
1111       uint32_t ParamType = readUint8(Ctx);
1112       Sig.Params.push_back(wasm::ValType(ParamType));
1113     }
1114     uint32_t ReturnCount = readVaruint32(Ctx);
1115     while (ReturnCount--) {
1116       uint32_t ReturnType = readUint8(Ctx);
1117       Sig.Returns.push_back(wasm::ValType(ReturnType));
1118     }
1119     Signatures.push_back(std::move(Sig));
1120   }
1121   if (Ctx.Ptr != Ctx.End)
1122     return make_error<GenericBinaryError>("type section ended prematurely",
1123                                           object_error::parse_failed);
1124   return Error::success();
1125 }
1126 
1127 Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1128   uint32_t Count = readVaruint32(Ctx);
1129   uint32_t NumTypes = Signatures.size();
1130   Imports.reserve(Count);
1131   for (uint32_t I = 0; I < Count; I++) {
1132     wasm::WasmImport Im;
1133     Im.Module = readString(Ctx);
1134     Im.Field = readString(Ctx);
1135     Im.Kind = readUint8(Ctx);
1136     switch (Im.Kind) {
1137     case wasm::WASM_EXTERNAL_FUNCTION:
1138       NumImportedFunctions++;
1139       Im.SigIndex = readVaruint32(Ctx);
1140       if (Im.SigIndex >= NumTypes)
1141         return make_error<GenericBinaryError>("invalid function type",
1142                                               object_error::parse_failed);
1143       break;
1144     case wasm::WASM_EXTERNAL_GLOBAL:
1145       NumImportedGlobals++;
1146       Im.Global.Type = readUint8(Ctx);
1147       Im.Global.Mutable = readVaruint1(Ctx);
1148       break;
1149     case wasm::WASM_EXTERNAL_MEMORY:
1150       Im.Memory = readLimits(Ctx);
1151       if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1152         HasMemory64 = true;
1153       break;
1154     case wasm::WASM_EXTERNAL_TABLE: {
1155       Im.Table = readTableType(Ctx);
1156       NumImportedTables++;
1157       auto ElemType = Im.Table.ElemType;
1158       if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1159           ElemType != wasm::WASM_TYPE_EXTERNREF)
1160         return make_error<GenericBinaryError>("invalid table element type",
1161                                               object_error::parse_failed);
1162       break;
1163     }
1164     case wasm::WASM_EXTERNAL_TAG:
1165       NumImportedTags++;
1166       if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1167         return make_error<GenericBinaryError>("invalid attribute",
1168                                               object_error::parse_failed);
1169       Im.SigIndex = readVaruint32(Ctx);
1170       if (Im.SigIndex >= NumTypes)
1171         return make_error<GenericBinaryError>("invalid tag type",
1172                                               object_error::parse_failed);
1173       break;
1174     default:
1175       return make_error<GenericBinaryError>("unexpected import kind",
1176                                             object_error::parse_failed);
1177     }
1178     Imports.push_back(Im);
1179   }
1180   if (Ctx.Ptr != Ctx.End)
1181     return make_error<GenericBinaryError>("import section ended prematurely",
1182                                           object_error::parse_failed);
1183   return Error::success();
1184 }
1185 
1186 Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1187   uint32_t Count = readVaruint32(Ctx);
1188   Functions.reserve(Count);
1189   uint32_t NumTypes = Signatures.size();
1190   while (Count--) {
1191     uint32_t Type = readVaruint32(Ctx);
1192     if (Type >= NumTypes)
1193       return make_error<GenericBinaryError>("invalid function type",
1194                                             object_error::parse_failed);
1195     wasm::WasmFunction F;
1196     F.SigIndex = Type;
1197     Functions.push_back(F);
1198   }
1199   if (Ctx.Ptr != Ctx.End)
1200     return make_error<GenericBinaryError>("function section ended prematurely",
1201                                           object_error::parse_failed);
1202   return Error::success();
1203 }
1204 
1205 Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1206   TableSection = Sections.size();
1207   uint32_t Count = readVaruint32(Ctx);
1208   Tables.reserve(Count);
1209   while (Count--) {
1210     wasm::WasmTable T;
1211     T.Type = readTableType(Ctx);
1212     T.Index = NumImportedTables + Tables.size();
1213     Tables.push_back(T);
1214     auto ElemType = Tables.back().Type.ElemType;
1215     if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1216         ElemType != wasm::WASM_TYPE_EXTERNREF) {
1217       return make_error<GenericBinaryError>("invalid table element type",
1218                                             object_error::parse_failed);
1219     }
1220   }
1221   if (Ctx.Ptr != Ctx.End)
1222     return make_error<GenericBinaryError>("table section ended prematurely",
1223                                           object_error::parse_failed);
1224   return Error::success();
1225 }
1226 
1227 Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1228   uint32_t Count = readVaruint32(Ctx);
1229   Memories.reserve(Count);
1230   while (Count--) {
1231     auto Limits = readLimits(Ctx);
1232     if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1233       HasMemory64 = true;
1234     Memories.push_back(Limits);
1235   }
1236   if (Ctx.Ptr != Ctx.End)
1237     return make_error<GenericBinaryError>("memory section ended prematurely",
1238                                           object_error::parse_failed);
1239   return Error::success();
1240 }
1241 
1242 Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1243   TagSection = Sections.size();
1244   uint32_t Count = readVaruint32(Ctx);
1245   Tags.reserve(Count);
1246   uint32_t NumTypes = Signatures.size();
1247   while (Count--) {
1248     if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1249       return make_error<GenericBinaryError>("invalid attribute",
1250                                             object_error::parse_failed);
1251     uint32_t Type = readVaruint32(Ctx);
1252     if (Type >= NumTypes)
1253       return make_error<GenericBinaryError>("invalid tag type",
1254                                             object_error::parse_failed);
1255     wasm::WasmTag Tag;
1256     Tag.Index = NumImportedTags + Tags.size();
1257     Tag.SigIndex = Type;
1258     Tags.push_back(Tag);
1259   }
1260 
1261   if (Ctx.Ptr != Ctx.End)
1262     return make_error<GenericBinaryError>("tag section ended prematurely",
1263                                           object_error::parse_failed);
1264   return Error::success();
1265 }
1266 
1267 Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1268   GlobalSection = Sections.size();
1269   uint32_t Count = readVaruint32(Ctx);
1270   Globals.reserve(Count);
1271   while (Count--) {
1272     wasm::WasmGlobal Global;
1273     Global.Index = NumImportedGlobals + Globals.size();
1274     Global.Type.Type = readUint8(Ctx);
1275     Global.Type.Mutable = readVaruint1(Ctx);
1276     if (Error Err = readInitExpr(Global.InitExpr, Ctx))
1277       return Err;
1278     Globals.push_back(Global);
1279   }
1280   if (Ctx.Ptr != Ctx.End)
1281     return make_error<GenericBinaryError>("global section ended prematurely",
1282                                           object_error::parse_failed);
1283   return Error::success();
1284 }
1285 
1286 Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1287   uint32_t Count = readVaruint32(Ctx);
1288   Exports.reserve(Count);
1289   for (uint32_t I = 0; I < Count; I++) {
1290     wasm::WasmExport Ex;
1291     Ex.Name = readString(Ctx);
1292     Ex.Kind = readUint8(Ctx);
1293     Ex.Index = readVaruint32(Ctx);
1294     switch (Ex.Kind) {
1295     case wasm::WASM_EXTERNAL_FUNCTION:
1296 
1297       if (!isDefinedFunctionIndex(Ex.Index))
1298         return make_error<GenericBinaryError>("invalid function export",
1299                                               object_error::parse_failed);
1300       getDefinedFunction(Ex.Index).ExportName = Ex.Name;
1301       break;
1302     case wasm::WASM_EXTERNAL_GLOBAL:
1303       if (!isValidGlobalIndex(Ex.Index))
1304         return make_error<GenericBinaryError>("invalid global export",
1305                                               object_error::parse_failed);
1306       break;
1307     case wasm::WASM_EXTERNAL_TAG:
1308       if (!isValidTagIndex(Ex.Index))
1309         return make_error<GenericBinaryError>("invalid tag export",
1310                                               object_error::parse_failed);
1311       break;
1312     case wasm::WASM_EXTERNAL_MEMORY:
1313     case wasm::WASM_EXTERNAL_TABLE:
1314       break;
1315     default:
1316       return make_error<GenericBinaryError>("unexpected export kind",
1317                                             object_error::parse_failed);
1318     }
1319     Exports.push_back(Ex);
1320   }
1321   if (Ctx.Ptr != Ctx.End)
1322     return make_error<GenericBinaryError>("export section ended prematurely",
1323                                           object_error::parse_failed);
1324   return Error::success();
1325 }
1326 
1327 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1328   return Index < NumImportedFunctions + Functions.size();
1329 }
1330 
1331 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1332   return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1333 }
1334 
1335 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1336   return Index < NumImportedGlobals + Globals.size();
1337 }
1338 
1339 bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1340   return Index < NumImportedTables + Tables.size();
1341 }
1342 
1343 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1344   return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1345 }
1346 
1347 bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1348   return Index >= NumImportedTables && isValidTableNumber(Index);
1349 }
1350 
1351 bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1352   return Index < NumImportedTags + Tags.size();
1353 }
1354 
1355 bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1356   return Index >= NumImportedTags && isValidTagIndex(Index);
1357 }
1358 
1359 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1360   return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1361 }
1362 
1363 bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1364   return Index < Symbols.size() && Symbols[Index].isTypeTable();
1365 }
1366 
1367 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1368   return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1369 }
1370 
1371 bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1372   return Index < Symbols.size() && Symbols[Index].isTypeTag();
1373 }
1374 
1375 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1376   return Index < Symbols.size() && Symbols[Index].isTypeData();
1377 }
1378 
1379 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1380   return Index < Symbols.size() && Symbols[Index].isTypeSection();
1381 }
1382 
1383 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1384   assert(isDefinedFunctionIndex(Index));
1385   return Functions[Index - NumImportedFunctions];
1386 }
1387 
1388 const wasm::WasmFunction &
1389 WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1390   assert(isDefinedFunctionIndex(Index));
1391   return Functions[Index - NumImportedFunctions];
1392 }
1393 
1394 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
1395   assert(isDefinedGlobalIndex(Index));
1396   return Globals[Index - NumImportedGlobals];
1397 }
1398 
1399 wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1400   assert(isDefinedTagIndex(Index));
1401   return Tags[Index - NumImportedTags];
1402 }
1403 
1404 Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1405   StartFunction = readVaruint32(Ctx);
1406   if (!isValidFunctionIndex(StartFunction))
1407     return make_error<GenericBinaryError>("invalid start function",
1408                                           object_error::parse_failed);
1409   return Error::success();
1410 }
1411 
1412 Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1413   SeenCodeSection = true;
1414   CodeSection = Sections.size();
1415   uint32_t FunctionCount = readVaruint32(Ctx);
1416   if (FunctionCount != Functions.size()) {
1417     return make_error<GenericBinaryError>("invalid function count",
1418                                           object_error::parse_failed);
1419   }
1420 
1421   for (uint32_t i = 0; i < FunctionCount; i++) {
1422     wasm::WasmFunction& Function = Functions[i];
1423     const uint8_t *FunctionStart = Ctx.Ptr;
1424     uint32_t Size = readVaruint32(Ctx);
1425     const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1426 
1427     Function.CodeOffset = Ctx.Ptr - FunctionStart;
1428     Function.Index = NumImportedFunctions + i;
1429     Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1430     Function.Size = FunctionEnd - FunctionStart;
1431 
1432     uint32_t NumLocalDecls = readVaruint32(Ctx);
1433     Function.Locals.reserve(NumLocalDecls);
1434     while (NumLocalDecls--) {
1435       wasm::WasmLocalDecl Decl;
1436       Decl.Count = readVaruint32(Ctx);
1437       Decl.Type = readUint8(Ctx);
1438       Function.Locals.push_back(Decl);
1439     }
1440 
1441     uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1442     Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1443     // This will be set later when reading in the linking metadata section.
1444     Function.Comdat = UINT32_MAX;
1445     Ctx.Ptr += BodySize;
1446     assert(Ctx.Ptr == FunctionEnd);
1447   }
1448   if (Ctx.Ptr != Ctx.End)
1449     return make_error<GenericBinaryError>("code section ended prematurely",
1450                                           object_error::parse_failed);
1451   return Error::success();
1452 }
1453 
1454 Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1455   uint32_t Count = readVaruint32(Ctx);
1456   ElemSegments.reserve(Count);
1457   while (Count--) {
1458     wasm::WasmElemSegment Segment;
1459     Segment.Flags = readVaruint32(Ctx);
1460 
1461     uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
1462                               wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |
1463                               wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;
1464     if (Segment.Flags & ~SupportedFlags)
1465       return make_error<GenericBinaryError>(
1466           "Unsupported flags for element segment", object_error::parse_failed);
1467 
1468     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
1469       Segment.TableNumber = readVaruint32(Ctx);
1470     else
1471       Segment.TableNumber = 0;
1472     if (!isValidTableNumber(Segment.TableNumber))
1473       return make_error<GenericBinaryError>("invalid TableNumber",
1474                                             object_error::parse_failed);
1475 
1476     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
1477       Segment.Offset.Extended = false;
1478       Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1479       Segment.Offset.Inst.Value.Int32 = 0;
1480     } else {
1481       if (Error Err = readInitExpr(Segment.Offset, Ctx))
1482         return Err;
1483     }
1484 
1485     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
1486       Segment.ElemKind = readUint8(Ctx);
1487       if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
1488         if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) &&
1489             Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) {
1490           return make_error<GenericBinaryError>("invalid reference type",
1491                                                 object_error::parse_failed);
1492         }
1493       } else {
1494         if (Segment.ElemKind != 0)
1495           return make_error<GenericBinaryError>("invalid elemtype",
1496                                                 object_error::parse_failed);
1497         Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1498       }
1499     } else {
1500       Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1501     }
1502 
1503     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS)
1504       return make_error<GenericBinaryError>(
1505           "elem segment init expressions not yet implemented",
1506           object_error::parse_failed);
1507 
1508     uint32_t NumElems = readVaruint32(Ctx);
1509     while (NumElems--) {
1510       Segment.Functions.push_back(readVaruint32(Ctx));
1511     }
1512     ElemSegments.push_back(Segment);
1513   }
1514   if (Ctx.Ptr != Ctx.End)
1515     return make_error<GenericBinaryError>("elem section ended prematurely",
1516                                           object_error::parse_failed);
1517   return Error::success();
1518 }
1519 
1520 Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1521   DataSection = Sections.size();
1522   uint32_t Count = readVaruint32(Ctx);
1523   if (DataCount && Count != DataCount.getValue())
1524     return make_error<GenericBinaryError>(
1525         "number of data segments does not match DataCount section");
1526   DataSegments.reserve(Count);
1527   while (Count--) {
1528     WasmSegment Segment;
1529     Segment.Data.InitFlags = readVaruint32(Ctx);
1530     Segment.Data.MemoryIndex =
1531         (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1532             ? readVaruint32(Ctx)
1533             : 0;
1534     if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1535       if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1536         return Err;
1537     } else {
1538       Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1539       Segment.Data.Offset.Inst.Value.Int32 = 0;
1540     }
1541     uint32_t Size = readVaruint32(Ctx);
1542     if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1543       return make_error<GenericBinaryError>("invalid segment size",
1544                                             object_error::parse_failed);
1545     Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1546     // The rest of these Data fields are set later, when reading in the linking
1547     // metadata section.
1548     Segment.Data.Alignment = 0;
1549     Segment.Data.LinkingFlags = 0;
1550     Segment.Data.Comdat = UINT32_MAX;
1551     Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1552     Ctx.Ptr += Size;
1553     DataSegments.push_back(Segment);
1554   }
1555   if (Ctx.Ptr != Ctx.End)
1556     return make_error<GenericBinaryError>("data section ended prematurely",
1557                                           object_error::parse_failed);
1558   return Error::success();
1559 }
1560 
1561 Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1562   DataCount = readVaruint32(Ctx);
1563   return Error::success();
1564 }
1565 
1566 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1567   return Header;
1568 }
1569 
1570 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1571 
1572 Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1573   uint32_t Result = SymbolRef::SF_None;
1574   const WasmSymbol &Sym = getWasmSymbol(Symb);
1575 
1576   LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1577   if (Sym.isBindingWeak())
1578     Result |= SymbolRef::SF_Weak;
1579   if (!Sym.isBindingLocal())
1580     Result |= SymbolRef::SF_Global;
1581   if (Sym.isHidden())
1582     Result |= SymbolRef::SF_Hidden;
1583   if (!Sym.isDefined())
1584     Result |= SymbolRef::SF_Undefined;
1585   if (Sym.isTypeFunction())
1586     Result |= SymbolRef::SF_Executable;
1587   return Result;
1588 }
1589 
1590 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1591   DataRefImpl Ref;
1592   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1593   Ref.d.b = 0; // Symbol index
1594   return BasicSymbolRef(Ref, this);
1595 }
1596 
1597 basic_symbol_iterator WasmObjectFile::symbol_end() const {
1598   DataRefImpl Ref;
1599   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1600   Ref.d.b = Symbols.size(); // Symbol index
1601   return BasicSymbolRef(Ref, this);
1602 }
1603 
1604 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1605   return Symbols[Symb.d.b];
1606 }
1607 
1608 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1609   return getWasmSymbol(Symb.getRawDataRefImpl());
1610 }
1611 
1612 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1613   return getWasmSymbol(Symb).Info.Name;
1614 }
1615 
1616 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1617   auto &Sym = getWasmSymbol(Symb);
1618   if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1619       isDefinedFunctionIndex(Sym.Info.ElementIndex))
1620     return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
1621   else
1622     return getSymbolValue(Symb);
1623 }
1624 
1625 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1626   switch (Sym.Info.Kind) {
1627   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1628   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1629   case wasm::WASM_SYMBOL_TYPE_TAG:
1630   case wasm::WASM_SYMBOL_TYPE_TABLE:
1631     return Sym.Info.ElementIndex;
1632   case wasm::WASM_SYMBOL_TYPE_DATA: {
1633     // The value of a data symbol is the segment offset, plus the symbol
1634     // offset within the segment.
1635     uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1636     const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1637     if (Segment.Offset.Extended) {
1638       llvm_unreachable("extended init exprs not supported");
1639     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1640       return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
1641     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1642       return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
1643     } else {
1644       llvm_unreachable("unknown init expr opcode");
1645     }
1646   }
1647   case wasm::WASM_SYMBOL_TYPE_SECTION:
1648     return 0;
1649   }
1650   llvm_unreachable("invalid symbol type");
1651 }
1652 
1653 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1654   return getWasmSymbolValue(getWasmSymbol(Symb));
1655 }
1656 
1657 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1658   llvm_unreachable("not yet implemented");
1659   return 0;
1660 }
1661 
1662 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1663   llvm_unreachable("not yet implemented");
1664   return 0;
1665 }
1666 
1667 Expected<SymbolRef::Type>
1668 WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1669   const WasmSymbol &Sym = getWasmSymbol(Symb);
1670 
1671   switch (Sym.Info.Kind) {
1672   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1673     return SymbolRef::ST_Function;
1674   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1675     return SymbolRef::ST_Other;
1676   case wasm::WASM_SYMBOL_TYPE_DATA:
1677     return SymbolRef::ST_Data;
1678   case wasm::WASM_SYMBOL_TYPE_SECTION:
1679     return SymbolRef::ST_Debug;
1680   case wasm::WASM_SYMBOL_TYPE_TAG:
1681     return SymbolRef::ST_Other;
1682   case wasm::WASM_SYMBOL_TYPE_TABLE:
1683     return SymbolRef::ST_Other;
1684   }
1685 
1686   llvm_unreachable("unknown WasmSymbol::SymbolType");
1687   return SymbolRef::ST_Other;
1688 }
1689 
1690 Expected<section_iterator>
1691 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1692   const WasmSymbol &Sym = getWasmSymbol(Symb);
1693   if (Sym.isUndefined())
1694     return section_end();
1695 
1696   DataRefImpl Ref;
1697   Ref.d.a = getSymbolSectionIdImpl(Sym);
1698   return section_iterator(SectionRef(Ref, this));
1699 }
1700 
1701 uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
1702   const WasmSymbol &Sym = getWasmSymbol(Symb);
1703   return getSymbolSectionIdImpl(Sym);
1704 }
1705 
1706 uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
1707   switch (Sym.Info.Kind) {
1708   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1709     return CodeSection;
1710   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1711     return GlobalSection;
1712   case wasm::WASM_SYMBOL_TYPE_DATA:
1713     return DataSection;
1714   case wasm::WASM_SYMBOL_TYPE_SECTION:
1715     return Sym.Info.ElementIndex;
1716   case wasm::WASM_SYMBOL_TYPE_TAG:
1717     return TagSection;
1718   case wasm::WASM_SYMBOL_TYPE_TABLE:
1719     return TableSection;
1720   default:
1721     llvm_unreachable("unknown WasmSymbol::SymbolType");
1722   }
1723 }
1724 
1725 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1726 
1727 Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
1728   const WasmSection &S = Sections[Sec.d.a];
1729 #define ECase(X)                                                               \
1730   case wasm::WASM_SEC_##X:                                                     \
1731     return #X;
1732   switch (S.Type) {
1733     ECase(TYPE);
1734     ECase(IMPORT);
1735     ECase(FUNCTION);
1736     ECase(TABLE);
1737     ECase(MEMORY);
1738     ECase(GLOBAL);
1739     ECase(TAG);
1740     ECase(EXPORT);
1741     ECase(START);
1742     ECase(ELEM);
1743     ECase(CODE);
1744     ECase(DATA);
1745     ECase(DATACOUNT);
1746   case wasm::WASM_SEC_CUSTOM:
1747     return S.Name;
1748   default:
1749     return createStringError(object_error::invalid_section_index, "");
1750   }
1751 #undef ECase
1752 }
1753 
1754 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1755 
1756 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1757   return Sec.d.a;
1758 }
1759 
1760 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1761   const WasmSection &S = Sections[Sec.d.a];
1762   return S.Content.size();
1763 }
1764 
1765 Expected<ArrayRef<uint8_t>>
1766 WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
1767   const WasmSection &S = Sections[Sec.d.a];
1768   // This will never fail since wasm sections can never be empty (user-sections
1769   // must have a name and non-user sections each have a defined structure).
1770   return S.Content;
1771 }
1772 
1773 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1774   return 1;
1775 }
1776 
1777 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1778   return false;
1779 }
1780 
1781 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1782   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1783 }
1784 
1785 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1786   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1787 }
1788 
1789 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1790 
1791 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1792 
1793 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1794   DataRefImpl RelocRef;
1795   RelocRef.d.a = Ref.d.a;
1796   RelocRef.d.b = 0;
1797   return relocation_iterator(RelocationRef(RelocRef, this));
1798 }
1799 
1800 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1801   const WasmSection &Sec = getWasmSection(Ref);
1802   DataRefImpl RelocRef;
1803   RelocRef.d.a = Ref.d.a;
1804   RelocRef.d.b = Sec.Relocations.size();
1805   return relocation_iterator(RelocationRef(RelocRef, this));
1806 }
1807 
1808 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1809 
1810 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1811   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1812   return Rel.Offset;
1813 }
1814 
1815 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1816   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1817   if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
1818     return symbol_end();
1819   DataRefImpl Sym;
1820   Sym.d.a = 1;
1821   Sym.d.b = Rel.Index;
1822   return symbol_iterator(SymbolRef(Sym, this));
1823 }
1824 
1825 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1826   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1827   return Rel.Type;
1828 }
1829 
1830 void WasmObjectFile::getRelocationTypeName(
1831     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1832   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1833   StringRef Res = "Unknown";
1834 
1835 #define WASM_RELOC(name, value)                                                \
1836   case wasm::name:                                                             \
1837     Res = #name;                                                               \
1838     break;
1839 
1840   switch (Rel.Type) {
1841 #include "llvm/BinaryFormat/WasmRelocs.def"
1842   }
1843 
1844 #undef WASM_RELOC
1845 
1846   Result.append(Res.begin(), Res.end());
1847 }
1848 
1849 section_iterator WasmObjectFile::section_begin() const {
1850   DataRefImpl Ref;
1851   Ref.d.a = 0;
1852   return section_iterator(SectionRef(Ref, this));
1853 }
1854 
1855 section_iterator WasmObjectFile::section_end() const {
1856   DataRefImpl Ref;
1857   Ref.d.a = Sections.size();
1858   return section_iterator(SectionRef(Ref, this));
1859 }
1860 
1861 uint8_t WasmObjectFile::getBytesInAddress() const {
1862   return HasMemory64 ? 8 : 4;
1863 }
1864 
1865 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1866 
1867 Triple::ArchType WasmObjectFile::getArch() const {
1868   return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
1869 }
1870 
1871 SubtargetFeatures WasmObjectFile::getFeatures() const {
1872   return SubtargetFeatures();
1873 }
1874 
1875 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1876 
1877 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1878 
1879 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1880   assert(Ref.d.a < Sections.size());
1881   return Sections[Ref.d.a];
1882 }
1883 
1884 const WasmSection &
1885 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1886   return getWasmSection(Section.getRawDataRefImpl());
1887 }
1888 
1889 const wasm::WasmRelocation &
1890 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1891   return getWasmRelocation(Ref.getRawDataRefImpl());
1892 }
1893 
1894 const wasm::WasmRelocation &
1895 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1896   assert(Ref.d.a < Sections.size());
1897   const WasmSection &Sec = Sections[Ref.d.a];
1898   assert(Ref.d.b < Sec.Relocations.size());
1899   return Sec.Relocations[Ref.d.b];
1900 }
1901 
1902 int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1903                                              StringRef CustomSectionName) {
1904   switch (ID) {
1905   case wasm::WASM_SEC_CUSTOM:
1906     return StringSwitch<unsigned>(CustomSectionName)
1907         .Case("dylink", WASM_SEC_ORDER_DYLINK)
1908         .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
1909         .Case("linking", WASM_SEC_ORDER_LINKING)
1910         .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1911         .Case("name", WASM_SEC_ORDER_NAME)
1912         .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1913         .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
1914         .Default(WASM_SEC_ORDER_NONE);
1915   case wasm::WASM_SEC_TYPE:
1916     return WASM_SEC_ORDER_TYPE;
1917   case wasm::WASM_SEC_IMPORT:
1918     return WASM_SEC_ORDER_IMPORT;
1919   case wasm::WASM_SEC_FUNCTION:
1920     return WASM_SEC_ORDER_FUNCTION;
1921   case wasm::WASM_SEC_TABLE:
1922     return WASM_SEC_ORDER_TABLE;
1923   case wasm::WASM_SEC_MEMORY:
1924     return WASM_SEC_ORDER_MEMORY;
1925   case wasm::WASM_SEC_GLOBAL:
1926     return WASM_SEC_ORDER_GLOBAL;
1927   case wasm::WASM_SEC_EXPORT:
1928     return WASM_SEC_ORDER_EXPORT;
1929   case wasm::WASM_SEC_START:
1930     return WASM_SEC_ORDER_START;
1931   case wasm::WASM_SEC_ELEM:
1932     return WASM_SEC_ORDER_ELEM;
1933   case wasm::WASM_SEC_CODE:
1934     return WASM_SEC_ORDER_CODE;
1935   case wasm::WASM_SEC_DATA:
1936     return WASM_SEC_ORDER_DATA;
1937   case wasm::WASM_SEC_DATACOUNT:
1938     return WASM_SEC_ORDER_DATACOUNT;
1939   case wasm::WASM_SEC_TAG:
1940     return WASM_SEC_ORDER_TAG;
1941   default:
1942     return WASM_SEC_ORDER_NONE;
1943   }
1944 }
1945 
1946 // Represents the edges in a directed graph where any node B reachable from node
1947 // A is not allowed to appear before A in the section ordering, but may appear
1948 // afterward.
1949 int WasmSectionOrderChecker::DisallowedPredecessors
1950     [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
1951         // WASM_SEC_ORDER_NONE
1952         {},
1953         // WASM_SEC_ORDER_TYPE
1954         {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
1955         // WASM_SEC_ORDER_IMPORT
1956         {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
1957         // WASM_SEC_ORDER_FUNCTION
1958         {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
1959         // WASM_SEC_ORDER_TABLE
1960         {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
1961         // WASM_SEC_ORDER_MEMORY
1962         {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
1963         // WASM_SEC_ORDER_TAG
1964         {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
1965         // WASM_SEC_ORDER_GLOBAL
1966         {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
1967         // WASM_SEC_ORDER_EXPORT
1968         {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
1969         // WASM_SEC_ORDER_START
1970         {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
1971         // WASM_SEC_ORDER_ELEM
1972         {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
1973         // WASM_SEC_ORDER_DATACOUNT
1974         {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
1975         // WASM_SEC_ORDER_CODE
1976         {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
1977         // WASM_SEC_ORDER_DATA
1978         {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
1979 
1980         // Custom Sections
1981         // WASM_SEC_ORDER_DYLINK
1982         {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
1983         // WASM_SEC_ORDER_LINKING
1984         {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
1985         // WASM_SEC_ORDER_RELOC (can be repeated)
1986         {},
1987         // WASM_SEC_ORDER_NAME
1988         {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
1989         // WASM_SEC_ORDER_PRODUCERS
1990         {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
1991         // WASM_SEC_ORDER_TARGET_FEATURES
1992         {WASM_SEC_ORDER_TARGET_FEATURES}};
1993 
1994 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
1995                                                   StringRef CustomSectionName) {
1996   int Order = getSectionOrder(ID, CustomSectionName);
1997   if (Order == WASM_SEC_ORDER_NONE)
1998     return true;
1999 
2000   // Disallowed predecessors we need to check for
2001   SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
2002 
2003   // Keep track of completed checks to avoid repeating work
2004   bool Checked[WASM_NUM_SEC_ORDERS] = {};
2005 
2006   int Curr = Order;
2007   while (true) {
2008     // Add new disallowed predecessors to work list
2009     for (size_t I = 0;; ++I) {
2010       int Next = DisallowedPredecessors[Curr][I];
2011       if (Next == WASM_SEC_ORDER_NONE)
2012         break;
2013       if (Checked[Next])
2014         continue;
2015       WorkList.push_back(Next);
2016       Checked[Next] = true;
2017     }
2018 
2019     if (WorkList.empty())
2020       break;
2021 
2022     // Consider next disallowed predecessor
2023     Curr = WorkList.pop_back_val();
2024     if (Seen[Curr])
2025       return false;
2026   }
2027 
2028   // Have not seen any disallowed predecessors
2029   Seen[Order] = true;
2030   return true;
2031 }
2032