diff options
author | Derek Schuff <dschuff@chromium.org> | 2024-02-08 13:20:47 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-08 13:20:47 -0800 |
commit | 581857278961b41bc1676499f92167b97a5e4c58 (patch) | |
tree | a525608246d6e89d276e71be91d5635db4395a57 /llvm/lib/Object/WasmObjectFile.cpp | |
parent | 3f9d8d892e2de2ac2542cb8e88ae5317f3282244 (diff) | |
download | llvm-581857278961b41bc1676499f92167b97a5e4c58.zip llvm-581857278961b41bc1676499f92167b97a5e4c58.tar.gz llvm-581857278961b41bc1676499f92167b97a5e4c58.tar.bz2 |
[Object][Wasm] Generate symbol info from name section names (#81063)
Currently symbol info is generated from a linking section or from export
names. This PR generates symbols in a WasmObjectFile from the name
section as well, which allows tools like objdump and nm to show useful
information for more linked binaries. There are some limitations:
most notably that we don't assume any particular ABI, so we don't get
detailed information about data symbols if the segments are merged
(which is the default).
Covers most of the desired functionality from #76107
Diffstat (limited to 'llvm/lib/Object/WasmObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/WasmObjectFile.cpp | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp index 8c1bbe9..ea17154 100644 --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -508,10 +508,17 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { llvm::DenseSet<uint64_t> SeenGlobals; llvm::DenseSet<uint64_t> SeenSegments; + // If there is symbol info from the export section, this info will supersede + // it, but not info from a linking section + if (!HasLinkingSection) { + Symbols.clear(); + } + while (Ctx.Ptr < Ctx.End) { uint8_t Type = readUint8(Ctx); uint32_t Size = readVaruint32(Ctx); const uint8_t *SubSectionEnd = Ctx.Ptr + Size; + switch (Type) { case wasm::WASM_NAMES_FUNCTION: case wasm::WASM_NAMES_GLOBAL: @@ -521,6 +528,16 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { uint32_t Index = readVaruint32(Ctx); StringRef Name = readString(Ctx); wasm::NameType nameType = wasm::NameType::FUNCTION; + wasm::WasmSymbolInfo Info{Name, + /*Kind */ wasm::WASM_SYMBOL_TYPE_FUNCTION, + /* Flags */ 0, + /* ImportModule */ std::nullopt, + /* ImportName */ std::nullopt, + /* ExportName */ std::nullopt, + {/* ElementIndex */ Index}}; + const wasm::WasmSignature *Signature = nullptr; + const wasm::WasmGlobalType *GlobalType = nullptr; + const wasm::WasmTableType *TableType = nullptr; if (Type == wasm::WASM_NAMES_FUNCTION) { if (!SeenFunctions.insert(Index).second) return make_error<GenericBinaryError>( @@ -529,26 +546,50 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { return make_error<GenericBinaryError>("invalid function name entry", object_error::parse_failed); - if (isDefinedFunctionIndex(Index)) - getDefinedFunction(Index).DebugName = Name; + if (isDefinedFunctionIndex(Index)) { + wasm::WasmFunction &F = getDefinedFunction(Index); + F.DebugName = Name; + Signature = &Signatures[F.SigIndex]; + if (F.ExportName) { + Info.ExportName = F.ExportName; + Info.Flags |= wasm::WASM_SYMBOL_BINDING_GLOBAL; + } else { + Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL; + } + } else { + Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED; + } } else if (Type == wasm::WASM_NAMES_GLOBAL) { - nameType = wasm::NameType::GLOBAL; if (!SeenGlobals.insert(Index).second) return make_error<GenericBinaryError>("global named more than once", object_error::parse_failed); if (!isValidGlobalIndex(Index) || Name.empty()) return make_error<GenericBinaryError>("invalid global name entry", object_error::parse_failed); + nameType = wasm::NameType::GLOBAL; + Info.Kind = wasm::WASM_SYMBOL_TYPE_GLOBAL; + if (isDefinedGlobalIndex(Index)) { + GlobalType = &getDefinedGlobal(Index).Type; + } else { + Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED; + } } else { - nameType = wasm::NameType::DATA_SEGMENT; if (!SeenSegments.insert(Index).second) return make_error<GenericBinaryError>( "segment named more than once", object_error::parse_failed); if (Index > DataSegments.size()) return make_error<GenericBinaryError>("invalid data segment name entry", object_error::parse_failed); + nameType = wasm::NameType::DATA_SEGMENT; + Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA; + Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL; + assert(Index < DataSegments.size()); + Info.DataRef = wasm::WasmDataReference{ + Index, 0, DataSegments[Index].Data.Content.size()}; } DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name}); + if (!HasLinkingSection) + Symbols.emplace_back(Info, GlobalType, TableType, Signature); } break; } |