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