aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp328
1 files changed, 255 insertions, 73 deletions
diff --git a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp
index b9a8e970216b..f244099d664d 100644
--- a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp
@@ -21,6 +21,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/TargetParser/SubtargetFeature.h"
@@ -29,6 +30,7 @@
#include <cassert>
#include <cstdint>
#include <cstring>
+#include <limits>
#define DEBUG_TYPE "wasm-object"
@@ -173,6 +175,27 @@ static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
return readUint8(Ctx);
}
+static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx,
+ uint32_t Code) {
+ // only directly encoded FUNCREF/EXTERNREF/EXNREF are supported
+ // (not ref null func, ref null extern, or ref null exn)
+ switch (Code) {
+ case wasm::WASM_TYPE_I32:
+ case wasm::WASM_TYPE_I64:
+ case wasm::WASM_TYPE_F32:
+ case wasm::WASM_TYPE_F64:
+ case wasm::WASM_TYPE_V128:
+ case wasm::WASM_TYPE_FUNCREF:
+ case wasm::WASM_TYPE_EXTERNREF:
+ case wasm::WASM_TYPE_EXNREF:
+ return wasm::ValType(Code);
+ }
+ if (Code == wasm::WASM_TYPE_NULLABLE || Code == wasm::WASM_TYPE_NONNULLABLE) {
+ /* Discard HeapType */ readVarint64(Ctx);
+ }
+ return wasm::ValType(wasm::ValType::OTHERREF);
+}
+
static Error readInitExpr(wasm::WasmInitExpr &Expr,
WasmObjectFile::ReadContext &Ctx) {
auto Start = Ctx.Ptr;
@@ -196,11 +219,7 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
Expr.Inst.Value.Global = readULEB128(Ctx);
break;
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",
- object_error::parse_failed);
- }
+ /* Discard type */ parseValType(Ctx, readVaruint32(Ctx));
break;
}
default:
@@ -221,10 +240,15 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
case wasm::WASM_OPCODE_I32_CONST:
case wasm::WASM_OPCODE_GLOBAL_GET:
case wasm::WASM_OPCODE_REF_NULL:
+ case wasm::WASM_OPCODE_REF_FUNC:
case wasm::WASM_OPCODE_I64_CONST:
+ readULEB128(Ctx);
+ break;
case wasm::WASM_OPCODE_F32_CONST:
+ readFloat32(Ctx);
+ break;
case wasm::WASM_OPCODE_F64_CONST:
- readULEB128(Ctx);
+ readFloat64(Ctx);
break;
case wasm::WASM_OPCODE_I32_ADD:
case wasm::WASM_OPCODE_I32_SUB:
@@ -233,6 +257,23 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
case wasm::WASM_OPCODE_I64_SUB:
case wasm::WASM_OPCODE_I64_MUL:
break;
+ case wasm::WASM_OPCODE_GC_PREFIX:
+ break;
+ // The GC opcodes are in a separate (prefixed space). This flat switch
+ // structure works as long as there is no overlap between the GC and
+ // general opcodes used in init exprs.
+ case wasm::WASM_OPCODE_STRUCT_NEW:
+ case wasm::WASM_OPCODE_STRUCT_NEW_DEFAULT:
+ case wasm::WASM_OPCODE_ARRAY_NEW:
+ case wasm::WASM_OPCODE_ARRAY_NEW_DEFAULT:
+ readULEB128(Ctx); // heap type index
+ break;
+ case wasm::WASM_OPCODE_ARRAY_NEW_FIXED:
+ readULEB128(Ctx); // heap type index
+ readULEB128(Ctx); // array size
+ break;
+ case wasm::WASM_OPCODE_REF_I31:
+ break;
case wasm::WASM_OPCODE_END:
Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);
return Error::success();
@@ -258,7 +299,8 @@ static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {
wasm::WasmTableType TableType;
- TableType.ElemType = wasm::ValType(readVaruint32(Ctx));
+ auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
+ TableType.ElemType = ElemType;
TableType.Limits = readLimits(Ctx);
return TableType;
}
@@ -467,10 +509,20 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
llvm::DenseSet<uint64_t> SeenGlobals;
llvm::DenseSet<uint64_t> SeenSegments;
+ // If we have linking section (symbol table) or if we are parsing a DSO
+ // then we don't use the name section for symbol information.
+ bool PopulateSymbolTable = !HasLinkingSection && !HasDylinkSection;
+
+ // If we are using the name section for symbol information then it will
+ // supersede any symbols created by the export section.
+ if (PopulateSymbolTable)
+ Symbols.clear();
+
while (Ctx.Ptr < Ctx.End) {
uint8_t Type = readUint8(Ctx);
uint32_t Size = readVaruint32(Ctx);
const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
+
switch (Type) {
case wasm::WASM_NAMES_FUNCTION:
case wasm::WASM_NAMES_GLOBAL:
@@ -480,6 +532,16 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
uint32_t Index = readVaruint32(Ctx);
StringRef Name = readString(Ctx);
wasm::NameType nameType = wasm::NameType::FUNCTION;
+ wasm::WasmSymbolInfo Info{Name,
+ /*Kind */ wasm::WASM_SYMBOL_TYPE_FUNCTION,
+ /* Flags */ 0,
+ /* ImportModule */ std::nullopt,
+ /* ImportName */ std::nullopt,
+ /* ExportName */ std::nullopt,
+ {/* ElementIndex */ Index}};
+ const wasm::WasmSignature *Signature = nullptr;
+ const wasm::WasmGlobalType *GlobalType = nullptr;
+ const wasm::WasmTableType *TableType = nullptr;
if (Type == wasm::WASM_NAMES_FUNCTION) {
if (!SeenFunctions.insert(Index).second)
return make_error<GenericBinaryError>(
@@ -488,26 +550,50 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
return make_error<GenericBinaryError>("invalid function name entry",
object_error::parse_failed);
- if (isDefinedFunctionIndex(Index))
- getDefinedFunction(Index).DebugName = Name;
+ if (isDefinedFunctionIndex(Index)) {
+ wasm::WasmFunction &F = getDefinedFunction(Index);
+ F.DebugName = Name;
+ Signature = &Signatures[F.SigIndex];
+ if (F.ExportName) {
+ Info.ExportName = F.ExportName;
+ Info.Flags |= wasm::WASM_SYMBOL_BINDING_GLOBAL;
+ } else {
+ Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
+ }
+ } else {
+ Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED;
+ }
} 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 global name entry",
object_error::parse_failed);
+ nameType = wasm::NameType::GLOBAL;
+ Info.Kind = wasm::WASM_SYMBOL_TYPE_GLOBAL;
+ if (isDefinedGlobalIndex(Index)) {
+ GlobalType = &getDefinedGlobal(Index).Type;
+ } else {
+ Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED;
+ }
} 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 data segment name entry",
object_error::parse_failed);
+ nameType = wasm::NameType::DATA_SEGMENT;
+ Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA;
+ Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
+ assert(Index < DataSegments.size());
+ Info.DataRef = wasm::WasmDataReference{
+ Index, 0, DataSegments[Index].Data.Content.size()};
}
DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
+ if (PopulateSymbolTable)
+ Symbols.emplace_back(Info, GlobalType, TableType, Signature);
}
break;
}
@@ -601,9 +687,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
uint32_t Count = readVaruint32(Ctx);
// Clear out any symbol information that was derived from the exports
// section.
- LinkingData.SymbolTable.clear();
Symbols.clear();
- LinkingData.SymbolTable.reserve(Count);
Symbols.reserve(Count);
StringSet<> SymbolNames;
@@ -803,9 +887,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
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, TableType,
- Signature);
+ Symbols.emplace_back(Info, GlobalType, TableType, Signature);
LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
}
@@ -956,6 +1038,13 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
if (Reloc.Offset < PreviousOffset)
return make_error<GenericBinaryError>("relocations not in offset order",
object_error::parse_failed);
+
+ auto badReloc = [&](StringRef msg) {
+ return make_error<GenericBinaryError>(
+ msg + ": " + Twine(Symbols[Reloc.Index].Info.Name),
+ object_error::parse_failed);
+ };
+
PreviousOffset = Reloc.Offset;
Reloc.Index = readVaruint32(Ctx);
switch (type) {
@@ -968,18 +1057,15 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
if (!isValidFunctionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>(
- "invalid relocation function index", object_error::parse_failed);
+ return badReloc("invalid function relocation");
break;
case wasm::R_WASM_TABLE_NUMBER_LEB:
if (!isValidTableSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation table index",
- object_error::parse_failed);
+ return badReloc("invalid table relocation");
break;
case wasm::R_WASM_TYPE_INDEX_LEB:
if (Reloc.Index >= Signatures.size())
- return make_error<GenericBinaryError>("invalid relocation type index",
- object_error::parse_failed);
+ return badReloc("invalid relocation type index");
break;
case wasm::R_WASM_GLOBAL_INDEX_LEB:
// R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
@@ -987,18 +1073,15 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
if (!isValidGlobalSymbol(Reloc.Index) &&
!isValidDataSymbol(Reloc.Index) &&
!isValidFunctionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation global index",
- object_error::parse_failed);
+ return badReloc("invalid global relocation");
break;
case wasm::R_WASM_GLOBAL_INDEX_I32:
if (!isValidGlobalSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation global index",
- object_error::parse_failed);
+ return badReloc("invalid global relocation");
break;
case wasm::R_WASM_TAG_INDEX_LEB:
if (!isValidTagSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation tag index",
- object_error::parse_failed);
+ return badReloc("invalid tag relocation");
break;
case wasm::R_WASM_MEMORY_ADDR_LEB:
case wasm::R_WASM_MEMORY_ADDR_SLEB:
@@ -1007,8 +1090,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
if (!isValidDataSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation data index",
- object_error::parse_failed);
+ return badReloc("invalid data relocation");
Reloc.Addend = readVarint32(Ctx);
break;
case wasm::R_WASM_MEMORY_ADDR_LEB64:
@@ -1017,26 +1099,22 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
if (!isValidDataSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation data index",
- object_error::parse_failed);
+ return badReloc("invalid data relocation");
Reloc.Addend = readVarint64(Ctx);
break;
case wasm::R_WASM_FUNCTION_OFFSET_I32:
if (!isValidFunctionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>(
- "invalid relocation function index", object_error::parse_failed);
+ return badReloc("invalid function relocation");
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);
+ return badReloc("invalid function relocation");
Reloc.Addend = readVarint64(Ctx);
break;
case wasm::R_WASM_SECTION_OFFSET_I32:
if (!isValidSectionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>(
- "invalid relocation section index", object_error::parse_failed);
+ return badReloc("invalid section relocation");
Reloc.Addend = readVarint32(Ctx);
break;
default:
@@ -1104,26 +1182,75 @@ Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
}
Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
+ auto parseFieldDef = [&]() {
+ uint32_t TypeCode = readVaruint32((Ctx));
+ /* Discard StorageType */ parseValType(Ctx, TypeCode);
+ /* Discard Mutability */ readVaruint32(Ctx);
+ };
+
uint32_t Count = readVaruint32(Ctx);
Signatures.reserve(Count);
while (Count--) {
wasm::WasmSignature Sig;
uint8_t Form = readUint8(Ctx);
+ if (Form == wasm::WASM_TYPE_REC) {
+ // Rec groups expand the type index space (beyond what was declared at
+ // the top of the section, and also consume one element in that space.
+ uint32_t RecSize = readVaruint32(Ctx);
+ if (RecSize == 0)
+ return make_error<GenericBinaryError>("Rec group size cannot be 0",
+ object_error::parse_failed);
+ Signatures.reserve(Signatures.size() + RecSize);
+ Count += RecSize;
+ Sig.Kind = wasm::WasmSignature::Placeholder;
+ Signatures.push_back(std::move(Sig));
+ HasUnmodeledTypes = true;
+ continue;
+ }
if (Form != wasm::WASM_TYPE_FUNC) {
- return make_error<GenericBinaryError>("invalid signature type",
- object_error::parse_failed);
+ // Currently LLVM only models function types, and not other composite
+ // types. Here we parse the type declarations just enough to skip past
+ // them in the binary.
+ if (Form == wasm::WASM_TYPE_SUB || Form == wasm::WASM_TYPE_SUB_FINAL) {
+ uint32_t Supers = readVaruint32(Ctx);
+ if (Supers > 0) {
+ if (Supers != 1)
+ return make_error<GenericBinaryError>(
+ "Invalid number of supertypes", object_error::parse_failed);
+ /* Discard SuperIndex */ readVaruint32(Ctx);
+ }
+ Form = readVaruint32(Ctx);
+ }
+ if (Form == wasm::WASM_TYPE_STRUCT) {
+ uint32_t FieldCount = readVaruint32(Ctx);
+ while (FieldCount--) {
+ parseFieldDef();
+ }
+ } else if (Form == wasm::WASM_TYPE_ARRAY) {
+ parseFieldDef();
+ } else {
+ return make_error<GenericBinaryError>("bad form",
+ object_error::parse_failed);
+ }
+ Sig.Kind = wasm::WasmSignature::Placeholder;
+ Signatures.push_back(std::move(Sig));
+ HasUnmodeledTypes = true;
+ continue;
}
+
uint32_t ParamCount = readVaruint32(Ctx);
Sig.Params.reserve(ParamCount);
while (ParamCount--) {
uint32_t ParamType = readUint8(Ctx);
- Sig.Params.push_back(wasm::ValType(ParamType));
+ Sig.Params.push_back(parseValType(Ctx, ParamType));
+ continue;
}
uint32_t ReturnCount = readVaruint32(Ctx);
while (ReturnCount--) {
uint32_t ReturnType = readUint8(Ctx);
- Sig.Returns.push_back(wasm::ValType(ReturnType));
+ Sig.Returns.push_back(parseValType(Ctx, ReturnType));
}
+
Signatures.push_back(std::move(Sig));
}
if (Ctx.Ptr != Ctx.End)
@@ -1164,7 +1291,9 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
NumImportedTables++;
auto ElemType = Im.Table.ElemType;
if (ElemType != wasm::ValType::FUNCREF &&
- ElemType != wasm::ValType::EXTERNREF)
+ ElemType != wasm::ValType::EXTERNREF &&
+ ElemType != wasm::ValType::EXNREF &&
+ ElemType != wasm::ValType::OTHERREF)
return make_error<GenericBinaryError>("invalid table element type",
object_error::parse_failed);
break;
@@ -1221,7 +1350,9 @@ Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
Tables.push_back(T);
auto ElemType = Tables.back().Type.ElemType;
if (ElemType != wasm::ValType::FUNCREF &&
- ElemType != wasm::ValType::EXTERNREF) {
+ ElemType != wasm::ValType::EXTERNREF &&
+ ElemType != wasm::ValType::EXNREF &&
+ ElemType != wasm::ValType::OTHERREF) {
return make_error<GenericBinaryError>("invalid table element type",
object_error::parse_failed);
}
@@ -1263,6 +1394,7 @@ Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
wasm::WasmTag Tag;
Tag.Index = NumImportedTags + Tags.size();
Tag.SigIndex = Type;
+ Signatures[Type].Kind = wasm::WasmSignature::Tag;
Tags.push_back(Tag);
}
@@ -1274,15 +1406,20 @@ Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
GlobalSection = Sections.size();
+ const uint8_t *SectionStart = Ctx.Ptr;
uint32_t Count = readVaruint32(Ctx);
Globals.reserve(Count);
while (Count--) {
wasm::WasmGlobal Global;
Global.Index = NumImportedGlobals + Globals.size();
- Global.Type.Type = readUint8(Ctx);
+ const uint8_t *GlobalStart = Ctx.Ptr;
+ Global.Offset = static_cast<uint32_t>(GlobalStart - SectionStart);
+ auto GlobalOpcode = readVaruint32(Ctx);
+ Global.Type.Type = (uint8_t)parseValType(Ctx, GlobalOpcode);
Global.Type.Mutable = readVaruint1(Ctx);
if (Error Err = readInitExpr(Global.InitExpr, Ctx))
return Err;
+ Global.Size = static_cast<uint32_t>(Ctx.Ptr - GlobalStart);
Globals.push_back(Global);
}
if (Ctx.Ptr != Ctx.End)
@@ -1294,7 +1431,6 @@ Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
uint32_t Count = readVaruint32(Ctx);
Exports.reserve(Count);
- LinkingData.SymbolTable.reserve(Count);
Symbols.reserve(Count);
for (uint32_t I = 0; I < Count; I++) {
wasm::WasmExport Ex;
@@ -1359,9 +1495,7 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
}
Exports.push_back(Ex);
if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) {
- LinkingData.SymbolTable.emplace_back(Info);
- Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType,
- TableType, Signature);
+ Symbols.emplace_back(Info, GlobalType, TableType, Signature);
LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
}
}
@@ -1438,7 +1572,7 @@ WasmObjectFile::getDefinedFunction(uint32_t Index) const {
return Functions[Index - NumImportedFunctions];
}
-wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
+const wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) const {
assert(isDefinedGlobalIndex(Index));
return Globals[Index - NumImportedGlobals];
}
@@ -1516,15 +1650,28 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
return make_error<GenericBinaryError>(
"Unsupported flags for element segment", object_error::parse_failed);
- if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
+ bool IsPassive = (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) != 0;
+ bool IsDeclarative =
+ IsPassive && (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE);
+ bool HasTableNumber =
+ !IsPassive &&
+ (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER);
+ bool HasInitExprs =
+ (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS);
+ bool HasElemKind =
+ (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) &&
+ !HasInitExprs;
+
+ if (HasTableNumber)
Segment.TableNumber = readVaruint32(Ctx);
else
Segment.TableNumber = 0;
+
if (!isValidTableNumber(Segment.TableNumber))
return make_error<GenericBinaryError>("invalid TableNumber",
object_error::parse_failed);
- if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
+ if (IsPassive || IsDeclarative) {
Segment.Offset.Extended = false;
Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
Segment.Offset.Inst.Value.Int32 = 0;
@@ -1533,33 +1680,42 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
return Err;
}
- if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
+ if (HasElemKind) {
auto ElemKind = readVaruint32(Ctx);
if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
- Segment.ElemKind = wasm::ValType(ElemKind);
+ Segment.ElemKind = parseValType(Ctx, ElemKind);
if (Segment.ElemKind != wasm::ValType::FUNCREF &&
- Segment.ElemKind != wasm::ValType::EXTERNREF) {
- return make_error<GenericBinaryError>("invalid reference type",
+ Segment.ElemKind != wasm::ValType::EXTERNREF &&
+ Segment.ElemKind != wasm::ValType::EXNREF &&
+ Segment.ElemKind != wasm::ValType::OTHERREF) {
+ return make_error<GenericBinaryError>("invalid elem type",
object_error::parse_failed);
}
} else {
if (ElemKind != 0)
- return make_error<GenericBinaryError>("invalid elemtype",
+ return make_error<GenericBinaryError>("invalid elem type",
object_error::parse_failed);
Segment.ElemKind = wasm::ValType::FUNCREF;
}
+ } else if (HasInitExprs) {
+ auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
+ Segment.ElemKind = ElemType;
} else {
Segment.ElemKind = wasm::ValType::FUNCREF;
}
- if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS)
- return make_error<GenericBinaryError>(
- "elem segment init expressions not yet implemented",
- object_error::parse_failed);
-
uint32_t NumElems = readVaruint32(Ctx);
- while (NumElems--) {
- Segment.Functions.push_back(readVaruint32(Ctx));
+
+ if (HasInitExprs) {
+ while (NumElems--) {
+ wasm::WasmInitExpr Expr;
+ if (Error Err = readInitExpr(Expr, Ctx))
+ return Err;
+ }
+ } else {
+ while (NumElems--) {
+ Segment.Functions.push_back(readVaruint32(Ctx));
+ }
}
ElemSegments.push_back(Segment);
}
@@ -1668,18 +1824,22 @@ Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
auto &Sym = getWasmSymbol(Symb);
+ if (!Sym.isDefined())
+ return 0;
+ Expected<section_iterator> Sec = getSymbolSection(Symb);
+ if (!Sec)
+ return Sec.takeError();
+ uint32_t SectionAddress = getSectionAddress(Sec.get()->getRawDataRefImpl());
if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
- // For object files, use the section offset. The linker relies on this.
- // For linked files, use the file offset. This behavior matches the way
- // browsers print stack traces and is useful for binary size analysis.
- // (see https://webassembly.github.io/spec/web-api/index.html#conventions)
- uint32_t Adjustment = isRelocatableObject() || isSharedObject()
- ? 0
- : Sections[CodeSection].Offset;
return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
- Adjustment;
+ SectionAddress;
}
+ if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL &&
+ isDefinedGlobalIndex(Sym.Info.ElementIndex)) {
+ return getDefinedGlobal(Sym.Info.ElementIndex).Offset + SectionAddress;
+ }
+
return getSymbolValue(Symb);
}
@@ -1785,6 +1945,22 @@ uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
}
}
+uint32_t WasmObjectFile::getSymbolSize(SymbolRef Symb) const {
+ const WasmSymbol &Sym = getWasmSymbol(Symb);
+ if (!Sym.isDefined())
+ return 0;
+ if (Sym.isTypeGlobal())
+ return getDefinedGlobal(Sym.Info.ElementIndex).Size;
+ if (Sym.isTypeData())
+ return Sym.Info.DataRef.Size;
+ if (Sym.isTypeFunction())
+ return functions()[Sym.Info.ElementIndex - getNumImportedFunctions()].Size;
+ // Currently symbol size is only tracked for data segments and functions. In
+ // principle we could also track size (e.g. binary size) for tables, globals
+ // and element segments etc too.
+ return 0;
+}
+
void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
@@ -1796,7 +1972,13 @@ Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
return wasm::sectionTypeToString(S.Type);
}
-uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
+uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const {
+ // For object files, use 0 for section addresses, and section offsets for
+ // symbol addresses. For linked files, use file offsets.
+ // See also getSymbolAddress.
+ return isRelocatableObject() || isSharedObject() ? 0
+ : Sections[Sec.d.a].Offset;
+}
uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
return Sec.d.a;