blob: 16063e483af5744152da71f0f89ac53131a9ce5d [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 <pthread.h>
12#include <stdio.h>
13#include <stdarg.h>
14#include <stdlib.h>
15#include <unistd.h>
16
17// C++ Includes
18#include <map>
19#include <string>
20
21// Other libraries and framework includes
22// Project includes
23#include "lldb/Core/Debugger.h"
24#include "lldb/Core/Log.h"
25#include "lldb/Core/PluginManager.h"
26#include "lldb/Core/StreamFile.h"
27#include "lldb/Core/StreamString.h"
28#include "lldb/Host/Host.h"
29#include "lldb/Host/TimeValue.h"
30#include "lldb/Host/Mutex.h"
Caroline Tice20ad3c42010-10-29 21:48:37 +000031#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000032using namespace lldb;
33using namespace lldb_private;
34
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035Log::Log () :
36 m_stream_sp(),
37 m_options(0),
38 m_mask_bits(0)
39{
40}
41
42Log::Log (StreamSP &stream_sp) :
43 m_stream_sp(stream_sp),
44 m_options(0),
45 m_mask_bits(0)
46{
47}
48
49Log::~Log ()
50{
51}
52
53Flags &
54Log::GetOptions()
55{
56 return m_options;
57}
58
59const Flags &
60Log::GetOptions() const
61{
62 return m_options;
63}
64
65Flags &
66Log::GetMask()
67{
68 return m_mask_bits;
69}
70
71const Flags &
72Log::GetMask() const
73{
74 return m_mask_bits;
75}
76
77
78//----------------------------------------------------------------------
79// All logging eventually boils down to this function call. If we have
80// a callback registered, then we call the logging callback. If we have
81// a valid file handle, we also log to the file.
82//----------------------------------------------------------------------
83void
84Log::PrintfWithFlagsVarArg (uint32_t flags, const char *format, va_list args)
85{
86 if (m_stream_sp)
87 {
88 static uint32_t g_sequence_id = 0;
89 StreamString header;
90 static Mutex g_LogThreadedMutex(Mutex::eMutexTypeRecursive);
91
92 Mutex::Locker locker;
93
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094 // Lock the threaded logging mutex if we are doing thread safe logging
Greg Clayton73b472d2010-10-27 03:32:59 +000095 if (m_options.Test (LLDB_LOG_OPTION_THREADSAFE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096 locker.Reset(g_LogThreadedMutex.GetMutex());
97
98 // Add a sequence ID if requested
Greg Clayton73b472d2010-10-27 03:32:59 +000099 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_SEQUENCE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100 header.Printf ("%u ", ++g_sequence_id);
101
102 // Timestamp if requested
Greg Clayton73b472d2010-10-27 03:32:59 +0000103 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_TIMESTAMP))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104 {
105 struct timeval tv = TimeValue::Now().GetAsTimeVal();
106 header.Printf ("%9llu.%6.6llu ", tv.tv_sec, tv.tv_usec);
107 }
108
109 // Add the process and thread if requested
Greg Clayton73b472d2010-10-27 03:32:59 +0000110 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD))
Eli Friedmane01b70b2010-06-11 04:29:29 +0000111 header.Printf ("[%4.4x/%4.4x]: ", getpid(), Host::GetCurrentThreadID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112
113 // Add the process and thread if requested
Greg Clayton73b472d2010-10-27 03:32:59 +0000114 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_THREAD_NAME))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000115 {
Eli Friedmane01b70b2010-06-11 04:29:29 +0000116 const char *thread_name_str = Host::GetThreadName (getpid(), Host::GetCurrentThreadID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117 if (thread_name_str)
118 header.Printf ("%s ", thread_name_str);
119 }
120
121 header.PrintfVarArg (format, args);
122 m_stream_sp->Printf("%s\n", header.GetData());
123 }
124}
125
126
127void
128Log::PutCString (const char *cstr)
129{
130 Printf ("%s", cstr);
131}
132
133
134//----------------------------------------------------------------------
135// Simple variable argument logging with flags.
136//----------------------------------------------------------------------
137void
138Log::Printf(const char *format, ...)
139{
140 va_list args;
141 va_start (args, format);
142 PrintfWithFlagsVarArg (0, format, args);
143 va_end (args);
144}
145
146void
147Log::VAPrintf (const char *format, va_list args)
148{
149 PrintfWithFlagsVarArg (0, format, args);
150}
151
152
153//----------------------------------------------------------------------
154// Simple variable argument logging with flags.
155//----------------------------------------------------------------------
156void
157Log::PrintfWithFlags (uint32_t flags, const char *format, ...)
158{
159 va_list args;
160 va_start (args, format);
161 PrintfWithFlagsVarArg (flags, format, args);
162 va_end (args);
163}
164
165//----------------------------------------------------------------------
166// Print debug strings if and only if the global debug option is set to
167// a non-zero value.
168//----------------------------------------------------------------------
169void
170Log::Debug (const char *format, ...)
171{
Greg Clayton73b472d2010-10-27 03:32:59 +0000172 if (GetOptions().Test(LLDB_LOG_OPTION_DEBUG))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173 {
174 va_list args;
175 va_start (args, format);
176 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG, format, args);
177 va_end (args);
178 }
179}
180
181
182//----------------------------------------------------------------------
183// Print debug strings if and only if the global debug option is set to
184// a non-zero value.
185//----------------------------------------------------------------------
186void
187Log::DebugVerbose (const char *format, ...)
188{
Greg Clayton73b472d2010-10-27 03:32:59 +0000189 if (GetOptions().AllSet (LLDB_LOG_OPTION_DEBUG | LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000190 {
191 va_list args;
192 va_start (args, format);
193 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG | LLDB_LOG_FLAG_VERBOSE, format, args);
194 va_end (args);
195 }
196}
197
198
199//----------------------------------------------------------------------
200// Log only if all of the bits are set
201//----------------------------------------------------------------------
202void
203Log::LogIf (uint32_t bits, const char *format, ...)
204{
Greg Clayton73b472d2010-10-27 03:32:59 +0000205 if (m_options.AllSet (bits))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000206 {
207 va_list args;
208 va_start (args, format);
209 PrintfWithFlagsVarArg (0, format, args);
210 va_end (args);
211 }
212}
213
214
215//----------------------------------------------------------------------
216// Printing of errors that are not fatal.
217//----------------------------------------------------------------------
218void
219Log::Error (const char *format, ...)
220{
221 char *arg_msg = NULL;
222 va_list args;
223 va_start (args, format);
224 ::vasprintf (&arg_msg, format, args);
225 va_end (args);
226
227 if (arg_msg != NULL)
228 {
229 PrintfWithFlags (LLDB_LOG_FLAG_ERROR, "error: %s", arg_msg);
230 free (arg_msg);
231 }
232}
233
234//----------------------------------------------------------------------
235// Printing of errors that ARE fatal. Exit with ERR exit code
236// immediately.
237//----------------------------------------------------------------------
238void
239Log::FatalError (int err, const char *format, ...)
240{
241 char *arg_msg = NULL;
242 va_list args;
243 va_start (args, format);
244 ::vasprintf (&arg_msg, format, args);
245 va_end (args);
246
247 if (arg_msg != NULL)
248 {
249 PrintfWithFlags (LLDB_LOG_FLAG_ERROR | LLDB_LOG_FLAG_FATAL, "error: %s", arg_msg);
250 ::free (arg_msg);
251 }
252 ::exit (err);
253}
254
255
256//----------------------------------------------------------------------
257// Printing of warnings that are not fatal only if verbose mode is
258// enabled.
259//----------------------------------------------------------------------
260void
261Log::Verbose (const char *format, ...)
262{
Greg Clayton73b472d2010-10-27 03:32:59 +0000263 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000264 {
265 va_list args;
266 va_start (args, format);
267 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_VERBOSE, format, args);
268 va_end (args);
269 }
270}
271
272//----------------------------------------------------------------------
273// Printing of warnings that are not fatal only if verbose mode is
274// enabled.
275//----------------------------------------------------------------------
276void
277Log::WarningVerbose (const char *format, ...)
278{
Greg Clayton73b472d2010-10-27 03:32:59 +0000279 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000280 {
281 char *arg_msg = NULL;
282 va_list args;
283 va_start (args, format);
284 ::vasprintf (&arg_msg, format, args);
285 va_end (args);
286
287 if (arg_msg != NULL)
288 {
289 PrintfWithFlags (LLDB_LOG_FLAG_WARNING | LLDB_LOG_FLAG_VERBOSE, "warning: %s", arg_msg);
290 free (arg_msg);
291 }
292 }
293}
294//----------------------------------------------------------------------
295// Printing of warnings that are not fatal.
296//----------------------------------------------------------------------
297void
298Log::Warning (const char *format, ...)
299{
300 char *arg_msg = NULL;
301 va_list args;
302 va_start (args, format);
303 ::vasprintf (&arg_msg, format, args);
304 va_end (args);
305
306 if (arg_msg != NULL)
307 {
308 PrintfWithFlags (LLDB_LOG_FLAG_WARNING, "warning: %s", arg_msg);
309 free (arg_msg);
310 }
311}
312
313typedef std::map <std::string, Log::Callbacks> CallbackMap;
314typedef CallbackMap::iterator CallbackMapIter;
315
316typedef std::map <ConstString, LogChannelSP> LogChannelMap;
317typedef LogChannelMap::iterator LogChannelMapIter;
318
319
320// Surround our callback map with a singleton function so we don't have any
321// global initializers.
322static CallbackMap &
323GetCallbackMap ()
324{
325 static CallbackMap g_callback_map;
326 return g_callback_map;
327}
328
329static LogChannelMap &
330GetChannelMap ()
331{
332 static LogChannelMap g_channel_map;
333 return g_channel_map;
334}
335
336void
337Log::RegisterLogChannel (const char *channel, const Log::Callbacks &log_callbacks)
338{
339 GetCallbackMap().insert(std::make_pair(channel, log_callbacks));
340}
341
342bool
343Log::UnregisterLogChannel (const char *channel)
344{
345 return GetCallbackMap().erase(channel) != 0;
346}
347
348bool
349Log::GetLogChannelCallbacks (const char *channel, Log::Callbacks &log_callbacks)
350{
351 CallbackMap &callback_map = GetCallbackMap ();
352 CallbackMapIter pos = callback_map.find(channel);
353 if (pos != callback_map.end())
354 {
355 log_callbacks = pos->second;
356 return true;
357 }
358 ::bzero (&log_callbacks, sizeof(log_callbacks));
359 return false;
360}
361
362void
363Log::EnableAllLogChannels
364(
365 StreamSP &log_stream_sp,
366 uint32_t log_options,
367 Args &args,
368 Stream *feedback_strm
369)
370{
371 CallbackMap &callback_map = GetCallbackMap ();
372 CallbackMapIter pos, end = callback_map.end();
373
374 for (pos = callback_map.begin(); pos != end; ++pos)
375 pos->second.enable (log_stream_sp, log_options, args, feedback_strm);
376
377 LogChannelMap &channel_map = GetChannelMap ();
378 LogChannelMapIter channel_pos, channel_end = channel_map.end();
379 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
380 {
381 channel_pos->second->Enable (log_stream_sp, log_options, feedback_strm, args);
382 }
383
384}
385
386void
Caroline Tice20ad3c42010-10-29 21:48:37 +0000387Log::DisableAllLogChannels (Stream *feedback_strm)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388{
389 CallbackMap &callback_map = GetCallbackMap ();
390 CallbackMapIter pos, end = callback_map.end();
Caroline Tice20ad3c42010-10-29 21:48:37 +0000391 Args args ("all");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392
393 for (pos = callback_map.begin(); pos != end; ++pos)
Caroline Tice20ad3c42010-10-29 21:48:37 +0000394 pos->second.disable (args, feedback_strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000395
396 LogChannelMap &channel_map = GetChannelMap ();
397 LogChannelMapIter channel_pos, channel_end = channel_map.end();
398 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
Caroline Tice20ad3c42010-10-29 21:48:37 +0000399 channel_pos->second->Disable (args, feedback_strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000400}
401
402void
403Log::ListAllLogChannels (Stream *strm)
404{
405 CallbackMap &callback_map = GetCallbackMap ();
406 LogChannelMap &channel_map = GetChannelMap ();
407
408 if (callback_map.empty() && channel_map.empty())
409 {
410 strm->PutCString ("No logging channels are currently registered.\n");
411 return;
412 }
413
414 CallbackMapIter pos, end = callback_map.end();
415 for (pos = callback_map.begin(); pos != end; ++pos)
416 pos->second.list_categories (strm);
417
418 uint32_t idx = 0;
419 const char *name;
420 for (idx = 0; (name = PluginManager::GetLogChannelCreateNameAtIndex (idx)) != NULL; ++idx)
421 {
422 LogChannelSP log_channel_sp(LogChannel::FindPlugin (name));
423 if (log_channel_sp)
424 log_channel_sp->ListCategories (strm);
425 }
426}
427
428bool
429Log::GetVerbose() const
430{
431 if (m_stream_sp)
432 return m_stream_sp->GetVerbose();
433 return false;
434}
435
436//------------------------------------------------------------------
437// Returns true if the debug flag bit is set in this stream.
438//------------------------------------------------------------------
439bool
440Log::GetDebug() const
441{
442 if (m_stream_sp)
443 return m_stream_sp->GetDebug();
444 return false;
445}
446
447
448LogChannelSP
449LogChannel::FindPlugin (const char *plugin_name)
450{
451 LogChannelSP log_channel_sp;
452 LogChannelMap &channel_map = GetChannelMap ();
453 ConstString log_channel_name (plugin_name);
454 LogChannelMapIter pos = channel_map.find (log_channel_name);
455 if (pos == channel_map.end())
456 {
457 LogChannelCreateInstance create_callback = PluginManager::GetLogChannelCreateCallbackForPluginName (plugin_name);
458 if (create_callback)
459 {
460 log_channel_sp.reset(create_callback());
461 if (log_channel_sp)
462 {
463 // Cache the one and only loaded instance of each log channel
464 // plug-in after it has been loaded once.
465 channel_map[log_channel_name] = log_channel_sp;
466 }
467 }
468 }
469 else
470 {
471 // We have already loaded an instance of this log channel class,
472 // so just return the cached instance.
473 log_channel_sp = pos->second;
474 }
475 return log_channel_sp;
476}
477
478LogChannel::LogChannel () :
479 m_log_sp ()
480{
481}
482
483LogChannel::~LogChannel ()
484{
485}
486
487const char *
488LogChannel::GetPluginSuffix ()
489{
490 return ".log-channel";
491}
492
493