aadsm created this revision.
aadsm added reviewers: clayborg, xiaobai.
Herald added subscribers: lldb-commits, krytarowski, srhines.
Herald added a project: LLDB.
aadsm added a parent revision: D62501: Implement GetSharedLibraryInfoAddress.
aadsm added a child revision: D62503: Add ReadCStringFromMemory for faster 
string reads.

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

Implement the `xfer:libraries-svr4` packet by adding a new function that 
generates the list and then in Handle_xfer I generate the XML for it. The XML 
is really simple so I'm just using string concatenation because I believe it's 
more readable than having to deal with a DOM api.

Concerns
--------

- I'm not sure about the having the ELFLinkMap and the SharedLibraryInfo struct 
in there. I thought about creating a function or class outside of 
NativeProcessLinux so it could be reusable in other contexts but the core 
functions need to use ReadMemory so it was not convinent and I guess would have 
forced me to pass a lambda as a wrapper to ReadMemory. This would introduce 
more complexity to the code and I'm not sure if it would be worthwhile.

- On Handle_xfer function the backing buffer structure uses MemoryBuffers so I 
had to create one out of the StreamString response I generate with the XML. 
This kind of sucks because I'm copying all this data when I usually don't even 
need it. And if I do need it still sucks because I'm copying something that I 
just generated right there. I couldn't find a way to generate the XML into a 
MemoryBuffer (as it requires to know the size before hand) or use another 
structure that would make this easier. I've thought about changing the backing 
structure to StringRefs but that object doesn't really own the underlying 
"const char*" so I can't keep it without copying again. Any suggestions here?


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D62502

Files:
  lldb/include/lldb/Host/common/NativeProcessProtocol.h
  lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
  lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp

Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -2760,6 +2760,28 @@
 #else
       return SendUnimplementedResponse("not implemented on this platform");
 #endif
+    } else if (xfer_object == "libraries-svr4") {
+#if defined(__linux__)
+      std::vector<SharedLibraryInfo> library_list;
+      auto error =
+          m_debugged_process_up->GetLoadedSharedLibraries(library_list);
+      if (!error.Success())
+        return SendErrorResponse(error.GetError());
+
+      StreamString response;
+      response.Printf("<library-list-svr4 version=\"1.0\">");
+      for (auto const &library : library_list) {
+        response.Printf("<library name=\"%s\" ", library.name.c_str());
+        response.Printf("lm=\"0x%" PRIx64 "\" ", library.link_map);
+        response.Printf("l_addr=\"0x%" PRIx64 "\" ", library.base_addr);
+        response.Printf("l_ld=\"0x%" PRIx64 "\" />", library.ld_addr);
+      }
+      response.Printf("</library-list-svr4>");
+      memory_buffer_sp = std::move(
+          MemoryBuffer::getMemBufferCopy(response.GetString(), __FUNCTION__));
+#else
+      return SendUnimplementedResponse("not implemented on this platform");
+#endif
     } else
       return SendUnimplementedResponse("Xfer object not supported");
   }
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -826,6 +826,9 @@
   response.PutCString(";QPassSignals+");
   response.PutCString(";qXfer:auxv:read+");
 #endif
+#if defined(__linux__)
+  response.PutCString(";qXfer:libraries-svr4:read+");
+#endif
 
   return SendPacketNoLock(response.GetString());
 }
Index: lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
+++ lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
@@ -79,6 +79,9 @@
 
   lldb::addr_t GetSharedLibraryInfoAddress() override;
 
+  Status GetLoadedSharedLibraries(
+      std::vector<SharedLibraryInfo> &library_list) override;
+
   size_t UpdateThreads() override;
 
   const ArchSpec &GetArchitecture() const override { return m_arch; }
@@ -133,6 +136,17 @@
   template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN>
   lldb::addr_t GetELFImageInfoAddress();
 
+  template <typename T> struct ELFLinkMap {
+    T l_addr;
+    T l_name;
+    T l_ld;
+    T l_next;
+    T l_prev;
+  };
+  template <typename T>
+  Status ReadSharedLibraryInfo(lldb::addr_t link_map_addr,
+                               SharedLibraryInfo &info);
+
 private:
   MainLoop::SignalHandleUP m_sigchld_handle;
   ArchSpec m_arch;
Index: lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
===================================================================
--- lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -2169,3 +2169,76 @@
 
   return LLDB_INVALID_ADDRESS;
 }
+
+template <typename T>
+Status NativeProcessLinux::ReadSharedLibraryInfo(lldb::addr_t link_map_addr,
+                                                 SharedLibraryInfo &info) {
+  ELFLinkMap<T> link_map;
+  size_t bytes_read;
+  auto error =
+      ReadMemory(link_map_addr, &link_map, sizeof(link_map), bytes_read);
+  if (!error.Success())
+    return error;
+
+  char name_buffer[PATH_MAX];
+  error = ReadMemory(link_map.l_name, &name_buffer, sizeof(name_buffer),
+                     bytes_read);
+  if (!error.Success())
+    return error;
+
+  info.name = std::string(name_buffer);
+  info.link_map = link_map_addr;
+  info.base_addr = link_map.l_addr;
+  info.ld_addr = link_map.l_ld;
+  info.next = link_map.l_next;
+#if defined(__linux__) && !defined(__ANDROID__)
+  // On non-android linux systems, main executable has an empty path.
+  info.main = info.main.empty();
+#elif defined(__linux__) && defined(__ANDROID__)
+  // On android, the main executable has a load address of 0.
+  info.main = info.ld_addr == 0;
+#else
+  info.main = false;
+#endif
+
+  return Status();
+}
+
+Status NativeProcessLinux::GetLoadedSharedLibraries(
+    std::vector<SharedLibraryInfo> &library_list) {
+  // Address of DT_DEBUG.d_ptr which points to r_debug
+  lldb::addr_t info_address = GetSharedLibraryInfoAddress();
+  if (info_address == LLDB_INVALID_ADDRESS)
+    return Status("Invalid shared library info address");
+  // Address of r_debug
+  lldb::addr_t address = 0;
+  size_t bytes_read;
+  auto error =
+      ReadMemory(info_address, &address, GetAddressByteSize(), bytes_read);
+  if (!error.Success())
+    return error;
+  if (address == 0)
+    return Status("Invalid r_debug address");
+  // Read r_debug.r_map
+  lldb::addr_t link_map = 0;
+  error = ReadMemory(address + GetAddressByteSize(), &link_map,
+                     GetAddressByteSize(), bytes_read);
+  if (!error.Success())
+    return error;
+  if (address == 0)
+    return Status("Invalid link_map address");
+
+  while (link_map) {
+    SharedLibraryInfo info;
+    if (GetAddressByteSize() == 8)
+      error = ReadSharedLibraryInfo<uint64_t>(link_map, info);
+    else
+      error = ReadSharedLibraryInfo<uint32_t>(link_map, info);
+    if (!error.Success())
+      return error;
+    library_list.push_back(info);
+    link_map = info.next;
+  }
+
+  return Status();
+}
Index: lldb/include/lldb/Host/common/NativeProcessProtocol.h
===================================================================
--- lldb/include/lldb/Host/common/NativeProcessProtocol.h
+++ lldb/include/lldb/Host/common/NativeProcessProtocol.h
@@ -32,6 +32,15 @@
 class MemoryRegionInfo;
 class ResumeActionList;
 
+struct SharedLibraryInfo {
+  std::string name;
+  lldb::addr_t link_map;
+  lldb::addr_t base_addr;
+  lldb::addr_t ld_addr;
+  bool main;
+  lldb::addr_t next;
+};
+
 // NativeProcessProtocol
 class NativeProcessProtocol {
 public:
@@ -86,6 +95,11 @@
 
   virtual lldb::addr_t GetSharedLibraryInfoAddress() = 0;
 
+  virtual Status
+  GetLoadedSharedLibraries(std::vector<SharedLibraryInfo> &library_list) {
+    return Status("Not implemented");
+  }
+
   virtual bool IsAlive() const;
 
   virtual size_t UpdateThreads() = 0;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to