Index: test/wasm/archive.ll =================================================================== --- test/wasm/archive.ll +++ test/wasm/archive.ll @@ -27,11 +27,9 @@ ; correctly. ; CHECK: 00000003 T _start -; CHECK-NEXT: 00000003 T _start -; CHECK-NEXT: 00000001 T bar ; CHECK-NEXT: 00000001 T bar ; CHECK-NEXT: 00000002 T foo -; CHECK-NEXT: 00000002 T foo +; CHECK-NEXT: U missing_func ; Verify that symbols from unused objects don't appear in the symbol table ; CHECK-NOT: hello Index: test/wasm/data-layout.ll =================================================================== --- test/wasm/data-layout.ll +++ test/wasm/data-layout.ll @@ -45,7 +45,7 @@ ; CHECK: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 -; CHECK-NEXT: Index: 4 +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: Offset: 0x0000001F ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 7 Index: test/wasm/relocatable.ll =================================================================== --- test/wasm/relocatable.ll +++ test/wasm/relocatable.ll @@ -62,8 +62,8 @@ ; CHECK-NEXT: - ElemType: ANYFUNC ; CHECK-NEXT: Limits: ; CHECK-NEXT: Flags: [ HAS_MAX ] -; CHECK-NEXT: Initial: 0x00000002 -; CHECK-NEXT: Maximum: 0x00000002 +; CHECK-NEXT: Initial: 0x00000003 +; CHECK-NEXT: Maximum: 0x00000003 ; CHECK-NEXT: - Type: MEMORY ; CHECK-NEXT: Memories: ; CHECK-NEXT: - Initial: 0x00000001 @@ -129,7 +129,7 @@ ; CHECK-NEXT: Segments: ; CHECK-NEXT: - Offset: ; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 0 +; CHECK-NEXT: Value: 1 ; CHECK-NEXT: Functions: [ 3, 1 ] ; CHECK-NEXT: - Type: CODE ; CHECK-NEXT: Relocations: @@ -158,7 +158,7 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 3 ; CHECK-NEXT: Offset: 0x00000012 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 ; CHECK-NEXT: Index: 1 @@ -178,13 +178,13 @@ ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 -; CHECK-NEXT: Content: '00000000' +; CHECK-NEXT: Content: '01000000' ; CHECK-NEXT: - SectionOffset: 27 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 12 -; CHECK-NEXT: Content: '01000000' +; CHECK-NEXT: Content: '02000000' ; CHECK-NEXT: - SectionOffset: 36 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: @@ -231,12 +231,10 @@ ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: name ; CHECK-NEXT: FunctionNames: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Name: puts -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Name: foo_import ; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Name: hello ; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Name: my_func +; CHECK-NEXT: - Index: 4 +; CHECK-NEXT: Name: func_comdat ; CHECK-NEXT: ... Index: test/wasm/weak-symbols.ll =================================================================== --- test/wasm/weak-symbols.ll +++ test/wasm/weak-symbols.ll @@ -99,8 +99,12 @@ ; CHECK-NEXT: FunctionNames: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: _start +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: weakFn ; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Name: exportWeak1 +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Name: weakFn ; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Name: exportWeak2 ; CHECK-NEXT: ... Index: wasm/InputChunks.h =================================================================== --- wasm/InputChunks.h +++ wasm/InputChunks.h @@ -48,6 +48,7 @@ } uint32_t getOutputOffset() const { return OutputOffset; } + ArrayRef getRelocations() const { return Relocations; } bool Discarded = false; std::vector OutRelocations; @@ -130,12 +131,12 @@ }; const WasmSignature &Signature; + const WasmFunction &Function; protected: uint32_t getInputSectionOffset() const override { return Function.CodeSectionOffset; } - const WasmFunction &Function; llvm::Optional OutputIndex; }; Index: wasm/InputChunks.cpp =================================================================== --- wasm/InputChunks.cpp +++ wasm/InputChunks.cpp @@ -57,12 +57,6 @@ encodeULEB128(Reloc.Value, Buf, 5); break; case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - ExistingValue = decodeSLEB128(Buf); - if (ExistingValue != Reloc.Reloc.Index) { - DEBUG(dbgs() << "existing value: " << decodeSLEB128(Buf) << "\n"); - assert(decodeSLEB128(Buf) == Reloc.Reloc.Index); - } - LLVM_FALLTHROUGH; case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: encodeSLEB128(static_cast(Reloc.Value), Buf, 5); break; @@ -106,17 +100,7 @@ if (Config->EmitRelocs) NewReloc.NewIndex = File.calcNewIndex(Reloc); - - switch (Reloc.Type) { - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_I32: - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - NewReloc.Value = File.getRelocatedAddress(Reloc.Index) + Reloc.Addend; - break; - default: - NewReloc.Value = File.calcNewIndex(Reloc); - break; - } + NewReloc.Value = File.calcNewValue(Reloc); OutRelocations.emplace_back(NewReloc); } Index: wasm/InputFiles.h =================================================================== --- wasm/InputFiles.h +++ wasm/InputFiles.h @@ -93,9 +93,9 @@ void dumpInfo() const; - uint32_t relocateFunctionIndex(uint32_t Original) const; - uint32_t getRelocatedAddress(uint32_t Index) const; + uint32_t relocateFunctionSymbolIndex(uint32_t Original) const; uint32_t calcNewIndex(const WasmRelocation &Reloc) const; + uint32_t calcNewValue(const WasmRelocation &Reloc) const; const WasmSection *CodeSection = nullptr; const WasmSection *DataSection = nullptr; @@ -104,12 +104,15 @@ std::vector Segments; std::vector Functions; - ArrayRef getSymbols() { return Symbols; } - ArrayRef getTableSymbols() { return TableSymbols; } + ArrayRef getSymbols() const { return Symbols; } + ArrayRef getFunctionSymbols() const { return FunctionSymbols; } private: + uint32_t getRelocatedAddress(uint32_t Index) const; uint32_t relocateTypeIndex(uint32_t Original) const; - uint32_t relocateGlobalIndex(uint32_t Original) const; + uint32_t relocateGlobalSymbolIndex(uint32_t Original) const; + uint32_t relocateFunctionWasmIndex(uint32_t Original) const; + uint32_t relocateGlobalWasmIndex(uint32_t Original) const; uint32_t relocateTableIndex(uint32_t Original) const; Symbol *createDefined(const WasmSymbol &Sym, Symbol::Kind Kind, @@ -128,17 +131,22 @@ // List of all symbols referenced or defined by this file. std::vector Symbols; - // List of all function symbols indexed by the function index space + // List of all function symbols indexed by the function Symbol index space, + // that is, function imports followed by function exports (not the Wasm + // function definition index space, function imports followed by function + // bodies). std::vector FunctionSymbols; - // List of all global symbols indexed by the global index space + // List of all global symbols indexed by the global Symbol index space, + // that is, global imports followed by global exports (not the Wasm + // global definition index space, global imports followed by global + // definitions). std::vector GlobalSymbols; - // List of all indirect symbols indexed by table index space. - std::vector TableSymbols; - uint32_t NumGlobalImports = 0; uint32_t NumFunctionImports = 0; + uint32_t NumGlobalExports = 0; + uint32_t NumFunctionExports = 0; std::unique_ptr WasmObj; }; Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -47,38 +47,55 @@ " Total Functions : " + Twine(FunctionSymbols.size()) + "\n" + " Total Globals : " + Twine(GlobalSymbols.size()) + "\n" + " Function Imports : " + Twine(NumFunctionImports) + "\n" + - " Global Imports : " + Twine(NumGlobalImports) + "\n" + - " Table Entries : " + Twine(TableSymbols.size()) + "\n"); + " Global Imports : " + Twine(NumGlobalImports) + "\n"); } uint32_t ObjFile::getRelocatedAddress(uint32_t GlobalIndex) const { return GlobalSymbols[GlobalIndex]->getVirtualAddress(); } -uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const { - Symbol *Sym = FunctionSymbols[Original]; - uint32_t Index = Sym->getOutputIndex(); - DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": " - << Original << " -> " << Index << "\n"); - return Index; -} - uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const { return TypeMap[Original]; } -uint32_t ObjFile::relocateTableIndex(uint32_t Original) const { - Symbol *Sym = TableSymbols[Original]; - uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0; - DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original +uint32_t ObjFile::relocateFunctionSymbolIndex(uint32_t Original) const { + Symbol *Sym = FunctionSymbols[Original]; + uint32_t Index = Sym->getOutputSymbolIndex(); + DEBUG(dbgs() << "relocateFunctionSymbolIndex: " << toString(*Sym) << ": " + << Original << " -> " << Index << "\n"); + return Index; +} + +uint32_t ObjFile::relocateGlobalSymbolIndex(uint32_t Original) const { + Symbol *Sym = GlobalSymbols[Original]; + uint32_t Index = Sym->getOutputSymbolIndex(); + DEBUG(dbgs() << "relocateGlobalSymbolIndex: " << toString(*Sym) << ": " << Original << " -> " << Index << "\n"); return Index; } -uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const { - Symbol *Sym = GlobalSymbols[Original]; +uint32_t ObjFile::relocateFunctionWasmIndex(uint32_t Original) const { + Symbol *Sym = FunctionSymbols[Original]; uint32_t Index = Sym->hasOutputIndex() ? Sym->getOutputIndex() : 0; - DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original + DEBUG(dbgs() << "relocateFunctionWasmIndex: " << toString(*Sym) << ": " + << Original << " -> " << Index << "\n"); + return Index; +} + +uint32_t ObjFile::relocateGlobalWasmIndex(uint32_t Original) const { + Symbol *Sym = GlobalSymbols[Original]; + uint32_t Index = Sym->hasTableIndex() ? Sym->getOutputIndex() : 0; + DEBUG(dbgs() << "relocateGlobalWasmIndex: " << toString(*Sym) << ": " << Original + << " -> " << Index << "\n"); + return Index; +} + +uint32_t ObjFile::relocateTableIndex(uint32_t Original) const { + Symbol *Sym = FunctionSymbols[Original]; + // The null case is possible, if you take the address of a weak function + // that's simply not supplied. + uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0; + DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original << " -> " << Index << "\n"); return Index; } @@ -92,15 +109,35 @@ case R_WEBASSEMBLY_TYPE_INDEX_LEB: return relocateTypeIndex(Reloc.Index); case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - return relocateFunctionIndex(Reloc.Index); case R_WEBASSEMBLY_TABLE_INDEX_I32: case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - return relocateTableIndex(Reloc.Index); + return relocateFunctionSymbolIndex(Reloc.Index); case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: case R_WEBASSEMBLY_MEMORY_ADDR_LEB: case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: case R_WEBASSEMBLY_MEMORY_ADDR_I32: - return relocateGlobalIndex(Reloc.Index); + return relocateGlobalSymbolIndex(Reloc.Index); + default: + llvm_unreachable("unknown relocation type"); + } +} + +// Translate from the relocation's index into the final linked output value. +uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const { + switch (Reloc.Type) { + case R_WEBASSEMBLY_TABLE_INDEX_I32: + case R_WEBASSEMBLY_TABLE_INDEX_SLEB: + return relocateTableIndex(Reloc.Index); + case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: + case R_WEBASSEMBLY_MEMORY_ADDR_I32: + case R_WEBASSEMBLY_MEMORY_ADDR_LEB: + return getRelocatedAddress(Reloc.Index) + Reloc.Addend; + case R_WEBASSEMBLY_TYPE_INDEX_LEB: + return relocateTypeIndex(Reloc.Index); + case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + return relocateFunctionWasmIndex(Reloc.Index); + case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: + return relocateGlobalWasmIndex(Reloc.Index); default: llvm_unreachable("unknown relocation type"); } @@ -151,8 +188,9 @@ // Get the value stored in the wasm global represented by this symbol. // This represents the virtual address of the symbol in the input file. uint32_t ObjFile::getGlobalValue(const WasmSymbol &Sym) const { + assert(Sym.WasmIndex >= getWasmObj()->getNumImportedGlobals()); const WasmGlobal &Global = - getWasmObj()->globals()[Sym.ElementIndex - NumGlobalImports]; + getWasmObj()->globals()[Sym.WasmIndex - NumGlobalImports]; assert(Global.Type == llvm::wasm::WASM_TYPE_I32); return Global.InitExpr.Value.Int32; } @@ -166,7 +204,8 @@ } InputFunction *ObjFile::getFunction(const WasmSymbol &Sym) const { - uint32_t FunctionIndex = Sym.ElementIndex - NumFunctionImports; + assert(Sym.WasmIndex >= NumFunctionImports); + uint32_t FunctionIndex = Sym.WasmIndex - NumFunctionImports; return Functions[FunctionIndex]; } @@ -178,27 +217,20 @@ void ObjFile::initializeSymbols() { Symbols.reserve(WasmObj->getNumberOfSymbols()); - for (const WasmImport &Import : WasmObj->imports()) { - switch (Import.Kind) { - case WASM_EXTERNAL_FUNCTION: - ++NumFunctionImports; - break; - case WASM_EXTERNAL_GLOBAL: - ++NumGlobalImports; - break; - } - } + NumFunctionImports = WasmObj->getNumImportedFunctions(); + NumGlobalImports = WasmObj->getNumImportedGlobals(); + NumFunctionExports = WasmObj->getNumExportedFunctions(); + NumGlobalExports = WasmObj->getNumExportedGlobals(); ArrayRef Funcs = WasmObj->functions(); ArrayRef FuncTypes = WasmObj->functionTypes(); ArrayRef Types = WasmObj->types(); - ArrayRef Globals = WasmObj->globals(); for (const auto &C : WasmObj->comdats()) Symtab->addComdat(C, this); - FunctionSymbols.resize(NumFunctionImports + Funcs.size()); - GlobalSymbols.resize(NumGlobalImports + Globals.size()); + FunctionSymbols.resize(NumFunctionImports + NumFunctionExports); + GlobalSymbols.resize(NumGlobalImports + NumGlobalExports); for (const WasmSegment &S : WasmObj->dataSegments()) { InputSegment *Seg = make(S, *this); @@ -249,24 +281,17 @@ case WasmSymbol::SymbolType::GLOBAL_IMPORT: S = createUndefined(WasmSym, Symbol::Kind::UndefinedGlobalKind); break; - case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: - // These are for debugging only, no need to create linker symbols for them - continue; } Symbols.push_back(S); if (WasmSym.isFunction()) { - DEBUG(dbgs() << "Function: " << WasmSym.ElementIndex << " -> " + DEBUG(dbgs() << "Function: " << WasmSym.SymbolIndex << " -> " << toString(*S) << "\n"); - FunctionSymbols[WasmSym.ElementIndex] = S; - if (WasmSym.HasAltIndex) - FunctionSymbols[WasmSym.AltIndex] = S; + FunctionSymbols[WasmSym.SymbolIndex] = S; } else { - DEBUG(dbgs() << "Global: " << WasmSym.ElementIndex << " -> " + DEBUG(dbgs() << "Global: " << WasmSym.SymbolIndex << " -> " << toString(*S) << "\n"); - GlobalSymbols[WasmSym.ElementIndex] = S; - if (WasmSym.HasAltIndex) - GlobalSymbols[WasmSym.AltIndex] = S; + GlobalSymbols[WasmSym.SymbolIndex] = S; } } @@ -275,24 +300,6 @@ for (size_t I = 0; I < GlobalSymbols.size(); ++I) assert(GlobalSymbols[I] != nullptr);); - // Populate `TableSymbols` with all symbols that are called indirectly - uint32_t SegmentCount = WasmObj->elements().size(); - if (SegmentCount) { - if (SegmentCount > 1) - fatal(getName() + ": contains more than one element segment"); - const WasmElemSegment &Segment = WasmObj->elements()[0]; - if (Segment.Offset.Opcode != WASM_OPCODE_I32_CONST) - fatal(getName() + ": unsupported element segment"); - if (Segment.TableIndex != 0) - fatal(getName() + ": unsupported table index in elem segment"); - if (Segment.Offset.Value.Int32 != 0) - fatal(getName() + ": unsupported element segment offset"); - TableSymbols.reserve(Segment.Functions.size()); - for (uint64_t FunctionIndex : Segment.Functions) - TableSymbols.push_back(FunctionSymbols[FunctionIndex]); - } - - DEBUG(dbgs() << "TableSymbols: " << TableSymbols.size() << "\n"); DEBUG(dbgs() << "Functions : " << FunctionSymbols.size() << "\n"); DEBUG(dbgs() << "Globals : " << GlobalSymbols.size() << "\n"); } Index: wasm/Symbols.h =================================================================== --- wasm/Symbols.h +++ wasm/Symbols.h @@ -39,7 +39,7 @@ }; Symbol(StringRef Name, uint32_t Flags) - : WrittenToSymtab(0), WrittenToNameSec(0), Flags(Flags), Name(Name) {} + : Flags(Flags), Name(Name) {} Kind getKind() const { return SymbolKind; } @@ -73,10 +73,17 @@ // Returns true if an output index has been set for this symbol bool hasOutputIndex() const; - // Set the output index of the symbol (in the function or global index - // space of the output object. + // Set the output index of the symbol, in the function or global Wasm + // index space of the output object - that is, for defined symbols only, + // its position in the list of defined function bodies / global decls. void setOutputIndex(uint32_t Index); + // Get/set the output symbol index, in the function or global Symbol index + // space - that is, the position in the list of imports+exports. This is + // only used for relocatable output. + uint32_t getOutputSymbolIndex() const { return OutputSymbolIndex.getValue(); } + void setOutputSymbolIndex(uint32_t Index); + uint32_t getTableIndex() const { return TableIndex.getValue(); } // Returns true if a table index has been set for this symbol @@ -99,11 +106,6 @@ void setArchiveSymbol(const Archive::Symbol &Sym) { ArchiveSymbol = Sym; } const Archive::Symbol &getArchiveSymbol() { return ArchiveSymbol; } - // This bit is used by Writer::writeNameSection() to prevent - // symbols from being written to the symbol table more than once. - unsigned WrittenToSymtab : 1; - unsigned WrittenToNameSec : 1; - protected: uint32_t Flags; uint32_t VirtualAddress = 0; @@ -115,6 +117,7 @@ const InputSegment *Segment = nullptr; const InputFunction *Function = nullptr; llvm::Optional OutputIndex; + llvm::Optional OutputSymbolIndex; llvm::Optional TableIndex; const WasmSignature *FunctionType = nullptr; }; Index: wasm/Symbols.cpp =================================================================== --- wasm/Symbols.cpp +++ wasm/Symbols.cpp @@ -67,6 +67,12 @@ OutputIndex = Index; } +void Symbol::setOutputSymbolIndex(uint32_t Index) { + DEBUG(dbgs() << "setOutputSymbolIndex " << Name << " -> " << Index << "\n"); + assert(!OutputSymbolIndex.hasValue()); + OutputSymbolIndex = Index; +} + void Symbol::setTableIndex(uint32_t Index) { DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n"); assert(!TableIndex.hasValue()); Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -73,7 +73,6 @@ uint32_t registerType(const WasmSignature &Sig); void assignIndexes(); void calculateImports(); - void calculateOffsets(); void calculateTypes(); void createOutputSegments(); void layoutMemory(); @@ -106,13 +105,13 @@ uint64_t FileSize = 0; uint32_t DataSize = 0; uint32_t NumMemoryPages = 0; - uint32_t InitialTableOffset = 0; + uint32_t InitialTableOffset = 1; std::vector Types; DenseMap TypeIndices; std::vector ImportedFunctions; std::vector ImportedGlobals; - std::vector DefinedGlobals; + std::vector DefinedGlobals; std::vector DefinedFunctions; std::vector IndirectFunctions; @@ -260,25 +259,31 @@ uint32_t NumExports = ExportMemory ? 1 : 0; + unsigned FunctionIndex = ImportedFunctions.size(); std::vector SymbolExports; - if (ExportEntry) + if (ExportEntry) { + EntrySym->setOutputSymbolIndex(FunctionIndex++); SymbolExports.emplace_back(EntrySym); + } - for (const Symbol *Sym : Symtab->getSymbols()) { + for (Symbol *Sym : Symtab->getSymbols()) { if (Sym->isUndefined() || Sym->isGlobal()) continue; if (Sym->isHidden() && !ExportHidden) continue; if (ExportEntry && Sym == EntrySym) continue; + Sym->setOutputSymbolIndex(FunctionIndex++); SymbolExports.emplace_back(Sym); } - for (const Symbol *Sym : DefinedGlobals) { - // Can't export the SP right now because it mutable and mutable globals - // connot be exported. + unsigned GlobalIndex = ImportedGlobals.size(); + for (Symbol *Sym : DefinedGlobals) { + // Can't export the SP right now because it's mutable and mutable globals + // cannot be exported. if (Sym == Config->StackPointerSymbol) continue; + Sym->setOutputSymbolIndex(GlobalIndex++); SymbolExports.emplace_back(Sym); } @@ -417,13 +422,13 @@ InitFunctions.reserve(InitFunctions.size() + L.InitFunctions.size()); for (const WasmInitFunc &F : L.InitFunctions) InitFunctions.emplace_back(WasmInitFunc{ - F.Priority, File->relocateFunctionIndex(F.FunctionIndex)}); + F.Priority, File->relocateFunctionSymbolIndex(F.FunctionIndex)}); } if (!InitFunctions.empty()) { SubSection SubSection(WASM_INIT_FUNCS); writeUleb128(SubSection.getStream(), InitFunctions.size(), - "num init functionsw"); + "num init functions"); for (const WasmInitFunc &F : InitFunctions) { writeUleb128(SubSection.getStream(), F.Priority, "priority"); writeUleb128(SubSection.getStream(), F.FunctionIndex, "function index"); @@ -471,34 +476,22 @@ // Create the custom "name" section containing debug symbol names. void Writer::createNameSection() { - // Create an array of all function sorted by function index space - std::vector Names; - - for (ObjFile *File : Symtab->ObjectFiles) { - Names.reserve(Names.size() + File->getSymbols().size()); - for (Symbol *S : File->getSymbols()) { - if (!S->isFunction() || S->isWeak() || S->WrittenToNameSec) - continue; - S->WrittenToNameSec = true; - Names.emplace_back(S); - } - } + unsigned Names = 0; + for (const InputFunction *F : DefinedFunctions) + if (!F->Function.Name.empty()) + ++Names; SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name"); - std::sort(Names.begin(), Names.end(), [](const Symbol *A, const Symbol *B) { - return A->getOutputIndex() < B->getOutputIndex(); - }); - SubSection FunctionSubsection(WASM_NAMES_FUNCTION); raw_ostream &OS = FunctionSubsection.getStream(); - writeUleb128(OS, Names.size(), "name count"); + writeUleb128(OS, Names, "name count"); - // We have to iterate through the inputs twice so that all the imports - // appear first before any of the local function names. - for (const Symbol *S : Names) { - writeUleb128(OS, S->getOutputIndex(), "func index"); - writeStr(OS, S->getName(), "symbol name"); + for (const InputFunction *F : DefinedFunctions) { + if (!F->Function.Name.empty()) { + writeUleb128(OS, F->getOutputIndex(), "func index"); + writeStr(OS, F->Function.Name, "symbol name"); + } } FunctionSubsection.finalizeContents(); @@ -599,9 +592,11 @@ if (Sym->isFunction()) { Sym->setOutputIndex(ImportedFunctions.size()); + Sym->setOutputSymbolIndex(ImportedFunctions.size()); ImportedFunctions.push_back(Sym); } else { Sym->setOutputIndex(ImportedGlobals.size()); + Sym->setOutputSymbolIndex(ImportedGlobals.size()); ImportedGlobals.push_back(Sym); } } @@ -675,11 +670,27 @@ for (ObjFile *File : Symtab->ObjectFiles) { DEBUG(dbgs() << "Table Indexes: " << File->getName() << "\n"); - for (Symbol *Sym : File->getTableSymbols()) { - if (Sym->hasTableIndex() || !Sym->hasOutputIndex()) + auto HandleRelocs = [&](ArrayRef Relocations) { + for (const WasmRelocation& Reloc : Relocations) { + if (Reloc.Type != R_WEBASSEMBLY_TABLE_INDEX_I32 && + Reloc.Type != R_WEBASSEMBLY_TABLE_INDEX_SLEB) + continue; + Symbol *Sym = File->getFunctionSymbols()[Reloc.Index]; + if (Sym->hasTableIndex() || !Sym->hasOutputIndex()) + continue; + Sym->setTableIndex(TableIndex++); + IndirectFunctions.emplace_back(Sym); + } + }; + for (InputFunction* Func : File->Functions) { + if (Func->Discarded) continue; - Sym->setTableIndex(TableIndex++); - IndirectFunctions.emplace_back(Sym); + HandleRelocs(Func->getRelocations()); + } + for (InputSegment* Seg : File->Segments) { + if (Seg->Discarded) + continue; + HandleRelocs(Seg->getRelocations()); } } } @@ -719,9 +730,6 @@ } void Writer::run() { - if (!Config->Relocatable) - InitialTableOffset = 1; - log("-- calculateTypes"); calculateTypes(); log("-- calculateImports");