diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 |
commit | 08bbd35a80bf7765fe0d3043f9eb5a2f2786b649 (patch) | |
tree | 80108f0f128657f8623f8f66ad9735b4d88e7b47 /lib/MC/WasmObjectWriter.cpp | |
parent | 7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (diff) |
Notes
Diffstat (limited to 'lib/MC/WasmObjectWriter.cpp')
-rw-r--r-- | lib/MC/WasmObjectWriter.cpp | 318 |
1 files changed, 196 insertions, 122 deletions
diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp index db304c027f991..45534ba182123 100644 --- a/lib/MC/WasmObjectWriter.cpp +++ b/lib/MC/WasmObjectWriter.cpp @@ -129,15 +129,15 @@ struct WasmGlobal { // Information about a single relocation. struct WasmRelocationEntry { - uint64_t Offset; // Where is the relocation. - const MCSymbolWasm *Symbol; // The symbol to relocate with. - int64_t Addend; // A value to add to the symbol. - unsigned Type; // The type of the relocation. - MCSectionWasm *FixupSection;// The section the relocation is targeting. + uint64_t Offset; // Where is the relocation. + const MCSymbolWasm *Symbol; // The symbol to relocate with. + int64_t Addend; // A value to add to the symbol. + unsigned Type; // The type of the relocation. + const MCSectionWasm *FixupSection;// The section the relocation is targeting. WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol, int64_t Addend, unsigned Type, - MCSectionWasm *FixupSection) + const MCSectionWasm *FixupSection) : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type), FixupSection(FixupSection) {} @@ -156,9 +156,19 @@ struct WasmRelocationEntry { Out << "Off=" << Offset << ", Sym=" << Symbol << ", Addend=" << Addend << ", Type=" << Type << ", FixupSection=" << FixupSection; } - void dump() const { print(errs()); } + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + LLVM_DUMP_METHOD void dump() const { print(dbgs()); } +#endif }; +#if !defined(NDEBUG) +raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) { + Rel.print(OS); + return OS; +} +#endif + class WasmObjectWriter : public MCObjectWriter { /// Helper struct for containing some precomputed information on symbols. struct WasmSymbolData { @@ -229,6 +239,11 @@ private: void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; + void writeString(const StringRef Str) { + encodeULEB128(Str.size(), getStream()); + writeBytes(Str); + } + void writeValueType(wasm::ValType Ty) { encodeSLEB128(int32_t(Ty), getStream()); } @@ -250,7 +265,8 @@ private: uint32_t NumFuncImports); void writeCodeRelocSection(); void writeDataRelocSection(uint64_t DataSectionHeaderSize); - void writeLinkingMetaDataSection(bool HasStackPointer, + void writeLinkingMetaDataSection(ArrayRef<StringRef> WeakSymbols, + bool HasStackPointer, uint32_t StackPointerGlobal); void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations, @@ -282,6 +298,7 @@ void WasmObjectWriter::startSection(SectionBookkeeping &Section, assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) && "Only custom sections can have names"); + DEBUG(dbgs() << "startSection " << SectionId << ": " << Name << "\n"); encodeULEB128(SectionId, getStream()); Section.SizeOffset = getStream().tell(); @@ -295,8 +312,8 @@ void WasmObjectWriter::startSection(SectionBookkeeping &Section, // Custom sections in wasm also have a string identifier. if (SectionId == wasm::WASM_SEC_CUSTOM) { - encodeULEB128(strlen(Name), getStream()); - writeBytes(Name); + assert(Name); + writeString(StringRef(Name)); } } @@ -307,6 +324,7 @@ void WasmObjectWriter::endSection(SectionBookkeeping &Section) { if (uint32_t(Size) != Size) report_fatal_error("section size does not fit in a uint32_t"); + DEBUG(dbgs() << "endSection size=" << Size << "\n"); unsigned Padding = PaddingFor5ByteULEB128(Size); // Write the final section size to the payload_len field, which follows @@ -332,7 +350,7 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) { - MCSectionWasm &FixupSection = cast<MCSectionWasm>(*Fragment->getParent()); + const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent()); uint64_t C = Target.getConstant(); uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); MCContext &Ctx = Asm.getContext(); @@ -406,9 +424,12 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, } assert(!IsPCRel); + assert(SymA); + unsigned Type = getRelocType(Target, Fixup); WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection); + DEBUG(dbgs() << "WasmReloc: " << Rec << "\n"); if (FixupSection.hasInstructions()) CodeRelocations.push_back(Rec); @@ -453,11 +474,10 @@ static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) { const MCSymbolWasm *Sym = RelEntry.Symbol; // For undefined symbols, use a hopefully invalid value. - if (!Sym->isDefined(false)) + if (!Sym->isDefined(/*SetUsed=*/false)) return UINT32_MAX; - MCSectionWasm &Section = - cast<MCSectionWasm>(RelEntry.Symbol->getSection(false)); + const auto &Section = cast<MCSectionWasm>(RelEntry.Symbol->getSection(false)); uint64_t Address = Section.getSectionOffset() + RelEntry.Addend; // Ignore overflow. LLVM allows address arithmetic to silently wrap. @@ -471,16 +491,23 @@ uint32_t WasmObjectWriter::getRelocationIndexValue( switch (RelEntry.Type) { case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: - assert(IndirectSymbolIndices.count(RelEntry.Symbol)); + if (!IndirectSymbolIndices.count(RelEntry.Symbol)) + report_fatal_error("symbol not found table index space:" + + RelEntry.Symbol->getName()); return IndirectSymbolIndices[RelEntry.Symbol]; case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: - assert(SymbolIndices.count(RelEntry.Symbol)); + if (!SymbolIndices.count(RelEntry.Symbol)) + report_fatal_error("symbol not found function/global index space:" + + RelEntry.Symbol->getName()); return SymbolIndices[RelEntry.Symbol]; case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: - assert(TypeIndices.count(RelEntry.Symbol)); + if (!TypeIndices.count(RelEntry.Symbol)) + report_fatal_error("symbol not found in type index space:" + + RelEntry.Symbol->getName()); return TypeIndices[RelEntry.Symbol]; default: llvm_unreachable("invalid relocation type"); @@ -497,10 +524,12 @@ void WasmObjectWriter::applyRelocations( RelEntry.FixupSection->getSectionOffset() + RelEntry.Offset; + DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n"); switch (RelEntry.Type) { case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: { + case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: { uint32_t Index = getRelocationIndexValue(RelEntry); WritePatchableSLEB(Stream, Index, Offset); break; @@ -526,7 +555,7 @@ void WasmObjectWriter::applyRelocations( break; } default: - llvm_unreachable("unsupported relocation type"); + llvm_unreachable("invalid relocation type"); } } } @@ -573,6 +602,7 @@ void WasmObjectWriter::writeTypeSection( endSection(Section); } + void WasmObjectWriter::writeImportSection( const SmallVector<WasmImport, 4> &Imports) { if (Imports.empty()) @@ -583,13 +613,8 @@ void WasmObjectWriter::writeImportSection( encodeULEB128(Imports.size(), getStream()); for (const WasmImport &Import : Imports) { - StringRef ModuleName = Import.ModuleName; - encodeULEB128(ModuleName.size(), getStream()); - writeBytes(ModuleName); - - StringRef FieldName = Import.FieldName; - encodeULEB128(FieldName.size(), getStream()); - writeBytes(FieldName); + writeString(Import.ModuleName); + writeString(Import.FieldName); encodeULEB128(Import.Kind, getStream()); @@ -697,11 +722,8 @@ void WasmObjectWriter::writeExportSection( encodeULEB128(Exports.size(), getStream()); for (const WasmExport &Export : Exports) { - encodeULEB128(Export.FieldName.size(), getStream()); - writeBytes(Export.FieldName); - + writeString(Export.FieldName); encodeSLEB128(Export.Kind, getStream()); - encodeULEB128(Export.Index, getStream()); } @@ -743,17 +765,7 @@ void WasmObjectWriter::writeCodeSection( encodeULEB128(Functions.size(), getStream()); for (const WasmFunction &Func : Functions) { - MCSectionWasm &FuncSection = - static_cast<MCSectionWasm &>(Func.Sym->getSection()); - - if (Func.Sym->isVariable()) - report_fatal_error("weak symbols not supported yet"); - - if (Func.Sym->getOffset() != 0) - report_fatal_error("function sections must contain one function each"); - - if (!Func.Sym->getSize()) - report_fatal_error("function symbols must have a size set with .size"); + auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection()); int64_t Size = 0; if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout)) @@ -761,8 +773,7 @@ void WasmObjectWriter::writeCodeSection( encodeULEB128(Size, getStream()); - FuncSection.setSectionOffset(getStream().tell() - - Section.ContentsOffset); + FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset); Asm.writeSectionData(&FuncSection, Layout); } @@ -815,15 +826,13 @@ void WasmObjectWriter::writeNameSection( for (const WasmImport &Import : Imports) { if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) { encodeULEB128(Index, getStream()); - encodeULEB128(Import.FieldName.size(), getStream()); - writeBytes(Import.FieldName); + writeString(Import.FieldName); ++Index; } } for (const WasmFunction &Func : Functions) { encodeULEB128(Index, getStream()); - encodeULEB128(Func.Sym->getName().size(), getStream()); - writeBytes(Func.Sym->getName()); + writeString(Func.Sym->getName()); ++Index; } @@ -868,22 +877,37 @@ void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) { } void WasmObjectWriter::writeLinkingMetaDataSection( - bool HasStackPointer, uint32_t StackPointerGlobal) { - if (!HasStackPointer) + ArrayRef<StringRef> WeakSymbols, bool HasStackPointer, + uint32_t StackPointerGlobal) { + if (!HasStackPointer && WeakSymbols.empty()) return; + SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_CUSTOM, "linking"); + SectionBookkeeping SubSection; - encodeULEB128(1, getStream()); // count + if (HasStackPointer) { + startSection(SubSection, wasm::WASM_STACK_POINTER); + encodeULEB128(StackPointerGlobal, getStream()); // id + endSection(SubSection); + } - encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type - encodeULEB128(StackPointerGlobal, getStream()); // id + if (WeakSymbols.size() != 0) { + startSection(SubSection, wasm::WASM_SYMBOL_INFO); + encodeULEB128(WeakSymbols.size(), getStream()); + for (const StringRef Export: WeakSymbols) { + writeString(Export); + encodeULEB128(wasm::WASM_SYMBOL_FLAG_WEAK, getStream()); + } + endSection(SubSection); + } endSection(Section); } void WasmObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { + DEBUG(dbgs() << "WasmObjectWriter::writeObject\n"); MCContext &Ctx = Asm.getContext(); wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32; @@ -894,6 +918,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, SmallVector<WasmGlobal, 4> Globals; SmallVector<WasmImport, 4> Imports; SmallVector<WasmExport, 4> Exports; + SmallVector<StringRef, 4> WeakSymbols; SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken; unsigned NumFuncImports = 0; unsigned NumGlobalImports = 0; @@ -902,7 +927,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, bool HasStackPointer = false; // Populate the IsAddressTaken set. - for (WasmRelocationEntry RelEntry : CodeRelocations) { + for (const WasmRelocationEntry &RelEntry : CodeRelocations) { switch (RelEntry.Type) { case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: @@ -912,7 +937,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, break; } } - for (WasmRelocationEntry RelEntry : DataRelocations) { + for (const WasmRelocationEntry &RelEntry : DataRelocations) { switch (RelEntry.Type) { case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: @@ -975,7 +1000,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, const MCFragment &Frag = *GlobalVars->begin(); if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) report_fatal_error("only data supported in .global_variables"); - const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag); + const auto &DataFrag = cast<MCDataFragment>(Frag); if (!DataFrag.getFixups().empty()) report_fatal_error("fixups not supported in .global_variables"); const SmallVectorImpl<char> &Contents = DataFrag.getContents(); @@ -1031,7 +1056,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, const MCFragment &Frag = *StackPtr->begin(); if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) report_fatal_error("only data supported in .stack_pointer"); - const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag); + const auto &DataFrag = cast<MCDataFragment>(Frag); if (!DataFrag.getFixups().empty()) report_fatal_error("fixups not supported in .stack_pointer"); const SmallVectorImpl<char> &Contents = DataFrag.getContents(); @@ -1041,14 +1066,30 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data(); } - // Handle defined symbols. + // Handle regular defined and undefined symbols. for (const MCSymbol &S : Asm.symbols()) { // Ignore unnamed temporary symbols, which aren't ever exported, imported, // or used in relocations. if (S.isTemporary() && S.getName().empty()) continue; + + // Variable references (weak references) are handled in a second pass + if (S.isVariable()) + continue; + const auto &WS = static_cast<const MCSymbolWasm &>(S); + DEBUG(dbgs() << "MCSymbol: '" << S << "'" + << " isDefined=" << S.isDefined() << " isExternal=" + << S.isExternal() << " isTemporary=" << S.isTemporary() + << " isFunction=" << WS.isFunction() + << " isWeak=" << WS.isWeak() + << " isVariable=" << WS.isVariable() << "\n"); + + if (WS.isWeak()) + WeakSymbols.push_back(WS.getName()); + unsigned Index; + if (WS.isFunction()) { // Prepare the function's type, if we haven't seen it yet. WasmFunctionType F; @@ -1062,6 +1103,14 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, int32_t Type = Pair.first->second; if (WS.isDefined(/*SetUsed=*/false)) { + if (WS.getOffset() != 0) + report_fatal_error( + "function sections must contain one function each"); + + if (WS.getSize() == 0) + report_fatal_error( + "function symbols must have a size set with .size"); + // A definition. Take the next available index. Index = NumFuncImports + Functions.size(); @@ -1072,6 +1121,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, SymbolIndices[&WS] = Index; Functions.push_back(Func); } else { + // Should be no such thing as weak undefined symbol + assert(!WS.isVariable()); + // An import; the index was assigned above. Index = SymbolIndices.find(&WS)->second; } @@ -1085,86 +1137,108 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, if (WS.isTemporary() && !WS.getSize()) continue; - if (WS.isDefined(false)) { - if (WS.getOffset() != 0) - report_fatal_error("data sections must contain one variable each: " + - WS.getName()); - if (!WS.getSize()) - report_fatal_error("data symbols must have a size set with .size: " + - WS.getName()); - - int64_t Size = 0; - if (!WS.getSize()->evaluateAsAbsolute(Size, Layout)) - report_fatal_error(".size expression must be evaluatable"); - - MCSectionWasm &DataSection = - static_cast<MCSectionWasm &>(WS.getSection()); - - if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection)) - report_fatal_error("data sections must contain at most one variable"); - - DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment())); - - DataSection.setSectionOffset(DataBytes.size()); - - for (MCSection::iterator I = DataSection.begin(), E = DataSection.end(); - I != E; ++I) { - const MCFragment &Frag = *I; - if (Frag.hasInstructions()) - report_fatal_error("only data supported in data sections"); - - if (const MCAlignFragment *Align = dyn_cast<MCAlignFragment>(&Frag)) { - if (Align->getValueSize() != 1) - report_fatal_error("only byte values supported for alignment"); - // If nops are requested, use zeros, as this is the data section. - uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue(); - uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(), - Align->getAlignment()), - DataBytes.size() + - Align->getMaxBytesToEmit()); - DataBytes.resize(Size, Value); - } else if (const MCFillFragment *Fill = - dyn_cast<MCFillFragment>(&Frag)) { - DataBytes.insert(DataBytes.end(), Size, Fill->getValue()); - } else { - const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag); - const SmallVectorImpl<char> &Contents = DataFrag.getContents(); - - DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end()); - } - } - - // For each global, prepare a corresponding wasm global holding its - // address. For externals these will also be named exports. - Index = NumGlobalImports + Globals.size(); + if (!WS.isDefined(/*SetUsed=*/false)) + continue; - WasmGlobal Global; - Global.Type = PtrType; - Global.IsMutable = false; - Global.HasImport = false; - Global.InitialValue = DataSection.getSectionOffset(); - Global.ImportIndex = 0; - SymbolIndices[&WS] = Index; - Globals.push_back(Global); + if (WS.getOffset() != 0) + report_fatal_error("data sections must contain one variable each: " + + WS.getName()); + if (!WS.getSize()) + report_fatal_error("data symbols must have a size set with .size: " + + WS.getName()); + + int64_t Size = 0; + if (!WS.getSize()->evaluateAsAbsolute(Size, Layout)) + report_fatal_error(".size expression must be evaluatable"); + + auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection()); + + if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection)) + report_fatal_error("data sections must contain at most one variable"); + + DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment())); + + DataSection.setSectionOffset(DataBytes.size()); + + for (const MCFragment &Frag : DataSection) { + if (Frag.hasInstructions()) + report_fatal_error("only data supported in data sections"); + + if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) { + if (Align->getValueSize() != 1) + report_fatal_error("only byte values supported for alignment"); + // If nops are requested, use zeros, as this is the data section. + uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue(); + uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(), + Align->getAlignment()), + DataBytes.size() + + Align->getMaxBytesToEmit()); + DataBytes.resize(Size, Value); + } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) { + DataBytes.insert(DataBytes.end(), Size, Fill->getValue()); + } else { + const auto &DataFrag = cast<MCDataFragment>(Frag); + const SmallVectorImpl<char> &Contents = DataFrag.getContents(); + + DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end()); + } } + + // For each global, prepare a corresponding wasm global holding its + // address. For externals these will also be named exports. + Index = NumGlobalImports + Globals.size(); + + WasmGlobal Global; + Global.Type = PtrType; + Global.IsMutable = false; + Global.HasImport = false; + Global.InitialValue = DataSection.getSectionOffset(); + Global.ImportIndex = 0; + SymbolIndices[&WS] = Index; + Globals.push_back(Global); } // If the symbol is visible outside this translation unit, export it. - if (WS.isExternal()) { - assert(WS.isDefined(false)); + if (WS.isExternal() && WS.isDefined(/*SetUsed=*/false)) { WasmExport Export; Export.FieldName = WS.getName(); Export.Index = Index; - if (WS.isFunction()) Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; else Export.Kind = wasm::WASM_EXTERNAL_GLOBAL; - Exports.push_back(Export); } } + // Handle weak aliases + for (const MCSymbol &S : Asm.symbols()) { + if (!S.isVariable()) + continue; + assert(S.isExternal()); + assert(S.isDefined(/*SetUsed=*/false)); + + const auto &WS = static_cast<const MCSymbolWasm &>(S); + + // Find the target symbol of this weak alias + const MCExpr *Expr = WS.getVariableValue(); + auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr); + const auto *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol()); + uint32_t Index = SymbolIndices.find(ResolvedSym)->second; + DEBUG(dbgs() << "Weak alias: '" << WS << "' -> '" << ResolvedSym << "' = " << Index << "\n"); + SymbolIndices[&WS] = Index; + + WasmExport Export; + Export.FieldName = WS.getName(); + Export.Index = Index; + if (WS.isFunction()) + Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; + else + Export.Kind = wasm::WASM_EXTERNAL_GLOBAL; + WeakSymbols.push_back(Export.FieldName); + Exports.push_back(Export); + } + // Add types for indirect function calls. for (const WasmRelocationEntry &Fixup : CodeRelocations) { if (Fixup.Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) @@ -1198,7 +1272,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, writeNameSection(Functions, Imports, NumFuncImports); writeCodeRelocSection(); writeDataRelocSection(DataSectionHeaderSize); - writeLinkingMetaDataSection(HasStackPointer, StackPointerGlobal); + writeLinkingMetaDataSection(WeakSymbols, HasStackPointer, StackPointerGlobal); // TODO: Translate the .comment section to the output. // TODO: Translate debug sections to the output. |