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