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
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())
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."""
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):
#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"
// 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;
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) {