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