blob: 0b163fb04f54082ddd16ec1c356c7d7dfe34aa33 [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;
Greg Clayton64195a22011-02-23 00:35:02 +000090 // Enabling the thread safe logging actually deadlocks right now.
91 // Need to fix this at some point.
92// static Mutex g_LogThreadedMutex(Mutex::eMutexTypeRecursive);
93// Mutex::Locker locker (g_LogThreadedMutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094
95 // Add a sequence ID if requested
Greg Clayton73b472d2010-10-27 03:32:59 +000096 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_SEQUENCE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +000097 header.Printf ("%u ", ++g_sequence_id);
98
99 // Timestamp if requested
Greg Clayton73b472d2010-10-27 03:32:59 +0000100 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_TIMESTAMP))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101 {
102 struct timeval tv = TimeValue::Now().GetAsTimeVal();
Jason Molendafd54b362011-09-20 21:44:10 +0000103 header.Printf ("%9ld.%6.6d ", tv.tv_sec, tv.tv_usec);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104 }
105
106 // Add the process and thread if requested
Greg Clayton73b472d2010-10-27 03:32:59 +0000107 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD))
Greg Clayton61e7a582011-12-01 23:28:38 +0000108 header.Printf ("[%4.4x/%4.4llx]: ", getpid(), Host::GetCurrentThreadID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109
110 // Add the process and thread if requested
Greg Clayton73b472d2010-10-27 03:32:59 +0000111 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_THREAD_NAME))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112 {
Eli Friedmane01b70b2010-06-11 04:29:29 +0000113 const char *thread_name_str = Host::GetThreadName (getpid(), Host::GetCurrentThreadID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114 if (thread_name_str)
115 header.Printf ("%s ", thread_name_str);
Greg Claytoncfd1ace2010-10-31 03:01:06 +0000116
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117 }
118
119 header.PrintfVarArg (format, args);
120 m_stream_sp->Printf("%s\n", header.GetData());
Jim Ingham228063c2012-02-21 02:23:08 +0000121 m_stream_sp->Flush();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000122 }
123}
124
125
126void
127Log::PutCString (const char *cstr)
128{
129 Printf ("%s", cstr);
130}
131
132
133//----------------------------------------------------------------------
134// Simple variable argument logging with flags.
135//----------------------------------------------------------------------
136void
137Log::Printf(const char *format, ...)
138{
139 va_list args;
140 va_start (args, format);
141 PrintfWithFlagsVarArg (0, format, args);
142 va_end (args);
143}
144
145void
146Log::VAPrintf (const char *format, va_list args)
147{
148 PrintfWithFlagsVarArg (0, format, args);
149}
150
151
152//----------------------------------------------------------------------
153// Simple variable argument logging with flags.
154//----------------------------------------------------------------------
155void
156Log::PrintfWithFlags (uint32_t flags, const char *format, ...)
157{
158 va_list args;
159 va_start (args, format);
160 PrintfWithFlagsVarArg (flags, format, args);
161 va_end (args);
162}
163
164//----------------------------------------------------------------------
165// Print debug strings if and only if the global debug option is set to
166// a non-zero value.
167//----------------------------------------------------------------------
168void
169Log::Debug (const char *format, ...)
170{
Greg Clayton73b472d2010-10-27 03:32:59 +0000171 if (GetOptions().Test(LLDB_LOG_OPTION_DEBUG))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000172 {
173 va_list args;
174 va_start (args, format);
175 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG, format, args);
176 va_end (args);
177 }
178}
179
180
181//----------------------------------------------------------------------
182// Print debug strings if and only if the global debug option is set to
183// a non-zero value.
184//----------------------------------------------------------------------
185void
186Log::DebugVerbose (const char *format, ...)
187{
Greg Clayton73b472d2010-10-27 03:32:59 +0000188 if (GetOptions().AllSet (LLDB_LOG_OPTION_DEBUG | LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000189 {
190 va_list args;
191 va_start (args, format);
192 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_DEBUG | LLDB_LOG_FLAG_VERBOSE, format, args);
193 va_end (args);
194 }
195}
196
197
198//----------------------------------------------------------------------
199// Log only if all of the bits are set
200//----------------------------------------------------------------------
201void
202Log::LogIf (uint32_t bits, const char *format, ...)
203{
Greg Clayton73b472d2010-10-27 03:32:59 +0000204 if (m_options.AllSet (bits))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000205 {
206 va_list args;
207 va_start (args, format);
208 PrintfWithFlagsVarArg (0, format, args);
209 va_end (args);
210 }
211}
212
213
214//----------------------------------------------------------------------
215// Printing of errors that are not fatal.
216//----------------------------------------------------------------------
217void
218Log::Error (const char *format, ...)
219{
220 char *arg_msg = NULL;
221 va_list args;
222 va_start (args, format);
223 ::vasprintf (&arg_msg, format, args);
224 va_end (args);
225
226 if (arg_msg != NULL)
227 {
228 PrintfWithFlags (LLDB_LOG_FLAG_ERROR, "error: %s", arg_msg);
229 free (arg_msg);
230 }
231}
232
233//----------------------------------------------------------------------
234// Printing of errors that ARE fatal. Exit with ERR exit code
235// immediately.
236//----------------------------------------------------------------------
237void
238Log::FatalError (int err, const char *format, ...)
239{
240 char *arg_msg = NULL;
241 va_list args;
242 va_start (args, format);
243 ::vasprintf (&arg_msg, format, args);
244 va_end (args);
245
246 if (arg_msg != NULL)
247 {
248 PrintfWithFlags (LLDB_LOG_FLAG_ERROR | LLDB_LOG_FLAG_FATAL, "error: %s", arg_msg);
249 ::free (arg_msg);
250 }
251 ::exit (err);
252}
253
254
255//----------------------------------------------------------------------
256// Printing of warnings that are not fatal only if verbose mode is
257// enabled.
258//----------------------------------------------------------------------
259void
260Log::Verbose (const char *format, ...)
261{
Greg Clayton73b472d2010-10-27 03:32:59 +0000262 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000263 {
264 va_list args;
265 va_start (args, format);
266 PrintfWithFlagsVarArg (LLDB_LOG_FLAG_VERBOSE, format, args);
267 va_end (args);
268 }
269}
270
271//----------------------------------------------------------------------
272// Printing of warnings that are not fatal only if verbose mode is
273// enabled.
274//----------------------------------------------------------------------
275void
276Log::WarningVerbose (const char *format, ...)
277{
Greg Clayton73b472d2010-10-27 03:32:59 +0000278 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000279 {
280 char *arg_msg = NULL;
281 va_list args;
282 va_start (args, format);
283 ::vasprintf (&arg_msg, format, args);
284 va_end (args);
285
286 if (arg_msg != NULL)
287 {
288 PrintfWithFlags (LLDB_LOG_FLAG_WARNING | LLDB_LOG_FLAG_VERBOSE, "warning: %s", arg_msg);
289 free (arg_msg);
290 }
291 }
292}
293//----------------------------------------------------------------------
294// Printing of warnings that are not fatal.
295//----------------------------------------------------------------------
296void
297Log::Warning (const char *format, ...)
298{
299 char *arg_msg = NULL;
300 va_list args;
301 va_start (args, format);
302 ::vasprintf (&arg_msg, format, args);
303 va_end (args);
304
305 if (arg_msg != NULL)
306 {
307 PrintfWithFlags (LLDB_LOG_FLAG_WARNING, "warning: %s", arg_msg);
308 free (arg_msg);
309 }
310}
311
312typedef std::map <std::string, Log::Callbacks> CallbackMap;
313typedef CallbackMap::iterator CallbackMapIter;
314
315typedef std::map <ConstString, LogChannelSP> LogChannelMap;
316typedef LogChannelMap::iterator LogChannelMapIter;
317
318
319// Surround our callback map with a singleton function so we don't have any
320// global initializers.
321static CallbackMap &
322GetCallbackMap ()
323{
324 static CallbackMap g_callback_map;
325 return g_callback_map;
326}
327
328static LogChannelMap &
329GetChannelMap ()
330{
331 static LogChannelMap g_channel_map;
332 return g_channel_map;
333}
334
335void
336Log::RegisterLogChannel (const char *channel, const Log::Callbacks &log_callbacks)
337{
338 GetCallbackMap().insert(std::make_pair(channel, log_callbacks));
339}
340
341bool
342Log::UnregisterLogChannel (const char *channel)
343{
344 return GetCallbackMap().erase(channel) != 0;
345}
346
347bool
348Log::GetLogChannelCallbacks (const char *channel, Log::Callbacks &log_callbacks)
349{
350 CallbackMap &callback_map = GetCallbackMap ();
351 CallbackMapIter pos = callback_map.find(channel);
352 if (pos != callback_map.end())
353 {
354 log_callbacks = pos->second;
355 return true;
356 }
Greg Clayton72b77eb2011-02-04 21:13:05 +0000357 ::memset (&log_callbacks, 0, sizeof(log_callbacks));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000358 return false;
359}
360
361void
362Log::EnableAllLogChannels
363(
364 StreamSP &log_stream_sp,
365 uint32_t log_options,
Jim Ingham228063c2012-02-21 02:23:08 +0000366 const char **categories,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000367 Stream *feedback_strm
368)
369{
370 CallbackMap &callback_map = GetCallbackMap ();
371 CallbackMapIter pos, end = callback_map.end();
372
373 for (pos = callback_map.begin(); pos != end; ++pos)
Jim Ingham228063c2012-02-21 02:23:08 +0000374 pos->second.enable (log_stream_sp, log_options, categories, feedback_strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000375
376 LogChannelMap &channel_map = GetChannelMap ();
377 LogChannelMapIter channel_pos, channel_end = channel_map.end();
378 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
379 {
Jim Ingham228063c2012-02-21 02:23:08 +0000380 channel_pos->second->Enable (log_stream_sp, log_options, feedback_strm, categories);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000381 }
382
383}
384
385void
Greg Claytonab65b342011-04-13 22:47:15 +0000386Log::AutoCompleteChannelName (const char *channel_name, StringList &matches)
387{
388 LogChannelMap &map = GetChannelMap ();
389 LogChannelMapIter pos, end = map.end();
390 for (pos = map.begin(); pos != end; ++pos)
391 {
392 const char *pos_channel_name = pos->first.GetCString();
393 if (channel_name && channel_name[0])
394 {
395 if (NameMatches (channel_name, eNameMatchStartsWith, pos_channel_name))
396 {
397 matches.AppendString(pos_channel_name);
398 }
399 }
400 else
401 matches.AppendString(pos_channel_name);
402
403 }
404}
405
406void
Caroline Tice20ad3c42010-10-29 21:48:37 +0000407Log::DisableAllLogChannels (Stream *feedback_strm)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000408{
409 CallbackMap &callback_map = GetCallbackMap ();
410 CallbackMapIter pos, end = callback_map.end();
Jim Ingham228063c2012-02-21 02:23:08 +0000411 const char *categories[1] = {NULL};
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000412
413 for (pos = callback_map.begin(); pos != end; ++pos)
Jim Ingham228063c2012-02-21 02:23:08 +0000414 pos->second.disable (categories, feedback_strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000415
416 LogChannelMap &channel_map = GetChannelMap ();
417 LogChannelMapIter channel_pos, channel_end = channel_map.end();
418 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
Jim Ingham228063c2012-02-21 02:23:08 +0000419 channel_pos->second->Disable (categories, feedback_strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000420}
421
422void
Greg Clayton99d0faf2010-11-18 23:32:35 +0000423Log::Initialize()
424{
425 Log::Callbacks log_callbacks = { DisableLog, EnableLog, ListLogCategories };
426 Log::RegisterLogChannel ("lldb", log_callbacks);
427}
428
429void
430Log::Terminate ()
431{
432 DisableAllLogChannels (NULL);
433}
434
435void
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000436Log::ListAllLogChannels (Stream *strm)
437{
438 CallbackMap &callback_map = GetCallbackMap ();
439 LogChannelMap &channel_map = GetChannelMap ();
440
441 if (callback_map.empty() && channel_map.empty())
442 {
443 strm->PutCString ("No logging channels are currently registered.\n");
444 return;
445 }
446
447 CallbackMapIter pos, end = callback_map.end();
448 for (pos = callback_map.begin(); pos != end; ++pos)
449 pos->second.list_categories (strm);
450
451 uint32_t idx = 0;
452 const char *name;
453 for (idx = 0; (name = PluginManager::GetLogChannelCreateNameAtIndex (idx)) != NULL; ++idx)
454 {
455 LogChannelSP log_channel_sp(LogChannel::FindPlugin (name));
456 if (log_channel_sp)
457 log_channel_sp->ListCategories (strm);
458 }
459}
460
461bool
462Log::GetVerbose() const
463{
Jim Inghamd8d148e2011-01-22 01:24:30 +0000464 // FIXME: This has to be centralized between the stream and the log...
465 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
466 return true;
467
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000468 if (m_stream_sp)
469 return m_stream_sp->GetVerbose();
470 return false;
471}
472
473//------------------------------------------------------------------
474// Returns true if the debug flag bit is set in this stream.
475//------------------------------------------------------------------
476bool
477Log::GetDebug() const
478{
479 if (m_stream_sp)
480 return m_stream_sp->GetDebug();
481 return false;
482}
483
484
485LogChannelSP
486LogChannel::FindPlugin (const char *plugin_name)
487{
488 LogChannelSP log_channel_sp;
489 LogChannelMap &channel_map = GetChannelMap ();
490 ConstString log_channel_name (plugin_name);
491 LogChannelMapIter pos = channel_map.find (log_channel_name);
492 if (pos == channel_map.end())
493 {
494 LogChannelCreateInstance create_callback = PluginManager::GetLogChannelCreateCallbackForPluginName (plugin_name);
495 if (create_callback)
496 {
497 log_channel_sp.reset(create_callback());
498 if (log_channel_sp)
499 {
500 // Cache the one and only loaded instance of each log channel
501 // plug-in after it has been loaded once.
502 channel_map[log_channel_name] = log_channel_sp;
503 }
504 }
505 }
506 else
507 {
508 // We have already loaded an instance of this log channel class,
509 // so just return the cached instance.
510 log_channel_sp = pos->second;
511 }
512 return log_channel_sp;
513}
514
515LogChannel::LogChannel () :
516 m_log_sp ()
517{
518}
519
520LogChannel::~LogChannel ()
521{
522}
523
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000524