Index: lldb/include/lldb/API/SBError.h =================================================================== --- lldb/include/lldb/API/SBError.h +++ lldb/include/lldb/API/SBError.h @@ -61,6 +61,7 @@ friend class SBData; friend class SBDebugger; friend class SBHostOS; + friend class SBModule; friend class SBPlatform; friend class SBProcess; friend class SBReproducer; Index: lldb/include/lldb/API/SBModule.h =================================================================== --- lldb/include/lldb/API/SBModule.h +++ lldb/include/lldb/API/SBModule.h @@ -288,6 +288,22 @@ lldb::SBAddress GetObjectFileHeaderAddress() const; lldb::SBAddress GetObjectFileEntryPointAddress() const; + /// Checks if debug info in the module is compatible with the language + /// support that LLDB implements for the given language. + /// + /// A module may be incompatible with LLDB's language version if the language + /// version that is used in the module isn't supported by LLDB even though + /// the language itself is supported. This can happen if the language itself + /// evolved but LLDB's only supports a newer or older version of the language. + /// + /// \param[in] language + /// The language that should be checked for compability with this module. + /// + /// \return + /// An error object that describes the errors that were encounterd when + /// checking if LLDB's language support is compatible. + lldb::SBError IsDebugInfoCompatible(lldb::LanguageType language); + private: friend class SBAddress; friend class SBFrame; Index: lldb/include/lldb/Symbol/TypeSystem.h =================================================================== --- lldb/include/lldb/Symbol/TypeSystem.h +++ lldb/include/lldb/Symbol/TypeSystem.h @@ -207,6 +207,14 @@ // TypeSystems can support more than one language virtual bool SupportsLanguage(lldb::LanguageType language) = 0; + /// Check if the current module or target that was used to create this + /// type system is compatible with the TypeSystem plug-in. + /// + /// \return A Status object that is either describing any potential errors + /// that make the module/target incompatible or contains no errors + /// when the module/target is compatible. + virtual Status IsCompatible(); + // Type Completion virtual bool GetCompleteType(lldb::opaque_compiler_type_t type) = 0; Index: lldb/packages/Python/lldbsuite/test/python_api/module_compability/Makefile =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/python_api/module_compability/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules Index: lldb/packages/Python/lldbsuite/test/python_api/module_compability/TestModuleDebugInfoCompatible.py =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/python_api/module_compability/TestModuleDebugInfoCompatible.py @@ -0,0 +1,64 @@ +""" +Test SBModule's IsDebugInfoCompatible. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ModuleDebugInfoCheckTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def assert_invalid_module_err(self, error): + self.assertEquals("invalid module", error.GetCString()) + self.assertFalse(error.Success()) + + # Py3 asserts due to a bug in SWIG. A fix for this was upstreamed into + # SWIG 3.0.8. + @skipIf(py_version=['>=', (3, 0)], swig_version=['<', (3, 0, 8)]) + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_default_module(self): + exe_module = lldb.SBModule() + self.assert_invalid_module_err(exe_module.IsDebugInfoCompatible(lldb.eLanguageTypeUnknown)) + self.assert_invalid_module_err(error = exe_module.IsDebugInfoCompatible(lldb.eLanguageTypeC)) + + def assert_compatible(self, exe_module, lang): + error = exe_module.IsDebugInfoCompatible(lang) + self.assertTrue(error.Success()) + + # Py3 asserts due to a bug in SWIG. A fix for this was upstreamed into + # SWIG 3.0.8. + @skipIf(py_version=['>=', (3, 0)], swig_version=['<', (3, 0, 8)]) + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_c_languages(self): + self.build() + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + self.assertTrue(target.GetNumModules() > 0) + + exe_module = target.GetModuleAtIndex(0) + + # Check that we get an error if LLDB doesn't implement the language + error = exe_module.IsDebugInfoCompatible(lldb.eLanguageTypeModula2) + self.assertEquals("TypeSystem for language modula2 doesn't exist", error.GetCString()) + self.assertFalse(error.Success()) + + # Check that C languages are compatible with the module. + self.assert_compatible(exe_module, lldb.eLanguageTypeC) + self.assert_compatible(exe_module, lldb.eLanguageTypeC89) + self.assert_compatible(exe_module, lldb.eLanguageTypeC99) + self.assert_compatible(exe_module, lldb.eLanguageTypeC11) + self.assert_compatible(exe_module, lldb.eLanguageTypeC_plus_plus) + self.assert_compatible(exe_module, lldb.eLanguageTypeC_plus_plus_03) + self.assert_compatible(exe_module, lldb.eLanguageTypeC_plus_plus_11) + self.assert_compatible(exe_module, lldb.eLanguageTypeC_plus_plus_14) + + # 'Unknown' language gets mapped to a generic C language right now. + self.assert_compatible(exe_module, lldb.eLanguageTypeUnknown) Index: lldb/packages/Python/lldbsuite/test/python_api/module_compability/main.cpp =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/python_api/module_compability/main.cpp @@ -0,0 +1 @@ +int main() {} Index: lldb/scripts/interface/SBModule.i =================================================================== --- lldb/scripts/interface/SBModule.i +++ lldb/scripts/interface/SBModule.i @@ -342,6 +342,9 @@ lldb::SBAddress GetObjectFileEntryPointAddress() const; + lldb::SBError + IsDebugInfoCompatible(lldb::LanguageType language); + %pythoncode %{ def __len__(self): '''Return the number of symbols in a lldb.SBModule object.''' Index: lldb/source/API/SBModule.cpp =================================================================== --- lldb/source/API/SBModule.cpp +++ lldb/source/API/SBModule.cpp @@ -23,6 +23,7 @@ #include "lldb/Symbol/Symtab.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Target.h" #include "lldb/Utility/StreamString.h" @@ -687,6 +688,24 @@ return LLDB_RECORD_RESULT(sb_addr); } +lldb::SBError SBModule::IsDebugInfoCompatible(lldb::LanguageType language) { + SBError sb_error; + ModuleSP module_sp(GetSP()); + if (!module_sp) { + sb_error.SetErrorString("invalid module"); + return sb_error; + } + + auto type_system_or_err = module_sp->GetTypeSystemForLanguage(language); + if (!type_system_or_err) { + sb_error.ref() = type_system_or_err.takeError(); + return sb_error; + } + + sb_error.SetError(type_system_or_err->IsCompatible()); + return sb_error; +} + namespace lldb_private { namespace repro { Index: lldb/source/Symbol/TypeSystem.cpp =================================================================== --- lldb/source/Symbol/TypeSystem.cpp +++ lldb/source/Symbol/TypeSystem.cpp @@ -147,6 +147,12 @@ return false; } +Status TypeSystem::IsCompatible() { + // Assume a language is compatible. Override this virtual function + // in your TypeSystem plug-in if version checking is desired. + return Status(); +} + ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) { return ConstString(); }