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