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