blob: d641979b0b045f92693cab30fd47f7080a778883 [file] [log] [blame]
Adrian McCarthy42b33802015-04-10 16:18:08 +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
Adrian McCarthy42b33802015-04-10 16:18:08 +000014#include "lldb/Core/StreamFile.h"
Zachary Turner610e5292015-05-07 21:39:33 +000015#include "lldb/Interpreter/Args.h"
Adrian McCarthy42b33802015-04-10 16:18:08 +000016#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;
Zachary Turner610e5292015-05-07 21:39:33 +000029static Log * g_log = nullptr;
Adrian McCarthy42b33802015-04-10 16:18:08 +000030
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
Zachary Turner610e5292015-05-07 21:39:33 +000050void
51ProcessWindowsLog::Terminate()
Adrian McCarthy42b33802015-04-10 16:18:08 +000052{
Zachary Turner610e5292015-05-07 21:39:33 +000053}
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);
Adrian McCarthy42b33802015-04-10 16:18:08 +000073}
74
75static uint32_t
76GetFlagBits(const char *arg)
77{
Zachary Turner610e5292015-05-07 21:39:33 +000078 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;
Adrian McCarthy42b33802015-04-10 16:18:08 +000088 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
99 flag_bits = log->GetMask().Get();
100 for (; args[0]; args++)
101 {
102 const char *arg = args[0];
103 uint32_t bits = GetFlagBits(arg);
104
105 if (bits)
106 {
107 flag_bits &= ~bits;
108 }
109 else
110 {
111 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
112 ListLogCategories(feedback_strm);
113 }
114 }
115
116 log->GetMask().Reset(flag_bits);
117 if (flag_bits == 0)
118 g_log_enabled = false;
119 }
120
121 return;
122}
123
124Log *
125ProcessWindowsLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm)
126{
127 // Try see if there already is a log - that way we can reuse its settings.
128 // We could reuse the log in toto, but we don't know that the stream is the same.
129 uint32_t flag_bits = 0;
130 if (g_log)
131 flag_bits = g_log->GetMask().Get();
132
133 // Now make a new log with this stream if one was provided
134 if (log_stream_sp)
135 {
136 if (g_log)
137 g_log->SetStream(log_stream_sp);
138 else
139 g_log = new Log(log_stream_sp);
140 }
141
142 if (g_log)
143 {
144 bool got_unknown_category = false;
145 for (; args[0]; args++)
146 {
147 const char *arg = args[0];
148 uint32_t bits = GetFlagBits(arg);
149
150 if (bits)
151 {
152 flag_bits |= bits;
153 }
154 else
155 {
156 feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
157 if (got_unknown_category == false)
158 {
159 got_unknown_category = true;
160 ListLogCategories (feedback_strm);
161 }
162 }
163 }
164 if (flag_bits == 0)
Zachary Turner610e5292015-05-07 21:39:33 +0000165 flag_bits = WINDOWS_LOG_ALL;
Adrian McCarthy42b33802015-04-10 16:18:08 +0000166 g_log->GetMask().Reset(flag_bits);
167 g_log->GetOptions().Reset(log_options);
168 g_log_enabled = true;
169 }
170 return g_log;
171}
172
173void
174ProcessWindowsLog::ListLogCategories(Stream *strm)
175{
Zachary Turner610e5292015-05-07 21:39:33 +0000176 strm->Printf("Logging categories for '%s':\n"
177 " all - turn on all available logging categories\n"
178 " break - log breakpoints\n"
179 " event - log low level debugger events\n"
180 " exception - log exception information\n"
181 " memory - log memory reads and writes\n"
182 " process - log process events and activities\n"
183 " registers - log register read/writes\n"
184 " thread - log thread events and activities\n"
185 " step - log step related activities\n"
186 " verbose - enable verbose logging\n",
187 ProcessWindowsLog::m_pluginname);
Adrian McCarthy42b33802015-04-10 16:18:08 +0000188}
189
Adrian McCarthy42b33802015-04-10 16:18:08 +0000190const char *ProcessWindowsLog::m_pluginname = "";