]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / source / Plugins / Process / POSIX / ProcessPOSIXLog.cpp
1 //===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++
2 //-*-===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10
11 #include "ProcessPOSIXLog.h"
12
13 #include <mutex>
14
15 #include "lldb/Core/StreamFile.h"
16 #include "lldb/Interpreter/Args.h"
17
18 #include "ProcessPOSIXLog.h"
19
20 using namespace lldb;
21 using namespace lldb_private;
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_log_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 ProcessPOSIXLog::Initialize(ConstString name) {
36   static std::once_flag g_once_flag;
37
38   std::call_once(g_once_flag, [name]() {
39     Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories};
40
41     Log::RegisterLogChannel(name, log_callbacks);
42     RegisterPluginName(name);
43   });
44 }
45
46 Log *ProcessPOSIXLog::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 static uint32_t GetFlagBits(const char *arg) {
57   if (::strcasecmp(arg, "all") == 0)
58     return POSIX_LOG_ALL;
59   else if (::strcasecmp(arg, "async") == 0)
60     return POSIX_LOG_ASYNC;
61   else if (::strncasecmp(arg, "break", 5) == 0)
62     return POSIX_LOG_BREAKPOINTS;
63   else if (::strncasecmp(arg, "comm", 4) == 0)
64     return POSIX_LOG_COMM;
65   else if (::strcasecmp(arg, "default") == 0)
66     return POSIX_LOG_DEFAULT;
67   else if (::strcasecmp(arg, "packets") == 0)
68     return POSIX_LOG_PACKETS;
69   else if (::strcasecmp(arg, "memory") == 0)
70     return POSIX_LOG_MEMORY;
71   else if (::strcasecmp(arg, "data-short") == 0)
72     return POSIX_LOG_MEMORY_DATA_SHORT;
73   else if (::strcasecmp(arg, "data-long") == 0)
74     return POSIX_LOG_MEMORY_DATA_LONG;
75   else if (::strcasecmp(arg, "process") == 0)
76     return POSIX_LOG_PROCESS;
77   else if (::strcasecmp(arg, "ptrace") == 0)
78     return POSIX_LOG_PTRACE;
79   else if (::strcasecmp(arg, "registers") == 0)
80     return POSIX_LOG_REGISTERS;
81   else if (::strcasecmp(arg, "step") == 0)
82     return POSIX_LOG_STEP;
83   else if (::strcasecmp(arg, "thread") == 0)
84     return POSIX_LOG_THREAD;
85   else if (::strcasecmp(arg, "verbose") == 0)
86     return POSIX_LOG_VERBOSE;
87   else if (::strncasecmp(arg, "watch", 5) == 0)
88     return POSIX_LOG_WATCHPOINTS;
89   return 0;
90 }
91
92 void ProcessPOSIXLog::DisableLog(const char **args, Stream *feedback_strm) {
93   Log *log(GetLog());
94   if (log) {
95     uint32_t flag_bits = 0;
96
97     flag_bits = log->GetMask().Get();
98     for (; args && args[0]; args++) {
99       const char *arg = args[0];
100       uint32_t bits = GetFlagBits(arg);
101
102       if (bits) {
103         flag_bits &= ~bits;
104       } else {
105         feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
106         ListLogCategories(feedback_strm);
107       }
108     }
109
110     log->GetMask().Reset(flag_bits);
111     if (flag_bits == 0)
112       g_log_enabled = false;
113   }
114
115   return;
116 }
117
118 Log *ProcessPOSIXLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options,
119                                 const char **args, Stream *feedback_strm) {
120   // Try see if there already is a log - that way we can reuse its settings.
121   // We could reuse the log in toto, but we don't know that the stream is the
122   // same.
123   uint32_t flag_bits = 0;
124   if (g_log)
125     flag_bits = g_log->GetMask().Get();
126
127   // Now make a new log with this stream if one was provided
128   if (log_stream_sp) {
129     if (g_log)
130       g_log->SetStream(log_stream_sp);
131     else
132       g_log = new Log(log_stream_sp);
133   }
134
135   if (g_log) {
136     bool got_unknown_category = false;
137     for (; args && args[0]; args++) {
138       const char *arg = args[0];
139       uint32_t bits = GetFlagBits(arg);
140
141       if (bits) {
142         flag_bits |= bits;
143       } else {
144         feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
145         if (got_unknown_category == false) {
146           got_unknown_category = true;
147           ListLogCategories(feedback_strm);
148         }
149       }
150     }
151     if (flag_bits == 0)
152       flag_bits = POSIX_LOG_DEFAULT;
153     g_log->GetMask().Reset(flag_bits);
154     g_log->GetOptions().Reset(log_options);
155     g_log_enabled = true;
156   }
157   return g_log;
158 }
159
160 void ProcessPOSIXLog::ListLogCategories(Stream *strm) {
161   strm->Printf(
162       "Logging categories for '%s':\n"
163       "  all - turn on all available logging categories\n"
164       "  async - log asynchronous activity\n"
165       "  break - log breakpoints\n"
166       "  communication - log communication activity\n"
167       "  default - enable the default set of logging categories for liblldb\n"
168       "  packets - log gdb remote packets\n"
169       "  memory - log memory reads and writes\n"
170       "  data-short - log memory bytes for memory reads and writes for short "
171       "transactions only\n"
172       "  data-long - log memory bytes for memory reads and writes for all "
173       "transactions\n"
174       "  process - log process events and activities\n"
175 #ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION
176       "  ptrace - log all calls to ptrace\n"
177 #endif
178       "  registers - log register read/writes\n"
179       "  thread - log thread events and activities\n"
180       "  step - log step related activities\n"
181       "  verbose - enable verbose logging\n"
182       "  watch - log watchpoint related activities\n",
183       ProcessPOSIXLog::m_pluginname);
184 }
185
186 void ProcessPOSIXLog::LogIf(uint32_t mask, const char *format, ...) {
187   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(mask));
188   if (log) {
189     va_list args;
190     va_start(args, format);
191     log->VAPrintf(format, args);
192     va_end(args);
193   }
194 }
195
196 int ProcessPOSIXLog::m_nestinglevel;
197 const char *ProcessPOSIXLog::m_pluginname = "";