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