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