Index: wasm/InputChunks.h =================================================================== --- wasm/InputChunks.h +++ wasm/InputChunks.h @@ -130,12 +130,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 @@ -107,6 +107,10 @@ NewReloc.NewIndex = File.calcNewIndex(Reloc); switch (Reloc.Type) { + case R_WEBASSEMBLY_TABLE_INDEX_I32: + case R_WEBASSEMBLY_TABLE_INDEX_SLEB: + NewReloc.Value = File.relocateTableIndex(Reloc.Index); + break; case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: case R_WEBASSEMBLY_MEMORY_ADDR_I32: case R_WEBASSEMBLY_MEMORY_ADDR_LEB: Index: wasm/InputFiles.h =================================================================== --- wasm/InputFiles.h +++ wasm/InputFiles.h @@ -93,7 +93,7 @@ void dumpInfo() const; - uint32_t relocateFunctionIndex(uint32_t Original) const; + uint32_t relocateFunctionSymbolIndex(uint32_t Original) const; uint32_t getRelocatedAddress(uint32_t Index) const; uint32_t calcNewIndex(const WasmRelocation &Reloc) const; @@ -104,12 +104,12 @@ 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 relocateTypeIndex(uint32_t Original) const; - uint32_t relocateGlobalIndex(uint32_t Original) const; + uint32_t relocateGlobalSymbolIndex(uint32_t Original) const; uint32_t relocateTableIndex(uint32_t Original) const; Symbol *createDefined(const WasmSymbol &Sym, Symbol::Kind Kind, @@ -128,17 +128,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,37 @@ " 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->getOutputIndex(); + 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->hasOutputIndex() ? Sym->getOutputIndex() : 0; + DEBUG(dbgs() << "relocateGlobalSymbolIndex: " << toString(*Sym) << ": " << Original << " -> " << Index << "\n"); return Index; } -uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const { - Symbol *Sym = GlobalSymbols[Original]; - uint32_t Index = Sym->hasOutputIndex() ? Sym->getOutputIndex() : 0; - DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original +uint32_t ObjFile::relocateTableIndex(uint32_t Original) const { + Symbol *Sym = FunctionSymbols[Original]; + uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0; + DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original << " -> " << Index << "\n"); return Index; } @@ -92,15 +91,14 @@ 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"); } @@ -151,8 +149,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 +165,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,16 +178,10 @@ 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(); @@ -249,24 +243,18 @@ 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; + InputFunction &Func = *Functions[WasmSym.WasmIndex - NumFunctionImports]; } 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 +263,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,8 +73,9 @@ // 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); uint32_t getTableIndex() const { return TableIndex.getValue(); } @@ -99,11 +100,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; 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,7 +105,7 @@ 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; @@ -417,13 +416,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 +470,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(); @@ -675,11 +662,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->Relocations); + } + for (InputSegment* Seg : File->Segments) { + if (Seg->Discarded) + continue; + HandleRelocs(Seg->Relocations); } } } @@ -719,9 +722,6 @@ } void Writer::run() { - if (!Config->Relocatable) - InitialTableOffset = 1; - log("-- calculateTypes"); calculateTypes(); log("-- calculateImports");