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 if (!HasLinkingSection) {
518 while (Ctx.Ptr < Ctx.End) {
521 const uint8_t *SubSectionEnd = Ctx.Ptr +
Size;
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;
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;
579 return make_error<GenericBinaryError>(
581 if (
Index > DataSegments.size())
582 return make_error<GenericBinaryError>(
"invalid data segment name entry",
589 Index, 0, DataSegments[
Index].Data.Content.size()};
592 if (!HasLinkingSection)
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",
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) {
1003 return make_error<GenericBinaryError>(
"unknown feature policy prefix",
1007 if (!FeaturesSeen.
insert(Feature.
Name).second)
1008 return make_error<GenericBinaryError>(
1009 "target features section contains repeated feature \"" +
1010 Feature.
Name +
"\"",
1012 TargetFeatures.push_back(Feature);
1014 if (Ctx.Ptr != Ctx.End)
1015 return make_error<GenericBinaryError>(
1016 "target features section ended prematurely",
1023 if (SectionIndex >= Sections.size())
1024 return make_error<GenericBinaryError>(
"invalid section index",
1030 while (RelocCount--) {
1035 if (Reloc.
Offset < PreviousOffset)
1036 return make_error<GenericBinaryError>(
"relocations not in offset order",
1040 return make_error<GenericBinaryError>(
1041 msg +
": " +
Twine(Symbols[Reloc.
Index].Info.Name),
1045 PreviousOffset = Reloc.
Offset;
1048 case wasm::R_WASM_FUNCTION_INDEX_LEB:
1049 case wasm::R_WASM_FUNCTION_INDEX_I32:
1050 case wasm::R_WASM_TABLE_INDEX_SLEB:
1051 case wasm::R_WASM_TABLE_INDEX_SLEB64:
1052 case wasm::R_WASM_TABLE_INDEX_I32:
1053 case wasm::R_WASM_TABLE_INDEX_I64:
1054 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
1055 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
1056 if (!isValidFunctionSymbol(Reloc.
Index))
1057 return badReloc(
"invalid function relocation");
1059 case wasm::R_WASM_TABLE_NUMBER_LEB:
1060 if (!isValidTableSymbol(Reloc.
Index))
1061 return badReloc(
"invalid table relocation");
1063 case wasm::R_WASM_TYPE_INDEX_LEB:
1064 if (Reloc.
Index >= Signatures.size())
1065 return badReloc(
"invalid relocation type index");
1067 case wasm::R_WASM_GLOBAL_INDEX_LEB:
1070 if (!isValidGlobalSymbol(Reloc.
Index) &&
1071 !isValidDataSymbol(Reloc.
Index) &&
1072 !isValidFunctionSymbol(Reloc.
Index))
1073 return badReloc(
"invalid global relocation");
1075 case wasm::R_WASM_GLOBAL_INDEX_I32:
1076 if (!isValidGlobalSymbol(Reloc.
Index))
1077 return badReloc(
"invalid global relocation");
1079 case wasm::R_WASM_TAG_INDEX_LEB:
1080 if (!isValidTagSymbol(Reloc.
Index))
1081 return badReloc(
"invalid tag relocation");
1083 case wasm::R_WASM_MEMORY_ADDR_LEB:
1084 case wasm::R_WASM_MEMORY_ADDR_SLEB:
1085 case wasm::R_WASM_MEMORY_ADDR_I32:
1086 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1087 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1088 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1089 if (!isValidDataSymbol(Reloc.
Index))
1090 return badReloc(
"invalid data relocation");
1093 case wasm::R_WASM_MEMORY_ADDR_LEB64:
1094 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1095 case wasm::R_WASM_MEMORY_ADDR_I64:
1096 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1097 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1098 if (!isValidDataSymbol(Reloc.
Index))
1099 return badReloc(
"invalid data relocation");
1102 case wasm::R_WASM_FUNCTION_OFFSET_I32:
1103 if (!isValidFunctionSymbol(Reloc.
Index))
1104 return badReloc(
"invalid function relocation");
1107 case wasm::R_WASM_FUNCTION_OFFSET_I64:
1108 if (!isValidFunctionSymbol(Reloc.
Index))
1109 return badReloc(
"invalid function relocation");
1112 case wasm::R_WASM_SECTION_OFFSET_I32:
1113 if (!isValidSectionSymbol(Reloc.
Index))
1114 return badReloc(
"invalid section relocation");
1118 return make_error<GenericBinaryError>(
"invalid relocation type: " +
1127 if (Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1128 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1129 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1131 if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1132 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1133 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1134 Reloc.
Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1135 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1136 Reloc.
Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
1137 Reloc.
Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1139 if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1140 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1141 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1144 return make_error<GenericBinaryError>(
"invalid relocation offset",
1147 Section.Relocations.push_back(Reloc);
1149 if (Ctx.Ptr != Ctx.End)
1150 return make_error<GenericBinaryError>(
"reloc section ended prematurely",
1155Error WasmObjectFile::parseCustomSection(
WasmSection &Sec, ReadContext &Ctx) {
1156 if (Sec.
Name ==
"dylink") {
1157 if (
Error Err = parseDylinkSection(Ctx))
1159 }
else if (Sec.
Name ==
"dylink.0") {
1160 if (
Error Err = parseDylink0Section(Ctx))
1162 }
else if (Sec.
Name ==
"name") {
1163 if (
Error Err = parseNameSection(Ctx))
1165 }
else if (Sec.
Name ==
"linking") {
1166 if (
Error Err = parseLinkingSection(Ctx))
1168 }
else if (Sec.
Name ==
"producers") {
1169 if (
Error Err = parseProducersSection(Ctx))
1171 }
else if (Sec.
Name ==
"target_features") {
1172 if (
Error Err = parseTargetFeaturesSection(Ctx))
1175 if (
Error Err = parseRelocSection(Sec.
Name, Ctx))
1181Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1182 auto parseFieldDef = [&]() {
1189 Signatures.reserve(Count);
1198 return make_error<GenericBinaryError>(
"Rec group size cannot be 0",
1200 Signatures.reserve(Signatures.size() + RecSize);
1203 Signatures.push_back(std::move(Sig));
1204 HasUnmodeledTypes =
true;
1215 return make_error<GenericBinaryError>(
1223 while (FieldCount--) {
1229 return make_error<GenericBinaryError>(
"bad form",
1233 Signatures.push_back(std::move(Sig));
1234 HasUnmodeledTypes =
true;
1240 while (ParamCount--) {
1246 while (ReturnCount--) {
1251 Signatures.push_back(std::move(Sig));
1253 if (Ctx.Ptr != Ctx.End)
1254 return make_error<GenericBinaryError>(
"type section ended prematurely",
1259Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1261 uint32_t NumTypes = Signatures.size();
1262 Imports.reserve(Count);
1270 NumImportedFunctions++;
1273 return make_error<GenericBinaryError>(
"invalid function type",
1277 NumImportedGlobals++;
1288 NumImportedTables++;
1294 return make_error<GenericBinaryError>(
"invalid table element type",
1301 return make_error<GenericBinaryError>(
"invalid attribute",
1305 return make_error<GenericBinaryError>(
"invalid tag type",
1309 return make_error<GenericBinaryError>(
"unexpected import kind",
1312 Imports.push_back(Im);
1314 if (Ctx.Ptr != Ctx.End)
1315 return make_error<GenericBinaryError>(
"import section ended prematurely",
1320Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1322 Functions.reserve(Count);
1323 uint32_t NumTypes = Signatures.size();
1326 if (
Type >= NumTypes)
1327 return make_error<GenericBinaryError>(
"invalid function type",
1331 Functions.push_back(
F);
1333 if (Ctx.Ptr != Ctx.End)
1334 return make_error<GenericBinaryError>(
"function section ended prematurely",
1339Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1340 TableSection = Sections.size();
1342 Tables.reserve(Count);
1346 T.Index = NumImportedTables + Tables.size();
1347 Tables.push_back(
T);
1348 auto ElemType = Tables.back().Type.ElemType;
1353 return make_error<GenericBinaryError>(
"invalid table element type",
1357 if (Ctx.Ptr != Ctx.End)
1358 return make_error<GenericBinaryError>(
"table section ended prematurely",
1363Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1365 Memories.reserve(Count);
1370 Memories.push_back(Limits);
1372 if (Ctx.Ptr != Ctx.End)
1373 return make_error<GenericBinaryError>(
"memory section ended prematurely",
1378Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1379 TagSection = Sections.size();
1381 Tags.reserve(Count);
1382 uint32_t NumTypes = Signatures.size();
1385 return make_error<GenericBinaryError>(
"invalid attribute",
1388 if (
Type >= NumTypes)
1389 return make_error<GenericBinaryError>(
"invalid tag type",
1392 Tag.Index = NumImportedTags + Tags.size();
1395 Tags.push_back(
Tag);
1398 if (Ctx.Ptr != Ctx.End)
1399 return make_error<GenericBinaryError>(
"tag section ended prematurely",
1404Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1405 GlobalSection = Sections.size();
1406 const uint8_t *SectionStart = Ctx.Ptr;
1408 Globals.reserve(Count);
1411 Global.Index = NumImportedGlobals + Globals.size();
1412 const uint8_t *GlobalStart = Ctx.Ptr;
1413 Global.Offset =
static_cast<uint32_t>(GlobalStart - SectionStart);
1420 Globals.push_back(
Global);
1422 if (Ctx.Ptr != Ctx.End)
1423 return make_error<GenericBinaryError>(
"global section ended prematurely",
1428Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1430 Exports.reserve(Count);
1431 Symbols.reserve(Count);
1445 if (!isDefinedFunctionIndex(Ex.
Index))
1446 return make_error<GenericBinaryError>(
"invalid function export",
1451 unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
1453 Signature = &Signatures[
Function.SigIndex];
1457 if (!isValidGlobalIndex(Ex.
Index))
1458 return make_error<GenericBinaryError>(
"invalid global export",
1462 if (isDefinedGlobalIndex(Ex.
Index)) {
1464 if (!
Global.InitExpr.Extended) {
1465 auto Inst =
Global.InitExpr.Inst;
1467 Offset = Inst.Value.Int32;
1469 Offset = Inst.Value.Int64;
1477 if (!isValidTagIndex(Ex.
Index))
1478 return make_error<GenericBinaryError>(
"invalid tag export",
1490 return make_error<GenericBinaryError>(
"unexpected export kind",
1493 Exports.push_back(Ex);
1495 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
1496 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
1499 if (Ctx.Ptr != Ctx.End)
1500 return make_error<GenericBinaryError>(
"export section ended prematurely",
1505bool WasmObjectFile::isValidFunctionIndex(
uint32_t Index)
const {
1506 return Index < NumImportedFunctions + Functions.size();
1509bool WasmObjectFile::isDefinedFunctionIndex(
uint32_t Index)
const {
1510 return Index >= NumImportedFunctions && isValidFunctionIndex(
Index);
1513bool WasmObjectFile::isValidGlobalIndex(
uint32_t Index)
const {
1514 return Index < NumImportedGlobals + Globals.size();
1517bool WasmObjectFile::isValidTableNumber(
uint32_t Index)
const {
1518 return Index < NumImportedTables + Tables.size();
1521bool WasmObjectFile::isDefinedGlobalIndex(
uint32_t Index)
const {
1522 return Index >= NumImportedGlobals && isValidGlobalIndex(
Index);
1525bool WasmObjectFile::isDefinedTableNumber(
uint32_t Index)
const {
1526 return Index >= NumImportedTables && isValidTableNumber(
Index);
1530 return Index < NumImportedTags + Tags.size();
1533bool WasmObjectFile::isDefinedTagIndex(
uint32_t Index)
const {
1534 return Index >= NumImportedTags && isValidTagIndex(
Index);
1537bool WasmObjectFile::isValidFunctionSymbol(
uint32_t Index)
const {
1538 return Index < Symbols.size() && Symbols[
Index].isTypeFunction();
1541bool WasmObjectFile::isValidTableSymbol(
uint32_t Index)
const {
1542 return Index < Symbols.size() && Symbols[
Index].isTypeTable();
1545bool WasmObjectFile::isValidGlobalSymbol(
uint32_t Index)
const {
1546 return Index < Symbols.size() && Symbols[
Index].isTypeGlobal();
1549bool WasmObjectFile::isValidTagSymbol(
uint32_t Index)
const {
1550 return Index < Symbols.size() && Symbols[
Index].isTypeTag();
1553bool WasmObjectFile::isValidDataSymbol(
uint32_t Index)
const {
1554 return Index < Symbols.size() && Symbols[
Index].isTypeData();
1557bool WasmObjectFile::isValidSectionSymbol(
uint32_t Index)
const {
1558 return Index < Symbols.size() && Symbols[
Index].isTypeSection();
1563 return Functions[
Index - NumImportedFunctions];
1569 return Functions[
Index - NumImportedFunctions];
1574 return Globals[
Index - NumImportedGlobals];
1579 return Tags[
Index - NumImportedTags];
1582Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1584 if (!isValidFunctionIndex(StartFunction))
1585 return make_error<GenericBinaryError>(
"invalid start function",
1590Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1591 CodeSection = Sections.size();
1593 if (FunctionCount != Functions.size()) {
1594 return make_error<GenericBinaryError>(
"invalid function count",
1598 for (
uint32_t i = 0; i < FunctionCount; i++) {
1600 const uint8_t *FunctionStart = Ctx.Ptr;
1602 const uint8_t *FunctionEnd = Ctx.Ptr +
Size;
1604 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1605 Function.Index = NumImportedFunctions + i;
1606 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1607 Function.Size = FunctionEnd - FunctionStart;
1610 Function.Locals.reserve(NumLocalDecls);
1611 while (NumLocalDecls--) {
1618 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1620 if (Ctx.Ptr + BodySize > Ctx.End) {
1621 return make_error<GenericBinaryError>(
"Function extends beyond buffer",
1627 Ctx.Ptr += BodySize;
1628 assert(Ctx.Ptr == FunctionEnd);
1630 if (Ctx.Ptr != Ctx.End)
1631 return make_error<GenericBinaryError>(
"code section ended prematurely",
1636Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1638 ElemSegments.reserve(Count);
1646 if (Segment.
Flags & ~SupportedFlags)
1647 return make_error<GenericBinaryError>(
1651 bool IsDeclarative =
1653 bool HasTableNumber =
1668 return make_error<GenericBinaryError>(
"invalid TableNumber",
1671 if (IsPassive || IsDeclarative) {
1688 return make_error<GenericBinaryError>(
"invalid elem type",
1693 return make_error<GenericBinaryError>(
"invalid elem type",
1697 }
else if (HasInitExprs) {
1707 while (NumElems--) {
1713 while (NumElems--) {
1717 ElemSegments.push_back(Segment);
1719 if (Ctx.Ptr != Ctx.End)
1720 return make_error<GenericBinaryError>(
"elem section ended prematurely",
1725Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1726 DataSection = Sections.size();
1728 if (DataCount && Count != *DataCount)
1729 return make_error<GenericBinaryError>(
1730 "number of data segments does not match DataCount section");
1731 DataSegments.reserve(Count);
1748 if (
Size > (
size_t)(Ctx.End - Ctx.Ptr))
1749 return make_error<GenericBinaryError>(
"invalid segment size",
1759 DataSegments.push_back(Segment);
1761 if (Ctx.Ptr != Ctx.End)
1762 return make_error<GenericBinaryError>(
"data section ended prematurely",
1767Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1783 if (
Sym.isBindingWeak())
1785 if (!
Sym.isBindingLocal())
1789 if (!
Sym.isDefined())
1791 if (
Sym.isTypeFunction())
1806 Ref.d.b = Symbols.size();
1811 return Symbols[Symb.
d.
b];
1824 if (!
Sym.isDefined())
1831 isDefinedFunctionIndex(
Sym.Info.ElementIndex)) {
1836 isDefinedGlobalIndex(
Sym.Info.ElementIndex)) {
1837 return getDefinedGlobal(
Sym.Info.ElementIndex).
Offset + SectionAddress;
1844 switch (
Sym.Info.Kind) {
1849 return Sym.Info.ElementIndex;
1862 return Sym.Info.DataRef.Offset;
1891 switch (
Sym.Info.Kind) {
1913 if (
Sym.isUndefined())
1917 Ref.d.a = getSymbolSectionIdImpl(
Sym);
1923 return getSymbolSectionIdImpl(
Sym);
1927 switch (
Sym.Info.Kind) {
1931 return GlobalSection;
1935 return Sym.Info.ElementIndex;
1939 return TableSection;
1947 if (!
Sym.isDefined())
1949 if (
Sym.isTypeGlobal())
1950 return getDefinedGlobal(
Sym.Info.ElementIndex).
Size;
1951 if (
Sym.isTypeData())
1952 return Sym.Info.DataRef.Size;
1953 if (
Sym.isTypeFunction())
1977 : Sections[Sec.
d.
a].Offset;
2019 RelocRef.
d.
a =
Ref.d.a;
2027 RelocRef.
d.
a =
Ref.d.a;
2041 if (Rel.
Type == wasm::R_WASM_TYPE_INDEX_LEB)
2059#define WASM_RELOC(name, value) \
2065#include "llvm/BinaryFormat/WasmRelocs.def"
2070 Result.append(Res.
begin(), Res.
end());
2081 Ref.d.a = Sections.size();
2086 return HasMemory64 ? 8 : 4;
2105 return Sections[
Ref.d.a];
2126int WasmSectionOrderChecker::getSectionOrder(
unsigned ID,
2174 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2178 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2180 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2182 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2184 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2186 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2188 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2190 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2192 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2194 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2196 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2198 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2200 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2202 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2206 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2208 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2212 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2214 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2216 {WASM_SEC_ORDER_TARGET_FEATURES}};
2220 int Order = getSectionOrder(
ID, CustomSectionName);
2233 for (
size_t I = 0;; ++
I) {
2240 Checked[Next] =
true;
2243 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_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_UNDEFINED
@ WASM_LIMITS_FLAG_HAS_MAX
@ WASM_NAMES_DATA_SEGMENT
@ WASM_OPCODE_ARRAY_NEW_FIXED
@ WASM_OPCODE_ARRAY_NEW_DEFAULT
@ WASM_OPCODE_STRUCT_NEW_DEFAULT
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
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
const unsigned WASM_SYMBOL_BINDING_MASK
@ WASM_DYLINK_EXPORT_INFO
@ WASM_DYLINK_IMPORT_INFO
@ WASM_FEATURE_PREFIX_USED
@ WASM_FEATURE_PREFIX_REQUIRED
@ WASM_FEATURE_PREFIX_DISALLOWED
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::@181 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::@186 Kind
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params
WasmDataReference DataRef
struct llvm::object::DataRefImpl::@359 d