lemo updated this revision to Diff 142799.
lemo edited the summary of this revision.
lemo added a comment.
Thanks for the feedback.
PS. The sample output in the description if from LLDB running on Linux, reading
minidumps captured on Windows.
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,63 @@
// 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:
+ static std::shared_ptr<PlaceholderModule> Create(const FileSpec &file_spec,
+ const ArchSpec &arch,
+ const MinidumpModule *module,
+ Target &target) {
+ std::shared_ptr<PlaceholderModule> placeholder_module(
+ new PlaceholderModule(file_spec, arch));
+ placeholder_module->CreateImageSection(module, target);
+ return placeholder_module;
+ }
+
+ ObjectFile *GetObjectFile() override { return nullptr; }
+
+ SectionList *GetSectionList() override {
+ return Module::GetUnifiedSectionList();
+ }
+
+private:
+ PlaceholderModule(const FileSpec &file_spec, const ArchSpec &arch) :
+ Module(file_spec, arch) {}
+
+ // Creates a synthetic module section covering the whole module image
+ 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);
+ }
+};
+
ConstString ProcessMinidump::GetPluginNameStatic() {
static ConstString g_name("minidump");
return g_name;
@@ -281,7 +336,16 @@
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, ...)
+ module_sp = PlaceholderModule::Create(file_spec, GetArchitecture(),
+ module, GetTarget());
+ 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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits