118a9135dSAdrian McCarthy //===-- ProcessWindowsLog.cpp -----------------------------------*- C++ -*-===// 218a9135dSAdrian McCarthy // 318a9135dSAdrian McCarthy // The LLVM Compiler Infrastructure 418a9135dSAdrian McCarthy // 518a9135dSAdrian McCarthy // This file is distributed under the University of Illinois Open Source 618a9135dSAdrian McCarthy // License. See LICENSE.TXT for details. 718a9135dSAdrian McCarthy // 818a9135dSAdrian McCarthy //===----------------------------------------------------------------------===// 918a9135dSAdrian McCarthy 1018a9135dSAdrian McCarthy #include "ProcessWindowsLog.h" 1118a9135dSAdrian McCarthy 1218a9135dSAdrian McCarthy #include <mutex> 1318a9135dSAdrian McCarthy 1418a9135dSAdrian McCarthy #include "lldb/Core/StreamFile.h" 1518a9135dSAdrian McCarthy #include "lldb/Interpreter/Args.h" 1618a9135dSAdrian McCarthy #include "llvm/Support/ManagedStatic.h" 1718a9135dSAdrian McCarthy 1818a9135dSAdrian McCarthy using namespace lldb; 1918a9135dSAdrian McCarthy using namespace lldb_private; 2018a9135dSAdrian McCarthy 2118a9135dSAdrian McCarthy // We want to avoid global constructors where code needs to be run so here we 2218a9135dSAdrian McCarthy // control access to our static g_log_sp by hiding it in a singleton function 2318a9135dSAdrian McCarthy // that will construct the static g_log_sp the first time this function is 2418a9135dSAdrian McCarthy // called. 2518a9135dSAdrian McCarthy static bool g_log_enabled = false; 2618a9135dSAdrian McCarthy static Log *g_log = nullptr; 2718a9135dSAdrian McCarthy 2818a9135dSAdrian McCarthy static llvm::ManagedStatic<std::once_flag> g_once_flag; 2918a9135dSAdrian McCarthy 30*b9c1b51eSKate Stone void ProcessWindowsLog::Initialize() { 3118a9135dSAdrian McCarthy static ConstString g_name("windows"); 3218a9135dSAdrian McCarthy 3318a9135dSAdrian McCarthy std::call_once(*g_once_flag, []() { 34*b9c1b51eSKate Stone Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories}; 3518a9135dSAdrian McCarthy 3618a9135dSAdrian McCarthy Log::RegisterLogChannel(g_name, log_callbacks); 3718a9135dSAdrian McCarthy RegisterPluginName(g_name); 3818a9135dSAdrian McCarthy }); 3918a9135dSAdrian McCarthy } 4018a9135dSAdrian McCarthy 41*b9c1b51eSKate Stone void ProcessWindowsLog::Terminate() {} 4218a9135dSAdrian McCarthy 43*b9c1b51eSKate Stone Log *ProcessWindowsLog::GetLog() { return (g_log_enabled) ? g_log : nullptr; } 4418a9135dSAdrian McCarthy 45*b9c1b51eSKate Stone bool ProcessWindowsLog::TestLogFlags(uint32_t mask, LogMaskReq req) { 4618a9135dSAdrian McCarthy Log *log = GetLog(); 4718a9135dSAdrian McCarthy if (!log) 4818a9135dSAdrian McCarthy return false; 4918a9135dSAdrian McCarthy 5018a9135dSAdrian McCarthy uint32_t log_mask = log->GetMask().Get(); 5118a9135dSAdrian McCarthy if (req == LogMaskReq::All) 5218a9135dSAdrian McCarthy return ((log_mask & mask) == mask); 5318a9135dSAdrian McCarthy else 5418a9135dSAdrian McCarthy return (log_mask & mask); 5518a9135dSAdrian McCarthy } 5618a9135dSAdrian McCarthy 57*b9c1b51eSKate Stone static uint32_t GetFlagBits(const char *arg) { 58*b9c1b51eSKate Stone if (::strcasecmp(arg, "all") == 0) 59*b9c1b51eSKate Stone return WINDOWS_LOG_ALL; 60*b9c1b51eSKate Stone else if (::strcasecmp(arg, "break") == 0) 61*b9c1b51eSKate Stone return WINDOWS_LOG_BREAKPOINTS; 62*b9c1b51eSKate Stone else if (::strcasecmp(arg, "event") == 0) 63*b9c1b51eSKate Stone return WINDOWS_LOG_EVENT; 64*b9c1b51eSKate Stone else if (::strcasecmp(arg, "exception") == 0) 65*b9c1b51eSKate Stone return WINDOWS_LOG_EXCEPTION; 66*b9c1b51eSKate Stone else if (::strcasecmp(arg, "memory") == 0) 67*b9c1b51eSKate Stone return WINDOWS_LOG_MEMORY; 68*b9c1b51eSKate Stone else if (::strcasecmp(arg, "process") == 0) 69*b9c1b51eSKate Stone return WINDOWS_LOG_PROCESS; 70*b9c1b51eSKate Stone else if (::strcasecmp(arg, "registers") == 0) 71*b9c1b51eSKate Stone return WINDOWS_LOG_REGISTERS; 72*b9c1b51eSKate Stone else if (::strcasecmp(arg, "step") == 0) 73*b9c1b51eSKate Stone return WINDOWS_LOG_STEP; 74*b9c1b51eSKate Stone else if (::strcasecmp(arg, "thread") == 0) 75*b9c1b51eSKate Stone return WINDOWS_LOG_THREAD; 76*b9c1b51eSKate Stone else if (::strcasecmp(arg, "verbose") == 0) 77*b9c1b51eSKate Stone return WINDOWS_LOG_VERBOSE; 7818a9135dSAdrian McCarthy return 0; 7918a9135dSAdrian McCarthy } 8018a9135dSAdrian McCarthy 81*b9c1b51eSKate Stone void ProcessWindowsLog::DisableLog(const char **args, Stream *feedback_strm) { 8218a9135dSAdrian McCarthy Log *log(GetLog()); 83*b9c1b51eSKate Stone if (log) { 8418a9135dSAdrian McCarthy uint32_t flag_bits = 0; 8518a9135dSAdrian McCarthy 86*b9c1b51eSKate Stone if (args[0] != nullptr) { 8718a9135dSAdrian McCarthy flag_bits = log->GetMask().Get(); 88*b9c1b51eSKate Stone for (; args[0]; args++) { 8918a9135dSAdrian McCarthy const char *arg = args[0]; 9018a9135dSAdrian McCarthy uint32_t bits = GetFlagBits(arg); 9118a9135dSAdrian McCarthy 92*b9c1b51eSKate Stone if (bits) { 9318a9135dSAdrian McCarthy flag_bits &= ~bits; 94*b9c1b51eSKate Stone } else { 9518a9135dSAdrian McCarthy feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 9618a9135dSAdrian McCarthy ListLogCategories(feedback_strm); 9718a9135dSAdrian McCarthy } 9818a9135dSAdrian McCarthy } 9918a9135dSAdrian McCarthy } 10018a9135dSAdrian McCarthy 10118a9135dSAdrian McCarthy log->GetMask().Reset(flag_bits); 102*b9c1b51eSKate Stone if (flag_bits == 0) { 10318a9135dSAdrian McCarthy g_log_enabled = false; 10418a9135dSAdrian McCarthy log->SetStream(lldb::StreamSP()); 10518a9135dSAdrian McCarthy } 10618a9135dSAdrian McCarthy } 10718a9135dSAdrian McCarthy 10818a9135dSAdrian McCarthy return; 10918a9135dSAdrian McCarthy } 11018a9135dSAdrian McCarthy 111*b9c1b51eSKate Stone Log *ProcessWindowsLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, 112*b9c1b51eSKate Stone const char **args, Stream *feedback_strm) { 11318a9135dSAdrian McCarthy // Try see if there already is a log - that way we can reuse its settings. 114*b9c1b51eSKate Stone // We could reuse the log in toto, but we don't know that the stream is the 115*b9c1b51eSKate Stone // same. 11618a9135dSAdrian McCarthy uint32_t flag_bits = 0; 11718a9135dSAdrian McCarthy if (g_log) 11818a9135dSAdrian McCarthy flag_bits = g_log->GetMask().Get(); 11918a9135dSAdrian McCarthy 12018a9135dSAdrian McCarthy // Now make a new log with this stream if one was provided 121*b9c1b51eSKate Stone if (log_stream_sp) { 12218a9135dSAdrian McCarthy if (g_log) 12318a9135dSAdrian McCarthy g_log->SetStream(log_stream_sp); 12418a9135dSAdrian McCarthy else 12518a9135dSAdrian McCarthy g_log = new Log(log_stream_sp); 12618a9135dSAdrian McCarthy } 12718a9135dSAdrian McCarthy 128*b9c1b51eSKate Stone if (g_log) { 12918a9135dSAdrian McCarthy bool got_unknown_category = false; 130*b9c1b51eSKate Stone for (; args[0]; args++) { 13118a9135dSAdrian McCarthy const char *arg = args[0]; 13218a9135dSAdrian McCarthy uint32_t bits = GetFlagBits(arg); 13318a9135dSAdrian McCarthy 134*b9c1b51eSKate Stone if (bits) { 13518a9135dSAdrian McCarthy flag_bits |= bits; 136*b9c1b51eSKate Stone } else { 13718a9135dSAdrian McCarthy feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 138*b9c1b51eSKate Stone if (got_unknown_category == false) { 13918a9135dSAdrian McCarthy got_unknown_category = true; 14018a9135dSAdrian McCarthy ListLogCategories(feedback_strm); 14118a9135dSAdrian McCarthy } 14218a9135dSAdrian McCarthy } 14318a9135dSAdrian McCarthy } 14418a9135dSAdrian McCarthy if (flag_bits == 0) 14518a9135dSAdrian McCarthy flag_bits = WINDOWS_LOG_ALL; 14618a9135dSAdrian McCarthy g_log->GetMask().Reset(flag_bits); 14718a9135dSAdrian McCarthy g_log->GetOptions().Reset(log_options); 14818a9135dSAdrian McCarthy g_log_enabled = true; 14918a9135dSAdrian McCarthy } 15018a9135dSAdrian McCarthy return g_log; 15118a9135dSAdrian McCarthy } 15218a9135dSAdrian McCarthy 153*b9c1b51eSKate Stone void ProcessWindowsLog::ListLogCategories(Stream *strm) { 15418a9135dSAdrian McCarthy strm->Printf("Logging categories for '%s':\n" 15518a9135dSAdrian McCarthy " all - turn on all available logging categories\n" 15618a9135dSAdrian McCarthy " break - log breakpoints\n" 15718a9135dSAdrian McCarthy " event - log low level debugger events\n" 15818a9135dSAdrian McCarthy " exception - log exception information\n" 15918a9135dSAdrian McCarthy " memory - log memory reads and writes\n" 16018a9135dSAdrian McCarthy " process - log process events and activities\n" 16118a9135dSAdrian McCarthy " registers - log register read/writes\n" 16218a9135dSAdrian McCarthy " thread - log thread events and activities\n" 16318a9135dSAdrian McCarthy " step - log step related activities\n" 16418a9135dSAdrian McCarthy " verbose - enable verbose logging\n", 16518a9135dSAdrian McCarthy ProcessWindowsLog::m_pluginname); 16618a9135dSAdrian McCarthy } 16718a9135dSAdrian McCarthy 16818a9135dSAdrian McCarthy const char *ProcessWindowsLog::m_pluginname = ""; 169