Index: include/lldb/Core/Mangled.h =================================================================== --- include/lldb/Core/Mangled.h +++ include/lldb/Core/Mangled.h @@ -49,7 +49,8 @@ enum ManglingScheme { eManglingSchemeNone = 0, eManglingSchemeMSVC, - eManglingSchemeItanium + eManglingSchemeItanium, + eManglingSchemeD }; //---------------------------------------------------------------------- Index: include/lldb/Core/PluginManager.h =================================================================== --- include/lldb/Core/PluginManager.h +++ include/lldb/Core/PluginManager.h @@ -148,8 +148,10 @@ //------------------------------------------------------------------ // Language //------------------------------------------------------------------ - static bool RegisterPlugin(const ConstString &name, const char *description, - LanguageCreateInstance create_callback); + static bool + RegisterPlugin(const ConstString &name, const char *description, + LanguageCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr); static bool UnregisterPlugin(LanguageCreateInstance create_callback); @@ -540,6 +542,14 @@ static bool CreateSettingForStructuredDataPlugin( Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, const ConstString &description, bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForLanguagePlugin(Debugger &debugger, + const ConstString &setting_name); + + static bool CreateSettingForLanguagePlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property); }; } // namespace lldb_private Index: source/API/SystemInitializerFull.cpp =================================================================== --- source/API/SystemInitializerFull.cpp +++ source/API/SystemInitializerFull.cpp @@ -56,6 +56,7 @@ #include "Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.h" #include "Plugins/JITLoader/GDB/JITLoaderGDB.h" #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/D/DLanguage.h" #include "Plugins/Language/Go/GoLanguage.h" #include "Plugins/Language/Java/JavaLanguage.h" #include "Plugins/Language/OCaml/OCamlLanguage.h" @@ -290,6 +291,7 @@ ClangASTContext::Initialize(); GoASTContext::Initialize(); JavaASTContext::Initialize(); + DLanguage::Initialize(); OCamlASTContext::Initialize(); ABIMacOSX_i386::Initialize(); @@ -419,6 +421,7 @@ ClangASTContext::Terminate(); GoASTContext::Terminate(); JavaASTContext::Terminate(); + DLanguage::Terminate(); OCamlASTContext::Terminate(); ABIMacOSX_i386::Terminate(); Index: source/Core/CMakeLists.txt =================================================================== --- source/Core/CMakeLists.txt +++ source/Core/CMakeLists.txt @@ -69,6 +69,7 @@ lldbPluginProcessUtility lldbPluginCPlusPlusLanguage lldbPluginObjCLanguage + lldbPluginDLanguage lldbPluginObjectFileJIT ${LLDB_CURSES_LIBS} Index: source/Core/Mangled.cpp =================================================================== --- source/Core/Mangled.cpp +++ source/Core/Mangled.cpp @@ -36,6 +36,7 @@ #include "lldb/lldb-enumerations.h" // for LanguageType #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/D/DLanguage.h" #include "Plugins/Language/ObjC/ObjCLanguage.h" #include "llvm/ADT/StringRef.h" // for StringRef @@ -74,6 +75,8 @@ return Mangled::eManglingSchemeMSVC; if (s[0] == '_' && s[1] == 'Z') return Mangled::eManglingSchemeItanium; + if (DLanguage::IsDMangledName(s)) + return Mangled::eManglingSchemeD; } return Mangled::eManglingSchemeNone; } @@ -322,6 +325,10 @@ } break; } + case eManglingSchemeD: { + demangled_name = DLanguage::demangle(m_mangled); + break; + } case eManglingSchemeNone: break; } @@ -431,6 +438,8 @@ return lldb::eLanguageTypeC_plus_plus; else if (ObjCLanguage::IsPossibleObjCMethodName(mangled_name)) return lldb::eLanguageTypeObjC; + else if (DLanguage::IsDMangledName(mangled_name)) + return lldb::eLanguageTypeD; } } else { // ObjC names aren't really mangled, so they won't necessarily be in the Index: source/Core/PluginManager.cpp =================================================================== --- source/Core/PluginManager.cpp +++ source/Core/PluginManager.cpp @@ -741,11 +741,14 @@ #pragma mark Language struct LanguageInstance { - LanguageInstance() : name(), description(), create_callback(nullptr) {} + LanguageInstance() + : name(), description(), create_callback(nullptr), + debugger_init_callback(nullptr) {} ConstString name; std::string description; LanguageCreateInstance create_callback; + DebuggerInitializeCallback debugger_init_callback; }; typedef std::vector LanguageInstances; @@ -760,9 +763,10 @@ return g_instances; } -bool PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - LanguageCreateInstance create_callback) { +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + LanguageCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback) { if (create_callback) { LanguageInstance instance; assert((bool)name); @@ -770,6 +774,7 @@ if (description && description[0]) instance.description = description; instance.create_callback = create_callback; + instance.debugger_init_callback = debugger_init_callback; std::lock_guard guard(GetLanguageMutex()); GetLanguageInstances().push_back(instance); } @@ -2358,6 +2363,15 @@ plugin.debugger_init_callback(debugger); } } + + // Initialize the LanguagePlugin plugins + { + std::lock_guard guard(GetLanguageMutex()); + for (auto &plugin : GetLanguageInstances()) { + if (plugin.debugger_init_callback) + plugin.debugger_init_callback(debugger); + } + } } // This is the preferred new way to register plugin specific settings. e.g. @@ -2480,6 +2494,7 @@ const char *kSymbolFilePluginName("symbol-file"); const char *kJITLoaderPluginName("jit-loader"); const char *kStructuredDataPluginName("structured-data"); +const char *kLanguagePluginName("language"); } // anonymous namespace @@ -2609,3 +2624,18 @@ ConstString("Settings for structured data plug-ins"), properties_sp, description, is_global_property); } + +lldb::OptionValuePropertiesSP +PluginManager::GetSettingForLanguagePlugin(Debugger &debugger, + const ConstString &setting_name) { + return GetSettingForPlugin(debugger, setting_name, + ConstString(kLanguagePluginName)); +} + +bool PluginManager::CreateSettingForLanguagePlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property) { + return CreateSettingForPlugin(debugger, ConstString(kLanguagePluginName), + ConstString("Settings for language plug-ins"), + properties_sp, description, is_global_property); +} Index: source/Plugins/Language/CMakeLists.txt =================================================================== --- source/Plugins/Language/CMakeLists.txt +++ source/Plugins/Language/CMakeLists.txt @@ -4,3 +4,4 @@ add_subdirectory(ObjC) add_subdirectory(ObjCPlusPlus) add_subdirectory(OCaml) +add_subdirectory(D) Index: source/Plugins/Language/D/CMakeLists.txt =================================================================== --- /dev/null +++ source/Plugins/Language/D/CMakeLists.txt @@ -0,0 +1,7 @@ +add_lldb_library(lldbPluginDLanguage PLUGIN + DLanguage.cpp + + LINK_LIBS + lldbCore + lldbTarget +) Index: source/Plugins/Language/D/DLanguage.h =================================================================== --- /dev/null +++ source/Plugins/Language/D/DLanguage.h @@ -0,0 +1,74 @@ +//===-- DLanguage.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_DLanguage_h_ +#define liblldb_DLanguage_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/Language.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class DLanguageProperties : public Properties { +public: + DLanguageProperties(); + + ~DLanguageProperties() override; + + llvm::StringRef GetPluginfileDlang(); +}; + +class DLanguage : public Language { +public: + typedef std::shared_ptr DLanguagePropertiesSP; + + DLanguage() = default; + + ~DLanguage() override = default; + + lldb::LanguageType GetLanguageType() const override { + return lldb::eLanguageTypeD; + } + + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + static void Initialize(); + + static void Terminate(); + + static lldb_private::Language *CreateInstance(lldb::LanguageType language); + + static void DebuggerInitialize(lldb_private::Debugger &debugger); + + static DLanguage *Instance(); + + static const DLanguagePropertiesSP &GetGlobalProperties(); + + static lldb_private::ConstString GetPluginNameStatic(); + + static bool IsDMangledName(const char *name); + // Consider using non-static methods + static char *demangle(const ConstString &mangled); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override; +}; + +} // namespace lldb_private + +#endif // liblldb_DLanguage_h_ Index: source/Plugins/Language/D/DLanguage.cpp =================================================================== --- /dev/null +++ source/Plugins/Language/D/DLanguage.cpp @@ -0,0 +1,151 @@ +//===-- DLanguage.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DLanguage.h" + +#include "lldb/Core/PluginManager.h" +#include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Interpreter/OptionValueString.h" +#include "lldb/Interpreter/Property.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Log.h" +#include "llvm/Support/DynamicLibrary.h" + +#include + +using namespace lldb; +using namespace lldb_private; + +using llvm::sys::DynamicLibrary; + +namespace { + +template +Fun *getTypedSymbol(DynamicLibrary &lib, const char *symbol) { + return reinterpret_cast(lib.getAddressOfSymbol(symbol)); +} + +// D Plugin will define these symbols. They're declared to use with decltype. +extern "C" { +char *lldbd_demangle(size_t length, const char *mangled); +void d_initialize(); +} + +static PropertyDefinition g_properties[] = { + {"pluginfile", OptionValue::eTypeString, true, + OptionValueString::eOptionEncodeCharacterEscapeSequences, "", nullptr, + "The plugin shared library file to use for D language."}, +}; + +enum { + ePropertyPluginfileDlang, +}; + +} // anonymous namespace + +// DLanguageProperties +DLanguageProperties::~DLanguageProperties() = default; + +DLanguageProperties::DLanguageProperties() : Properties() { + m_collection_sp.reset( + new OptionValueProperties(DLanguage::GetPluginNameStatic())); + m_collection_sp->Initialize(g_properties); +} + +// DLanguage +llvm::StringRef DLanguageProperties::GetPluginfileDlang() { + const uint32_t idx = ePropertyPluginfileDlang; + assert(m_collection_sp); + return m_collection_sp->GetPropertyAtIndexAsString( + nullptr, idx, g_properties[idx].default_cstr_value); +} + +void DLanguage::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), "D Language", + CreateInstance, DebuggerInitialize); +} + +void DLanguage::DebuggerInitialize(Debugger &debugger) { + if (!PluginManager::GetSettingForLanguagePlugin(debugger, + GetPluginNameStatic())) { + const bool is_global_setting = true; + PluginManager::CreateSettingForLanguagePlugin( + debugger, GetGlobalProperties()->GetValueProperties(), + ConstString("Properties for the dlang plug-in."), is_global_setting); + } +} + +void DLanguage::Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } + +lldb_private::ConstString DLanguage::GetPluginNameStatic() { + static ConstString g_name("D"); + return g_name; +} + +lldb_private::ConstString DLanguage::GetPluginName() { + return GetPluginNameStatic(); +} + +uint32_t DLanguage::GetPluginVersion() { return 1; } + +Language *DLanguage::CreateInstance(lldb::LanguageType language) { + switch (language) { + case lldb::eLanguageTypeD: + return DLanguage::Instance(); + default: + return nullptr; + } +} + +const DLanguage::DLanguagePropertiesSP &DLanguage::GetGlobalProperties() { + static DLanguage::DLanguagePropertiesSP *g_settings_sp_ptr = + new DLanguage::DLanguagePropertiesSP(new DLanguageProperties()); + return *g_settings_sp_ptr; +} + +DLanguage *DLanguage::Instance() { + static auto ret = new DLanguage(); + return ret; +} + +char *DLanguage::demangle(const ConstString &mangled) { + auto len = mangled.GetLength(); + auto s = mangled.GetCString(); + static auto fun = []() -> decltype(lldbd_demangle) * { + std::string file = + DLanguage::GetGlobalProperties()->GetPluginfileDlang().str(); + std::string errMsg; + auto lib2 = DynamicLibrary::getPermanentLibrary(file.c_str(), &errMsg); + + if (!file.empty() && !lib2.isValid()) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log) { + log->Printf("errMsg:%s\b", errMsg.c_str()); + } + return nullptr; + } + + auto fun0 = getTypedSymbol(lib2, "d_initialize"); + assert(fun0); + (*fun0)(); + + auto fun = getTypedSymbol(lib2, "lldbd_demangle"); + assert(fun); + return fun; + }(); + if (!fun) + return nullptr; + return (*fun)(len, s); +} + +bool DLanguage::IsDMangledName(const char *name) { + if (name == nullptr) + return false; + return (name[0] != '\0' && name[0] == '_' && name[1] == 'D'); +}