diff options
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 db304c027f99..45534ba18212 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.  | 
