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