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