aboutsummaryrefslogtreecommitdiff
path: root/source/Core/Log.cpp
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2013-08-23 17:46:38 +0000
committerEd Maste <emaste@FreeBSD.org>2013-08-23 17:46:38 +0000
commitf034231a6a1fd5d6395206c1651de8cd9402cca3 (patch)
treef561dabc721ad515599172c16da3a4400b7f4aec /source/Core/Log.cpp
downloadsrc-f034231a6a1fd5d6395206c1651de8cd9402cca3.tar.gz
src-f034231a6a1fd5d6395206c1651de8cd9402cca3.zip
Import lldb as of SVN r188801
(A number of files not required for the FreeBSD build have been removed.) Sponsored by: DARPA, AFRL
Notes
Notes: svn path=/vendor/lldb/dist/; revision=254721
Diffstat (limited to 'source/Core/Log.cpp')
-rw-r--r--source/Core/Log.cpp529
1 files changed, 529 insertions, 0 deletions
diff --git a/source/Core/Log.cpp b/source/Core/Log.cpp
new file mode 100644
index 000000000000..d73ab15f697a
--- /dev/null
+++ b/source/Core/Log.cpp
@@ -0,0 +1,529 @@
+//===-- Log.cpp -------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+// C Includes
+#include <pthread.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+// C++ Includes
+#include <map>
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Interpreter/Args.h"
+using namespace lldb;
+using namespace lldb_private;
+
+Log::Log () :
+ m_stream_sp(),
+ m_options(0),
+ m_mask_bits(0)
+{
+}
+
+Log::Log (const StreamSP &stream_sp) :
+ m_stream_sp(stream_sp),
+ m_options(0),
+ m_mask_bits(0)
+{
+}
+
+Log::~Log ()
+{
+}
+
+Flags &
+Log::GetOptions()
+{
+ return m_options;
+}
+
+const Flags &
+Log::GetOptions() const
+{
+ return m_options;
+}
+
+Flags &
+Log::GetMask()
+{
+ return m_mask_bits;
+}
+
+const Flags &
+Log::GetMask() const
+{
+ return m_mask_bits;
+}
+
+
+//----------------------------------------------------------------------
+// All logging eventually boils down to this function call. If we have
+// a callback registered, then we call the logging callback. If we have
+// a valid file handle, we also log to the file.
+//----------------------------------------------------------------------
+void
+Log::PrintfWithFlagsVarArg (uint32_t flags, const char *format, va_list args)
+{
+ if (m_stream_sp)
+ {
+ static uint32_t g_sequence_id = 0;
+ StreamString header;
+ // Enabling the thread safe logging actually deadlocks right now.
+ // Need to fix this at some point.
+// static Mutex g_LogThreadedMutex(Mutex::eMutexTypeRecursive);
+// Mutex::Locker locker (g_LogThreadedMutex);
+
+ // Add a sequence ID if requested
+ if (m_options.Test (LLDB_LOG_OPTION_PREPEND_SEQUENCE))
+ header.Printf ("%u ", ++g_sequence_id);
+
+ // Timestamp if requested
+ if (m_options.Test (LLDB_LOG_OPTION_PREPEND_TIMESTAMP))
+ {
+ struct timeval tv = TimeValue::Now().GetAsTimeVal();
+ header.Printf ("%9ld.%6.6d ", tv.tv_sec, (int32_t)tv.tv_usec);
+ }
+
+ // Add the process and thread if requested
+ if (m_options.Test (LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD))
+ header.Printf ("[%4.4x/%4.4" PRIx64 "]: ", getpid(), Host::GetCurrentThreadID());
+
+ // Add the process and thread if requested
+ if (m_options.Test (LLDB_LOG_OPTION_PREPEND_THREAD_NAME))
+ {
+ std::string thread_name (Host::GetThreadName (getpid(), Host::GetCurrentThreadID()));
+ if (!thread_name.empty())
+ header.Printf ("%s ", thread_name.c_str());
+ }
+
+ header.PrintfVarArg (format, args);
+ m_stream_sp->Printf("%s\n", header.GetData());
+
+ if (m_options.Test (LLDB_LOG_OPTION_BACKTRACE))
+ Host::Backtrace (*m_stream_sp, 1024);
+ m_stream_sp->Flush();
+ }
+}
+
+
+void
+Log::PutCString (const char *cstr)
+{
+ Printf ("%s", cstr);
+}
+
+
+//----------------------------------------------------------------------
+// Simple variable argument logging with flags.
+//----------------------------------------------------------------------
+void
+Log::Printf(const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ PrintfWithFlagsVarArg (0, format, args);
+ va_end (args);
+}
+
+void
+Log::VAPrintf (const char *format, va_list args)
+{
+ PrintfWithFlagsVarArg (0, format, args);
+}
+
+
+//----------------------------------------------------------------------
+// Simple variable argument logging with flags.
+//----------------------------------------------------------------------
+void
+Log::PrintfWithFlags (uint32_t flags, const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ PrintfWithFlagsVarArg (flags, format, args);
+ va_end (args);
+}
+
+//----------------------------------------------------------------------
+// Print debug strings if and only if the global debug option is set to
+// a non-zero value.
+//----------------------------------------------------------------------
+void
+Log::Debug (const char *format, ...)
+{
+ if (GetOptions().Test(LLDB_LOG_OPTION_DEBUG))
+ {
+ va_list args;
+ va_start (args, format);
+ PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG, format, args);
+ va_end (args);
+ }
+}
+
+
+//----------------------------------------------------------------------
+// Print debug strings if and only if the global debug option is set to
+// a non-zero value.
+//----------------------------------------------------------------------
+void
+Log::DebugVerbose (const char *format, ...)
+{
+ if (GetOptions().AllSet (LLDB_LOG_OPTION_DEBUG | LLDB_LOG_OPTION_VERBOSE))
+ {
+ va_list args;
+ va_start (args, format);
+ PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG | LLDB_LOG_FLAG_VERBOSE, format, args);
+ va_end (args);
+ }
+}
+
+
+//----------------------------------------------------------------------
+// Log only if all of the bits are set
+//----------------------------------------------------------------------
+void
+Log::LogIf (uint32_t bits, const char *format, ...)
+{
+ if (m_options.AllSet (bits))
+ {
+ va_list args;
+ va_start (args, format);
+ PrintfWithFlagsVarArg (0, format, args);
+ va_end (args);
+ }
+}
+
+
+//----------------------------------------------------------------------
+// Printing of errors that are not fatal.
+//----------------------------------------------------------------------
+void
+Log::Error (const char *format, ...)
+{
+ char *arg_msg = NULL;
+ va_list args;
+ va_start (args, format);
+ ::vasprintf (&arg_msg, format, args);
+ va_end (args);
+
+ if (arg_msg != NULL)
+ {
+ PrintfWithFlags (LLDB_LOG_FLAG_ERROR, "error: %s", arg_msg);
+ free (arg_msg);
+ }
+}
+
+//----------------------------------------------------------------------
+// Printing of errors that ARE fatal. Exit with ERR exit code
+// immediately.
+//----------------------------------------------------------------------
+void
+Log::FatalError (int err, const char *format, ...)
+{
+ char *arg_msg = NULL;
+ va_list args;
+ va_start (args, format);
+ ::vasprintf (&arg_msg, format, args);
+ va_end (args);
+
+ if (arg_msg != NULL)
+ {
+ PrintfWithFlags (LLDB_LOG_FLAG_ERROR | LLDB_LOG_FLAG_FATAL, "error: %s", arg_msg);
+ ::free (arg_msg);
+ }
+ ::exit (err);
+}
+
+
+//----------------------------------------------------------------------
+// Printing of warnings that are not fatal only if verbose mode is
+// enabled.
+//----------------------------------------------------------------------
+void
+Log::Verbose (const char *format, ...)
+{
+ if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
+ {
+ va_list args;
+ va_start (args, format);
+ PrintfWithFlagsVarArg (LLDB_LOG_FLAG_VERBOSE, format, args);
+ va_end (args);
+ }
+}
+
+//----------------------------------------------------------------------
+// Printing of warnings that are not fatal only if verbose mode is
+// enabled.
+//----------------------------------------------------------------------
+void
+Log::WarningVerbose (const char *format, ...)
+{
+ if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
+ {
+ char *arg_msg = NULL;
+ va_list args;
+ va_start (args, format);
+ ::vasprintf (&arg_msg, format, args);
+ va_end (args);
+
+ if (arg_msg != NULL)
+ {
+ PrintfWithFlags (LLDB_LOG_FLAG_WARNING | LLDB_LOG_FLAG_VERBOSE, "warning: %s", arg_msg);
+ free (arg_msg);
+ }
+ }
+}
+//----------------------------------------------------------------------
+// Printing of warnings that are not fatal.
+//----------------------------------------------------------------------
+void
+Log::Warning (const char *format, ...)
+{
+ char *arg_msg = NULL;
+ va_list args;
+ va_start (args, format);
+ ::vasprintf (&arg_msg, format, args);
+ va_end (args);
+
+ if (arg_msg != NULL)
+ {
+ PrintfWithFlags (LLDB_LOG_FLAG_WARNING, "warning: %s", arg_msg);
+ free (arg_msg);
+ }
+}
+
+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 ()
+{
+ static CallbackMap g_callback_map;
+ return g_callback_map;
+}
+
+static LogChannelMap &
+GetChannelMap ()
+{
+ static LogChannelMap g_channel_map;
+ return g_channel_map;
+}
+
+void
+Log::RegisterLogChannel (const ConstString &channel, const Log::Callbacks &log_callbacks)
+{
+ GetCallbackMap().insert(std::make_pair(channel, log_callbacks));
+}
+
+bool
+Log::UnregisterLogChannel (const ConstString &channel)
+{
+ return GetCallbackMap().erase(channel) != 0;
+}
+
+bool
+Log::GetLogChannelCallbacks (const ConstString &channel, Log::Callbacks &log_callbacks)
+{
+ CallbackMap &callback_map = GetCallbackMap ();
+ CallbackMapIter pos = callback_map.find(channel);
+ if (pos != callback_map.end())
+ {
+ log_callbacks = pos->second;
+ return true;
+ }
+ ::memset (&log_callbacks, 0, sizeof(log_callbacks));
+ return false;
+}
+
+void
+Log::EnableAllLogChannels
+(
+ StreamSP &log_stream_sp,
+ uint32_t log_options,
+ const char **categories,
+ Stream *feedback_strm
+)
+{
+ CallbackMap &callback_map = GetCallbackMap ();
+ CallbackMapIter pos, end = callback_map.end();
+
+ 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);
+ }
+
+}
+
+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);
+
+ }
+}
+
+void
+Log::DisableAllLogChannels (Stream *feedback_strm)
+{
+ CallbackMap &callback_map = GetCallbackMap ();
+ CallbackMapIter pos, end = callback_map.end();
+ const char *categories[1] = {NULL};
+
+ for (pos = callback_map.begin(); pos != end; ++pos)
+ pos->second.disable (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->Disable (categories, feedback_strm);
+}
+
+void
+Log::Initialize()
+{
+ Log::Callbacks log_callbacks = { DisableLog, EnableLog, ListLogCategories };
+ Log::RegisterLogChannel (ConstString("lldb"), log_callbacks);
+}
+
+void
+Log::Terminate ()
+{
+ DisableAllLogChannels (NULL);
+}
+
+void
+Log::ListAllLogChannels (Stream *strm)
+{
+ CallbackMap &callback_map = GetCallbackMap ();
+ LogChannelMap &channel_map = GetChannelMap ();
+
+ if (callback_map.empty() && channel_map.empty())
+ {
+ strm->PutCString ("No logging channels are currently registered.\n");
+ return;
+ }
+
+ CallbackMapIter pos, end = callback_map.end();
+ for (pos = callback_map.begin(); pos != end; ++pos)
+ pos->second.list_categories (strm);
+
+ uint32_t idx = 0;
+ const char *name;
+ for (idx = 0; (name = PluginManager::GetLogChannelCreateNameAtIndex (idx)) != NULL; ++idx)
+ {
+ LogChannelSP log_channel_sp(LogChannel::FindPlugin (name));
+ if (log_channel_sp)
+ log_channel_sp->ListCategories (strm);
+ }
+}
+
+bool
+Log::GetVerbose() const
+{
+ // FIXME: This has to be centralized between the stream and the log...
+ if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
+ return true;
+
+ if (m_stream_sp)
+ return m_stream_sp->GetVerbose();
+ return false;
+}
+
+//------------------------------------------------------------------
+// Returns true if the debug flag bit is set in this stream.
+//------------------------------------------------------------------
+bool
+Log::GetDebug() const
+{
+ if (m_stream_sp)
+ return m_stream_sp->GetDebug();
+ return false;
+}
+
+
+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 ()
+{
+}
+
+