32#define DEBUG_TYPE "wasm-object"
38 Out <<
"Name=" <<
Info.Name
62 Out <<
", ElemIndex=" <<
Info.ElementIndex;
64 Out <<
", Segment=" <<
Info.DataRef.Segment;
65 Out <<
", Offset=" <<
Info.DataRef.Offset;
66 Out <<
", Size=" <<
Info.DataRef.Size;
70#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
77 auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
79 return std::move(Err);
84#define VARINT7_MAX ((1 << 7) - 1)
85#define VARINT7_MIN (-(1 << 7))
86#define VARUINT7_MAX (1 << 7)
87#define VARUINT1_MAX (1)
90 if (Ctx.Ptr == Ctx.End)
96 if (Ctx.Ptr + 4 > Ctx.End)
104 if (Ctx.Ptr + 4 > Ctx.End)
107 memcpy(&Result, Ctx.Ptr,
sizeof(Result));
108 Ctx.Ptr +=
sizeof(Result);
113 if (Ctx.Ptr + 8 > Ctx.End)
116 memcpy(&Result, Ctx.Ptr,
sizeof(Result));
117 Ctx.Ptr +=
sizeof(Result);
123 const char *
Error =
nullptr;
133 if (Ctx.Ptr + StringLen > Ctx.End)
136 StringRef(
reinterpret_cast<const char *
>(Ctx.Ptr), StringLen);
137 Ctx.Ptr += StringLen;
143 const char *
Error =
nullptr;
160 if (Result > INT32_MAX || Result < INT32_MIN)
167 if (Result > UINT32_MAX)
207 auto Start = Ctx.Ptr;
288 Twine(
unsigned(Opcode)),
305 if (PageSizeLog2 >= 32)
307 Result.PageSize = 1 << PageSizeLog2;
315 TableType.ElemType = ElemType;
323 LLVM_DEBUG(
dbgs() <<
"readSection type=" << Section.Type <<
"\n");
326 const uint8_t *PreSizePtr = Ctx.Ptr;
328 Section.HeaderSecSizeEncodingLen = Ctx.Ptr - PreSizePtr;
329 Section.Offset = Ctx.Ptr - Ctx.Start;
333 if (Ctx.Ptr +
Size > Ctx.End)
338 SectionCtx.
Start = Ctx.Ptr;
339 SectionCtx.
Ptr = Ctx.Ptr;
340 SectionCtx.
End = Ctx.Ptr +
Size;
345 Ctx.Ptr += SectionNameSize;
346 Size -= SectionNameSize;
364 if (Header.Magic !=
StringRef(
"\0asm", 4)) {
372 Ctx.Ptr = Ctx.Start + 4;
375 if (Ctx.Ptr + 4 > Ctx.End) {
384 Twine(Header.Version),
390 while (Ctx.Ptr < Ctx.End) {
394 if ((Err = parseSection(Sec)))
397 Sections.push_back(Sec);
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);
441Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
444 HasDylinkSection =
true;
454 if (Ctx.Ptr != Ctx.End)
460Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
463 HasDylinkSection =
true;
465 const uint8_t *OrigEnd = Ctx.End;
466 while (Ctx.Ptr < OrigEnd) {
472 Ctx.End = Ctx.Ptr +
Size;
497 DylinkInfo.ImportInfo.push_back(
505 DylinkInfo.RuntimePath.push_back(
readString(Ctx));
517 if (Ctx.Ptr != Ctx.End) {
523 if (Ctx.Ptr != Ctx.End)
529Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
530 llvm::DenseSet<uint64_t> SeenFunctions;
531 llvm::DenseSet<uint64_t> SeenGlobals;
532 llvm::DenseSet<uint64_t> SeenSegments;
536 bool PopulateSymbolTable = !HasLinkingSection && !HasDylinkSection;
540 if (PopulateSymbolTable)
543 while (Ctx.Ptr < Ctx.End) {
546 const uint8_t *SubSectionEnd = Ctx.Ptr +
Size;
564 const wasm::WasmSignature *Signature =
nullptr;
565 const wasm::WasmGlobalType *GlobalType =
nullptr;
566 const wasm::WasmTableType *TableType =
nullptr;
568 if (!SeenFunctions.
insert(Index).second)
571 if (!isValidFunctionIndex(Index) ||
Name.empty())
575 if (isDefinedFunctionIndex(Index)) {
576 wasm::WasmFunction &
F = getDefinedFunction(Index);
578 Signature = &Signatures[
F.SigIndex];
580 Info.ExportName =
F.ExportName;
589 if (!SeenGlobals.
insert(Index).second)
592 if (!isValidGlobalIndex(Index) ||
Name.empty())
597 if (isDefinedGlobalIndex(Index)) {
598 GlobalType = &getDefinedGlobal(Index).
Type;
603 if (!SeenSegments.
insert(Index).second)
606 if (Index >= DataSegments.size())
612 assert(Index < DataSegments.size());
613 Info.DataRef = wasm::WasmDataReference{
614 Index, 0, DataSegments[
Index].Data.Content.size()};
616 DebugNames.push_back(wasm::WasmDebugName{nameType,
Index,
Name});
617 if (PopulateSymbolTable)
618 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
628 if (Ctx.Ptr != SubSectionEnd)
633 if (Ctx.Ptr != Ctx.End)
639Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
640 HasLinkingSection =
true;
645 "unexpected metadata version: " + Twine(LinkingData.Version) +
650 const uint8_t *OrigEnd = Ctx.End;
651 while (Ctx.Ptr < OrigEnd) {
657 Ctx.End = Ctx.Ptr +
Size;
660 if (
Error Err = parseLinkingSectionSymtab(Ctx))
665 if (
Count > DataSegments.size())
668 for (uint32_t
I = 0;
I <
Count;
I++) {
671 if (DataSegments[
I].
Data.Alignment > 32)
673 "invalid data segment alignment: `" + DataSegments[
I].
Data.Name +
674 "` (alignment: " + Twine(DataSegments[
I].
Data.Alignment) +
683 LinkingData.InitFunctions.reserve(
Count);
684 for (uint32_t
I = 0;
I <
Count;
I++) {
685 wasm::WasmInitFunc Init;
688 if (!isValidFunctionSymbol(Init.
Symbol))
692 LinkingData.InitFunctions.emplace_back(Init);
697 if (
Error Err = parseLinkingSectionComdat(Ctx))
707 if (Ctx.Ptr != Ctx.End)
711 if (Ctx.Ptr != OrigEnd)
717Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
722 Symbols.reserve(
Count);
723 StringSet<> SymbolNames;
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);
737 ImportedGlobals.emplace_back(&
I);
739 ImportedTags.emplace_back(&
I);
741 ImportedTables.emplace_back(&
I);
745 wasm::WasmSymbolInfo
Info;
746 const wasm::WasmSignature *Signature =
nullptr;
747 const wasm::WasmGlobalType *GlobalType =
nullptr;
748 const wasm::WasmTableType *TableType =
nullptr;
757 if (!isValidFunctionIndex(
Info.ElementIndex) ||
758 IsDefined != isDefinedFunctionIndex(
Info.ElementIndex))
763 unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
764 wasm::WasmFunction &
Function = Functions[FuncIndex];
765 Signature = &Signatures[
Function.SigIndex];
769 wasm::WasmImport &
Import = *ImportedFunctions[
Info.ElementIndex];
776 Signature = &Signatures[
Import.SigIndex];
783 if (!isValidGlobalIndex(
Info.ElementIndex) ||
784 IsDefined != isDefinedGlobalIndex(
Info.ElementIndex))
793 unsigned GlobalIndex =
Info.ElementIndex - NumImportedGlobals;
794 wasm::WasmGlobal &
Global = Globals[GlobalIndex];
796 if (
Global.SymbolName.empty())
799 wasm::WasmImport &
Import = *ImportedGlobals[
Info.ElementIndex];
806 GlobalType = &
Import.Global;
813 if (!isValidTableNumber(
Info.ElementIndex) ||
814 IsDefined != isDefinedTableNumber(
Info.ElementIndex))
823 unsigned TableNumber =
Info.ElementIndex - NumImportedTables;
824 wasm::WasmTable &
Table = Tables[TableNumber];
825 TableType = &
Table.Type;
826 if (
Table.SymbolName.empty())
829 wasm::WasmImport &
Import = *ImportedTables[
Info.ElementIndex];
836 TableType = &
Import.Table;
848 "common symbols cannot be absolute: " +
Info.Name,
854 "invalid common symbol alignment: `" +
Info.Name +
855 "` (alignment: " + Twine(
unsigned(Alignment)) +
")",
863 if (Index >= DataSegments.size())
865 "invalid data segment index: " + Twine(Index),
867 size_t SegmentSize = DataSegments[
Index].Data.Content.size();
870 "invalid data symbol offset: `" +
Info.Name +
871 "` (offset: " + Twine(
Offset) +
872 " segment size: " + Twine(SegmentSize) +
")",
884 "section symbols must have local binding",
887 if (
Info.ElementIndex >= Sections.size())
892 "section symbols must reference custom sections",
902 if (!isValidTagIndex(
Info.ElementIndex) ||
903 IsDefined != isDefinedTagIndex(
Info.ElementIndex))
912 unsigned TagIndex =
Info.ElementIndex - NumImportedTags;
913 wasm::WasmTag &
Tag = Tags[TagIndex];
914 Signature = &Signatures[
Tag.SigIndex];
915 if (
Tag.SymbolName.empty())
919 wasm::WasmImport &
Import = *ImportedTags[
Info.ElementIndex];
926 Signature = &Signatures[
Import.SigIndex];
934 Twine(
unsigned(
Info.Kind)),
944 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
945 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
951Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
953 StringSet<> ComdatSet;
954 for (
unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
956 if (
Name.empty() || !ComdatSet.
insert(Name).second)
960 LinkingData.Comdats.emplace_back(Name);
967 while (EntryCount--) {
975 if (Index >= DataSegments.size())
978 if (DataSegments[Index].
Data.Comdat != UINT32_MAX)
981 DataSegments[
Index].Data.Comdat = ComdatIndex;
984 if (!isDefinedFunctionIndex(Index))
987 if (getDefinedFunction(Index).Comdat != UINT32_MAX)
990 getDefinedFunction(Index).Comdat = ComdatIndex;
993 if (Index >= Sections.size())
999 Sections[
Index].Comdat = ComdatIndex;
1007Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
1008 llvm::SmallSet<StringRef, 3> FieldsSeen;
1010 for (
size_t I = 0;
I < Fields; ++
I) {
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;
1025 "producers section field is not named one of language, processed-by, "
1030 llvm::SmallSet<StringRef, 8> ProducersSeen;
1031 for (
size_t J = 0; J < ValueCount; ++J) {
1034 if (!ProducersSeen.
insert(Name).second) {
1036 "producers section contains repeated producer",
1039 ProducerVec->emplace_back(std::string(Name), std::string(
Version));
1042 if (Ctx.Ptr != Ctx.End)
1048Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
1049 llvm::SmallSet<std::string, 8> FeaturesSeen;
1052 wasm::WasmFeatureEntry Feature;
1054 switch (Feature.
Prefix) {
1063 if (!FeaturesSeen.
insert(Feature.
Name).second)
1065 "target features section contains repeated feature \"" +
1066 Feature.
Name +
"\"",
1068 TargetFeatures.push_back(Feature);
1070 if (Ctx.Ptr != Ctx.End)
1072 "target features section ended prematurely",
1077Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
1079 if (SectionIndex >= Sections.size())
1082 WasmSection &
Section = Sections[SectionIndex];
1084 uint32_t EndOffset =
Section.Content.size();
1085 uint32_t PreviousOffset = 0;
1086 while (RelocCount--) {
1087 wasm::WasmRelocation Reloc = {};
1091 if (Reloc.
Offset < PreviousOffset)
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),
1105 PreviousOffset = Reloc.
Offset;
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");
1119 case wasm::R_WASM_TABLE_NUMBER_LEB:
1120 if (!isValidTableSymbol(Reloc.
Index))
1121 return badReloc(
"invalid table relocation");
1123 case wasm::R_WASM_TYPE_INDEX_LEB:
1124 if (Reloc.
Index >= Signatures.size())
1125 return badReloc(
"invalid relocation type index");
1127 case wasm::R_WASM_GLOBAL_INDEX_LEB:
1130 if (!isValidGlobalSymbol(Reloc.
Index) &&
1131 !isValidDataSymbol(Reloc.
Index) &&
1132 !isValidFunctionSymbol(Reloc.
Index))
1133 return badReloc(
"invalid global relocation");
1135 case wasm::R_WASM_GLOBAL_INDEX_I32:
1136 if (!isValidGlobalSymbol(Reloc.
Index))
1137 return badReloc(
"invalid global relocation");
1139 case wasm::R_WASM_TAG_INDEX_LEB:
1140 if (!isValidTagSymbol(Reloc.
Index))
1141 return badReloc(
"invalid tag relocation");
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");
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");
1163 case wasm::R_WASM_FUNCTION_OFFSET_I32:
1164 if (!isValidFunctionSymbol(Reloc.
Index))
1165 return badReloc(
"invalid function relocation");
1168 case wasm::R_WASM_FUNCTION_OFFSET_I64:
1169 if (!isValidFunctionSymbol(Reloc.
Index))
1170 return badReloc(
"invalid function relocation");
1173 case wasm::R_WASM_SECTION_OFFSET_I32:
1174 if (!isValidSectionSymbol(Reloc.
Index))
1175 return badReloc(
"invalid section relocation");
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)
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)
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)
1209 Section.Relocations.push_back(Reloc);
1211 if (Ctx.Ptr != Ctx.End)
1217Error WasmObjectFile::parseCustomSection(
WasmSection &Sec, ReadContext &Ctx) {
1218 if (Sec.
Name ==
"dylink") {
1219 if (
Error Err = parseDylinkSection(Ctx))
1221 }
else if (Sec.
Name ==
"dylink.0") {
1222 if (
Error Err = parseDylink0Section(Ctx))
1224 }
else if (Sec.
Name ==
"name") {
1225 if (
Error Err = parseNameSection(Ctx))
1227 }
else if (Sec.
Name ==
"linking") {
1228 if (
Error Err = parseLinkingSection(Ctx))
1230 }
else if (Sec.
Name ==
"producers") {
1231 if (
Error Err = parseProducersSection(Ctx))
1233 }
else if (Sec.
Name ==
"target_features") {
1234 if (
Error Err = parseTargetFeaturesSection(Ctx))
1237 if (
Error Err = parseRelocSection(Sec.
Name, Ctx))
1243Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1244 auto parseFieldDef = [&]() {
1251 Signatures.reserve(
Count);
1253 wasm::WasmSignature Sig;
1262 Signatures.reserve(Signatures.size() + RecSize);
1265 Signatures.push_back(std::move(Sig));
1266 HasUnmodeledTypes =
true;
1285 while (FieldCount--) {
1295 Signatures.push_back(std::move(Sig));
1296 HasUnmodeledTypes =
true;
1302 while (ParamCount--) {
1307 while (ReturnCount--) {
1312 Signatures.push_back(std::move(Sig));
1314 if (Ctx.Ptr != Ctx.End)
1320Error WasmObjectFile::parseImport(ReadContext &Ctx, wasm::WasmImport &Im) {
1323 NumImportedFunctions++;
1325 if (Im.
SigIndex >= Signatures.size())
1330 NumImportedGlobals++;
1341 NumImportedTables++;
1357 if (Im.
SigIndex >= Signatures.size())
1363 Twine(
unsigned(Im.
Kind)),
1366 Imports.push_back(Im);
1370Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1372 Imports.reserve(
Count);
1375 wasm::WasmImport Im;
1380 if (Im.
Kind == 0x7E && Im.
Field ==
"") {
1382 "compact import format (0x7E) is not yet supported",
1384 }
else if (Im.
Kind == 0x7F && Im.
Field ==
"") {
1386 while (NumCompactImports--) {
1389 Error rtn = parseImport(Ctx, Im);
1395 Error rtn = parseImport(Ctx, Im);
1401 if (Ctx.Ptr != Ctx.End)
1407Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1409 Functions.reserve(
Count);
1410 uint32_t NumTypes = Signatures.size();
1413 if (
Type >= NumTypes)
1416 wasm::WasmFunction
F;
1418 Functions.push_back(
F);
1420 if (Ctx.Ptr != Ctx.End)
1426Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1427 TableSection = Sections.size();
1429 Tables.reserve(
Count);
1433 T.Index = NumImportedTables + Tables.size();
1434 Tables.push_back(
T);
1435 auto ElemType = Tables.back().Type.ElemType;
1444 if (Ctx.Ptr != Ctx.End)
1450Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1452 Memories.reserve(
Count);
1457 Memories.push_back(Limits);
1459 if (Ctx.Ptr != Ctx.End)
1465Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1466 TagSection = Sections.size();
1468 Tags.reserve(
Count);
1469 uint32_t NumTypes = Signatures.size();
1475 if (
Type >= NumTypes)
1479 Tag.Index = NumImportedTags + Tags.size();
1482 Tags.push_back(
Tag);
1485 if (Ctx.Ptr != Ctx.End)
1491Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1492 GlobalSection = Sections.size();
1493 const uint8_t *SectionStart = Ctx.Ptr;
1495 Globals.reserve(
Count);
1498 Global.Index = NumImportedGlobals + Globals.size();
1499 const uint8_t *GlobalStart = Ctx.Ptr;
1500 Global.Offset =
static_cast<uint32_t
>(GlobalStart - SectionStart);
1506 Global.Size =
static_cast<uint32_t
>(Ctx.Ptr - GlobalStart);
1507 Globals.push_back(
Global);
1509 if (Ctx.Ptr != Ctx.End)
1515Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1517 Exports.reserve(
Count);
1518 Symbols.reserve(
Count);
1522 if (HasDylinkSection) {
1523 for (
const auto &ExportInfo : DylinkInfo.ExportInfo) {
1528 for (uint32_t
I = 0;
I <
Count;
I++) {
1529 wasm::WasmExport Ex;
1533 const wasm::WasmSignature *Signature =
nullptr;
1534 const wasm::WasmGlobalType *GlobalType =
nullptr;
1535 const wasm::WasmTableType *TableType =
nullptr;
1536 wasm::WasmSymbolInfo
Info;
1541 if (HasDylinkSection) {
1544 Info.Flags = It->second;
1549 if (!isValidFunctionIndex(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];
1566 if (!isValidGlobalIndex(Ex.
Index))
1571 if (isDefinedGlobalIndex(Ex.
Index)) {
1573 if (!
Global.InitExpr.Extended) {
1574 auto Inst =
Global.InitExpr.Inst;
1576 Offset = Inst.Value.Int32;
1578 Offset = Inst.Value.Int64;
1582 Info.DataRef = wasm::WasmDataReference{0,
Offset, 0};
1586 if (!isValidTagIndex(Ex.
Index))
1591 if (isDefinedTagIndex(Ex.
Index)) {
1592 unsigned TagIndex = Ex.
Index - NumImportedTags;
1593 Signature = &Signatures[Tags[TagIndex].SigIndex];
1606 Exports.push_back(Ex);
1608 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
1609 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
1612 if (Ctx.Ptr != Ctx.End)
1618bool WasmObjectFile::isValidFunctionIndex(uint32_t Index)
const {
1619 return Index < NumImportedFunctions + Functions.size();
1622bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index)
const {
1623 return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1626bool WasmObjectFile::isValidGlobalIndex(uint32_t Index)
const {
1627 return Index < NumImportedGlobals + Globals.size();
1630bool WasmObjectFile::isValidTableNumber(uint32_t Index)
const {
1631 return Index < NumImportedTables + Tables.size();
1634bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index)
const {
1635 return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1638bool WasmObjectFile::isDefinedTableNumber(uint32_t Index)
const {
1639 return Index >= NumImportedTables && isValidTableNumber(Index);
1642bool WasmObjectFile::isValidTagIndex(uint32_t Index)
const {
1643 return Index < NumImportedTags + Tags.size();
1646bool WasmObjectFile::isDefinedTagIndex(uint32_t Index)
const {
1647 return Index >= NumImportedTags && isValidTagIndex(Index);
1650bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index)
const {
1651 return Index < Symbols.size() && Symbols[
Index].isTypeFunction();
1654bool WasmObjectFile::isValidTableSymbol(uint32_t Index)
const {
1655 return Index < Symbols.size() && Symbols[
Index].isTypeTable();
1658bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index)
const {
1659 return Index < Symbols.size() && Symbols[
Index].isTypeGlobal();
1662bool WasmObjectFile::isValidTagSymbol(uint32_t Index)
const {
1663 return Index < Symbols.size() && Symbols[
Index].isTypeTag();
1666bool WasmObjectFile::isValidDataSymbol(uint32_t Index)
const {
1667 return Index < Symbols.size() && Symbols[
Index].isTypeData();
1670bool WasmObjectFile::isValidSectionSymbol(uint32_t Index)
const {
1671 return Index < Symbols.size() && Symbols[
Index].isTypeSection();
1674wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1675 assert(isDefinedFunctionIndex(Index));
1676 return Functions[
Index - NumImportedFunctions];
1679const wasm::WasmFunction &
1680WasmObjectFile::getDefinedFunction(uint32_t Index)
const {
1681 assert(isDefinedFunctionIndex(Index));
1682 return Functions[
Index - NumImportedFunctions];
1685const wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index)
const {
1686 assert(isDefinedGlobalIndex(Index));
1687 return Globals[
Index - NumImportedGlobals];
1690wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1691 assert(isDefinedTagIndex(Index));
1692 return Tags[
Index - NumImportedTags];
1695Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1697 if (!isValidFunctionIndex(StartFunction))
1703Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1704 CodeSection = Sections.size();
1706 if (FunctionCount != Functions.size()) {
1711 for (uint32_t i = 0; i < FunctionCount; i++) {
1712 wasm::WasmFunction&
Function = Functions[i];
1713 const uint8_t *FunctionStart = Ctx.Ptr;
1715 const uint8_t *FunctionEnd = Ctx.Ptr +
Size;
1717 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1718 Function.Index = NumImportedFunctions + i;
1719 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1720 Function.Size = FunctionEnd - FunctionStart;
1723 Function.Locals.reserve(NumLocalDecls);
1724 while (NumLocalDecls--) {
1725 wasm::WasmLocalDecl Decl;
1731 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1733 if (Ctx.Ptr + BodySize > Ctx.End) {
1737 Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1740 Ctx.Ptr += BodySize;
1741 assert(Ctx.Ptr == FunctionEnd);
1743 if (Ctx.Ptr != Ctx.End)
1749Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1751 ElemSegments.reserve(
Count);
1753 wasm::WasmElemSegment Segment;
1759 if (Segment.
Flags & ~SupportedFlags)
1771 bool HasTableNumber =
1818 }
else if (HasElemType) {
1828 while (NumElems--) {
1829 wasm::WasmInitExpr Expr;
1834 while (NumElems--) {
1838 ElemSegments.push_back(Segment);
1840 if (Ctx.Ptr != Ctx.End)
1846Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1847 DataSection = Sections.size();
1849 if (DataCount &&
Count != *DataCount)
1851 "number of data segments does not match DataCount section");
1852 DataSegments.reserve(
Count);
1854 WasmSegment Segment;
1869 if (
Size > (
size_t)(Ctx.End - Ctx.Ptr))
1880 DataSegments.push_back(Segment);
1882 if (Ctx.Ptr != Ctx.End)
1888Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1903 LLVM_DEBUG(
dbgs() <<
"getSymbolFlags: ptr=" << &Sym <<
" " << Sym <<
"\n");
1927 Ref.d.b = Symbols.size();
1932 return Symbols[Symb.
d.
b];
1945 if (!Sym.isDefined())
1952 isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
1953 return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
1957 isDefinedGlobalIndex(Sym.Info.ElementIndex)) {
1958 return getDefinedGlobal(Sym.Info.ElementIndex).Offset + SectionAddress;
2038 Ref.d.a = getSymbolSectionIdImpl(Sym);
2044 return getSymbolSectionIdImpl(Sym);
2052 return GlobalSection;
2060 return TableSection;
2098 : Sections[Sec.
d.
a].Offset;
2140 RelocRef.
d.
a =
Ref.d.a;
2148 RelocRef.
d.
a =
Ref.d.a;
2162 if (Rel.
Type == wasm::R_WASM_TYPE_INDEX_LEB)
2180#define WASM_RELOC(name, value) \
2186#include "llvm/BinaryFormat/WasmRelocs.def"
2191 Result.append(Res.
begin(), Res.
end());
2202 Ref.d.a = Sections.size();
2213 if (!LinkingData.TargetArch.empty())
2215 if (!DylinkInfo.TargetArch.empty())
2233 return Sections[
Ref.d.a];
2254int WasmSectionOrderChecker::getSectionOrder(
unsigned ID,
2302 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2306 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2308 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2310 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2312 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2314 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2316 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2318 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2320 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2322 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2324 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2326 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2328 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2330 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2334 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2336 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2340 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2342 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2344 {WASM_SEC_ORDER_TARGET_FEATURES}};
2348 int Order = getSectionOrder(ID, CustomSectionName);
2361 for (
size_t I = 0;; ++
I) {
2368 Checked[
Next] =
true;
2371 if (WorkList.
empty())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseSet and SmallDenseSet classes.
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...
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)
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),...
size_t size() const
Get the array size.
Helper for Errors used as out-parameters.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
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.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr size_t size() const
Get the string size.
const unsigned char * bytes_begin() const
std::pair< typename Base::iterator, bool > insert(StringRef key)
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.
ArchType getArch() const
Get the parsed architecture type of this triple.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static Twine utohexstr(uint64_t Val)
std::pair< iterator, bool > insert(const ValueT &V)
This is a value type class that represents a single symbol in the list of symbols in the object file.
DataRefImpl getRawDataRefImpl() const
StringRef getData() const
friend class RelocationRef
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
bool isSharedObject() const
const wasm::WasmRelocation & getWasmRelocation(const RelocationRef &Ref) const
uint32_t getSymbolSize(SymbolRef Sym) const
ArrayRef< wasm::WasmFunction > functions() const
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="")
@ WASM_SEC_ORDER_TARGET_FEATURES
@ WASM_SEC_ORDER_PRODUCERS
@ WASM_SEC_ORDER_DATACOUNT
@ WASM_SEC_ORDER_FUNCTION
static LLVM_ABI int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]
bool isTypeFunction() const
unsigned getBinding() const
LLVM_DUMP_METHOD void dump() const
bool isBindingWeak() const
wasm::WasmSymbolInfo Info
LLVM_ABI void print(raw_ostream &Out) const
bool isBindingLocal() const
bool isTypeGlobal() const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
content_iterator< SectionRef > section_iterator
content_iterator< BasicSymbolRef > basic_symbol_iterator
content_iterator< RelocationRef > relocation_iterator
uint32_t read32le(const void *P)
const unsigned WASM_SYMBOL_UNDEFINED
@ WASM_NAMES_DATA_SEGMENT
const unsigned WASM_SYMBOL_NO_STRIP
const unsigned WASM_SYMBOL_BINDING_GLOBAL
const unsigned WASM_SYMBOL_TLS
const uint32_t WasmMetadataVersion
const unsigned WASM_SYMBOL_BINDING_WEAK
const unsigned WASM_SYMBOL_BINDING_LOCAL
@ WASM_LIMITS_FLAG_HAS_MAX
@ WASM_LIMITS_FLAG_HAS_PAGE_SIZE
@ WASM_FEATURE_PREFIX_USED
@ WASM_FEATURE_PREFIX_DISALLOWED
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_FUNCTION
const uint32_t WasmVersion
const unsigned WASM_SYMBOL_BINDING_COMMON
const unsigned WASM_SYMBOL_EXPORTED
const unsigned WASM_SYMBOL_BINDING_MASK
@ WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
@ WASM_ELEM_SEGMENT_IS_DECLARATIVE
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
@ WASM_ELEM_SEGMENT_IS_PASSIVE
@ WASM_DYLINK_RUNTIME_PATH
@ WASM_DYLINK_EXPORT_INFO
@ WASM_DYLINK_IMPORT_INFO
@ WASM_DYLINK_TARGET_ARCH
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
LLVM_ABI llvm::StringRef sectionTypeToString(uint32_t type)
const unsigned WASM_SYMBOL_EXPLICIT_NAME
const unsigned WASM_SYMBOL_ABSOLUTE
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC
@ WASM_OPCODE_ARRAY_NEW_FIXED
@ WASM_OPCODE_ARRAY_NEW_DEFAULT
@ WASM_OPCODE_STRUCT_NEW_DEFAULT
This is an optimization pass for GlobalISel generic memory operations.
@ 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.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
const char * to_string(ThinOrFullLTOPhase Phase)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
@ Global
Append to llvm.global_dtors.
@ Ref
The access may reference the value stored in memory.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
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.
ArrayRef< uint8_t > Content
std::vector< wasm::WasmRelocation > Relocations
wasm::WasmDataSegment Data
ArrayRef< uint8_t > Content
std::vector< StringRef > Needed
std::vector< uint32_t > Functions
union llvm::wasm::WasmInitExprMVP::@234311111124136373374304035273310237314141125040 Value
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params
enum llvm::wasm::WasmSignature::@330257225222011177372050205212257221301063235146 Kind
WasmDataReference DataRef
struct llvm::object::DataRefImpl::@005117267142344013370254144343227032034000327225 d