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)
201 auto Start = Ctx.
Ptr;
281 return make_error<GenericBinaryError>(
282 Twine(
"invalid opcode in init_expr: ") +
Twine(
unsigned(Opcode)),
311 LLVM_DEBUG(
dbgs() <<
"readSection type=" << Section.Type <<
"\n");
314 const uint8_t *PreSizePtr = Ctx.
Ptr;
316 Section.HeaderSecSizeEncodingLen = Ctx.
Ptr - PreSizePtr;
317 Section.Offset = Ctx.
Ptr - Ctx.
Start;
319 return make_error<StringError>(
"zero length section",
322 return make_error<StringError>(
"section too large",
333 Ctx.
Ptr += SectionNameSize;
334 Size -= SectionNameSize;
338 return make_error<StringError>(
"out of order section type: " +
353 Err = make_error<StringError>(
"invalid magic number",
363 if (Ctx.
Ptr + 4 > Ctx.
End) {
364 Err = make_error<StringError>(
"missing version number",
371 Err = make_error<StringError>(
"invalid version number: " +
378 while (Ctx.
Ptr < Ctx.
End) {
382 if ((Err = parseSection(Sec)))
385 Sections.push_back(Sec);
396 return parseCustomSection(Sec, Ctx);
398 return parseTypeSection(Ctx);
400 return parseImportSection(Ctx);
402 return parseFunctionSection(Ctx);
404 return parseTableSection(Ctx);
406 return parseMemorySection(Ctx);
408 return parseTagSection(Ctx);
410 return parseGlobalSection(Ctx);
412 return parseExportSection(Ctx);
414 return parseStartSection(Ctx);
416 return parseElemSection(Ctx);
418 return parseCodeSection(Ctx);
420 return parseDataSection(Ctx);
422 return parseDataCountSection(Ctx);
424 return make_error<GenericBinaryError>(
429Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
432 HasDylinkSection =
true;
442 if (Ctx.Ptr != Ctx.End)
443 return make_error<GenericBinaryError>(
"dylink section ended prematurely",
448Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
451 HasDylinkSection =
true;
453 const uint8_t *OrigEnd = Ctx.End;
454 while (Ctx.Ptr < OrigEnd) {
460 Ctx.End = Ctx.Ptr +
Size;
495 if (Ctx.Ptr != Ctx.End) {
496 return make_error<GenericBinaryError>(
501 if (Ctx.Ptr != Ctx.End)
502 return make_error<GenericBinaryError>(
"dylink.0 section ended prematurely",
507Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
514 bool PopulateSymbolTable = !HasLinkingSection && !HasDylinkSection;
518 if (PopulateSymbolTable)
521 while (Ctx.Ptr < Ctx.End) {
524 const uint8_t *SubSectionEnd = Ctx.Ptr +
Size;
547 return make_error<GenericBinaryError>(
549 if (!isValidFunctionIndex(
Index) ||
Name.empty())
550 return make_error<GenericBinaryError>(
"invalid function name entry",
553 if (isDefinedFunctionIndex(
Index)) {
556 Signature = &Signatures[
F.SigIndex];
558 Info.ExportName =
F.ExportName;
568 return make_error<GenericBinaryError>(
"global named more than once",
570 if (!isValidGlobalIndex(
Index) ||
Name.empty())
571 return make_error<GenericBinaryError>(
"invalid global name entry",
575 if (isDefinedGlobalIndex(
Index)) {
576 GlobalType = &getDefinedGlobal(
Index).
Type;
582 return make_error<GenericBinaryError>(
584 if (
Index > DataSegments.size())
585 return make_error<GenericBinaryError>(
"invalid data segment name entry",
592 Index, 0, DataSegments[
Index].Data.Content.size()};
595 if (PopulateSymbolTable)
596 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
606 if (Ctx.Ptr != SubSectionEnd)
607 return make_error<GenericBinaryError>(
611 if (Ctx.Ptr != Ctx.End)
612 return make_error<GenericBinaryError>(
"name section ended prematurely",
617Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
618 HasLinkingSection =
true;
622 return make_error<GenericBinaryError>(
623 "unexpected metadata version: " +
Twine(LinkingData.
Version) +
628 const uint8_t *OrigEnd = Ctx.End;
629 while (Ctx.Ptr < OrigEnd) {
635 Ctx.End = Ctx.Ptr +
Size;
638 if (
Error Err = parseLinkingSectionSymtab(Ctx))
643 if (Count > DataSegments.size())
644 return make_error<GenericBinaryError>(
"too many segment names",
660 if (!isValidFunctionSymbol(
Init.Symbol))
661 return make_error<GenericBinaryError>(
"invalid function symbol: " +
669 if (
Error Err = parseLinkingSectionComdat(Ctx))
676 if (Ctx.Ptr != Ctx.End)
677 return make_error<GenericBinaryError>(
680 if (Ctx.Ptr != OrigEnd)
681 return make_error<GenericBinaryError>(
"linking section ended prematurely",
686Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
691 Symbols.reserve(Count);
694 std::vector<wasm::WasmImport *> ImportedGlobals;
695 std::vector<wasm::WasmImport *> ImportedFunctions;
696 std::vector<wasm::WasmImport *> ImportedTags;
697 std::vector<wasm::WasmImport *> ImportedTables;
698 ImportedGlobals.reserve(Imports.size());
699 ImportedFunctions.reserve(Imports.size());
700 ImportedTags.reserve(Imports.size());
701 ImportedTables.reserve(Imports.size());
702 for (
auto &
I : Imports) {
704 ImportedFunctions.emplace_back(&
I);
706 ImportedGlobals.emplace_back(&
I);
708 ImportedTags.emplace_back(&
I);
710 ImportedTables.emplace_back(&
I);
726 if (!isValidFunctionIndex(
Info.ElementIndex) ||
727 IsDefined != isDefinedFunctionIndex(
Info.ElementIndex))
728 return make_error<GenericBinaryError>(
"invalid function symbol index",
732 unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
734 Signature = &Signatures[
Function.SigIndex];
745 Signature = &Signatures[
Import.SigIndex];
752 if (!isValidGlobalIndex(
Info.ElementIndex) ||
753 IsDefined != isDefinedGlobalIndex(
Info.ElementIndex))
754 return make_error<GenericBinaryError>(
"invalid global symbol index",
758 return make_error<GenericBinaryError>(
"undefined weak global symbol",
762 unsigned GlobalIndex =
Info.ElementIndex - NumImportedGlobals;
764 GlobalType = &
Global.Type;
765 if (
Global.SymbolName.empty())
775 GlobalType = &
Import.Global;
782 if (!isValidTableNumber(
Info.ElementIndex) ||
783 IsDefined != isDefinedTableNumber(
Info.ElementIndex))
784 return make_error<GenericBinaryError>(
"invalid table symbol index",
788 return make_error<GenericBinaryError>(
"undefined weak table symbol",
792 unsigned TableNumber =
Info.ElementIndex - NumImportedTables;
794 TableType = &Table.
Type;
805 TableType = &
Import.Table;
817 if (
static_cast<size_t>(
Index) >= DataSegments.size())
818 return make_error<GenericBinaryError>(
819 "invalid data segment index: " +
Twine(
Index),
821 size_t SegmentSize = DataSegments[
Index].Data.Content.size();
823 return make_error<GenericBinaryError>(
824 "invalid data symbol offset: `" +
Info.Name +
826 " segment size: " +
Twine(SegmentSize) +
")",
836 return make_error<GenericBinaryError>(
837 "section symbols must have local binding",
848 if (!isValidTagIndex(
Info.ElementIndex) ||
849 IsDefined != isDefinedTagIndex(
Info.ElementIndex))
850 return make_error<GenericBinaryError>(
"invalid tag symbol index",
854 return make_error<GenericBinaryError>(
"undefined weak global symbol",
858 unsigned TagIndex =
Info.ElementIndex - NumImportedTags;
860 Signature = &Signatures[
Tag.SigIndex];
861 if (
Tag.SymbolName.empty())
872 Signature = &Signatures[
Import.SigIndex];
879 return make_error<GenericBinaryError>(
"invalid symbol type: " +
887 return make_error<GenericBinaryError>(
"duplicate symbol name " +
890 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
891 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
897Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
900 for (
unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
903 return make_error<GenericBinaryError>(
"bad/duplicate COMDAT name " +
909 return make_error<GenericBinaryError>(
"unsupported COMDAT flags",
913 while (EntryCount--) {
918 return make_error<GenericBinaryError>(
"invalid COMDAT entry type",
921 if (
Index >= DataSegments.size())
922 return make_error<GenericBinaryError>(
924 if (DataSegments[
Index].
Data.Comdat != UINT32_MAX)
925 return make_error<GenericBinaryError>(
"data segment in two COMDATs",
927 DataSegments[
Index].Data.Comdat = ComdatIndex;
930 if (!isDefinedFunctionIndex(
Index))
931 return make_error<GenericBinaryError>(
933 if (getDefinedFunction(
Index).
Comdat != UINT32_MAX)
934 return make_error<GenericBinaryError>(
"function in two COMDATs",
939 if (
Index >= Sections.size())
940 return make_error<GenericBinaryError>(
943 return make_error<GenericBinaryError>(
945 Sections[
Index].Comdat = ComdatIndex;
953Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
956 for (
size_t I = 0;
I < Fields; ++
I) {
958 if (!FieldsSeen.
insert(FieldName).second)
959 return make_error<GenericBinaryError>(
960 "producers section does not have unique fields",
962 std::vector<std::pair<std::string, std::string>> *ProducerVec =
nullptr;
963 if (FieldName ==
"language") {
965 }
else if (FieldName ==
"processed-by") {
966 ProducerVec = &ProducerInfo.
Tools;
967 }
else if (FieldName ==
"sdk") {
968 ProducerVec = &ProducerInfo.
SDKs;
970 return make_error<GenericBinaryError>(
971 "producers section field is not named one of language, processed-by, "
977 for (
size_t J = 0; J < ValueCount; ++J) {
981 return make_error<GenericBinaryError>(
982 "producers section contains repeated producer",
985 ProducerVec->emplace_back(std::string(
Name), std::string(
Version));
988 if (Ctx.Ptr != Ctx.End)
989 return make_error<GenericBinaryError>(
"producers section ended prematurely",
994Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
1000 switch (Feature.
Prefix) {
1006 return make_error<GenericBinaryError>(
"unknown feature policy prefix",
1010 if (!FeaturesSeen.
insert(Feature.
Name).second)
1011 return make_error<GenericBinaryError>(
1012 "target features section contains repeated feature \"" +
1013 Feature.
Name +
"\"",
1015 TargetFeatures.push_back(Feature);
1017 if (Ctx.Ptr != Ctx.End)
1018 return make_error<GenericBinaryError>(
1019 "target features section ended prematurely",
1026 if (SectionIndex >= Sections.size())
1027 return make_error<GenericBinaryError>(
"invalid section index",
1033 while (RelocCount--) {
1038 if (Reloc.
Offset < PreviousOffset)
1039 return make_error<GenericBinaryError>(
"relocations not in offset order",
1043 return make_error<GenericBinaryError>(
1044 msg +
": " +
Twine(Symbols[Reloc.
Index].Info.Name),
1048 PreviousOffset = Reloc.
Offset;
1051 case wasm::R_WASM_FUNCTION_INDEX_LEB:
1052 case wasm::R_WASM_FUNCTION_INDEX_I32:
1053 case wasm::R_WASM_TABLE_INDEX_SLEB:
1054 case wasm::R_WASM_TABLE_INDEX_SLEB64:
1055 case wasm::R_WASM_TABLE_INDEX_I32:
1056 case wasm::R_WASM_TABLE_INDEX_I64:
1057 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
1058 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
1059 if (!isValidFunctionSymbol(Reloc.
Index))
1060 return badReloc(
"invalid function relocation");
1062 case wasm::R_WASM_TABLE_NUMBER_LEB:
1063 if (!isValidTableSymbol(Reloc.
Index))
1064 return badReloc(
"invalid table relocation");
1066 case wasm::R_WASM_TYPE_INDEX_LEB:
1067 if (Reloc.
Index >= Signatures.size())
1068 return badReloc(
"invalid relocation type index");
1070 case wasm::R_WASM_GLOBAL_INDEX_LEB:
1073 if (!isValidGlobalSymbol(Reloc.
Index) &&
1074 !isValidDataSymbol(Reloc.
Index) &&
1075 !isValidFunctionSymbol(Reloc.
Index))
1076 return badReloc(
"invalid global relocation");
1078 case wasm::R_WASM_GLOBAL_INDEX_I32:
1079 if (!isValidGlobalSymbol(Reloc.
Index))
1080 return badReloc(
"invalid global relocation");
1082 case wasm::R_WASM_TAG_INDEX_LEB:
1083 if (!isValidTagSymbol(Reloc.
Index))
1084 return badReloc(
"invalid tag relocation");
1086 case wasm::R_WASM_MEMORY_ADDR_LEB:
1087 case wasm::R_WASM_MEMORY_ADDR_SLEB:
1088 case wasm::R_WASM_MEMORY_ADDR_I32:
1089 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1090 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1091 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1092 if (!isValidDataSymbol(Reloc.
Index))
1093 return badReloc(
"invalid data relocation");
1096 case wasm::R_WASM_MEMORY_ADDR_LEB64:
1097 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1098 case wasm::R_WASM_MEMORY_ADDR_I64:
1099 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1100 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1101 if (!isValidDataSymbol(Reloc.
Index))
1102 return badReloc(
"invalid data relocation");
1105 case wasm::R_WASM_FUNCTION_OFFSET_I32:
1106 if (!isValidFunctionSymbol(Reloc.
Index))
1107 return badReloc(
"invalid function relocation");
1110 case wasm::R_WASM_FUNCTION_OFFSET_I64:
1111 if (!isValidFunctionSymbol(Reloc.
Index))
1112 return badReloc(
"invalid function relocation");
1115 case wasm::R_WASM_SECTION_OFFSET_I32:
1116 if (!isValidSectionSymbol(Reloc.
Index))
1117 return badReloc(
"invalid section relocation");
1121 return make_error<GenericBinaryError>(
"invalid relocation type: " +
1130 if (Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1131 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1132 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1134 if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1135 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1136 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1137 Reloc.
Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1138 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1139 Reloc.
Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
1140 Reloc.
Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1142 if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1143 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1144 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1147 return make_error<GenericBinaryError>(
"invalid relocation offset",
1150 Section.Relocations.push_back(Reloc);
1152 if (Ctx.Ptr != Ctx.End)
1153 return make_error<GenericBinaryError>(
"reloc section ended prematurely",
1158Error WasmObjectFile::parseCustomSection(
WasmSection &Sec, ReadContext &Ctx) {
1159 if (Sec.
Name ==
"dylink") {
1160 if (
Error Err = parseDylinkSection(Ctx))
1162 }
else if (Sec.
Name ==
"dylink.0") {
1163 if (
Error Err = parseDylink0Section(Ctx))
1165 }
else if (Sec.
Name ==
"name") {
1166 if (
Error Err = parseNameSection(Ctx))
1168 }
else if (Sec.
Name ==
"linking") {
1169 if (
Error Err = parseLinkingSection(Ctx))
1171 }
else if (Sec.
Name ==
"producers") {
1172 if (
Error Err = parseProducersSection(Ctx))
1174 }
else if (Sec.
Name ==
"target_features") {
1175 if (
Error Err = parseTargetFeaturesSection(Ctx))
1178 if (
Error Err = parseRelocSection(Sec.
Name, Ctx))
1184Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1185 auto parseFieldDef = [&]() {
1192 Signatures.reserve(Count);
1201 return make_error<GenericBinaryError>(
"Rec group size cannot be 0",
1203 Signatures.reserve(Signatures.size() + RecSize);
1206 Signatures.push_back(std::move(Sig));
1207 HasUnmodeledTypes =
true;
1218 return make_error<GenericBinaryError>(
1226 while (FieldCount--) {
1232 return make_error<GenericBinaryError>(
"bad form",
1236 Signatures.push_back(std::move(Sig));
1237 HasUnmodeledTypes =
true;
1243 while (ParamCount--) {
1249 while (ReturnCount--) {
1254 Signatures.push_back(std::move(Sig));
1256 if (Ctx.Ptr != Ctx.End)
1257 return make_error<GenericBinaryError>(
"type section ended prematurely",
1262Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1264 uint32_t NumTypes = Signatures.size();
1265 Imports.reserve(Count);
1273 NumImportedFunctions++;
1276 return make_error<GenericBinaryError>(
"invalid function type",
1280 NumImportedGlobals++;
1291 NumImportedTables++;
1297 return make_error<GenericBinaryError>(
"invalid table element type",
1304 return make_error<GenericBinaryError>(
"invalid attribute",
1308 return make_error<GenericBinaryError>(
"invalid tag type",
1312 return make_error<GenericBinaryError>(
"unexpected import kind",
1315 Imports.push_back(Im);
1317 if (Ctx.Ptr != Ctx.End)
1318 return make_error<GenericBinaryError>(
"import section ended prematurely",
1323Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1325 Functions.reserve(Count);
1326 uint32_t NumTypes = Signatures.size();
1329 if (
Type >= NumTypes)
1330 return make_error<GenericBinaryError>(
"invalid function type",
1334 Functions.push_back(
F);
1336 if (Ctx.Ptr != Ctx.End)
1337 return make_error<GenericBinaryError>(
"function section ended prematurely",
1342Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1343 TableSection = Sections.size();
1345 Tables.reserve(Count);
1349 T.Index = NumImportedTables + Tables.size();
1350 Tables.push_back(
T);
1351 auto ElemType = Tables.back().Type.ElemType;
1356 return make_error<GenericBinaryError>(
"invalid table element type",
1360 if (Ctx.Ptr != Ctx.End)
1361 return make_error<GenericBinaryError>(
"table section ended prematurely",
1366Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1368 Memories.reserve(Count);
1373 Memories.push_back(Limits);
1375 if (Ctx.Ptr != Ctx.End)
1376 return make_error<GenericBinaryError>(
"memory section ended prematurely",
1381Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1382 TagSection = Sections.size();
1384 Tags.reserve(Count);
1385 uint32_t NumTypes = Signatures.size();
1388 return make_error<GenericBinaryError>(
"invalid attribute",
1391 if (
Type >= NumTypes)
1392 return make_error<GenericBinaryError>(
"invalid tag type",
1395 Tag.Index = NumImportedTags + Tags.size();
1398 Tags.push_back(
Tag);
1401 if (Ctx.Ptr != Ctx.End)
1402 return make_error<GenericBinaryError>(
"tag section ended prematurely",
1407Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1408 GlobalSection = Sections.size();
1409 const uint8_t *SectionStart = Ctx.Ptr;
1411 Globals.reserve(Count);
1414 Global.Index = NumImportedGlobals + Globals.size();
1415 const uint8_t *GlobalStart = Ctx.Ptr;
1416 Global.Offset =
static_cast<uint32_t>(GlobalStart - SectionStart);
1423 Globals.push_back(
Global);
1425 if (Ctx.Ptr != Ctx.End)
1426 return make_error<GenericBinaryError>(
"global section ended prematurely",
1431Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1433 Exports.reserve(Count);
1434 Symbols.reserve(Count);
1448 if (!isDefinedFunctionIndex(Ex.
Index))
1449 return make_error<GenericBinaryError>(
"invalid function export",
1454 unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
1456 Signature = &Signatures[
Function.SigIndex];
1460 if (!isValidGlobalIndex(Ex.
Index))
1461 return make_error<GenericBinaryError>(
"invalid global export",
1465 if (isDefinedGlobalIndex(Ex.
Index)) {
1467 if (!
Global.InitExpr.Extended) {
1468 auto Inst =
Global.InitExpr.Inst;
1470 Offset = Inst.Value.Int32;
1472 Offset = Inst.Value.Int64;
1480 if (!isValidTagIndex(Ex.
Index))
1481 return make_error<GenericBinaryError>(
"invalid tag export",
1493 return make_error<GenericBinaryError>(
"unexpected export kind",
1496 Exports.push_back(Ex);
1498 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
1499 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
1502 if (Ctx.Ptr != Ctx.End)
1503 return make_error<GenericBinaryError>(
"export section ended prematurely",
1508bool WasmObjectFile::isValidFunctionIndex(
uint32_t Index)
const {
1509 return Index < NumImportedFunctions + Functions.size();
1512bool WasmObjectFile::isDefinedFunctionIndex(
uint32_t Index)
const {
1513 return Index >= NumImportedFunctions && isValidFunctionIndex(
Index);
1516bool WasmObjectFile::isValidGlobalIndex(
uint32_t Index)
const {
1517 return Index < NumImportedGlobals + Globals.size();
1520bool WasmObjectFile::isValidTableNumber(
uint32_t Index)
const {
1521 return Index < NumImportedTables + Tables.size();
1524bool WasmObjectFile::isDefinedGlobalIndex(
uint32_t Index)
const {
1525 return Index >= NumImportedGlobals && isValidGlobalIndex(
Index);
1528bool WasmObjectFile::isDefinedTableNumber(
uint32_t Index)
const {
1529 return Index >= NumImportedTables && isValidTableNumber(
Index);
1533 return Index < NumImportedTags + Tags.size();
1536bool WasmObjectFile::isDefinedTagIndex(
uint32_t Index)
const {
1537 return Index >= NumImportedTags && isValidTagIndex(
Index);
1540bool WasmObjectFile::isValidFunctionSymbol(
uint32_t Index)
const {
1541 return Index < Symbols.size() && Symbols[
Index].isTypeFunction();
1544bool WasmObjectFile::isValidTableSymbol(
uint32_t Index)
const {
1545 return Index < Symbols.size() && Symbols[
Index].isTypeTable();
1548bool WasmObjectFile::isValidGlobalSymbol(
uint32_t Index)
const {
1549 return Index < Symbols.size() && Symbols[
Index].isTypeGlobal();
1552bool WasmObjectFile::isValidTagSymbol(
uint32_t Index)
const {
1553 return Index < Symbols.size() && Symbols[
Index].isTypeTag();
1556bool WasmObjectFile::isValidDataSymbol(
uint32_t Index)
const {
1557 return Index < Symbols.size() && Symbols[
Index].isTypeData();
1560bool WasmObjectFile::isValidSectionSymbol(
uint32_t Index)
const {
1561 return Index < Symbols.size() && Symbols[
Index].isTypeSection();
1566 return Functions[
Index - NumImportedFunctions];
1572 return Functions[
Index - NumImportedFunctions];
1577 return Globals[
Index - NumImportedGlobals];
1582 return Tags[
Index - NumImportedTags];
1585Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1587 if (!isValidFunctionIndex(StartFunction))
1588 return make_error<GenericBinaryError>(
"invalid start function",
1593Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1594 CodeSection = Sections.size();
1596 if (FunctionCount != Functions.size()) {
1597 return make_error<GenericBinaryError>(
"invalid function count",
1601 for (
uint32_t i = 0; i < FunctionCount; i++) {
1603 const uint8_t *FunctionStart = Ctx.Ptr;
1605 const uint8_t *FunctionEnd = Ctx.Ptr +
Size;
1607 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1608 Function.Index = NumImportedFunctions + i;
1609 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1610 Function.Size = FunctionEnd - FunctionStart;
1613 Function.Locals.reserve(NumLocalDecls);
1614 while (NumLocalDecls--) {
1621 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1623 if (Ctx.Ptr + BodySize > Ctx.End) {
1624 return make_error<GenericBinaryError>(
"Function extends beyond buffer",
1630 Ctx.Ptr += BodySize;
1631 assert(Ctx.Ptr == FunctionEnd);
1633 if (Ctx.Ptr != Ctx.End)
1634 return make_error<GenericBinaryError>(
"code section ended prematurely",
1639Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1641 ElemSegments.reserve(Count);
1649 if (Segment.
Flags & ~SupportedFlags)
1650 return make_error<GenericBinaryError>(
1654 bool IsDeclarative =
1656 bool HasTableNumber =
1671 return make_error<GenericBinaryError>(
"invalid TableNumber",
1674 if (IsPassive || IsDeclarative) {
1691 return make_error<GenericBinaryError>(
"invalid elem type",
1696 return make_error<GenericBinaryError>(
"invalid elem type",
1700 }
else if (HasInitExprs) {
1710 while (NumElems--) {
1716 while (NumElems--) {
1720 ElemSegments.push_back(Segment);
1722 if (Ctx.Ptr != Ctx.End)
1723 return make_error<GenericBinaryError>(
"elem section ended prematurely",
1728Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1729 DataSection = Sections.size();
1731 if (DataCount && Count != *DataCount)
1732 return make_error<GenericBinaryError>(
1733 "number of data segments does not match DataCount section");
1734 DataSegments.reserve(Count);
1751 if (
Size > (
size_t)(Ctx.End - Ctx.Ptr))
1752 return make_error<GenericBinaryError>(
"invalid segment size",
1762 DataSegments.push_back(Segment);
1764 if (Ctx.Ptr != Ctx.End)
1765 return make_error<GenericBinaryError>(
"data section ended prematurely",
1770Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1786 if (
Sym.isBindingWeak())
1788 if (!
Sym.isBindingLocal())
1792 if (!
Sym.isDefined())
1794 if (
Sym.isTypeFunction())
1809 Ref.d.b = Symbols.size();
1814 return Symbols[Symb.
d.
b];
1827 if (!
Sym.isDefined())
1834 isDefinedFunctionIndex(
Sym.Info.ElementIndex)) {
1839 isDefinedGlobalIndex(
Sym.Info.ElementIndex)) {
1840 return getDefinedGlobal(
Sym.Info.ElementIndex).
Offset + SectionAddress;
1847 switch (
Sym.Info.Kind) {
1852 return Sym.Info.ElementIndex;
1865 return Sym.Info.DataRef.Offset;
1894 switch (
Sym.Info.Kind) {
1916 if (
Sym.isUndefined())
1920 Ref.d.a = getSymbolSectionIdImpl(
Sym);
1926 return getSymbolSectionIdImpl(
Sym);
1930 switch (
Sym.Info.Kind) {
1934 return GlobalSection;
1938 return Sym.Info.ElementIndex;
1942 return TableSection;
1950 if (!
Sym.isDefined())
1952 if (
Sym.isTypeGlobal())
1953 return getDefinedGlobal(
Sym.Info.ElementIndex).
Size;
1954 if (
Sym.isTypeData())
1955 return Sym.Info.DataRef.Size;
1956 if (
Sym.isTypeFunction())
1980 : Sections[Sec.
d.
a].Offset;
2022 RelocRef.
d.
a =
Ref.d.a;
2030 RelocRef.
d.
a =
Ref.d.a;
2044 if (Rel.
Type == wasm::R_WASM_TYPE_INDEX_LEB)
2062#define WASM_RELOC(name, value) \
2068#include "llvm/BinaryFormat/WasmRelocs.def"
2073 Result.append(Res.
begin(), Res.
end());
2084 Ref.d.a = Sections.size();
2089 return HasMemory64 ? 8 : 4;
2108 return Sections[
Ref.d.a];
2129int WasmSectionOrderChecker::getSectionOrder(
unsigned ID,
2177 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2181 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2183 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2185 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2187 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2189 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2191 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2193 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2195 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2197 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2199 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2201 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2203 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2205 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2209 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2211 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2215 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2217 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2219 {WASM_SEC_ORDER_TARGET_FEATURES}};
2223 int Order = getSectionOrder(
ID, CustomSectionName);
2236 for (
size_t I = 0;; ++
I) {
2243 Checked[Next] =
true;
2246 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)
const unsigned WASM_SYMBOL_UNDEFINED
@ WASM_OPCODE_ARRAY_NEW_FIXED
@ WASM_OPCODE_ARRAY_NEW_DEFAULT
@ WASM_OPCODE_STRUCT_NEW_DEFAULT
@ 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
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_REQUIRED
@ 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.
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::@368 d