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( 94 const std::shared_ptr<llvm::raw_ostream> &log_stream_sp, 95 uint32_t log_options, const char **categories, Stream *feedback_strm) { 96 // Try see if there already is a log - that way we can reuse its settings. 97 // We could reuse the log in toto, but we don't know that the stream is the 98 // same. 99 uint32_t flag_bits = 0; 100 if (g_log) 101 flag_bits = g_log->GetMask().Get(); 102 103 // Now make a new log with this stream if one was provided 104 if (log_stream_sp) { 105 if (g_log) 106 g_log->SetStream(log_stream_sp); 107 else 108 g_log = new Log(log_stream_sp); 109 } 110 111 if (g_log) { 112 bool got_unknown_category = false; 113 for (size_t i = 0; categories[i] != NULL; ++i) { 114 const char *arg = categories[i]; 115 116 if (::strcasecmp(arg, "all") == 0) 117 flag_bits |= KDP_LOG_ALL; 118 else if (::strcasecmp(arg, "async") == 0) 119 flag_bits |= KDP_LOG_ASYNC; 120 else if (::strncasecmp(arg, "break", 5) == 0) 121 flag_bits |= KDP_LOG_BREAKPOINTS; 122 else if (::strncasecmp(arg, "comm", 4) == 0) 123 flag_bits |= KDP_LOG_COMM; 124 else if (::strcasecmp(arg, "default") == 0) 125 flag_bits |= KDP_LOG_DEFAULT; 126 else if (::strcasecmp(arg, "packets") == 0) 127 flag_bits |= KDP_LOG_PACKETS; 128 else if (::strcasecmp(arg, "memory") == 0) 129 flag_bits |= KDP_LOG_MEMORY; 130 else if (::strcasecmp(arg, "data-short") == 0) 131 flag_bits |= KDP_LOG_MEMORY_DATA_SHORT; 132 else if (::strcasecmp(arg, "data-long") == 0) 133 flag_bits |= KDP_LOG_MEMORY_DATA_LONG; 134 else if (::strcasecmp(arg, "process") == 0) 135 flag_bits |= KDP_LOG_PROCESS; 136 else if (::strcasecmp(arg, "step") == 0) 137 flag_bits |= KDP_LOG_STEP; 138 else if (::strcasecmp(arg, "thread") == 0) 139 flag_bits |= KDP_LOG_THREAD; 140 else if (::strncasecmp(arg, "watch", 5) == 0) 141 flag_bits |= KDP_LOG_WATCHPOINTS; 142 else { 143 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); 144 if (got_unknown_category == false) { 145 got_unknown_category = true; 146 ListLogCategories(feedback_strm); 147 } 148 } 149 } 150 if (flag_bits == 0) 151 flag_bits = KDP_LOG_DEFAULT; 152 g_log->GetMask().Reset(flag_bits); 153 g_log->GetOptions().Reset(log_options); 154 } 155 g_log_enabled = true; 156 return g_log; 157 } 158 159 void ProcessKDPLog::ListLogCategories(Stream *strm) { 160 strm->Printf( 161 "Logging categories for '%s':\n" 162 " all - turn on all available logging categories\n" 163 " async - log asynchronous activity\n" 164 " break - log breakpoints\n" 165 " communication - log communication activity\n" 166 " default - enable the default set of logging categories for liblldb\n" 167 " packets - log gdb remote packets\n" 168 " memory - log memory reads and writes\n" 169 " data-short - log memory bytes for memory reads and writes for short " 170 "transactions only\n" 171 " data-long - log memory bytes for memory reads and writes for all " 172 "transactions\n" 173 " process - log process events and activities\n" 174 " thread - log thread events and activities\n" 175 " step - log step related activities\n" 176 " verbose - enable verbose logging\n" 177 " watch - log watchpoint related activities\n", 178 ProcessKDP::GetPluginNameStatic().GetCString()); 179 } 180 181 void ProcessKDPLog::LogIf(uint32_t mask, const char *format, ...) { 182 Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(mask)); 183 if (log) { 184 va_list args; 185 va_start(args, format); 186 log->VAPrintf(format, args); 187 va_end(args); 188 } 189 } 190