lemo updated this revision to Diff 142960.

https://reviews.llvm.org/D45700

Files:
  
packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
  
packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
  source/Commands/CommandObjectTarget.cpp
  source/Core/Module.cpp
  source/Core/Section.cpp
  source/Plugins/Process/minidump/ProcessMinidump.cpp
  source/Plugins/Process/minidump/ProcessMinidump.h

Index: source/Plugins/Process/minidump/ProcessMinidump.h
===================================================================
--- source/Plugins/Process/minidump/ProcessMinidump.h
+++ source/Plugins/Process/minidump/ProcessMinidump.h
@@ -61,6 +61,8 @@
 
   uint32_t GetPluginVersion() override;
 
+  SystemRuntime *GetSystemRuntime() override { return nullptr; }
+
   Status DoDestroy() override;
 
   void RefreshStateAfterStop() override;
Index: source/Plugins/Process/minidump/ProcessMinidump.cpp
===================================================================
--- source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -19,6 +19,7 @@
 #include "lldb/Core/State.h"
 #include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/SectionLoadList.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/UnixSignals.h"
 #include "lldb/Utility/DataBufferLLVM.h"
@@ -31,9 +32,53 @@
 // C includes
 // C++ includes
 
+using namespace lldb;
 using namespace lldb_private;
 using namespace minidump;
 
+//------------------------------------------------------------------
+/// A placeholder module used for minidumps, where the original
+/// object files may not be available (so we can't parse the object
+/// files to extract the set of sections/segments)
+///
+/// This placeholder module has a single synthetic section (.module_image)
+/// which represents the module memory range covering the whole module.
+//------------------------------------------------------------------
+class PlaceholderModule : public Module {
+public:
+  PlaceholderModule(const FileSpec &file_spec, const ArchSpec &arch) :
+    Module(file_spec, arch) {}
+
+  // Creates a synthetic module section covering the whole module image
+  // (and sets the section load address as well)
+  void CreateImageSection(const MinidumpModule *module, Target& target) {
+    const ConstString section_name(".module_image");
+    lldb::SectionSP section_sp(new Section(
+        shared_from_this(),     // Module to which this section belongs.
+        nullptr,                // ObjectFile
+        0,                      // Section ID.
+        section_name,           // Section name.
+        eSectionTypeContainer,  // Section type.
+        module->base_of_image,  // VM address.
+        module->size_of_image,  // VM size in bytes of this section.
+        0,                      // Offset of this section in the file.
+        module->size_of_image,  // Size of the section as found in the file.
+        12,                     // Alignment of the section (log2)
+        0,                      // Flags for this section.
+        1));                    // Number of host bytes per target byte
+    section_sp->SetPermissions(ePermissionsExecutable | ePermissionsReadable);
+    GetSectionList()->AddSection(section_sp);
+    target.GetSectionLoadList().SetSectionLoadAddress(
+        section_sp, module->base_of_image);
+  }
+
+  ObjectFile *GetObjectFile() override { return nullptr; }
+
+  SectionList *GetSectionList() override {
+    return Module::GetUnifiedSectionList();
+  }
+};
+
 ConstString ProcessMinidump::GetPluginNameStatic() {
   static ConstString g_name("minidump");
   return g_name;
@@ -281,7 +326,18 @@
     Status error;
     lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error);
     if (!module_sp || error.Fail()) {
-      continue;
+      // We failed to locate a matching local object file. Fortunately,
+      // the minidump format encodes enough information about each module's
+      // memory range to allow us to create placeholder modules.
+      //
+      // This enables most LLDB functionality involving address-to-module
+      // translations (ex. identifing the module for a stack frame PC) and
+      // modules/sections commands (ex. target modules list, ...)
+      auto placeholder_module =
+          std::make_shared<PlaceholderModule>(file_spec, GetArchitecture());
+      placeholder_module->CreateImageSection(module, GetTarget());
+      module_sp = placeholder_module;
+      GetTarget().GetImages().Append(module_sp);
     }
 
     if (log) {
Index: source/Core/Section.cpp
===================================================================
--- source/Core/Section.cpp
+++ source/Core/Section.cpp
@@ -326,10 +326,11 @@
     // The top most section prints the module basename
     const char *name = NULL;
     ModuleSP module_sp(GetModule());
-    const FileSpec &file_spec = m_obj_file->GetFileSpec();
 
-    if (m_obj_file)
+    if (m_obj_file) {
+      const FileSpec &file_spec = m_obj_file->GetFileSpec();
       name = file_spec.GetFilename().AsCString();
+    }
     if ((!name || !name[0]) && module_sp)
       name = module_sp->GetFileSpec().GetFilename().AsCString();
     if (name && name[0])
Index: source/Core/Module.cpp
===================================================================
--- source/Core/Module.cpp
+++ source/Core/Module.cpp
@@ -1278,7 +1278,7 @@
 }
 
 SectionList *Module::GetSectionList() {
-  // Populate m_unified_sections_ap with sections from objfile.
+  // Populate m_sections_ap with sections from objfile.
   if (!m_sections_ap) {
     ObjectFile *obj_file = GetObjectFile();
     if (obj_file != nullptr)
@@ -1297,7 +1297,6 @@
 }
 
 SectionList *Module::GetUnifiedSectionList() {
-  // Populate m_unified_sections_ap with sections from objfile.
   if (!m_sections_ap)
     m_sections_ap = llvm::make_unique<SectionList>();
   return m_sections_ap.get();
Index: source/Commands/CommandObjectTarget.cpp
===================================================================
--- source/Commands/CommandObjectTarget.cpp
+++ source/Commands/CommandObjectTarget.cpp
@@ -1388,7 +1388,8 @@
           strm.EOL();
         }
         ObjectFile *objfile = module->GetObjectFile();
-        objfile->Dump(&strm);
+        if (objfile)
+          objfile->Dump(&strm);
       }
     }
     strm.IndentLess();
Index: packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
===================================================================
--- packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
+++ packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
@@ -70,6 +70,17 @@
         self.assertEqual(self.process.GetProcessID(), self._linux_x86_64_pid)
         self.check_state()
 
+    def test_modules_in_mini_dump(self):
+        """Test that lldb can read the list of modules from the minidump."""
+        # target create -c linux-x86_64.dmp
+        self.dbg.CreateTarget(None)
+        self.target = self.dbg.GetSelectedTarget()
+        self.process = self.target.LoadCore("linux-x86_64.dmp")
+        self.assertTrue(self.process, PROCESS_IS_VALID)
+        self.assertEqual(self.target.GetNumModules(), 9)
+        for module in self.target.modules:
+            self.assertTrue(module.IsValid())
+
     def test_thread_info_in_minidump(self):
         """Test that lldb can read the thread information from the Minidump."""
         # target create -c linux-x86_64.dmp
@@ -100,6 +111,7 @@
         self.assertEqual(thread.GetNumFrames(), 2)
         frame = thread.GetFrameAtIndex(0)
         self.assertTrue(frame.IsValid())
+        self.assertTrue(frame.GetModule().IsValid())
         pc = frame.GetPC()
         eip = frame.FindRegister("pc")
         self.assertTrue(eip.IsValid())
Index: packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
===================================================================
--- packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
+++ packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
@@ -41,6 +41,26 @@
         stop_description = thread.GetStopDescription(256)
         self.assertTrue("0xc0000005" in stop_description)
 
+    def test_modules_in_mini_dump(self):
+        """Test that lldb can read the list of modules from the minidump."""
+        # target create -c fizzbuzz_no_heap.dmp
+        self.dbg.CreateTarget("")
+        self.target = self.dbg.GetSelectedTarget()
+        self.process = self.target.LoadCore("fizzbuzz_no_heap.dmp")
+        self.assertTrue(self.process, PROCESS_IS_VALID)
+        expected_modules = [
+            r"C:\Windows\System32\MSVCP120D.dll",
+            r"C:\Windows\SysWOW64\kernel32.dll",
+            r"C:\Users\amccarth\Documents\Visual Studio 2013\Projects\fizzbuzz\Debug\fizzbuzz.exe",
+            r"C:\Windows\System32\MSVCR120D.dll",
+            r"C:\Windows\SysWOW64\KERNELBASE.dll",
+            r"C:\Windows\SysWOW64\ntdll.dll",
+        ]
+        self.assertEqual(self.target.GetNumModules(), len(expected_modules))
+        for module, expected in zip(self.target.modules, expected_modules):
+            self.assertTrue(module.IsValid())
+            self.assertEqual(module.file.fullpath, expected)
+
     @expectedFailureAll(bugnumber="llvm.org/pr35193", hostoslist=["windows"])
     def test_stack_info_in_mini_dump(self):
         """Test that we can see a trivial stack in a VS-generate mini dump."""
@@ -58,6 +78,7 @@
             frame = thread.GetFrameAtIndex(i)
             self.assertTrue(frame.IsValid())
             self.assertEqual(frame.GetPC(), pc_list[i])
+            self.assertTrue(frame.GetModule().IsValid())
 
     @skipUnlessWindows # Minidump saving works only on windows
     def test_deeper_stack_in_mini_dump(self):
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to