LLVM  8.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 
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)
53 #endif
54 
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");
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 
162  WasmObjectFile::ReadContext &Ctx) {
163  Expr.Opcode = readOpcode(Ctx);
164 
165  switch (Expr.Opcode) {
167  Expr.Value.Int32 = readVarint32(Ctx);
168  break;
170  Expr.Value.Int64 = readVarint64(Ctx);
171  break;
173  Expr.Value.Float32 = readFloat32(Ctx);
174  break;
176  Expr.Value.Float64 = readFloat64(Ctx);
177  break;
179  Expr.Value.Global = readULEB128(Ctx);
180  break;
181  default:
182  return make_error<GenericBinaryError>("Invalid opcode in init_expr",
184  }
185 
186  uint8_t EndOpcode = readOpcode(Ctx);
187  if (EndOpcode != wasm::WASM_OPCODE_END) {
188  return make_error<GenericBinaryError>("Invalid init_expr",
190  }
191  return Error::success();
192 }
193 
194 static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
196  Result.Flags = readVaruint1(Ctx);
197  Result.Initial = readVaruint32(Ctx);
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",
219  if (Ctx.Ptr + Size > Ctx.End)
220  return make_error<StringError>("Section too large",
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 
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",
257  return;
258  }
259 
260  Header.Version = readUint32(Ctx);
261  if (Header.Version != wasm::WasmVersion) {
262  Err = make_error<StringError>("Bad version number",
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) {
285  return parseCustomSection(Sec, Ctx);
286  case wasm::WASM_SEC_TYPE:
287  return parseTypeSection(Ctx);
289  return parseImportSection(Ctx);
291  return parseFunctionSection(Ctx);
293  return parseTableSection(Ctx);
295  return parseMemorySection(Ctx);
297  return parseGlobalSection(Ctx);
299  return parseExportSection(Ctx);
301  return parseStartSection(Ctx);
302  case wasm::WASM_SEC_ELEM:
303  return parseElemSection(Ctx);
304  case wasm::WASM_SEC_CODE:
305  return parseCodeSection(Ctx);
306  case wasm::WASM_SEC_DATA:
307  return parseDataSection(Ctx);
308  default:
309  return make_error<GenericBinaryError>("Bad section type",
311  }
312 }
313 
314 Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
316  if (Functions.size() != FunctionTypes.size()) {
317  return make_error<GenericBinaryError>("Names must come after code section",
319  }
320 
321  while (Ctx.Ptr < Ctx.End) {
322  uint8_t Type = readUint8(Ctx);
323  uint32_t Size = readVaruint32(Ctx);
324  const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
325  switch (Type) {
327  uint32_t Count = readVaruint32(Ctx);
328  while (Count--) {
330  if (!Seen.insert(Index).second)
331  return make_error<GenericBinaryError>("Function named more than once",
333  StringRef Name = readString(Ctx);
334  if (!isValidFunctionIndex(Index) || Name.empty())
335  return make_error<GenericBinaryError>("Invalid name entry",
337  DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
338  if (isDefinedFunctionIndex(Index))
339  getDefinedFunction(Index).DebugName = Name;
340  }
341  break;
342  }
343  // Ignore local names for now
345  default:
346  Ctx.Ptr += Size;
347  break;
348  }
349  if (Ctx.Ptr != SubSectionEnd)
350  return make_error<GenericBinaryError>(
351  "Name sub-section ended prematurely", object_error::parse_failed);
352  }
353 
354  if (Ctx.Ptr != Ctx.End)
355  return make_error<GenericBinaryError>("Name section ended prematurely",
357  return Error::success();
358 }
359 
360 Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
361  HasLinkingSection = true;
362  if (Functions.size() != FunctionTypes.size()) {
363  return make_error<GenericBinaryError>(
364  "Linking data must come after code section",
366  }
367 
368  LinkingData.Version = readVaruint32(Ctx);
369  if (LinkingData.Version != wasm::WasmMetadataVersion) {
370  return make_error<GenericBinaryError>(
371  "Unexpected metadata version: " + Twine(LinkingData.Version) +
372  " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
374  }
375 
376  const uint8_t *OrigEnd = Ctx.End;
377  while (Ctx.Ptr < OrigEnd) {
378  Ctx.End = OrigEnd;
379  uint8_t Type = readUint8(Ctx);
380  uint32_t Size = readVaruint32(Ctx);
381  LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
382  << "\n");
383  Ctx.End = Ctx.Ptr + Size;
384  switch (Type) {
386  if (Error Err = parseLinkingSectionSymtab(Ctx))
387  return Err;
388  break;
390  uint32_t Count = readVaruint32(Ctx);
391  if (Count > DataSegments.size())
392  return make_error<GenericBinaryError>("Too many segment names",
394  for (uint32_t i = 0; i < Count; i++) {
395  DataSegments[i].Data.Name = readString(Ctx);
396  DataSegments[i].Data.Alignment = readVaruint32(Ctx);
397  DataSegments[i].Data.Flags = readVaruint32(Ctx);
398  }
399  break;
400  }
401  case wasm::WASM_INIT_FUNCS: {
402  uint32_t Count = readVaruint32(Ctx);
403  LinkingData.InitFunctions.reserve(Count);
404  for (uint32_t i = 0; i < Count; i++) {
406  Init.Priority = readVaruint32(Ctx);
407  Init.Symbol = readVaruint32(Ctx);
408  if (!isValidFunctionSymbol(Init.Symbol))
409  return make_error<GenericBinaryError>("Invalid function symbol: " +
410  Twine(Init.Symbol),
412  LinkingData.InitFunctions.emplace_back(Init);
413  }
414  break;
415  }
417  if (Error Err = parseLinkingSectionComdat(Ctx))
418  return Err;
419  break;
420  default:
421  Ctx.Ptr += Size;
422  break;
423  }
424  if (Ctx.Ptr != Ctx.End)
425  return make_error<GenericBinaryError>(
426  "Linking sub-section ended prematurely", object_error::parse_failed);
427  }
428  if (Ctx.Ptr != OrigEnd)
429  return make_error<GenericBinaryError>("Linking section ended prematurely",
431  return Error::success();
432 }
433 
434 Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
435  uint32_t Count = readVaruint32(Ctx);
436  LinkingData.SymbolTable.reserve(Count);
437  Symbols.reserve(Count);
438  StringSet<> SymbolNames;
439 
440  std::vector<wasm::WasmImport *> ImportedGlobals;
441  std::vector<wasm::WasmImport *> ImportedFunctions;
442  ImportedGlobals.reserve(Imports.size());
443  ImportedFunctions.reserve(Imports.size());
444  for (auto &I : Imports) {
445  if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
446  ImportedFunctions.emplace_back(&I);
447  else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
448  ImportedGlobals.emplace_back(&I);
449  }
450 
451  while (Count--) {
453  const wasm::WasmSignature *FunctionType = nullptr;
454  const wasm::WasmGlobalType *GlobalType = nullptr;
455 
456  Info.Kind = readUint8(Ctx);
457  Info.Flags = readVaruint32(Ctx);
458  bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
459 
460  switch (Info.Kind) {
462  Info.ElementIndex = readVaruint32(Ctx);
463  if (!isValidFunctionIndex(Info.ElementIndex) ||
464  IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
465  return make_error<GenericBinaryError>("invalid function symbol index",
467  if (IsDefined) {
468  Info.Name = readString(Ctx);
469  unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
470  FunctionType = &Signatures[FunctionTypes[FuncIndex]];
471  wasm::WasmFunction &Function = Functions[FuncIndex];
472  if (Function.SymbolName.empty())
473  Function.SymbolName = Info.Name;
474  } else {
475  wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
476  FunctionType = &Signatures[Import.SigIndex];
477  Info.Name = Import.Field;
478  Info.Module = Import.Module;
479  }
480  break;
481 
483  Info.ElementIndex = readVaruint32(Ctx);
484  if (!isValidGlobalIndex(Info.ElementIndex) ||
485  IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
486  return make_error<GenericBinaryError>("invalid global symbol index",
488  if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
490  return make_error<GenericBinaryError>("undefined weak global symbol",
492  if (IsDefined) {
493  Info.Name = readString(Ctx);
494  unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
495  wasm::WasmGlobal &Global = Globals[GlobalIndex];
496  GlobalType = &Global.Type;
497  if (Global.SymbolName.empty())
498  Global.SymbolName = Info.Name;
499  } else {
500  wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
501  Info.Name = Import.Field;
502  GlobalType = &Import.Global;
503  }
504  break;
505 
507  Info.Name = readString(Ctx);
508  if (IsDefined) {
510  if (Index >= DataSegments.size())
511  return make_error<GenericBinaryError>("invalid data symbol index",
514  uint32_t Size = readVaruint32(Ctx);
515  if (Offset + Size > DataSegments[Index].Data.Content.size())
516  return make_error<GenericBinaryError>("invalid data symbol offset",
519  }
520  break;
521 
523  if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
525  return make_error<GenericBinaryError>(
526  "Section symbols must have local binding",
528  Info.ElementIndex = readVaruint32(Ctx);
529  // Use somewhat unique section name as symbol name.
530  StringRef SectionName = Sections[Info.ElementIndex].Name;
531  Info.Name = SectionName;
532  break;
533  }
534 
535  default:
536  return make_error<GenericBinaryError>("Invalid symbol type",
538  }
539 
540  if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
542  !SymbolNames.insert(Info.Name).second)
543  return make_error<GenericBinaryError>("Duplicate symbol name " +
544  Twine(Info.Name),
546  LinkingData.SymbolTable.emplace_back(Info);
547  Symbols.emplace_back(LinkingData.SymbolTable.back(), FunctionType,
548  GlobalType);
549  LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
550  }
551 
552  return Error::success();
553 }
554 
555 Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
556  uint32_t ComdatCount = readVaruint32(Ctx);
557  StringSet<> ComdatSet;
558  for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
559  StringRef Name = readString(Ctx);
560  if (Name.empty() || !ComdatSet.insert(Name).second)
561  return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
562  Twine(Name),
564  LinkingData.Comdats.emplace_back(Name);
565  uint32_t Flags = readVaruint32(Ctx);
566  if (Flags != 0)
567  return make_error<GenericBinaryError>("Unsupported COMDAT flags",
569 
570  uint32_t EntryCount = readVaruint32(Ctx);
571  while (EntryCount--) {
572  unsigned Kind = readVaruint32(Ctx);
573  unsigned Index = readVaruint32(Ctx);
574  switch (Kind) {
575  default:
576  return make_error<GenericBinaryError>("Invalid COMDAT entry type",
579  if (Index >= DataSegments.size())
580  return make_error<GenericBinaryError>(
581  "COMDAT data index out of range", object_error::parse_failed);
582  if (DataSegments[Index].Data.Comdat != UINT32_MAX)
583  return make_error<GenericBinaryError>("Data segment in two COMDATs",
585  DataSegments[Index].Data.Comdat = ComdatIndex;
586  break;
588  if (!isDefinedFunctionIndex(Index))
589  return make_error<GenericBinaryError>(
590  "COMDAT function index out of range", object_error::parse_failed);
591  if (getDefinedFunction(Index).Comdat != UINT32_MAX)
592  return make_error<GenericBinaryError>("Function in two COMDATs",
594  getDefinedFunction(Index).Comdat = ComdatIndex;
595  break;
596  }
597  }
598  }
599  return Error::success();
600 }
601 
602 Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
603  uint32_t SectionIndex = readVaruint32(Ctx);
604  if (SectionIndex >= Sections.size())
605  return make_error<GenericBinaryError>("Invalid section index",
607  WasmSection &Section = Sections[SectionIndex];
608  uint32_t RelocCount = readVaruint32(Ctx);
609  uint32_t EndOffset = Section.Content.size();
610  uint32_t PreviousOffset = 0;
611  while (RelocCount--) {
612  wasm::WasmRelocation Reloc = {};
613  Reloc.Type = readVaruint32(Ctx);
614  Reloc.Offset = readVaruint32(Ctx);
615  if (Reloc.Offset < PreviousOffset)
616  return make_error<GenericBinaryError>("Relocations not in offset order",
618  PreviousOffset = Reloc.Offset;
619  Reloc.Index = readVaruint32(Ctx);
620  switch (Reloc.Type) {
621  case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
622  case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
623  case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
624  if (!isValidFunctionSymbol(Reloc.Index))
625  return make_error<GenericBinaryError>("Bad relocation function index",
627  break;
628  case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
629  if (Reloc.Index >= Signatures.size())
630  return make_error<GenericBinaryError>("Bad relocation type index",
632  break;
633  case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
634  if (!isValidGlobalSymbol(Reloc.Index))
635  return make_error<GenericBinaryError>("Bad relocation global index",
637  break;
638  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
639  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
640  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
641  if (!isValidDataSymbol(Reloc.Index))
642  return make_error<GenericBinaryError>("Bad relocation data index",
644  Reloc.Addend = readVarint32(Ctx);
645  break;
646  case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
647  if (!isValidFunctionSymbol(Reloc.Index))
648  return make_error<GenericBinaryError>("Bad relocation function index",
650  Reloc.Addend = readVarint32(Ctx);
651  break;
652  case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
653  if (!isValidSectionSymbol(Reloc.Index))
654  return make_error<GenericBinaryError>("Bad relocation section index",
656  Reloc.Addend = readVarint32(Ctx);
657  break;
658  default:
659  return make_error<GenericBinaryError>("Bad relocation type: " +
660  Twine(Reloc.Type),
662  }
663 
664  // Relocations must fit inside the section, and must appear in order. They
665  // also shouldn't overlap a function/element boundary, but we don't bother
666  // to check that.
667  uint64_t Size = 5;
668  if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 ||
669  Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32 ||
670  Reloc.Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32 ||
671  Reloc.Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32)
672  Size = 4;
673  if (Reloc.Offset + Size > EndOffset)
674  return make_error<GenericBinaryError>("Bad relocation offset",
676 
677  Section.Relocations.push_back(Reloc);
678  }
679  if (Ctx.Ptr != Ctx.End)
680  return make_error<GenericBinaryError>("Reloc section ended prematurely",
682  return Error::success();
683 }
684 
685 Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
686  if (Sec.Name == "name") {
687  if (Error Err = parseNameSection(Ctx))
688  return Err;
689  } else if (Sec.Name == "linking") {
690  if (Error Err = parseLinkingSection(Ctx))
691  return Err;
692  } else if (Sec.Name.startswith("reloc.")) {
693  if (Error Err = parseRelocSection(Sec.Name, Ctx))
694  return Err;
695  }
696  return Error::success();
697 }
698 
699 Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
700  uint32_t Count = readVaruint32(Ctx);
701  Signatures.reserve(Count);
702  while (Count--) {
704  uint8_t Form = readUint8(Ctx);
705  if (Form != wasm::WASM_TYPE_FUNC) {
706  return make_error<GenericBinaryError>("Invalid signature type",
708  }
709  uint32_t ParamCount = readVaruint32(Ctx);
710  Sig.Params.reserve(ParamCount);
711  while (ParamCount--) {
712  uint32_t ParamType = readUint8(Ctx);
713  Sig.Params.push_back(wasm::ValType(ParamType));
714  }
715  uint32_t ReturnCount = readVaruint32(Ctx);
716  if (ReturnCount) {
717  if (ReturnCount != 1) {
718  return make_error<GenericBinaryError>(
719  "Multiple return types not supported", object_error::parse_failed);
720  }
722  }
723  Signatures.push_back(std::move(Sig));
724  }
725  if (Ctx.Ptr != Ctx.End)
726  return make_error<GenericBinaryError>("Type section ended prematurely",
728  return Error::success();
729 }
730 
731 Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
732  uint32_t Count = readVaruint32(Ctx);
733  Imports.reserve(Count);
734  for (uint32_t i = 0; i < Count; i++) {
735  wasm::WasmImport Im;
736  Im.Module = readString(Ctx);
737  Im.Field = readString(Ctx);
738  Im.Kind = readUint8(Ctx);
739  switch (Im.Kind) {
741  NumImportedFunctions++;
742  Im.SigIndex = readVaruint32(Ctx);
743  break;
745  NumImportedGlobals++;
746  Im.Global.Type = readUint8(Ctx);
747  Im.Global.Mutable = readVaruint1(Ctx);
748  break;
750  Im.Memory = readLimits(Ctx);
751  break;
753  Im.Table = readTable(Ctx);
755  return make_error<GenericBinaryError>("Invalid table element type",
757  break;
758  default:
759  return make_error<GenericBinaryError>("Unexpected import kind",
761  }
762  Imports.push_back(Im);
763  }
764  if (Ctx.Ptr != Ctx.End)
765  return make_error<GenericBinaryError>("Import section ended prematurely",
767  return Error::success();
768 }
769 
770 Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
771  uint32_t Count = readVaruint32(Ctx);
772  FunctionTypes.reserve(Count);
773  uint32_t NumTypes = Signatures.size();
774  while (Count--) {
775  uint32_t Type = readVaruint32(Ctx);
776  if (Type >= NumTypes)
777  return make_error<GenericBinaryError>("Invalid function type",
779  FunctionTypes.push_back(Type);
780  }
781  if (Ctx.Ptr != Ctx.End)
782  return make_error<GenericBinaryError>("Function section ended prematurely",
784  return Error::success();
785 }
786 
787 Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
788  uint32_t Count = readVaruint32(Ctx);
789  Tables.reserve(Count);
790  while (Count--) {
791  Tables.push_back(readTable(Ctx));
792  if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) {
793  return make_error<GenericBinaryError>("Invalid table element type",
795  }
796  }
797  if (Ctx.Ptr != Ctx.End)
798  return make_error<GenericBinaryError>("Table section ended prematurely",
800  return Error::success();
801 }
802 
803 Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
804  uint32_t Count = readVaruint32(Ctx);
805  Memories.reserve(Count);
806  while (Count--) {
807  Memories.push_back(readLimits(Ctx));
808  }
809  if (Ctx.Ptr != Ctx.End)
810  return make_error<GenericBinaryError>("Memory section ended prematurely",
812  return Error::success();
813 }
814 
815 Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
816  GlobalSection = Sections.size();
817  uint32_t Count = readVaruint32(Ctx);
818  Globals.reserve(Count);
819  while (Count--) {
820  wasm::WasmGlobal Global;
821  Global.Index = NumImportedGlobals + Globals.size();
822  Global.Type.Type = readUint8(Ctx);
823  Global.Type.Mutable = readVaruint1(Ctx);
824  if (Error Err = readInitExpr(Global.InitExpr, Ctx))
825  return Err;
826  Globals.push_back(Global);
827  }
828  if (Ctx.Ptr != Ctx.End)
829  return make_error<GenericBinaryError>("Global section ended prematurely",
831  return Error::success();
832 }
833 
834 Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
835  uint32_t Count = readVaruint32(Ctx);
836  Exports.reserve(Count);
837  for (uint32_t i = 0; i < Count; i++) {
838  wasm::WasmExport Ex;
839  Ex.Name = readString(Ctx);
840  Ex.Kind = readUint8(Ctx);
841  Ex.Index = readVaruint32(Ctx);
842  switch (Ex.Kind) {
844  if (!isValidFunctionIndex(Ex.Index))
845  return make_error<GenericBinaryError>("Invalid function export",
847  break;
849  if (!isValidGlobalIndex(Ex.Index))
850  return make_error<GenericBinaryError>("Invalid global export",
852  break;
855  break;
856  default:
857  return make_error<GenericBinaryError>("Unexpected export kind",
859  }
860  Exports.push_back(Ex);
861  }
862  if (Ctx.Ptr != Ctx.End)
863  return make_error<GenericBinaryError>("Export section ended prematurely",
865  return Error::success();
866 }
867 
868 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
869  return Index < NumImportedFunctions + FunctionTypes.size();
870 }
871 
872 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
873  return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
874 }
875 
876 bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
877  return Index < NumImportedGlobals + Globals.size();
878 }
879 
880 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
881  return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
882 }
883 
884 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
885  return Index < Symbols.size() && Symbols[Index].isTypeFunction();
886 }
887 
888 bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
889  return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
890 }
891 
892 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
893  return Index < Symbols.size() && Symbols[Index].isTypeData();
894 }
895 
896 bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
897  return Index < Symbols.size() && Symbols[Index].isTypeSection();
898 }
899 
900 wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
901  assert(isDefinedFunctionIndex(Index));
902  return Functions[Index - NumImportedFunctions];
903 }
904 
905 wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
906  assert(isDefinedGlobalIndex(Index));
907  return Globals[Index - NumImportedGlobals];
908 }
909 
910 Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
911  StartFunction = readVaruint32(Ctx);
912  if (!isValidFunctionIndex(StartFunction))
913  return make_error<GenericBinaryError>("Invalid start function",
915  return Error::success();
916 }
917 
918 Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
919  CodeSection = Sections.size();
920  uint32_t FunctionCount = readVaruint32(Ctx);
921  if (FunctionCount != FunctionTypes.size()) {
922  return make_error<GenericBinaryError>("Invalid function count",
924  }
925 
926  while (FunctionCount--) {
928  const uint8_t *FunctionStart = Ctx.Ptr;
929  uint32_t Size = readVaruint32(Ctx);
930  const uint8_t *FunctionEnd = Ctx.Ptr + Size;
931 
932  Function.CodeOffset = Ctx.Ptr - FunctionStart;
933  Function.Index = NumImportedFunctions + Functions.size();
934  Function.CodeSectionOffset = FunctionStart - Ctx.Start;
935  Function.Size = FunctionEnd - FunctionStart;
936 
937  uint32_t NumLocalDecls = readVaruint32(Ctx);
938  Function.Locals.reserve(NumLocalDecls);
939  while (NumLocalDecls--) {
940  wasm::WasmLocalDecl Decl;
941  Decl.Count = readVaruint32(Ctx);
942  Decl.Type = readUint8(Ctx);
943  Function.Locals.push_back(Decl);
944  }
945 
946  uint32_t BodySize = FunctionEnd - Ctx.Ptr;
947  Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
948  // This will be set later when reading in the linking metadata section.
949  Function.Comdat = UINT32_MAX;
950  Ctx.Ptr += BodySize;
951  assert(Ctx.Ptr == FunctionEnd);
952  Functions.push_back(Function);
953  }
954  if (Ctx.Ptr != Ctx.End)
955  return make_error<GenericBinaryError>("Code section ended prematurely",
957  return Error::success();
958 }
959 
960 Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
961  uint32_t Count = readVaruint32(Ctx);
962  ElemSegments.reserve(Count);
963  while (Count--) {
964  wasm::WasmElemSegment Segment;
965  Segment.TableIndex = readVaruint32(Ctx);
966  if (Segment.TableIndex != 0) {
967  return make_error<GenericBinaryError>("Invalid TableIndex",
969  }
970  if (Error Err = readInitExpr(Segment.Offset, Ctx))
971  return Err;
972  uint32_t NumElems = readVaruint32(Ctx);
973  while (NumElems--) {
974  Segment.Functions.push_back(readVaruint32(Ctx));
975  }
976  ElemSegments.push_back(Segment);
977  }
978  if (Ctx.Ptr != Ctx.End)
979  return make_error<GenericBinaryError>("Elem section ended prematurely",
981  return Error::success();
982 }
983 
984 Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
985  DataSection = Sections.size();
986  uint32_t Count = readVaruint32(Ctx);
987  DataSegments.reserve(Count);
988  while (Count--) {
989  WasmSegment Segment;
990  Segment.Data.MemoryIndex = readVaruint32(Ctx);
991  if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
992  return Err;
993  uint32_t Size = readVaruint32(Ctx);
994  if (Size > (size_t)(Ctx.End - Ctx.Ptr))
995  return make_error<GenericBinaryError>("Invalid segment size",
997  Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
998  // The rest of these Data fields are set later, when reading in the linking
999  // metadata section.
1000  Segment.Data.Alignment = 0;
1001  Segment.Data.Flags = 0;
1002  Segment.Data.Comdat = UINT32_MAX;
1003  Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1004  Ctx.Ptr += Size;
1005  DataSegments.push_back(Segment);
1006  }
1007  if (Ctx.Ptr != Ctx.End)
1008  return make_error<GenericBinaryError>("Data section ended prematurely",
1010  return Error::success();
1011 }
1012 
1013 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
1014  return reinterpret_cast<const uint8_t *>(getData().data() + Offset);
1015 }
1016 
1018  return Header;
1019 }
1020 
1021 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
1022 
1025  const WasmSymbol &Sym = getWasmSymbol(Symb);
1026 
1027  LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1028  if (Sym.isBindingWeak())
1029  Result |= SymbolRef::SF_Weak;
1030  if (!Sym.isBindingLocal())
1031  Result |= SymbolRef::SF_Global;
1032  if (Sym.isHidden())
1033  Result |= SymbolRef::SF_Hidden;
1034  if (!Sym.isDefined())
1035  Result |= SymbolRef::SF_Undefined;
1036  if (Sym.isTypeFunction())
1037  Result |= SymbolRef::SF_Executable;
1038  return Result;
1039 }
1040 
1042  DataRefImpl Ref;
1043  Ref.d.a = 0;
1044  return BasicSymbolRef(Ref, this);
1045 }
1046 
1048  DataRefImpl Ref;
1049  Ref.d.a = Symbols.size();
1050  return BasicSymbolRef(Ref, this);
1051 }
1052 
1054  return Symbols[Symb.d.a];
1055 }
1056 
1057 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
1058  return getWasmSymbol(Symb.getRawDataRefImpl());
1059 }
1060 
1062  return getWasmSymbol(Symb).Info.Name;
1063 }
1064 
1066  return getSymbolValue(Symb);
1067 }
1068 
1070  switch (Sym.Info.Kind) {
1073  return Sym.Info.ElementIndex;
1075  // The value of a data symbol is the segment offset, plus the symbol
1076  // offset within the segment.
1077  uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1078  const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1080  return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
1081  }
1083  return 0;
1084  }
1085  llvm_unreachable("invalid symbol type");
1086 }
1087 
1089  return getWasmSymbolValue(getWasmSymbol(Symb));
1090 }
1091 
1093  llvm_unreachable("not yet implemented");
1094  return 0;
1095 }
1096 
1098  llvm_unreachable("not yet implemented");
1099  return 0;
1100 }
1101 
1104  const WasmSymbol &Sym = getWasmSymbol(Symb);
1105 
1106  switch (Sym.Info.Kind) {
1108  return SymbolRef::ST_Function;
1110  return SymbolRef::ST_Other;
1112  return SymbolRef::ST_Data;
1114  return SymbolRef::ST_Debug;
1115  }
1116 
1117  llvm_unreachable("Unknown WasmSymbol::SymbolType");
1118  return SymbolRef::ST_Other;
1119 }
1120 
1123  const WasmSymbol &Sym = getWasmSymbol(Symb);
1124  if (Sym.isUndefined())
1125  return section_end();
1126 
1127  DataRefImpl Ref;
1128  switch (Sym.Info.Kind) {
1130  Ref.d.a = CodeSection;
1131  break;
1133  Ref.d.a = GlobalSection;
1134  break;
1136  Ref.d.a = DataSection;
1137  break;
1139  Ref.d.a = Sym.Info.ElementIndex;
1140  break;
1141  }
1142  default:
1143  llvm_unreachable("Unknown WasmSymbol::SymbolType");
1144  }
1145  return section_iterator(SectionRef(Ref, this));
1146 }
1147 
1148 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1149 
1151  StringRef &Res) const {
1152  const WasmSection &S = Sections[Sec.d.a];
1153 #define ECase(X) \
1154  case wasm::WASM_SEC_##X: \
1155  Res = #X; \
1156  break
1157  switch (S.Type) {
1158  ECase(TYPE);
1159  ECase(IMPORT);
1160  ECase(FUNCTION);
1161  ECase(TABLE);
1162  ECase(MEMORY);
1163  ECase(GLOBAL);
1164  ECase(EXPORT);
1165  ECase(START);
1166  ECase(ELEM);
1167  ECase(CODE);
1168  ECase(DATA);
1169  case wasm::WASM_SEC_CUSTOM:
1170  Res = S.Name;
1171  break;
1172  default:
1174  }
1175 #undef ECase
1176  return std::error_code();
1177 }
1178 
1179 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1180 
1182  return Sec.d.a;
1183 }
1184 
1186  const WasmSection &S = Sections[Sec.d.a];
1187  return S.Content.size();
1188 }
1189 
1191  StringRef &Res) const {
1192  const WasmSection &S = Sections[Sec.d.a];
1193  // This will never fail since wasm sections can never be empty (user-sections
1194  // must have a name and non-user sections each have a defined structure).
1195  Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
1196  S.Content.size());
1197  return std::error_code();
1198 }
1199 
1201  return 1;
1202 }
1203 
1205  return false;
1206 }
1207 
1209  return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1210 }
1211 
1213  return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1214 }
1215 
1216 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1217 
1218 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1219 
1220 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1221 
1223  DataRefImpl RelocRef;
1224  RelocRef.d.a = Ref.d.a;
1225  RelocRef.d.b = 0;
1226  return relocation_iterator(RelocationRef(RelocRef, this));
1227 }
1228 
1230  const WasmSection &Sec = getWasmSection(Ref);
1231  DataRefImpl RelocRef;
1232  RelocRef.d.a = Ref.d.a;
1233  RelocRef.d.b = Sec.Relocations.size();
1234  return relocation_iterator(RelocationRef(RelocRef, this));
1235 }
1236 
1238 
1240  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1241  return Rel.Offset;
1242 }
1243 
1245  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1246  if (Rel.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
1247  return symbol_end();
1248  DataRefImpl Sym;
1249  Sym.d.a = Rel.Index;
1250  Sym.d.b = 0;
1251  return symbol_iterator(SymbolRef(Sym, this));
1252 }
1253 
1255  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1256  return Rel.Type;
1257 }
1258 
1260  DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1261  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1262  StringRef Res = "Unknown";
1263 
1264 #define WASM_RELOC(name, value) \
1265  case wasm::name: \
1266  Res = #name; \
1267  break;
1268 
1269  switch (Rel.Type) {
1270 #include "llvm/BinaryFormat/WasmRelocs.def"
1271  }
1272 
1273 #undef WASM_RELOC
1274 
1275  Result.append(Res.begin(), Res.end());
1276 }
1277 
1279  DataRefImpl Ref;
1280  Ref.d.a = 0;
1281  return section_iterator(SectionRef(Ref, this));
1282 }
1283 
1285  DataRefImpl Ref;
1286  Ref.d.a = Sections.size();
1287  return section_iterator(SectionRef(Ref, this));
1288 }
1289 
1290 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1291 
1293 
1295 
1297  return SubtargetFeatures();
1298 }
1299 
1300 bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1301 
1303  assert(Ref.d.a < Sections.size());
1304  return Sections[Ref.d.a];
1305 }
1306 
1307 const WasmSection &
1309  return getWasmSection(Section.getRawDataRefImpl());
1310 }
1311 
1312 const wasm::WasmRelocation &
1314  return getWasmRelocation(Ref.getRawDataRefImpl());
1315 }
1316 
1317 const wasm::WasmRelocation &
1319  assert(Ref.d.a < Sections.size());
1320  const WasmSection &Sec = Sections[Ref.d.a];
1321  assert(Ref.d.b < Sec.Relocations.size());
1322  return Sec.Relocations[Ref.d.b];
1323 }
bool isTypeData() const
Definition: Wasm.h:52
bool isSectionText(DataRefImpl Sec) const override
uint64_t getRelocationType(DataRefImpl Rel) const override
void push_back(const T &Elt)
Definition: SmallVector.h:218
static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx)
std::vector< WasmInitFunc > InitFunctions
Definition: Wasm.h:164
uint64_t getSectionAddress(DataRefImpl Sec) const override
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override
WasmSymbolType
Definition: Wasm.h:240
#define VARUINT1_MAX
friend class SymbolRef
Definition: ObjectFile.h:208
StringRef getFileFormatName() const override
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:139
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
uint64_t getSectionSize(DataRefImpl Sec) const override
static Error readInitExpr(wasm::WasmInitExpr &Expr, WasmObjectFile::ReadContext &Ctx)
section_iterator section_begin() const override
const unsigned WASM_SYMBOL_BINDING_LOCAL
Definition: Wasm.h:252
friend class SectionRef
Definition: ObjectFile.h:222
const WasmSymbol & getWasmSymbol(const DataRefImpl &Symb) const
WasmGlobalType Type
Definition: Wasm.h:73
Implements a dense probed hash-table based set.
Definition: DenseSet.h:250
static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
uint32_t SectionOffset
Definition: Wasm.h:110
const uint32_t WasmMetadataVersion
Definition: Wasm.h:29
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
SmallVector< wasm::ValType, 1 > Returns
Definition: Wasm.h:276
void reserve(size_type N)
Definition: SmallVector.h:376
std::vector< StringRef > Comdats
Definition: Wasm.h:165
std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override
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
StringRef SymbolName
Definition: Wasm.h:102
static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx)
static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx)
const unsigned WASM_SYMBOL_UNDEFINED
Definition: Wasm.h:255
std::vector< wasm::WasmRelocation > Relocations
Definition: Wasm.h:106
amdgpu Simplify well known AMD library false Value Value const Twine & Name
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Definition: Error.h:963
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
WasmTable Table
Definition: Wasm.h:85
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
The access may reference the value stored in memory.
StringRef Module
Definition: Wasm.h:79
uint32_t CodeOffset
Definition: Wasm.h:101
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
#define LLVM_DUMP_METHOD
Definition: Compiler.h:74
const uint32_t WasmVersion
Definition: Wasm.h:27
ArrayRef< uint8_t > Content
Definition: Wasm.h:110
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx)
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
Class to represent function types.
Definition: DerivedTypes.h:103
ArrayRef< uint8_t > Body
Definition: Wasm.h:98
wasm::WasmDataSegment Data
Definition: Wasm.h:111
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:133
uint32_t Initial
Definition: Wasm.h:46
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
uint32_t SigIndex
Definition: Wasm.h:83
WasmLimits Memory
Definition: Wasm.h:86
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:120
static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx)
bool isBindingLocal() const
Definition: Wasm.h:76
static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx)
Import information from summary.
LLVM_DUMP_METHOD void dump() const
ArrayRef< uint8_t > Content
Definition: Wasm.h:105
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
static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx)
section_iterator section_end() const override
uint8_t ElemType
Definition: Wasm.h:51
const unsigned WASM_SYMBOL_BINDING_WEAK
Definition: Wasm.h:251
uint32_t CodeSectionOffset
Definition: Wasm.h:99
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
WasmInitExpr Offset
Definition: Wasm.h:109
const wasm::WasmRelocation & getWasmRelocation(const RelocationRef &Ref) const
uint64_t getSectionAlignment(DataRefImpl Sec) const override
bool isSectionBSS(DataRefImpl Sec) const override
StringRef DebugName
Definition: Wasm.h:103
DataRefImpl getRawDataRefImpl() const
Definition: ObjectFile.h:464
bool isSectionData(DataRefImpl Sec) const override
bool isDefined() const
Definition: Wasm.h:62
#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)
SubtargetFeatures getFeatures() const override
bool isSectionCompressed(DataRefImpl Sec) const override
static ErrorSuccess success()
Create a success value.
Definition: Error.h:327
static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx)
friend class RelocationRef
Definition: ObjectFile.h:246
WasmInitExpr InitExpr
Definition: Wasm.h:74
void moveSymbolNext(DataRefImpl &Symb) const override
uint64_t getSymbolValue(DataRefImpl Symb) const
Definition: ObjectFile.cpp:51
const wasm::WasmSymbolInfo & Info
Definition: Wasm.h:44
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx)
bool isTypeFunction() const
Definition: Wasm.h:48
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
static StringRef readString(WasmObjectFile::ReadContext &Ctx)
MemoryBufferRef Data
Definition: Binary.h:37
Manages the enabling and disabling of subtarget specific features.
union llvm::wasm::WasmInitExpr::@138 Value
const wasm::WasmObjectHeader & getHeader() const
static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx)
Helper for Errors used as out-parameters.
Definition: Error.h:1018
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:394
WasmLimits Limits
Definition: Wasm.h:52
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx)
WasmGlobalType Global
Definition: Wasm.h:84
const unsigned WASM_SYMBOL_BINDING_MASK
Definition: Wasm.h:247
Expected< StringRef > getSymbolName(DataRefImpl Symb) const override
void moveRelocationNext(DataRefImpl &Rel) const override
#define I(x, y, z)
Definition: MD5.cpp:58
uint32_t read32le(const void *P)
Definition: Endian.h:369
bool isHidden() const
Definition: Wasm.h:84
This is a value type class that represents a single symbol in the list of symbols in the object file...
Definition: SymbolicFile.h:99
struct llvm::object::DataRefImpl::@271 d
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx)
uint32_t Size
Definition: Profile.cpp:47
Expected< uint64_t > getSymbolAddress(DataRefImpl Symb) const override
uint32_t Index
Definition: Wasm.h:41
relocation_iterator section_rel_begin(DataRefImpl Sec) const override
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx)
bool isUndefined() const
Definition: Wasm.h:64
WasmDataReference DataRef
Definition: Wasm.h:153
uint32_t Index
Definition: Wasm.h:72
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
content_iterator< RelocationRef > relocation_iterator
Definition: ObjectFile.h:77
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition: StringSet.h:28
const char SectionName[]
Definition: AMDGPUPTNote.h:24
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
StringRef Name
Definition: Wasm.h:39
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
StringRef SymbolName
Definition: Wasm.h:75
Expected< section_iterator > getSymbolSection(DataRefImpl Symb) const override
uint32_t getSymbolFlags(DataRefImpl Symb) const override
#define LLVM_DEBUG(X)
Definition: Debug.h:123
std::vector< WasmSymbolInfo > SymbolTable
Definition: Wasm.h:166
iterator end() const
Definition: StringRef.h:108
std::vector< WasmLocalDecl > Locals
Definition: Wasm.h:97
SmallVector< wasm::ValType, 4 > Params
Definition: Wasm.h:277
bool isBindingWeak() const
Definition: Wasm.h:68
StringRef getData() const
Definition: Binary.cpp:39
WasmInitExpr Offset
Definition: Wasm.h:119
uint32_t Maximum
Definition: Wasm.h:47
#define ECase(X)
relocation_iterator section_rel_end(DataRefImpl Sec) const override
DataRefImpl getRawDataRefImpl() const
Definition: ObjectFile.h:502
StringRef Field
Definition: Wasm.h:80
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)
void print(raw_ostream &Out) const
basic_symbol_iterator symbol_end() const override