blob: f8e422e2df7945f7231e6e9956f905178d47be2a [file] [log] [blame]
Chris Lattner24943d22010-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
Daniel Malead891f9b2012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner24943d22010-06-08 16:52:24 +000012// C Includes
Chris Lattner24943d22010-06-08 16:52:24 +000013#include <pthread.h>
14#include <stdio.h>
15#include <stdarg.h>
16#include <stdlib.h>
17#include <unistd.h>
18
19// C++ Includes
20#include <map>
21#include <string>
22
23// Other libraries and framework includes
24// Project includes
25#include "lldb/Core/Debugger.h"
26#include "lldb/Core/Log.h"
27#include "lldb/Core/PluginManager.h"
28#include "lldb/Core/StreamFile.h"
29#include "lldb/Core/StreamString.h"
30#include "lldb/Host/Host.h"
31#include "lldb/Host/TimeValue.h"
32#include "lldb/Host/Mutex.h"
Caroline Tice926060e2010-10-29 21:48:37 +000033#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000034using namespace lldb;
35using namespace lldb_private;
36
Chris Lattner24943d22010-06-08 16:52:24 +000037Log::Log () :
38 m_stream_sp(),
39 m_options(0),
40 m_mask_bits(0)
41{
42}
43
44Log::Log (StreamSP &stream_sp) :
45 m_stream_sp(stream_sp),
46 m_options(0),
47 m_mask_bits(0)
48{
49}
50
51Log::~Log ()
52{
53}
54
55Flags &
56Log::GetOptions()
57{
58 return m_options;
59}
60
61const Flags &
62Log::GetOptions() const
63{
64 return m_options;
65}
66
67Flags &
68Log::GetMask()
69{
70 return m_mask_bits;
71}
72
73const Flags &
74Log::GetMask() const
75{
76 return m_mask_bits;
77}
78
79
80//----------------------------------------------------------------------
81// All logging eventually boils down to this function call. If we have
82// a callback registered, then we call the logging callback. If we have
83// a valid file handle, we also log to the file.
84//----------------------------------------------------------------------
85void
86Log::PrintfWithFlagsVarArg (uint32_t flags, const char *format, va_list args)
87{
88 if (m_stream_sp)
89 {
90 static uint32_t g_sequence_id = 0;
91 StreamString header;
Greg Clayton940b1032011-02-23 00:35:02 +000092 // Enabling the thread safe logging actually deadlocks right now.
93 // Need to fix this at some point.
94// static Mutex g_LogThreadedMutex(Mutex::eMutexTypeRecursive);
95// Mutex::Locker locker (g_LogThreadedMutex);
Chris Lattner24943d22010-06-08 16:52:24 +000096
97 // Add a sequence ID if requested
Greg Claytonf3d0b0c2010-10-27 03:32:59 +000098 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_SEQUENCE))
Chris Lattner24943d22010-06-08 16:52:24 +000099 header.Printf ("%u ", ++g_sequence_id);
100
101 // Timestamp if requested
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000102 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_TIMESTAMP))
Chris Lattner24943d22010-06-08 16:52:24 +0000103 {
104 struct timeval tv = TimeValue::Now().GetAsTimeVal();
Daniel Maleab9db9d52012-12-07 22:21:08 +0000105 header.Printf ("%9ld.%6.6d ", tv.tv_sec, (int32_t)tv.tv_usec);
Chris Lattner24943d22010-06-08 16:52:24 +0000106 }
107
108 // Add the process and thread if requested
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000109 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD))
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000110 header.Printf ("[%4.4x/%4.4" PRIx64 "]: ", getpid(), Host::GetCurrentThreadID());
Chris Lattner24943d22010-06-08 16:52:24 +0000111
112 // Add the process and thread if requested
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000113 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_THREAD_NAME))
Chris Lattner24943d22010-06-08 16:52:24 +0000114 {
Eli Friedman18cba0c2010-06-11 04:29:29 +0000115 const char *thread_name_str = Host::GetThreadName (getpid(), Host::GetCurrentThreadID());
Chris Lattner24943d22010-06-08 16:52:24 +0000116 if (thread_name_str)
117 header.Printf ("%s ", thread_name_str);
Greg Clayton49ce6822010-10-31 03:01:06 +0000118
Chris Lattner24943d22010-06-08 16:52:24 +0000119 }
120
121 header.PrintfVarArg (format, args);
122 m_stream_sp->Printf("%s\n", header.GetData());
Greg Claytonf737d372012-10-08 22:41:53 +0000123
124 if (m_options.Test (LLDB_LOG_OPTION_BACKTRACE))
125 Host::Backtrace (*m_stream_sp, 1024);
Jim Ingham6c530f22012-02-21 02:23:08 +0000126 m_stream_sp->Flush();
Chris Lattner24943d22010-06-08 16:52:24 +0000127 }
128}
129
130
131void
132Log::PutCString (const char *cstr)
133{
134 Printf ("%s", cstr);
135}
136
137
138//----------------------------------------------------------------------
139// Simple variable argument logging with flags.
140//----------------------------------------------------------------------
141void
142Log::Printf(const char *format, ...)
143{
144 va_list args;
145 va_start (args, format);
146 PrintfWithFlagsVarArg (0, format, args);
147 va_end (args);
148}
149
150void
151Log::VAPrintf (const char *format, va_list args)
152{
153 PrintfWithFlagsVarArg (0, format, args);
154}
155
156
157//----------------------------------------------------------------------
158// Simple variable argument logging with flags.
159//----------------------------------------------------------------------
160void
161Log::PrintfWithFlags (uint32_t flags, const char *format, ...)
162{
163 va_list args;
164 va_start (args, format);
165 PrintfWithFlagsVarArg (flags, format, args);
166 va_end (args);
167}
168
169//----------------------------------------------------------------------
170// Print debug strings if and only if the global debug option is set to
171// a non-zero value.
172//----------------------------------------------------------------------
173void
174Log::Debug (const char *format, ...)
175{
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000176 if (GetOptions().Test(LLDB_LOG_OPTION_DEBUG))
Chris Lattner24943d22010-06-08 16:52:24 +0000177 {
178 va_list args;
179 va_start (args, format);
180 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG, format, args);
181 va_end (args);
182 }
183}
184
185
186//----------------------------------------------------------------------
187// Print debug strings if and only if the global debug option is set to
188// a non-zero value.
189//----------------------------------------------------------------------
190void
191Log::DebugVerbose (const char *format, ...)
192{
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000193 if (GetOptions().AllSet (LLDB_LOG_OPTION_DEBUG | LLDB_LOG_OPTION_VERBOSE))
Chris Lattner24943d22010-06-08 16:52:24 +0000194 {
195 va_list args;
196 va_start (args, format);
197 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG | LLDB_LOG_FLAG_VERBOSE, format, args);
198 va_end (args);
199 }
200}
201
202
203//----------------------------------------------------------------------
204// Log only if all of the bits are set
205//----------------------------------------------------------------------
206void
207Log::LogIf (uint32_t bits, const char *format, ...)
208{
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000209 if (m_options.AllSet (bits))
Chris Lattner24943d22010-06-08 16:52:24 +0000210 {
211 va_list args;
212 va_start (args, format);
213 PrintfWithFlagsVarArg (0, format, args);
214 va_end (args);
215 }
216}
217
218
219//----------------------------------------------------------------------
220// Printing of errors that are not fatal.
221//----------------------------------------------------------------------
222void
223Log::Error (const char *format, ...)
224{
225 char *arg_msg = NULL;
226 va_list args;
227 va_start (args, format);
228 ::vasprintf (&arg_msg, format, args);
229 va_end (args);
230
231 if (arg_msg != NULL)
232 {
233 PrintfWithFlags (LLDB_LOG_FLAG_ERROR, "error: %s", arg_msg);
234 free (arg_msg);
235 }
236}
237
238//----------------------------------------------------------------------
239// Printing of errors that ARE fatal. Exit with ERR exit code
240// immediately.
241//----------------------------------------------------------------------
242void
243Log::FatalError (int err, const char *format, ...)
244{
245 char *arg_msg = NULL;
246 va_list args;
247 va_start (args, format);
248 ::vasprintf (&arg_msg, format, args);
249 va_end (args);
250
251 if (arg_msg != NULL)
252 {
253 PrintfWithFlags (LLDB_LOG_FLAG_ERROR | LLDB_LOG_FLAG_FATAL, "error: %s", arg_msg);
254 ::free (arg_msg);
255 }
256 ::exit (err);
257}
258
259
260//----------------------------------------------------------------------
261// Printing of warnings that are not fatal only if verbose mode is
262// enabled.
263//----------------------------------------------------------------------
264void
265Log::Verbose (const char *format, ...)
266{
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000267 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
Chris Lattner24943d22010-06-08 16:52:24 +0000268 {
269 va_list args;
270 va_start (args, format);
271 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_VERBOSE, format, args);
272 va_end (args);
273 }
274}
275
276//----------------------------------------------------------------------
277// Printing of warnings that are not fatal only if verbose mode is
278// enabled.
279//----------------------------------------------------------------------
280void
281Log::WarningVerbose (const char *format, ...)
282{
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000283 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
Chris Lattner24943d22010-06-08 16:52:24 +0000284 {
285 char *arg_msg = NULL;
286 va_list args;
287 va_start (args, format);
288 ::vasprintf (&arg_msg, format, args);
289 va_end (args);
290
291 if (arg_msg != NULL)
292 {
293 PrintfWithFlags (LLDB_LOG_FLAG_WARNING | LLDB_LOG_FLAG_VERBOSE, "warning: %s", arg_msg);
294 free (arg_msg);
295 }
296 }
297}
298//----------------------------------------------------------------------
299// Printing of warnings that are not fatal.
300//----------------------------------------------------------------------
301void
302Log::Warning (const char *format, ...)
303{
304 char *arg_msg = NULL;
305 va_list args;
306 va_start (args, format);
307 ::vasprintf (&arg_msg, format, args);
308 va_end (args);
309
310 if (arg_msg != NULL)
311 {
312 PrintfWithFlags (LLDB_LOG_FLAG_WARNING, "warning: %s", arg_msg);
313 free (arg_msg);
314 }
315}
316
317typedef std::map <std::string, Log::Callbacks> CallbackMap;
318typedef CallbackMap::iterator CallbackMapIter;
319
320typedef std::map <ConstString, LogChannelSP> LogChannelMap;
321typedef LogChannelMap::iterator LogChannelMapIter;
322
323
324// Surround our callback map with a singleton function so we don't have any
325// global initializers.
326static CallbackMap &
327GetCallbackMap ()
328{
329 static CallbackMap g_callback_map;
330 return g_callback_map;
331}
332
333static LogChannelMap &
334GetChannelMap ()
335{
336 static LogChannelMap g_channel_map;
337 return g_channel_map;
338}
339
340void
341Log::RegisterLogChannel (const char *channel, const Log::Callbacks &log_callbacks)
342{
343 GetCallbackMap().insert(std::make_pair(channel, log_callbacks));
344}
345
346bool
347Log::UnregisterLogChannel (const char *channel)
348{
349 return GetCallbackMap().erase(channel) != 0;
350}
351
352bool
353Log::GetLogChannelCallbacks (const char *channel, Log::Callbacks &log_callbacks)
354{
355 CallbackMap &callback_map = GetCallbackMap ();
356 CallbackMapIter pos = callback_map.find(channel);
357 if (pos != callback_map.end())
358 {
359 log_callbacks = pos->second;
360 return true;
361 }
Greg Claytonddff7cc2011-02-04 21:13:05 +0000362 ::memset (&log_callbacks, 0, sizeof(log_callbacks));
Chris Lattner24943d22010-06-08 16:52:24 +0000363 return false;
364}
365
366void
367Log::EnableAllLogChannels
368(
369 StreamSP &log_stream_sp,
370 uint32_t log_options,
Jim Ingham6c530f22012-02-21 02:23:08 +0000371 const char **categories,
Chris Lattner24943d22010-06-08 16:52:24 +0000372 Stream *feedback_strm
373)
374{
375 CallbackMap &callback_map = GetCallbackMap ();
376 CallbackMapIter pos, end = callback_map.end();
377
378 for (pos = callback_map.begin(); pos != end; ++pos)
Jim Ingham6c530f22012-02-21 02:23:08 +0000379 pos->second.enable (log_stream_sp, log_options, categories, feedback_strm);
Chris Lattner24943d22010-06-08 16:52:24 +0000380
381 LogChannelMap &channel_map = GetChannelMap ();
382 LogChannelMapIter channel_pos, channel_end = channel_map.end();
383 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
384 {
Jim Ingham6c530f22012-02-21 02:23:08 +0000385 channel_pos->second->Enable (log_stream_sp, log_options, feedback_strm, categories);
Chris Lattner24943d22010-06-08 16:52:24 +0000386 }
387
388}
389
390void
Greg Clayton5e342f52011-04-13 22:47:15 +0000391Log::AutoCompleteChannelName (const char *channel_name, StringList &matches)
392{
393 LogChannelMap &map = GetChannelMap ();
394 LogChannelMapIter pos, end = map.end();
395 for (pos = map.begin(); pos != end; ++pos)
396 {
397 const char *pos_channel_name = pos->first.GetCString();
398 if (channel_name && channel_name[0])
399 {
400 if (NameMatches (channel_name, eNameMatchStartsWith, pos_channel_name))
401 {
402 matches.AppendString(pos_channel_name);
403 }
404 }
405 else
406 matches.AppendString(pos_channel_name);
407
408 }
409}
410
411void
Caroline Tice926060e2010-10-29 21:48:37 +0000412Log::DisableAllLogChannels (Stream *feedback_strm)
Chris Lattner24943d22010-06-08 16:52:24 +0000413{
414 CallbackMap &callback_map = GetCallbackMap ();
415 CallbackMapIter pos, end = callback_map.end();
Jim Ingham6c530f22012-02-21 02:23:08 +0000416 const char *categories[1] = {NULL};
Chris Lattner24943d22010-06-08 16:52:24 +0000417
418 for (pos = callback_map.begin(); pos != end; ++pos)
Jim Ingham6c530f22012-02-21 02:23:08 +0000419 pos->second.disable (categories, feedback_strm);
Chris Lattner24943d22010-06-08 16:52:24 +0000420
421 LogChannelMap &channel_map = GetChannelMap ();
422 LogChannelMapIter channel_pos, channel_end = channel_map.end();
423 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
Jim Ingham6c530f22012-02-21 02:23:08 +0000424 channel_pos->second->Disable (categories, feedback_strm);
Chris Lattner24943d22010-06-08 16:52:24 +0000425}
426
427void
Greg Clayton990de7b2010-11-18 23:32:35 +0000428Log::Initialize()
429{
430 Log::Callbacks log_callbacks = { DisableLog, EnableLog, ListLogCategories };
431 Log::RegisterLogChannel ("lldb", log_callbacks);
432}
433
434void
435Log::Terminate ()
436{
437 DisableAllLogChannels (NULL);
438}
439
440void
Chris Lattner24943d22010-06-08 16:52:24 +0000441Log::ListAllLogChannels (Stream *strm)
442{
443 CallbackMap &callback_map = GetCallbackMap ();
444 LogChannelMap &channel_map = GetChannelMap ();
445
446 if (callback_map.empty() && channel_map.empty())
447 {
448 strm->PutCString ("No logging channels are currently registered.\n");
449 return;
450 }
451
452 CallbackMapIter pos, end = callback_map.end();
453 for (pos = callback_map.begin(); pos != end; ++pos)
454 pos->second.list_categories (strm);
455
456 uint32_t idx = 0;
457 const char *name;
458 for (idx = 0; (name = PluginManager::GetLogChannelCreateNameAtIndex (idx)) != NULL; ++idx)
459 {
460 LogChannelSP log_channel_sp(LogChannel::FindPlugin (name));
461 if (log_channel_sp)
462 log_channel_sp->ListCategories (strm);
463 }
464}
465
466bool
467Log::GetVerbose() const
468{
Jim Ingham931851c2011-01-22 01:24:30 +0000469 // FIXME: This has to be centralized between the stream and the log...
470 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
471 return true;
472
Chris Lattner24943d22010-06-08 16:52:24 +0000473 if (m_stream_sp)
474 return m_stream_sp->GetVerbose();
475 return false;
476}
477
478//------------------------------------------------------------------
479// Returns true if the debug flag bit is set in this stream.
480//------------------------------------------------------------------
481bool
482Log::GetDebug() const
483{
484 if (m_stream_sp)
485 return m_stream_sp->GetDebug();
486 return false;
487}
488
489
490LogChannelSP
491LogChannel::FindPlugin (const char *plugin_name)
492{
493 LogChannelSP log_channel_sp;
494 LogChannelMap &channel_map = GetChannelMap ();
495 ConstString log_channel_name (plugin_name);
496 LogChannelMapIter pos = channel_map.find (log_channel_name);
497 if (pos == channel_map.end())
498 {
499 LogChannelCreateInstance create_callback = PluginManager::GetLogChannelCreateCallbackForPluginName (plugin_name);
500 if (create_callback)
501 {
502 log_channel_sp.reset(create_callback());
503 if (log_channel_sp)
504 {
505 // Cache the one and only loaded instance of each log channel
506 // plug-in after it has been loaded once.
507 channel_map[log_channel_name] = log_channel_sp;
508 }
509 }
510 }
511 else
512 {
513 // We have already loaded an instance of this log channel class,
514 // so just return the cached instance.
515 log_channel_sp = pos->second;
516 }
517 return log_channel_sp;
518}
519
520LogChannel::LogChannel () :
521 m_log_sp ()
522{
523}
524
525LogChannel::~LogChannel ()
526{
527}
528
Chris Lattner24943d22010-06-08 16:52:24 +0000529