diff options
Diffstat (limited to 'llvm/lib/Object/WasmObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/WasmObjectFile.cpp | 50 |
1 files changed, 47 insertions, 3 deletions
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp index 168fb57..05bd730 100644 --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -599,6 +599,10 @@ Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) { 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; @@ -1290,37 +1294,75 @@ 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; Ex.Name = readString(Ctx); Ex.Kind = readUint8(Ctx); Ex.Index = readVaruint32(Ctx); + const wasm::WasmSignature *Signature = nullptr; + const wasm::WasmGlobalType *GlobalType = nullptr; + const wasm::WasmTableType *TableType = nullptr; + wasm::WasmSymbolInfo Info; + Info.Name = Ex.Name; + Info.Flags = 0; switch (Ex.Kind) { - case wasm::WASM_EXTERNAL_FUNCTION: - + case wasm::WASM_EXTERNAL_FUNCTION: { if (!isDefinedFunctionIndex(Ex.Index)) return make_error<GenericBinaryError>("invalid function export", object_error::parse_failed); getDefinedFunction(Ex.Index).ExportName = Ex.Name; + Info.Kind = wasm::WASM_SYMBOL_TYPE_FUNCTION; + Info.ElementIndex = Ex.Index; + unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; + wasm::WasmFunction &Function = Functions[FuncIndex]; + Signature = &Signatures[Function.SigIndex]; break; - case wasm::WASM_EXTERNAL_GLOBAL: + } + case wasm::WASM_EXTERNAL_GLOBAL: { if (!isValidGlobalIndex(Ex.Index)) return make_error<GenericBinaryError>("invalid global export", object_error::parse_failed); + Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA; + uint64_t Offset = 0; + if (isDefinedGlobalIndex(Ex.Index)) { + auto Global = getDefinedGlobal(Ex.Index); + if (!Global.InitExpr.Extended) { + auto Inst = Global.InitExpr.Inst; + if (Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) { + Offset = Inst.Value.Int32; + } else if (Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) { + Offset = Inst.Value.Int64; + } + } + } + Info.DataRef = wasm::WasmDataReference{0, Offset, 0}; break; + } case wasm::WASM_EXTERNAL_TAG: if (!isValidTagIndex(Ex.Index)) return make_error<GenericBinaryError>("invalid tag export", object_error::parse_failed); + Info.Kind = wasm::WASM_SYMBOL_TYPE_TAG; + Info.ElementIndex = Ex.Index; break; case wasm::WASM_EXTERNAL_MEMORY: + break; case wasm::WASM_EXTERNAL_TABLE: + Info.Kind = wasm::WASM_SYMBOL_TYPE_TABLE; break; default: return make_error<GenericBinaryError>("unexpected export kind", object_error::parse_failed); } 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); + LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); + } } if (Ctx.Ptr != Ctx.End) return make_error<GenericBinaryError>("export section ended prematurely", @@ -1644,6 +1686,8 @@ uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset; } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) { return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset; + } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) { + return Sym.Info.DataRef.Offset; } else { llvm_unreachable("unknown init expr opcode"); } |