xref: /freebsd/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp (revision 02e9120893770924227138ba49df1edb3896112a)
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   // When reading the section's size, store the size of the LEB used to encode
272   // it. This allows objcopy/strip to reproduce the binary identically.
273   const uint8_t *PreSizePtr = Ctx.Ptr;
274   uint32_t Size = readVaruint32(Ctx);
275   Section.HeaderSecSizeEncodingLen = Ctx.Ptr - PreSizePtr;
276   if (Size == 0)
277     return make_error<StringError>("zero length section",
278                                    object_error::parse_failed);
279   if (Ctx.Ptr + Size > Ctx.End)
280     return make_error<StringError>("section too large",
281                                    object_error::parse_failed);
282   if (Section.Type == wasm::WASM_SEC_CUSTOM) {
283     WasmObjectFile::ReadContext SectionCtx;
284     SectionCtx.Start = Ctx.Ptr;
285     SectionCtx.Ptr = Ctx.Ptr;
286     SectionCtx.End = Ctx.Ptr + Size;
287 
288     Section.Name = readString(SectionCtx);
289 
290     uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
291     Ctx.Ptr += SectionNameSize;
292     Size -= SectionNameSize;
293   }
294 
295   if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
296     return make_error<StringError>("out of order section type: " +
297                                        llvm::to_string(Section.Type),
298                                    object_error::parse_failed);
299   }
300 
301   Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
302   Ctx.Ptr += Size;
303   return Error::success();
304 }
305 
306 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
307     : ObjectFile(Binary::ID_Wasm, Buffer) {
308   ErrorAsOutParameter ErrAsOutParam(&Err);
309   Header.Magic = getData().substr(0, 4);
310   if (Header.Magic != StringRef("\0asm", 4)) {
311     Err = make_error<StringError>("invalid magic number",
312                                   object_error::parse_failed);
313     return;
314   }
315 
316   ReadContext Ctx;
317   Ctx.Start = getData().bytes_begin();
318   Ctx.Ptr = Ctx.Start + 4;
319   Ctx.End = Ctx.Start + getData().size();
320 
321   if (Ctx.Ptr + 4 > Ctx.End) {
322     Err = make_error<StringError>("missing version number",
323                                   object_error::parse_failed);
324     return;
325   }
326 
327   Header.Version = readUint32(Ctx);
328   if (Header.Version != wasm::WasmVersion) {
329     Err = make_error<StringError>("invalid version number: " +
330                                       Twine(Header.Version),
331                                   object_error::parse_failed);
332     return;
333   }
334 
335   WasmSectionOrderChecker Checker;
336   while (Ctx.Ptr < Ctx.End) {
337     WasmSection Sec;
338     if ((Err = readSection(Sec, Ctx, Checker)))
339       return;
340     if ((Err = parseSection(Sec)))
341       return;
342 
343     Sections.push_back(Sec);
344   }
345 }
346 
347 Error WasmObjectFile::parseSection(WasmSection &Sec) {
348   ReadContext Ctx;
349   Ctx.Start = Sec.Content.data();
350   Ctx.End = Ctx.Start + Sec.Content.size();
351   Ctx.Ptr = Ctx.Start;
352   switch (Sec.Type) {
353   case wasm::WASM_SEC_CUSTOM:
354     return parseCustomSection(Sec, Ctx);
355   case wasm::WASM_SEC_TYPE:
356     return parseTypeSection(Ctx);
357   case wasm::WASM_SEC_IMPORT:
358     return parseImportSection(Ctx);
359   case wasm::WASM_SEC_FUNCTION:
360     return parseFunctionSection(Ctx);
361   case wasm::WASM_SEC_TABLE:
362     return parseTableSection(Ctx);
363   case wasm::WASM_SEC_MEMORY:
364     return parseMemorySection(Ctx);
365   case wasm::WASM_SEC_TAG:
366     return parseTagSection(Ctx);
367   case wasm::WASM_SEC_GLOBAL:
368     return parseGlobalSection(Ctx);
369   case wasm::WASM_SEC_EXPORT:
370     return parseExportSection(Ctx);
371   case wasm::WASM_SEC_START:
372     return parseStartSection(Ctx);
373   case wasm::WASM_SEC_ELEM:
374     return parseElemSection(Ctx);
375   case wasm::WASM_SEC_CODE:
376     return parseCodeSection(Ctx);
377   case wasm::WASM_SEC_DATA:
378     return parseDataSection(Ctx);
379   case wasm::WASM_SEC_DATACOUNT:
380     return parseDataCountSection(Ctx);
381   default:
382     return make_error<GenericBinaryError>(
383         "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
384   }
385 }
386 
387 Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
388   // Legacy "dylink" section support.
389   // See parseDylink0Section for the current "dylink.0" section parsing.
390   HasDylinkSection = true;
391   DylinkInfo.MemorySize = readVaruint32(Ctx);
392   DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
393   DylinkInfo.TableSize = readVaruint32(Ctx);
394   DylinkInfo.TableAlignment = readVaruint32(Ctx);
395   uint32_t Count = readVaruint32(Ctx);
396   while (Count--) {
397     DylinkInfo.Needed.push_back(readString(Ctx));
398   }
399 
400   if (Ctx.Ptr != Ctx.End)
401     return make_error<GenericBinaryError>("dylink section ended prematurely",
402                                           object_error::parse_failed);
403   return Error::success();
404 }
405 
406 Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
407   // See
408   // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
409   HasDylinkSection = true;
410 
411   const uint8_t *OrigEnd = Ctx.End;
412   while (Ctx.Ptr < OrigEnd) {
413     Ctx.End = OrigEnd;
414     uint8_t Type = readUint8(Ctx);
415     uint32_t Size = readVaruint32(Ctx);
416     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
417                       << "\n");
418     Ctx.End = Ctx.Ptr + Size;
419     uint32_t Count;
420     switch (Type) {
421     case wasm::WASM_DYLINK_MEM_INFO:
422       DylinkInfo.MemorySize = readVaruint32(Ctx);
423       DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
424       DylinkInfo.TableSize = readVaruint32(Ctx);
425       DylinkInfo.TableAlignment = readVaruint32(Ctx);
426       break;
427     case wasm::WASM_DYLINK_NEEDED:
428       Count = readVaruint32(Ctx);
429       while (Count--) {
430         DylinkInfo.Needed.push_back(readString(Ctx));
431       }
432       break;
433     case wasm::WASM_DYLINK_EXPORT_INFO: {
434       uint32_t Count = readVaruint32(Ctx);
435       while (Count--) {
436         DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)});
437       }
438       break;
439     }
440     case wasm::WASM_DYLINK_IMPORT_INFO: {
441       uint32_t Count = readVaruint32(Ctx);
442       while (Count--) {
443         DylinkInfo.ImportInfo.push_back(
444             {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
445       }
446       break;
447     }
448     default:
449       LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
450       Ctx.Ptr += Size;
451       break;
452     }
453     if (Ctx.Ptr != Ctx.End) {
454       return make_error<GenericBinaryError>(
455           "dylink.0 sub-section ended prematurely", object_error::parse_failed);
456     }
457   }
458 
459   if (Ctx.Ptr != Ctx.End)
460     return make_error<GenericBinaryError>("dylink.0 section ended prematurely",
461                                           object_error::parse_failed);
462   return Error::success();
463 }
464 
465 Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
466   llvm::DenseSet<uint64_t> SeenFunctions;
467   llvm::DenseSet<uint64_t> SeenGlobals;
468   llvm::DenseSet<uint64_t> SeenSegments;
469 
470   while (Ctx.Ptr < Ctx.End) {
471     uint8_t Type = readUint8(Ctx);
472     uint32_t Size = readVaruint32(Ctx);
473     const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
474     switch (Type) {
475     case wasm::WASM_NAMES_FUNCTION:
476     case wasm::WASM_NAMES_GLOBAL:
477     case wasm::WASM_NAMES_DATA_SEGMENT: {
478       uint32_t Count = readVaruint32(Ctx);
479       while (Count--) {
480         uint32_t Index = readVaruint32(Ctx);
481         StringRef Name = readString(Ctx);
482         wasm::NameType nameType = wasm::NameType::FUNCTION;
483         if (Type == wasm::WASM_NAMES_FUNCTION) {
484           if (!SeenFunctions.insert(Index).second)
485             return make_error<GenericBinaryError>(
486                 "function named more than once", object_error::parse_failed);
487           if (!isValidFunctionIndex(Index) || Name.empty())
488             return make_error<GenericBinaryError>("invalid function name entry",
489                                                   object_error::parse_failed);
490 
491           if (isDefinedFunctionIndex(Index))
492             getDefinedFunction(Index).DebugName = Name;
493         } else if (Type == wasm::WASM_NAMES_GLOBAL) {
494           nameType = wasm::NameType::GLOBAL;
495           if (!SeenGlobals.insert(Index).second)
496             return make_error<GenericBinaryError>("global named more than once",
497                                                   object_error::parse_failed);
498           if (!isValidGlobalIndex(Index) || Name.empty())
499             return make_error<GenericBinaryError>("invalid global name entry",
500                                                   object_error::parse_failed);
501         } else {
502           nameType = wasm::NameType::DATA_SEGMENT;
503           if (!SeenSegments.insert(Index).second)
504             return make_error<GenericBinaryError>(
505                 "segment named more than once", object_error::parse_failed);
506           if (Index > DataSegments.size())
507             return make_error<GenericBinaryError>("invalid data segment name entry",
508                                                   object_error::parse_failed);
509         }
510         DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
511       }
512       break;
513     }
514     // Ignore local names for now
515     case wasm::WASM_NAMES_LOCAL:
516     default:
517       Ctx.Ptr += Size;
518       break;
519     }
520     if (Ctx.Ptr != SubSectionEnd)
521       return make_error<GenericBinaryError>(
522           "name sub-section ended prematurely", object_error::parse_failed);
523   }
524 
525   if (Ctx.Ptr != Ctx.End)
526     return make_error<GenericBinaryError>("name section ended prematurely",
527                                           object_error::parse_failed);
528   return Error::success();
529 }
530 
531 Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
532   HasLinkingSection = true;
533 
534   LinkingData.Version = readVaruint32(Ctx);
535   if (LinkingData.Version != wasm::WasmMetadataVersion) {
536     return make_error<GenericBinaryError>(
537         "unexpected metadata version: " + Twine(LinkingData.Version) +
538             " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
539         object_error::parse_failed);
540   }
541 
542   const uint8_t *OrigEnd = Ctx.End;
543   while (Ctx.Ptr < OrigEnd) {
544     Ctx.End = OrigEnd;
545     uint8_t Type = readUint8(Ctx);
546     uint32_t Size = readVaruint32(Ctx);
547     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
548                       << "\n");
549     Ctx.End = Ctx.Ptr + Size;
550     switch (Type) {
551     case wasm::WASM_SYMBOL_TABLE:
552       if (Error Err = parseLinkingSectionSymtab(Ctx))
553         return Err;
554       break;
555     case wasm::WASM_SEGMENT_INFO: {
556       uint32_t Count = readVaruint32(Ctx);
557       if (Count > DataSegments.size())
558         return make_error<GenericBinaryError>("too many segment names",
559                                               object_error::parse_failed);
560       for (uint32_t I = 0; I < Count; I++) {
561         DataSegments[I].Data.Name = readString(Ctx);
562         DataSegments[I].Data.Alignment = readVaruint32(Ctx);
563         DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
564       }
565       break;
566     }
567     case wasm::WASM_INIT_FUNCS: {
568       uint32_t Count = readVaruint32(Ctx);
569       LinkingData.InitFunctions.reserve(Count);
570       for (uint32_t I = 0; I < Count; I++) {
571         wasm::WasmInitFunc Init;
572         Init.Priority = readVaruint32(Ctx);
573         Init.Symbol = readVaruint32(Ctx);
574         if (!isValidFunctionSymbol(Init.Symbol))
575           return make_error<GenericBinaryError>("invalid function symbol: " +
576                                                     Twine(Init.Symbol),
577                                                 object_error::parse_failed);
578         LinkingData.InitFunctions.emplace_back(Init);
579       }
580       break;
581     }
582     case wasm::WASM_COMDAT_INFO:
583       if (Error Err = parseLinkingSectionComdat(Ctx))
584         return Err;
585       break;
586     default:
587       Ctx.Ptr += Size;
588       break;
589     }
590     if (Ctx.Ptr != Ctx.End)
591       return make_error<GenericBinaryError>(
592           "linking sub-section ended prematurely", object_error::parse_failed);
593   }
594   if (Ctx.Ptr != OrigEnd)
595     return make_error<GenericBinaryError>("linking section ended prematurely",
596                                           object_error::parse_failed);
597   return Error::success();
598 }
599 
600 Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
601   uint32_t Count = readVaruint32(Ctx);
602   LinkingData.SymbolTable.reserve(Count);
603   Symbols.reserve(Count);
604   StringSet<> SymbolNames;
605 
606   std::vector<wasm::WasmImport *> ImportedGlobals;
607   std::vector<wasm::WasmImport *> ImportedFunctions;
608   std::vector<wasm::WasmImport *> ImportedTags;
609   std::vector<wasm::WasmImport *> ImportedTables;
610   ImportedGlobals.reserve(Imports.size());
611   ImportedFunctions.reserve(Imports.size());
612   ImportedTags.reserve(Imports.size());
613   ImportedTables.reserve(Imports.size());
614   for (auto &I : Imports) {
615     if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
616       ImportedFunctions.emplace_back(&I);
617     else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
618       ImportedGlobals.emplace_back(&I);
619     else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
620       ImportedTags.emplace_back(&I);
621     else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
622       ImportedTables.emplace_back(&I);
623   }
624 
625   while (Count--) {
626     wasm::WasmSymbolInfo Info;
627     const wasm::WasmSignature *Signature = nullptr;
628     const wasm::WasmGlobalType *GlobalType = nullptr;
629     const wasm::WasmTableType *TableType = nullptr;
630 
631     Info.Kind = readUint8(Ctx);
632     Info.Flags = readVaruint32(Ctx);
633     bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
634 
635     switch (Info.Kind) {
636     case wasm::WASM_SYMBOL_TYPE_FUNCTION:
637       Info.ElementIndex = readVaruint32(Ctx);
638       if (!isValidFunctionIndex(Info.ElementIndex) ||
639           IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
640         return make_error<GenericBinaryError>("invalid function symbol index",
641                                               object_error::parse_failed);
642       if (IsDefined) {
643         Info.Name = readString(Ctx);
644         unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
645         wasm::WasmFunction &Function = Functions[FuncIndex];
646         Signature = &Signatures[Function.SigIndex];
647         if (Function.SymbolName.empty())
648           Function.SymbolName = Info.Name;
649       } else {
650         wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
651         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
652           Info.Name = readString(Ctx);
653           Info.ImportName = Import.Field;
654         } else {
655           Info.Name = Import.Field;
656         }
657         Signature = &Signatures[Import.SigIndex];
658         Info.ImportModule = Import.Module;
659       }
660       break;
661 
662     case wasm::WASM_SYMBOL_TYPE_GLOBAL:
663       Info.ElementIndex = readVaruint32(Ctx);
664       if (!isValidGlobalIndex(Info.ElementIndex) ||
665           IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
666         return make_error<GenericBinaryError>("invalid global symbol index",
667                                               object_error::parse_failed);
668       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
669                             wasm::WASM_SYMBOL_BINDING_WEAK)
670         return make_error<GenericBinaryError>("undefined weak global symbol",
671                                               object_error::parse_failed);
672       if (IsDefined) {
673         Info.Name = readString(Ctx);
674         unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
675         wasm::WasmGlobal &Global = Globals[GlobalIndex];
676         GlobalType = &Global.Type;
677         if (Global.SymbolName.empty())
678           Global.SymbolName = Info.Name;
679       } else {
680         wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
681         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
682           Info.Name = readString(Ctx);
683           Info.ImportName = Import.Field;
684         } else {
685           Info.Name = Import.Field;
686         }
687         GlobalType = &Import.Global;
688         Info.ImportModule = Import.Module;
689       }
690       break;
691 
692     case wasm::WASM_SYMBOL_TYPE_TABLE:
693       Info.ElementIndex = readVaruint32(Ctx);
694       if (!isValidTableNumber(Info.ElementIndex) ||
695           IsDefined != isDefinedTableNumber(Info.ElementIndex))
696         return make_error<GenericBinaryError>("invalid table symbol index",
697                                               object_error::parse_failed);
698       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
699                             wasm::WASM_SYMBOL_BINDING_WEAK)
700         return make_error<GenericBinaryError>("undefined weak table symbol",
701                                               object_error::parse_failed);
702       if (IsDefined) {
703         Info.Name = readString(Ctx);
704         unsigned TableNumber = Info.ElementIndex - NumImportedTables;
705         wasm::WasmTable &Table = Tables[TableNumber];
706         TableType = &Table.Type;
707         if (Table.SymbolName.empty())
708           Table.SymbolName = Info.Name;
709       } else {
710         wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
711         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
712           Info.Name = readString(Ctx);
713           Info.ImportName = Import.Field;
714         } else {
715           Info.Name = Import.Field;
716         }
717         TableType = &Import.Table;
718         Info.ImportModule = Import.Module;
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         Info.ImportModule = Import.Module;
782       }
783       break;
784     }
785 
786     default:
787       return make_error<GenericBinaryError>("invalid symbol type: " +
788                                                 Twine(unsigned(Info.Kind)),
789                                             object_error::parse_failed);
790     }
791 
792     if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
793             wasm::WASM_SYMBOL_BINDING_LOCAL &&
794         !SymbolNames.insert(Info.Name).second)
795       return make_error<GenericBinaryError>("duplicate symbol name " +
796                                                 Twine(Info.Name),
797                                             object_error::parse_failed);
798     LinkingData.SymbolTable.emplace_back(Info);
799     Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
800                          Signature);
801     LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
802   }
803 
804   return Error::success();
805 }
806 
807 Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
808   uint32_t ComdatCount = readVaruint32(Ctx);
809   StringSet<> ComdatSet;
810   for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
811     StringRef Name = readString(Ctx);
812     if (Name.empty() || !ComdatSet.insert(Name).second)
813       return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
814                                                 Twine(Name),
815                                             object_error::parse_failed);
816     LinkingData.Comdats.emplace_back(Name);
817     uint32_t Flags = readVaruint32(Ctx);
818     if (Flags != 0)
819       return make_error<GenericBinaryError>("unsupported COMDAT flags",
820                                             object_error::parse_failed);
821 
822     uint32_t EntryCount = readVaruint32(Ctx);
823     while (EntryCount--) {
824       unsigned Kind = readVaruint32(Ctx);
825       unsigned Index = readVaruint32(Ctx);
826       switch (Kind) {
827       default:
828         return make_error<GenericBinaryError>("invalid COMDAT entry type",
829                                               object_error::parse_failed);
830       case wasm::WASM_COMDAT_DATA:
831         if (Index >= DataSegments.size())
832           return make_error<GenericBinaryError>(
833               "COMDAT data index out of range", object_error::parse_failed);
834         if (DataSegments[Index].Data.Comdat != UINT32_MAX)
835           return make_error<GenericBinaryError>("data segment in two COMDATs",
836                                                 object_error::parse_failed);
837         DataSegments[Index].Data.Comdat = ComdatIndex;
838         break;
839       case wasm::WASM_COMDAT_FUNCTION:
840         if (!isDefinedFunctionIndex(Index))
841           return make_error<GenericBinaryError>(
842               "COMDAT function index out of range", object_error::parse_failed);
843         if (getDefinedFunction(Index).Comdat != UINT32_MAX)
844           return make_error<GenericBinaryError>("function in two COMDATs",
845                                                 object_error::parse_failed);
846         getDefinedFunction(Index).Comdat = ComdatIndex;
847         break;
848       case wasm::WASM_COMDAT_SECTION:
849         if (Index >= Sections.size())
850           return make_error<GenericBinaryError>(
851               "COMDAT section index out of range", object_error::parse_failed);
852         if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
853           return make_error<GenericBinaryError>(
854               "non-custom section in a COMDAT", object_error::parse_failed);
855         Sections[Index].Comdat = ComdatIndex;
856         break;
857       }
858     }
859   }
860   return Error::success();
861 }
862 
863 Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
864   llvm::SmallSet<StringRef, 3> FieldsSeen;
865   uint32_t Fields = readVaruint32(Ctx);
866   for (size_t I = 0; I < Fields; ++I) {
867     StringRef FieldName = readString(Ctx);
868     if (!FieldsSeen.insert(FieldName).second)
869       return make_error<GenericBinaryError>(
870           "producers section does not have unique fields",
871           object_error::parse_failed);
872     std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
873     if (FieldName == "language") {
874       ProducerVec = &ProducerInfo.Languages;
875     } else if (FieldName == "processed-by") {
876       ProducerVec = &ProducerInfo.Tools;
877     } else if (FieldName == "sdk") {
878       ProducerVec = &ProducerInfo.SDKs;
879     } else {
880       return make_error<GenericBinaryError>(
881           "producers section field is not named one of language, processed-by, "
882           "or sdk",
883           object_error::parse_failed);
884     }
885     uint32_t ValueCount = readVaruint32(Ctx);
886     llvm::SmallSet<StringRef, 8> ProducersSeen;
887     for (size_t J = 0; J < ValueCount; ++J) {
888       StringRef Name = readString(Ctx);
889       StringRef Version = readString(Ctx);
890       if (!ProducersSeen.insert(Name).second) {
891         return make_error<GenericBinaryError>(
892             "producers section contains repeated producer",
893             object_error::parse_failed);
894       }
895       ProducerVec->emplace_back(std::string(Name), std::string(Version));
896     }
897   }
898   if (Ctx.Ptr != Ctx.End)
899     return make_error<GenericBinaryError>("producers section ended prematurely",
900                                           object_error::parse_failed);
901   return Error::success();
902 }
903 
904 Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
905   llvm::SmallSet<std::string, 8> FeaturesSeen;
906   uint32_t FeatureCount = readVaruint32(Ctx);
907   for (size_t I = 0; I < FeatureCount; ++I) {
908     wasm::WasmFeatureEntry Feature;
909     Feature.Prefix = readUint8(Ctx);
910     switch (Feature.Prefix) {
911     case wasm::WASM_FEATURE_PREFIX_USED:
912     case wasm::WASM_FEATURE_PREFIX_REQUIRED:
913     case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
914       break;
915     default:
916       return make_error<GenericBinaryError>("unknown feature policy prefix",
917                                             object_error::parse_failed);
918     }
919     Feature.Name = std::string(readString(Ctx));
920     if (!FeaturesSeen.insert(Feature.Name).second)
921       return make_error<GenericBinaryError>(
922           "target features section contains repeated feature \"" +
923               Feature.Name + "\"",
924           object_error::parse_failed);
925     TargetFeatures.push_back(Feature);
926   }
927   if (Ctx.Ptr != Ctx.End)
928     return make_error<GenericBinaryError>(
929         "target features section ended prematurely",
930         object_error::parse_failed);
931   return Error::success();
932 }
933 
934 Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
935   uint32_t SectionIndex = readVaruint32(Ctx);
936   if (SectionIndex >= Sections.size())
937     return make_error<GenericBinaryError>("invalid section index",
938                                           object_error::parse_failed);
939   WasmSection &Section = Sections[SectionIndex];
940   uint32_t RelocCount = readVaruint32(Ctx);
941   uint32_t EndOffset = Section.Content.size();
942   uint32_t PreviousOffset = 0;
943   while (RelocCount--) {
944     wasm::WasmRelocation Reloc = {};
945     uint32_t type = readVaruint32(Ctx);
946     Reloc.Type = type;
947     Reloc.Offset = readVaruint32(Ctx);
948     if (Reloc.Offset < PreviousOffset)
949       return make_error<GenericBinaryError>("relocations not in offset order",
950                                             object_error::parse_failed);
951     PreviousOffset = Reloc.Offset;
952     Reloc.Index = readVaruint32(Ctx);
953     switch (type) {
954     case wasm::R_WASM_FUNCTION_INDEX_LEB:
955     case wasm::R_WASM_FUNCTION_INDEX_I32:
956     case wasm::R_WASM_TABLE_INDEX_SLEB:
957     case wasm::R_WASM_TABLE_INDEX_SLEB64:
958     case wasm::R_WASM_TABLE_INDEX_I32:
959     case wasm::R_WASM_TABLE_INDEX_I64:
960     case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
961     case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
962       if (!isValidFunctionSymbol(Reloc.Index))
963         return make_error<GenericBinaryError>(
964             "invalid relocation function index", object_error::parse_failed);
965       break;
966     case wasm::R_WASM_TABLE_NUMBER_LEB:
967       if (!isValidTableSymbol(Reloc.Index))
968         return make_error<GenericBinaryError>("invalid relocation table index",
969                                               object_error::parse_failed);
970       break;
971     case wasm::R_WASM_TYPE_INDEX_LEB:
972       if (Reloc.Index >= Signatures.size())
973         return make_error<GenericBinaryError>("invalid relocation type index",
974                                               object_error::parse_failed);
975       break;
976     case wasm::R_WASM_GLOBAL_INDEX_LEB:
977       // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
978       // symbols to refer to their GOT entries.
979       if (!isValidGlobalSymbol(Reloc.Index) &&
980           !isValidDataSymbol(Reloc.Index) &&
981           !isValidFunctionSymbol(Reloc.Index))
982         return make_error<GenericBinaryError>("invalid relocation global index",
983                                               object_error::parse_failed);
984       break;
985     case wasm::R_WASM_GLOBAL_INDEX_I32:
986       if (!isValidGlobalSymbol(Reloc.Index))
987         return make_error<GenericBinaryError>("invalid relocation global index",
988                                               object_error::parse_failed);
989       break;
990     case wasm::R_WASM_TAG_INDEX_LEB:
991       if (!isValidTagSymbol(Reloc.Index))
992         return make_error<GenericBinaryError>("invalid relocation tag index",
993                                               object_error::parse_failed);
994       break;
995     case wasm::R_WASM_MEMORY_ADDR_LEB:
996     case wasm::R_WASM_MEMORY_ADDR_SLEB:
997     case wasm::R_WASM_MEMORY_ADDR_I32:
998     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
999     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1000     case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1001       if (!isValidDataSymbol(Reloc.Index))
1002         return make_error<GenericBinaryError>("invalid relocation data index",
1003                                               object_error::parse_failed);
1004       Reloc.Addend = readVarint32(Ctx);
1005       break;
1006     case wasm::R_WASM_MEMORY_ADDR_LEB64:
1007     case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1008     case wasm::R_WASM_MEMORY_ADDR_I64:
1009     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1010     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1011       if (!isValidDataSymbol(Reloc.Index))
1012         return make_error<GenericBinaryError>("invalid relocation data index",
1013                                               object_error::parse_failed);
1014       Reloc.Addend = readVarint64(Ctx);
1015       break;
1016     case wasm::R_WASM_FUNCTION_OFFSET_I32:
1017       if (!isValidFunctionSymbol(Reloc.Index))
1018         return make_error<GenericBinaryError>(
1019             "invalid relocation function index", object_error::parse_failed);
1020       Reloc.Addend = readVarint32(Ctx);
1021       break;
1022     case wasm::R_WASM_FUNCTION_OFFSET_I64:
1023       if (!isValidFunctionSymbol(Reloc.Index))
1024         return make_error<GenericBinaryError>(
1025             "invalid relocation function index", object_error::parse_failed);
1026       Reloc.Addend = readVarint64(Ctx);
1027       break;
1028     case wasm::R_WASM_SECTION_OFFSET_I32:
1029       if (!isValidSectionSymbol(Reloc.Index))
1030         return make_error<GenericBinaryError>(
1031             "invalid relocation section index", object_error::parse_failed);
1032       Reloc.Addend = readVarint32(Ctx);
1033       break;
1034     default:
1035       return make_error<GenericBinaryError>("invalid relocation type: " +
1036                                                 Twine(type),
1037                                             object_error::parse_failed);
1038     }
1039 
1040     // Relocations must fit inside the section, and must appear in order.  They
1041     // also shouldn't overlap a function/element boundary, but we don't bother
1042     // to check that.
1043     uint64_t Size = 5;
1044     if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1045         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1046         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1047       Size = 10;
1048     if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1049         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1050         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1051         Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1052         Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1053         Reloc.Type == wasm::R_WASM_FUNCTION_INDEX_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   CodeSection = Sections.size();
1414   uint32_t FunctionCount = readVaruint32(Ctx);
1415   if (FunctionCount != Functions.size()) {
1416     return make_error<GenericBinaryError>("invalid function count",
1417                                           object_error::parse_failed);
1418   }
1419 
1420   for (uint32_t i = 0; i < FunctionCount; i++) {
1421     wasm::WasmFunction& Function = Functions[i];
1422     const uint8_t *FunctionStart = Ctx.Ptr;
1423     uint32_t Size = readVaruint32(Ctx);
1424     const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1425 
1426     Function.CodeOffset = Ctx.Ptr - FunctionStart;
1427     Function.Index = NumImportedFunctions + i;
1428     Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1429     Function.Size = FunctionEnd - FunctionStart;
1430 
1431     uint32_t NumLocalDecls = readVaruint32(Ctx);
1432     Function.Locals.reserve(NumLocalDecls);
1433     while (NumLocalDecls--) {
1434       wasm::WasmLocalDecl Decl;
1435       Decl.Count = readVaruint32(Ctx);
1436       Decl.Type = readUint8(Ctx);
1437       Function.Locals.push_back(Decl);
1438     }
1439 
1440     uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1441     Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1442     // This will be set later when reading in the linking metadata section.
1443     Function.Comdat = UINT32_MAX;
1444     Ctx.Ptr += BodySize;
1445     assert(Ctx.Ptr == FunctionEnd);
1446   }
1447   if (Ctx.Ptr != Ctx.End)
1448     return make_error<GenericBinaryError>("code section ended prematurely",
1449                                           object_error::parse_failed);
1450   return Error::success();
1451 }
1452 
1453 Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1454   uint32_t Count = readVaruint32(Ctx);
1455   ElemSegments.reserve(Count);
1456   while (Count--) {
1457     wasm::WasmElemSegment Segment;
1458     Segment.Flags = readVaruint32(Ctx);
1459 
1460     uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
1461                               wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |
1462                               wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;
1463     if (Segment.Flags & ~SupportedFlags)
1464       return make_error<GenericBinaryError>(
1465           "Unsupported flags for element segment", object_error::parse_failed);
1466 
1467     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
1468       Segment.TableNumber = readVaruint32(Ctx);
1469     else
1470       Segment.TableNumber = 0;
1471     if (!isValidTableNumber(Segment.TableNumber))
1472       return make_error<GenericBinaryError>("invalid TableNumber",
1473                                             object_error::parse_failed);
1474 
1475     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
1476       Segment.Offset.Extended = false;
1477       Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1478       Segment.Offset.Inst.Value.Int32 = 0;
1479     } else {
1480       if (Error Err = readInitExpr(Segment.Offset, Ctx))
1481         return Err;
1482     }
1483 
1484     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
1485       Segment.ElemKind = readUint8(Ctx);
1486       if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
1487         if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) &&
1488             Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) {
1489           return make_error<GenericBinaryError>("invalid reference type",
1490                                                 object_error::parse_failed);
1491         }
1492       } else {
1493         if (Segment.ElemKind != 0)
1494           return make_error<GenericBinaryError>("invalid elemtype",
1495                                                 object_error::parse_failed);
1496         Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1497       }
1498     } else {
1499       Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1500     }
1501 
1502     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS)
1503       return make_error<GenericBinaryError>(
1504           "elem segment init expressions not yet implemented",
1505           object_error::parse_failed);
1506 
1507     uint32_t NumElems = readVaruint32(Ctx);
1508     while (NumElems--) {
1509       Segment.Functions.push_back(readVaruint32(Ctx));
1510     }
1511     ElemSegments.push_back(Segment);
1512   }
1513   if (Ctx.Ptr != Ctx.End)
1514     return make_error<GenericBinaryError>("elem section ended prematurely",
1515                                           object_error::parse_failed);
1516   return Error::success();
1517 }
1518 
1519 Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1520   DataSection = Sections.size();
1521   uint32_t Count = readVaruint32(Ctx);
1522   if (DataCount && Count != *DataCount)
1523     return make_error<GenericBinaryError>(
1524         "number of data segments does not match DataCount section");
1525   DataSegments.reserve(Count);
1526   while (Count--) {
1527     WasmSegment Segment;
1528     Segment.Data.InitFlags = readVaruint32(Ctx);
1529     Segment.Data.MemoryIndex =
1530         (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1531             ? readVaruint32(Ctx)
1532             : 0;
1533     if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1534       if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1535         return Err;
1536     } else {
1537       Segment.Data.Offset.Extended = false;
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   if (S.Type == wasm::WASM_SEC_CUSTOM)
1730     return S.Name;
1731   if (S.Type > wasm::WASM_SEC_LAST_KNOWN)
1732     return createStringError(object_error::invalid_section_index, "");
1733   return wasm::sectionTypeToString(S.Type);
1734 }
1735 
1736 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1737 
1738 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1739   return Sec.d.a;
1740 }
1741 
1742 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1743   const WasmSection &S = Sections[Sec.d.a];
1744   return S.Content.size();
1745 }
1746 
1747 Expected<ArrayRef<uint8_t>>
1748 WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
1749   const WasmSection &S = Sections[Sec.d.a];
1750   // This will never fail since wasm sections can never be empty (user-sections
1751   // must have a name and non-user sections each have a defined structure).
1752   return S.Content;
1753 }
1754 
1755 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1756   return 1;
1757 }
1758 
1759 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1760   return false;
1761 }
1762 
1763 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1764   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1765 }
1766 
1767 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1768   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1769 }
1770 
1771 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1772 
1773 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1774 
1775 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1776   DataRefImpl RelocRef;
1777   RelocRef.d.a = Ref.d.a;
1778   RelocRef.d.b = 0;
1779   return relocation_iterator(RelocationRef(RelocRef, this));
1780 }
1781 
1782 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1783   const WasmSection &Sec = getWasmSection(Ref);
1784   DataRefImpl RelocRef;
1785   RelocRef.d.a = Ref.d.a;
1786   RelocRef.d.b = Sec.Relocations.size();
1787   return relocation_iterator(RelocationRef(RelocRef, this));
1788 }
1789 
1790 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1791 
1792 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1793   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1794   return Rel.Offset;
1795 }
1796 
1797 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1798   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1799   if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
1800     return symbol_end();
1801   DataRefImpl Sym;
1802   Sym.d.a = 1;
1803   Sym.d.b = Rel.Index;
1804   return symbol_iterator(SymbolRef(Sym, this));
1805 }
1806 
1807 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1808   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1809   return Rel.Type;
1810 }
1811 
1812 void WasmObjectFile::getRelocationTypeName(
1813     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1814   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1815   StringRef Res = "Unknown";
1816 
1817 #define WASM_RELOC(name, value)                                                \
1818   case wasm::name:                                                             \
1819     Res = #name;                                                               \
1820     break;
1821 
1822   switch (Rel.Type) {
1823 #include "llvm/BinaryFormat/WasmRelocs.def"
1824   }
1825 
1826 #undef WASM_RELOC
1827 
1828   Result.append(Res.begin(), Res.end());
1829 }
1830 
1831 section_iterator WasmObjectFile::section_begin() const {
1832   DataRefImpl Ref;
1833   Ref.d.a = 0;
1834   return section_iterator(SectionRef(Ref, this));
1835 }
1836 
1837 section_iterator WasmObjectFile::section_end() const {
1838   DataRefImpl Ref;
1839   Ref.d.a = Sections.size();
1840   return section_iterator(SectionRef(Ref, this));
1841 }
1842 
1843 uint8_t WasmObjectFile::getBytesInAddress() const {
1844   return HasMemory64 ? 8 : 4;
1845 }
1846 
1847 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1848 
1849 Triple::ArchType WasmObjectFile::getArch() const {
1850   return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
1851 }
1852 
1853 Expected<SubtargetFeatures> WasmObjectFile::getFeatures() const {
1854   return SubtargetFeatures();
1855 }
1856 
1857 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1858 
1859 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1860 
1861 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1862   assert(Ref.d.a < Sections.size());
1863   return Sections[Ref.d.a];
1864 }
1865 
1866 const WasmSection &
1867 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1868   return getWasmSection(Section.getRawDataRefImpl());
1869 }
1870 
1871 const wasm::WasmRelocation &
1872 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1873   return getWasmRelocation(Ref.getRawDataRefImpl());
1874 }
1875 
1876 const wasm::WasmRelocation &
1877 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1878   assert(Ref.d.a < Sections.size());
1879   const WasmSection &Sec = Sections[Ref.d.a];
1880   assert(Ref.d.b < Sec.Relocations.size());
1881   return Sec.Relocations[Ref.d.b];
1882 }
1883 
1884 int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1885                                              StringRef CustomSectionName) {
1886   switch (ID) {
1887   case wasm::WASM_SEC_CUSTOM:
1888     return StringSwitch<unsigned>(CustomSectionName)
1889         .Case("dylink", WASM_SEC_ORDER_DYLINK)
1890         .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
1891         .Case("linking", WASM_SEC_ORDER_LINKING)
1892         .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1893         .Case("name", WASM_SEC_ORDER_NAME)
1894         .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1895         .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
1896         .Default(WASM_SEC_ORDER_NONE);
1897   case wasm::WASM_SEC_TYPE:
1898     return WASM_SEC_ORDER_TYPE;
1899   case wasm::WASM_SEC_IMPORT:
1900     return WASM_SEC_ORDER_IMPORT;
1901   case wasm::WASM_SEC_FUNCTION:
1902     return WASM_SEC_ORDER_FUNCTION;
1903   case wasm::WASM_SEC_TABLE:
1904     return WASM_SEC_ORDER_TABLE;
1905   case wasm::WASM_SEC_MEMORY:
1906     return WASM_SEC_ORDER_MEMORY;
1907   case wasm::WASM_SEC_GLOBAL:
1908     return WASM_SEC_ORDER_GLOBAL;
1909   case wasm::WASM_SEC_EXPORT:
1910     return WASM_SEC_ORDER_EXPORT;
1911   case wasm::WASM_SEC_START:
1912     return WASM_SEC_ORDER_START;
1913   case wasm::WASM_SEC_ELEM:
1914     return WASM_SEC_ORDER_ELEM;
1915   case wasm::WASM_SEC_CODE:
1916     return WASM_SEC_ORDER_CODE;
1917   case wasm::WASM_SEC_DATA:
1918     return WASM_SEC_ORDER_DATA;
1919   case wasm::WASM_SEC_DATACOUNT:
1920     return WASM_SEC_ORDER_DATACOUNT;
1921   case wasm::WASM_SEC_TAG:
1922     return WASM_SEC_ORDER_TAG;
1923   default:
1924     return WASM_SEC_ORDER_NONE;
1925   }
1926 }
1927 
1928 // Represents the edges in a directed graph where any node B reachable from node
1929 // A is not allowed to appear before A in the section ordering, but may appear
1930 // afterward.
1931 int WasmSectionOrderChecker::DisallowedPredecessors
1932     [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
1933         // WASM_SEC_ORDER_NONE
1934         {},
1935         // WASM_SEC_ORDER_TYPE
1936         {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
1937         // WASM_SEC_ORDER_IMPORT
1938         {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
1939         // WASM_SEC_ORDER_FUNCTION
1940         {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
1941         // WASM_SEC_ORDER_TABLE
1942         {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
1943         // WASM_SEC_ORDER_MEMORY
1944         {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
1945         // WASM_SEC_ORDER_TAG
1946         {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
1947         // WASM_SEC_ORDER_GLOBAL
1948         {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
1949         // WASM_SEC_ORDER_EXPORT
1950         {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
1951         // WASM_SEC_ORDER_START
1952         {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
1953         // WASM_SEC_ORDER_ELEM
1954         {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
1955         // WASM_SEC_ORDER_DATACOUNT
1956         {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
1957         // WASM_SEC_ORDER_CODE
1958         {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
1959         // WASM_SEC_ORDER_DATA
1960         {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
1961 
1962         // Custom Sections
1963         // WASM_SEC_ORDER_DYLINK
1964         {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
1965         // WASM_SEC_ORDER_LINKING
1966         {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
1967         // WASM_SEC_ORDER_RELOC (can be repeated)
1968         {},
1969         // WASM_SEC_ORDER_NAME
1970         {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
1971         // WASM_SEC_ORDER_PRODUCERS
1972         {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
1973         // WASM_SEC_ORDER_TARGET_FEATURES
1974         {WASM_SEC_ORDER_TARGET_FEATURES}};
1975 
1976 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
1977                                                   StringRef CustomSectionName) {
1978   int Order = getSectionOrder(ID, CustomSectionName);
1979   if (Order == WASM_SEC_ORDER_NONE)
1980     return true;
1981 
1982   // Disallowed predecessors we need to check for
1983   SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
1984 
1985   // Keep track of completed checks to avoid repeating work
1986   bool Checked[WASM_NUM_SEC_ORDERS] = {};
1987 
1988   int Curr = Order;
1989   while (true) {
1990     // Add new disallowed predecessors to work list
1991     for (size_t I = 0;; ++I) {
1992       int Next = DisallowedPredecessors[Curr][I];
1993       if (Next == WASM_SEC_ORDER_NONE)
1994         break;
1995       if (Checked[Next])
1996         continue;
1997       WorkList.push_back(Next);
1998       Checked[Next] = true;
1999     }
2000 
2001     if (WorkList.empty())
2002       break;
2003 
2004     // Consider next disallowed predecessor
2005     Curr = WorkList.pop_back_val();
2006     if (Seen[Curr])
2007       return false;
2008   }
2009 
2010   // Have not seen any disallowed predecessors
2011   Seen[Order] = true;
2012   return true;
2013 }
2014