33#define DEBUG_TYPE "wasm-object"
36using namespace object;
62#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
69 auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
71 return std::move(Err);
76#define VARINT7_MAX ((1 << 7) - 1)
77#define VARINT7_MIN (-(1 << 7))
78#define VARUINT7_MAX (1 << 7)
79#define VARUINT1_MAX (1)
99 memcpy(&Result, Ctx.
Ptr,
sizeof(Result));
100 Ctx.
Ptr +=
sizeof(Result);
105 if (Ctx.
Ptr + 8 > Ctx.
End)
108 memcpy(&Result, Ctx.
Ptr,
sizeof(Result));
109 Ctx.
Ptr +=
sizeof(Result);
115 const char *
Error =
nullptr;
125 if (Ctx.
Ptr + StringLen > Ctx.
End)
128 StringRef(
reinterpret_cast<const char *
>(Ctx.
Ptr), StringLen);
129 Ctx.
Ptr += StringLen;
135 const char *
Error =
nullptr;
152 if (Result > INT32_MAX || Result < INT32_MIN)
159 if (Result > UINT32_MAX)
178 auto Start = Ctx.
Ptr;
201 return make_error<GenericBinaryError>(
"invalid type for ref.null",
240 return make_error<GenericBinaryError>(
241 Twine(
"invalid opcode in init_expr: ") +
Twine(
unsigned(Opcode)),
268 Section.Offset = Ctx.
Ptr - Ctx.
Start;
270 LLVM_DEBUG(
dbgs() <<
"readSection type=" << Section.Type <<
"\n");
273 return make_error<StringError>(
"zero length section",
276 return make_error<StringError>(
"section too large",
287 Ctx.
Ptr += SectionNameSize;
288 Size -= SectionNameSize;
292 return make_error<StringError>(
"out of order section type: " +
307 Err = make_error<StringError>(
"invalid magic number",
317 if (Ctx.
Ptr + 4 > Ctx.
End) {
318 Err = make_error<StringError>(
"missing version number",
325 Err = make_error<StringError>(
"invalid version number: " +
332 while (Ctx.
Ptr < Ctx.
End) {
336 if ((Err = parseSection(Sec)))
339 Sections.push_back(Sec);
350 return parseCustomSection(Sec, Ctx);
352 return parseTypeSection(Ctx);
354 return parseImportSection(Ctx);
356 return parseFunctionSection(Ctx);
358 return parseTableSection(Ctx);
360 return parseMemorySection(Ctx);
362 return parseTagSection(Ctx);
364 return parseGlobalSection(Ctx);
366 return parseExportSection(Ctx);
368 return parseStartSection(Ctx);
370 return parseElemSection(Ctx);
372 return parseCodeSection(Ctx);
374 return parseDataSection(Ctx);
376 return parseDataCountSection(Ctx);
378 return make_error<GenericBinaryError>(
383Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
386 HasDylinkSection =
true;
396 if (Ctx.Ptr != Ctx.End)
397 return make_error<GenericBinaryError>(
"dylink section ended prematurely",
402Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
405 HasDylinkSection =
true;
407 const uint8_t *OrigEnd = Ctx.End;
408 while (Ctx.Ptr < OrigEnd) {
414 Ctx.End = Ctx.Ptr +
Size;
449 if (Ctx.Ptr != Ctx.End) {
450 return make_error<GenericBinaryError>(
455 if (Ctx.Ptr != Ctx.End)
456 return make_error<GenericBinaryError>(
"dylink.0 section ended prematurely",
461Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
466 while (Ctx.Ptr < Ctx.End) {
469 const uint8_t *SubSectionEnd = Ctx.Ptr +
Size;
481 return make_error<GenericBinaryError>(
483 if (!isValidFunctionIndex(
Index) ||
Name.empty())
484 return make_error<GenericBinaryError>(
"invalid function name entry",
487 if (isDefinedFunctionIndex(
Index))
492 return make_error<GenericBinaryError>(
"global named more than once",
494 if (!isValidGlobalIndex(
Index) ||
Name.empty())
495 return make_error<GenericBinaryError>(
"invalid global name entry",
500 return make_error<GenericBinaryError>(
502 if (
Index > DataSegments.size())
503 return make_error<GenericBinaryError>(
"invalid data segment name entry",
516 if (Ctx.Ptr != SubSectionEnd)
517 return make_error<GenericBinaryError>(
521 if (Ctx.Ptr != Ctx.End)
522 return make_error<GenericBinaryError>(
"name section ended prematurely",
527Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
528 HasLinkingSection =
true;
532 return make_error<GenericBinaryError>(
533 "unexpected metadata version: " +
Twine(LinkingData.
Version) +
538 const uint8_t *OrigEnd = Ctx.End;
539 while (Ctx.Ptr < OrigEnd) {
545 Ctx.End = Ctx.Ptr +
Size;
548 if (
Error Err = parseLinkingSectionSymtab(Ctx))
553 if (Count > DataSegments.size())
554 return make_error<GenericBinaryError>(
"too many segment names",
570 if (!isValidFunctionSymbol(
Init.Symbol))
571 return make_error<GenericBinaryError>(
"invalid function symbol: " +
579 if (
Error Err = parseLinkingSectionComdat(Ctx))
586 if (Ctx.Ptr != Ctx.End)
587 return make_error<GenericBinaryError>(
590 if (Ctx.Ptr != OrigEnd)
591 return make_error<GenericBinaryError>(
"linking section ended prematurely",
596Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
599 Symbols.reserve(Count);
602 std::vector<wasm::WasmImport *> ImportedGlobals;
603 std::vector<wasm::WasmImport *> ImportedFunctions;
604 std::vector<wasm::WasmImport *> ImportedTags;
605 std::vector<wasm::WasmImport *> ImportedTables;
606 ImportedGlobals.reserve(Imports.size());
607 ImportedFunctions.reserve(Imports.size());
608 ImportedTags.reserve(Imports.size());
609 ImportedTables.reserve(Imports.size());
610 for (
auto &
I : Imports) {
612 ImportedFunctions.emplace_back(&
I);
614 ImportedGlobals.emplace_back(&
I);
616 ImportedTags.emplace_back(&
I);
618 ImportedTables.emplace_back(&
I);
634 if (!isValidFunctionIndex(
Info.ElementIndex) ||
635 IsDefined != isDefinedFunctionIndex(
Info.ElementIndex))
636 return make_error<GenericBinaryError>(
"invalid function symbol index",
640 unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
642 Signature = &Signatures[
Function.SigIndex];
653 Signature = &Signatures[
Import.SigIndex];
660 if (!isValidGlobalIndex(
Info.ElementIndex) ||
661 IsDefined != isDefinedGlobalIndex(
Info.ElementIndex))
662 return make_error<GenericBinaryError>(
"invalid global symbol index",
666 return make_error<GenericBinaryError>(
"undefined weak global symbol",
670 unsigned GlobalIndex =
Info.ElementIndex - NumImportedGlobals;
672 GlobalType = &
Global.Type;
673 if (
Global.SymbolName.empty())
683 GlobalType = &
Import.Global;
690 if (!isValidTableNumber(
Info.ElementIndex) ||
691 IsDefined != isDefinedTableNumber(
Info.ElementIndex))
692 return make_error<GenericBinaryError>(
"invalid table symbol index",
696 return make_error<GenericBinaryError>(
"undefined weak table symbol",
700 unsigned TableNumber =
Info.ElementIndex - NumImportedTables;
702 TableType = &Table.
Type;
713 TableType = &
Import.Table;
722 if (
Index >= DataSegments.size())
723 return make_error<GenericBinaryError>(
"invalid data symbol index",
727 size_t SegmentSize = DataSegments[
Index].Data.Content.size();
729 return make_error<GenericBinaryError>(
730 "invalid data symbol offset: `" +
Info.Name +
"` (offset: " +
740 return make_error<GenericBinaryError>(
741 "section symbols must have local binding",
752 if (!isValidTagIndex(
Info.ElementIndex) ||
753 IsDefined != isDefinedTagIndex(
Info.ElementIndex))
754 return make_error<GenericBinaryError>(
"invalid tag symbol index",
758 return make_error<GenericBinaryError>(
"undefined weak global symbol",
762 unsigned TagIndex =
Info.ElementIndex - NumImportedTags;
764 Signature = &Signatures[
Tag.SigIndex];
765 if (
Tag.SymbolName.empty())
776 Signature = &Signatures[
Import.SigIndex];
783 return make_error<GenericBinaryError>(
"invalid symbol type: " +
791 return make_error<GenericBinaryError>(
"duplicate symbol name " +
795 Symbols.emplace_back(LinkingData.
SymbolTable.back(), GlobalType, TableType,
797 LLVM_DEBUG(
dbgs() <<
"Adding symbol: " << Symbols.back() <<
"\n");
803Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
806 for (
unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
809 return make_error<GenericBinaryError>(
"bad/duplicate COMDAT name " +
815 return make_error<GenericBinaryError>(
"unsupported COMDAT flags",
819 while (EntryCount--) {
824 return make_error<GenericBinaryError>(
"invalid COMDAT entry type",
827 if (
Index >= DataSegments.size())
828 return make_error<GenericBinaryError>(
830 if (DataSegments[
Index].
Data.Comdat != UINT32_MAX)
831 return make_error<GenericBinaryError>(
"data segment in two COMDATs",
833 DataSegments[
Index].Data.Comdat = ComdatIndex;
836 if (!isDefinedFunctionIndex(
Index))
837 return make_error<GenericBinaryError>(
839 if (getDefinedFunction(
Index).
Comdat != UINT32_MAX)
840 return make_error<GenericBinaryError>(
"function in two COMDATs",
845 if (
Index >= Sections.size())
846 return make_error<GenericBinaryError>(
849 return make_error<GenericBinaryError>(
851 Sections[
Index].Comdat = ComdatIndex;
859Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
862 for (
size_t I = 0;
I < Fields; ++
I) {
864 if (!FieldsSeen.
insert(FieldName).second)
865 return make_error<GenericBinaryError>(
866 "producers section does not have unique fields",
868 std::vector<std::pair<std::string, std::string>> *ProducerVec =
nullptr;
869 if (FieldName ==
"language") {
871 }
else if (FieldName ==
"processed-by") {
872 ProducerVec = &ProducerInfo.
Tools;
873 }
else if (FieldName ==
"sdk") {
874 ProducerVec = &ProducerInfo.
SDKs;
876 return make_error<GenericBinaryError>(
877 "producers section field is not named one of language, processed-by, "
883 for (
size_t J = 0; J < ValueCount; ++J) {
887 return make_error<GenericBinaryError>(
888 "producers section contains repeated producer",
891 ProducerVec->emplace_back(std::string(
Name), std::string(Version));
894 if (Ctx.Ptr != Ctx.End)
895 return make_error<GenericBinaryError>(
"producers section ended prematurely",
900Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
912 return make_error<GenericBinaryError>(
"unknown feature policy prefix",
916 if (!FeaturesSeen.
insert(Feature.
Name).second)
917 return make_error<GenericBinaryError>(
918 "target features section contains repeated feature \"" +
921 TargetFeatures.push_back(Feature);
923 if (Ctx.Ptr != Ctx.End)
924 return make_error<GenericBinaryError>(
925 "target features section ended prematurely",
932 if (SectionIndex >= Sections.size())
933 return make_error<GenericBinaryError>(
"invalid section index",
939 while (RelocCount--) {
944 if (Reloc.
Offset < PreviousOffset)
945 return make_error<GenericBinaryError>(
"relocations not in offset order",
947 PreviousOffset = Reloc.
Offset;
950 case wasm::R_WASM_FUNCTION_INDEX_LEB:
951 case wasm::R_WASM_TABLE_INDEX_SLEB:
952 case wasm::R_WASM_TABLE_INDEX_SLEB64:
953 case wasm::R_WASM_TABLE_INDEX_I32:
954 case wasm::R_WASM_TABLE_INDEX_I64:
955 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
956 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
957 if (!isValidFunctionSymbol(Reloc.
Index))
958 return make_error<GenericBinaryError>(
961 case wasm::R_WASM_TABLE_NUMBER_LEB:
962 if (!isValidTableSymbol(Reloc.
Index))
963 return make_error<GenericBinaryError>(
"invalid relocation table index",
966 case wasm::R_WASM_TYPE_INDEX_LEB:
967 if (Reloc.
Index >= Signatures.size())
968 return make_error<GenericBinaryError>(
"invalid relocation type index",
971 case wasm::R_WASM_GLOBAL_INDEX_LEB:
974 if (!isValidGlobalSymbol(Reloc.
Index) &&
975 !isValidDataSymbol(Reloc.
Index) &&
976 !isValidFunctionSymbol(Reloc.
Index))
977 return make_error<GenericBinaryError>(
"invalid relocation global index",
980 case wasm::R_WASM_GLOBAL_INDEX_I32:
981 if (!isValidGlobalSymbol(Reloc.
Index))
982 return make_error<GenericBinaryError>(
"invalid relocation global index",
985 case wasm::R_WASM_TAG_INDEX_LEB:
986 if (!isValidTagSymbol(Reloc.
Index))
987 return make_error<GenericBinaryError>(
"invalid relocation tag index",
990 case wasm::R_WASM_MEMORY_ADDR_LEB:
991 case wasm::R_WASM_MEMORY_ADDR_SLEB:
992 case wasm::R_WASM_MEMORY_ADDR_I32:
993 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
994 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
995 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
996 if (!isValidDataSymbol(Reloc.
Index))
997 return make_error<GenericBinaryError>(
"invalid relocation data index",
1001 case wasm::R_WASM_MEMORY_ADDR_LEB64:
1002 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1003 case wasm::R_WASM_MEMORY_ADDR_I64:
1004 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1005 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1006 if (!isValidDataSymbol(Reloc.
Index))
1007 return make_error<GenericBinaryError>(
"invalid relocation data index",
1011 case wasm::R_WASM_FUNCTION_OFFSET_I32:
1012 if (!isValidFunctionSymbol(Reloc.
Index))
1013 return make_error<GenericBinaryError>(
1017 case wasm::R_WASM_FUNCTION_OFFSET_I64:
1018 if (!isValidFunctionSymbol(Reloc.
Index))
1019 return make_error<GenericBinaryError>(
1023 case wasm::R_WASM_SECTION_OFFSET_I32:
1024 if (!isValidSectionSymbol(Reloc.
Index))
1025 return make_error<GenericBinaryError>(
1030 return make_error<GenericBinaryError>(
"invalid relocation type: " +
1039 if (Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1040 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1041 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1043 if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1044 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1045 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1046 Reloc.
Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1047 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1048 Reloc.
Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1050 if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1051 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1052 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1055 return make_error<GenericBinaryError>(
"invalid relocation offset",
1058 Section.Relocations.push_back(Reloc);
1060 if (Ctx.Ptr != Ctx.End)
1061 return make_error<GenericBinaryError>(
"reloc section ended prematurely",
1066Error WasmObjectFile::parseCustomSection(
WasmSection &Sec, ReadContext &Ctx) {
1067 if (Sec.
Name ==
"dylink") {
1068 if (
Error Err = parseDylinkSection(Ctx))
1070 }
else if (Sec.
Name ==
"dylink.0") {
1071 if (
Error Err = parseDylink0Section(Ctx))
1073 }
else if (Sec.
Name ==
"name") {
1074 if (
Error Err = parseNameSection(Ctx))
1076 }
else if (Sec.
Name ==
"linking") {
1077 if (
Error Err = parseLinkingSection(Ctx))
1079 }
else if (Sec.
Name ==
"producers") {
1080 if (
Error Err = parseProducersSection(Ctx))
1082 }
else if (Sec.
Name ==
"target_features") {
1083 if (
Error Err = parseTargetFeaturesSection(Ctx))
1086 if (
Error Err = parseRelocSection(Sec.
Name, Ctx))
1092Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1094 Signatures.reserve(Count);
1099 return make_error<GenericBinaryError>(
"invalid signature type",
1104 while (ParamCount--) {
1109 while (ReturnCount--) {
1113 Signatures.push_back(std::move(Sig));
1115 if (Ctx.Ptr != Ctx.End)
1116 return make_error<GenericBinaryError>(
"type section ended prematurely",
1121Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1123 uint32_t NumTypes = Signatures.size();
1124 Imports.reserve(Count);
1132 NumImportedFunctions++;
1135 return make_error<GenericBinaryError>(
"invalid function type",
1139 NumImportedGlobals++;
1150 NumImportedTables++;
1154 return make_error<GenericBinaryError>(
"invalid table element type",
1161 return make_error<GenericBinaryError>(
"invalid attribute",
1165 return make_error<GenericBinaryError>(
"invalid tag type",
1169 return make_error<GenericBinaryError>(
"unexpected import kind",
1172 Imports.push_back(Im);
1174 if (Ctx.Ptr != Ctx.End)
1175 return make_error<GenericBinaryError>(
"import section ended prematurely",
1180Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1182 Functions.reserve(Count);
1183 uint32_t NumTypes = Signatures.size();
1186 if (
Type >= NumTypes)
1187 return make_error<GenericBinaryError>(
"invalid function type",
1191 Functions.push_back(
F);
1193 if (Ctx.Ptr != Ctx.End)
1194 return make_error<GenericBinaryError>(
"function section ended prematurely",
1199Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1200 TableSection = Sections.size();
1202 Tables.reserve(Count);
1206 T.Index = NumImportedTables + Tables.size();
1207 Tables.push_back(
T);
1208 auto ElemType = Tables.back().Type.ElemType;
1211 return make_error<GenericBinaryError>(
"invalid table element type",
1215 if (Ctx.Ptr != Ctx.End)
1216 return make_error<GenericBinaryError>(
"table section ended prematurely",
1221Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1223 Memories.reserve(Count);
1228 Memories.push_back(Limits);
1230 if (Ctx.Ptr != Ctx.End)
1231 return make_error<GenericBinaryError>(
"memory section ended prematurely",
1236Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1237 TagSection = Sections.size();
1239 Tags.reserve(Count);
1240 uint32_t NumTypes = Signatures.size();
1243 return make_error<GenericBinaryError>(
"invalid attribute",
1246 if (
Type >= NumTypes)
1247 return make_error<GenericBinaryError>(
"invalid tag type",
1250 Tag.Index = NumImportedTags + Tags.size();
1252 Tags.push_back(
Tag);
1255 if (Ctx.Ptr != Ctx.End)
1256 return make_error<GenericBinaryError>(
"tag section ended prematurely",
1261Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1262 GlobalSection = Sections.size();
1264 Globals.reserve(Count);
1267 Global.Index = NumImportedGlobals + Globals.size();
1272 Globals.push_back(
Global);
1274 if (Ctx.Ptr != Ctx.End)
1275 return make_error<GenericBinaryError>(
"global section ended prematurely",
1280Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1282 Exports.reserve(Count);
1291 if (!isDefinedFunctionIndex(Ex.
Index))
1292 return make_error<GenericBinaryError>(
"invalid function export",
1297 if (!isValidGlobalIndex(Ex.
Index))
1298 return make_error<GenericBinaryError>(
"invalid global export",
1302 if (!isValidTagIndex(Ex.
Index))
1303 return make_error<GenericBinaryError>(
"invalid tag export",
1310 return make_error<GenericBinaryError>(
"unexpected export kind",
1313 Exports.push_back(Ex);
1315 if (Ctx.Ptr != Ctx.End)
1316 return make_error<GenericBinaryError>(
"export section ended prematurely",
1321bool WasmObjectFile::isValidFunctionIndex(
uint32_t Index)
const {
1322 return Index < NumImportedFunctions + Functions.size();
1325bool WasmObjectFile::isDefinedFunctionIndex(
uint32_t Index)
const {
1326 return Index >= NumImportedFunctions && isValidFunctionIndex(
Index);
1329bool WasmObjectFile::isValidGlobalIndex(
uint32_t Index)
const {
1330 return Index < NumImportedGlobals + Globals.size();
1333bool WasmObjectFile::isValidTableNumber(
uint32_t Index)
const {
1334 return Index < NumImportedTables + Tables.size();
1337bool WasmObjectFile::isDefinedGlobalIndex(
uint32_t Index)
const {
1338 return Index >= NumImportedGlobals && isValidGlobalIndex(
Index);
1341bool WasmObjectFile::isDefinedTableNumber(
uint32_t Index)
const {
1342 return Index >= NumImportedTables && isValidTableNumber(
Index);
1346 return Index < NumImportedTags + Tags.size();
1349bool WasmObjectFile::isDefinedTagIndex(
uint32_t Index)
const {
1350 return Index >= NumImportedTags && isValidTagIndex(
Index);
1353bool WasmObjectFile::isValidFunctionSymbol(
uint32_t Index)
const {
1354 return Index < Symbols.size() && Symbols[
Index].isTypeFunction();
1357bool WasmObjectFile::isValidTableSymbol(
uint32_t Index)
const {
1358 return Index < Symbols.size() && Symbols[
Index].isTypeTable();
1361bool WasmObjectFile::isValidGlobalSymbol(
uint32_t Index)
const {
1362 return Index < Symbols.size() && Symbols[
Index].isTypeGlobal();
1365bool WasmObjectFile::isValidTagSymbol(
uint32_t Index)
const {
1366 return Index < Symbols.size() && Symbols[
Index].isTypeTag();
1369bool WasmObjectFile::isValidDataSymbol(
uint32_t Index)
const {
1370 return Index < Symbols.size() && Symbols[
Index].isTypeData();
1373bool WasmObjectFile::isValidSectionSymbol(
uint32_t Index)
const {
1374 return Index < Symbols.size() && Symbols[
Index].isTypeSection();
1379 return Functions[
Index - NumImportedFunctions];
1385 return Functions[
Index - NumImportedFunctions];
1390 return Globals[
Index - NumImportedGlobals];
1395 return Tags[
Index - NumImportedTags];
1398Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1400 if (!isValidFunctionIndex(StartFunction))
1401 return make_error<GenericBinaryError>(
"invalid start function",
1406Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1407 CodeSection = Sections.size();
1409 if (FunctionCount != Functions.size()) {
1410 return make_error<GenericBinaryError>(
"invalid function count",
1414 for (
uint32_t i = 0; i < FunctionCount; i++) {
1416 const uint8_t *FunctionStart = Ctx.Ptr;
1418 const uint8_t *FunctionEnd = Ctx.Ptr +
Size;
1420 Function.CodeOffset = Ctx.Ptr - FunctionStart;
1421 Function.Index = NumImportedFunctions + i;
1422 Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1423 Function.Size = FunctionEnd - FunctionStart;
1426 Function.Locals.reserve(NumLocalDecls);
1427 while (NumLocalDecls--) {
1434 uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1438 Ctx.Ptr += BodySize;
1439 assert(Ctx.Ptr == FunctionEnd);
1441 if (Ctx.Ptr != Ctx.End)
1442 return make_error<GenericBinaryError>(
"code section ended prematurely",
1447Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1449 ElemSegments.reserve(Count);
1457 if (Segment.
Flags & ~SupportedFlags)
1458 return make_error<GenericBinaryError>(
1466 return make_error<GenericBinaryError>(
"invalid TableNumber",
1483 return make_error<GenericBinaryError>(
"invalid reference type",
1488 return make_error<GenericBinaryError>(
"invalid elemtype",
1497 return make_error<GenericBinaryError>(
1498 "elem segment init expressions not yet implemented",
1502 while (NumElems--) {
1505 ElemSegments.push_back(Segment);
1507 if (Ctx.Ptr != Ctx.End)
1508 return make_error<GenericBinaryError>(
"elem section ended prematurely",
1513Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1514 DataSection = Sections.size();
1516 if (DataCount && Count != *DataCount)
1517 return make_error<GenericBinaryError>(
1518 "number of data segments does not match DataCount section");
1519 DataSegments.reserve(Count);
1536 if (
Size > (
size_t)(Ctx.End - Ctx.Ptr))
1537 return make_error<GenericBinaryError>(
"invalid segment size",
1547 DataSegments.push_back(Segment);
1549 if (Ctx.Ptr != Ctx.End)
1550 return make_error<GenericBinaryError>(
"data section ended prematurely",
1555Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1571 if (
Sym.isBindingWeak())
1573 if (!
Sym.isBindingLocal())
1577 if (!
Sym.isDefined())
1579 if (
Sym.isTypeFunction())
1594 Ref.d.b = Symbols.size();
1599 return Symbols[Symb.
d.
b];
1613 isDefinedFunctionIndex(
Sym.Info.ElementIndex))
1620 switch (
Sym.Info.Kind) {
1625 return Sym.Info.ElementIndex;
1665 switch (
Sym.Info.Kind) {
1687 if (
Sym.isUndefined())
1691 Ref.d.a = getSymbolSectionIdImpl(
Sym);
1697 return getSymbolSectionIdImpl(
Sym);
1701 switch (
Sym.Info.Kind) {
1705 return GlobalSection;
1709 return Sym.Info.ElementIndex;
1713 return TableSection;
1771 RelocRef.
d.
a =
Ref.d.a;
1779 RelocRef.
d.
a =
Ref.d.a;
1793 if (Rel.
Type == wasm::R_WASM_TYPE_INDEX_LEB)
1811#define WASM_RELOC(name, value) \
1817#include "llvm/BinaryFormat/WasmRelocs.def"
1822 Result.append(Res.
begin(), Res.
end());
1833 Ref.d.a = Sections.size();
1838 return HasMemory64 ? 8 : 4;
1857 return Sections[
Ref.d.a];
1878int WasmSectionOrderChecker::getSectionOrder(
unsigned ID,
1926 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
1930 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
1932 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
1934 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
1936 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
1938 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
1940 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
1942 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
1944 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
1946 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
1948 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
1950 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
1952 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
1954 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
1958 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
1960 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
1964 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
1966 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
1968 {WASM_SEC_ORDER_TARGET_FEATURES}};
1972 int Order = getSectionOrder(
ID, CustomSectionName);
1985 for (
size_t I = 0;; ++
I) {
1992 Checked[Next] =
true;
1995 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 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.
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).
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
bool startswith(StringRef Prefix) const
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
bool isSharedObject() const
const wasm::WasmRelocation & getWasmRelocation(const RelocationRef &Ref) 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="")
static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]
@ WASM_SEC_ORDER_TARGET_FEATURES
@ WASM_SEC_ORDER_PRODUCERS
@ WASM_SEC_ORDER_DATACOUNT
@ WASM_SEC_ORDER_FUNCTION
unsigned getBinding() const
LLVM_DUMP_METHOD void dump() const
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_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
@ WASM_LIMITS_FLAG_HAS_MAX
@ WASM_DYLINK_EXPORT_INFO
@ WASM_DYLINK_IMPORT_INFO
const unsigned WASM_SYMBOL_BINDING_GLOBAL
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
@ WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
@ WASM_ELEM_SEGMENT_IS_PASSIVE
const uint32_t WasmMetadataVersion
const unsigned WASM_SYMBOL_BINDING_WEAK
const unsigned WASM_SYMBOL_BINDING_LOCAL
@ WASM_FEATURE_PREFIX_USED
@ WASM_FEATURE_PREFIX_REQUIRED
@ WASM_FEATURE_PREFIX_DISALLOWED
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_FUNCTION
const uint32_t WasmVersion
@ WASM_NAMES_DATA_SEGMENT
const unsigned WASM_SYMBOL_BINDING_MASK
llvm::StringRef sectionTypeToString(uint32_t type)
const unsigned WASM_SYMBOL_EXPLICIT_NAME
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::@176 Value
std::vector< WasmSymbolInfo > SymbolTable
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
WasmDataReference DataRef
struct llvm::object::DataRefImpl::@339 d