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