35#define DEBUG_TYPE "wasm-object"
38using namespace object;
64#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
71 auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
73 return std::move(Err);
78#define VARINT7_MAX ((1 << 7) - 1)
79#define VARINT7_MIN (-(1 << 7))
80#define VARUINT7_MAX (1 << 7)
81#define VARUINT1_MAX (1)
101 memcpy(&Result, Ctx.
Ptr,
sizeof(Result));
102 Ctx.
Ptr +=
sizeof(Result);
107 if (Ctx.
Ptr + 8 > Ctx.
End)
110 memcpy(&Result, Ctx.
Ptr,
sizeof(Result));
111 Ctx.
Ptr +=
sizeof(Result);
117 const char *
Error =
nullptr;
127 if (Ctx.
Ptr + StringLen > Ctx.
End)
130 StringRef(
reinterpret_cast<const char *
>(Ctx.
Ptr), StringLen);
131 Ctx.
Ptr += StringLen;
137 const char *
Error =
nullptr;
154 if (Result > INT32_MAX || Result < INT32_MIN)
161 if (Result > UINT32_MAX)
200 auto Start = Ctx.
Ptr;
280 return make_error<GenericBinaryError>(
281 Twine(
"invalid opcode in init_expr: ") +
Twine(
unsigned(Opcode)),
310 LLVM_DEBUG(
dbgs() <<
"readSection type=" << Section.Type <<
"\n");
313 const uint8_t *PreSizePtr = Ctx.
Ptr;
315 Section.HeaderSecSizeEncodingLen = Ctx.
Ptr - PreSizePtr;
316 Section.Offset = Ctx.
Ptr - Ctx.
Start;
318 return make_error<StringError>(
"zero length section",
321 return make_error<StringError>(
"section too large",
332 Ctx.
Ptr += SectionNameSize;
333 Size -= SectionNameSize;
337 return make_error<StringError>(
"out of order section type: " +
352 Err = make_error<StringError>(
"invalid magic number",
362 if (Ctx.
Ptr + 4 > Ctx.
End) {
363 Err = make_error<StringError>(
"missing version number",
370 Err = make_error<StringError>(
"invalid version number: " +
377 while (Ctx.
Ptr < Ctx.
End) {
381 if ((Err = parseSection(Sec)))
384 Sections.push_back(Sec);
395 return parseCustomSection(Sec, Ctx);
397 return parseTypeSection(Ctx);
399 return parseImportSection(Ctx);
401 return parseFunctionSection(Ctx);
403 return parseTableSection(Ctx);
405 return parseMemorySection(Ctx);
407 return parseTagSection(Ctx);
409 return parseGlobalSection(Ctx);
411 return parseExportSection(Ctx);
413 return parseStartSection(Ctx);
415 return parseElemSection(Ctx);
417 return parseCodeSection(Ctx);
419 return parseDataSection(Ctx);
421 return parseDataCountSection(Ctx);
423 return make_error<GenericBinaryError>(
428Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
431 HasDylinkSection =
true;
441 if (Ctx.Ptr != Ctx.End)
442 return make_error<GenericBinaryError>(
"dylink section ended prematurely",
447Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
450 HasDylinkSection =
true;
452 const uint8_t *OrigEnd = Ctx.End;
453 while (Ctx.Ptr < OrigEnd) {
459 Ctx.End = Ctx.Ptr +
Size;
494 if (Ctx.Ptr != Ctx.End) {
495 return make_error<GenericBinaryError>(
500 if (Ctx.Ptr != Ctx.End)
501 return make_error<GenericBinaryError>(
"dylink.0 section ended prematurely",
506Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
513 if (!HasLinkingSection) {
517 while (Ctx.Ptr < Ctx.End) {
520 const uint8_t *SubSectionEnd = Ctx.Ptr +
Size;
543 return make_error<GenericBinaryError>(
545 if (!isValidFunctionIndex(
Index) ||
Name.empty())
546 return make_error<GenericBinaryError>(
"invalid function name entry",
549 if (isDefinedFunctionIndex(
Index)) {
552 Signature = &Signatures[
F.SigIndex];
554 Info.ExportName =
F.ExportName;
564 return make_error<GenericBinaryError>(
"global named more than once",
566 if (!isValidGlobalIndex(
Index) ||
Name.empty())
567 return make_error<GenericBinaryError>(
"invalid global name entry",
571 if (isDefinedGlobalIndex(
Index)) {
572 GlobalType = &getDefinedGlobal(
Index).
Type;
578 return make_error<GenericBinaryError>(
580 if (
Index > DataSegments.size())
581 return make_error<GenericBinaryError>(
"invalid data segment name entry",
588 Index, 0, DataSegments[
Index].Data.Content.size()};
591 if (!HasLinkingSection)
592 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
602 if (Ctx.Ptr != SubSectionEnd)
603 return make_error<GenericBinaryError>(
607 if (Ctx.Ptr != Ctx.End)
608 return make_error<GenericBinaryError>(
"name section ended prematurely",
613Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
614 HasLinkingSection =
true;
618 return make_error<GenericBinaryError>(
619 "unexpected metadata version: " +
Twine(LinkingData.
Version) +
624 const uint8_t *OrigEnd = Ctx.End;
625 while (Ctx.Ptr < OrigEnd) {
631 Ctx.End = Ctx.Ptr +
Size;
634 if (
Error Err = parseLinkingSectionSymtab(Ctx))
639 if (Count > DataSegments.size())
640 return make_error<GenericBinaryError>(
"too many segment names",
656 if (!isValidFunctionSymbol(
Init.Symbol))
657 return make_error<GenericBinaryError>(
"invalid function symbol: " +
665 if (
Error Err = parseLinkingSectionComdat(Ctx))
672 if (Ctx.Ptr != Ctx.End)
673 return make_error<GenericBinaryError>(
676 if (Ctx.Ptr != OrigEnd)
677 return make_error<GenericBinaryError>(
"linking section ended prematurely",
682Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
687 Symbols.reserve(Count);
690 std::vector<wasm::WasmImport *> ImportedGlobals;
691 std::vector<wasm::WasmImport *> ImportedFunctions;
692 std::vector<wasm::WasmImport *> ImportedTags;
693 std::vector<wasm::WasmImport *> ImportedTables;
694 ImportedGlobals.reserve(Imports.size());
695 ImportedFunctions.reserve(Imports.size());
696 ImportedTags.reserve(Imports.size());
697 ImportedTables.reserve(Imports.size());
698 for (
auto &
I : Imports) {
700 ImportedFunctions.emplace_back(&
I);
702 ImportedGlobals.emplace_back(&
I);
704 ImportedTags.emplace_back(&
I);
706 ImportedTables.emplace_back(&
I);
722 if (!isValidFunctionIndex(
Info.ElementIndex) ||
723 IsDefined != isDefinedFunctionIndex(
Info.ElementIndex))
724 return make_error<GenericBinaryError>(
"invalid function symbol index",
728 unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
730 Signature = &Signatures[
Function.SigIndex];
741 Signature = &Signatures[
Import.SigIndex];
748 if (!isValidGlobalIndex(
Info.ElementIndex) ||
749 IsDefined != isDefinedGlobalIndex(
Info.ElementIndex))
750 return make_error<GenericBinaryError>(
"invalid global symbol index",
754 return make_error<GenericBinaryError>(
"undefined weak global symbol",
758 unsigned GlobalIndex =
Info.ElementIndex - NumImportedGlobals;
760 GlobalType = &
Global.Type;
761 if (
Global.SymbolName.empty())
771 GlobalType = &
Import.Global;
778 if (!isValidTableNumber(
Info.ElementIndex) ||
779 IsDefined != isDefinedTableNumber(
Info.ElementIndex))
780 return make_error<GenericBinaryError>(
"invalid table symbol index",
784 return make_error<GenericBinaryError>(
"undefined weak table symbol",
788 unsigned TableNumber =
Info.ElementIndex - NumImportedTables;
790 TableType = &Table.
Type;
801 TableType = &
Import.Table;
813 if (
static_cast<size_t>(
Index) >= DataSegments.size())
814 return make_error<GenericBinaryError>(
815 "invalid data segment index: " +
Twine(
Index),
817 size_t SegmentSize = DataSegments[
Index].Data.Content.size();
819 return make_error<GenericBinaryError>(
820 "invalid data symbol offset: `" +
Info.Name +
822 " segment size: " +
Twine(SegmentSize) +
")",
832 return make_error<GenericBinaryError>(
833 "section symbols must have local binding",
844 if (!isValidTagIndex(
Info.ElementIndex) ||
845 IsDefined != isDefinedTagIndex(
Info.ElementIndex))
846 return make_error<GenericBinaryError>(
"invalid tag symbol index",
850 return make_error<GenericBinaryError>(
"undefined weak global symbol",
854 unsigned TagIndex =
Info.ElementIndex - NumImportedTags;
856 Signature = &Signatures[
Tag.SigIndex];
857 if (
Tag.SymbolName.empty())
868 Signature = &Signatures[
Import.SigIndex];
875 return make_error<GenericBinaryError>(
"invalid symbol type: " +
883 return make_error<GenericBinaryError>(
"duplicate symbol name " +
886 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
887 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
893Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
896 for (
unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
899 return make_error<GenericBinaryError>(
"bad/duplicate COMDAT name " +
905 return make_error<GenericBinaryError>(
"unsupported COMDAT flags",
909 while (EntryCount--) {
914 return make_error<GenericBinaryError>(
"invalid COMDAT entry type",
917 if (
Index >= DataSegments.size())
918 return make_error<GenericBinaryError>(
920 if (DataSegments[
Index].
Data.Comdat != UINT32_MAX)
921 return make_error<GenericBinaryError>(
"data segment in two COMDATs",
923 DataSegments[
Index].Data.Comdat = ComdatIndex;
926 if (!isDefinedFunctionIndex(
Index))
927 return make_error<GenericBinaryError>(
929 if (getDefinedFunction(
Index).
Comdat != UINT32_MAX)
930 return make_error<GenericBinaryError>(
"function in two COMDATs",
935 if (
Index >= Sections.size())
936 return make_error<GenericBinaryError>(
939 return make_error<GenericBinaryError>(
941 Sections[
Index].Comdat = ComdatIndex;
949Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
952 for (
size_t I = 0;
I < Fields; ++
I) {
954 if (!FieldsSeen.
insert(FieldName).second)
955 return make_error<GenericBinaryError>(
956 "producers section does not have unique fields",
958 std::vector<std::pair<std::string, std::string>> *ProducerVec =
nullptr;
959 if (FieldName ==
"language") {
961 }
else if (FieldName ==
"processed-by") {
962 ProducerVec = &ProducerInfo.
Tools;
963 }
else if (FieldName ==
"sdk") {
964 ProducerVec = &ProducerInfo.
SDKs;
966 return make_error<GenericBinaryError>(
967 "producers section field is not named one of language, processed-by, "
973 for (
size_t J = 0; J < ValueCount; ++J) {
977 return make_error<GenericBinaryError>(
978 "producers section contains repeated producer",
981 ProducerVec->emplace_back(std::string(
Name), std::string(Version));
984 if (Ctx.Ptr != Ctx.End)
985 return make_error<GenericBinaryError>(
"producers section ended prematurely",
990Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
1002 return make_error<GenericBinaryError>(
"unknown feature policy prefix",
1006 if (!FeaturesSeen.
insert(Feature.
Name).second)
1007 return make_error<GenericBinaryError>(
1008 "target features section contains repeated feature \"" +
1009 Feature.
Name +
"\"",
1011 TargetFeatures.push_back(Feature);
1013 if (Ctx.Ptr != Ctx.End)
1014 return make_error<GenericBinaryError>(
1015 "target features section ended prematurely",
1022 if (SectionIndex >= Sections.size())
1023 return make_error<GenericBinaryError>(
"invalid section index",
1029 while (RelocCount--) {
1034 if (Reloc.
Offset < PreviousOffset)
1035 return make_error<GenericBinaryError>(
"relocations not in offset order",
1039 return make_error<GenericBinaryError>(
1040 msg +
": " +
Twine(Symbols[Reloc.
Index].Info.Name),
1044 PreviousOffset = Reloc.
Offset;
1047 case wasm::R_WASM_FUNCTION_INDEX_LEB:
1048 case wasm::R_WASM_FUNCTION_INDEX_I32:
1049 case wasm::R_WASM_TABLE_INDEX_SLEB:
1050 case wasm::R_WASM_TABLE_INDEX_SLEB64:
1051 case wasm::R_WASM_TABLE_INDEX_I32:
1052 case wasm::R_WASM_TABLE_INDEX_I64:
1053 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
1054 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
1055 if (!isValidFunctionSymbol(Reloc.
Index))
1056 return badReloc(
"invalid function relocation");
1058 case wasm::R_WASM_TABLE_NUMBER_LEB:
1059 if (!isValidTableSymbol(Reloc.
Index))
1060 return badReloc(
"invalid table relocation");
1062 case wasm::R_WASM_TYPE_INDEX_LEB:
1063 if (Reloc.
Index >= Signatures.size())
1064 return badReloc(
"invalid relocation type index");
1066 case wasm::R_WASM_GLOBAL_INDEX_LEB:
1069 if (!isValidGlobalSymbol(Reloc.
Index) &&
1070 !isValidDataSymbol(Reloc.
Index) &&
1071 !isValidFunctionSymbol(Reloc.
Index))
1072 return badReloc(
"invalid global relocation");
1074 case wasm::R_WASM_GLOBAL_INDEX_I32:
1075 if (!isValidGlobalSymbol(Reloc.
Index))
1076 return badReloc(
"invalid global relocation");
1078 case wasm::R_WASM_TAG_INDEX_LEB:
1079 if (!isValidTagSymbol(Reloc.
Index))
1080 return badReloc(
"invalid tag relocation");
1082 case wasm::R_WASM_MEMORY_ADDR_LEB:
1083 case wasm::R_WASM_MEMORY_ADDR_SLEB:
1084 case wasm::R_WASM_MEMORY_ADDR_I32:
1085 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1086 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1087 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1088 if (!isValidDataSymbol(Reloc.
Index))
1089 return badReloc(
"invalid data relocation");
1092 case wasm::R_WASM_MEMORY_ADDR_LEB64:
1093 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1094 case wasm::R_WASM_MEMORY_ADDR_I64:
1095 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1096 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1097 if (!isValidDataSymbol(Reloc.
Index))
1098 return badReloc(
"invalid data relocation");
1101 case wasm::R_WASM_FUNCTION_OFFSET_I32:
1102 if (!isValidFunctionSymbol(Reloc.
Index))
1103 return badReloc(
"invalid function relocation");
1106 case wasm::R_WASM_FUNCTION_OFFSET_I64:
1107 if (!isValidFunctionSymbol(Reloc.
Index))
1108 return badReloc(
"invalid function relocation");
1111 case wasm::R_WASM_SECTION_OFFSET_I32:
1112 if (!isValidSectionSymbol(Reloc.
Index))
1113 return badReloc(
"invalid section relocation");
1117 return make_error<GenericBinaryError>(
"invalid relocation type: " +
1126 if (Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1127 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1128 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1130 if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1131 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1132 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1133 Reloc.
Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1134 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1135 Reloc.
Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
1136 Reloc.
Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1138 if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1139 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1140 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1143 return make_error<GenericBinaryError>(
"invalid relocation offset",
1146 Section.Relocations.push_back(Reloc);
1148 if (Ctx.Ptr != Ctx.End)
1149 return make_error<GenericBinaryError>(
"reloc section ended prematurely",
1154Error WasmObjectFile::parseCustomSection(
WasmSection &Sec, ReadContext &Ctx) {
1155 if (Sec.
Name ==
"dylink") {
1156 if (
Error Err = parseDylinkSection(Ctx))
1158 }
else if (Sec.
Name ==
"dylink.0") {
1159 if (
Error Err = parseDylink0Section(Ctx))
1161 }
else if (Sec.
Name ==
"name") {
1162 if (
Error Err = parseNameSection(Ctx))
1164 }
else if (Sec.
Name ==
"linking") {
1165 if (
Error Err = parseLinkingSection(Ctx))
1167 }
else if (Sec.
Name ==
"producers") {
1168 if (
Error Err = parseProducersSection(Ctx))
1170 }
else if (Sec.
Name ==
"target_features") {
1171 if (
Error Err = parseTargetFeaturesSection(Ctx))
1174 if (
Error Err = parseRelocSection(Sec.
Name, Ctx))
1180Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1181 auto parseFieldDef = [&]() {
1188 Signatures.reserve(Count);
1197 return make_error<GenericBinaryError>(
"Rec group size cannot be 0",
1199 Signatures.reserve(Signatures.size() + RecSize);
1202 Signatures.push_back(std::move(Sig));
1203 HasUnmodeledTypes =
true;
1214 return make_error<GenericBinaryError>(
1222 while (FieldCount--) {
1228 return make_error<GenericBinaryError>(
"bad form",
1232 Signatures.push_back(std::move(Sig));
1233 HasUnmodeledTypes =
true;
1239 while (ParamCount--) {
1245 while (ReturnCount--) {
1250 Signatures.push_back(std::move(Sig));
1252 if (Ctx.Ptr != Ctx.End)
1253 return make_error<GenericBinaryError>(
"type section ended prematurely",
1258Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1260 uint32_t NumTypes = Signatures.size();
1261 Imports.reserve(Count);
1269 NumImportedFunctions++;
1272 return make_error<GenericBinaryError>(
"invalid function type",
1276 NumImportedGlobals++;
1287 NumImportedTables++;
1292 return make_error<GenericBinaryError>(
"invalid table element type",
1299 return make_error<GenericBinaryError>(
"invalid attribute",
1303 return make_error<GenericBinaryError>(
"invalid tag type",
1307 return make_error<GenericBinaryError>(
"unexpected import kind",
1310 Imports.push_back(Im);
1312 if (Ctx.Ptr != Ctx.End)
1313 return make_error<GenericBinaryError>(
"import section ended prematurely",
1318Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1320 Functions.reserve(Count);
1321 uint32_t NumTypes = Signatures.size();
1324 if (
Type >= NumTypes)
1325 return make_error<GenericBinaryError>(
"invalid function type",
1329 Functions.push_back(
F);
1331 if (Ctx.Ptr != Ctx.End)
1332 return make_error<GenericBinaryError>(
"function section ended prematurely",
1337Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1338 TableSection = Sections.size();
1340 Tables.reserve(Count);
1344 T.Index = NumImportedTables + Tables.size();
1345 Tables.push_back(
T);
1346 auto ElemType = Tables.back().Type.ElemType;
1350 return make_error<GenericBinaryError>(
"invalid table element type",
1354 if (Ctx.Ptr != Ctx.End)
1355 return make_error<GenericBinaryError>(
"table section ended prematurely",
1360Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1362 Memories.reserve(Count);
1367 Memories.push_back(Limits);
1369 if (Ctx.Ptr != Ctx.End)
1370 return make_error<GenericBinaryError>(
"memory section ended prematurely",
1375Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1376 TagSection = Sections.size();
1378 Tags.reserve(Count);
1379 uint32_t NumTypes = Signatures.size();
1382 return make_error<GenericBinaryError>(
"invalid attribute",
1385 if (
Type >= NumTypes)
1386 return make_error<GenericBinaryError>(
"invalid tag type",
1389 Tag.Index = NumImportedTags + Tags.size();
1392 Tags.push_back(
Tag);
1395 if (Ctx.Ptr != Ctx.End)
1396 return make_error<GenericBinaryError>(
"tag section ended prematurely",
1401Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1402 GlobalSection = Sections.size();
1403 const uint8_t *SectionStart = Ctx.Ptr;
1405 Globals.reserve(Count);
1408 Global.Index = NumImportedGlobals + Globals.size();
1409 const uint8_t *GlobalStart = Ctx.Ptr;
1410 Global.Offset =
static_cast<uint32_t>(GlobalStart - SectionStart);
1417 Globals.push_back(
Global);
1419 if (Ctx.Ptr != Ctx.End)
1420 return make_error<GenericBinaryError>(
"global section ended prematurely",
1425Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1427 Exports.reserve(Count);
1428 Symbols.reserve(Count);
1442 if (!isDefinedFunctionIndex(Ex.
Index))
1443 return make_error<GenericBinaryError>(
"invalid function export",
1448 unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
1450 Signature = &Signatures[
Function.SigIndex];
1454 if (!isValidGlobalIndex(Ex.
Index))
1455 return make_error<GenericBinaryError>(
"invalid global export",
1459 if (isDefinedGlobalIndex(Ex.
Index)) {
1461 if (!
Global.InitExpr.Extended) {
1462 auto Inst =
Global.InitExpr.Inst;
1464 Offset = Inst.Value.Int32;
1466 Offset = Inst.Value.Int64;
1474 if (!isValidTagIndex(Ex.
Index))
1475 return make_error<GenericBinaryError>(
"invalid tag export",
1487 return make_error<GenericBinaryError>(
"unexpected export kind",
1490 Exports.push_back(Ex);
1492 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
1493 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
1496 if (Ctx.Ptr != Ctx.End)
1497 return make_error<GenericBinaryError>(
"export section ended prematurely",
1502bool WasmObjectFile::isValidFunctionIndex(
uint32_t Index)
const {
1503 return Index < NumImportedFunctions + Functions.size();
1506bool WasmObjectFile::isDefinedFunctionIndex(
uint32_t Index)
const {
1507 return Index >= NumImportedFunctions && isValidFunctionIndex(
Index);
1510bool WasmObjectFile::isValidGlobalIndex(
uint32_t Index)
const {
1511 return Index < NumImportedGlobals + Globals.size();
1514bool WasmObjectFile::isValidTableNumber(
uint32_t Index)
const {
1515 return Index < NumImportedTables + Tables.size();
1518bool WasmObjectFile::isDefinedGlobalIndex(
uint32_t Index)
const {
1519 return Index >= NumImportedGlobals && isValidGlobalIndex(
Index);
1522bool WasmObjectFile::isDefinedTableNumber(
uint32_t Index)
const {
1523 return Index >= NumImportedTables && isValidTableNumber(
Index);
1527 return Index < NumImportedTags + Tags.size();
1530bool WasmObjectFile::isDefinedTagIndex(
uint32_t Index)
const {
1531 return Index >= NumImportedTags && isValidTagIndex(
Index);
1534bool WasmObjectFile::isValidFunctionSymbol(
uint32_t Index)
const {
1535 return Index < Symbols.size() && Symbols[
Index].isTypeFunction();
1538bool WasmObjectFile::isValidTableSymbol(
uint32_t Index)
const {
1539 return Index < Symbols.size() && Symbols[
Index].isTypeTable();
1542bool WasmObjectFile::isValidGlobalSymbol(
uint32_t Index)
const {
1543 return Index < Symbols.size() && Symbols[
Index].isTypeGlobal();
1546bool WasmObjectFile::isValidTagSymbol(
uint32_t Index)
const {
1547 return Index < Symbols.size() && Symbols[
Index].isTypeTag();
1550bool WasmObjectFile::isValidDataSymbol(
uint32_t Index)
const {
1551 return Index < Symbols.size() && Symbols[
Index].isTypeData();
1554bool WasmObjectFile::isValidSectionSymbol(
uint32_t Index)
const {
1555 return Index < Symbols.size() && Symbols[
Index].isTypeSection();
1560 return Functions[
Index - NumImportedFunctions];
1566 return Functions[
Index - NumImportedFunctions];
1571 return Globals[
Index - NumImportedGlobals];
1576 return Tags[
Index - NumImportedTags];
1579Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1581 if (!isValidFunctionIndex(StartFunction))
1582 return make_error<GenericBinaryError>(
"invalid start function",
1587Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1588 CodeSection = Sections.size();
1590 if (FunctionCount != Functions.size()) {
1591 return make_error<GenericBinaryError>(
"invalid function count",
1595 for (
uint32_t i = 0; i < FunctionCount; i++) {
1597 const uint8_t *FunctionStart = Ctx.Ptr;
1599 const uint8_t *FunctionEnd = Ctx.Ptr +
Size;
1601 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1602 Function.Index = NumImportedFunctions + i;
1603 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1604 Function.Size = FunctionEnd - FunctionStart;
1607 Function.Locals.reserve(NumLocalDecls);
1608 while (NumLocalDecls--) {
1615 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1617 if (Ctx.Ptr + BodySize > Ctx.End) {
1618 return make_error<GenericBinaryError>(
"Function extends beyond buffer",
1624 Ctx.Ptr += BodySize;
1625 assert(Ctx.Ptr == FunctionEnd);
1627 if (Ctx.Ptr != Ctx.End)
1628 return make_error<GenericBinaryError>(
"code section ended prematurely",
1633Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1635 ElemSegments.reserve(Count);
1643 if (Segment.
Flags & ~SupportedFlags)
1644 return make_error<GenericBinaryError>(
1648 bool IsDeclarative =
1650 bool HasTableNumber =
1665 return make_error<GenericBinaryError>(
"invalid TableNumber",
1668 if (IsPassive || IsDeclarative) {
1684 return make_error<GenericBinaryError>(
"invalid elem type",
1689 return make_error<GenericBinaryError>(
"invalid elem type",
1693 }
else if (HasInitExprs) {
1703 while (NumElems--) {
1709 while (NumElems--) {
1713 ElemSegments.push_back(Segment);
1715 if (Ctx.Ptr != Ctx.End)
1716 return make_error<GenericBinaryError>(
"elem section ended prematurely",
1721Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1722 DataSection = Sections.size();
1724 if (DataCount && Count != *DataCount)
1725 return make_error<GenericBinaryError>(
1726 "number of data segments does not match DataCount section");
1727 DataSegments.reserve(Count);
1744 if (
Size > (
size_t)(Ctx.End - Ctx.Ptr))
1745 return make_error<GenericBinaryError>(
"invalid segment size",
1755 DataSegments.push_back(Segment);
1757 if (Ctx.Ptr != Ctx.End)
1758 return make_error<GenericBinaryError>(
"data section ended prematurely",
1763Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1779 if (
Sym.isBindingWeak())
1781 if (!
Sym.isBindingLocal())
1785 if (!
Sym.isDefined())
1787 if (
Sym.isTypeFunction())
1802 Ref.d.b = Symbols.size();
1807 return Symbols[Symb.
d.
b];
1820 if (!
Sym.isDefined())
1827 isDefinedFunctionIndex(
Sym.Info.ElementIndex)) {
1832 isDefinedGlobalIndex(
Sym.Info.ElementIndex)) {
1833 return getDefinedGlobal(
Sym.Info.ElementIndex).
Offset + SectionAddress;
1840 switch (
Sym.Info.Kind) {
1845 return Sym.Info.ElementIndex;
1858 return Sym.Info.DataRef.Offset;
1887 switch (
Sym.Info.Kind) {
1909 if (
Sym.isUndefined())
1913 Ref.d.a = getSymbolSectionIdImpl(
Sym);
1919 return getSymbolSectionIdImpl(
Sym);
1923 switch (
Sym.Info.Kind) {
1927 return GlobalSection;
1931 return Sym.Info.ElementIndex;
1935 return TableSection;
1943 if (!
Sym.isDefined())
1945 if (
Sym.isTypeGlobal())
1946 return getDefinedGlobal(
Sym.Info.ElementIndex).
Size;
1947 if (
Sym.isTypeData())
1948 return Sym.Info.DataRef.Size;
1949 if (
Sym.isTypeFunction())
1973 : Sections[Sec.
d.
a].Offset;
2015 RelocRef.
d.
a =
Ref.d.a;
2023 RelocRef.
d.
a =
Ref.d.a;
2037 if (Rel.
Type == wasm::R_WASM_TYPE_INDEX_LEB)
2055#define WASM_RELOC(name, value) \
2061#include "llvm/BinaryFormat/WasmRelocs.def"
2066 Result.append(Res.
begin(), Res.
end());
2077 Ref.d.a = Sections.size();
2082 return HasMemory64 ? 8 : 4;
2101 return Sections[
Ref.d.a];
2122int WasmSectionOrderChecker::getSectionOrder(
unsigned ID,
2170 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2174 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2176 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2178 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2180 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2182 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2184 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2186 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2188 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2190 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2192 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2194 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2196 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2198 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2202 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2204 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2208 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2210 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2212 {WASM_SEC_ORDER_TARGET_FEATURES}};
2216 int Order = getSectionOrder(
ID, CustomSectionName);
2229 for (
size_t I = 0;; ++
I) {
2236 Checked[Next] =
true;
2239 if (WorkList.
empty())
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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
StringSet - A set-like wrapper for the StringMap.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx)
static Error readInitExpr(wasm::WasmInitExpr &Expr, WasmObjectFile::ReadContext &Ctx)
static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx)
static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx)
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx)
static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx)
static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx, WasmSectionOrderChecker &Checker)
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx)
static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx)
static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx)
static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx)
static StringRef readString(WasmObjectFile::ReadContext &Ctx)
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx)
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
bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")
@ WASM_SEC_ORDER_TARGET_FEATURES
@ WASM_SEC_ORDER_PRODUCERS
@ WASM_SEC_ORDER_DATACOUNT
@ WASM_SEC_ORDER_FUNCTION
static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]
unsigned getBinding() const
LLVM_DUMP_METHOD void dump() const
wasm::WasmSymbolInfo Info
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.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
content_iterator< SectionRef > section_iterator
content_iterator< RelocationRef > relocation_iterator
uint32_t read32le(const void *P)
@ WASM_NAMES_DATA_SEGMENT
const unsigned WASM_SYMBOL_UNDEFINED
@ WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
@ WASM_ELEM_SEGMENT_IS_DECLARATIVE
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
@ WASM_ELEM_SEGMENT_IS_PASSIVE
@ WASM_OPCODE_ARRAY_NEW_FIXED
@ WASM_OPCODE_ARRAY_NEW_DEFAULT
@ WASM_OPCODE_STRUCT_NEW_DEFAULT
@ WASM_DYLINK_EXPORT_INFO
@ WASM_DYLINK_IMPORT_INFO
@ WASM_FEATURE_PREFIX_USED
@ WASM_FEATURE_PREFIX_REQUIRED
@ WASM_FEATURE_PREFIX_DISALLOWED
@ WASM_LIMITS_FLAG_HAS_MAX
const unsigned WASM_SYMBOL_BINDING_GLOBAL
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
const uint32_t WasmMetadataVersion
const unsigned WASM_SYMBOL_BINDING_WEAK
const unsigned WASM_SYMBOL_BINDING_LOCAL
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_FUNCTION
const uint32_t WasmVersion
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
const unsigned WASM_SYMBOL_BINDING_MASK
llvm::StringRef sectionTypeToString(uint32_t type)
const unsigned WASM_SYMBOL_EXPLICIT_NAME
const unsigned WASM_SYMBOL_ABSOLUTE
This is an optimization pass for GlobalISel generic memory operations.
std::string to_string(const T &Value)
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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
@ Global
Append to llvm.global_dtors.
@ Ref
The access may reference the value stored in memory.
ArrayRef< uint8_t > Content
std::vector< wasm::WasmRelocation > Relocations
wasm::WasmDataSegment Data
ArrayRef< uint8_t > Content
std::vector< StringRef > Needed
std::vector< WasmDylinkExportInfo > ExportInfo
std::vector< WasmDylinkImportInfo > ImportInfo
std::vector< uint32_t > Functions
std::optional< StringRef > ExportName
uint32_t CodeSectionOffset
union llvm::wasm::WasmInitExprMVP::@179 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::@184 Kind
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params
WasmDataReference DataRef
struct llvm::object::DataRefImpl::@355 d