1 //===-- 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
11 #include <stdio.h>
12 #include <stdarg.h>
13 #include <stdlib.h>
14
15 // C++ Includes
16 #include <map>
17 #include <string>
18
19 // Other libraries and framework includes
20 // Project includes
21 #include "lldb/Core/Log.h"
22 #include "lldb/Core/PluginManager.h"
23 #include "lldb/Core/StreamFile.h"
24 #include "lldb/Core/StreamString.h"
25 #include "lldb/Host/Host.h"
26 #include "lldb/Host/Mutex.h"
27 #include "lldb/Host/ThisThread.h"
28 #include "lldb/Host/TimeValue.h"
29 #include "lldb/Interpreter/Args.h"
30 #include "lldb/Utility/NameMatches.h"
31
32 #include "llvm/ADT/SmallString.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include "llvm/Support/Signals.h"
35 using namespace lldb;
36 using namespace lldb_private;
37
Log()38 Log::Log () :
39 m_stream_sp(),
40 m_options(0),
41 m_mask_bits(0)
42 {
43 }
44
Log(const StreamSP & stream_sp)45 Log::Log (const StreamSP &stream_sp) :
46 m_stream_sp(stream_sp),
47 m_options(0),
48 m_mask_bits(0)
49 {
50 }
51
~Log()52 Log::~Log ()
53 {
54 }
55
56 Flags &
GetOptions()57 Log::GetOptions()
58 {
59 return m_options;
60 }
61
62 const Flags &
GetOptions() const63 Log::GetOptions() const
64 {
65 return m_options;
66 }
67
68 Flags &
GetMask()69 Log::GetMask()
70 {
71 return m_mask_bits;
72 }
73
74 const Flags &
GetMask() const75 Log::GetMask() const
76 {
77 return m_mask_bits;
78 }
79
80 void
PutCString(const char * cstr)81 Log::PutCString(const char *cstr)
82 {
83 Printf("%s", cstr);
84 }
85
86 //----------------------------------------------------------------------
87 // Simple variable argument logging with flags.
88 //----------------------------------------------------------------------
89 void
Printf(const char * format,...)90 Log::Printf(const char *format, ...)
91 {
92 va_list args;
93 va_start(args, format);
94 VAPrintf(format, args);
95 va_end(args);
96 }
97
98 //----------------------------------------------------------------------
99 // All logging eventually boils down to this function call. If we have
100 // a callback registered, then we call the logging callback. If we have
101 // a valid file handle, we also log to the file.
102 //----------------------------------------------------------------------
103 void
VAPrintf(const char * format,va_list args)104 Log::VAPrintf(const char *format, va_list args)
105 {
106 // Make a copy of our stream shared pointer in case someone disables our
107 // log while we are logging and releases the stream
108 StreamSP stream_sp(m_stream_sp);
109 if (stream_sp)
110 {
111 static uint32_t g_sequence_id = 0;
112 StreamString header;
113
114 // Add a sequence ID if requested
115 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_SEQUENCE))
116 header.Printf ("%u ", ++g_sequence_id);
117
118 // Timestamp if requested
119 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_TIMESTAMP))
120 {
121 TimeValue now = TimeValue::Now();
122 header.Printf ("%9d.%09.9d ", now.seconds(), now.nanoseconds());
123 }
124
125 // Add the process and thread if requested
126 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD))
127 header.Printf ("[%4.4x/%4.4" PRIx64 "]: ", getpid(), Host::GetCurrentThreadID());
128
129 // Add the thread name if requested
130 if (m_options.Test (LLDB_LOG_OPTION_PREPEND_THREAD_NAME))
131 {
132 llvm::SmallString<32> thread_name;
133 ThisThread::GetName(thread_name);
134 if (!thread_name.empty())
135 header.Printf ("%s ", thread_name.c_str());
136 }
137
138 header.PrintfVarArg (format, args);
139 header.PutCString("\n");
140
141 if (m_options.Test(LLDB_LOG_OPTION_BACKTRACE))
142 {
143 std::string back_trace;
144 llvm::raw_string_ostream stream(back_trace);
145 llvm::sys::PrintStackTrace(stream);
146 header.PutCString(back_trace.c_str());
147 }
148
149 if (m_options.Test(LLDB_LOG_OPTION_THREADSAFE))
150 {
151 static Mutex g_LogThreadedMutex(Mutex::eMutexTypeRecursive);
152 Mutex::Locker locker(g_LogThreadedMutex);
153 stream_sp->PutCString(header.GetString().c_str());
154 stream_sp->Flush();
155 }
156 else
157 {
158 stream_sp->PutCString(header.GetString().c_str());
159 stream_sp->Flush();
160 }
161 }
162 }
163
164 //----------------------------------------------------------------------
165 // Print debug strings if and only if the global debug option is set to
166 // a non-zero value.
167 //----------------------------------------------------------------------
168 void
Debug(const char * format,...)169 Log::Debug(const char *format, ...)
170 {
171 if (!GetOptions().Test(LLDB_LOG_OPTION_DEBUG))
172 return;
173
174 va_list args;
175 va_start(args, format);
176 VAPrintf(format, args);
177 va_end(args);
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 //----------------------------------------------------------------------
185 void
DebugVerbose(const char * format,...)186 Log::DebugVerbose(const char *format, ...)
187 {
188 if (!GetOptions().AllSet(LLDB_LOG_OPTION_DEBUG | LLDB_LOG_OPTION_VERBOSE))
189 return;
190
191 va_list args;
192 va_start(args, format);
193 VAPrintf(format, args);
194 va_end(args);
195 }
196
197
198 //----------------------------------------------------------------------
199 // Log only if all of the bits are set
200 //----------------------------------------------------------------------
201 void
LogIf(uint32_t bits,const char * format,...)202 Log::LogIf(uint32_t bits, const char *format, ...)
203 {
204 if (!m_options.AllSet(bits))
205 return;
206
207 va_list args;
208 va_start(args, format);
209 VAPrintf(format, args);
210 va_end(args);
211 }
212
213 //----------------------------------------------------------------------
214 // Printing of errors that are not fatal.
215 //----------------------------------------------------------------------
216 void
Error(const char * format,...)217 Log::Error(const char *format, ...)
218 {
219 va_list args;
220 va_start(args, format);
221 VAError(format, args);
222 va_end(args);
223 }
224
225
226 void
VAError(const char * format,va_list args)227 Log::VAError(const char *format, va_list args)
228 {
229 char *arg_msg = nullptr;
230 ::vasprintf(&arg_msg, format, args);
231
232 if (arg_msg == nullptr)
233 return;
234
235 Printf("error: %s", arg_msg);
236 free(arg_msg);
237 }
238
239
240 //----------------------------------------------------------------------
241 // Printing of errors that ARE fatal. Exit with ERR exit code
242 // immediately.
243 //----------------------------------------------------------------------
244 void
FatalError(int err,const char * format,...)245 Log::FatalError(int err, const char *format, ...)
246 {
247 char *arg_msg = nullptr;
248 va_list args;
249 va_start(args, format);
250 ::vasprintf(&arg_msg, format, args);
251 va_end(args);
252
253 if (arg_msg != nullptr)
254 {
255 Printf("error: %s", arg_msg);
256 ::free(arg_msg);
257 }
258 ::exit(err);
259 }
260
261
262 //----------------------------------------------------------------------
263 // Printing of warnings that are not fatal only if verbose mode is
264 // enabled.
265 //----------------------------------------------------------------------
266 void
Verbose(const char * format,...)267 Log::Verbose(const char *format, ...)
268 {
269 if (!m_options.Test(LLDB_LOG_OPTION_VERBOSE))
270 return;
271
272 va_list args;
273 va_start(args, format);
274 VAPrintf(format, args);
275 va_end(args);
276 }
277
278 //----------------------------------------------------------------------
279 // Printing of warnings that are not fatal only if verbose mode is
280 // enabled.
281 //----------------------------------------------------------------------
282 void
WarningVerbose(const char * format,...)283 Log::WarningVerbose(const char *format, ...)
284 {
285 if (!m_options.Test(LLDB_LOG_OPTION_VERBOSE))
286 return;
287
288 char *arg_msg = nullptr;
289 va_list args;
290 va_start(args, format);
291 ::vasprintf(&arg_msg, format, args);
292 va_end(args);
293
294 if (arg_msg == nullptr)
295 return;
296
297 Printf("warning: %s", arg_msg);
298 free(arg_msg);
299 }
300 //----------------------------------------------------------------------
301 // Printing of warnings that are not fatal.
302 //----------------------------------------------------------------------
303 void
Warning(const char * format,...)304 Log::Warning(const char *format, ...)
305 {
306 char *arg_msg = nullptr;
307 va_list args;
308 va_start(args, format);
309 ::vasprintf(&arg_msg, format, args);
310 va_end(args);
311
312 if (arg_msg == nullptr)
313 return;
314
315 Printf("warning: %s", arg_msg);
316 free(arg_msg);
317 }
318
319 typedef std::map <ConstString, Log::Callbacks> CallbackMap;
320 typedef CallbackMap::iterator CallbackMapIter;
321
322 typedef std::map <ConstString, LogChannelSP> LogChannelMap;
323 typedef LogChannelMap::iterator LogChannelMapIter;
324
325
326 // Surround our callback map with a singleton function so we don't have any
327 // global initializers.
328 static CallbackMap &
GetCallbackMap()329 GetCallbackMap ()
330 {
331 static CallbackMap g_callback_map;
332 return g_callback_map;
333 }
334
335 static LogChannelMap &
GetChannelMap()336 GetChannelMap ()
337 {
338 static LogChannelMap g_channel_map;
339 return g_channel_map;
340 }
341
342 void
RegisterLogChannel(const ConstString & channel,const Log::Callbacks & log_callbacks)343 Log::RegisterLogChannel (const ConstString &channel, const Log::Callbacks &log_callbacks)
344 {
345 GetCallbackMap().insert(std::make_pair(channel, log_callbacks));
346 }
347
348 bool
UnregisterLogChannel(const ConstString & channel)349 Log::UnregisterLogChannel (const ConstString &channel)
350 {
351 return GetCallbackMap().erase(channel) != 0;
352 }
353
354 bool
GetLogChannelCallbacks(const ConstString & channel,Log::Callbacks & log_callbacks)355 Log::GetLogChannelCallbacks (const ConstString &channel, Log::Callbacks &log_callbacks)
356 {
357 CallbackMap &callback_map = GetCallbackMap ();
358 CallbackMapIter pos = callback_map.find(channel);
359 if (pos != callback_map.end())
360 {
361 log_callbacks = pos->second;
362 return true;
363 }
364 ::memset (&log_callbacks, 0, sizeof(log_callbacks));
365 return false;
366 }
367
368 bool
EnableLogChannel(lldb::StreamSP & log_stream_sp,uint32_t log_options,const char * channel,const char ** categories,Stream & error_stream)369 Log::EnableLogChannel(lldb::StreamSP &log_stream_sp,
370 uint32_t log_options,
371 const char *channel,
372 const char **categories,
373 Stream &error_stream)
374 {
375 Log::Callbacks log_callbacks;
376 if (Log::GetLogChannelCallbacks (ConstString(channel), log_callbacks))
377 {
378 log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream);
379 return true;
380 }
381
382 LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel));
383 if (log_channel_sp)
384 {
385 if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories))
386 {
387 return true;
388 }
389 else
390 {
391 error_stream.Printf ("Invalid log channel '%s'.\n", channel);
392 return false;
393 }
394 }
395 else
396 {
397 error_stream.Printf ("Invalid log channel '%s'.\n", channel);
398 return false;
399 }
400 }
401
402 void
EnableAllLogChannels(StreamSP & log_stream_sp,uint32_t log_options,const char ** categories,Stream * feedback_strm)403 Log::EnableAllLogChannels
404 (
405 StreamSP &log_stream_sp,
406 uint32_t log_options,
407 const char **categories,
408 Stream *feedback_strm
409 )
410 {
411 CallbackMap &callback_map = GetCallbackMap ();
412 CallbackMapIter pos, end = callback_map.end();
413
414 for (pos = callback_map.begin(); pos != end; ++pos)
415 pos->second.enable (log_stream_sp, log_options, categories, feedback_strm);
416
417 LogChannelMap &channel_map = GetChannelMap ();
418 LogChannelMapIter channel_pos, channel_end = channel_map.end();
419 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
420 {
421 channel_pos->second->Enable (log_stream_sp, log_options, feedback_strm, categories);
422 }
423
424 }
425
426 void
AutoCompleteChannelName(const char * channel_name,StringList & matches)427 Log::AutoCompleteChannelName (const char *channel_name, StringList &matches)
428 {
429 LogChannelMap &map = GetChannelMap ();
430 LogChannelMapIter pos, end = map.end();
431 for (pos = map.begin(); pos != end; ++pos)
432 {
433 const char *pos_channel_name = pos->first.GetCString();
434 if (channel_name && channel_name[0])
435 {
436 if (NameMatches (channel_name, eNameMatchStartsWith, pos_channel_name))
437 {
438 matches.AppendString(pos_channel_name);
439 }
440 }
441 else
442 matches.AppendString(pos_channel_name);
443
444 }
445 }
446
447 void
DisableAllLogChannels(Stream * feedback_strm)448 Log::DisableAllLogChannels (Stream *feedback_strm)
449 {
450 CallbackMap &callback_map = GetCallbackMap ();
451 CallbackMapIter pos, end = callback_map.end();
452 const char *categories[1] = {NULL};
453
454 for (pos = callback_map.begin(); pos != end; ++pos)
455 pos->second.disable (categories, feedback_strm);
456
457 LogChannelMap &channel_map = GetChannelMap ();
458 LogChannelMapIter channel_pos, channel_end = channel_map.end();
459 for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos)
460 channel_pos->second->Disable (categories, feedback_strm);
461 }
462
463 void
Initialize()464 Log::Initialize()
465 {
466 Log::Callbacks log_callbacks = { DisableLog, EnableLog, ListLogCategories };
467 Log::RegisterLogChannel (ConstString("lldb"), log_callbacks);
468 }
469
470 void
Terminate()471 Log::Terminate ()
472 {
473 DisableAllLogChannels (NULL);
474 }
475
476 void
ListAllLogChannels(Stream * strm)477 Log::ListAllLogChannels (Stream *strm)
478 {
479 CallbackMap &callback_map = GetCallbackMap ();
480 LogChannelMap &channel_map = GetChannelMap ();
481
482 if (callback_map.empty() && channel_map.empty())
483 {
484 strm->PutCString ("No logging channels are currently registered.\n");
485 return;
486 }
487
488 CallbackMapIter pos, end = callback_map.end();
489 for (pos = callback_map.begin(); pos != end; ++pos)
490 pos->second.list_categories (strm);
491
492 uint32_t idx = 0;
493 const char *name;
494 for (idx = 0; (name = PluginManager::GetLogChannelCreateNameAtIndex (idx)) != NULL; ++idx)
495 {
496 LogChannelSP log_channel_sp(LogChannel::FindPlugin (name));
497 if (log_channel_sp)
498 log_channel_sp->ListCategories (strm);
499 }
500 }
501
502 bool
GetVerbose() const503 Log::GetVerbose() const
504 {
505 // FIXME: This has to be centralized between the stream and the log...
506 if (m_options.Test(LLDB_LOG_OPTION_VERBOSE))
507 return true;
508
509 // Make a copy of our stream shared pointer in case someone disables our
510 // log while we are logging and releases the stream
511 StreamSP stream_sp(m_stream_sp);
512 if (stream_sp)
513 return stream_sp->GetVerbose();
514 return false;
515 }
516
517 //------------------------------------------------------------------
518 // Returns true if the debug flag bit is set in this stream.
519 //------------------------------------------------------------------
520 bool
GetDebug() const521 Log::GetDebug() const
522 {
523 // Make a copy of our stream shared pointer in case someone disables our
524 // log while we are logging and releases the stream
525 StreamSP stream_sp(m_stream_sp);
526 if (stream_sp)
527 return stream_sp->GetDebug();
528 return false;
529 }
530
531
532 LogChannelSP
FindPlugin(const char * plugin_name)533 LogChannel::FindPlugin (const char *plugin_name)
534 {
535 LogChannelSP log_channel_sp;
536 LogChannelMap &channel_map = GetChannelMap ();
537 ConstString log_channel_name (plugin_name);
538 LogChannelMapIter pos = channel_map.find (log_channel_name);
539 if (pos == channel_map.end())
540 {
541 ConstString const_plugin_name (plugin_name);
542 LogChannelCreateInstance create_callback = PluginManager::GetLogChannelCreateCallbackForPluginName (const_plugin_name);
543 if (create_callback)
544 {
545 log_channel_sp.reset(create_callback());
546 if (log_channel_sp)
547 {
548 // Cache the one and only loaded instance of each log channel
549 // plug-in after it has been loaded once.
550 channel_map[log_channel_name] = log_channel_sp;
551 }
552 }
553 }
554 else
555 {
556 // We have already loaded an instance of this log channel class,
557 // so just return the cached instance.
558 log_channel_sp = pos->second;
559 }
560 return log_channel_sp;
561 }
562
LogChannel()563 LogChannel::LogChannel () :
564 m_log_ap ()
565 {
566 }
567
~LogChannel()568 LogChannel::~LogChannel ()
569 {
570 }
571
572
573