blob: a2ff2f2b711e6125704d5f1407d376379970a91d [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
Kate Stoneb9c1b512016-09-06 20:57:50 +000041Log::Log(const StreamSP &stream_sp)
42 : 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
205bool Log::EnableLogChannel(lldb::StreamSP &log_stream_sp, uint32_t log_options,
206 const char *channel, const char **categories,
207 Stream &error_stream) {
208 Log::Callbacks log_callbacks;
209 if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) {
210 log_callbacks.enable(log_stream_sp, log_options, categories, &error_stream);
211 return true;
212 }
213
214 LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel));
215 if (log_channel_sp) {
216 if (log_channel_sp->Enable(log_stream_sp, log_options, &error_stream,
217 categories)) {
218 return true;
219 } else {
220 error_stream.Printf("Invalid log channel '%s'.\n", channel);
221 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000222 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000223 } else {
224 error_stream.Printf("Invalid log channel '%s'.\n", channel);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000225 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000226 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000227}
228
Kate Stoneb9c1b512016-09-06 20:57:50 +0000229void Log::EnableAllLogChannels(StreamSP &log_stream_sp, uint32_t log_options,
230 const char **categories, Stream *feedback_strm) {
231 CallbackMap &callback_map = GetCallbackMap();
232 CallbackMapIter pos, end = callback_map.end();
233
234 for (pos = callback_map.begin(); pos != end; ++pos)
235 pos->second.enable(log_stream_sp, log_options, categories, feedback_strm);
236
237 LogChannelMap &channel_map = GetChannelMap();
238 LogChannelMapIter channel_pos, channel_end = channel_map.end();
239 for (channel_pos = channel_map.begin(); channel_pos != channel_end;
240 ++channel_pos) {
241 channel_pos->second->Enable(log_stream_sp, log_options, feedback_strm,
242 categories);
243 }
244}
245
246void Log::AutoCompleteChannelName(const char *channel_name,
247 StringList &matches) {
248 LogChannelMap &map = GetChannelMap();
249 LogChannelMapIter pos, end = map.end();
250 for (pos = map.begin(); pos != end; ++pos) {
251 const char *pos_channel_name = pos->first.GetCString();
252 if (channel_name && channel_name[0]) {
253 if (NameMatches(channel_name, eNameMatchStartsWith, pos_channel_name)) {
254 matches.AppendString(pos_channel_name);
255 }
256 } else
257 matches.AppendString(pos_channel_name);
258 }
259}
260
261void Log::DisableAllLogChannels(Stream *feedback_strm) {
262 CallbackMap &callback_map = GetCallbackMap();
263 CallbackMapIter pos, end = callback_map.end();
264 const char *categories[] = {"all", nullptr};
265
266 for (pos = callback_map.begin(); pos != end; ++pos)
267 pos->second.disable(categories, feedback_strm);
268
269 LogChannelMap &channel_map = GetChannelMap();
270 LogChannelMapIter channel_pos, channel_end = channel_map.end();
271 for (channel_pos = channel_map.begin(); channel_pos != channel_end;
272 ++channel_pos)
273 channel_pos->second->Disable(categories, feedback_strm);
274}
275
276void Log::Initialize() {
277 Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories};
278 Log::RegisterLogChannel(ConstString("lldb"), log_callbacks);
279}
280
281void Log::Terminate() { DisableAllLogChannels(nullptr); }
282
283void Log::ListAllLogChannels(Stream *strm) {
284 CallbackMap &callback_map = GetCallbackMap();
285 LogChannelMap &channel_map = GetChannelMap();
286
287 if (callback_map.empty() && channel_map.empty()) {
288 strm->PutCString("No logging channels are currently registered.\n");
289 return;
290 }
291
292 CallbackMapIter pos, end = callback_map.end();
293 for (pos = callback_map.begin(); pos != end; ++pos)
294 pos->second.list_categories(strm);
295
296 uint32_t idx = 0;
297 const char *name;
298 for (idx = 0;
299 (name = PluginManager::GetLogChannelCreateNameAtIndex(idx)) != nullptr;
300 ++idx) {
301 LogChannelSP log_channel_sp(LogChannel::FindPlugin(name));
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +0000302 if (log_channel_sp)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000303 log_channel_sp->ListCategories(strm);
304 }
Tamas Berghammer9c9ecce2015-05-27 13:34:04 +0000305}
306
Pavel Labath0cfd7dc92017-01-13 10:41:59 +0000307bool Log::GetVerbose() const { return m_options.Test(LLDB_LOG_OPTION_VERBOSE); }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000308
309//------------------------------------------------------------------
310// Returns true if the debug flag bit is set in this stream.
311//------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000312bool Log::GetDebug() const {
Pavel Labath0cfd7dc92017-01-13 10:41:59 +0000313 // TODO: remove and clean up callers
Kate Stoneb9c1b512016-09-06 20:57:50 +0000314 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000315}
316
Pavel Labath107d9bb2017-01-18 11:00:26 +0000317void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file,
318 llvm::StringRef function) {
319 static uint32_t g_sequence_id = 0;
320 // Add a sequence ID if requested
321 if (m_options.Test(LLDB_LOG_OPTION_PREPEND_SEQUENCE))
322 OS << ++g_sequence_id << " ";
323
324 // Timestamp if requested
325 if (m_options.Test(LLDB_LOG_OPTION_PREPEND_TIMESTAMP)) {
326 auto now = std::chrono::duration<double>(
327 std::chrono::system_clock::now().time_since_epoch());
328 OS << llvm::formatv("{0:f9} ", now.count());
329 }
330
331 // Add the process and thread if requested
332 if (m_options.Test(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD))
333 OS << llvm::formatv("[{0,0+4}/{1,0+4}] ", getpid(),
334 Host::GetCurrentThreadID());
335
336 // Add the thread name if requested
337 if (m_options.Test(LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) {
338 llvm::SmallString<32> thread_name;
339 ThisThread::GetName(thread_name);
340 if (!thread_name.empty())
341 OS << thread_name;
342 }
343
344 if (m_options.Test(LLDB_LOG_OPTION_BACKTRACE))
345 llvm::sys::PrintStackTrace(OS);
346
347 if (m_options.Test(LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION) &&
348 (!file.empty() || !function.empty())) {
349 file = llvm::sys::path::filename(file).take_front(40);
350 function = function.take_front(40);
351 OS << llvm::formatv("{0,-60:60} ", (file + ":" + function).str());
352 }
353}
354
355void Log::WriteMessage(const std::string &message) {
356 // Make a copy of our stream shared pointer in case someone disables our
357 // log while we are logging and releases the stream
358 StreamSP stream_sp(m_stream_sp);
359 if (!stream_sp)
360 return;
361
362 if (m_options.Test(LLDB_LOG_OPTION_THREADSAFE)) {
363 static std::recursive_mutex g_LogThreadedMutex;
364 std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);
365 stream_sp->PutCString(message.c_str());
366 stream_sp->Flush();
367 } else {
368 stream_sp->PutCString(message.c_str());
369 stream_sp->Flush();
370 }
371}
372
373void Log::Format(llvm::StringRef file, llvm::StringRef function,
374 const llvm::formatv_object_base &payload) {
375 std::string message_string;
376 llvm::raw_string_ostream message(message_string);
377 WriteHeader(message, file, function);
378 message << payload << "\n";
379 WriteMessage(message.str());
380}
381
Kate Stoneb9c1b512016-09-06 20:57:50 +0000382LogChannelSP LogChannel::FindPlugin(const char *plugin_name) {
383 LogChannelSP log_channel_sp;
384 LogChannelMap &channel_map = GetChannelMap();
385 ConstString log_channel_name(plugin_name);
386 LogChannelMapIter pos = channel_map.find(log_channel_name);
387 if (pos == channel_map.end()) {
388 ConstString const_plugin_name(plugin_name);
389 LogChannelCreateInstance create_callback =
390 PluginManager::GetLogChannelCreateCallbackForPluginName(
391 const_plugin_name);
392 if (create_callback) {
393 log_channel_sp.reset(create_callback());
394 if (log_channel_sp) {
395 // Cache the one and only loaded instance of each log channel
396 // plug-in after it has been loaded once.
397 channel_map[log_channel_name] = log_channel_sp;
398 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000399 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000400 } else {
401 // We have already loaded an instance of this log channel class,
402 // so just return the cached instance.
403 log_channel_sp = pos->second;
404 }
405 return log_channel_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000406}
407
Kate Stoneb9c1b512016-09-06 20:57:50 +0000408LogChannel::LogChannel() : m_log_ap() {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000409
Eugene Zelenkoa74f37a2016-03-10 23:57:12 +0000410LogChannel::~LogChannel() = default;