1//===- WasmObjectFile.cpp - Wasm object file implementation ---------------===// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7//===----------------------------------------------------------------------===// 32#define DEBUG_TYPE "wasm-object" 61#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 68autoObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
75#define VARINT7_MAX ((1 << 7) - 1) 76#define VARINT7_MIN (-(1 << 7)) 77#define VARUINT7_MAX (1 << 7) 78#define VARUINT1_MAX (1) 98 memcpy(&Result, Ctx.
Ptr,
sizeof(Result));
99 Ctx.
Ptr +=
sizeof(Result);
107 memcpy(&Result, Ctx.
Ptr,
sizeof(Result));
108 Ctx.
Ptr +=
sizeof(Result);
114constchar *
Error =
nullptr;
124if (Ctx.
Ptr + StringLen > Ctx.
End)
127StringRef(
reinterpret_cast<constchar *
>(Ctx.
Ptr), StringLen);
128 Ctx.
Ptr += StringLen;
134constchar *
Error =
nullptr;
151if (Result > INT32_MAX || Result < INT32_MIN)
158if (Result > UINT32_MAX)
177// only directly encoded FUNCREF/EXTERNREF/EXNREF are supported 178// (not ref null func, ref null extern, or ref null exn) 259// The GC opcodes are in a separate (prefixed space). This flat switch 260// structure works as long as there is no overlap between the GC and 261// general opcodes used in init exprs. 278return make_error<GenericBinaryError>(
279Twine(
"invalid opcode in init_expr: ") +
Twine(
unsigned(Opcode)),
309// When reading the section's size, store the size of the LEB used to encode 310// it. This allows objcopy/strip to reproduce the binary identically. 313 Section.HeaderSecSizeEncodingLen = Ctx.
Ptr - PreSizePtr;
314 Section.Offset = Ctx.
Ptr - Ctx.
Start;
316return make_error<StringError>(
"zero length section",
319return make_error<StringError>(
"section too large",
330 Ctx.
Ptr += SectionNameSize;
331Size -= SectionNameSize;
334if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
335return make_error<StringError>(
"out of order section type: " +
350 Err = make_error<StringError>(
"invalid magic number",
360if (Ctx.
Ptr + 4 > Ctx.
End) {
361 Err = make_error<StringError>(
"missing version number",
368 Err = make_error<StringError>(
"invalid version number: " +
375while (Ctx.
Ptr < Ctx.
End) {
379if ((Err = parseSection(Sec)))
382 Sections.push_back(Sec);
393return parseCustomSection(Sec, Ctx);
395return parseTypeSection(Ctx);
397return parseImportSection(Ctx);
399return parseFunctionSection(Ctx);
401return parseTableSection(Ctx);
403return parseMemorySection(Ctx);
405return parseTagSection(Ctx);
407return parseGlobalSection(Ctx);
409return parseExportSection(Ctx);
411return parseStartSection(Ctx);
413return parseElemSection(Ctx);
415return parseCodeSection(Ctx);
417return parseDataSection(Ctx);
419return parseDataCountSection(Ctx);
421return make_error<GenericBinaryError>(
426Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
427// Legacy "dylink" section support. 428// See parseDylink0Section for the current "dylink.0" section parsing. 429 HasDylinkSection =
true;
439if (Ctx.Ptr != Ctx.End)
440return make_error<GenericBinaryError>(
"dylink section ended prematurely",
445Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
447// https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md 448 HasDylinkSection =
true;
450constuint8_t *OrigEnd = Ctx.End;
451while (Ctx.Ptr < OrigEnd) {
457 Ctx.End = Ctx.Ptr +
Size;
492if (Ctx.Ptr != Ctx.End) {
493return make_error<GenericBinaryError>(
498if (Ctx.Ptr != Ctx.End)
499return make_error<GenericBinaryError>(
"dylink.0 section ended prematurely",
504Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
509// If we have linking section (symbol table) or if we are parsing a DSO 510// then we don't use the name section for symbol information. 511bool PopulateSymbolTable = !HasLinkingSection && !HasDylinkSection;
513// If we are using the name section for symbol information then it will 514// supersede any symbols created by the export section. 515if (PopulateSymbolTable)
518while (Ctx.Ptr < Ctx.End) {
535/* ImportModule */ std::nullopt,
536/* ImportName */ std::nullopt,
537/* ExportName */ std::nullopt,
538 {
/* ElementIndex */Index}};
543if (!SeenFunctions.
insert(Index).second)
544return make_error<GenericBinaryError>(
546if (!isValidFunctionIndex(Index) ||
Name.empty())
547return make_error<GenericBinaryError>(
"invalid function name entry",
550if (isDefinedFunctionIndex(Index)) {
553 Signature = &Signatures[
F.SigIndex];
555Info.ExportName =
F.ExportName;
564if (!SeenGlobals.
insert(Index).second)
565return make_error<GenericBinaryError>(
"global named more than once",
567if (!isValidGlobalIndex(Index) ||
Name.empty())
568return make_error<GenericBinaryError>(
"invalid global name entry",
572if (isDefinedGlobalIndex(Index)) {
573 GlobalType = &getDefinedGlobal(Index).
Type;
578if (!SeenSegments.
insert(Index).second)
579return make_error<GenericBinaryError>(
581if (Index > DataSegments.size())
582return make_error<GenericBinaryError>(
"invalid data segment name entry",
587assert(Index < DataSegments.size());
589Index, 0, DataSegments[
Index].Data.Content.size()};
592if (PopulateSymbolTable)
593 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
597// Ignore local names for now 603if (Ctx.Ptr != SubSectionEnd)
604return make_error<GenericBinaryError>(
608if (Ctx.Ptr != Ctx.End)
609return make_error<GenericBinaryError>(
"name section ended prematurely",
614Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
615 HasLinkingSection =
true;
619return make_error<GenericBinaryError>(
620"unexpected metadata version: " +
Twine(LinkingData.
Version) +
625constuint8_t *OrigEnd = Ctx.End;
626while (Ctx.Ptr < OrigEnd) {
632 Ctx.End = Ctx.Ptr +
Size;
635if (
Error Err = parseLinkingSectionSymtab(Ctx))
640if (Count > DataSegments.size())
641return make_error<GenericBinaryError>(
"too many segment names",
657if (!isValidFunctionSymbol(
Init.Symbol))
658return make_error<GenericBinaryError>(
"invalid function symbol: " +
666if (
Error Err = parseLinkingSectionComdat(Ctx))
673if (Ctx.Ptr != Ctx.End)
674return make_error<GenericBinaryError>(
677if (Ctx.Ptr != OrigEnd)
678return make_error<GenericBinaryError>(
"linking section ended prematurely",
683Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
685// Clear out any symbol information that was derived from the exports 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());
699for (
auto &
I : Imports) {
701 ImportedFunctions.emplace_back(&
I);
703 ImportedGlobals.emplace_back(&
I);
705 ImportedTags.emplace_back(&
I);
707 ImportedTables.emplace_back(&
I);
723if (!isValidFunctionIndex(
Info.ElementIndex) ||
724 IsDefined != isDefinedFunctionIndex(
Info.ElementIndex))
725return make_error<GenericBinaryError>(
"invalid function symbol index",
729unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
731 Signature = &Signatures[
Function.SigIndex];
742 Signature = &Signatures[
Import.SigIndex];
749if (!isValidGlobalIndex(
Info.ElementIndex) ||
750 IsDefined != isDefinedGlobalIndex(
Info.ElementIndex))
751return make_error<GenericBinaryError>(
"invalid global symbol index",
755return make_error<GenericBinaryError>(
"undefined weak global symbol",
759unsigned GlobalIndex =
Info.ElementIndex - NumImportedGlobals;
761 GlobalType = &
Global.Type;
762if (
Global.SymbolName.empty())
772 GlobalType = &
Import.Global;
779if (!isValidTableNumber(
Info.ElementIndex) ||
780 IsDefined != isDefinedTableNumber(
Info.ElementIndex))
781return make_error<GenericBinaryError>(
"invalid table symbol index",
785return make_error<GenericBinaryError>(
"undefined weak table symbol",
789unsigned TableNumber =
Info.ElementIndex - NumImportedTables;
791 TableType = &Table.
Type;
802 TableType = &
Import.Table;
814if (
static_cast<size_t>(Index) >= DataSegments.size())
815return make_error<GenericBinaryError>(
816"invalid data segment index: " +
Twine(Index),
818size_t SegmentSize = DataSegments[
Index].Data.Content.size();
820return make_error<GenericBinaryError>(
821"invalid data symbol offset: `" +
Info.Name +
823" segment size: " +
Twine(SegmentSize) +
")",
833return make_error<GenericBinaryError>(
834"section symbols must have local binding",
837// Use somewhat unique section name as symbol name. 845if (!isValidTagIndex(
Info.ElementIndex) ||
846 IsDefined != isDefinedTagIndex(
Info.ElementIndex))
847return make_error<GenericBinaryError>(
"invalid tag symbol index",
851return make_error<GenericBinaryError>(
"undefined weak global symbol",
855unsigned TagIndex =
Info.ElementIndex - NumImportedTags;
857 Signature = &Signatures[
Tag.SigIndex];
858if (
Tag.SymbolName.empty())
869 Signature = &Signatures[
Import.SigIndex];
876return make_error<GenericBinaryError>(
"invalid symbol type: " +
884return make_error<GenericBinaryError>(
"duplicate symbol name " +
887 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
894Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
897for (
unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
900return make_error<GenericBinaryError>(
"bad/duplicate COMDAT name " +
906return make_error<GenericBinaryError>(
"unsupported COMDAT flags",
910while (EntryCount--) {
915return make_error<GenericBinaryError>(
"invalid COMDAT entry type",
918if (Index >= DataSegments.size())
919return make_error<GenericBinaryError>(
921if (DataSegments[Index].
Data.Comdat != UINT32_MAX)
922return make_error<GenericBinaryError>(
"data segment in two COMDATs",
924 DataSegments[
Index].Data.Comdat = ComdatIndex;
927if (!isDefinedFunctionIndex(Index))
928return make_error<GenericBinaryError>(
930if (getDefinedFunction(Index).
Comdat != UINT32_MAX)
931return make_error<GenericBinaryError>(
"function in two COMDATs",
933 getDefinedFunction(Index).
Comdat = ComdatIndex;
936if (Index >= Sections.size())
937return make_error<GenericBinaryError>(
940return make_error<GenericBinaryError>(
942 Sections[
Index].Comdat = ComdatIndex;
950Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
953for (
size_tI = 0;
I < Fields; ++
I) {
955if (!FieldsSeen.
insert(FieldName).second)
956return make_error<GenericBinaryError>(
957"producers section does not have unique fields",
959 std::vector<std::pair<std::string, std::string>> *ProducerVec =
nullptr;
960if (FieldName ==
"language") {
962 }
elseif (FieldName ==
"processed-by") {
963 ProducerVec = &ProducerInfo.
Tools;
964 }
elseif (FieldName ==
"sdk") {
965 ProducerVec = &ProducerInfo.
SDKs;
967return make_error<GenericBinaryError>(
968"producers section field is not named one of language, processed-by, " 974for (
size_t J = 0; J < ValueCount; ++J) {
978return make_error<GenericBinaryError>(
979"producers section contains repeated producer",
982 ProducerVec->emplace_back(std::string(
Name), std::string(
Version));
985if (Ctx.Ptr != Ctx.End)
986return make_error<GenericBinaryError>(
"producers section ended prematurely",
991Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
1002return make_error<GenericBinaryError>(
"unknown feature policy prefix",
1006if (!FeaturesSeen.
insert(Feature.
Name).second)
1007return make_error<GenericBinaryError>(
1008"target features section contains repeated feature \"" +
1011 TargetFeatures.push_back(Feature);
1013if (Ctx.Ptr != Ctx.End)
1014return make_error<GenericBinaryError>(
1015"target features section ended prematurely",
1022if (SectionIndex >= Sections.size())
1023return make_error<GenericBinaryError>(
"invalid section index",
1029while (RelocCount--) {
1034if (Reloc.
Offset < PreviousOffset)
1035return make_error<GenericBinaryError>(
"relocations not in offset order",
1039return make_error<GenericBinaryError>(
1040 msg +
": " +
Twine(Symbols[Reloc.
Index].Info.Name),
1044 PreviousOffset = Reloc.
Offset;
1047case wasm::R_WASM_FUNCTION_INDEX_LEB:
1048case wasm::R_WASM_FUNCTION_INDEX_I32:
1049case wasm::R_WASM_TABLE_INDEX_SLEB:
1050case wasm::R_WASM_TABLE_INDEX_SLEB64:
1051case wasm::R_WASM_TABLE_INDEX_I32:
1052case wasm::R_WASM_TABLE_INDEX_I64:
1053case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
1054case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
1055if (!isValidFunctionSymbol(Reloc.
Index))
1056return badReloc(
"invalid function relocation");
1058case wasm::R_WASM_TABLE_NUMBER_LEB:
1059if (!isValidTableSymbol(Reloc.
Index))
1060return badReloc(
"invalid table relocation");
1062case wasm::R_WASM_TYPE_INDEX_LEB:
1063if (Reloc.
Index >= Signatures.size())
1064return badReloc(
"invalid relocation type index");
1066case wasm::R_WASM_GLOBAL_INDEX_LEB:
1067// R_WASM_GLOBAL_INDEX_LEB are can be used against function and data 1068// symbols to refer to their GOT entries. 1069if (!isValidGlobalSymbol(Reloc.
Index) &&
1070 !isValidDataSymbol(Reloc.
Index) &&
1071 !isValidFunctionSymbol(Reloc.
Index))
1072return badReloc(
"invalid global relocation");
1074case wasm::R_WASM_GLOBAL_INDEX_I32:
1075if (!isValidGlobalSymbol(Reloc.
Index))
1076return badReloc(
"invalid global relocation");
1078case wasm::R_WASM_TAG_INDEX_LEB:
1079if (!isValidTagSymbol(Reloc.
Index))
1080return badReloc(
"invalid tag relocation");
1082case wasm::R_WASM_MEMORY_ADDR_LEB:
1083case wasm::R_WASM_MEMORY_ADDR_SLEB:
1084case wasm::R_WASM_MEMORY_ADDR_I32:
1085case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1086case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1087case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1088if (!isValidDataSymbol(Reloc.
Index))
1089return badReloc(
"invalid data relocation");
1092case wasm::R_WASM_MEMORY_ADDR_LEB64:
1093case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1094case wasm::R_WASM_MEMORY_ADDR_I64:
1095case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1096case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1097if (!isValidDataSymbol(Reloc.
Index))
1098return badReloc(
"invalid data relocation");
1101case wasm::R_WASM_FUNCTION_OFFSET_I32:
1102if (!isValidFunctionSymbol(Reloc.
Index))
1103return badReloc(
"invalid function relocation");
1106case wasm::R_WASM_FUNCTION_OFFSET_I64:
1107if (!isValidFunctionSymbol(Reloc.
Index))
1108return badReloc(
"invalid function relocation");
1111case wasm::R_WASM_SECTION_OFFSET_I32:
1112if (!isValidSectionSymbol(Reloc.
Index))
1113return badReloc(
"invalid section relocation");
1117return make_error<GenericBinaryError>(
"invalid relocation type: " +
1122// Relocations must fit inside the section, and must appear in order. They 1123// also shouldn't overlap a function/element boundary, but we don't bother 1126if (Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1127 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1128 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1130if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1131 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1132 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1133 Reloc.
Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1134 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1135 Reloc.
Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
1136 Reloc.
Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1138if (Reloc.
Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1139 Reloc.
Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1140 Reloc.
Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1143return make_error<GenericBinaryError>(
"invalid relocation offset",
1146Section.Relocations.push_back(Reloc);
1148if (Ctx.Ptr != Ctx.End)
1149return make_error<GenericBinaryError>(
"reloc section ended prematurely",
1154Error WasmObjectFile::parseCustomSection(
WasmSection &Sec, ReadContext &Ctx) {
1155if (Sec.
Name ==
"dylink") {
1156if (
Error Err = parseDylinkSection(Ctx))
1158 }
elseif (Sec.
Name ==
"dylink.0") {
1159if (
Error Err = parseDylink0Section(Ctx))
1161 }
elseif (Sec.
Name ==
"name") {
1162if (
Error Err = parseNameSection(Ctx))
1164 }
elseif (Sec.
Name ==
"linking") {
1165if (
Error Err = parseLinkingSection(Ctx))
1167 }
elseif (Sec.
Name ==
"producers") {
1168if (
Error Err = parseProducersSection(Ctx))
1170 }
elseif (Sec.
Name ==
"target_features") {
1171if (
Error Err = parseTargetFeaturesSection(Ctx))
1174if (
Error Err = parseRelocSection(Sec.
Name, Ctx))
1180Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1181auto parseFieldDef = [&]() {
1188 Signatures.reserve(Count);
1193// Rec groups expand the type index space (beyond what was declared at 1194// the top of the section, and also consume one element in that space. 1197return make_error<GenericBinaryError>(
"Rec group size cannot be 0",
1199 Signatures.reserve(Signatures.size() + RecSize);
1202 Signatures.push_back(std::move(Sig));
1203 HasUnmodeledTypes =
true;
1207// Currently LLVM only models function types, and not other composite 1208// types. Here we parse the type declarations just enough to skip past 1209// them in the binary. 1214return make_error<GenericBinaryError>(
1222while (FieldCount--) {
1228return make_error<GenericBinaryError>(
"bad form",
1232 Signatures.push_back(std::move(Sig));
1233 HasUnmodeledTypes =
true;
1239while (ParamCount--) {
1244while (ReturnCount--) {
1249 Signatures.push_back(std::move(Sig));
1251if (Ctx.Ptr != Ctx.End)
1252return make_error<GenericBinaryError>(
"type section ended prematurely",
1257Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1259uint32_t NumTypes = Signatures.size();
1260 Imports.reserve(Count);
1268 NumImportedFunctions++;
1271return make_error<GenericBinaryError>(
"invalid function type",
1275 NumImportedGlobals++;
1286 NumImportedTables++;
1292return make_error<GenericBinaryError>(
"invalid table element type",
1298if (
readUint8(Ctx) != 0)
// Reserved 'attribute' field 1299return make_error<GenericBinaryError>(
"invalid attribute",
1303return make_error<GenericBinaryError>(
"invalid tag type",
1307return make_error<GenericBinaryError>(
"unexpected import kind",
1310 Imports.push_back(Im);
1312if (Ctx.Ptr != Ctx.End)
1313return make_error<GenericBinaryError>(
"import section ended prematurely",
1318Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1320 Functions.reserve(Count);
1321uint32_t NumTypes = Signatures.size();
1324if (
Type >= NumTypes)
1325return make_error<GenericBinaryError>(
"invalid function type",
1329 Functions.push_back(
F);
1331if (Ctx.Ptr != Ctx.End)
1332return make_error<GenericBinaryError>(
"function section ended prematurely",
1337Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1338 TableSection = Sections.size();
1340 Tables.reserve(Count);
1344T.Index = NumImportedTables + Tables.size();
1345 Tables.push_back(
T);
1346auto ElemType = Tables.back().Type.ElemType;
1351return make_error<GenericBinaryError>(
"invalid table element type",
1355if (Ctx.Ptr != Ctx.End)
1356return make_error<GenericBinaryError>(
"table section ended prematurely",
1361Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1363 Memories.reserve(Count);
1368 Memories.push_back(Limits);
1370if (Ctx.Ptr != Ctx.End)
1371return make_error<GenericBinaryError>(
"memory section ended prematurely",
1376Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1377 TagSection = Sections.size();
1379 Tags.reserve(Count);
1380uint32_t NumTypes = Signatures.size();
1382if (
readUint8(Ctx) != 0)
// Reserved 'attribute' field 1383return make_error<GenericBinaryError>(
"invalid attribute",
1386if (
Type >= NumTypes)
1387return make_error<GenericBinaryError>(
"invalid tag type",
1390Tag.Index = NumImportedTags + Tags.size();
1393 Tags.push_back(
Tag);
1396if (Ctx.Ptr != Ctx.End)
1397return make_error<GenericBinaryError>(
"tag section ended prematurely",
1402Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1403 GlobalSection = Sections.size();
1404constuint8_t *SectionStart = Ctx.Ptr;
1406 Globals.reserve(Count);
1409Global.Index = NumImportedGlobals + Globals.size();
1410constuint8_t *GlobalStart = Ctx.Ptr;
1418 Globals.push_back(
Global);
1420if (Ctx.Ptr != Ctx.End)
1421return make_error<GenericBinaryError>(
"global section ended prematurely",
1426Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1428 Exports.reserve(Count);
1429 Symbols.reserve(Count);
1443if (!isValidFunctionIndex(Ex.
Index))
1444return make_error<GenericBinaryError>(
"invalid function export",
1448if (isDefinedFunctionIndex(Ex.
Index)) {
1450unsigned FuncIndex =
Info.ElementIndex - NumImportedFunctions;
1452 Signature = &Signatures[
Function.SigIndex];
1454// Else the function is imported. LLVM object files don't use this 1455// pattern and we still treat this as an undefined symbol, but we want to 1456// parse it without crashing. 1460if (!isValidGlobalIndex(Ex.
Index))
1461return make_error<GenericBinaryError>(
"invalid global export",
1465if (isDefinedGlobalIndex(Ex.
Index)) {
1467if (!
Global.InitExpr.Extended) {
1468auto Inst =
Global.InitExpr.Inst;
1470Offset = Inst.Value.Int32;
1472Offset = Inst.Value.Int64;
1480if (!isValidTagIndex(Ex.
Index))
1481return make_error<GenericBinaryError>(
"invalid tag export",
1493return make_error<GenericBinaryError>(
"unexpected export kind",
1496 Exports.push_back(Ex);
1498 Symbols.emplace_back(Info, GlobalType, TableType, Signature);
1502if (Ctx.Ptr != Ctx.End)
1503return make_error<GenericBinaryError>(
"export section ended prematurely",
1508bool WasmObjectFile::isValidFunctionIndex(
uint32_t Index)
const{
1509returnIndex < NumImportedFunctions + Functions.size();
1512bool WasmObjectFile::isDefinedFunctionIndex(
uint32_t Index)
const{
1513returnIndex >= NumImportedFunctions && isValidFunctionIndex(Index);
1516bool WasmObjectFile::isValidGlobalIndex(
uint32_t Index)
const{
1517returnIndex < NumImportedGlobals + Globals.size();
1520bool WasmObjectFile::isValidTableNumber(
uint32_t Index)
const{
1521returnIndex < NumImportedTables + Tables.size();
1524bool WasmObjectFile::isDefinedGlobalIndex(
uint32_t Index)
const{
1525returnIndex >= NumImportedGlobals && isValidGlobalIndex(Index);
1528bool WasmObjectFile::isDefinedTableNumber(
uint32_t Index)
const{
1529returnIndex >= NumImportedTables && isValidTableNumber(Index);
1532bool WasmObjectFile::isValidTagIndex(
uint32_t Index)
const{
1533returnIndex < NumImportedTags + Tags.size();
1536bool WasmObjectFile::isDefinedTagIndex(
uint32_t Index)
const{
1537returnIndex >= NumImportedTags && isValidTagIndex(Index);
1540bool WasmObjectFile::isValidFunctionSymbol(
uint32_t Index)
const{
1541returnIndex < Symbols.size() && Symbols[
Index].isTypeFunction();
1544bool WasmObjectFile::isValidTableSymbol(
uint32_t Index)
const{
1545returnIndex < Symbols.size() && Symbols[
Index].isTypeTable();
1548bool WasmObjectFile::isValidGlobalSymbol(
uint32_t Index)
const{
1549returnIndex < Symbols.size() && Symbols[
Index].isTypeGlobal();
1552bool WasmObjectFile::isValidTagSymbol(
uint32_t Index)
const{
1553returnIndex < Symbols.size() && Symbols[
Index].isTypeTag();
1556bool WasmObjectFile::isValidDataSymbol(
uint32_t Index)
const{
1557returnIndex < Symbols.size() && Symbols[
Index].isTypeData();
1560bool WasmObjectFile::isValidSectionSymbol(
uint32_t Index)
const{
1561returnIndex < Symbols.size() && Symbols[
Index].isTypeSection();
1565assert(isDefinedFunctionIndex(Index));
1566return Functions[
Index - NumImportedFunctions];
1570WasmObjectFile::getDefinedFunction(
uint32_t Index)
const{
1571assert(isDefinedFunctionIndex(Index));
1572return Functions[
Index - NumImportedFunctions];
1576assert(isDefinedGlobalIndex(Index));
1577return Globals[
Index - NumImportedGlobals];
1581assert(isDefinedTagIndex(Index));
1582return Tags[
Index - NumImportedTags];
1585Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1587if (!isValidFunctionIndex(StartFunction))
1588return make_error<GenericBinaryError>(
"invalid start function",
1593Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1594 CodeSection = Sections.size();
1596if (FunctionCount != Functions.size()) {
1597return make_error<GenericBinaryError>(
"invalid function count",
1601for (
uint32_t i = 0; i < FunctionCount; i++) {
1603constuint8_t *FunctionStart = Ctx.Ptr;
1607Function.CodeOffset = Ctx.Ptr - FunctionStart;
1608Function.Index = NumImportedFunctions + i;
1609Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1610Function.Size = FunctionEnd - FunctionStart;
1613Function.Locals.reserve(NumLocalDecls);
1614while (NumLocalDecls--) {
1621uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1622// Ensure that Function is within Ctx's buffer. 1623if (Ctx.Ptr + BodySize > Ctx.End) {
1624return make_error<GenericBinaryError>(
"Function extends beyond buffer",
1628// This will be set later when reading in the linking metadata section. 1630 Ctx.Ptr += BodySize;
1631assert(Ctx.Ptr == FunctionEnd);
1633if (Ctx.Ptr != Ctx.End)
1634return make_error<GenericBinaryError>(
"code section ended prematurely",
1639Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1641 ElemSegments.reserve(Count);
1649if (Segment.
Flags & ~SupportedFlags)
1650return make_error<GenericBinaryError>(
1661bool HasTableNumber =
1679return make_error<GenericBinaryError>(
"invalid TableNumber",
1699return make_error<GenericBinaryError>(
"invalid elem type",
1704return make_error<GenericBinaryError>(
"invalid elem type",
1708 }
elseif (HasElemType) {
1728 ElemSegments.push_back(Segment);
1730if (Ctx.Ptr != Ctx.End)
1731return make_error<GenericBinaryError>(
"elem section ended prematurely",
1736Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1737 DataSection = Sections.size();
1739if (DataCount && Count != *DataCount)
1740return make_error<GenericBinaryError>(
1741"number of data segments does not match DataCount section");
1742 DataSegments.reserve(Count);
1759if (
Size > (
size_t)(Ctx.End - Ctx.Ptr))
1760return make_error<GenericBinaryError>(
"invalid segment size",
1763// The rest of these Data fields are set later, when reading in the linking 1770 DataSegments.push_back(Segment);
1772if (Ctx.Ptr != Ctx.End)
1773return make_error<GenericBinaryError>(
"data section ended prematurely",
1778Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1794if (
Sym.isBindingWeak())
1796if (!
Sym.isBindingLocal())
1800if (!
Sym.isDefined())
1802if (
Sym.isTypeFunction())
1809Ref.d.a = 1;
// Arbitrary non-zero value so that Ref.p is non-null 1810Ref.d.b = 0;
// Symbol index 1816Ref.d.a = 1;
// Arbitrary non-zero value so that Ref.p is non-null 1817Ref.d.b = Symbols.size();
// Symbol index 1822return Symbols[Symb.
d.
b];
1835if (!
Sym.isDefined())
1842 isDefinedFunctionIndex(
Sym.Info.ElementIndex)) {
1847 isDefinedGlobalIndex(
Sym.Info.ElementIndex)) {
1848return getDefinedGlobal(
Sym.Info.ElementIndex).
Offset + SectionAddress;
1855switch (
Sym.Info.Kind) {
1860returnSym.Info.ElementIndex;
1862// The value of a data symbol is the segment offset, plus the symbol 1863// offset within the segment. 1873returnSym.Info.DataRef.Offset;
1902switch (
Sym.Info.Kind) {
1924if (
Sym.isUndefined())
1928Ref.d.a = getSymbolSectionIdImpl(
Sym);
1934return getSymbolSectionIdImpl(
Sym);
1938switch (
Sym.Info.Kind) {
1942return GlobalSection;
1946returnSym.Info.ElementIndex;
1958if (!
Sym.isDefined())
1960if (
Sym.isTypeGlobal())
1961return getDefinedGlobal(
Sym.Info.ElementIndex).
Size;
1962if (
Sym.isTypeData())
1963returnSym.Info.DataRef.Size;
1964if (
Sym.isTypeFunction())
1966// Currently symbol size is only tracked for data segments and functions. In 1967// principle we could also track size (e.g. binary size) for tables, globals 1968// and element segments etc too. 1984// For object files, use 0 for section addresses, and section offsets for 1985// symbol addresses. For linked files, use file offsets. 1986// See also getSymbolAddress. 1988 : Sections[Sec.
d.
a].Offset;
2003// This will never fail since wasm sections can never be empty (user-sections 2004// must have a name and non-user sections each have a defined structure). 2030 RelocRef.
d.
a =
Ref.d.a;
2038 RelocRef.
d.
a =
Ref.d.a;
2052if (Rel.
Type == wasm::R_WASM_TYPE_INDEX_LEB)
2070#define WASM_RELOC(name, value) \ 2076#include "llvm/BinaryFormat/WasmRelocs.def" 2081 Result.append(Res.
begin(), Res.
end());
2092Ref.d.a = Sections.size();
2097return HasMemory64 ? 8 : 4;
2116return Sections[
Ref.d.a];
2137int WasmSectionOrderChecker::getSectionOrder(
unsignedID,
2181// Represents the edges in a directed graph where any node B reachable from node 2182// A is not allowed to appear before A in the section ordering, but may appear 2185 [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2186// WASM_SEC_ORDER_NONE 2188// WASM_SEC_ORDER_TYPE 2189 {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2190// WASM_SEC_ORDER_IMPORT 2191 {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2192// WASM_SEC_ORDER_FUNCTION 2193 {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2194// WASM_SEC_ORDER_TABLE 2195 {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2196// WASM_SEC_ORDER_MEMORY 2197 {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2198// WASM_SEC_ORDER_TAG 2199 {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2200// WASM_SEC_ORDER_GLOBAL 2201 {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2202// WASM_SEC_ORDER_EXPORT 2203 {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2204// WASM_SEC_ORDER_START 2205 {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2206// WASM_SEC_ORDER_ELEM 2207 {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2208// WASM_SEC_ORDER_DATACOUNT 2209 {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2210// WASM_SEC_ORDER_CODE 2211 {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2212// WASM_SEC_ORDER_DATA 2213 {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2216// WASM_SEC_ORDER_DYLINK 2217 {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2218// WASM_SEC_ORDER_LINKING 2219 {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2220// WASM_SEC_ORDER_RELOC (can be repeated) 2222// WASM_SEC_ORDER_NAME 2223 {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2224// WASM_SEC_ORDER_PRODUCERS 2225 {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2226// WASM_SEC_ORDER_TARGET_FEATURES 2227 {WASM_SEC_ORDER_TARGET_FEATURES}};
2231int Order = getSectionOrder(
ID, CustomSectionName);
2235// Disallowed predecessors we need to check for 2238// Keep track of completed checks to avoid repeating work 2243// Add new disallowed predecessors to work list 2244for (
size_tI = 0;; ++
I) {
2251 Checked[Next] =
true;
2254if (WorkList.
empty())
2257// Consider next disallowed predecessor 2263// Have not seen any disallowed predecessors Analysis containing CSE Info
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseSet and SmallDenseSet classes.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
StringSet - A set-like wrapper for the StringMap.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx)
static Error readInitExpr(wasm::WasmInitExpr &Expr, WasmObjectFile::ReadContext &Ctx)
static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx)
static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx)
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx)
static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx)
static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx, WasmSectionOrderChecker &Checker)
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx)
static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx)
static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx)
static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx)
static StringRef readString(WasmObjectFile::ReadContext &Ctx)
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx)
static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx)
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx)
static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx)
static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx, uint32_t Code)
static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
Implements a dense probed hash-table based set.
Helper for Errors used as out-parameters.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
const unsigned char * bytes_begin() const
StringSet - A wrapper for StringMap that provides set-like functionality.
std::pair< typename Base::iterator, bool > insert(StringRef key)
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & StartsWith(StringLiteral S, T Value)
Manages the enabling and disabling of subtarget specific features.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static Twine utohexstr(const uint64_t &Val)
The instances of the Type class are immutable: once they are created, they are never changed.
std::pair< iterator, bool > insert(const ValueT &V)
This is a value type class that represents a single symbol in the list of symbols in the object file.
DataRefImpl getRawDataRefImpl() const
StringRef getData() const
This class is the base class for all object file types.
friend class RelocationRef
static Expected< std::unique_ptr< WasmObjectFile > > createWasmObjectFile(MemoryBufferRef Object)
Expected< uint64_t > getSymbolValue(DataRefImpl Symb) const
This is a value type class that represents a single relocation in the list of relocations in the obje...
This is a value type class that represents a single section in the list of sections in the object fil...
This is a value type class that represents a single symbol in the list of symbols in the object file.
basic_symbol_iterator symbol_begin() const override
relocation_iterator section_rel_end(DataRefImpl Sec) const override
void moveSymbolNext(DataRefImpl &Symb) const override
uint64_t getSectionAlignment(DataRefImpl Sec) const override
uint64_t getRelocationOffset(DataRefImpl Rel) const override
Expected< SymbolRef::Type > getSymbolType(DataRefImpl Symb) const override
uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override
bool isSectionText(DataRefImpl Sec) const override
bool isSectionBSS(DataRefImpl Sec) const override
basic_symbol_iterator symbol_end() const override
Expected< uint32_t > getSymbolFlags(DataRefImpl Symb) const override
section_iterator section_begin() const override
bool isRelocatableObject() const override
True if this is a relocatable object (.o/.obj).
void moveRelocationNext(DataRefImpl &Rel) const override
uint32_t getSymbolSectionId(SymbolRef Sym) const
bool isSectionCompressed(DataRefImpl Sec) const override
bool isSectionVirtual(DataRefImpl Sec) const override
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override
void getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl< char > &Result) const override
StringRef getFileFormatName() const override
Expected< StringRef > getSymbolName(DataRefImpl Symb) const override
relocation_iterator section_rel_begin(DataRefImpl Sec) const override
uint8_t getBytesInAddress() const override
The number of bytes used to represent an address in this object file format.
WasmObjectFile(MemoryBufferRef Object, Error &Err)
section_iterator section_end() const override
Expected< ArrayRef< uint8_t > > getSectionContents(DataRefImpl Sec) const override
uint64_t getSectionIndex(DataRefImpl Sec) const override
uint32_t getSymbolAlignment(DataRefImpl Symb) const override
uint64_t getSectionSize(DataRefImpl Sec) const override
Triple::ArchType getArch() const override
uint64_t getRelocationType(DataRefImpl Rel) const override
const WasmSection & getWasmSection(const SectionRef &Section) const
Expected< section_iterator > getSymbolSection(DataRefImpl Symb) const override
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override
Expected< SubtargetFeatures > getFeatures() const override
const wasm::WasmObjectHeader & getHeader() const
void moveSectionNext(DataRefImpl &Sec) const override
uint32_t getNumImportedFunctions() const
bool isSharedObject() const
const wasm::WasmRelocation & getWasmRelocation(const RelocationRef &Ref) const
uint32_t getSymbolSize(SymbolRef Sym) const
ArrayRef< wasm::WasmFunction > functions() const
const WasmSymbol & getWasmSymbol(const DataRefImpl &Symb) const
uint64_t getSectionAddress(DataRefImpl Sec) const override
Expected< uint64_t > getSymbolAddress(DataRefImpl Symb) const override
bool isSectionData(DataRefImpl Sec) const override
Expected< StringRef > getSectionName(DataRefImpl Sec) const override
bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")
@ WASM_SEC_ORDER_TARGET_FEATURES
@ WASM_SEC_ORDER_PRODUCERS
@ WASM_SEC_ORDER_DATACOUNT
@ WASM_SEC_ORDER_FUNCTION
static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]
unsigned getBinding() const
LLVM_DUMP_METHOD void dump() const
wasm::WasmSymbolInfo Info
void print(raw_ostream &Out) const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
content_iterator< SectionRef > section_iterator
content_iterator< RelocationRef > relocation_iterator
uint32_t read32le(const void *P)
const unsigned WASM_SYMBOL_UNDEFINED
@ WASM_ELEM_SEGMENT_HAS_INIT_EXPRS
@ WASM_ELEM_SEGMENT_IS_DECLARATIVE
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
@ WASM_ELEM_SEGMENT_IS_PASSIVE
const unsigned WASM_SYMBOL_BINDING_GLOBAL
const uint32_t WasmMetadataVersion
const unsigned WASM_SYMBOL_BINDING_WEAK
const unsigned WASM_SYMBOL_BINDING_LOCAL
@ WASM_NAMES_DATA_SEGMENT
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_FUNCTION
const uint32_t WasmVersion
@ WASM_OPCODE_ARRAY_NEW_FIXED
@ WASM_OPCODE_ARRAY_NEW_DEFAULT
@ WASM_OPCODE_STRUCT_NEW_DEFAULT
const unsigned WASM_SYMBOL_BINDING_MASK
@ WASM_LIMITS_FLAG_HAS_MAX
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
llvm::StringRef sectionTypeToString(uint32_t type)
const unsigned WASM_SYMBOL_EXPLICIT_NAME
@ WASM_FEATURE_PREFIX_USED
@ WASM_FEATURE_PREFIX_DISALLOWED
const unsigned WASM_SYMBOL_ABSOLUTE
@ WASM_DYLINK_EXPORT_INFO
@ WASM_DYLINK_IMPORT_INFO
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC
This is an optimization pass for GlobalISel generic memory operations.
std::string to_string(const T &Value)
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a ULEB128 value.
@ Import
Import information from summary.
int64_t decodeSLEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a SLEB128 value.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
@ Global
Append to llvm.global_dtors.
@ Ref
The access may reference the value stored in memory.
const char * toString(DWARFSectionKind Kind)
ArrayRef< uint8_t > Content
std::vector< wasm::WasmRelocation > Relocations
wasm::WasmDataSegment Data
ArrayRef< uint8_t > Content
std::vector< StringRef > Needed
std::vector< WasmDylinkExportInfo > ExportInfo
std::vector< WasmDylinkImportInfo > ImportInfo
std::vector< uint32_t > Functions
std::optional< StringRef > ExportName
uint32_t CodeSectionOffset
union llvm::wasm::WasmInitExprMVP::@187 Value
std::vector< WasmInitFunc > InitFunctions
std::vector< StringRef > Comdats
std::vector< std::pair< std::string, std::string > > SDKs
std::vector< std::pair< std::string, std::string > > Languages
std::vector< std::pair< std::string, std::string > > Tools
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params
enum llvm::wasm::WasmSignature::@192 Kind
WasmDataReference DataRef
struct llvm::object::DataRefImpl::@370 d