diff options
Diffstat (limited to 'lib/Object/WasmObjectFile.cpp')
-rw-r--r-- | lib/Object/WasmObjectFile.cpp | 310 |
1 files changed, 249 insertions, 61 deletions
diff --git a/lib/Object/WasmObjectFile.cpp b/lib/Object/WasmObjectFile.cpp index 4d4c887b2d97..d84cb48c9fbd 100644 --- a/lib/Object/WasmObjectFile.cpp +++ b/lib/Object/WasmObjectFile.cpp @@ -24,6 +24,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" +#include "llvm/Support/ScopedPrinter.h" #include <algorithm> #include <cassert> #include <cstdint> @@ -37,8 +38,8 @@ using namespace object; void WasmSymbol::print(raw_ostream &Out) const { Out << "Name=" << Info.Name - << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) - << ", Flags=" << Info.Flags; + << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) + << ", Flags=" << Info.Flags; if (!isTypeData()) { Out << ", ElemIndex=" << Info.ElementIndex; } else if (isDefined()) { @@ -62,9 +63,9 @@ ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { return std::move(ObjectFile); } -#define VARINT7_MAX ((1<<7)-1) -#define VARINT7_MIN (-(1<<7)) -#define VARUINT7_MAX (1<<7) +#define VARINT7_MAX ((1 << 7) - 1) +#define VARINT7_MIN (-(1 << 7)) +#define VARUINT7_MAX (1 << 7) #define VARUINT1_MAX (1) static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) { @@ -82,6 +83,8 @@ static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) { } static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) { + if (Ctx.Ptr + 4 > Ctx.End) + report_fatal_error("EOF while reading float64"); int32_t Result = 0; memcpy(&Result, Ctx.Ptr, sizeof(Result)); Ctx.Ptr += sizeof(Result); @@ -89,6 +92,8 @@ static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) { } static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) { + if (Ctx.Ptr + 8 > Ctx.End) + report_fatal_error("EOF while reading float64"); int64_t Result = 0; memcpy(&Result, Ctx.Ptr, sizeof(Result)); Ctx.Ptr += sizeof(Result); @@ -97,7 +102,7 @@ static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) { static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) { unsigned Count; - const char* Error = nullptr; + const char *Error = nullptr; uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error); if (Error) report_fatal_error(Error); @@ -117,7 +122,7 @@ static StringRef readString(WasmObjectFile::ReadContext &Ctx) { static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) { unsigned Count; - const char* Error = nullptr; + const char *Error = nullptr; uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error); if (Error) report_fatal_error(Error); @@ -171,7 +176,7 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr, case wasm::WASM_OPCODE_F64_CONST: Expr.Value.Float64 = readFloat64(Ctx); break; - case wasm::WASM_OPCODE_GET_GLOBAL: + case wasm::WASM_OPCODE_GLOBAL_GET: Expr.Value.Global = readULEB128(Ctx); break; default: @@ -189,7 +194,7 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr, static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) { wasm::WasmLimits Result; - Result.Flags = readVaruint1(Ctx); + Result.Flags = readVaruint32(Ctx); Result.Initial = readVaruint32(Ctx); if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) Result.Maximum = readVaruint32(Ctx); @@ -203,8 +208,8 @@ static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) { return Table; } -static Error readSection(WasmSection &Section, - WasmObjectFile::ReadContext &Ctx) { +static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx, + WasmSectionOrderChecker &Checker) { Section.Offset = Ctx.Ptr - Ctx.Start; Section.Type = readUint8(Ctx); LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n"); @@ -216,10 +221,24 @@ static Error readSection(WasmSection &Section, return make_error<StringError>("Section too large", object_error::parse_failed); if (Section.Type == wasm::WASM_SEC_CUSTOM) { - const uint8_t *NameStart = Ctx.Ptr; - Section.Name = readString(Ctx); - Size -= Ctx.Ptr - NameStart; + WasmObjectFile::ReadContext SectionCtx; + SectionCtx.Start = Ctx.Ptr; + SectionCtx.Ptr = Ctx.Ptr; + SectionCtx.End = Ctx.Ptr + Size; + + Section.Name = readString(SectionCtx); + + uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start; + Ctx.Ptr += SectionNameSize; + Size -= SectionNameSize; + } + + if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) { + return make_error<StringError>("Out of order section type: " + + llvm::to_string(Section.Type), + object_error::parse_failed); } + Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size); Ctx.Ptr += Size; return Error::success(); @@ -230,8 +249,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>("Bad magic number", object_error::parse_failed); return; } @@ -254,8 +273,9 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) } WasmSection Sec; + WasmSectionOrderChecker Checker; while (Ctx.Ptr < Ctx.End) { - if ((Err = readSection(Sec, Ctx))) + if ((Err = readSection(Sec, Ctx, Checker))) return; if ((Err = parseSection(Sec))) return; @@ -284,6 +304,8 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) { return parseMemorySection(Ctx); case wasm::WASM_SEC_GLOBAL: return parseGlobalSection(Ctx); + case wasm::WASM_SEC_EVENT: + return parseEventSection(Ctx); case wasm::WASM_SEC_EXPORT: return parseExportSection(Ctx); case wasm::WASM_SEC_START: @@ -300,6 +322,22 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) { } } +Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) { + // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md + DylinkInfo.MemorySize = readVaruint32(Ctx); + DylinkInfo.MemoryAlignment = readVaruint32(Ctx); + DylinkInfo.TableSize = readVaruint32(Ctx); + DylinkInfo.TableAlignment = readVaruint32(Ctx); + uint32_t Count = readVaruint32(Ctx); + while (Count--) { + DylinkInfo.Needed.push_back(readString(Ctx)); + } + if (Ctx.Ptr != Ctx.End) + return make_error<GenericBinaryError>("dylink section ended prematurely", + object_error::parse_failed); + return Error::success(); +} + Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { llvm::DenseSet<uint64_t> Seen; if (Functions.size() != FunctionTypes.size()) { @@ -336,8 +374,8 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { break; } if (Ctx.Ptr != SubSectionEnd) - return make_error<GenericBinaryError>("Name sub-section ended prematurely", - object_error::parse_failed); + return make_error<GenericBinaryError>( + "Name sub-section ended prematurely", object_error::parse_failed); } if (Ctx.Ptr != Ctx.End) @@ -350,7 +388,8 @@ Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) { HasLinkingSection = true; if (Functions.size() != FunctionTypes.size()) { return make_error<GenericBinaryError>( - "Linking data must come after code section", object_error::parse_failed); + "Linking data must come after code section", + object_error::parse_failed); } LinkingData.Version = readVaruint32(Ctx); @@ -427,19 +466,24 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { std::vector<wasm::WasmImport *> ImportedGlobals; std::vector<wasm::WasmImport *> ImportedFunctions; + std::vector<wasm::WasmImport *> ImportedEvents; ImportedGlobals.reserve(Imports.size()); ImportedFunctions.reserve(Imports.size()); + ImportedEvents.reserve(Imports.size()); for (auto &I : Imports) { if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION) ImportedFunctions.emplace_back(&I); else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL) ImportedGlobals.emplace_back(&I); + else if (I.Kind == wasm::WASM_EXTERNAL_EVENT) + ImportedEvents.emplace_back(&I); } while (Count--) { wasm::WasmSymbolInfo Info; - const wasm::WasmSignature *FunctionType = nullptr; + const wasm::WasmSignature *Signature = nullptr; const wasm::WasmGlobalType *GlobalType = nullptr; + const wasm::WasmEventType *EventType = nullptr; Info.Kind = readUint8(Ctx); Info.Flags = readVaruint32(Ctx); @@ -455,13 +499,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { if (IsDefined) { Info.Name = readString(Ctx); unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; - FunctionType = &Signatures[FunctionTypes[FuncIndex]]; + Signature = &Signatures[FunctionTypes[FuncIndex]]; wasm::WasmFunction &Function = Functions[FuncIndex]; if (Function.SymbolName.empty()) Function.SymbolName = Info.Name; } else { wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; - FunctionType = &Signatures[Import.SigIndex]; + Signature = &Signatures[Import.SigIndex]; Info.Name = Import.Field; Info.Module = Import.Module; } @@ -473,9 +517,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { IsDefined != isDefinedGlobalIndex(Info.ElementIndex)) return make_error<GenericBinaryError>("invalid global symbol index", object_error::parse_failed); - if (!IsDefined && - (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == - wasm::WASM_SYMBOL_BINDING_WEAK) + if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == + wasm::WASM_SYMBOL_BINDING_WEAK) return make_error<GenericBinaryError>("undefined weak global symbol", object_error::parse_failed); if (IsDefined) { @@ -521,6 +564,34 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { break; } + case wasm::WASM_SYMBOL_TYPE_EVENT: { + Info.ElementIndex = readVaruint32(Ctx); + if (!isValidEventIndex(Info.ElementIndex) || + IsDefined != isDefinedEventIndex(Info.ElementIndex)) + return make_error<GenericBinaryError>("invalid event 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 global symbol", + object_error::parse_failed); + if (IsDefined) { + Info.Name = readString(Ctx); + unsigned EventIndex = Info.ElementIndex - NumImportedEvents; + wasm::WasmEvent &Event = Events[EventIndex]; + Signature = &Signatures[Event.Type.SigIndex]; + EventType = &Event.Type; + if (Event.SymbolName.empty()) + Event.SymbolName = Info.Name; + + } else { + wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex]; + EventType = &Import.Event; + Signature = &Signatures[EventType->SigIndex]; + Info.Name = Import.Field; + } + break; + } + default: return make_error<GenericBinaryError>("Invalid symbol type", object_error::parse_failed); @@ -533,8 +604,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Twine(Info.Name), object_error::parse_failed); LinkingData.SymbolTable.emplace_back(Info); - Symbols.emplace_back(LinkingData.SymbolTable.back(), FunctionType, - GlobalType); + Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, EventType, + Signature); LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); } @@ -547,7 +618,8 @@ 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 " + Twine(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); @@ -565,8 +637,8 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) { 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); + 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", object_error::parse_failed); @@ -574,8 +646,8 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) { break; case wasm::WASM_COMDAT_FUNCTION: if (!isDefinedFunctionIndex(Index)) - return make_error<GenericBinaryError>("COMDAT function index out of range", - object_error::parse_failed); + 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", object_error::parse_failed); @@ -592,13 +664,18 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { if (SectionIndex >= Sections.size()) return make_error<GenericBinaryError>("Invalid section index", object_error::parse_failed); - WasmSection& Section = Sections[SectionIndex]; + WasmSection &Section = Sections[SectionIndex]; uint32_t RelocCount = readVaruint32(Ctx); uint32_t EndOffset = Section.Content.size(); + uint32_t PreviousOffset = 0; while (RelocCount--) { wasm::WasmRelocation Reloc = {}; Reloc.Type = readVaruint32(Ctx); Reloc.Offset = readVaruint32(Ctx); + if (Reloc.Offset < PreviousOffset) + return make_error<GenericBinaryError>("Relocations not in offset order", + object_error::parse_failed); + PreviousOffset = Reloc.Offset; Reloc.Index = readVaruint32(Ctx); switch (Reloc.Type) { case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: @@ -618,6 +695,11 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { return make_error<GenericBinaryError>("Bad relocation global index", object_error::parse_failed); break; + case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB: + if (!isValidEventSymbol(Reloc.Index)) + return make_error<GenericBinaryError>("Bad relocation event index", + object_error::parse_failed); + break; case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: @@ -666,7 +748,10 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { } Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) { - if (Sec.Name == "name") { + if (Sec.Name == "dylink") { + if (Error Err = parseDylinkSection(Ctx)) + return Err; + } else if (Sec.Name == "name") { if (Error Err = parseNameSection(Ctx)) return Err; } else if (Sec.Name == "linking") { @@ -684,17 +769,16 @@ Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) { Signatures.reserve(Count); while (Count--) { wasm::WasmSignature Sig; - Sig.ReturnType = wasm::WASM_TYPE_NORESULT; uint8_t Form = readUint8(Ctx); if (Form != wasm::WASM_TYPE_FUNC) { return make_error<GenericBinaryError>("Invalid signature type", object_error::parse_failed); } uint32_t ParamCount = readVaruint32(Ctx); - Sig.ParamTypes.reserve(ParamCount); + Sig.Params.reserve(ParamCount); while (ParamCount--) { uint32_t ParamType = readUint8(Ctx); - Sig.ParamTypes.push_back(ParamType); + Sig.Params.push_back(wasm::ValType(ParamType)); } uint32_t ReturnCount = readVaruint32(Ctx); if (ReturnCount) { @@ -702,9 +786,9 @@ Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) { return make_error<GenericBinaryError>( "Multiple return types not supported", object_error::parse_failed); } - Sig.ReturnType = readUint8(Ctx); + Sig.Returns.push_back(wasm::ValType(readUint8(Ctx))); } - Signatures.push_back(Sig); + Signatures.push_back(std::move(Sig)); } if (Ctx.Ptr != Ctx.End) return make_error<GenericBinaryError>("Type section ended prematurely", @@ -735,13 +819,18 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) { break; case wasm::WASM_EXTERNAL_TABLE: Im.Table = readTable(Ctx); - if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) + if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF) 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", object_error::parse_failed); + return make_error<GenericBinaryError>("Unexpected import kind", + object_error::parse_failed); } Imports.push_back(Im); } @@ -773,7 +862,7 @@ Error WasmObjectFile::parseTableSection(ReadContext &Ctx) { Tables.reserve(Count); while (Count--) { Tables.push_back(readTable(Ctx)); - if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) { + if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) { return make_error<GenericBinaryError>("Invalid table element type", object_error::parse_failed); } @@ -815,6 +904,24 @@ 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); @@ -834,12 +941,17 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) { 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", + object_error::parse_failed); + break; case wasm::WASM_EXTERNAL_MEMORY: case wasm::WASM_EXTERNAL_TABLE: break; default: - return make_error<GenericBinaryError>( - "Unexpected export kind", object_error::parse_failed); + return make_error<GenericBinaryError>("Unexpected export kind", + object_error::parse_failed); } Exports.push_back(Ex); } @@ -865,6 +977,14 @@ bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const { return Index >= NumImportedGlobals && isValidGlobalIndex(Index); } +bool WasmObjectFile::isValidEventIndex(uint32_t Index) const { + return Index < NumImportedEvents + Events.size(); +} + +bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const { + return Index >= NumImportedEvents && isValidEventIndex(Index); +} + bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const { return Index < Symbols.size() && Symbols[Index].isTypeFunction(); } @@ -873,6 +993,10 @@ bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const { return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); } +bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const { + return Index < Symbols.size() && Symbols[Index].isTypeEvent(); +} + bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const { return Index < Symbols.size() && Symbols[Index].isTypeData(); } @@ -891,6 +1015,11 @@ wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) { return Globals[Index - NumImportedGlobals]; } +wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) { + assert(isDefinedEventIndex(Index)); + return Events[Index - NumImportedEvents]; +} + Error WasmObjectFile::parseStartSection(ReadContext &Ctx) { StartFunction = readVaruint32(Ctx); if (!isValidFunctionIndex(StartFunction)) @@ -1050,10 +1179,11 @@ Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { return getSymbolValue(Symb); } -uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const { +uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { switch (Sym.Info.Kind) { case wasm::WASM_SYMBOL_TYPE_FUNCTION: case wasm::WASM_SYMBOL_TYPE_GLOBAL: + case wasm::WASM_SYMBOL_TYPE_EVENT: return Sym.Info.ElementIndex; case wasm::WASM_SYMBOL_TYPE_DATA: { // The value of a data symbol is the segment offset, plus the symbol @@ -1096,6 +1226,8 @@ WasmObjectFile::getSymbolType(DataRefImpl Symb) const { return SymbolRef::ST_Data; case wasm::WASM_SYMBOL_TYPE_SECTION: return SymbolRef::ST_Debug; + case wasm::WASM_SYMBOL_TYPE_EVENT: + return SymbolRef::ST_Other; } llvm_unreachable("Unknown WasmSymbol::SymbolType"); @@ -1104,7 +1236,7 @@ WasmObjectFile::getSymbolType(DataRefImpl Symb) const { Expected<section_iterator> WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { - const WasmSymbol& Sym = getWasmSymbol(Symb); + const WasmSymbol &Sym = getWasmSymbol(Symb); if (Sym.isUndefined()) return section_end(); @@ -1119,10 +1251,12 @@ WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { case wasm::WASM_SYMBOL_TYPE_DATA: Ref.d.a = DataSection; break; - case wasm::WASM_SYMBOL_TYPE_SECTION: { + case wasm::WASM_SYMBOL_TYPE_SECTION: Ref.d.a = Sym.Info.ElementIndex; break; - } + case wasm::WASM_SYMBOL_TYPE_EVENT: + Ref.d.a = EventSection; + break; default: llvm_unreachable("Unknown WasmSymbol::SymbolType"); } @@ -1145,6 +1279,7 @@ std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, ECase(TABLE); ECase(MEMORY); ECase(GLOBAL); + ECase(EVENT); ECase(EXPORT); ECase(START); ECase(ELEM); @@ -1218,9 +1353,7 @@ relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const { return relocation_iterator(RelocationRef(RelocRef, this)); } -void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { - Rel.d.b++; -} +void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; } uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); @@ -1244,12 +1377,12 @@ uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const { void WasmObjectFile::getRelocationTypeName( DataRefImpl Ref, SmallVectorImpl<char> &Result) const { - const wasm::WasmRelocation& Rel = getWasmRelocation(Ref); + const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); StringRef Res = "Unknown"; -#define WASM_RELOC(name, value) \ - case wasm::name: \ - Res = #name; \ +#define WASM_RELOC(name, value) \ + case wasm::name: \ + Res = #name; \ break; switch (Rel.Type) { @@ -1283,9 +1416,9 @@ SubtargetFeatures WasmObjectFile::getFeatures() const { return SubtargetFeatures(); } -bool WasmObjectFile::isRelocatableObject() const { - return HasLinkingSection; -} +bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; } + +bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; } const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { assert(Ref.d.a < Sections.size()); @@ -1305,7 +1438,62 @@ WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const { const wasm::WasmRelocation & WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { assert(Ref.d.a < Sections.size()); - const WasmSection& Sec = Sections[Ref.d.a]; + const WasmSection &Sec = Sections[Ref.d.a]; assert(Ref.d.b < Sec.Relocations.size()); return Sec.Relocations[Ref.d.b]; } + +int WasmSectionOrderChecker::getSectionOrder(unsigned ID, + StringRef CustomSectionName) { + switch (ID) { + case wasm::WASM_SEC_CUSTOM: + return StringSwitch<unsigned>(CustomSectionName) + .Case("dylink", WASM_SEC_ORDER_DYLINK) + .Case("linking", WASM_SEC_ORDER_LINKING) + .StartsWith("reloc.", WASM_SEC_ORDER_RELOC) + .Case("name", WASM_SEC_ORDER_NAME) + .Case("producers", WASM_SEC_ORDER_PRODUCERS) + .Default(-1); + case wasm::WASM_SEC_TYPE: + return WASM_SEC_ORDER_TYPE; + case wasm::WASM_SEC_IMPORT: + return WASM_SEC_ORDER_IMPORT; + case wasm::WASM_SEC_FUNCTION: + return WASM_SEC_ORDER_FUNCTION; + case wasm::WASM_SEC_TABLE: + return WASM_SEC_ORDER_TABLE; + case wasm::WASM_SEC_MEMORY: + return WASM_SEC_ORDER_MEMORY; + case wasm::WASM_SEC_GLOBAL: + return WASM_SEC_ORDER_GLOBAL; + case wasm::WASM_SEC_EXPORT: + return WASM_SEC_ORDER_EXPORT; + case wasm::WASM_SEC_START: + return WASM_SEC_ORDER_START; + case wasm::WASM_SEC_ELEM: + return WASM_SEC_ORDER_ELEM; + case wasm::WASM_SEC_CODE: + return WASM_SEC_ORDER_CODE; + case wasm::WASM_SEC_DATA: + return WASM_SEC_ORDER_DATA; + case wasm::WASM_SEC_DATACOUNT: + return WASM_SEC_ORDER_DATACOUNT; + case wasm::WASM_SEC_EVENT: + return WASM_SEC_ORDER_EVENT; + default: + llvm_unreachable("invalid section"); + } +} + +bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID, + StringRef CustomSectionName) { + int Order = getSectionOrder(ID, CustomSectionName); + if (Order == -1) // Skip unknown sections + return true; + // There can be multiple "reloc." sections. Otherwise there shouldn't be any + // duplicate section orders. + bool IsValid = (LastOrder == Order && Order == WASM_SEC_ORDER_RELOC) || + LastOrder < Order; + LastOrder = Order; + return IsValid; +} |