LLDB  mainline
Log.cpp
Go to the documentation of this file.
1 //===-- Log.cpp -----------------------------------------------------------===//
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 #include "lldb/Utility/Log.h"
10 #include "lldb/Utility/VASPrintf.h"
11 
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/ADT/iterator.h"
15 
16 #include "llvm/Support/Chrono.h"
17 #include "llvm/Support/ManagedStatic.h"
18 #include "llvm/Support/Path.h"
19 #include "llvm/Support/Signals.h"
20 #include "llvm/Support/Threading.h"
21 #include "llvm/Support/raw_ostream.h"
22 
23 #include <chrono>
24 #include <cstdarg>
25 #include <mutex>
26 #include <utility>
27 
28 #include <cassert>
29 #if defined(_WIN32)
30 #include <process.h>
31 #else
32 #include <unistd.h>
33 #endif
34 
35 using namespace lldb_private;
36 
37 llvm::ManagedStatic<Log::ChannelMap> Log::g_channel_map;
38 
40  const Log::ChannelMap::value_type &entry,
41  llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> lambda) {
42  lambda("all", "all available logging categories");
43  lambda("default", "default set of logging categories");
44  for (const auto &category : entry.second.m_channel.categories)
45  lambda(category.name, category.description);
46 }
47 
48 void Log::ListCategories(llvm::raw_ostream &stream,
49  const ChannelMap::value_type &entry) {
50  stream << llvm::formatv("Logging categories for '{0}':\n", entry.first());
51  ForEachCategory(entry,
52  [&stream](llvm::StringRef name, llvm::StringRef description) {
53  stream << llvm::formatv(" {0} - {1}\n", name, description);
54  });
55 }
56 
57 uint32_t Log::GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry,
58  llvm::ArrayRef<const char *> categories) {
59  bool list_categories = false;
60  uint32_t flags = 0;
61  for (const char *category : categories) {
62  if (llvm::StringRef("all").equals_insensitive(category)) {
63  flags |= UINT32_MAX;
64  continue;
65  }
66  if (llvm::StringRef("default").equals_insensitive(category)) {
67  flags |= entry.second.m_channel.default_flags;
68  continue;
69  }
70  auto cat = llvm::find_if(entry.second.m_channel.categories,
71  [&](const Log::Category &c) {
72  return c.name.equals_insensitive(category);
73  });
74  if (cat != entry.second.m_channel.categories.end()) {
75  flags |= cat->flag;
76  continue;
77  }
78  stream << llvm::formatv("error: unrecognized log category '{0}'\n",
79  category);
80  list_categories = true;
81  }
82  if (list_categories)
83  ListCategories(stream, entry);
84  return flags;
85 }
86 
87 void Log::Enable(const std::shared_ptr<llvm::raw_ostream> &stream_sp,
88  uint32_t options, uint32_t flags) {
89  llvm::sys::ScopedWriter lock(m_mutex);
90 
91  MaskType mask = m_mask.fetch_or(flags, std::memory_order_relaxed);
92  if (mask | flags) {
93  m_options.store(options, std::memory_order_relaxed);
94  m_stream_sp = stream_sp;
95  m_channel.log_ptr.store(this, std::memory_order_relaxed);
96  }
97 }
98 
99 void Log::Disable(uint32_t flags) {
100  llvm::sys::ScopedWriter lock(m_mutex);
101 
102  MaskType mask = m_mask.fetch_and(~flags, std::memory_order_relaxed);
103  if (!(mask & ~flags)) {
104  m_stream_sp.reset();
105  m_channel.log_ptr.store(nullptr, std::memory_order_relaxed);
106  }
107 }
108 
109 const Flags Log::GetOptions() const {
110  return m_options.load(std::memory_order_relaxed);
111 }
112 
113 const Flags Log::GetMask() const {
114  return m_mask.load(std::memory_order_relaxed);
115 }
116 
117 void Log::PutCString(const char *cstr) { Printf("%s", cstr); }
118 void Log::PutString(llvm::StringRef str) { PutCString(str.str().c_str()); }
119 
120 // Simple variable argument logging with flags.
121 void Log::Printf(const char *format, ...) {
122  va_list args;
123  va_start(args, format);
124  VAPrintf(format, args);
125  va_end(args);
126 }
127 
128 // All logging eventually boils down to this function call. If we have a
129 // callback registered, then we call the logging callback. If we have a valid
130 // file handle, we also log to the file.
131 void Log::VAPrintf(const char *format, va_list args) {
132  llvm::SmallString<64> FinalMessage;
133  llvm::raw_svector_ostream Stream(FinalMessage);
134  WriteHeader(Stream, "", "");
135 
136  llvm::SmallString<64> Content;
137  lldb_private::VASprintf(Content, format, args);
138 
139  Stream << Content << "\n";
140 
141  WriteMessage(std::string(FinalMessage.str()));
142 }
143 
144 // Printing of errors that are not fatal.
145 void Log::Error(const char *format, ...) {
146  va_list args;
147  va_start(args, format);
148  VAError(format, args);
149  va_end(args);
150 }
151 
152 void Log::VAError(const char *format, va_list args) {
153  llvm::SmallString<64> Content;
154  VASprintf(Content, format, args);
155 
156  Printf("error: %s", Content.c_str());
157 }
158 
159 // Printing of warnings that are not fatal only if verbose mode is enabled.
160 void Log::Verbose(const char *format, ...) {
161  if (!GetVerbose())
162  return;
163 
164  va_list args;
165  va_start(args, format);
166  VAPrintf(format, args);
167  va_end(args);
168 }
169 
170 // Printing of warnings that are not fatal.
171 void Log::Warning(const char *format, ...) {
172  llvm::SmallString<64> Content;
173  va_list args;
174  va_start(args, format);
175  VASprintf(Content, format, args);
176  va_end(args);
177 
178  Printf("warning: %s", Content.c_str());
179 }
180 
181 void Log::Register(llvm::StringRef name, Channel &channel) {
182  auto iter = g_channel_map->try_emplace(name, channel);
183  assert(iter.second == true);
184  (void)iter;
185 }
186 
187 void Log::Unregister(llvm::StringRef name) {
188  auto iter = g_channel_map->find(name);
189  assert(iter != g_channel_map->end());
190  iter->second.Disable(UINT32_MAX);
191  g_channel_map->erase(iter);
192 }
193 
195  const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
196  uint32_t log_options, llvm::StringRef channel,
197  llvm::ArrayRef<const char *> categories, llvm::raw_ostream &error_stream) {
198  auto iter = g_channel_map->find(channel);
199  if (iter == g_channel_map->end()) {
200  error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
201  return false;
202  }
203  uint32_t flags = categories.empty()
204  ? iter->second.m_channel.default_flags
205  : GetFlags(error_stream, *iter, categories);
206  iter->second.Enable(log_stream_sp, log_options, flags);
207  return true;
208 }
209 
210 bool Log::DisableLogChannel(llvm::StringRef channel,
211  llvm::ArrayRef<const char *> categories,
212  llvm::raw_ostream &error_stream) {
213  auto iter = g_channel_map->find(channel);
214  if (iter == g_channel_map->end()) {
215  error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
216  return false;
217  }
218  uint32_t flags = categories.empty()
219  ? UINT32_MAX
220  : GetFlags(error_stream, *iter, categories);
221  iter->second.Disable(flags);
222  return true;
223 }
224 
225 bool Log::ListChannelCategories(llvm::StringRef channel,
226  llvm::raw_ostream &stream) {
227  auto ch = g_channel_map->find(channel);
228  if (ch == g_channel_map->end()) {
229  stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
230  return false;
231  }
232  ListCategories(stream, *ch);
233  return true;
234 }
235 
237  for (auto &entry : *g_channel_map)
238  entry.second.Disable(UINT32_MAX);
239 }
240 
242  llvm::StringRef channel,
243  llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> lambda) {
244  auto ch = g_channel_map->find(channel);
245  if (ch == g_channel_map->end())
246  return;
247 
248  ForEachCategory(*ch, lambda);
249 }
250 
251 std::vector<llvm::StringRef> Log::ListChannels() {
252  std::vector<llvm::StringRef> result;
253  for (const auto &channel : *g_channel_map)
254  result.push_back(channel.first());
255  return result;
256 }
257 
258 void Log::ListAllLogChannels(llvm::raw_ostream &stream) {
259  if (g_channel_map->empty()) {
260  stream << "No logging channels are currently registered.\n";
261  return;
262  }
263 
264  for (const auto &channel : *g_channel_map)
265  ListCategories(stream, channel);
266 }
267 
268 bool Log::GetVerbose() const {
269  return m_options.load(std::memory_order_relaxed) & LLDB_LOG_OPTION_VERBOSE;
270 }
271 
272 void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file,
273  llvm::StringRef function) {
274  Flags options = GetOptions();
275  static uint32_t g_sequence_id = 0;
276  // Add a sequence ID if requested
278  OS << ++g_sequence_id << " ";
279 
280  // Timestamp if requested
282  auto now = std::chrono::duration<double>(
283  std::chrono::system_clock::now().time_since_epoch());
284  OS << llvm::formatv("{0:f9} ", now.count());
285  }
286 
287  // Add the process and thread if requested
289  OS << llvm::formatv("[{0,0+4}/{1,0+4}] ", getpid(),
290  llvm::get_threadid());
291 
292  // Add the thread name if requested
294  llvm::SmallString<32> thread_name;
295  llvm::get_thread_name(thread_name);
296 
297  llvm::SmallString<12> format_str;
298  llvm::raw_svector_ostream format_os(format_str);
299  format_os << "{0,-" << llvm::alignTo<16>(thread_name.size()) << "} ";
300  OS << llvm::formatv(format_str.c_str(), thread_name);
301  }
302 
303  if (options.Test(LLDB_LOG_OPTION_BACKTRACE))
304  llvm::sys::PrintStackTrace(OS);
305 
307  (!file.empty() || !function.empty())) {
308  file = llvm::sys::path::filename(file).take_front(40);
309  function = function.take_front(40);
310  OS << llvm::formatv("{0,-60:60} ", (file + ":" + function).str());
311  }
312 }
313 
315  // Make a copy of our stream shared pointer in case someone disables our log
316  // while we are logging and releases the stream
317  auto stream_sp = GetStream();
318  if (!stream_sp)
319  return;
320 
321  Flags options = GetOptions();
322  if (options.Test(LLDB_LOG_OPTION_THREADSAFE)) {
323  static std::recursive_mutex g_LogThreadedMutex;
324  std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);
325  *stream_sp << message;
326  stream_sp->flush();
327  } else {
328  *stream_sp << message;
329  stream_sp->flush();
330  }
331 }
332 
333 void Log::Format(llvm::StringRef file, llvm::StringRef function,
334  const llvm::formatv_object_base &payload) {
335  std::string message_string;
336  llvm::raw_string_ostream message(message_string);
337  WriteHeader(message, file, function);
338  message << payload << "\n";
339  WriteMessage(message.str());
340 }
lldb_private::Log::VAError
void VAError(const char *format, va_list args)
Definition: Log.cpp:152
LLDB_LOG_OPTION_PREPEND_THREAD_NAME
#define LLDB_LOG_OPTION_PREPEND_THREAD_NAME
Definition: Log.h:40
lldb_private::Log::PutString
void PutString(llvm::StringRef str)
Definition: Log.cpp:118
lldb_private::Log::m_options
std::atomic< uint32_t > m_options
Definition: Log.h:192
lldb_private::Log::GetVerbose
bool GetVerbose() const
Definition: Log.cpp:268
lldb_private::Log::VAPrintf
void VAPrintf(const char *format, va_list args)
Definition: Log.cpp:131
lldb_private::Log::Register
static void Register(llvm::StringRef name, Channel &channel)
Definition: Log.cpp:181
lldb_private::Log::m_mask
std::atomic< MaskType > m_mask
Definition: Log.h:193
lldb_private::Log::Warning
void void void void Warning(const char *fmt,...) __attribute__((format(printf
Definition: Log.cpp:171
lldb_private::Flags
Definition: Flags.h:22
lldb_private::Log::DisableLogChannel
static bool DisableLogChannel(llvm::StringRef channel, llvm::ArrayRef< const char * > categories, llvm::raw_ostream &error_stream)
Definition: Log.cpp:210
lldb_private::Log::m_stream_sp
std::shared_ptr< llvm::raw_ostream > m_stream_sp
Definition: Log.h:191
lldb_private::Flags::Test
bool Test(ValueType bit) const
Test a single flag bit.
Definition: Flags.h:96
lldb_private::Stream
Definition: Stream.h:28
lldb_private::Log::ForEachChannelCategory
static void ForEachChannelCategory(llvm::StringRef channel, llvm::function_ref< void(llvm::StringRef, llvm::StringRef)> lambda)
Calls the given lambda for every category in the given channel.
Definition: Log.cpp:241
lldb_private::Log::GetMask
const Flags GetMask() const
Definition: Log.cpp:113
LLDB_LOG_OPTION_VERBOSE
#define LLDB_LOG_OPTION_VERBOSE
Definition: Log.h:36
lldb_private::Log::ForEachCategory
static void ForEachCategory(const Log::ChannelMap::value_type &entry, llvm::function_ref< void(llvm::StringRef, llvm::StringRef)> lambda)
Definition: Log.cpp:39
lldb_private::Log::GetStream
std::shared_ptr< llvm::raw_ostream > GetStream()
Definition: Log.h:202
LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD
#define LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD
Definition: Log.h:39
lldb_private::Log::Printf
void Printf(const char *format,...) __attribute__((format(printf
Prefer using LLDB_LOGF whenever possible.
Definition: Log.cpp:121
lldb_private::Log::Category
Definition: Log.h:63
lldb_private::Log::ListChannelCategories
static bool ListChannelCategories(llvm::StringRef channel, llvm::raw_ostream &stream)
Definition: Log.cpp:225
lldb_private::Log::ListAllLogChannels
static void ListAllLogChannels(llvm::raw_ostream &stream)
Definition: Log.cpp:258
lldb_private::Log::Format
void Format(llvm::StringRef file, llvm::StringRef function, const char *format, Args &&... args)
Definition: Log.h:150
VASPrintf.h
Log.h
lldb_private::Log::DisableAllLogChannels
static void DisableAllLogChannels()
Definition: Log.cpp:236
lldb_private::Log::Unregister
static void Unregister(llvm::StringRef name)
Definition: Log.cpp:187
lldb_private::Log::m_channel
Channel & m_channel
Definition: Log.h:183
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::VASprintf
bool VASprintf(llvm::SmallVectorImpl< char > &buf, const char *fmt, va_list args)
Definition: VASprintf.cpp:19
lldb_private::Log::WriteHeader
void WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file, llvm::StringRef function)
Definition: Log.cpp:272
lldb_private::Log::MaskType
uint64_t MaskType
The underlying type of all log channel enums.
Definition: Log.h:57
lldb_private::Log::EnableLogChannel
static bool EnableLogChannel(const std::shared_ptr< llvm::raw_ostream > &log_stream_sp, uint32_t log_options, llvm::StringRef channel, llvm::ArrayRef< const char * > categories, llvm::raw_ostream &error_stream)
Definition: Log.cpp:194
lldb_private::Log::Channel
Definition: Log.h:79
LLDB_LOG_OPTION_PREPEND_TIMESTAMP
#define LLDB_LOG_OPTION_PREPEND_TIMESTAMP
Definition: Log.h:38
lldb_private::Log::Error
void void Error(const char *fmt,...) __attribute__((format(printf
Definition: Log.cpp:145
message
message(FATAL_ERROR "invalid libipt include path provided") endif() include_directories($
Definition: Plugins/Trace/intel-pt/CMakeLists.txt:6
uint32_t
lldb_private::Log::Verbose
void void void Verbose(const char *fmt,...) __attribute__((format(printf
Definition: Log.cpp:160
lldb_private::Log::g_channel_map
static llvm::ManagedStatic< ChannelMap > g_channel_map
Definition: Log.h:213
lldb_private::Log::m_mutex
llvm::sys::RWMutex m_mutex
Definition: Log.h:189
lldb_private::Log::Enable
void Enable(const std::shared_ptr< llvm::raw_ostream > &stream_sp, uint32_t options, uint32_t flags)
Definition: Log.cpp:87
LLDB_LOG_OPTION_PREPEND_SEQUENCE
#define LLDB_LOG_OPTION_PREPEND_SEQUENCE
Definition: Log.h:37
UINT32_MAX
#define UINT32_MAX
Definition: lldb-defines.h:19
lldb_private::Log::WriteMessage
void WriteMessage(const std::string &message)
Definition: Log.cpp:314
lldb_private::Log::GetFlags
static uint32_t GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry, llvm::ArrayRef< const char * > categories)
Definition: Log.cpp:57
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
LLDB_LOG_OPTION_THREADSAFE
#define LLDB_LOG_OPTION_THREADSAFE
Definition: Log.h:35
lldb_private::Log::GetOptions
void void void void const Flags GetOptions() const
Definition: Log.cpp:109
lldb_private::Log::Channel::log_ptr
std::atomic< Log * > log_ptr
Definition: Log.h:80
LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION
#define LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION
Definition: Log.h:43
lldb_private::Log::ListCategories
static void ListCategories(llvm::raw_ostream &stream, const ChannelMap::value_type &entry)
Definition: Log.cpp:48
LLDB_LOG_OPTION_BACKTRACE
#define LLDB_LOG_OPTION_BACKTRACE
Definition: Log.h:41
lldb_private::Log::Disable
void Disable(uint32_t flags)
Definition: Log.cpp:99
lldb_private::Log::ListChannels
static std::vector< llvm::StringRef > ListChannels()
Returns the list of log channels.
Definition: Log.cpp:251
lldb_private::LLDBLog::OS
@ OS
lldb_private::Log::PutCString
void PutCString(const char *cstr)
Definition: Log.cpp:117