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