diff options
| -rw-r--r-- | lldb/include/lldb/Core/RangeMap.h | 11 | ||||
| -rw-r--r-- | lldb/include/lldb/Target/Memory.h | 19 | ||||
| -rw-r--r-- | lldb/include/lldb/Target/Process.h | 19 | ||||
| -rw-r--r-- | lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme | 6 | ||||
| -rw-r--r-- | lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp | 79 | ||||
| -rw-r--r-- | lldb/source/Target/Memory.cpp | 51 | ||||
| -rw-r--r-- | lldb/source/Target/Process.cpp | 13 |
7 files changed, 159 insertions, 39 deletions
diff --git a/lldb/include/lldb/Core/RangeMap.h b/lldb/include/lldb/Core/RangeMap.h index dd41375499b..e4336558f98 100644 --- a/lldb/include/lldb/Core/RangeMap.h +++ b/lldb/include/lldb/Core/RangeMap.h @@ -188,6 +188,17 @@ namespace lldb_private { 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 () { diff --git a/lldb/include/lldb/Target/Memory.h b/lldb/include/lldb/Target/Memory.h index 3a45c911b3e..8171a9862f0 100644 --- a/lldb/include/lldb/Target/Memory.h +++ b/lldb/include/lldb/Target/Memory.h @@ -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 @@ namespace lldb_private { { 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 @@ namespace lldb_private { 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; }; diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index ce0e145f64a..cf556a37e20 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -1297,6 +1297,8 @@ public: 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 @@ public: 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 ®ion); + + //------------------------------------------------------------------ + // Remove a permanent region of memory that should never be read or + // written to that was previously added with AddInvalidMemoryRegion. + //------------------------------------------------------------------ + bool + RemoveInvalidMemoryRange (const LoadRange ®ion); + protected: //------------------------------------------------------------------ // NextEventAction provides a way to register an action on the next diff --git a/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme b/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme index 3a6ee591b31..5c24cc3fc9b 100644 --- a/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme +++ b/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme @@ -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" diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp index e77f948cba8..4f78e3e88e8 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -433,39 +433,80 @@ DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, DYLDImageInfo& 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); + } + } } } } diff --git a/lldb/source/Target/Memory.cpp b/lldb/source/Target/Memory.cpp index 3f5567b7c8f..fb05c9723c3 100644 --- a/lldb/source/Target/Memory.cpp +++ b/lldb/source/Target/Memory.cpp @@ -26,8 +26,9 @@ using namespace lldb_private; 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 @@ MemoryCache::~MemoryCache() void MemoryCache::Clear() { - Mutex::Locker locker (m_cache_mutex); + Mutex::Locker locker (m_mutex); m_cache.clear(); } @@ -56,7 +57,7 @@ MemoryCache::Flush (addr_t addr, size_t size) 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 @@ MemoryCache::Flush (addr_t addr, size_t size) 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 @@ MemoryCache::Read (addr_t addr, 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) { diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index e959e407001..d0b7a2b8a53 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -4451,6 +4451,19 @@ Process::GetThreadStatus (Stream &strm, return num_thread_infos_dumped; } +void +Process::AddInvalidMemoryRegion (const LoadRange ®ion) +{ + m_memory_cache.AddInvalidRange(region.GetRangeBase(), region.GetByteSize()); +} + +bool +Process::RemoveInvalidMemoryRange (const LoadRange ®ion) +{ + return m_memory_cache.RemoveInvalidRange(region.GetRangeBase(), region.GetByteSize()); +} + + //-------------------------------------------------------------- // class Process::SettingsController //-------------------------------------------------------------- |

