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