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