[Lldb-commits] [PATCH] D134906: Have MemoryCache cache addresses that were unreadable, so duplicate read attempts can be suppressed

Jason Molenda via Phabricator via lldb-commits lldb-commits at lists.llvm.org
Thu Sep 29 13:57:43 PDT 2022


jasonmolenda created this revision.
jasonmolenda added reviewers: jingham, JDevlieghere.
jasonmolenda added a project: LLDB.
Herald added a project: All.
jasonmolenda requested review of this revision.
Herald added a subscriber: lldb-commits.

This patch is to address an issue hit by one of our heavy SB API scripting developers; they have some code iterating over a large number of objects in SBValue's and one of the elements of the object has a type of void*; the Itanium ABI is trying to sniff the memory there to see if it might have a dynamic type.  In this case, the elements often have the value 0, so lldb is trying to read memory at address 0, which fails, and the number of reads is quite large.  Each failing memory read takes long enough in a JTAG like environment that this is a big perf issue.

We have a MemoryCache subsystem that saves blocks of inferior memory when we do a read, so repeated reads of the same address, or reads near the address that were cached, are saved at a single point in time.  These memory cache buffers are flushed when execution is resumed.

This patch adds a new list of addresses we've tried to read from at this execution stop, which returned an error, and will not try to read from those addresses again.  If lldb allocates memory in the inferior, or if we resume execution, this list of addresses is flushed.

I settled on using an llvm::SmallSet container for these addr_t's, but I'd appreciate if people have a different suggestion for the most appropriate container.  I expect this list to be relatively small -- it is not common that lldb tries to read from addresses that are unreadable -- and my primary optimization concern is quick lookup because I will consult this list before I read from any address in memory.

When I was outlining my idea for this, Jim pointed out that MemoryCache has a `InvalidRanges m_invalid_ranges` ivar already, and could I reuse this.  This is called by the DynamicLoader to mark a region of memory as never accessible (e.g. the lower 4GB on a 64-bit Darwin process), and is not flushed on execution resume / memory allocation.  It is expressed in terms of memory ranges, when I don't know the range of memory that is inaccessible beyond an address.  I could assume the range extends to the end of a page boundary, if I knew the page boundary size, but that still doesn't address the fact that `m_invalid_ranges` is intended to track inaccessible memory that is invariant during the process lifetime.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134906

Files:
  lldb/include/lldb/Target/Memory.h
  lldb/source/Target/Memory.cpp
  lldb/source/Target/Process.cpp
  lldb/test/API/functionalities/gdb_remote_client/TestMemoryReadFailCache.py

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D134906.464017.patch
Type: text/x-patch
Size: 7444 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20220929/a0d46092/attachment.bin>


More information about the lldb-commits mailing list