xref: /freebsd-src/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
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.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::WASM_TYPE_FUNCREF &&
1167           ElemType != wasm::WASM_TYPE_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::WASM_TYPE_FUNCREF &&
1224         ElemType != wasm::WASM_TYPE_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       break;
1355     default:
1356       return make_error<GenericBinaryError>("unexpected export kind",
1357                                             object_error::parse_failed);
1358     }
1359     Exports.push_back(Ex);
1360     if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) {
1361       LinkingData.SymbolTable.emplace_back(Info);
1362       Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType,
1363                            TableType, Signature);
1364       LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
1365     }
1366   }
1367   if (Ctx.Ptr != Ctx.End)
1368     return make_error<GenericBinaryError>("export section ended prematurely",
1369                                           object_error::parse_failed);
1370   return Error::success();
1371 }
1372 
1373 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1374   return Index < NumImportedFunctions + Functions.size();
1375 }
1376 
1377 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1378   return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1379 }
1380 
1381 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1382   return Index < NumImportedGlobals + Globals.size();
1383 }
1384 
1385 bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1386   return Index < NumImportedTables + Tables.size();
1387 }
1388 
1389 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1390   return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1391 }
1392 
1393 bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1394   return Index >= NumImportedTables && isValidTableNumber(Index);
1395 }
1396 
1397 bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1398   return Index < NumImportedTags + Tags.size();
1399 }
1400 
1401 bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1402   return Index >= NumImportedTags && isValidTagIndex(Index);
1403 }
1404 
1405 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1406   return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1407 }
1408 
1409 bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1410   return Index < Symbols.size() && Symbols[Index].isTypeTable();
1411 }
1412 
1413 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1414   return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1415 }
1416 
1417 bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1418   return Index < Symbols.size() && Symbols[Index].isTypeTag();
1419 }
1420 
1421 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1422   return Index < Symbols.size() && Symbols[Index].isTypeData();
1423 }
1424 
1425 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1426   return Index < Symbols.size() && Symbols[Index].isTypeSection();
1427 }
1428 
1429 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1430   assert(isDefinedFunctionIndex(Index));
1431   return Functions[Index - NumImportedFunctions];
1432 }
1433 
1434 const wasm::WasmFunction &
1435 WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1436   assert(isDefinedFunctionIndex(Index));
1437   return Functions[Index - NumImportedFunctions];
1438 }
1439 
1440 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
1441   assert(isDefinedGlobalIndex(Index));
1442   return Globals[Index - NumImportedGlobals];
1443 }
1444 
1445 wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1446   assert(isDefinedTagIndex(Index));
1447   return Tags[Index - NumImportedTags];
1448 }
1449 
1450 Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1451   StartFunction = readVaruint32(Ctx);
1452   if (!isValidFunctionIndex(StartFunction))
1453     return make_error<GenericBinaryError>("invalid start function",
1454                                           object_error::parse_failed);
1455   return Error::success();
1456 }
1457 
1458 Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1459   CodeSection = Sections.size();
1460   uint32_t FunctionCount = readVaruint32(Ctx);
1461   if (FunctionCount != Functions.size()) {
1462     return make_error<GenericBinaryError>("invalid function count",
1463                                           object_error::parse_failed);
1464   }
1465 
1466   for (uint32_t i = 0; i < FunctionCount; i++) {
1467     wasm::WasmFunction& Function = Functions[i];
1468     const uint8_t *FunctionStart = Ctx.Ptr;
1469     uint32_t Size = readVaruint32(Ctx);
1470     const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1471 
1472     Function.CodeOffset = Ctx.Ptr - FunctionStart;
1473     Function.Index = NumImportedFunctions + i;
1474     Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1475     Function.Size = FunctionEnd - FunctionStart;
1476 
1477     uint32_t NumLocalDecls = readVaruint32(Ctx);
1478     Function.Locals.reserve(NumLocalDecls);
1479     while (NumLocalDecls--) {
1480       wasm::WasmLocalDecl Decl;
1481       Decl.Count = readVaruint32(Ctx);
1482       Decl.Type = readUint8(Ctx);
1483       Function.Locals.push_back(Decl);
1484     }
1485 
1486     uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1487     Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1488     // This will be set later when reading in the linking metadata section.
1489     Function.Comdat = UINT32_MAX;
1490     Ctx.Ptr += BodySize;
1491     assert(Ctx.Ptr == FunctionEnd);
1492   }
1493   if (Ctx.Ptr != Ctx.End)
1494     return make_error<GenericBinaryError>("code section ended prematurely",
1495                                           object_error::parse_failed);
1496   return Error::success();
1497 }
1498 
1499 Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1500   uint32_t Count = readVaruint32(Ctx);
1501   ElemSegments.reserve(Count);
1502   while (Count--) {
1503     wasm::WasmElemSegment Segment;
1504     Segment.Flags = readVaruint32(Ctx);
1505 
1506     uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
1507                               wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |
1508                               wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;
1509     if (Segment.Flags & ~SupportedFlags)
1510       return make_error<GenericBinaryError>(
1511           "Unsupported flags for element segment", object_error::parse_failed);
1512 
1513     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
1514       Segment.TableNumber = readVaruint32(Ctx);
1515     else
1516       Segment.TableNumber = 0;
1517     if (!isValidTableNumber(Segment.TableNumber))
1518       return make_error<GenericBinaryError>("invalid TableNumber",
1519                                             object_error::parse_failed);
1520 
1521     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
1522       Segment.Offset.Extended = false;
1523       Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1524       Segment.Offset.Inst.Value.Int32 = 0;
1525     } else {
1526       if (Error Err = readInitExpr(Segment.Offset, Ctx))
1527         return Err;
1528     }
1529 
1530     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
1531       Segment.ElemKind = readUint8(Ctx);
1532       if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
1533         if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) &&
1534             Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) {
1535           return make_error<GenericBinaryError>("invalid reference type",
1536                                                 object_error::parse_failed);
1537         }
1538       } else {
1539         if (Segment.ElemKind != 0)
1540           return make_error<GenericBinaryError>("invalid elemtype",
1541                                                 object_error::parse_failed);
1542         Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1543       }
1544     } else {
1545       Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1546     }
1547 
1548     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS)
1549       return make_error<GenericBinaryError>(
1550           "elem segment init expressions not yet implemented",
1551           object_error::parse_failed);
1552 
1553     uint32_t NumElems = readVaruint32(Ctx);
1554     while (NumElems--) {
1555       Segment.Functions.push_back(readVaruint32(Ctx));
1556     }
1557     ElemSegments.push_back(Segment);
1558   }
1559   if (Ctx.Ptr != Ctx.End)
1560     return make_error<GenericBinaryError>("elem section ended prematurely",
1561                                           object_error::parse_failed);
1562   return Error::success();
1563 }
1564 
1565 Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1566   DataSection = Sections.size();
1567   uint32_t Count = readVaruint32(Ctx);
1568   if (DataCount && Count != *DataCount)
1569     return make_error<GenericBinaryError>(
1570         "number of data segments does not match DataCount section");
1571   DataSegments.reserve(Count);
1572   while (Count--) {
1573     WasmSegment Segment;
1574     Segment.Data.InitFlags = readVaruint32(Ctx);
1575     Segment.Data.MemoryIndex =
1576         (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1577             ? readVaruint32(Ctx)
1578             : 0;
1579     if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1580       if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1581         return Err;
1582     } else {
1583       Segment.Data.Offset.Extended = false;
1584       Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1585       Segment.Data.Offset.Inst.Value.Int32 = 0;
1586     }
1587     uint32_t Size = readVaruint32(Ctx);
1588     if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1589       return make_error<GenericBinaryError>("invalid segment size",
1590                                             object_error::parse_failed);
1591     Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1592     // The rest of these Data fields are set later, when reading in the linking
1593     // metadata section.
1594     Segment.Data.Alignment = 0;
1595     Segment.Data.LinkingFlags = 0;
1596     Segment.Data.Comdat = UINT32_MAX;
1597     Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1598     Ctx.Ptr += Size;
1599     DataSegments.push_back(Segment);
1600   }
1601   if (Ctx.Ptr != Ctx.End)
1602     return make_error<GenericBinaryError>("data section ended prematurely",
1603                                           object_error::parse_failed);
1604   return Error::success();
1605 }
1606 
1607 Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1608   DataCount = readVaruint32(Ctx);
1609   return Error::success();
1610 }
1611 
1612 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1613   return Header;
1614 }
1615 
1616 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1617 
1618 Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1619   uint32_t Result = SymbolRef::SF_None;
1620   const WasmSymbol &Sym = getWasmSymbol(Symb);
1621 
1622   LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1623   if (Sym.isBindingWeak())
1624     Result |= SymbolRef::SF_Weak;
1625   if (!Sym.isBindingLocal())
1626     Result |= SymbolRef::SF_Global;
1627   if (Sym.isHidden())
1628     Result |= SymbolRef::SF_Hidden;
1629   if (!Sym.isDefined())
1630     Result |= SymbolRef::SF_Undefined;
1631   if (Sym.isTypeFunction())
1632     Result |= SymbolRef::SF_Executable;
1633   return Result;
1634 }
1635 
1636 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1637   DataRefImpl Ref;
1638   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1639   Ref.d.b = 0; // Symbol index
1640   return BasicSymbolRef(Ref, this);
1641 }
1642 
1643 basic_symbol_iterator WasmObjectFile::symbol_end() const {
1644   DataRefImpl Ref;
1645   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1646   Ref.d.b = Symbols.size(); // Symbol index
1647   return BasicSymbolRef(Ref, this);
1648 }
1649 
1650 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1651   return Symbols[Symb.d.b];
1652 }
1653 
1654 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1655   return getWasmSymbol(Symb.getRawDataRefImpl());
1656 }
1657 
1658 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1659   return getWasmSymbol(Symb).Info.Name;
1660 }
1661 
1662 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1663   auto &Sym = getWasmSymbol(Symb);
1664   if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1665       isDefinedFunctionIndex(Sym.Info.ElementIndex))
1666     return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
1667   else
1668     return getSymbolValue(Symb);
1669 }
1670 
1671 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1672   switch (Sym.Info.Kind) {
1673   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1674   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1675   case wasm::WASM_SYMBOL_TYPE_TAG:
1676   case wasm::WASM_SYMBOL_TYPE_TABLE:
1677     return Sym.Info.ElementIndex;
1678   case wasm::WASM_SYMBOL_TYPE_DATA: {
1679     // The value of a data symbol is the segment offset, plus the symbol
1680     // offset within the segment.
1681     uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1682     const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1683     if (Segment.Offset.Extended) {
1684       llvm_unreachable("extended init exprs not supported");
1685     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1686       return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
1687     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1688       return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
1689     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {
1690       return Sym.Info.DataRef.Offset;
1691     } else {
1692       llvm_unreachable("unknown init expr opcode");
1693     }
1694   }
1695   case wasm::WASM_SYMBOL_TYPE_SECTION:
1696     return 0;
1697   }
1698   llvm_unreachable("invalid symbol type");
1699 }
1700 
1701 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1702   return getWasmSymbolValue(getWasmSymbol(Symb));
1703 }
1704 
1705 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1706   llvm_unreachable("not yet implemented");
1707   return 0;
1708 }
1709 
1710 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1711   llvm_unreachable("not yet implemented");
1712   return 0;
1713 }
1714 
1715 Expected<SymbolRef::Type>
1716 WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1717   const WasmSymbol &Sym = getWasmSymbol(Symb);
1718 
1719   switch (Sym.Info.Kind) {
1720   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1721     return SymbolRef::ST_Function;
1722   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1723     return SymbolRef::ST_Other;
1724   case wasm::WASM_SYMBOL_TYPE_DATA:
1725     return SymbolRef::ST_Data;
1726   case wasm::WASM_SYMBOL_TYPE_SECTION:
1727     return SymbolRef::ST_Debug;
1728   case wasm::WASM_SYMBOL_TYPE_TAG:
1729     return SymbolRef::ST_Other;
1730   case wasm::WASM_SYMBOL_TYPE_TABLE:
1731     return SymbolRef::ST_Other;
1732   }
1733 
1734   llvm_unreachable("unknown WasmSymbol::SymbolType");
1735   return SymbolRef::ST_Other;
1736 }
1737 
1738 Expected<section_iterator>
1739 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1740   const WasmSymbol &Sym = getWasmSymbol(Symb);
1741   if (Sym.isUndefined())
1742     return section_end();
1743 
1744   DataRefImpl Ref;
1745   Ref.d.a = getSymbolSectionIdImpl(Sym);
1746   return section_iterator(SectionRef(Ref, this));
1747 }
1748 
1749 uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
1750   const WasmSymbol &Sym = getWasmSymbol(Symb);
1751   return getSymbolSectionIdImpl(Sym);
1752 }
1753 
1754 uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
1755   switch (Sym.Info.Kind) {
1756   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1757     return CodeSection;
1758   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1759     return GlobalSection;
1760   case wasm::WASM_SYMBOL_TYPE_DATA:
1761     return DataSection;
1762   case wasm::WASM_SYMBOL_TYPE_SECTION:
1763     return Sym.Info.ElementIndex;
1764   case wasm::WASM_SYMBOL_TYPE_TAG:
1765     return TagSection;
1766   case wasm::WASM_SYMBOL_TYPE_TABLE:
1767     return TableSection;
1768   default:
1769     llvm_unreachable("unknown WasmSymbol::SymbolType");
1770   }
1771 }
1772 
1773 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1774 
1775 Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
1776   const WasmSection &S = Sections[Sec.d.a];
1777   if (S.Type == wasm::WASM_SEC_CUSTOM)
1778     return S.Name;
1779   if (S.Type > wasm::WASM_SEC_LAST_KNOWN)
1780     return createStringError(object_error::invalid_section_index, "");
1781   return wasm::sectionTypeToString(S.Type);
1782 }
1783 
1784 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1785 
1786 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1787   return Sec.d.a;
1788 }
1789 
1790 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1791   const WasmSection &S = Sections[Sec.d.a];
1792   return S.Content.size();
1793 }
1794 
1795 Expected<ArrayRef<uint8_t>>
1796 WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
1797   const WasmSection &S = Sections[Sec.d.a];
1798   // This will never fail since wasm sections can never be empty (user-sections
1799   // must have a name and non-user sections each have a defined structure).
1800   return S.Content;
1801 }
1802 
1803 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1804   return 1;
1805 }
1806 
1807 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1808   return false;
1809 }
1810 
1811 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1812   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1813 }
1814 
1815 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1816   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1817 }
1818 
1819 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1820 
1821 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1822 
1823 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1824   DataRefImpl RelocRef;
1825   RelocRef.d.a = Ref.d.a;
1826   RelocRef.d.b = 0;
1827   return relocation_iterator(RelocationRef(RelocRef, this));
1828 }
1829 
1830 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1831   const WasmSection &Sec = getWasmSection(Ref);
1832   DataRefImpl RelocRef;
1833   RelocRef.d.a = Ref.d.a;
1834   RelocRef.d.b = Sec.Relocations.size();
1835   return relocation_iterator(RelocationRef(RelocRef, this));
1836 }
1837 
1838 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1839 
1840 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1841   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1842   return Rel.Offset;
1843 }
1844 
1845 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1846   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1847   if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
1848     return symbol_end();
1849   DataRefImpl Sym;
1850   Sym.d.a = 1;
1851   Sym.d.b = Rel.Index;
1852   return symbol_iterator(SymbolRef(Sym, this));
1853 }
1854 
1855 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1856   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1857   return Rel.Type;
1858 }
1859 
1860 void WasmObjectFile::getRelocationTypeName(
1861     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1862   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1863   StringRef Res = "Unknown";
1864 
1865 #define WASM_RELOC(name, value)                                                \
1866   case wasm::name:                                                             \
1867     Res = #name;                                                               \
1868     break;
1869 
1870   switch (Rel.Type) {
1871 #include "llvm/BinaryFormat/WasmRelocs.def"
1872   }
1873 
1874 #undef WASM_RELOC
1875 
1876   Result.append(Res.begin(), Res.end());
1877 }
1878 
1879 section_iterator WasmObjectFile::section_begin() const {
1880   DataRefImpl Ref;
1881   Ref.d.a = 0;
1882   return section_iterator(SectionRef(Ref, this));
1883 }
1884 
1885 section_iterator WasmObjectFile::section_end() const {
1886   DataRefImpl Ref;
1887   Ref.d.a = Sections.size();
1888   return section_iterator(SectionRef(Ref, this));
1889 }
1890 
1891 uint8_t WasmObjectFile::getBytesInAddress() const {
1892   return HasMemory64 ? 8 : 4;
1893 }
1894 
1895 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1896 
1897 Triple::ArchType WasmObjectFile::getArch() const {
1898   return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
1899 }
1900 
1901 Expected<SubtargetFeatures> WasmObjectFile::getFeatures() const {
1902   return SubtargetFeatures();
1903 }
1904 
1905 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1906 
1907 bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1908 
1909 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1910   assert(Ref.d.a < Sections.size());
1911   return Sections[Ref.d.a];
1912 }
1913 
1914 const WasmSection &
1915 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1916   return getWasmSection(Section.getRawDataRefImpl());
1917 }
1918 
1919 const wasm::WasmRelocation &
1920 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1921   return getWasmRelocation(Ref.getRawDataRefImpl());
1922 }
1923 
1924 const wasm::WasmRelocation &
1925 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1926   assert(Ref.d.a < Sections.size());
1927   const WasmSection &Sec = Sections[Ref.d.a];
1928   assert(Ref.d.b < Sec.Relocations.size());
1929   return Sec.Relocations[Ref.d.b];
1930 }
1931 
1932 int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1933                                              StringRef CustomSectionName) {
1934   switch (ID) {
1935   case wasm::WASM_SEC_CUSTOM:
1936     return StringSwitch<unsigned>(CustomSectionName)
1937         .Case("dylink", WASM_SEC_ORDER_DYLINK)
1938         .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
1939         .Case("linking", WASM_SEC_ORDER_LINKING)
1940         .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1941         .Case("name", WASM_SEC_ORDER_NAME)
1942         .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1943         .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
1944         .Default(WASM_SEC_ORDER_NONE);
1945   case wasm::WASM_SEC_TYPE:
1946     return WASM_SEC_ORDER_TYPE;
1947   case wasm::WASM_SEC_IMPORT:
1948     return WASM_SEC_ORDER_IMPORT;
1949   case wasm::WASM_SEC_FUNCTION:
1950     return WASM_SEC_ORDER_FUNCTION;
1951   case wasm::WASM_SEC_TABLE:
1952     return WASM_SEC_ORDER_TABLE;
1953   case wasm::WASM_SEC_MEMORY:
1954     return WASM_SEC_ORDER_MEMORY;
1955   case wasm::WASM_SEC_GLOBAL:
1956     return WASM_SEC_ORDER_GLOBAL;
1957   case wasm::WASM_SEC_EXPORT:
1958     return WASM_SEC_ORDER_EXPORT;
1959   case wasm::WASM_SEC_START:
1960     return WASM_SEC_ORDER_START;
1961   case wasm::WASM_SEC_ELEM:
1962     return WASM_SEC_ORDER_ELEM;
1963   case wasm::WASM_SEC_CODE:
1964     return WASM_SEC_ORDER_CODE;
1965   case wasm::WASM_SEC_DATA:
1966     return WASM_SEC_ORDER_DATA;
1967   case wasm::WASM_SEC_DATACOUNT:
1968     return WASM_SEC_ORDER_DATACOUNT;
1969   case wasm::WASM_SEC_TAG:
1970     return WASM_SEC_ORDER_TAG;
1971   default:
1972     return WASM_SEC_ORDER_NONE;
1973   }
1974 }
1975 
1976 // Represents the edges in a directed graph where any node B reachable from node
1977 // A is not allowed to appear before A in the section ordering, but may appear
1978 // afterward.
1979 int WasmSectionOrderChecker::DisallowedPredecessors
1980     [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
1981         // WASM_SEC_ORDER_NONE
1982         {},
1983         // WASM_SEC_ORDER_TYPE
1984         {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
1985         // WASM_SEC_ORDER_IMPORT
1986         {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
1987         // WASM_SEC_ORDER_FUNCTION
1988         {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
1989         // WASM_SEC_ORDER_TABLE
1990         {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
1991         // WASM_SEC_ORDER_MEMORY
1992         {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
1993         // WASM_SEC_ORDER_TAG
1994         {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
1995         // WASM_SEC_ORDER_GLOBAL
1996         {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
1997         // WASM_SEC_ORDER_EXPORT
1998         {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
1999         // WASM_SEC_ORDER_START
2000         {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2001         // WASM_SEC_ORDER_ELEM
2002         {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2003         // WASM_SEC_ORDER_DATACOUNT
2004         {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2005         // WASM_SEC_ORDER_CODE
2006         {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2007         // WASM_SEC_ORDER_DATA
2008         {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2009 
2010         // Custom Sections
2011         // WASM_SEC_ORDER_DYLINK
2012         {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2013         // WASM_SEC_ORDER_LINKING
2014         {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2015         // WASM_SEC_ORDER_RELOC (can be repeated)
2016         {},
2017         // WASM_SEC_ORDER_NAME
2018         {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2019         // WASM_SEC_ORDER_PRODUCERS
2020         {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2021         // WASM_SEC_ORDER_TARGET_FEATURES
2022         {WASM_SEC_ORDER_TARGET_FEATURES}};
2023 
2024 bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
2025                                                   StringRef CustomSectionName) {
2026   int Order = getSectionOrder(ID, CustomSectionName);
2027   if (Order == WASM_SEC_ORDER_NONE)
2028     return true;
2029 
2030   // Disallowed predecessors we need to check for
2031   SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
2032 
2033   // Keep track of completed checks to avoid repeating work
2034   bool Checked[WASM_NUM_SEC_ORDERS] = {};
2035 
2036   int Curr = Order;
2037   while (true) {
2038     // Add new disallowed predecessors to work list
2039     for (size_t I = 0;; ++I) {
2040       int Next = DisallowedPredecessors[Curr][I];
2041       if (Next == WASM_SEC_ORDER_NONE)
2042         break;
2043       if (Checked[Next])
2044         continue;
2045       WorkList.push_back(Next);
2046       Checked[Next] = true;
2047     }
2048 
2049     if (WorkList.empty())
2050       break;
2051 
2052     // Consider next disallowed predecessor
2053     Curr = WorkList.pop_back_val();
2054     if (Seen[Curr])
2055       return false;
2056   }
2057 
2058   // Have not seen any disallowed predecessors
2059   Seen[Order] = true;
2060   return true;
2061 }
2062