aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/WasmObjectFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Object/WasmObjectFile.cpp')
-rw-r--r--llvm/lib/Object/WasmObjectFile.cpp229
1 files changed, 150 insertions, 79 deletions
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index ab8918ce1919..bb2e81d64047 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -12,6 +12,7 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/MC/SubtargetFeature.h"
@@ -155,6 +156,10 @@ static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
return readLEB128(Ctx);
}
+static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
+ return readULEB128(Ctx);
+}
+
static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
return readUint8(Ctx);
}
@@ -179,6 +184,14 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
case wasm::WASM_OPCODE_GLOBAL_GET:
Expr.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);
+ }
+ break;
+ }
default:
return make_error<GenericBinaryError>("Invalid opcode in init_expr",
object_error::parse_failed);
@@ -195,9 +208,9 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
wasm::WasmLimits Result;
Result.Flags = readVaruint32(Ctx);
- Result.Initial = readVaruint32(Ctx);
+ Result.Initial = readVaruint64(Ctx);
if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
- Result.Maximum = readVaruint32(Ctx);
+ Result.Maximum = readVaruint64(Ctx);
return Result;
}
@@ -302,10 +315,10 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) {
return parseTableSection(Ctx);
case wasm::WASM_SEC_MEMORY:
return parseMemorySection(Ctx);
- case wasm::WASM_SEC_GLOBAL:
- return parseGlobalSection(Ctx);
case wasm::WASM_SEC_EVENT:
return parseEventSection(Ctx);
+ case wasm::WASM_SEC_GLOBAL:
+ return parseGlobalSection(Ctx);
case wasm::WASM_SEC_EXPORT:
return parseExportSection(Ctx);
case wasm::WASM_SEC_START:
@@ -508,13 +521,16 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Function.SymbolName = Info.Name;
} else {
wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
- if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
+ if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
Info.Name = readString(Ctx);
- else
+ Info.ImportName = Import.Field;
+ } else {
Info.Name = Import.Field;
+ }
Signature = &Signatures[Import.SigIndex];
- Info.ImportName = Import.Field;
- Info.ImportModule = Import.Module;
+ if (!Import.Module.empty()) {
+ Info.ImportModule = Import.Module;
+ }
}
break;
@@ -537,25 +553,29 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Global.SymbolName = Info.Name;
} else {
wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
- if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
+ if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
Info.Name = readString(Ctx);
- else
+ Info.ImportName = Import.Field;
+ } else {
Info.Name = Import.Field;
+ }
GlobalType = &Import.Global;
Info.ImportName = Import.Field;
- Info.ImportModule = Import.Module;
+ if (!Import.Module.empty()) {
+ Info.ImportModule = Import.Module;
+ }
}
break;
case wasm::WASM_SYMBOL_TYPE_DATA:
Info.Name = readString(Ctx);
if (IsDefined) {
- uint32_t Index = readVaruint32(Ctx);
+ auto Index = readVaruint32(Ctx);
if (Index >= DataSegments.size())
return make_error<GenericBinaryError>("invalid data symbol index",
object_error::parse_failed);
- uint32_t Offset = readVaruint32(Ctx);
- uint32_t Size = readVaruint32(Ctx);
+ auto Offset = readVaruint64(Ctx);
+ auto Size = readVaruint64(Ctx);
if (Offset + Size > DataSegments[Index].Data.Content.size())
return make_error<GenericBinaryError>("invalid data symbol offset",
object_error::parse_failed);
@@ -597,14 +617,17 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
} else {
wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
- if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
+ if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
Info.Name = readString(Ctx);
- else
+ Info.ImportName = Import.Field;
+ } else {
Info.Name = Import.Field;
+ }
EventType = &Import.Event;
Signature = &Signatures[EventType->SigIndex];
- Info.ImportName = Import.Field;
- Info.ImportModule = Import.Module;
+ if (!Import.Module.empty()) {
+ Info.ImportModule = Import.Module;
+ }
}
break;
}
@@ -708,7 +731,7 @@ Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
"Producers section contains repeated producer",
object_error::parse_failed);
}
- ProducerVec->emplace_back(Name, Version);
+ ProducerVec->emplace_back(std::string(Name), std::string(Version));
}
}
if (Ctx.Ptr != Ctx.End)
@@ -732,7 +755,7 @@ Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
return make_error<GenericBinaryError>("Unknown feature policy prefix",
object_error::parse_failed);
}
- Feature.Name = readString(Ctx);
+ Feature.Name = std::string(readString(Ctx));
if (!FeaturesSeen.insert(Feature.Name).second)
return make_error<GenericBinaryError>(
"Target features section contains repeated feature \"" +
@@ -788,6 +811,11 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
return make_error<GenericBinaryError>("Bad 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",
+ object_error::parse_failed);
+ break;
case wasm::R_WASM_EVENT_INDEX_LEB:
if (!isValidEventSymbol(Reloc.Index))
return make_error<GenericBinaryError>("Bad relocation event index",
@@ -802,6 +830,15 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
object_error::parse_failed);
Reloc.Addend = readVarint32(Ctx);
break;
+ case wasm::R_WASM_MEMORY_ADDR_LEB64:
+ case wasm::R_WASM_MEMORY_ADDR_SLEB64:
+ 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",
+ 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",
@@ -824,11 +861,18 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
// also shouldn't overlap a function/element boundary, but we don't bother
// to check that.
uint64_t Size = 5;
+ if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
+ Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
+ Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
+ Size = 10;
if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
- Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32)
+ 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)
+ Size = 8;
if (Reloc.Offset + Size > EndOffset)
return make_error<GenericBinaryError>("Bad relocation offset",
object_error::parse_failed);
@@ -983,6 +1027,24 @@ Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
return Error::success();
}
+Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
+ EventSection = Sections.size();
+ uint32_t Count = readVarint32(Ctx);
+ Events.reserve(Count);
+ while (Count--) {
+ wasm::WasmEvent Event;
+ Event.Index = NumImportedEvents + Events.size();
+ Event.Type.Attribute = readVaruint32(Ctx);
+ Event.Type.SigIndex = readVarint32(Ctx);
+ Events.push_back(Event);
+ }
+
+ if (Ctx.Ptr != Ctx.End)
+ return make_error<GenericBinaryError>("Event section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
GlobalSection = Sections.size();
uint32_t Count = readVaruint32(Ctx);
@@ -1002,24 +1064,6 @@ Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
return Error::success();
}
-Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
- EventSection = Sections.size();
- uint32_t Count = readVarint32(Ctx);
- Events.reserve(Count);
- while (Count--) {
- wasm::WasmEvent Event;
- Event.Index = NumImportedEvents + Events.size();
- Event.Type.Attribute = readVaruint32(Ctx);
- Event.Type.SigIndex = readVarint32(Ctx);
- Events.push_back(Event);
- }
-
- if (Ctx.Ptr != Ctx.End)
- return make_error<GenericBinaryError>("Event section ended prematurely",
- object_error::parse_failed);
- return Error::success();
-}
-
Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
uint32_t Count = readVaruint32(Ctx);
Exports.reserve(Count);
@@ -1250,7 +1294,7 @@ const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
-uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
+Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
uint32_t Result = SymbolRef::SF_None;
const WasmSymbol &Sym = getWasmSymbol(Symb);
@@ -1314,8 +1358,13 @@ uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
// offset within the segment.
uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
- assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST);
- return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
+ if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST) {
+ return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
+ } else if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST) {
+ return Segment.Offset.Value.Int64 + Sym.Info.DataRef.Offset;
+ } else {
+ llvm_unreachable("unknown init expr opcode");
+ }
}
case wasm::WASM_SYMBOL_TYPE_SECTION:
return 0;
@@ -1365,26 +1414,30 @@ WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
return section_end();
DataRefImpl Ref;
+ Ref.d.a = getSymbolSectionIdImpl(Sym);
+ return section_iterator(SectionRef(Ref, this));
+}
+
+uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
+ const WasmSymbol &Sym = getWasmSymbol(Symb);
+ return getSymbolSectionIdImpl(Sym);
+}
+
+uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
switch (Sym.Info.Kind) {
case wasm::WASM_SYMBOL_TYPE_FUNCTION:
- Ref.d.a = CodeSection;
- break;
+ return CodeSection;
case wasm::WASM_SYMBOL_TYPE_GLOBAL:
- Ref.d.a = GlobalSection;
- break;
+ return GlobalSection;
case wasm::WASM_SYMBOL_TYPE_DATA:
- Ref.d.a = DataSection;
- break;
+ return DataSection;
case wasm::WASM_SYMBOL_TYPE_SECTION:
- Ref.d.a = Sym.Info.ElementIndex;
- break;
+ return Sym.Info.ElementIndex;
case wasm::WASM_SYMBOL_TYPE_EVENT:
- Ref.d.a = EventSection;
- break;
+ return EventSection;
default:
llvm_unreachable("Unknown WasmSymbol::SymbolType");
}
- return section_iterator(SectionRef(Ref, this));
}
void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
@@ -1455,8 +1508,6 @@ bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
-bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
-
relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
DataRefImpl RelocRef;
RelocRef.d.a = Ref.d.a;
@@ -1608,30 +1659,50 @@ int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
// Represents the edges in a directed graph where any node B reachable from node
// A is not allowed to appear before A in the section ordering, but may appear
// afterward.
-int WasmSectionOrderChecker::DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
- {}, // WASM_SEC_ORDER_NONE
- {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT}, // WASM_SEC_ORDER_TYPE,
- {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION}, // WASM_SEC_ORDER_IMPORT,
- {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE}, // WASM_SEC_ORDER_FUNCTION,
- {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY}, // WASM_SEC_ORDER_TABLE,
- {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_GLOBAL}, // WASM_SEC_ORDER_MEMORY,
- {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EVENT}, // WASM_SEC_ORDER_GLOBAL,
- {WASM_SEC_ORDER_EVENT, WASM_SEC_ORDER_EXPORT}, // WASM_SEC_ORDER_EVENT,
- {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START}, // WASM_SEC_ORDER_EXPORT,
- {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM}, // WASM_SEC_ORDER_START,
- {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT}, // WASM_SEC_ORDER_ELEM,
- {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE}, // WASM_SEC_ORDER_DATACOUNT,
- {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA}, // WASM_SEC_ORDER_CODE,
- {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING}, // WASM_SEC_ORDER_DATA,
-
- // Custom Sections
- {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE}, // WASM_SEC_ORDER_DYLINK,
- {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME}, // WASM_SEC_ORDER_LINKING,
- {}, // WASM_SEC_ORDER_RELOC (can be repeated),
- {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS}, // WASM_SEC_ORDER_NAME,
- {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES}, // WASM_SEC_ORDER_PRODUCERS,
- {WASM_SEC_ORDER_TARGET_FEATURES} // WASM_SEC_ORDER_TARGET_FEATURES
-};
+int WasmSectionOrderChecker::DisallowedPredecessors
+ [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
+ // WASM_SEC_ORDER_NONE
+ {},
+ // WASM_SEC_ORDER_TYPE
+ {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
+ // WASM_SEC_ORDER_IMPORT
+ {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
+ // WASM_SEC_ORDER_FUNCTION
+ {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
+ // WASM_SEC_ORDER_TABLE
+ {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
+ // WASM_SEC_ORDER_MEMORY
+ {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_EVENT},
+ // WASM_SEC_ORDER_EVENT
+ {WASM_SEC_ORDER_EVENT, WASM_SEC_ORDER_GLOBAL},
+ // WASM_SEC_ORDER_GLOBAL
+ {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
+ // WASM_SEC_ORDER_EXPORT
+ {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
+ // WASM_SEC_ORDER_START
+ {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
+ // WASM_SEC_ORDER_ELEM
+ {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
+ // WASM_SEC_ORDER_DATACOUNT
+ {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
+ // WASM_SEC_ORDER_CODE
+ {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
+ // WASM_SEC_ORDER_DATA
+ {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
+
+ // Custom Sections
+ // WASM_SEC_ORDER_DYLINK
+ {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
+ // WASM_SEC_ORDER_LINKING
+ {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
+ // WASM_SEC_ORDER_RELOC (can be repeated)
+ {},
+ // WASM_SEC_ORDER_NAME
+ {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
+ // WASM_SEC_ORDER_PRODUCERS
+ {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
+ // WASM_SEC_ORDER_TARGET_FEATURES
+ {WASM_SEC_ORDER_TARGET_FEATURES}};
bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
StringRef CustomSectionName) {