LLVM 19.0.0git
WasmObjectFile.cpp
Go to the documentation of this file.
1//===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ADT/ArrayRef.h"
10#include "llvm/ADT/DenseSet.h"
11#include "llvm/ADT/SmallSet.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/ADT/StringSet.h"
16#include "llvm/Object/Binary.h"
17#include "llvm/Object/Error.h"
20#include "llvm/Object/Wasm.h"
21#include "llvm/Support/Endian.h"
22#include "llvm/Support/Error.h"
24#include "llvm/Support/Format.h"
25#include "llvm/Support/LEB128.h"
29#include <algorithm>
30#include <cassert>
31#include <cstdint>
32#include <cstring>
33#include <limits>
34
35#define DEBUG_TYPE "wasm-object"
36
37using namespace llvm;
38using namespace object;
39
41 Out << "Name=" << Info.Name
42 << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
43 << Twine::utohexstr(Info.Flags) << " [";
44 switch (getBinding()) {
45 case wasm::WASM_SYMBOL_BINDING_GLOBAL: Out << "global"; break;
46 case wasm::WASM_SYMBOL_BINDING_LOCAL: Out << "local"; break;
47 case wasm::WASM_SYMBOL_BINDING_WEAK: Out << "weak"; break;
48 }
49 if (isHidden()) {
50 Out << ", hidden";
51 } else {
52 Out << ", default";
53 }
54 Out << "]";
55 if (!isTypeData()) {
56 Out << ", ElemIndex=" << Info.ElementIndex;
57 } else if (isDefined()) {
58 Out << ", Segment=" << Info.DataRef.Segment;
59 Out << ", Offset=" << Info.DataRef.Offset;
60 Out << ", Size=" << Info.DataRef.Size;
61 }
62}
63
64#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
66#endif
67
70 Error Err = Error::success();
71 auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
72 if (Err)
73 return std::move(Err);
74
75 return std::move(ObjectFile);
76}
77
78#define VARINT7_MAX ((1 << 7) - 1)
79#define VARINT7_MIN (-(1 << 7))
80#define VARUINT7_MAX (1 << 7)
81#define VARUINT1_MAX (1)
82
84 if (Ctx.Ptr == Ctx.End)
85 report_fatal_error("EOF while reading uint8");
86 return *Ctx.Ptr++;
87}
88
90 if (Ctx.Ptr + 4 > Ctx.End)
91 report_fatal_error("EOF while reading uint32");
93 Ctx.Ptr += 4;
94 return Result;
95}
96
98 if (Ctx.Ptr + 4 > Ctx.End)
99 report_fatal_error("EOF while reading float64");
100 int32_t Result = 0;
101 memcpy(&Result, Ctx.Ptr, sizeof(Result));
102 Ctx.Ptr += sizeof(Result);
103 return Result;
104}
105
107 if (Ctx.Ptr + 8 > Ctx.End)
108 report_fatal_error("EOF while reading float64");
109 int64_t Result = 0;
110 memcpy(&Result, Ctx.Ptr, sizeof(Result));
111 Ctx.Ptr += sizeof(Result);
112 return Result;
113}
114
116 unsigned Count;
117 const char *Error = nullptr;
118 uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
119 if (Error)
121 Ctx.Ptr += Count;
122 return Result;
123}
124
126 uint32_t StringLen = readULEB128(Ctx);
127 if (Ctx.Ptr + StringLen > Ctx.End)
128 report_fatal_error("EOF while reading string");
129 StringRef Return =
130 StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
131 Ctx.Ptr += StringLen;
132 return Return;
133}
134
136 unsigned Count;
137 const char *Error = nullptr;
138 uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
139 if (Error)
141 Ctx.Ptr += Count;
142 return Result;
143}
144
146 int64_t Result = readLEB128(Ctx);
147 if (Result > VARUINT1_MAX || Result < 0)
148 report_fatal_error("LEB is outside Varuint1 range");
149 return Result;
150}
151
153 int64_t Result = readLEB128(Ctx);
154 if (Result > INT32_MAX || Result < INT32_MIN)
155 report_fatal_error("LEB is outside Varint32 range");
156 return Result;
157}
158
160 uint64_t Result = readULEB128(Ctx);
161 if (Result > UINT32_MAX)
162 report_fatal_error("LEB is outside Varuint32 range");
163 return Result;
164}
165
167 return readLEB128(Ctx);
168}
169
171 return readULEB128(Ctx);
172}
173
175 return readUint8(Ctx);
176}
177
179 uint32_t Code) {
180 // only directly encoded FUNCREF/EXTERNREF/EXNREF are supported
181 // (not ref null func, ref null extern, or ref null exn)
182 switch (Code) {
191 return wasm::ValType(Code);
192 }
194 /* Discard HeapType */ readVarint64(Ctx);
195 }
197}
198
201 auto Start = Ctx.Ptr;
202
203 Expr.Extended = false;
204 Expr.Inst.Opcode = readOpcode(Ctx);
205 switch (Expr.Inst.Opcode) {
207 Expr.Inst.Value.Int32 = readVarint32(Ctx);
208 break;
210 Expr.Inst.Value.Int64 = readVarint64(Ctx);
211 break;
213 Expr.Inst.Value.Float32 = readFloat32(Ctx);
214 break;
216 Expr.Inst.Value.Float64 = readFloat64(Ctx);
217 break;
219 Expr.Inst.Value.Global = readULEB128(Ctx);
220 break;
222 /* Discard type */ parseValType(Ctx, readVaruint32(Ctx));
223 break;
224 }
225 default:
226 Expr.Extended = true;
227 }
228
229 if (!Expr.Extended) {
230 uint8_t EndOpcode = readOpcode(Ctx);
231 if (EndOpcode != wasm::WASM_OPCODE_END)
232 Expr.Extended = true;
233 }
234
235 if (Expr.Extended) {
236 Ctx.Ptr = Start;
237 while (true) {
238 uint8_t Opcode = readOpcode(Ctx);
239 switch (Opcode) {
245 readULEB128(Ctx);
246 break;
248 readFloat32(Ctx);
249 break;
251 readFloat64(Ctx);
252 break;
259 break;
261 break;
262 // The GC opcodes are in a separate (prefixed space). This flat switch
263 // structure works as long as there is no overlap between the GC and
264 // general opcodes used in init exprs.
269 readULEB128(Ctx); // heap type index
270 break;
272 readULEB128(Ctx); // heap type index
273 readULEB128(Ctx); // array size
274 break;
276 break;
278 Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);
279 return Error::success();
280 default:
281 return make_error<GenericBinaryError>(
282 Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)),
284 }
285 }
286 }
287
288 return Error::success();
289}
290
292 wasm::WasmLimits Result;
293 Result.Flags = readVaruint32(Ctx);
294 Result.Minimum = readVaruint64(Ctx);
295 if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
296 Result.Maximum = readVaruint64(Ctx);
297 return Result;
298}
299
301 wasm::WasmTableType TableType;
302 auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
303 TableType.ElemType = ElemType;
304 TableType.Limits = readLimits(Ctx);
305 return TableType;
306}
307
309 WasmSectionOrderChecker &Checker) {
310 Section.Type = readUint8(Ctx);
311 LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
312 // When reading the section's size, store the size of the LEB used to encode
313 // it. This allows objcopy/strip to reproduce the binary identically.
314 const uint8_t *PreSizePtr = Ctx.Ptr;
316 Section.HeaderSecSizeEncodingLen = Ctx.Ptr - PreSizePtr;
317 Section.Offset = Ctx.Ptr - Ctx.Start;
318 if (Size == 0)
319 return make_error<StringError>("zero length section",
321 if (Ctx.Ptr + Size > Ctx.End)
322 return make_error<StringError>("section too large",
324 if (Section.Type == wasm::WASM_SEC_CUSTOM) {
326 SectionCtx.Start = Ctx.Ptr;
327 SectionCtx.Ptr = Ctx.Ptr;
328 SectionCtx.End = Ctx.Ptr + Size;
329
330 Section.Name = readString(SectionCtx);
331
332 uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
333 Ctx.Ptr += SectionNameSize;
334 Size -= SectionNameSize;
335 }
336
337 if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
338 return make_error<StringError>("out of order section type: " +
339 llvm::to_string(Section.Type),
341 }
342
343 Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
344 Ctx.Ptr += Size;
345 return Error::success();
346}
347
349 : ObjectFile(Binary::ID_Wasm, Buffer) {
350 ErrorAsOutParameter ErrAsOutParam(&Err);
351 Header.Magic = getData().substr(0, 4);
352 if (Header.Magic != StringRef("\0asm", 4)) {
353 Err = make_error<StringError>("invalid magic number",
355 return;
356 }
357
358 ReadContext Ctx;
359 Ctx.Start = getData().bytes_begin();
360 Ctx.Ptr = Ctx.Start + 4;
361 Ctx.End = Ctx.Start + getData().size();
362
363 if (Ctx.Ptr + 4 > Ctx.End) {
364 Err = make_error<StringError>("missing version number",
366 return;
367 }
368
369 Header.Version = readUint32(Ctx);
370 if (Header.Version != wasm::WasmVersion) {
371 Err = make_error<StringError>("invalid version number: " +
372 Twine(Header.Version),
374 return;
375 }
376
378 while (Ctx.Ptr < Ctx.End) {
379 WasmSection Sec;
380 if ((Err = readSection(Sec, Ctx, Checker)))
381 return;
382 if ((Err = parseSection(Sec)))
383 return;
384
385 Sections.push_back(Sec);
386 }
387}
388
389Error WasmObjectFile::parseSection(WasmSection &Sec) {
390 ReadContext Ctx;
391 Ctx.Start = Sec.Content.data();
392 Ctx.End = Ctx.Start + Sec.Content.size();
393 Ctx.Ptr = Ctx.Start;
394 switch (Sec.Type) {
396 return parseCustomSection(Sec, Ctx);
398 return parseTypeSection(Ctx);
400 return parseImportSection(Ctx);
402 return parseFunctionSection(Ctx);
404 return parseTableSection(Ctx);
406 return parseMemorySection(Ctx);
408 return parseTagSection(Ctx);
410 return parseGlobalSection(Ctx);
412 return parseExportSection(Ctx);
414 return parseStartSection(Ctx);
416 return parseElemSection(Ctx);
418 return parseCodeSection(Ctx);
420 return parseDataSection(Ctx);
422 return parseDataCountSection(Ctx);
423 default:
424 return make_error<GenericBinaryError>(
425 "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
426 }
427}
428
429Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
430 // Legacy "dylink" section support.
431 // See parseDylink0Section for the current "dylink.0" section parsing.
432 HasDylinkSection = true;
433 DylinkInfo.MemorySize = readVaruint32(Ctx);
434 DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
435 DylinkInfo.TableSize = readVaruint32(Ctx);
436 DylinkInfo.TableAlignment = readVaruint32(Ctx);
437 uint32_t Count = readVaruint32(Ctx);
438 while (Count--) {
439 DylinkInfo.Needed.push_back(readString(Ctx));
440 }
441
442 if (Ctx.Ptr != Ctx.End)
443 return make_error<GenericBinaryError>("dylink section ended prematurely",
445 return Error::success();
446}
447
448Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
449 // See
450 // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
451 HasDylinkSection = true;
452
453 const uint8_t *OrigEnd = Ctx.End;
454 while (Ctx.Ptr < OrigEnd) {
455 Ctx.End = OrigEnd;
456 uint8_t Type = readUint8(Ctx);
458 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
459 << "\n");
460 Ctx.End = Ctx.Ptr + Size;
461 uint32_t Count;
462 switch (Type) {
464 DylinkInfo.MemorySize = readVaruint32(Ctx);
465 DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
466 DylinkInfo.TableSize = readVaruint32(Ctx);
467 DylinkInfo.TableAlignment = readVaruint32(Ctx);
468 break;
470 Count = readVaruint32(Ctx);
471 while (Count--) {
472 DylinkInfo.Needed.push_back(readString(Ctx));
473 }
474 break;
476 uint32_t Count = readVaruint32(Ctx);
477 while (Count--) {
478 DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)});
479 }
480 break;
481 }
483 uint32_t Count = readVaruint32(Ctx);
484 while (Count--) {
485 DylinkInfo.ImportInfo.push_back(
486 {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
487 }
488 break;
489 }
490 default:
491 LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
492 Ctx.Ptr += Size;
493 break;
494 }
495 if (Ctx.Ptr != Ctx.End) {
496 return make_error<GenericBinaryError>(
497 "dylink.0 sub-section ended prematurely", object_error::parse_failed);
498 }
499 }
500
501 if (Ctx.Ptr != Ctx.End)
502 return make_error<GenericBinaryError>("dylink.0 section ended prematurely",
504 return Error::success();
505}
506
507Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
508 llvm::DenseSet<uint64_t> SeenFunctions;
509 llvm::DenseSet<uint64_t> SeenGlobals;
510 llvm::DenseSet<uint64_t> SeenSegments;
511
512 // If there is symbol info from the export section, this info will supersede
513 // it, but not info from a linking section
514 if (!HasLinkingSection) {
515 Symbols.clear();
516 }
517
518 while (Ctx.Ptr < Ctx.End) {
519 uint8_t Type = readUint8(Ctx);
521 const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
522
523 switch (Type) {
527 uint32_t Count = readVaruint32(Ctx);
528 while (Count--) {
534 /* Flags */ 0,
535 /* ImportModule */ std::nullopt,
536 /* ImportName */ std::nullopt,
537 /* ExportName */ std::nullopt,
538 {/* ElementIndex */ Index}};
539 const wasm::WasmSignature *Signature = nullptr;
540 const wasm::WasmGlobalType *GlobalType = nullptr;
541 const wasm::WasmTableType *TableType = nullptr;
543 if (!SeenFunctions.insert(Index).second)
544 return make_error<GenericBinaryError>(
545 "function named more than once", object_error::parse_failed);
546 if (!isValidFunctionIndex(Index) || Name.empty())
547 return make_error<GenericBinaryError>("invalid function name entry",
549
550 if (isDefinedFunctionIndex(Index)) {
551 wasm::WasmFunction &F = getDefinedFunction(Index);
552 F.DebugName = Name;
553 Signature = &Signatures[F.SigIndex];
554 if (F.ExportName) {
555 Info.ExportName = F.ExportName;
557 } else {
559 }
560 } else {
562 }
563 } else if (Type == wasm::WASM_NAMES_GLOBAL) {
564 if (!SeenGlobals.insert(Index).second)
565 return make_error<GenericBinaryError>("global named more than once",
567 if (!isValidGlobalIndex(Index) || Name.empty())
568 return make_error<GenericBinaryError>("invalid global name entry",
570 nameType = wasm::NameType::GLOBAL;
572 if (isDefinedGlobalIndex(Index)) {
573 GlobalType = &getDefinedGlobal(Index).Type;
574 } else {
576 }
577 } else {
578 if (!SeenSegments.insert(Index).second)
579 return make_error<GenericBinaryError>(
580 "segment named more than once", object_error::parse_failed);
581 if (Index > DataSegments.size())
582 return make_error<GenericBinaryError>("invalid data segment name entry",
587 assert(Index < DataSegments.size());
589 Index, 0, DataSegments[Index].Data.Content.size()};
590 }
591 DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
592 if (!HasLinkingSection)
593 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
594 }
595 break;
596 }
597 // Ignore local names for now
599 default:
600 Ctx.Ptr += Size;
601 break;
602 }
603 if (Ctx.Ptr != SubSectionEnd)
604 return make_error<GenericBinaryError>(
605 "name sub-section ended prematurely", object_error::parse_failed);
606 }
607
608 if (Ctx.Ptr != Ctx.End)
609 return make_error<GenericBinaryError>("name section ended prematurely",
611 return Error::success();
612}
613
614Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
615 HasLinkingSection = true;
616
617 LinkingData.Version = readVaruint32(Ctx);
618 if (LinkingData.Version != wasm::WasmMetadataVersion) {
619 return make_error<GenericBinaryError>(
620 "unexpected metadata version: " + Twine(LinkingData.Version) +
621 " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
623 }
624
625 const uint8_t *OrigEnd = Ctx.End;
626 while (Ctx.Ptr < OrigEnd) {
627 Ctx.End = OrigEnd;
628 uint8_t Type = readUint8(Ctx);
630 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
631 << "\n");
632 Ctx.End = Ctx.Ptr + Size;
633 switch (Type) {
635 if (Error Err = parseLinkingSectionSymtab(Ctx))
636 return Err;
637 break;
639 uint32_t Count = readVaruint32(Ctx);
640 if (Count > DataSegments.size())
641 return make_error<GenericBinaryError>("too many segment names",
643 for (uint32_t I = 0; I < Count; I++) {
644 DataSegments[I].Data.Name = readString(Ctx);
645 DataSegments[I].Data.Alignment = readVaruint32(Ctx);
646 DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
647 }
648 break;
649 }
651 uint32_t Count = readVaruint32(Ctx);
652 LinkingData.InitFunctions.reserve(Count);
653 for (uint32_t I = 0; I < Count; I++) {
655 Init.Priority = readVaruint32(Ctx);
656 Init.Symbol = readVaruint32(Ctx);
657 if (!isValidFunctionSymbol(Init.Symbol))
658 return make_error<GenericBinaryError>("invalid function symbol: " +
659 Twine(Init.Symbol),
661 LinkingData.InitFunctions.emplace_back(Init);
662 }
663 break;
664 }
666 if (Error Err = parseLinkingSectionComdat(Ctx))
667 return Err;
668 break;
669 default:
670 Ctx.Ptr += Size;
671 break;
672 }
673 if (Ctx.Ptr != Ctx.End)
674 return make_error<GenericBinaryError>(
675 "linking sub-section ended prematurely", object_error::parse_failed);
676 }
677 if (Ctx.Ptr != OrigEnd)
678 return make_error<GenericBinaryError>("linking section ended prematurely",
680 return Error::success();
681}
682
683Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
684 uint32_t Count = readVaruint32(Ctx);
685 // Clear out any symbol information that was derived from the exports
686 // section.
687 Symbols.clear();
688 Symbols.reserve(Count);
689 StringSet<> SymbolNames;
690
691 std::vector<wasm::WasmImport *> ImportedGlobals;
692 std::vector<wasm::WasmImport *> ImportedFunctions;
693 std::vector<wasm::WasmImport *> ImportedTags;
694 std::vector<wasm::WasmImport *> ImportedTables;
695 ImportedGlobals.reserve(Imports.size());
696 ImportedFunctions.reserve(Imports.size());
697 ImportedTags.reserve(Imports.size());
698 ImportedTables.reserve(Imports.size());
699 for (auto &I : Imports) {
701 ImportedFunctions.emplace_back(&I);
702 else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
703 ImportedGlobals.emplace_back(&I);
704 else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
705 ImportedTags.emplace_back(&I);
706 else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
707 ImportedTables.emplace_back(&I);
708 }
709
710 while (Count--) {
712 const wasm::WasmSignature *Signature = nullptr;
713 const wasm::WasmGlobalType *GlobalType = nullptr;
714 const wasm::WasmTableType *TableType = nullptr;
715
716 Info.Kind = readUint8(Ctx);
717 Info.Flags = readVaruint32(Ctx);
718 bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
719
720 switch (Info.Kind) {
722 Info.ElementIndex = readVaruint32(Ctx);
723 if (!isValidFunctionIndex(Info.ElementIndex) ||
724 IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
725 return make_error<GenericBinaryError>("invalid function symbol index",
727 if (IsDefined) {
728 Info.Name = readString(Ctx);
729 unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
730 wasm::WasmFunction &Function = Functions[FuncIndex];
731 Signature = &Signatures[Function.SigIndex];
732 if (Function.SymbolName.empty())
733 Function.SymbolName = Info.Name;
734 } else {
735 wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
736 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
737 Info.Name = readString(Ctx);
738 Info.ImportName = Import.Field;
739 } else {
740 Info.Name = Import.Field;
741 }
742 Signature = &Signatures[Import.SigIndex];
743 Info.ImportModule = Import.Module;
744 }
745 break;
746
748 Info.ElementIndex = readVaruint32(Ctx);
749 if (!isValidGlobalIndex(Info.ElementIndex) ||
750 IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
751 return make_error<GenericBinaryError>("invalid global symbol index",
753 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
755 return make_error<GenericBinaryError>("undefined weak global symbol",
757 if (IsDefined) {
758 Info.Name = readString(Ctx);
759 unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
760 wasm::WasmGlobal &Global = Globals[GlobalIndex];
761 GlobalType = &Global.Type;
762 if (Global.SymbolName.empty())
763 Global.SymbolName = Info.Name;
764 } else {
765 wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
766 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
767 Info.Name = readString(Ctx);
768 Info.ImportName = Import.Field;
769 } else {
770 Info.Name = Import.Field;
771 }
772 GlobalType = &Import.Global;
773 Info.ImportModule = Import.Module;
774 }
775 break;
776
778 Info.ElementIndex = readVaruint32(Ctx);
779 if (!isValidTableNumber(Info.ElementIndex) ||
780 IsDefined != isDefinedTableNumber(Info.ElementIndex))
781 return make_error<GenericBinaryError>("invalid table symbol index",
783 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
785 return make_error<GenericBinaryError>("undefined weak table symbol",
787 if (IsDefined) {
788 Info.Name = readString(Ctx);
789 unsigned TableNumber = Info.ElementIndex - NumImportedTables;
790 wasm::WasmTable &Table = Tables[TableNumber];
791 TableType = &Table.Type;
792 if (Table.SymbolName.empty())
793 Table.SymbolName = Info.Name;
794 } else {
795 wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
796 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
797 Info.Name = readString(Ctx);
798 Info.ImportName = Import.Field;
799 } else {
800 Info.Name = Import.Field;
801 }
802 TableType = &Import.Table;
803 Info.ImportModule = Import.Module;
804 }
805 break;
806
808 Info.Name = readString(Ctx);
809 if (IsDefined) {
810 auto Index = readVaruint32(Ctx);
811 auto Offset = readVaruint64(Ctx);
812 auto Size = readVaruint64(Ctx);
813 if (!(Info.Flags & wasm::WASM_SYMBOL_ABSOLUTE)) {
814 if (static_cast<size_t>(Index) >= DataSegments.size())
815 return make_error<GenericBinaryError>(
816 "invalid data segment index: " + Twine(Index),
818 size_t SegmentSize = DataSegments[Index].Data.Content.size();
819 if (Offset > SegmentSize)
820 return make_error<GenericBinaryError>(
821 "invalid data symbol offset: `" + Info.Name +
822 "` (offset: " + Twine(Offset) +
823 " segment size: " + Twine(SegmentSize) + ")",
825 }
827 }
828 break;
829
831 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
833 return make_error<GenericBinaryError>(
834 "section symbols must have local binding",
836 Info.ElementIndex = readVaruint32(Ctx);
837 // Use somewhat unique section name as symbol name.
838 StringRef SectionName = Sections[Info.ElementIndex].Name;
839 Info.Name = SectionName;
840 break;
841 }
842
844 Info.ElementIndex = readVaruint32(Ctx);
845 if (!isValidTagIndex(Info.ElementIndex) ||
846 IsDefined != isDefinedTagIndex(Info.ElementIndex))
847 return make_error<GenericBinaryError>("invalid tag symbol index",
849 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
851 return make_error<GenericBinaryError>("undefined weak global symbol",
853 if (IsDefined) {
854 Info.Name = readString(Ctx);
855 unsigned TagIndex = Info.ElementIndex - NumImportedTags;
856 wasm::WasmTag &Tag = Tags[TagIndex];
857 Signature = &Signatures[Tag.SigIndex];
858 if (Tag.SymbolName.empty())
859 Tag.SymbolName = Info.Name;
860
861 } else {
862 wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
863 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
864 Info.Name = readString(Ctx);
865 Info.ImportName = Import.Field;
866 } else {
867 Info.Name = Import.Field;
868 }
869 Signature = &Signatures[Import.SigIndex];
870 Info.ImportModule = Import.Module;
871 }
872 break;
873 }
874
875 default:
876 return make_error<GenericBinaryError>("invalid symbol type: " +
877 Twine(unsigned(Info.Kind)),
879 }
880
881 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
883 !SymbolNames.insert(Info.Name).second)
884 return make_error<GenericBinaryError>("duplicate symbol name " +
885 Twine(Info.Name),
887 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
888 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
889 }
890
891 return Error::success();
892}
893
894Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
895 uint32_t ComdatCount = readVaruint32(Ctx);
896 StringSet<> ComdatSet;
897 for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
899 if (Name.empty() || !ComdatSet.insert(Name).second)
900 return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
901 Twine(Name),
903 LinkingData.Comdats.emplace_back(Name);
905 if (Flags != 0)
906 return make_error<GenericBinaryError>("unsupported COMDAT flags",
908
909 uint32_t EntryCount = readVaruint32(Ctx);
910 while (EntryCount--) {
911 unsigned Kind = readVaruint32(Ctx);
912 unsigned Index = readVaruint32(Ctx);
913 switch (Kind) {
914 default:
915 return make_error<GenericBinaryError>("invalid COMDAT entry type",
918 if (Index >= DataSegments.size())
919 return make_error<GenericBinaryError>(
920 "COMDAT data index out of range", object_error::parse_failed);
921 if (DataSegments[Index].Data.Comdat != UINT32_MAX)
922 return make_error<GenericBinaryError>("data segment in two COMDATs",
924 DataSegments[Index].Data.Comdat = ComdatIndex;
925 break;
927 if (!isDefinedFunctionIndex(Index))
928 return make_error<GenericBinaryError>(
929 "COMDAT function index out of range", object_error::parse_failed);
930 if (getDefinedFunction(Index).Comdat != UINT32_MAX)
931 return make_error<GenericBinaryError>("function in two COMDATs",
933 getDefinedFunction(Index).Comdat = ComdatIndex;
934 break;
936 if (Index >= Sections.size())
937 return make_error<GenericBinaryError>(
938 "COMDAT section index out of range", object_error::parse_failed);
939 if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
940 return make_error<GenericBinaryError>(
941 "non-custom section in a COMDAT", object_error::parse_failed);
942 Sections[Index].Comdat = ComdatIndex;
943 break;
944 }
945 }
946 }
947 return Error::success();
948}
949
950Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
952 uint32_t Fields = readVaruint32(Ctx);
953 for (size_t I = 0; I < Fields; ++I) {
954 StringRef FieldName = readString(Ctx);
955 if (!FieldsSeen.insert(FieldName).second)
956 return make_error<GenericBinaryError>(
957 "producers section does not have unique fields",
959 std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
960 if (FieldName == "language") {
961 ProducerVec = &ProducerInfo.Languages;
962 } else if (FieldName == "processed-by") {
963 ProducerVec = &ProducerInfo.Tools;
964 } else if (FieldName == "sdk") {
965 ProducerVec = &ProducerInfo.SDKs;
966 } else {
967 return make_error<GenericBinaryError>(
968 "producers section field is not named one of language, processed-by, "
969 "or sdk",
971 }
972 uint32_t ValueCount = readVaruint32(Ctx);
973 llvm::SmallSet<StringRef, 8> ProducersSeen;
974 for (size_t J = 0; J < ValueCount; ++J) {
977 if (!ProducersSeen.insert(Name).second) {
978 return make_error<GenericBinaryError>(
979 "producers section contains repeated producer",
981 }
982 ProducerVec->emplace_back(std::string(Name), std::string(Version));
983 }
984 }
985 if (Ctx.Ptr != Ctx.End)
986 return make_error<GenericBinaryError>("producers section ended prematurely",
988 return Error::success();
989}
990
991Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
994 for (size_t I = 0; I < FeatureCount; ++I) {
996 Feature.Prefix = readUint8(Ctx);
997 switch (Feature.Prefix) {
1001 break;
1002 default:
1003 return make_error<GenericBinaryError>("unknown feature policy prefix",
1005 }
1006 Feature.Name = std::string(readString(Ctx));
1007 if (!FeaturesSeen.insert(Feature.Name).second)
1008 return make_error<GenericBinaryError>(
1009 "target features section contains repeated feature \"" +
1010 Feature.Name + "\"",
1012 TargetFeatures.push_back(Feature);
1013 }
1014 if (Ctx.Ptr != Ctx.End)
1015 return make_error<GenericBinaryError>(
1016 "target features section ended prematurely",
1018 return Error::success();
1019}
1020
1021Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
1022 uint32_t SectionIndex = readVaruint32(Ctx);
1023 if (SectionIndex >= Sections.size())
1024 return make_error<GenericBinaryError>("invalid section index",
1026 WasmSection &Section = Sections[SectionIndex];
1027 uint32_t RelocCount = readVaruint32(Ctx);
1028 uint32_t EndOffset = Section.Content.size();
1029 uint32_t PreviousOffset = 0;
1030 while (RelocCount--) {
1031 wasm::WasmRelocation Reloc = {};
1032 uint32_t type = readVaruint32(Ctx);
1033 Reloc.Type = type;
1034 Reloc.Offset = readVaruint32(Ctx);
1035 if (Reloc.Offset < PreviousOffset)
1036 return make_error<GenericBinaryError>("relocations not in offset order",
1038
1039 auto badReloc = [&](StringRef msg) {
1040 return make_error<GenericBinaryError>(
1041 msg + ": " + Twine(Symbols[Reloc.Index].Info.Name),
1043 };
1044
1045 PreviousOffset = Reloc.Offset;
1046 Reloc.Index = readVaruint32(Ctx);
1047 switch (type) {
1048 case wasm::R_WASM_FUNCTION_INDEX_LEB:
1049 case wasm::R_WASM_FUNCTION_INDEX_I32:
1050 case wasm::R_WASM_TABLE_INDEX_SLEB:
1051 case wasm::R_WASM_TABLE_INDEX_SLEB64:
1052 case wasm::R_WASM_TABLE_INDEX_I32:
1053 case wasm::R_WASM_TABLE_INDEX_I64:
1054 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
1055 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
1056 if (!isValidFunctionSymbol(Reloc.Index))
1057 return badReloc("invalid function relocation");
1058 break;
1059 case wasm::R_WASM_TABLE_NUMBER_LEB:
1060 if (!isValidTableSymbol(Reloc.Index))
1061 return badReloc("invalid table relocation");
1062 break;
1063 case wasm::R_WASM_TYPE_INDEX_LEB:
1064 if (Reloc.Index >= Signatures.size())
1065 return badReloc("invalid relocation type index");
1066 break;
1067 case wasm::R_WASM_GLOBAL_INDEX_LEB:
1068 // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
1069 // symbols to refer to their GOT entries.
1070 if (!isValidGlobalSymbol(Reloc.Index) &&
1071 !isValidDataSymbol(Reloc.Index) &&
1072 !isValidFunctionSymbol(Reloc.Index))
1073 return badReloc("invalid global relocation");
1074 break;
1075 case wasm::R_WASM_GLOBAL_INDEX_I32:
1076 if (!isValidGlobalSymbol(Reloc.Index))
1077 return badReloc("invalid global relocation");
1078 break;
1079 case wasm::R_WASM_TAG_INDEX_LEB:
1080 if (!isValidTagSymbol(Reloc.Index))
1081 return badReloc("invalid tag relocation");
1082 break;
1083 case wasm::R_WASM_MEMORY_ADDR_LEB:
1084 case wasm::R_WASM_MEMORY_ADDR_SLEB:
1085 case wasm::R_WASM_MEMORY_ADDR_I32:
1086 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1087 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1088 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1089 if (!isValidDataSymbol(Reloc.Index))
1090 return badReloc("invalid data relocation");
1091 Reloc.Addend = readVarint32(Ctx);
1092 break;
1093 case wasm::R_WASM_MEMORY_ADDR_LEB64:
1094 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1095 case wasm::R_WASM_MEMORY_ADDR_I64:
1096 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1097 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1098 if (!isValidDataSymbol(Reloc.Index))
1099 return badReloc("invalid data relocation");
1100 Reloc.Addend = readVarint64(Ctx);
1101 break;
1102 case wasm::R_WASM_FUNCTION_OFFSET_I32:
1103 if (!isValidFunctionSymbol(Reloc.Index))
1104 return badReloc("invalid function relocation");
1105 Reloc.Addend = readVarint32(Ctx);
1106 break;
1107 case wasm::R_WASM_FUNCTION_OFFSET_I64:
1108 if (!isValidFunctionSymbol(Reloc.Index))
1109 return badReloc("invalid function relocation");
1110 Reloc.Addend = readVarint64(Ctx);
1111 break;
1112 case wasm::R_WASM_SECTION_OFFSET_I32:
1113 if (!isValidSectionSymbol(Reloc.Index))
1114 return badReloc("invalid section relocation");
1115 Reloc.Addend = readVarint32(Ctx);
1116 break;
1117 default:
1118 return make_error<GenericBinaryError>("invalid relocation type: " +
1119 Twine(type),
1121 }
1122
1123 // Relocations must fit inside the section, and must appear in order. They
1124 // also shouldn't overlap a function/element boundary, but we don't bother
1125 // to check that.
1126 uint64_t Size = 5;
1127 if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1128 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1129 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1130 Size = 10;
1131 if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1132 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1133 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1134 Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1135 Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1136 Reloc.Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
1137 Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1138 Size = 4;
1139 if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1140 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1141 Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1142 Size = 8;
1143 if (Reloc.Offset + Size > EndOffset)
1144 return make_error<GenericBinaryError>("invalid relocation offset",
1146
1147 Section.Relocations.push_back(Reloc);
1148 }
1149 if (Ctx.Ptr != Ctx.End)
1150 return make_error<GenericBinaryError>("reloc section ended prematurely",
1152 return Error::success();
1153}
1154
1155Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
1156 if (Sec.Name == "dylink") {
1157 if (Error Err = parseDylinkSection(Ctx))
1158 return Err;
1159 } else if (Sec.Name == "dylink.0") {
1160 if (Error Err = parseDylink0Section(Ctx))
1161 return Err;
1162 } else if (Sec.Name == "name") {
1163 if (Error Err = parseNameSection(Ctx))
1164 return Err;
1165 } else if (Sec.Name == "linking") {
1166 if (Error Err = parseLinkingSection(Ctx))
1167 return Err;
1168 } else if (Sec.Name == "producers") {
1169 if (Error Err = parseProducersSection(Ctx))
1170 return Err;
1171 } else if (Sec.Name == "target_features") {
1172 if (Error Err = parseTargetFeaturesSection(Ctx))
1173 return Err;
1174 } else if (Sec.Name.starts_with("reloc.")) {
1175 if (Error Err = parseRelocSection(Sec.Name, Ctx))
1176 return Err;
1177 }
1178 return Error::success();
1179}
1180
1181Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1182 auto parseFieldDef = [&]() {
1183 uint32_t TypeCode = readVaruint32((Ctx));
1184 /* Discard StorageType */ parseValType(Ctx, TypeCode);
1185 /* Discard Mutability */ readVaruint32(Ctx);
1186 };
1187
1188 uint32_t Count = readVaruint32(Ctx);
1189 Signatures.reserve(Count);
1190 while (Count--) {
1192 uint8_t Form = readUint8(Ctx);
1193 if (Form == wasm::WASM_TYPE_REC) {
1194 // Rec groups expand the type index space (beyond what was declared at
1195 // the top of the section, and also consume one element in that space.
1196 uint32_t RecSize = readVaruint32(Ctx);
1197 if (RecSize == 0)
1198 return make_error<GenericBinaryError>("Rec group size cannot be 0",
1200 Signatures.reserve(Signatures.size() + RecSize);
1201 Count += RecSize;
1203 Signatures.push_back(std::move(Sig));
1204 HasUnmodeledTypes = true;
1205 continue;
1206 }
1207 if (Form != wasm::WASM_TYPE_FUNC) {
1208 // Currently LLVM only models function types, and not other composite
1209 // types. Here we parse the type declarations just enough to skip past
1210 // them in the binary.
1212 uint32_t Supers = readVaruint32(Ctx);
1213 if (Supers > 0) {
1214 if (Supers != 1)
1215 return make_error<GenericBinaryError>(
1216 "Invalid number of supertypes", object_error::parse_failed);
1217 /* Discard SuperIndex */ readVaruint32(Ctx);
1218 }
1219 Form = readVaruint32(Ctx);
1220 }
1222 uint32_t FieldCount = readVaruint32(Ctx);
1223 while (FieldCount--) {
1224 parseFieldDef();
1225 }
1226 } else if (Form == wasm::WASM_TYPE_ARRAY) {
1227 parseFieldDef();
1228 } else {
1229 return make_error<GenericBinaryError>("bad form",
1231 }
1233 Signatures.push_back(std::move(Sig));
1234 HasUnmodeledTypes = true;
1235 continue;
1236 }
1237
1238 uint32_t ParamCount = readVaruint32(Ctx);
1239 Sig.Params.reserve(ParamCount);
1240 while (ParamCount--) {
1241 uint32_t ParamType = readUint8(Ctx);
1242 Sig.Params.push_back(parseValType(Ctx, ParamType));
1243 continue;
1244 }
1245 uint32_t ReturnCount = readVaruint32(Ctx);
1246 while (ReturnCount--) {
1248 Sig.Returns.push_back(parseValType(Ctx, ReturnType));
1249 }
1250
1251 Signatures.push_back(std::move(Sig));
1252 }
1253 if (Ctx.Ptr != Ctx.End)
1254 return make_error<GenericBinaryError>("type section ended prematurely",
1256 return Error::success();
1257}
1258
1259Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1260 uint32_t Count = readVaruint32(Ctx);
1261 uint32_t NumTypes = Signatures.size();
1262 Imports.reserve(Count);
1263 for (uint32_t I = 0; I < Count; I++) {
1265 Im.Module = readString(Ctx);
1266 Im.Field = readString(Ctx);
1267 Im.Kind = readUint8(Ctx);
1268 switch (Im.Kind) {
1270 NumImportedFunctions++;
1271 Im.SigIndex = readVaruint32(Ctx);
1272 if (Im.SigIndex >= NumTypes)
1273 return make_error<GenericBinaryError>("invalid function type",
1275 break;
1277 NumImportedGlobals++;
1278 Im.Global.Type = readUint8(Ctx);
1279 Im.Global.Mutable = readVaruint1(Ctx);
1280 break;
1282 Im.Memory = readLimits(Ctx);
1284 HasMemory64 = true;
1285 break;
1287 Im.Table = readTableType(Ctx);
1288 NumImportedTables++;
1289 auto ElemType = Im.Table.ElemType;
1290 if (ElemType != wasm::ValType::FUNCREF &&
1291 ElemType != wasm::ValType::EXTERNREF &&
1292 ElemType != wasm::ValType::EXNREF &&
1293 ElemType != wasm::ValType::OTHERREF)
1294 return make_error<GenericBinaryError>("invalid table element type",
1296 break;
1297 }
1299 NumImportedTags++;
1300 if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1301 return make_error<GenericBinaryError>("invalid attribute",
1303 Im.SigIndex = readVaruint32(Ctx);
1304 if (Im.SigIndex >= NumTypes)
1305 return make_error<GenericBinaryError>("invalid tag type",
1307 break;
1308 default:
1309 return make_error<GenericBinaryError>("unexpected import kind",
1311 }
1312 Imports.push_back(Im);
1313 }
1314 if (Ctx.Ptr != Ctx.End)
1315 return make_error<GenericBinaryError>("import section ended prematurely",
1317 return Error::success();
1318}
1319
1320Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1321 uint32_t Count = readVaruint32(Ctx);
1322 Functions.reserve(Count);
1323 uint32_t NumTypes = Signatures.size();
1324 while (Count--) {
1326 if (Type >= NumTypes)
1327 return make_error<GenericBinaryError>("invalid function type",
1330 F.SigIndex = Type;
1331 Functions.push_back(F);
1332 }
1333 if (Ctx.Ptr != Ctx.End)
1334 return make_error<GenericBinaryError>("function section ended prematurely",
1336 return Error::success();
1337}
1338
1339Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1340 TableSection = Sections.size();
1341 uint32_t Count = readVaruint32(Ctx);
1342 Tables.reserve(Count);
1343 while (Count--) {
1345 T.Type = readTableType(Ctx);
1346 T.Index = NumImportedTables + Tables.size();
1347 Tables.push_back(T);
1348 auto ElemType = Tables.back().Type.ElemType;
1349 if (ElemType != wasm::ValType::FUNCREF &&
1350 ElemType != wasm::ValType::EXTERNREF &&
1351 ElemType != wasm::ValType::EXNREF &&
1352 ElemType != wasm::ValType::OTHERREF) {
1353 return make_error<GenericBinaryError>("invalid table element type",
1355 }
1356 }
1357 if (Ctx.Ptr != Ctx.End)
1358 return make_error<GenericBinaryError>("table section ended prematurely",
1360 return Error::success();
1361}
1362
1363Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1364 uint32_t Count = readVaruint32(Ctx);
1365 Memories.reserve(Count);
1366 while (Count--) {
1367 auto Limits = readLimits(Ctx);
1368 if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1369 HasMemory64 = true;
1370 Memories.push_back(Limits);
1371 }
1372 if (Ctx.Ptr != Ctx.End)
1373 return make_error<GenericBinaryError>("memory section ended prematurely",
1375 return Error::success();
1376}
1377
1378Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1379 TagSection = Sections.size();
1380 uint32_t Count = readVaruint32(Ctx);
1381 Tags.reserve(Count);
1382 uint32_t NumTypes = Signatures.size();
1383 while (Count--) {
1384 if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1385 return make_error<GenericBinaryError>("invalid attribute",
1388 if (Type >= NumTypes)
1389 return make_error<GenericBinaryError>("invalid tag type",
1392 Tag.Index = NumImportedTags + Tags.size();
1393 Tag.SigIndex = Type;
1394 Signatures[Type].Kind = wasm::WasmSignature::Tag;
1395 Tags.push_back(Tag);
1396 }
1397
1398 if (Ctx.Ptr != Ctx.End)
1399 return make_error<GenericBinaryError>("tag section ended prematurely",
1401 return Error::success();
1402}
1403
1404Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1405 GlobalSection = Sections.size();
1406 const uint8_t *SectionStart = Ctx.Ptr;
1407 uint32_t Count = readVaruint32(Ctx);
1408 Globals.reserve(Count);
1409 while (Count--) {
1411 Global.Index = NumImportedGlobals + Globals.size();
1412 const uint8_t *GlobalStart = Ctx.Ptr;
1413 Global.Offset = static_cast<uint32_t>(GlobalStart - SectionStart);
1414 auto GlobalOpcode = readVaruint32(Ctx);
1415 Global.Type.Type = (uint8_t)parseValType(Ctx, GlobalOpcode);
1416 Global.Type.Mutable = readVaruint1(Ctx);
1417 if (Error Err = readInitExpr(Global.InitExpr, Ctx))
1418 return Err;
1419 Global.Size = static_cast<uint32_t>(Ctx.Ptr - GlobalStart);
1420 Globals.push_back(Global);
1421 }
1422 if (Ctx.Ptr != Ctx.End)
1423 return make_error<GenericBinaryError>("global section ended prematurely",
1425 return Error::success();
1426}
1427
1428Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1429 uint32_t Count = readVaruint32(Ctx);
1430 Exports.reserve(Count);
1431 Symbols.reserve(Count);
1432 for (uint32_t I = 0; I < Count; I++) {
1434 Ex.Name = readString(Ctx);
1435 Ex.Kind = readUint8(Ctx);
1436 Ex.Index = readVaruint32(Ctx);
1437 const wasm::WasmSignature *Signature = nullptr;
1438 const wasm::WasmGlobalType *GlobalType = nullptr;
1439 const wasm::WasmTableType *TableType = nullptr;
1441 Info.Name = Ex.Name;
1442 Info.Flags = 0;
1443 switch (Ex.Kind) {
1445 if (!isDefinedFunctionIndex(Ex.Index))
1446 return make_error<GenericBinaryError>("invalid function export",
1448 getDefinedFunction(Ex.Index).ExportName = Ex.Name;
1450 Info.ElementIndex = Ex.Index;
1451 unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
1452 wasm::WasmFunction &Function = Functions[FuncIndex];
1453 Signature = &Signatures[Function.SigIndex];
1454 break;
1455 }
1457 if (!isValidGlobalIndex(Ex.Index))
1458 return make_error<GenericBinaryError>("invalid global export",
1461 uint64_t Offset = 0;
1462 if (isDefinedGlobalIndex(Ex.Index)) {
1463 auto Global = getDefinedGlobal(Ex.Index);
1464 if (!Global.InitExpr.Extended) {
1465 auto Inst = Global.InitExpr.Inst;
1466 if (Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1467 Offset = Inst.Value.Int32;
1468 } else if (Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1469 Offset = Inst.Value.Int64;
1470 }
1471 }
1472 }
1473 Info.DataRef = wasm::WasmDataReference{0, Offset, 0};
1474 break;
1475 }
1477 if (!isValidTagIndex(Ex.Index))
1478 return make_error<GenericBinaryError>("invalid tag export",
1481 Info.ElementIndex = Ex.Index;
1482 break;
1484 break;
1487 Info.ElementIndex = Ex.Index;
1488 break;
1489 default:
1490 return make_error<GenericBinaryError>("unexpected export kind",
1492 }
1493 Exports.push_back(Ex);
1494 if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) {
1495 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
1496 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
1497 }
1498 }
1499 if (Ctx.Ptr != Ctx.End)
1500 return make_error<GenericBinaryError>("export section ended prematurely",
1502 return Error::success();
1503}
1504
1505bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1506 return Index < NumImportedFunctions + Functions.size();
1507}
1508
1509bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1510 return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1511}
1512
1513bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1514 return Index < NumImportedGlobals + Globals.size();
1515}
1516
1517bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1518 return Index < NumImportedTables + Tables.size();
1519}
1520
1521bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1522 return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1523}
1524
1525bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1526 return Index >= NumImportedTables && isValidTableNumber(Index);
1527}
1528
1529bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1530 return Index < NumImportedTags + Tags.size();
1531}
1532
1533bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1534 return Index >= NumImportedTags && isValidTagIndex(Index);
1535}
1536
1537bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1538 return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1539}
1540
1541bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1542 return Index < Symbols.size() && Symbols[Index].isTypeTable();
1543}
1544
1545bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1546 return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1547}
1548
1549bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1550 return Index < Symbols.size() && Symbols[Index].isTypeTag();
1551}
1552
1553bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1554 return Index < Symbols.size() && Symbols[Index].isTypeData();
1555}
1556
1557bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1558 return Index < Symbols.size() && Symbols[Index].isTypeSection();
1559}
1560
1561wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1562 assert(isDefinedFunctionIndex(Index));
1563 return Functions[Index - NumImportedFunctions];
1564}
1565
1566const wasm::WasmFunction &
1567WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1568 assert(isDefinedFunctionIndex(Index));
1569 return Functions[Index - NumImportedFunctions];
1570}
1571
1572const wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) const {
1573 assert(isDefinedGlobalIndex(Index));
1574 return Globals[Index - NumImportedGlobals];
1575}
1576
1577wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1578 assert(isDefinedTagIndex(Index));
1579 return Tags[Index - NumImportedTags];
1580}
1581
1582Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1583 StartFunction = readVaruint32(Ctx);
1584 if (!isValidFunctionIndex(StartFunction))
1585 return make_error<GenericBinaryError>("invalid start function",
1587 return Error::success();
1588}
1589
1590Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1591 CodeSection = Sections.size();
1592 uint32_t FunctionCount = readVaruint32(Ctx);
1593 if (FunctionCount != Functions.size()) {
1594 return make_error<GenericBinaryError>("invalid function count",
1596 }
1597
1598 for (uint32_t i = 0; i < FunctionCount; i++) {
1599 wasm::WasmFunction& Function = Functions[i];
1600 const uint8_t *FunctionStart = Ctx.Ptr;
1602 const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1603
1604 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1605 Function.Index = NumImportedFunctions + i;
1606 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1607 Function.Size = FunctionEnd - FunctionStart;
1608
1609 uint32_t NumLocalDecls = readVaruint32(Ctx);
1610 Function.Locals.reserve(NumLocalDecls);
1611 while (NumLocalDecls--) {
1613 Decl.Count = readVaruint32(Ctx);
1614 Decl.Type = readUint8(Ctx);
1615 Function.Locals.push_back(Decl);
1616 }
1617
1618 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1619 // Ensure that Function is within Ctx's buffer.
1620 if (Ctx.Ptr + BodySize > Ctx.End) {
1621 return make_error<GenericBinaryError>("Function extends beyond buffer",
1623 }
1624 Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1625 // This will be set later when reading in the linking metadata section.
1626 Function.Comdat = UINT32_MAX;
1627 Ctx.Ptr += BodySize;
1628 assert(Ctx.Ptr == FunctionEnd);
1629 }
1630 if (Ctx.Ptr != Ctx.End)
1631 return make_error<GenericBinaryError>("code section ended prematurely",
1633 return Error::success();
1634}
1635
1636Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1637 uint32_t Count = readVaruint32(Ctx);
1638 ElemSegments.reserve(Count);
1639 while (Count--) {
1640 wasm::WasmElemSegment Segment;
1641 Segment.Flags = readVaruint32(Ctx);
1642
1646 if (Segment.Flags & ~SupportedFlags)
1647 return make_error<GenericBinaryError>(
1648 "Unsupported flags for element segment", object_error::parse_failed);
1649
1650 bool IsPassive = (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) != 0;
1651 bool IsDeclarative =
1652 IsPassive && (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE);
1653 bool HasTableNumber =
1654 !IsPassive &&
1656 bool HasInitExprs =
1658 bool HasElemKind =
1660 !HasInitExprs;
1661
1662 if (HasTableNumber)
1663 Segment.TableNumber = readVaruint32(Ctx);
1664 else
1665 Segment.TableNumber = 0;
1666
1667 if (!isValidTableNumber(Segment.TableNumber))
1668 return make_error<GenericBinaryError>("invalid TableNumber",
1670
1671 if (IsPassive || IsDeclarative) {
1672 Segment.Offset.Extended = false;
1674 Segment.Offset.Inst.Value.Int32 = 0;
1675 } else {
1676 if (Error Err = readInitExpr(Segment.Offset, Ctx))
1677 return Err;
1678 }
1679
1680 if (HasElemKind) {
1681 auto ElemKind = readVaruint32(Ctx);
1683 Segment.ElemKind = parseValType(Ctx, ElemKind);
1684 if (Segment.ElemKind != wasm::ValType::FUNCREF &&
1686 Segment.ElemKind != wasm::ValType::EXNREF &&
1687 Segment.ElemKind != wasm::ValType::OTHERREF) {
1688 return make_error<GenericBinaryError>("invalid elem type",
1690 }
1691 } else {
1692 if (ElemKind != 0)
1693 return make_error<GenericBinaryError>("invalid elem type",
1696 }
1697 } else if (HasInitExprs) {
1698 auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
1699 Segment.ElemKind = ElemType;
1700 } else {
1702 }
1703
1704 uint32_t NumElems = readVaruint32(Ctx);
1705
1706 if (HasInitExprs) {
1707 while (NumElems--) {
1708 wasm::WasmInitExpr Expr;
1709 if (Error Err = readInitExpr(Expr, Ctx))
1710 return Err;
1711 }
1712 } else {
1713 while (NumElems--) {
1714 Segment.Functions.push_back(readVaruint32(Ctx));
1715 }
1716 }
1717 ElemSegments.push_back(Segment);
1718 }
1719 if (Ctx.Ptr != Ctx.End)
1720 return make_error<GenericBinaryError>("elem section ended prematurely",
1722 return Error::success();
1723}
1724
1725Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1726 DataSection = Sections.size();
1727 uint32_t Count = readVaruint32(Ctx);
1728 if (DataCount && Count != *DataCount)
1729 return make_error<GenericBinaryError>(
1730 "number of data segments does not match DataCount section");
1731 DataSegments.reserve(Count);
1732 while (Count--) {
1733 WasmSegment Segment;
1734 Segment.Data.InitFlags = readVaruint32(Ctx);
1735 Segment.Data.MemoryIndex =
1737 ? readVaruint32(Ctx)
1738 : 0;
1739 if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1740 if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1741 return Err;
1742 } else {
1743 Segment.Data.Offset.Extended = false;
1745 Segment.Data.Offset.Inst.Value.Int32 = 0;
1746 }
1748 if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1749 return make_error<GenericBinaryError>("invalid segment size",
1751 Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1752 // The rest of these Data fields are set later, when reading in the linking
1753 // metadata section.
1754 Segment.Data.Alignment = 0;
1755 Segment.Data.LinkingFlags = 0;
1756 Segment.Data.Comdat = UINT32_MAX;
1757 Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1758 Ctx.Ptr += Size;
1759 DataSegments.push_back(Segment);
1760 }
1761 if (Ctx.Ptr != Ctx.End)
1762 return make_error<GenericBinaryError>("data section ended prematurely",
1764 return Error::success();
1765}
1766
1767Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1768 DataCount = readVaruint32(Ctx);
1769 return Error::success();
1770}
1771
1773 return Header;
1774}
1775
1776void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1777
1780 const WasmSymbol &Sym = getWasmSymbol(Symb);
1781
1782 LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1783 if (Sym.isBindingWeak())
1784 Result |= SymbolRef::SF_Weak;
1785 if (!Sym.isBindingLocal())
1786 Result |= SymbolRef::SF_Global;
1787 if (Sym.isHidden())
1788 Result |= SymbolRef::SF_Hidden;
1789 if (!Sym.isDefined())
1790 Result |= SymbolRef::SF_Undefined;
1791 if (Sym.isTypeFunction())
1792 Result |= SymbolRef::SF_Executable;
1793 return Result;
1794}
1795
1798 Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1799 Ref.d.b = 0; // Symbol index
1800 return BasicSymbolRef(Ref, this);
1801}
1802
1805 Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1806 Ref.d.b = Symbols.size(); // Symbol index
1807 return BasicSymbolRef(Ref, this);
1808}
1809
1811 return Symbols[Symb.d.b];
1812}
1813
1815 return getWasmSymbol(Symb.getRawDataRefImpl());
1816}
1817
1819 return getWasmSymbol(Symb).Info.Name;
1820}
1821
1823 auto &Sym = getWasmSymbol(Symb);
1824 if (!Sym.isDefined())
1825 return 0;
1827 if (!Sec)
1828 return Sec.takeError();
1829 uint32_t SectionAddress = getSectionAddress(Sec.get()->getRawDataRefImpl());
1830 if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1831 isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
1832 return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
1833 SectionAddress;
1834 }
1835 if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL &&
1836 isDefinedGlobalIndex(Sym.Info.ElementIndex)) {
1837 return getDefinedGlobal(Sym.Info.ElementIndex).Offset + SectionAddress;
1838 }
1839
1840 return getSymbolValue(Symb);
1841}
1842
1844 switch (Sym.Info.Kind) {
1849 return Sym.Info.ElementIndex;
1851 // The value of a data symbol is the segment offset, plus the symbol
1852 // offset within the segment.
1853 uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1854 const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1855 if (Segment.Offset.Extended) {
1856 llvm_unreachable("extended init exprs not supported");
1857 } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1858 return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
1859 } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1860 return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
1861 } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {
1862 return Sym.Info.DataRef.Offset;
1863 } else {
1864 llvm_unreachable("unknown init expr opcode");
1865 }
1866 }
1868 return 0;
1869 }
1870 llvm_unreachable("invalid symbol type");
1871}
1872
1874 return getWasmSymbolValue(getWasmSymbol(Symb));
1875}
1876
1878 llvm_unreachable("not yet implemented");
1879 return 0;
1880}
1881
1883 llvm_unreachable("not yet implemented");
1884 return 0;
1885}
1886
1889 const WasmSymbol &Sym = getWasmSymbol(Symb);
1890
1891 switch (Sym.Info.Kind) {
1895 return SymbolRef::ST_Other;
1897 return SymbolRef::ST_Data;
1899 return SymbolRef::ST_Debug;
1901 return SymbolRef::ST_Other;
1903 return SymbolRef::ST_Other;
1904 }
1905
1906 llvm_unreachable("unknown WasmSymbol::SymbolType");
1907 return SymbolRef::ST_Other;
1908}
1909
1912 const WasmSymbol &Sym = getWasmSymbol(Symb);
1913 if (Sym.isUndefined())
1914 return section_end();
1915
1917 Ref.d.a = getSymbolSectionIdImpl(Sym);
1918 return section_iterator(SectionRef(Ref, this));
1919}
1920
1922 const WasmSymbol &Sym = getWasmSymbol(Symb);
1923 return getSymbolSectionIdImpl(Sym);
1924}
1925
1926uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
1927 switch (Sym.Info.Kind) {
1929 return CodeSection;
1931 return GlobalSection;
1933 return DataSection;
1935 return Sym.Info.ElementIndex;
1937 return TagSection;
1939 return TableSection;
1940 default:
1941 llvm_unreachable("unknown WasmSymbol::SymbolType");
1942 }
1943}
1944
1946 const WasmSymbol &Sym = getWasmSymbol(Symb);
1947 if (!Sym.isDefined())
1948 return 0;
1949 if (Sym.isTypeGlobal())
1950 return getDefinedGlobal(Sym.Info.ElementIndex).Size;
1951 if (Sym.isTypeData())
1952 return Sym.Info.DataRef.Size;
1953 if (Sym.isTypeFunction())
1954 return functions()[Sym.Info.ElementIndex - getNumImportedFunctions()].Size;
1955 // Currently symbol size is only tracked for data segments and functions. In
1956 // principle we could also track size (e.g. binary size) for tables, globals
1957 // and element segments etc too.
1958 return 0;
1959}
1960
1962
1964 const WasmSection &S = Sections[Sec.d.a];
1965 if (S.Type == wasm::WASM_SEC_CUSTOM)
1966 return S.Name;
1970}
1971
1973 // For object files, use 0 for section addresses, and section offsets for
1974 // symbol addresses. For linked files, use file offsets.
1975 // See also getSymbolAddress.
1976 return isRelocatableObject() || isSharedObject() ? 0
1977 : Sections[Sec.d.a].Offset;
1978}
1979
1981 return Sec.d.a;
1982}
1983
1985 const WasmSection &S = Sections[Sec.d.a];
1986 return S.Content.size();
1987}
1988
1991 const WasmSection &S = Sections[Sec.d.a];
1992 // This will never fail since wasm sections can never be empty (user-sections
1993 // must have a name and non-user sections each have a defined structure).
1994 return S.Content;
1995}
1996
1998 return 1;
1999}
2000
2002 return false;
2003}
2004
2007}
2008
2011}
2012
2013bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
2014
2015bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
2016
2018 DataRefImpl RelocRef;
2019 RelocRef.d.a = Ref.d.a;
2020 RelocRef.d.b = 0;
2021 return relocation_iterator(RelocationRef(RelocRef, this));
2022}
2023
2025 const WasmSection &Sec = getWasmSection(Ref);
2026 DataRefImpl RelocRef;
2027 RelocRef.d.a = Ref.d.a;
2028 RelocRef.d.b = Sec.Relocations.size();
2029 return relocation_iterator(RelocationRef(RelocRef, this));
2030}
2031
2033
2036 return Rel.Offset;
2037}
2038
2041 if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
2042 return symbol_end();
2044 Sym.d.a = 1;
2045 Sym.d.b = Rel.Index;
2046 return symbol_iterator(SymbolRef(Sym, this));
2047}
2048
2051 return Rel.Type;
2052}
2053
2055 DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
2057 StringRef Res = "Unknown";
2058
2059#define WASM_RELOC(name, value) \
2060 case wasm::name: \
2061 Res = #name; \
2062 break;
2063
2064 switch (Rel.Type) {
2065#include "llvm/BinaryFormat/WasmRelocs.def"
2066 }
2067
2068#undef WASM_RELOC
2069
2070 Result.append(Res.begin(), Res.end());
2071}
2072
2075 Ref.d.a = 0;
2076 return section_iterator(SectionRef(Ref, this));
2077}
2078
2081 Ref.d.a = Sections.size();
2082 return section_iterator(SectionRef(Ref, this));
2083}
2084
2086 return HasMemory64 ? 8 : 4;
2087}
2088
2090
2092 return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
2093}
2094
2096 return SubtargetFeatures();
2097}
2098
2099bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
2100
2101bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
2102
2104 assert(Ref.d.a < Sections.size());
2105 return Sections[Ref.d.a];
2106}
2107
2108const WasmSection &
2110 return getWasmSection(Section.getRawDataRefImpl());
2111}
2112
2115 return getWasmRelocation(Ref.getRawDataRefImpl());
2116}
2117
2120 assert(Ref.d.a < Sections.size());
2121 const WasmSection &Sec = Sections[Ref.d.a];
2122 assert(Ref.d.b < Sec.Relocations.size());
2123 return Sec.Relocations[Ref.d.b];
2124}
2125
2126int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
2127 StringRef CustomSectionName) {
2128 switch (ID) {
2130 return StringSwitch<unsigned>(CustomSectionName)
2131 .Case("dylink", WASM_SEC_ORDER_DYLINK)
2132 .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
2133 .Case("linking", WASM_SEC_ORDER_LINKING)
2135 .Case("name", WASM_SEC_ORDER_NAME)
2136 .Case("producers", WASM_SEC_ORDER_PRODUCERS)
2137 .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
2140 return WASM_SEC_ORDER_TYPE;
2142 return WASM_SEC_ORDER_IMPORT;
2146 return WASM_SEC_ORDER_TABLE;
2148 return WASM_SEC_ORDER_MEMORY;
2150 return WASM_SEC_ORDER_GLOBAL;
2152 return WASM_SEC_ORDER_EXPORT;
2154 return WASM_SEC_ORDER_START;
2156 return WASM_SEC_ORDER_ELEM;
2158 return WASM_SEC_ORDER_CODE;
2160 return WASM_SEC_ORDER_DATA;
2163 case wasm::WASM_SEC_TAG:
2164 return WASM_SEC_ORDER_TAG;
2165 default:
2166 return WASM_SEC_ORDER_NONE;
2167 }
2168}
2169
2170// Represents the edges in a directed graph where any node B reachable from node
2171// A is not allowed to appear before A in the section ordering, but may appear
2172// afterward.
2174 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2175 // WASM_SEC_ORDER_NONE
2176 {},
2177 // WASM_SEC_ORDER_TYPE
2178 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2179 // WASM_SEC_ORDER_IMPORT
2180 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2181 // WASM_SEC_ORDER_FUNCTION
2182 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2183 // WASM_SEC_ORDER_TABLE
2184 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2185 // WASM_SEC_ORDER_MEMORY
2186 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2187 // WASM_SEC_ORDER_TAG
2188 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2189 // WASM_SEC_ORDER_GLOBAL
2190 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2191 // WASM_SEC_ORDER_EXPORT
2192 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2193 // WASM_SEC_ORDER_START
2194 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2195 // WASM_SEC_ORDER_ELEM
2196 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2197 // WASM_SEC_ORDER_DATACOUNT
2198 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2199 // WASM_SEC_ORDER_CODE
2200 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2201 // WASM_SEC_ORDER_DATA
2202 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2203
2204 // Custom Sections
2205 // WASM_SEC_ORDER_DYLINK
2206 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2207 // WASM_SEC_ORDER_LINKING
2208 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2209 // WASM_SEC_ORDER_RELOC (can be repeated)
2210 {},
2211 // WASM_SEC_ORDER_NAME
2212 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2213 // WASM_SEC_ORDER_PRODUCERS
2214 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2215 // WASM_SEC_ORDER_TARGET_FEATURES
2216 {WASM_SEC_ORDER_TARGET_FEATURES}};
2217
2219 StringRef CustomSectionName) {
2220 int Order = getSectionOrder(ID, CustomSectionName);
2221 if (Order == WASM_SEC_ORDER_NONE)
2222 return true;
2223
2224 // Disallowed predecessors we need to check for
2226
2227 // Keep track of completed checks to avoid repeating work
2228 bool Checked[WASM_NUM_SEC_ORDERS] = {};
2229
2230 int Curr = Order;
2231 while (true) {
2232 // Add new disallowed predecessors to work list
2233 for (size_t I = 0;; ++I) {
2234 int Next = DisallowedPredecessors[Curr][I];
2235 if (Next == WASM_SEC_ORDER_NONE)
2236 break;
2237 if (Checked[Next])
2238 continue;
2239 WorkList.push_back(Next);
2240 Checked[Next] = true;
2241 }
2242
2243 if (WorkList.empty())
2244 break;
2245
2246 // Consider next disallowed predecessor
2247 Curr = WorkList.pop_back_val();
2248 if (Seen[Curr])
2249 return false;
2250 }
2251
2252 // Have not seen any disallowed predecessors
2253 Seen[Order] = true;
2254 return true;
2255}
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:537
#define LLVM_DEBUG(X)
Definition: Debug.h:101
This file defines the DenseSet and SmallDenseSet classes.
std::string Name
uint64_t Size
Symbol * Sym
Definition: ELF_riscv.cpp:479
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
StringSet - A set-like wrapper for the StringMap.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx)
static Error readInitExpr(wasm::WasmInitExpr &Expr, WasmObjectFile::ReadContext &Ctx)
static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx)
static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx)
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx)
static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx)
static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx, WasmSectionOrderChecker &Checker)
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx)
static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx)
static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx)
static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx)
static StringRef readString(WasmObjectFile::ReadContext &Ctx)
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx)
#define VARUINT1_MAX
static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx)
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx)
static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx)
static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx, uint32_t Code)
static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
const T * data() const
Definition: ArrayRef.h:162
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
Helper for Errors used as out-parameters.
Definition: Error.h:1130
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
reference get()
Returns a reference to the stored T value.
Definition: Error.h:578
bool empty() const
Definition: Function.h:822
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:135
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:179
bool empty() const
Definition: SmallVector.h:94
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void reserve(size_type N)
Definition: SmallVector.h:676
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:564
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:258
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
iterator begin() const
Definition: StringRef.h:111
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
iterator end() const
Definition: StringRef.h:113
const unsigned char * bytes_begin() const
Definition: StringRef.h:115
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition: StringSet.h:23
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition: StringSet.h:38
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
R Default(T Value)
Definition: StringSwitch.h:182
StringSwitch & StartsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:83
Manages the enabling and disabling of subtarget specific features.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
static Twine utohexstr(const uint64_t &Val)
Definition: Twine.h:416
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition: SymbolicFile.h:103
DataRefImpl getRawDataRefImpl() const
Definition: SymbolicFile.h:210
MemoryBufferRef Data
Definition: Binary.h:37
StringRef getData() const
Definition: Binary.cpp:39
This class is the base class for all object file types.
Definition: ObjectFile.h:229
friend class RelocationRef
Definition: ObjectFile.h:287
friend class SymbolRef
Definition: ObjectFile.h:247
friend class SectionRef
Definition: ObjectFile.h:261
static Expected< std::unique_ptr< WasmObjectFile > > createWasmObjectFile(MemoryBufferRef Object)
Expected< uint64_t > getSymbolValue(DataRefImpl Symb) const
Definition: ObjectFile.cpp:56
This is a value type class that represents a single relocation in the list of relocations in the obje...
Definition: ObjectFile.h:52
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:81
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition: ObjectFile.h:168
basic_symbol_iterator symbol_begin() const override
relocation_iterator section_rel_end(DataRefImpl Sec) const override
void moveSymbolNext(DataRefImpl &Symb) const override
uint64_t getSectionAlignment(DataRefImpl Sec) const override
uint64_t getRelocationOffset(DataRefImpl Rel) const override
Expected< SymbolRef::Type > getSymbolType(DataRefImpl Symb) const override
uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override
bool isSectionText(DataRefImpl Sec) const override
bool isSectionBSS(DataRefImpl Sec) const override
basic_symbol_iterator symbol_end() const override
Expected< uint32_t > getSymbolFlags(DataRefImpl Symb) const override
section_iterator section_begin() const override
bool isRelocatableObject() const override
True if this is a relocatable object (.o/.obj).
void moveRelocationNext(DataRefImpl &Rel) const override
uint32_t getSymbolSectionId(SymbolRef Sym) const
bool isSectionCompressed(DataRefImpl Sec) const override
bool isSectionVirtual(DataRefImpl Sec) const override
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override
void getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl< char > &Result) const override
StringRef getFileFormatName() const override
Expected< StringRef > getSymbolName(DataRefImpl Symb) const override
relocation_iterator section_rel_begin(DataRefImpl Sec) const override
uint8_t getBytesInAddress() const override
The number of bytes used to represent an address in this object file format.
WasmObjectFile(MemoryBufferRef Object, Error &Err)
section_iterator section_end() const override
Expected< ArrayRef< uint8_t > > getSectionContents(DataRefImpl Sec) const override
uint64_t getSectionIndex(DataRefImpl Sec) const override
uint32_t getSymbolAlignment(DataRefImpl Symb) const override
uint64_t getSectionSize(DataRefImpl Sec) const override
Triple::ArchType getArch() const override
uint64_t getRelocationType(DataRefImpl Rel) const override
const WasmSection & getWasmSection(const SectionRef &Section) const
Expected< section_iterator > getSymbolSection(DataRefImpl Symb) const override
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override
Expected< SubtargetFeatures > getFeatures() const override
const wasm::WasmObjectHeader & getHeader() const
void moveSectionNext(DataRefImpl &Sec) const override
uint32_t getNumImportedFunctions() const
Definition: Wasm.h:160
const wasm::WasmRelocation & getWasmRelocation(const RelocationRef &Ref) const
uint32_t getSymbolSize(SymbolRef Sym) const
ArrayRef< wasm::WasmFunction > functions() const
Definition: Wasm.h:155
const WasmSymbol & getWasmSymbol(const DataRefImpl &Symb) const
uint64_t getSectionAddress(DataRefImpl Sec) const override
Expected< uint64_t > getSymbolAddress(DataRefImpl Symb) const override
bool isSectionData(DataRefImpl Sec) const override
Expected< StringRef > getSectionName(DataRefImpl Sec) const override
bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")
static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]
Definition: Wasm.h:356
unsigned getBinding() const
Definition: Wasm.h:89
LLVM_DUMP_METHOD void dump() const
bool isTypeData() const
Definition: Wasm.h:59
bool isHidden() const
Definition: Wasm.h:93
wasm::WasmSymbolInfo Info
Definition: Wasm.h:48
void print(raw_ostream &Out) const
bool isDefined() const
Definition: Wasm.h:71
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
content_iterator< SectionRef > section_iterator
Definition: ObjectFile.h:47
content_iterator< RelocationRef > relocation_iterator
Definition: ObjectFile.h:77
uint32_t read32le(const void *P)
Definition: Endian.h:425
@ WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
Definition: Wasm.h:163
@ WASM_ELEM_SEGMENT_IS_DECLARATIVE
Definition: Wasm.h:161
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
Definition: Wasm.h:162
@ WASM_ELEM_SEGMENT_IS_PASSIVE
Definition: Wasm.h:160
const unsigned WASM_SYMBOL_UNDEFINED
Definition: Wasm.h:236
@ WASM_LIMITS_FLAG_HAS_MAX
Definition: Wasm.h:149
@ WASM_LIMITS_FLAG_IS_64
Definition: Wasm.h:151
@ WASM_EXTERNAL_TABLE
Definition: Wasm.h:85
@ WASM_EXTERNAL_FUNCTION
Definition: Wasm.h:84
@ WASM_EXTERNAL_TAG
Definition: Wasm.h:88
@ WASM_EXTERNAL_MEMORY
Definition: Wasm.h:86
@ WASM_EXTERNAL_GLOBAL
Definition: Wasm.h:87
@ WASM_NAMES_LOCAL
Definition: Wasm.h:178
@ WASM_NAMES_DATA_SEGMENT
Definition: Wasm.h:180
@ WASM_NAMES_GLOBAL
Definition: Wasm.h:179
@ WASM_NAMES_FUNCTION
Definition: Wasm.h:177
@ WASM_OPCODE_ARRAY_NEW_FIXED
Definition: Wasm.h:123
@ WASM_OPCODE_REF_I31
Definition: Wasm.h:124
@ WASM_OPCODE_ARRAY_NEW_DEFAULT
Definition: Wasm.h:122
@ WASM_OPCODE_STRUCT_NEW
Definition: Wasm.h:119
@ WASM_OPCODE_STRUCT_NEW_DEFAULT
Definition: Wasm.h:120
@ WASM_OPCODE_ARRAY_NEW
Definition: Wasm.h:121
@ WASM_TYPE_ARRAY
Definition: Wasm.h:74
@ WASM_TYPE_NULLABLE
Definition: Wasm.h:72
@ WASM_TYPE_I64
Definition: Wasm.h:55
@ WASM_TYPE_F64
Definition: Wasm.h:57
@ WASM_TYPE_FUNCREF
Definition: Wasm.h:63
@ WASM_TYPE_REC
Definition: Wasm.h:78
@ WASM_TYPE_EXTERNREF
Definition: Wasm.h:64
@ WASM_TYPE_SUB
Definition: Wasm.h:76
@ WASM_TYPE_FUNC
Definition: Wasm.h:73
@ WASM_TYPE_STRUCT
Definition: Wasm.h:75
@ WASM_TYPE_NONNULLABLE
Definition: Wasm.h:71
@ WASM_TYPE_I32
Definition: Wasm.h:54
@ WASM_TYPE_F32
Definition: Wasm.h:56
@ WASM_TYPE_V128
Definition: Wasm.h:58
@ WASM_TYPE_SUB_FINAL
Definition: Wasm.h:77
@ WASM_TYPE_EXNREF
Definition: Wasm.h:65
@ WASM_DATA_SEGMENT_IS_PASSIVE
Definition: Wasm.h:155
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
Definition: Wasm.h:156
const unsigned WASM_SYMBOL_BINDING_GLOBAL
Definition: Wasm.h:231
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
Definition: Wasm.h:165
@ WASM_OPCODE_I64_ADD
Definition: Wasm.h:109
@ WASM_OPCODE_I32_SUB
Definition: Wasm.h:107
@ WASM_OPCODE_F64_CONST
Definition: Wasm.h:105
@ WASM_OPCODE_END
Definition: Wasm.h:93
@ WASM_OPCODE_I64_MUL
Definition: Wasm.h:111
@ WASM_OPCODE_REF_NULL
Definition: Wasm.h:112
@ WASM_OPCODE_GC_PREFIX
Definition: Wasm.h:114
@ WASM_OPCODE_REF_FUNC
Definition: Wasm.h:113
@ WASM_OPCODE_F32_CONST
Definition: Wasm.h:104
@ WASM_OPCODE_GLOBAL_GET
Definition: Wasm.h:98
@ WASM_OPCODE_I64_SUB
Definition: Wasm.h:110
@ WASM_OPCODE_I32_MUL
Definition: Wasm.h:108
@ WASM_OPCODE_I32_ADD
Definition: Wasm.h:106
@ WASM_OPCODE_I64_CONST
Definition: Wasm.h:103
@ WASM_OPCODE_I32_CONST
Definition: Wasm.h:102
const uint32_t WasmMetadataVersion
Definition: Wasm.h:30
const unsigned WASM_SYMBOL_BINDING_WEAK
Definition: Wasm.h:232
const unsigned WASM_SYMBOL_BINDING_LOCAL
Definition: Wasm.h:233
WasmSymbolType
Definition: Wasm.h:208
@ WASM_SYMBOL_TYPE_GLOBAL
Definition: Wasm.h:211
@ WASM_SYMBOL_TYPE_DATA
Definition: Wasm.h:210
@ WASM_SYMBOL_TYPE_TAG
Definition: Wasm.h:213
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:214
@ WASM_SYMBOL_TYPE_SECTION
Definition: Wasm.h:212
@ WASM_SYMBOL_TYPE_FUNCTION
Definition: Wasm.h:209
const uint32_t WasmVersion
Definition: Wasm.h:28
const unsigned WASM_SYMBOL_BINDING_MASK
Definition: Wasm.h:228
@ WASM_DYLINK_NEEDED
Definition: Wasm.h:194
@ WASM_DYLINK_MEM_INFO
Definition: Wasm.h:193
@ WASM_DYLINK_EXPORT_INFO
Definition: Wasm.h:195
@ WASM_DYLINK_IMPORT_INFO
Definition: Wasm.h:196
NameType
Definition: Wasm.h:464
@ WASM_INIT_FUNCS
Definition: Wasm.h:186
@ WASM_COMDAT_INFO
Definition: Wasm.h:187
@ WASM_SEGMENT_INFO
Definition: Wasm.h:185
@ WASM_SYMBOL_TABLE
Definition: Wasm.h:188
@ WASM_COMDAT_SECTION
Definition: Wasm.h:204
@ WASM_COMDAT_FUNCTION
Definition: Wasm.h:202
@ WASM_COMDAT_DATA
Definition: Wasm.h:201
@ WASM_FEATURE_PREFIX_USED
Definition: Wasm.h:169
@ WASM_FEATURE_PREFIX_REQUIRED
Definition: Wasm.h:170
@ WASM_FEATURE_PREFIX_DISALLOWED
Definition: Wasm.h:171
@ WASM_SEC_CODE
Definition: Wasm.h:45
@ WASM_SEC_MEMORY
Definition: Wasm.h:40
@ WASM_SEC_IMPORT
Definition: Wasm.h:37
@ WASM_SEC_EXPORT
Definition: Wasm.h:42
@ WASM_SEC_DATACOUNT
Definition: Wasm.h:47
@ WASM_SEC_LAST_KNOWN
Definition: Wasm.h:49
@ WASM_SEC_CUSTOM
Definition: Wasm.h:35
@ WASM_SEC_FUNCTION
Definition: Wasm.h:38
@ WASM_SEC_ELEM
Definition: Wasm.h:44
@ WASM_SEC_START
Definition: Wasm.h:43
@ WASM_SEC_TABLE
Definition: Wasm.h:39
@ WASM_SEC_TYPE
Definition: Wasm.h:36
@ WASM_SEC_TAG
Definition: Wasm.h:48
@ WASM_SEC_GLOBAL
Definition: Wasm.h:41
@ WASM_SEC_DATA
Definition: Wasm.h:46
llvm::StringRef sectionTypeToString(uint32_t type)
Definition: Wasm.cpp:41
const unsigned WASM_SYMBOL_EXPLICIT_NAME
Definition: Wasm.h:238
const unsigned WASM_SYMBOL_ABSOLUTE
Definition: Wasm.h:241
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
std::string to_string(const T &Value)
Definition: ScopedPrinter.h:85
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:131
@ Import
Import information from summary.
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:165
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1286
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
@ Global
Append to llvm.global_dtors.
@ Ref
The access may reference the value stored in memory.
ArrayRef< uint8_t > Content
Definition: Wasm.h:115
std::vector< wasm::WasmRelocation > Relocations
Definition: Wasm.h:116
wasm::WasmDataSegment Data
Definition: Wasm.h:123
uint32_t SectionOffset
Definition: Wasm.h:122
ArrayRef< uint8_t > Content
Definition: Wasm.h:404
WasmInitExpr Offset
Definition: Wasm.h:402
uint32_t MemoryAlignment
Definition: Wasm.h:284
std::vector< StringRef > Needed
Definition: Wasm.h:287
std::vector< WasmDylinkExportInfo > ExportInfo
Definition: Wasm.h:289
std::vector< WasmDylinkImportInfo > ImportInfo
Definition: Wasm.h:288
uint32_t TableAlignment
Definition: Wasm.h:286
WasmInitExpr Offset
Definition: Wasm.h:421
std::vector< uint32_t > Functions
Definition: Wasm.h:422
StringRef Name
Definition: Wasm.h:304
uint32_t Index
Definition: Wasm.h:306
std::optional< StringRef > ExportName
Definition: Wasm.h:391
uint32_t CodeSectionOffset
Definition: Wasm.h:388
uint32_t Offset
Definition: Wasm.h:356
WasmGlobalType Type
Definition: Wasm.h:353
WasmLimits Memory
Definition: Wasm.h:374
StringRef Field
Definition: Wasm.h:368
WasmGlobalType Global
Definition: Wasm.h:372
StringRef Module
Definition: Wasm.h:367
uint32_t SigIndex
Definition: Wasm.h:371
WasmTableType Table
Definition: Wasm.h:373
union llvm::wasm::WasmInitExprMVP::@181 Value
WasmInitExprMVP Inst
Definition: Wasm.h:342
ArrayRef< uint8_t > Body
Definition: Wasm.h:343
std::vector< WasmInitFunc > InitFunctions
Definition: Wasm.h:479
std::vector< StringRef > Comdats
Definition: Wasm.h:480
std::vector< std::pair< std::string, std::string > > SDKs
Definition: Wasm.h:295
std::vector< std::pair< std::string, std::string > > Languages
Definition: Wasm.h:293
std::vector< std::pair< std::string, std::string > > Tools
Definition: Wasm.h:294
enum llvm::wasm::WasmSignature::@186 Kind
SmallVector< ValType, 1 > Returns
Definition: Wasm.h:488
SmallVector< ValType, 4 > Params
Definition: Wasm.h:489
WasmDataReference DataRef
Definition: Wasm.h:460
WasmLimits Limits
Definition: Wasm.h:317
WasmTableType Type
Definition: Wasm.h:322
StringRef SymbolName
Definition: Wasm.h:323
struct llvm::object::DataRefImpl::@359 d