[Lldb-commits] [lldb] r295201 - Revert "Refactor log channel registration mechanism"

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Wed Feb 15 09:13:20 PST 2017


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());
-}




More information about the lldb-commits mailing list