blob: 57b888a3bacc53c2b70c739a15d67a5de5182641 [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
10// C Includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000011#include <stdio.h>
12#include <stdarg.h>
13#include <stdlib.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014
15// C++ Includes
16#include <map>
17#include <string>
18
19// Other libraries and framework includes
20// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021#include "lldb/Core/Log.h"
22#include "lldb/Core/PluginManager.h"
23#include "lldb/Core/StreamFile.h"
24#include "lldb/Core/StreamString.h"
25#include "lldb/Host/Host.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026#include "lldb/Host/Mutex.h"
Zachary Turner39de3112014-09-09 20:54:56 +000027#include "lldb/Host/ThisThread.h"
28#include "lldb/Host/TimeValue.h"
Caroline Tice20ad3c42010-10-29 21:48:37 +000029#include "lldb/Interpreter/Args.h"
Zachary Turner50232572015-03-18 21:31:45 +000030#include "lldb/Utility/NameMatches.h"
Zachary Turner39de3112014-09-09 20:54:56 +000031
32#include "llvm/ADT/SmallString.h"
Zachary Turnera893d302015-03-06 20:45:43 +000033#include "llvm/Support/raw_ostream.h"
34#include "llvm/Support/Signals.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035using namespace lldb;
36using namespace lldb_private;
37
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038Log::Log () :
39 m_stream_sp(),
40 m_options(0),
41 m_mask_bits(0)
42{
43}
44
Greg Clayton5160ce52013-03-27 23:08:40 +000045Log::Log (const StreamSP &stream_sp) :
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046 m_stream_sp(stream_sp),
47 m_options(0),
48 m_mask_bits(0)
49{
50}
51
52Log::~Log ()
53{
54}
55
56Flags &
57Log::GetOptions()
58{
59 return m_options;
60}
61
62const Flags &
63Log::GetOptions() const
64{
65 return m_options;
66}
67
68Flags &
69Log::GetMask()
70{
71 return m_mask_bits;
72}
73
74const Flags &
75Log::GetMask() const
76{
77 return m_mask_bits;
78}
79
80
81//----------------------------------------------------------------------
82// All logging eventually boils down to this function call. If we have
83// a callback registered, then we call the logging callback. If we have
84// a valid file handle, we also log to the file.
85//----------------------------------------------------------------------
86void
87Log::PrintfWithFlagsVarArg (uint32_t flags, const char *format, va_list args)
88{
Greg Claytone98008c2014-02-13 23:34:38 +000089 // Make a copy of our stream shared pointer in case someone disables our
90 // log while we are logging and releases the stream
91 StreamSP stream_sp(m_stream_sp);
92 if (stream_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000093 {
94 static uint32_t g_sequence_id = 0;
95 StreamString header;
Greg Clayton64195a22011-02-23 00:35:02 +000096 // Enabling the thread safe logging actually deadlocks right now.
97 // Need to fix this at some point.
98// static Mutex g_LogThreadedMutex(Mutex::eMutexTypeRecursive);
99// Mutex::Locker locker (g_LogThreadedMutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100
101 // Add a sequence ID if requested
Greg Clayton73b472d2010-10-27 03:32:59 +0000102 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_SEQUENCE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000103 header.Printf ("%u ", ++g_sequence_id);
104
105 // Timestamp if requested
Greg Clayton73b472d2010-10-27 03:32:59 +0000106 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_TIMESTAMP))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000107 {
Virgile Bello0a3b1512013-09-04 13:56:11 +0000108 TimeValue now = TimeValue::Now();
Jason Molenda3c2daca2013-09-11 21:00:37 +0000109 header.Printf ("%9d.%6.6d ", now.seconds(), now.nanoseconds());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000110 }
111
112 // Add the process and thread if requested
Greg Clayton73b472d2010-10-27 03:32:59 +0000113 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD))
Daniel Malead01b2952012-11-29 21:49:15 +0000114 header.Printf ("[%4.4x/%4.4" PRIx64 "]: ", getpid(), Host::GetCurrentThreadID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000115
Ed Mastecc913d142014-05-21 13:46:46 +0000116 // Add the thread name if requested
Greg Clayton73b472d2010-10-27 03:32:59 +0000117 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_THREAD_NAME))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000118 {
Zachary Turner39de3112014-09-09 20:54:56 +0000119 llvm::SmallString<32> thread_name;
120 ThisThread::GetName(thread_name);
Greg Clayton85719632013-02-27 22:51:58 +0000121 if (!thread_name.empty())
122 header.Printf ("%s ", thread_name.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000123 }
124
125 header.PrintfVarArg (format, args);
Greg Claytone98008c2014-02-13 23:34:38 +0000126 stream_sp->Printf("%s\n", header.GetData());
Greg Clayton3a18e312012-10-08 22:41:53 +0000127
Zachary Turnera893d302015-03-06 20:45:43 +0000128 if (m_options.Test(LLDB_LOG_OPTION_BACKTRACE))
129 {
130 std::string back_trace;
131 llvm::raw_string_ostream stream(back_trace);
132 llvm::sys::PrintStackTrace(stream);
133 stream_sp->PutCString(back_trace.c_str());
134 }
Greg Claytone98008c2014-02-13 23:34:38 +0000135 stream_sp->Flush();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136 }
137}
138
139
140void
141Log::PutCString (const char *cstr)
142{
143 Printf ("%s", cstr);
144}
145
146
147//----------------------------------------------------------------------
148// Simple variable argument logging with flags.
149//----------------------------------------------------------------------
150void
151Log::Printf(const char *format, ...)
152{
153 va_list args;
154 va_start (args, format);
155 PrintfWithFlagsVarArg (0, format, args);
156 va_end (args);
157}
158
159void
160Log::VAPrintf (const char *format, va_list args)
161{
162 PrintfWithFlagsVarArg (0, format, args);
163}
164
165
166//----------------------------------------------------------------------
167// Simple variable argument logging with flags.
168//----------------------------------------------------------------------
169void
170Log::PrintfWithFlags (uint32_t flags, const char *format, ...)
171{
172 va_list args;
173 va_start (args, format);
174 PrintfWithFlagsVarArg (flags, format, args);
175 va_end (args);
176}
177
178//----------------------------------------------------------------------
179// Print debug strings if and only if the global debug option is set to
180// a non-zero value.
181//----------------------------------------------------------------------
182void
183Log::Debug (const char *format, ...)
184{
Greg Clayton73b472d2010-10-27 03:32:59 +0000185 if (GetOptions().Test(LLDB_LOG_OPTION_DEBUG))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000186 {
187 va_list args;
188 va_start (args, format);
189 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG, format, args);
190 va_end (args);
191 }
192}
193
194
195//----------------------------------------------------------------------
196// Print debug strings if and only if the global debug option is set to
197// a non-zero value.
198//----------------------------------------------------------------------
199void
200Log::DebugVerbose (const char *format, ...)
201{
Greg Clayton73b472d2010-10-27 03:32:59 +0000202 if (GetOptions().AllSet (LLDB_LOG_OPTION_DEBUG | LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000203 {
204 va_list args;
205 va_start (args, format);
206 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG | LLDB_LOG_FLAG_VERBOSE, format, args);
207 va_end (args);
208 }
209}
210
211
212//----------------------------------------------------------------------
213// Log only if all of the bits are set
214//----------------------------------------------------------------------
215void
216Log::LogIf (uint32_t bits, const char *format, ...)
217{
Greg Clayton73b472d2010-10-27 03:32:59 +0000218 if (m_options.AllSet (bits))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000219 {
220 va_list args;
221 va_start (args, format);
222 PrintfWithFlagsVarArg (0, format, args);
223 va_end (args);
224 }
225}
226
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000227//----------------------------------------------------------------------
228// Printing of errors that are not fatal.
229//----------------------------------------------------------------------
230void
231Log::Error (const char *format, ...)
232{
233 char *arg_msg = NULL;
234 va_list args;
235 va_start (args, format);
236 ::vasprintf (&arg_msg, format, args);
237 va_end (args);
238
239 if (arg_msg != NULL)
240 {
241 PrintfWithFlags (LLDB_LOG_FLAG_ERROR, "error: %s", arg_msg);
242 free (arg_msg);
243 }
244}
245
246//----------------------------------------------------------------------
247// Printing of errors that ARE fatal. Exit with ERR exit code
248// immediately.
249//----------------------------------------------------------------------
250void
251Log::FatalError (int err, const char *format, ...)
252{
253 char *arg_msg = NULL;
254 va_list args;
255 va_start (args, format);
256 ::vasprintf (&arg_msg, format, args);
257 va_end (args);
258
259 if (arg_msg != NULL)
260 {
261 PrintfWithFlags (LLDB_LOG_FLAG_ERROR | LLDB_LOG_FLAG_FATAL, "error: %s", arg_msg);
262 ::free (arg_msg);
263 }
264 ::exit (err);
265}
266
267
268//----------------------------------------------------------------------
269// Printing of warnings that are not fatal only if verbose mode is
270// enabled.
271//----------------------------------------------------------------------
272void
273Log::Verbose (const char *format, ...)
274{
Greg Clayton73b472d2010-10-27 03:32:59 +0000275 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000276 {
277 va_list args;
278 va_start (args, format);
279 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_VERBOSE, format, args);
280 va_end (args);
281 }
282}
283
284//----------------------------------------------------------------------
285// Printing of warnings that are not fatal only if verbose mode is
286// enabled.
287//----------------------------------------------------------------------
288void
289Log::WarningVerbose (const char *format, ...)
290{
Greg Clayton73b472d2010-10-27 03:32:59 +0000291 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000292 {
293 char *arg_msg = NULL;
294 va_list args;
295 va_start (args, format);
296 ::vasprintf (&arg_msg, format, args);
297 va_end (args);
298
299 if (arg_msg != NULL)
300 {
301 PrintfWithFlags (LLDB_LOG_FLAG_WARNING | LLDB_LOG_FLAG_VERBOSE, "warning: %s", arg_msg);
302 free (arg_msg);
303 }
304 }
305}
306//----------------------------------------------------------------------
307// Printing of warnings that are not fatal.
308//----------------------------------------------------------------------
309void
310Log::Warning (const char *format, ...)
311{
312 char *arg_msg = NULL;
313 va_list args;
314 va_start (args, format);
315 ::vasprintf (&arg_msg, format, args);
316 va_end (args);
317
318 if (arg_msg != NULL)
319 {
320 PrintfWithFlags (LLDB_LOG_FLAG_WARNING, "warning: %s", arg_msg);
321 free (arg_msg);
322 }
323}
324
Greg Clayton57abc5d2013-05-10 21:47:16 +0000325typedef std::map <ConstString, Log::Callbacks> CallbackMap;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000326typedef CallbackMap::iterator CallbackMapIter;
327
328typedef std::map <ConstString, LogChannelSP> LogChannelMap;
329typedef LogChannelMap::iterator LogChannelMapIter;
330
331
332// Surround our callback map with a singleton function so we don't have any
333// global initializers.
334static CallbackMap &
335GetCallbackMap ()
336{
337 static CallbackMap g_callback_map;
338 return g_callback_map;
339}
340
341static LogChannelMap &
342GetChannelMap ()
343{
344 static LogChannelMap g_channel_map;
345 return g_channel_map;
346}
347
348void
Greg Clayton57abc5d2013-05-10 21:47:16 +0000349Log::RegisterLogChannel (const ConstString &channel, const Log::Callbacks &log_callbacks)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000350{
351 GetCallbackMap().insert(std::make_pair(channel, log_callbacks));
352}
353
354bool
Greg Clayton57abc5d2013-05-10 21:47:16 +0000355Log::UnregisterLogChannel (const ConstString &channel)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000356{
357 return GetCallbackMap().erase(channel) != 0;
358}
359
360bool
Greg Clayton57abc5d2013-05-10 21:47:16 +0000361Log::GetLogChannelCallbacks (const ConstString &channel, Log::Callbacks &log_callbacks)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000362{
363 CallbackMap &callback_map = GetCallbackMap ();
364 CallbackMapIter pos = callback_map.find(channel);
365 if (pos != callback_map.end())
366 {
367 log_callbacks = pos->second;
368 return true;
369 }
Greg Clayton72b77eb2011-02-04 21:13:05 +0000370 ::memset (&log_callbacks, 0, sizeof(log_callbacks));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000371 return false;
372}
373
374void
375Log::EnableAllLogChannels
376(
377 StreamSP &log_stream_sp,
378 uint32_t log_options,
Jim Ingham228063c2012-02-21 02:23:08 +0000379 const char **categories,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380 Stream *feedback_strm
381)
382{
383 CallbackMap &callback_map = GetCallbackMap ();
384 CallbackMapIter pos, end = callback_map.end();
385
386 for (pos = callback_map.begin(); pos != end; ++pos)
Jim Ingham228063c2012-02-21 02:23:08 +0000387 pos->second.enable (log_stream_sp, log_options, categories, feedback_strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388
389 LogChannelMap &channel_map = GetChannelMap ();
390 LogChannelMapIter channel_pos, channel_end = channel_map.end();
391 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
392 {
Jim Ingham228063c2012-02-21 02:23:08 +0000393 channel_pos->second->Enable (log_stream_sp, log_options, feedback_strm, categories);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000394 }
395
396}
397
398void
Greg Claytonab65b342011-04-13 22:47:15 +0000399Log::AutoCompleteChannelName (const char *channel_name, StringList &matches)
400{
401 LogChannelMap &map = GetChannelMap ();
402 LogChannelMapIter pos, end = map.end();
403 for (pos = map.begin(); pos != end; ++pos)
404 {
405 const char *pos_channel_name = pos->first.GetCString();
406 if (channel_name && channel_name[0])
407 {
408 if (NameMatches (channel_name, eNameMatchStartsWith, pos_channel_name))
409 {
410 matches.AppendString(pos_channel_name);
411 }
412 }
413 else
414 matches.AppendString(pos_channel_name);
415
416 }
417}
418
419void
Caroline Tice20ad3c42010-10-29 21:48:37 +0000420Log::DisableAllLogChannels (Stream *feedback_strm)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000421{
422 CallbackMap &callback_map = GetCallbackMap ();
423 CallbackMapIter pos, end = callback_map.end();
Jim Ingham228063c2012-02-21 02:23:08 +0000424 const char *categories[1] = {NULL};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000425
426 for (pos = callback_map.begin(); pos != end; ++pos)
Jim Ingham228063c2012-02-21 02:23:08 +0000427 pos->second.disable (categories, feedback_strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000428
429 LogChannelMap &channel_map = GetChannelMap ();
430 LogChannelMapIter channel_pos, channel_end = channel_map.end();
431 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
Jim Ingham228063c2012-02-21 02:23:08 +0000432 channel_pos->second->Disable (categories, feedback_strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000433}
434
435void
Greg Clayton99d0faf2010-11-18 23:32:35 +0000436Log::Initialize()
437{
438 Log::Callbacks log_callbacks = { DisableLog, EnableLog, ListLogCategories };
Greg Clayton57abc5d2013-05-10 21:47:16 +0000439 Log::RegisterLogChannel (ConstString("lldb"), log_callbacks);
Greg Clayton99d0faf2010-11-18 23:32:35 +0000440}
441
442void
443Log::Terminate ()
444{
445 DisableAllLogChannels (NULL);
446}
447
448void
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000449Log::ListAllLogChannels (Stream *strm)
450{
451 CallbackMap &callback_map = GetCallbackMap ();
452 LogChannelMap &channel_map = GetChannelMap ();
453
454 if (callback_map.empty() && channel_map.empty())
455 {
456 strm->PutCString ("No logging channels are currently registered.\n");
457 return;
458 }
459
460 CallbackMapIter pos, end = callback_map.end();
461 for (pos = callback_map.begin(); pos != end; ++pos)
462 pos->second.list_categories (strm);
463
464 uint32_t idx = 0;
465 const char *name;
466 for (idx = 0; (name = PluginManager::GetLogChannelCreateNameAtIndex (idx)) != NULL; ++idx)
467 {
468 LogChannelSP log_channel_sp(LogChannel::FindPlugin (name));
469 if (log_channel_sp)
470 log_channel_sp->ListCategories (strm);
471 }
472}
473
474bool
475Log::GetVerbose() const
476{
Jim Inghamd8d148e2011-01-22 01:24:30 +0000477 // FIXME: This has to be centralized between the stream and the log...
478 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
479 return true;
480
Greg Claytone98008c2014-02-13 23:34:38 +0000481 // Make a copy of our stream shared pointer in case someone disables our
482 // log while we are logging and releases the stream
483 StreamSP stream_sp(m_stream_sp);
484 if (stream_sp)
485 return stream_sp->GetVerbose();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000486 return false;
487}
488
489//------------------------------------------------------------------
490// Returns true if the debug flag bit is set in this stream.
491//------------------------------------------------------------------
492bool
493Log::GetDebug() const
494{
Greg Claytone98008c2014-02-13 23:34:38 +0000495 // Make a copy of our stream shared pointer in case someone disables our
496 // log while we are logging and releases the stream
497 StreamSP stream_sp(m_stream_sp);
498 if (stream_sp)
499 return stream_sp->GetDebug();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000500 return false;
501}
502
503
504LogChannelSP
505LogChannel::FindPlugin (const char *plugin_name)
506{
507 LogChannelSP log_channel_sp;
508 LogChannelMap &channel_map = GetChannelMap ();
509 ConstString log_channel_name (plugin_name);
510 LogChannelMapIter pos = channel_map.find (log_channel_name);
511 if (pos == channel_map.end())
512 {
Greg Clayton57abc5d2013-05-10 21:47:16 +0000513 ConstString const_plugin_name (plugin_name);
514 LogChannelCreateInstance create_callback = PluginManager::GetLogChannelCreateCallbackForPluginName (const_plugin_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000515 if (create_callback)
516 {
517 log_channel_sp.reset(create_callback());
518 if (log_channel_sp)
519 {
520 // Cache the one and only loaded instance of each log channel
521 // plug-in after it has been loaded once.
522 channel_map[log_channel_name] = log_channel_sp;
523 }
524 }
525 }
526 else
527 {
528 // We have already loaded an instance of this log channel class,
529 // so just return the cached instance.
530 log_channel_sp = pos->second;
531 }
532 return log_channel_sp;
533}
534
535LogChannel::LogChannel () :
Greg Clayton5160ce52013-03-27 23:08:40 +0000536 m_log_ap ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000537{
538}
539
540LogChannel::~LogChannel ()
541{
542}
543
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000544