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 (::strncasecmp(arg, "watch", 5) == 0) 101 flag_bits &= ~GDBR_LOG_WATCHPOINTS; 102 else { 103 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 104 ListLogCategories(feedback_strm); 105 } 106 } 107 } 108 109 if (flag_bits == 0) 110 g_log_enabled = false; 111 else 112 log->GetMask().Reset(flag_bits); 113 } 114 115 return; 116 } 117 118 Log *ProcessGDBRemoteLog::EnableLog( 119 const std::shared_ptr<llvm::raw_ostream> &log_stream_sp, 120 uint32_t log_options, const char **categories, Stream *feedback_strm) { 121 // Try see if there already is a log - that way we can reuse its settings. 122 // We could reuse the log in toto, but we don't know that the stream is the 123 // same. 124 uint32_t flag_bits = 0; 125 if (g_log) 126 flag_bits = g_log->GetMask().Get(); 127 128 // Now make a new log with this stream if one was provided 129 if (log_stream_sp) { 130 if (g_log) 131 g_log->SetStream(log_stream_sp); 132 else 133 g_log = new Log(log_stream_sp); 134 } 135 136 if (g_log) { 137 bool got_unknown_category = false; 138 for (size_t i = 0; categories[i] != NULL; ++i) { 139 const char *arg = categories[i]; 140 141 if (::strcasecmp(arg, "all") == 0) 142 flag_bits |= GDBR_LOG_ALL; 143 else if (::strcasecmp(arg, "async") == 0) 144 flag_bits |= GDBR_LOG_ASYNC; 145 else if (::strncasecmp(arg, "break", 5) == 0) 146 flag_bits |= GDBR_LOG_BREAKPOINTS; 147 else if (::strncasecmp(arg, "comm", 4) == 0) 148 flag_bits |= GDBR_LOG_COMM; 149 else if (::strcasecmp(arg, "default") == 0) 150 flag_bits |= GDBR_LOG_DEFAULT; 151 else if (::strcasecmp(arg, "packets") == 0) 152 flag_bits |= GDBR_LOG_PACKETS; 153 else if (::strcasecmp(arg, "memory") == 0) 154 flag_bits |= GDBR_LOG_MEMORY; 155 else if (::strcasecmp(arg, "data-short") == 0) 156 flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT; 157 else if (::strcasecmp(arg, "data-long") == 0) 158 flag_bits |= GDBR_LOG_MEMORY_DATA_LONG; 159 else if (::strcasecmp(arg, "process") == 0) 160 flag_bits |= GDBR_LOG_PROCESS; 161 else if (::strcasecmp(arg, "step") == 0) 162 flag_bits |= GDBR_LOG_STEP; 163 else if (::strcasecmp(arg, "thread") == 0) 164 flag_bits |= GDBR_LOG_THREAD; 165 else if (::strncasecmp(arg, "watch", 5) == 0) 166 flag_bits |= GDBR_LOG_WATCHPOINTS; 167 else { 168 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 169 if (got_unknown_category == false) { 170 got_unknown_category = true; 171 ListLogCategories(feedback_strm); 172 } 173 } 174 } 175 if (flag_bits == 0) 176 flag_bits = GDBR_LOG_DEFAULT; 177 g_log->GetMask().Reset(flag_bits); 178 g_log->GetOptions().Reset(log_options); 179 } 180 g_log_enabled = true; 181 return g_log; 182 } 183 184 void ProcessGDBRemoteLog::ListLogCategories(Stream *strm) { 185 strm->Printf( 186 "Logging categories for '%s':\n" 187 " all - turn on all available logging categories\n" 188 " async - log asynchronous activity\n" 189 " break - log breakpoints\n" 190 " communication - log communication activity\n" 191 " default - enable the default set of logging categories for liblldb\n" 192 " packets - log gdb remote packets\n" 193 " memory - log memory reads and writes\n" 194 " data-short - log memory bytes for memory reads and writes for short " 195 "transactions only\n" 196 " data-long - log memory bytes for memory reads and writes for all " 197 "transactions\n" 198 " process - log process events and activities\n" 199 " thread - log thread events and activities\n" 200 " step - log step related activities\n" 201 " verbose - enable verbose logging\n" 202 " watch - log watchpoint related activities\n", 203 ProcessGDBRemote::GetPluginNameStatic().GetCString()); 204 } 205 206 void ProcessGDBRemoteLog::LogIf(uint32_t mask, const char *format, ...) { 207 Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(mask)); 208 if (log) { 209 va_list args; 210 va_start(args, format); 211 log->VAPrintf(format, args); 212 va_end(args); 213 } 214 } 215