LLVM  7.0.0svn
WasmObjectFile.cpp
Go to the documentation of this file.
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"
18 #include "llvm/Object/Binary.h"
19 #include "llvm/Object/Error.h"
20 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Object/Wasm.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/Error.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 
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) {
139  Expr.Value.Int32 = readVarint32(Ptr);
140  break;
142  Expr.Value.Int64 = readVarint64(Ptr);
143  break;
145  Expr.Value.Float32 = readFloat32(Ptr);
146  break;
148  Expr.Value.Float64 = readFloat64(Ptr);
149  break;
151  Expr.Value.Global = readULEB128(Ptr);
152  break;
153  default:
154  return make_error<GenericBinaryError>("Invalid opcode in init_expr",
156  }
157 
158  uint8_t EndOpcode = readOpcode(Ptr);
159  if (EndOpcode != wasm::WASM_OPCODE_END) {
160  return make_error<GenericBinaryError>("Invalid init_expr",
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);
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",
190  if (Ptr + Size > Eof)
191  return make_error<StringError>("Section too large",
193  Section.Content = ArrayRef<uint8_t>(Ptr, Size);
194  Ptr += Size;
195  return Error::success();
196 }
197 
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",
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",
216  return;
217  }
218 
219  Header.Version = readUint32(Ptr);
220  if (Header.Version != wasm::WasmVersion) {
221  Err = make_error<StringError>("Bad version number",
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) {
242  return parseCustomSection(Sec, Start, End);
243  case wasm::WASM_SEC_TYPE:
244  return parseTypeSection(Start, End);
246  return parseImportSection(Start, End);
248  return parseFunctionSection(Start, End);
250  return parseTableSection(Start, End);
252  return parseMemorySection(Start, End);
254  return parseGlobalSection(Start, End);
256  return parseExportSection(Start, End);
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",
268  }
269 }
270 
271 Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
273  if (Functions.size() != FunctionTypes.size()) {
274  return make_error<GenericBinaryError>("Names must come after code section",
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) {
284  uint32_t Count = readVaruint32(Ptr);
285  while (Count--) {
287  if (!Seen.insert(Index).second)
288  return make_error<GenericBinaryError>("Function named more than once",
290  StringRef Name = readString(Ptr);
291  if (!isValidFunctionIndex(Index) || Name.empty())
292  return make_error<GenericBinaryError>("Invalid name entry",
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
305  default:
306  Ptr += Size;
307  break;
308  }
309  if (Ptr != SubSectionEnd)
310  return make_error<GenericBinaryError>("Name sub-section ended prematurely",
312  }
313 
314  if (Ptr != End)
315  return make_error<GenericBinaryError>("Name section ended prematurely",
317  return Error::success();
318 }
319 
320 void WasmObjectFile::populateSymbolTable() {
321  // Add imports to symbol table
322  size_t GlobalIndex = 0;
323  size_t FunctionIndex = 0;
324  for (const wasm::WasmImport& Import : Imports) {
325  switch (Import.Kind) {
327  assert(Import.Global.Type == wasm::WASM_TYPE_I32);
328  SymbolMap.try_emplace(Import.Field, Symbols.size());
329  Symbols.emplace_back(Import.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
330  GlobalIndex++);
331  DEBUG(dbgs() << "Adding import: " << Symbols.back()
332  << " sym index:" << Symbols.size() << "\n");
333  break;
335  SymbolMap.try_emplace(Import.Field, Symbols.size());
336  Symbols.emplace_back(Import.Field,
338  FunctionIndex++, Import.SigIndex);
339  DEBUG(dbgs() << "Adding import: " << Symbols.back()
340  << " sym index:" << Symbols.size() << "\n");
341  break;
342  default:
343  break;
344  }
345  }
346 
347  // Add exports to symbol table
348  for (const wasm::WasmExport& Export : Exports) {
349  if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION ||
351  WasmSymbol::SymbolType ExportType =
355  auto Pair = SymbolMap.try_emplace(Export.Name, Symbols.size());
356  if (Pair.second) {
357  Symbols.emplace_back(Export.Name, ExportType, Export.Index);
358  DEBUG(dbgs() << "Adding export: " << Symbols.back()
359  << " sym index:" << Symbols.size() << "\n");
360  } else {
361  uint32_t SymIndex = Pair.first->second;
362  const WasmSymbol &OldSym = Symbols[SymIndex];
363  WasmSymbol NewSym(Export.Name, ExportType, Export.Index);
364  NewSym.setAltIndex(OldSym.ElementIndex);
365  Symbols[SymIndex] = NewSym;
366 
367  DEBUG(dbgs() << "Replacing existing symbol: " << NewSym
368  << " sym index:" << SymIndex << "\n");
369  }
370  }
371  if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION &&
372  isDefinedFunctionIndex(Export.Index)) {
373  auto &Function = getDefinedFunction(Export.Index);
374  if (Function.Name.empty()) {
375  // Use the export's name to set a name for the Function, but only if one
376  // hasn't already been set.
377  Function.Name = Export.Name;
378  }
379  }
380  }
381 }
382 
383 Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
384  const uint8_t *End) {
385  HasLinkingSection = true;
386  if (Functions.size() != FunctionTypes.size()) {
387  return make_error<GenericBinaryError>(
388  "Linking data must come after code section", object_error::parse_failed);
389  }
390 
391  // Only populate the symbol table with imports and exports if the object
392  // has a linking section (i.e. its a relocatable object file). Otherwise
393  // the global might not represent symbols at all.
394  populateSymbolTable();
395 
396  while (Ptr < End) {
397  uint8_t Type = readVarint7(Ptr);
398  uint32_t Size = readVaruint32(Ptr);
399  const uint8_t *SubSectionEnd = Ptr + Size;
400  switch (Type) {
401  case wasm::WASM_SYMBOL_INFO: {
402  uint32_t Count = readVaruint32(Ptr);
403  while (Count--) {
404  StringRef Symbol = readString(Ptr);
405  uint32_t Flags = readVaruint32(Ptr);
406  auto iter = SymbolMap.find(Symbol);
407  if (iter == SymbolMap.end()) {
408  return make_error<GenericBinaryError>(
409  "Invalid symbol name in linking section: " + Symbol,
411  }
412  uint32_t SymIndex = iter->second;
413  assert(SymIndex < Symbols.size());
414  Symbols[SymIndex].Flags = Flags;
415  DEBUG(dbgs() << "Set symbol flags index:"
416  << SymIndex << " name:"
417  << Symbols[SymIndex].Name << " expected:"
418  << Symbol << " flags: " << Flags << "\n");
419  }
420  break;
421  }
423  LinkingData.DataSize = readVaruint32(Ptr);
424  break;
426  uint32_t Count = readVaruint32(Ptr);
427  if (Count > DataSegments.size())
428  return make_error<GenericBinaryError>("Too many segment names",
430  for (uint32_t i = 0; i < Count; i++) {
431  DataSegments[i].Data.Name = readString(Ptr);
432  DataSegments[i].Data.Alignment = readVaruint32(Ptr);
433  DataSegments[i].Data.Flags = readVaruint32(Ptr);
434  }
435  break;
436  }
437  case wasm::WASM_INIT_FUNCS: {
438  uint32_t Count = readVaruint32(Ptr);
439  LinkingData.InitFunctions.reserve(Count);
440  for (uint32_t i = 0; i < Count; i++) {
442  Init.Priority = readVaruint32(Ptr);
443  Init.FunctionIndex = readVaruint32(Ptr);
444  if (!isValidFunctionIndex(Init.FunctionIndex))
445  return make_error<GenericBinaryError>("Invalid function index: " +
446  Twine(Init.FunctionIndex),
448  LinkingData.InitFunctions.emplace_back(Init);
449  }
450  break;
451  }
453  if (Error Err = parseLinkingSectionComdat(Ptr, SubSectionEnd))
454  return Err;
455  break;
456  default:
457  Ptr += Size;
458  break;
459  }
460  if (Ptr != SubSectionEnd)
461  return make_error<GenericBinaryError>(
462  "Linking sub-section ended prematurely", object_error::parse_failed);
463  }
464  if (Ptr != End)
465  return make_error<GenericBinaryError>("Linking section ended prematurely",
467  return Error::success();
468 }
469 
470 Error WasmObjectFile::parseLinkingSectionComdat(const uint8_t *&Ptr,
471  const uint8_t *End)
472 {
473  uint32_t ComdatCount = readVaruint32(Ptr);
474  StringSet<> ComdatSet;
475  while (ComdatCount--) {
476  StringRef Name = readString(Ptr);
477  if (Name.empty() || !ComdatSet.insert(Name).second)
478  return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " + Twine(Name),
480  Comdats.emplace_back(Name);
481  uint32_t Flags = readVaruint32(Ptr);
482  if (Flags != 0)
483  return make_error<GenericBinaryError>("Unsupported COMDAT flags",
485 
486  uint32_t EntryCount = readVaruint32(Ptr);
487  while (EntryCount--) {
488  unsigned Kind = readVaruint32(Ptr);
489  unsigned Index = readVaruint32(Ptr);
490  switch (Kind) {
491  default:
492  return make_error<GenericBinaryError>("Invalid COMDAT entry type",
495  if (Index >= DataSegments.size())
496  return make_error<GenericBinaryError>("COMDAT data index out of range",
498  if (!DataSegments[Index].Data.Comdat.empty())
499  return make_error<GenericBinaryError>("Data segment in two COMDATs",
501  DataSegments[Index].Data.Comdat = Name;
502  break;
504  if (!isDefinedFunctionIndex(Index))
505  return make_error<GenericBinaryError>("COMDAT function index out of range",
507  if (!getDefinedFunction(Index).Comdat.empty())
508  return make_error<GenericBinaryError>("Function in two COMDATs",
510  getDefinedFunction(Index).Comdat = Name;
511  break;
512  }
513  }
514  }
515  return Error::success();
516 }
517 
518 WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) {
519  for (WasmSection& Section : Sections) {
520  if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name)
521  return &Section;
522  }
523  return nullptr;
524 }
525 
526 WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) {
527  assert(Type != wasm::WASM_SEC_CUSTOM);
528  for (WasmSection& Section : Sections) {
529  if (Section.Type == Type)
530  return &Section;
531  }
532  return nullptr;
533 }
534 
535 Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
536  const uint8_t *End) {
537  uint8_t SectionCode = readVarint7(Ptr);
538  WasmSection* Section = nullptr;
539  if (SectionCode == wasm::WASM_SEC_CUSTOM) {
540  StringRef Name = readString(Ptr);
541  Section = findCustomSectionByName(Name);
542  } else {
543  Section = findSectionByType(SectionCode);
544  }
545  if (!Section)
546  return make_error<GenericBinaryError>("Invalid section code",
548  uint32_t RelocCount = readVaruint32(Ptr);
549  while (RelocCount--) {
550  wasm::WasmRelocation Reloc;
551  memset(&Reloc, 0, sizeof(Reloc));
552  Reloc.Type = readVaruint32(Ptr);
553  Reloc.Offset = readVaruint32(Ptr);
554  Reloc.Index = readVaruint32(Ptr);
555  switch (Reloc.Type) {
556  case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
557  case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
558  case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
559  case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
560  case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
561  break;
562  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
563  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
564  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
565  Reloc.Addend = readVarint32(Ptr);
566  break;
567  default:
568  return make_error<GenericBinaryError>("Bad relocation type: " +
569  Twine(Reloc.Type),
571  }
572  Section->Relocations.push_back(Reloc);
573  }
574  if (Ptr != End)
575  return make_error<GenericBinaryError>("Reloc section ended prematurely",
577  return Error::success();
578 }
579 
580 Error WasmObjectFile::parseCustomSection(WasmSection &Sec,
581  const uint8_t *Ptr, const uint8_t *End) {
582  Sec.Name = readString(Ptr);
583  if (Sec.Name == "name") {
584  if (Error Err = parseNameSection(Ptr, End))
585  return Err;
586  } else if (Sec.Name == "linking") {
587  if (Error Err = parseLinkingSection(Ptr, End))
588  return Err;
589  } else if (Sec.Name.startswith("reloc.")) {
590  if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
591  return Err;
592  }
593  return Error::success();
594 }
595 
596 Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) {
597  uint32_t Count = readVaruint32(Ptr);
598  Signatures.reserve(Count);
599  while (Count--) {
602  int8_t Form = readVarint7(Ptr);
603  if (Form != wasm::WASM_TYPE_FUNC) {
604  return make_error<GenericBinaryError>("Invalid signature type",
606  }
607  uint32_t ParamCount = readVaruint32(Ptr);
608  Sig.ParamTypes.reserve(ParamCount);
609  while (ParamCount--) {
610  uint32_t ParamType = readVarint7(Ptr);
611  Sig.ParamTypes.push_back(ParamType);
612  }
613  uint32_t ReturnCount = readVaruint32(Ptr);
614  if (ReturnCount) {
615  if (ReturnCount != 1) {
616  return make_error<GenericBinaryError>(
617  "Multiple return types not supported", object_error::parse_failed);
618  }
619  Sig.ReturnType = readVarint7(Ptr);
620  }
621  Signatures.push_back(Sig);
622  }
623  if (Ptr != End)
624  return make_error<GenericBinaryError>("Type section ended prematurely",
626  return Error::success();
627 }
628 
629 Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) {
630  uint32_t Count = readVaruint32(Ptr);
631  Imports.reserve(Count);
632  for (uint32_t i = 0; i < Count; i++) {
633  wasm::WasmImport Im;
634  Im.Module = readString(Ptr);
635  Im.Field = readString(Ptr);
636  Im.Kind = readUint8(Ptr);
637  switch (Im.Kind) {
639  NumImportedFunctions++;
640  Im.SigIndex = readVaruint32(Ptr);
641  break;
643  NumImportedGlobals++;
644  Im.Global.Type = readVarint7(Ptr);
645  Im.Global.Mutable = readVaruint1(Ptr);
646  break;
648  Im.Memory = readLimits(Ptr);
649  break;
651  Im.Table = readTable(Ptr);
653  return make_error<GenericBinaryError>("Invalid table element type",
655  break;
656  default:
657  return make_error<GenericBinaryError>(
658  "Unexpected import kind", object_error::parse_failed);
659  }
660  Imports.push_back(Im);
661  }
662  if (Ptr != End)
663  return make_error<GenericBinaryError>("Import section ended prematurely",
665  return Error::success();
666 }
667 
668 Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) {
669  uint32_t Count = readVaruint32(Ptr);
670  FunctionTypes.reserve(Count);
671  while (Count--) {
672  FunctionTypes.push_back(readVaruint32(Ptr));
673  }
674  if (Ptr != End)
675  return make_error<GenericBinaryError>("Function section ended prematurely",
677  return Error::success();
678 }
679 
680 Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) {
681  uint32_t Count = readVaruint32(Ptr);
682  Tables.reserve(Count);
683  while (Count--) {
684  Tables.push_back(readTable(Ptr));
685  if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) {
686  return make_error<GenericBinaryError>("Invalid table element type",
688  }
689  }
690  if (Ptr != End)
691  return make_error<GenericBinaryError>("Table section ended prematurely",
693  return Error::success();
694 }
695 
696 Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) {
697  uint32_t Count = readVaruint32(Ptr);
698  Memories.reserve(Count);
699  while (Count--) {
700  Memories.push_back(readLimits(Ptr));
701  }
702  if (Ptr != End)
703  return make_error<GenericBinaryError>("Memory section ended prematurely",
705  return Error::success();
706 }
707 
708 Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) {
709  uint32_t Count = readVaruint32(Ptr);
710  Globals.reserve(Count);
711  while (Count--) {
712  wasm::WasmGlobal Global;
713  Global.Index = NumImportedGlobals + Globals.size();
714  Global.Type.Type = readVarint7(Ptr);
715  Global.Type.Mutable = readVaruint1(Ptr);
716  if (Error Err = readInitExpr(Global.InitExpr, Ptr))
717  return Err;
718  Globals.push_back(Global);
719  }
720  if (Ptr != End)
721  return make_error<GenericBinaryError>("Global section ended prematurely",
723  return Error::success();
724 }
725 
726 Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) {
727  uint32_t Count = readVaruint32(Ptr);
728  Exports.reserve(Count);
729  for (uint32_t i = 0; i < Count; i++) {
730  wasm::WasmExport Ex;
731  Ex.Name = readString(Ptr);
732  Ex.Kind = readUint8(Ptr);
733  Ex.Index = readVaruint32(Ptr);
734  switch (Ex.Kind) {
736  if (!isValidFunctionIndex(Ex.Index))
737  return make_error<GenericBinaryError>("Invalid function export",
739  break;
741  if (Ex.Index >= Globals.size() + NumImportedGlobals)
742  return make_error<GenericBinaryError>("Invalid global export",
744  break;
745  }
748  break;
749  default:
750  return make_error<GenericBinaryError>(
751  "Unexpected export kind", object_error::parse_failed);
752  }
753  Exports.push_back(Ex);
754  }
755  if (Ptr != End)
756  return make_error<GenericBinaryError>("Export section ended prematurely",
758  return Error::success();
759 }
760 
761 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
762  return Index < FunctionTypes.size() + NumImportedFunctions;
763 }
764 
765 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
766  return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
767 }
768 
769 wasm::WasmFunction& WasmObjectFile::getDefinedFunction(uint32_t Index) {
770  assert(isDefinedFunctionIndex(Index));
771  return Functions[Index - NumImportedFunctions];
772 }
773 
774 Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
775  StartFunction = readVaruint32(Ptr);
776  if (!isValidFunctionIndex(StartFunction))
777  return make_error<GenericBinaryError>("Invalid start function",
779  return Error::success();
780 }
781 
782 Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) {
783  CodeSection = Sections.size();
784  const uint8_t *CodeSectionStart = Ptr;
785  uint32_t FunctionCount = readVaruint32(Ptr);
786  if (FunctionCount != FunctionTypes.size()) {
787  return make_error<GenericBinaryError>("Invalid function count",
789  }
790 
791  while (FunctionCount--) {
793  const uint8_t *FunctionStart = Ptr;
794  uint32_t Size = readVaruint32(Ptr);
795  const uint8_t *FunctionEnd = Ptr + Size;
796 
797  Function.Index = NumImportedFunctions + Functions.size();
798  Function.CodeSectionOffset = FunctionStart - CodeSectionStart;
799  Function.Size = FunctionEnd - FunctionStart;
800 
801  uint32_t NumLocalDecls = readVaruint32(Ptr);
802  Function.Locals.reserve(NumLocalDecls);
803  while (NumLocalDecls--) {
804  wasm::WasmLocalDecl Decl;
805  Decl.Count = readVaruint32(Ptr);
806  Decl.Type = readVarint7(Ptr);
807  Function.Locals.push_back(Decl);
808  }
809 
810  uint32_t BodySize = FunctionEnd - Ptr;
811  Function.Body = ArrayRef<uint8_t>(Ptr, BodySize);
812  Ptr += BodySize;
813  assert(Ptr == FunctionEnd);
814  Functions.push_back(Function);
815  }
816  if (Ptr != End)
817  return make_error<GenericBinaryError>("Code section ended prematurely",
819  return Error::success();
820 }
821 
822 Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) {
823  uint32_t Count = readVaruint32(Ptr);
824  ElemSegments.reserve(Count);
825  while (Count--) {
826  wasm::WasmElemSegment Segment;
827  Segment.TableIndex = readVaruint32(Ptr);
828  if (Segment.TableIndex != 0) {
829  return make_error<GenericBinaryError>("Invalid TableIndex",
831  }
832  if (Error Err = readInitExpr(Segment.Offset, Ptr))
833  return Err;
834  uint32_t NumElems = readVaruint32(Ptr);
835  while (NumElems--) {
836  Segment.Functions.push_back(readVaruint32(Ptr));
837  }
838  ElemSegments.push_back(Segment);
839  }
840  if (Ptr != End)
841  return make_error<GenericBinaryError>("Elem section ended prematurely",
843  return Error::success();
844 }
845 
846 Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) {
847  DataSection = Sections.size();
848  const uint8_t *Start = Ptr;
849  uint32_t Count = readVaruint32(Ptr);
850  DataSegments.reserve(Count);
851  while (Count--) {
852  WasmSegment Segment;
853  Segment.Data.MemoryIndex = readVaruint32(Ptr);
854  if (Error Err = readInitExpr(Segment.Data.Offset, Ptr))
855  return Err;
856  uint32_t Size = readVaruint32(Ptr);
857  Segment.Data.Content = ArrayRef<uint8_t>(Ptr, Size);
858  Segment.Data.Alignment = 0;
859  Segment.Data.Flags = 0;
860  Segment.SectionOffset = Ptr - Start;
861  Ptr += Size;
862  DataSegments.push_back(Segment);
863  }
864  if (Ptr != End)
865  return make_error<GenericBinaryError>("Data section ended prematurely",
867  return Error::success();
868 }
869 
870 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
871  return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data());
872 }
873 
875  return Header;
876 }
877 
878 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
879 
881  uint32_t Result = SymbolRef::SF_None;
882  const WasmSymbol &Sym = getWasmSymbol(Symb);
883 
884  DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
885  if (Sym.isBindingWeak())
886  Result |= SymbolRef::SF_Weak;
887  if (!Sym.isBindingLocal())
888  Result |= SymbolRef::SF_Global;
889  if (Sym.isHidden())
890  Result |= SymbolRef::SF_Hidden;
891 
892  switch (Sym.Type) {
895  break;
897  Result |= SymbolRef::SF_Executable;
898  break;
900  Result |= SymbolRef::SF_Undefined;
901  break;
903  break;
904  }
905 
906  return Result;
907 }
908 
911  Ref.d.a = 0;
912  return BasicSymbolRef(Ref, this);
913 }
914 
917  Ref.d.a = Symbols.size();
918  return BasicSymbolRef(Ref, this);
919 }
920 
922  return Symbols[Symb.d.a];
923 }
924 
925 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
926  return getWasmSymbol(Symb.getRawDataRefImpl());
927 }
928 
930  return getWasmSymbol(Symb).Name;
931 }
932 
934  return getSymbolValue(Symb);
935 }
936 
937 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const {
938  switch (Sym.Type) {
942  return Sym.ElementIndex;
944  uint32_t GlobalIndex = Sym.ElementIndex - NumImportedGlobals;
945  assert(GlobalIndex < Globals.size());
946  const wasm::WasmGlobal &Global = Globals[GlobalIndex];
947  // WasmSymbols correspond only to I32_CONST globals
948  assert(Global.InitExpr.Opcode == wasm::WASM_OPCODE_I32_CONST);
949  return Global.InitExpr.Value.Int32;
950  }
951  }
952  llvm_unreachable("invalid symbol type");
953 }
954 
956  return getWasmSymbolValue(getWasmSymbol(Symb));
957 }
958 
960  llvm_unreachable("not yet implemented");
961  return 0;
962 }
963 
965  llvm_unreachable("not yet implemented");
966  return 0;
967 }
968 
971  const WasmSymbol &Sym = getWasmSymbol(Symb);
972 
973  switch (Sym.Type) {
976  return SymbolRef::ST_Function;
979  return SymbolRef::ST_Data;
980  }
981 
982  llvm_unreachable("Unknown WasmSymbol::SymbolType");
983  return SymbolRef::ST_Other;
984 }
985 
989  const WasmSymbol& Sym = getWasmSymbol(Symb);
991  Ref.d.a = DataSection;
993  Ref.d.a = CodeSection;
994  else
995  return section_end();
996  return section_iterator(SectionRef(Ref, this));
997 }
998 
999 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1000 
1002  StringRef &Res) const {
1003  const WasmSection &S = Sections[Sec.d.a];
1004 #define ECase(X) \
1005  case wasm::WASM_SEC_##X: \
1006  Res = #X; \
1007  break
1008  switch (S.Type) {
1009  ECase(TYPE);
1010  ECase(IMPORT);
1011  ECase(FUNCTION);
1012  ECase(TABLE);
1013  ECase(MEMORY);
1014  ECase(GLOBAL);
1015  ECase(EXPORT);
1016  ECase(START);
1017  ECase(ELEM);
1018  ECase(CODE);
1019  ECase(DATA);
1020  case wasm::WASM_SEC_CUSTOM:
1021  Res = S.Name;
1022  break;
1023  default:
1025  }
1026 #undef ECase
1027  return std::error_code();
1028 }
1029 
1030 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1031 
1033  return Sec.d.a;
1034 }
1035 
1037  const WasmSection &S = Sections[Sec.d.a];
1038  return S.Content.size();
1039 }
1040 
1042  StringRef &Res) const {
1043  const WasmSection &S = Sections[Sec.d.a];
1044  // This will never fail since wasm sections can never be empty (user-sections
1045  // must have a name and non-user sections each have a defined structure).
1046  Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
1047  S.Content.size());
1048  return std::error_code();
1049 }
1050 
1052  return 1;
1053 }
1054 
1056  return false;
1057 }
1058 
1060  return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1061 }
1062 
1064  return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1065 }
1066 
1067 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1068 
1069 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1070 
1071 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1072 
1074  DataRefImpl RelocRef;
1075  RelocRef.d.a = Ref.d.a;
1076  RelocRef.d.b = 0;
1077  return relocation_iterator(RelocationRef(RelocRef, this));
1078 }
1079 
1081  const WasmSection &Sec = getWasmSection(Ref);
1082  DataRefImpl RelocRef;
1083  RelocRef.d.a = Ref.d.a;
1084  RelocRef.d.b = Sec.Relocations.size();
1085  return relocation_iterator(RelocationRef(RelocRef, this));
1086 }
1087 
1089  Rel.d.b++;
1090 }
1091 
1093  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1094  return Rel.Offset;
1095 }
1096 
1098  llvm_unreachable("not yet implemented");
1099  SymbolRef Ref;
1100  return symbol_iterator(Ref);
1101 }
1102 
1104  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1105  return Rel.Type;
1106 }
1107 
1109  DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1110  const wasm::WasmRelocation& Rel = getWasmRelocation(Ref);
1111  StringRef Res = "Unknown";
1112 
1113 #define WASM_RELOC(name, value) \
1114  case wasm::name: \
1115  Res = #name; \
1116  break;
1117 
1118  switch (Rel.Type) {
1119 #include "llvm/BinaryFormat/WasmRelocs.def"
1120  }
1121 
1122 #undef WASM_RELOC
1123 
1124  Result.append(Res.begin(), Res.end());
1125 }
1126 
1128  DataRefImpl Ref;
1129  Ref.d.a = 0;
1130  return section_iterator(SectionRef(Ref, this));
1131 }
1132 
1134  DataRefImpl Ref;
1135  Ref.d.a = Sections.size();
1136  return section_iterator(SectionRef(Ref, this));
1137 }
1138 
1139 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1140 
1142 
1144 
1146  return SubtargetFeatures();
1147 }
1148 
1150  return HasLinkingSection;
1151 }
1152 
1154  assert(Ref.d.a < Sections.size());
1155  return Sections[Ref.d.a];
1156 }
1157 
1158 const WasmSection &
1160  return getWasmSection(Section.getRawDataRefImpl());
1161 }
1162 
1163 const wasm::WasmRelocation &
1165  return getWasmRelocation(Ref.getRawDataRefImpl());
1166 }
1167 
1168 const wasm::WasmRelocation &
1170  assert(Ref.d.a < Sections.size());
1171  const WasmSection& Sec = Sections[Ref.d.a];
1172  assert(Ref.d.b < Sec.Relocations.size());
1173  return Sec.Relocations[Ref.d.b];
1174 }
bool isSectionText(DataRefImpl Sec) const override
uint64_t getRelocationType(DataRefImpl Rel) const override
bool empty() const
Definition: Function.h:640
std::vector< WasmInitFunc > InitFunctions
Definition: Wasm.h:141
uint64_t getSectionAddress(DataRefImpl Sec) const override
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override
union llvm::wasm::WasmInitExpr::@132 Value
StringRef getFileFormatName() const override
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
uint64_t getSectionSize(DataRefImpl Sec) const override
#define VARINT7_MIN
static uint8_t readVaruint7(const uint8_t *&Ptr)
section_iterator section_begin() const override
friend class SectionRef
Definition: ObjectFile.h:222
const WasmSymbol & getWasmSymbol(const DataRefImpl &Symb) const
WasmGlobalType Type
Definition: Wasm.h:75
Implements a dense probed hash-table based set.
Definition: DenseSet.h:221
static Error readInitExpr(wasm::WasmInitExpr &Expr, const uint8_t *&Ptr)
uint32_t SectionOffset
Definition: Wasm.h:125
static wasm::WasmLimits readLimits(const uint8_t *&Ptr)
iterator find(StringRef Key)
Definition: StringMap.h:335
This class is the base class for all object file types.
Definition: ObjectFile.h:190
uint8_t getBytesInAddress() const override
The number of bytes used to represent an address in this object file format.
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override
std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override
std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override
static StringRef readString(const uint8_t *&Ptr)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:128
void getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl< char > &Result) const override
Export information to summary.
static int64_t readVarint64(const uint8_t *&Ptr)
StringRef Name
Definition: Wasm.h:49
std::vector< wasm::WasmRelocation > Relocations
Definition: Wasm.h:121
#define VARUINT7_MAX
uint64_t getRelocationOffset(DataRefImpl Rel) const override
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
uint32_t getSymbolAlignment(DataRefImpl Symb) const override
DataRefImpl getRawDataRefImpl() const
Definition: SymbolicFile.h:205
static int32_t readFloat32(const uint8_t *&Ptr)
WasmTable Table
Definition: Wasm.h:86
int64_t decodeSLEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a SLEB128 value.
Definition: LEB128.h:162
This is a value type class that represents a single relocation in the list of relocations in the obje...
Definition: ObjectFile.h:52
static Error readSection(WasmSection &Section, const uint8_t *&Ptr, const uint8_t *Start, const uint8_t *Eof)
StringRef Module
Definition: Wasm.h:80
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
static int64_t readLEB128(const uint8_t *&Ptr)
const uint32_t WasmVersion
Definition: Wasm.h:26
ArrayRef< uint8_t > Content
Definition: Wasm.h:109
content_iterator< SectionRef > section_iterator
Definition: ObjectFile.h:48
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:267
ArrayRef< uint8_t > Body
Definition: Wasm.h:99
wasm::WasmDataSegment Data
Definition: Wasm.h:126
void setAltIndex(uint32_t Index)
Definition: Wasm.h:64
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:133
static uint32_t readVaruint32(const uint8_t *&Ptr)
uint32_t Initial
Definition: Wasm.h:48
bool isSectionBitcode(DataRefImpl Sec) const override
Expected< SymbolRef::Type > getSymbolType(DataRefImpl Symb) const override
Triple::ArchType getArch() const override
uint64_t getSectionIndex(DataRefImpl Sec) const override
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:598
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&... Args)
Emplace a new element for the specified key into the map if the key isn&#39;t already in the map...
Definition: StringMap.h:397
uint32_t SigIndex
Definition: Wasm.h:84
WasmLimits Memory
Definition: Wasm.h:87
void moveSectionNext(DataRefImpl &Sec) const override
bool isRelocatableObject() const override
True if this is a relocatable object (.o/.obj).
std::vector< uint32_t > Functions
Definition: Wasm.h:119
bool isBindingLocal() const
Definition: Wasm.h:88
uint32_t Kind
Definition: Wasm.h:82
static int64_t readFloat64(const uint8_t *&Ptr)
Import information from summary.
ArrayRef< uint8_t > Content
Definition: Wasm.h:120
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:149
uint32_t Flags
Definition: Wasm.h:47
section_iterator section_end() const override
static uint8_t readOpcode(const uint8_t *&Ptr)
uint32_t CodeSectionOffset
Definition: Wasm.h:100
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a ULEB128 value.
Definition: LEB128.h:129
static int32_t readVarint32(const uint8_t *&Ptr)
static const unsigned End
WasmInitExpr Offset
Definition: Wasm.h:108
const wasm::WasmRelocation & getWasmRelocation(const RelocationRef &Ref) const
uint64_t getSectionAlignment(DataRefImpl Sec) const override
bool isSectionBSS(DataRefImpl Sec) const override
static uint8_t readVaruint1(const uint8_t *&Ptr)
DataRefImpl getRawDataRefImpl() const
Definition: ObjectFile.h:457
bool isSectionData(DataRefImpl Sec) const override
uint32_t Kind
Definition: Wasm.h:42
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::pair< typename base::iterator, bool > insert(StringRef Key)
Definition: StringSet.h:38
const T * data() const
Definition: ArrayRef.h:146
basic_symbol_iterator symbol_begin() const override
static Expected< std::unique_ptr< WasmObjectFile > > createWasmObjectFile(MemoryBufferRef Object)
struct llvm::object::DataRefImpl::@259 d
SubtargetFeatures getFeatures() const override
static int8_t readVarint7(const uint8_t *&Ptr)
bool isSectionCompressed(DataRefImpl Sec) const override
static ErrorSuccess success()
Create a success value.
Definition: Error.h:313
static uint64_t readULEB128(const uint8_t *&Ptr)
friend class RelocationRef
Definition: ObjectFile.h:246
WasmInitExpr InitExpr
Definition: Wasm.h:76
void moveSymbolNext(DataRefImpl &Symb) const override
SymbolType Type
Definition: Wasm.h:50
uint64_t getSymbolValue(DataRefImpl Symb) const
Definition: ObjectFile.cpp:51
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
MemoryBufferRef Data
Definition: Binary.h:37
Manages the enabling and disabling of subtarget specific features.
const wasm::WasmObjectHeader & getHeader() const
Helper for Errors used as out-parameters.
Definition: Error.h:1002
This is a value type class that represents a single symbol in the list of symbols in the object file...
Definition: ObjectFile.h:129
iterator begin() const
Definition: StringRef.h:106
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:396
StringRef Comdat
Definition: Wasm.h:103
uint32_t ElementIndex
Definition: Wasm.h:54
WasmLimits Limits
Definition: Wasm.h:54
WasmGlobalType Global
Definition: Wasm.h:85
Expected< StringRef > getSymbolName(DataRefImpl Symb) const override
void moveRelocationNext(DataRefImpl &Rel) const override
int32_t ElemType
Definition: Wasm.h:53
uint32_t read32le(const void *P)
Definition: Endian.h:369
bool isHidden() const
Definition: Wasm.h:96
This is a value type class that represents a single symbol in the list of symbols in the object file...
Definition: SymbolicFile.h:99
static wasm::WasmTable readTable(const uint8_t *&Ptr)
Expected< uint64_t > getSymbolAddress(DataRefImpl Symb) const override
uint32_t Index
Definition: Wasm.h:43
static uint32_t readUint32(const uint8_t *&Ptr)
relocation_iterator section_rel_begin(DataRefImpl Sec) const override
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::vector< int32_t > ParamTypes
Definition: Wasm.h:36
constexpr char Size[]
Key for Kernel::Arg::Metadata::mSize.
uint32_t Index
Definition: Wasm.h:74
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
The access may reference the value stored in memory.
content_iterator< RelocationRef > relocation_iterator
Definition: ObjectFile.h:77
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition: StringSet.h:28
#define DEBUG(X)
Definition: Debug.h:118
StringRef Name
Definition: Wasm.h:41
const WasmSection & getWasmSection(const SectionRef &Section) const
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
bool isSectionVirtual(DataRefImpl Sec) const override
uint32_t FunctionIndex
Definition: Wasm.h:131
Expected< section_iterator > getSymbolSection(DataRefImpl Symb) const override
uint32_t getSymbolFlags(DataRefImpl Symb) const override
static uint8_t readUint8(const uint8_t *&Ptr)
iterator end() const
Definition: StringRef.h:108
std::vector< WasmLocalDecl > Locals
Definition: Wasm.h:98
bool isBindingWeak() const
Definition: Wasm.h:80
StringRef getData() const
Definition: Binary.cpp:39
WasmInitExpr Offset
Definition: Wasm.h:118
uint32_t Maximum
Definition: Wasm.h:49
#define ECase(X)
iterator end()
Definition: StringMap.h:320
relocation_iterator section_rel_end(DataRefImpl Sec) const override
DataRefImpl getRawDataRefImpl() const
Definition: ObjectFile.h:495
StringRef Field
Definition: Wasm.h:81
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:81
WasmObjectFile(MemoryBufferRef Object, Error &Err)
basic_symbol_iterator symbol_end() const override