lldb-log.cpp revision 2ade6115e2aaf88cd90ccc8bf499108099bdeb86
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    uint32_t flag_bits;
105
106    if (log)
107    {
108        flag_bits = log->GetMask().Get();
109        const size_t argc = args.GetArgumentCount ();
110        for (size_t i = 0; i < argc; ++i)
111        {
112            const char *arg = args.GetArgumentAtIndex (i);
113
114            if      (strcasecmp(arg, "all")     == 0  ) flag_bits &= ~LIBLLDB_LOG_ALL;
115            else if (strcasecmp(arg, "api")     == 0)   flag_bits &= ~LIBLLDB_LOG_API;
116            else if (strcasestr(arg, "break")   == arg) flag_bits &= ~LIBLLDB_LOG_BREAKPOINTS;
117            else if (strcasecmp(arg, "default") == 0  ) flag_bits &= ~LIBLLDB_LOG_DEFAULT;
118            else if (strcasecmp(arg, "dyld")    == 0  ) flag_bits &= ~LIBLLDB_LOG_DYNAMIC_LOADER;
119            else if (strcasestr(arg, "event")   == arg) flag_bits &= ~LIBLLDB_LOG_EVENTS;
120            else if (strcasestr(arg, "expr")    == arg) flag_bits &= ~LIBLLDB_LOG_EXPRESSIONS;
121            else if (strcasestr(arg, "object")  == arg) flag_bits &= ~LIBLLDB_LOG_OBJECT;
122            else if (strcasecmp(arg, "process") == 0  ) flag_bits &= ~LIBLLDB_LOG_PROCESS;
123            else if (strcasecmp(arg, "script") == 0)    flag_bits &= ~LIBLLDB_LOG_SCRIPT;
124            else if (strcasecmp(arg, "state")   == 0  ) flag_bits &= ~LIBLLDB_LOG_STATE;
125            else if (strcasecmp(arg, "step")    == 0  ) flag_bits &= ~LIBLLDB_LOG_STEP;
126            else if (strcasecmp(arg, "thread")  == 0  ) flag_bits &= ~LIBLLDB_LOG_THREAD;
127            else if (strcasecmp(arg, "verbose") == 0  ) flag_bits &= ~LIBLLDB_LOG_VERBOSE;
128            else if (strcasestr(arg, "watch")   == arg) flag_bits &= ~LIBLLDB_LOG_WATCHPOINTS;
129            else if (strcasestr(arg, "temp")   == arg)  flag_bits &= ~LIBLLDB_LOG_TEMPORARY;
130            else if (strcasestr(arg, "comm")   == arg)  flag_bits &= ~LIBLLDB_LOG_COMMUNICATION;
131            else if (strcasestr(arg, "conn")   == arg)  flag_bits &= ~LIBLLDB_LOG_CONNECTION;
132            else if (strcasestr(arg, "host")   == arg)  flag_bits &= ~LIBLLDB_LOG_HOST;
133            else if (strcasestr(arg, "unwind") == arg)  flag_bits &= ~LIBLLDB_LOG_UNWIND;
134            else
135            {
136                feedback_strm->Printf ("error:  unrecognized log category '%s'\n", arg);
137                ListLogCategories (feedback_strm);
138                return;
139            }
140
141        }
142        if (flag_bits == 0)
143            GetLog ().reset();
144        else
145            log->GetMask().Reset (flag_bits);
146    }
147
148    return;
149}
150
151LogSP
152lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm)
153{
154    // Try see if there already is a log - that way we can reuse its settings.
155    // We could reuse the log in toto, but we don't know that the stream is the same.
156    uint32_t flag_bits;
157    LogSP log(GetLog ());
158    if (log)
159        flag_bits = log->GetMask().Get();
160    else
161        flag_bits = 0;
162
163    // Now make a new log with this stream if one was provided
164    if (log_stream_sp)
165    {
166        log = make_shared<Log>(log_stream_sp);
167        GetLog () = log;
168    }
169
170    if (log)
171    {
172        bool got_unknown_category = false;
173        const size_t argc = args.GetArgumentCount();
174        for (size_t i=0; i<argc; ++i)
175        {
176            const char *arg = args.GetArgumentAtIndex(i);
177
178            if      (strcasecmp(arg, "all")     == 0  ) flag_bits |= LIBLLDB_LOG_ALL;
179            else if (strcasecmp(arg, "api")     == 0)   flag_bits |= LIBLLDB_LOG_API;
180            else if (strcasestr(arg, "break")   == arg) flag_bits |= LIBLLDB_LOG_BREAKPOINTS;
181            else if (strcasecmp(arg, "default") == 0  ) flag_bits |= LIBLLDB_LOG_DEFAULT;
182            else if (strcasecmp(arg, "dyld")    == 0  ) flag_bits |= LIBLLDB_LOG_DYNAMIC_LOADER;
183            else if (strcasestr(arg, "event")   == arg) flag_bits |= LIBLLDB_LOG_EVENTS;
184            else if (strcasestr(arg, "expr")    == arg) flag_bits |= LIBLLDB_LOG_EXPRESSIONS;
185            else if (strcasestr(arg, "object")  == arg) flag_bits |= LIBLLDB_LOG_OBJECT;
186            else if (strcasecmp(arg, "process") == 0  ) flag_bits |= LIBLLDB_LOG_PROCESS;
187            else if (strcasecmp(arg, "script") == 0)    flag_bits |= LIBLLDB_LOG_SCRIPT;
188            else if (strcasecmp(arg, "state")   == 0  ) flag_bits |= LIBLLDB_LOG_STATE;
189            else if (strcasecmp(arg, "step")    == 0  ) flag_bits |= LIBLLDB_LOG_STEP;
190            else if (strcasecmp(arg, "thread")  == 0  ) flag_bits |= LIBLLDB_LOG_THREAD;
191            else if (strcasecmp(arg, "verbose") == 0  ) flag_bits |= LIBLLDB_LOG_VERBOSE;
192            else if (strcasestr(arg, "watch")   == arg) flag_bits |= LIBLLDB_LOG_WATCHPOINTS;
193            else if (strcasestr(arg, "temp")   == arg)  flag_bits |= LIBLLDB_LOG_TEMPORARY;
194            else if (strcasestr(arg, "comm")   == arg)  flag_bits |= LIBLLDB_LOG_COMMUNICATION;
195            else if (strcasestr(arg, "conn")   == arg)  flag_bits |= LIBLLDB_LOG_CONNECTION;
196            else if (strcasestr(arg, "host")   == arg)  flag_bits |= LIBLLDB_LOG_HOST;
197            else if (strcasestr(arg, "unwind") == arg)  flag_bits |= LIBLLDB_LOG_UNWIND;
198            else
199            {
200                feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
201                if (got_unknown_category == false)
202                {
203                    got_unknown_category = true;
204                    ListLogCategories (feedback_strm);
205                    return log;
206                }
207            }
208        }
209
210        log->GetMask().Reset(flag_bits);
211        log->GetOptions().Reset(log_options);
212    }
213    return log;
214}
215
216
217void
218lldb_private::ListLogCategories (Stream *strm)
219{
220    strm->Printf("Logging categories for 'lldb':\n"
221        "\tall - turn on all available logging categories\n"
222        "\tapi - enable logging of API calls and return values\n"
223        "\tdefault - enable the default set of logging categories for liblldb\n"
224        "\tbreak - log breakpoints\n"
225        "\tevents - log broadcaster, listener and event queue activities\n"
226        "\texpr - log expressions\n"
227        "\tobject - log object construction/destruction for important objects\n"
228        "\tprocess - log process events and activities\n"
229        "\tthread - log thread events and activities\n"
230        "\tscript - log events about the script interpreter\n"
231        "\tshlib - log shared library related activities\n"
232        "\tstate - log private and public process state changes\n"
233        "\tstep - log step related activities\n"
234        "\tunwind - log stack unwind activities\n"
235        "\tverbose - enable verbose loggging\n"
236        "\twatch - log watchpoint related activities\n");
237}
238