Index: llvm/trunk/include/llvm/Object/Wasm.h =================================================================== --- llvm/trunk/include/llvm/Object/Wasm.h +++ llvm/trunk/include/llvm/Object/Wasm.h @@ -204,6 +204,8 @@ Error parseRelocSection(StringRef Name, const uint8_t *Ptr, const uint8_t *End); + void populateSymbolTable(); + wasm::WasmObjectHeader Header; std::vector Sections; std::vector Signatures; @@ -223,6 +225,8 @@ wasm::WasmLinkingData LinkingData; uint32_t NumImportedGlobals = 0; uint32_t NumImportedFunctions = 0; + uint32_t ImportSection = 0; + uint32_t ExportSection = 0; StringMap SymbolMap; }; Index: llvm/trunk/lib/Object/WasmObjectFile.cpp =================================================================== --- llvm/trunk/lib/Object/WasmObjectFile.cpp +++ llvm/trunk/lib/Object/WasmObjectFile.cpp @@ -300,9 +300,69 @@ return Error::success(); } +void WasmObjectFile::populateSymbolTable() { + // Add imports to symbol table + size_t ImportIndex = 0; + for (const wasm::WasmImport& Import : Imports) { + switch (Import.Kind) { + case wasm::WASM_EXTERNAL_GLOBAL: + assert(Import.Global.Type == wasm::WASM_TYPE_I32); + SymbolMap.try_emplace(Import.Field, Symbols.size()); + Symbols.emplace_back(Import.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT, + ImportSection, ImportIndex); + DEBUG(dbgs() << "Adding import: " << Symbols.back() + << " sym index:" << Symbols.size() << "\n"); + break; + case wasm::WASM_EXTERNAL_FUNCTION: + SymbolMap.try_emplace(Import.Field, Symbols.size()); + Symbols.emplace_back(Import.Field, + WasmSymbol::SymbolType::FUNCTION_IMPORT, + ImportSection, ImportIndex); + DEBUG(dbgs() << "Adding import: " << Symbols.back() + << " sym index:" << Symbols.size() << "\n"); + break; + default: + break; + } + ImportIndex++; + } + + // Add exports to symbol table + size_t ExportIndex = 0; + for (const wasm::WasmExport& Export : Exports) { + if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION || + Export.Kind == wasm::WASM_EXTERNAL_GLOBAL) { + WasmSymbol::SymbolType ExportType = + Export.Kind == wasm::WASM_EXTERNAL_FUNCTION + ? WasmSymbol::SymbolType::FUNCTION_EXPORT + : WasmSymbol::SymbolType::GLOBAL_EXPORT; + auto Pair = SymbolMap.try_emplace(Export.Name, Symbols.size()); + if (Pair.second) { + Symbols.emplace_back(Export.Name, ExportType, + ExportSection, ExportIndex); + DEBUG(dbgs() << "Adding export: " << Symbols.back() + << " sym index:" << Symbols.size() << "\n"); + } else { + uint32_t SymIndex = Pair.first->second; + Symbols[SymIndex] = + WasmSymbol(Export.Name, ExportType, ExportSection, ExportIndex); + DEBUG(dbgs() << "Replacing existing symbol: " << Symbols[SymIndex] + << " sym index:" << SymIndex << "\n"); + } + } + ExportIndex++; + } +} + Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr, const uint8_t *End) { HasLinkingSection = true; + + // Only populate the symbol table with imports and exports if the object + // has a linking section (i.e. its a relocatable object file). Otherwise + // the global might not represent symbols at all. + populateSymbolTable(); + while (Ptr < End) { uint8_t Type = readVarint7(Ptr); uint32_t Size = readVaruint32(Ptr); @@ -463,6 +523,7 @@ } Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) { + ImportSection = Sections.size(); uint32_t Count = readVaruint32(Ptr); Imports.reserve(Count); for (uint32_t i = 0; i < Count; i++) { @@ -474,31 +535,20 @@ case wasm::WASM_EXTERNAL_FUNCTION: NumImportedFunctions++; Im.SigIndex = readVaruint32(Ptr); - SymbolMap.try_emplace(Im.Field, Symbols.size()); - Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT, - Sections.size(), i); - DEBUG(dbgs() << "Adding import: " << Symbols.back() - << " sym index:" << Symbols.size() << "\n"); break; case wasm::WASM_EXTERNAL_GLOBAL: NumImportedGlobals++; Im.Global.Type = readVarint7(Ptr); Im.Global.Mutable = readVaruint1(Ptr); - SymbolMap.try_emplace(Im.Field, Symbols.size()); - Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT, - Sections.size(), i); - DEBUG(dbgs() << "Adding import: " << Symbols.back() - << " sym index:" << Symbols.size() << "\n"); break; case wasm::WASM_EXTERNAL_MEMORY: Im.Memory = readLimits(Ptr); break; case wasm::WASM_EXTERNAL_TABLE: Im.Table = readTable(Ptr); - if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) { + if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) return make_error("Invalid table element type", object_error::parse_failed); - } break; default: return make_error( @@ -570,6 +620,7 @@ } Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) { + ExportSection = Sections.size(); uint32_t Count = readVaruint32(Ptr); Exports.reserve(Count); for (uint32_t i = 0; i < Count; i++) { @@ -577,23 +628,18 @@ Ex.Name = readString(Ptr); Ex.Kind = readUint8(Ptr); Ex.Index = readVaruint32(Ptr); - WasmSymbol::SymbolType ExportType; - bool MakeSymbol = false; switch (Ex.Kind) { case wasm::WASM_EXTERNAL_FUNCTION: - ExportType = WasmSymbol::SymbolType::FUNCTION_EXPORT; if (Ex.Index >= FunctionTypes.size() + NumImportedFunctions) return make_error("Invalid function export", object_error::parse_failed); - MakeSymbol = true; break; - case wasm::WASM_EXTERNAL_GLOBAL: - ExportType = WasmSymbol::SymbolType::GLOBAL_EXPORT; + case wasm::WASM_EXTERNAL_GLOBAL: { if (Ex.Index >= Globals.size() + NumImportedGlobals) return make_error("Invalid global export", object_error::parse_failed); - MakeSymbol = true; break; + } case wasm::WASM_EXTERNAL_MEMORY: case wasm::WASM_EXTERNAL_TABLE: break; @@ -601,20 +647,6 @@ return make_error( "Unexpected export kind", object_error::parse_failed); } - if (MakeSymbol) { - auto Pair = SymbolMap.try_emplace(Ex.Name, Symbols.size()); - if (Pair.second) { - Symbols.emplace_back(Ex.Name, ExportType, - Sections.size(), i); - DEBUG(dbgs() << "Adding export: " << Symbols.back() - << " sym index:" << Symbols.size() << "\n"); - } else { - uint32_t SymIndex = Pair.first->second; - Symbols[SymIndex] = WasmSymbol(Ex.Name, ExportType, Sections.size(), i); - DEBUG(dbgs() << "Replacing existing symbol: " << Symbols[SymIndex] - << " sym index:" << SymIndex << "\n"); - } - } Exports.push_back(Ex); } if (Ptr != End) @@ -791,6 +823,8 @@ uint32_t GlobalIndex = Exports[Sym.ElementIndex].Index - NumImportedGlobals; assert(GlobalIndex < Globals.size()); const wasm::WasmGlobal& Global = Globals[GlobalIndex]; + // WasmSymbols correspond only to I32_CONST globals + assert(Global.InitExpr.Opcode == wasm::WASM_OPCODE_I32_CONST); return Global.InitExpr.Value.Int32; } case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: Index: llvm/trunk/lib/ObjectYAML/WasmYAML.cpp =================================================================== --- llvm/trunk/lib/ObjectYAML/WasmYAML.cpp +++ llvm/trunk/lib/ObjectYAML/WasmYAML.cpp @@ -59,7 +59,7 @@ IO.mapRequired("Name", Section.Name); IO.mapRequired("DataSize", Section.DataSize); IO.mapRequired("DataAlignment", Section.DataAlignment); - IO.mapRequired("SymbolInfo", Section.SymbolInfos); + IO.mapOptional("SymbolInfo", Section.SymbolInfos); } static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) { Index: llvm/trunk/test/MC/WebAssembly/unnamed-data.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/unnamed-data.ll +++ llvm/trunk/test/MC/WebAssembly/unnamed-data.ll @@ -56,5 +56,4 @@ ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 28 ; CHECK-NEXT: DataAlignment: 8 -; CHECK-NEXT: SymbolInfo: ; CHECK-NEXT: ... Index: llvm/trunk/test/tools/llvm-nm/wasm/exports.yaml =================================================================== --- llvm/trunk/test/tools/llvm-nm/wasm/exports.yaml +++ llvm/trunk/test/tools/llvm-nm/wasm/exports.yaml @@ -24,12 +24,12 @@ - Type: I32 Mutable: false InitExpr: - Opcode: I64_CONST + Opcode: I32_CONST Value: 64 - Type: I32 Mutable: false InitExpr: - Opcode: I64_CONST + Opcode: I32_CONST Value: 1024 - Type: IMPORT Imports: @@ -50,6 +50,10 @@ - Name: bar Kind: GLOBAL Index: 0x00000003 + - Type: CUSTOM + Name: "linking" + DataSize: 0 + DataAlignment: 0 # CHECK: 00000400 D bar # CHECK-NEXT: U fimport Index: llvm/trunk/test/tools/llvm-nm/wasm/imports.yaml =================================================================== --- llvm/trunk/test/tools/llvm-nm/wasm/imports.yaml +++ llvm/trunk/test/tools/llvm-nm/wasm/imports.yaml @@ -20,6 +20,10 @@ Kind: GLOBAL GlobalType: I32 GlobalMutable: false + - Type: CUSTOM + Name: "linking" + DataSize: 0 + DataAlignment: 0 # CHECK: U bar # CHECK: U foo Index: llvm/trunk/test/tools/llvm-nm/wasm/weak-symbols.yaml =================================================================== --- llvm/trunk/test/tools/llvm-nm/wasm/weak-symbols.yaml +++ llvm/trunk/test/tools/llvm-nm/wasm/weak-symbols.yaml @@ -35,12 +35,12 @@ - Type: I32 Mutable: false InitExpr: - Opcode: I64_CONST + Opcode: I32_CONST Value: 64 - Type: I32 Mutable: false InitExpr: - Opcode: I64_CONST + Opcode: I32_CONST Value: 1024 - Type: EXPORT Exports: Index: llvm/trunk/test/tools/llvm-objdump/WebAssembly/symbol-table.test =================================================================== --- llvm/trunk/test/tools/llvm-objdump/WebAssembly/symbol-table.test +++ llvm/trunk/test/tools/llvm-objdump/WebAssembly/symbol-table.test @@ -1,11 +1,11 @@ RUN: llvm-objdump -t %p/../Inputs/trivial.obj.wasm | FileCheck %s CHECK: SYMBOL TABLE: +CHECK-NEXT: 00000000 l F name puts +CHECK-NEXT: 00000001 l F name SomeOtherFunction +CHECK-NEXT: 00000002 l F name main CHECK-NEXT: 00000000 l F IMPORT puts CHECK-NEXT: 00000000 l F IMPORT SomeOtherFunction CHECK-NEXT: 00000002 g F EXPORT main CHECK-NEXT: 00000010 g EXPORT var -CHECK-NEXT: 00000000 l F name puts -CHECK-NEXT: 00000001 l F name SomeOtherFunction -CHECK-NEXT: 00000002 l F name main Index: llvm/trunk/test/tools/llvm-readobj/symbols.test =================================================================== --- llvm/trunk/test/tools/llvm-readobj/symbols.test +++ llvm/trunk/test/tools/llvm-readobj/symbols.test @@ -74,32 +74,32 @@ WASM: Symbols [ WASM-NEXT: Symbol { WASM-NEXT: Name: puts -WASM-NEXT: Type: FUNCTION_IMPORT (0x0) +WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4) WASM-NEXT: Flags: 0x0 WASM-NEXT: } WASM-NEXT: Symbol { WASM-NEXT: Name: SomeOtherFunction -WASM-NEXT: Type: FUNCTION_IMPORT (0x0) +WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4) WASM-NEXT: Flags: 0x0 WASM-NEXT: } WASM-NEXT: Symbol { WASM-NEXT: Name: main -WASM-NEXT: Type: FUNCTION_EXPORT (0x1) +WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4) WASM-NEXT: Flags: 0x0 WASM-NEXT: } WASM-NEXT: Symbol { WASM-NEXT: Name: puts -WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4) +WASM-NEXT: Type: FUNCTION_IMPORT (0x0) WASM-NEXT: Flags: 0x0 WASM-NEXT: } WASM-NEXT: Symbol { WASM-NEXT: Name: SomeOtherFunction -WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4) +WASM-NEXT: Type: FUNCTION_IMPORT (0x0) WASM-NEXT: Flags: 0x0 WASM-NEXT: } WASM-NEXT: Symbol { WASM-NEXT: Name: main -WASM-NEXT: Type: DEBUG_FUNCTION_NAME (0x4) +WASM-NEXT: Type: FUNCTION_EXPORT (0x1) WASM-NEXT: Flags: 0x0 WASM-NEXT: } WASM-NEXT: ]