xref: /NextBSD/contrib/llvm/tools/lldb/source/Core/Log.cpp (revision 84d351007654069f9643c8e4b4802a7f5f08ee42)
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