xref: /llvm-project/lldb/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp (revision 18a9135d56522bb585ae005fdafa4678048d0214)
1 //===-- ProcessWindowsLog.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 "ProcessWindowsLog.h"
11 
12 #include <mutex>
13 
14 #include "lldb/Core/StreamFile.h"
15 #include "lldb/Interpreter/Args.h"
16 #include "llvm/Support/ManagedStatic.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 
22 // We want to avoid global constructors where code needs to be run so here we
23 // control access to our static g_log_sp by hiding it in a singleton function
24 // that will construct the static g_log_sp the first time this function is
25 // called.
26 static bool g_log_enabled = false;
27 static Log * g_log = nullptr;
28 
29 static llvm::ManagedStatic<std::once_flag> g_once_flag;
30 
31 void
32 ProcessWindowsLog::Initialize()
33 {
34     static ConstString g_name("windows");
35 
36     std::call_once(*g_once_flag, [](){
37         Log::Callbacks log_callbacks = {
38             DisableLog,
39             EnableLog,
40             ListLogCategories
41         };
42 
43         Log::RegisterLogChannel(g_name, log_callbacks);
44         RegisterPluginName(g_name);
45     });
46 }
47 
48 void
49 ProcessWindowsLog::Terminate()
50 {
51 }
52 
53 Log *
54 ProcessWindowsLog::GetLog()
55 {
56     return (g_log_enabled) ? g_log : nullptr;
57 }
58 
59 bool
60 ProcessWindowsLog::TestLogFlags(uint32_t mask, LogMaskReq req)
61 {
62     Log *log = GetLog();
63     if (!log)
64         return false;
65 
66     uint32_t log_mask = log->GetMask().Get();
67     if (req == LogMaskReq::All)
68         return ((log_mask & mask) == mask);
69     else
70         return (log_mask & mask);
71 }
72 
73 static uint32_t
74 GetFlagBits(const char *arg)
75 {
76     if      (::strcasecmp(arg, "all") == 0 ) return WINDOWS_LOG_ALL;
77     else if (::strcasecmp(arg, "break") == 0 ) return WINDOWS_LOG_BREAKPOINTS;
78     else if (::strcasecmp(arg, "event") == 0 ) return WINDOWS_LOG_EVENT;
79     else if (::strcasecmp(arg, "exception") == 0 ) return WINDOWS_LOG_EXCEPTION;
80     else if (::strcasecmp(arg, "memory") == 0 ) return WINDOWS_LOG_MEMORY;
81     else if (::strcasecmp(arg, "process") == 0 ) return WINDOWS_LOG_PROCESS;
82     else if (::strcasecmp(arg, "registers") == 0 ) return WINDOWS_LOG_REGISTERS;
83     else if (::strcasecmp(arg, "step") == 0 ) return WINDOWS_LOG_STEP;
84     else if (::strcasecmp(arg, "thread") == 0 ) return WINDOWS_LOG_THREAD;
85     else if (::strcasecmp(arg, "verbose") == 0 ) return WINDOWS_LOG_VERBOSE;
86     return 0;
87 }
88 
89 void
90 ProcessWindowsLog::DisableLog(const char **args, Stream *feedback_strm)
91 {
92     Log *log (GetLog());
93     if (log)
94     {
95         uint32_t flag_bits = 0;
96 
97         if (args[0] != nullptr)
98         {
99             flag_bits = log->GetMask().Get();
100             for (; args[0]; args++)
101             {
102                 const char *arg = args[0];
103                 uint32_t bits = GetFlagBits(arg);
104 
105                 if (bits)
106                 {
107                     flag_bits &= ~bits;
108                 }
109                 else
110                 {
111                     feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
112                     ListLogCategories(feedback_strm);
113                 }
114             }
115         }
116 
117         log->GetMask().Reset(flag_bits);
118         if (flag_bits == 0)
119         {
120             g_log_enabled = false;
121             log->SetStream(lldb::StreamSP());
122         }
123     }
124 
125     return;
126 }
127 
128 Log *
129 ProcessWindowsLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm)
130 {
131     // Try see if there already is a log - that way we can reuse its settings.
132     // We could reuse the log in toto, but we don't know that the stream is the same.
133     uint32_t flag_bits = 0;
134     if (g_log)
135         flag_bits = g_log->GetMask().Get();
136 
137     // Now make a new log with this stream if one was provided
138     if (log_stream_sp)
139     {
140         if (g_log)
141             g_log->SetStream(log_stream_sp);
142         else
143             g_log = new Log(log_stream_sp);
144     }
145 
146     if (g_log)
147     {
148         bool got_unknown_category = false;
149         for (; args[0]; args++)
150         {
151             const char *arg = args[0];
152             uint32_t bits = GetFlagBits(arg);
153 
154             if (bits)
155             {
156                 flag_bits |= bits;
157             }
158             else
159             {
160                 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
161                 if (got_unknown_category == false)
162                 {
163                     got_unknown_category = true;
164                     ListLogCategories (feedback_strm);
165                 }
166             }
167         }
168         if (flag_bits == 0)
169             flag_bits = WINDOWS_LOG_ALL;
170         g_log->GetMask().Reset(flag_bits);
171         g_log->GetOptions().Reset(log_options);
172         g_log_enabled = true;
173     }
174     return g_log;
175 }
176 
177 void
178 ProcessWindowsLog::ListLogCategories(Stream *strm)
179 {
180     strm->Printf("Logging categories for '%s':\n"
181                  "  all - turn on all available logging categories\n"
182                  "  break - log breakpoints\n"
183                  "  event - log low level debugger events\n"
184                  "  exception - log exception information\n"
185                  "  memory - log memory reads and writes\n"
186                  "  process - log process events and activities\n"
187                  "  registers - log register read/writes\n"
188                  "  thread - log thread events and activities\n"
189                  "  step - log step related activities\n"
190                  "  verbose - enable verbose logging\n",
191                  ProcessWindowsLog::m_pluginname);
192 }
193 
194 const char *ProcessWindowsLog::m_pluginname = "";
195