Index: include/lldb/Core/Log.h =================================================================== --- include/lldb/Core/Log.h +++ include/lldb/Core/Log.h @@ -10,14 +10,6 @@ #ifndef liblldb_Log_h_ #define liblldb_Log_h_ -// C Includes -#include -#include -#include -#include - -// C++ Includes -// Other libraries and framework includes // Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/Flags.h" @@ -25,7 +17,12 @@ #include "lldb/Core/PluginInterface.h" #include "lldb/lldb-private.h" +// Other libraries and framework includes #include "llvm/Support/FormatVariadic.h" +// C++ Includes +#include +#include +// C Includes //---------------------------------------------------------------------- // Logging Options @@ -39,6 +36,7 @@ #define LLDB_LOG_OPTION_PREPEND_THREAD_NAME (1U << 6) #define LLDB_LOG_OPTION_BACKTRACE (1U << 7) #define LLDB_LOG_OPTION_APPEND (1U << 8) +#define LLDB_LOG_OPTION_PREPEND_ORIGIN (1U << 9) //---------------------------------------------------------------------- // Logging Functions @@ -109,8 +107,10 @@ void PutCString(const char *cstr); void PutString(llvm::StringRef str); - template void Format(const char *fmt, Args &&... args) { - PutString(llvm::formatv(fmt, std::forward(args)...).str()); + template + void Format(llvm::StringRef file, llvm::StringRef function, + const char *format, Args &&... args) { + Format(file, function, llvm::formatv(format, std::forward(args)...)); } // CLEANUP: Add llvm::raw_ostream &Stream() function. @@ -155,6 +155,13 @@ private: DISALLOW_COPY_AND_ASSIGN(Log); + + void WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file, + llvm::StringRef function); + void WriteMessage(const std::string &message); + + void Format(llvm::StringRef file, llvm::StringRef function, + const llvm::formatv_object_base &payload); }; class LogChannel : public PluginInterface { @@ -186,4 +193,11 @@ } // namespace lldb_private +#define LLDB_LOG(log, ...) \ + do { \ + ::lldb_private::Log *log_private = (log); \ + if (log_private) \ + log_private->Format(__FILE__, __FUNCTION__, __VA_ARGS__); \ + } while (0) + #endif // liblldb_Log_h_ Index: source/Commands/CommandObjectLog.cpp =================================================================== --- source/Commands/CommandObjectLog.cpp +++ source/Commands/CommandObjectLog.cpp @@ -48,6 +48,7 @@ { LLDB_OPT_SET_1, false, "thread-name",'n', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." }, { LLDB_OPT_SET_1, false, "stack", 'S', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append a stack backtrace to each log line." }, { LLDB_OPT_SET_1, false, "append", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to the log file instead of overwriting." }, + { LLDB_OPT_SET_1, false, "no-origin", 'O', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Do not prepend log origin (source file) information." }, // clang-format on }; @@ -99,6 +100,7 @@ Error error; const int short_option = m_getopt_table[option_idx].val; + log_options |= LLDB_LOG_OPTION_PREPEND_ORIGIN; // Defaults to on. switch (short_option) { case 'f': log_file.SetFile(option_arg, true); @@ -130,6 +132,8 @@ case 'a': log_options |= LLDB_LOG_OPTION_APPEND; break; + case 'O': + log_options &= ~LLDB_LOG_OPTION_PREPEND_ORIGIN; default: error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); Index: source/Core/Log.cpp =================================================================== --- source/Core/Log.cpp +++ source/Core/Log.cpp @@ -20,6 +20,7 @@ // Other libraries and framework includes #include "llvm/ADT/SmallString.h" #include "llvm/Support/Chrono.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" @@ -69,58 +70,18 @@ // a valid file handle, we also log to the file. //---------------------------------------------------------------------- void Log::VAPrintf(const char *format, va_list args) { - // Make a copy of our stream shared pointer in case someone disables our - // log while we are logging and releases the stream - StreamSP stream_sp(m_stream_sp); - if (stream_sp) { - static uint32_t g_sequence_id = 0; - StreamString header; - - // Add a sequence ID if requested - if (m_options.Test(LLDB_LOG_OPTION_PREPEND_SEQUENCE)) - header.Printf("%u ", ++g_sequence_id); - - // Timestamp if requested - if (m_options.Test(LLDB_LOG_OPTION_PREPEND_TIMESTAMP)) { - auto now = std::chrono::duration( - std::chrono::system_clock::now().time_since_epoch()); - header.Printf("%.9f ", now.count()); - } + std::string message_string; + llvm::raw_string_ostream message(message_string); + WriteHeader(message, "", ""); - // Add the process and thread if requested - if (m_options.Test(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD)) - header.Printf("[%4.4x/%4.4" PRIx64 "]: ", getpid(), - Host::GetCurrentThreadID()); - - // Add the thread name if requested - if (m_options.Test(LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) { - llvm::SmallString<32> thread_name; - ThisThread::GetName(thread_name); - if (!thread_name.empty()) - header.Printf("%s ", thread_name.c_str()); - } - - header.PrintfVarArg(format, args); - header.PutCString("\n"); + char *text; + vasprintf(&text, format, args); + message << text; + free(text); - if (m_options.Test(LLDB_LOG_OPTION_BACKTRACE)) { - std::string back_trace; - llvm::raw_string_ostream stream(back_trace); - llvm::sys::PrintStackTrace(stream); - stream.flush(); - header.PutCString(back_trace); - } + message << "\n"; - if (m_options.Test(LLDB_LOG_OPTION_THREADSAFE)) { - static std::recursive_mutex g_LogThreadedMutex; - std::lock_guard guard(g_LogThreadedMutex); - stream_sp->PutCString(header.GetString()); - stream_sp->Flush(); - } else { - stream_sp->PutCString(header.GetString()); - stream_sp->Flush(); - } - } + WriteMessage(message.str()); } //---------------------------------------------------------------------- @@ -368,6 +329,71 @@ return false; } +void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file, + llvm::StringRef function) { + static uint32_t g_sequence_id = 0; + // Add a sequence ID if requested + if (m_options.Test(LLDB_LOG_OPTION_PREPEND_SEQUENCE)) + OS << ++g_sequence_id << " "; + + // Timestamp if requested + if (m_options.Test(LLDB_LOG_OPTION_PREPEND_TIMESTAMP)) { + auto now = std::chrono::duration( + std::chrono::system_clock::now().time_since_epoch()); + OS << llvm::formatv("{0:f9} ", now.count()); + } + + // Add the process and thread if requested + if (m_options.Test(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD)) + OS << llvm::formatv("[{0,0+4}/{1,0+4}] ", getpid(), + Host::GetCurrentThreadID()); + + // Add the thread name if requested + if (m_options.Test(LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) { + llvm::SmallString<32> thread_name; + ThisThread::GetName(thread_name); + if (!thread_name.empty()) + OS << thread_name; + } + + if (m_options.Test(LLDB_LOG_OPTION_BACKTRACE)) + llvm::sys::PrintStackTrace(OS); + + if (m_options.Test(LLDB_LOG_OPTION_PREPEND_ORIGIN) && + (!file.empty() || !function.empty())) { + file = llvm::sys::path::filename(file).take_front(40); + function = function.take_front(40); + OS << llvm::formatv("{0,-60:60} ", (file + ":" + function).str()); + } +} + +void Log::WriteMessage(const std::string &message) { + // Make a copy of our stream shared pointer in case someone disables our + // log while we are logging and releases the stream + StreamSP stream_sp(m_stream_sp); + if (!stream_sp) + return; + + if (m_options.Test(LLDB_LOG_OPTION_THREADSAFE)) { + static std::recursive_mutex g_LogThreadedMutex; + std::lock_guard guard(g_LogThreadedMutex); + stream_sp->PutCString(message.c_str()); + stream_sp->Flush(); + } else { + stream_sp->PutCString(message.c_str()); + stream_sp->Flush(); + } +} + +void Log::Format(llvm::StringRef file, llvm::StringRef function, + const llvm::formatv_object_base &payload) { + std::string message_string; + llvm::raw_string_ostream message(message_string); + WriteHeader(message, file, function); + message << payload << "\n"; + WriteMessage(message.str()); +} + LogChannelSP LogChannel::FindPlugin(const char *plugin_name) { LogChannelSP log_channel_sp; LogChannelMap &channel_map = GetChannelMap(); Index: source/Plugins/ExpressionParser/Clang/IRForTarget.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -512,11 +512,9 @@ break; default: encoding_flags = 0x0600; /* fall back to 0x0600, kCFStringEncodingASCII */ - if (log) { - log->Format("Encountered an Objective-C constant string with unusual " + LLDB_LOG(log, "Encountered an Objective-C constant string with unusual " "element size {0}", - string_array->getElementByteSize()); - } + string_array->getElementByteSize()); } Constant *encoding_arg = ConstantInt::get(i32_ty, encoding_flags, false); Constant *isExternal_arg = Index: source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -92,16 +92,13 @@ // value from our own process. ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0); is_supported = (res == sizeof(source) && source == dest); - if (log) { - if (is_supported) - log->Printf("%s: Detected kernel support for process_vm_readv syscall. " - "Fast memory reads enabled.", - __FUNCTION__); - else - log->Printf("%s: syscall process_vm_readv failed (error: %s). Fast " - "memory reads disabled.", - __FUNCTION__, strerror(errno)); - } + if (is_supported) + LLDB_LOG(log, "Detected kernel support for process_vm_readv syscall. " + "Fast memory reads enabled."); + else + LLDB_LOG(log, "syscall process_vm_readv failed (error: {0}). Fast memory " + "reads disabled.", + strerror(errno)); }); return is_supported; @@ -114,28 +111,24 @@ return; if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO)) - log->Printf("%s: setting STDIN to '%s'", __FUNCTION__, - action->GetFileSpec().GetCString()); + LLDB_LOG(log, "setting STDIN to '{0}'", action->GetFileSpec()); else - log->Printf("%s leaving STDIN as is", __FUNCTION__); + LLDB_LOG(log, "leaving STDIN as is"); if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO)) - log->Printf("%s setting STDOUT to '%s'", __FUNCTION__, - action->GetFileSpec().GetCString()); + LLDB_LOG(log, "setting STDOUT to '{0}'", action->GetFileSpec()); else - log->Printf("%s leaving STDOUT as is", __FUNCTION__); + LLDB_LOG(log, "leaving STDOUT as is"); if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO)) - log->Printf("%s setting STDERR to '%s'", __FUNCTION__, - action->GetFileSpec().GetCString()); + LLDB_LOG(log, "setting STDERR to '{0}'", action->GetFileSpec()); else - log->Printf("%s leaving STDERR as is", __FUNCTION__); + LLDB_LOG(log, "leaving STDERR as is"); int i = 0; for (const char **args = info.GetArguments().GetConstArgumentVector(); *args; ++args, ++i) - log->Printf("%s arg %d: \"%s\"", __FUNCTION__, i, - *args ? *args : "nullptr"); + LLDB_LOG(log, "arg {0}: '{1}'", i, *args); } void DisplayBytes(StreamString &s, void *bytes, uint32_t count) { @@ -148,50 +141,50 @@ } void PtraceDisplayBytes(int &req, void *data, size_t data_size) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE | + POSIX_LOG_VERBOSE)); + if (!log) + return; StreamString buf; - Log *verbose_log(ProcessPOSIXLog::GetLogIfAllCategoriesSet( - POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE)); - - if (verbose_log) { - switch (req) { - case PTRACE_POKETEXT: { - DisplayBytes(buf, &data, 8); - verbose_log->Printf("PTRACE_POKETEXT %s", buf.GetData()); - break; - } - case PTRACE_POKEDATA: { - DisplayBytes(buf, &data, 8); - verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData()); - break; - } - case PTRACE_POKEUSER: { - DisplayBytes(buf, &data, 8); - verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData()); - break; - } - case PTRACE_SETREGS: { - DisplayBytes(buf, data, data_size); - verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData()); - break; - } - case PTRACE_SETFPREGS: { - DisplayBytes(buf, data, data_size); - verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData()); - break; - } - case PTRACE_SETSIGINFO: { - DisplayBytes(buf, data, sizeof(siginfo_t)); - verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData()); - break; - } - case PTRACE_SETREGSET: { - // Extract iov_base from data, which is a pointer to the struct IOVEC - DisplayBytes(buf, *(void **)data, data_size); - verbose_log->Printf("PTRACE_SETREGSET %s", buf.GetData()); - break; - } - default: {} - } + + switch (req) { + case PTRACE_POKETEXT: { + DisplayBytes(buf, &data, 8); + LLDB_LOG(log, "PTRACE_POKETEXT {0}", buf.GetData()); + break; + } + case PTRACE_POKEDATA: { + DisplayBytes(buf, &data, 8); + LLDB_LOG(log, "PTRACE_POKEDATA {0}", buf.GetData()); + break; + } + case PTRACE_POKEUSER: { + DisplayBytes(buf, &data, 8); + LLDB_LOG(log, "PTRACE_POKEUSER {0}", buf.GetData()); + break; + } + case PTRACE_SETREGS: { + DisplayBytes(buf, data, data_size); + LLDB_LOG(log, "PTRACE_SETREGS {0}", buf.GetData()); + break; + } + case PTRACE_SETFPREGS: { + DisplayBytes(buf, data, data_size); + LLDB_LOG(log, "PTRACE_SETFPREGS {0}", buf.GetData()); + break; + } + case PTRACE_SETSIGINFO: { + DisplayBytes(buf, data, sizeof(siginfo_t)); + LLDB_LOG(log, "PTRACE_SETSIGINFO {0}", buf.GetData()); + break; + } + case PTRACE_SETREGSET: { + // Extract iov_base from data, which is a pointer to the struct IOVEC + DisplayBytes(buf, *(void **)data, data_size); + LLDB_LOG(log, "PTRACE_SETREGSET {0}", buf.GetData()); + break; + } + default: {} } } @@ -255,9 +248,7 @@ if (error.Fail()) { native_process_sp.reset(); - if (log) - log->Printf("NativeProcessLinux::%s failed to launch process: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOG(log, "failed to launch process: {0}", error); return error; } @@ -270,8 +261,7 @@ lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf("NativeProcessLinux::%s(pid = %" PRIi64 ")", __FUNCTION__, pid); + LLDB_LOG(log, "pid = {0:x}", pid); // Retrieve the architecture for the running process. ArchSpec process_arch; @@ -307,9 +297,7 @@ void NativeProcessLinux::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Error &error) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessLinux::%s (pid = %" PRIi64 ")", __FUNCTION__, - pid); + LLDB_LOG(log, "pid = {0:x}", pid); m_sigchld_handle = mainloop.RegisterSignal( SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); @@ -321,11 +309,8 @@ return; // Set the architecture to the exe architecture. - if (log) - log->Printf("NativeProcessLinux::%s (pid = %" PRIi64 - ") detected architecture %s", - __FUNCTION__, pid, m_arch.GetArchitectureName()); - + LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, + m_arch.GetArchitectureName()); m_pid = pid; SetState(eStateAttaching); @@ -356,9 +341,7 @@ int status; if ((wpid = waitpid(pid, &status, 0)) < 0) { error.SetErrorToErrno(); - if (log) - log->Printf("NativeProcessLinux::%s waitpid for inferior failed with %s", - __FUNCTION__, error.AsCString()); + LLDB_LOG(log, "waitpid for inferior failed with %s", error); // Mark the inferior as invalid. // FIXME this could really use a new state - eStateLaunchFailure. For now, @@ -370,16 +353,10 @@ assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) && "Could not sync with inferior process."); - if (log) - log->Printf("NativeProcessLinux::%s inferior started, now in stopped state", - __FUNCTION__); - + LLDB_LOG(log, "inferior started, now in stopped state"); error = SetDefaultPtraceOpts(pid); if (error.Fail()) { - if (log) - log->Printf("NativeProcessLinux::%s inferior failed to set default " - "ptrace options: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOG(log, "failed to set default ptrace options: {0}", error); // Mark the inferior as invalid. // FIXME this could really use a new state - eStateLaunchFailure. For now, @@ -398,10 +375,9 @@ if (m_terminal_fd != -1) { error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); if (error.Fail()) { - if (log) - log->Printf("NativeProcessLinux::%s inferior EnsureFDFlags failed for " - "ensuring terminal O_NONBLOCK setting: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOG(log, "inferior EnsureFDFlags failed for ensuring terminal " + "O_NONBLOCK setting: {0}", + error); // Mark the inferior as invalid. // FIXME this could really use a new state - eStateLaunchFailure. For @@ -412,10 +388,7 @@ } } - if (log) - log->Printf("NativeProcessLinux::%s() adding pid = %" PRIu64, __FUNCTION__, - uint64_t(pid)); - + LLDB_LOG(log, "adding pid = {0}", pid); ResolveProcessArchitecture(m_pid, m_arch); NativeThreadLinuxSP thread_sp = AddThread(pid); assert(thread_sp && "AddThread() returned a nullptr thread"); @@ -426,14 +399,8 @@ SetCurrentThreadID(thread_sp->GetID()); SetState(StateType::eStateStopped); - if (log) { - if (error.Success()) - log->Printf("NativeProcessLinux::%s inferior launching succeeded", - __FUNCTION__); - else - log->Printf("NativeProcessLinux::%s inferior launching failed: %s", - __FUNCTION__, error.AsCString()); - } + if (error.Fail()) + LLDB_LOG(log, "inferior launching failed {0}", error); return error; } @@ -487,10 +454,7 @@ if (error.Fail()) return -1; - if (log) - log->Printf("NativeProcessLinux::%s() adding tid = %" PRIu64, - __FUNCTION__, tid); - + LLDB_LOG(log, "adding tid = {0}", tid); it->second = true; // Create the thread, mark it as stopped. @@ -578,11 +542,8 @@ // Handle when the thread exits. if (exited) { - if (log) - log->Printf( - "NativeProcessLinux::%s() got exit signal(%d) , tid = %" PRIu64 - " (%s main thread)", - __FUNCTION__, signal, pid, is_main_thread ? "is" : "is not"); + LLDB_LOG(log, "got exit signal({0}) , tid = {1} ({2} main thread)", signal, + pid, is_main_thread ? "is" : "is not"); // This is a thread that exited. Ensure we're not tracking it anymore. const bool thread_found = StopTrackingThread(pid); @@ -596,41 +557,32 @@ const bool already_notified = (GetState() == StateType::eStateExited) || (GetState() == StateType::eStateCrashed); if (!already_notified) { - if (log) - log->Printf("NativeProcessLinux::%s() tid = %" PRIu64 - " handling main thread exit (%s), expected exit state " - "already set but state was %s instead, setting exit " - "state now", - __FUNCTION__, pid, - thread_found ? "stopped tracking thread metadata" - : "thread metadata not found", - StateAsCString(GetState())); + LLDB_LOG( + log, + "tid = {0} handling main thread exit ({1}), expected exit state " + "already set but state was {2} instead, setting exit state now", + pid, + thread_found ? "stopped tracking thread metadata" + : "thread metadata not found", + StateAsCString(GetState())); // The main thread exited. We're done monitoring. Report to delegate. SetExitStatus(convert_pid_status_to_exit_type(status), convert_pid_status_to_return_code(status), nullptr, true); // Notify delegate that our process has exited. SetState(StateType::eStateExited, true); - } else { - if (log) - log->Printf("NativeProcessLinux::%s() tid = %" PRIu64 - " main thread now exited (%s)", - __FUNCTION__, pid, - thread_found ? "stopped tracking thread metadata" - : "thread metadata not found"); - } + } else + LLDB_LOG(log, "tid = {0} main thread now exited (%s)", pid, + thread_found ? "stopped tracking thread metadata" + : "thread metadata not found"); } else { // Do we want to report to the delegate in this case? I think not. If - // this was an orderly - // thread exit, we would already have received the SIGTRAP | - // (PTRACE_EVENT_EXIT << 8) signal, - // and we would have done an all-stop then. - if (log) - log->Printf("NativeProcessLinux::%s() tid = %" PRIu64 - " handling non-main thread exit (%s)", - __FUNCTION__, pid, - thread_found ? "stopped tracking thread metadata" - : "thread metadata not found"); + // this was an orderly thread exit, we would already have received the + // SIGTRAP | (PTRACE_EVENT_EXIT << 8) signal, and we would have done an + // all-stop then. + LLDB_LOG(log, "tid = {0} handling non-main thread exit (%s)", pid, + thread_found ? "stopped tracking thread metadata" + : "thread metadata not found"); } return; } Index: source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp =================================================================== --- source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp +++ source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp @@ -176,6 +176,7 @@ bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) { + Log *log = ProcessWindowsLog::GetLogIfAllCategoriesSet(WINDOWS_LOG_REGISTERS); if (!CacheAllRegisterValues()) return false; @@ -203,7 +204,7 @@ return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags, reg_value); default: - WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Requested unknown register %u", reg); + LLDB_LOG(log, "Requested unknown register %u", reg); break; } return false; @@ -219,62 +220,52 @@ if (!CacheAllRegisterValues()) return false; + Log *log = ProcessWindowsLog::GetLogIfAllCategoriesSet(WINDOWS_LOG_REGISTERS); uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; switch (reg) { case lldb_eax_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EAX", - reg_value.GetAsUInt32()); + LLDB_LOG(log, "Write value {0:x} to EAX", reg_value.GetAsUInt32()); m_context.Eax = reg_value.GetAsUInt32(); break; case lldb_ebx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBX", - reg_value.GetAsUInt32()); + LLDB_LOG(log, "Write value {0:x} to EBX", reg_value.GetAsUInt32()); m_context.Ebx = reg_value.GetAsUInt32(); break; case lldb_ecx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ECX", - reg_value.GetAsUInt32()); + LLDB_LOG("Write value {0:x} to ECX", reg_value.GetAsUInt32()); m_context.Ecx = reg_value.GetAsUInt32(); break; case lldb_edx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDX", - reg_value.GetAsUInt32()); + LLDB_LOG(log, "Write value {0:x} to EDX", reg_value.GetAsUInt32()); m_context.Edx = reg_value.GetAsUInt32(); break; case lldb_edi_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDI", - reg_value.GetAsUInt32()); + LLDB_LOG(log, "Write value {0:x} to EDI", reg_value.GetAsUInt32()); m_context.Edi = reg_value.GetAsUInt32(); break; case lldb_esi_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESI", - reg_value.GetAsUInt32()); + LLDB_LOG(log, "Write value {0:x} to ESI", reg_value.GetAsUInt32()); m_context.Esi = reg_value.GetAsUInt32(); break; case lldb_ebp_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBP", - reg_value.GetAsUInt32()); + LLDB_LOG(log, "Write value {0:x} to EBP", reg_value.GetAsUInt32()); m_context.Ebp = reg_value.GetAsUInt32(); break; case lldb_esp_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESP", - reg_value.GetAsUInt32()); + LLDB_LOG(log, "Write value {0:x} to ESP", reg_value.GetAsUInt32()); m_context.Esp = reg_value.GetAsUInt32(); break; case lldb_eip_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EIP", - reg_value.GetAsUInt32()); + LLDB_LOG(log, "Write value {0:x} to EIP", reg_value.GetAsUInt32()); m_context.Eip = reg_value.GetAsUInt32(); break; case lldb_eflags_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EFLAGS", - reg_value.GetAsUInt32()); + LLDB_LOG(log, "Write value {0:x} to EFLAGS", reg_value.GetAsUInt32()); m_context.EFlags = reg_value.GetAsUInt32(); break; default: - WINWARN_IFALL(WINDOWS_LOG_REGISTERS, - "Write value 0x%x to unknown register %u", - reg_value.GetAsUInt32(), reg); + LLDB_LOG(log, "Write value {0:x} to unknown register {1}", + reg_value.GetAsUInt32(), reg); } // Physically update the registers in the target process. @@ -286,13 +277,12 @@ bool RegisterContextWindows_x86::ReadRegisterHelper( DWORD flags_required, const char *reg_name, DWORD value, RegisterValue ®_value) const { + Log *log = ProcessWindowsLog::GetLogIfAllCategoriesSet(WINDOWS_LOG_REGISTERS); if ((m_context.ContextFlags & flags_required) != flags_required) { - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Thread context doesn't have %s", - reg_name); + LLDB_LOG(log, "Thread context doesn't have {0}", reg_name); return false; } - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%lx from %s", value, - reg_name); + LLDB_LOG(log, "Read value {0:x} from {1}", value, reg_name); reg_value.SetUInt32(value); return true; } Index: tools/lldb-server/lldb-gdbserver.cpp =================================================================== --- tools/lldb-server/lldb-gdbserver.cpp +++ tools/lldb-server/lldb-gdbserver.cpp @@ -425,7 +425,8 @@ } if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, - LLDB_LOG_OPTION_PREPEND_TIMESTAMP)) + LLDB_LOG_OPTION_PREPEND_TIMESTAMP | + LLDB_LOG_OPTION_PREPEND_ORIGIN)) return -1; Log *log(lldb_private::GetLogIfAnyCategoriesSet(GDBR_LOG_VERBOSE)); Index: unittests/Core/CMakeLists.txt =================================================================== --- unittests/Core/CMakeLists.txt +++ unittests/Core/CMakeLists.txt @@ -4,6 +4,7 @@ DataExtractorTest.cpp ErrorTest.cpp ListenerTest.cpp + LogTest.cpp ScalarTest.cpp StructuredDataTest.cpp TimerTest.cpp Index: unittests/Core/LogTest.cpp =================================================================== --- /dev/null +++ unittests/Core/LogTest.cpp @@ -0,0 +1,56 @@ +//===-- LogTest.cpp ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/Host.h" +#include "gtest/gtest.h" + +using namespace lldb; +using namespace lldb_private; + +static std::string GetLogString(uint32_t log_options, const char *format, + int arg) { + std::shared_ptr stream_sp(new StreamString()); + Log log_(stream_sp); + log_.GetOptions().Reset(log_options); + Log *log = &log_; + LLDB_LOG(log, format, arg); + return stream_sp->GetString(); +} + +TEST(LogTest, LLDB_LOG_nullptr) { + Log *log = nullptr; + LLDB_LOG(log, "{0}", 0); // Shouldn't crash +} + +TEST(LogTest, log_options) { + EXPECT_EQ("Hello World 47\n", GetLogString(0, "Hello World {0}", 47)); + EXPECT_EQ("Hello World 47\n", + GetLogString(LLDB_LOG_OPTION_THREADSAFE, "Hello World {0}", 47)); + + { + std::string msg = + GetLogString(LLDB_LOG_OPTION_PREPEND_SEQUENCE, "Hello World {0}", 47); + int seq_no; + EXPECT_EQ(1, sscanf(msg.c_str(), "%d Hello World 47", &seq_no)); + } + + EXPECT_EQ( + "LogTest.cpp:GetLogString Hello " + "World 47\n", + GetLogString(LLDB_LOG_OPTION_PREPEND_ORIGIN, "Hello World {0}", 47)); + + EXPECT_EQ(llvm::formatv("[{0}/{1}] Hello World 47\n", + Host::GetCurrentProcessID(), + Host::GetCurrentThreadID()) + .str(), + GetLogString(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD, + "Hello World {0}", 47)); +}