spyffe created this revision.
spyffe added reviewers: tfiala, clayborg.
spyffe added a subscriber: lldb-commits.
spyffe set the repository for this revision to rL LLVM.

Right now the default initial address is 0x0, which is very problematic on 
embedded targets where that's the CPU's initialization vector.
To help in these scenarios, this patch uses the GetMemoryRegionInfo() API to 
find an appropriately-sized region.
It also sets better fallback defaults than 0x0 if all of the other approaches 
fail

Repository:
  rL LLVM

http://reviews.llvm.org/D21152

Files:
  source/Expression/IRMemoryMap.cpp

Index: source/Expression/IRMemoryMap.cpp
===================================================================
--- source/Expression/IRMemoryMap.cpp
+++ source/Expression/IRMemoryMap.cpp
@@ -13,8 +13,10 @@
 #include "lldb/Core/Log.h"
 #include "lldb/Core/Scalar.h"
 #include "lldb/Expression/IRMemoryMap.h"
+#include "lldb/Target/MemoryRegionInfo.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Utility/LLDBAssert.h"
 
 using namespace lldb_private;
 
@@ -47,23 +49,34 @@
 }
 
 lldb::addr_t
-IRMemoryMap::FindSpace (size_t size, bool zero_memory)
+IRMemoryMap::FindSpace (size_t size)
 {
+    // The FindSpace algorithm's job is to find a region of memory that the
+    // underlying process is unlikely to be using.
+    //
+    // The memory returned by this function will never be written to.  The only
+    // point is that it should not shadow process memory if possible, so that
+    // expressions processing real values from the process do not use the
+    // wrong data.
+    //
+    // If the process can in fact allocate memory (CanJIT() lets us know this)
+    // then this can be accomplished just be allocating memory in the inferior.
+    // Then no guessing is required.
+
     lldb::TargetSP target_sp = m_target_wp.lock();
     lldb::ProcessSP process_sp = m_process_wp.lock();
+    
+    const bool is_alive = process_sp->IsAlive();
 
     lldb::addr_t ret = LLDB_INVALID_ADDRESS;
     if (size == 0)
         return ret;
 
-    if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
+    if (process_sp && process_sp->CanJIT() && is_alive)
     {
         Error alloc_error;
 
-        if (!zero_memory)
-            ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
-        else
-            ret = process_sp->CallocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
+        ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
 
         if (!alloc_error.Success())
             return LLDB_INVALID_ADDRESS;
@@ -70,15 +83,103 @@
         else
             return ret;
     }
+    
+    // At this point we know that we need to hunt.
+    //
+    // First, go to the end of the existing allocations we've made if there are
+    // any allocations.  Otherwise start at the beginning of memory.
 
-    ret = 0;
-    if (!m_allocations.empty())
+    if (m_allocations.empty())
     {
+        ret = 0x0;
+    }
+    else
+    {
         auto back = m_allocations.rbegin();
         lldb::addr_t addr = back->first;
         size_t alloc_size = back->second.m_size;
         ret = llvm::alignTo(addr+alloc_size, 4096);
     }
+    
+    // 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.
+    if (process_sp && is_alive)
+    {
+        const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8 ?
+            0xffffffffffffffffull : 0xffffffffull;
+        
+        lldbassert(process_sp->GetAddressByteSize() == 4 || end_of_memory != 0xffffffffull);
+        
+        MemoryRegionInfo region_info;
+        Error err = process_sp->GetMemoryRegionInfo(ret, region_info);
+        if (err.Success())
+        {
+            while (true)
+            {
+                if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo ||
+                    region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo ||
+                    region_info.GetExecutable() != MemoryRegionInfo::OptionalBool::eNo)
+                {
+                    if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory)
+                    {
+                        ret = LLDB_INVALID_ADDRESS;
+                        break;
+                    }
+                    else
+                    {
+                        ret = region_info.GetRange().GetRangeEnd();
+                    }
+                }
+                else if (ret + size < region_info.GetRange().GetRangeEnd())
+                {
+                    return ret;
+                }
+                else
+                {
+                    // ret stays the same.  We just need to walk a bit further.
+                }
+                
+                err = process_sp->GetMemoryRegionInfo(region_info.GetRange().GetRangeEnd(), region_info);
+                if (err.Fail())
+                {
+                    lldbassert(!"GetMemoryRegionInfo() succeeded, then failed");
+                    ret = LLDB_INVALID_ADDRESS;
+                    break;
+                }
+            }
+        }
+    }
+    
+    // We've tried our algorithm, and it didn't work.  Now we have to reset back
+    // to the end of the allocations we've already reported, or use a 'sensible'
+    // default if this is our first allocation.
+    
+    if (m_allocations.empty())
+    {
+        uint32_t address_byte_size = GetAddressByteSize();
+        if (address_byte_size != UINT32_MAX)
+        {
+            switch (address_byte_size)
+            {
+                case 8:
+                    ret = 0xffffffff00000000ull;
+                    break;
+                case 4:
+                    ret = 0xee000000ull;
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+    else
+    {
+        auto back = m_allocations.rbegin();
+        lldb::addr_t addr = back->first;
+        size_t alloc_size = back->second.m_size;
+        ret = llvm::alignTo(addr+alloc_size, 4096);
+    }
 
     return ret;
 }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to