OSDN Git Service

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