| //===-- LogChannelDWARF.cpp ------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "LogChannelDWARF.h" |
| |
| #include "SymbolFileDWARF.h" |
| #include "lldb/Core/PluginManager.h" |
| #include "lldb/Core/StreamFile.h" |
| #include "lldb/Interpreter/Args.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| // when the one and only logging channel is enabled, then this will be non NULL. |
| static LogChannelDWARF *g_log_channel = NULL; |
| |
| LogChannelDWARF::LogChannelDWARF() : LogChannel() {} |
| |
| LogChannelDWARF::~LogChannelDWARF() {} |
| |
| void LogChannelDWARF::Initialize() { |
| PluginManager::RegisterPlugin(GetPluginNameStatic(), |
| GetPluginDescriptionStatic(), |
| LogChannelDWARF::CreateInstance); |
| } |
| |
| void LogChannelDWARF::Terminate() { |
| PluginManager::UnregisterPlugin(LogChannelDWARF::CreateInstance); |
| } |
| |
| LogChannel *LogChannelDWARF::CreateInstance() { return new LogChannelDWARF(); } |
| |
| lldb_private::ConstString LogChannelDWARF::GetPluginNameStatic() { |
| return SymbolFileDWARF::GetPluginNameStatic(); |
| } |
| |
| const char *LogChannelDWARF::GetPluginDescriptionStatic() { |
| return "DWARF log channel for debugging plug-in issues."; |
| } |
| |
| lldb_private::ConstString LogChannelDWARF::GetPluginName() { |
| return GetPluginNameStatic(); |
| } |
| |
| uint32_t LogChannelDWARF::GetPluginVersion() { return 1; } |
| |
| void LogChannelDWARF::Delete() { g_log_channel = NULL; } |
| |
| void LogChannelDWARF::Disable(const char **categories, Stream *feedback_strm) { |
| if (m_log_ap.get() == NULL) |
| return; |
| |
| uint32_t flag_bits = m_log_ap->GetMask().Get(); |
| for (size_t i = 0; categories[i] != NULL; ++i) { |
| const char *arg = categories[i]; |
| |
| if (::strcasecmp(arg, "all") == 0) |
| flag_bits &= ~DWARF_LOG_ALL; |
| else if (::strcasecmp(arg, "info") == 0) |
| flag_bits &= ~DWARF_LOG_DEBUG_INFO; |
| else if (::strcasecmp(arg, "line") == 0) |
| flag_bits &= ~DWARF_LOG_DEBUG_LINE; |
| else if (::strcasecmp(arg, "pubnames") == 0) |
| flag_bits &= ~DWARF_LOG_DEBUG_PUBNAMES; |
| else if (::strcasecmp(arg, "pubtypes") == 0) |
| flag_bits &= ~DWARF_LOG_DEBUG_PUBTYPES; |
| else if (::strcasecmp(arg, "aranges") == 0) |
| flag_bits &= ~DWARF_LOG_DEBUG_ARANGES; |
| else if (::strcasecmp(arg, "lookups") == 0) |
| flag_bits &= ~DWARF_LOG_LOOKUPS; |
| else if (::strcasecmp(arg, "map") == 0) |
| flag_bits &= ~DWARF_LOG_DEBUG_MAP; |
| else if (::strcasecmp(arg, "default") == 0) |
| flag_bits &= ~DWARF_LOG_DEFAULT; |
| else if (::strcasecmp(arg, "verbose") == 0) |
| flag_bits &= ~DWARF_LOG_VERBOSE; |
| else if (::strncasecmp(arg, "comp", 4) == 0) |
| flag_bits &= ~DWARF_LOG_TYPE_COMPLETION; |
| else { |
| feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); |
| ListCategories(feedback_strm); |
| } |
| } |
| |
| if (flag_bits == 0) |
| Delete(); |
| else |
| m_log_ap->GetMask().Reset(flag_bits); |
| |
| return; |
| } |
| |
| bool LogChannelDWARF::Enable( |
| StreamSP &log_stream_sp, uint32_t log_options, |
| Stream *feedback_strm, // Feedback stream for argument errors etc |
| const char **categories // The categories to enable within this logging |
| // stream, if empty, enable default set |
| ) { |
| Delete(); |
| |
| if (m_log_ap) |
| m_log_ap->SetStream(log_stream_sp); |
| else |
| m_log_ap.reset(new Log(log_stream_sp)); |
| |
| g_log_channel = this; |
| uint32_t flag_bits = 0; |
| bool got_unknown_category = false; |
| for (size_t i = 0; categories[i] != NULL; ++i) { |
| const char *arg = categories[i]; |
| |
| if (::strcasecmp(arg, "all") == 0) |
| flag_bits |= DWARF_LOG_ALL; |
| else if (::strcasecmp(arg, "info") == 0) |
| flag_bits |= DWARF_LOG_DEBUG_INFO; |
| else if (::strcasecmp(arg, "line") == 0) |
| flag_bits |= DWARF_LOG_DEBUG_LINE; |
| else if (::strcasecmp(arg, "pubnames") == 0) |
| flag_bits |= DWARF_LOG_DEBUG_PUBNAMES; |
| else if (::strcasecmp(arg, "pubtypes") == 0) |
| flag_bits |= DWARF_LOG_DEBUG_PUBTYPES; |
| else if (::strcasecmp(arg, "aranges") == 0) |
| flag_bits |= DWARF_LOG_DEBUG_ARANGES; |
| else if (::strcasecmp(arg, "lookups") == 0) |
| flag_bits |= DWARF_LOG_LOOKUPS; |
| else if (::strcasecmp(arg, "map") == 0) |
| flag_bits |= DWARF_LOG_DEBUG_MAP; |
| else if (::strcasecmp(arg, "default") == 0) |
| flag_bits |= DWARF_LOG_DEFAULT; |
| else if (::strcasecmp(arg, "verbose") == 0) |
| flag_bits |= DWARF_LOG_VERBOSE; |
| else if (::strncasecmp(arg, "comp", 4) == 0) |
| flag_bits |= DWARF_LOG_TYPE_COMPLETION; |
| else { |
| feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); |
| if (got_unknown_category == false) { |
| got_unknown_category = true; |
| ListCategories(feedback_strm); |
| } |
| } |
| } |
| if (flag_bits == 0) |
| flag_bits = DWARF_LOG_DEFAULT; |
| m_log_ap->GetMask().Reset(flag_bits); |
| m_log_ap->GetOptions().Reset(log_options); |
| return m_log_ap.get() != NULL; |
| } |
| |
| void LogChannelDWARF::ListCategories(Stream *strm) { |
| strm->Printf( |
| "Logging categories for '%s':\n" |
| " all - turn on all available logging categories\n" |
| " info - log the parsing of .debug_info\n" |
| " line - log the parsing of .debug_line\n" |
| " pubnames - log the parsing of .debug_pubnames\n" |
| " pubtypes - log the parsing of .debug_pubtypes\n" |
| " aranges - log the parsing of .debug_aranges\n" |
| " lookups - log any lookups that happen by name, regex, or address\n" |
| " completion - log struct/unions/class type completions\n" |
| " map - log insertions of object files into DWARF debug maps\n", |
| SymbolFileDWARF::GetPluginNameStatic().GetCString()); |
| } |
| |
| Log *LogChannelDWARF::GetLog() { |
| if (g_log_channel) |
| return g_log_channel->m_log_ap.get(); |
| |
| return NULL; |
| } |
| |
| Log *LogChannelDWARF::GetLogIfAll(uint32_t mask) { |
| if (g_log_channel && g_log_channel->m_log_ap.get()) { |
| if (g_log_channel->m_log_ap->GetMask().AllSet(mask)) |
| return g_log_channel->m_log_ap.get(); |
| } |
| return NULL; |
| } |
| |
| Log *LogChannelDWARF::GetLogIfAny(uint32_t mask) { |
| if (g_log_channel && g_log_channel->m_log_ap.get()) { |
| if (g_log_channel->m_log_ap->GetMask().AnySet(mask)) |
| return g_log_channel->m_log_ap.get(); |
| } |
| return NULL; |
| } |
| |
| void LogChannelDWARF::LogIf(uint32_t mask, const char *format, ...) { |
| if (g_log_channel) { |
| Log *log = g_log_channel->m_log_ap.get(); |
| if (log && log->GetMask().AnySet(mask)) { |
| va_list args; |
| va_start(args, format); |
| log->VAPrintf(format, args); |
| va_end(args); |
| } |
| } |
| } |