This revision was automatically updated to reflect the committed changes.
Closed by commit rGe67cee09499c: [lldb] Avoid duplicate vdso modules when 
opening core files (authored by labath).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D122660/new/

https://reviews.llvm.org/D122660

Files:
  lldb/include/lldb/Target/DynamicLoader.h
  lldb/packages/Python/lldbsuite/test/gdbclientutils.py
  lldb/source/Core/DynamicLoader.cpp
  lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
  lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
  lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp
  lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.h
  lldb/test/API/functionalities/gdb_remote_client/TestGdbClientModuleLoad.py
  lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
  lldb/test/API/functionalities/gdb_remote_client/module_load.yaml

Index: lldb/test/API/functionalities/gdb_remote_client/module_load.yaml
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/gdb_remote_client/module_load.yaml
@@ -0,0 +1,53 @@
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x0000
+    AddressAlign:    0x4
+    Content:         "c3c3c3c3"
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x1000
+    AddressAlign:    0x4
+    Size:            0x28
+  - Name:            .dynamic
+    Type:            SHT_DYNAMIC
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x8
+    Entries:
+      - Tag:             DT_DEBUG
+        Value:           0xdead0000
+
+ProgramHeaders:
+  - Type: PT_LOAD
+    Flags: [ PF_X, PF_R ]
+    VAddr: 0x0000
+    Align: 0x4
+    FirstSec: .text
+    LastSec:  .text
+  - Type: PT_LOAD
+    Flags: [ PF_R, PF_W ]
+    VAddr: 0x1000
+    Align: 0x4
+    FirstSec: .data
+    LastSec:  .dynamic
+  - Type:            PT_DYNAMIC
+    Flags:           [ PF_W, PF_R ]
+    VAddr:           0x1028
+    FirstSec:        .dynamic
+    LastSec:         .dynamic
+DynamicSymbols:
+  - Name:            _r_debug
+    Type:            STT_OBJECT
+    Section:         .data
+    Binding:         STB_GLOBAL
+    Value:           0x0
+    Size:            0x28
+
Index: lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
===================================================================
--- lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
+++ lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
@@ -32,8 +32,6 @@
         MockGDBServerResponder.__init__(self)
 
     def respond(self, packet):
-        if packet == "qProcessInfo":
-            return self.qProcessInfo()
         if packet[0:13] == "qRegisterInfo":
             return self.qRegisterInfo(packet[13:])
         return MockGDBServerResponder.respond(self, packet)
Index: lldb/test/API/functionalities/gdb_remote_client/TestGdbClientModuleLoad.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/gdb_remote_client/TestGdbClientModuleLoad.py
@@ -0,0 +1,133 @@
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test.gdbclientutils import *
+from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
+from lldbsuite.support import seven
+
+class MyResponder(MockGDBServerResponder):
+    """
+    A responder which simulates a process with a single shared library loaded.
+    Its parameters allow configuration of various properties of the library.
+    """
+
+    def __init__(self, testcase, triple, library_name, auxv_entry, region_info):
+        MockGDBServerResponder.__init__(self)
+        self.testcase = testcase
+        self._triple = triple
+        self._library_name = library_name
+        self._auxv_entry = auxv_entry
+        self._region_info = region_info
+
+    def qSupported(self, client_supported):
+        return (super().qSupported(client_supported) +
+            ";qXfer:auxv:read+;qXfer:libraries-svr4:read+")
+
+    def qXferRead(self, obj, annex, offset, length):
+        if obj == "features" and annex == "target.xml":
+            return """<?xml version="1.0"?>
+                <target version="1.0">
+                  <architecture>i386:x86-64</architecture>
+                  <feature name="org.gnu.gdb.i386.core">
+                    <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/>
+                  </feature>
+                </target>""", False
+        elif obj == "auxv":
+            # 0x09 = AT_ENTRY, which lldb uses to compute the load bias of the
+            # main binary.
+            return hex_decode_bytes(self._auxv_entry +
+                "09000000000000000000ee000000000000000000000000000000000000000000"), False
+        elif obj == "libraries-svr4":
+            return """<?xml version="1.0"?>
+                <library-list-svr4 version="1.0">
+                  <library name="%s" lm="0xdeadbeef" l_addr="0xef0000" l_ld="0xdeadbeef"/>
+                </library-list-svr4>""" % self._library_name, False
+        else:
+            return None, False
+
+    def qfThreadInfo(self):
+        return "m47"
+
+    def qsThreadInfo(self):
+        return "l"
+
+    def qProcessInfo(self):
+        return "pid:47;ptrsize:8;endian:little;triple:%s;" % hex_encode_bytes(self._triple)
+
+    def setBreakpoint(self, packet):
+        return "OK"
+
+    def readMemory(self, addr, length):
+        if addr == 0xee1000:
+            return "00"*0x30 + "0020ee0000000000"
+        elif addr == 0xee2000:
+            return "01000000000000000030ee0000000000dead00000000000000000000000000000000000000000000"
+        elif addr == 0xef0000:
+            with open(self.testcase.getBuildArtifact("libmodule_load.so"), "rb") as f:
+                contents = f.read(-1)
+            return hex_encode_bytes(seven.bitcast_to_string(contents))
+        return ("baadf00d00"*1000)[0:length*2]
+
+    def qMemoryRegionInfo(self, addr):
+        if addr < 0xee0000:
+            return "start:0;size:ee0000;"
+        elif addr < 0xef0000:
+            return "start:ee0000;size:10000;"
+        elif addr < 0xf00000:
+            return "start:ef0000;size:1000;permissions:rx;" + self._region_info
+        else:
+            return "start:ef1000;size:ffffffffff10f000"
+
+class TestGdbClientModuleLoad(GDBRemoteTestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @skipIfXmlSupportMissing
+    def test_android_app_process(self):
+        """
+        This test simulates the scenario where the (android) dynamic linker
+        reports incorrect file name of the main executable. Lldb uses
+        qMemoryRegionInfo to get the correct value.
+        """
+        region_info = "name:%s;" % (
+                    hex_encode_bytes(self.getBuildArtifact("libmodule_load.so")))
+        self.server.responder = MyResponder(self, "x86_64-pc-linux-android",
+                "bogus-name", "", region_info)
+        self.yaml2obj("module_load.yaml", self.getBuildArtifact("libmodule_load.so"))
+        target = self.createTarget("module_load.yaml")
+
+        process = self.connect(target)
+        self.assertTrue(process.IsValid(), "Process is valid")
+
+        lldbutil.expect_state_changes(self, self.dbg.GetListener(), process,
+                [lldb.eStateStopped])
+
+        self.filecheck("image list", __file__, "-check-prefix=ANDROID")
+# ANDROID: [  0] {{.*}} 0x0000000000ee0000 {{.*}}module_load
+# ANDROID: [  1] {{.*}} 0x0000000000ef0000 {{.*}}libmodule_load.so
+
+    @skipIfXmlSupportMissing
+    def test_vdso(self):
+        """
+        This test checks vdso loading in the situation where the process does
+        not have memory region information about the vdso address. This can
+        happen in core files, as they don't store this data.
+        We want to check that the vdso is loaded exactly once.
+        """
+        # vdso address
+        AT_SYSINFO_EHDR = "21000000000000000000ef0000000000"
+        self.server.responder = MyResponder(self, "x86_64-pc-linux",
+                "linux-vdso.so.1", AT_SYSINFO_EHDR, "")
+        self.yaml2obj("module_load.yaml", self.getBuildArtifact("libmodule_load.so"))
+        target = self.createTarget("module_load.yaml")
+
+        process = self.connect(target)
+        self.assertTrue(process.IsValid(), "Process is valid")
+
+        lldbutil.expect_state_changes(self, self.dbg.GetListener(), process,
+                [lldb.eStateStopped])
+
+        self.filecheck("image list", __file__, "-check-prefix=VDSO")
+# VDSO: [  0] {{.*}} 0x0000000000ee0000 {{.*}}module_load
+# VDSO: [  1] {{.*}} 0x0000000000ef0000 {{.*}}[vdso]
+        self.assertEquals(self.target().GetNumModules(), 2)
Index: lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.h
===================================================================
--- lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.h
+++ lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.h
@@ -33,6 +33,11 @@
   Status CanLoadImage() override { return Status(); }
   lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
                                                   bool stop) override;
+  lldb::ModuleSP LoadModuleAtAddress(const lldb_private::FileSpec &file,
+                                     lldb::addr_t link_map_addr,
+                                     lldb::addr_t base_addr,
+                                     bool base_addr_is_offset) override;
+
   /// \}
 
   /// PluginInterface protocol.
Index: lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp
===================================================================
--- lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp
+++ lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp
@@ -64,3 +64,19 @@
                                                                  bool stop) {
   return ThreadPlanSP();
 }
+
+lldb::ModuleSP DynamicLoaderWasmDYLD::LoadModuleAtAddress(
+    const lldb_private::FileSpec &file, lldb::addr_t link_map_addr,
+    lldb::addr_t base_addr, bool base_addr_is_offset) {
+  if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(
+          file, link_map_addr, base_addr, base_addr_is_offset))
+    return module_sp;
+
+  if (ModuleSP module_sp = m_process->ReadModuleFromMemory(file, base_addr)) {
+    UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
+    m_process->GetTarget().GetImages().AppendIfNeeded(module_sp);
+    return module_sp;
+  }
+
+  return nullptr;
+}
Index: lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
===================================================================
--- lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -55,6 +55,11 @@
   // PluginInterface protocol
   llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
 
+  lldb::ModuleSP LoadModuleAtAddress(const lldb_private::FileSpec &file,
+                                     lldb::addr_t link_map_addr,
+                                     lldb::addr_t base_addr,
+                                     bool base_addr_is_offset) override;
+
 protected:
   /// Runtime linker rendezvous structure.
   DYLDRendezvous m_rendezvous;
Index: lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
===================================================================
--- lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -575,6 +575,38 @@
   return nullptr;
 }
 
+ModuleSP DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file,
+                                                     addr_t link_map_addr,
+                                                     addr_t base_addr,
+                                                     bool base_addr_is_offset) {
+  if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(
+          file, link_map_addr, base_addr, base_addr_is_offset))
+    return module_sp;
+
+  // This works around an dynamic linker "bug" on android <= 23, where the
+  // dynamic linker would report the application name
+  // (e.g. com.example.myapplication) instead of the main process binary
+  // (/system/bin/app_process(32)). The logic is not sound in general (it
+  // assumes base_addr is the real address, even though it actually is a load
+  // bias), but it happens to work on adroid because app_process has a file
+  // address of zero.
+  // This should be removed after we drop support for android-23.
+  if (m_process->GetTarget().GetArchitecture().GetTriple().isAndroid()) {
+    MemoryRegionInfo memory_info;
+    Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
+    if (error.Success() && memory_info.GetMapped() &&
+        memory_info.GetRange().GetRangeBase() == base_addr &&
+        !(memory_info.GetName().IsEmpty())) {
+      if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(
+              FileSpec(memory_info.GetName().GetStringRef()), link_map_addr,
+              base_addr, base_addr_is_offset))
+        return module_sp;
+    }
+  }
+
+  return nullptr;
+}
+
 void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {
   DYLDRendezvous::iterator I;
   DYLDRendezvous::iterator E;
Index: lldb/source/Core/DynamicLoader.cpp
===================================================================
--- lldb/source/Core/DynamicLoader.cpp
+++ lldb/source/Core/DynamicLoader.cpp
@@ -145,72 +145,31 @@
   return sections;
 }
 
-ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
-                                            addr_t link_map_addr,
-                                            addr_t base_addr,
-                                            bool base_addr_is_offset) {
+ModuleSP DynamicLoader::FindModuleViaTarget(const FileSpec &file) {
   Target &target = m_process->GetTarget();
-  ModuleList &modules = target.GetImages();
   ModuleSpec module_spec(file, target.GetArchitecture());
-  ModuleSP module_sp;
 
-  if ((module_sp = modules.FindFirstModule(module_spec))) {
-    UpdateLoadedSections(module_sp, link_map_addr, base_addr,
-                         base_addr_is_offset);
+  if (ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec))
     return module_sp;
-  }
 
-  if ((module_sp = target.GetOrCreateModule(module_spec, 
-                                            true /* notify */))) {
-    UpdateLoadedSections(module_sp, link_map_addr, base_addr,
-                         base_addr_is_offset);
+  if (ModuleSP module_sp = target.GetOrCreateModule(module_spec,
+                                                    /*notify=*/true))
     return module_sp;
-  }
-
-  bool check_alternative_file_name = true;
-  if (base_addr_is_offset) {
-    // Try to fetch the load address of the file from the process as we need
-    // absolute load address to read the file out of the memory instead of a
-    // load bias.
-    bool is_loaded = false;
-    lldb::addr_t load_addr;
-    Status error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
-    if (error.Success() && is_loaded) {
-      check_alternative_file_name = false;
-      base_addr = load_addr;
-    }
-  }
-
-  // We failed to find the module based on its name. Lets try to check if we
-  // can find a different name based on the memory region info.
-  if (check_alternative_file_name) {
-    MemoryRegionInfo memory_info;
-    Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
-    if (error.Success() && memory_info.GetMapped() &&
-        memory_info.GetRange().GetRangeBase() == base_addr && 
-        !(memory_info.GetName().IsEmpty())) {
-      ModuleSpec new_module_spec(FileSpec(memory_info.GetName().GetStringRef()),
-                                 target.GetArchitecture());
-
-      if ((module_sp = modules.FindFirstModule(new_module_spec))) {
-        UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
-        return module_sp;
-      }
 
-      if ((module_sp = target.GetOrCreateModule(new_module_spec, 
-                                                true /* notify */))) {
-        UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
-        return module_sp;
-      }
-    }
-  }
+  return nullptr;
+}
 
-  if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr))) {
-    UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
-    target.GetImages().AppendIfNeeded(module_sp);
+ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
+                                            addr_t link_map_addr,
+                                            addr_t base_addr,
+                                            bool base_addr_is_offset) {
+  if (ModuleSP module_sp = FindModuleViaTarget(file)) {
+    UpdateLoadedSections(module_sp, link_map_addr, base_addr,
+                         base_addr_is_offset);
+    return module_sp;
   }
 
-  return module_sp;
+  return nullptr;
 }
 
 int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr,
Index: lldb/packages/Python/lldbsuite/test/gdbclientutils.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/gdbclientutils.py
+++ lldb/packages/Python/lldbsuite/test/gdbclientutils.py
@@ -66,8 +66,9 @@
     """
     out = ""
     hex_len = len(hex_bytes)
+    i = 0
     while i < hex_len - 1:
-        out += chr(int(hex_bytes[i:i + 2]), 16)
+        out += chr(int(hex_bytes[i:i + 2], 16))
         i += 2
     return out
 
@@ -178,6 +179,8 @@
             return self.qGetWorkingDir()
         if packet == "qOffsets":
             return self.qOffsets();
+        if packet == "qProcessInfo":
+            return self.qProcessInfo()
         if packet == "qsProcessInfo":
             return self.qsProcessInfo()
         if packet.startswith("qfProcessInfo"):
@@ -214,6 +217,9 @@
     def qOffsets(self):
         return ""
 
+    def qProcessInfo(self):
+        return ""
+
     def qHostInfo(self):
         return "ptrsize:8;endian:little;"
 
Index: lldb/include/lldb/Target/DynamicLoader.h
===================================================================
--- lldb/include/lldb/Target/DynamicLoader.h
+++ lldb/include/lldb/Target/DynamicLoader.h
@@ -263,6 +263,8 @@
 protected:
   // Utility methods for derived classes
 
+  lldb::ModuleSP FindModuleViaTarget(const FileSpec &file);
+
   /// Checks to see if the target module has changed, updates the target
   /// accordingly and returns the target executable module.
   lldb::ModuleSP GetTargetExecutable();
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to