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