lldb-log.cpp revision ed11c1ebc344458c2bc83aa5b0bf6b3d0e2ef987
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
25// We want to avoid global constructors where code needs to be run so here we
26// control access to our static g_log_sp by hiding it in a singleton function
27// that will construct the static g_lob_sp the first time this function is
28// called.
29static LogSP &
30GetLog ()
31{
32    static LogSP g_log_sp;
33    return g_log_sp;
34}
35
36uint32_t
37lldb_private::GetLogMask ()
38{
39    LogSP log(GetLog ());
40    if (log)
41        return log->GetMask().Get();
42    return 0;
43}
44
45bool
46lldb_private::IsLogVerbose ()
47{
48    uint32_t mask = GetLogMask();
49    return (mask & LIBLLDB_LOG_VERBOSE);
50}
51
52LogSP
53lldb_private::GetLogIfAllCategoriesSet (uint32_t mask)
54{
55    LogSP log(GetLog ());
56    if (log && mask)
57    {
58        uint32_t log_mask = log->GetMask().Get();
59        if ((log_mask & mask) != mask)
60            return LogSP();
61    }
62    return log;
63}
64
65void
66lldb_private::LogIfAllCategoriesSet (uint32_t mask, const char *format, ...)
67{
68    LogSP log(GetLogIfAllCategoriesSet (mask));
69    if (log)
70    {
71        va_list args;
72        va_start (args, format);
73        log->VAPrintf (format, args);
74        va_end (args);
75    }
76}
77
78void
79lldb_private::LogIfAnyCategoriesSet (uint32_t mask, const char *format, ...)
80{
81    LogSP log(GetLogIfAnyCategoriesSet (mask));
82    if (log)
83    {
84        va_list args;
85        va_start (args, format);
86        log->VAPrintf (format, args);
87        va_end (args);
88    }
89}
90
91LogSP
92lldb_private::GetLogIfAnyCategoriesSet (uint32_t mask)
93{
94    LogSP log(GetLog ());
95    if (log && mask && (mask & log->GetMask().Get()))
96        return log;
97    return LogSP();
98}
99
100void
101lldb_private::DisableLog (Args &args, Stream *feedback_strm)
102{
103    LogSP log(GetLog ());
104
105    if (log)
106    {
107        uint32_t flag_bits = 0;
108        const size_t argc = args.GetArgumentCount ();
109        if (argc > 0)
110        {
111            flag_bits = log->GetMask().Get();
112            for (size_t i = 0; i < argc; ++i)
113            {
114                const char *arg = args.GetArgumentAtIndex (i);
115
116                if      (0 == ::strcasecmp(arg, "all"))         flag_bits &= ~LIBLLDB_LOG_ALL;
117                else if (0 == ::strcasecmp(arg, "api"))         flag_bits &= ~LIBLLDB_LOG_API;
118                else if (0 == ::strncasecmp(arg, "break", 5))   flag_bits &= ~LIBLLDB_LOG_BREAKPOINTS;
119                else if (0 == ::strcasecmp(arg, "commands"))    flag_bits &= ~LIBLLDB_LOG_COMMANDS;
120                else if (0 == ::strcasecmp(arg, "default"))     flag_bits &= ~LIBLLDB_LOG_DEFAULT;
121                else if (0 == ::strcasecmp(arg, "dyld"))        flag_bits &= ~LIBLLDB_LOG_DYNAMIC_LOADER;
122                else if (0 == ::strncasecmp(arg, "event", 5))   flag_bits &= ~LIBLLDB_LOG_EVENTS;
123                else if (0 == ::strncasecmp(arg, "expr", 4))    flag_bits &= ~LIBLLDB_LOG_EXPRESSIONS;
124                else if (0 == ::strncasecmp(arg, "object", 6))  flag_bits &= ~LIBLLDB_LOG_OBJECT;
125                else if (0 == ::strcasecmp(arg, "process"))     flag_bits &= ~LIBLLDB_LOG_PROCESS;
126                else if (0 == ::strcasecmp(arg, "script"))      flag_bits &= ~LIBLLDB_LOG_SCRIPT;
127                else if (0 == ::strcasecmp(arg, "state"))       flag_bits &= ~LIBLLDB_LOG_STATE;
128                else if (0 == ::strcasecmp(arg, "step"))        flag_bits &= ~LIBLLDB_LOG_STEP;
129                else if (0 == ::strcasecmp(arg, "thread"))      flag_bits &= ~LIBLLDB_LOG_THREAD;
130                else if (0 == ::strcasecmp(arg, "verbose"))     flag_bits &= ~LIBLLDB_LOG_VERBOSE;
131                else if (0 == ::strncasecmp(arg, "watch", 5))   flag_bits &= ~LIBLLDB_LOG_WATCHPOINTS;
132                else if (0 == ::strncasecmp(arg, "temp", 4))    flag_bits &= ~LIBLLDB_LOG_TEMPORARY;
133                else if (0 == ::strncasecmp(arg, "comm", 4))    flag_bits &= ~LIBLLDB_LOG_COMMUNICATION;
134                else if (0 == ::strncasecmp(arg, "conn", 4))    flag_bits &= ~LIBLLDB_LOG_CONNECTION;
135                else if (0 == ::strncasecmp(arg, "host", 4))    flag_bits &= ~LIBLLDB_LOG_HOST;
136                else if (0 == ::strncasecmp(arg, "unwind", 6))  flag_bits &= ~LIBLLDB_LOG_UNWIND;
137                else if (0 == ::strncasecmp(arg, "types", 5))   flag_bits &= ~LIBLLDB_LOG_TYPES;
138                else if (0 == ::strncasecmp(arg, "symbol", 6))  flag_bits &= ~LIBLLDB_LOG_SYMBOLS;
139                else
140                {
141                    feedback_strm->Printf ("error:  unrecognized log category '%s'\n", arg);
142                    ListLogCategories (feedback_strm);
143                    return;
144                }
145
146            }
147        }
148        if (flag_bits == 0)
149            GetLog ().reset();
150        else
151            log->GetMask().Reset (flag_bits);
152    }
153
154    return;
155}
156
157LogSP
158lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm)
159{
160    // Try see if there already is a log - that way we can reuse its settings.
161    // We could reuse the log in toto, but we don't know that the stream is the same.
162    uint32_t flag_bits;
163    LogSP log(GetLog ());
164    if (log)
165        flag_bits = log->GetMask().Get();
166    else
167        flag_bits = 0;
168
169    // Now make a new log with this stream if one was provided
170    if (log_stream_sp)
171    {
172        log = make_shared<Log>(log_stream_sp);
173        GetLog () = log;
174    }
175
176    if (log)
177    {
178        bool got_unknown_category = false;
179        const size_t argc = args.GetArgumentCount();
180        for (size_t i=0; i<argc; ++i)
181        {
182            const char *arg = args.GetArgumentAtIndex(i);
183
184            if      (0 == ::strcasecmp(arg, "all"))         flag_bits |= LIBLLDB_LOG_ALL;
185            else if (0 == ::strcasecmp(arg, "api"))         flag_bits |= LIBLLDB_LOG_API;
186            else if (0 == ::strncasecmp(arg, "break", 5))   flag_bits |= LIBLLDB_LOG_BREAKPOINTS;
187            else if (0 == ::strcasecmp(arg, "commands"))    flag_bits |= LIBLLDB_LOG_COMMANDS;
188            else if (0 == ::strcasecmp(arg, "default"))     flag_bits |= LIBLLDB_LOG_DEFAULT;
189            else if (0 == ::strcasecmp(arg, "dyld"))        flag_bits |= LIBLLDB_LOG_DYNAMIC_LOADER;
190            else if (0 == ::strncasecmp(arg, "event", 5))   flag_bits |= LIBLLDB_LOG_EVENTS;
191            else if (0 == ::strncasecmp(arg, "expr", 4))    flag_bits |= LIBLLDB_LOG_EXPRESSIONS;
192            else if (0 == ::strncasecmp(arg, "object", 6))  flag_bits |= LIBLLDB_LOG_OBJECT;
193            else if (0 == ::strcasecmp(arg, "process"))     flag_bits |= LIBLLDB_LOG_PROCESS;
194            else if (0 == ::strcasecmp(arg, "script"))      flag_bits |= LIBLLDB_LOG_SCRIPT;
195            else if (0 == ::strcasecmp(arg, "state"))       flag_bits |= LIBLLDB_LOG_STATE;
196            else if (0 == ::strcasecmp(arg, "step"))        flag_bits |= LIBLLDB_LOG_STEP;
197            else if (0 == ::strcasecmp(arg, "thread"))      flag_bits |= LIBLLDB_LOG_THREAD;
198            else if (0 == ::strcasecmp(arg, "verbose"))     flag_bits |= LIBLLDB_LOG_VERBOSE;
199            else if (0 == ::strncasecmp(arg, "watch", 5))   flag_bits |= LIBLLDB_LOG_WATCHPOINTS;
200            else if (0 == ::strncasecmp(arg, "temp", 4))    flag_bits |= LIBLLDB_LOG_TEMPORARY;
201            else if (0 == ::strncasecmp(arg, "comm", 4))    flag_bits |= LIBLLDB_LOG_COMMUNICATION;
202            else if (0 == ::strncasecmp(arg, "conn", 4))    flag_bits |= LIBLLDB_LOG_CONNECTION;
203            else if (0 == ::strncasecmp(arg, "host", 4))    flag_bits |= LIBLLDB_LOG_HOST;
204            else if (0 == ::strncasecmp(arg, "unwind", 6))  flag_bits |= LIBLLDB_LOG_UNWIND;
205            else if (0 == ::strncasecmp(arg, "types", 5))   flag_bits |= LIBLLDB_LOG_TYPES;
206            else if (0 == ::strncasecmp(arg, "symbol", 6))  flag_bits |= LIBLLDB_LOG_SYMBOLS;
207            else
208            {
209                feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
210                if (got_unknown_category == false)
211                {
212                    got_unknown_category = true;
213                    ListLogCategories (feedback_strm);
214                    return log;
215                }
216            }
217        }
218
219        log->GetMask().Reset(flag_bits);
220        log->GetOptions().Reset(log_options);
221    }
222    return log;
223}
224
225
226void
227lldb_private::ListLogCategories (Stream *strm)
228{
229    strm->Printf("Logging categories for 'lldb':\n"
230        "  all - turn on all available logging categories\n"
231        "  api - enable logging of API calls and return values\n"
232        "  command - log command argument parsing\n"
233        "  default - enable the default set of logging categories for liblldb\n"
234        "  break - log breakpoints\n"
235        "  events - log broadcaster, listener and event queue activities\n"
236        "  expr - log expressions\n"
237        "  object - log object construction/destruction for important objects\n"
238        "  process - log process events and activities\n"
239        "  thread - log thread events and activities\n"
240        "  script - log events about the script interpreter\n"
241        "  dyld - log shared library related activities\n"
242        "  state - log private and public process state changes\n"
243        "  step - log step related activities\n"
244        "  unwind - log stack unwind activities\n"
245        "  verbose - enable verbose logging\n"
246        "  symbol - log symbol related issues and warnings\n"
247        "  watch - log watchpoint related activities\n"
248        "  types - log type system related activities\n");
249}
250