Author: labath Date: Wed Feb 15 11:13:19 2017 New Revision: 295201 URL: http://llvm.org/viewvc/llvm-project?rev=295201&view=rev Log: Revert "Refactor log channel registration mechanism"
The change breaks on Windows and NetBSD bots. Revert while I investigate. Modified: lldb/trunk/include/lldb/Core/Log.h lldb/trunk/include/lldb/Core/PluginManager.h lldb/trunk/include/lldb/lldb-forward.h lldb/trunk/include/lldb/lldb-private-interfaces.h lldb/trunk/source/Commands/CommandObjectLog.cpp lldb/trunk/source/Core/Log.cpp lldb/trunk/source/Core/PluginManager.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/unittests/Core/LogTest.cpp Modified: lldb/trunk/include/lldb/Core/Log.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Log.h?rev=295201&r1=295200&r2=295201&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Log.h (original) +++ lldb/trunk/include/lldb/Core/Log.h Wed Feb 15 11:13:19 2017 @@ -44,53 +44,6 @@ namespace lldb_private { class Log final { public: - // Description of a log channel category. - struct Category { - llvm::StringLiteral name; - llvm::StringLiteral description; - uint32_t flag; - }; - - // This class describes a log channel. It also encapsulates the behavior - // necessary to enable a log channel in an atomic manner. - class Channel { - std::atomic<Log *> log_ptr; - - public: - const llvm::ArrayRef<Category> categories; - const uint32_t default_flags; - - constexpr Channel(llvm::ArrayRef<Log::Category> categories, - uint32_t default_flags) - : log_ptr(nullptr), categories(categories), - default_flags(default_flags) {} - - // This function is safe to call at any time - // FIXME: Not true yet, mask access is not atomic - Log *GetLogIfAll(uint32_t mask) { - Log *log = log_ptr.load(std::memory_order_acquire); - if (log && log->GetMask().AllSet(mask)) - return log; - return nullptr; - } - - // This function is safe to call at any time - // FIXME: Not true yet, mask access is not atomic - Log *GetLogIfAny(uint32_t mask) { - Log *log = log_ptr.load(std::memory_order_acquire); - if (log && log->GetMask().AnySet(mask)) - return log; - return nullptr; - } - - // Calls to Enable and disable need to be serialized externally. - void Enable(Log &log, const std::shared_ptr<llvm::raw_ostream> &stream_sp, - uint32_t flags); - - // Calls to Enable and disable need to be serialized externally. - void Disable(uint32_t flags); - }; - //------------------------------------------------------------------ // Callback definitions for abstracted plug-in log access. //------------------------------------------------------------------ @@ -110,9 +63,6 @@ public: //------------------------------------------------------------------ // Static accessors for logging channels //------------------------------------------------------------------ - static void Register(llvm::StringRef name, Channel &channel); - static void Unregister(llvm::StringRef name); - static void RegisterLogChannel(const ConstString &channel, const Log::Callbacks &log_callbacks); @@ -123,13 +73,13 @@ public: static bool EnableLogChannel(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp, - uint32_t log_options, llvm::StringRef channel, + uint32_t log_options, const char *channel, const char **categories, Stream &error_stream); - static bool DisableLogChannel(llvm::StringRef channel, - const char **categories, Stream &error_stream); - - static bool ListChannelCategories(llvm::StringRef channel, Stream &stream); + static void + EnableAllLogChannels(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp, + uint32_t log_options, const char **categories, + Stream *feedback_strm); static void DisableAllLogChannels(Stream *feedback_strm); @@ -140,6 +90,12 @@ public: static void Terminate(); //------------------------------------------------------------------ + // Auto completion + //------------------------------------------------------------------ + static void AutoCompleteChannelName(const char *channel_name, + StringList &matches); + + //------------------------------------------------------------------ // Member functions //------------------------------------------------------------------ Log(); @@ -206,6 +162,34 @@ private: const llvm::formatv_object_base &payload); }; +class LogChannel : public PluginInterface { +public: + LogChannel(); + + ~LogChannel() override; + + static lldb::LogChannelSP FindPlugin(const char *plugin_name); + + // categories is an array of chars that ends with a NULL element. + virtual void Disable(const char **categories, Stream *feedback_strm) = 0; + + virtual bool + Enable(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp, + uint32_t log_options, + Stream *feedback_strm, // Feedback stream for argument errors etc + const char **categories) = 0; // The categories to enable within this + // logging stream, if empty, enable + // default set + + virtual void ListCategories(Stream *strm) = 0; + +protected: + std::unique_ptr<Log> m_log_ap; + +private: + DISALLOW_COPY_AND_ASSIGN(LogChannel); +}; + } // namespace lldb_private #define LLDB_LOG(log, ...) \ Modified: lldb/trunk/include/lldb/Core/PluginManager.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/PluginManager.h?rev=295201&r1=295200&r2=295201&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/PluginManager.h (original) +++ lldb/trunk/include/lldb/Core/PluginManager.h Wed Feb 15 11:13:19 2017 @@ -210,6 +210,22 @@ public: GetObjectContainerGetModuleSpecificationsCallbackAtIndex(uint32_t idx); //------------------------------------------------------------------ + // LogChannel + //------------------------------------------------------------------ + static bool RegisterPlugin(const ConstString &name, const char *description, + LogChannelCreateInstance create_callback); + + static bool UnregisterPlugin(LogChannelCreateInstance create_callback); + + static LogChannelCreateInstance + GetLogChannelCreateCallbackAtIndex(uint32_t idx); + + static LogChannelCreateInstance + GetLogChannelCreateCallbackForPluginName(const ConstString &name); + + static const char *GetLogChannelCreateNameAtIndex(uint32_t idx); + + //------------------------------------------------------------------ // Platform //------------------------------------------------------------------ static bool Modified: lldb/trunk/include/lldb/lldb-forward.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=295201&r1=295200&r2=295201&view=diff ============================================================================== --- lldb/trunk/include/lldb/lldb-forward.h (original) +++ lldb/trunk/include/lldb/lldb-forward.h Wed Feb 15 11:13:19 2017 @@ -127,6 +127,7 @@ class MemoryRegionInfo; class LineTable; class Listener; class Log; +class LogChannel; class Mangled; class Materializer; class MemoryHistory; @@ -361,6 +362,7 @@ typedef std::unique_ptr<lldb_private::Sy typedef std::shared_ptr<lldb_private::LineTable> LineTableSP; typedef std::shared_ptr<lldb_private::Listener> ListenerSP; typedef std::weak_ptr<lldb_private::Listener> ListenerWP; +typedef std::shared_ptr<lldb_private::LogChannel> LogChannelSP; typedef std::shared_ptr<lldb_private::MemoryHistory> MemoryHistorySP; typedef std::shared_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoSP; typedef std::unique_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoUP; Modified: lldb/trunk/include/lldb/lldb-private-interfaces.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-interfaces.h?rev=295201&r1=295200&r2=295201&view=diff ============================================================================== --- lldb/trunk/include/lldb/lldb-private-interfaces.h (original) +++ lldb/trunk/include/lldb/lldb-private-interfaces.h Wed Feb 15 11:13:19 2017 @@ -45,6 +45,7 @@ typedef ObjectFile *(*ObjectFileCreateMe const lldb::ProcessSP &process_sp, lldb::addr_t offset); typedef bool (*ObjectFileSaveCore)(const lldb::ProcessSP &process_sp, const FileSpec &outfile, Error &error); +typedef LogChannel *(*LogChannelCreateInstance)(); typedef EmulateInstruction *(*EmulateInstructionCreateInstance)( const ArchSpec &arch, InstructionType inst_type); typedef OperatingSystem *(*OperatingSystemCreateInstance)(Process *process, Modified: lldb/trunk/source/Commands/CommandObjectLog.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectLog.cpp?rev=295201&r1=295200&r2=295201&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectLog.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectLog.cpp Wed Feb 15 11:13:19 2017 @@ -227,15 +227,25 @@ protected: return false; } + Log::Callbacks log_callbacks; + const std::string channel = args[0].ref; args.Shift(); // Shift off the channel - if (channel == "all") { - Log::DisableAllLogChannels(&result.GetErrorStream()); + if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) { + log_callbacks.disable(args.GetConstArgumentVector(), + &result.GetErrorStream()); result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else if (channel == "all") { + Log::DisableAllLogChannels(&result.GetErrorStream()); } else { - if (Log::DisableLogChannel(channel, args.GetConstArgumentVector(), - result.GetErrorStream())) + LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel.data())); + if (log_channel_sp) { + log_channel_sp->Disable(args.GetConstArgumentVector(), + &result.GetErrorStream()); result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else + result.AppendErrorWithFormat("Invalid log channel '%s'.\n", + channel.data()); } return result.Succeeded(); } @@ -274,12 +284,26 @@ protected: Log::ListAllLogChannels(&result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); } else { - bool success = true; - for (const auto &entry : args.entries()) - success = success && Log::ListChannelCategories( - entry.ref, result.GetOutputStream()); - if (success) - result.SetStatus(eReturnStatusSuccessFinishResult); + for (auto &entry : args.entries()) { + Log::Callbacks log_callbacks; + + if (Log::GetLogChannelCallbacks(ConstString(entry.ref), + log_callbacks)) { + log_callbacks.list_categories(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else if (entry.ref == "all") { + Log::ListAllLogChannels(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + LogChannelSP log_channel_sp(LogChannel::FindPlugin(entry.c_str())); + if (log_channel_sp) { + log_channel_sp->ListCategories(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else + result.AppendErrorWithFormat("Invalid log channel '%s'.\n", + entry.c_str()); + } + } } return result.Succeeded(); } Modified: lldb/trunk/source/Core/Log.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Log.cpp?rev=295201&r1=295200&r2=295201&view=diff ============================================================================== --- lldb/trunk/source/Core/Log.cpp (original) +++ lldb/trunk/source/Core/Log.cpp Wed Feb 15 11:13:19 2017 @@ -18,10 +18,8 @@ #include "lldb/Utility/StreamString.h" // Other libraries and framework includes -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Chrono.h" -#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" @@ -38,76 +36,6 @@ using namespace lldb; using namespace lldb_private; -namespace { - struct ChannelAndLog { - Log log; - Log::Channel &channel; - - ChannelAndLog(Log::Channel &channel) : channel(channel) {} - }; - typedef llvm::StringMap<ChannelAndLog> ChannelMap; -} - -static llvm::ManagedStatic<ChannelMap> g_channel_map; - -static void ListCategories(Stream &stream, const ChannelMap::value_type &entry) { - stream.Format("Logging categories for '{0}':\n", entry.first()); - stream.Format(" all - all available logging categories\n"); - stream.Format(" default - default set of logging categories\n"); - for (const auto &category : entry.second.channel.categories) - stream.Format(" {0} - {1}\n", category.name, category.description); -} - -static uint32_t GetFlags(Stream &stream, const ChannelMap::value_type &entry, - const char **categories) { - bool list_categories = false; - uint32_t flags = 0; - for (size_t i = 0; categories[i]; ++i) { - if (llvm::StringRef("all").equals_lower(categories[i])) { - flags |= UINT32_MAX; - continue; - } - if (llvm::StringRef("default").equals_lower(categories[i])) { - flags |= entry.second.channel.default_flags; - continue; - } - auto cat = llvm::find_if(entry.second.channel.categories, - [&](const Log::Category &c) { - return c.name.equals_lower(categories[i]); - }); - if (cat != entry.second.channel.categories.end()) { - flags |= cat->flag; - continue; - } - stream.Format("error: unrecognized log category '{0}'\n", categories[i]); - list_categories = true; - } - if (list_categories) - ListCategories(stream, entry); - return flags; -} - -void Log::Channel::Enable(Log &log, - const std::shared_ptr<llvm::raw_ostream> &stream_sp, - uint32_t flags) { - log.GetMask().Set(flags); - if (log.GetMask().Get()) { - log.SetStream(stream_sp); - log_ptr.store(&log, std::memory_order_release); - } -} - -void Log::Channel::Disable(uint32_t flags) { - Log *log = log_ptr.load(std::memory_order_acquire); - if (!log) - return; - log->GetMask().Clear(flags); - if (!log->GetMask().Get()) { - log->SetStream(nullptr); - log_ptr.store(nullptr, std::memory_order_release); - } -} - Log::Log() : m_stream_sp(), m_options(0), m_mask_bits(0) {} Log::Log(const std::shared_ptr<llvm::raw_ostream> &stream_sp) @@ -224,6 +152,9 @@ void Log::Warning(const char *format, .. typedef std::map<ConstString, Log::Callbacks> CallbackMap; typedef CallbackMap::iterator CallbackMapIter; +typedef std::map<ConstString, LogChannelSP> LogChannelMap; +typedef LogChannelMap::iterator LogChannelMapIter; + // Surround our callback map with a singleton function so we don't have any // global initializers. static CallbackMap &GetCallbackMap() { @@ -231,17 +162,9 @@ static CallbackMap &GetCallbackMap() { return g_callback_map; } -void Log::Register(llvm::StringRef name, Channel &channel) { - auto iter = g_channel_map->try_emplace(name, channel); - assert(iter.second == true); - (void)iter; -} - -void Log::Unregister(llvm::StringRef name) { - auto iter = g_channel_map->find(name); - assert(iter != g_channel_map->end()); - iter->second.channel.Disable(UINT32_MAX); - g_channel_map->erase(iter); +static LogChannelMap &GetChannelMap() { + static LogChannelMap g_channel_map; + return g_channel_map; } void Log::RegisterLogChannel(const ConstString &channel, @@ -267,7 +190,7 @@ bool Log::GetLogChannelCallbacks(const C bool Log::EnableLogChannel( const std::shared_ptr<llvm::raw_ostream> &log_stream_sp, - uint32_t log_options, llvm::StringRef channel, const char **categories, + uint32_t log_options, const char *channel, const char **categories, Stream &error_stream) { Log::Callbacks log_callbacks; if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) { @@ -275,52 +198,52 @@ bool Log::EnableLogChannel( return true; } - auto iter = g_channel_map->find(channel); - if (iter == g_channel_map->end()) { - error_stream.Format("Invalid log channel '{0}'.\n", channel); + LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel)); + if (log_channel_sp) { + if (log_channel_sp->Enable(log_stream_sp, log_options, &error_stream, + categories)) { + return true; + } else { + error_stream.Printf("Invalid log channel '%s'.\n", channel); + return false; + } + } else { + error_stream.Printf("Invalid log channel '%s'.\n", channel); return false; } - uint32_t flags = categories && categories[0] - ? GetFlags(error_stream, *iter, categories) - : iter->second.channel.default_flags; - iter->second.channel.Enable(iter->second.log, log_stream_sp, flags); - return true; } -bool Log::DisableLogChannel(llvm::StringRef channel, const char **categories, - Stream &error_stream) { - Log::Callbacks log_callbacks; - if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) { - log_callbacks.disable(categories, &error_stream); - return true; - } +void Log::EnableAllLogChannels( + const std::shared_ptr<llvm::raw_ostream> &log_stream_sp, + uint32_t log_options, const char **categories, Stream *feedback_strm) { + CallbackMap &callback_map = GetCallbackMap(); + CallbackMapIter pos, end = callback_map.end(); - auto iter = g_channel_map->find(channel); - if (iter == g_channel_map->end()) { - error_stream.Format("Invalid log channel '{0}'.\n", channel); - return false; + for (pos = callback_map.begin(); pos != end; ++pos) + pos->second.enable(log_stream_sp, log_options, categories, feedback_strm); + + LogChannelMap &channel_map = GetChannelMap(); + LogChannelMapIter channel_pos, channel_end = channel_map.end(); + for (channel_pos = channel_map.begin(); channel_pos != channel_end; + ++channel_pos) { + channel_pos->second->Enable(log_stream_sp, log_options, feedback_strm, + categories); } - uint32_t flags = categories && categories[0] - ? GetFlags(error_stream, *iter, categories) - : UINT32_MAX; - iter->second.channel.Disable(flags); - return true; } -bool Log::ListChannelCategories(llvm::StringRef channel, Stream &stream) { - Log::Callbacks log_callbacks; - if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) { - log_callbacks.list_categories(&stream); - return true; +void Log::AutoCompleteChannelName(const char *channel_name, + StringList &matches) { + LogChannelMap &map = GetChannelMap(); + LogChannelMapIter pos, end = map.end(); + for (pos = map.begin(); pos != end; ++pos) { + const char *pos_channel_name = pos->first.GetCString(); + if (channel_name && channel_name[0]) { + if (NameMatches(channel_name, eNameMatchStartsWith, pos_channel_name)) { + matches.AppendString(pos_channel_name); + } + } else + matches.AppendString(pos_channel_name); } - - auto ch = g_channel_map->find(channel); - if (ch == g_channel_map->end()) { - stream.Format("Invalid log channel '{0}'.\n", channel); - return false; - } - ListCategories(stream, *ch); - return true; } void Log::DisableAllLogChannels(Stream *feedback_strm) { @@ -331,8 +254,11 @@ void Log::DisableAllLogChannels(Stream * for (pos = callback_map.begin(); pos != end; ++pos) pos->second.disable(categories, feedback_strm); - for (auto &entry : *g_channel_map) - entry.second.channel.Disable(UINT32_MAX); + LogChannelMap &channel_map = GetChannelMap(); + LogChannelMapIter channel_pos, channel_end = channel_map.end(); + for (channel_pos = channel_map.begin(); channel_pos != channel_end; + ++channel_pos) + channel_pos->second->Disable(categories, feedback_strm); } void Log::Initialize() { @@ -344,8 +270,9 @@ void Log::Terminate() { DisableAllLogCha void Log::ListAllLogChannels(Stream *strm) { CallbackMap &callback_map = GetCallbackMap(); + LogChannelMap &channel_map = GetChannelMap(); - if (callback_map.empty() && g_channel_map->empty()) { + if (callback_map.empty() && channel_map.empty()) { strm->PutCString("No logging channels are currently registered.\n"); return; } @@ -354,9 +281,17 @@ void Log::ListAllLogChannels(Stream *str for (pos = callback_map.begin(); pos != end; ++pos) pos->second.list_categories(strm); - for (const auto &channel : *g_channel_map) - ListCategories(*strm, channel); + uint32_t idx = 0; + const char *name; + for (idx = 0; + (name = PluginManager::GetLogChannelCreateNameAtIndex(idx)) != nullptr; + ++idx) { + LogChannelSP log_channel_sp(LogChannel::FindPlugin(name)); + if (log_channel_sp) + log_channel_sp->ListCategories(strm); + } } + bool Log::GetVerbose() const { return m_options.Test(LLDB_LOG_OPTION_VERBOSE); } void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file, @@ -423,3 +358,33 @@ void Log::Format(llvm::StringRef file, l message << payload << "\n"; WriteMessage(message.str()); } + +LogChannelSP LogChannel::FindPlugin(const char *plugin_name) { + LogChannelSP log_channel_sp; + LogChannelMap &channel_map = GetChannelMap(); + ConstString log_channel_name(plugin_name); + LogChannelMapIter pos = channel_map.find(log_channel_name); + if (pos == channel_map.end()) { + ConstString const_plugin_name(plugin_name); + LogChannelCreateInstance create_callback = + PluginManager::GetLogChannelCreateCallbackForPluginName( + const_plugin_name); + if (create_callback) { + log_channel_sp.reset(create_callback()); + if (log_channel_sp) { + // Cache the one and only loaded instance of each log channel + // plug-in after it has been loaded once. + channel_map[log_channel_name] = log_channel_sp; + } + } + } else { + // We have already loaded an instance of this log channel class, + // so just return the cached instance. + log_channel_sp = pos->second; + } + return log_channel_sp; +} + +LogChannel::LogChannel() : m_log_ap() {} + +LogChannel::~LogChannel() = default; Modified: lldb/trunk/source/Core/PluginManager.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/PluginManager.cpp?rev=295201&r1=295200&r2=295201&view=diff ============================================================================== --- lldb/trunk/source/Core/PluginManager.cpp (original) +++ lldb/trunk/source/Core/PluginManager.cpp Wed Feb 15 11:13:19 2017 @@ -1167,6 +1167,93 @@ PluginManager::GetObjectContainerGetModu return nullptr; } +#pragma mark LogChannel + +struct LogInstance { + LogInstance() : name(), description(), create_callback(nullptr) {} + + ConstString name; + std::string description; + LogChannelCreateInstance create_callback; +}; + +typedef std::vector<LogInstance> LogInstances; + +static std::recursive_mutex &GetLogMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; +} + +static LogInstances &GetLogInstances() { + static LogInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin(const ConstString &name, + const char *description, + LogChannelCreateInstance create_callback) { + if (create_callback) { + LogInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); + GetLogInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin(LogChannelCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); + LogInstances &instances = GetLogInstances(); + + LogInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } + } + } + return false; +} + +const char *PluginManager::GetLogChannelCreateNameAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); + LogInstances &instances = GetLogInstances(); + if (idx < instances.size()) + return instances[idx].name.GetCString(); + return nullptr; +} + +LogChannelCreateInstance +PluginManager::GetLogChannelCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); + LogInstances &instances = GetLogInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; +} + +LogChannelCreateInstance +PluginManager::GetLogChannelCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); + LogInstances &instances = GetLogInstances(); + + LogInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; + } + } + return nullptr; +} + #pragma mark Platform struct PlatformInstance { Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp?rev=295201&r1=295200&r2=295201&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp Wed Feb 15 11:13:19 2017 @@ -9,28 +9,192 @@ #include "LogChannelDWARF.h" +#include "SymbolFileDWARF.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Interpreter/Args.h" + using namespace lldb; using namespace lldb_private; -static constexpr Log::Category g_categories[] = { - {"aranges", "log the parsing of .debug_aranges", DWARF_LOG_DEBUG_ARANGES}, - {"comp", "log insertions of object files into DWARF debug maps", - DWARF_LOG_TYPE_COMPLETION}, - {"info", "log the parsing of .debug_info", DWARF_LOG_DEBUG_INFO}, - {"line", "log the parsing of .debug_line", DWARF_LOG_DEBUG_LINE}, - {"lookups", "log any lookups that happen by name, regex, or address", - DWARF_LOG_LOOKUPS}, - {"map", "log struct/unions/class type completions", DWARF_LOG_DEBUG_MAP}, - {"pubnames", "log the parsing of .debug_pubnames", - DWARF_LOG_DEBUG_PUBNAMES}, - {"pubtypes", "log the parsing of .debug_pubtypes", - DWARF_LOG_DEBUG_PUBTYPES}, -}; +// when the one and only logging channel is enabled, then this will be non NULL. +static LogChannelDWARF *g_log_channel = NULL; + +LogChannelDWARF::LogChannelDWARF() : LogChannel() {} -Log::Channel LogChannelDWARF::g_channel(g_categories, DWARF_LOG_DEFAULT); +LogChannelDWARF::~LogChannelDWARF() {} void LogChannelDWARF::Initialize() { - Log::Register("dwarf", g_channel); + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), + LogChannelDWARF::CreateInstance); +} + +void LogChannelDWARF::Terminate() { + PluginManager::UnregisterPlugin(LogChannelDWARF::CreateInstance); +} + +LogChannel *LogChannelDWARF::CreateInstance() { return new LogChannelDWARF(); } + +lldb_private::ConstString LogChannelDWARF::GetPluginNameStatic() { + return SymbolFileDWARF::GetPluginNameStatic(); +} + +const char *LogChannelDWARF::GetPluginDescriptionStatic() { + return "DWARF log channel for debugging plug-in issues."; +} + +lldb_private::ConstString LogChannelDWARF::GetPluginName() { + return GetPluginNameStatic(); +} + +uint32_t LogChannelDWARF::GetPluginVersion() { return 1; } + +void LogChannelDWARF::Delete() { g_log_channel = NULL; } + +void LogChannelDWARF::Disable(const char **categories, Stream *feedback_strm) { + if (m_log_ap.get() == NULL) + return; + + uint32_t flag_bits = m_log_ap->GetMask().Get(); + for (size_t i = 0; categories[i] != NULL; ++i) { + const char *arg = categories[i]; + + if (::strcasecmp(arg, "all") == 0) + flag_bits &= ~DWARF_LOG_ALL; + else if (::strcasecmp(arg, "info") == 0) + flag_bits &= ~DWARF_LOG_DEBUG_INFO; + else if (::strcasecmp(arg, "line") == 0) + flag_bits &= ~DWARF_LOG_DEBUG_LINE; + else if (::strcasecmp(arg, "pubnames") == 0) + flag_bits &= ~DWARF_LOG_DEBUG_PUBNAMES; + else if (::strcasecmp(arg, "pubtypes") == 0) + flag_bits &= ~DWARF_LOG_DEBUG_PUBTYPES; + else if (::strcasecmp(arg, "aranges") == 0) + flag_bits &= ~DWARF_LOG_DEBUG_ARANGES; + else if (::strcasecmp(arg, "lookups") == 0) + flag_bits &= ~DWARF_LOG_LOOKUPS; + else if (::strcasecmp(arg, "map") == 0) + flag_bits &= ~DWARF_LOG_DEBUG_MAP; + else if (::strcasecmp(arg, "default") == 0) + flag_bits &= ~DWARF_LOG_DEFAULT; + else if (::strncasecmp(arg, "comp", 4) == 0) + flag_bits &= ~DWARF_LOG_TYPE_COMPLETION; + else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + ListCategories(feedback_strm); + } + } + + if (flag_bits == 0) + Delete(); + else + m_log_ap->GetMask().Reset(flag_bits); + + return; +} + +bool LogChannelDWARF::Enable( + const std::shared_ptr<llvm::raw_ostream> &log_stream_sp, + uint32_t log_options, + Stream *feedback_strm, // Feedback stream for argument errors etc + const char **categories // The categories to enable within this logging + // stream, if empty, enable default set + ) { + Delete(); + + if (m_log_ap) + m_log_ap->SetStream(log_stream_sp); + else + m_log_ap.reset(new Log(log_stream_sp)); + + g_log_channel = this; + uint32_t flag_bits = 0; + bool got_unknown_category = false; + for (size_t i = 0; categories[i] != NULL; ++i) { + const char *arg = categories[i]; + + if (::strcasecmp(arg, "all") == 0) + flag_bits |= DWARF_LOG_ALL; + else if (::strcasecmp(arg, "info") == 0) + flag_bits |= DWARF_LOG_DEBUG_INFO; + else if (::strcasecmp(arg, "line") == 0) + flag_bits |= DWARF_LOG_DEBUG_LINE; + else if (::strcasecmp(arg, "pubnames") == 0) + flag_bits |= DWARF_LOG_DEBUG_PUBNAMES; + else if (::strcasecmp(arg, "pubtypes") == 0) + flag_bits |= DWARF_LOG_DEBUG_PUBTYPES; + else if (::strcasecmp(arg, "aranges") == 0) + flag_bits |= DWARF_LOG_DEBUG_ARANGES; + else if (::strcasecmp(arg, "lookups") == 0) + flag_bits |= DWARF_LOG_LOOKUPS; + else if (::strcasecmp(arg, "map") == 0) + flag_bits |= DWARF_LOG_DEBUG_MAP; + else if (::strcasecmp(arg, "default") == 0) + flag_bits |= DWARF_LOG_DEFAULT; + else if (::strncasecmp(arg, "comp", 4) == 0) + flag_bits |= DWARF_LOG_TYPE_COMPLETION; + else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + if (got_unknown_category == false) { + got_unknown_category = true; + ListCategories(feedback_strm); + } + } + } + if (flag_bits == 0) + flag_bits = DWARF_LOG_DEFAULT; + m_log_ap->GetMask().Reset(flag_bits); + m_log_ap->GetOptions().Reset(log_options); + return m_log_ap.get() != NULL; +} + +void LogChannelDWARF::ListCategories(Stream *strm) { + strm->Printf( + "Logging categories for '%s':\n" + " all - turn on all available logging categories\n" + " info - log the parsing of .debug_info\n" + " line - log the parsing of .debug_line\n" + " pubnames - log the parsing of .debug_pubnames\n" + " pubtypes - log the parsing of .debug_pubtypes\n" + " aranges - log the parsing of .debug_aranges\n" + " lookups - log any lookups that happen by name, regex, or address\n" + " completion - log struct/unions/class type completions\n" + " map - log insertions of object files into DWARF debug maps\n", + SymbolFileDWARF::GetPluginNameStatic().GetCString()); +} + +Log *LogChannelDWARF::GetLog() { + if (g_log_channel) + return g_log_channel->m_log_ap.get(); + + return NULL; +} + +Log *LogChannelDWARF::GetLogIfAll(uint32_t mask) { + if (g_log_channel && g_log_channel->m_log_ap.get()) { + if (g_log_channel->m_log_ap->GetMask().AllSet(mask)) + return g_log_channel->m_log_ap.get(); + } + return NULL; } -void LogChannelDWARF::Terminate() { Log::Unregister("dwarf"); } +Log *LogChannelDWARF::GetLogIfAny(uint32_t mask) { + if (g_log_channel && g_log_channel->m_log_ap.get()) { + if (g_log_channel->m_log_ap->GetMask().AnySet(mask)) + return g_log_channel->m_log_ap.get(); + } + return NULL; +} + +void LogChannelDWARF::LogIf(uint32_t mask, const char *format, ...) { + if (g_log_channel) { + Log *log = g_log_channel->m_log_ap.get(); + if (log && log->GetMask().AnySet(mask)) { + va_list args; + va_start(args, format); + log->VAPrintf(format, args); + va_end(args); + } + } +} Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h?rev=295201&r1=295200&r2=295201&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h Wed Feb 15 11:13:19 2017 @@ -27,17 +27,48 @@ #define DWARF_LOG_ALL (UINT32_MAX) #define DWARF_LOG_DEFAULT (DWARF_LOG_DEBUG_INFO) -namespace lldb_private { -class LogChannelDWARF { - static Log::Channel g_channel; - +class LogChannelDWARF : public lldb_private::LogChannel { public: + LogChannelDWARF(); + + ~LogChannelDWARF() override; + static void Initialize(); + static void Terminate(); - static Log *GetLogIfAll(uint32_t mask) { return g_channel.GetLogIfAll(mask); } - static Log *GetLogIfAny(uint32_t mask) { return g_channel.GetLogIfAny(mask); } + static lldb_private::ConstString GetPluginNameStatic(); + + static const char *GetPluginDescriptionStatic(); + + static lldb_private::LogChannel *CreateInstance(); + + lldb_private::ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override; + + void Disable(const char **categories, + lldb_private::Stream *feedback_strm) override; + + void Delete(); + + bool Enable(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp, + uint32_t log_options, + lldb_private::Stream + *feedback_strm, // Feedback stream for argument errors etc + const char **categories) override; // The categories to enable + // within this logging stream, + // if empty, enable default set + + void ListCategories(lldb_private::Stream *strm) override; + + static lldb_private::Log *GetLog(); + + static lldb_private::Log *GetLogIfAll(uint32_t mask); + + static lldb_private::Log *GetLogIfAny(uint32_t mask); + + static void LogIf(uint32_t mask, const char *format, ...); }; -} #endif // SymbolFileDWARF_LogChannelDWARF_h_ Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=295201&r1=295200&r2=295201&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Wed Feb 15 11:13:19 2017 @@ -223,7 +223,7 @@ void SymbolFileDWARF::DebuggerInitialize void SymbolFileDWARF::Terminate() { PluginManager::UnregisterPlugin(CreateInstance); - LogChannelDWARF::Terminate(); + LogChannelDWARF::Initialize(); } lldb_private::ConstString SymbolFileDWARF::GetPluginNameStatic() { Modified: lldb/trunk/unittests/Core/LogTest.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Core/LogTest.cpp?rev=295201&r1=295200&r2=295201&view=diff ============================================================================== --- lldb/trunk/unittests/Core/LogTest.cpp (original) +++ lldb/trunk/unittests/Core/LogTest.cpp Wed Feb 15 11:13:19 2017 @@ -12,30 +12,10 @@ #include "lldb/Core/Log.h" #include "lldb/Host/Host.h" #include "lldb/Utility/StreamString.h" -#include "llvm/Support/ManagedStatic.h" using namespace lldb; using namespace lldb_private; -enum { FOO = 1, BAR = 2 }; -static constexpr Log::Category test_categories[] = { - {"foo", "log foo", FOO}, {"bar", "log bar", BAR}, -}; -static constexpr uint32_t default_flags = FOO; - -static Log::Channel test_channel(test_categories, default_flags); - -struct LogChannelTest : public ::testing::Test { - static void SetUpTestCase() { - Log::Register("chan", test_channel); - } - - static void TearDownTestCase() { - Log::Unregister("chan"); - llvm::llvm_shutdown(); - } -}; - static std::string GetLogString(uint32_t log_options, const char *format, int arg) { std::string stream_string; @@ -77,96 +57,3 @@ TEST(LogTest, log_options) { GetLogString(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD, "Hello World {0}", 47)); } - -TEST(LogTest, Register) { - llvm::llvm_shutdown_obj obj; - Log::Register("chan", test_channel); - Log::Unregister("chan"); - Log::Register("chan", test_channel); - Log::Unregister("chan"); -} - -TEST(LogTest, Unregister) { - llvm::llvm_shutdown_obj obj; - Log::Register("chan", test_channel); - EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO)); - const char *cat1[] = {"foo", nullptr}; - std::string message; - std::shared_ptr<llvm::raw_string_ostream> stream_sp( - new llvm::raw_string_ostream(message)); - StreamString err; - EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat1, err)); - EXPECT_NE(nullptr, test_channel.GetLogIfAny(FOO)); - Log::Unregister("chan"); - EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO)); -} - -TEST_F(LogChannelTest, Enable) { - EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO)); - std::string message; - std::shared_ptr<llvm::raw_string_ostream> stream_sp( - new llvm::raw_string_ostream(message)); - StreamString err; - EXPECT_FALSE(Log::EnableLogChannel(stream_sp, 0, "chanchan", nullptr, err)); - EXPECT_EQ("Invalid log channel 'chanchan'.\n", err.GetString()); - err.Clear(); - - EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", nullptr, err)); - EXPECT_EQ("", err.GetString()); - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); - EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); - - const char *cat2[] = {"bar", nullptr}; - EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat2, err)); - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); - - const char *cat3[] = {"baz", nullptr}; - EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat3, err)); - EXPECT_TRUE(err.GetString().contains("unrecognized log category 'baz'")) - << "err: " << err.GetString().str(); - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); -} - -TEST_F(LogChannelTest, Disable) { - EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO)); - const char *cat12[] = {"foo", "bar", nullptr}; - std::string message; - std::shared_ptr<llvm::raw_string_ostream> stream_sp( - new llvm::raw_string_ostream(message)); - StreamString err; - EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat12, err)); - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); - - const char *cat2[] = {"bar", nullptr}; - EXPECT_TRUE(Log::DisableLogChannel("chan", cat2, err)); - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); - EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); - - const char *cat3[] = {"baz", nullptr}; - EXPECT_TRUE(Log::DisableLogChannel("chan", cat3, err)); - EXPECT_TRUE(err.GetString().contains("unrecognized log category 'baz'")) - << "err: " << err.GetString().str(); - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); - EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); - err.Clear(); - - EXPECT_TRUE(Log::DisableLogChannel("chan", nullptr, err)); - EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO | BAR)); -} - -TEST_F(LogChannelTest, List) { - StreamString str; - EXPECT_TRUE(Log::ListChannelCategories("chan", str)); - std::string expected = - R"(Logging categories for 'chan': - all - all available logging categories - default - default set of logging categories - foo - log foo - bar - log bar -)"; - EXPECT_EQ(expected, str.GetString().str()); - str.Clear(); - - EXPECT_FALSE(Log::ListChannelCategories("chanchan", str)); - EXPECT_EQ("Invalid log channel 'chanchan'.\n", str.GetString().str()); -} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits