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