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