blob: 49bd653d14ee06bdc30e43d697668bc1d42f4be0 [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);
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000119
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120 }
121
122 header.PrintfVarArg (format, args);
123 m_stream_sp->Printf("%s\n", header.GetData());
124 }
125}
126
127
128void
129Log::PutCString (const char *cstr)
130{
131 Printf ("%s", cstr);
132}
133
134
135//----------------------------------------------------------------------
136// Simple variable argument logging with flags.
137//----------------------------------------------------------------------
138void
139Log::Printf(const char *format, ...)
140{
141 va_list args;
142 va_start (args, format);
143 PrintfWithFlagsVarArg (0, format, args);
144 va_end (args);
145}
146
147void
148Log::VAPrintf (const char *format, va_list args)
149{
150 PrintfWithFlagsVarArg (0, format, args);
151}
152
153
154//----------------------------------------------------------------------
155// Simple variable argument logging with flags.
156//----------------------------------------------------------------------
157void
158Log::PrintfWithFlags (uint32_t flags, const char *format, ...)
159{
160 va_list args;
161 va_start (args, format);
162 PrintfWithFlagsVarArg (flags, format, args);
163 va_end (args);
164}
165
166//----------------------------------------------------------------------
167// Print debug strings if and only if the global debug option is set to
168// a non-zero value.
169//----------------------------------------------------------------------
170void
171Log::Debug (const char *format, ...)
172{
Greg Clayton73b472d2010-10-27 03:32:59 +0000173 if (GetOptions().Test(LLDB_LOG_OPTION_DEBUG))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000174 {
175 va_list args;
176 va_start (args, format);
177 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG, format, args);
178 va_end (args);
179 }
180}
181
182
183//----------------------------------------------------------------------
184// Print debug strings if and only if the global debug option is set to
185// a non-zero value.
186//----------------------------------------------------------------------
187void
188Log::DebugVerbose (const char *format, ...)
189{
Greg Clayton73b472d2010-10-27 03:32:59 +0000190 if (GetOptions().AllSet (LLDB_LOG_OPTION_DEBUG | LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000191 {
192 va_list args;
193 va_start (args, format);
194 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG | LLDB_LOG_FLAG_VERBOSE, format, args);
195 va_end (args);
196 }
197}
198
199
200//----------------------------------------------------------------------
201// Log only if all of the bits are set
202//----------------------------------------------------------------------
203void
204Log::LogIf (uint32_t bits, const char *format, ...)
205{
Greg Clayton73b472d2010-10-27 03:32:59 +0000206 if (m_options.AllSet (bits))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000207 {
208 va_list args;
209 va_start (args, format);
210 PrintfWithFlagsVarArg (0, format, args);
211 va_end (args);
212 }
213}
214
215
216//----------------------------------------------------------------------
217// Printing of errors that are not fatal.
218//----------------------------------------------------------------------
219void
220Log::Error (const char *format, ...)
221{
222 char *arg_msg = NULL;
223 va_list args;
224 va_start (args, format);
225 ::vasprintf (&arg_msg, format, args);
226 va_end (args);
227
228 if (arg_msg != NULL)
229 {
230 PrintfWithFlags (LLDB_LOG_FLAG_ERROR, "error: %s", arg_msg);
231 free (arg_msg);
232 }
233}
234
235//----------------------------------------------------------------------
236// Printing of errors that ARE fatal. Exit with ERR exit code
237// immediately.
238//----------------------------------------------------------------------
239void
240Log::FatalError (int err, const char *format, ...)
241{
242 char *arg_msg = NULL;
243 va_list args;
244 va_start (args, format);
245 ::vasprintf (&arg_msg, format, args);
246 va_end (args);
247
248 if (arg_msg != NULL)
249 {
250 PrintfWithFlags (LLDB_LOG_FLAG_ERROR | LLDB_LOG_FLAG_FATAL, "error: %s", arg_msg);
251 ::free (arg_msg);
252 }
253 ::exit (err);
254}
255
256
257//----------------------------------------------------------------------
258// Printing of warnings that are not fatal only if verbose mode is
259// enabled.
260//----------------------------------------------------------------------
261void
262Log::Verbose (const char *format, ...)
263{
Greg Clayton73b472d2010-10-27 03:32:59 +0000264 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000265 {
266 va_list args;
267 va_start (args, format);
268 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_VERBOSE, format, args);
269 va_end (args);
270 }
271}
272
273//----------------------------------------------------------------------
274// Printing of warnings that are not fatal only if verbose mode is
275// enabled.
276//----------------------------------------------------------------------
277void
278Log::WarningVerbose (const char *format, ...)
279{
Greg Clayton73b472d2010-10-27 03:32:59 +0000280 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000281 {
282 char *arg_msg = NULL;
283 va_list args;
284 va_start (args, format);
285 ::vasprintf (&arg_msg, format, args);
286 va_end (args);
287
288 if (arg_msg != NULL)
289 {
290 PrintfWithFlags (LLDB_LOG_FLAG_WARNING | LLDB_LOG_FLAG_VERBOSE, "warning: %s", arg_msg);
291 free (arg_msg);
292 }
293 }
294}
295//----------------------------------------------------------------------
296// Printing of warnings that are not fatal.
297//----------------------------------------------------------------------
298void
299Log::Warning (const char *format, ...)
300{
301 char *arg_msg = NULL;
302 va_list args;
303 va_start (args, format);
304 ::vasprintf (&arg_msg, format, args);
305 va_end (args);
306
307 if (arg_msg != NULL)
308 {
309 PrintfWithFlags (LLDB_LOG_FLAG_WARNING, "warning: %s", arg_msg);
310 free (arg_msg);
311 }
312}
313
314typedef std::map <std::string, Log::Callbacks> CallbackMap;
315typedef CallbackMap::iterator CallbackMapIter;
316
317typedef std::map <ConstString, LogChannelSP> LogChannelMap;
318typedef LogChannelMap::iterator LogChannelMapIter;
319
320
321// Surround our callback map with a singleton function so we don't have any
322// global initializers.
323static CallbackMap &
324GetCallbackMap ()
325{
326 static CallbackMap g_callback_map;
327 return g_callback_map;
328}
329
330static LogChannelMap &
331GetChannelMap ()
332{
333 static LogChannelMap g_channel_map;
334 return g_channel_map;
335}
336
337void
338Log::RegisterLogChannel (const char *channel, const Log::Callbacks &log_callbacks)
339{
340 GetCallbackMap().insert(std::make_pair(channel, log_callbacks));
341}
342
343bool
344Log::UnregisterLogChannel (const char *channel)
345{
346 return GetCallbackMap().erase(channel) != 0;
347}
348
349bool
350Log::GetLogChannelCallbacks (const char *channel, Log::Callbacks &log_callbacks)
351{
352 CallbackMap &callback_map = GetCallbackMap ();
353 CallbackMapIter pos = callback_map.find(channel);
354 if (pos != callback_map.end())
355 {
356 log_callbacks = pos->second;
357 return true;
358 }
Greg Clayton72b77eb2011-02-04 21:13:05 +0000359 ::memset (&log_callbacks, 0, sizeof(log_callbacks));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000360 return false;
361}
362
363void
364Log::EnableAllLogChannels
365(
366 StreamSP &log_stream_sp,
367 uint32_t log_options,
368 Args &args,
369 Stream *feedback_strm
370)
371{
372 CallbackMap &callback_map = GetCallbackMap ();
373 CallbackMapIter pos, end = callback_map.end();
374
375 for (pos = callback_map.begin(); pos != end; ++pos)
376 pos->second.enable (log_stream_sp, log_options, args, feedback_strm);
377
378 LogChannelMap &channel_map = GetChannelMap ();
379 LogChannelMapIter channel_pos, channel_end = channel_map.end();
380 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
381 {
382 channel_pos->second->Enable (log_stream_sp, log_options, feedback_strm, args);
383 }
384
385}
386
387void
Caroline Tice20ad3c42010-10-29 21:48:37 +0000388Log::DisableAllLogChannels (Stream *feedback_strm)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000389{
390 CallbackMap &callback_map = GetCallbackMap ();
391 CallbackMapIter pos, end = callback_map.end();
Greg Clayton99d0faf2010-11-18 23:32:35 +0000392 Args args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000393
394 for (pos = callback_map.begin(); pos != end; ++pos)
Caroline Tice20ad3c42010-10-29 21:48:37 +0000395 pos->second.disable (args, feedback_strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000396
397 LogChannelMap &channel_map = GetChannelMap ();
398 LogChannelMapIter channel_pos, channel_end = channel_map.end();
399 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
Caroline Tice20ad3c42010-10-29 21:48:37 +0000400 channel_pos->second->Disable (args, feedback_strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000401}
402
403void
Greg Clayton99d0faf2010-11-18 23:32:35 +0000404Log::Initialize()
405{
406 Log::Callbacks log_callbacks = { DisableLog, EnableLog, ListLogCategories };
407 Log::RegisterLogChannel ("lldb", log_callbacks);
408}
409
410void
411Log::Terminate ()
412{
413 DisableAllLogChannels (NULL);
414}
415
416void
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000417Log::ListAllLogChannels (Stream *strm)
418{
419 CallbackMap &callback_map = GetCallbackMap ();
420 LogChannelMap &channel_map = GetChannelMap ();
421
422 if (callback_map.empty() && channel_map.empty())
423 {
424 strm->PutCString ("No logging channels are currently registered.\n");
425 return;
426 }
427
428 CallbackMapIter pos, end = callback_map.end();
429 for (pos = callback_map.begin(); pos != end; ++pos)
430 pos->second.list_categories (strm);
431
432 uint32_t idx = 0;
433 const char *name;
434 for (idx = 0; (name = PluginManager::GetLogChannelCreateNameAtIndex (idx)) != NULL; ++idx)
435 {
436 LogChannelSP log_channel_sp(LogChannel::FindPlugin (name));
437 if (log_channel_sp)
438 log_channel_sp->ListCategories (strm);
439 }
440}
441
442bool
443Log::GetVerbose() const
444{
Jim Inghamd8d148e2011-01-22 01:24:30 +0000445 // FIXME: This has to be centralized between the stream and the log...
446 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
447 return true;
448
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000449 if (m_stream_sp)
450 return m_stream_sp->GetVerbose();
451 return false;
452}
453
454//------------------------------------------------------------------
455// Returns true if the debug flag bit is set in this stream.
456//------------------------------------------------------------------
457bool
458Log::GetDebug() const
459{
460 if (m_stream_sp)
461 return m_stream_sp->GetDebug();
462 return false;
463}
464
465
466LogChannelSP
467LogChannel::FindPlugin (const char *plugin_name)
468{
469 LogChannelSP log_channel_sp;
470 LogChannelMap &channel_map = GetChannelMap ();
471 ConstString log_channel_name (plugin_name);
472 LogChannelMapIter pos = channel_map.find (log_channel_name);
473 if (pos == channel_map.end())
474 {
475 LogChannelCreateInstance create_callback = PluginManager::GetLogChannelCreateCallbackForPluginName (plugin_name);
476 if (create_callback)
477 {
478 log_channel_sp.reset(create_callback());
479 if (log_channel_sp)
480 {
481 // Cache the one and only loaded instance of each log channel
482 // plug-in after it has been loaded once.
483 channel_map[log_channel_name] = log_channel_sp;
484 }
485 }
486 }
487 else
488 {
489 // We have already loaded an instance of this log channel class,
490 // so just return the cached instance.
491 log_channel_sp = pos->second;
492 }
493 return log_channel_sp;
494}
495
496LogChannel::LogChannel () :
497 m_log_sp ()
498{
499}
500
501LogChannel::~LogChannel ()
502{
503}
504
505const char *
506LogChannel::GetPluginSuffix ()
507{
508 return ".log-channel";
509}
510
511