[Lldb-commits] [lldb] [lldb] Handle partial memory region coverage in IRMemoryMap::FindSpace (PR #194001)

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Fri Apr 24 09:15:46 PDT 2026


https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/194001

FindSpace walks process memory regions to find addresses that won't collide with the inferior's real memory. This is necessary even for host-only allocations because the IR Interpreter works entirely in inferior virtual addresses. IRMemoryMap remaps those addresses to read from host memory instead of inferior memory, so overlapping ranges would silently read the wrong data.

For WebAssembly, GetMemoryRegionInfo succeeds for the first region (linear memory) but fails for addresses beyond it. The previous fix (#193124) skipped the memory region walk entirely when `CanJIT()` is false. However, as Jason points out, that removes the collision-avoidance mechanism and risks overlapping with real inferior memory.

Instead, handle the GetMemoryRegionInfo failure gracefully. If the target can't describe memory beyond a certain point, treat the remaining address space as unmapped and use it for the allocation. This preserves the collision avoidance while avoiding the lldbassert.

>From 779b803bad0078ade2b8699a817b74a2b6f53d17 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Fri, 24 Apr 2026 09:10:55 -0700
Subject: [PATCH] [lldb] Handle partial memory region coverage in
 IRMemoryMap::FindSpace

FindSpace walks process memory regions to find addresses that won't
collide with the inferior's real memory. This is necessary even for
host-only allocations because the IR Interpreter works entirely in
inferior virtual addresses. IRMemoryMap remaps those addresses to read
from host memory instead of inferior memory, so overlapping ranges would
silently read the wrong data.

On targets like WebAssembly, GetMemoryRegionInfo succeeds for the first
region (linear memory) but fails for addresses beyond it. The previous
fix (#193124) skipped the memory region walk entirely when CanJIT() is
false. However, as Jason points out, that removes the
collision-avoidance mechanism and risks overlapping with real inferior
memory.

Instead, handle the mid-walk GetMemoryRegionInfo failure gracefully. If
the target can't describe memory beyond a certain point, treat the
remaining address space as unmapped and use it for the allocation. This
preserves the collision avoidance while fixing the lldbassert.
---
 lldb/source/Expression/IRMemoryMap.cpp        | 14 ++++++--------
 lldb/unittests/Expression/IRMemoryMapTest.cpp | 12 ++++++------
 2 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp
index 66578bed1d367..fd46a48930bd4 100644
--- a/lldb/source/Expression/IRMemoryMap.cpp
+++ b/lldb/source/Expression/IRMemoryMap.cpp
@@ -111,11 +111,7 @@ lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
   // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
   // regions, walk forward through memory until a region is found that has
   // adequate space for our allocation.
-  //
-  // Skip this when the process can't JIT. In that case, allocations are
-  // host-only and never written to process memory, so there's no need to probe
-  // the process's memory map.
-  if (process_is_alive && process_sp->CanJIT()) {
+  if (process_is_alive) {
     MemoryRegionInfo region_info;
     Status err = process_sp->GetMemoryRegionInfo(ret, region_info);
     if (err.Success()) {
@@ -141,12 +137,14 @@ lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
           // ret stays the same.  We just need to walk a bit further.
         }
 
-        // FIXME: When we're able to JIT WebAssembly, this strategy won't work
-        // because we might probe beyond its linear memory.
         err = process_sp->GetMemoryRegionInfo(
             region_info.GetRange().GetRangeEnd(), region_info);
         if (err.Fail()) {
-          lldbassert(0 && "GetMemoryRegionInfo() succeeded, then failed");
+          // The target can't describe memory beyond this point (e.g.
+          // WebAssembly linear memory). Treat the remaining address space
+          // as unmapped.
+          if (ret + size < end_of_memory)
+            return ret;
           ret = LLDB_INVALID_ADDRESS;
           break;
         }
diff --git a/lldb/unittests/Expression/IRMemoryMapTest.cpp b/lldb/unittests/Expression/IRMemoryMapTest.cpp
index 39b7d23312db9..7c78a3abd359c 100644
--- a/lldb/unittests/Expression/IRMemoryMapTest.cpp
+++ b/lldb/unittests/Expression/IRMemoryMapTest.cpp
@@ -79,10 +79,8 @@ class IRMemoryMapTest : public ::testing::Test {
 
 } // namespace
 
-// Verify that host-only allocations succeed when the process is alive but
-// can't JIT. Before the fix, FindSpace would probe GetMemoryRegionInfo,
-// which could assert/crash for targets with partial address-space coverage.
-TEST_F(IRMemoryMapTest, FindSpaceNoJIT) {
+// Verify that FindSpace handles partial memory region coverage gracefully.
+TEST_F(IRMemoryMapTest, FindSpacePartialRegionCoverage) {
   ArchSpec arch("i386-pc-linux");
   Platform::SetHostPlatform(
       platform_linux::PlatformLinux::CreateInstance(true, &arch));
@@ -105,13 +103,15 @@ TEST_F(IRMemoryMapTest, FindSpaceNoJIT) {
   TestIRMemoryMap memory_map(target_sp);
   memory_map.SetProcess(process_sp);
 
-  // This would previously crash in FindSpace via lldbassert when
-  // GetMemoryRegionInfo succeeded then failed on a subsequent call.
+  // FindSpace treats the remaining address space as unmapped.
   auto addr_or_err =
       memory_map.Malloc(1024, 8, ePermissionsReadable | ePermissionsWritable,
                         IRMemoryMap::eAllocationPolicyHostOnly, false);
   ASSERT_THAT_EXPECTED(addr_or_err, llvm::Succeeded());
   EXPECT_NE(*addr_or_err, LLDB_INVALID_ADDRESS);
+  // The allocation must not overlap with the inferior's mapped region
+  // [0, 0x10000).
+  EXPECT_GE(*addr_or_err, 0x10000ULL);
 
   // A second allocation should also succeed and not overlap.
   auto addr2_or_err =



More information about the lldb-commits mailing list