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     m_log_sp.reset();
90 }
91 
92 
93 void
94 LogChannelDWARF::Disable (Args &categories, Stream *feedback_strm)
95 {
96     if (!m_log_sp)
97         return;
98 
99     g_log_channel = this;
100     uint32_t flag_bits = m_log_sp->GetMask().Get();
101     const size_t argc = categories.GetArgumentCount();
102     for (size_t i = 0; i < argc; ++i)
103     {
104          const char *arg = categories.GetArgumentAtIndex(i);
105 
106         if      (::strcasecmp (arg, "all")        == 0   ) flag_bits &= ~DWARF_LOG_ALL;
107         else if (::strcasecmp (arg, "info")       == 0   ) flag_bits &= ~DWARF_LOG_DEBUG_INFO;
108         else if (::strcasecmp (arg, "line")       == 0   ) flag_bits &= ~DWARF_LOG_DEBUG_LINE;
109         else if (::strcasecmp (arg, "pubnames")   == 0   ) flag_bits &= ~DWARF_LOG_DEBUG_PUBNAMES;
110         else if (::strcasecmp (arg, "pubtypes")   == 0   ) flag_bits &= ~DWARF_LOG_DEBUG_PUBTYPES;
111         else if (::strcasecmp (arg, "default")    == 0   ) flag_bits &= ~DWARF_LOG_DEFAULT;
112         else
113         {
114             feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
115             ListCategories (feedback_strm);
116         }
117    }
118 
119     if (flag_bits == 0)
120         Delete ();
121     else
122         m_log_sp->GetMask().Reset (flag_bits);
123 
124     return;
125 }
126 
127 bool
128 LogChannelDWARF::Enable
129 (
130     StreamSP &log_stream_sp,
131     uint32_t log_options,
132     Stream *feedback_strm,  // Feedback stream for argument errors etc
133     const Args &categories  // The categories to enable within this logging stream, if empty, enable default set
134 )
135 {
136     Delete ();
137 
138     m_log_sp.reset(new Log (log_stream_sp));
139     g_log_channel = this;
140     uint32_t flag_bits = 0;
141     bool got_unknown_category = false;
142     const size_t argc = categories.GetArgumentCount();
143     for (size_t i=0; i<argc; ++i)
144     {
145         const char *arg = categories.GetArgumentAtIndex(i);
146 
147         if      (::strcasecmp (arg, "all")        == 0   ) flag_bits |= DWARF_LOG_ALL;
148         else if (::strcasecmp (arg, "info")       == 0   ) flag_bits |= DWARF_LOG_DEBUG_INFO;
149         else if (::strcasecmp (arg, "line")       == 0   ) flag_bits |= DWARF_LOG_DEBUG_LINE;
150         else if (::strcasecmp (arg, "pubnames")   == 0   ) flag_bits |= DWARF_LOG_DEBUG_PUBNAMES;
151         else if (::strcasecmp (arg, "pubtypes")   == 0   ) flag_bits |= DWARF_LOG_DEBUG_PUBTYPES;
152         else if (::strcasecmp (arg, "default")    == 0   ) flag_bits |= DWARF_LOG_DEFAULT;
153         else
154         {
155             feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
156             if (got_unknown_category == false)
157             {
158                 got_unknown_category = true;
159                 ListCategories (feedback_strm);
160             }
161         }
162     }
163     if (flag_bits == 0)
164         flag_bits = DWARF_LOG_DEFAULT;
165     m_log_sp->GetMask().Reset(flag_bits);
166     m_log_sp->GetOptions().Reset(log_options);
167     return m_log_sp.get() != NULL;
168 }
169 
170 void
171 LogChannelDWARF::ListCategories (Stream *strm)
172 {
173     strm->Printf("Logging categories for '%s':\n"
174         "   all - turn on all available logging categories\n"
175         "   info - log the parsing if .debug_info\n"
176         "   line - log the parsing if .debug_line\n"
177         "   pubnames - log the parsing if .debug_pubnames\n"
178         "   pubtypes - log the parsing if .debug_pubtypes\n\n",
179         SymbolFileDWARF::GetPluginNameStatic());
180 }
181 
182 Log *
183 LogChannelDWARF::GetLog ()
184 {
185     if (g_log_channel)
186         return g_log_channel->m_log_sp.get();
187     else
188         return NULL;
189 }
190 
191 Log *
192 LogChannelDWARF::GetLogIfAll (uint32_t mask)
193 {
194     Log *log = GetLog();
195     if (log)
196     {
197         if (log->GetMask().AllSet(mask))
198             return log;
199     }
200     return NULL;
201 }
202 
203 
204 void
205 LogChannelDWARF::LogIf (uint32_t mask, const char *format, ...)
206 {
207     if (g_log_channel)
208     {
209         LogSP log_sp(g_log_channel->m_log_sp);
210         va_list args;
211         va_start (args, format);
212         log_sp->VAPrintf (format, args);
213         va_end (args);
214     }
215 }
216