1 //===-- LogChannelDWARF.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 "LogChannelDWARF.h"
11 
12 #include "SymbolFileDWARF.h"
13 #include "lldb/Core/PluginManager.h"
14 #include "lldb/Core/StreamFile.h"
15 #include "lldb/Interpreter/Args.h"
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 
20 // when the one and only logging channel is enabled, then this will be non NULL.
21 static LogChannelDWARF *g_log_channel = NULL;
22 
23 LogChannelDWARF::LogChannelDWARF() : LogChannel() {}
24 
25 LogChannelDWARF::~LogChannelDWARF() {}
26 
27 void LogChannelDWARF::Initialize() {
28   PluginManager::RegisterPlugin(GetPluginNameStatic(),
29                                 GetPluginDescriptionStatic(),
30                                 LogChannelDWARF::CreateInstance);
31 }
32 
33 void LogChannelDWARF::Terminate() {
34   PluginManager::UnregisterPlugin(LogChannelDWARF::CreateInstance);
35 }
36 
37 LogChannel *LogChannelDWARF::CreateInstance() { return new LogChannelDWARF(); }
38 
39 lldb_private::ConstString LogChannelDWARF::GetPluginNameStatic() {
40   return SymbolFileDWARF::GetPluginNameStatic();
41 }
42 
43 const char *LogChannelDWARF::GetPluginDescriptionStatic() {
44   return "DWARF log channel for debugging plug-in issues.";
45 }
46 
47 lldb_private::ConstString LogChannelDWARF::GetPluginName() {
48   return GetPluginNameStatic();
49 }
50 
51 uint32_t LogChannelDWARF::GetPluginVersion() { return 1; }
52 
53 void LogChannelDWARF::Delete() { g_log_channel = NULL; }
54 
55 void LogChannelDWARF::Disable(const char **categories, Stream *feedback_strm) {
56   if (m_log_ap.get() == NULL)
57     return;
58 
59   uint32_t flag_bits = m_log_ap->GetMask().Get();
60   for (size_t i = 0; categories[i] != NULL; ++i) {
61     const char *arg = categories[i];
62 
63     if (::strcasecmp(arg, "all") == 0)
64       flag_bits &= ~DWARF_LOG_ALL;
65     else if (::strcasecmp(arg, "info") == 0)
66       flag_bits &= ~DWARF_LOG_DEBUG_INFO;
67     else if (::strcasecmp(arg, "line") == 0)
68       flag_bits &= ~DWARF_LOG_DEBUG_LINE;
69     else if (::strcasecmp(arg, "pubnames") == 0)
70       flag_bits &= ~DWARF_LOG_DEBUG_PUBNAMES;
71     else if (::strcasecmp(arg, "pubtypes") == 0)
72       flag_bits &= ~DWARF_LOG_DEBUG_PUBTYPES;
73     else if (::strcasecmp(arg, "aranges") == 0)
74       flag_bits &= ~DWARF_LOG_DEBUG_ARANGES;
75     else if (::strcasecmp(arg, "lookups") == 0)
76       flag_bits &= ~DWARF_LOG_LOOKUPS;
77     else if (::strcasecmp(arg, "map") == 0)
78       flag_bits &= ~DWARF_LOG_DEBUG_MAP;
79     else if (::strcasecmp(arg, "default") == 0)
80       flag_bits &= ~DWARF_LOG_DEFAULT;
81     else if (::strncasecmp(arg, "comp", 4) == 0)
82       flag_bits &= ~DWARF_LOG_TYPE_COMPLETION;
83     else {
84       feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
85       ListCategories(feedback_strm);
86     }
87   }
88 
89   if (flag_bits == 0)
90     Delete();
91   else
92     m_log_ap->GetMask().Reset(flag_bits);
93 
94   return;
95 }
96 
97 bool LogChannelDWARF::Enable(
98     const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
99     uint32_t log_options,
100     Stream *feedback_strm,  // Feedback stream for argument errors etc
101     const char **categories // The categories to enable within this logging
102                             // stream, if empty, enable default set
103     ) {
104   Delete();
105 
106   if (m_log_ap)
107     m_log_ap->SetStream(log_stream_sp);
108   else
109     m_log_ap.reset(new Log(log_stream_sp));
110 
111   g_log_channel = this;
112   uint32_t flag_bits = 0;
113   bool got_unknown_category = false;
114   for (size_t i = 0; categories[i] != NULL; ++i) {
115     const char *arg = categories[i];
116 
117     if (::strcasecmp(arg, "all") == 0)
118       flag_bits |= DWARF_LOG_ALL;
119     else if (::strcasecmp(arg, "info") == 0)
120       flag_bits |= DWARF_LOG_DEBUG_INFO;
121     else if (::strcasecmp(arg, "line") == 0)
122       flag_bits |= DWARF_LOG_DEBUG_LINE;
123     else if (::strcasecmp(arg, "pubnames") == 0)
124       flag_bits |= DWARF_LOG_DEBUG_PUBNAMES;
125     else if (::strcasecmp(arg, "pubtypes") == 0)
126       flag_bits |= DWARF_LOG_DEBUG_PUBTYPES;
127     else if (::strcasecmp(arg, "aranges") == 0)
128       flag_bits |= DWARF_LOG_DEBUG_ARANGES;
129     else if (::strcasecmp(arg, "lookups") == 0)
130       flag_bits |= DWARF_LOG_LOOKUPS;
131     else if (::strcasecmp(arg, "map") == 0)
132       flag_bits |= DWARF_LOG_DEBUG_MAP;
133     else if (::strcasecmp(arg, "default") == 0)
134       flag_bits |= DWARF_LOG_DEFAULT;
135     else if (::strncasecmp(arg, "comp", 4) == 0)
136       flag_bits |= DWARF_LOG_TYPE_COMPLETION;
137     else {
138       feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
139       if (got_unknown_category == false) {
140         got_unknown_category = true;
141         ListCategories(feedback_strm);
142       }
143     }
144   }
145   if (flag_bits == 0)
146     flag_bits = DWARF_LOG_DEFAULT;
147   m_log_ap->GetMask().Reset(flag_bits);
148   m_log_ap->GetOptions().Reset(log_options);
149   return m_log_ap.get() != NULL;
150 }
151 
152 void LogChannelDWARF::ListCategories(Stream *strm) {
153   strm->Printf(
154       "Logging categories for '%s':\n"
155       "  all - turn on all available logging categories\n"
156       "  info - log the parsing of .debug_info\n"
157       "  line - log the parsing of .debug_line\n"
158       "  pubnames - log the parsing of .debug_pubnames\n"
159       "  pubtypes - log the parsing of .debug_pubtypes\n"
160       "  aranges - log the parsing of .debug_aranges\n"
161       "  lookups - log any lookups that happen by name, regex, or address\n"
162       "  completion - log struct/unions/class type completions\n"
163       "  map - log insertions of object files into DWARF debug maps\n",
164       SymbolFileDWARF::GetPluginNameStatic().GetCString());
165 }
166 
167 Log *LogChannelDWARF::GetLog() {
168   if (g_log_channel)
169     return g_log_channel->m_log_ap.get();
170 
171   return NULL;
172 }
173 
174 Log *LogChannelDWARF::GetLogIfAll(uint32_t mask) {
175   if (g_log_channel && g_log_channel->m_log_ap.get()) {
176     if (g_log_channel->m_log_ap->GetMask().AllSet(mask))
177       return g_log_channel->m_log_ap.get();
178   }
179   return NULL;
180 }
181 
182 Log *LogChannelDWARF::GetLogIfAny(uint32_t mask) {
183   if (g_log_channel && g_log_channel->m_log_ap.get()) {
184     if (g_log_channel->m_log_ap->GetMask().AnySet(mask))
185       return g_log_channel->m_log_ap.get();
186   }
187   return NULL;
188 }
189 
190 void LogChannelDWARF::LogIf(uint32_t mask, const char *format, ...) {
191   if (g_log_channel) {
192     Log *log = g_log_channel->m_log_ap.get();
193     if (log && log->GetMask().AnySet(mask)) {
194       va_list args;
195       va_start(args, format);
196       log->VAPrintf(format, args);
197       va_end(args);
198     }
199   }
200 }
201