32#define DEBUG_TYPE "wasm-object"
35using namespace object;
61#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
68 auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
70 return std::move(Err);
75#define VARINT7_MAX ((1 << 7) - 1)
76#define VARINT7_MIN (-(1 << 7))
77#define VARUINT7_MAX (1 << 7)
78#define VARUINT1_MAX (1)
98 memcpy(&Result, Ctx.
Ptr,
sizeof(Result));
99 Ctx.
Ptr +=
sizeof(Result);
104 if (Ctx.
Ptr + 8 > Ctx.
End)
107 memcpy(&Result, Ctx.
Ptr,
sizeof(Result));
108 Ctx.
Ptr +=
sizeof(Result);
114 const char *
Error =
nullptr;
124 if (Ctx.
Ptr + StringLen > Ctx.
End)
127 StringRef(
reinterpret_cast<const char *
>(Ctx.
Ptr), StringLen);
128 Ctx.
Ptr += StringLen;
134 const char *
Error =
nullptr;
151 if (Result > INT32_MAX || Result < INT32_MIN)
158 if (Result > UINT32_MAX)
198 auto Start = Ctx.
Ptr;
278 return make_error<GenericBinaryError>(
279 Twine(
"invalid opcode in init_expr: ") +
Twine(
unsigned(Opcode)),
296 if (PageSizeLog2 >= 32)
298 Result.PageSize = 1 << PageSizeLog2;
314 LLVM_DEBUG(
dbgs() <<
"readSection type=" << Section.Type <<
"\n");
319 Section.HeaderSecSizeEncodingLen = Ctx.
Ptr - PreSizePtr;
320 Section.Offset = Ctx.
Ptr - Ctx.
Start;
322 return make_error<StringError>(
"zero length section",
325 return make_error<StringError>(
"section too large",
336 Ctx.
Ptr += SectionNameSize;
337 Size -= SectionNameSize;
340 if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
341 return make_error<StringError>(
"out of order section type: " +
356 Err = make_error<StringError>(
"invalid magic number",
366 if (Ctx.
Ptr + 4 > Ctx.
End) {
367 Err = make_error<StringError>(
"missing version number",
374 Err = make_error<StringError>(
"invalid version number: " +
381 while (Ctx.
Ptr < Ctx.
End) {
385 if ((Err = parseSection(Sec)))
388 Sections.push_back(Sec);
399 return parseCustomSection(Sec, Ctx);
401 return parseTypeSection(Ctx);
403 return parseImportSection(Ctx);
405 return parseFunctionSection(Ctx);
407 return parseTableSection(Ctx);
409 return parseMemorySection(Ctx);
411 return parseTagSection(Ctx);
413 return parseGlobalSection(Ctx);
415 return parseExportSection(Ctx);
417 return parseStartSection(Ctx);
419 return parseElemSection(Ctx);
421 return parseCodeSection(Ctx);
423 return parseDataSection(Ctx);
425 return parseDataCountSection(Ctx);
427 return make_error<GenericBinaryError>(
432Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
435 HasDylinkSection =
true;
445 if (Ctx.Ptr != Ctx.End)
446 return make_error<GenericBinaryError>(
"dylink section ended prematurely",
451Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
454 HasDylinkSection =
true;
456 const uint8_t *OrigEnd = Ctx.End;
457 while (Ctx.Ptr < OrigEnd) {
463 Ctx.End = Ctx.Ptr +
Size;
505 if (Ctx.Ptr != Ctx.End) {
506 return make_error<GenericBinaryError>(
511 if (Ctx.Ptr != Ctx.End)
512 return make_error<GenericBinaryError>(
"dylink.0 section ended prematurely",
517Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
524 bool PopulateSymbolTable = !HasLinkingSection && !HasDylinkSection;
528 if (PopulateSymbolTable)
531 while (Ctx.Ptr < Ctx.End) {
556 if (!SeenFunctions.
insert(Index).second)
557 return make_error<GenericBinaryError>(
559 if (!isValidFunctionIndex(Index) ||
Name.empty())
560 return make_error<GenericBinaryError>(
"invalid function name entry",
563 if (isDefinedFunctionIndex(Index)) {
566 Signature = &Signatures[
F.SigIndex];
568 Info.ExportName =
F.ExportName;
577 if (!SeenGlobals.
insert(Index).second)
578 return make_error<GenericBinaryError>(
"global named more than once",
580 if (!isValidGlobalIndex(Index) ||
Name.empty())
581 return make_error<GenericBinaryError>(
"invalid global name entry",
585 if (isDefinedGlobalIndex(Index)) {
586 GlobalType = &getDefinedGlobal(Index).
Type;
591 if (!SeenSegments.
insert(Index).second)
592 return make_error<GenericBinaryError>(
594 if (Index > DataSegments.size())
595 return make_error<GenericBinaryError>(
"invalid data segment name entry",
600 assert(Index < DataSegments.size());
602 Index, 0, DataSegments[
Index].Data.Content.size()};
605 if (PopulateSymbolTable)
606 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
616 if (Ctx.Ptr != SubSectionEnd)
617 return make_error<GenericBinaryError>(
621 if (Ctx.Ptr != Ctx.End)
622 return make_error<GenericBinaryError>(
"name section ended prematurely",
627Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
628 HasLinkingSection =
true;
632 return make_error<GenericBinaryError>(
633 "unexpected metadata version: " +
Twine(LinkingData.
Version) +
638 const uint8_t *OrigEnd = Ctx.End;
639 while (Ctx.Ptr < OrigEnd) {
645 Ctx.End = Ctx.Ptr +
Size;
648 if (
Error Err = parseLinkingSectionSymtab(Ctx))
653 if (Count > DataSegments.size())
654 return make_error<GenericBinaryError>(
"too many segment names",
670 if (!isValidFunctionSymbol(
Init.Symbol))
671 return make_error<GenericBinaryError>(
"invalid function symbol: " +
679 if (
Error Err = parseLinkingSectionComdat(Ctx))
686 if (Ctx.Ptr != Ctx.End)
687 return make_error<GenericBinaryError>(
690 if (Ctx.Ptr != OrigEnd)
691 return make_error<GenericBinaryError>(
"linking section ended prematurely",
696Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
701 Symbols.reserve(Count);
704 std::vector<wasm::WasmImport *> ImportedGlobals;
705 std::vector<wasm::WasmImport *> ImportedFunctions;
706 std::vector<wasm::WasmImport *> ImportedTags;
707 std::vector<wasm::WasmImport *> ImportedTables;
708 ImportedGlobals.reserve(Imports.size());
709 ImportedFunctions.reserve(Imports.size());
710 ImportedTags.reserve(Imports.size());
711 ImportedTables.reserve(Imports.size());
712 for (
auto &
I : Imports) {
714 ImportedFunctions.emplace_back(&
I);
716 ImportedGlobals.emplace_back(&
I);
718 ImportedTags.emplace_back(&
I);
720 ImportedTables.emplace_back(&
I);
736 if (!isValidFunctionIndex(
Info.ElementIndex) ||
737 IsDefined != isDefinedFunctionIndex(
Info.ElementIndex))
738 return make_error<GenericBinaryError>(
"invalid function symbol index",
742 unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
744 Signature = &Signatures[
Function.SigIndex];
755 Signature = &Signatures[
Import.SigIndex];
762 if (!isValidGlobalIndex(
Info.ElementIndex) ||
763 IsDefined != isDefinedGlobalIndex(
Info.ElementIndex))
764 return make_error<GenericBinaryError>(
"invalid global symbol index",
768 return make_error<GenericBinaryError>(
"undefined weak global symbol",
772 unsigned GlobalIndex =
Info.ElementIndex - NumImportedGlobals;
774 GlobalType = &
Global.Type;
775 if (
Global.SymbolName.empty())
785 GlobalType = &
Import.Global;
792 if (!isValidTableNumber(
Info.ElementIndex) ||
793 IsDefined != isDefinedTableNumber(
Info.ElementIndex))
794 return make_error<GenericBinaryError>(
"invalid table symbol index",
798 return make_error<GenericBinaryError>(
"undefined weak table symbol",
802 unsigned TableNumber =
Info.ElementIndex - NumImportedTables;
804 TableType = &Table.
Type;
815 TableType = &
Import.Table;
827 if (
static_cast<size_t>(Index) >= DataSegments.size())
828 return make_error<GenericBinaryError>(
829 "invalid data segment index: " +
Twine(Index),
831 size_t SegmentSize = DataSegments[
Index].Data.Content.size();
833 return make_error<GenericBinaryError>(
834 "invalid data symbol offset: `" +
Info.Name +
836 " segment size: " +
Twine(SegmentSize) +
")",
846 return make_error<GenericBinaryError>(
847 "section symbols must have local binding",
858 if (!isValidTagIndex(
Info.ElementIndex) ||
859 IsDefined != isDefinedTagIndex(
Info.ElementIndex))
860 return make_error<GenericBinaryError>(
"invalid tag symbol index",
864 return make_error<GenericBinaryError>(
"undefined weak global symbol",
868 unsigned TagIndex =
Info.ElementIndex - NumImportedTags;
870 Signature = &Signatures[
Tag.SigIndex];
871 if (
Tag.SymbolName.empty())
882 Signature = &Signatures[
Import.SigIndex];
889 return make_error<GenericBinaryError>(
"invalid symbol type: " +
897 return make_error<GenericBinaryError>(
"duplicate symbol name " +
900 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
901 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
907Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
910 for (
unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
913 return make_error<GenericBinaryError>(
"bad/duplicate COMDAT name " +
919 return make_error<GenericBinaryError>(
"unsupported COMDAT flags",
923 while (EntryCount--) {
928 return make_error<GenericBinaryError>(
"invalid COMDAT entry type",
931 if (Index >= DataSegments.size())
932 return make_error<GenericBinaryError>(
934 if (DataSegments[Index].
Data.Comdat != UINT32_MAX)
935 return make_error<GenericBinaryError>(
"data segment in two COMDATs",
937 DataSegments[
Index].Data.Comdat = ComdatIndex;
940 if (!isDefinedFunctionIndex(Index))
941 return make_error<GenericBinaryError>(
943 if (getDefinedFunction(Index).
Comdat != UINT32_MAX)
944 return make_error<GenericBinaryError>(
"function in two COMDATs",
946 getDefinedFunction(Index).
Comdat = ComdatIndex;
949 if (Index >= Sections.size())
950 return make_error<GenericBinaryError>(
953 return make_error<GenericBinaryError>(
955 Sections[
Index].Comdat = ComdatIndex;
963Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
966 for (
size_t I = 0;
I < Fields; ++
I) {
968 if (!FieldsSeen.
insert(FieldName).second)
969 return make_error<GenericBinaryError>(
970 "producers section does not have unique fields",
972 std::vector<std::pair<std::string, std::string>> *ProducerVec =
nullptr;
973 if (FieldName ==
"language") {
975 }
else if (FieldName ==
"processed-by") {
976 ProducerVec = &ProducerInfo.
Tools;
977 }
else if (FieldName ==
"sdk") {
978 ProducerVec = &ProducerInfo.
SDKs;
980 return make_error<GenericBinaryError>(
981 "producers section field is not named one of language, processed-by, "
987 for (
size_t J = 0; J < ValueCount; ++J) {
991 return make_error<GenericBinaryError>(
992 "producers section contains repeated producer",
995 ProducerVec->emplace_back(std::string(
Name), std::string(
Version));
998 if (Ctx.Ptr != Ctx.End)
999 return make_error<GenericBinaryError>(
"producers section ended prematurely",
1004Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
1010 switch (Feature.
Prefix) {
1015 return make_error<GenericBinaryError>(
"unknown feature policy prefix",
1019 if (!FeaturesSeen.
insert(Feature.
Name).second)
1020 return make_error<GenericBinaryError>(
1021 "target features section contains repeated feature \"" +
1022 Feature.
Name +
"\"",
1024 TargetFeatures.push_back(Feature);
1026 if (Ctx.Ptr != Ctx.End)
1027 return make_error<GenericBinaryError>(
1028 "target features section ended prematurely",
1035 if (SectionIndex >= Sections.size())
1036 return make_error<GenericBinaryError>(
"invalid section index",
1042 while (RelocCount--) {
1047 if (Reloc.
Offset < PreviousOffset)
1048 return make_error<GenericBinaryError>(
"relocations not in offset order",
1052 return make_error<GenericBinaryError>(
1053 msg +
": " +
Twine(Symbols[Reloc.
Index].Info.Name),
1057 PreviousOffset = Reloc.
Offset;
1060 case wasm::R_WASM_FUNCTION_INDEX_LEB:
1061 case wasm::R_WASM_FUNCTION_INDEX_I32:
1062 case wasm::R_WASM_TABLE_INDEX_SLEB:
1063 case wasm::R_WASM_TABLE_INDEX_SLEB64:
1064 case wasm::R_WASM_TABLE_INDEX_I32:
1065 case wasm::R_WASM_TABLE_INDEX_I64:
1066 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
1067 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
1068 if (!isValidFunctionSymbol(Reloc.
Index))
1069 return badReloc(
"invalid function relocation");
1071 case wasm::R_WASM_TABLE_NUMBER_LEB:
1072 if (!isValidTableSymbol(Reloc.
Index))
1073 return badReloc(
"invalid table relocation");
1075 case wasm::R_WASM_TYPE_INDEX_LEB:
1076 if (Reloc.
Index >= Signatures.size())
1077 return badReloc(
"invalid relocation type index");
1079 case wasm::R_WASM_GLOBAL_INDEX_LEB:
1082 if (!isValidGlobalSymbol(Reloc.
Index) &&
1083 !isValidDataSymbol(Reloc.
Index) &&
1084 !isValidFunctionSymbol(Reloc.
Index))
1085 return badReloc(
"invalid global relocation");
1087 case wasm::R_WASM_GLOBAL_INDEX_I32:
1088 if (!isValidGlobalSymbol(Reloc.
Index))
1089 return badReloc(
"invalid global relocation");
1091 case wasm::R_WASM_TAG_INDEX_LEB:
1092 if (!isValidTagSymbol(Reloc.
Index))
1093 return badReloc(
"invalid tag relocation");
1095 case wasm::R_WASM_MEMORY_ADDR_LEB:
1096 case wasm::R_WASM_MEMORY_ADDR_SLEB:
1097 case wasm::R_WASM_MEMORY_ADDR_I32:
1098 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1099 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1100 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1101 if (!isValidDataSymbol(Reloc.
Index))
1102 return badReloc(
"invalid data relocation");
1105 case wasm::R_WASM_MEMORY_ADDR_LEB64:
1106 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1107 case wasm::R_WASM_MEMORY_ADDR_I64:
1108 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1109 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1110 if (!isValidDataSymbol(Reloc.
Index))
1111 return badReloc(
"invalid data relocation");
1114 case wasm::R_WASM_FUNCTION_OFFSET_I32:
1115 if (!isValidFunctionSymbol(Reloc.
Index))
1116 return badReloc(
"invalid function relocation");
1119 case wasm::R_WASM_FUNCTION_OFFSET_I64:
1120 if (!isValidFunctionSymbol(Reloc.
Index))
1121 return badReloc(
"invalid function relocation");
1124 case wasm::R_WASM_SECTION_OFFSET_I32:
1125 if (!isValidSectionSymbol(Reloc.
Index))
1126 return badReloc(
"invalid section relocation");
1130 return make_error<GenericBinaryError>(
"invalid relocation type: " +
1139 if (Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1140 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1141 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1143 if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1144 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1145 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1146 Reloc.
Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1147 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1148 Reloc.
Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
1149 Reloc.
Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1151 if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1152 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1153 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1156 return make_error<GenericBinaryError>(
"invalid relocation offset",
1159 Section.Relocations.push_back(Reloc);
1161 if (Ctx.Ptr != Ctx.End)
1162 return make_error<GenericBinaryError>(
"reloc section ended prematurely",
1167Error WasmObjectFile::parseCustomSection(
WasmSection &Sec, ReadContext &Ctx) {
1168 if (Sec.
Name ==
"dylink") {
1169 if (
Error Err = parseDylinkSection(Ctx))
1171 }
else if (Sec.
Name ==
"dylink.0") {
1172 if (
Error Err = parseDylink0Section(Ctx))
1174 }
else if (Sec.
Name ==
"name") {
1175 if (
Error Err = parseNameSection(Ctx))
1177 }
else if (Sec.
Name ==
"linking") {
1178 if (
Error Err = parseLinkingSection(Ctx))
1180 }
else if (Sec.
Name ==
"producers") {
1181 if (
Error Err = parseProducersSection(Ctx))
1183 }
else if (Sec.
Name ==
"target_features") {
1184 if (
Error Err = parseTargetFeaturesSection(Ctx))
1187 if (
Error Err = parseRelocSection(Sec.
Name, Ctx))
1193Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1194 auto parseFieldDef = [&]() {
1201 Signatures.reserve(Count);
1210 return make_error<GenericBinaryError>(
"Rec group size cannot be 0",
1212 Signatures.reserve(Signatures.size() + RecSize);
1215 Signatures.push_back(std::move(Sig));
1216 HasUnmodeledTypes =
true;
1227 return make_error<GenericBinaryError>(
1235 while (FieldCount--) {
1241 return make_error<GenericBinaryError>(
"bad form",
1245 Signatures.push_back(std::move(Sig));
1246 HasUnmodeledTypes =
true;
1252 while (ParamCount--) {
1257 while (ReturnCount--) {
1262 Signatures.push_back(std::move(Sig));
1264 if (Ctx.Ptr != Ctx.End)
1265 return make_error<GenericBinaryError>(
"type section ended prematurely",
1270Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1272 uint32_t NumTypes = Signatures.size();
1273 Imports.reserve(Count);
1281 NumImportedFunctions++;
1284 return make_error<GenericBinaryError>(
"invalid function type",
1288 NumImportedGlobals++;
1299 NumImportedTables++;
1305 return make_error<GenericBinaryError>(
"invalid table element type",
1312 return make_error<GenericBinaryError>(
"invalid attribute",
1316 return make_error<GenericBinaryError>(
"invalid tag type",
1320 return make_error<GenericBinaryError>(
"unexpected import kind",
1323 Imports.push_back(Im);
1325 if (Ctx.Ptr != Ctx.End)
1326 return make_error<GenericBinaryError>(
"import section ended prematurely",
1331Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1333 Functions.reserve(Count);
1334 uint32_t NumTypes = Signatures.size();
1337 if (
Type >= NumTypes)
1338 return make_error<GenericBinaryError>(
"invalid function type",
1342 Functions.push_back(
F);
1344 if (Ctx.Ptr != Ctx.End)
1345 return make_error<GenericBinaryError>(
"function section ended prematurely",
1350Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1351 TableSection = Sections.size();
1353 Tables.reserve(Count);
1357 T.Index = NumImportedTables + Tables.size();
1358 Tables.push_back(
T);
1359 auto ElemType = Tables.back().Type.ElemType;
1364 return make_error<GenericBinaryError>(
"invalid table element type",
1368 if (Ctx.Ptr != Ctx.End)
1369 return make_error<GenericBinaryError>(
"table section ended prematurely",
1374Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1376 Memories.reserve(Count);
1381 Memories.push_back(Limits);
1383 if (Ctx.Ptr != Ctx.End)
1384 return make_error<GenericBinaryError>(
"memory section ended prematurely",
1389Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1390 TagSection = Sections.size();
1392 Tags.reserve(Count);
1393 uint32_t NumTypes = Signatures.size();
1396 return make_error<GenericBinaryError>(
"invalid attribute",
1399 if (
Type >= NumTypes)
1400 return make_error<GenericBinaryError>(
"invalid tag type",
1403 Tag.Index = NumImportedTags + Tags.size();
1406 Tags.push_back(
Tag);
1409 if (Ctx.Ptr != Ctx.End)
1410 return make_error<GenericBinaryError>(
"tag section ended prematurely",
1415Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1416 GlobalSection = Sections.size();
1417 const uint8_t *SectionStart = Ctx.Ptr;
1419 Globals.reserve(Count);
1422 Global.Index = NumImportedGlobals + Globals.size();
1423 const uint8_t *GlobalStart = Ctx.Ptr;
1424 Global.Offset =
static_cast<uint32_t>(GlobalStart - SectionStart);
1431 Globals.push_back(
Global);
1433 if (Ctx.Ptr != Ctx.End)
1434 return make_error<GenericBinaryError>(
"global section ended prematurely",
1439Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1441 Exports.reserve(Count);
1442 Symbols.reserve(Count);
1456 if (!isValidFunctionIndex(Ex.
Index))
1457 return make_error<GenericBinaryError>(
"invalid function export",
1461 if (isDefinedFunctionIndex(Ex.
Index)) {
1463 unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
1465 Signature = &Signatures[
Function.SigIndex];
1473 if (!isValidGlobalIndex(Ex.
Index))
1474 return make_error<GenericBinaryError>(
"invalid global export",
1478 if (isDefinedGlobalIndex(Ex.
Index)) {
1480 if (!
Global.InitExpr.Extended) {
1481 auto Inst =
Global.InitExpr.Inst;
1483 Offset = Inst.Value.Int32;
1485 Offset = Inst.Value.Int64;
1493 if (!isValidTagIndex(Ex.
Index))
1494 return make_error<GenericBinaryError>(
"invalid tag export",
1506 return make_error<GenericBinaryError>(
"unexpected export kind",
1509 Exports.push_back(Ex);
1511 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
1512 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
1515 if (Ctx.Ptr != Ctx.End)
1516 return make_error<GenericBinaryError>(
"export section ended prematurely",
1521bool WasmObjectFile::isValidFunctionIndex(
uint32_t Index)
const {
1522 return Index < NumImportedFunctions + Functions.size();
1525bool WasmObjectFile::isDefinedFunctionIndex(
uint32_t Index)
const {
1526 return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1529bool WasmObjectFile::isValidGlobalIndex(
uint32_t Index)
const {
1530 return Index < NumImportedGlobals + Globals.size();
1533bool WasmObjectFile::isValidTableNumber(
uint32_t Index)
const {
1534 return Index < NumImportedTables + Tables.size();
1537bool WasmObjectFile::isDefinedGlobalIndex(
uint32_t Index)
const {
1538 return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1541bool WasmObjectFile::isDefinedTableNumber(
uint32_t Index)
const {
1542 return Index >= NumImportedTables && isValidTableNumber(Index);
1545bool WasmObjectFile::isValidTagIndex(
uint32_t Index)
const {
1546 return Index < NumImportedTags + Tags.size();
1549bool WasmObjectFile::isDefinedTagIndex(
uint32_t Index)
const {
1550 return Index >= NumImportedTags && isValidTagIndex(Index);
1553bool WasmObjectFile::isValidFunctionSymbol(
uint32_t Index)
const {
1554 return Index < Symbols.size() && Symbols[
Index].isTypeFunction();
1557bool WasmObjectFile::isValidTableSymbol(
uint32_t Index)
const {
1558 return Index < Symbols.size() && Symbols[
Index].isTypeTable();
1561bool WasmObjectFile::isValidGlobalSymbol(
uint32_t Index)
const {
1562 return Index < Symbols.size() && Symbols[
Index].isTypeGlobal();
1565bool WasmObjectFile::isValidTagSymbol(
uint32_t Index)
const {
1566 return Index < Symbols.size() && Symbols[
Index].isTypeTag();
1569bool WasmObjectFile::isValidDataSymbol(
uint32_t Index)
const {
1570 return Index < Symbols.size() && Symbols[
Index].isTypeData();
1573bool WasmObjectFile::isValidSectionSymbol(
uint32_t Index)
const {
1574 return Index < Symbols.size() && Symbols[
Index].isTypeSection();
1578 assert(isDefinedFunctionIndex(Index));
1579 return Functions[
Index - NumImportedFunctions];
1583WasmObjectFile::getDefinedFunction(
uint32_t Index)
const {
1584 assert(isDefinedFunctionIndex(Index));
1585 return Functions[
Index - NumImportedFunctions];
1589 assert(isDefinedGlobalIndex(Index));
1590 return Globals[
Index - NumImportedGlobals];
1594 assert(isDefinedTagIndex(Index));
1595 return Tags[
Index - NumImportedTags];
1598Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1600 if (!isValidFunctionIndex(StartFunction))
1601 return make_error<GenericBinaryError>(
"invalid start function",
1606Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1607 CodeSection = Sections.size();
1609 if (FunctionCount != Functions.size()) {
1610 return make_error<GenericBinaryError>(
"invalid function count",
1614 for (
uint32_t i = 0; i < FunctionCount; i++) {
1616 const uint8_t *FunctionStart = Ctx.Ptr;
1620 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1621 Function.Index = NumImportedFunctions + i;
1622 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1623 Function.Size = FunctionEnd - FunctionStart;
1626 Function.Locals.reserve(NumLocalDecls);
1627 while (NumLocalDecls--) {
1634 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1636 if (Ctx.Ptr + BodySize > Ctx.End) {
1637 return make_error<GenericBinaryError>(
"Function extends beyond buffer",
1643 Ctx.Ptr += BodySize;
1644 assert(Ctx.Ptr == FunctionEnd);
1646 if (Ctx.Ptr != Ctx.End)
1647 return make_error<GenericBinaryError>(
"code section ended prematurely",
1652Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1654 ElemSegments.reserve(Count);
1662 if (Segment.
Flags & ~SupportedFlags)
1663 return make_error<GenericBinaryError>(
1674 bool HasTableNumber =
1692 return make_error<GenericBinaryError>(
"invalid TableNumber",
1712 return make_error<GenericBinaryError>(
"invalid elem type",
1717 return make_error<GenericBinaryError>(
"invalid elem type",
1721 }
else if (HasElemType) {
1731 while (NumElems--) {
1737 while (NumElems--) {
1741 ElemSegments.push_back(Segment);
1743 if (Ctx.Ptr != Ctx.End)
1744 return make_error<GenericBinaryError>(
"elem section ended prematurely",
1749Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1750 DataSection = Sections.size();
1752 if (DataCount && Count != *DataCount)
1753 return make_error<GenericBinaryError>(
1754 "number of data segments does not match DataCount section");
1755 DataSegments.reserve(Count);
1772 if (
Size > (
size_t)(Ctx.End - Ctx.Ptr))
1773 return make_error<GenericBinaryError>(
"invalid segment size",
1783 DataSegments.push_back(Segment);
1785 if (Ctx.Ptr != Ctx.End)
1786 return make_error<GenericBinaryError>(
"data section ended prematurely",
1791Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1807 if (
Sym.isBindingWeak())
1809 if (!
Sym.isBindingLocal())
1813 if (!
Sym.isDefined())
1815 if (
Sym.isTypeFunction())
1830 Ref.d.b = Symbols.size();
1835 return Symbols[Symb.
d.
b];
1848 if (!
Sym.isDefined())
1855 isDefinedFunctionIndex(
Sym.Info.ElementIndex)) {
1860 isDefinedGlobalIndex(
Sym.Info.ElementIndex)) {
1861 return getDefinedGlobal(
Sym.Info.ElementIndex).
Offset + SectionAddress;
1868 switch (
Sym.Info.Kind) {
1873 return Sym.Info.ElementIndex;
1886 return Sym.Info.DataRef.Offset;
1915 switch (
Sym.Info.Kind) {
1937 if (
Sym.isUndefined())
1941 Ref.d.a = getSymbolSectionIdImpl(
Sym);
1947 return getSymbolSectionIdImpl(
Sym);
1951 switch (
Sym.Info.Kind) {
1955 return GlobalSection;
1959 return Sym.Info.ElementIndex;
1963 return TableSection;
1971 if (!
Sym.isDefined())
1973 if (
Sym.isTypeGlobal())
1974 return getDefinedGlobal(
Sym.Info.ElementIndex).
Size;
1975 if (
Sym.isTypeData())
1976 return Sym.Info.DataRef.Size;
1977 if (
Sym.isTypeFunction())
2001 : Sections[Sec.
d.
a].Offset;
2043 RelocRef.
d.
a =
Ref.d.a;
2051 RelocRef.
d.
a =
Ref.d.a;
2065 if (Rel.
Type == wasm::R_WASM_TYPE_INDEX_LEB)
2083#define WASM_RELOC(name, value) \
2089#include "llvm/BinaryFormat/WasmRelocs.def"
2094 Result.append(Res.
begin(), Res.
end());
2105 Ref.d.a = Sections.size();
2110 return HasMemory64 ? 8 : 4;
2129 return Sections[
Ref.d.a];
2150int WasmSectionOrderChecker::getSectionOrder(
unsigned ID,
2198 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2202 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2204 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2206 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2208 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2210 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2212 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2214 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2216 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2218 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2220 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2222 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2224 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2226 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2230 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2232 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2236 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2238 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2240 {WASM_SEC_ORDER_TARGET_FEATURES}};
2244 int Order = getSectionOrder(
ID, CustomSectionName);
2257 for (
size_t I = 0;; ++
I) {
2264 Checked[Next] =
true;
2267 if (WorkList.
empty())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Analysis containing CSE Info
#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.
This file defines the SmallSet class.
StringSet - A set-like wrapper for the StringMap.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx)
static Error readInitExpr(wasm::WasmInitExpr &Expr, WasmObjectFile::ReadContext &Ctx)
static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx)
static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx)
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx)
static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx)
static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx, WasmSectionOrderChecker &Checker)
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx)
static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx)
static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx)
static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx)
static StringRef readString(WasmObjectFile::ReadContext &Ctx)
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx)
static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx)
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx)
static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx)
static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx, uint32_t Code)
static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
Implements a dense probed hash-table based set.
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.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
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.
StringRef - 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 bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
const unsigned char * bytes_begin() const
StringSet - A wrapper for StringMap that provides set-like functionality.
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.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static Twine utohexstr(const uint64_t &Val)
The instances of the Type class are immutable: once they are created, they are never changed.
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
This class is the base class for all object file types.
friend class RelocationRef
static Expected< std::unique_ptr< WasmObjectFile > > createWasmObjectFile(MemoryBufferRef Object)
Expected< uint64_t > getSymbolValue(DataRefImpl Symb) const
This is a value type class that represents a single relocation in the list of relocations in the obje...
This is a value type class that represents a single section in the list of sections in the object fil...
This is a value type class that represents a single symbol in the list of symbols in the object file.
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
@ WASM_SEC_ORDER_TARGET_FEATURES
@ WASM_SEC_ORDER_PRODUCERS
@ WASM_SEC_ORDER_DATACOUNT
@ WASM_SEC_ORDER_FUNCTION
LLVM_ABI bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")
static LLVM_ABI int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]
unsigned getBinding() const
LLVM_DUMP_METHOD void dump() const
wasm::WasmSymbolInfo Info
LLVM_ABI void print(raw_ostream &Out) 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< RelocationRef > relocation_iterator
uint32_t read32le(const void *P)
const unsigned WASM_SYMBOL_UNDEFINED
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
@ WASM_LIMITS_FLAG_HAS_MAX
@ WASM_LIMITS_FLAG_HAS_PAGE_SIZE
const unsigned WASM_SYMBOL_BINDING_GLOBAL
@ WASM_DYLINK_RUNTIME_PATH
@ WASM_DYLINK_EXPORT_INFO
@ WASM_DYLINK_IMPORT_INFO
const uint32_t WasmMetadataVersion
const unsigned WASM_SYMBOL_BINDING_WEAK
const unsigned WASM_SYMBOL_BINDING_LOCAL
@ WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
@ WASM_ELEM_SEGMENT_IS_DECLARATIVE
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
@ WASM_ELEM_SEGMENT_IS_PASSIVE
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_FUNCTION
const uint32_t WasmVersion
const unsigned WASM_SYMBOL_BINDING_MASK
@ WASM_OPCODE_ARRAY_NEW_FIXED
@ WASM_OPCODE_ARRAY_NEW_DEFAULT
@ WASM_OPCODE_STRUCT_NEW_DEFAULT
@ WASM_FEATURE_PREFIX_USED
@ WASM_FEATURE_PREFIX_DISALLOWED
LLVM_ABI llvm::StringRef sectionTypeToString(uint32_t type)
const unsigned WASM_SYMBOL_EXPLICIT_NAME
const unsigned WASM_SYMBOL_ABSOLUTE
@ WASM_NAMES_DATA_SEGMENT
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC
This is an optimization pass for GlobalISel generic memory operations.
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a ULEB128 value.
@ 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)
@ Global
Append to llvm.global_dtors.
@ Ref
The access may reference the value stored in memory.
const char * toString(DWARFSectionKind Kind)
ArrayRef< uint8_t > Content
std::vector< wasm::WasmRelocation > Relocations
wasm::WasmDataSegment Data
ArrayRef< uint8_t > Content
std::vector< StringRef > Needed
std::vector< StringRef > RuntimePath
std::vector< WasmDylinkExportInfo > ExportInfo
std::vector< WasmDylinkImportInfo > ImportInfo
std::vector< uint32_t > Functions
std::optional< StringRef > ExportName
uint32_t CodeSectionOffset
union llvm::wasm::WasmInitExprMVP::@188 Value
std::vector< WasmInitFunc > InitFunctions
std::vector< StringRef > Comdats
std::vector< std::pair< std::string, std::string > > SDKs
std::vector< std::pair< std::string, std::string > > Languages
std::vector< std::pair< std::string, std::string > > Tools
enum llvm::wasm::WasmSignature::@193 Kind
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params
WasmDataReference DataRef
struct llvm::object::DataRefImpl::@378 d