Log.h revision 317027
1//===-- Log.h ---------------------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef LLDB_UTILITY_LOG_H 11#define LLDB_UTILITY_LOG_H 12 13#include "lldb/Utility/Flags.h" 14#include "lldb/Utility/Logging.h" 15#include "lldb/lldb-defines.h" 16 17#include "llvm/ADT/ArrayRef.h" 18#include "llvm/ADT/StringMap.h" // for StringMap 19#include "llvm/ADT/StringRef.h" // for StringRef, StringLiteral 20#include "llvm/Support/FormatVariadic.h" 21#include "llvm/Support/RWMutex.h" 22 23#include <atomic> 24#include <cstdarg> 25#include <cstdint> 26#include <memory> // for shared_ptr 27#include <string> // for string 28#include <type_traits> // for forward 29 30namespace llvm { 31class raw_ostream; 32} 33namespace llvm { 34template <class C> class ManagedStatic; 35} 36//---------------------------------------------------------------------- 37// Logging Options 38//---------------------------------------------------------------------- 39#define LLDB_LOG_OPTION_THREADSAFE (1u << 0) 40#define LLDB_LOG_OPTION_VERBOSE (1u << 1) 41#define LLDB_LOG_OPTION_PREPEND_SEQUENCE (1u << 3) 42#define LLDB_LOG_OPTION_PREPEND_TIMESTAMP (1u << 4) 43#define LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD (1u << 5) 44#define LLDB_LOG_OPTION_PREPEND_THREAD_NAME (1U << 6) 45#define LLDB_LOG_OPTION_BACKTRACE (1U << 7) 46#define LLDB_LOG_OPTION_APPEND (1U << 8) 47#define LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION (1U << 9) 48 49//---------------------------------------------------------------------- 50// Logging Functions 51//---------------------------------------------------------------------- 52namespace lldb_private { 53 54class Log final { 55public: 56 // Description of a log channel category. 57 struct Category { 58 llvm::StringLiteral name; 59 llvm::StringLiteral description; 60 uint32_t flag; 61 }; 62 63 // This class describes a log channel. It also encapsulates the behavior 64 // necessary to enable a log channel in an atomic manner. 65 class Channel { 66 std::atomic<Log *> log_ptr; 67 friend class Log; 68 69 public: 70 const llvm::ArrayRef<Category> categories; 71 const uint32_t default_flags; 72 73 constexpr Channel(llvm::ArrayRef<Log::Category> categories, 74 uint32_t default_flags) 75 : log_ptr(nullptr), categories(categories), 76 default_flags(default_flags) {} 77 78 // This function is safe to call at any time 79 // If the channel is disabled after (or concurrently with) this function 80 // returning a non-null Log pointer, it is still safe to attempt to write to 81 // the Log object -- the output will be discarded. 82 Log *GetLogIfAll(uint32_t mask) { 83 Log *log = log_ptr.load(std::memory_order_relaxed); 84 if (log && log->GetMask().AllSet(mask)) 85 return log; 86 return nullptr; 87 } 88 89 // This function is safe to call at any time 90 // If the channel is disabled after (or concurrently with) this function 91 // returning a non-null Log pointer, it is still safe to attempt to write to 92 // the Log object -- the output will be discarded. 93 Log *GetLogIfAny(uint32_t mask) { 94 Log *log = log_ptr.load(std::memory_order_relaxed); 95 if (log && log->GetMask().AnySet(mask)) 96 return log; 97 return nullptr; 98 } 99 }; 100 101 //------------------------------------------------------------------ 102 // Static accessors for logging channels 103 //------------------------------------------------------------------ 104 static void Register(llvm::StringRef name, Channel &channel); 105 static void Unregister(llvm::StringRef name); 106 107 static bool 108 EnableLogChannel(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp, 109 uint32_t log_options, llvm::StringRef channel, 110 llvm::ArrayRef<const char *> categories, 111 llvm::raw_ostream &error_stream); 112 113 static bool DisableLogChannel(llvm::StringRef channel, 114 llvm::ArrayRef<const char *> categories, 115 llvm::raw_ostream &error_stream); 116 117 static bool ListChannelCategories(llvm::StringRef channel, llvm::raw_ostream &stream); 118 119 static void DisableAllLogChannels(); 120 121 static void ListAllLogChannels(llvm::raw_ostream &stream); 122 123 //------------------------------------------------------------------ 124 // Member functions 125 // 126 // These functions are safe to call at any time you have a Log* obtained from 127 // the Channel class. If logging is disabled between you obtaining the Log 128 // object and writing to it, the output will be silently discarded. 129 //------------------------------------------------------------------ 130 Log(Channel &channel) : m_channel(channel) {} 131 ~Log() = default; 132 133 void PutCString(const char *cstr); 134 void PutString(llvm::StringRef str); 135 136 template <typename... Args> 137 void Format(llvm::StringRef file, llvm::StringRef function, 138 const char *format, Args &&... args) { 139 Format(file, function, llvm::formatv(format, std::forward<Args>(args)...)); 140 } 141 142 void Printf(const char *format, ...) __attribute__((format(printf, 2, 3))); 143 144 void VAPrintf(const char *format, va_list args); 145 146 void Error(const char *fmt, ...) __attribute__((format(printf, 2, 3))); 147 148 void VAError(const char *format, va_list args); 149 150 void Verbose(const char *fmt, ...) __attribute__((format(printf, 2, 3))); 151 152 void Warning(const char *fmt, ...) __attribute__((format(printf, 2, 3))); 153 154 const Flags GetOptions() const; 155 156 const Flags GetMask() const; 157 158 bool GetVerbose() const; 159 160private: 161 Channel &m_channel; 162 163 // The mutex makes sure enable/disable operations are thread-safe. The options 164 // and mask variables are atomic to enable their reading in 165 // Channel::GetLogIfAny without taking the mutex to speed up the fast path. 166 // Their modification however, is still protected by this mutex. 167 llvm::sys::RWMutex m_mutex; 168 169 std::shared_ptr<llvm::raw_ostream> m_stream_sp; 170 std::atomic<uint32_t> m_options{0}; 171 std::atomic<uint32_t> m_mask{0}; 172 173 void WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file, 174 llvm::StringRef function); 175 void WriteMessage(const std::string &message); 176 177 void Format(llvm::StringRef file, llvm::StringRef function, 178 const llvm::formatv_object_base &payload); 179 180 std::shared_ptr<llvm::raw_ostream> GetStream() { 181 llvm::sys::ScopedReader lock(m_mutex); 182 return m_stream_sp; 183 } 184 185 void Enable(const std::shared_ptr<llvm::raw_ostream> &stream_sp, 186 uint32_t options, uint32_t flags); 187 188 void Disable(uint32_t flags); 189 190 typedef llvm::StringMap<Log> ChannelMap; 191 static llvm::ManagedStatic<ChannelMap> g_channel_map; 192 193 static void ListCategories(llvm::raw_ostream &stream, 194 const ChannelMap::value_type &entry); 195 static uint32_t GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry, 196 llvm::ArrayRef<const char *> categories); 197 198 Log(const Log &) = delete; 199 void operator=(const Log &) = delete; 200}; 201 202} // namespace lldb_private 203 204#define LLDB_LOG(log, ...) \ 205 do { \ 206 ::lldb_private::Log *log_private = (log); \ 207 if (log_private) \ 208 log_private->Format(__FILE__, __FUNCTION__, __VA_ARGS__); \ 209 } while (0) 210 211#define LLDB_LOGV(log, ...) \ 212 do { \ 213 ::lldb_private::Log *log_private = (log); \ 214 if (log_private && log_private->GetVerbose()) \ 215 log_private->Format(__FILE__, __FUNCTION__, __VA_ARGS__); \ 216 } while (0) 217 218#endif // LLDB_UTILITY_LOG_H 219