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