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