lldb-log.cpp revision 8280cbe80c79bc206335831dd732e0f9fb69c519
1//===-- lldb-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-private-log.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Interpreter/Args.h"
17#include "lldb/Core/Log.h"
18#include "lldb/Core/StreamFile.h"
19#include <string.h>
20
21using namespace lldb;
22using namespace lldb_private;
23
24
25static Log *
26LogAccessor (bool get, StreamSP *stream_sp_ptr)
27{
28    static Log* g_log = NULL; // Leak for now as auto_ptr was being cleaned up
29                                // by global constructors before other threads
30                                // were done with it.
31    if (!get)
32    {
33        if (g_log)
34            delete g_log;
35        if (stream_sp_ptr)
36            g_log = new Log (*stream_sp_ptr);
37        else
38            g_log = NULL;
39    }
40
41    return g_log;
42
43}
44
45uint32_t
46lldb_private::GetLogMask ()
47{
48    Log *log = LogAccessor (true, NULL);
49    if (log)
50        return log->GetMask().GetAllFlagBits();
51    return 0;
52}
53
54bool
55lldb_private::IsLogVerbose ()
56{
57    uint32_t mask = GetLogMask();
58    return (mask & LIBLLDB_LOG_VERBOSE);
59}
60
61Log *
62lldb_private::GetLogIfAllCategoriesSet (uint32_t mask)
63{
64    Log *log = LogAccessor (true, NULL);
65    if (log && mask)
66    {
67        uint32_t log_mask = log->GetMask().GetAllFlagBits();
68        if ((log_mask & mask) != mask)
69            return NULL;
70    }
71    return log;
72}
73
74void
75lldb_private::LogIfAllCategoriesSet (uint32_t mask, const char *format, ...)
76{
77    Log *log = GetLogIfAllCategoriesSet (mask);
78    if (log)
79    {
80        va_list args;
81        va_start (args, format);
82        log->VAPrintf (format, args);
83        va_end (args);
84    }
85}
86
87void
88lldb_private::LogIfAnyCategoriesSet (uint32_t mask, const char *format, ...)
89{
90    Log *log = GetLogIfAnyCategoriesSet (mask);
91    if (log)
92    {
93        va_list args;
94        va_start (args, format);
95        log->VAPrintf (format, args);
96        va_end (args);
97    }
98}
99
100Log *
101lldb_private::GetLogIfAnyCategoriesSet (uint32_t mask)
102{
103    Log *log = LogAccessor (true, NULL);
104    if (log && mask && (mask & log->GetMask().GetAllFlagBits()))
105        return log;
106    return NULL;
107}
108
109void
110lldb_private::DisableLog ()
111{
112    LogAccessor (false, NULL);
113}
114
115
116Log *
117lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm)
118{
119    // Try see if there already is a log - that way we can reuse its settings.
120    // We could reuse the log in toto, but we don't know that the stream is the same.
121    uint32_t flag_bits;
122    Log* log = LogAccessor (true, NULL);
123    if (log)
124        flag_bits = log->GetMask().GetAllFlagBits();
125    else
126        flag_bits = 0;
127
128    // Now make a new log with this stream.
129    log = LogAccessor (false, &log_stream_sp);
130    if (log)
131    {
132        bool got_unknown_category = false;
133        const size_t argc = args.GetArgumentCount();
134        for (size_t i=0; i<argc; ++i)
135        {
136            const char *arg = args.GetArgumentAtIndex(i);
137
138            if      (strcasecmp(arg, "all")     == 0  ) flag_bits |= LIBLLDB_LOG_ALL;
139            else if (strcasestr(arg, "break")   == arg) flag_bits |= LIBLLDB_LOG_BREAKPOINTS;
140            else if (strcasecmp(arg, "default") == 0  ) flag_bits |= LIBLLDB_LOG_DEFAULT;
141            else if (strcasestr(arg, "event")   == arg) flag_bits |= LIBLLDB_LOG_EVENTS;
142            else if (strcasestr(arg, "expr")    == arg) flag_bits |= LIBLLDB_LOG_EXPRESSIONS;
143            else if (strcasestr(arg, "object")  == arg) flag_bits |= LIBLLDB_LOG_OBJECT;
144            else if (strcasecmp(arg, "process") == 0  ) flag_bits |= LIBLLDB_LOG_PROCESS;
145            else if (strcasecmp(arg, "shlib")   == 0  ) flag_bits |= LIBLLDB_LOG_SHLIB;
146            else if (strcasecmp(arg, "state")   == 0  ) flag_bits |= LIBLLDB_LOG_STATE;
147            else if (strcasecmp(arg, "step")    == 0  ) flag_bits |= LIBLLDB_LOG_STEP;
148            else if (strcasecmp(arg, "thread")  == 0  ) flag_bits |= LIBLLDB_LOG_THREAD;
149            else if (strcasecmp(arg, "verbose") == 0  ) flag_bits |= LIBLLDB_LOG_VERBOSE;
150            else if (strcasestr(arg, "watch")   == arg) flag_bits |= LIBLLDB_LOG_WATCHPOINTS;
151            else if (strcasestr(arg, "temp")   == arg)  flag_bits |= LIBLLDB_LOG_TEMPORARY;
152            else if (strcasestr(arg, "comm")   == arg)  flag_bits |= LIBLLDB_LOG_COMMUNICATION;
153            else if (strcasestr(arg, "conn")   == arg)  flag_bits |= LIBLLDB_LOG_CONNECTION;
154            else if (strcasestr(arg, "host")   == arg)  flag_bits |= LIBLLDB_LOG_HOST;
155            else if (strcasestr(arg, "unwind") == arg)  flag_bits |= LIBLLDB_LOG_UNWIND;
156            else
157            {
158                feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
159                if (got_unknown_category == false)
160                {
161                    got_unknown_category = true;
162                    ListLogCategories (feedback_strm);
163                    return log;
164                }
165            }
166        }
167
168        log->GetMask().SetAllFlagBits(flag_bits);
169        log->GetOptions().SetAllFlagBits(log_options);
170    }
171    return log;
172}
173
174
175void
176lldb_private::ListLogCategories (Stream *strm)
177{
178    strm->Printf("Logging categories for 'lldb':\n"
179        "\tall - turn on all available logging categories\n"
180        "\tdefault - enable the default set of logging categories for liblldb\n"
181        "\tbreak - log breakpoints\n"
182        "\tevents - log broadcaster, listener and event queue activities\n"
183        "\texpr - log expressions\n"
184        "\tobject - log object construction/destruction for important objects\n"
185        "\tprocess - log process events and activities\n"
186        "\tthread - log thread events and activities\n"
187        "\tshlib - log shared library related activities\n"
188        "\tstate - log private and public process state changes\n"
189        "\tstep - log step related activities\n"
190        "\tunwind - log stack unwind activities\n"
191        "\tverbose - enable verbose loggging\n"
192        "\twatch - log watchpoint related activities\n");
193}
194