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)),
308 LLVM_DEBUG(
dbgs() <<
"readSection type=" << Section.Type <<
"\n");
313 Section.HeaderSecSizeEncodingLen = Ctx.
Ptr - PreSizePtr;
314 Section.Offset = Ctx.
Ptr - Ctx.
Start;
316 return make_error<StringError>(
"zero length section",
319 return make_error<StringError>(
"section too large",
330 Ctx.
Ptr += SectionNameSize;
331 Size -= SectionNameSize;
334 if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
335 return make_error<StringError>(
"out of order section type: " +
350 Err = make_error<StringError>(
"invalid magic number",
360 if (Ctx.
Ptr + 4 > Ctx.
End) {
361 Err = make_error<StringError>(
"missing version number",
368 Err = make_error<StringError>(
"invalid version number: " +
375 while (Ctx.
Ptr < Ctx.
End) {
379 if ((Err = parseSection(Sec)))
382 Sections.push_back(Sec);
393 return parseCustomSection(Sec, Ctx);
395 return parseTypeSection(Ctx);
397 return parseImportSection(Ctx);
399 return parseFunctionSection(Ctx);
401 return parseTableSection(Ctx);
403 return parseMemorySection(Ctx);
405 return parseTagSection(Ctx);
407 return parseGlobalSection(Ctx);
409 return parseExportSection(Ctx);
411 return parseStartSection(Ctx);
413 return parseElemSection(Ctx);
415 return parseCodeSection(Ctx);
417 return parseDataSection(Ctx);
419 return parseDataCountSection(Ctx);
421 return make_error<GenericBinaryError>(
426Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
429 HasDylinkSection =
true;
439 if (Ctx.Ptr != Ctx.End)
440 return make_error<GenericBinaryError>(
"dylink section ended prematurely",
445Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
448 HasDylinkSection =
true;
450 const uint8_t *OrigEnd = Ctx.End;
451 while (Ctx.Ptr < OrigEnd) {
457 Ctx.End = Ctx.Ptr +
Size;
492 if (Ctx.Ptr != Ctx.End) {
493 return make_error<GenericBinaryError>(
498 if (Ctx.Ptr != Ctx.End)
499 return make_error<GenericBinaryError>(
"dylink.0 section ended prematurely",
504Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
511 bool PopulateSymbolTable = !HasLinkingSection && !HasDylinkSection;
515 if (PopulateSymbolTable)
518 while (Ctx.Ptr < Ctx.End) {
543 if (!SeenFunctions.
insert(Index).second)
544 return make_error<GenericBinaryError>(
546 if (!isValidFunctionIndex(Index) ||
Name.empty())
547 return make_error<GenericBinaryError>(
"invalid function name entry",
550 if (isDefinedFunctionIndex(Index)) {
553 Signature = &Signatures[
F.SigIndex];
555 Info.ExportName =
F.ExportName;
564 if (!SeenGlobals.
insert(Index).second)
565 return make_error<GenericBinaryError>(
"global named more than once",
567 if (!isValidGlobalIndex(Index) ||
Name.empty())
568 return make_error<GenericBinaryError>(
"invalid global name entry",
572 if (isDefinedGlobalIndex(Index)) {
573 GlobalType = &getDefinedGlobal(Index).
Type;
578 if (!SeenSegments.
insert(Index).second)
579 return make_error<GenericBinaryError>(
581 if (Index > DataSegments.size())
582 return make_error<GenericBinaryError>(
"invalid data segment name entry",
587 assert(Index < DataSegments.size());
589 Index, 0, DataSegments[
Index].Data.Content.size()};
592 if (PopulateSymbolTable)
593 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
603 if (Ctx.Ptr != SubSectionEnd)
604 return make_error<GenericBinaryError>(
608 if (Ctx.Ptr != Ctx.End)
609 return make_error<GenericBinaryError>(
"name section ended prematurely",
614Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
615 HasLinkingSection =
true;
619 return make_error<GenericBinaryError>(
620 "unexpected metadata version: " +
Twine(LinkingData.
Version) +
625 const uint8_t *OrigEnd = Ctx.End;
626 while (Ctx.Ptr < OrigEnd) {
632 Ctx.End = Ctx.Ptr +
Size;
635 if (
Error Err = parseLinkingSectionSymtab(Ctx))
640 if (Count > DataSegments.size())
641 return make_error<GenericBinaryError>(
"too many segment names",
657 if (!isValidFunctionSymbol(
Init.Symbol))
658 return make_error<GenericBinaryError>(
"invalid function symbol: " +
666 if (
Error Err = parseLinkingSectionComdat(Ctx))
673 if (Ctx.Ptr != Ctx.End)
674 return make_error<GenericBinaryError>(
677 if (Ctx.Ptr != OrigEnd)
678 return make_error<GenericBinaryError>(
"linking section ended prematurely",
683Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
688 Symbols.reserve(Count);
691 std::vector<wasm::WasmImport *> ImportedGlobals;
692 std::vector<wasm::WasmImport *> ImportedFunctions;
693 std::vector<wasm::WasmImport *> ImportedTags;
694 std::vector<wasm::WasmImport *> ImportedTables;
695 ImportedGlobals.reserve(Imports.size());
696 ImportedFunctions.reserve(Imports.size());
697 ImportedTags.reserve(Imports.size());
698 ImportedTables.reserve(Imports.size());
699 for (
auto &
I : Imports) {
701 ImportedFunctions.emplace_back(&
I);
703 ImportedGlobals.emplace_back(&
I);
705 ImportedTags.emplace_back(&
I);
707 ImportedTables.emplace_back(&
I);
723 if (!isValidFunctionIndex(
Info.ElementIndex) ||
724 IsDefined != isDefinedFunctionIndex(
Info.ElementIndex))
725 return make_error<GenericBinaryError>(
"invalid function symbol index",
729 unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
731 Signature = &Signatures[
Function.SigIndex];
742 Signature = &Signatures[
Import.SigIndex];
749 if (!isValidGlobalIndex(
Info.ElementIndex) ||
750 IsDefined != isDefinedGlobalIndex(
Info.ElementIndex))
751 return make_error<GenericBinaryError>(
"invalid global symbol index",
755 return make_error<GenericBinaryError>(
"undefined weak global symbol",
759 unsigned GlobalIndex =
Info.ElementIndex - NumImportedGlobals;
761 GlobalType = &
Global.Type;
762 if (
Global.SymbolName.empty())
772 GlobalType = &
Import.Global;
779 if (!isValidTableNumber(
Info.ElementIndex) ||
780 IsDefined != isDefinedTableNumber(
Info.ElementIndex))
781 return make_error<GenericBinaryError>(
"invalid table symbol index",
785 return make_error<GenericBinaryError>(
"undefined weak table symbol",
789 unsigned TableNumber =
Info.ElementIndex - NumImportedTables;
791 TableType = &Table.
Type;
802 TableType = &
Import.Table;
814 if (
static_cast<size_t>(Index) >= DataSegments.size())
815 return make_error<GenericBinaryError>(
816 "invalid data segment index: " +
Twine(Index),
818 size_t SegmentSize = DataSegments[
Index].Data.Content.size();
820 return make_error<GenericBinaryError>(
821 "invalid data symbol offset: `" +
Info.Name +
823 " segment size: " +
Twine(SegmentSize) +
")",
833 return make_error<GenericBinaryError>(
834 "section symbols must have local binding",
845 if (!isValidTagIndex(
Info.ElementIndex) ||
846 IsDefined != isDefinedTagIndex(
Info.ElementIndex))
847 return make_error<GenericBinaryError>(
"invalid tag symbol index",
851 return make_error<GenericBinaryError>(
"undefined weak global symbol",
855 unsigned TagIndex =
Info.ElementIndex - NumImportedTags;
857 Signature = &Signatures[
Tag.SigIndex];
858 if (
Tag.SymbolName.empty())
869 Signature = &Signatures[
Import.SigIndex];
876 return make_error<GenericBinaryError>(
"invalid symbol type: " +
884 return make_error<GenericBinaryError>(
"duplicate symbol name " +
887 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
888 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
894Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
897 for (
unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
900 return make_error<GenericBinaryError>(
"bad/duplicate COMDAT name " +
906 return make_error<GenericBinaryError>(
"unsupported COMDAT flags",
910 while (EntryCount--) {
915 return make_error<GenericBinaryError>(
"invalid COMDAT entry type",
918 if (Index >= DataSegments.size())
919 return make_error<GenericBinaryError>(
921 if (DataSegments[Index].
Data.Comdat != UINT32_MAX)
922 return make_error<GenericBinaryError>(
"data segment in two COMDATs",
924 DataSegments[
Index].Data.Comdat = ComdatIndex;
927 if (!isDefinedFunctionIndex(Index))
928 return make_error<GenericBinaryError>(
930 if (getDefinedFunction(Index).
Comdat != UINT32_MAX)
931 return make_error<GenericBinaryError>(
"function in two COMDATs",
933 getDefinedFunction(Index).
Comdat = ComdatIndex;
936 if (Index >= Sections.size())
937 return make_error<GenericBinaryError>(
940 return make_error<GenericBinaryError>(
942 Sections[
Index].Comdat = ComdatIndex;
950Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
953 for (
size_t I = 0;
I < Fields; ++
I) {
955 if (!FieldsSeen.
insert(FieldName).second)
956 return make_error<GenericBinaryError>(
957 "producers section does not have unique fields",
959 std::vector<std::pair<std::string, std::string>> *ProducerVec =
nullptr;
960 if (FieldName ==
"language") {
962 }
else if (FieldName ==
"processed-by") {
963 ProducerVec = &ProducerInfo.
Tools;
964 }
else if (FieldName ==
"sdk") {
965 ProducerVec = &ProducerInfo.
SDKs;
967 return make_error<GenericBinaryError>(
968 "producers section field is not named one of language, processed-by, "
974 for (
size_t J = 0; J < ValueCount; ++J) {
978 return make_error<GenericBinaryError>(
979 "producers section contains repeated producer",
982 ProducerVec->emplace_back(std::string(
Name), std::string(
Version));
985 if (Ctx.Ptr != Ctx.End)
986 return make_error<GenericBinaryError>(
"producers section ended prematurely",
991Error 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--) {
1244 while (ReturnCount--) {
1249 Signatures.push_back(std::move(Sig));
1251 if (Ctx.Ptr != Ctx.End)
1252 return make_error<GenericBinaryError>(
"type section ended prematurely",
1257Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1259 uint32_t NumTypes = Signatures.size();
1260 Imports.reserve(Count);
1268 NumImportedFunctions++;
1271 return make_error<GenericBinaryError>(
"invalid function type",
1275 NumImportedGlobals++;
1286 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;
1351 return make_error<GenericBinaryError>(
"invalid table element type",
1355 if (Ctx.Ptr != Ctx.End)
1356 return make_error<GenericBinaryError>(
"table section ended prematurely",
1361Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1363 Memories.reserve(Count);
1368 Memories.push_back(Limits);
1370 if (Ctx.Ptr != Ctx.End)
1371 return make_error<GenericBinaryError>(
"memory section ended prematurely",
1376Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1377 TagSection = Sections.size();
1379 Tags.reserve(Count);
1380 uint32_t NumTypes = Signatures.size();
1383 return make_error<GenericBinaryError>(
"invalid attribute",
1386 if (
Type >= NumTypes)
1387 return make_error<GenericBinaryError>(
"invalid tag type",
1390 Tag.Index = NumImportedTags + Tags.size();
1393 Tags.push_back(
Tag);
1396 if (Ctx.Ptr != Ctx.End)
1397 return make_error<GenericBinaryError>(
"tag section ended prematurely",
1402Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1403 GlobalSection = Sections.size();
1404 const uint8_t *SectionStart = Ctx.Ptr;
1406 Globals.reserve(Count);
1409 Global.Index = NumImportedGlobals + Globals.size();
1410 const uint8_t *GlobalStart = Ctx.Ptr;
1411 Global.Offset =
static_cast<uint32_t>(GlobalStart - SectionStart);
1418 Globals.push_back(
Global);
1420 if (Ctx.Ptr != Ctx.End)
1421 return make_error<GenericBinaryError>(
"global section ended prematurely",
1426Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1428 Exports.reserve(Count);
1429 Symbols.reserve(Count);
1443 if (!isDefinedFunctionIndex(Ex.
Index))
1444 return make_error<GenericBinaryError>(
"invalid function export",
1449 unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
1451 Signature = &Signatures[
Function.SigIndex];
1455 if (!isValidGlobalIndex(Ex.
Index))
1456 return make_error<GenericBinaryError>(
"invalid global export",
1460 if (isDefinedGlobalIndex(Ex.
Index)) {
1462 if (!
Global.InitExpr.Extended) {
1463 auto Inst =
Global.InitExpr.Inst;
1465 Offset = Inst.Value.Int32;
1467 Offset = Inst.Value.Int64;
1475 if (!isValidTagIndex(Ex.
Index))
1476 return make_error<GenericBinaryError>(
"invalid tag export",
1488 return make_error<GenericBinaryError>(
"unexpected export kind",
1491 Exports.push_back(Ex);
1493 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
1494 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
1497 if (Ctx.Ptr != Ctx.End)
1498 return make_error<GenericBinaryError>(
"export section ended prematurely",
1503bool WasmObjectFile::isValidFunctionIndex(
uint32_t Index)
const {
1504 return Index < NumImportedFunctions + Functions.size();
1507bool WasmObjectFile::isDefinedFunctionIndex(
uint32_t Index)
const {
1508 return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1511bool WasmObjectFile::isValidGlobalIndex(
uint32_t Index)
const {
1512 return Index < NumImportedGlobals + Globals.size();
1515bool WasmObjectFile::isValidTableNumber(
uint32_t Index)
const {
1516 return Index < NumImportedTables + Tables.size();
1519bool WasmObjectFile::isDefinedGlobalIndex(
uint32_t Index)
const {
1520 return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1523bool WasmObjectFile::isDefinedTableNumber(
uint32_t Index)
const {
1524 return Index >= NumImportedTables && isValidTableNumber(Index);
1527bool WasmObjectFile::isValidTagIndex(
uint32_t Index)
const {
1528 return Index < NumImportedTags + Tags.size();
1531bool WasmObjectFile::isDefinedTagIndex(
uint32_t Index)
const {
1532 return Index >= NumImportedTags && isValidTagIndex(Index);
1535bool WasmObjectFile::isValidFunctionSymbol(
uint32_t Index)
const {
1536 return Index < Symbols.size() && Symbols[
Index].isTypeFunction();
1539bool WasmObjectFile::isValidTableSymbol(
uint32_t Index)
const {
1540 return Index < Symbols.size() && Symbols[
Index].isTypeTable();
1543bool WasmObjectFile::isValidGlobalSymbol(
uint32_t Index)
const {
1544 return Index < Symbols.size() && Symbols[
Index].isTypeGlobal();
1547bool WasmObjectFile::isValidTagSymbol(
uint32_t Index)
const {
1548 return Index < Symbols.size() && Symbols[
Index].isTypeTag();
1551bool WasmObjectFile::isValidDataSymbol(
uint32_t Index)
const {
1552 return Index < Symbols.size() && Symbols[
Index].isTypeData();
1555bool WasmObjectFile::isValidSectionSymbol(
uint32_t Index)
const {
1556 return Index < Symbols.size() && Symbols[
Index].isTypeSection();
1560 assert(isDefinedFunctionIndex(Index));
1561 return Functions[
Index - NumImportedFunctions];
1565WasmObjectFile::getDefinedFunction(
uint32_t Index)
const {
1566 assert(isDefinedFunctionIndex(Index));
1567 return Functions[
Index - NumImportedFunctions];
1571 assert(isDefinedGlobalIndex(Index));
1572 return Globals[
Index - NumImportedGlobals];
1576 assert(isDefinedTagIndex(Index));
1577 return Tags[
Index - NumImportedTags];
1580Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1582 if (!isValidFunctionIndex(StartFunction))
1583 return make_error<GenericBinaryError>(
"invalid start function",
1588Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1589 CodeSection = Sections.size();
1591 if (FunctionCount != Functions.size()) {
1592 return make_error<GenericBinaryError>(
"invalid function count",
1596 for (
uint32_t i = 0; i < FunctionCount; i++) {
1598 const uint8_t *FunctionStart = Ctx.Ptr;
1602 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1603 Function.Index = NumImportedFunctions + i;
1604 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1605 Function.Size = FunctionEnd - FunctionStart;
1608 Function.Locals.reserve(NumLocalDecls);
1609 while (NumLocalDecls--) {
1616 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1618 if (Ctx.Ptr + BodySize > Ctx.End) {
1619 return make_error<GenericBinaryError>(
"Function extends beyond buffer",
1625 Ctx.Ptr += BodySize;
1626 assert(Ctx.Ptr == FunctionEnd);
1628 if (Ctx.Ptr != Ctx.End)
1629 return make_error<GenericBinaryError>(
"code section ended prematurely",
1634Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1636 ElemSegments.reserve(Count);
1644 if (Segment.
Flags & ~SupportedFlags)
1645 return make_error<GenericBinaryError>(
1649 bool IsDeclarative =
1651 bool HasTableNumber =
1666 return make_error<GenericBinaryError>(
"invalid TableNumber",
1669 if (IsPassive || IsDeclarative) {
1686 return make_error<GenericBinaryError>(
"invalid elem type",
1691 return make_error<GenericBinaryError>(
"invalid elem type",
1695 }
else if (HasInitExprs) {
1705 while (NumElems--) {
1711 while (NumElems--) {
1715 ElemSegments.push_back(Segment);
1717 if (Ctx.Ptr != Ctx.End)
1718 return make_error<GenericBinaryError>(
"elem section ended prematurely",
1723Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1724 DataSection = Sections.size();
1726 if (DataCount && Count != *DataCount)
1727 return make_error<GenericBinaryError>(
1728 "number of data segments does not match DataCount section");
1729 DataSegments.reserve(Count);
1746 if (
Size > (
size_t)(Ctx.End - Ctx.Ptr))
1747 return make_error<GenericBinaryError>(
"invalid segment size",
1757 DataSegments.push_back(Segment);
1759 if (Ctx.Ptr != Ctx.End)
1760 return make_error<GenericBinaryError>(
"data section ended prematurely",
1765Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1781 if (
Sym.isBindingWeak())
1783 if (!
Sym.isBindingLocal())
1787 if (!
Sym.isDefined())
1789 if (
Sym.isTypeFunction())
1804 Ref.d.b = Symbols.size();
1809 return Symbols[Symb.
d.
b];
1822 if (!
Sym.isDefined())
1829 isDefinedFunctionIndex(
Sym.Info.ElementIndex)) {
1834 isDefinedGlobalIndex(
Sym.Info.ElementIndex)) {
1835 return getDefinedGlobal(
Sym.Info.ElementIndex).
Offset + SectionAddress;
1842 switch (
Sym.Info.Kind) {
1847 return Sym.Info.ElementIndex;
1860 return Sym.Info.DataRef.Offset;
1889 switch (
Sym.Info.Kind) {
1911 if (
Sym.isUndefined())
1915 Ref.d.a = getSymbolSectionIdImpl(
Sym);
1921 return getSymbolSectionIdImpl(
Sym);
1925 switch (
Sym.Info.Kind) {
1929 return GlobalSection;
1933 return Sym.Info.ElementIndex;
1937 return TableSection;
1945 if (!
Sym.isDefined())
1947 if (
Sym.isTypeGlobal())
1948 return getDefinedGlobal(
Sym.Info.ElementIndex).
Size;
1949 if (
Sym.isTypeData())
1950 return Sym.Info.DataRef.Size;
1951 if (
Sym.isTypeFunction())
1975 : Sections[Sec.
d.
a].Offset;
2017 RelocRef.
d.
a =
Ref.d.a;
2025 RelocRef.
d.
a =
Ref.d.a;
2039 if (Rel.
Type == wasm::R_WASM_TYPE_INDEX_LEB)
2057#define WASM_RELOC(name, value) \
2063#include "llvm/BinaryFormat/WasmRelocs.def"
2068 Result.append(Res.
begin(), Res.
end());
2079 Ref.d.a = Sections.size();
2084 return HasMemory64 ? 8 : 4;
2103 return Sections[
Ref.d.a];
2124int WasmSectionOrderChecker::getSectionOrder(
unsigned ID,
2172 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2176 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2178 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2180 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2182 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2184 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2186 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2188 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2190 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2192 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2194 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2196 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2198 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2200 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2204 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2206 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2210 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2212 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2214 {WASM_SEC_ORDER_TARGET_FEATURES}};
2218 int Order = getSectionOrder(
ID, CustomSectionName);
2231 for (
size_t I = 0;; ++
I) {
2238 Checked[Next] =
true;
2241 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.
content_iterator< SectionRef > section_iterator
content_iterator< RelocationRef > relocation_iterator
uint32_t read32le(const void *P)
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
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_NAMES_DATA_SEGMENT
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_FUNCTION
const uint32_t WasmVersion
@ WASM_OPCODE_ARRAY_NEW_FIXED
@ WASM_OPCODE_ARRAY_NEW_DEFAULT
@ WASM_OPCODE_STRUCT_NEW_DEFAULT
const unsigned WASM_SYMBOL_BINDING_MASK
@ WASM_LIMITS_FLAG_HAS_MAX
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
llvm::StringRef sectionTypeToString(uint32_t type)
const unsigned WASM_SYMBOL_EXPLICIT_NAME
@ WASM_FEATURE_PREFIX_USED
@ WASM_FEATURE_PREFIX_DISALLOWED
const unsigned WASM_SYMBOL_ABSOLUTE
@ WASM_DYLINK_EXPORT_INFO
@ WASM_DYLINK_IMPORT_INFO
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.
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< WasmDylinkExportInfo > ExportInfo
std::vector< WasmDylinkImportInfo > ImportInfo
std::vector< uint32_t > Functions
std::optional< StringRef > ExportName
uint32_t CodeSectionOffset
union llvm::wasm::WasmInitExprMVP::@187 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
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params
enum llvm::wasm::WasmSignature::@192 Kind
WasmDataReference DataRef
struct llvm::object::DataRefImpl::@371 d