blob: 14b237826ff01a1081bb1f3b4092bb9387151f24 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Log.cpp -------------------------------------------------*- 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
Pavel Labath774103c2016-11-02 12:18:42 +000010// Project includes
11#include "lldb/Core/Log.h"
12#include "lldb/Core/PluginManager.h"
13#include "lldb/Core/StreamFile.h"
Pavel Labath774103c2016-11-02 12:18:42 +000014#include "lldb/Host/Host.h"
15#include "lldb/Host/ThisThread.h"
16#include "lldb/Interpreter/Args.h"
17#include "lldb/Utility/NameMatches.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000018#include "lldb/Utility/StreamString.h"
Pavel Labath774103c2016-11-02 12:18:42 +000019
20// Other libraries and framework includes
21#include "llvm/ADT/SmallString.h"
22#include "llvm/Support/Chrono.h"
Pavel Labath107d9bb2017-01-18 11:00:26 +000023#include "llvm/Support/Path.h"
Pavel Labath774103c2016-11-02 12:18:42 +000024#include "llvm/Support/Signals.h"
25#include "llvm/Support/raw_ostream.h"
26
Chris Lattner30fdc8d2010-06-08 16:52:24 +000027// C Includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028// C++ Includes
Eugene Zelenkoa74f37a2016-03-10 23:57:12 +000029#include <cstdarg>
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000030#include <cstdio>
Eugene Zelenkoa74f37a2016-03-10 23:57:12 +000031#include <cstdlib>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000032#include <map>
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000033#include <mutex>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034#include <string>
35
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036using namespace lldb;
37using namespace lldb_private;
38
Kate Stoneb9c1b512016-09-06 20:57:50 +000039Log::Log() : m_stream_sp(), m_options(0), m_mask_bits(0) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040
Pavel Labath5fae71c2017-02-10 11:49:21 +000041Log::Log(const std::shared_ptr<llvm::raw_ostream> &stream_sp)
Kate Stoneb9c1b512016-09-06 20:57:50 +000042 : m_stream_sp(stream_sp), m_options(0), m_mask_bits(0) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043
Eugene Zelenkoa74f37a2016-03-10 23:57:12 +000044Log::~Log() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000045
Kate Stoneb9c1b512016-09-06 20:57:50 +000046Flags &Log::GetOptions() { return m_options; }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047
Kate Stoneb9c1b512016-09-06 20:57:50 +000048const Flags &Log::GetOptions() const { return m_options; }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000049
Kate Stoneb9c1b512016-09-06 20:57:50 +000050Flags &Log::GetMask() { return m_mask_bits; }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000051
Kate Stoneb9c1b512016-09-06 20:57:50 +000052const Flags &Log::GetMask() const { return m_mask_bits; }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000053
Kate Stoneb9c1b512016-09-06 20:57:50 +000054void Log::PutCString(const char *cstr) { Printf("%s", cstr); }
Zachary Turnerc1564272016-11-16 21:15:24 +000055void Log::PutString(llvm::StringRef str) { PutCString(str.str().c_str()); }
Zachary Turnerc1592652015-04-29 22:55:28 +000056
57//----------------------------------------------------------------------
58// Simple variable argument logging with flags.
59//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000060void Log::Printf(const char *format, ...) {
61 va_list args;
62 va_start(args, format);
63 VAPrintf(format, args);
64 va_end(args);
Zachary Turnerc1592652015-04-29 22:55:28 +000065}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000066
67//----------------------------------------------------------------------
68// All logging eventually boils down to this function call. If we have
69// a callback registered, then we call the logging callback. If we have
70// a valid file handle, we also log to the file.
71//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000072void Log::VAPrintf(const char *format, va_list args) {
Pavel Labath107d9bb2017-01-18 11:00:26 +000073 std::string message_string;
74 llvm::raw_string_ostream message(message_string);
75 WriteHeader(message, "", "");
Chris Lattner30fdc8d2010-06-08 16:52:24 +000076
Pavel Labath107d9bb2017-01-18 11:00:26 +000077 char *text;
78 vasprintf(&text, format, args);
79 message << text;
80 free(text);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000081
Pavel Labath107d9bb2017-01-18 11:00:26 +000082 message << "\n";
Kate Stoneb9c1b512016-09-06 20:57:50 +000083
Pavel Labath107d9bb2017-01-18 11:00:26 +000084 WriteMessage(message.str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +000085}
86
Chris Lattner30fdc8d2010-06-08 16:52:24 +000087//----------------------------------------------------------------------
88// Print debug strings if and only if the global debug option is set to
89// a non-zero value.
90//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000091void Log::Debug(const char *format, ...) {
92 if (!GetOptions().Test(LLDB_LOG_OPTION_DEBUG))
93 return;
Zachary Turnerc1592652015-04-29 22:55:28 +000094
Kate Stoneb9c1b512016-09-06 20:57:50 +000095 va_list args;
96 va_start(args, format);
97 VAPrintf(format, args);
98 va_end(args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000099}
100
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000102// Log only if all of the bits are set
103//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104void Log::LogIf(uint32_t bits, const char *format, ...) {
105 if (!m_options.AllSet(bits))
106 return;
Zachary Turnerc1592652015-04-29 22:55:28 +0000107
Kate Stoneb9c1b512016-09-06 20:57:50 +0000108 va_list args;
109 va_start(args, format);
110 VAPrintf(format, args);
111 va_end(args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112}
113
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114//----------------------------------------------------------------------
115// Printing of errors that are not fatal.
116//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000117void Log::Error(const char *format, ...) {
118 va_list args;
119 va_start(args, format);
120 VAError(format, args);
121 va_end(args);
Zachary Turner610e5292015-05-07 21:39:33 +0000122}
123
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124void Log::VAError(const char *format, va_list args) {
125 char *arg_msg = nullptr;
126 ::vasprintf(&arg_msg, format, args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000127
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128 if (arg_msg == nullptr)
129 return;
Zachary Turnerc1592652015-04-29 22:55:28 +0000130
Kate Stoneb9c1b512016-09-06 20:57:50 +0000131 Printf("error: %s", arg_msg);
132 free(arg_msg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000133}
134
135//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136// Printing of warnings that are not fatal only if verbose mode is
137// enabled.
138//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139void Log::Verbose(const char *format, ...) {
140 if (!m_options.Test(LLDB_LOG_OPTION_VERBOSE))
141 return;
Zachary Turnerc1592652015-04-29 22:55:28 +0000142
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 va_list args;
144 va_start(args, format);
145 VAPrintf(format, args);
146 va_end(args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000147}
148
149//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150// Printing of warnings that are not fatal.
151//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000152void Log::Warning(const char *format, ...) {
153 char *arg_msg = nullptr;
154 va_list args;
155 va_start(args, format);
156 ::vasprintf(&arg_msg, format, args);
157 va_end(args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000158
Kate Stoneb9c1b512016-09-06 20:57:50 +0000159 if (arg_msg == nullptr)
160 return;
Zachary Turnerc1592652015-04-29 22:55:28 +0000161
Kate Stoneb9c1b512016-09-06 20:57:50 +0000162 Printf("warning: %s", arg_msg);
163 free(arg_msg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164}
165
Kate Stoneb9c1b512016-09-06 20:57:50 +0000166typedef std::map<ConstString, Log::Callbacks> CallbackMap;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167typedef CallbackMap::iterator CallbackMapIter;
168
Kate Stoneb9c1b512016-09-06 20:57:50 +0000169typedef std::map<ConstString, LogChannelSP> LogChannelMap;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170typedef LogChannelMap::iterator LogChannelMapIter;
171
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000172// Surround our callback map with a singleton function so we don't have any
173// global initializers.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174static CallbackMap &GetCallbackMap() {
175 static CallbackMap g_callback_map;
176 return g_callback_map;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000177}
178
Kate Stoneb9c1b512016-09-06 20:57:50 +0000179static LogChannelMap &GetChannelMap() {
180 static LogChannelMap g_channel_map;
181 return g_channel_map;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000182}
183
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184void Log::RegisterLogChannel(const ConstString &channel,
185 const Log::Callbacks &log_callbacks) {
186 GetCallbackMap().insert(std::make_pair(channel, log_callbacks));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000187}
188
Kate Stoneb9c1b512016-09-06 20:57:50 +0000189bool Log::UnregisterLogChannel(const ConstString &channel) {
190 return GetCallbackMap().erase(channel) != 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191}
192
Kate Stoneb9c1b512016-09-06 20:57:50 +0000193bool Log::GetLogChannelCallbacks(const ConstString &channel,
194 Log::Callbacks &log_callbacks) {
195 CallbackMap &callback_map = GetCallbackMap();
196 CallbackMapIter pos = callback_map.find(channel);
197 if (pos != callback_map.end()) {
198 log_callbacks = pos->second;
199 return true;
200 }
201 ::memset(&log_callbacks, 0, sizeof(log_callbacks));
202 return false;
203}
204
Pavel Labath5fae71c2017-02-10 11:49:21 +0000205bool Log::EnableLogChannel(
206 const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
207 uint32_t log_options, const char *channel, const char **categories,
208 Stream &error_stream) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000209 Log::Callbacks log_callbacks;
210 if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) {
211 log_callbacks.enable(log_stream_sp, log_options, categories, &error_stream);
212 return true;
213 }
214
215 LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel));
216 if (log_channel_sp) {
217 if (log_channel_sp->Enable(log_stream_sp, log_options, &error_stream,
218 categories)) {
219 return true;
220 } else {
221 error_stream.Printf("Invalid log channel '%s'.\n", channel);
222 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000224 } else {
225 error_stream.Printf("Invalid log channel '%s'.\n", channel);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000227 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000228}
229
Pavel Labath5fae71c2017-02-10 11:49:21 +0000230void Log::EnableAllLogChannels(
231 const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
232 uint32_t log_options, const char **categories, Stream *feedback_strm) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000233 CallbackMap &callback_map = GetCallbackMap();
234 CallbackMapIter pos, end = callback_map.end();
235
236 for (pos = callback_map.begin(); pos != end; ++pos)
237 pos->second.enable(log_stream_sp, log_options, categories, feedback_strm);
238
239 LogChannelMap &channel_map = GetChannelMap();
240 LogChannelMapIter channel_pos, channel_end = channel_map.end();
241 for (channel_pos = channel_map.begin(); channel_pos != channel_end;
242 ++channel_pos) {
243 channel_pos->second->Enable(log_stream_sp, log_options, feedback_strm,
244 categories);
245 }
246}
247
248void Log::AutoCompleteChannelName(const char *channel_name,
249 StringList &matches) {
250 LogChannelMap &map = GetChannelMap();
251 LogChannelMapIter pos, end = map.end();
252 for (pos = map.begin(); pos != end; ++pos) {
253 const char *pos_channel_name = pos->first.GetCString();
254 if (channel_name && channel_name[0]) {
255 if (NameMatches(channel_name, eNameMatchStartsWith, pos_channel_name)) {
256 matches.AppendString(pos_channel_name);
257 }
258 } else
259 matches.AppendString(pos_channel_name);
260 }
261}
262
263void Log::DisableAllLogChannels(Stream *feedback_strm) {
264 CallbackMap &callback_map = GetCallbackMap();
265 CallbackMapIter pos, end = callback_map.end();
266 const char *categories[] = {"all", nullptr};
267
268 for (pos = callback_map.begin(); pos != end; ++pos)
269 pos->second.disable(categories, feedback_strm);
270
271 LogChannelMap &channel_map = GetChannelMap();
272 LogChannelMapIter channel_pos, channel_end = channel_map.end();
273 for (channel_pos = channel_map.begin(); channel_pos != channel_end;
274 ++channel_pos)
275 channel_pos->second->Disable(categories, feedback_strm);
276}
277
278void Log::Initialize() {
279 Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories};
280 Log::RegisterLogChannel(ConstString("lldb"), log_callbacks);
281}
282
283void Log::Terminate() { DisableAllLogChannels(nullptr); }
284
285void Log::ListAllLogChannels(Stream *strm) {
286 CallbackMap &callback_map = GetCallbackMap();
287 LogChannelMap &channel_map = GetChannelMap();
288
289 if (callback_map.empty() && channel_map.empty()) {
290 strm->PutCString("No logging channels are currently registered.\n");
291 return;
292 }
293
294 CallbackMapIter pos, end = callback_map.end();
295 for (pos = callback_map.begin(); pos != end; ++pos)
296 pos->second.list_categories(strm);
297
298 uint32_t idx = 0;
299 const char *name;
300 for (idx = 0;
301 (name = PluginManager::GetLogChannelCreateNameAtIndex(idx)) != nullptr;
302 ++idx) {
303 LogChannelSP log_channel_sp(LogChannel::FindPlugin(name));
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +0000304 if (log_channel_sp)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000305 log_channel_sp->ListCategories(strm);
306 }
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +0000307}
308
Pavel Labath0cfd7dc92017-01-13 10:41:59 +0000309bool Log::GetVerbose() const { return m_options.Test(LLDB_LOG_OPTION_VERBOSE); }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000310
311//------------------------------------------------------------------
312// Returns true if the debug flag bit is set in this stream.
313//------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000314bool Log::GetDebug() const {
Pavel Labath0cfd7dc92017-01-13 10:41:59 +0000315 // TODO: remove and clean up callers
Kate Stoneb9c1b512016-09-06 20:57:50 +0000316 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000317}
318
Pavel Labath107d9bb2017-01-18 11:00:26 +0000319void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file,
320 llvm::StringRef function) {
321 static uint32_t g_sequence_id = 0;
322 // Add a sequence ID if requested
323 if (m_options.Test(LLDB_LOG_OPTION_PREPEND_SEQUENCE))
324 OS << ++g_sequence_id << " ";
325
326 // Timestamp if requested
327 if (m_options.Test(LLDB_LOG_OPTION_PREPEND_TIMESTAMP)) {
328 auto now = std::chrono::duration<double>(
329 std::chrono::system_clock::now().time_since_epoch());
330 OS << llvm::formatv("{0:f9} ", now.count());
331 }
332
333 // Add the process and thread if requested
334 if (m_options.Test(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD))
335 OS << llvm::formatv("[{0,0+4}/{1,0+4}] ", getpid(),
336 Host::GetCurrentThreadID());
337
338 // Add the thread name if requested
339 if (m_options.Test(LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) {
340 llvm::SmallString<32> thread_name;
341 ThisThread::GetName(thread_name);
342 if (!thread_name.empty())
343 OS << thread_name;
344 }
345
346 if (m_options.Test(LLDB_LOG_OPTION_BACKTRACE))
347 llvm::sys::PrintStackTrace(OS);
348
349 if (m_options.Test(LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION) &&
350 (!file.empty() || !function.empty())) {
351 file = llvm::sys::path::filename(file).take_front(40);
352 function = function.take_front(40);
353 OS << llvm::formatv("{0,-60:60} ", (file + ":" + function).str());
354 }
355}
356
357void Log::WriteMessage(const std::string &message) {
358 // Make a copy of our stream shared pointer in case someone disables our
359 // log while we are logging and releases the stream
Pavel Labath5fae71c2017-02-10 11:49:21 +0000360 auto stream_sp = m_stream_sp;
Pavel Labath107d9bb2017-01-18 11:00:26 +0000361 if (!stream_sp)
362 return;
363
364 if (m_options.Test(LLDB_LOG_OPTION_THREADSAFE)) {
365 static std::recursive_mutex g_LogThreadedMutex;
366 std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);
Pavel Labath5fae71c2017-02-10 11:49:21 +0000367 *stream_sp << message;
368 stream_sp->flush();
Pavel Labath107d9bb2017-01-18 11:00:26 +0000369 } else {
Pavel Labath5fae71c2017-02-10 11:49:21 +0000370 *stream_sp << message;
371 stream_sp->flush();
Pavel Labath107d9bb2017-01-18 11:00:26 +0000372 }
373}
374
375void Log::Format(llvm::StringRef file, llvm::StringRef function,
376 const llvm::formatv_object_base &payload) {
377 std::string message_string;
378 llvm::raw_string_ostream message(message_string);
379 WriteHeader(message, file, function);
380 message << payload << "\n";
381 WriteMessage(message.str());
382}
383
Kate Stoneb9c1b512016-09-06 20:57:50 +0000384LogChannelSP LogChannel::FindPlugin(const char *plugin_name) {
385 LogChannelSP log_channel_sp;
386 LogChannelMap &channel_map = GetChannelMap();
387 ConstString log_channel_name(plugin_name);
388 LogChannelMapIter pos = channel_map.find(log_channel_name);
389 if (pos == channel_map.end()) {
390 ConstString const_plugin_name(plugin_name);
391 LogChannelCreateInstance create_callback =
392 PluginManager::GetLogChannelCreateCallbackForPluginName(
393 const_plugin_name);
394 if (create_callback) {
395 log_channel_sp.reset(create_callback());
396 if (log_channel_sp) {
397 // Cache the one and only loaded instance of each log channel
398 // plug-in after it has been loaded once.
399 channel_map[log_channel_name] = log_channel_sp;
400 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000401 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000402 } else {
403 // We have already loaded an instance of this log channel class,
404 // so just return the cached instance.
405 log_channel_sp = pos->second;
406 }
407 return log_channel_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000408}
409
Kate Stoneb9c1b512016-09-06 20:57:50 +0000410LogChannel::LogChannel() : m_log_ap() {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000411
Eugene Zelenkoa74f37a2016-03-10 23:57:12 +0000412LogChannel::~LogChannel() = default;