[Lldb-commits] [lldb] r151128 - in /lldb/trunk: include/lldb/Core/RangeMap.h include/lldb/Target/Memory.h include/lldb/Target/Process.h lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp source/Target/Memory.cpp source/Target/Process.cpp

Greg Clayton gclayton at apple.com
Tue Feb 21 20:37:26 PST 2012


Author: gclayton
Date: Tue Feb 21 22:37:26 2012
New Revision: 151128

URL: http://llvm.org/viewvc/llvm-project?rev=151128&view=rev
Log:
For stepping performance I added the ability to outlaw all memory accesseses
to the __PAGEZERO segment on darwin. The dynamic loader now correctly doesn't
slide __PAGEZERO and it also registers it as an invalid region of memory. This
allows us to not make any memory requests from the local or remote debug session
for any addresses in this region. Stepping performance can improve when uninitialized
local variables that point to locations in __PAGEZERO are attempted to be read 
from memory as we won't even make the memory read or write request.


Modified:
    lldb/trunk/include/lldb/Core/RangeMap.h
    lldb/trunk/include/lldb/Target/Memory.h
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
    lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
    lldb/trunk/source/Target/Memory.cpp
    lldb/trunk/source/Target/Process.cpp

Modified: lldb/trunk/include/lldb/Core/RangeMap.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/RangeMap.h?rev=151128&r1=151127&r2=151128&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/RangeMap.h (original)
+++ lldb/trunk/include/lldb/Core/RangeMap.h Tue Feb 21 22:37:26 2012
@@ -188,6 +188,17 @@
             m_entries.push_back (entry);
         }
         
+        bool
+        RemoveEntrtAtIndex (uint32_t idx)
+        {
+            if (idx < m_entries.size())
+            {
+                m_entries.erase (m_entries.begin() + idx);
+                return true;
+            }
+            return false;
+        }
+        
         void
         Sort ()
         {

Modified: lldb/trunk/include/lldb/Target/Memory.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Memory.h?rev=151128&r1=151127&r2=151128&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Memory.h (original)
+++ lldb/trunk/include/lldb/Target/Memory.h Tue Feb 21 22:37:26 2012
@@ -16,10 +16,10 @@
 #include <vector>
 
 // Other libraries and framework includes
-//#include "llvm/ADT/BitVector.h"
 
 // Project includes
 #include "lldb/lldb-private.h"
+#include "lldb/Core/RangeMap.h"
 #include "lldb/Host/Mutex.h"
 
 namespace lldb_private {
@@ -54,16 +54,24 @@
         {
             return m_cache_line_byte_size ;
         }
+        
+        void
+        AddInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size);
+
+        bool
+        RemoveInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size);
+
     protected:
-        typedef std::map<lldb::addr_t, lldb::DataBufferSP> collection;
+        typedef std::map<lldb::addr_t, lldb::DataBufferSP> BlockMap;
+        typedef RangeArray<lldb::addr_t, lldb::addr_t, 4> InvalidRanges;
         //------------------------------------------------------------------
         // Classes that inherit from MemoryCache can see and modify these
         //------------------------------------------------------------------
         Process &m_process;
         uint32_t m_cache_line_byte_size;
-        Mutex m_cache_mutex;
-        collection m_cache;
-        
+        Mutex m_mutex;
+        BlockMap m_cache;
+        InvalidRanges m_invalid_ranges;
     private:
         DISALLOW_COPY_AND_ASSIGN (MemoryCache);
     };
@@ -132,7 +140,6 @@
         const uint32_t m_chunk_size;  // The size of chunks that the memory at m_addr is divied up into
         typedef std::map<uint32_t, uint32_t> OffsetToChunkSize;
         OffsetToChunkSize m_offset_to_chunk_size;
-        //llvm::BitVector m_allocated;
     };
     
 

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=151128&r1=151127&r2=151128&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Tue Feb 21 22:37:26 2012
@@ -1297,6 +1297,8 @@
         eBroadcastInternalStateControlResume = (1<<2)
     };
     
+    typedef Range<lldb::addr_t, lldb::addr_t> LoadRange;
+
     // These two functions fill out the Broadcaster interface:
     
     static ConstString &GetStaticBroadcasterClass ();
@@ -3091,6 +3093,23 @@
     void
     SetSTDIOFileDescriptor (int file_descriptor);
 
+    //------------------------------------------------------------------
+    // Add a permanent region of memory that should never be read or 
+    // written to. This can be used to ensure that memory reads or writes
+    // to certain areas of memory never end up being sent to the 
+    // DoReadMemory or DoWriteMemory functions which can improve 
+    // performance.
+    //------------------------------------------------------------------
+    void
+    AddInvalidMemoryRegion (const LoadRange &region);
+    
+    //------------------------------------------------------------------
+    // Remove a permanent region of memory that should never be read or 
+    // written to that was previously added with AddInvalidMemoryRegion.
+    //------------------------------------------------------------------
+    bool
+    RemoveInvalidMemoryRange (const LoadRange &region);
+                              
 protected:
     //------------------------------------------------------------------
     // NextEventAction provides a way to register an action on the next

Modified: lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme?rev=151128&r1=151127&r2=151128&view=diff
==============================================================================
--- lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme (original)
+++ lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme Tue Feb 21 22:37:26 2012
@@ -100,12 +100,6 @@
             ReferencedContainer = "container:lldb.xcodeproj">
          </BuildableReference>
       </BuildableProductRunnable>
-      <CommandLineArguments>
-         <CommandLineArgument
-            argument = "/private/tmp/a.out"
-            isEnabled = "YES">
-         </CommandLineArgument>
-      </CommandLineArguments>
       <EnvironmentVariables>
          <EnvironmentVariable
             key = "LLDB_LAUNCH_FLAG_DISABLE_ASLR"

Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp?rev=151128&r1=151127&r2=151128&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp Tue Feb 21 22:37:26 2012
@@ -433,39 +433,80 @@
             SectionList *section_list = image_object_file->GetSectionList ();
             if (section_list)
             {
+                std::vector<uint32_t> inaccessible_segment_indexes;
                 // We now know the slide amount, so go through all sections
                 // and update the load addresses with the correct values.
                 uint32_t num_segments = info.segments.size();
                 for (uint32_t i=0; i<num_segments; ++i)
                 {
+                    // Only load a segment if it has protections. Things like
+                    // __PAGEZERO don't have any protections, and they shouldn't
+                    // be slid
                     SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
-                    const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide;
-                    static ConstString g_section_name_LINKEDIT ("__LINKEDIT");
 
-                    if (section_sp)
+                    if (info.segments[i].maxprot == 0)
+                    {
+                        inaccessible_segment_indexes.push_back(i);
+                    }
+                    else
                     {
-                        // Don't ever load any __LINKEDIT sections since the ones in the shared
-                        // cached will be coalesced into a single section and we will get warnings
-                        // about multiple sections mapping to the same address.
-                        if (section_sp->GetName() != g_section_name_LINKEDIT)
+                        const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide;
+                        static ConstString g_section_name_LINKEDIT ("__LINKEDIT");
+
+                        if (section_sp)
                         {
-                            const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
-                            if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
-                                old_section_load_addr != new_section_load_addr)
+                            // Don't ever load any __LINKEDIT sections since the ones in the shared
+                            // cached will be coalesced into a single section and we will get warnings
+                            // about multiple sections mapping to the same address.
+                            if (section_sp->GetName() != g_section_name_LINKEDIT)
                             {
-                                if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
-                                    changed = true;
+                                const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get());
+                                if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
+                                    old_section_load_addr != new_section_load_addr)
+                                {
+                                    if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr))
+                                        changed = true;
+                                }
                             }
                         }
+                        else
+                        {
+                            Host::SystemLog (Host::eSystemLogWarning, 
+                                             "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
+                                             info.segments[i].name.AsCString("<invalid>"),
+                                             (uint64_t)new_section_load_addr,
+                                             image_object_file->GetFileSpec().GetDirectory().AsCString(),
+                                             image_object_file->GetFileSpec().GetFilename().AsCString());
+                        }
                     }
-                    else
+                }
+                
+                // If the loaded the file (it changed) and we have segments that
+                // are not readable or writeable, add them to the invalid memory
+                // region cache for the process. This will typically only be
+                // the __PAGEZERO segment in the main executable. We might be able
+                // to apply this more generally to more sections that have no
+                // protections in the future, but for now we are going to just
+                // do __PAGEZERO.
+                if (changed && !inaccessible_segment_indexes.empty())
+                {
+                    for (uint32_t i=0; i<inaccessible_segment_indexes.size(); ++i)
                     {
-                        Host::SystemLog (Host::eSystemLogWarning, 
-                                         "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
-                                         info.segments[i].name.AsCString("<invalid>"),
-                                         (uint64_t)new_section_load_addr,
-                                         image_object_file->GetFileSpec().GetDirectory().AsCString(),
-                                         image_object_file->GetFileSpec().GetFilename().AsCString());
+                        const uint32_t seg_idx = inaccessible_segment_indexes[i];
+                        SectionSP section_sp(section_list->FindSectionByName(info.segments[seg_idx].name));
+
+                        if (section_sp)
+                        {
+                            static ConstString g_pagezero_section_name("__PAGEZERO");
+                            if (g_pagezero_section_name == section_sp->GetName())
+                            {
+                                // __PAGEZERO never slides...
+                                const lldb::addr_t vmaddr = info.segments[seg_idx].vmaddr;
+                                const lldb::addr_t vmsize = info.segments[seg_idx].vmsize;
+                                Process::LoadRange pagezero_range (vmaddr, vmsize);
+                                m_process->AddInvalidMemoryRegion(pagezero_range);
+                            }
+                        }
                     }
                 }
             }

Modified: lldb/trunk/source/Target/Memory.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Memory.cpp?rev=151128&r1=151127&r2=151128&view=diff
==============================================================================
--- lldb/trunk/source/Target/Memory.cpp (original)
+++ lldb/trunk/source/Target/Memory.cpp Tue Feb 21 22:37:26 2012
@@ -26,8 +26,9 @@
 MemoryCache::MemoryCache(Process &process) :
     m_process (process),
     m_cache_line_byte_size (512),
-    m_cache_mutex (Mutex::eMutexTypeRecursive),
-    m_cache ()
+    m_mutex (Mutex::eMutexTypeRecursive),
+    m_cache (),
+    m_invalid_ranges ()
 {
 }
 
@@ -41,7 +42,7 @@
 void
 MemoryCache::Clear()
 {
-    Mutex::Locker locker (m_cache_mutex);
+    Mutex::Locker locker (m_mutex);
     m_cache.clear();
 }
 
@@ -56,7 +57,7 @@
     const addr_t flush_start_addr = addr - (addr % cache_line_byte_size);
     const addr_t flush_end_addr = end_addr - (end_addr % cache_line_byte_size);
     
-    Mutex::Locker locker (m_cache_mutex);
+    Mutex::Locker locker (m_mutex);
     if (m_cache.empty())
         return;
     
@@ -64,12 +65,43 @@
     
     for (addr_t curr_addr = flush_start_addr; curr_addr <= flush_end_addr; curr_addr += cache_line_byte_size)
     {
-        collection::iterator pos = m_cache.find (curr_addr);
+        BlockMap::iterator pos = m_cache.find (curr_addr);
         if (pos != m_cache.end())
             m_cache.erase(pos);
     }
 }
 
+void
+MemoryCache::AddInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size)
+{
+    if (byte_size > 0)
+    {
+        Mutex::Locker locker (m_mutex);
+        InvalidRanges::Entry range (base_addr, byte_size);
+        m_invalid_ranges.Append(range);
+        m_invalid_ranges.Sort();
+    }
+}
+
+bool
+MemoryCache::RemoveInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size)
+{
+    if (byte_size > 0)
+    {
+        Mutex::Locker locker (m_mutex);
+        const uint32_t idx = m_invalid_ranges.FindEntryIndexThatContains(base_addr);
+        if (idx != UINT32_MAX)
+        {
+            const InvalidRanges::Entry *entry = m_invalid_ranges.GetEntryAtIndex (idx);
+            if (entry->GetRangeBase() == base_addr && entry->GetByteSize() == byte_size)
+                return m_invalid_ranges.RemoveEntrtAtIndex (idx);
+        }
+    }
+    return false;
+}
+
+
+
 size_t
 MemoryCache::Read (addr_t addr,  
                    void *dst, 
@@ -83,12 +115,15 @@
         uint8_t *dst_buf = (uint8_t *)dst;
         addr_t curr_addr = addr - (addr % cache_line_byte_size);
         addr_t cache_offset = addr - curr_addr;
-        Mutex::Locker locker (m_cache_mutex);
+        Mutex::Locker locker (m_mutex);
         
         while (bytes_left > 0)
         {
-            collection::const_iterator pos = m_cache.find (curr_addr);
-            collection::const_iterator end = m_cache.end ();
+            if (m_invalid_ranges.FindEntryThatContains(curr_addr))
+                return dst_len - bytes_left;
+
+            BlockMap::const_iterator pos = m_cache.find (curr_addr);
+            BlockMap::const_iterator end = m_cache.end ();
             
             if (pos != end)
             {

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=151128&r1=151127&r2=151128&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Tue Feb 21 22:37:26 2012
@@ -4451,6 +4451,19 @@
     return num_thread_infos_dumped;
 }
 
+void
+Process::AddInvalidMemoryRegion (const LoadRange &region)
+{
+    m_memory_cache.AddInvalidRange(region.GetRangeBase(), region.GetByteSize());
+}
+
+bool
+Process::RemoveInvalidMemoryRange (const LoadRange &region)
+{
+    return m_memory_cache.RemoveInvalidRange(region.GetRangeBase(), region.GetByteSize());
+}
+
+
 //--------------------------------------------------------------
 // class Process::SettingsController
 //--------------------------------------------------------------





More information about the lldb-commits mailing list