Author: zturner Date: Thu May 7 16:39:33 2015 New Revision: 236776 URL: http://llvm.org/viewvc/llvm-project?rev=236776&view=rev Log: Add logging to ProcessWindows.
Modified: lldb/trunk/include/lldb/Core/Log.h lldb/trunk/source/Core/Log.cpp lldb/trunk/source/Initialization/SystemInitializerCommon.cpp lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp lldb/trunk/source/Plugins/Process/Windows/ProcessWindowsLog.cpp lldb/trunk/source/Plugins/Process/Windows/ProcessWindowsLog.h lldb/trunk/source/Plugins/Process/Windows/RegisterContextWindows.cpp lldb/trunk/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp Modified: lldb/trunk/include/lldb/Core/Log.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Log.h?rev=236776&r1=236775&r2=236776&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Log.h (original) +++ lldb/trunk/include/lldb/Core/Log.h Thu May 7 16:39:33 2015 @@ -128,6 +128,9 @@ public: Error(const char *fmt, ...) __attribute__((format(printf, 2, 3))); virtual void + VAError(const char *format, va_list args) __attribute__((format(printf, 2, 3))); + + virtual void FatalError(int err, const char *fmt, ...) __attribute__((format(printf, 3, 4))); virtual void Modified: lldb/trunk/source/Core/Log.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Log.cpp?rev=236776&r1=236775&r2=236776&view=diff ============================================================================== --- lldb/trunk/source/Core/Log.cpp (original) +++ lldb/trunk/source/Core/Log.cpp Thu May 7 16:39:33 2015 @@ -208,11 +208,18 @@ Log::LogIf(uint32_t bits, const char *fo void Log::Error(const char *format, ...) { - char *arg_msg = nullptr; va_list args; va_start(args, format); - ::vasprintf(&arg_msg, format, args); + VAError(format, args); va_end(args); +} + + +void +Log::VAError(const char *format, va_list args) +{ + char *arg_msg = nullptr; + ::vasprintf(&arg_msg, format, args); if (arg_msg == nullptr) return; @@ -221,6 +228,7 @@ Log::Error(const char *format, ...) free(arg_msg); } + //---------------------------------------------------------------------- // Printing of errors that ARE fatal. Exit with ERR exit code // immediately. Modified: lldb/trunk/source/Initialization/SystemInitializerCommon.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Initialization/SystemInitializerCommon.cpp?rev=236776&r1=236775&r2=236776&view=diff ============================================================================== --- lldb/trunk/source/Initialization/SystemInitializerCommon.cpp (original) +++ lldb/trunk/source/Initialization/SystemInitializerCommon.cpp Thu May 7 16:39:33 2015 @@ -171,6 +171,10 @@ SystemInitializerCommon::Terminate() PlatformDarwinKernel::Terminate(); #endif +#if defined(__WIN32__) + ProcessWindowsLog::Terminate(); +#endif + #ifndef LLDB_DISABLE_PYTHON OperatingSystemPython::Terminate(); #endif Modified: lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp?rev=236776&r1=236775&r2=236776&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp (original) +++ lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp Thu May 7 16:39:33 2015 @@ -23,6 +23,8 @@ #include "lldb/Host/windows/ProcessLauncherWindows.h" #include "lldb/Target/ProcessLaunchInfo.h" +#include "Plugins/Process/Windows/ProcessWindowsLog.h" + #include "llvm/ADT/STLExtras.h" #include "llvm/Support/raw_ostream.h" @@ -56,10 +58,19 @@ DebuggerThread::~DebuggerThread() Error DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { - Error error; + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "DebuggerThread::DebugLaunch launching '%s'", launch_info.GetExecutableFile().GetPath().c_str()); + Error error; DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); - HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", DebuggerThreadRoutine, context, &error)); + HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", + DebuggerThreadRoutine, context, &error)); + + if (!error.Success()) + { + WINERR_IFALL(WINDOWS_LOG_PROCESS, + "DebugLaunch couldn't launch debugger thread. %s", error.AsCString()); + } return error; } @@ -80,6 +91,10 @@ DebuggerThread::DebuggerThreadRoutine(co // thread routine has exited. std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "DebuggerThread preparing to launch '%s'.", + launch_info.GetExecutableFile().GetPath().c_str()); + Error error; ProcessLauncherWindows launcher; HostProcess process(launcher.LaunchProcess(launch_info, error)); @@ -101,29 +116,51 @@ DebuggerThread::StopDebugging(bool termi { Error error; + lldb::pid_t pid = m_process.GetProcessId(); + + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging('%s') called (inferior=%I64u).", + (terminate ? "true" : "false"), pid); + if (terminate) { - // Make a copy of the process, since the termination sequence will reset DebuggerThread's - // internal copy and it needs to remain open for us to perform the Wait operation. + // Make a copy of the process, since the termination sequence will reset + // DebuggerThread's internal copy and it needs to remain open for the Wait operation. HostProcess process_copy = m_process; - lldb::process_t handle = process_copy.GetNativeProcess().GetSystemHandle(); + lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); - // Initiate the termination before continuing the exception, so that the next debug event - // we get is the exit process event, and not some other event. + // Initiate the termination before continuing the exception, so that the next debug + // event we get is the exit process event, and not some other event. BOOL terminate_suceeded = TerminateProcess(handle, 0); + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging called TerminateProcess(0x%p, 0) (inferior=%I64u), success='%s'", + handle, pid, (terminate_suceeded ? "true" : "false")); + // If we're stuck waiting for an exception to continue, continue it now. But only // AFTER setting the termination event, to make sure that we don't race and enter // another wait for another debug event. if (m_active_exception.get()) + { + WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_EXCEPTION, + "StopDebugging masking active exception"); + ContinueAsyncException(ExceptionResult::MaskException); + } // Don't return until the process has exited. if (terminate_suceeded) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging waiting for termination of process %u to complete.", pid); + DWORD wait_result = ::WaitForSingleObject(handle, 5000); if (wait_result != WAIT_OBJECT_0) terminate_suceeded = false; + + WINLOG_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging WaitForSingleObject(0x%p, 5000) returned %u", + handle, wait_result); } if (!terminate_suceeded) @@ -134,6 +171,13 @@ DebuggerThread::StopDebugging(bool termi error.SetErrorString("Detach not yet supported on Windows."); // TODO: Implement detach. } + + if (!error.Success()) + { + WINERR_IFALL(WINDOWS_LOG_PROCESS, + "StopDebugging encountered an error while trying to stop process %u. %s", + pid, error.AsCString()); + } return error; } @@ -143,6 +187,10 @@ DebuggerThread::ContinueAsyncException(E if (!m_active_exception.get()) return; + WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_EXCEPTION, + "ContinueAsyncException called for inferior process %I64u, broadcasting.", + m_process.GetProcessId()); + m_active_exception.reset(); m_exception_pred.SetValue(result, eBroadcastAlways); } @@ -164,51 +212,68 @@ DebuggerThread::DebugLoop() { DEBUG_EVENT dbe = {0}; bool should_debug = true; - while (should_debug && WaitForDebugEvent(&dbe, INFINITE)) + WINLOG_IFALL(WINDOWS_LOG_EVENT, "Entering WaitForDebugEvent loop"); + while (should_debug) { - DWORD continue_status = DBG_CONTINUE; - switch (dbe.dwDebugEventCode) + WINLOGD_IFALL(WINDOWS_LOG_EVENT, "Calling WaitForDebugEvent"); + BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); + if (wait_result) { - case EXCEPTION_DEBUG_EVENT: + DWORD continue_status = DBG_CONTINUE; + switch (dbe.dwDebugEventCode) { - ExceptionResult status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); - - if (status == ExceptionResult::MaskException) - continue_status = DBG_CONTINUE; - else if (status == ExceptionResult::SendToApplication) - continue_status = DBG_EXCEPTION_NOT_HANDLED; - break; - } - case CREATE_THREAD_DEBUG_EVENT: - continue_status = HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); - break; - case CREATE_PROCESS_DEBUG_EVENT: - continue_status = HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); - break; - case EXIT_THREAD_DEBUG_EVENT: - continue_status = HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); - break; - case EXIT_PROCESS_DEBUG_EVENT: - continue_status = HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); - should_debug = false; - break; - case LOAD_DLL_DEBUG_EVENT: - continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); - break; - case UNLOAD_DLL_DEBUG_EVENT: - continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); - break; - case OUTPUT_DEBUG_STRING_EVENT: - continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); - break; - case RIP_EVENT: - continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); - if (dbe.u.RipInfo.dwType == SLE_ERROR) + case EXCEPTION_DEBUG_EVENT: + { + ExceptionResult status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); + + if (status == ExceptionResult::MaskException) + continue_status = DBG_CONTINUE; + else if (status == ExceptionResult::SendToApplication) + continue_status = DBG_EXCEPTION_NOT_HANDLED; + break; + } + case CREATE_THREAD_DEBUG_EVENT: + continue_status = HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); + break; + case CREATE_PROCESS_DEBUG_EVENT: + continue_status = HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); + break; + case EXIT_THREAD_DEBUG_EVENT: + continue_status = HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); + break; + case EXIT_PROCESS_DEBUG_EVENT: + continue_status = HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); should_debug = false; - break; + break; + case LOAD_DLL_DEBUG_EVENT: + continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); + break; + case UNLOAD_DLL_DEBUG_EVENT: + continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); + break; + case OUTPUT_DEBUG_STRING_EVENT: + continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); + break; + case RIP_EVENT: + continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); + if (dbe.u.RipInfo.dwType == SLE_ERROR) + should_debug = false; + break; + } + + WINLOGD_IFALL(WINDOWS_LOG_EVENT, "DebugLoop calling ContinueDebugEvent(%u, %u, %u) on thread %u.", + dbe.dwProcessId, dbe.dwThreadId, continue_status, ::GetCurrentThreadId()); + + ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); } + else + { + WINERR_IFALL(WINDOWS_LOG_EVENT, + "DebugLoop returned FALSE from WaitForDebugEvent. Error = %u", + ::GetCurrentThreadId(), ::GetLastError()); - ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); + should_debug = false; + } } FreeProcessHandles(); } @@ -219,26 +284,46 @@ DebuggerThread::HandleExceptionEvent(con bool first_chance = (info.dwFirstChance != 0); m_active_exception.reset(new ExceptionRecord(info.ExceptionRecord)); + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, + "HandleExceptionEvent encountered %s chance exception 0x%x on thread %u", + first_chance ? "first" : "second", info.ExceptionRecord.ExceptionCode, thread_id); - ExceptionResult result = m_debug_delegate->OnDebugException(first_chance, *m_active_exception); + ExceptionResult result = m_debug_delegate->OnDebugException(first_chance, + *m_active_exception); m_exception_pred.SetValue(result, eBroadcastNever); + + WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_EXCEPTION, + "DebuggerThread::HandleExceptionEvent waiting for ExceptionPred != BreakInDebugger"); + m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger, result); + WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_EXCEPTION, + "DebuggerThread::HandleExceptionEvent got ExceptionPred = %u", + m_exception_pred.GetValue()); + return result; } DWORD DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id) { + WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD, + "HandleCreateThreadEvent Thread %u spawned in process %I64u", + m_process.GetProcessId(), thread_id); + return DBG_CONTINUE; } DWORD DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id) { + uint32_t process_id = ::GetProcessId(info.hProcess); + + WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS, "HandleCreateProcessEvent process %u spawned", process_id); + std::string thread_name; llvm::raw_string_ostream name_stream(thread_name); - name_stream << "lldb.plugin.process-windows.slave[" << m_process.GetProcessId() << "]"; + name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]"; name_stream.flush(); ThisThread::SetName(thread_name.c_str()); @@ -259,12 +344,20 @@ DebuggerThread::HandleCreateProcessEvent DWORD DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id) { + WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD, + "HandleExitThreadEvent Thread %u exited with code %u in process %I64u", + thread_id, info.dwExitCode, m_process.GetProcessId()); + return DBG_CONTINUE; } DWORD DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id) { + WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD, + "HandleExitProcessEvent process %I64u exited with code %u", + m_process.GetProcessId(), info.dwExitCode); + FreeProcessHandles(); m_debug_delegate->OnExitProcess(info.dwExitCode); @@ -277,6 +370,8 @@ DebuggerThread::HandleLoadDllEvent(const if (info.hFile == nullptr) { // Not sure what this is, so just ignore it. + WINWARN_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent has a NULL file handle, returning...", + m_process.GetProcessId()); return DBG_CONTINUE; } @@ -294,11 +389,17 @@ DebuggerThread::HandleLoadDllEvent(const FileSpec file_spec(path, false); ModuleSpec module_spec(file_spec); lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll); + + WINLOG_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent DLL '%s' loaded at address 0x%p...", + m_process.GetProcessId(), path, info.lpBaseOfDll); + m_debug_delegate->OnLoadDll(module_spec, load_addr); } else { - // An unknown error occurred getting the path name. + WINERR_IFALL(WINDOWS_LOG_EVENT, + "Inferior %I64u - HandleLoadDllEvent Error %u occurred calling GetFinalPathNameByHandle", + m_process.GetProcessId(), ::GetLastError()); } // Windows does not automatically close info.hFile, so we need to do it. ::CloseHandle(info.hFile); @@ -308,6 +409,10 @@ DebuggerThread::HandleLoadDllEvent(const DWORD DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id) { + WINLOG_IFALL(WINDOWS_LOG_EVENT, + "HandleUnloadDllEvent process %I64u unloading DLL at addr 0x%p.", + m_process.GetProcessId(), info.lpBaseOfDll); + m_debug_delegate->OnUnloadDll(reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); return DBG_CONTINUE; } @@ -321,6 +426,10 @@ DebuggerThread::HandleODSEvent(const OUT DWORD DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) { + WINERR_IFALL(WINDOWS_LOG_EVENT, + "HandleRipEvent encountered error %u (type=%u) in process %I64u thread %u", + info.dwError, info.dwType, m_process.GetProcessId(), thread_id); + Error error(info.dwError, eErrorTypeWin32); m_debug_delegate->OnDebuggerError(error, info.dwType); Modified: lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp?rev=236776&r1=236775&r2=236776&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp (original) +++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp Thu May 7 16:39:33 2015 @@ -37,17 +37,22 @@ #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" +#include "Plugins/Process/Windows/ProcessWindowsLog.h" + #include "DebuggerThread.h" #include "ExceptionRecord.h" #include "LocalDebugDelegate.h" #include "ProcessWindows.h" #include "TargetThreadWindows.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" using namespace lldb; using namespace lldb_private; +#define BOOL_STR(b) ((b) ? "true" : "false") + namespace lldb_private { @@ -152,13 +157,32 @@ ProcessWindows::PutSTDIN(const char *buf Error ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) { - return EnableSoftwareBreakpoint(bp_site); + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite called with bp_site 0x%p " + "(id=%d, addr=0x%x)", + bp_site->GetID(), bp_site->GetLoadAddress()); + + Error error = EnableSoftwareBreakpoint(bp_site); + if (!error.Success()) + { + WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed. %s", error.AsCString()); + } + return error; } Error ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site) { - return DisableSoftwareBreakpoint(bp_site); + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite called with bp_site 0x%p " + "(id=%d, addr=0x%x)", + bp_site->GetID(), bp_site->GetLoadAddress()); + + Error error = DisableSoftwareBreakpoint(bp_site); + + if (!error.Success()) + { + WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite failed. %s", error.AsCString()); + } + return error; } bool @@ -167,6 +191,10 @@ ProcessWindows::UpdateThreadList(ThreadL // Add all the threads that were previously running and for which we did not detect a thread // exited event. int new_size = 0; + int continued_threads = 0; + int exited_threads = 0; + int new_threads = 0; + for (ThreadSP old_thread : old_thread_list.Threads()) { lldb::tid_t old_thread_id = old_thread->GetID(); @@ -175,18 +203,32 @@ ProcessWindows::UpdateThreadList(ThreadL { new_thread_list.AddThread(old_thread); ++new_size; + ++continued_threads; + WINLOGV_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - Thread %u was running and is still running.", + old_thread_id); + } + else + { + WINLOGV_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - Thread %u was running and has exited.", + old_thread_id); + ++exited_threads; } } // Also add all the threads that are new since the last time we broke into the debugger. - for (auto iter = m_session_data->m_new_threads.begin(); iter != m_session_data->m_new_threads.end(); ++iter) + for (const auto &thread_info : m_session_data->m_new_threads) { - ThreadSP thread(new TargetThreadWindows(*this, iter->second)); - thread->SetID(iter->first); + ThreadSP thread(new TargetThreadWindows(*this, thread_info.second)); + thread->SetID(thread_info.first); new_thread_list.AddThread(thread); ++new_size; + ++new_threads; + WINLOGV_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - Thread %u is new since last update.", thread_info.first); } + WINLOG_IFALL(WINDOWS_LOG_THREAD, "UpdateThreadList - %d new threads, %d old threads, %d exited threads.", + new_threads, continued_threads, exited_threads); + m_session_data->m_new_threads.clear(); m_session_data->m_exited_threads.clear(); @@ -204,7 +246,13 @@ ProcessWindows::DoLaunch(Module *exe_mod Error result; if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) { - result.SetErrorString("ProcessWindows can only be used to launch processes for debugging."); + StreamString stream; + stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can only be used for debug launches.", + launch_info.GetExecutableFile().GetPath().c_str()); + std::string message = stream.GetString(); + result.SetErrorString(message.c_str()); + + WINERR_IFALL(WINDOWS_LOG_PROCESS, message.c_str()); return result; } @@ -221,6 +269,9 @@ ProcessWindows::DoLaunch(Module *exe_mod HostProcess process; if (result.Success()) { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch started asynchronous launch of '%s'. Waiting for initial stop.", + launch_info.GetExecutableFile().GetPath().c_str()); + // Block this function until we receive the initial stop from the process. if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == WAIT_OBJECT_0) { @@ -232,8 +283,17 @@ ProcessWindows::DoLaunch(Module *exe_mod result.SetError(::GetLastError(), eErrorTypeWin32); } - if (!result.Success()) + if (result.Success()) + { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'", + launch_info.GetExecutableFile().GetPath().c_str()); + } + else + { + WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", + launch_info.GetExecutableFile().GetPath().c_str(), result.AsCString()); return result; + } // We've hit the initial stop. The private state should already be set to stopped as a result // of encountering the breakpoint exception in ProcessWindows::OnDebugException. @@ -247,27 +307,42 @@ Error ProcessWindows::DoResume() { llvm::sys::ScopedLock lock(m_mutex); - Error error; - if (GetPrivateState() == eStateStopped || GetPrivateState() == eStateCrashed) + + StateType private_state = GetPrivateState(); + if (private_state == eStateStopped || private_state == eStateCrashed) { - ExceptionRecordSP active_exception = m_session_data->m_debugger->GetActiveException().lock(); + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoResume called for process %I64u while state is %u. Resuming...", + m_session_data->m_debugger->GetProcess().GetProcessId(), GetPrivateState()); + + ExceptionRecordSP active_exception = + m_session_data->m_debugger->GetActiveException().lock(); if (active_exception) { - // Resume the process and continue processing debug events. Mask the exception so that - // from the process's view, there is no indication that anything happened. - m_session_data->m_debugger->ContinueAsyncException(ExceptionResult::MaskException); + // Resume the process and continue processing debug events. Mask + // the exception so that from the process's view, there is no + // indication that anything happened. + m_session_data->m_debugger->ContinueAsyncException( + ExceptionResult::MaskException); } + WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_THREAD, "DoResume resuming %u threads.", + m_thread_list.GetSize()); + for (int i = 0; i < m_thread_list.GetSize(); ++i) { - typedef std::shared_ptr<TargetThreadWindows> TargetThreadWindowsSP; - TargetThreadWindowsSP thread = std::static_pointer_cast<TargetThreadWindows>(m_thread_list.GetThreadAtIndex(i)); + auto thread = std::static_pointer_cast<TargetThreadWindows>( + m_thread_list.GetThreadAtIndex(i)); thread->DoResume(); } SetPrivateState(eStateRunning); } + else + { + WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoResume called for process %I64u but state is %u. Returning...", + m_session_data->m_debugger->GetProcess().GetProcessId(), GetPrivateState()); + } return error; } @@ -300,12 +375,29 @@ ProcessWindows::DoDestroy() llvm::sys::ScopedLock lock(m_mutex); Error error; - if (GetPrivateState() != eStateExited && GetPrivateState() != eStateDetached && m_session_data) + StateType private_state = GetPrivateState(); + if (!m_session_data) { - DebuggerThread &debugger = *m_session_data->m_debugger; + WINWARN_IFALL(WINDOWS_LOG_PROCESS, "DoDestroy called while state = %u, but there is no active session.", + private_state); + return error; + } + + DebuggerThread &debugger = *m_session_data->m_debugger; + if (private_state != eStateExited && private_state != eStateDetached) + { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoDestroy called for process 0x%I64u while state = %u. Shutting down...", + debugger.GetProcess().GetNativeProcess().GetSystemHandle(), private_state); error = debugger.StopDebugging(true); + m_session_data.reset(); } - m_session_data.reset(); + else + { + WINERR_IFALL(WINDOWS_LOG_PROCESS, + "DoDestroy called for process %I64u while state = %u, but cannot destroy in this state.", + debugger.GetProcess().GetNativeProcess().GetSystemHandle(), private_state); + } + return error; } @@ -315,28 +407,56 @@ ProcessWindows::RefreshStateAfterStop() llvm::sys::ScopedLock lock(m_mutex); if (!m_session_data) + { + WINWARN_IFALL(WINDOWS_LOG_PROCESS, "RefreshStateAfterStop called with no active session. Returning..."); return; + } m_thread_list.RefreshStateAfterStop(); std::weak_ptr<ExceptionRecord> exception_record = m_session_data->m_debugger->GetActiveException(); ExceptionRecordSP active_exception = exception_record.lock(); if (!active_exception) + { + WINERR_IFALL(WINDOWS_LOG_PROCESS, "RefreshStateAfterStop called for process %I64u but there is no " + "active exception. Why is the process stopped?", + m_session_data->m_debugger->GetProcess().GetProcessId()); return; + } StopInfoSP stop_info; ThreadSP stop_thread = m_thread_list.GetSelectedThread(); RegisterContextSP register_context = stop_thread->GetRegisterContext(); - uint64_t pc = register_context->GetPC(); + // The current EIP is AFTER the BP opcode, which is one byte. + // TODO(zturner): Can't we just use active_exception->GetExceptionAddress()? + uint64_t pc = register_context->GetPC() - 1; if (active_exception->GetExceptionCode() == EXCEPTION_BREAKPOINT) { - // TODO(zturner): The current EIP is AFTER the BP opcode, which is one byte. - BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc - 1)); - if (site && site->ValidForThisThread(stop_thread.get())) + BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); + + if (site) { - stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, site->GetID()); - register_context->SetPC(pc - 1); + WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, + "RefreshStateAfterStop detected breakpoint in process %I64u at " + "address 0x%I64x with breakpoint site %d", + m_session_data->m_debugger->GetProcess().GetProcessId(), pc, site->GetID()); + + if (site->ValidForThisThread(stop_thread.get())) + { + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, + "Breakpoint site %d is valid for this thread, creating stop info.", site->GetID()); + + stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID( + *stop_thread, site->GetID()); + register_context->SetPC(pc); + } + else + { + WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, + "Breakpoint site %d is not valid for this thread, creating empty stop info.", + site->GetID()); + } } stop_thread->SetStopInfo(stop_info); } @@ -344,14 +464,18 @@ ProcessWindows::RefreshStateAfterStop() { stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); stop_thread->SetStopInfo(stop_info); + WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, "RefreshStateAfterStop single stepping thread %u", + stop_thread->GetID()); } else { std::string desc; llvm::raw_string_ostream desc_stream(desc); - desc_stream << "Exception " << active_exception->GetExceptionCode() << " encountered at address " << pc; + desc_stream << "Exception 0x" << llvm::format_hex(active_exception->GetExceptionCode(), 8) + << " encountered at address 0x" << llvm::format_hex(pc, 8); stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str()); stop_thread->SetStopInfo(stop_info); + WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, desc_stream.str().c_str()); } } @@ -384,7 +508,11 @@ ProcessWindows::DoHalt(bool &caused_stop llvm::sys::ScopedLock lock(m_mutex); caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess().GetNativeProcess().GetSystemHandle()); if (!caused_stop) - error.SetError(GetLastError(), eErrorTypeWin32); + { + error.SetError(::GetLastError(), eErrorTypeWin32); + WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoHalt called DebugBreakProcess, but it failed with error %u", + error.GetError()); + } } return error; } @@ -410,11 +538,16 @@ ProcessWindows::DoReadMemory(lldb::addr_ if (!m_session_data) return 0; + WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory attempting to read %u bytes from address 0x%I64x", size, vm_addr); + HostProcess process = m_session_data->m_debugger->GetProcess(); void *addr = reinterpret_cast<void *>(vm_addr); SIZE_T bytes_read = 0; if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr, buf, size, &bytes_read)) + { error.SetError(GetLastError(), eErrorTypeWin32); + WINERR_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory failed with error code %u", error.GetError()); + } return bytes_read; } @@ -426,6 +559,8 @@ ProcessWindows::DoWriteMemory(lldb::addr if (!m_session_data) return 0; + WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory attempting to write %u bytes into address 0x%I64x", size, vm_addr); + HostProcess process = m_session_data->m_debugger->GetProcess(); void *addr = reinterpret_cast<void *>(vm_addr); SIZE_T bytes_written = 0; @@ -433,7 +568,10 @@ ProcessWindows::DoWriteMemory(lldb::addr if (WriteProcessMemory(handle, addr, buf, size, &bytes_written)) FlushInstructionCache(handle, addr, bytes_written); else + { error.SetError(GetLastError(), eErrorTypeWin32); + WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory failed with error code %u", error.GetError()); + } return bytes_written; } @@ -445,7 +583,8 @@ ProcessWindows::GetMemoryRegionInfo(lldb if (!m_session_data) { - error.SetErrorString("ProcessWindows::GetMemoryRegionInfo called with no debugging session."); + error.SetErrorString("GetMemoryRegionInfo called with no debugging session."); + WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); return error; } @@ -453,25 +592,33 @@ ProcessWindows::GetMemoryRegionInfo(lldb lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); if (handle == nullptr || handle == LLDB_INVALID_PROCESS) { - error.SetErrorString("ProcessWindows::GetMemoryRegionInfo called with an invalid target process."); + error.SetErrorString("GetMemoryRegionInfo called with an invalid target process."); + WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); return error; } + WINLOG_IFALL(WINDOWS_LOG_MEMORY, "GetMemoryRegionInfo getting info for address 0x%I64x", vm_addr); + void *addr = reinterpret_cast<void *>(vm_addr); MEMORY_BASIC_INFORMATION mem_info = {0}; SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); if (result == 0) { error.SetError(::GetLastError(), eErrorTypeWin32); + WINERR_IFALL(WINDOWS_LOG_MEMORY, + "VirtualQueryEx returned error %u while getting memory region info for address 0x%I64x", + error.GetError(), vm_addr); return error; } - bool readable = !(mem_info.Protect & PAGE_NOACCESS); bool executable = mem_info.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); bool writable = mem_info.Protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_READWRITE | PAGE_WRITECOPY); info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); info.SetExecutable(executable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + error.SetError(::GetLastError(), eErrorTypeWin32); + WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address 0x%I64u: readable=%s, executable=%s, writable=%s", + BOOL_STR(readable), BOOL_STR(executable), BOOL_STR(writable)); return error; } @@ -504,6 +651,7 @@ void ProcessWindows::OnExitProcess(uint32_t exit_code) { // No need to acquire the lock since m_session_data isn't accessed. + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Process %u exited with code %u", GetID(), exit_code); ModuleSP executable_module = GetTarget().GetExecutableModule(); ModuleList unloaded_modules; @@ -517,6 +665,11 @@ ProcessWindows::OnExitProcess(uint32_t e void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) { + DebuggerThreadSP debugger = m_session_data->m_debugger; + + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Debugger established connected to process %I64u. Image base = 0x%I64x", + debugger->GetProcess().GetProcessId(), image_base); + // Either we successfully attached to an existing process, or we successfully launched a new // process under the debugger. ModuleSP module = GetTarget().GetExecutableModule(); @@ -531,7 +684,6 @@ ProcessWindows::OnDebuggerConnected(lldb llvm::sys::ScopedLock lock(m_mutex); - DebuggerThreadSP debugger = m_session_data->m_debugger; const HostThreadWindows &wmain_thread = debugger->GetMainThread().GetNativeThread(); m_session_data->m_new_threads[wmain_thread.GetThreadId()] = debugger->GetMainThread(); } @@ -547,7 +699,12 @@ ProcessWindows::OnDebugException(bool fi // this, we probably need to first figure allow the test suite to print out full // lldb logs, and then add logging to the process plugin. if (!m_session_data) + { + WINERR_IFANY(WINDOWS_LOG_EXCEPTION, + "Debugger thread reported exception 0x%u at address 0x%I64x, but there is no session.", + record.GetExceptionCode(), record.GetExceptionAddress()); return ExceptionResult::SendToApplication; + } if (!first_chance) { @@ -574,6 +731,9 @@ ProcessWindows::OnDebugException(bool fi SetPrivateState(eStateStopped); break; default: + WINLOG_IFANY(WINDOWS_LOG_EXCEPTION, + "Debugger thread reported exception 0x%u at address 0x%I64x (first_chance=%s)", + record.GetExceptionCode(), record.GetExceptionAddress(), BOOL_STR(first_chance)); // For non-breakpoints, give the application a chance to handle the exception first. if (first_chance) result = ExceptionResult::SendToApplication; @@ -588,7 +748,6 @@ void ProcessWindows::OnCreateThread(const HostThread &new_thread) { llvm::sys::ScopedLock lock(m_mutex); - const HostThreadWindows &wnew_thread = new_thread.GetNativeThread(); m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread; } @@ -649,16 +808,22 @@ ProcessWindows::OnDebuggerError(const Er { llvm::sys::ScopedLock lock(m_mutex); - if (!m_session_data->m_initial_stop_received) + if (m_session_data->m_initial_stop_received) + { + // This happened while debugging. Do we shutdown the debugging session, try to continue, + // or do something else? + WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred during debugging. Unexpected behavior may result. %s", + error.GetError(), error.AsCString()); + } + else { // If we haven't actually launched the process yet, this was an error launching the // process. Set the internal error and signal the initial stop event so that the DoLaunch // method wakes up and returns a failure. m_session_data->m_launch_error = error; ::SetEvent(m_session_data->m_initial_stop_event); + WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred launching the process before the initial stop. %s", + error.GetError(), error.AsCString()); return; } - - // This happened while debugging. Do we shutdown the debugging session, try to continue, - // or do something else? } Modified: lldb/trunk/source/Plugins/Process/Windows/ProcessWindowsLog.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ProcessWindowsLog.cpp?rev=236776&r1=236775&r2=236776&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Windows/ProcessWindowsLog.cpp (original) +++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindowsLog.cpp Thu May 7 16:39:33 2015 @@ -11,8 +11,8 @@ #include <mutex> -#include "lldb/Interpreter/Args.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Interpreter/Args.h" #include "llvm/Support/ManagedStatic.h" #include "ProcessWindows.h" @@ -26,14 +26,7 @@ using namespace lldb_private; // that will construct the static g_log_sp the first time this function is // called. static bool g_log_enabled = false; -static Log * g_log = NULL; -static Log * -GetLog() -{ - if (!g_log_enabled) - return NULL; - return g_log; -} +static Log * g_log = nullptr; static llvm::ManagedStatic<std::once_flag> g_once_flag; @@ -54,34 +47,44 @@ ProcessWindowsLog::Initialize() }); } +void +ProcessWindowsLog::Terminate() +{ +} + Log * -ProcessWindowsLog::GetLogIfAllCategoriesSet(uint32_t mask) +ProcessWindowsLog::GetLog() { - Log *log(GetLog()); - if (log && mask) - { - uint32_t log_mask = log->GetMask().Get(); - if ((log_mask & mask) != mask) - return NULL; - } - return log; + return (g_log_enabled) ? g_log : nullptr; +} + +bool +ProcessWindowsLog::TestLogFlags(uint32_t mask, LogMaskReq req) +{ + Log *log = GetLog(); + if (!log) + return false; + + uint32_t log_mask = log->GetMask().Get(); + if (req == LogMaskReq::All) + return ((log_mask & mask) == mask); + else + return (log_mask & mask); } static uint32_t GetFlagBits(const char *arg) { - if (::strcasecmp (arg, "all") == 0 ) return WINDOWS_LOG_ALL; - else if (::strcasecmp (arg, "async") == 0 ) return WINDOWS_LOG_ASYNC; - else if (::strncasecmp (arg, "break", 5) == 0 ) return WINDOWS_LOG_BREAKPOINTS; - else if (::strcasecmp (arg, "default") == 0 ) return WINDOWS_LOG_DEFAULT; - else if (::strcasecmp (arg, "memory") == 0 ) return WINDOWS_LOG_MEMORY; - else if (::strcasecmp (arg, "data-short") == 0 ) return WINDOWS_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp (arg, "data-long") == 0 ) return WINDOWS_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp (arg, "process") == 0 ) return WINDOWS_LOG_PROCESS; - else if (::strcasecmp (arg, "registers") == 0 ) return WINDOWS_LOG_REGISTERS; - else if (::strcasecmp (arg, "step") == 0 ) return WINDOWS_LOG_STEP; - else if (::strcasecmp (arg, "thread") == 0 ) return WINDOWS_LOG_THREAD; - else if (::strcasecmp (arg, "verbose") == 0 ) return WINDOWS_LOG_VERBOSE; + if (::strcasecmp(arg, "all") == 0 ) return WINDOWS_LOG_ALL; + else if (::strcasecmp(arg, "break") == 0 ) return WINDOWS_LOG_BREAKPOINTS; + else if (::strcasecmp(arg, "event") == 0 ) return WINDOWS_LOG_EVENT; + else if (::strcasecmp(arg, "exception") == 0 ) return WINDOWS_LOG_EXCEPTION; + else if (::strcasecmp(arg, "memory") == 0 ) return WINDOWS_LOG_MEMORY; + else if (::strcasecmp(arg, "process") == 0 ) return WINDOWS_LOG_PROCESS; + else if (::strcasecmp(arg, "registers") == 0 ) return WINDOWS_LOG_REGISTERS; + else if (::strcasecmp(arg, "step") == 0 ) return WINDOWS_LOG_STEP; + else if (::strcasecmp(arg, "thread") == 0 ) return WINDOWS_LOG_THREAD; + else if (::strcasecmp(arg, "verbose") == 0 ) return WINDOWS_LOG_VERBOSE; return 0; } @@ -159,7 +162,7 @@ ProcessWindowsLog::EnableLog(StreamSP &l } } if (flag_bits == 0) - flag_bits = WINDOWS_LOG_DEFAULT; + flag_bits = WINDOWS_LOG_ALL; g_log->GetMask().Reset(flag_bits); g_log->GetOptions().Reset(log_options); g_log_enabled = true; @@ -170,35 +173,18 @@ ProcessWindowsLog::EnableLog(StreamSP &l void ProcessWindowsLog::ListLogCategories(Stream *strm) { - strm->Printf ("Logging categories for '%s':\n" - " all - turn on all available logging categories\n" - " async - log asynchronous activity\n" - " break - log breakpoints\n" - " default - enable the default set of logging categories for liblldb\n" - " memory - log memory reads and writes\n" - " data-short - log memory bytes for memory reads and writes for short transactions only\n" - " data-long - log memory bytes for memory reads and writes for all transactions\n" - " process - log process events and activities\n" - " registers - log register read/writes\n" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n", - ProcessWindowsLog::m_pluginname); -} - - -void -ProcessWindowsLog::LogIf(uint32_t mask, const char *format, ...) -{ - Log *log = GetLogIfAllCategoriesSet(mask); - if (log) - { - va_list args; - va_start(args, format); - log->VAPrintf(format, args); - va_end(args); - } + strm->Printf("Logging categories for '%s':\n" + " all - turn on all available logging categories\n" + " break - log breakpoints\n" + " event - log low level debugger events\n" + " exception - log exception information\n" + " memory - log memory reads and writes\n" + " process - log process events and activities\n" + " registers - log register read/writes\n" + " thread - log thread events and activities\n" + " step - log step related activities\n" + " verbose - enable verbose logging\n", + ProcessWindowsLog::m_pluginname); } -int ProcessWindowsLog::m_nestinglevel = 0; const char *ProcessWindowsLog::m_pluginname = ""; Modified: lldb/trunk/source/Plugins/Process/Windows/ProcessWindowsLog.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ProcessWindowsLog.h?rev=236776&r1=236775&r2=236776&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Windows/ProcessWindowsLog.h (original) +++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindowsLog.h Thu May 7 16:39:33 2015 @@ -12,25 +12,25 @@ #include "lldb/Core/Log.h" -#define WINDOWS_LOG_VERBOSE (1u << 0) -#define WINDOWS_LOG_PROCESS (1u << 1) -#define WINDOWS_LOG_THREAD (1u << 2) -#define WINDOWS_LOG_MEMORY (1u << 3) // Log memory reads/writes calls -#define WINDOWS_LOG_MEMORY_DATA_SHORT (1u << 4) // Log short memory reads/writes bytes -#define WINDOWS_LOG_MEMORY_DATA_LONG (1u << 5) // Log all memory reads/writes bytes -#define WINDOWS_LOG_BREAKPOINTS (1u << 6) -#define WINDOWS_LOG_STEP (1u << 7) -#define WINDOWS_LOG_ASYNC (1u << 8) -#define WINDOWS_LOG_REGISTERS (1u << 9) -#define WINDOWS_LOG_ALL (UINT32_MAX) -#define WINDOWS_LOG_DEFAULT WINDOWS_LOG_ASYNC +#define WINDOWS_LOG_VERBOSE (1u << 0) +#define WINDOWS_LOG_PROCESS (1u << 1) // Log process operations +#define WINDOWS_LOG_EXCEPTION (1u << 1) // Log exceptions +#define WINDOWS_LOG_THREAD (1u << 2) // Log thread operations +#define WINDOWS_LOG_MEMORY (1u << 3) // Log memory reads/writes calls +#define WINDOWS_LOG_BREAKPOINTS (1u << 4) // Log breakpoint operations +#define WINDOWS_LOG_STEP (1u << 5) // Log step operations +#define WINDOWS_LOG_REGISTERS (1u << 6) // Log register operations +#define WINDOWS_LOG_EVENT (1u << 7) // Low level debug events +#define WINDOWS_LOG_ALL (UINT32_MAX) -// The size which determines "short memory reads/writes". -#define WINDOWS_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) +enum class LogMaskReq +{ + All, + Any +}; class ProcessWindowsLog { - static int m_nestinglevel; static const char *m_pluginname; public: @@ -41,6 +41,9 @@ public: Initialize(); static void + Terminate(); + + static void RegisterPluginName(const char *pluginName) { m_pluginname = pluginName; @@ -52,8 +55,11 @@ public: m_pluginname = pluginName.GetCString(); } + static bool + TestLogFlags(uint32_t mask, LogMaskReq req); + static lldb_private::Log * - GetLogIfAllCategoriesSet(uint32_t mask = 0); + GetLog(); static void DisableLog(const char **args, lldb_private::Stream *feedback_strm); @@ -64,10 +70,27 @@ public: static void ListLogCategories(lldb_private::Stream *strm); +}; - static void - LogIf(uint32_t mask, const char *format, ...); +#define WINLOGF_IF(Flags, Req, Method, ...) \ + { \ + if (ProcessWindowsLog::TestLogFlags(Flags, Req)) \ + { \ + Log *log = ProcessWindowsLog::GetLog(); \ + if (log) \ + log->Method(__VA_ARGS__); \ + } \ + } -}; +#define WINLOG_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Printf, __VA_ARGS__) +#define WINLOG_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Printf, __VA_ARGS__) +#define WINLOGV_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Verbose, __VA_ARGS__) +#define WINLOGV_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Verbose, __VA_ARGS__) +#define WINLOGD_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Debug, __VA_ARGS__) +#define WINLOGD_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Debug, __VA_ARGS__) +#define WINERR_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Error, __VA_ARGS__) +#define WINERR_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Error, __VA_ARGS__) +#define WINWARN_IFANY(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::Any, Warning, __VA_ARGS__) +#define WINWARN_IFALL(Flags, ...) WINLOGF_IF(Flags, LogMaskReq::All, Warning, __VA_ARGS__) #endif // liblldb_ProcessWindowsLog_h_ Modified: lldb/trunk/source/Plugins/Process/Windows/RegisterContextWindows.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/RegisterContextWindows.cpp?rev=236776&r1=236775&r2=236776&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Windows/RegisterContextWindows.cpp (original) +++ lldb/trunk/source/Plugins/Process/Windows/RegisterContextWindows.cpp Thu May 7 16:39:33 2015 @@ -13,6 +13,7 @@ #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "ProcessWindowsLog.h" #include "RegisterContextWindows.h" #include "TargetThreadWindows.h" @@ -143,7 +144,12 @@ RegisterContextWindows::CacheAllRegister memset(&m_context, 0, sizeof(m_context)); m_context.ContextFlags = kWinContextFlags; if (!::GetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context)) + { + WINERR_IFALL(WINDOWS_LOG_REGISTERS, "GetThreadContext failed with error %u while caching register values.", + ::GetLastError()); return false; + } + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "GetThreadContext successfully updated the register values.", ::GetLastError()); m_context_stale = false; return true; } Modified: lldb/trunk/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp?rev=236776&r1=236775&r2=236776&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp (original) +++ lldb/trunk/source/Plugins/Process/Windows/x86/RegisterContextWindows_x86.cpp Thu May 7 16:39:33 2015 @@ -14,6 +14,7 @@ #include "lldb/Host/windows/windows.h" #include "lldb-x86-register-enums.h" +#include "ProcessWindowsLog.h" #include "RegisterContext_x86.h" #include "RegisterContextWindows_x86.h" #include "TargetThreadWindows.h" @@ -127,38 +128,52 @@ RegisterContextWindows_x86::ReadRegister if (!CacheAllRegisterValues()) return false; - switch (reg_info->kinds[eRegisterKindLLDB]) + uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + switch (reg) { case lldb_eax_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EAX", m_context.Eax); reg_value.SetUInt32(m_context.Eax); break; case lldb_ebx_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EBX", m_context.Ebx); reg_value.SetUInt32(m_context.Ebx); break; case lldb_ecx_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from ECX", m_context.Ecx); reg_value.SetUInt32(m_context.Ecx); break; case lldb_edx_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EDX", m_context.Edx); reg_value.SetUInt32(m_context.Edx); break; case lldb_edi_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EDI", m_context.Edi); reg_value.SetUInt32(m_context.Edi); break; case lldb_esi_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from ESI", m_context.Esi); reg_value.SetUInt32(m_context.Esi); break; case lldb_ebp_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EBP", m_context.Ebp); reg_value.SetUInt32(m_context.Ebp); break; case lldb_esp_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from ESP", m_context.Esp); reg_value.SetUInt32(m_context.Esp); break; case lldb_eip_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EIP", m_context.Eip); reg_value.SetUInt32(m_context.Eip); break; case lldb_eflags_i386: + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EFLAGS", m_context.EFlags); reg_value.SetUInt32(m_context.EFlags); break; + default: + WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Requested unknown register %u", reg); + break; } return true; } @@ -172,38 +187,52 @@ RegisterContextWindows_x86::WriteRegiste if (!CacheAllRegisterValues()) return false; - switch (reg_info->kinds[eRegisterKindLLDB]) + 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()); 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()); 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()); 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()); 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()); 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()); 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()); 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()); 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()); 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()); 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); } // Physically update the registers in the target process. _______________________________________________ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits