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