aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/WasmObjectFile.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
commitb60736ec1405bb0a8dd40989f67ef4c93da068ab (patch)
tree5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /llvm/lib/Object/WasmObjectFile.cpp
parentcfca06d7963fa0909f90483b42a6d7d194d01e08 (diff)
Diffstat (limited to 'llvm/lib/Object/WasmObjectFile.cpp')
-rw-r--r--llvm/lib/Object/WasmObjectFile.cpp350
1 files changed, 238 insertions, 112 deletions
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index bb2e81d64047..40f468881edd 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -187,19 +187,19 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
case wasm::WASM_OPCODE_REF_NULL: {
wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
if (Ty != wasm::ValType::EXTERNREF) {
- return make_error<GenericBinaryError>("Invalid type for ref.null",
+ return make_error<GenericBinaryError>("invalid type for ref.null",
object_error::parse_failed);
}
break;
}
default:
- return make_error<GenericBinaryError>("Invalid opcode in init_expr",
+ return make_error<GenericBinaryError>("invalid opcode in init_expr",
object_error::parse_failed);
}
uint8_t EndOpcode = readOpcode(Ctx);
if (EndOpcode != wasm::WASM_OPCODE_END) {
- return make_error<GenericBinaryError>("Invalid init_expr",
+ return make_error<GenericBinaryError>("invalid init_expr",
object_error::parse_failed);
}
return Error::success();
@@ -214,11 +214,11 @@ static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
return Result;
}
-static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
- wasm::WasmTable Table;
- Table.ElemType = readUint8(Ctx);
- Table.Limits = readLimits(Ctx);
- return Table;
+static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {
+ wasm::WasmTableType TableType;
+ TableType.ElemType = readUint8(Ctx);
+ TableType.Limits = readLimits(Ctx);
+ return TableType;
}
static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
@@ -228,10 +228,10 @@ static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
uint32_t Size = readVaruint32(Ctx);
if (Size == 0)
- return make_error<StringError>("Zero length section",
+ return make_error<StringError>("zero length section",
object_error::parse_failed);
if (Ctx.Ptr + Size > Ctx.End)
- return make_error<StringError>("Section too large",
+ return make_error<StringError>("section too large",
object_error::parse_failed);
if (Section.Type == wasm::WASM_SEC_CUSTOM) {
WasmObjectFile::ReadContext SectionCtx;
@@ -247,7 +247,7 @@ static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
}
if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
- return make_error<StringError>("Out of order section type: " +
+ return make_error<StringError>("out of order section type: " +
llvm::to_string(Section.Type),
object_error::parse_failed);
}
@@ -262,8 +262,8 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
ErrorAsOutParameter ErrAsOutParam(&Err);
Header.Magic = getData().substr(0, 4);
if (Header.Magic != StringRef("\0asm", 4)) {
- Err =
- make_error<StringError>("Bad magic number", object_error::parse_failed);
+ Err = make_error<StringError>("invalid magic number",
+ object_error::parse_failed);
return;
}
@@ -273,14 +273,15 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
Ctx.End = Ctx.Start + getData().size();
if (Ctx.Ptr + 4 > Ctx.End) {
- Err = make_error<StringError>("Missing version number",
+ Err = make_error<StringError>("missing version number",
object_error::parse_failed);
return;
}
Header.Version = readUint32(Ctx);
if (Header.Version != wasm::WasmVersion) {
- Err = make_error<StringError>("Bad version number",
+ Err = make_error<StringError>("invalid version number: " +
+ Twine(Header.Version),
object_error::parse_failed);
return;
}
@@ -333,7 +334,7 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) {
return parseDataCountSection(Ctx);
default:
return make_error<GenericBinaryError>(
- "Invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
+ "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
}
}
@@ -355,9 +356,11 @@ Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
}
Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
- llvm::DenseSet<uint64_t> Seen;
+ llvm::DenseSet<uint64_t> SeenFunctions;
+ llvm::DenseSet<uint64_t> SeenGlobals;
+ llvm::DenseSet<uint64_t> SeenSegments;
if (FunctionTypes.size() && !SeenCodeSection) {
- return make_error<GenericBinaryError>("Names must come after code section",
+ return make_error<GenericBinaryError>("names must come after code section",
object_error::parse_failed);
}
@@ -366,20 +369,42 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
uint32_t Size = readVaruint32(Ctx);
const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
switch (Type) {
- case wasm::WASM_NAMES_FUNCTION: {
+ case wasm::WASM_NAMES_FUNCTION:
+ case wasm::WASM_NAMES_GLOBAL:
+ case wasm::WASM_NAMES_DATA_SEGMENT: {
uint32_t Count = readVaruint32(Ctx);
while (Count--) {
uint32_t Index = readVaruint32(Ctx);
- if (!Seen.insert(Index).second)
- return make_error<GenericBinaryError>("Function named more than once",
- object_error::parse_failed);
StringRef Name = readString(Ctx);
- if (!isValidFunctionIndex(Index) || Name.empty())
- return make_error<GenericBinaryError>("Invalid name entry",
- object_error::parse_failed);
- DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
- if (isDefinedFunctionIndex(Index))
- getDefinedFunction(Index).DebugName = Name;
+ wasm::NameType nameType = wasm::NameType::FUNCTION;
+ if (Type == wasm::WASM_NAMES_FUNCTION) {
+ if (!SeenFunctions.insert(Index).second)
+ return make_error<GenericBinaryError>(
+ "function named more than once", object_error::parse_failed);
+ if (!isValidFunctionIndex(Index) || Name.empty())
+ return make_error<GenericBinaryError>("invalid name entry",
+ object_error::parse_failed);
+
+ if (isDefinedFunctionIndex(Index))
+ getDefinedFunction(Index).DebugName = Name;
+ } else if (Type == wasm::WASM_NAMES_GLOBAL) {
+ nameType = wasm::NameType::GLOBAL;
+ if (!SeenGlobals.insert(Index).second)
+ return make_error<GenericBinaryError>("global named more than once",
+ object_error::parse_failed);
+ if (!isValidGlobalIndex(Index) || Name.empty())
+ return make_error<GenericBinaryError>("invalid name entry",
+ object_error::parse_failed);
+ } else {
+ nameType = wasm::NameType::DATA_SEGMENT;
+ if (!SeenSegments.insert(Index).second)
+ return make_error<GenericBinaryError>(
+ "segment named more than once", object_error::parse_failed);
+ if (Index > DataSegments.size())
+ return make_error<GenericBinaryError>("invalid named data segment",
+ object_error::parse_failed);
+ }
+ DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
}
break;
}
@@ -391,11 +416,11 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
}
if (Ctx.Ptr != SubSectionEnd)
return make_error<GenericBinaryError>(
- "Name sub-section ended prematurely", object_error::parse_failed);
+ "name sub-section ended prematurely", object_error::parse_failed);
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Name section ended prematurely",
+ return make_error<GenericBinaryError>("name section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -404,14 +429,14 @@ Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
HasLinkingSection = true;
if (FunctionTypes.size() && !SeenCodeSection) {
return make_error<GenericBinaryError>(
- "Linking data must come after code section",
+ "linking data must come after code section",
object_error::parse_failed);
}
LinkingData.Version = readVaruint32(Ctx);
if (LinkingData.Version != wasm::WasmMetadataVersion) {
return make_error<GenericBinaryError>(
- "Unexpected metadata version: " + Twine(LinkingData.Version) +
+ "unexpected metadata version: " + Twine(LinkingData.Version) +
" (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
object_error::parse_failed);
}
@@ -432,7 +457,7 @@ Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
case wasm::WASM_SEGMENT_INFO: {
uint32_t Count = readVaruint32(Ctx);
if (Count > DataSegments.size())
- return make_error<GenericBinaryError>("Too many segment names",
+ return make_error<GenericBinaryError>("too many segment names",
object_error::parse_failed);
for (uint32_t I = 0; I < Count; I++) {
DataSegments[I].Data.Name = readString(Ctx);
@@ -449,7 +474,7 @@ Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
Init.Priority = readVaruint32(Ctx);
Init.Symbol = readVaruint32(Ctx);
if (!isValidFunctionSymbol(Init.Symbol))
- return make_error<GenericBinaryError>("Invalid function symbol: " +
+ return make_error<GenericBinaryError>("invalid function symbol: " +
Twine(Init.Symbol),
object_error::parse_failed);
LinkingData.InitFunctions.emplace_back(Init);
@@ -466,10 +491,10 @@ Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
}
if (Ctx.Ptr != Ctx.End)
return make_error<GenericBinaryError>(
- "Linking sub-section ended prematurely", object_error::parse_failed);
+ "linking sub-section ended prematurely", object_error::parse_failed);
}
if (Ctx.Ptr != OrigEnd)
- return make_error<GenericBinaryError>("Linking section ended prematurely",
+ return make_error<GenericBinaryError>("linking section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -483,9 +508,11 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
std::vector<wasm::WasmImport *> ImportedGlobals;
std::vector<wasm::WasmImport *> ImportedFunctions;
std::vector<wasm::WasmImport *> ImportedEvents;
+ std::vector<wasm::WasmImport *> ImportedTables;
ImportedGlobals.reserve(Imports.size());
ImportedFunctions.reserve(Imports.size());
ImportedEvents.reserve(Imports.size());
+ ImportedTables.reserve(Imports.size());
for (auto &I : Imports) {
if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
ImportedFunctions.emplace_back(&I);
@@ -493,12 +520,15 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
ImportedGlobals.emplace_back(&I);
else if (I.Kind == wasm::WASM_EXTERNAL_EVENT)
ImportedEvents.emplace_back(&I);
+ else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
+ ImportedTables.emplace_back(&I);
}
while (Count--) {
wasm::WasmSymbolInfo Info;
const wasm::WasmSignature *Signature = nullptr;
const wasm::WasmGlobalType *GlobalType = nullptr;
+ const wasm::WasmTableType *TableType = nullptr;
const wasm::WasmEventType *EventType = nullptr;
Info.Kind = readUint8(Ctx);
@@ -560,7 +590,38 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Info.Name = Import.Field;
}
GlobalType = &Import.Global;
- Info.ImportName = Import.Field;
+ if (!Import.Module.empty()) {
+ Info.ImportModule = Import.Module;
+ }
+ }
+ break;
+
+ case wasm::WASM_SYMBOL_TYPE_TABLE:
+ Info.ElementIndex = readVaruint32(Ctx);
+ if (!isValidTableIndex(Info.ElementIndex) ||
+ IsDefined != isDefinedTableIndex(Info.ElementIndex))
+ return make_error<GenericBinaryError>("invalid table symbol index",
+ object_error::parse_failed);
+ if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
+ wasm::WASM_SYMBOL_BINDING_WEAK)
+ return make_error<GenericBinaryError>("undefined weak table symbol",
+ object_error::parse_failed);
+ if (IsDefined) {
+ Info.Name = readString(Ctx);
+ unsigned TableIndex = Info.ElementIndex - NumImportedTables;
+ wasm::WasmTable &Table = Tables[TableIndex];
+ TableType = &Table.Type;
+ if (Table.SymbolName.empty())
+ Table.SymbolName = Info.Name;
+ } else {
+ wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
+ if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
+ Info.Name = readString(Ctx);
+ Info.ImportName = Import.Field;
+ } else {
+ Info.Name = Import.Field;
+ }
+ TableType = &Import.Table;
if (!Import.Module.empty()) {
Info.ImportModule = Import.Module;
}
@@ -587,7 +648,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
wasm::WASM_SYMBOL_BINDING_LOCAL)
return make_error<GenericBinaryError>(
- "Section symbols must have local binding",
+ "section symbols must have local binding",
object_error::parse_failed);
Info.ElementIndex = readVaruint32(Ctx);
// Use somewhat unique section name as symbol name.
@@ -633,19 +694,20 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
}
default:
- return make_error<GenericBinaryError>("Invalid symbol type",
+ return make_error<GenericBinaryError>("invalid symbol type: " +
+ Twine(unsigned(Info.Kind)),
object_error::parse_failed);
}
if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
wasm::WASM_SYMBOL_BINDING_LOCAL &&
!SymbolNames.insert(Info.Name).second)
- return make_error<GenericBinaryError>("Duplicate symbol name " +
+ return make_error<GenericBinaryError>("duplicate symbol name " +
Twine(Info.Name),
object_error::parse_failed);
LinkingData.SymbolTable.emplace_back(Info);
- Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, EventType,
- Signature);
+ Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
+ EventType, Signature);
LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
}
@@ -658,13 +720,13 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
StringRef Name = readString(Ctx);
if (Name.empty() || !ComdatSet.insert(Name).second)
- return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
+ return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
Twine(Name),
object_error::parse_failed);
LinkingData.Comdats.emplace_back(Name);
uint32_t Flags = readVaruint32(Ctx);
if (Flags != 0)
- return make_error<GenericBinaryError>("Unsupported COMDAT flags",
+ return make_error<GenericBinaryError>("unsupported COMDAT flags",
object_error::parse_failed);
uint32_t EntryCount = readVaruint32(Ctx);
@@ -673,14 +735,14 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
unsigned Index = readVaruint32(Ctx);
switch (Kind) {
default:
- return make_error<GenericBinaryError>("Invalid COMDAT entry type",
+ return make_error<GenericBinaryError>("invalid COMDAT entry type",
object_error::parse_failed);
case wasm::WASM_COMDAT_DATA:
if (Index >= DataSegments.size())
return make_error<GenericBinaryError>(
"COMDAT data index out of range", object_error::parse_failed);
if (DataSegments[Index].Data.Comdat != UINT32_MAX)
- return make_error<GenericBinaryError>("Data segment in two COMDATs",
+ return make_error<GenericBinaryError>("data segment in two COMDATs",
object_error::parse_failed);
DataSegments[Index].Data.Comdat = ComdatIndex;
break;
@@ -689,10 +751,19 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
return make_error<GenericBinaryError>(
"COMDAT function index out of range", object_error::parse_failed);
if (getDefinedFunction(Index).Comdat != UINT32_MAX)
- return make_error<GenericBinaryError>("Function in two COMDATs",
+ return make_error<GenericBinaryError>("function in two COMDATs",
object_error::parse_failed);
getDefinedFunction(Index).Comdat = ComdatIndex;
break;
+ case wasm::WASM_COMDAT_SECTION:
+ if (Index >= Sections.size())
+ return make_error<GenericBinaryError>(
+ "COMDAT section index out of range", object_error::parse_failed);
+ if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
+ return make_error<GenericBinaryError>(
+ "non-custom section in a COMDAT", object_error::parse_failed);
+ Sections[Index].Comdat = ComdatIndex;
+ break;
}
}
}
@@ -706,7 +777,7 @@ Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
StringRef FieldName = readString(Ctx);
if (!FieldsSeen.insert(FieldName).second)
return make_error<GenericBinaryError>(
- "Producers section does not have unique fields",
+ "producers section does not have unique fields",
object_error::parse_failed);
std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
if (FieldName == "language") {
@@ -717,7 +788,7 @@ Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
ProducerVec = &ProducerInfo.SDKs;
} else {
return make_error<GenericBinaryError>(
- "Producers section field is not named one of language, processed-by, "
+ "producers section field is not named one of language, processed-by, "
"or sdk",
object_error::parse_failed);
}
@@ -728,14 +799,14 @@ Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
StringRef Version = readString(Ctx);
if (!ProducersSeen.insert(Name).second) {
return make_error<GenericBinaryError>(
- "Producers section contains repeated producer",
+ "producers section contains repeated producer",
object_error::parse_failed);
}
ProducerVec->emplace_back(std::string(Name), std::string(Version));
}
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Producers section ended prematurely",
+ return make_error<GenericBinaryError>("producers section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -752,20 +823,20 @@ Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
break;
default:
- return make_error<GenericBinaryError>("Unknown feature policy prefix",
+ return make_error<GenericBinaryError>("unknown feature policy prefix",
object_error::parse_failed);
}
Feature.Name = std::string(readString(Ctx));
if (!FeaturesSeen.insert(Feature.Name).second)
return make_error<GenericBinaryError>(
- "Target features section contains repeated feature \"" +
+ "target features section contains repeated feature \"" +
Feature.Name + "\"",
object_error::parse_failed);
TargetFeatures.push_back(Feature);
}
if (Ctx.Ptr != Ctx.End)
return make_error<GenericBinaryError>(
- "Target features section ended prematurely",
+ "target features section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -773,7 +844,7 @@ Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
uint32_t SectionIndex = readVaruint32(Ctx);
if (SectionIndex >= Sections.size())
- return make_error<GenericBinaryError>("Invalid section index",
+ return make_error<GenericBinaryError>("invalid section index",
object_error::parse_failed);
WasmSection &Section = Sections[SectionIndex];
uint32_t RelocCount = readVaruint32(Ctx);
@@ -781,25 +852,33 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
uint32_t PreviousOffset = 0;
while (RelocCount--) {
wasm::WasmRelocation Reloc = {};
- Reloc.Type = readVaruint32(Ctx);
+ uint32_t type = readVaruint32(Ctx);
+ Reloc.Type = type;
Reloc.Offset = readVaruint32(Ctx);
if (Reloc.Offset < PreviousOffset)
- return make_error<GenericBinaryError>("Relocations not in offset order",
+ return make_error<GenericBinaryError>("relocations not in offset order",
object_error::parse_failed);
PreviousOffset = Reloc.Offset;
Reloc.Index = readVaruint32(Ctx);
- switch (Reloc.Type) {
+ switch (type) {
case wasm::R_WASM_FUNCTION_INDEX_LEB:
case wasm::R_WASM_TABLE_INDEX_SLEB:
+ case wasm::R_WASM_TABLE_INDEX_SLEB64:
case wasm::R_WASM_TABLE_INDEX_I32:
+ case wasm::R_WASM_TABLE_INDEX_I64:
case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
if (!isValidFunctionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("Bad relocation function index",
+ return make_error<GenericBinaryError>(
+ "invalid relocation function index", object_error::parse_failed);
+ break;
+ case wasm::R_WASM_TABLE_NUMBER_LEB:
+ if (!isValidTableSymbol(Reloc.Index))
+ return make_error<GenericBinaryError>("invalid relocation table index",
object_error::parse_failed);
break;
case wasm::R_WASM_TYPE_INDEX_LEB:
if (Reloc.Index >= Signatures.size())
- return make_error<GenericBinaryError>("Bad relocation type index",
+ return make_error<GenericBinaryError>("invalid relocation type index",
object_error::parse_failed);
break;
case wasm::R_WASM_GLOBAL_INDEX_LEB:
@@ -808,25 +887,26 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
if (!isValidGlobalSymbol(Reloc.Index) &&
!isValidDataSymbol(Reloc.Index) &&
!isValidFunctionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("Bad relocation global index",
+ return make_error<GenericBinaryError>("invalid relocation global index",
object_error::parse_failed);
break;
case wasm::R_WASM_GLOBAL_INDEX_I32:
if (!isValidGlobalSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("Bad relocation global index",
+ return make_error<GenericBinaryError>("invalid relocation global index",
object_error::parse_failed);
break;
case wasm::R_WASM_EVENT_INDEX_LEB:
if (!isValidEventSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("Bad relocation event index",
+ return make_error<GenericBinaryError>("invalid relocation event index",
object_error::parse_failed);
break;
case wasm::R_WASM_MEMORY_ADDR_LEB:
case wasm::R_WASM_MEMORY_ADDR_SLEB:
case wasm::R_WASM_MEMORY_ADDR_I32:
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
+ case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
if (!isValidDataSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("Bad relocation data index",
+ return make_error<GenericBinaryError>("invalid relocation data index",
object_error::parse_failed);
Reloc.Addend = readVarint32(Ctx);
break;
@@ -835,25 +915,31 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
case wasm::R_WASM_MEMORY_ADDR_I64:
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
if (!isValidDataSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("Bad relocation data index",
+ return make_error<GenericBinaryError>("invalid relocation data index",
object_error::parse_failed);
Reloc.Addend = readVarint64(Ctx);
break;
case wasm::R_WASM_FUNCTION_OFFSET_I32:
if (!isValidFunctionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("Bad relocation function index",
- object_error::parse_failed);
+ return make_error<GenericBinaryError>(
+ "invalid relocation function index", object_error::parse_failed);
Reloc.Addend = readVarint32(Ctx);
break;
+ case wasm::R_WASM_FUNCTION_OFFSET_I64:
+ if (!isValidFunctionSymbol(Reloc.Index))
+ return make_error<GenericBinaryError>(
+ "invalid relocation function index", object_error::parse_failed);
+ Reloc.Addend = readVarint64(Ctx);
+ break;
case wasm::R_WASM_SECTION_OFFSET_I32:
if (!isValidSectionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("Bad relocation section index",
- object_error::parse_failed);
+ return make_error<GenericBinaryError>(
+ "invalid relocation section index", object_error::parse_failed);
Reloc.Addend = readVarint32(Ctx);
break;
default:
- return make_error<GenericBinaryError>("Bad relocation type: " +
- Twine(Reloc.Type),
+ return make_error<GenericBinaryError>("invalid relocation type: " +
+ Twine(type),
object_error::parse_failed);
}
@@ -871,16 +957,18 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
Size = 4;
- if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64)
+ if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
+ Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
+ Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
Size = 8;
if (Reloc.Offset + Size > EndOffset)
- return make_error<GenericBinaryError>("Bad relocation offset",
+ return make_error<GenericBinaryError>("invalid relocation offset",
object_error::parse_failed);
Section.Relocations.push_back(Reloc);
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Reloc section ended prematurely",
+ return make_error<GenericBinaryError>("reloc section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -915,7 +1003,7 @@ Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
wasm::WasmSignature Sig;
uint8_t Form = readUint8(Ctx);
if (Form != wasm::WASM_TYPE_FUNC) {
- return make_error<GenericBinaryError>("Invalid signature type",
+ return make_error<GenericBinaryError>("invalid signature type",
object_error::parse_failed);
}
uint32_t ParamCount = readVaruint32(Ctx);
@@ -932,7 +1020,7 @@ Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
Signatures.push_back(std::move(Sig));
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Type section ended prematurely",
+ return make_error<GenericBinaryError>("type section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -957,26 +1045,32 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
break;
case wasm::WASM_EXTERNAL_MEMORY:
Im.Memory = readLimits(Ctx);
+ if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
+ HasMemory64 = true;
break;
- case wasm::WASM_EXTERNAL_TABLE:
- Im.Table = readTable(Ctx);
- if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF)
- return make_error<GenericBinaryError>("Invalid table element type",
+ case wasm::WASM_EXTERNAL_TABLE: {
+ Im.Table = readTableType(Ctx);
+ NumImportedTables++;
+ auto ElemType = Im.Table.ElemType;
+ if (ElemType != wasm::WASM_TYPE_FUNCREF &&
+ ElemType != wasm::WASM_TYPE_EXTERNREF)
+ return make_error<GenericBinaryError>("invalid table element type",
object_error::parse_failed);
break;
+ }
case wasm::WASM_EXTERNAL_EVENT:
NumImportedEvents++;
Im.Event.Attribute = readVarint32(Ctx);
Im.Event.SigIndex = readVarint32(Ctx);
break;
default:
- return make_error<GenericBinaryError>("Unexpected import kind",
+ return make_error<GenericBinaryError>("unexpected import kind",
object_error::parse_failed);
}
Imports.push_back(Im);
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Import section ended prematurely",
+ return make_error<GenericBinaryError>("import section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -989,28 +1083,34 @@ Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
while (Count--) {
uint32_t Type = readVaruint32(Ctx);
if (Type >= NumTypes)
- return make_error<GenericBinaryError>("Invalid function type",
+ return make_error<GenericBinaryError>("invalid function type",
object_error::parse_failed);
FunctionTypes.push_back(Type);
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Function section ended prematurely",
+ return make_error<GenericBinaryError>("function section ended prematurely",
object_error::parse_failed);
return Error::success();
}
Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
+ TableSection = Sections.size();
uint32_t Count = readVaruint32(Ctx);
Tables.reserve(Count);
while (Count--) {
- Tables.push_back(readTable(Ctx));
- if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) {
- return make_error<GenericBinaryError>("Invalid table element type",
+ wasm::WasmTable T;
+ T.Type = readTableType(Ctx);
+ T.Index = NumImportedTables + Tables.size();
+ Tables.push_back(T);
+ auto ElemType = Tables.back().Type.ElemType;
+ if (ElemType != wasm::WASM_TYPE_FUNCREF &&
+ ElemType != wasm::WASM_TYPE_EXTERNREF) {
+ return make_error<GenericBinaryError>("invalid table element type",
object_error::parse_failed);
}
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Table section ended prematurely",
+ return make_error<GenericBinaryError>("table section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -1019,10 +1119,13 @@ Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
uint32_t Count = readVaruint32(Ctx);
Memories.reserve(Count);
while (Count--) {
- Memories.push_back(readLimits(Ctx));
+ auto Limits = readLimits(Ctx);
+ if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
+ HasMemory64 = true;
+ Memories.push_back(Limits);
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Memory section ended prematurely",
+ return make_error<GenericBinaryError>("memory section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -1040,7 +1143,7 @@ Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Event section ended prematurely",
+ return make_error<GenericBinaryError>("event section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -1059,7 +1162,7 @@ Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
Globals.push_back(Global);
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Global section ended prematurely",
+ return make_error<GenericBinaryError>("global section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -1076,31 +1179,31 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
case wasm::WASM_EXTERNAL_FUNCTION:
if (!isDefinedFunctionIndex(Ex.Index))
- return make_error<GenericBinaryError>("Invalid function export",
+ return make_error<GenericBinaryError>("invalid function export",
object_error::parse_failed);
getDefinedFunction(Ex.Index).ExportName = Ex.Name;
break;
case wasm::WASM_EXTERNAL_GLOBAL:
if (!isValidGlobalIndex(Ex.Index))
- return make_error<GenericBinaryError>("Invalid global export",
+ return make_error<GenericBinaryError>("invalid global export",
object_error::parse_failed);
break;
case wasm::WASM_EXTERNAL_EVENT:
if (!isValidEventIndex(Ex.Index))
- return make_error<GenericBinaryError>("Invalid event export",
+ return make_error<GenericBinaryError>("invalid event export",
object_error::parse_failed);
break;
case wasm::WASM_EXTERNAL_MEMORY:
case wasm::WASM_EXTERNAL_TABLE:
break;
default:
- return make_error<GenericBinaryError>("Unexpected export kind",
+ return make_error<GenericBinaryError>("unexpected export kind",
object_error::parse_failed);
}
Exports.push_back(Ex);
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Export section ended prematurely",
+ return make_error<GenericBinaryError>("export section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -1117,10 +1220,18 @@ bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
return Index < NumImportedGlobals + Globals.size();
}
+bool WasmObjectFile::isValidTableIndex(uint32_t Index) const {
+ return Index < NumImportedTables + Tables.size();
+}
+
bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
}
+bool WasmObjectFile::isDefinedTableIndex(uint32_t Index) const {
+ return Index >= NumImportedTables && isValidTableIndex(Index);
+}
+
bool WasmObjectFile::isValidEventIndex(uint32_t Index) const {
return Index < NumImportedEvents + Events.size();
}
@@ -1133,6 +1244,10 @@ bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
return Index < Symbols.size() && Symbols[Index].isTypeFunction();
}
+bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
+ return Index < Symbols.size() && Symbols[Index].isTypeTable();
+}
+
bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
}
@@ -1173,7 +1288,7 @@ wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) {
Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
StartFunction = readVaruint32(Ctx);
if (!isValidFunctionIndex(StartFunction))
- return make_error<GenericBinaryError>("Invalid start function",
+ return make_error<GenericBinaryError>("invalid start function",
object_error::parse_failed);
return Error::success();
}
@@ -1183,7 +1298,7 @@ Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
CodeSection = Sections.size();
uint32_t FunctionCount = readVaruint32(Ctx);
if (FunctionCount != FunctionTypes.size()) {
- return make_error<GenericBinaryError>("Invalid function count",
+ return make_error<GenericBinaryError>("invalid function count",
object_error::parse_failed);
}
@@ -1215,7 +1330,7 @@ Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
assert(Ctx.Ptr == FunctionEnd);
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Code section ended prematurely",
+ return make_error<GenericBinaryError>("code section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -1227,7 +1342,7 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
wasm::WasmElemSegment Segment;
Segment.TableIndex = readVaruint32(Ctx);
if (Segment.TableIndex != 0) {
- return make_error<GenericBinaryError>("Invalid TableIndex",
+ return make_error<GenericBinaryError>("invalid TableIndex",
object_error::parse_failed);
}
if (Error Err = readInitExpr(Segment.Offset, Ctx))
@@ -1239,7 +1354,7 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
ElemSegments.push_back(Segment);
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Elem section ended prematurely",
+ return make_error<GenericBinaryError>("elem section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -1249,14 +1364,16 @@ Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
uint32_t Count = readVaruint32(Ctx);
if (DataCount && Count != DataCount.getValue())
return make_error<GenericBinaryError>(
- "Number of data segments does not match DataCount section");
+ "number of data segments does not match DataCount section");
DataSegments.reserve(Count);
while (Count--) {
WasmSegment Segment;
Segment.Data.InitFlags = readVaruint32(Ctx);
- Segment.Data.MemoryIndex = (Segment.Data.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
- ? readVaruint32(Ctx) : 0;
- if ((Segment.Data.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) {
+ Segment.Data.MemoryIndex =
+ (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
+ ? readVaruint32(Ctx)
+ : 0;
+ if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
return Err;
} else {
@@ -1265,7 +1382,7 @@ Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
}
uint32_t Size = readVaruint32(Ctx);
if (Size > (size_t)(Ctx.End - Ctx.Ptr))
- return make_error<GenericBinaryError>("Invalid segment size",
+ return make_error<GenericBinaryError>("invalid segment size",
object_error::parse_failed);
Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
// The rest of these Data fields are set later, when reading in the linking
@@ -1278,7 +1395,7 @@ Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
DataSegments.push_back(Segment);
}
if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Data section ended prematurely",
+ return make_error<GenericBinaryError>("data section ended prematurely",
object_error::parse_failed);
return Error::success();
}
@@ -1352,6 +1469,7 @@ uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
case wasm::WASM_SYMBOL_TYPE_FUNCTION:
case wasm::WASM_SYMBOL_TYPE_GLOBAL:
case wasm::WASM_SYMBOL_TYPE_EVENT:
+ case wasm::WASM_SYMBOL_TYPE_TABLE:
return Sym.Info.ElementIndex;
case wasm::WASM_SYMBOL_TYPE_DATA: {
// The value of a data symbol is the segment offset, plus the symbol
@@ -1401,9 +1519,11 @@ WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
return SymbolRef::ST_Debug;
case wasm::WASM_SYMBOL_TYPE_EVENT:
return SymbolRef::ST_Other;
+ case wasm::WASM_SYMBOL_TYPE_TABLE:
+ return SymbolRef::ST_Other;
}
- llvm_unreachable("Unknown WasmSymbol::SymbolType");
+ llvm_unreachable("unknown WasmSymbol::SymbolType");
return SymbolRef::ST_Other;
}
@@ -1435,8 +1555,10 @@ uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
return Sym.Info.ElementIndex;
case wasm::WASM_SYMBOL_TYPE_EVENT:
return EventSection;
+ case wasm::WASM_SYMBOL_TYPE_TABLE:
+ return TableSection;
default:
- llvm_unreachable("Unknown WasmSymbol::SymbolType");
+ llvm_unreachable("unknown WasmSymbol::SymbolType");
}
}
@@ -1576,11 +1698,15 @@ section_iterator WasmObjectFile::section_end() const {
return section_iterator(SectionRef(Ref, this));
}
-uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
+uint8_t WasmObjectFile::getBytesInAddress() const {
+ return HasMemory64 ? 8 : 4;
+}
StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
-Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
+Triple::ArchType WasmObjectFile::getArch() const {
+ return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
+}
SubtargetFeatures WasmObjectFile::getFeatures() const {
return SubtargetFeatures();