xref: /llvm-project/llvm/lib/Object/WasmObjectFile.cpp (revision f208f6311b6ea3468b35deab208e307f8a59781b)
1 //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/ADT/ArrayRef.h"
11 #include "llvm/ADT/DenseSet.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/ADT/StringSet.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/BinaryFormat/Wasm.h"
17 #include "llvm/MC/SubtargetFeature.h"
18 #include "llvm/Object/Binary.h"
19 #include "llvm/Object/Error.h"
20 #include "llvm/Object/ObjectFile.h"
21 #include "llvm/Object/SymbolicFile.h"
22 #include "llvm/Object/Wasm.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/Error.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/LEB128.h"
27 #include <algorithm>
28 #include <cassert>
29 #include <cstdint>
30 #include <cstring>
31 #include <system_error>
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))
41       << ", Flags=" << Info.Flags;
42   if (!isTypeData()) {
43     Out << ", ElemIndex=" << Info.ElementIndex;
44   } else if (isDefined()) {
45     Out << ", Segment=" << Info.DataRef.Segment;
46     Out << ", Offset=" << Info.DataRef.Offset;
47     Out << ", Size=" << Info.DataRef.Size;
48   }
49 }
50 
51 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
52 LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
53 #endif
54 
55 Expected<std::unique_ptr<WasmObjectFile>>
56 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
57   Error Err = Error::success();
58   auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
59   if (Err)
60     return std::move(Err);
61 
62   return std::move(ObjectFile);
63 }
64 
65 #define VARINT7_MAX ((1 << 7) - 1)
66 #define VARINT7_MIN (-(1 << 7))
67 #define VARUINT7_MAX (1 << 7)
68 #define VARUINT1_MAX (1)
69 
70 static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
71   if (Ctx.Ptr == Ctx.End)
72     report_fatal_error("EOF while reading uint8");
73   return *Ctx.Ptr++;
74 }
75 
76 static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
77   if (Ctx.Ptr + 4 > Ctx.End)
78     report_fatal_error("EOF while reading uint32");
79   uint32_t Result = support::endian::read32le(Ctx.Ptr);
80   Ctx.Ptr += 4;
81   return Result;
82 }
83 
84 static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
85   if (Ctx.Ptr + 4 > Ctx.End)
86     report_fatal_error("EOF while reading float64");
87   int32_t Result = 0;
88   memcpy(&Result, Ctx.Ptr, sizeof(Result));
89   Ctx.Ptr += sizeof(Result);
90   return Result;
91 }
92 
93 static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
94   if (Ctx.Ptr + 8 > Ctx.End)
95     report_fatal_error("EOF while reading float64");
96   int64_t Result = 0;
97   memcpy(&Result, Ctx.Ptr, sizeof(Result));
98   Ctx.Ptr += sizeof(Result);
99   return Result;
100 }
101 
102 static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
103   unsigned Count;
104   const char *Error = nullptr;
105   uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
106   if (Error)
107     report_fatal_error(Error);
108   Ctx.Ptr += Count;
109   return Result;
110 }
111 
112 static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
113   uint32_t StringLen = readULEB128(Ctx);
114   if (Ctx.Ptr + StringLen > Ctx.End)
115     report_fatal_error("EOF while reading string");
116   StringRef Return =
117       StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
118   Ctx.Ptr += StringLen;
119   return Return;
120 }
121 
122 static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
123   unsigned Count;
124   const char *Error = nullptr;
125   uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
126   if (Error)
127     report_fatal_error(Error);
128   Ctx.Ptr += Count;
129   return Result;
130 }
131 
132 static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
133   int64_t result = readLEB128(Ctx);
134   if (result > VARUINT1_MAX || result < 0)
135     report_fatal_error("LEB is outside Varuint1 range");
136   return result;
137 }
138 
139 static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
140   int64_t result = readLEB128(Ctx);
141   if (result > INT32_MAX || result < INT32_MIN)
142     report_fatal_error("LEB is outside Varint32 range");
143   return result;
144 }
145 
146 static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
147   uint64_t result = readULEB128(Ctx);
148   if (result > UINT32_MAX)
149     report_fatal_error("LEB is outside Varuint32 range");
150   return result;
151 }
152 
153 static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
154   return readLEB128(Ctx);
155 }
156 
157 static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
158   return readUint8(Ctx);
159 }
160 
161 static Error readInitExpr(wasm::WasmInitExpr &Expr,
162                           WasmObjectFile::ReadContext &Ctx) {
163   Expr.Opcode = readOpcode(Ctx);
164 
165   switch (Expr.Opcode) {
166   case wasm::WASM_OPCODE_I32_CONST:
167     Expr.Value.Int32 = readVarint32(Ctx);
168     break;
169   case wasm::WASM_OPCODE_I64_CONST:
170     Expr.Value.Int64 = readVarint64(Ctx);
171     break;
172   case wasm::WASM_OPCODE_F32_CONST:
173     Expr.Value.Float32 = readFloat32(Ctx);
174     break;
175   case wasm::WASM_OPCODE_F64_CONST:
176     Expr.Value.Float64 = readFloat64(Ctx);
177     break;
178   case wasm::WASM_OPCODE_GET_GLOBAL:
179     Expr.Value.Global = readULEB128(Ctx);
180     break;
181   default:
182     return make_error<GenericBinaryError>("Invalid opcode in init_expr",
183                                           object_error::parse_failed);
184   }
185 
186   uint8_t EndOpcode = readOpcode(Ctx);
187   if (EndOpcode != wasm::WASM_OPCODE_END) {
188     return make_error<GenericBinaryError>("Invalid init_expr",
189                                           object_error::parse_failed);
190   }
191   return Error::success();
192 }
193 
194 static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
195   wasm::WasmLimits Result;
196   Result.Flags = readVaruint1(Ctx);
197   Result.Initial = readVaruint32(Ctx);
198   if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
199     Result.Maximum = readVaruint32(Ctx);
200   return Result;
201 }
202 
203 static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
204   wasm::WasmTable Table;
205   Table.ElemType = readUint8(Ctx);
206   Table.Limits = readLimits(Ctx);
207   return Table;
208 }
209 
210 static Error readSection(WasmSection &Section,
211                          WasmObjectFile::ReadContext &Ctx) {
212   Section.Offset = Ctx.Ptr - Ctx.Start;
213   Section.Type = readUint8(Ctx);
214   LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
215   uint32_t Size = readVaruint32(Ctx);
216   if (Size == 0)
217     return make_error<StringError>("Zero length section",
218                                    object_error::parse_failed);
219   if (Ctx.Ptr + Size > Ctx.End)
220     return make_error<StringError>("Section too large",
221                                    object_error::parse_failed);
222   if (Section.Type == wasm::WASM_SEC_CUSTOM) {
223     WasmObjectFile::ReadContext SectionCtx;
224     SectionCtx.Start = Ctx.Ptr;
225     SectionCtx.Ptr = Ctx.Ptr;
226     SectionCtx.End = Ctx.Ptr + Size;
227 
228     Section.Name = readString(SectionCtx);
229 
230     uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
231     Ctx.Ptr += SectionNameSize;
232     Size -= SectionNameSize;
233   }
234   Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
235   Ctx.Ptr += Size;
236   return Error::success();
237 }
238 
239 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
240     : ObjectFile(Binary::ID_Wasm, Buffer) {
241   ErrorAsOutParameter ErrAsOutParam(&Err);
242   Header.Magic = getData().substr(0, 4);
243   if (Header.Magic != StringRef("\0asm", 4)) {
244     Err =
245         make_error<StringError>("Bad magic number", object_error::parse_failed);
246     return;
247   }
248 
249   ReadContext Ctx;
250   Ctx.Start = getPtr(0);
251   Ctx.Ptr = Ctx.Start + 4;
252   Ctx.End = Ctx.Start + getData().size();
253 
254   if (Ctx.Ptr + 4 > Ctx.End) {
255     Err = make_error<StringError>("Missing version number",
256                                   object_error::parse_failed);
257     return;
258   }
259 
260   Header.Version = readUint32(Ctx);
261   if (Header.Version != wasm::WasmVersion) {
262     Err = make_error<StringError>("Bad version number",
263                                   object_error::parse_failed);
264     return;
265   }
266 
267   WasmSection Sec;
268   while (Ctx.Ptr < Ctx.End) {
269     if ((Err = readSection(Sec, Ctx)))
270       return;
271     if ((Err = parseSection(Sec)))
272       return;
273 
274     Sections.push_back(Sec);
275   }
276 }
277 
278 Error WasmObjectFile::parseSection(WasmSection &Sec) {
279   ReadContext Ctx;
280   Ctx.Start = Sec.Content.data();
281   Ctx.End = Ctx.Start + Sec.Content.size();
282   Ctx.Ptr = Ctx.Start;
283   switch (Sec.Type) {
284   case wasm::WASM_SEC_CUSTOM:
285     return parseCustomSection(Sec, Ctx);
286   case wasm::WASM_SEC_TYPE:
287     return parseTypeSection(Ctx);
288   case wasm::WASM_SEC_IMPORT:
289     return parseImportSection(Ctx);
290   case wasm::WASM_SEC_FUNCTION:
291     return parseFunctionSection(Ctx);
292   case wasm::WASM_SEC_TABLE:
293     return parseTableSection(Ctx);
294   case wasm::WASM_SEC_MEMORY:
295     return parseMemorySection(Ctx);
296   case wasm::WASM_SEC_GLOBAL:
297     return parseGlobalSection(Ctx);
298   case wasm::WASM_SEC_EXPORT:
299     return parseExportSection(Ctx);
300   case wasm::WASM_SEC_START:
301     return parseStartSection(Ctx);
302   case wasm::WASM_SEC_ELEM:
303     return parseElemSection(Ctx);
304   case wasm::WASM_SEC_CODE:
305     return parseCodeSection(Ctx);
306   case wasm::WASM_SEC_DATA:
307     return parseDataSection(Ctx);
308   default:
309     return make_error<GenericBinaryError>("Bad section type",
310                                           object_error::parse_failed);
311   }
312 }
313 
314 Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
315   llvm::DenseSet<uint64_t> Seen;
316   if (Functions.size() != FunctionTypes.size()) {
317     return make_error<GenericBinaryError>("Names must come after code section",
318                                           object_error::parse_failed);
319   }
320 
321   while (Ctx.Ptr < Ctx.End) {
322     uint8_t Type = readUint8(Ctx);
323     uint32_t Size = readVaruint32(Ctx);
324     const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
325     switch (Type) {
326     case wasm::WASM_NAMES_FUNCTION: {
327       uint32_t Count = readVaruint32(Ctx);
328       while (Count--) {
329         uint32_t Index = readVaruint32(Ctx);
330         if (!Seen.insert(Index).second)
331           return make_error<GenericBinaryError>("Function named more than once",
332                                                 object_error::parse_failed);
333         StringRef Name = readString(Ctx);
334         if (!isValidFunctionIndex(Index) || Name.empty())
335           return make_error<GenericBinaryError>("Invalid name entry",
336                                                 object_error::parse_failed);
337         DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
338         if (isDefinedFunctionIndex(Index))
339           getDefinedFunction(Index).DebugName = Name;
340       }
341       break;
342     }
343     // Ignore local names for now
344     case wasm::WASM_NAMES_LOCAL:
345     default:
346       Ctx.Ptr += Size;
347       break;
348     }
349     if (Ctx.Ptr != SubSectionEnd)
350       return make_error<GenericBinaryError>(
351           "Name sub-section ended prematurely", object_error::parse_failed);
352   }
353 
354   if (Ctx.Ptr != Ctx.End)
355     return make_error<GenericBinaryError>("Name section ended prematurely",
356                                           object_error::parse_failed);
357   return Error::success();
358 }
359 
360 Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
361   HasLinkingSection = true;
362   if (Functions.size() != FunctionTypes.size()) {
363     return make_error<GenericBinaryError>(
364         "Linking data must come after code section",
365         object_error::parse_failed);
366   }
367 
368   LinkingData.Version = readVaruint32(Ctx);
369   if (LinkingData.Version != wasm::WasmMetadataVersion) {
370     return make_error<GenericBinaryError>(
371         "Unexpected metadata version: " + Twine(LinkingData.Version) +
372             " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
373         object_error::parse_failed);
374   }
375 
376   const uint8_t *OrigEnd = Ctx.End;
377   while (Ctx.Ptr < OrigEnd) {
378     Ctx.End = OrigEnd;
379     uint8_t Type = readUint8(Ctx);
380     uint32_t Size = readVaruint32(Ctx);
381     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
382                       << "\n");
383     Ctx.End = Ctx.Ptr + Size;
384     switch (Type) {
385     case wasm::WASM_SYMBOL_TABLE:
386       if (Error Err = parseLinkingSectionSymtab(Ctx))
387         return Err;
388       break;
389     case wasm::WASM_SEGMENT_INFO: {
390       uint32_t Count = readVaruint32(Ctx);
391       if (Count > DataSegments.size())
392         return make_error<GenericBinaryError>("Too many segment names",
393                                               object_error::parse_failed);
394       for (uint32_t i = 0; i < Count; i++) {
395         DataSegments[i].Data.Name = readString(Ctx);
396         DataSegments[i].Data.Alignment = readVaruint32(Ctx);
397         DataSegments[i].Data.Flags = readVaruint32(Ctx);
398       }
399       break;
400     }
401     case wasm::WASM_INIT_FUNCS: {
402       uint32_t Count = readVaruint32(Ctx);
403       LinkingData.InitFunctions.reserve(Count);
404       for (uint32_t i = 0; i < Count; i++) {
405         wasm::WasmInitFunc Init;
406         Init.Priority = readVaruint32(Ctx);
407         Init.Symbol = readVaruint32(Ctx);
408         if (!isValidFunctionSymbol(Init.Symbol))
409           return make_error<GenericBinaryError>("Invalid function symbol: " +
410                                                     Twine(Init.Symbol),
411                                                 object_error::parse_failed);
412         LinkingData.InitFunctions.emplace_back(Init);
413       }
414       break;
415     }
416     case wasm::WASM_COMDAT_INFO:
417       if (Error Err = parseLinkingSectionComdat(Ctx))
418         return Err;
419       break;
420     default:
421       Ctx.Ptr += Size;
422       break;
423     }
424     if (Ctx.Ptr != Ctx.End)
425       return make_error<GenericBinaryError>(
426           "Linking sub-section ended prematurely", object_error::parse_failed);
427   }
428   if (Ctx.Ptr != OrigEnd)
429     return make_error<GenericBinaryError>("Linking section ended prematurely",
430                                           object_error::parse_failed);
431   return Error::success();
432 }
433 
434 Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
435   uint32_t Count = readVaruint32(Ctx);
436   LinkingData.SymbolTable.reserve(Count);
437   Symbols.reserve(Count);
438   StringSet<> SymbolNames;
439 
440   std::vector<wasm::WasmImport *> ImportedGlobals;
441   std::vector<wasm::WasmImport *> ImportedFunctions;
442   ImportedGlobals.reserve(Imports.size());
443   ImportedFunctions.reserve(Imports.size());
444   for (auto &I : Imports) {
445     if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
446       ImportedFunctions.emplace_back(&I);
447     else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
448       ImportedGlobals.emplace_back(&I);
449   }
450 
451   while (Count--) {
452     wasm::WasmSymbolInfo Info;
453     const wasm::WasmSignature *FunctionType = nullptr;
454     const wasm::WasmGlobalType *GlobalType = nullptr;
455 
456     Info.Kind = readUint8(Ctx);
457     Info.Flags = readVaruint32(Ctx);
458     bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
459 
460     switch (Info.Kind) {
461     case wasm::WASM_SYMBOL_TYPE_FUNCTION:
462       Info.ElementIndex = readVaruint32(Ctx);
463       if (!isValidFunctionIndex(Info.ElementIndex) ||
464           IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
465         return make_error<GenericBinaryError>("invalid function symbol index",
466                                               object_error::parse_failed);
467       if (IsDefined) {
468         Info.Name = readString(Ctx);
469         unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
470         FunctionType = &Signatures[FunctionTypes[FuncIndex]];
471         wasm::WasmFunction &Function = Functions[FuncIndex];
472         if (Function.SymbolName.empty())
473           Function.SymbolName = Info.Name;
474       } else {
475         wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
476         FunctionType = &Signatures[Import.SigIndex];
477         Info.Name = Import.Field;
478         Info.Module = Import.Module;
479       }
480       break;
481 
482     case wasm::WASM_SYMBOL_TYPE_GLOBAL:
483       Info.ElementIndex = readVaruint32(Ctx);
484       if (!isValidGlobalIndex(Info.ElementIndex) ||
485           IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
486         return make_error<GenericBinaryError>("invalid global symbol index",
487                                               object_error::parse_failed);
488       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
489                             wasm::WASM_SYMBOL_BINDING_WEAK)
490         return make_error<GenericBinaryError>("undefined weak global symbol",
491                                               object_error::parse_failed);
492       if (IsDefined) {
493         Info.Name = readString(Ctx);
494         unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
495         wasm::WasmGlobal &Global = Globals[GlobalIndex];
496         GlobalType = &Global.Type;
497         if (Global.SymbolName.empty())
498           Global.SymbolName = Info.Name;
499       } else {
500         wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
501         Info.Name = Import.Field;
502         GlobalType = &Import.Global;
503       }
504       break;
505 
506     case wasm::WASM_SYMBOL_TYPE_DATA:
507       Info.Name = readString(Ctx);
508       if (IsDefined) {
509         uint32_t Index = readVaruint32(Ctx);
510         if (Index >= DataSegments.size())
511           return make_error<GenericBinaryError>("invalid data symbol index",
512                                                 object_error::parse_failed);
513         uint32_t Offset = readVaruint32(Ctx);
514         uint32_t Size = readVaruint32(Ctx);
515         if (Offset + Size > DataSegments[Index].Data.Content.size())
516           return make_error<GenericBinaryError>("invalid data symbol offset",
517                                                 object_error::parse_failed);
518         Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
519       }
520       break;
521 
522     case wasm::WASM_SYMBOL_TYPE_SECTION: {
523       if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
524           wasm::WASM_SYMBOL_BINDING_LOCAL)
525         return make_error<GenericBinaryError>(
526             "Section symbols must have local binding",
527             object_error::parse_failed);
528       Info.ElementIndex = readVaruint32(Ctx);
529       // Use somewhat unique section name as symbol name.
530       StringRef SectionName = Sections[Info.ElementIndex].Name;
531       Info.Name = SectionName;
532       break;
533     }
534 
535     default:
536       return make_error<GenericBinaryError>("Invalid symbol type",
537                                             object_error::parse_failed);
538     }
539 
540     if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
541             wasm::WASM_SYMBOL_BINDING_LOCAL &&
542         !SymbolNames.insert(Info.Name).second)
543       return make_error<GenericBinaryError>("Duplicate symbol name " +
544                                                 Twine(Info.Name),
545                                             object_error::parse_failed);
546     LinkingData.SymbolTable.emplace_back(Info);
547     Symbols.emplace_back(LinkingData.SymbolTable.back(), FunctionType,
548                          GlobalType);
549     LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
550   }
551 
552   return Error::success();
553 }
554 
555 Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
556   uint32_t ComdatCount = readVaruint32(Ctx);
557   StringSet<> ComdatSet;
558   for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
559     StringRef Name = readString(Ctx);
560     if (Name.empty() || !ComdatSet.insert(Name).second)
561       return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
562                                                 Twine(Name),
563                                             object_error::parse_failed);
564     LinkingData.Comdats.emplace_back(Name);
565     uint32_t Flags = readVaruint32(Ctx);
566     if (Flags != 0)
567       return make_error<GenericBinaryError>("Unsupported COMDAT flags",
568                                             object_error::parse_failed);
569 
570     uint32_t EntryCount = readVaruint32(Ctx);
571     while (EntryCount--) {
572       unsigned Kind = readVaruint32(Ctx);
573       unsigned Index = readVaruint32(Ctx);
574       switch (Kind) {
575       default:
576         return make_error<GenericBinaryError>("Invalid COMDAT entry type",
577                                               object_error::parse_failed);
578       case wasm::WASM_COMDAT_DATA:
579         if (Index >= DataSegments.size())
580           return make_error<GenericBinaryError>(
581               "COMDAT data index out of range", object_error::parse_failed);
582         if (DataSegments[Index].Data.Comdat != UINT32_MAX)
583           return make_error<GenericBinaryError>("Data segment in two COMDATs",
584                                                 object_error::parse_failed);
585         DataSegments[Index].Data.Comdat = ComdatIndex;
586         break;
587       case wasm::WASM_COMDAT_FUNCTION:
588         if (!isDefinedFunctionIndex(Index))
589           return make_error<GenericBinaryError>(
590               "COMDAT function index out of range", object_error::parse_failed);
591         if (getDefinedFunction(Index).Comdat != UINT32_MAX)
592           return make_error<GenericBinaryError>("Function in two COMDATs",
593                                                 object_error::parse_failed);
594         getDefinedFunction(Index).Comdat = ComdatIndex;
595         break;
596       }
597     }
598   }
599   return Error::success();
600 }
601 
602 Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
603   uint32_t SectionIndex = readVaruint32(Ctx);
604   if (SectionIndex >= Sections.size())
605     return make_error<GenericBinaryError>("Invalid section index",
606                                           object_error::parse_failed);
607   WasmSection &Section = Sections[SectionIndex];
608   uint32_t RelocCount = readVaruint32(Ctx);
609   uint32_t EndOffset = Section.Content.size();
610   uint32_t PreviousOffset = 0;
611   while (RelocCount--) {
612     wasm::WasmRelocation Reloc = {};
613     Reloc.Type = readVaruint32(Ctx);
614     Reloc.Offset = readVaruint32(Ctx);
615     if (Reloc.Offset < PreviousOffset)
616       return make_error<GenericBinaryError>("Relocations not in offset order",
617                                             object_error::parse_failed);
618     PreviousOffset = Reloc.Offset;
619     Reloc.Index = readVaruint32(Ctx);
620     switch (Reloc.Type) {
621     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
622     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
623     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
624       if (!isValidFunctionSymbol(Reloc.Index))
625         return make_error<GenericBinaryError>("Bad relocation function index",
626                                               object_error::parse_failed);
627       break;
628     case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
629       if (Reloc.Index >= Signatures.size())
630         return make_error<GenericBinaryError>("Bad relocation type index",
631                                               object_error::parse_failed);
632       break;
633     case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
634       if (!isValidGlobalSymbol(Reloc.Index))
635         return make_error<GenericBinaryError>("Bad relocation global index",
636                                               object_error::parse_failed);
637       break;
638     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
639     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
640     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
641       if (!isValidDataSymbol(Reloc.Index))
642         return make_error<GenericBinaryError>("Bad relocation data index",
643                                               object_error::parse_failed);
644       Reloc.Addend = readVarint32(Ctx);
645       break;
646     case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
647       if (!isValidFunctionSymbol(Reloc.Index))
648         return make_error<GenericBinaryError>("Bad relocation function index",
649                                               object_error::parse_failed);
650       Reloc.Addend = readVarint32(Ctx);
651       break;
652     case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
653       if (!isValidSectionSymbol(Reloc.Index))
654         return make_error<GenericBinaryError>("Bad relocation section index",
655                                               object_error::parse_failed);
656       Reloc.Addend = readVarint32(Ctx);
657       break;
658     default:
659       return make_error<GenericBinaryError>("Bad relocation type: " +
660                                                 Twine(Reloc.Type),
661                                             object_error::parse_failed);
662     }
663 
664     // Relocations must fit inside the section, and must appear in order.  They
665     // also shouldn't overlap a function/element boundary, but we don't bother
666     // to check that.
667     uint64_t Size = 5;
668     if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 ||
669         Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32 ||
670         Reloc.Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32 ||
671         Reloc.Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32)
672       Size = 4;
673     if (Reloc.Offset + Size > EndOffset)
674       return make_error<GenericBinaryError>("Bad relocation offset",
675                                             object_error::parse_failed);
676 
677     Section.Relocations.push_back(Reloc);
678   }
679   if (Ctx.Ptr != Ctx.End)
680     return make_error<GenericBinaryError>("Reloc section ended prematurely",
681                                           object_error::parse_failed);
682   return Error::success();
683 }
684 
685 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
686   if (Sec.Name == "name") {
687     if (Error Err = parseNameSection(Ctx))
688       return Err;
689   } else if (Sec.Name == "linking") {
690     if (Error Err = parseLinkingSection(Ctx))
691       return Err;
692   } else if (Sec.Name.startswith("reloc.")) {
693     if (Error Err = parseRelocSection(Sec.Name, Ctx))
694       return Err;
695   }
696   return Error::success();
697 }
698 
699 Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
700   uint32_t Count = readVaruint32(Ctx);
701   Signatures.reserve(Count);
702   while (Count--) {
703     wasm::WasmSignature Sig;
704     Sig.ReturnType = wasm::WASM_TYPE_NORESULT;
705     uint8_t Form = readUint8(Ctx);
706     if (Form != wasm::WASM_TYPE_FUNC) {
707       return make_error<GenericBinaryError>("Invalid signature type",
708                                             object_error::parse_failed);
709     }
710     uint32_t ParamCount = readVaruint32(Ctx);
711     Sig.ParamTypes.reserve(ParamCount);
712     while (ParamCount--) {
713       uint32_t ParamType = readUint8(Ctx);
714       Sig.ParamTypes.push_back(ParamType);
715     }
716     uint32_t ReturnCount = readVaruint32(Ctx);
717     if (ReturnCount) {
718       if (ReturnCount != 1) {
719         return make_error<GenericBinaryError>(
720             "Multiple return types not supported", object_error::parse_failed);
721       }
722       Sig.ReturnType = readUint8(Ctx);
723     }
724     Signatures.push_back(Sig);
725   }
726   if (Ctx.Ptr != Ctx.End)
727     return make_error<GenericBinaryError>("Type section ended prematurely",
728                                           object_error::parse_failed);
729   return Error::success();
730 }
731 
732 Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
733   uint32_t Count = readVaruint32(Ctx);
734   Imports.reserve(Count);
735   for (uint32_t i = 0; i < Count; i++) {
736     wasm::WasmImport Im;
737     Im.Module = readString(Ctx);
738     Im.Field = readString(Ctx);
739     Im.Kind = readUint8(Ctx);
740     switch (Im.Kind) {
741     case wasm::WASM_EXTERNAL_FUNCTION:
742       NumImportedFunctions++;
743       Im.SigIndex = readVaruint32(Ctx);
744       break;
745     case wasm::WASM_EXTERNAL_GLOBAL:
746       NumImportedGlobals++;
747       Im.Global.Type = readUint8(Ctx);
748       Im.Global.Mutable = readVaruint1(Ctx);
749       break;
750     case wasm::WASM_EXTERNAL_MEMORY:
751       Im.Memory = readLimits(Ctx);
752       break;
753     case wasm::WASM_EXTERNAL_TABLE:
754       Im.Table = readTable(Ctx);
755       if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC)
756         return make_error<GenericBinaryError>("Invalid table element type",
757                                               object_error::parse_failed);
758       break;
759     default:
760       return make_error<GenericBinaryError>("Unexpected import kind",
761                                             object_error::parse_failed);
762     }
763     Imports.push_back(Im);
764   }
765   if (Ctx.Ptr != Ctx.End)
766     return make_error<GenericBinaryError>("Import section ended prematurely",
767                                           object_error::parse_failed);
768   return Error::success();
769 }
770 
771 Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
772   uint32_t Count = readVaruint32(Ctx);
773   FunctionTypes.reserve(Count);
774   uint32_t NumTypes = Signatures.size();
775   while (Count--) {
776     uint32_t Type = readVaruint32(Ctx);
777     if (Type >= NumTypes)
778       return make_error<GenericBinaryError>("Invalid function type",
779                                             object_error::parse_failed);
780     FunctionTypes.push_back(Type);
781   }
782   if (Ctx.Ptr != Ctx.End)
783     return make_error<GenericBinaryError>("Function section ended prematurely",
784                                           object_error::parse_failed);
785   return Error::success();
786 }
787 
788 Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
789   uint32_t Count = readVaruint32(Ctx);
790   Tables.reserve(Count);
791   while (Count--) {
792     Tables.push_back(readTable(Ctx));
793     if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) {
794       return make_error<GenericBinaryError>("Invalid table element type",
795                                             object_error::parse_failed);
796     }
797   }
798   if (Ctx.Ptr != Ctx.End)
799     return make_error<GenericBinaryError>("Table section ended prematurely",
800                                           object_error::parse_failed);
801   return Error::success();
802 }
803 
804 Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
805   uint32_t Count = readVaruint32(Ctx);
806   Memories.reserve(Count);
807   while (Count--) {
808     Memories.push_back(readLimits(Ctx));
809   }
810   if (Ctx.Ptr != Ctx.End)
811     return make_error<GenericBinaryError>("Memory section ended prematurely",
812                                           object_error::parse_failed);
813   return Error::success();
814 }
815 
816 Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
817   GlobalSection = Sections.size();
818   uint32_t Count = readVaruint32(Ctx);
819   Globals.reserve(Count);
820   while (Count--) {
821     wasm::WasmGlobal Global;
822     Global.Index = NumImportedGlobals + Globals.size();
823     Global.Type.Type = readUint8(Ctx);
824     Global.Type.Mutable = readVaruint1(Ctx);
825     if (Error Err = readInitExpr(Global.InitExpr, Ctx))
826       return Err;
827     Globals.push_back(Global);
828   }
829   if (Ctx.Ptr != Ctx.End)
830     return make_error<GenericBinaryError>("Global section ended prematurely",
831                                           object_error::parse_failed);
832   return Error::success();
833 }
834 
835 Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
836   uint32_t Count = readVaruint32(Ctx);
837   Exports.reserve(Count);
838   for (uint32_t i = 0; i < Count; i++) {
839     wasm::WasmExport Ex;
840     Ex.Name = readString(Ctx);
841     Ex.Kind = readUint8(Ctx);
842     Ex.Index = readVaruint32(Ctx);
843     switch (Ex.Kind) {
844     case wasm::WASM_EXTERNAL_FUNCTION:
845       if (!isValidFunctionIndex(Ex.Index))
846         return make_error<GenericBinaryError>("Invalid function export",
847                                               object_error::parse_failed);
848       break;
849     case wasm::WASM_EXTERNAL_GLOBAL:
850       if (!isValidGlobalIndex(Ex.Index))
851         return make_error<GenericBinaryError>("Invalid global export",
852                                               object_error::parse_failed);
853       break;
854     case wasm::WASM_EXTERNAL_MEMORY:
855     case wasm::WASM_EXTERNAL_TABLE:
856       break;
857     default:
858       return make_error<GenericBinaryError>("Unexpected export kind",
859                                             object_error::parse_failed);
860     }
861     Exports.push_back(Ex);
862   }
863   if (Ctx.Ptr != Ctx.End)
864     return make_error<GenericBinaryError>("Export section ended prematurely",
865                                           object_error::parse_failed);
866   return Error::success();
867 }
868 
869 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
870   return Index < NumImportedFunctions + FunctionTypes.size();
871 }
872 
873 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
874   return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
875 }
876 
877 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
878   return Index < NumImportedGlobals + Globals.size();
879 }
880 
881 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
882   return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
883 }
884 
885 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
886   return Index < Symbols.size() && Symbols[Index].isTypeFunction();
887 }
888 
889 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
890   return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
891 }
892 
893 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
894   return Index < Symbols.size() && Symbols[Index].isTypeData();
895 }
896 
897 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
898   return Index < Symbols.size() && Symbols[Index].isTypeSection();
899 }
900 
901 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
902   assert(isDefinedFunctionIndex(Index));
903   return Functions[Index - NumImportedFunctions];
904 }
905 
906 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
907   assert(isDefinedGlobalIndex(Index));
908   return Globals[Index - NumImportedGlobals];
909 }
910 
911 Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
912   StartFunction = readVaruint32(Ctx);
913   if (!isValidFunctionIndex(StartFunction))
914     return make_error<GenericBinaryError>("Invalid start function",
915                                           object_error::parse_failed);
916   return Error::success();
917 }
918 
919 Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
920   CodeSection = Sections.size();
921   uint32_t FunctionCount = readVaruint32(Ctx);
922   if (FunctionCount != FunctionTypes.size()) {
923     return make_error<GenericBinaryError>("Invalid function count",
924                                           object_error::parse_failed);
925   }
926 
927   while (FunctionCount--) {
928     wasm::WasmFunction Function;
929     const uint8_t *FunctionStart = Ctx.Ptr;
930     uint32_t Size = readVaruint32(Ctx);
931     const uint8_t *FunctionEnd = Ctx.Ptr + Size;
932 
933     Function.CodeOffset = Ctx.Ptr - FunctionStart;
934     Function.Index = NumImportedFunctions + Functions.size();
935     Function.CodeSectionOffset = FunctionStart - Ctx.Start;
936     Function.Size = FunctionEnd - FunctionStart;
937 
938     uint32_t NumLocalDecls = readVaruint32(Ctx);
939     Function.Locals.reserve(NumLocalDecls);
940     while (NumLocalDecls--) {
941       wasm::WasmLocalDecl Decl;
942       Decl.Count = readVaruint32(Ctx);
943       Decl.Type = readUint8(Ctx);
944       Function.Locals.push_back(Decl);
945     }
946 
947     uint32_t BodySize = FunctionEnd - Ctx.Ptr;
948     Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
949     // This will be set later when reading in the linking metadata section.
950     Function.Comdat = UINT32_MAX;
951     Ctx.Ptr += BodySize;
952     assert(Ctx.Ptr == FunctionEnd);
953     Functions.push_back(Function);
954   }
955   if (Ctx.Ptr != Ctx.End)
956     return make_error<GenericBinaryError>("Code section ended prematurely",
957                                           object_error::parse_failed);
958   return Error::success();
959 }
960 
961 Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
962   uint32_t Count = readVaruint32(Ctx);
963   ElemSegments.reserve(Count);
964   while (Count--) {
965     wasm::WasmElemSegment Segment;
966     Segment.TableIndex = readVaruint32(Ctx);
967     if (Segment.TableIndex != 0) {
968       return make_error<GenericBinaryError>("Invalid TableIndex",
969                                             object_error::parse_failed);
970     }
971     if (Error Err = readInitExpr(Segment.Offset, Ctx))
972       return Err;
973     uint32_t NumElems = readVaruint32(Ctx);
974     while (NumElems--) {
975       Segment.Functions.push_back(readVaruint32(Ctx));
976     }
977     ElemSegments.push_back(Segment);
978   }
979   if (Ctx.Ptr != Ctx.End)
980     return make_error<GenericBinaryError>("Elem section ended prematurely",
981                                           object_error::parse_failed);
982   return Error::success();
983 }
984 
985 Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
986   DataSection = Sections.size();
987   uint32_t Count = readVaruint32(Ctx);
988   DataSegments.reserve(Count);
989   while (Count--) {
990     WasmSegment Segment;
991     Segment.Data.MemoryIndex = readVaruint32(Ctx);
992     if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
993       return Err;
994     uint32_t Size = readVaruint32(Ctx);
995     if (Size > (size_t)(Ctx.End - Ctx.Ptr))
996       return make_error<GenericBinaryError>("Invalid segment size",
997                                             object_error::parse_failed);
998     Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
999     // The rest of these Data fields are set later, when reading in the linking
1000     // metadata section.
1001     Segment.Data.Alignment = 0;
1002     Segment.Data.Flags = 0;
1003     Segment.Data.Comdat = UINT32_MAX;
1004     Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1005     Ctx.Ptr += Size;
1006     DataSegments.push_back(Segment);
1007   }
1008   if (Ctx.Ptr != Ctx.End)
1009     return make_error<GenericBinaryError>("Data section ended prematurely",
1010                                           object_error::parse_failed);
1011   return Error::success();
1012 }
1013 
1014 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
1015   return reinterpret_cast<const uint8_t *>(getData().data() + Offset);
1016 }
1017 
1018 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1019   return Header;
1020 }
1021 
1022 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
1023 
1024 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1025   uint32_t Result = SymbolRef::SF_None;
1026   const WasmSymbol &Sym = getWasmSymbol(Symb);
1027 
1028   LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1029   if (Sym.isBindingWeak())
1030     Result |= SymbolRef::SF_Weak;
1031   if (!Sym.isBindingLocal())
1032     Result |= SymbolRef::SF_Global;
1033   if (Sym.isHidden())
1034     Result |= SymbolRef::SF_Hidden;
1035   if (!Sym.isDefined())
1036     Result |= SymbolRef::SF_Undefined;
1037   if (Sym.isTypeFunction())
1038     Result |= SymbolRef::SF_Executable;
1039   return Result;
1040 }
1041 
1042 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1043   DataRefImpl Ref;
1044   Ref.d.a = 0;
1045   return BasicSymbolRef(Ref, this);
1046 }
1047 
1048 basic_symbol_iterator WasmObjectFile::symbol_end() const {
1049   DataRefImpl Ref;
1050   Ref.d.a = Symbols.size();
1051   return BasicSymbolRef(Ref, this);
1052 }
1053 
1054 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1055   return Symbols[Symb.d.a];
1056 }
1057 
1058 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1059   return getWasmSymbol(Symb.getRawDataRefImpl());
1060 }
1061 
1062 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1063   return getWasmSymbol(Symb).Info.Name;
1064 }
1065 
1066 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1067   return getSymbolValue(Symb);
1068 }
1069 
1070 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1071   switch (Sym.Info.Kind) {
1072   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1073   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1074     return Sym.Info.ElementIndex;
1075   case wasm::WASM_SYMBOL_TYPE_DATA: {
1076     // The value of a data symbol is the segment offset, plus the symbol
1077     // offset within the segment.
1078     uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1079     const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1080     assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST);
1081     return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
1082   }
1083   case wasm::WASM_SYMBOL_TYPE_SECTION:
1084     return 0;
1085   }
1086   llvm_unreachable("invalid symbol type");
1087 }
1088 
1089 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1090   return getWasmSymbolValue(getWasmSymbol(Symb));
1091 }
1092 
1093 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1094   llvm_unreachable("not yet implemented");
1095   return 0;
1096 }
1097 
1098 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1099   llvm_unreachable("not yet implemented");
1100   return 0;
1101 }
1102 
1103 Expected<SymbolRef::Type>
1104 WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1105   const WasmSymbol &Sym = getWasmSymbol(Symb);
1106 
1107   switch (Sym.Info.Kind) {
1108   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1109     return SymbolRef::ST_Function;
1110   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1111     return SymbolRef::ST_Other;
1112   case wasm::WASM_SYMBOL_TYPE_DATA:
1113     return SymbolRef::ST_Data;
1114   case wasm::WASM_SYMBOL_TYPE_SECTION:
1115     return SymbolRef::ST_Debug;
1116   }
1117 
1118   llvm_unreachable("Unknown WasmSymbol::SymbolType");
1119   return SymbolRef::ST_Other;
1120 }
1121 
1122 Expected<section_iterator>
1123 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1124   const WasmSymbol &Sym = getWasmSymbol(Symb);
1125   if (Sym.isUndefined())
1126     return section_end();
1127 
1128   DataRefImpl Ref;
1129   switch (Sym.Info.Kind) {
1130   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1131     Ref.d.a = CodeSection;
1132     break;
1133   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1134     Ref.d.a = GlobalSection;
1135     break;
1136   case wasm::WASM_SYMBOL_TYPE_DATA:
1137     Ref.d.a = DataSection;
1138     break;
1139   case wasm::WASM_SYMBOL_TYPE_SECTION: {
1140     Ref.d.a = Sym.Info.ElementIndex;
1141     break;
1142   }
1143   default:
1144     llvm_unreachable("Unknown WasmSymbol::SymbolType");
1145   }
1146   return section_iterator(SectionRef(Ref, this));
1147 }
1148 
1149 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1150 
1151 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
1152                                                StringRef &Res) const {
1153   const WasmSection &S = Sections[Sec.d.a];
1154 #define ECase(X)                                                               \
1155   case wasm::WASM_SEC_##X:                                                     \
1156     Res = #X;                                                                  \
1157     break
1158   switch (S.Type) {
1159     ECase(TYPE);
1160     ECase(IMPORT);
1161     ECase(FUNCTION);
1162     ECase(TABLE);
1163     ECase(MEMORY);
1164     ECase(GLOBAL);
1165     ECase(EXPORT);
1166     ECase(START);
1167     ECase(ELEM);
1168     ECase(CODE);
1169     ECase(DATA);
1170   case wasm::WASM_SEC_CUSTOM:
1171     Res = S.Name;
1172     break;
1173   default:
1174     return object_error::invalid_section_index;
1175   }
1176 #undef ECase
1177   return std::error_code();
1178 }
1179 
1180 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1181 
1182 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1183   return Sec.d.a;
1184 }
1185 
1186 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1187   const WasmSection &S = Sections[Sec.d.a];
1188   return S.Content.size();
1189 }
1190 
1191 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
1192                                                    StringRef &Res) const {
1193   const WasmSection &S = Sections[Sec.d.a];
1194   // This will never fail since wasm sections can never be empty (user-sections
1195   // must have a name and non-user sections each have a defined structure).
1196   Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
1197                   S.Content.size());
1198   return std::error_code();
1199 }
1200 
1201 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1202   return 1;
1203 }
1204 
1205 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1206   return false;
1207 }
1208 
1209 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1210   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1211 }
1212 
1213 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1214   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1215 }
1216 
1217 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1218 
1219 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1220 
1221 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1222 
1223 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1224   DataRefImpl RelocRef;
1225   RelocRef.d.a = Ref.d.a;
1226   RelocRef.d.b = 0;
1227   return relocation_iterator(RelocationRef(RelocRef, this));
1228 }
1229 
1230 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1231   const WasmSection &Sec = getWasmSection(Ref);
1232   DataRefImpl RelocRef;
1233   RelocRef.d.a = Ref.d.a;
1234   RelocRef.d.b = Sec.Relocations.size();
1235   return relocation_iterator(RelocationRef(RelocRef, this));
1236 }
1237 
1238 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1239 
1240 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1241   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1242   return Rel.Offset;
1243 }
1244 
1245 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1246   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1247   if (Rel.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
1248     return symbol_end();
1249   DataRefImpl Sym;
1250   Sym.d.a = Rel.Index;
1251   Sym.d.b = 0;
1252   return symbol_iterator(SymbolRef(Sym, this));
1253 }
1254 
1255 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1256   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1257   return Rel.Type;
1258 }
1259 
1260 void WasmObjectFile::getRelocationTypeName(
1261     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1262   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1263   StringRef Res = "Unknown";
1264 
1265 #define WASM_RELOC(name, value)                                                \
1266   case wasm::name:                                                             \
1267     Res = #name;                                                               \
1268     break;
1269 
1270   switch (Rel.Type) {
1271 #include "llvm/BinaryFormat/WasmRelocs.def"
1272   }
1273 
1274 #undef WASM_RELOC
1275 
1276   Result.append(Res.begin(), Res.end());
1277 }
1278 
1279 section_iterator WasmObjectFile::section_begin() const {
1280   DataRefImpl Ref;
1281   Ref.d.a = 0;
1282   return section_iterator(SectionRef(Ref, this));
1283 }
1284 
1285 section_iterator WasmObjectFile::section_end() const {
1286   DataRefImpl Ref;
1287   Ref.d.a = Sections.size();
1288   return section_iterator(SectionRef(Ref, this));
1289 }
1290 
1291 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1292 
1293 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1294 
1295 Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
1296 
1297 SubtargetFeatures WasmObjectFile::getFeatures() const {
1298   return SubtargetFeatures();
1299 }
1300 
1301 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1302 
1303 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1304   assert(Ref.d.a < Sections.size());
1305   return Sections[Ref.d.a];
1306 }
1307 
1308 const WasmSection &
1309 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1310   return getWasmSection(Section.getRawDataRefImpl());
1311 }
1312 
1313 const wasm::WasmRelocation &
1314 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1315   return getWasmRelocation(Ref.getRawDataRefImpl());
1316 }
1317 
1318 const wasm::WasmRelocation &
1319 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1320   assert(Ref.d.a < Sections.size());
1321   const WasmSection &Sec = Sections[Ref.d.a];
1322   assert(Ref.d.b < Sec.Relocations.size());
1323   return Sec.Relocations[Ref.d.b];
1324 }
1325