1 //===-- ProcessGDBRemoteLog.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 "ProcessGDBRemoteLog.h" 11 12 #include <mutex> 13 14 #include "lldb/Core/StreamFile.h" 15 #include "lldb/Interpreter/Args.h" 16 17 #include "llvm/Support/Threading.h" 18 19 #include "ProcessGDBRemote.h" 20 21 using namespace lldb; 22 using namespace lldb_private; 23 using namespace lldb_private::process_gdb_remote; 24 25 // We want to avoid global constructors where code needs to be run so here we 26 // control access to our static g_log_sp by hiding it in a singleton function 27 // that will construct the static g_lob_sp the first time this function is 28 // called. 29 static bool g_log_enabled = false; 30 static Log *g_log = NULL; 31 static Log *GetLog() { 32 if (!g_log_enabled) 33 return NULL; 34 return g_log; 35 } 36 37 void ProcessGDBRemoteLog::Initialize() { 38 static ConstString g_name("gdb-remote"); 39 static llvm::once_flag g_once_flag; 40 41 llvm::call_once(g_once_flag, []() { 42 Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories}; 43 44 Log::RegisterLogChannel(g_name, log_callbacks); 45 }); 46 } 47 48 Log *ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(uint32_t mask) { 49 Log *log(GetLog()); 50 if (log && mask) { 51 uint32_t log_mask = log->GetMask().Get(); 52 if ((log_mask & mask) != mask) 53 return NULL; 54 } 55 return log; 56 } 57 58 Log *ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(uint32_t mask) { 59 Log *log(GetLog()); 60 if (log && log->GetMask().Get() & mask) 61 return log; 62 return NULL; 63 } 64 65 void ProcessGDBRemoteLog::DisableLog(const char **categories, 66 Stream *feedback_strm) { 67 Log *log(GetLog()); 68 if (log) { 69 uint32_t flag_bits = 0; 70 71 if (categories && categories[0]) { 72 flag_bits = log->GetMask().Get(); 73 for (size_t i = 0; categories[i] != NULL; ++i) { 74 const char *arg = categories[i]; 75 76 if (::strcasecmp(arg, "all") == 0) 77 flag_bits &= ~GDBR_LOG_ALL; 78 else if (::strcasecmp(arg, "async") == 0) 79 flag_bits &= ~GDBR_LOG_ASYNC; 80 else if (::strncasecmp(arg, "break", 5) == 0) 81 flag_bits &= ~GDBR_LOG_BREAKPOINTS; 82 else if (::strncasecmp(arg, "comm", 4) == 0) 83 flag_bits &= ~GDBR_LOG_COMM; 84 else if (::strcasecmp(arg, "default") == 0) 85 flag_bits &= ~GDBR_LOG_DEFAULT; 86 else if (::strcasecmp(arg, "packets") == 0) 87 flag_bits &= ~GDBR_LOG_PACKETS; 88 else if (::strcasecmp(arg, "memory") == 0) 89 flag_bits &= ~GDBR_LOG_MEMORY; 90 else if (::strcasecmp(arg, "data-short") == 0) 91 flag_bits &= ~GDBR_LOG_MEMORY_DATA_SHORT; 92 else if (::strcasecmp(arg, "data-long") == 0) 93 flag_bits &= ~GDBR_LOG_MEMORY_DATA_LONG; 94 else if (::strcasecmp(arg, "process") == 0) 95 flag_bits &= ~GDBR_LOG_PROCESS; 96 else if (::strcasecmp(arg, "step") == 0) 97 flag_bits &= ~GDBR_LOG_STEP; 98 else if (::strcasecmp(arg, "thread") == 0) 99 flag_bits &= ~GDBR_LOG_THREAD; 100 else if (::strcasecmp(arg, "verbose") == 0) 101 flag_bits &= ~GDBR_LOG_VERBOSE; 102 else if (::strncasecmp(arg, "watch", 5) == 0) 103 flag_bits &= ~GDBR_LOG_WATCHPOINTS; 104 else { 105 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 106 ListLogCategories(feedback_strm); 107 } 108 } 109 } 110 111 if (flag_bits == 0) 112 g_log_enabled = false; 113 else 114 log->GetMask().Reset(flag_bits); 115 } 116 117 return; 118 } 119 120 Log *ProcessGDBRemoteLog::EnableLog(StreamSP &log_stream_sp, 121 uint32_t log_options, 122 const char **categories, 123 Stream *feedback_strm) { 124 // Try see if there already is a log - that way we can reuse its settings. 125 // We could reuse the log in toto, but we don't know that the stream is the 126 // same. 127 uint32_t flag_bits = 0; 128 if (g_log) 129 flag_bits = g_log->GetMask().Get(); 130 131 // Now make a new log with this stream if one was provided 132 if (log_stream_sp) { 133 if (g_log) 134 g_log->SetStream(log_stream_sp); 135 else 136 g_log = new Log(log_stream_sp); 137 } 138 139 if (g_log) { 140 bool got_unknown_category = false; 141 for (size_t i = 0; categories[i] != NULL; ++i) { 142 const char *arg = categories[i]; 143 144 if (::strcasecmp(arg, "all") == 0) 145 flag_bits |= GDBR_LOG_ALL; 146 else if (::strcasecmp(arg, "async") == 0) 147 flag_bits |= GDBR_LOG_ASYNC; 148 else if (::strncasecmp(arg, "break", 5) == 0) 149 flag_bits |= GDBR_LOG_BREAKPOINTS; 150 else if (::strncasecmp(arg, "comm", 4) == 0) 151 flag_bits |= GDBR_LOG_COMM; 152 else if (::strcasecmp(arg, "default") == 0) 153 flag_bits |= GDBR_LOG_DEFAULT; 154 else if (::strcasecmp(arg, "packets") == 0) 155 flag_bits |= GDBR_LOG_PACKETS; 156 else if (::strcasecmp(arg, "memory") == 0) 157 flag_bits |= GDBR_LOG_MEMORY; 158 else if (::strcasecmp(arg, "data-short") == 0) 159 flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT; 160 else if (::strcasecmp(arg, "data-long") == 0) 161 flag_bits |= GDBR_LOG_MEMORY_DATA_LONG; 162 else if (::strcasecmp(arg, "process") == 0) 163 flag_bits |= GDBR_LOG_PROCESS; 164 else if (::strcasecmp(arg, "step") == 0) 165 flag_bits |= GDBR_LOG_STEP; 166 else if (::strcasecmp(arg, "thread") == 0) 167 flag_bits |= GDBR_LOG_THREAD; 168 else if (::strcasecmp(arg, "verbose") == 0) 169 flag_bits |= GDBR_LOG_VERBOSE; 170 else if (::strncasecmp(arg, "watch", 5) == 0) 171 flag_bits |= GDBR_LOG_WATCHPOINTS; 172 else { 173 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 174 if (got_unknown_category == false) { 175 got_unknown_category = true; 176 ListLogCategories(feedback_strm); 177 } 178 } 179 } 180 if (flag_bits == 0) 181 flag_bits = GDBR_LOG_DEFAULT; 182 g_log->GetMask().Reset(flag_bits); 183 g_log->GetOptions().Reset(log_options); 184 } 185 g_log_enabled = true; 186 return g_log; 187 } 188 189 void ProcessGDBRemoteLog::ListLogCategories(Stream *strm) { 190 strm->Printf( 191 "Logging categories for '%s':\n" 192 " all - turn on all available logging categories\n" 193 " async - log asynchronous activity\n" 194 " break - log breakpoints\n" 195 " communication - log communication activity\n" 196 " default - enable the default set of logging categories for liblldb\n" 197 " packets - log gdb remote packets\n" 198 " memory - log memory reads and writes\n" 199 " data-short - log memory bytes for memory reads and writes for short " 200 "transactions only\n" 201 " data-long - log memory bytes for memory reads and writes for all " 202 "transactions\n" 203 " process - log process events and activities\n" 204 " thread - log thread events and activities\n" 205 " step - log step related activities\n" 206 " verbose - enable verbose logging\n" 207 " watch - log watchpoint related activities\n", 208 ProcessGDBRemote::GetPluginNameStatic().GetCString()); 209 } 210 211 void ProcessGDBRemoteLog::LogIf(uint32_t mask, const char *format, ...) { 212 Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(mask)); 213 if (log) { 214 va_list args; 215 va_start(args, format); 216 log->VAPrintf(format, args); 217 va_end(args); 218 } 219 } 220