1 //===-- ProcessKDPLog.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 "ProcessKDPLog.h"
11 
12 #include "lldb/Core/StreamFile.h"
13 #include "lldb/Interpreter/Args.h"
14 
15 #include "ProcessKDP.h"
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 
20 // We want to avoid global constructors where code needs to be run so here we
21 // control access to our static g_log_sp by hiding it in a singleton function
22 // that will construct the static g_log_sp the first time this function is
23 // called.
24 static bool g_log_enabled = false;
25 static Log *g_log = NULL;
26 static Log *GetLog() {
27   if (!g_log_enabled)
28     return NULL;
29   return g_log;
30 }
31 
32 Log *ProcessKDPLog::GetLogIfAllCategoriesSet(uint32_t mask) {
33   Log *log(GetLog());
34   if (log && mask) {
35     uint32_t log_mask = log->GetMask().Get();
36     if ((log_mask & mask) != mask)
37       return NULL;
38   }
39   return log;
40 }
41 
42 void ProcessKDPLog::DisableLog(const char **categories, Stream *feedback_strm) {
43   Log *log(GetLog());
44   if (log) {
45     uint32_t flag_bits = 0;
46 
47     if (categories[0] != NULL) {
48       flag_bits = log->GetMask().Get();
49       for (size_t i = 0; categories[i] != NULL; ++i) {
50         const char *arg = categories[i];
51 
52         if (::strcasecmp(arg, "all") == 0)
53           flag_bits &= ~KDP_LOG_ALL;
54         else if (::strcasecmp(arg, "async") == 0)
55           flag_bits &= ~KDP_LOG_ASYNC;
56         else if (::strncasecmp(arg, "break", 5) == 0)
57           flag_bits &= ~KDP_LOG_BREAKPOINTS;
58         else if (::strncasecmp(arg, "comm", 4) == 0)
59           flag_bits &= ~KDP_LOG_COMM;
60         else if (::strcasecmp(arg, "default") == 0)
61           flag_bits &= ~KDP_LOG_DEFAULT;
62         else if (::strcasecmp(arg, "packets") == 0)
63           flag_bits &= ~KDP_LOG_PACKETS;
64         else if (::strcasecmp(arg, "memory") == 0)
65           flag_bits &= ~KDP_LOG_MEMORY;
66         else if (::strcasecmp(arg, "data-short") == 0)
67           flag_bits &= ~KDP_LOG_MEMORY_DATA_SHORT;
68         else if (::strcasecmp(arg, "data-long") == 0)
69           flag_bits &= ~KDP_LOG_MEMORY_DATA_LONG;
70         else if (::strcasecmp(arg, "process") == 0)
71           flag_bits &= ~KDP_LOG_PROCESS;
72         else if (::strcasecmp(arg, "step") == 0)
73           flag_bits &= ~KDP_LOG_STEP;
74         else if (::strcasecmp(arg, "thread") == 0)
75           flag_bits &= ~KDP_LOG_THREAD;
76         else if (::strncasecmp(arg, "watch", 5) == 0)
77           flag_bits &= ~KDP_LOG_WATCHPOINTS;
78         else {
79           feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
80           ListLogCategories(feedback_strm);
81         }
82       }
83     }
84 
85     log->GetMask().Reset(flag_bits);
86     if (flag_bits == 0)
87       g_log_enabled = false;
88   }
89 
90   return;
91 }
92 
93 Log *ProcessKDPLog::EnableLog(
94     const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
95     uint32_t log_options, const char **categories, Stream *feedback_strm) {
96   // Try see if there already is a log - that way we can reuse its settings.
97   // We could reuse the log in toto, but we don't know that the stream is the
98   // same.
99   uint32_t flag_bits = 0;
100   if (g_log)
101     flag_bits = g_log->GetMask().Get();
102 
103   // Now make a new log with this stream if one was provided
104   if (log_stream_sp) {
105     if (g_log)
106       g_log->SetStream(log_stream_sp);
107     else
108       g_log = new Log(log_stream_sp);
109   }
110 
111   if (g_log) {
112     bool got_unknown_category = false;
113     for (size_t i = 0; categories[i] != NULL; ++i) {
114       const char *arg = categories[i];
115 
116       if (::strcasecmp(arg, "all") == 0)
117         flag_bits |= KDP_LOG_ALL;
118       else if (::strcasecmp(arg, "async") == 0)
119         flag_bits |= KDP_LOG_ASYNC;
120       else if (::strncasecmp(arg, "break", 5) == 0)
121         flag_bits |= KDP_LOG_BREAKPOINTS;
122       else if (::strncasecmp(arg, "comm", 4) == 0)
123         flag_bits |= KDP_LOG_COMM;
124       else if (::strcasecmp(arg, "default") == 0)
125         flag_bits |= KDP_LOG_DEFAULT;
126       else if (::strcasecmp(arg, "packets") == 0)
127         flag_bits |= KDP_LOG_PACKETS;
128       else if (::strcasecmp(arg, "memory") == 0)
129         flag_bits |= KDP_LOG_MEMORY;
130       else if (::strcasecmp(arg, "data-short") == 0)
131         flag_bits |= KDP_LOG_MEMORY_DATA_SHORT;
132       else if (::strcasecmp(arg, "data-long") == 0)
133         flag_bits |= KDP_LOG_MEMORY_DATA_LONG;
134       else if (::strcasecmp(arg, "process") == 0)
135         flag_bits |= KDP_LOG_PROCESS;
136       else if (::strcasecmp(arg, "step") == 0)
137         flag_bits |= KDP_LOG_STEP;
138       else if (::strcasecmp(arg, "thread") == 0)
139         flag_bits |= KDP_LOG_THREAD;
140       else if (::strncasecmp(arg, "watch", 5) == 0)
141         flag_bits |= KDP_LOG_WATCHPOINTS;
142       else {
143         feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
144         if (got_unknown_category == false) {
145           got_unknown_category = true;
146           ListLogCategories(feedback_strm);
147         }
148       }
149     }
150     if (flag_bits == 0)
151       flag_bits = KDP_LOG_DEFAULT;
152     g_log->GetMask().Reset(flag_bits);
153     g_log->GetOptions().Reset(log_options);
154   }
155   g_log_enabled = true;
156   return g_log;
157 }
158 
159 void ProcessKDPLog::ListLogCategories(Stream *strm) {
160   strm->Printf(
161       "Logging categories for '%s':\n"
162       "  all - turn on all available logging categories\n"
163       "  async - log asynchronous activity\n"
164       "  break - log breakpoints\n"
165       "  communication - log communication activity\n"
166       "  default - enable the default set of logging categories for liblldb\n"
167       "  packets - log gdb remote packets\n"
168       "  memory - log memory reads and writes\n"
169       "  data-short - log memory bytes for memory reads and writes for short "
170       "transactions only\n"
171       "  data-long - log memory bytes for memory reads and writes for all "
172       "transactions\n"
173       "  process - log process events and activities\n"
174       "  thread - log thread events and activities\n"
175       "  step - log step related activities\n"
176       "  verbose - enable verbose logging\n"
177       "  watch - log watchpoint related activities\n",
178       ProcessKDP::GetPluginNameStatic().GetCString());
179 }
180 
181 void ProcessKDPLog::LogIf(uint32_t mask, const char *format, ...) {
182   Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(mask));
183   if (log) {
184     va_list args;
185     va_start(args, format);
186     log->VAPrintf(format, args);
187     va_end(args);
188   }
189 }
190