diff --git a/lldb/include/lldb/Interpreter/ScriptedInterface.h b/lldb/include/lldb/Interpreter/ScriptedInterface.h --- a/lldb/include/lldb/Interpreter/ScriptedInterface.h +++ b/lldb/include/lldb/Interpreter/ScriptedInterface.h @@ -31,8 +31,7 @@ template Ret ErrorWithMessage(llvm::StringRef caller_name, llvm::StringRef error_msg, - Status &error, - uint32_t log_caterogy = LIBLLDB_LOG_PROCESS) { + Status &error, LLDBLog log_caterogy = LLDBLog::Process) { LLDB_LOGF(GetLogIfAllCategoriesSet(log_caterogy), "%s ERROR = %s", caller_name.data(), error_msg.data()); error.SetErrorString(llvm::Twine(caller_name + llvm::Twine(" ERROR = ") + diff --git a/lldb/include/lldb/Utility/Log.h b/lldb/include/lldb/Utility/Log.h --- a/lldb/include/lldb/Utility/Log.h +++ b/lldb/include/lldb/Utility/Log.h @@ -10,7 +10,6 @@ #define LLDB_UTILITY_LOG_H #include "lldb/Utility/Flags.h" -#include "lldb/Utility/Logging.h" #include "lldb/lldb-defines.h" #include "llvm/ADT/ArrayRef.h" @@ -48,11 +47,31 @@ class Log final { public: + /// The underlying type of all log channel enums. Declare them as: + /// enum class MyLog : MaskType { + /// Channel0 = Log::ChannelFlag<0>, + /// Channel1 = Log::ChannelFlag<1>, + /// ..., + /// LLVM_MARK_AS_BITMASK_ENUM(LastChannel), + /// }; + using MaskType = uint64_t; + + template + static constexpr MaskType ChannelFlag = MaskType(1) << Bit; + // Description of a log channel category. struct Category { llvm::StringLiteral name; llvm::StringLiteral description; - uint32_t flag; + MaskType flag; + + template + constexpr Category(llvm::StringLiteral name, + llvm::StringLiteral description, Cat mask) + : name(name), description(description), flag(MaskType(mask)) { + static_assert( + std::is_same>::value, ""); + } }; // This class describes a log channel. It also encapsulates the behavior @@ -63,18 +82,22 @@ public: const llvm::ArrayRef categories; - const uint32_t default_flags; + const MaskType default_flags; + template constexpr Channel(llvm::ArrayRef categories, - uint32_t default_flags) + Cat default_flags) : log_ptr(nullptr), categories(categories), - default_flags(default_flags) {} + default_flags(MaskType(default_flags)) { + static_assert( + std::is_same>::value, ""); + } // This function is safe to call at any time. If the channel is disabled // after (or concurrently with) this function returning a non-null Log // pointer, it is still safe to attempt to write to the Log object -- the // output will be discarded. - Log *GetLogIfAll(uint32_t mask) { + Log *GetLogIfAll(MaskType mask) { Log *log = log_ptr.load(std::memory_order_relaxed); if (log && log->GetMask().AllSet(mask)) return log; @@ -85,7 +108,7 @@ // after (or concurrently with) this function returning a non-null Log // pointer, it is still safe to attempt to write to the Log object -- the // output will be discarded. - Log *GetLogIfAny(uint32_t mask) { + Log *GetLogIfAny(MaskType mask) { Log *log = log_ptr.load(std::memory_order_relaxed); if (log && log->GetMask().AnySet(mask)) return log; @@ -180,7 +203,7 @@ std::shared_ptr m_stream_sp; std::atomic m_options{0}; - std::atomic m_mask{0}; + std::atomic m_mask{0}; void WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file, llvm::StringRef function); @@ -215,6 +238,19 @@ void operator=(const Log &) = delete; }; +// Must be specialized for a particular log type. +template Log::Channel &LogChannelFor() = delete; + +/// Retrieve the Log object for the channel associated with the given log enum. +/// +/// Returns a valid Log object if any of the provided categories are enabled. +/// Otherwise, returns nullptr. +template Log *GetLog(Cat mask) { + static_assert(std::is_same>::value, + ""); + return LogChannelFor().GetLogIfAny(Log::MaskType(mask)); +} + } // namespace lldb_private /// The LLDB_LOG* macros defined below are the way to emit log messages. @@ -272,3 +308,6 @@ } while (0) #endif // LLDB_UTILITY_LOG_H + +// TODO: Remove this and fix includes everywhere. +#include "lldb/Utility/Logging.h" diff --git a/lldb/include/lldb/Utility/Logging.h b/lldb/include/lldb/Utility/Logging.h --- a/lldb/include/lldb/Utility/Logging.h +++ b/lldb/include/lldb/Utility/Logging.h @@ -9,57 +9,89 @@ #ifndef LLDB_UTILITY_LOGGING_H #define LLDB_UTILITY_LOGGING_H +#include "lldb/Utility/Log.h" +#include "llvm/ADT/BitmaskEnum.h" #include -// Log Bits specific to logging in lldb -#define LIBLLDB_LOG_PROCESS (1u << 1) -#define LIBLLDB_LOG_THREAD (1u << 2) -#define LIBLLDB_LOG_DYNAMIC_LOADER (1u << 3) -#define LIBLLDB_LOG_EVENTS (1u << 4) -#define LIBLLDB_LOG_BREAKPOINTS (1u << 5) -#define LIBLLDB_LOG_WATCHPOINTS (1u << 6) -#define LIBLLDB_LOG_STEP (1u << 7) -#define LIBLLDB_LOG_EXPRESSIONS (1u << 8) -#define LIBLLDB_LOG_TEMPORARY (1u << 9) -#define LIBLLDB_LOG_STATE (1u << 10) -#define LIBLLDB_LOG_OBJECT (1u << 11) -#define LIBLLDB_LOG_COMMUNICATION (1u << 12) -#define LIBLLDB_LOG_CONNECTION (1u << 13) -#define LIBLLDB_LOG_HOST (1u << 14) -#define LIBLLDB_LOG_UNWIND (1u << 15) -#define LIBLLDB_LOG_API (1u << 16) -#define LIBLLDB_LOG_SCRIPT (1u << 17) -#define LIBLLDB_LOG_COMMANDS (1U << 18) -#define LIBLLDB_LOG_TYPES (1u << 19) -#define LIBLLDB_LOG_SYMBOLS (1u << 20) -#define LIBLLDB_LOG_MODULES (1u << 21) -#define LIBLLDB_LOG_TARGET (1u << 22) -#define LIBLLDB_LOG_MMAP (1u << 23) -#define LIBLLDB_LOG_OS (1u << 24) -#define LIBLLDB_LOG_PLATFORM (1u << 25) -#define LIBLLDB_LOG_SYSTEM_RUNTIME (1u << 26) -#define LIBLLDB_LOG_JIT_LOADER (1u << 27) -#define LIBLLDB_LOG_LANGUAGE (1u << 28) -#define LIBLLDB_LOG_DATAFORMATTERS (1u << 29) -#define LIBLLDB_LOG_DEMANGLE (1u << 30) -#define LIBLLDB_LOG_AST (1u << 31) -#define LIBLLDB_LOG_ALL (UINT32_MAX) -#define LIBLLDB_LOG_DEFAULT \ - (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD | LIBLLDB_LOG_DYNAMIC_LOADER | \ - LIBLLDB_LOG_BREAKPOINTS | LIBLLDB_LOG_WATCHPOINTS | LIBLLDB_LOG_STEP | \ - LIBLLDB_LOG_STATE | LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_TARGET | \ - LIBLLDB_LOG_COMMANDS) - namespace lldb_private { -class Log; +enum class LLDBLog : Log::MaskType { + API = Log::ChannelFlag<0>, + AST = Log::ChannelFlag<1>, + Breakpoints = Log::ChannelFlag<2>, + Commands = Log::ChannelFlag<3>, + Communication = Log::ChannelFlag<4>, + Connection = Log::ChannelFlag<5>, + DataFormatters = Log::ChannelFlag<6>, + Demangle = Log::ChannelFlag<7>, + DynamicLoader = Log::ChannelFlag<8>, + Events = Log::ChannelFlag<9>, + Expressions = Log::ChannelFlag<10>, + Host = Log::ChannelFlag<11>, + JITLoader = Log::ChannelFlag<12>, + Language = Log::ChannelFlag<13>, + MMap = Log::ChannelFlag<14>, + Modules = Log::ChannelFlag<15>, + Object = Log::ChannelFlag<16>, + OS = Log::ChannelFlag<17>, + Platform = Log::ChannelFlag<18>, + Process = Log::ChannelFlag<19>, + Script = Log::ChannelFlag<20>, + State = Log::ChannelFlag<21>, + Step = Log::ChannelFlag<22>, + Symbols = Log::ChannelFlag<23>, + SystemRuntime = Log::ChannelFlag<24>, + Target = Log::ChannelFlag<25>, + Temporary = Log::ChannelFlag<26>, + Thread = Log::ChannelFlag<27>, + Types = Log::ChannelFlag<28>, + Unwind = Log::ChannelFlag<29>, + Watchpoints = Log::ChannelFlag<30>, + LLVM_MARK_AS_BITMASK_ENUM(Watchpoints), +}; + +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + +// Log Bits specific to logging in lldb +#define LIBLLDB_LOG_PROCESS ::lldb_private::LLDBLog::Process +#define LIBLLDB_LOG_THREAD ::lldb_private::LLDBLog::Thread +#define LIBLLDB_LOG_DYNAMIC_LOADER ::lldb_private::LLDBLog::DynamicLoader +#define LIBLLDB_LOG_EVENTS ::lldb_private::LLDBLog::Events +#define LIBLLDB_LOG_BREAKPOINTS ::lldb_private::LLDBLog::Breakpoints +#define LIBLLDB_LOG_WATCHPOINTS ::lldb_private::LLDBLog::Watchpoints +#define LIBLLDB_LOG_STEP ::lldb_private::LLDBLog::Step +#define LIBLLDB_LOG_EXPRESSIONS ::lldb_private::LLDBLog::Expressions +#define LIBLLDB_LOG_TEMPORARY ::lldb_private::LLDBLog::Temporary +#define LIBLLDB_LOG_STATE ::lldb_private::LLDBLog::State +#define LIBLLDB_LOG_OBJECT ::lldb_private::LLDBLog::Object +#define LIBLLDB_LOG_COMMUNICATION ::lldb_private::LLDBLog::Communication +#define LIBLLDB_LOG_CONNECTION ::lldb_private::LLDBLog::Connection +#define LIBLLDB_LOG_HOST ::lldb_private::LLDBLog::Host +#define LIBLLDB_LOG_UNWIND ::lldb_private::LLDBLog::Unwind +#define LIBLLDB_LOG_API ::lldb_private::LLDBLog::API +#define LIBLLDB_LOG_SCRIPT ::lldb_private::LLDBLog::Script +#define LIBLLDB_LOG_COMMANDS ::lldb_private::LLDBLog::Commands +#define LIBLLDB_LOG_TYPES ::lldb_private::LLDBLog::Types +#define LIBLLDB_LOG_SYMBOLS ::lldb_private::LLDBLog::Symbols +#define LIBLLDB_LOG_MODULES ::lldb_private::LLDBLog::Modules +#define LIBLLDB_LOG_TARGET ::lldb_private::LLDBLog::Target +#define LIBLLDB_LOG_MMAP ::lldb_private::LLDBLog::MMap +#define LIBLLDB_LOG_OS ::lldb_private::LLDBLog::OS +#define LIBLLDB_LOG_PLATFORM ::lldb_private::LLDBLog::Platform +#define LIBLLDB_LOG_SYSTEM_RUNTIME ::lldb_private::LLDBLog::SystemRuntime +#define LIBLLDB_LOG_JIT_LOADER ::lldb_private::LLDBLog::JITLoader +#define LIBLLDB_LOG_LANGUAGE ::lldb_private::LLDBLog::Language +#define LIBLLDB_LOG_DATAFORMATTERS ::lldb_private::LLDBLog::DataFormatters +#define LIBLLDB_LOG_DEMANGLE ::lldb_private::LLDBLog::Demangle +#define LIBLLDB_LOG_AST ::lldb_private::LLDBLog::AST -Log *GetLogIfAllCategoriesSet(uint32_t mask); +Log *GetLogIfAllCategoriesSet(LLDBLog mask); -Log *GetLogIfAnyCategoriesSet(uint32_t mask); +Log *GetLogIfAnyCategoriesSet(LLDBLog mask); void InitializeLldbChannel(); +template <> Log::Channel &LogChannelFor(); } // namespace lldb_private #endif // LLDB_UTILITY_LOGGING_H diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h --- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h +++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.h @@ -13,27 +13,35 @@ #include "lldb/Utility/Log.h" -#define POSIX_LOG_PROCESS (1u << 1) -#define POSIX_LOG_THREAD (1u << 2) -#define POSIX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define POSIX_LOG_PTRACE (1u << 5) -#define POSIX_LOG_REGISTERS (1u << 6) -#define POSIX_LOG_BREAKPOINTS (1u << 7) -#define POSIX_LOG_WATCHPOINTS (1u << 8) -#define POSIX_LOG_ALL (UINT32_MAX) -#define POSIX_LOG_DEFAULT POSIX_LOG_PROCESS - namespace lldb_private { -class ProcessPOSIXLog { - static Log::Channel g_channel; +enum class POSIXLog : Log::MaskType { + Breakpoints = Log::ChannelFlag<0>, + Memory = Log::ChannelFlag<1>, + Process = Log::ChannelFlag<2>, + Ptrace = Log::ChannelFlag<3>, + Registers = Log::ChannelFlag<4>, + Thread = Log::ChannelFlag<5>, + Watchpoints = Log::ChannelFlag<6>, + LLVM_MARK_AS_BITMASK_ENUM(Watchpoints) +}; + +#define POSIX_LOG_PROCESS ::lldb_private::POSIXLog::Process +#define POSIX_LOG_THREAD ::lldb_private::POSIXLog::Thread +#define POSIX_LOG_MEMORY ::lldb_private::POSIXLog::Memory +#define POSIX_LOG_PTRACE ::lldb_private::POSIXLog::Ptrace +#define POSIX_LOG_REGISTERS ::lldb_private::POSIXLog::Registers +#define POSIX_LOG_BREAKPOINTS ::lldb_private::POSIXLog::Breakpoints +#define POSIX_LOG_WATCHPOINTS ::lldb_private::POSIXLog::Watchpoints + +class ProcessPOSIXLog { public: static void Initialize(); - static Log *GetLogIfAllCategoriesSet(uint32_t mask) { - return g_channel.GetLogIfAll(mask); - } + static Log *GetLogIfAllCategoriesSet(POSIXLog mask) { return GetLog(mask); } }; -} + +template <> Log::Channel &LogChannelFor(); +} // namespace lldb_private #endif // liblldb_ProcessPOSIXLog_h_ diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp --- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp +++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp @@ -13,16 +13,20 @@ using namespace lldb_private; static constexpr Log::Category g_categories[] = { - {{"break"}, {"log breakpoints"}, POSIX_LOG_BREAKPOINTS}, - {{"memory"}, {"log memory reads and writes"}, POSIX_LOG_MEMORY}, - {{"process"}, {"log process events and activities"}, POSIX_LOG_PROCESS}, - {{"ptrace"}, {"log all calls to ptrace"}, POSIX_LOG_PTRACE}, - {{"registers"}, {"log register read/writes"}, POSIX_LOG_REGISTERS}, - {{"thread"}, {"log thread events and activities"}, POSIX_LOG_THREAD}, - {{"watch"}, {"log watchpoint related activities"}, POSIX_LOG_WATCHPOINTS}, + {{"break"}, {"log breakpoints"}, POSIXLog::Breakpoints}, + {{"memory"}, {"log memory reads and writes"}, POSIXLog::Memory}, + {{"process"}, {"log process events and activities"}, POSIXLog::Process}, + {{"ptrace"}, {"log all calls to ptrace"}, POSIXLog::Ptrace}, + {{"registers"}, {"log register read/writes"}, POSIXLog::Registers}, + {{"thread"}, {"log thread events and activities"}, POSIXLog::Thread}, + {{"watch"}, {"log watchpoint related activities"}, POSIXLog::Watchpoints}, }; -Log::Channel ProcessPOSIXLog::g_channel(g_categories, POSIX_LOG_DEFAULT); +static Log::Channel g_channel(g_categories, POSIXLog::Process); + +template <> Log::Channel &lldb_private::LogChannelFor() { + return g_channel; +} void ProcessPOSIXLog::Initialize() { static llvm::once_flag g_once_flag; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1086,7 +1086,7 @@ } void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { - Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM)); + Log *log = GetLog(GDBRLog::Comm); bool interrupt = false; bool done = false; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -529,7 +529,7 @@ } Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) { - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + Log *log = GetLog(GDBRLog::Process); Status error(WillLaunchOrAttach()); if (error.Fail()) @@ -606,8 +606,7 @@ ReadModuleFromMemory(FileSpec(namebuf), standalone_value); } - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet( - LIBLLDB_LOG_DYNAMIC_LOADER)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (module_sp.get()) { target.GetImages().AppendIfNeeded(module_sp, false); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h @@ -11,35 +11,52 @@ #include "lldb/Utility/Log.h" -#define GDBR_LOG_PROCESS (1u << 1) -#define GDBR_LOG_THREAD (1u << 2) -#define GDBR_LOG_PACKETS (1u << 3) -#define GDBR_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define GDBR_LOG_MEMORY_DATA_SHORT \ - (1u << 5) // Log short memory reads/writes bytes -#define GDBR_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes -#define GDBR_LOG_BREAKPOINTS (1u << 7) -#define GDBR_LOG_WATCHPOINTS (1u << 8) -#define GDBR_LOG_STEP (1u << 9) -#define GDBR_LOG_COMM (1u << 10) -#define GDBR_LOG_ASYNC (1u << 11) -#define GDBR_LOG_ALL (UINT32_MAX) -#define GDBR_LOG_DEFAULT GDBR_LOG_PACKETS - namespace lldb_private { namespace process_gdb_remote { -class ProcessGDBRemoteLog { - static Log::Channel g_channel; +enum class GDBRLog : Log::MaskType { + Async = Log::ChannelFlag<0>, + Breakpoints = Log::ChannelFlag<1>, + Comm = Log::ChannelFlag<2>, + Memory = Log::ChannelFlag<3>, // Log memory reads/writes calls + MemoryDataLong = Log::ChannelFlag<4>, // Log all memory reads/writes bytes + MemoryDataShort = Log::ChannelFlag<5>, // Log short memory reads/writes bytes + Packets = Log::ChannelFlag<6>, + Process = Log::ChannelFlag<7>, + Step = Log::ChannelFlag<8>, + Thread = Log::ChannelFlag<9>, + Watchpoints = Log::ChannelFlag<10>, + LLVM_MARK_AS_BITMASK_ENUM(Watchpoints) +}; +#define GDBR_LOG_PROCESS ::lldb_private::process_gdb_remote::GDBRLog::Process +#define GDBR_LOG_THREAD ::lldb_private::process_gdb_remote::GDBRLog::Thread +#define GDBR_LOG_PACKETS ::lldb_private::process_gdb_remote::GDBRLog::Packets +#define GDBR_LOG_MEMORY ::lldb_private::process_gdb_remote::GDBRLog::Memory +#define GDBR_LOG_MEMORY_DATA_SHORT \ + ::lldb_private::process_gdb_remote::GDBRLog::MemoryDataShort +#define GDBR_LOG_MEMORY_DATA_LONG \ + ::lldb_private::process_gdb_remote::GDBRLog::MemoryDataLong +#define GDBR_LOG_BREAKPOINTS \ + ::lldb_private::process_gdb_remote::GDBRLog::Breakpoints +#define GDBR_LOG_WATCHPOINTS \ + ::lldb_private::process_gdb_remote::GDBRLog::Watchpoints +#define GDBR_LOG_STEP ::lldb_private::process_gdb_remote::GDBRLog::Step +#define GDBR_LOG_COMM ::lldb_private::process_gdb_remote::GDBRLog::Comm +#define GDBR_LOG_ASYNC ::lldb_private::process_gdb_remote::GDBRLog::Async + +class ProcessGDBRemoteLog { public: static void Initialize(); - static Log *GetLogIfAllCategoriesSet(uint32_t mask) { return g_channel.GetLogIfAll(mask); } - static Log *GetLogIfAnyCategoryIsSet(uint32_t mask) { return g_channel.GetLogIfAny(mask); } + static Log *GetLogIfAllCategoriesSet(GDBRLog mask) { return GetLog(mask); } + static Log *GetLogIfAnyCategoryIsSet(GDBRLog mask) { return GetLog(mask); } }; } // namespace process_gdb_remote + +template <> Log::Channel &LogChannelFor(); + } // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_PROCESSGDBREMOTELOG_H diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp @@ -15,25 +15,29 @@ using namespace lldb_private::process_gdb_remote; static constexpr Log::Category g_categories[] = { - {{"async"}, {"log asynchronous activity"}, GDBR_LOG_ASYNC}, - {{"break"}, {"log breakpoints"}, GDBR_LOG_BREAKPOINTS}, - {{"comm"}, {"log communication activity"}, GDBR_LOG_COMM}, - {{"packets"}, {"log gdb remote packets"}, GDBR_LOG_PACKETS}, - {{"memory"}, {"log memory reads and writes"}, GDBR_LOG_MEMORY}, + {{"async"}, {"log asynchronous activity"}, GDBRLog::Async}, + {{"break"}, {"log breakpoints"}, GDBRLog::Breakpoints}, + {{"comm"}, {"log communication activity"}, GDBRLog::Comm}, + {{"packets"}, {"log gdb remote packets"}, GDBRLog::Packets}, + {{"memory"}, {"log memory reads and writes"}, GDBRLog::Memory}, {{"data-short"}, {"log memory bytes for memory reads and writes for short transactions " "only"}, - GDBR_LOG_MEMORY_DATA_SHORT}, + GDBRLog::MemoryDataShort}, {{"data-long"}, {"log memory bytes for memory reads and writes for all transactions"}, - GDBR_LOG_MEMORY_DATA_LONG}, - {{"process"}, {"log process events and activities"}, GDBR_LOG_PROCESS}, - {{"step"}, {"log step related activities"}, GDBR_LOG_STEP}, - {{"thread"}, {"log thread events and activities"}, GDBR_LOG_THREAD}, - {{"watch"}, {"log watchpoint related activities"}, GDBR_LOG_WATCHPOINTS}, + GDBRLog::MemoryDataLong}, + {{"process"}, {"log process events and activities"}, GDBRLog::Process}, + {{"step"}, {"log step related activities"}, GDBRLog::Step}, + {{"thread"}, {"log thread events and activities"}, GDBRLog::Thread}, + {{"watch"}, {"log watchpoint related activities"}, GDBRLog::Watchpoints}, }; -Log::Channel ProcessGDBRemoteLog::g_channel(g_categories, GDBR_LOG_DEFAULT); +static Log::Channel g_channel(g_categories, GDBRLog::Packets); + +template <> Log::Channel &lldb_private::LogChannelFor() { + return g_channel; +} void ProcessGDBRemoteLog::Initialize() { static llvm::once_flag g_once_flag; diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -39,7 +39,7 @@ m_dispatch_queue_t(LLDB_INVALID_ADDRESS), m_queue_kind(eQueueKindUnknown), m_queue_serial_number(LLDB_INVALID_QUEUE_ID), m_associated_with_libdispatch_queue(eLazyBoolCalculate) { - Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + Log *log = GetLog(GDBRLog::Thread); LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this, process.GetID(), GetID()); // At this point we can clone reg_info for architectures supporting @@ -54,7 +54,7 @@ ThreadGDBRemote::~ThreadGDBRemote() { ProcessSP process_sp(GetProcess()); - Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + Log *log = GetLog(GDBRLog::Thread); LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this, process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, GetID()); DestroyThread(); @@ -222,7 +222,7 @@ StructuredData::ObjectSP ThreadGDBRemote::FetchThreadExtendedInfo() { StructuredData::ObjectSP object_sp; const lldb::user_id_t tid = GetProtocolID(); - Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + Log *log = GetLog(GDBRLog::Thread); LLDB_LOGF(log, "Fetching extended information for thread %4.4" PRIx64, tid); ProcessSP process_sp(GetProcess()); if (process_sp) { @@ -236,7 +236,7 @@ void ThreadGDBRemote::WillResume(StateType resume_state) { int signo = GetResumeSignal(); const lldb::user_id_t tid = GetProtocolID(); - Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + Log *log = GetLog(GDBRLog::Thread); LLDB_LOGF(log, "Resuming thread: %4.4" PRIx64 " with state: %s.", tid, StateAsCString(resume_state)); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h --- a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h @@ -11,25 +11,32 @@ #include "lldb/Utility/Log.h" -#define DWARF_LOG_DEBUG_INFO (1u << 1) -#define DWARF_LOG_DEBUG_LINE (1u << 2) -#define DWARF_LOG_LOOKUPS (1u << 3) -#define DWARF_LOG_TYPE_COMPLETION (1u << 4) -#define DWARF_LOG_DEBUG_MAP (1u << 5) -#define DWARF_LOG_ALL (UINT32_MAX) -#define DWARF_LOG_DEFAULT (DWARF_LOG_DEBUG_INFO) - namespace lldb_private { -class LogChannelDWARF { - static Log::Channel g_channel; +enum class DWARFLog : Log::MaskType { + DebugInfo = Log::ChannelFlag<0>, + DebugLine = Log::ChannelFlag<1>, + DebugMap = Log::ChannelFlag<2>, + Lookups = Log::ChannelFlag<3>, + TypeCompletion = Log::ChannelFlag<4>, + LLVM_MARK_AS_BITMASK_ENUM(TypeCompletion) +}; +#define DWARF_LOG_DEBUG_INFO ::lldb_private::DWARFLog::DebugInfo +#define DWARF_LOG_DEBUG_LINE ::lldb_private::DWARFLog::DebugLine +#define DWARF_LOG_LOOKUPS ::lldb_private::DWARFLog::Lookups +#define DWARF_LOG_TYPE_COMPLETION ::lldb_private::DWARFLog::TypeCompletion +#define DWARF_LOG_DEBUG_MAP ::lldb_private::DWARFLog::DebugMap + +class LogChannelDWARF { public: static void Initialize(); static void Terminate(); - static Log *GetLogIfAll(uint32_t mask) { return g_channel.GetLogIfAll(mask); } - static Log *GetLogIfAny(uint32_t mask) { return g_channel.GetLogIfAny(mask); } + static Log *GetLogIfAll(DWARFLog mask) { return GetLog(mask); } + static Log *GetLogIfAny(DWARFLog mask) { return GetLog(mask); } }; -} + +template <> Log::Channel &LogChannelFor(); +} // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_LOGCHANNELDWARF_H diff --git a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp @@ -13,18 +13,20 @@ static constexpr Log::Category g_categories[] = { {{"comp"}, {"log insertions of object files into DWARF debug maps"}, - DWARF_LOG_TYPE_COMPLETION}, - {{"info"}, {"log the parsing of .debug_info"}, DWARF_LOG_DEBUG_INFO}, - {{"line"}, {"log the parsing of .debug_line"}, DWARF_LOG_DEBUG_LINE}, + DWARFLog::TypeCompletion}, + {{"info"}, {"log the parsing of .debug_info"}, DWARFLog::DebugInfo}, + {{"line"}, {"log the parsing of .debug_line"}, DWARFLog::DebugLine}, {{"lookups"}, {"log any lookups that happen by name, regex, or address"}, - DWARF_LOG_LOOKUPS}, - {{"map"}, - {"log struct/unions/class type completions"}, - DWARF_LOG_DEBUG_MAP}, + DWARFLog::Lookups}, + {{"map"}, {"log struct/unions/class type completions"}, DWARFLog::DebugMap}, }; -Log::Channel LogChannelDWARF::g_channel(g_categories, DWARF_LOG_DEFAULT); +static Log::Channel g_channel(g_categories, DWARFLog::DebugInfo); + +template <> Log::Channel &lldb_private::LogChannelFor() { + return g_channel; +} void LogChannelDWARF::Initialize() { Log::Register("dwarf", g_channel); diff --git a/lldb/source/Utility/Log.cpp b/lldb/source/Utility/Log.cpp --- a/lldb/source/Utility/Log.cpp +++ b/lldb/source/Utility/Log.cpp @@ -88,7 +88,7 @@ uint32_t options, uint32_t flags) { llvm::sys::ScopedWriter lock(m_mutex); - uint32_t mask = m_mask.fetch_or(flags, std::memory_order_relaxed); + MaskType mask = m_mask.fetch_or(flags, std::memory_order_relaxed); if (mask | flags) { m_options.store(options, std::memory_order_relaxed); m_stream_sp = stream_sp; @@ -99,7 +99,7 @@ void Log::Disable(uint32_t flags) { llvm::sys::ScopedWriter lock(m_mutex); - uint32_t mask = m_mask.fetch_and(~flags, std::memory_order_relaxed); + MaskType mask = m_mask.fetch_and(~flags, std::memory_order_relaxed); if (!(mask & ~flags)) { m_stream_sp.reset(); m_channel.log_ptr.store(nullptr, std::memory_order_relaxed); diff --git a/lldb/source/Utility/Logging.cpp b/lldb/source/Utility/Logging.cpp --- a/lldb/source/Utility/Logging.cpp +++ b/lldb/source/Utility/Logging.cpp @@ -16,49 +16,74 @@ using namespace lldb_private; static constexpr Log::Category g_categories[] = { - {{"api"}, {"log API calls and return values"}, LIBLLDB_LOG_API}, - {{"ast"}, {"log AST"}, LIBLLDB_LOG_AST}, - {{"break"}, {"log breakpoints"}, LIBLLDB_LOG_BREAKPOINTS}, - {{"commands"}, {"log command argument parsing"}, LIBLLDB_LOG_COMMANDS}, - {{"comm"}, {"log communication activities"}, LIBLLDB_LOG_COMMUNICATION}, - {{"conn"}, {"log connection details"}, LIBLLDB_LOG_CONNECTION}, - {{"demangle"}, {"log mangled names to catch demangler crashes"}, LIBLLDB_LOG_DEMANGLE}, - {{"dyld"}, {"log shared library related activities"}, LIBLLDB_LOG_DYNAMIC_LOADER}, - {{"event"}, {"log broadcaster, listener and event queue activities"}, LIBLLDB_LOG_EVENTS}, - {{"expr"}, {"log expressions"}, LIBLLDB_LOG_EXPRESSIONS}, - {{"formatters"}, {"log data formatters related activities"}, LIBLLDB_LOG_DATAFORMATTERS}, - {{"host"}, {"log host activities"}, LIBLLDB_LOG_HOST}, - {{"jit"}, {"log JIT events in the target"}, LIBLLDB_LOG_JIT_LOADER}, - {{"language"}, {"log language runtime events"}, LIBLLDB_LOG_LANGUAGE}, - {{"mmap"}, {"log mmap related activities"}, LIBLLDB_LOG_MMAP}, - {{"module"}, {"log module activities such as when modules are created, destroyed, replaced, and more"}, LIBLLDB_LOG_MODULES}, - {{"object"}, {"log object construction/destruction for important objects"}, LIBLLDB_LOG_OBJECT}, - {{"os"}, {"log OperatingSystem plugin related activities"}, LIBLLDB_LOG_OS}, - {{"platform"}, {"log platform events and activities"}, LIBLLDB_LOG_PLATFORM}, - {{"process"}, {"log process events and activities"}, LIBLLDB_LOG_PROCESS}, - {{"script"}, {"log events about the script interpreter"}, LIBLLDB_LOG_SCRIPT}, - {{"state"}, {"log private and public process state changes"}, LIBLLDB_LOG_STATE}, - {{"step"}, {"log step related activities"}, LIBLLDB_LOG_STEP}, - {{"symbol"}, {"log symbol related issues and warnings"}, LIBLLDB_LOG_SYMBOLS}, - {{"system-runtime"}, {"log system runtime events"}, LIBLLDB_LOG_SYSTEM_RUNTIME}, - {{"target"}, {"log target events and activities"}, LIBLLDB_LOG_TARGET}, - {{"temp"}, {"log internal temporary debug messages"}, LIBLLDB_LOG_TEMPORARY}, - {{"thread"}, {"log thread events and activities"}, LIBLLDB_LOG_THREAD}, - {{"types"}, {"log type system related activities"}, LIBLLDB_LOG_TYPES}, - {{"unwind"}, {"log stack unwind activities"}, LIBLLDB_LOG_UNWIND}, - {{"watch"}, {"log watchpoint related activities"}, LIBLLDB_LOG_WATCHPOINTS}, + {{"api"}, {"log API calls and return values"}, LLDBLog::API}, + {{"ast"}, {"log AST"}, LLDBLog::AST}, + {{"break"}, {"log breakpoints"}, LLDBLog::Breakpoints}, + {{"commands"}, {"log command argument parsing"}, LLDBLog::Commands}, + {{"comm"}, {"log communication activities"}, LLDBLog::Communication}, + {{"conn"}, {"log connection details"}, LLDBLog::Connection}, + {{"demangle"}, + {"log mangled names to catch demangler crashes"}, + LLDBLog::Demangle}, + {{"dyld"}, + {"log shared library related activities"}, + LLDBLog::DynamicLoader}, + {{"event"}, + {"log broadcaster, listener and event queue activities"}, + LLDBLog::Events}, + {{"expr"}, {"log expressions"}, LLDBLog::Expressions}, + {{"formatters"}, + {"log data formatters related activities"}, + LLDBLog::DataFormatters}, + {{"host"}, {"log host activities"}, LLDBLog::Host}, + {{"jit"}, {"log JIT events in the target"}, LLDBLog::JITLoader}, + {{"language"}, {"log language runtime events"}, LLDBLog::Language}, + {{"mmap"}, {"log mmap related activities"}, LLDBLog::MMap}, + {{"module"}, + {"log module activities such as when modules are created, destroyed, " + "replaced, and more"}, + LLDBLog::Modules}, + {{"object"}, + {"log object construction/destruction for important objects"}, + LLDBLog::Object}, + {{"os"}, {"log OperatingSystem plugin related activities"}, LLDBLog::OS}, + {{"platform"}, {"log platform events and activities"}, LLDBLog::Platform}, + {{"process"}, {"log process events and activities"}, LLDBLog::Process}, + {{"script"}, {"log events about the script interpreter"}, LLDBLog::Script}, + {{"state"}, + {"log private and public process state changes"}, + LLDBLog::State}, + {{"step"}, {"log step related activities"}, LLDBLog::Step}, + {{"symbol"}, {"log symbol related issues and warnings"}, LLDBLog::Symbols}, + {{"system-runtime"}, {"log system runtime events"}, LLDBLog::SystemRuntime}, + {{"target"}, {"log target events and activities"}, LLDBLog::Target}, + {{"temp"}, {"log internal temporary debug messages"}, LLDBLog::Temporary}, + {{"thread"}, {"log thread events and activities"}, LLDBLog::Thread}, + {{"types"}, {"log type system related activities"}, LLDBLog::Types}, + {{"unwind"}, {"log stack unwind activities"}, LLDBLog::Unwind}, + {{"watch"}, {"log watchpoint related activities"}, LLDBLog::Watchpoints}, }; -static Log::Channel g_log_channel(g_categories, LIBLLDB_LOG_DEFAULT); +static Log::Channel g_log_channel(g_categories, + LLDBLog::Process | LLDBLog::Thread | + LLDBLog::DynamicLoader | + LLDBLog::Breakpoints | + LLDBLog::Watchpoints | LLDBLog::Step | + LLDBLog::State | LLDBLog::Symbols | + LLDBLog::Target | LLDBLog::Commands); + +template <> Log::Channel &lldb_private::LogChannelFor() { + return g_log_channel; +} void lldb_private::InitializeLldbChannel() { Log::Register("lldb", g_log_channel); } -Log *lldb_private::GetLogIfAllCategoriesSet(uint32_t mask) { - return g_log_channel.GetLogIfAll(mask); +Log *lldb_private::GetLogIfAllCategoriesSet(LLDBLog mask) { + return GetLog(mask); } -Log *lldb_private::GetLogIfAnyCategoriesSet(uint32_t mask) { - return g_log_channel.GetLogIfAny(mask); +Log *lldb_private::GetLogIfAnyCategoriesSet(LLDBLog mask) { + return GetLog(mask); } diff --git a/lldb/tools/lldb-server/lldb-gdbserver.cpp b/lldb/tools/lldb-server/lldb-gdbserver.cpp --- a/lldb/tools/lldb-server/lldb-gdbserver.cpp +++ b/lldb/tools/lldb-server/lldb-gdbserver.cpp @@ -27,6 +27,7 @@ #include "lldb/Host/Socket.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/Logging.h" #include "lldb/Utility/Status.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/ArgList.h" diff --git a/lldb/unittests/Utility/LogTest.cpp b/lldb/unittests/Utility/LogTest.cpp --- a/lldb/unittests/Utility/LogTest.cpp +++ b/lldb/unittests/Utility/LogTest.cpp @@ -18,13 +18,24 @@ using namespace lldb; using namespace lldb_private; -enum { FOO = 1, BAR = 2 }; +enum class TestChannel : Log::MaskType { + FOO = Log::ChannelFlag<0>, + BAR = Log::ChannelFlag<1>, + LLVM_MARK_AS_BITMASK_ENUM(BAR), +}; + +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + static constexpr Log::Category test_categories[] = { - {{"foo"}, {"log foo"}, FOO}, {{"bar"}, {"log bar"}, BAR}, + {{"foo"}, {"log foo"}, TestChannel::FOO}, + {{"bar"}, {"log bar"}, TestChannel::BAR}, }; -static constexpr uint32_t default_flags = FOO; -static Log::Channel test_channel(test_categories, default_flags); +static Log::Channel test_channel(test_categories, TestChannel::FOO); + +namespace lldb_private { +template <> Log::Channel &LogChannelFor() { return test_channel; } +} // namespace lldb_private // Wrap enable, disable and list functions to make them easier to test. static bool EnableChannel(std::shared_ptr stream_sp, @@ -93,7 +104,7 @@ std::string error; ASSERT_TRUE(EnableChannel(m_stream_sp, 0, "chan", {}, error)); - m_log = test_channel.GetLogIfAll(FOO); + m_log = GetLog(TestChannel::FOO); ASSERT_NE(nullptr, m_log); } @@ -124,18 +135,18 @@ TEST(LogTest, Unregister) { llvm::llvm_shutdown_obj obj; Log::Register("chan", test_channel); - EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO)); + EXPECT_EQ(nullptr, GetLog(TestChannel::FOO)); std::string message; std::shared_ptr stream_sp( new llvm::raw_string_ostream(message)); EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", {"foo"}, llvm::nulls())); - EXPECT_NE(nullptr, test_channel.GetLogIfAny(FOO)); + EXPECT_NE(nullptr, GetLog(TestChannel::FOO)); Log::Unregister("chan"); - EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO)); + EXPECT_EQ(nullptr, GetLog(TestChannel::FOO)); } TEST_F(LogChannelTest, Enable) { - EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO)); + EXPECT_EQ(nullptr, GetLog(TestChannel::FOO)); std::string message; std::shared_ptr stream_sp( new llvm::raw_string_ostream(message)); @@ -144,20 +155,22 @@ EXPECT_EQ("Invalid log channel 'chanchan'.\n", error); EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {}, error)); - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); - EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); + EXPECT_NE(nullptr, GetLog(TestChannel::FOO)); + EXPECT_EQ(nullptr, GetLog(TestChannel::BAR)); EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"bar"}, error)); - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); + EXPECT_NE(nullptr, test_channel.GetLogIfAll( + Log::MaskType(TestChannel::FOO | TestChannel::BAR))); EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"baz"}, error)); EXPECT_NE(std::string::npos, error.find("unrecognized log category 'baz'")) << "error: " << error; - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); + EXPECT_NE(nullptr, test_channel.GetLogIfAll( + Log::MaskType(TestChannel::FOO | TestChannel::BAR))); } TEST_F(LogChannelTest, EnableOptions) { - EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO)); + EXPECT_EQ(nullptr, GetLog(TestChannel::FOO)); std::string message; std::shared_ptr stream_sp( new llvm::raw_string_ostream(message)); @@ -165,32 +178,33 @@ EXPECT_TRUE( EnableChannel(stream_sp, LLDB_LOG_OPTION_VERBOSE, "chan", {}, error)); - Log *log = test_channel.GetLogIfAll(FOO); + Log *log = GetLog(TestChannel::FOO); ASSERT_NE(nullptr, log); EXPECT_TRUE(log->GetVerbose()); } TEST_F(LogChannelTest, Disable) { - EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO)); + EXPECT_EQ(nullptr, GetLog(TestChannel::FOO)); std::string message; std::shared_ptr stream_sp( new llvm::raw_string_ostream(message)); std::string error; EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"foo", "bar"}, error)); - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); + EXPECT_NE(nullptr, test_channel.GetLogIfAll( + Log::MaskType(TestChannel::FOO | TestChannel::BAR))); EXPECT_TRUE(DisableChannel("chan", {"bar"}, error)); - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); - EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); + EXPECT_NE(nullptr, GetLog(TestChannel::FOO)); + EXPECT_EQ(nullptr, GetLog(TestChannel::BAR)); EXPECT_TRUE(DisableChannel("chan", {"baz"}, error)); EXPECT_NE(std::string::npos, error.find("unrecognized log category 'baz'")) << "error: " << error; - EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); - EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); + EXPECT_NE(nullptr, GetLog(TestChannel::FOO)); + EXPECT_EQ(nullptr, GetLog(TestChannel::BAR)); EXPECT_TRUE(DisableChannel("chan", {}, error)); - EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO | BAR)); + EXPECT_EQ(nullptr, GetLog(TestChannel::FOO | TestChannel::BAR)); } TEST_F(LogChannelTest, List) { @@ -309,5 +323,5 @@ // The mask should be either zero of "FOO". In either case, we should not trip // any undefined behavior (run the test under TSAN to verify this). - EXPECT_THAT(mask, testing::AnyOf(0, FOO)); + EXPECT_THAT(mask, testing::AnyOf(0, Log::MaskType(TestChannel::FOO))); }