diff --git a/lldb/bindings/interface/SBModule.i b/lldb/bindings/interface/SBModule.i --- a/lldb/bindings/interface/SBModule.i +++ b/lldb/bindings/interface/SBModule.i @@ -137,6 +137,13 @@ void Clear(); + %feature("docstring", "Check if the module is file backed. + @return + True, if the module is backed by an object file on disk. + False, if the module is backed by an object file in memory.") IsFileBacked; + bool + IsFileBacked() const; + %feature("docstring", " Get const accessor for the module file specification. diff --git a/lldb/include/lldb/API/SBModule.h b/lldb/include/lldb/API/SBModule.h --- a/lldb/include/lldb/API/SBModule.h +++ b/lldb/include/lldb/API/SBModule.h @@ -37,6 +37,8 @@ void Clear(); + bool IsFileBacked() const; + /// Get const accessor for the module file specification. /// /// This function returns the file for the module on the host system diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp --- a/lldb/source/API/SBModule.cpp +++ b/lldb/source/API/SBModule.cpp @@ -88,6 +88,20 @@ m_opaque_sp.reset(); } +bool SBModule::IsFileBacked() const { + LLDB_INSTRUMENT_VA(this); + + ModuleSP module_sp(GetSP()); + if (!module_sp) + return false; + + ObjectFile *obj_file = module_sp->GetObjectFile(); + if (!obj_file) + return false; + + return !obj_file->IsInMemory(); +} + SBFileSpec SBModule::GetFileSpec() const { LLDB_INSTRUMENT_VA(this); diff --git a/lldb/test/API/python_api/sbmodule/Makefile b/lldb/test/API/python_api/sbmodule/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/python_api/sbmodule/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/python_api/sbmodule/TestSBModule.py b/lldb/test/API/python_api/sbmodule/TestSBModule.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/python_api/sbmodule/TestSBModule.py @@ -0,0 +1,58 @@ +"""Test the SBDModule APIs.""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +import os, signal, subprocess + +class SBModuleAPICase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + self.background_pid = None + + def tearDown(self): + TestBase.tearDown(self) + if self.background_pid: + os.kill(self.background_pid, signal.SIGKILL) + + + def test_module_is_file_backed(self): + """Test the SBModule::IsFileBacked() method""" + self.build() + target, _, _, _ = lldbutil.run_to_source_breakpoint(self, "// break here", + lldb.SBFileSpec("main.c")) + + self.assertGreater(target.GetNumModules(), 0) + main_module = target.GetModuleAtIndex(0) + self.assertEqual(main_module.GetFileSpec().GetFilename(), "a.out") + self.assertTrue(main_module.IsFileBacked(), + "The module should be backed by a file on disk") + + self.dbg.DeleteTarget(target) + self.assertEqual(self.dbg.GetNumTargets(), 0) + + exe = self.getBuildArtifact("a.out") + background_process = subprocess.Popen([exe]) + self.assertTrue(background_process, "process is not valid") + self.background_pid = background_process.pid + os.unlink(exe) + + target = self.dbg.CreateTarget('') + self.assertEqual(self.dbg.GetNumTargets(), 1) + error = lldb.SBError() + process = target.AttachToProcessWithID(self.dbg.GetListener(), + self.background_pid, error) + self.assertTrue(error.Success() and process, PROCESS_IS_VALID) + main_module = target.GetModuleAtIndex(0) + self.assertEqual(main_module.GetFileSpec().GetFilename(), "a.out") + self.assertFalse(main_module.IsFileBacked(), + "The module should not be backed by a file on disk.") + + error = process.Destroy() + self.assertTrue(error.Success(), "couldn't destroy process %s" % background_process.pid) + diff --git a/lldb/test/API/python_api/sbmodule/main.c b/lldb/test/API/python_api/sbmodule/main.c new file mode 100644 --- /dev/null +++ b/lldb/test/API/python_api/sbmodule/main.c @@ -0,0 +1,5 @@ +int main() { + while (1) // break here + ; + return 42; +}