xref: /llvm-project/llvm/lib/Object/WasmObjectFile.cpp (revision da419bdb5e3e167ea90c6923660059f35fa17d67)
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 = readVaruint32(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_EVENT:
299     return parseEventSection(Ctx);
300   case wasm::WASM_SEC_EXPORT:
301     return parseExportSection(Ctx);
302   case wasm::WASM_SEC_START:
303     return parseStartSection(Ctx);
304   case wasm::WASM_SEC_ELEM:
305     return parseElemSection(Ctx);
306   case wasm::WASM_SEC_CODE:
307     return parseCodeSection(Ctx);
308   case wasm::WASM_SEC_DATA:
309     return parseDataSection(Ctx);
310   default:
311     return make_error<GenericBinaryError>("Bad section type",
312                                           object_error::parse_failed);
313   }
314 }
315 
316 Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
317   llvm::DenseSet<uint64_t> Seen;
318   if (Functions.size() != FunctionTypes.size()) {
319     return make_error<GenericBinaryError>("Names must come after code section",
320                                           object_error::parse_failed);
321   }
322 
323   while (Ctx.Ptr < Ctx.End) {
324     uint8_t Type = readUint8(Ctx);
325     uint32_t Size = readVaruint32(Ctx);
326     const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
327     switch (Type) {
328     case wasm::WASM_NAMES_FUNCTION: {
329       uint32_t Count = readVaruint32(Ctx);
330       while (Count--) {
331         uint32_t Index = readVaruint32(Ctx);
332         if (!Seen.insert(Index).second)
333           return make_error<GenericBinaryError>("Function named more than once",
334                                                 object_error::parse_failed);
335         StringRef Name = readString(Ctx);
336         if (!isValidFunctionIndex(Index) || Name.empty())
337           return make_error<GenericBinaryError>("Invalid name entry",
338                                                 object_error::parse_failed);
339         DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
340         if (isDefinedFunctionIndex(Index))
341           getDefinedFunction(Index).DebugName = Name;
342       }
343       break;
344     }
345     // Ignore local names for now
346     case wasm::WASM_NAMES_LOCAL:
347     default:
348       Ctx.Ptr += Size;
349       break;
350     }
351     if (Ctx.Ptr != SubSectionEnd)
352       return make_error<GenericBinaryError>(
353           "Name sub-section ended prematurely", object_error::parse_failed);
354   }
355 
356   if (Ctx.Ptr != Ctx.End)
357     return make_error<GenericBinaryError>("Name section ended prematurely",
358                                           object_error::parse_failed);
359   return Error::success();
360 }
361 
362 Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
363   HasLinkingSection = true;
364   if (Functions.size() != FunctionTypes.size()) {
365     return make_error<GenericBinaryError>(
366         "Linking data must come after code section",
367         object_error::parse_failed);
368   }
369 
370   LinkingData.Version = readVaruint32(Ctx);
371   if (LinkingData.Version != wasm::WasmMetadataVersion) {
372     return make_error<GenericBinaryError>(
373         "Unexpected metadata version: " + Twine(LinkingData.Version) +
374             " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
375         object_error::parse_failed);
376   }
377 
378   const uint8_t *OrigEnd = Ctx.End;
379   while (Ctx.Ptr < OrigEnd) {
380     Ctx.End = OrigEnd;
381     uint8_t Type = readUint8(Ctx);
382     uint32_t Size = readVaruint32(Ctx);
383     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
384                       << "\n");
385     Ctx.End = Ctx.Ptr + Size;
386     switch (Type) {
387     case wasm::WASM_SYMBOL_TABLE:
388       if (Error Err = parseLinkingSectionSymtab(Ctx))
389         return Err;
390       break;
391     case wasm::WASM_SEGMENT_INFO: {
392       uint32_t Count = readVaruint32(Ctx);
393       if (Count > DataSegments.size())
394         return make_error<GenericBinaryError>("Too many segment names",
395                                               object_error::parse_failed);
396       for (uint32_t i = 0; i < Count; i++) {
397         DataSegments[i].Data.Name = readString(Ctx);
398         DataSegments[i].Data.Alignment = readVaruint32(Ctx);
399         DataSegments[i].Data.Flags = readVaruint32(Ctx);
400       }
401       break;
402     }
403     case wasm::WASM_INIT_FUNCS: {
404       uint32_t Count = readVaruint32(Ctx);
405       LinkingData.InitFunctions.reserve(Count);
406       for (uint32_t i = 0; i < Count; i++) {
407         wasm::WasmInitFunc Init;
408         Init.Priority = readVaruint32(Ctx);
409         Init.Symbol = readVaruint32(Ctx);
410         if (!isValidFunctionSymbol(Init.Symbol))
411           return make_error<GenericBinaryError>("Invalid function symbol: " +
412                                                     Twine(Init.Symbol),
413                                                 object_error::parse_failed);
414         LinkingData.InitFunctions.emplace_back(Init);
415       }
416       break;
417     }
418     case wasm::WASM_COMDAT_INFO:
419       if (Error Err = parseLinkingSectionComdat(Ctx))
420         return Err;
421       break;
422     default:
423       Ctx.Ptr += Size;
424       break;
425     }
426     if (Ctx.Ptr != Ctx.End)
427       return make_error<GenericBinaryError>(
428           "Linking sub-section ended prematurely", object_error::parse_failed);
429   }
430   if (Ctx.Ptr != OrigEnd)
431     return make_error<GenericBinaryError>("Linking section ended prematurely",
432                                           object_error::parse_failed);
433   return Error::success();
434 }
435 
436 Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
437   uint32_t Count = readVaruint32(Ctx);
438   LinkingData.SymbolTable.reserve(Count);
439   Symbols.reserve(Count);
440   StringSet<> SymbolNames;
441 
442   std::vector<wasm::WasmImport *> ImportedGlobals;
443   std::vector<wasm::WasmImport *> ImportedFunctions;
444   std::vector<wasm::WasmImport *> ImportedEvents;
445   ImportedGlobals.reserve(Imports.size());
446   ImportedFunctions.reserve(Imports.size());
447   ImportedEvents.reserve(Imports.size());
448   for (auto &I : Imports) {
449     if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
450       ImportedFunctions.emplace_back(&I);
451     else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
452       ImportedGlobals.emplace_back(&I);
453     else if (I.Kind == wasm::WASM_EXTERNAL_EVENT)
454       ImportedEvents.emplace_back(&I);
455   }
456 
457   while (Count--) {
458     wasm::WasmSymbolInfo Info;
459     const wasm::WasmSignature *FunctionType = nullptr;
460     const wasm::WasmGlobalType *GlobalType = nullptr;
461     const wasm::WasmEventType *EventType = nullptr;
462 
463     Info.Kind = readUint8(Ctx);
464     Info.Flags = readVaruint32(Ctx);
465     bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
466 
467     switch (Info.Kind) {
468     case wasm::WASM_SYMBOL_TYPE_FUNCTION:
469       Info.ElementIndex = readVaruint32(Ctx);
470       if (!isValidFunctionIndex(Info.ElementIndex) ||
471           IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
472         return make_error<GenericBinaryError>("invalid function symbol index",
473                                               object_error::parse_failed);
474       if (IsDefined) {
475         Info.Name = readString(Ctx);
476         unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
477         FunctionType = &Signatures[FunctionTypes[FuncIndex]];
478         wasm::WasmFunction &Function = Functions[FuncIndex];
479         if (Function.SymbolName.empty())
480           Function.SymbolName = Info.Name;
481       } else {
482         wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
483         FunctionType = &Signatures[Import.SigIndex];
484         Info.Name = Import.Field;
485         Info.Module = Import.Module;
486       }
487       break;
488 
489     case wasm::WASM_SYMBOL_TYPE_GLOBAL:
490       Info.ElementIndex = readVaruint32(Ctx);
491       if (!isValidGlobalIndex(Info.ElementIndex) ||
492           IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
493         return make_error<GenericBinaryError>("invalid global symbol index",
494                                               object_error::parse_failed);
495       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
496                             wasm::WASM_SYMBOL_BINDING_WEAK)
497         return make_error<GenericBinaryError>("undefined weak global symbol",
498                                               object_error::parse_failed);
499       if (IsDefined) {
500         Info.Name = readString(Ctx);
501         unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
502         wasm::WasmGlobal &Global = Globals[GlobalIndex];
503         GlobalType = &Global.Type;
504         if (Global.SymbolName.empty())
505           Global.SymbolName = Info.Name;
506       } else {
507         wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
508         Info.Name = Import.Field;
509         GlobalType = &Import.Global;
510       }
511       break;
512 
513     case wasm::WASM_SYMBOL_TYPE_DATA:
514       Info.Name = readString(Ctx);
515       if (IsDefined) {
516         uint32_t Index = readVaruint32(Ctx);
517         if (Index >= DataSegments.size())
518           return make_error<GenericBinaryError>("invalid data symbol index",
519                                                 object_error::parse_failed);
520         uint32_t Offset = readVaruint32(Ctx);
521         uint32_t Size = readVaruint32(Ctx);
522         if (Offset + Size > DataSegments[Index].Data.Content.size())
523           return make_error<GenericBinaryError>("invalid data symbol offset",
524                                                 object_error::parse_failed);
525         Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
526       }
527       break;
528 
529     case wasm::WASM_SYMBOL_TYPE_SECTION: {
530       if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
531           wasm::WASM_SYMBOL_BINDING_LOCAL)
532         return make_error<GenericBinaryError>(
533             "Section symbols must have local binding",
534             object_error::parse_failed);
535       Info.ElementIndex = readVaruint32(Ctx);
536       // Use somewhat unique section name as symbol name.
537       StringRef SectionName = Sections[Info.ElementIndex].Name;
538       Info.Name = SectionName;
539       break;
540     }
541 
542     case wasm::WASM_SYMBOL_TYPE_EVENT: {
543       Info.ElementIndex = readVaruint32(Ctx);
544       if (!isValidEventIndex(Info.ElementIndex) ||
545           IsDefined != isDefinedEventIndex(Info.ElementIndex))
546         return make_error<GenericBinaryError>("invalid event symbol index",
547                                               object_error::parse_failed);
548       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
549                             wasm::WASM_SYMBOL_BINDING_WEAK)
550         return make_error<GenericBinaryError>("undefined weak global symbol",
551                                               object_error::parse_failed);
552       if (IsDefined) {
553         Info.Name = readString(Ctx);
554         unsigned EventIndex = Info.ElementIndex - NumImportedEvents;
555         wasm::WasmEvent &Event = Events[EventIndex];
556         EventType = &Event.Type;
557         if (Event.SymbolName.empty())
558           Event.SymbolName = Info.Name;
559 
560       } else {
561         wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
562         EventType = &Import.Event;
563         Info.Name = Import.Field;
564       }
565       break;
566     }
567 
568     default:
569       return make_error<GenericBinaryError>("Invalid symbol type",
570                                             object_error::parse_failed);
571     }
572 
573     if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
574             wasm::WASM_SYMBOL_BINDING_LOCAL &&
575         !SymbolNames.insert(Info.Name).second)
576       return make_error<GenericBinaryError>("Duplicate symbol name " +
577                                                 Twine(Info.Name),
578                                             object_error::parse_failed);
579     LinkingData.SymbolTable.emplace_back(Info);
580     Symbols.emplace_back(LinkingData.SymbolTable.back(), FunctionType,
581                          GlobalType, EventType);
582     LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
583   }
584 
585   return Error::success();
586 }
587 
588 Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
589   uint32_t ComdatCount = readVaruint32(Ctx);
590   StringSet<> ComdatSet;
591   for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
592     StringRef Name = readString(Ctx);
593     if (Name.empty() || !ComdatSet.insert(Name).second)
594       return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
595                                                 Twine(Name),
596                                             object_error::parse_failed);
597     LinkingData.Comdats.emplace_back(Name);
598     uint32_t Flags = readVaruint32(Ctx);
599     if (Flags != 0)
600       return make_error<GenericBinaryError>("Unsupported COMDAT flags",
601                                             object_error::parse_failed);
602 
603     uint32_t EntryCount = readVaruint32(Ctx);
604     while (EntryCount--) {
605       unsigned Kind = readVaruint32(Ctx);
606       unsigned Index = readVaruint32(Ctx);
607       switch (Kind) {
608       default:
609         return make_error<GenericBinaryError>("Invalid COMDAT entry type",
610                                               object_error::parse_failed);
611       case wasm::WASM_COMDAT_DATA:
612         if (Index >= DataSegments.size())
613           return make_error<GenericBinaryError>(
614               "COMDAT data index out of range", object_error::parse_failed);
615         if (DataSegments[Index].Data.Comdat != UINT32_MAX)
616           return make_error<GenericBinaryError>("Data segment in two COMDATs",
617                                                 object_error::parse_failed);
618         DataSegments[Index].Data.Comdat = ComdatIndex;
619         break;
620       case wasm::WASM_COMDAT_FUNCTION:
621         if (!isDefinedFunctionIndex(Index))
622           return make_error<GenericBinaryError>(
623               "COMDAT function index out of range", object_error::parse_failed);
624         if (getDefinedFunction(Index).Comdat != UINT32_MAX)
625           return make_error<GenericBinaryError>("Function in two COMDATs",
626                                                 object_error::parse_failed);
627         getDefinedFunction(Index).Comdat = ComdatIndex;
628         break;
629       }
630     }
631   }
632   return Error::success();
633 }
634 
635 Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
636   uint32_t SectionIndex = readVaruint32(Ctx);
637   if (SectionIndex >= Sections.size())
638     return make_error<GenericBinaryError>("Invalid section index",
639                                           object_error::parse_failed);
640   WasmSection &Section = Sections[SectionIndex];
641   uint32_t RelocCount = readVaruint32(Ctx);
642   uint32_t EndOffset = Section.Content.size();
643   uint32_t PreviousOffset = 0;
644   while (RelocCount--) {
645     wasm::WasmRelocation Reloc = {};
646     Reloc.Type = readVaruint32(Ctx);
647     Reloc.Offset = readVaruint32(Ctx);
648     if (Reloc.Offset < PreviousOffset)
649       return make_error<GenericBinaryError>("Relocations not in offset order",
650                                             object_error::parse_failed);
651     PreviousOffset = Reloc.Offset;
652     Reloc.Index = readVaruint32(Ctx);
653     switch (Reloc.Type) {
654     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
655     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
656     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
657       if (!isValidFunctionSymbol(Reloc.Index))
658         return make_error<GenericBinaryError>("Bad relocation function index",
659                                               object_error::parse_failed);
660       break;
661     case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
662       if (Reloc.Index >= Signatures.size())
663         return make_error<GenericBinaryError>("Bad relocation type index",
664                                               object_error::parse_failed);
665       break;
666     case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
667       if (!isValidGlobalSymbol(Reloc.Index))
668         return make_error<GenericBinaryError>("Bad relocation global index",
669                                               object_error::parse_failed);
670       break;
671     case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
672       if (!isValidEventSymbol(Reloc.Index))
673         return make_error<GenericBinaryError>("Bad relocation event index",
674                                               object_error::parse_failed);
675       break;
676     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
677     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
678     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
679       if (!isValidDataSymbol(Reloc.Index))
680         return make_error<GenericBinaryError>("Bad relocation data index",
681                                               object_error::parse_failed);
682       Reloc.Addend = readVarint32(Ctx);
683       break;
684     case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
685       if (!isValidFunctionSymbol(Reloc.Index))
686         return make_error<GenericBinaryError>("Bad relocation function index",
687                                               object_error::parse_failed);
688       Reloc.Addend = readVarint32(Ctx);
689       break;
690     case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
691       if (!isValidSectionSymbol(Reloc.Index))
692         return make_error<GenericBinaryError>("Bad relocation section index",
693                                               object_error::parse_failed);
694       Reloc.Addend = readVarint32(Ctx);
695       break;
696     default:
697       return make_error<GenericBinaryError>("Bad relocation type: " +
698                                                 Twine(Reloc.Type),
699                                             object_error::parse_failed);
700     }
701 
702     // Relocations must fit inside the section, and must appear in order.  They
703     // also shouldn't overlap a function/element boundary, but we don't bother
704     // to check that.
705     uint64_t Size = 5;
706     if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 ||
707         Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32 ||
708         Reloc.Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32 ||
709         Reloc.Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32)
710       Size = 4;
711     if (Reloc.Offset + Size > EndOffset)
712       return make_error<GenericBinaryError>("Bad relocation offset",
713                                             object_error::parse_failed);
714 
715     Section.Relocations.push_back(Reloc);
716   }
717   if (Ctx.Ptr != Ctx.End)
718     return make_error<GenericBinaryError>("Reloc section ended prematurely",
719                                           object_error::parse_failed);
720   return Error::success();
721 }
722 
723 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
724   if (Sec.Name == "name") {
725     if (Error Err = parseNameSection(Ctx))
726       return Err;
727   } else if (Sec.Name == "linking") {
728     if (Error Err = parseLinkingSection(Ctx))
729       return Err;
730   } else if (Sec.Name.startswith("reloc.")) {
731     if (Error Err = parseRelocSection(Sec.Name, Ctx))
732       return Err;
733   }
734   return Error::success();
735 }
736 
737 Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
738   uint32_t Count = readVaruint32(Ctx);
739   Signatures.reserve(Count);
740   while (Count--) {
741     wasm::WasmSignature Sig;
742     uint8_t Form = readUint8(Ctx);
743     if (Form != wasm::WASM_TYPE_FUNC) {
744       return make_error<GenericBinaryError>("Invalid signature type",
745                                             object_error::parse_failed);
746     }
747     uint32_t ParamCount = readVaruint32(Ctx);
748     Sig.Params.reserve(ParamCount);
749     while (ParamCount--) {
750       uint32_t ParamType = readUint8(Ctx);
751       Sig.Params.push_back(wasm::ValType(ParamType));
752     }
753     uint32_t ReturnCount = readVaruint32(Ctx);
754     if (ReturnCount) {
755       if (ReturnCount != 1) {
756         return make_error<GenericBinaryError>(
757             "Multiple return types not supported", object_error::parse_failed);
758       }
759       Sig.Returns.push_back(wasm::ValType(readUint8(Ctx)));
760     }
761     Signatures.push_back(std::move(Sig));
762   }
763   if (Ctx.Ptr != Ctx.End)
764     return make_error<GenericBinaryError>("Type section ended prematurely",
765                                           object_error::parse_failed);
766   return Error::success();
767 }
768 
769 Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
770   uint32_t Count = readVaruint32(Ctx);
771   Imports.reserve(Count);
772   for (uint32_t i = 0; i < Count; i++) {
773     wasm::WasmImport Im;
774     Im.Module = readString(Ctx);
775     Im.Field = readString(Ctx);
776     Im.Kind = readUint8(Ctx);
777     switch (Im.Kind) {
778     case wasm::WASM_EXTERNAL_FUNCTION:
779       NumImportedFunctions++;
780       Im.SigIndex = readVaruint32(Ctx);
781       break;
782     case wasm::WASM_EXTERNAL_GLOBAL:
783       NumImportedGlobals++;
784       Im.Global.Type = readUint8(Ctx);
785       Im.Global.Mutable = readVaruint1(Ctx);
786       break;
787     case wasm::WASM_EXTERNAL_MEMORY:
788       Im.Memory = readLimits(Ctx);
789       break;
790     case wasm::WASM_EXTERNAL_TABLE:
791       Im.Table = readTable(Ctx);
792       if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC)
793         return make_error<GenericBinaryError>("Invalid table element type",
794                                               object_error::parse_failed);
795       break;
796     case wasm::WASM_EXTERNAL_EVENT:
797       NumImportedEvents++;
798       Im.Event.Attribute = readVarint32(Ctx);
799       Im.Event.SigIndex = readVarint32(Ctx);
800       break;
801     default:
802       return make_error<GenericBinaryError>("Unexpected import kind",
803                                             object_error::parse_failed);
804     }
805     Imports.push_back(Im);
806   }
807   if (Ctx.Ptr != Ctx.End)
808     return make_error<GenericBinaryError>("Import section ended prematurely",
809                                           object_error::parse_failed);
810   return Error::success();
811 }
812 
813 Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
814   uint32_t Count = readVaruint32(Ctx);
815   FunctionTypes.reserve(Count);
816   uint32_t NumTypes = Signatures.size();
817   while (Count--) {
818     uint32_t Type = readVaruint32(Ctx);
819     if (Type >= NumTypes)
820       return make_error<GenericBinaryError>("Invalid function type",
821                                             object_error::parse_failed);
822     FunctionTypes.push_back(Type);
823   }
824   if (Ctx.Ptr != Ctx.End)
825     return make_error<GenericBinaryError>("Function section ended prematurely",
826                                           object_error::parse_failed);
827   return Error::success();
828 }
829 
830 Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
831   uint32_t Count = readVaruint32(Ctx);
832   Tables.reserve(Count);
833   while (Count--) {
834     Tables.push_back(readTable(Ctx));
835     if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) {
836       return make_error<GenericBinaryError>("Invalid table element type",
837                                             object_error::parse_failed);
838     }
839   }
840   if (Ctx.Ptr != Ctx.End)
841     return make_error<GenericBinaryError>("Table section ended prematurely",
842                                           object_error::parse_failed);
843   return Error::success();
844 }
845 
846 Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
847   uint32_t Count = readVaruint32(Ctx);
848   Memories.reserve(Count);
849   while (Count--) {
850     Memories.push_back(readLimits(Ctx));
851   }
852   if (Ctx.Ptr != Ctx.End)
853     return make_error<GenericBinaryError>("Memory section ended prematurely",
854                                           object_error::parse_failed);
855   return Error::success();
856 }
857 
858 Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
859   GlobalSection = Sections.size();
860   uint32_t Count = readVaruint32(Ctx);
861   Globals.reserve(Count);
862   while (Count--) {
863     wasm::WasmGlobal Global;
864     Global.Index = NumImportedGlobals + Globals.size();
865     Global.Type.Type = readUint8(Ctx);
866     Global.Type.Mutable = readVaruint1(Ctx);
867     if (Error Err = readInitExpr(Global.InitExpr, Ctx))
868       return Err;
869     Globals.push_back(Global);
870   }
871   if (Ctx.Ptr != Ctx.End)
872     return make_error<GenericBinaryError>("Global section ended prematurely",
873                                           object_error::parse_failed);
874   return Error::success();
875 }
876 
877 Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
878   EventSection = Sections.size();
879   uint32_t Count = readVarint32(Ctx);
880   Events.reserve(Count);
881   while (Count--) {
882     wasm::WasmEvent Event;
883     Event.Index = NumImportedEvents + Events.size();
884     Event.Type.Attribute = readVaruint32(Ctx);
885     Event.Type.SigIndex = readVarint32(Ctx);
886     Events.push_back(Event);
887   }
888 
889   if (Ctx.Ptr != Ctx.End)
890     return make_error<GenericBinaryError>("Event section ended prematurely",
891                                           object_error::parse_failed);
892   return Error::success();
893 }
894 
895 Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
896   uint32_t Count = readVaruint32(Ctx);
897   Exports.reserve(Count);
898   for (uint32_t i = 0; i < Count; i++) {
899     wasm::WasmExport Ex;
900     Ex.Name = readString(Ctx);
901     Ex.Kind = readUint8(Ctx);
902     Ex.Index = readVaruint32(Ctx);
903     switch (Ex.Kind) {
904     case wasm::WASM_EXTERNAL_FUNCTION:
905       if (!isValidFunctionIndex(Ex.Index))
906         return make_error<GenericBinaryError>("Invalid function export",
907                                               object_error::parse_failed);
908       break;
909     case wasm::WASM_EXTERNAL_GLOBAL:
910       if (!isValidGlobalIndex(Ex.Index))
911         return make_error<GenericBinaryError>("Invalid global export",
912                                               object_error::parse_failed);
913       break;
914     case wasm::WASM_EXTERNAL_EVENT:
915       if (!isValidEventIndex(Ex.Index))
916         return make_error<GenericBinaryError>("Invalid event export",
917                                               object_error::parse_failed);
918       break;
919     case wasm::WASM_EXTERNAL_MEMORY:
920     case wasm::WASM_EXTERNAL_TABLE:
921       break;
922     default:
923       return make_error<GenericBinaryError>("Unexpected export kind",
924                                             object_error::parse_failed);
925     }
926     Exports.push_back(Ex);
927   }
928   if (Ctx.Ptr != Ctx.End)
929     return make_error<GenericBinaryError>("Export section ended prematurely",
930                                           object_error::parse_failed);
931   return Error::success();
932 }
933 
934 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
935   return Index < NumImportedFunctions + FunctionTypes.size();
936 }
937 
938 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
939   return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
940 }
941 
942 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
943   return Index < NumImportedGlobals + Globals.size();
944 }
945 
946 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
947   return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
948 }
949 
950 bool WasmObjectFile::isValidEventIndex(uint32_t Index) const {
951   return Index < NumImportedEvents + Events.size();
952 }
953 
954 bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const {
955   return Index >= NumImportedEvents && isValidEventIndex(Index);
956 }
957 
958 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
959   return Index < Symbols.size() && Symbols[Index].isTypeFunction();
960 }
961 
962 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
963   return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
964 }
965 
966 bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const {
967   return Index < Symbols.size() && Symbols[Index].isTypeEvent();
968 }
969 
970 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
971   return Index < Symbols.size() && Symbols[Index].isTypeData();
972 }
973 
974 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
975   return Index < Symbols.size() && Symbols[Index].isTypeSection();
976 }
977 
978 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
979   assert(isDefinedFunctionIndex(Index));
980   return Functions[Index - NumImportedFunctions];
981 }
982 
983 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
984   assert(isDefinedGlobalIndex(Index));
985   return Globals[Index - NumImportedGlobals];
986 }
987 
988 wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) {
989   assert(isDefinedEventIndex(Index));
990   return Events[Index - NumImportedEvents];
991 }
992 
993 Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
994   StartFunction = readVaruint32(Ctx);
995   if (!isValidFunctionIndex(StartFunction))
996     return make_error<GenericBinaryError>("Invalid start function",
997                                           object_error::parse_failed);
998   return Error::success();
999 }
1000 
1001 Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1002   CodeSection = Sections.size();
1003   uint32_t FunctionCount = readVaruint32(Ctx);
1004   if (FunctionCount != FunctionTypes.size()) {
1005     return make_error<GenericBinaryError>("Invalid function count",
1006                                           object_error::parse_failed);
1007   }
1008 
1009   while (FunctionCount--) {
1010     wasm::WasmFunction Function;
1011     const uint8_t *FunctionStart = Ctx.Ptr;
1012     uint32_t Size = readVaruint32(Ctx);
1013     const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1014 
1015     Function.CodeOffset = Ctx.Ptr - FunctionStart;
1016     Function.Index = NumImportedFunctions + Functions.size();
1017     Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1018     Function.Size = FunctionEnd - FunctionStart;
1019 
1020     uint32_t NumLocalDecls = readVaruint32(Ctx);
1021     Function.Locals.reserve(NumLocalDecls);
1022     while (NumLocalDecls--) {
1023       wasm::WasmLocalDecl Decl;
1024       Decl.Count = readVaruint32(Ctx);
1025       Decl.Type = readUint8(Ctx);
1026       Function.Locals.push_back(Decl);
1027     }
1028 
1029     uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1030     Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1031     // This will be set later when reading in the linking metadata section.
1032     Function.Comdat = UINT32_MAX;
1033     Ctx.Ptr += BodySize;
1034     assert(Ctx.Ptr == FunctionEnd);
1035     Functions.push_back(Function);
1036   }
1037   if (Ctx.Ptr != Ctx.End)
1038     return make_error<GenericBinaryError>("Code section ended prematurely",
1039                                           object_error::parse_failed);
1040   return Error::success();
1041 }
1042 
1043 Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1044   uint32_t Count = readVaruint32(Ctx);
1045   ElemSegments.reserve(Count);
1046   while (Count--) {
1047     wasm::WasmElemSegment Segment;
1048     Segment.TableIndex = readVaruint32(Ctx);
1049     if (Segment.TableIndex != 0) {
1050       return make_error<GenericBinaryError>("Invalid TableIndex",
1051                                             object_error::parse_failed);
1052     }
1053     if (Error Err = readInitExpr(Segment.Offset, Ctx))
1054       return Err;
1055     uint32_t NumElems = readVaruint32(Ctx);
1056     while (NumElems--) {
1057       Segment.Functions.push_back(readVaruint32(Ctx));
1058     }
1059     ElemSegments.push_back(Segment);
1060   }
1061   if (Ctx.Ptr != Ctx.End)
1062     return make_error<GenericBinaryError>("Elem section ended prematurely",
1063                                           object_error::parse_failed);
1064   return Error::success();
1065 }
1066 
1067 Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1068   DataSection = Sections.size();
1069   uint32_t Count = readVaruint32(Ctx);
1070   DataSegments.reserve(Count);
1071   while (Count--) {
1072     WasmSegment Segment;
1073     Segment.Data.MemoryIndex = readVaruint32(Ctx);
1074     if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1075       return Err;
1076     uint32_t Size = readVaruint32(Ctx);
1077     if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1078       return make_error<GenericBinaryError>("Invalid segment size",
1079                                             object_error::parse_failed);
1080     Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1081     // The rest of these Data fields are set later, when reading in the linking
1082     // metadata section.
1083     Segment.Data.Alignment = 0;
1084     Segment.Data.Flags = 0;
1085     Segment.Data.Comdat = UINT32_MAX;
1086     Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1087     Ctx.Ptr += Size;
1088     DataSegments.push_back(Segment);
1089   }
1090   if (Ctx.Ptr != Ctx.End)
1091     return make_error<GenericBinaryError>("Data section ended prematurely",
1092                                           object_error::parse_failed);
1093   return Error::success();
1094 }
1095 
1096 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
1097   return reinterpret_cast<const uint8_t *>(getData().data() + Offset);
1098 }
1099 
1100 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1101   return Header;
1102 }
1103 
1104 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
1105 
1106 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1107   uint32_t Result = SymbolRef::SF_None;
1108   const WasmSymbol &Sym = getWasmSymbol(Symb);
1109 
1110   LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1111   if (Sym.isBindingWeak())
1112     Result |= SymbolRef::SF_Weak;
1113   if (!Sym.isBindingLocal())
1114     Result |= SymbolRef::SF_Global;
1115   if (Sym.isHidden())
1116     Result |= SymbolRef::SF_Hidden;
1117   if (!Sym.isDefined())
1118     Result |= SymbolRef::SF_Undefined;
1119   if (Sym.isTypeFunction())
1120     Result |= SymbolRef::SF_Executable;
1121   return Result;
1122 }
1123 
1124 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
1125   DataRefImpl Ref;
1126   Ref.d.a = 0;
1127   return BasicSymbolRef(Ref, this);
1128 }
1129 
1130 basic_symbol_iterator WasmObjectFile::symbol_end() const {
1131   DataRefImpl Ref;
1132   Ref.d.a = Symbols.size();
1133   return BasicSymbolRef(Ref, this);
1134 }
1135 
1136 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1137   return Symbols[Symb.d.a];
1138 }
1139 
1140 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1141   return getWasmSymbol(Symb.getRawDataRefImpl());
1142 }
1143 
1144 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1145   return getWasmSymbol(Symb).Info.Name;
1146 }
1147 
1148 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1149   return getSymbolValue(Symb);
1150 }
1151 
1152 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1153   switch (Sym.Info.Kind) {
1154   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1155   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1156   case wasm::WASM_SYMBOL_TYPE_EVENT:
1157     return Sym.Info.ElementIndex;
1158   case wasm::WASM_SYMBOL_TYPE_DATA: {
1159     // The value of a data symbol is the segment offset, plus the symbol
1160     // offset within the segment.
1161     uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1162     const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1163     assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST);
1164     return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
1165   }
1166   case wasm::WASM_SYMBOL_TYPE_SECTION:
1167     return 0;
1168   }
1169   llvm_unreachable("invalid symbol type");
1170 }
1171 
1172 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1173   return getWasmSymbolValue(getWasmSymbol(Symb));
1174 }
1175 
1176 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1177   llvm_unreachable("not yet implemented");
1178   return 0;
1179 }
1180 
1181 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1182   llvm_unreachable("not yet implemented");
1183   return 0;
1184 }
1185 
1186 Expected<SymbolRef::Type>
1187 WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1188   const WasmSymbol &Sym = getWasmSymbol(Symb);
1189 
1190   switch (Sym.Info.Kind) {
1191   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1192     return SymbolRef::ST_Function;
1193   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1194     return SymbolRef::ST_Other;
1195   case wasm::WASM_SYMBOL_TYPE_DATA:
1196     return SymbolRef::ST_Data;
1197   case wasm::WASM_SYMBOL_TYPE_SECTION:
1198     return SymbolRef::ST_Debug;
1199   case wasm::WASM_SYMBOL_TYPE_EVENT:
1200     return SymbolRef::ST_Other;
1201   }
1202 
1203   llvm_unreachable("Unknown WasmSymbol::SymbolType");
1204   return SymbolRef::ST_Other;
1205 }
1206 
1207 Expected<section_iterator>
1208 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1209   const WasmSymbol &Sym = getWasmSymbol(Symb);
1210   if (Sym.isUndefined())
1211     return section_end();
1212 
1213   DataRefImpl Ref;
1214   switch (Sym.Info.Kind) {
1215   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1216     Ref.d.a = CodeSection;
1217     break;
1218   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1219     Ref.d.a = GlobalSection;
1220     break;
1221   case wasm::WASM_SYMBOL_TYPE_DATA:
1222     Ref.d.a = DataSection;
1223     break;
1224   case wasm::WASM_SYMBOL_TYPE_SECTION:
1225     Ref.d.a = Sym.Info.ElementIndex;
1226     break;
1227   case wasm::WASM_SYMBOL_TYPE_EVENT:
1228     Ref.d.a = EventSection;
1229     break;
1230   default:
1231     llvm_unreachable("Unknown WasmSymbol::SymbolType");
1232   }
1233   return section_iterator(SectionRef(Ref, this));
1234 }
1235 
1236 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1237 
1238 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
1239                                                StringRef &Res) const {
1240   const WasmSection &S = Sections[Sec.d.a];
1241 #define ECase(X)                                                               \
1242   case wasm::WASM_SEC_##X:                                                     \
1243     Res = #X;                                                                  \
1244     break
1245   switch (S.Type) {
1246     ECase(TYPE);
1247     ECase(IMPORT);
1248     ECase(FUNCTION);
1249     ECase(TABLE);
1250     ECase(MEMORY);
1251     ECase(GLOBAL);
1252     ECase(EVENT);
1253     ECase(EXPORT);
1254     ECase(START);
1255     ECase(ELEM);
1256     ECase(CODE);
1257     ECase(DATA);
1258   case wasm::WASM_SEC_CUSTOM:
1259     Res = S.Name;
1260     break;
1261   default:
1262     return object_error::invalid_section_index;
1263   }
1264 #undef ECase
1265   return std::error_code();
1266 }
1267 
1268 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1269 
1270 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1271   return Sec.d.a;
1272 }
1273 
1274 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1275   const WasmSection &S = Sections[Sec.d.a];
1276   return S.Content.size();
1277 }
1278 
1279 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
1280                                                    StringRef &Res) const {
1281   const WasmSection &S = Sections[Sec.d.a];
1282   // This will never fail since wasm sections can never be empty (user-sections
1283   // must have a name and non-user sections each have a defined structure).
1284   Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
1285                   S.Content.size());
1286   return std::error_code();
1287 }
1288 
1289 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1290   return 1;
1291 }
1292 
1293 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1294   return false;
1295 }
1296 
1297 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1298   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1299 }
1300 
1301 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1302   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1303 }
1304 
1305 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1306 
1307 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1308 
1309 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1310 
1311 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1312   DataRefImpl RelocRef;
1313   RelocRef.d.a = Ref.d.a;
1314   RelocRef.d.b = 0;
1315   return relocation_iterator(RelocationRef(RelocRef, this));
1316 }
1317 
1318 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1319   const WasmSection &Sec = getWasmSection(Ref);
1320   DataRefImpl RelocRef;
1321   RelocRef.d.a = Ref.d.a;
1322   RelocRef.d.b = Sec.Relocations.size();
1323   return relocation_iterator(RelocationRef(RelocRef, this));
1324 }
1325 
1326 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1327 
1328 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1329   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1330   return Rel.Offset;
1331 }
1332 
1333 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
1334   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1335   if (Rel.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
1336     return symbol_end();
1337   DataRefImpl Sym;
1338   Sym.d.a = Rel.Index;
1339   Sym.d.b = 0;
1340   return symbol_iterator(SymbolRef(Sym, this));
1341 }
1342 
1343 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1344   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1345   return Rel.Type;
1346 }
1347 
1348 void WasmObjectFile::getRelocationTypeName(
1349     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1350   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1351   StringRef Res = "Unknown";
1352 
1353 #define WASM_RELOC(name, value)                                                \
1354   case wasm::name:                                                             \
1355     Res = #name;                                                               \
1356     break;
1357 
1358   switch (Rel.Type) {
1359 #include "llvm/BinaryFormat/WasmRelocs.def"
1360   }
1361 
1362 #undef WASM_RELOC
1363 
1364   Result.append(Res.begin(), Res.end());
1365 }
1366 
1367 section_iterator WasmObjectFile::section_begin() const {
1368   DataRefImpl Ref;
1369   Ref.d.a = 0;
1370   return section_iterator(SectionRef(Ref, this));
1371 }
1372 
1373 section_iterator WasmObjectFile::section_end() const {
1374   DataRefImpl Ref;
1375   Ref.d.a = Sections.size();
1376   return section_iterator(SectionRef(Ref, this));
1377 }
1378 
1379 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1380 
1381 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1382 
1383 Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
1384 
1385 SubtargetFeatures WasmObjectFile::getFeatures() const {
1386   return SubtargetFeatures();
1387 }
1388 
1389 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1390 
1391 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1392   assert(Ref.d.a < Sections.size());
1393   return Sections[Ref.d.a];
1394 }
1395 
1396 const WasmSection &
1397 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1398   return getWasmSection(Section.getRawDataRefImpl());
1399 }
1400 
1401 const wasm::WasmRelocation &
1402 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1403   return getWasmRelocation(Ref.getRawDataRefImpl());
1404 }
1405 
1406 const wasm::WasmRelocation &
1407 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1408   assert(Ref.d.a < Sections.size());
1409   const WasmSection &Sec = Sections[Ref.d.a];
1410   assert(Ref.d.b < Sec.Relocations.size());
1411   return Sec.Relocations[Ref.d.b];
1412 }
1413