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