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