aadsm created this revision.
aadsm added reviewers: clayborg, xiaobai.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
aadsm added a parent revision: D62502: Implement xfer:libraries-svr4:read 
packet.

This is the fifth and final patch to improve module loading in a series that 
started here (where I explain the motivation and solution): D62499 
<https://reviews.llvm.org/D62499>

Reading strings with ReadMemory is really slow when reading the path of the 
shared library. This is because we don't know the length of the path so use 
PATH_MAX (4096) and these strings are actually super close to the boundary of 
an unreadable page. So even though we use process_vm_readv it will usually fail 
because the read size spans to the unreadable page and we then default to read 
the string word by word with ptrace.

This new function is very similar to another ReadCStringFromMemory that already 
exists in lldb that makes sure it never reads cross page boundaries and checks 
if we already read the entire string by finding '\0'.

I was able to reduce the GetLoadedSharedLibraries call from 30ms to 4ms (or 
something of that order).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D62503

Files:
  lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp


Index: lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -1499,6 +1499,44 @@
   return Status();
 }
 
+Status NativeProcessLinux::ReadCStringFromMemory(lldb::addr_t addr,
+                                                 char *buffer, size_t max_size,
+                                                 size_t &total_bytes_read) {
+  const size_t cache_line_size = 4096;
+  size_t bytes_read = 0;
+  size_t bytes_left = max_size;
+  addr_t curr_addr = addr;
+  char *curr_buffer = buffer;
+  total_bytes_read = 0;
+  Status error;
+
+  while (bytes_left > 0 && error.Success()) {
+    addr_t cache_line_bytes_left =
+        cache_line_size - (curr_addr % cache_line_size);
+    addr_t bytes_to_read = std::min<addr_t>(bytes_left, cache_line_bytes_left);
+    error = ReadMemory(curr_addr, reinterpret_cast<void *>(curr_buffer),
+                       bytes_to_read, bytes_read);
+
+    if (bytes_read == 0)
+      break;
+
+    auto str_end = std::memchr(curr_buffer, '\0', bytes_read);
+    if (str_end != NULL) {
+      total_bytes_read = (size_t)(reinterpret_cast<char *>(str_end) - buffer);
+      error.Clear();
+      break;
+    }
+
+    total_bytes_read += bytes_read;
+    curr_buffer += bytes_read;
+    curr_addr = reinterpret_cast<addr_t>(reinterpret_cast<char *>(curr_addr) +
+                                         bytes_read);
+    bytes_left -= bytes_read;
+  }
+
+  return error;
+}
+
 Status NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf,
                                        size_t size, size_t &bytes_written) {
   const unsigned char *src = static_cast<const unsigned char *>(buf);
@@ -2181,8 +2219,9 @@
     return error;
 
   char name_buffer[PATH_MAX];
-  error = ReadMemory(link_map.l_name, &name_buffer, sizeof(name_buffer),
-                     bytes_read);
+  error = ReadCStringFromMemory(link_map.l_name,
+                                reinterpret_cast<char *>(&name_buffer),
+                                sizeof(name_buffer), bytes_read);
   if (!error.Success())
     return error;
 


Index: lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -1499,6 +1499,44 @@
   return Status();
 }
 
+Status NativeProcessLinux::ReadCStringFromMemory(lldb::addr_t addr,
+                                                 char *buffer, size_t max_size,
+                                                 size_t &total_bytes_read) {
+  const size_t cache_line_size = 4096;
+  size_t bytes_read = 0;
+  size_t bytes_left = max_size;
+  addr_t curr_addr = addr;
+  char *curr_buffer = buffer;
+  total_bytes_read = 0;
+  Status error;
+
+  while (bytes_left > 0 && error.Success()) {
+    addr_t cache_line_bytes_left =
+        cache_line_size - (curr_addr % cache_line_size);
+    addr_t bytes_to_read = std::min<addr_t>(bytes_left, cache_line_bytes_left);
+    error = ReadMemory(curr_addr, reinterpret_cast<void *>(curr_buffer),
+                       bytes_to_read, bytes_read);
+
+    if (bytes_read == 0)
+      break;
+
+    auto str_end = std::memchr(curr_buffer, '\0', bytes_read);
+    if (str_end != NULL) {
+      total_bytes_read = (size_t)(reinterpret_cast<char *>(str_end) - buffer);
+      error.Clear();
+      break;
+    }
+
+    total_bytes_read += bytes_read;
+    curr_buffer += bytes_read;
+    curr_addr = reinterpret_cast<addr_t>(reinterpret_cast<char *>(curr_addr) +
+                                         bytes_read);
+    bytes_left -= bytes_read;
+  }
+
+  return error;
+}
+
 Status NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf,
                                        size_t size, size_t &bytes_written) {
   const unsigned char *src = static_cast<const unsigned char *>(buf);
@@ -2181,8 +2219,9 @@
     return error;
 
   char name_buffer[PATH_MAX];
-  error = ReadMemory(link_map.l_name, &name_buffer, sizeof(name_buffer),
-                     bytes_read);
+  error = ReadCStringFromMemory(link_map.l_name,
+                                reinterpret_cast<char *>(&name_buffer),
+                                sizeof(name_buffer), bytes_read);
   if (!error.Success())
     return error;
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to