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