[Lldb-commits] [lldb] [lldb] Identify a WebAssembly module by its build id (PR #213554)
via lldb-commits
lldb-commits at lists.llvm.org
Sun Aug 2 09:30:07 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Jonas Devlieghere (JDevlieghere)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/213554.diff
4 Files Affected:
- (modified) lldb/packages/Python/lldbsuite/test/make/WASI.rules (+5)
- (modified) lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp (+35)
- (modified) lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h (+1-1)
- (added) lldb/test/Shell/ObjectFile/wasm/build-id.yaml (+55)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/213554
More information about the lldb-commits
mailing list