https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/213554
A Wasm module carries the identifier its linker gave it in a `build_id` custom section, whose payload is the length of the identifier followed by its bytes. That identifier is the only thing that tells one build of a module from another. `wasm-ld` emits the section only when asked, so the API test build asks for it. A module linked without one still has no UUID. >From f8a60be6caeec393b1dac715ad2d04599adda96c Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <[email protected]> Date: Sat, 1 Aug 2026 23:45:01 -0700 Subject: [PATCH] [lldb] Identify a WebAssembly module by its build id A Wasm module carries the identifier its linker gave it in a build_id custom section, whose payload is the length of the identifier followed by its bytes. That identifier is the only thing that tells one build of a module from another, and ObjectFileWasm never read it: it declared a UUID and returned it without ever assigning one, so every Wasm module came back unidentified and anything keyed on module identity had nothing to work with. wasm-ld emits the section only when asked, so the API test build asks for it. A module linked without one still has no UUID, since there is nothing to read. (cherry picked from commit 0cc09feac1a57c994d326a6573452f1127bba23e) --- .../Python/lldbsuite/test/make/WASI.rules | 5 ++ .../ObjectFile/wasm/ObjectFileWasm.cpp | 35 ++++++++++++ .../Plugins/ObjectFile/wasm/ObjectFileWasm.h | 2 +- lldb/test/Shell/ObjectFile/wasm/build-id.yaml | 55 +++++++++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 lldb/test/Shell/ObjectFile/wasm/build-id.yaml diff --git a/lldb/packages/Python/lldbsuite/test/make/WASI.rules b/lldb/packages/Python/lldbsuite/test/make/WASI.rules index 32e5656c41c4f..a99dd3c85c877 100644 --- a/lldb/packages/Python/lldbsuite/test/make/WASI.rules +++ b/lldb/packages/Python/lldbsuite/test/make/WASI.rules @@ -14,3 +14,8 @@ ARCH_LDFLAGS += \ # Unlike most native linkers, wasm-ld garbage-collects unreferenced sections by # default, which strips globals and functions that a test wants to inspect. LDFLAGS += -Wl,--no-gc-sections + +# A debugger tells one build of a module from another by its build id, and +# wasm-ld emits one only when asked, so a module linked without this carries +# nothing that identifies it. +LDFLAGS += -Wl,--build-id diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp index 3f73e239afe47..2e98fd91432db 100644 --- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp +++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp @@ -1136,6 +1136,41 @@ DataExtractor ObjectFileWasm::ReadImageData(offset_t offset, uint32_t size) { return data; } +UUID ObjectFileWasm::GetUUID() { + if (m_uuid) + return m_uuid; + + // A Wasm module carries the identifier a linker gave it in a custom section, + // as a vector of bytes. It is the only thing that tells one build of a module + // from another, so a module linked without one cannot be identified at all. + static ConstString g_sect_name_build_id("build_id"); + for (const section_info §_info : m_sect_infos) { + if (g_sect_name_build_id != sect_info.name) + continue; + + DataExtractor section_data = ReadImageData(sect_info.offset, sect_info.size); + llvm::DataExtractor data = section_data.GetAsLLVM(); + llvm::DataExtractor::Cursor c(0); + llvm::Expected<uint32_t> length = GetULEB32(data, c); + if (!length) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Object), length.takeError(), + "failed to parse the build id length: {0}"); + return m_uuid; + } + llvm::SmallVector<uint8_t, 32> id(*length, 0); + data.getU8(c, id.data(), id.size()); + if (!c) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Object), c.takeError(), + "failed to parse the build id: {0}"); + return m_uuid; + } + m_uuid = UUID(id); + break; + } + + return m_uuid; +} + std::optional<FileSpec> ObjectFileWasm::GetExternalDebugInfoFileSpec() { static ConstString g_sect_name_external_debug_info("external_debug_info"); diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h index 80a955211ebb2..f70ae4e6a6d32 100644 --- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h +++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h @@ -103,7 +103,7 @@ class ObjectFileWasm : public ObjectFile { ArchSpec GetArchitecture() override { return m_arch; } - UUID GetUUID() override { return m_uuid; } + UUID GetUUID() override; uint32_t GetDependentModules(FileSpecList &files) override { return 0; } diff --git a/lldb/test/Shell/ObjectFile/wasm/build-id.yaml b/lldb/test/Shell/ObjectFile/wasm/build-id.yaml new file mode 100644 index 0000000000000..84f539da4c182 --- /dev/null +++ b/lldb/test/Shell/ObjectFile/wasm/build-id.yaml @@ -0,0 +1,55 @@ +# A Wasm module carries the identifier its linker gave it in a build_id custom +# section, whose payload is the length of the identifier followed by its bytes. + +# RUN: yaml2obj %s --docnum=1 -o %t.16 +# RUN: lldb-test object-file %t.16 | FileCheck %s --check-prefix=UUID16 + +# UUID16: Plugin name: wasm +# UUID16: UUID: 01020304-0506-0708-090A-0B0C0D0E0F10 + +# An identifier of any other length is just as good, since it is only ever +# compared with another. +# RUN: yaml2obj %s --docnum=2 -o %t.20 +# RUN: lldb-test object-file %t.20 | FileCheck %s --check-prefix=UUID20 + +# UUID20: UUID: 01020304-0506-0708-090A-0B0C0D0E0F10-11121314 + +# A module linked without the section has nothing that identifies it. +# RUN: yaml2obj %s --docnum=3 -o %t.none +# RUN: lldb-test object-file %t.none | FileCheck %s --check-prefix=NOUUID + +# NOUUID: UUID:{{ *$}} + +--- !WASM +FileHeader: + Version: 0x00000001 +Sections: + - Type: CUSTOM + Name: build_id + Payload: 100102030405060708090A0B0C0D0E0F10 + - Type: CODE + Functions: + - Index: 0 + Locals: + Body: 0B +--- !WASM +FileHeader: + Version: 0x00000001 +Sections: + - Type: CUSTOM + Name: build_id + Payload: 140102030405060708090A0B0C0D0E0F1011121314 + - Type: CODE + Functions: + - Index: 0 + Locals: + Body: 0B +--- !WASM +FileHeader: + Version: 0x00000001 +Sections: + - Type: CODE + Functions: + - Index: 0 + Locals: + Body: 0B _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
