//===-- 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 "lldb/Interpreter/Args.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamFile.h" #include "SymbolFileDWARF.h" using namespace lldb; using namespace lldb_private; // when the one and only logging channel is abled, 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 (::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 (::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 if .debug_info\n" " line - log the parsing if .debug_line\n" " pubnames - log the parsing if .debug_pubnames\n" " pubtypes - log the parsing if .debug_pubtypes\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); } } }