LLVM 24.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/LEB128.h"
28#include <cassert>
29#include <cstdint>
30#include <cstring>
31
32#define DEBUG_TYPE "wasm-object"
33
34using namespace llvm;
35using namespace object;
36
38 Out << "Name=" << Info.Name
39 << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
40 << Twine::utohexstr(Info.Flags) << " [";
41 switch (getBinding()) {
42 case wasm::WASM_SYMBOL_BINDING_GLOBAL: Out << "global"; break;
43 case wasm::WASM_SYMBOL_BINDING_LOCAL: Out << "local"; break;
44 case wasm::WASM_SYMBOL_BINDING_WEAK: Out << "weak"; break;
45 }
46 if (isHidden())
47 Out << ", hidden";
48 else
49 Out << ", default";
51 Out << ", no_strip";
52 if (Info.Flags & wasm::WASM_SYMBOL_TLS)
53 Out << ", tls";
55 Out << ", absolute";
57 Out << ", exported";
58 if (isUndefined())
59 Out << ", undefined";
60 Out << "]";
61 if (!isTypeData()) {
62 Out << ", ElemIndex=" << Info.ElementIndex;
63 } else if (isDefined()) {
64 Out << ", Segment=" << Info.DataRef.Segment;
65 Out << ", Offset=" << Info.DataRef.Offset;
66 Out << ", Size=" << Info.DataRef.Size;
67 }
68}
69
70#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
72#endif
73
76 Error Err = Error::success();
77 auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
78 if (Err)
79 return std::move(Err);
80
81 return std::move(ObjectFile);
82}
83
84#define VARINT7_MAX ((1 << 7) - 1)
85#define VARINT7_MIN (-(1 << 7))
86#define VARUINT7_MAX (1 << 7)
87#define VARUINT1_MAX (1)
88
90 if (Ctx.Ptr == Ctx.End)
91 report_fatal_error("EOF while reading uint8");
92 return *Ctx.Ptr++;
93}
94
96 if (Ctx.Ptr + 4 > Ctx.End)
97 report_fatal_error("EOF while reading uint32");
98 uint32_t Result = support::endian::read32le(Ctx.Ptr);
99 Ctx.Ptr += 4;
100 return Result;
101}
102
104 if (Ctx.Ptr + 4 > Ctx.End)
105 report_fatal_error("EOF while reading float64");
106 int32_t Result = 0;
107 memcpy(&Result, Ctx.Ptr, sizeof(Result));
108 Ctx.Ptr += sizeof(Result);
109 return Result;
110}
111
113 if (Ctx.Ptr + 8 > Ctx.End)
114 report_fatal_error("EOF while reading float64");
115 int64_t Result = 0;
116 memcpy(&Result, Ctx.Ptr, sizeof(Result));
117 Ctx.Ptr += sizeof(Result);
118 return Result;
119}
120
122 unsigned Count;
123 const char *Error = nullptr;
124 uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
125 if (Error)
127 Ctx.Ptr += Count;
128 return Result;
129}
130
132 uint32_t StringLen = readULEB128(Ctx);
133 if (Ctx.Ptr + StringLen > Ctx.End)
134 report_fatal_error("EOF while reading string");
135 StringRef Return =
136 StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
137 Ctx.Ptr += StringLen;
138 return Return;
139}
140
142 unsigned Count;
143 const char *Error = nullptr;
144 uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
145 if (Error)
147 Ctx.Ptr += Count;
148 return Result;
149}
150
152 int64_t Result = readLEB128(Ctx);
153 if (Result > VARUINT1_MAX || Result < 0)
154 report_fatal_error("LEB is outside Varuint1 range");
155 return Result;
156}
157
159 int64_t Result = readLEB128(Ctx);
160 if (Result > INT32_MAX || Result < INT32_MIN)
161 report_fatal_error("LEB is outside Varint32 range");
162 return Result;
163}
164
166 uint64_t Result = readULEB128(Ctx);
167 if (Result > UINT32_MAX)
168 report_fatal_error("LEB is outside Varuint32 range");
169 return Result;
170}
171
173 return readLEB128(Ctx);
174}
175
179
181 return readUint8(Ctx);
182}
183
185 uint32_t Code) {
186 // only directly encoded FUNCREF/EXTERNREF/EXNREF are supported
187 // (not ref null func, ref null extern, or ref null exn)
188 switch (Code) {
197 return wasm::ValType(Code);
198 }
200 /* Discard HeapType */ readVarint64(Ctx);
201 }
203}
204
207 auto Start = Ctx.Ptr;
208
209 Expr.Extended = false;
210 Expr.Inst.Opcode = readOpcode(Ctx);
211 switch (Expr.Inst.Opcode) {
213 Expr.Inst.Value.Int32 = readVarint32(Ctx);
214 break;
216 Expr.Inst.Value.Int64 = readVarint64(Ctx);
217 break;
219 Expr.Inst.Value.Float32 = readFloat32(Ctx);
220 break;
222 Expr.Inst.Value.Float64 = readFloat64(Ctx);
223 break;
225 Expr.Inst.Value.Global = readULEB128(Ctx);
226 break;
228 /* Discard type */ parseValType(Ctx, readVaruint32(Ctx));
229 break;
230 }
231 default:
232 Expr.Extended = true;
233 }
234
235 if (!Expr.Extended) {
236 uint8_t EndOpcode = readOpcode(Ctx);
237 if (EndOpcode != wasm::WASM_OPCODE_END)
238 Expr.Extended = true;
239 }
240
241 if (Expr.Extended) {
242 Ctx.Ptr = Start;
243 while (true) {
244 uint8_t Opcode = readOpcode(Ctx);
245 switch (Opcode) {
251 readULEB128(Ctx);
252 break;
254 readFloat32(Ctx);
255 break;
257 readFloat64(Ctx);
258 break;
265 break;
267 break;
268 // The GC opcodes are in a separate (prefixed space). This flat switch
269 // structure works as long as there is no overlap between the GC and
270 // general opcodes used in init exprs.
275 readULEB128(Ctx); // heap type index
276 break;
278 readULEB128(Ctx); // heap type index
279 readULEB128(Ctx); // array size
280 break;
282 break;
284 Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);
285 return Error::success();
286 default:
287 return make_error<GenericBinaryError>("invalid opcode in init_expr: " +
288 Twine(unsigned(Opcode)),
290 }
291 }
292 }
293
294 return Error::success();
295}
296
298 wasm::WasmLimits Result;
299 Result.Flags = readVaruint32(Ctx);
300 Result.Minimum = readVaruint64(Ctx);
301 if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
302 Result.Maximum = readVaruint64(Ctx);
303 if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_PAGE_SIZE) {
304 uint32_t PageSizeLog2 = readVaruint32(Ctx);
305 if (PageSizeLog2 >= 32)
306 report_fatal_error("log2(wasm page size) too large");
307 Result.PageSize = 1 << PageSizeLog2;
308 }
309 return Result;
310}
311
313 wasm::WasmTableType TableType;
314 auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
315 TableType.ElemType = ElemType;
316 TableType.Limits = readLimits(Ctx);
317 return TableType;
318}
319
321 WasmSectionOrderChecker &Checker) {
322 Section.Type = readUint8(Ctx);
323 LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
324 // When reading the section's size, store the size of the LEB used to encode
325 // it. This allows objcopy/strip to reproduce the binary identically.
326 const uint8_t *PreSizePtr = Ctx.Ptr;
328 Section.HeaderSecSizeEncodingLen = Ctx.Ptr - PreSizePtr;
329 Section.Offset = Ctx.Ptr - Ctx.Start;
330 if (Size == 0)
331 return make_error<StringError>("zero length section",
333 if (Ctx.Ptr + Size > Ctx.End)
334 return make_error<StringError>("section too large",
336 if (Section.Type == wasm::WASM_SEC_CUSTOM) {
338 SectionCtx.Start = Ctx.Ptr;
339 SectionCtx.Ptr = Ctx.Ptr;
340 SectionCtx.End = Ctx.Ptr + Size;
341
342 Section.Name = readString(SectionCtx);
343
344 uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
345 Ctx.Ptr += SectionNameSize;
346 Size -= SectionNameSize;
347 }
348
349 if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
350 return make_error<StringError>("out of order section type: " +
351 llvm::to_string(Section.Type),
353 }
354
355 Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
356 Ctx.Ptr += Size;
357 return Error::success();
358}
359
361 : ObjectFile(Binary::ID_Wasm, Buffer) {
362 ErrorAsOutParameter ErrAsOutParam(Err);
363 Header.Magic = getData().substr(0, 4);
364 if (Header.Magic != StringRef("\0asm", 4)) {
365 Err = make_error<StringError>("invalid magic number",
367 return;
368 }
369
370 ReadContext Ctx;
371 Ctx.Start = getData().bytes_begin();
372 Ctx.Ptr = Ctx.Start + 4;
373 Ctx.End = Ctx.Start + getData().size();
374
375 if (Ctx.Ptr + 4 > Ctx.End) {
376 Err = make_error<StringError>("missing version number",
378 return;
379 }
380
381 Header.Version = readUint32(Ctx);
382 if (Header.Version != wasm::WasmVersion) {
383 Err = make_error<StringError>("invalid version number: " +
384 Twine(Header.Version),
386 return;
387 }
388
390 while (Ctx.Ptr < Ctx.End) {
391 WasmSection Sec;
392 if ((Err = readSection(Sec, Ctx, Checker)))
393 return;
394 if ((Err = parseSection(Sec)))
395 return;
396
397 Sections.push_back(Sec);
398 }
399}
400
401Error WasmObjectFile::parseSection(WasmSection &Sec) {
402 ReadContext Ctx;
403 Ctx.Start = Sec.Content.data();
404 Ctx.End = Ctx.Start + Sec.Content.size();
405 Ctx.Ptr = Ctx.Start;
406 switch (Sec.Type) {
408 return parseCustomSection(Sec, Ctx);
410 return parseTypeSection(Ctx);
412 return parseImportSection(Ctx);
414 return parseFunctionSection(Ctx);
416 return parseTableSection(Ctx);
418 return parseMemorySection(Ctx);
420 return parseTagSection(Ctx);
422 return parseGlobalSection(Ctx);
424 return parseExportSection(Ctx);
426 return parseStartSection(Ctx);
428 return parseElemSection(Ctx);
430 return parseCodeSection(Ctx);
432 return parseDataSection(Ctx);
434 return parseDataCountSection(Ctx);
435 default:
437 "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
438 }
439}
440
441Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
442 // Legacy "dylink" section support.
443 // See parseDylink0Section for the current "dylink.0" section parsing.
444 HasDylinkSection = true;
445 DylinkInfo.MemorySize = readVaruint32(Ctx);
446 DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
447 DylinkInfo.TableSize = readVaruint32(Ctx);
448 DylinkInfo.TableAlignment = readVaruint32(Ctx);
450 while (Count--) {
451 DylinkInfo.Needed.push_back(readString(Ctx));
452 }
453
454 if (Ctx.Ptr != Ctx.End)
455 return make_error<GenericBinaryError>("dylink section ended prematurely",
457 return Error::success();
458}
459
460Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
461 // See
462 // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
463 HasDylinkSection = true;
464
465 const uint8_t *OrigEnd = Ctx.End;
466 while (Ctx.Ptr < OrigEnd) {
467 Ctx.End = OrigEnd;
468 uint8_t Type = readUint8(Ctx);
469 uint32_t Size = readVaruint32(Ctx);
470 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
471 << "\n");
472 Ctx.End = Ctx.Ptr + Size;
473 uint32_t Count;
474 switch (Type) {
476 DylinkInfo.MemorySize = readVaruint32(Ctx);
477 DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
478 DylinkInfo.TableSize = readVaruint32(Ctx);
479 DylinkInfo.TableAlignment = readVaruint32(Ctx);
480 break;
482 Count = readVaruint32(Ctx);
483 while (Count--) {
484 DylinkInfo.Needed.push_back(readString(Ctx));
485 }
486 break;
488 uint32_t Count = readVaruint32(Ctx);
489 while (Count--) {
490 DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)});
491 }
492 break;
493 }
495 uint32_t Count = readVaruint32(Ctx);
496 while (Count--) {
497 DylinkInfo.ImportInfo.push_back(
498 {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
499 }
500 break;
501 }
503 Count = readVaruint32(Ctx);
504 while (Count--) {
505 DylinkInfo.RuntimePath.push_back(readString(Ctx));
506 }
507 break;
508 }
510 DylinkInfo.TargetArch = readString(Ctx);
511 break;
512 default:
513 LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
514 Ctx.Ptr += Size;
515 break;
516 }
517 if (Ctx.Ptr != Ctx.End) {
519 "dylink.0 sub-section ended prematurely", object_error::parse_failed);
520 }
521 }
522
523 if (Ctx.Ptr != Ctx.End)
524 return make_error<GenericBinaryError>("dylink.0 section ended prematurely",
526 return Error::success();
527}
528
529Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
530 llvm::DenseSet<uint64_t> SeenFunctions;
531 llvm::DenseSet<uint64_t> SeenGlobals;
532 llvm::DenseSet<uint64_t> SeenSegments;
533
534 // If we have linking section (symbol table) or if we are parsing a DSO
535 // then we don't use the name section for symbol information.
536 bool PopulateSymbolTable = !HasLinkingSection && !HasDylinkSection;
537
538 // If we are using the name section for symbol information then it will
539 // supersede any symbols created by the export section.
540 if (PopulateSymbolTable)
541 Symbols.clear();
542
543 while (Ctx.Ptr < Ctx.End) {
544 uint8_t Type = readUint8(Ctx);
545 uint32_t Size = readVaruint32(Ctx);
546 const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
547
548 switch (Type) {
552 uint32_t Count = readVaruint32(Ctx);
553 while (Count--) {
554 uint32_t Index = readVaruint32(Ctx);
555 StringRef Name = readString(Ctx);
557 wasm::WasmSymbolInfo Info{Name,
559 /* Flags */ 0,
560 /* ImportModule */ std::nullopt,
561 /* ImportName */ std::nullopt,
562 /* ExportName */ std::nullopt,
563 {/* ElementIndex */ Index}};
564 const wasm::WasmSignature *Signature = nullptr;
565 const wasm::WasmGlobalType *GlobalType = nullptr;
566 const wasm::WasmTableType *TableType = nullptr;
568 if (!SeenFunctions.insert(Index).second)
570 "function named more than once", object_error::parse_failed);
571 if (!isValidFunctionIndex(Index) || Name.empty())
572 return make_error<GenericBinaryError>("invalid function name entry",
574
575 if (isDefinedFunctionIndex(Index)) {
576 wasm::WasmFunction &F = getDefinedFunction(Index);
577 F.DebugName = Name;
578 Signature = &Signatures[F.SigIndex];
579 if (F.ExportName) {
580 Info.ExportName = F.ExportName;
582 } else {
584 }
585 } else {
587 }
588 } else if (Type == wasm::WASM_NAMES_GLOBAL) {
589 if (!SeenGlobals.insert(Index).second)
590 return make_error<GenericBinaryError>("global named more than once",
592 if (!isValidGlobalIndex(Index) || Name.empty())
593 return make_error<GenericBinaryError>("invalid global name entry",
595 nameType = wasm::NameType::GLOBAL;
597 if (isDefinedGlobalIndex(Index)) {
598 GlobalType = &getDefinedGlobal(Index).Type;
599 } else {
601 }
602 } else {
603 if (!SeenSegments.insert(Index).second)
605 "segment named more than once", object_error::parse_failed);
606 if (Index >= DataSegments.size())
607 return make_error<GenericBinaryError>("invalid data segment name entry",
612 assert(Index < DataSegments.size());
613 Info.DataRef = wasm::WasmDataReference{
614 Index, 0, DataSegments[Index].Data.Content.size()};
615 }
616 DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
617 if (PopulateSymbolTable)
618 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
619 }
620 break;
621 }
622 // Ignore local names for now
624 default:
625 Ctx.Ptr += Size;
626 break;
627 }
628 if (Ctx.Ptr != SubSectionEnd)
630 "name sub-section ended prematurely", object_error::parse_failed);
631 }
632
633 if (Ctx.Ptr != Ctx.End)
634 return make_error<GenericBinaryError>("name section ended prematurely",
636 return Error::success();
637}
638
639Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
640 HasLinkingSection = true;
641
642 LinkingData.Version = readVaruint32(Ctx);
643 if (LinkingData.Version != wasm::WasmMetadataVersion) {
645 "unexpected metadata version: " + Twine(LinkingData.Version) +
646 " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
648 }
649
650 const uint8_t *OrigEnd = Ctx.End;
651 while (Ctx.Ptr < OrigEnd) {
652 Ctx.End = OrigEnd;
653 uint8_t Type = readUint8(Ctx);
654 uint32_t Size = readVaruint32(Ctx);
655 LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
656 << "\n");
657 Ctx.End = Ctx.Ptr + Size;
658 switch (Type) {
660 if (Error Err = parseLinkingSectionSymtab(Ctx))
661 return Err;
662 break;
664 uint32_t Count = readVaruint32(Ctx);
665 if (Count > DataSegments.size())
666 return make_error<GenericBinaryError>("too many segment names",
668 for (uint32_t I = 0; I < Count; I++) {
669 DataSegments[I].Data.Name = readString(Ctx);
670 DataSegments[I].Data.Alignment = readVaruint32(Ctx);
671 if (DataSegments[I].Data.Alignment > 32)
673 "invalid data segment alignment: `" + DataSegments[I].Data.Name +
674 "` (alignment: " + Twine(DataSegments[I].Data.Alignment) +
675 ")",
677 DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
678 }
679 break;
680 }
682 uint32_t Count = readVaruint32(Ctx);
683 LinkingData.InitFunctions.reserve(Count);
684 for (uint32_t I = 0; I < Count; I++) {
685 wasm::WasmInitFunc Init;
686 Init.Priority = readVaruint32(Ctx);
687 Init.Symbol = readVaruint32(Ctx);
688 if (!isValidFunctionSymbol(Init.Symbol))
689 return make_error<GenericBinaryError>("invalid function symbol: " +
690 Twine(Init.Symbol),
692 LinkingData.InitFunctions.emplace_back(Init);
693 }
694 break;
695 }
697 if (Error Err = parseLinkingSectionComdat(Ctx))
698 return Err;
699 break;
701 LinkingData.TargetArch = readString(Ctx);
702 break;
703 default:
704 Ctx.Ptr += Size;
705 break;
706 }
707 if (Ctx.Ptr != Ctx.End)
709 "linking sub-section ended prematurely", object_error::parse_failed);
710 }
711 if (Ctx.Ptr != OrigEnd)
712 return make_error<GenericBinaryError>("linking section ended prematurely",
714 return Error::success();
715}
716
717Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
718 uint32_t Count = readVaruint32(Ctx);
719 // Clear out any symbol information that was derived from the exports
720 // section.
721 Symbols.clear();
722 Symbols.reserve(Count);
723 StringSet<> SymbolNames;
724
725 std::vector<wasm::WasmImport *> ImportedGlobals;
726 std::vector<wasm::WasmImport *> ImportedFunctions;
727 std::vector<wasm::WasmImport *> ImportedTags;
728 std::vector<wasm::WasmImport *> ImportedTables;
729 ImportedGlobals.reserve(Imports.size());
730 ImportedFunctions.reserve(Imports.size());
731 ImportedTags.reserve(Imports.size());
732 ImportedTables.reserve(Imports.size());
733 for (auto &I : Imports) {
735 ImportedFunctions.emplace_back(&I);
736 else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
737 ImportedGlobals.emplace_back(&I);
738 else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
739 ImportedTags.emplace_back(&I);
740 else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
741 ImportedTables.emplace_back(&I);
742 }
743
744 while (Count--) {
745 wasm::WasmSymbolInfo Info;
746 const wasm::WasmSignature *Signature = nullptr;
747 const wasm::WasmGlobalType *GlobalType = nullptr;
748 const wasm::WasmTableType *TableType = nullptr;
749
750 Info.Kind = readUint8(Ctx);
751 Info.Flags = readVaruint32(Ctx);
752 bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
753
754 switch (Info.Kind) {
756 Info.ElementIndex = readVaruint32(Ctx);
757 if (!isValidFunctionIndex(Info.ElementIndex) ||
758 IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
759 return make_error<GenericBinaryError>("invalid function symbol index",
761 if (IsDefined) {
762 Info.Name = readString(Ctx);
763 unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
764 wasm::WasmFunction &Function = Functions[FuncIndex];
765 Signature = &Signatures[Function.SigIndex];
766 if (Function.SymbolName.empty())
767 Function.SymbolName = Info.Name;
768 } else {
769 wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
770 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
771 Info.Name = readString(Ctx);
772 Info.ImportName = Import.Field;
773 } else {
774 Info.Name = Import.Field;
775 }
776 Signature = &Signatures[Import.SigIndex];
777 Info.ImportModule = Import.Module;
778 }
779 break;
780
782 Info.ElementIndex = readVaruint32(Ctx);
783 if (!isValidGlobalIndex(Info.ElementIndex) ||
784 IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
785 return make_error<GenericBinaryError>("invalid global symbol index",
787 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
789 return make_error<GenericBinaryError>("undefined weak global symbol",
791 if (IsDefined) {
792 Info.Name = readString(Ctx);
793 unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
794 wasm::WasmGlobal &Global = Globals[GlobalIndex];
795 GlobalType = &Global.Type;
796 if (Global.SymbolName.empty())
797 Global.SymbolName = Info.Name;
798 } else {
799 wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
800 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
801 Info.Name = readString(Ctx);
802 Info.ImportName = Import.Field;
803 } else {
804 Info.Name = Import.Field;
805 }
806 GlobalType = &Import.Global;
807 Info.ImportModule = Import.Module;
808 }
809 break;
810
812 Info.ElementIndex = readVaruint32(Ctx);
813 if (!isValidTableNumber(Info.ElementIndex) ||
814 IsDefined != isDefinedTableNumber(Info.ElementIndex))
815 return make_error<GenericBinaryError>("invalid table symbol index",
817 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
819 return make_error<GenericBinaryError>("undefined weak table symbol",
821 if (IsDefined) {
822 Info.Name = readString(Ctx);
823 unsigned TableNumber = Info.ElementIndex - NumImportedTables;
824 wasm::WasmTable &Table = Tables[TableNumber];
825 TableType = &Table.Type;
826 if (Table.SymbolName.empty())
827 Table.SymbolName = Info.Name;
828 } else {
829 wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
830 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
831 Info.Name = readString(Ctx);
832 Info.ImportName = Import.Field;
833 } else {
834 Info.Name = Import.Field;
835 }
836 TableType = &Import.Table;
837 Info.ImportModule = Import.Module;
838 }
839 break;
840
842 Info.Name = readString(Ctx);
843 if (IsDefined) {
844 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
848 "common symbols cannot be absolute: " + Info.Name,
850 auto Size = readVaruint64(Ctx);
851 auto Alignment = readUint8(Ctx);
852 if (Alignment > 32)
854 "invalid common symbol alignment: `" + Info.Name +
855 "` (alignment: " + Twine(unsigned(Alignment)) + ")",
857 Info.CommonRef = wasm::WasmCommonReference{Size, Alignment};
858 } else {
859 auto Index = readVaruint32(Ctx);
860 auto Offset = readVaruint64(Ctx);
861 auto Size = readVaruint64(Ctx);
862 if (!(Info.Flags & wasm::WASM_SYMBOL_ABSOLUTE)) {
863 if (Index >= DataSegments.size())
865 "invalid data segment index: " + Twine(Index),
867 size_t SegmentSize = DataSegments[Index].Data.Content.size();
868 if (Offset > SegmentSize)
870 "invalid data symbol offset: `" + Info.Name +
871 "` (offset: " + Twine(Offset) +
872 " segment size: " + Twine(SegmentSize) + ")",
874 }
875 Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
876 }
877 }
878 break;
879
881 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
884 "section symbols must have local binding",
886 Info.ElementIndex = readVaruint32(Ctx);
887 if (Info.ElementIndex >= Sections.size())
888 return make_error<GenericBinaryError>("invalid section symbol index",
890 if (Sections[Info.ElementIndex].Type != wasm::WASM_SEC_CUSTOM)
892 "section symbols must reference custom sections",
894 // Use somewhat unique section name as symbol name.
895 StringRef SectionName = Sections[Info.ElementIndex].Name;
896 Info.Name = SectionName;
897 break;
898 }
899
901 Info.ElementIndex = readVaruint32(Ctx);
902 if (!isValidTagIndex(Info.ElementIndex) ||
903 IsDefined != isDefinedTagIndex(Info.ElementIndex))
904 return make_error<GenericBinaryError>("invalid tag symbol index",
906 if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
908 return make_error<GenericBinaryError>("undefined weak global symbol",
910 if (IsDefined) {
911 Info.Name = readString(Ctx);
912 unsigned TagIndex = Info.ElementIndex - NumImportedTags;
913 wasm::WasmTag &Tag = Tags[TagIndex];
914 Signature = &Signatures[Tag.SigIndex];
915 if (Tag.SymbolName.empty())
916 Tag.SymbolName = Info.Name;
917
918 } else {
919 wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
920 if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
921 Info.Name = readString(Ctx);
922 Info.ImportName = Import.Field;
923 } else {
924 Info.Name = Import.Field;
925 }
926 Signature = &Signatures[Import.SigIndex];
927 Info.ImportModule = Import.Module;
928 }
929 break;
930 }
931
932 default:
933 return make_error<GenericBinaryError>("invalid symbol type: " +
934 Twine(unsigned(Info.Kind)),
936 }
937
938 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
940 !SymbolNames.insert(Info.Name).second)
941 return make_error<GenericBinaryError>("duplicate symbol name " +
942 Twine(Info.Name),
944 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
945 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
946 }
947
948 return Error::success();
949}
950
951Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
952 uint32_t ComdatCount = readVaruint32(Ctx);
953 StringSet<> ComdatSet;
954 for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
955 StringRef Name = readString(Ctx);
956 if (Name.empty() || !ComdatSet.insert(Name).second)
957 return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
958 Twine(Name),
960 LinkingData.Comdats.emplace_back(Name);
961 uint32_t Flags = readVaruint32(Ctx);
962 if (Flags != 0)
963 return make_error<GenericBinaryError>("unsupported COMDAT flags",
965
966 uint32_t EntryCount = readVaruint32(Ctx);
967 while (EntryCount--) {
968 unsigned Kind = readVaruint32(Ctx);
969 unsigned Index = readVaruint32(Ctx);
970 switch (Kind) {
971 default:
972 return make_error<GenericBinaryError>("invalid COMDAT entry type",
975 if (Index >= DataSegments.size())
977 "COMDAT data index out of range", object_error::parse_failed);
978 if (DataSegments[Index].Data.Comdat != UINT32_MAX)
979 return make_error<GenericBinaryError>("data segment in two COMDATs",
981 DataSegments[Index].Data.Comdat = ComdatIndex;
982 break;
984 if (!isDefinedFunctionIndex(Index))
986 "COMDAT function index out of range", object_error::parse_failed);
987 if (getDefinedFunction(Index).Comdat != UINT32_MAX)
988 return make_error<GenericBinaryError>("function in two COMDATs",
990 getDefinedFunction(Index).Comdat = ComdatIndex;
991 break;
993 if (Index >= Sections.size())
995 "COMDAT section index out of range", object_error::parse_failed);
996 if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
998 "non-custom section in a COMDAT", object_error::parse_failed);
999 Sections[Index].Comdat = ComdatIndex;
1000 break;
1001 }
1002 }
1003 }
1004 return Error::success();
1005}
1006
1007Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
1008 llvm::SmallSet<StringRef, 3> FieldsSeen;
1009 uint32_t Fields = readVaruint32(Ctx);
1010 for (size_t I = 0; I < Fields; ++I) {
1011 StringRef FieldName = readString(Ctx);
1012 if (!FieldsSeen.insert(FieldName).second)
1014 "producers section does not have unique fields",
1016 std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
1017 if (FieldName == "language") {
1018 ProducerVec = &ProducerInfo.Languages;
1019 } else if (FieldName == "processed-by") {
1020 ProducerVec = &ProducerInfo.Tools;
1021 } else if (FieldName == "sdk") {
1022 ProducerVec = &ProducerInfo.SDKs;
1023 } else {
1025 "producers section field is not named one of language, processed-by, "
1026 "or sdk",
1028 }
1029 uint32_t ValueCount = readVaruint32(Ctx);
1030 llvm::SmallSet<StringRef, 8> ProducersSeen;
1031 for (size_t J = 0; J < ValueCount; ++J) {
1032 StringRef Name = readString(Ctx);
1033 StringRef Version = readString(Ctx);
1034 if (!ProducersSeen.insert(Name).second) {
1036 "producers section contains repeated producer",
1038 }
1039 ProducerVec->emplace_back(std::string(Name), std::string(Version));
1040 }
1041 }
1042 if (Ctx.Ptr != Ctx.End)
1043 return make_error<GenericBinaryError>("producers section ended prematurely",
1045 return Error::success();
1046}
1047
1048Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
1049 llvm::SmallSet<std::string, 8> FeaturesSeen;
1050 uint32_t FeatureCount = readVaruint32(Ctx);
1051 for (size_t I = 0; I < FeatureCount; ++I) {
1052 wasm::WasmFeatureEntry Feature;
1053 Feature.Prefix = readUint8(Ctx);
1054 switch (Feature.Prefix) {
1057 break;
1058 default:
1059 return make_error<GenericBinaryError>("unknown feature policy prefix",
1061 }
1062 Feature.Name = std::string(readString(Ctx));
1063 if (!FeaturesSeen.insert(Feature.Name).second)
1065 "target features section contains repeated feature \"" +
1066 Feature.Name + "\"",
1068 TargetFeatures.push_back(Feature);
1069 }
1070 if (Ctx.Ptr != Ctx.End)
1072 "target features section ended prematurely",
1074 return Error::success();
1075}
1076
1077Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
1078 uint32_t SectionIndex = readVaruint32(Ctx);
1079 if (SectionIndex >= Sections.size())
1080 return make_error<GenericBinaryError>("invalid section index",
1082 WasmSection &Section = Sections[SectionIndex];
1083 uint32_t RelocCount = readVaruint32(Ctx);
1084 uint32_t EndOffset = Section.Content.size();
1085 uint32_t PreviousOffset = 0;
1086 while (RelocCount--) {
1087 wasm::WasmRelocation Reloc = {};
1088 uint32_t type = readVaruint32(Ctx);
1089 Reloc.Type = type;
1090 Reloc.Offset = readVaruint32(Ctx);
1091 if (Reloc.Offset < PreviousOffset)
1092 return make_error<GenericBinaryError>("relocations not in offset order",
1094
1095 auto badReloc = [&](StringRef msg) {
1096 if (Reloc.Index >= Symbols.size())
1098 msg + ": index " + Twine(Reloc.Index) + " out of range",
1101 msg + ": " + Twine(Symbols[Reloc.Index].Info.Name),
1103 };
1104
1105 PreviousOffset = Reloc.Offset;
1106 Reloc.Index = readVaruint32(Ctx);
1107 switch (type) {
1108 case wasm::R_WASM_FUNCTION_INDEX_LEB:
1109 case wasm::R_WASM_FUNCTION_INDEX_I32:
1110 case wasm::R_WASM_TABLE_INDEX_SLEB:
1111 case wasm::R_WASM_TABLE_INDEX_SLEB64:
1112 case wasm::R_WASM_TABLE_INDEX_I32:
1113 case wasm::R_WASM_TABLE_INDEX_I64:
1114 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
1115 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
1116 if (!isValidFunctionSymbol(Reloc.Index))
1117 return badReloc("invalid function relocation");
1118 break;
1119 case wasm::R_WASM_TABLE_NUMBER_LEB:
1120 if (!isValidTableSymbol(Reloc.Index))
1121 return badReloc("invalid table relocation");
1122 break;
1123 case wasm::R_WASM_TYPE_INDEX_LEB:
1124 if (Reloc.Index >= Signatures.size())
1125 return badReloc("invalid relocation type index");
1126 break;
1127 case wasm::R_WASM_GLOBAL_INDEX_LEB:
1128 // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
1129 // symbols to refer to their GOT entries.
1130 if (!isValidGlobalSymbol(Reloc.Index) &&
1131 !isValidDataSymbol(Reloc.Index) &&
1132 !isValidFunctionSymbol(Reloc.Index))
1133 return badReloc("invalid global relocation");
1134 break;
1135 case wasm::R_WASM_GLOBAL_INDEX_I32:
1136 if (!isValidGlobalSymbol(Reloc.Index))
1137 return badReloc("invalid global relocation");
1138 break;
1139 case wasm::R_WASM_TAG_INDEX_LEB:
1140 if (!isValidTagSymbol(Reloc.Index))
1141 return badReloc("invalid tag relocation");
1142 break;
1143 case wasm::R_WASM_MEMORY_ADDR_LEB:
1144 case wasm::R_WASM_MEMORY_ADDR_SLEB:
1145 case wasm::R_WASM_MEMORY_ADDR_I32:
1146 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1147 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1148 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1149 if (!isValidDataSymbol(Reloc.Index))
1150 return badReloc("invalid data relocation");
1151 Reloc.Addend = readVarint32(Ctx);
1152 break;
1153 case wasm::R_WASM_MEMORY_ADDR_LEB64:
1154 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1155 case wasm::R_WASM_MEMORY_ADDR_I64:
1156 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1157 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1158 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I64:
1159 if (!isValidDataSymbol(Reloc.Index))
1160 return badReloc("invalid data relocation");
1161 Reloc.Addend = readVarint64(Ctx);
1162 break;
1163 case wasm::R_WASM_FUNCTION_OFFSET_I32:
1164 if (!isValidFunctionSymbol(Reloc.Index))
1165 return badReloc("invalid function relocation");
1166 Reloc.Addend = readVarint32(Ctx);
1167 break;
1168 case wasm::R_WASM_FUNCTION_OFFSET_I64:
1169 if (!isValidFunctionSymbol(Reloc.Index))
1170 return badReloc("invalid function relocation");
1171 Reloc.Addend = readVarint64(Ctx);
1172 break;
1173 case wasm::R_WASM_SECTION_OFFSET_I32:
1174 if (!isValidSectionSymbol(Reloc.Index))
1175 return badReloc("invalid section relocation");
1176 Reloc.Addend = readVarint32(Ctx);
1177 break;
1178 default:
1179 return make_error<GenericBinaryError>("invalid relocation type: " +
1180 Twine(type),
1182 }
1183
1184 // Relocations must fit inside the section, and must appear in order. They
1185 // also shouldn't overlap a function/element boundary, but we don't bother
1186 // to check that.
1187 uint64_t Size = 5;
1188 if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1189 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1190 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1191 Size = 10;
1192 if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1193 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1194 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1195 Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1196 Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1197 Reloc.Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
1198 Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1199 Size = 4;
1200 if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1201 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1202 Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
1203 Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I64)
1204 Size = 8;
1205 if (Reloc.Offset + Size > EndOffset)
1206 return make_error<GenericBinaryError>("invalid relocation offset",
1208
1209 Section.Relocations.push_back(Reloc);
1210 }
1211 if (Ctx.Ptr != Ctx.End)
1212 return make_error<GenericBinaryError>("reloc section ended prematurely",
1214 return Error::success();
1215}
1216
1217Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
1218 if (Sec.Name == "dylink") {
1219 if (Error Err = parseDylinkSection(Ctx))
1220 return Err;
1221 } else if (Sec.Name == "dylink.0") {
1222 if (Error Err = parseDylink0Section(Ctx))
1223 return Err;
1224 } else if (Sec.Name == "name") {
1225 if (Error Err = parseNameSection(Ctx))
1226 return Err;
1227 } else if (Sec.Name == "linking") {
1228 if (Error Err = parseLinkingSection(Ctx))
1229 return Err;
1230 } else if (Sec.Name == "producers") {
1231 if (Error Err = parseProducersSection(Ctx))
1232 return Err;
1233 } else if (Sec.Name == "target_features") {
1234 if (Error Err = parseTargetFeaturesSection(Ctx))
1235 return Err;
1236 } else if (Sec.Name.starts_with("reloc.")) {
1237 if (Error Err = parseRelocSection(Sec.Name, Ctx))
1238 return Err;
1239 }
1240 return Error::success();
1241}
1242
1243Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1244 auto parseFieldDef = [&]() {
1245 uint32_t TypeCode = readVaruint32((Ctx));
1246 /* Discard StorageType */ parseValType(Ctx, TypeCode);
1247 /* Discard Mutability */ readVaruint32(Ctx);
1248 };
1249
1250 uint32_t Count = readVaruint32(Ctx);
1251 Signatures.reserve(Count);
1252 while (Count--) {
1253 wasm::WasmSignature Sig;
1254 uint8_t Form = readUint8(Ctx);
1255 if (Form == wasm::WASM_TYPE_REC) {
1256 // Rec groups expand the type index space (beyond what was declared at
1257 // the top of the section, and also consume one element in that space.
1258 uint32_t RecSize = readVaruint32(Ctx);
1259 if (RecSize == 0)
1260 return make_error<GenericBinaryError>("Rec group size cannot be 0",
1262 Signatures.reserve(Signatures.size() + RecSize);
1263 Count += RecSize;
1265 Signatures.push_back(std::move(Sig));
1266 HasUnmodeledTypes = true;
1267 continue;
1268 }
1269 if (Form != wasm::WASM_TYPE_FUNC) {
1270 // Currently LLVM only models function types, and not other composite
1271 // types. Here we parse the type declarations just enough to skip past
1272 // them in the binary.
1273 if (Form == wasm::WASM_TYPE_SUB || Form == wasm::WASM_TYPE_SUB_FINAL) {
1274 uint32_t Supers = readVaruint32(Ctx);
1275 if (Supers > 0) {
1276 if (Supers != 1)
1278 "Invalid number of supertypes", object_error::parse_failed);
1279 /* Discard SuperIndex */ readVaruint32(Ctx);
1280 }
1281 Form = readVaruint32(Ctx);
1282 }
1283 if (Form == wasm::WASM_TYPE_STRUCT) {
1284 uint32_t FieldCount = readVaruint32(Ctx);
1285 while (FieldCount--) {
1286 parseFieldDef();
1287 }
1288 } else if (Form == wasm::WASM_TYPE_ARRAY) {
1289 parseFieldDef();
1290 } else {
1291 return make_error<GenericBinaryError>("bad form",
1293 }
1295 Signatures.push_back(std::move(Sig));
1296 HasUnmodeledTypes = true;
1297 continue;
1298 }
1299
1300 uint32_t ParamCount = readVaruint32(Ctx);
1301 Sig.Params.reserve(ParamCount);
1302 while (ParamCount--) {
1303 uint32_t ParamType = readUint8(Ctx);
1304 Sig.Params.push_back(parseValType(Ctx, ParamType));
1305 }
1306 uint32_t ReturnCount = readVaruint32(Ctx);
1307 while (ReturnCount--) {
1308 uint32_t ReturnType = readUint8(Ctx);
1309 Sig.Returns.push_back(parseValType(Ctx, ReturnType));
1310 }
1311
1312 Signatures.push_back(std::move(Sig));
1313 }
1314 if (Ctx.Ptr != Ctx.End)
1315 return make_error<GenericBinaryError>("type section ended prematurely",
1317 return Error::success();
1318}
1319
1320Error WasmObjectFile::parseImport(ReadContext &Ctx, wasm::WasmImport &Im) {
1321 switch (Im.Kind) {
1323 NumImportedFunctions++;
1324 Im.SigIndex = readVaruint32(Ctx);
1325 if (Im.SigIndex >= Signatures.size())
1326 return make_error<GenericBinaryError>("invalid function type",
1328 break;
1330 NumImportedGlobals++;
1331 Im.Global.Type = readUint8(Ctx);
1332 Im.Global.Mutable = readVaruint1(Ctx);
1333 break;
1335 Im.Memory = readLimits(Ctx);
1337 HasMemory64 = true;
1338 break;
1340 Im.Table = readTableType(Ctx);
1341 NumImportedTables++;
1342 auto ElemType = Im.Table.ElemType;
1343 if (ElemType != wasm::ValType::FUNCREF &&
1344 ElemType != wasm::ValType::EXTERNREF &&
1345 ElemType != wasm::ValType::EXNREF &&
1346 ElemType != wasm::ValType::OTHERREF)
1347 return make_error<GenericBinaryError>("invalid table element type",
1349 break;
1350 }
1352 NumImportedTags++;
1353 if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1354 return make_error<GenericBinaryError>("invalid attribute",
1356 Im.SigIndex = readVaruint32(Ctx);
1357 if (Im.SigIndex >= Signatures.size())
1358 return make_error<GenericBinaryError>("invalid tag type",
1360 break;
1361 default:
1362 return make_error<GenericBinaryError>("unexpected import kind: " +
1363 Twine(unsigned(Im.Kind)),
1365 }
1366 Imports.push_back(Im);
1367 return Error::success();
1368}
1369
1370Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1371 uint32_t Count = readVaruint32(Ctx);
1372 Imports.reserve(Count);
1373 uint32_t I = 0;
1374 while (I < Count) {
1375 wasm::WasmImport Im;
1376 Im.Module = readString(Ctx);
1377 Im.Field = readString(Ctx);
1378 Im.Kind = readUint8(Ctx);
1379 // 0x7E/0x7F along with an empty Field signals a block of compact imports.
1380 if (Im.Kind == 0x7E && Im.Field == "") {
1382 "compact import format (0x7E) is not yet supported",
1384 } else if (Im.Kind == 0x7F && Im.Field == "") {
1385 uint32_t NumCompactImports = readVaruint32(Ctx);
1386 while (NumCompactImports--) {
1387 Im.Field = readString(Ctx);
1388 Im.Kind = readUint8(Ctx);
1389 Error rtn = parseImport(Ctx, Im);
1390 if (rtn)
1391 return rtn;
1392 I++;
1393 }
1394 } else {
1395 Error rtn = parseImport(Ctx, Im);
1396 if (rtn)
1397 return rtn;
1398 I++;
1399 }
1400 }
1401 if (Ctx.Ptr != Ctx.End)
1402 return make_error<GenericBinaryError>("import section ended prematurely",
1404 return Error::success();
1405}
1406
1407Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1408 uint32_t Count = readVaruint32(Ctx);
1409 Functions.reserve(Count);
1410 uint32_t NumTypes = Signatures.size();
1411 while (Count--) {
1412 uint32_t Type = readVaruint32(Ctx);
1413 if (Type >= NumTypes)
1414 return make_error<GenericBinaryError>("invalid function type",
1416 wasm::WasmFunction F;
1417 F.SigIndex = Type;
1418 Functions.push_back(F);
1419 }
1420 if (Ctx.Ptr != Ctx.End)
1421 return make_error<GenericBinaryError>("function section ended prematurely",
1423 return Error::success();
1424}
1425
1426Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1427 TableSection = Sections.size();
1428 uint32_t Count = readVaruint32(Ctx);
1429 Tables.reserve(Count);
1430 while (Count--) {
1431 wasm::WasmTable T;
1432 T.Type = readTableType(Ctx);
1433 T.Index = NumImportedTables + Tables.size();
1434 Tables.push_back(T);
1435 auto ElemType = Tables.back().Type.ElemType;
1436 if (ElemType != wasm::ValType::FUNCREF &&
1437 ElemType != wasm::ValType::EXTERNREF &&
1438 ElemType != wasm::ValType::EXNREF &&
1439 ElemType != wasm::ValType::OTHERREF) {
1440 return make_error<GenericBinaryError>("invalid table element type",
1442 }
1443 }
1444 if (Ctx.Ptr != Ctx.End)
1445 return make_error<GenericBinaryError>("table section ended prematurely",
1447 return Error::success();
1448}
1449
1450Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1451 uint32_t Count = readVaruint32(Ctx);
1452 Memories.reserve(Count);
1453 while (Count--) {
1454 auto Limits = readLimits(Ctx);
1455 if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1456 HasMemory64 = true;
1457 Memories.push_back(Limits);
1458 }
1459 if (Ctx.Ptr != Ctx.End)
1460 return make_error<GenericBinaryError>("memory section ended prematurely",
1462 return Error::success();
1463}
1464
1465Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1466 TagSection = Sections.size();
1467 uint32_t Count = readVaruint32(Ctx);
1468 Tags.reserve(Count);
1469 uint32_t NumTypes = Signatures.size();
1470 while (Count--) {
1471 if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1472 return make_error<GenericBinaryError>("invalid attribute",
1474 uint32_t Type = readVaruint32(Ctx);
1475 if (Type >= NumTypes)
1476 return make_error<GenericBinaryError>("invalid tag type",
1478 wasm::WasmTag Tag;
1479 Tag.Index = NumImportedTags + Tags.size();
1480 Tag.SigIndex = Type;
1481 Signatures[Type].Kind = wasm::WasmSignature::Tag;
1482 Tags.push_back(Tag);
1483 }
1484
1485 if (Ctx.Ptr != Ctx.End)
1486 return make_error<GenericBinaryError>("tag section ended prematurely",
1488 return Error::success();
1489}
1490
1491Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1492 GlobalSection = Sections.size();
1493 const uint8_t *SectionStart = Ctx.Ptr;
1494 uint32_t Count = readVaruint32(Ctx);
1495 Globals.reserve(Count);
1496 while (Count--) {
1497 wasm::WasmGlobal Global;
1498 Global.Index = NumImportedGlobals + Globals.size();
1499 const uint8_t *GlobalStart = Ctx.Ptr;
1500 Global.Offset = static_cast<uint32_t>(GlobalStart - SectionStart);
1501 auto GlobalOpcode = readVaruint32(Ctx);
1502 Global.Type.Type = (uint8_t)parseValType(Ctx, GlobalOpcode);
1503 Global.Type.Mutable = readVaruint1(Ctx);
1504 if (Error Err = readInitExpr(Global.InitExpr, Ctx))
1505 return Err;
1506 Global.Size = static_cast<uint32_t>(Ctx.Ptr - GlobalStart);
1507 Globals.push_back(Global);
1508 }
1509 if (Ctx.Ptr != Ctx.End)
1510 return make_error<GenericBinaryError>("global section ended prematurely",
1512 return Error::success();
1513}
1514
1515Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1516 uint32_t Count = readVaruint32(Ctx);
1517 Exports.reserve(Count);
1518 Symbols.reserve(Count);
1519
1520 // Build hash map of export flags for faster cross-referencing
1521 llvm::DenseMap<StringRef, uint32_t> ExportFlags;
1522 if (HasDylinkSection) {
1523 for (const auto &ExportInfo : DylinkInfo.ExportInfo) {
1524 ExportFlags[ExportInfo.Name] = ExportInfo.Flags;
1525 }
1526 }
1527
1528 for (uint32_t I = 0; I < Count; I++) {
1529 wasm::WasmExport Ex;
1530 Ex.Name = readString(Ctx);
1531 Ex.Kind = readUint8(Ctx);
1532 Ex.Index = readVaruint32(Ctx);
1533 const wasm::WasmSignature *Signature = nullptr;
1534 const wasm::WasmGlobalType *GlobalType = nullptr;
1535 const wasm::WasmTableType *TableType = nullptr;
1536 wasm::WasmSymbolInfo Info;
1537 Info.Name = Ex.Name;
1538 Info.Flags = 0;
1539 // For shared objects, symbol flags may be specified in the dylink section
1540 // instead of the export section
1541 if (HasDylinkSection) {
1542 auto It = ExportFlags.find(Ex.Name);
1543 if (It != ExportFlags.end()) {
1544 Info.Flags = It->second;
1545 }
1546 }
1547 switch (Ex.Kind) {
1549 if (!isValidFunctionIndex(Ex.Index))
1550 return make_error<GenericBinaryError>("invalid function export",
1553 Info.ElementIndex = Ex.Index;
1554 if (isDefinedFunctionIndex(Ex.Index)) {
1555 getDefinedFunction(Ex.Index).ExportName = Ex.Name;
1556 unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
1557 wasm::WasmFunction &Function = Functions[FuncIndex];
1558 Signature = &Signatures[Function.SigIndex];
1559 }
1560 // Else the function is imported. LLVM object files don't use this
1561 // pattern and we still treat this as an undefined symbol, but we want to
1562 // parse it without crashing.
1563 break;
1564 }
1566 if (!isValidGlobalIndex(Ex.Index))
1567 return make_error<GenericBinaryError>("invalid global export",
1570 uint64_t Offset = 0;
1571 if (isDefinedGlobalIndex(Ex.Index)) {
1572 auto Global = getDefinedGlobal(Ex.Index);
1573 if (!Global.InitExpr.Extended) {
1574 auto Inst = Global.InitExpr.Inst;
1575 if (Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1576 Offset = Inst.Value.Int32;
1577 } else if (Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1578 Offset = Inst.Value.Int64;
1579 }
1580 }
1581 }
1582 Info.DataRef = wasm::WasmDataReference{0, Offset, 0};
1583 break;
1584 }
1586 if (!isValidTagIndex(Ex.Index))
1587 return make_error<GenericBinaryError>("invalid tag export",
1590 Info.ElementIndex = Ex.Index;
1591 if (isDefinedTagIndex(Ex.Index)) {
1592 unsigned TagIndex = Ex.Index - NumImportedTags;
1593 Signature = &Signatures[Tags[TagIndex].SigIndex];
1594 }
1595 break;
1597 break;
1600 Info.ElementIndex = Ex.Index;
1601 break;
1602 default:
1603 return make_error<GenericBinaryError>("unexpected export kind",
1605 }
1606 Exports.push_back(Ex);
1607 if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) {
1608 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
1609 LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
1610 }
1611 }
1612 if (Ctx.Ptr != Ctx.End)
1613 return make_error<GenericBinaryError>("export section ended prematurely",
1615 return Error::success();
1616}
1617
1618bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1619 return Index < NumImportedFunctions + Functions.size();
1620}
1621
1622bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1623 return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1624}
1625
1626bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1627 return Index < NumImportedGlobals + Globals.size();
1628}
1629
1630bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1631 return Index < NumImportedTables + Tables.size();
1632}
1633
1634bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1635 return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1636}
1637
1638bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1639 return Index >= NumImportedTables && isValidTableNumber(Index);
1640}
1641
1642bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1643 return Index < NumImportedTags + Tags.size();
1644}
1645
1646bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1647 return Index >= NumImportedTags && isValidTagIndex(Index);
1648}
1649
1650bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1651 return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1652}
1653
1654bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1655 return Index < Symbols.size() && Symbols[Index].isTypeTable();
1656}
1657
1658bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1659 return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1660}
1661
1662bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1663 return Index < Symbols.size() && Symbols[Index].isTypeTag();
1664}
1665
1666bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1667 return Index < Symbols.size() && Symbols[Index].isTypeData();
1668}
1669
1670bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1671 return Index < Symbols.size() && Symbols[Index].isTypeSection();
1672}
1673
1674wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1675 assert(isDefinedFunctionIndex(Index));
1676 return Functions[Index - NumImportedFunctions];
1677}
1678
1679const wasm::WasmFunction &
1680WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1681 assert(isDefinedFunctionIndex(Index));
1682 return Functions[Index - NumImportedFunctions];
1683}
1684
1685const wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) const {
1686 assert(isDefinedGlobalIndex(Index));
1687 return Globals[Index - NumImportedGlobals];
1688}
1689
1690wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1691 assert(isDefinedTagIndex(Index));
1692 return Tags[Index - NumImportedTags];
1693}
1694
1695Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1696 StartFunction = readVaruint32(Ctx);
1697 if (!isValidFunctionIndex(StartFunction))
1698 return make_error<GenericBinaryError>("invalid start function",
1700 return Error::success();
1701}
1702
1703Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1704 CodeSection = Sections.size();
1705 uint32_t FunctionCount = readVaruint32(Ctx);
1706 if (FunctionCount != Functions.size()) {
1707 return make_error<GenericBinaryError>("invalid function count",
1709 }
1710
1711 for (uint32_t i = 0; i < FunctionCount; i++) {
1712 wasm::WasmFunction& Function = Functions[i];
1713 const uint8_t *FunctionStart = Ctx.Ptr;
1714 uint32_t Size = readVaruint32(Ctx);
1715 const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1716
1717 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1718 Function.Index = NumImportedFunctions + i;
1719 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1720 Function.Size = FunctionEnd - FunctionStart;
1721
1722 uint32_t NumLocalDecls = readVaruint32(Ctx);
1723 Function.Locals.reserve(NumLocalDecls);
1724 while (NumLocalDecls--) {
1725 wasm::WasmLocalDecl Decl;
1726 Decl.Count = readVaruint32(Ctx);
1727 Decl.Type = readUint8(Ctx);
1728 Function.Locals.push_back(Decl);
1729 }
1730
1731 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1732 // Ensure that Function is within Ctx's buffer.
1733 if (Ctx.Ptr + BodySize > Ctx.End) {
1734 return make_error<GenericBinaryError>("Function extends beyond buffer",
1736 }
1737 Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1738 // This will be set later when reading in the linking metadata section.
1739 Function.Comdat = UINT32_MAX;
1740 Ctx.Ptr += BodySize;
1741 assert(Ctx.Ptr == FunctionEnd);
1742 }
1743 if (Ctx.Ptr != Ctx.End)
1744 return make_error<GenericBinaryError>("code section ended prematurely",
1746 return Error::success();
1747}
1748
1749Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1750 uint32_t Count = readVaruint32(Ctx);
1751 ElemSegments.reserve(Count);
1752 while (Count--) {
1753 wasm::WasmElemSegment Segment;
1754 Segment.Flags = readVaruint32(Ctx);
1755
1756 uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
1759 if (Segment.Flags & ~SupportedFlags)
1761 "Unsupported flags for element segment", object_error::parse_failed);
1762
1764 if ((Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) == 0) {
1766 } else if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE) {
1768 } else {
1770 }
1771 bool HasTableNumber =
1774 bool HasElemKind =
1777 bool HasElemType =
1780 bool HasInitExprs =
1782
1783 if (HasTableNumber)
1784 Segment.TableNumber = readVaruint32(Ctx);
1785 else
1786 Segment.TableNumber = 0;
1787
1788 if (!isValidTableNumber(Segment.TableNumber))
1789 return make_error<GenericBinaryError>("invalid TableNumber",
1791
1793 Segment.Offset.Extended = false;
1795 Segment.Offset.Inst.Value.Int32 = 0;
1796 } else {
1797 if (Error Err = readInitExpr(Segment.Offset, Ctx))
1798 return Err;
1799 }
1800
1801 if (HasElemKind) {
1802 auto ElemKind = readVaruint32(Ctx);
1804 Segment.ElemKind = parseValType(Ctx, ElemKind);
1805 if (Segment.ElemKind != wasm::ValType::FUNCREF &&
1807 Segment.ElemKind != wasm::ValType::EXNREF &&
1808 Segment.ElemKind != wasm::ValType::OTHERREF) {
1809 return make_error<GenericBinaryError>("invalid elem type",
1811 }
1812 } else {
1813 if (ElemKind != 0)
1814 return make_error<GenericBinaryError>("invalid elem type",
1817 }
1818 } else if (HasElemType) {
1819 auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
1820 Segment.ElemKind = ElemType;
1821 } else {
1823 }
1824
1825 uint32_t NumElems = readVaruint32(Ctx);
1826
1827 if (HasInitExprs) {
1828 while (NumElems--) {
1829 wasm::WasmInitExpr Expr;
1830 if (Error Err = readInitExpr(Expr, Ctx))
1831 return Err;
1832 }
1833 } else {
1834 while (NumElems--) {
1835 Segment.Functions.push_back(readVaruint32(Ctx));
1836 }
1837 }
1838 ElemSegments.push_back(Segment);
1839 }
1840 if (Ctx.Ptr != Ctx.End)
1841 return make_error<GenericBinaryError>("elem section ended prematurely",
1843 return Error::success();
1844}
1845
1846Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1847 DataSection = Sections.size();
1848 uint32_t Count = readVaruint32(Ctx);
1849 if (DataCount && Count != *DataCount)
1851 "number of data segments does not match DataCount section");
1852 DataSegments.reserve(Count);
1853 while (Count--) {
1854 WasmSegment Segment;
1855 Segment.Data.InitFlags = readVaruint32(Ctx);
1856 Segment.Data.MemoryIndex =
1858 ? readVaruint32(Ctx)
1859 : 0;
1860 if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1861 if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
1862 return Err;
1863 } else {
1864 Segment.Data.Offset.Extended = false;
1866 Segment.Data.Offset.Inst.Value.Int32 = 0;
1867 }
1868 uint32_t Size = readVaruint32(Ctx);
1869 if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1870 return make_error<GenericBinaryError>("invalid segment size",
1872 Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1873 // The rest of these Data fields are set later, when reading in the linking
1874 // metadata section.
1875 Segment.Data.Alignment = 0;
1876 Segment.Data.LinkingFlags = 0;
1877 Segment.Data.Comdat = UINT32_MAX;
1878 Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1879 Ctx.Ptr += Size;
1880 DataSegments.push_back(Segment);
1881 }
1882 if (Ctx.Ptr != Ctx.End)
1883 return make_error<GenericBinaryError>("data section ended prematurely",
1885 return Error::success();
1886}
1887
1888Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1889 DataCount = readVaruint32(Ctx);
1890 return Error::success();
1891}
1892
1894 return Header;
1895}
1896
1897void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1898
1901 const WasmSymbol &Sym = getWasmSymbol(Symb);
1902
1903 LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1904 if (Sym.isBindingWeak())
1905 Result |= SymbolRef::SF_Weak;
1906 if (!Sym.isBindingLocal())
1907 Result |= SymbolRef::SF_Global;
1908 if (Sym.isHidden())
1909 Result |= SymbolRef::SF_Hidden;
1910 if (!Sym.isDefined())
1911 Result |= SymbolRef::SF_Undefined;
1912 if (Sym.isTypeFunction())
1913 Result |= SymbolRef::SF_Executable;
1914 return Result;
1915}
1916
1919 Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1920 Ref.d.b = 0; // Symbol index
1921 return BasicSymbolRef(Ref, this);
1922}
1923
1926 Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1927 Ref.d.b = Symbols.size(); // Symbol index
1928 return BasicSymbolRef(Ref, this);
1929}
1930
1932 return Symbols[Symb.d.b];
1933}
1934
1936 return getWasmSymbol(Symb.getRawDataRefImpl());
1937}
1938
1942
1944 auto &Sym = getWasmSymbol(Symb);
1945 if (!Sym.isDefined())
1946 return 0;
1948 if (!Sec)
1949 return Sec.takeError();
1950 uint32_t SectionAddress = getSectionAddress(Sec.get()->getRawDataRefImpl());
1951 if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1952 isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
1953 return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
1954 SectionAddress;
1955 }
1956 if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL &&
1957 isDefinedGlobalIndex(Sym.Info.ElementIndex)) {
1958 return getDefinedGlobal(Sym.Info.ElementIndex).Offset + SectionAddress;
1959 }
1960
1961 return getSymbolValue(Symb);
1962}
1963
1965 switch (Sym.Info.Kind) {
1970 return Sym.Info.ElementIndex;
1972 // The value of a data symbol is the segment offset, plus the symbol
1973 // offset within the segment.
1974 uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1975 const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1976 if (Segment.Offset.Extended) {
1977 llvm_unreachable("extended init exprs not supported");
1978 } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1979 return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
1980 } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1981 return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
1982 } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {
1983 return Sym.Info.DataRef.Offset;
1984 } else {
1985 llvm_unreachable("unknown init expr opcode");
1986 }
1987 }
1989 return 0;
1990 }
1991 llvm_unreachable("invalid symbol type");
1992}
1993
1997
1999 llvm_unreachable("not yet implemented");
2000 return 0;
2001}
2002
2004 llvm_unreachable("not yet implemented");
2005 return 0;
2006}
2007
2010 const WasmSymbol &Sym = getWasmSymbol(Symb);
2011
2012 switch (Sym.Info.Kind) {
2016 return SymbolRef::ST_Other;
2018 return SymbolRef::ST_Data;
2020 return SymbolRef::ST_Debug;
2022 return SymbolRef::ST_Other;
2024 return SymbolRef::ST_Other;
2025 }
2026
2027 llvm_unreachable("unknown WasmSymbol::SymbolType");
2028 return SymbolRef::ST_Other;
2029}
2030
2033 const WasmSymbol &Sym = getWasmSymbol(Symb);
2034 if (Sym.isUndefined())
2035 return section_end();
2036
2038 Ref.d.a = getSymbolSectionIdImpl(Sym);
2039 return section_iterator(SectionRef(Ref, this));
2040}
2041
2043 const WasmSymbol &Sym = getWasmSymbol(Symb);
2044 return getSymbolSectionIdImpl(Sym);
2045}
2046
2047uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
2048 switch (Sym.Info.Kind) {
2050 return CodeSection;
2052 return GlobalSection;
2054 return DataSection;
2056 return Sym.Info.ElementIndex;
2058 return TagSection;
2060 return TableSection;
2061 default:
2062 llvm_unreachable("unknown WasmSymbol::SymbolType");
2063 }
2064}
2065
2067 const WasmSymbol &Sym = getWasmSymbol(Symb);
2068 if (!Sym.isDefined())
2069 return 0;
2070 if (Sym.isTypeGlobal())
2071 return getDefinedGlobal(Sym.Info.ElementIndex).Size;
2072 if (Sym.isTypeData())
2073 return Sym.Info.DataRef.Size;
2074 if (Sym.isTypeFunction())
2075 return functions()[Sym.Info.ElementIndex - getNumImportedFunctions()].Size;
2076 // Currently symbol size is only tracked for data segments and functions. In
2077 // principle we could also track size (e.g. binary size) for tables, globals
2078 // and element segments etc too.
2079 return 0;
2080}
2081
2083
2092
2094 // For object files, use 0 for section addresses, and section offsets for
2095 // symbol addresses. For linked files, use file offsets.
2096 // See also getSymbolAddress.
2097 return isRelocatableObject() || isSharedObject() ? 0
2098 : Sections[Sec.d.a].Offset;
2099}
2100
2102 return Sec.d.a;
2103}
2104
2106 const WasmSection &S = Sections[Sec.d.a];
2107 return S.Content.size();
2108}
2109
2112 const WasmSection &S = Sections[Sec.d.a];
2113 // This will never fail since wasm sections can never be empty (user-sections
2114 // must have a name and non-user sections each have a defined structure).
2115 return S.Content;
2116}
2117
2119 return 1;
2120}
2121
2123 return false;
2124}
2125
2129
2133
2134bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
2135
2136bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
2137
2139 DataRefImpl RelocRef;
2140 RelocRef.d.a = Ref.d.a;
2141 RelocRef.d.b = 0;
2142 return relocation_iterator(RelocationRef(RelocRef, this));
2143}
2144
2146 const WasmSection &Sec = getWasmSection(Ref);
2147 DataRefImpl RelocRef;
2148 RelocRef.d.a = Ref.d.a;
2149 RelocRef.d.b = Sec.Relocations.size();
2150 return relocation_iterator(RelocationRef(RelocRef, this));
2151}
2152
2154
2157 return Rel.Offset;
2158}
2159
2162 if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
2163 return symbol_end();
2164 DataRefImpl Sym;
2165 Sym.d.a = 1;
2166 Sym.d.b = Rel.Index;
2167 return symbol_iterator(SymbolRef(Sym, this));
2168}
2169
2172 return Rel.Type;
2173}
2174
2176 DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
2178 StringRef Res = "Unknown";
2179
2180#define WASM_RELOC(name, value) \
2181 case wasm::name: \
2182 Res = #name; \
2183 break;
2184
2185 switch (Rel.Type) {
2186#include "llvm/BinaryFormat/WasmRelocs.def"
2187 }
2188
2189#undef WASM_RELOC
2190
2191 Result.append(Res.begin(), Res.end());
2192}
2193
2196 Ref.d.a = 0;
2197 return section_iterator(SectionRef(Ref, this));
2198}
2199
2202 Ref.d.a = Sections.size();
2203 return section_iterator(SectionRef(Ref, this));
2204}
2205
2207 return getArch() == Triple::wasm64 ? 8 : 4;
2208}
2209
2211
2213 if (!LinkingData.TargetArch.empty())
2214 return Triple(LinkingData.TargetArch).getArch();
2215 if (!DylinkInfo.TargetArch.empty())
2216 return Triple(DylinkInfo.TargetArch).getArch();
2217 // Fall back to the HasMemory64 heuristic for backwards compatibility with
2218 // older object files/shared libraries that lack target architecture metadata,
2219 // as well as final executables that lack custom linking/dylink sections.
2220 return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
2221}
2222
2226
2227bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
2228
2229bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
2230
2232 assert(Ref.d.a < Sections.size());
2233 return Sections[Ref.d.a];
2234}
2235
2236const WasmSection &
2238 return getWasmSection(Section.getRawDataRefImpl());
2239}
2240
2243 return getWasmRelocation(Ref.getRawDataRefImpl());
2244}
2245
2248 assert(Ref.d.a < Sections.size());
2249 const WasmSection &Sec = Sections[Ref.d.a];
2250 assert(Ref.d.b < Sec.Relocations.size());
2251 return Sec.Relocations[Ref.d.b];
2252}
2253
2254int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
2255 StringRef CustomSectionName) {
2256 switch (ID) {
2258 return StringSwitch<unsigned>(CustomSectionName)
2259 .Case("dylink", WASM_SEC_ORDER_DYLINK)
2260 .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
2261 .Case("linking", WASM_SEC_ORDER_LINKING)
2263 .Case("name", WASM_SEC_ORDER_NAME)
2264 .Case("producers", WASM_SEC_ORDER_PRODUCERS)
2265 .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
2268 return WASM_SEC_ORDER_TYPE;
2270 return WASM_SEC_ORDER_IMPORT;
2274 return WASM_SEC_ORDER_TABLE;
2276 return WASM_SEC_ORDER_MEMORY;
2278 return WASM_SEC_ORDER_GLOBAL;
2280 return WASM_SEC_ORDER_EXPORT;
2282 return WASM_SEC_ORDER_START;
2284 return WASM_SEC_ORDER_ELEM;
2286 return WASM_SEC_ORDER_CODE;
2288 return WASM_SEC_ORDER_DATA;
2291 case wasm::WASM_SEC_TAG:
2292 return WASM_SEC_ORDER_TAG;
2293 default:
2294 return WASM_SEC_ORDER_NONE;
2295 }
2296}
2297
2298// Represents the edges in a directed graph where any node B reachable from node
2299// A is not allowed to appear before A in the section ordering, but may appear
2300// afterward.
2302 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2303 // WASM_SEC_ORDER_NONE
2304 {},
2305 // WASM_SEC_ORDER_TYPE
2306 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2307 // WASM_SEC_ORDER_IMPORT
2308 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2309 // WASM_SEC_ORDER_FUNCTION
2310 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2311 // WASM_SEC_ORDER_TABLE
2312 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2313 // WASM_SEC_ORDER_MEMORY
2314 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2315 // WASM_SEC_ORDER_TAG
2316 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2317 // WASM_SEC_ORDER_GLOBAL
2318 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2319 // WASM_SEC_ORDER_EXPORT
2320 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2321 // WASM_SEC_ORDER_START
2322 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2323 // WASM_SEC_ORDER_ELEM
2324 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2325 // WASM_SEC_ORDER_DATACOUNT
2326 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2327 // WASM_SEC_ORDER_CODE
2328 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2329 // WASM_SEC_ORDER_DATA
2330 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2331
2332 // Custom Sections
2333 // WASM_SEC_ORDER_DYLINK
2334 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2335 // WASM_SEC_ORDER_LINKING
2336 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2337 // WASM_SEC_ORDER_RELOC (can be repeated)
2338 {},
2339 // WASM_SEC_ORDER_NAME
2340 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2341 // WASM_SEC_ORDER_PRODUCERS
2342 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2343 // WASM_SEC_ORDER_TARGET_FEATURES
2344 {WASM_SEC_ORDER_TARGET_FEATURES}};
2345
2347 StringRef CustomSectionName) {
2348 int Order = getSectionOrder(ID, CustomSectionName);
2349 if (Order == WASM_SEC_ORDER_NONE)
2350 return true;
2351
2352 // Disallowed predecessors we need to check for
2354
2355 // Keep track of completed checks to avoid repeating work
2356 bool Checked[WASM_NUM_SEC_ORDERS] = {};
2357
2358 int Curr = Order;
2359 while (true) {
2360 // Add new disallowed predecessors to work list
2361 for (size_t I = 0;; ++I) {
2362 int Next = DisallowedPredecessors[Curr][I];
2364 break;
2365 if (Checked[Next])
2366 continue;
2367 WorkList.push_back(Next);
2368 Checked[Next] = true;
2369 }
2370
2371 if (WorkList.empty())
2372 break;
2373
2374 // Consider next disallowed predecessor
2375 Curr = WorkList.pop_back_val();
2376 if (Seen[Curr])
2377 return false;
2378 }
2379
2380 // Have not seen any disallowed predecessors
2381 Seen[Order] = true;
2382 return true;
2383}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:690
This file defines the DenseSet and SmallDenseSet classes.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
static Error readString(StringRef Buffer, const char *&Src, size_t MaxSize, StringRef &Val, Twine Desc)
Read a null-terminated string at the position Src from Buffer, with maximum byte size of MaxSize (inc...
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
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...
#define LLVM_DEBUG(...)
Definition Debug.h:119
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 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)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
const T * data() const
Definition ArrayRef.h:138
Helper for Errors used as out-parameters.
Definition Error.h:1160
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
reference get()
Returns a reference to the stored T value.
Definition Error.h:582
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:184
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:597
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
iterator begin() const
Definition StringRef.h:114
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
iterator end() const
Definition StringRef.h:116
const unsigned char * bytes_begin() const
Definition StringRef.h:122
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition StringSet.h:41
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & StartsWith(StringLiteral S, T Value)
Manages the enabling and disabling of subtarget specific features.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition Triple.h:515
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static Twine utohexstr(uint64_t Val)
Definition Twine.h:385
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:210
This is a value type class that represents a single symbol in the list of symbols in the object file.
DataRefImpl getRawDataRefImpl() const
MemoryBufferRef Data
Definition Binary.h:38
StringRef getData() const
Definition Binary.cpp:23
friend class RelocationRef
Definition ObjectFile.h:289
static Expected< std::unique_ptr< WasmObjectFile > > createWasmObjectFile(MemoryBufferRef Object)
Expected< uint64_t > getSymbolValue(DataRefImpl Symb) const
ObjectFile(unsigned int Type, MemoryBufferRef Source)
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:161
const wasm::WasmRelocation & getWasmRelocation(const RelocationRef &Ref) const
uint32_t getSymbolSize(SymbolRef Sym) const
ArrayRef< wasm::WasmFunction > functions() const
Definition Wasm.h:156
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
LLVM_ABI bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")
static LLVM_ABI int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]
Definition Wasm.h:360
bool isTypeFunction() const
Definition Wasm.h:54
unsigned getBinding() const
Definition Wasm.h:90
LLVM_DUMP_METHOD void dump() const
bool isTypeData() const
Definition Wasm.h:60
bool isBindingWeak() const
Definition Wasm.h:78
bool isHidden() const
Definition Wasm.h:94
wasm::WasmSymbolInfo Info
Definition Wasm.h:49
bool isUndefined() const
Definition Wasm.h:74
LLVM_ABI void print(raw_ostream &Out) const
bool isBindingLocal() const
Definition Wasm.h:86
bool isTypeGlobal() const
Definition Wasm.h:62
bool isDefined() const
Definition Wasm.h:72
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const char SectionName[]
content_iterator< SectionRef > section_iterator
Definition ObjectFile.h:49
content_iterator< BasicSymbolRef > basic_symbol_iterator
content_iterator< RelocationRef > relocation_iterator
Definition ObjectFile.h:79
uint32_t read32le(const void *P)
Definition Endian.h:412
const unsigned WASM_SYMBOL_UNDEFINED
Definition Wasm.h:259
@ WASM_NAMES_LOCAL
Definition Wasm.h:197
@ WASM_NAMES_DATA_SEGMENT
Definition Wasm.h:199
@ WASM_NAMES_GLOBAL
Definition Wasm.h:198
@ WASM_NAMES_FUNCTION
Definition Wasm.h:196
const unsigned WASM_SYMBOL_NO_STRIP
Definition Wasm.h:262
@ WASM_TYPE_ARRAY
Definition Wasm.h:76
@ WASM_TYPE_NULLABLE
Definition Wasm.h:74
@ WASM_TYPE_I64
Definition Wasm.h:57
@ WASM_TYPE_F64
Definition Wasm.h:59
@ WASM_TYPE_FUNCREF
Definition Wasm.h:65
@ WASM_TYPE_REC
Definition Wasm.h:80
@ WASM_TYPE_EXTERNREF
Definition Wasm.h:66
@ WASM_TYPE_SUB
Definition Wasm.h:78
@ WASM_TYPE_FUNC
Definition Wasm.h:75
@ WASM_TYPE_STRUCT
Definition Wasm.h:77
@ WASM_TYPE_NONNULLABLE
Definition Wasm.h:73
@ WASM_TYPE_I32
Definition Wasm.h:56
@ WASM_TYPE_F32
Definition Wasm.h:58
@ WASM_TYPE_V128
Definition Wasm.h:60
@ WASM_TYPE_SUB_FINAL
Definition Wasm.h:79
@ WASM_TYPE_EXNREF
Definition Wasm.h:67
const unsigned WASM_SYMBOL_BINDING_GLOBAL
Definition Wasm.h:253
const unsigned WASM_SYMBOL_TLS
Definition Wasm.h:263
const uint32_t WasmMetadataVersion
Definition Wasm.h:31
const unsigned WASM_SYMBOL_BINDING_WEAK
Definition Wasm.h:254
@ WASM_SEC_CODE
Definition Wasm.h:47
@ WASM_SEC_MEMORY
Definition Wasm.h:42
@ WASM_SEC_IMPORT
Definition Wasm.h:39
@ WASM_SEC_EXPORT
Definition Wasm.h:44
@ WASM_SEC_DATACOUNT
Definition Wasm.h:49
@ WASM_SEC_LAST_KNOWN
Definition Wasm.h:51
@ WASM_SEC_CUSTOM
Definition Wasm.h:37
@ WASM_SEC_FUNCTION
Definition Wasm.h:40
@ WASM_SEC_ELEM
Definition Wasm.h:46
@ WASM_SEC_START
Definition Wasm.h:45
@ WASM_SEC_TABLE
Definition Wasm.h:41
@ WASM_SEC_TYPE
Definition Wasm.h:38
@ WASM_SEC_TAG
Definition Wasm.h:50
@ WASM_SEC_GLOBAL
Definition Wasm.h:43
@ WASM_SEC_DATA
Definition Wasm.h:48
const unsigned WASM_SYMBOL_BINDING_LOCAL
Definition Wasm.h:255
@ WASM_LIMITS_FLAG_HAS_MAX
Definition Wasm.h:168
@ WASM_LIMITS_FLAG_IS_64
Definition Wasm.h:170
@ WASM_LIMITS_FLAG_HAS_PAGE_SIZE
Definition Wasm.h:171
@ WASM_FEATURE_PREFIX_USED
Definition Wasm.h:189
@ WASM_FEATURE_PREFIX_DISALLOWED
Definition Wasm.h:190
WasmSymbolType
Definition Wasm.h:230
@ WASM_SYMBOL_TYPE_GLOBAL
Definition Wasm.h:233
@ WASM_SYMBOL_TYPE_DATA
Definition Wasm.h:232
@ WASM_SYMBOL_TYPE_TAG
Definition Wasm.h:235
@ WASM_SYMBOL_TYPE_TABLE
Definition Wasm.h:236
@ WASM_SYMBOL_TYPE_SECTION
Definition Wasm.h:234
@ WASM_SYMBOL_TYPE_FUNCTION
Definition Wasm.h:231
const uint32_t WasmVersion
Definition Wasm.h:29
ElemSegmentMode
Definition Wasm.h:439
const unsigned WASM_SYMBOL_BINDING_COMMON
Definition Wasm.h:256
const unsigned WASM_SYMBOL_EXPORTED
Definition Wasm.h:260
const unsigned WASM_SYMBOL_BINDING_MASK
Definition Wasm.h:250
@ WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
Definition Wasm.h:183
@ WASM_ELEM_SEGMENT_IS_DECLARATIVE
Definition Wasm.h:181
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
Definition Wasm.h:182
@ WASM_ELEM_SEGMENT_IS_PASSIVE
Definition Wasm.h:180
@ WASM_DYLINK_RUNTIME_PATH
Definition Wasm.h:217
@ WASM_DYLINK_NEEDED
Definition Wasm.h:214
@ WASM_DYLINK_MEM_INFO
Definition Wasm.h:213
@ WASM_DYLINK_EXPORT_INFO
Definition Wasm.h:215
@ WASM_DYLINK_IMPORT_INFO
Definition Wasm.h:216
@ WASM_DYLINK_TARGET_ARCH
Definition Wasm.h:218
@ WASM_DATA_SEGMENT_IS_PASSIVE
Definition Wasm.h:175
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
Definition Wasm.h:176
@ WASM_EXTERNAL_TABLE
Definition Wasm.h:96
@ WASM_EXTERNAL_FUNCTION
Definition Wasm.h:95
@ WASM_EXTERNAL_TAG
Definition Wasm.h:99
@ WASM_EXTERNAL_MEMORY
Definition Wasm.h:97
@ WASM_EXTERNAL_GLOBAL
Definition Wasm.h:98
@ WASM_INIT_FUNCS
Definition Wasm.h:205
@ WASM_TARGET_ARCH
Definition Wasm.h:208
@ WASM_COMDAT_INFO
Definition Wasm.h:206
@ WASM_SEGMENT_INFO
Definition Wasm.h:204
@ WASM_SYMBOL_TABLE
Definition Wasm.h:207
@ WASM_COMDAT_SECTION
Definition Wasm.h:226
@ WASM_COMDAT_FUNCTION
Definition Wasm.h:224
@ WASM_COMDAT_DATA
Definition Wasm.h:223
@ WASM_OPCODE_I64_ADD
Definition Wasm.h:120
@ WASM_OPCODE_I32_SUB
Definition Wasm.h:118
@ WASM_OPCODE_F64_CONST
Definition Wasm.h:116
@ WASM_OPCODE_END
Definition Wasm.h:104
@ WASM_OPCODE_I64_MUL
Definition Wasm.h:122
@ WASM_OPCODE_REF_NULL
Definition Wasm.h:123
@ WASM_OPCODE_GC_PREFIX
Definition Wasm.h:125
@ WASM_OPCODE_REF_FUNC
Definition Wasm.h:124
@ WASM_OPCODE_F32_CONST
Definition Wasm.h:115
@ WASM_OPCODE_GLOBAL_GET
Definition Wasm.h:109
@ WASM_OPCODE_I64_SUB
Definition Wasm.h:121
@ WASM_OPCODE_I32_MUL
Definition Wasm.h:119
@ WASM_OPCODE_I32_ADD
Definition Wasm.h:117
@ WASM_OPCODE_I64_CONST
Definition Wasm.h:114
@ WASM_OPCODE_I32_CONST
Definition Wasm.h:113
LLVM_ABI llvm::StringRef sectionTypeToString(uint32_t type)
Definition Wasm.cpp:41
const unsigned WASM_SYMBOL_EXPLICIT_NAME
Definition Wasm.h:261
const unsigned WASM_SYMBOL_ABSOLUTE
Definition Wasm.h:264
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC
Definition Wasm.h:185
@ WASM_OPCODE_ARRAY_NEW_FIXED
Definition Wasm.h:134
@ WASM_OPCODE_REF_I31
Definition Wasm.h:135
@ WASM_OPCODE_ARRAY_NEW_DEFAULT
Definition Wasm.h:133
@ WASM_OPCODE_STRUCT_NEW
Definition Wasm.h:130
@ WASM_OPCODE_STRUCT_NEW_DEFAULT
Definition Wasm.h:131
@ WASM_OPCODE_ARRAY_NEW
Definition Wasm.h:132
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
@ Import
Import information from summary.
Definition IPO.h:39
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:203
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
const char * to_string(ThinOrFullLTOPhase Phase)
Definition Pass.cpp:311
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
@ Global
Append to llvm.global_dtors.
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
uint64_t decodeULEB128(const uint8_t *p, unsigned *n, const uint8_t *end, const char **error, ULEB128DecodeError *errorCode)
Utility function to decode a ULEB128 value and report a typed error.
Definition LEB128.h:145
ArrayRef< uint8_t > Content
Definition Wasm.h:116
std::vector< wasm::WasmRelocation > Relocations
Definition Wasm.h:117
wasm::WasmDataSegment Data
Definition Wasm.h:124
ArrayRef< uint8_t > Content
Definition Wasm.h:430
WasmInitExpr Offset
Definition Wasm.h:428
std::vector< StringRef > Needed
Definition Wasm.h:310
WasmInitExpr Offset
Definition Wasm.h:451
std::vector< uint32_t > Functions
Definition Wasm.h:452
WasmLimits Memory
Definition Wasm.h:400
StringRef Field
Definition Wasm.h:394
WasmGlobalType Global
Definition Wasm.h:398
StringRef Module
Definition Wasm.h:393
uint32_t SigIndex
Definition Wasm.h:397
WasmTableType Table
Definition Wasm.h:399
union llvm::wasm::WasmInitExprMVP::@234311111124136373374304035273310237314141125040 Value
WasmInitExprMVP Inst
Definition Wasm.h:368
ArrayRef< uint8_t > Body
Definition Wasm.h:369
SmallVector< ValType, 1 > Returns
Definition Wasm.h:528
SmallVector< ValType, 4 > Params
Definition Wasm.h:529
enum llvm::wasm::WasmSignature::@330257225222011177372050205212257221301063235146 Kind
WasmDataReference DataRef
Definition Wasm.h:497
struct llvm::object::DataRefImpl::@005117267142344013370254144343227032034000327225 d