diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:04:10 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:04:10 +0000 |
| commit | 74a628f776edb588bff8f8f5cc16eac947c9d631 (patch) | |
| tree | dc32e010ac4902621e5a279bfeb48628f7f0e166 /source/Plugins/Process | |
| parent | afed7be32164a598f8172282c249af7266c48b46 (diff) | |
Notes
Diffstat (limited to 'source/Plugins/Process')
160 files changed, 5564 insertions, 3757 deletions
diff --git a/source/Plugins/Process/CMakeLists.txt b/source/Plugins/Process/CMakeLists.txt index defa493088b6..62abd75a43b6 100644 --- a/source/Plugins/Process/CMakeLists.txt +++ b/source/Plugins/Process/CMakeLists.txt @@ -1,18 +1,19 @@ -if (CMAKE_SYSTEM_NAME MATCHES "Linux") +if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android") add_subdirectory(Linux) add_subdirectory(POSIX) elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") add_subdirectory(FreeBSD) add_subdirectory(POSIX) elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD") + add_subdirectory(NetBSD) add_subdirectory(POSIX) elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") add_subdirectory(Windows/Common) elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") add_subdirectory(MacOSX-Kernel) + add_subdirectory(mach-core) endif() add_subdirectory(gdb-remote) add_subdirectory(Utility) -add_subdirectory(mach-core) add_subdirectory(elf-core) add_subdirectory(minidump) diff --git a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp index 63b1ae6da968..feb7a11584f8 100644 --- a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp +++ b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp @@ -30,11 +30,11 @@ // LLDB includes #include "lldb/lldb-enumerations.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/StreamString.h" +#include "lldb/Host/PseudoTerminal.h" #include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Utility/PseudoTerminal.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" #include "CFBundle.h" #include "CFString.h" diff --git a/source/Plugins/Process/Darwin/MachException.cpp b/source/Plugins/Process/Darwin/MachException.cpp index 81706441494a..5a97a4b01be3 100644 --- a/source/Plugins/Process/Darwin/MachException.cpp +++ b/source/Plugins/Process/Darwin/MachException.cpp @@ -22,11 +22,11 @@ #include <mutex> // LLDB includes -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Stream.h" #include "lldb/Target/UnixSignals.h" +#include "lldb/Utility/Error.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Stream.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp b/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp index e56375ebaa49..65ab12fe1adf 100644 --- a/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp +++ b/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp @@ -19,11 +19,11 @@ // C++ includes // LLDB includes -#include "lldb/Core/Log.h" #include "lldb/Core/State.h" -#include "lldb/Core/StreamString.h" +#include "lldb/Host/PseudoTerminal.h" #include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Utility/PseudoTerminal.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" #include "CFBundle.h" #include "CFString.h" @@ -31,6 +31,8 @@ #include "MachException.h" +#include "llvm/Support/FileSystem.h" + using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_darwin; @@ -63,7 +65,7 @@ Error NativeProcessProtocol::Launch( FileSpec working_dir(launch_info.GetWorkingDirectory()); if (working_dir && (!working_dir.ResolvePath() || - working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) { + !llvm::sys::fs::is_directory(working_dir.GetPath())) { error.SetErrorStringWithFormat("No such file or directory: %s", working_dir.GetCString()); return error; diff --git a/source/Plugins/Process/Darwin/NativeProcessDarwin.h b/source/Plugins/Process/Darwin/NativeProcessDarwin.h index 69c1b8d9e4cc..01fdd64b1273 100644 --- a/source/Plugins/Process/Darwin/NativeProcessDarwin.h +++ b/source/Plugins/Process/Darwin/NativeProcessDarwin.h @@ -24,11 +24,11 @@ // Other libraries and framework includes #include "lldb/Core/ArchSpec.h" #include "lldb/Host/Debug.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/Pipe.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/FileSpec.h" #include "lldb/lldb-types.h" #include "LaunchFlavor.h" diff --git a/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp b/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp index 5e7f9ae7e6f9..b04f9053136b 100644 --- a/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp +++ b/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp @@ -13,7 +13,7 @@ #include <libproc.h> // LLDB includes -#include "lldb/Core/Stream.h" +#include "lldb/Utility/Stream.h" #include "NativeProcessDarwin.h" diff --git a/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp b/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp index aa9b04157658..fa06fb8b2a5f 100644 --- a/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp +++ b/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp @@ -20,9 +20,9 @@ #include <sys/sysctl.h> // LLDB includes -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Stream.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Stream.h" #include "lldb/lldb-enumerations.h" #include "NativeProcessDarwin.h" diff --git a/source/Plugins/Process/FreeBSD/CMakeLists.txt b/source/Plugins/Process/FreeBSD/CMakeLists.txt index c0e3374fef89..63855992d708 100644 --- a/source/Plugins/Process/FreeBSD/CMakeLists.txt +++ b/source/Plugins/Process/FreeBSD/CMakeLists.txt @@ -2,7 +2,7 @@ include_directories(.) include_directories(../POSIX) include_directories(../Utility) -add_lldb_library(lldbPluginProcessFreeBSD +add_lldb_library(lldbPluginProcessFreeBSD PLUGIN ProcessFreeBSD.cpp FreeBSDThread.cpp ProcessMonitor.cpp @@ -13,4 +13,16 @@ add_lldb_library(lldbPluginProcessFreeBSD RegisterContextPOSIXProcessMonitor_powerpc.cpp RegisterContextPOSIXProcessMonitor_x86.cpp RegisterContextPOSIXProcessMonitor_mips64.cpp + + LINK_LIBS + lldbBreakpoint + lldbCore + lldbHost + lldbSymbol + lldbTarget + lldbUtility + lldbPluginProcessUtility + lldbPluginProcessPOSIX + LINK_COMPONENTS + Support ) diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp index 0b09296cb7fd..bd8e5abe2255 100644 --- a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp +++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp @@ -9,6 +9,12 @@ // C Includes #include <errno.h> +#include <pthread.h> +#include <pthread_np.h> +#include <stdlib.h> +#include <sys/sysctl.h> +#include <sys/types.h> +#include <sys/user.h> // C++ Includes // Other libraries and framework includes @@ -18,16 +24,16 @@ // Project includes #include "FreeBSDThread.h" #include "POSIXStopInfo.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" #include "Plugins/Process/Utility/UnwindLLDB.h" #include "ProcessFreeBSD.h" #include "ProcessMonitor.h" -#include "ProcessPOSIXLog.h" #include "RegisterContextPOSIXProcessMonitor_arm.h" #include "RegisterContextPOSIXProcessMonitor_arm64.h" #include "RegisterContextPOSIXProcessMonitor_mips64.h" @@ -53,8 +59,7 @@ FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid) : Thread(process, tid), m_frame_ap(), m_breakpoint(), m_thread_name_valid(false), m_thread_name(), m_posix_thread(NULL) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf("FreeBSDThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid); + LLDB_LOGV(log, "tid = {0}", tid); // Set the current watchpoints for this thread. Target &target = GetProcess()->GetTarget(); @@ -114,9 +119,41 @@ void FreeBSDThread::SetName(const char *name) { const char *FreeBSDThread::GetName() { if (!m_thread_name_valid) { - llvm::SmallString<32> thread_name; - HostNativeThread::GetName(GetID(), thread_name); - m_thread_name = thread_name.c_str(); + m_thread_name.clear(); + int pid = GetProcess()->GetID(); + + struct kinfo_proc *kp = nullptr, *nkp; + size_t len = 0; + int error; + int ctl[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD, + pid}; + + while (1) { + error = sysctl(ctl, 4, kp, &len, nullptr, 0); + if (kp == nullptr || (error != 0 && errno == ENOMEM)) { + // Add extra space in case threads are added before next call. + len += sizeof(*kp) + len / 10; + nkp = (struct kinfo_proc *)realloc(kp, len); + if (nkp == nullptr) { + free(kp); + return nullptr; + } + kp = nkp; + continue; + } + if (error != 0) + len = 0; + break; + } + + for (size_t i = 0; i < len / sizeof(*kp); i++) { + if (kp[i].ki_tid == (lwpid_t)GetID()) { + m_thread_name.append(kp[i].ki_tdname, + kp[i].ki_tdname + strlen(kp[i].ki_tdname)); + break; + } + } + free(kp); m_thread_name_valid = true; } @@ -138,7 +175,7 @@ lldb::RegisterContextSP FreeBSDThread::GetRegisterContext() { reg_interface = new RegisterInfoPOSIX_arm64(target_arch); break; case llvm::Triple::arm: - reg_interface = new RegisterContextFreeBSD_arm(target_arch); + reg_interface = new RegisterInfoPOSIX_arm(target_arch); break; case llvm::Triple::ppc: #ifndef __powerpc64__ @@ -215,8 +252,7 @@ FreeBSDThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) { uint32_t concrete_frame_idx = 0; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf("FreeBSDThread::%s ()", __FUNCTION__); + LLDB_LOGV(log, "called"); if (frame) concrete_frame_idx = frame->GetConcreteFrameIndex(); diff --git a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h index 1ee16dd5f8f4..e51fc08d74cc 100644 --- a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h +++ b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h @@ -10,15 +10,9 @@ #ifndef liblldb_POSIXStopInfo_H_ #define liblldb_POSIXStopInfo_H_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Target/StopInfo.h" - -#include "CrashReason.h" #include "FreeBSDThread.h" - +#include "Plugins/Process/POSIX/CrashReason.h" +#include "lldb/Target/StopInfo.h" #include <string> //===----------------------------------------------------------------------===// diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index 82e45a5d5fc1..93d294fd040a 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -10,12 +10,21 @@ // C Includes #include <errno.h> +#include <pthread.h> +#include <pthread_np.h> +#include <stdlib.h> +#include <sys/sysctl.h> +#include <sys/types.h> +#include <sys/user.h> +#include <machine/elf.h> // C++ Includes #include <mutex> +#include <unordered_map> // Other libraries and framework includes #include "lldb/Core/PluginManager.h" +#include "lldb/Core/RegisterValue.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/ObjectFile.h" @@ -23,11 +32,11 @@ #include "lldb/Target/Target.h" #include "FreeBSDThread.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "Plugins/Process/Utility/FreeBSDSignals.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" #include "ProcessFreeBSD.h" #include "ProcessMonitor.h" -#include "ProcessPOSIXLog.h" // Other libraries and framework includes #include "lldb/Breakpoint/BreakpointLocation.h" @@ -36,15 +45,19 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/FileSpec.h" #include "lldb/Host/posix/Fcntl.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Threading.h" + using namespace lldb; using namespace lldb_private; @@ -70,12 +83,11 @@ ProcessFreeBSD::CreateInstance(lldb::TargetSP target_sp, } void ProcessFreeBSD::Initialize() { - static std::once_flag g_once_flag; + static llvm::once_flag g_once_flag; - std::call_once(g_once_flag, []() { + llvm::call_once(g_once_flag, []() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); - ProcessPOSIXLog::Initialize(GetPluginNameStatic()); }); } @@ -122,6 +134,7 @@ Error ProcessFreeBSD::DoResume() { std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); bool do_step = false; + bool software_single_step = !SupportHardwareSingleStepping(); for (tid_collection::const_iterator t_pos = m_run_tids.begin(), t_end = m_run_tids.end(); @@ -133,6 +146,11 @@ Error ProcessFreeBSD::DoResume() { t_pos != t_end; ++t_pos) { m_monitor->ThreadSuspend(*t_pos, false); do_step = true; + if (software_single_step) { + Error error = SetupSoftwareSingleStepping(*t_pos); + if (error.Fail()) + return error; + } } for (tid_collection::const_iterator t_pos = m_suspend_tids.begin(), t_end = m_suspend_tids.end(); @@ -145,7 +163,7 @@ Error ProcessFreeBSD::DoResume() { if (log) log->Printf("process %" PRIu64 " resuming (%s)", GetID(), do_step ? "step" : "continue"); - if (do_step) + if (do_step && !software_single_step) m_monitor->SingleStep(GetID(), m_resume_signo); else m_monitor->Resume(GetID(), m_resume_signo); @@ -281,8 +299,7 @@ Error ProcessFreeBSD::DoAttachToProcessWithID( assert(m_monitor == NULL); Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf("ProcessFreeBSD::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID()); + LLDB_LOGV(log, "pid = {0}", GetID()); m_monitor = new ProcessMonitor(this, pid, error); @@ -354,9 +371,9 @@ Error ProcessFreeBSD::DoLaunch(Module *module, ProcessLaunchInfo &launch_info) { assert(m_monitor == NULL); FileSpec working_dir = launch_info.GetWorkingDirectory(); - if (working_dir && - (!working_dir.ResolvePath() || - working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) { + namespace fs = llvm::sys::fs; + if (working_dir && (!working_dir.ResolvePath() || + !fs::is_directory(working_dir.GetPath()))) { error.SetErrorStringWithFormat("No such file or directory: %s", working_dir.GetCString()); return error; @@ -528,9 +545,7 @@ ProcessFreeBSD::CreateNewFreeBSDThread(lldb_private::Process &process, void ProcessFreeBSD::RefreshStateAfterStop() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf("ProcessFreeBSD::%s(), message_queue size = %d", __FUNCTION__, - (int)m_message_queue.size()); + LLDB_LOGV(log, "message_queue size = {0}", m_message_queue.size()); std::lock_guard<std::recursive_mutex> guard(m_message_mutex); @@ -542,10 +557,8 @@ void ProcessFreeBSD::RefreshStateAfterStop() { // Resolve the thread this message corresponds to and pass it along. lldb::tid_t tid = message.GetTID(); - if (log) - log->Printf( - "ProcessFreeBSD::%s(), message_queue size = %d, pid = %" PRIi64, - __FUNCTION__, (int)m_message_queue.size(), tid); + LLDB_LOGV(log, " message_queue size = {0}, pid = {1}", + m_message_queue.size(), tid); m_thread_list.RefreshStateAfterStop(); @@ -557,10 +570,7 @@ void ProcessFreeBSD::RefreshStateAfterStop() { if (message.GetKind() == ProcessMessage::eExitMessage) { // FIXME: We should tell the user about this, but the limbo message is // probably better for that. - if (log) - log->Printf("ProcessFreeBSD::%s() removing thread, tid = %" PRIi64, - __FUNCTION__, tid); - + LLDB_LOG(log, "removing thread, tid = {0}", tid); std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex()); ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false); @@ -903,13 +913,207 @@ bool ProcessFreeBSD::IsAThreadRunning() { const DataBufferSP ProcessFreeBSD::GetAuxvData() { // If we're the local platform, we can ask the host for auxv data. PlatformSP platform_sp = GetTarget().GetPlatform(); - if (platform_sp && platform_sp->IsHost()) - return lldb_private::Host::GetAuxvData(this); + assert(platform_sp && platform_sp->IsHost()); + + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_AUXV, (int)m_process->GetID()}; + size_t auxv_size = AT_COUNT * sizeof(Elf_Auxinfo); + DataBufferSP buf_sp(new DataBufferHeap(auxv_size, 0)); + + if (::sysctl(mib, 4, buf_sp->GetBytes(), &auxv_size, NULL, 0) != 0) { + perror("sysctl failed on auxv"); + buf_sp.reset(); + } + + return buf_sp; +} + +struct EmulatorBaton { + ProcessFreeBSD *m_process; + RegisterContext *m_reg_context; + + // eRegisterKindDWARF -> RegisterValue + std::unordered_map<uint32_t, RegisterValue> m_register_values; + + EmulatorBaton(ProcessFreeBSD *process, RegisterContext *reg_context) + : m_process(process), m_reg_context(reg_context) {} +}; + +static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, + lldb::addr_t addr, void *dst, size_t length) { + EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); + + Error error; + size_t bytes_read = + emulator_baton->m_process->DoReadMemory(addr, dst, length, error); + if (!error.Success()) + bytes_read = 0; + return bytes_read; +} - // Somewhat unexpected - the process is not running locally or we don't have a - // platform. - assert( - false && - "no platform or not the host - how did we get here with ProcessFreeBSD?"); - return DataBufferSP(); +static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value) { + EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); + + auto it = emulator_baton->m_register_values.find( + reg_info->kinds[eRegisterKindDWARF]); + if (it != emulator_baton->m_register_values.end()) { + reg_value = it->second; + return true; + } + + // The emulator only fills in the dwarf register numbers (and in some cases + // the generic register numbers). Get the full register info from the + // register context based on the dwarf register numbers. + const RegisterInfo *full_reg_info = + emulator_baton->m_reg_context->GetRegisterInfo( + eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); + + bool error = + emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); + return error; +} + +static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value) { + EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); + emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = + reg_value; + return true; +} + +static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, + lldb::addr_t addr, const void *dst, + size_t length) { + return length; +} + +bool ProcessFreeBSD::SingleStepBreakpointHit( + void *baton, lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, lldb::user_id_t break_loc_id) { + return false; +} + +Error ProcessFreeBSD::SetSoftwareSingleStepBreakpoint(lldb::tid_t tid, + lldb::addr_t addr) { + Error error; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + if (log) { + log->Printf("ProcessFreeBSD::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + } + + // Validate the address. + if (addr == LLDB_INVALID_ADDRESS) + return Error("ProcessFreeBSD::%s invalid load address specified.", + __FUNCTION__); + + Breakpoint *const sw_step_break = + m_process->GetTarget().CreateBreakpoint(addr, true, false).get(); + sw_step_break->SetCallback(SingleStepBreakpointHit, this, true); + sw_step_break->SetBreakpointKind("software-signle-step"); + + if (log) + log->Printf("ProcessFreeBSD::%s addr = 0x%" PRIx64 " -- SUCCESS", + __FUNCTION__, addr); + + m_threads_stepping_with_breakpoint.insert({tid, sw_step_break->GetID()}); + return Error(); +} + +bool ProcessFreeBSD::IsSoftwareStepBreakpoint(lldb::tid_t tid) { + ThreadSP thread = GetThreadList().FindThreadByID(tid); + if (!thread) + return false; + + assert(thread->GetRegisterContext()); + lldb::addr_t stop_pc = thread->GetRegisterContext()->GetPC(); + + const auto &iter = m_threads_stepping_with_breakpoint.find(tid); + if (iter == m_threads_stepping_with_breakpoint.end()) + return false; + + lldb::break_id_t bp_id = iter->second; + BreakpointSP bp = GetTarget().GetBreakpointByID(bp_id); + if (!bp) + return false; + + BreakpointLocationSP bp_loc = bp->FindLocationByAddress(stop_pc); + if (!bp_loc) + return false; + + GetTarget().RemoveBreakpointByID(bp_id); + m_threads_stepping_with_breakpoint.erase(tid); + return true; +} + +bool ProcessFreeBSD::SupportHardwareSingleStepping() const { + lldb_private::ArchSpec arch = GetTarget().GetArchitecture(); + if (arch.GetMachine() == llvm::Triple::arm || + arch.GetMachine() == llvm::Triple::mips64 || + arch.GetMachine() == llvm::Triple::mips64el || + arch.GetMachine() == llvm::Triple::mips || + arch.GetMachine() == llvm::Triple::mipsel) + return false; + return true; +} + +Error ProcessFreeBSD::SetupSoftwareSingleStepping(lldb::tid_t tid) { + std::unique_ptr<EmulateInstruction> emulator_ap( + EmulateInstruction::FindPlugin(GetTarget().GetArchitecture(), + eInstructionTypePCModifying, nullptr)); + + if (emulator_ap == nullptr) + return Error("Instruction emulator not found!"); + + FreeBSDThread *thread = static_cast<FreeBSDThread *>( + m_thread_list.FindThreadByID(tid, false).get()); + if (thread == NULL) + return Error("Thread not found not found!"); + + lldb::RegisterContextSP register_context_sp = thread->GetRegisterContext(); + + EmulatorBaton baton(this, register_context_sp.get()); + emulator_ap->SetBaton(&baton); + emulator_ap->SetReadMemCallback(&ReadMemoryCallback); + emulator_ap->SetReadRegCallback(&ReadRegisterCallback); + emulator_ap->SetWriteMemCallback(&WriteMemoryCallback); + emulator_ap->SetWriteRegCallback(&WriteRegisterCallback); + + if (!emulator_ap->ReadInstruction()) + return Error("Read instruction failed!"); + + bool emulation_result = + emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); + const RegisterInfo *reg_info_pc = register_context_sp->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + auto pc_it = + baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]); + + lldb::addr_t next_pc; + if (emulation_result) { + assert(pc_it != baton.m_register_values.end() && + "Emulation was successful but PC wasn't updated"); + next_pc = pc_it->second.GetAsUInt64(); + } else if (pc_it == baton.m_register_values.end()) { + // Emulate instruction failed and it haven't changed PC. Advance PC + // with the size of the current opcode because the emulation of all + // PC modifying instruction should be successful. The failure most + // likely caused by a not supported instruction which don't modify PC. + next_pc = + register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize(); + } else { + // The instruction emulation failed after it modified the PC. It is an + // unknown error where we can't continue because the next instruction is + // modifying the PC but we don't know how. + return Error("Instruction emulation failed unexpectedly"); + } + + SetSoftwareSingleStepBreakpoint(tid, next_pc); + return Error(); } diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h index cd38989f973c..063eb6f68123 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h @@ -11,19 +11,13 @@ #ifndef liblldb_ProcessFreeBSD_H_ #define liblldb_ProcessFreeBSD_H_ -// C Includes - -// C++ Includes +#include "Plugins/Process/POSIX/ProcessMessage.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/ThreadList.h" #include <mutex> #include <queue> #include <set> -// Other libraries and framework includes -#include "ProcessFreeBSD.h" -#include "ProcessMessage.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/ThreadList.h" - class ProcessMonitor; class FreeBSDThread; @@ -171,7 +165,25 @@ public: virtual FreeBSDThread *CreateNewFreeBSDThread(lldb_private::Process &process, lldb::tid_t tid); + static bool SingleStepBreakpointHit( + void *baton, lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + + lldb_private::Error SetupSoftwareSingleStepping(lldb::tid_t tid); + + lldb_private::Error SetSoftwareSingleStepBreakpoint(lldb::tid_t tid, + lldb::addr_t addr); + + bool IsSoftwareStepBreakpoint(lldb::tid_t tid); + + bool SupportHardwareSingleStepping() const; + + typedef std::vector<lldb::tid_t> tid_collection; + tid_collection &GetStepTids() { return m_step_tids; } + protected: + static const size_t MAX_TRAP_OPCODE_SIZE = 8; + /// Target byte order. lldb::ByteOrder m_byte_order; @@ -207,10 +219,10 @@ protected: friend class FreeBSDThread; - typedef std::vector<lldb::tid_t> tid_collection; tid_collection m_suspend_tids; tid_collection m_run_tids; tid_collection m_step_tids; + std::map<lldb::tid_t, lldb::break_id_t> m_threads_stepping_with_breakpoint; int m_resume_signo; }; diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index afc649de3b65..68ab41651162 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -21,21 +21,21 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" #include "lldb/Host/Host.h" +#include "lldb/Host/PseudoTerminal.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Target/UnixSignals.h" -#include "lldb/Utility/PseudoTerminal.h" +#include "lldb/Utility/Error.h" #include "FreeBSDThread.h" #include "Plugins/Process/POSIX/CrashReason.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "ProcessFreeBSD.h" #include "ProcessMonitor.h" -#include "ProcessPOSIXLog.h" extern "C" { extern char **environ; @@ -1141,11 +1141,19 @@ ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, case SI_KERNEL: case TRAP_BRKPT: - if (log) - log->Printf( - "ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, - __FUNCTION__, tid); - message = ProcessMessage::Break(tid); + if (monitor->m_process->IsSoftwareStepBreakpoint(tid)) { + if (log) + log->Printf("ProcessMonitor::%s() received sw single step breakpoint " + "event, tid = %" PRIu64, + __FUNCTION__, tid); + message = ProcessMessage::Trace(tid); + } else { + if (log) + log->Printf( + "ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, + __FUNCTION__, tid); + message = ProcessMessage::Break(tid); + } break; } diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h index 4c2594e9da6a..58629189b7b8 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -18,8 +18,8 @@ #include <mutex> // Other libraries and framework includes -#include "lldb/Host/FileSpec.h" #include "lldb/Host/HostThread.h" +#include "lldb/Utility/FileSpec.h" #include "lldb/lldb-types.h" namespace lldb_private { diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp index f8d5f2edd3a3..14171d614c9e 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp @@ -7,9 +7,9 @@ // //===---------------------------------------------------------------------===// -#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" #include "ProcessFreeBSD.h" #include "ProcessMonitor.h" diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp index 98a213a370fe..8a8eb0520cca 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp @@ -7,9 +7,9 @@ // //===---------------------------------------------------------------------===// -#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" #include "ProcessFreeBSD.h" diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp index 020636eb0a6b..ab50a5db3f3e 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" #include "ProcessFreeBSD.h" diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h index 2f75e6058fbc..6f57b0d9cd65 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h @@ -11,6 +11,7 @@ #define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_ #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" +#include "Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h" #include "RegisterContextPOSIX.h" class RegisterContextPOSIXProcessMonitor_mips64 @@ -72,6 +73,8 @@ protected: uint32_t NumSupportedHardwareWatchpoints(); private: + uint64_t + m_gpr_mips64[k_num_gpr_registers_mips64]; // general purpose registers. ProcessMonitor &GetMonitor(); }; diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp index e7b01fa8634a..70eec945ce8d 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" #include "ProcessFreeBSD.h" #include "ProcessMonitor.h" diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp index 976b190b2355..036306058ff8 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" #include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" #include "Plugins/Process/FreeBSD/ProcessMonitor.h" diff --git a/source/Plugins/Process/Linux/CMakeLists.txt b/source/Plugins/Process/Linux/CMakeLists.txt index 8291fef467e3..8a46d730caff 100644 --- a/source/Plugins/Process/Linux/CMakeLists.txt +++ b/source/Plugins/Process/Linux/CMakeLists.txt @@ -2,7 +2,7 @@ include_directories(.) include_directories(../POSIX) include_directories(../Utility) -add_lldb_library(lldbPluginProcessLinux +add_lldb_library(lldbPluginProcessLinux PLUGIN NativeProcessLinux.cpp NativeRegisterContextLinux.cpp NativeRegisterContextLinux_arm.cpp @@ -11,6 +11,16 @@ add_lldb_library(lldbPluginProcessLinux NativeRegisterContextLinux_mips64.cpp NativeRegisterContextLinux_s390x.cpp NativeThreadLinux.cpp - ProcFileReader.cpp SingleStepCheck.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + lldbTarget + lldbUtility + lldbPluginProcessPOSIX + lldbPluginProcessUtility + LINK_COMPONENTS + Support ) diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp index fb84729dd5f4..914d690ad88c 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -24,43 +24,40 @@ // Other libraries and framework includes #include "lldb/Core/EmulateInstruction.h" -#include "lldb/Core/Error.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostProcess.h" +#include "lldb/Host/PseudoTerminal.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/common/NativeBreakpoint.h" #include "lldb/Host/common/NativeRegisterContext.h" -#include "lldb/Host/linux/ProcessLauncherLinux.h" +#include "lldb/Host/linux/Ptrace.h" +#include "lldb/Host/linux/Uio.h" +#include "lldb/Host/posix/ProcessLauncherPosixFork.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/Error.h" #include "lldb/Utility/LLDBAssert.h" -#include "lldb/Utility/PseudoTerminal.h" #include "lldb/Utility/StringExtractor.h" #include "NativeThreadLinux.h" #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "ProcFileReader.h" #include "Procfs.h" -// System includes - They have to be included after framework includes because -// they define some -// macros which collide with variable names in other modules +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Threading.h" + #include <linux/unistd.h> #include <sys/socket.h> - #include <sys/syscall.h> #include <sys/types.h> #include <sys/user.h> #include <sys/wait.h> -#include "lldb/Host/linux/Ptrace.h" -#include "lldb/Host/linux/Uio.h" - // Support hardware breakpoints in case it has not been defined #ifndef TRAP_HWBKPT #define TRAP_HWBKPT 4 @@ -75,10 +72,10 @@ using namespace llvm; static bool ProcessVmReadvSupported() { static bool is_supported; - static std::once_flag flag; + static llvm::once_flag flag; - std::call_once(flag, [] { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + llvm::call_once(flag, [] { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); uint32_t source = 0x47424742; uint32_t dest = 0; @@ -92,16 +89,15 @@ static bool ProcessVmReadvSupported() { // 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; @@ -109,33 +105,29 @@ static bool ProcessVmReadvSupported() { namespace { void MaybeLogLaunchInfo(const ProcessLaunchInfo &info) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); if (!log) 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 +140,49 @@ void DisplayBytes(StreamString &s, void *bytes, uint32_t count) { } void PtraceDisplayBytes(int &req, void *data, size_t data_size) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + 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_LOGV(log, "PTRACE_POKETEXT {0}", buf.GetData()); + break; + } + case PTRACE_POKEDATA: { + DisplayBytes(buf, &data, 8); + LLDB_LOGV(log, "PTRACE_POKEDATA {0}", buf.GetData()); + break; + } + case PTRACE_POKEUSER: { + DisplayBytes(buf, &data, 8); + LLDB_LOGV(log, "PTRACE_POKEUSER {0}", buf.GetData()); + break; + } + case PTRACE_SETREGS: { + DisplayBytes(buf, data, data_size); + LLDB_LOGV(log, "PTRACE_SETREGS {0}", buf.GetData()); + break; + } + case PTRACE_SETFPREGS: { + DisplayBytes(buf, data, data_size); + LLDB_LOGV(log, "PTRACE_SETFPREGS {0}", buf.GetData()); + break; + } + case PTRACE_SETSIGINFO: { + DisplayBytes(buf, data, sizeof(siginfo_t)); + LLDB_LOGV(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_LOGV(log, "PTRACE_SETREGSET {0}", buf.GetData()); + break; + } + default: {} } } @@ -227,15 +218,14 @@ Error NativeProcessProtocol::Launch( ProcessLaunchInfo &launch_info, NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); Error error; // Verify the working directory is valid if one was specified. FileSpec working_dir{launch_info.GetWorkingDirectory()}; - if (working_dir && - (!working_dir.ResolvePath() || - working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) { + if (working_dir && (!working_dir.ResolvePath() || + !llvm::sys::fs::is_directory(working_dir.GetPath()))) { error.SetErrorStringWithFormat("No such file or directory: %s", working_dir.GetCString()); return error; @@ -255,9 +245,7 @@ Error NativeProcessProtocol::Launch( 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; } @@ -269,9 +257,8 @@ Error NativeProcessProtocol::Launch( Error NativeProcessProtocol::Attach( 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); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid = {0:x}", pid); // Retrieve the architecture for the running process. ArchSpec process_arch; @@ -306,10 +293,8 @@ NativeProcessLinux::NativeProcessLinux() 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); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid = {0:x}", pid); m_sigchld_handle = mainloop.RegisterSignal( SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); @@ -321,11 +306,8 @@ void NativeProcessLinux::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, 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); @@ -345,20 +327,18 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop, MaybeLogLaunchInfo(launch_info); ::pid_t pid = - ProcessLauncherLinux().LaunchProcess(launch_info, error).GetProcessId(); + ProcessLauncherPosixFork().LaunchProcess(launch_info, error).GetProcessId(); if (error.Fail()) return error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // Wait for the child process to trap on its call to execve. ::pid_t wpid; 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 +350,10 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop, 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 +372,10 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop, 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 +386,7 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop, } } - 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,19 +397,13 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop, 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; } ::pid_t NativeProcessLinux::Attach(lldb::pid_t pid, Error &error) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // Use a map to keep track of the threads which we have attached/need to // attach. @@ -487,10 +452,7 @@ Error NativeProcessLinux::LaunchInferior(MainLoop &mainloop, 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 +540,8 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, // 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 +555,32 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, 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", + 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; } @@ -641,28 +591,20 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, if (!thread_sp) { // Normally, the only situation when we cannot find the thread is if we have - // just - // received a new thread notification. This is indicated by GetSignalInfo() - // returning - // si_code == SI_USER and si_pid == 0 - if (log) - log->Printf("NativeProcessLinux::%s received notification about an " - "unknown tid %" PRIu64 ".", - __FUNCTION__, pid); + // just received a new thread notification. This is indicated by + // GetSignalInfo() returning si_code == SI_USER and si_pid == 0 + LLDB_LOG(log, "received notification about an unknown tid {0}.", pid); if (info_err.Fail()) { - if (log) - log->Printf("NativeProcessLinux::%s (tid %" PRIu64 - ") GetSignalInfo failed (%s). Ingoring this notification.", - __FUNCTION__, pid, info_err.AsCString()); + LLDB_LOG(log, + "(tid {0}) GetSignalInfo failed ({1}). " + "Ingoring this notification.", + pid, info_err); return; } - if (log && (info.si_code != SI_USER || info.si_pid != 0)) - log->Printf("NativeProcessLinux::%s (tid %" PRIu64 - ") unexpected signal info (si_code: %d, si_pid: %d). " - "Treating as a new thread notification anyway.", - __FUNCTION__, pid, info.si_code, info.si_pid); + LLDB_LOG(log, "tid {0}, si_code: {1}, si_pid: {2}", pid, info.si_code, + info.si_pid); auto thread_sp = AddThread(pid); // Resume the newly created thread. @@ -682,49 +624,35 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, if (info_err.GetError() == EINVAL) { // This is a group stop reception for this tid. // We can reach here if we reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU - // into the - // tracee, triggering the group-stop mechanism. Normally receiving these - // would stop - // the process, pending a SIGCONT. Simulating this state in a debugger is - // hard and is - // generally not needed (one use case is debugging background task being - // managed by a - // shell). For general use, it is sufficient to stop the process in a - // signal-delivery + // into the tracee, triggering the group-stop mechanism. Normally + // receiving these would stop the process, pending a SIGCONT. Simulating + // this state in a debugger is hard and is generally not needed (one use + // case is debugging background task being managed by a shell). For + // general use, it is sufficient to stop the process in a signal-delivery // stop which happens before the group stop. This done by MonitorSignal - // and works - // correctly for all signals. - if (log) - log->Printf( - "NativeProcessLinux::%s received a group stop for pid %" PRIu64 - " tid %" PRIu64 ". Transparent handling of group stops not " - "supported, resuming the thread.", - __FUNCTION__, GetID(), pid); + // and works correctly for all signals. + LLDB_LOG(log, + "received a group stop for pid {0} tid {1}. Transparent " + "handling of group stops not supported, resuming the " + "thread.", + GetID(), pid); ResumeThread(*thread_sp, thread_sp->GetState(), LLDB_INVALID_SIGNAL_NUMBER); } else { // ptrace(GETSIGINFO) failed (but not due to group-stop). // A return value of ESRCH means the thread/process is no longer on the - // system, - // so it was killed somehow outside of our control. Either way, we can't - // do anything - // with it anymore. + // system, so it was killed somehow outside of our control. Either way, + // we can't do anything with it anymore. // Stop tracking the metadata for the thread since it's entirely off the // system now. const bool thread_found = StopTrackingThread(pid); - if (log) - log->Printf( - "NativeProcessLinux::%s GetSignalInfo failed: %s, tid = %" PRIu64 - ", signal = %d, status = %d (%s, %s, %s)", - __FUNCTION__, info_err.AsCString(), pid, signal, status, - info_err.GetError() == ESRCH ? "thread/process killed" - : "unknown reason", - is_main_thread ? "is main thread" : "is not main thread", - thread_found ? "thread metadata removed" - : "thread metadata not found"); + LLDB_LOG(log, + "GetSignalInfo failed: {0}, tid = {1}, signal = {2}, " + "status = {3}, main_thread = {4}, thread_found: {5}", + info_err, pid, signal, status, is_main_thread, thread_found); if (is_main_thread) { // Notify the delegate - our process is not available but appears to @@ -736,19 +664,18 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, } else { // This thread was pulled out from underneath us. Anything to do here? // Do we want to do an all stop? - if (log) - log->Printf("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 - " non-main thread exit occurred, didn't tell delegate " - "anything since thread disappeared out from underneath " - "us", - __FUNCTION__, GetID(), pid); + LLDB_LOG(log, + "pid {0} tid {1} non-main thread exit occurred, didn't " + "tell delegate anything since thread disappeared out " + "from underneath us", + GetID(), pid); } } } } void NativeProcessLinux::WaitForNewThread(::pid_t tid) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); NativeThreadLinuxSP new_thread_sp = GetThreadByID(tid); @@ -763,65 +690,34 @@ void NativeProcessLinux::WaitForNewThread(::pid_t tid) { int status = -1; ::pid_t wait_pid; do { - if (log) - log->Printf("NativeProcessLinux::%s() received thread creation event for " - "tid %" PRIu32 - ". tid not tracked yet, waiting for thread to appear...", - __FUNCTION__, tid); + LLDB_LOG(log, + "received thread creation event for tid {0}. tid not tracked " + "yet, waiting for thread to appear...", + tid); wait_pid = waitpid(tid, &status, __WALL); } while (wait_pid == -1 && errno == EINTR); // Since we are waiting on a specific tid, this must be the creation event. - // But let's do - // some checks just in case. + // But let's do some checks just in case. if (wait_pid != tid) { - if (log) - log->Printf( - "NativeProcessLinux::%s() waiting for tid %" PRIu32 - " failed. Assuming the thread has disappeared in the meantime", - __FUNCTION__, tid); + LLDB_LOG(log, + "waiting for tid {0} failed. Assuming the thread has " + "disappeared in the meantime", + tid); // The only way I know of this could happen is if the whole process was // SIGKILLed in the mean time. In any case, we can't do anything about that // now. return; } if (WIFEXITED(status)) { - if (log) - log->Printf("NativeProcessLinux::%s() waiting for tid %" PRIu32 - " returned an 'exited' event. Not tracking the thread.", - __FUNCTION__, tid); + LLDB_LOG(log, + "waiting for tid {0} returned an 'exited' event. Not " + "tracking the thread.", + tid); // Also a very improbable event. return; } - siginfo_t info; - Error error = GetSignalInfo(tid, &info); - if (error.Fail()) { - if (log) - log->Printf( - "NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32 - " failed. Assuming the thread has disappeared in the meantime.", - __FUNCTION__, tid); - return; - } - - if (((info.si_pid != 0) || (info.si_code != SI_USER)) && log) { - // We should be getting a thread creation signal here, but we received - // something - // else. There isn't much we can do about it now, so we will just log that. - // Since the - // thread is alive and we are receiving events from it, we shall pretend - // that it was - // created properly. - log->Printf("NativeProcessLinux::%s() GetSignalInfo for tid %" PRIu32 - " received unexpected signal with code %d from pid %d.", - __FUNCTION__, tid, info.si_code, info.si_pid); - } - - if (log) - log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 - ": tracking new thread tid %" PRIu32, - __FUNCTION__, GetID(), tid); - + LLDB_LOG(log, "pid = {0}: tracking new thread tid {1}", GetID(), tid); new_thread_sp = AddThread(tid); ResumeThread(*new_thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); ThreadWasCreated(*new_thread_sp); @@ -829,7 +725,7 @@ void NativeProcessLinux::WaitForNewThread(::pid_t tid) { void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); const bool is_main_thread = (thread.GetID() == GetID()); assert(info.si_signo == SIGTRAP && "Unexpected child signal!"); @@ -852,11 +748,10 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, unsigned long event_message = 0; if (GetEventMessage(thread.GetID(), &event_message).Fail()) { - if (log) - log->Printf("NativeProcessLinux::%s() pid %" PRIu64 - " received thread creation event but GetEventMessage " - "failed so we don't know the new tid", - __FUNCTION__, thread.GetID()); + LLDB_LOG(log, + "pid {0} received thread creation event but " + "GetEventMessage failed so we don't know the new tid", + thread.GetID()); } else WaitForNewThread(event_message); @@ -866,35 +761,24 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)): { NativeThreadLinuxSP main_thread_sp; - if (log) - log->Printf("NativeProcessLinux::%s() received exec event, code = %d", - __FUNCTION__, info.si_code ^ SIGTRAP); + LLDB_LOG(log, "received exec event, code = {0}", info.si_code ^ SIGTRAP); // Exec clears any pending notifications. m_pending_notification_tid = LLDB_INVALID_THREAD_ID; // Remove all but the main thread here. Linux fork creates a new process // which only copies the main thread. - if (log) - log->Printf("NativeProcessLinux::%s exec received, stop tracking all but " - "main thread", - __FUNCTION__); + LLDB_LOG(log, "exec received, stop tracking all but main thread"); for (auto thread_sp : m_threads) { const bool is_main_thread = thread_sp && thread_sp->GetID() == GetID(); if (is_main_thread) { main_thread_sp = std::static_pointer_cast<NativeThreadLinux>(thread_sp); - if (log) - log->Printf( - "NativeProcessLinux::%s found main thread with tid %" PRIu64 - ", keeping", - __FUNCTION__, main_thread_sp->GetID()); + LLDB_LOG(log, "found main thread with tid {0}, keeping", + main_thread_sp->GetID()); } else { - if (log) - log->Printf( - "NativeProcessLinux::%s discarding non-main-thread tid %" PRIu64 - " due to exec", - __FUNCTION__, thread_sp->GetID()); + LLDB_LOG(log, "discarding non-main-thread tid {0} due to exec", + thread_sp->GetID()); } } @@ -906,11 +790,10 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, main_thread_sp->SetStoppedByExec(); } else { SetCurrentThreadID(LLDB_INVALID_THREAD_ID); - if (log) - log->Printf("NativeProcessLinux::%s pid %" PRIu64 - "no main thread found, discarded all threads, we're in a " - "no-thread state!", - __FUNCTION__, GetID()); + LLDB_LOG(log, + "pid {0} no main thread found, discarded all threads, " + "we're in a no-thread state!", + GetID()); } // Tell coordinator about about the "new" (since exec) stopped main thread. @@ -941,13 +824,11 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, if (GetEventMessage(thread.GetID(), &data).Fail()) data = -1; - if (log) { - log->Printf("NativeProcessLinux::%s() received PTRACE_EVENT_EXIT, data = " - "%lx (WIFEXITED=%s,WIFSIGNALED=%s), pid = %" PRIu64 " (%s)", - __FUNCTION__, data, WIFEXITED(data) ? "true" : "false", - WIFSIGNALED(data) ? "true" : "false", thread.GetID(), - is_main_thread ? "is main thread" : "not main thread"); - } + LLDB_LOG(log, + "received PTRACE_EVENT_EXIT, data = {0:x}, WIFEXITED={1}, " + "WIFSIGNALED={2}, pid = {3}, main_thread = {4}", + data, WIFEXITED(data), WIFSIGNALED(data), thread.GetID(), + is_main_thread); if (is_main_thread) { SetExitStatus(convert_pid_status_to_exit_type(data), @@ -978,16 +859,29 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, uint32_t wp_index; Error error = thread.GetRegisterContext()->GetWatchpointHitIndex( wp_index, (uintptr_t)info.si_addr); - if (error.Fail() && log) - log->Printf("NativeProcessLinux::%s() " - "received error while checking for watchpoint hits, " - "pid = %" PRIu64 " error = %s", - __FUNCTION__, thread.GetID(), error.AsCString()); + if (error.Fail()) + LLDB_LOG(log, + "received error while checking for watchpoint hits, pid = " + "{0}, error = {1}", + thread.GetID(), error); if (wp_index != LLDB_INVALID_INDEX32) { MonitorWatchpoint(thread, wp_index); break; } + // If a breakpoint was hit, report it + uint32_t bp_index; + error = thread.GetRegisterContext()->GetHardwareBreakHitIndex( + bp_index, (uintptr_t)info.si_addr); + if (error.Fail()) + LLDB_LOG(log, "received error while checking for hardware " + "breakpoint hits, pid = {0}, error = {1}", + thread.GetID(), error); + if (bp_index != LLDB_INVALID_INDEX32) { + MonitorBreakpoint(thread); + break; + } + // Otherwise, report step over MonitorTrace(thread); break; @@ -1002,11 +896,11 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, uint32_t wp_index; Error error = thread.GetRegisterContext()->GetWatchpointHitIndex( wp_index, LLDB_INVALID_ADDRESS); - if (error.Fail() && log) - log->Printf("NativeProcessLinux::%s() " - "received error while checking for watchpoint hits, " - "pid = %" PRIu64 " error = %s", - __FUNCTION__, thread.GetID(), error.AsCString()); + if (error.Fail()) + LLDB_LOG(log, + "received error while checking for watchpoint hits, pid = " + "{0}, error = {1}", + thread.GetID(), error); if (wp_index != LLDB_INVALID_INDEX32) { MonitorWatchpoint(thread, wp_index); break; @@ -1020,31 +914,28 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, case SIGTRAP: case (SIGTRAP | 0x80): - if (log) - log->Printf("NativeProcessLinux::%s() received unknown SIGTRAP system " - "call stop event, pid %" PRIu64 "tid %" PRIu64 ", resuming", - __FUNCTION__, GetID(), thread.GetID()); + LLDB_LOG( + log, + "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming", + info.si_code, GetID(), thread.GetID()); // Ignore these signals until we know more about them. ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER); break; default: - assert(false && "Unexpected SIGTRAP code!"); - if (log) - log->Printf("NativeProcessLinux::%s() pid %" PRIu64 "tid %" PRIu64 - " received unhandled SIGTRAP code: 0x%d", - __FUNCTION__, GetID(), thread.GetID(), info.si_code); + LLDB_LOG( + log, + "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming", + info.si_code, GetID(), thread.GetID()); + llvm_unreachable("Unexpected SIGTRAP code!"); break; } } void NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessLinux::%s() received trace event, pid = %" PRIu64 - " (single stepping)", - __FUNCTION__, thread.GetID()); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "received trace event, pid = {0}", thread.GetID()); // This thread is currently stopped. thread.SetStoppedByTrace(); @@ -1055,18 +946,13 @@ void NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread) { void NativeProcessLinux::MonitorBreakpoint(NativeThreadLinux &thread) { Log *log( GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf( - "NativeProcessLinux::%s() received breakpoint event, pid = %" PRIu64, - __FUNCTION__, thread.GetID()); + LLDB_LOG(log, "received breakpoint event, pid = {0}", thread.GetID()); // Mark the thread as stopped at breakpoint. thread.SetStoppedByBreakpoint(); Error error = FixupBreakpointPCAsNeeded(thread); if (error.Fail()) - if (log) - log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 " fixup: %s", - __FUNCTION__, thread.GetID(), error.AsCString()); + LLDB_LOG(log, "pid = {0} fixup: {1}", thread.GetID(), error); if (m_threads_stepping_with_breakpoint.find(thread.GetID()) != m_threads_stepping_with_breakpoint.end()) @@ -1079,10 +965,8 @@ void NativeProcessLinux::MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index) { Log *log( GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_WATCHPOINTS)); - if (log) - log->Printf("NativeProcessLinux::%s() received watchpoint event, " - "pid = %" PRIu64 ", wp_index = %" PRIu32, - __FUNCTION__, thread.GetID(), wp_index); + LLDB_LOG(log, "received watchpoint event, pid = {0}, wp_index = {1}", + thread.GetID(), wp_index); // Mark the thread as stopped at watchpoint. // The address is at (lldb::addr_t)info->si_addr if we need it. @@ -1098,7 +982,7 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info, const int signo = info.si_signo; const bool is_from_llgs = info.si_pid == getpid(); - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // POSIX says that process behaviour is undefined after it ignores a SIGFPE, // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a @@ -1110,47 +994,33 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info, // Similarly, ACK signals generated by this monitor. // Handle the signal. - if (info.si_code == SI_TKILL || info.si_code == SI_USER) { - if (log) - log->Printf("NativeProcessLinux::%s() received signal %s (%d) with code " - "%s, (siginfo pid = %d (%s), waitpid pid = %" PRIu64 ")", - __FUNCTION__, Host::GetSignalAsCString(signo), signo, - (info.si_code == SI_TKILL ? "SI_TKILL" : "SI_USER"), - info.si_pid, is_from_llgs ? "from llgs" : "not from llgs", - thread.GetID()); - } + LLDB_LOG(log, + "received signal {0} ({1}) with code {2}, (siginfo pid = {3}, " + "waitpid pid = {4})", + Host::GetSignalAsCString(signo), signo, info.si_code, + thread.GetID()); // Check for thread stop notification. if (is_from_llgs && (info.si_code == SI_TKILL) && (signo == SIGSTOP)) { // This is a tgkill()-based stop. - if (log) - log->Printf("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 - ", thread stopped", - __FUNCTION__, GetID(), thread.GetID()); + LLDB_LOG(log, "pid {0} tid {1}, thread stopped", GetID(), thread.GetID()); // Check that we're not already marked with a stop reason. // Note this thread really shouldn't already be marked as stopped - if we - // were, that would imply that - // the kernel signaled us with the thread stopping which we handled and - // marked as stopped, - // and that, without an intervening resume, we received another stop. It is - // more likely - // that we are missing the marking of a run state somewhere if we find that - // the thread was - // marked as stopped. + // were, that would imply that the kernel signaled us with the thread + // stopping which we handled and marked as stopped, and that, without an + // intervening resume, we received another stop. It is more likely that we + // are missing the marking of a run state somewhere if we find that the + // thread was marked as stopped. const StateType thread_state = thread.GetState(); if (!StateIsStoppedState(thread_state, false)) { // An inferior thread has stopped because of a SIGSTOP we have sent it. // Generally, these are not important stops and we don't want to report - // them as - // they are just used to stop other threads when one thread (the one with - // the - // *real* stop reason) hits a breakpoint (watchpoint, etc...). However, in - // the - // case of an asynchronous Interrupt(), this *is* the real stop reason, so - // we - // leave the signal intact if this is the thread that was chosen as the - // triggering thread. + // them as they are just used to stop other threads when one thread (the + // one with the *real* stop reason) hits a breakpoint (watchpoint, + // etc...). However, in the case of an asynchronous Interrupt(), this *is* + // the real stop reason, so we leave the signal intact if this is the + // thread that was chosen as the triggering thread. if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) { if (m_pending_notification_tid == thread.GetID()) thread.SetStoppedBySignal(SIGSTOP, &info); @@ -1163,30 +1033,15 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info, // We can end up here if stop was initiated by LLGS but by this time a // thread stop has occurred - maybe initiated by another event. Error error = ResumeThread(thread, thread.GetState(), 0); - if (error.Fail() && log) { - log->Printf( - "NativeProcessLinux::%s failed to resume thread tid %" PRIu64 - ": %s", - __FUNCTION__, thread.GetID(), error.AsCString()); - } + if (error.Fail()) + LLDB_LOG(log, "failed to resume thread {0}: {1}", thread.GetID(), + error); } } else { - if (log) { - // Retrieve the signal name if the thread was stopped by a signal. - int stop_signo = 0; - const bool stopped_by_signal = thread.IsStopped(&stop_signo); - const char *signal_name = stopped_by_signal - ? Host::GetSignalAsCString(stop_signo) - : "<not stopped by signal>"; - if (!signal_name) - signal_name = "<no-signal-name>"; - - log->Printf("NativeProcessLinux::%s() pid %" PRIu64 " tid %" PRIu64 - ", thread was already marked as a stopped state (state=%s, " - "signal=%d (%s)), leaving stop signal as is", - __FUNCTION__, GetID(), thread.GetID(), - StateAsCString(thread_state), stop_signo, signal_name); - } + LLDB_LOG(log, + "pid {0} tid {1}, thread was already marked as a stopped " + "state (state={2}), leaving stop signal as is", + GetID(), thread.GetID(), thread_state); SignalIfAllThreadsStopped(); } @@ -1194,11 +1049,15 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info, return; } - if (log) - log->Printf("NativeProcessLinux::%s() received signal %s", __FUNCTION__, - Host::GetSignalAsCString(signo)); + // Check if debugger should stop at this signal or just ignore it + // and resume the inferior. + if (m_signals_to_ignore.find(signo) != m_signals_to_ignore.end()) { + ResumeThread(thread, thread.GetState(), signo); + return; + } // This thread is stopped. + LLDB_LOG(log, "received signal {0}", Host::GetSignalAsCString(signo)); thread.SetStoppedBySignal(signo, &info); // Send a stop to the debugger after we get all other threads to stop. @@ -1383,10 +1242,8 @@ bool NativeProcessLinux::SupportHardwareSingleStepping() const { } Error NativeProcessLinux::Resume(const ResumeActionList &resume_actions) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("NativeProcessLinux::%s called: pid %" PRIu64, __FUNCTION__, - GetID()); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid {0}", GetID()); bool software_single_step = !SupportHardwareSingleStepping(); @@ -1415,20 +1272,13 @@ Error NativeProcessLinux::Resume(const ResumeActionList &resume_actions) { resume_actions.GetActionForThread(thread_sp->GetID(), true); if (action == nullptr) { - if (log) - log->Printf( - "NativeProcessLinux::%s no action specified for pid %" PRIu64 - " tid %" PRIu64, - __FUNCTION__, GetID(), thread_sp->GetID()); + LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), + thread_sp->GetID()); continue; } - if (log) { - log->Printf("NativeProcessLinux::%s processing resume action state %s " - "for pid %" PRIu64 " tid %" PRIu64, - __FUNCTION__, StateAsCString(action->state), GetID(), - thread_sp->GetID()); - } + LLDB_LOG(log, "processing resume action state {0} for pid {1} tid {2}", + action->state, GetID(), thread_sp->GetID()); switch (action->state) { case eStateRunning: @@ -1442,7 +1292,7 @@ Error NativeProcessLinux::Resume(const ResumeActionList &resume_actions) { case eStateSuspended: case eStateStopped: - lldbassert(0 && "Unexpected state"); + llvm_unreachable("Unexpected state"); default: return Error("NativeProcessLinux::%s (): unexpected state %s specified " @@ -1487,11 +1337,9 @@ Error NativeProcessLinux::Detach() { Error NativeProcessLinux::Signal(int signo) { Error error; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf( - "NativeProcessLinux::%s: sending signal %d (%s) to pid %" PRIu64, - __FUNCTION__, signo, Host::GetSignalAsCString(signo), GetID()); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "sending signal {0} ({1}) to pid {1}", signo, + Host::GetSignalAsCString(signo), GetID()); if (kill(GetID(), signo)) error.SetErrorToErrno(); @@ -1502,16 +1350,12 @@ Error NativeProcessLinux::Signal(int signo) { Error NativeProcessLinux::Interrupt() { // Pick a running thread (or if none, a not-dead stopped thread) as // the chosen thread that will be the stop-reason thread. - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); NativeThreadProtocolSP running_thread_sp; NativeThreadProtocolSP stopped_thread_sp; - if (log) - log->Printf( - "NativeProcessLinux::%s selecting running thread for interrupt target", - __FUNCTION__); - + LLDB_LOG(log, "selecting running thread for interrupt target"); for (auto thread_sp : m_threads) { // The thread shouldn't be null but lets just cover that here. if (!thread_sp) @@ -1533,9 +1377,7 @@ Error NativeProcessLinux::Interrupt() { if (!running_thread_sp && !stopped_thread_sp) { Error error("found no running/stepping or live stopped threads as target " "for interrupt"); - if (log) - log->Printf("NativeProcessLinux::%s skipping due to error: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOG(log, "skipping due to error: {0}", error); return error; } @@ -1543,12 +1385,9 @@ Error NativeProcessLinux::Interrupt() { NativeThreadProtocolSP deferred_signal_thread_sp = running_thread_sp ? running_thread_sp : stopped_thread_sp; - if (log) - log->Printf("NativeProcessLinux::%s pid %" PRIu64 " %s tid %" PRIu64 - " chosen for interrupt target", - __FUNCTION__, GetID(), - running_thread_sp ? "running" : "stopped", - deferred_signal_thread_sp->GetID()); + LLDB_LOG(log, "pid {0} {1} tid {2} chosen for interrupt target", GetID(), + running_thread_sp ? "running" : "stopped", + deferred_signal_thread_sp->GetID()); StopRunningThreads(deferred_signal_thread_sp->GetID()); @@ -1556,10 +1395,8 @@ Error NativeProcessLinux::Interrupt() { } Error NativeProcessLinux::Kill() { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessLinux::%s called for PID %" PRIu64, __FUNCTION__, - GetID()); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid {0}", GetID()); Error error; @@ -1570,10 +1407,8 @@ Error NativeProcessLinux::Kill() { case StateType::eStateDetached: case StateType::eStateUnloaded: // Nothing to do - the process is already dead. - if (log) - log->Printf("NativeProcessLinux::%s ignored for PID %" PRIu64 - " due to current state: %s", - __FUNCTION__, GetID(), StateAsCString(m_state)); + LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(), + m_state); return error; case StateType::eStateConnected: @@ -1596,11 +1431,11 @@ Error NativeProcessLinux::Kill() { } static Error -ParseMemoryRegionInfoFromProcMapsLine(const std::string &maps_line, +ParseMemoryRegionInfoFromProcMapsLine(llvm::StringRef &maps_line, MemoryRegionInfo &memory_region_info) { memory_region_info.Clear(); - StringExtractor line_extractor(maps_line.c_str()); + StringExtractor line_extractor(maps_line); // Format: {address_start_hex}-{address_end_hex} perms offset dev inode // pathname @@ -1712,6 +1547,7 @@ Error NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr, assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) && "descending /proc/pid/maps entries detected, unexpected"); prev_base_address = proc_entry_info.GetRange().GetRangeBase(); + UNUSED_IF_ASSERT_DISABLED(prev_base_address); // If the target address comes before this entry, indicate distance to next // region. @@ -1750,60 +1586,50 @@ Error NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr, } Error NativeProcessLinux::PopulateMemoryRegionCache() { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // If our cache is empty, pull the latest. There should always be at least // one memory region if memory region handling is supported. if (!m_mem_region_cache.empty()) { - if (log) - log->Printf("NativeProcessLinux::%s reusing %" PRIu64 - " cached memory region entries", - __FUNCTION__, - static_cast<uint64_t>(m_mem_region_cache.size())); + LLDB_LOG(log, "reusing {0} cached memory region entries", + m_mem_region_cache.size()); return Error(); } - Error error = ProcFileReader::ProcessLineByLine( - GetID(), "maps", [&](const std::string &line) -> bool { - MemoryRegionInfo info; - const Error parse_error = - ParseMemoryRegionInfoFromProcMapsLine(line, info); - if (parse_error.Success()) { - m_mem_region_cache.emplace_back( - info, FileSpec(info.GetName().GetCString(), true)); - return true; - } else { - if (log) - log->Printf("NativeProcessLinux::%s failed to parse proc maps " - "line '%s': %s", - __FUNCTION__, line.c_str(), parse_error.AsCString()); - return false; - } - }); - - // If we had an error, we'll mark unsupported. - if (error.Fail()) { + auto BufferOrError = getProcFile(GetID(), "maps"); + if (!BufferOrError) { m_supports_mem_region = LazyBool::eLazyBoolNo; - return error; - } else if (m_mem_region_cache.empty()) { + return BufferOrError.getError(); + } + StringRef Rest = BufferOrError.get()->getBuffer(); + while (! Rest.empty()) { + StringRef Line; + std::tie(Line, Rest) = Rest.split('\n'); + MemoryRegionInfo info; + const Error parse_error = ParseMemoryRegionInfoFromProcMapsLine(Line, info); + if (parse_error.Fail()) { + LLDB_LOG(log, "failed to parse proc maps line '{0}': {1}", Line, + parse_error); + m_supports_mem_region = LazyBool::eLazyBoolNo; + return parse_error; + } + m_mem_region_cache.emplace_back( + info, FileSpec(info.GetName().GetCString(), true)); + } + + if (m_mem_region_cache.empty()) { // No entries after attempting to read them. This shouldn't happen if // /proc/{pid}/maps is supported. Assume we don't support map entries // via procfs. - if (log) - log->Printf("NativeProcessLinux::%s failed to find any procfs maps " - "entries, assuming no support for memory region metadata " - "retrieval", - __FUNCTION__); m_supports_mem_region = LazyBool::eLazyBoolNo; - error.SetErrorString("not supported"); - return error; + LLDB_LOG(log, + "failed to find any procfs maps entries, assuming no support " + "for memory region metadata retrieval"); + return Error("not supported"); } - if (log) - log->Printf("NativeProcessLinux::%s read %" PRIu64 - " memory region entries from /proc/%" PRIu64 "/maps", - __FUNCTION__, static_cast<uint64_t>(m_mem_region_cache.size()), - GetID()); + LLDB_LOG(log, "read {0} memory region entries from /proc/{1}/maps", + m_mem_region_cache.size(), GetID()); // We support memory retrieval, remember that. m_supports_mem_region = LazyBool::eLazyBoolYes; @@ -1811,15 +1637,10 @@ Error NativeProcessLinux::PopulateMemoryRegionCache() { } void NativeProcessLinux::DoStopIDBumped(uint32_t newBumpId) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessLinux::%s(newBumpId=%" PRIu32 ") called", - __FUNCTION__, newBumpId); - - if (log) - log->Printf("NativeProcessLinux::%s clearing %" PRIu64 - " entries from the cache", - __FUNCTION__, static_cast<uint64_t>(m_mem_region_cache.size())); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "newBumpId={0}", newBumpId); + LLDB_LOG(log, "clearing {0} entries from memory region cache", + m_mem_region_cache.size()); m_mem_region_cache.clear(); } @@ -1917,11 +1738,18 @@ Error NativeProcessLinux::GetSoftwareBreakpointPCOffset( Error NativeProcessLinux::SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) { if (hardware) - return Error("NativeProcessLinux does not support hardware breakpoints"); + return SetHardwareBreakpoint(addr, size); else return SetSoftwareBreakpoint(addr, size); } +Error NativeProcessLinux::RemoveBreakpoint(lldb::addr_t addr, bool hardware) { + if (hardware) + return RemoveHardwareBreakpoint(addr); + else + return NativeProcessProtocol::RemoveBreakpoint(addr); +} + Error NativeProcessLinux::GetSoftwareBreakpointTrapOpcode( size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) { @@ -2154,40 +1982,30 @@ Error NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size, bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0); const bool success = bytes_read == size; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("NativeProcessLinux::%s using process_vm_readv to read %zd " - "bytes from inferior address 0x%" PRIx64 ": %s", - __FUNCTION__, size, addr, - success ? "Success" : strerror(errno)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, + "using process_vm_readv to read {0} bytes from inferior " + "address {1:x}: {2}", + size, addr, success ? "Success" : strerror(errno)); if (success) return Error(); - // else - // the call failed for some reason, let's retry the read using ptrace - // api. + // else the call failed for some reason, let's retry the read using ptrace + // api. } unsigned char *dst = static_cast<unsigned char *>(buf); size_t remainder; long data; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL)); - if (log) - ProcessPOSIXLog::IncNestLevel(); - if (log && ProcessPOSIXLog::AtTopNestLevel() && - log->GetMask().Test(POSIX_LOG_MEMORY)) - log->Printf("NativeProcessLinux::%s(%p, %p, %zd, _)", __FUNCTION__, - (void *)addr, buf, size); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); for (bytes_read = 0; bytes_read < size; bytes_read += remainder) { Error error = NativeProcessLinux::PtraceWrapper( PTRACE_PEEKDATA, GetID(), (void *)addr, nullptr, 0, &data); - if (error.Fail()) { - if (log) - ProcessPOSIXLog::DecNestLevel(); + if (error.Fail()) return error; - } remainder = size - bytes_read; remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; @@ -2195,24 +2013,10 @@ Error NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size, // Copy the data into our buffer memcpy(dst, &data, remainder); - if (log && ProcessPOSIXLog::AtTopNestLevel() && - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && - size <= POSIX_LOG_MEMORY_SHORT_BYTES))) { - uintptr_t print_dst = 0; - // Format bytes from data by moving into print_dst for log output - for (unsigned i = 0; i < remainder; ++i) - print_dst |= (((data >> i * 8) & 0xFF) << i * 8); - log->Printf("NativeProcessLinux::%s() [0x%" PRIx64 "]:0x%" PRIx64 - " (0x%" PRIx64 ")", - __FUNCTION__, addr, uint64_t(print_dst), uint64_t(data)); - } + LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data); addr += k_ptrace_word_size; dst += k_ptrace_word_size; } - - if (log) - ProcessPOSIXLog::DecNestLevel(); return Error(); } @@ -2231,13 +2035,8 @@ Error NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, size_t remainder; Error error; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL)); - if (log) - ProcessPOSIXLog::IncNestLevel(); - if (log && ProcessPOSIXLog::AtTopNestLevel() && - log->GetMask().Test(POSIX_LOG_MEMORY)) - log->Printf("NativeProcessLinux::%s(0x%" PRIx64 ", %p, %zu)", __FUNCTION__, - addr, buf, size); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); for (bytes_written = 0; bytes_written < size; bytes_written += remainder) { remainder = size - bytes_written; @@ -2247,54 +2046,32 @@ Error NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, unsigned long data = 0; memcpy(&data, src, k_ptrace_word_size); - if (log && ProcessPOSIXLog::AtTopNestLevel() && - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && - size <= POSIX_LOG_MEMORY_SHORT_BYTES))) - log->Printf("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, - (void *)addr, *(const unsigned long *)src, data); - + LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data); error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(), (void *)addr, (void *)data); - if (error.Fail()) { - if (log) - ProcessPOSIXLog::DecNestLevel(); + if (error.Fail()) return error; - } } else { unsigned char buff[8]; size_t bytes_read; error = ReadMemory(addr, buff, k_ptrace_word_size, bytes_read); - if (error.Fail()) { - if (log) - ProcessPOSIXLog::DecNestLevel(); + if (error.Fail()) return error; - } memcpy(buff, src, remainder); size_t bytes_written_rec; error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec); - if (error.Fail()) { - if (log) - ProcessPOSIXLog::DecNestLevel(); + if (error.Fail()) return error; - } - if (log && ProcessPOSIXLog::AtTopNestLevel() && - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && - size <= POSIX_LOG_MEMORY_SHORT_BYTES))) - log->Printf("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, - (void *)addr, *(const unsigned long *)src, - *(unsigned long *)buff); + LLDB_LOG(log, "[{0:x}]:{1:x} ({2:x})", addr, *(const unsigned long *)src, + *(unsigned long *)buff); } addr += k_ptrace_word_size; src += k_ptrace_word_size; } - if (log) - ProcessPOSIXLog::DecNestLevel(); return error; } @@ -2328,14 +2105,10 @@ bool NativeProcessLinux::HasThreadNoLock(lldb::tid_t thread_id) { } bool NativeProcessLinux::StopTrackingThread(lldb::tid_t thread_id) { - Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD); - - if (log) - log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, - thread_id); + Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); + LLDB_LOG(log, "tid: {0})", thread_id); bool found = false; - for (auto it = m_threads.begin(); it != m_threads.end(); ++it) { if (*it && ((*it)->GetID() == thread_id)) { m_threads.erase(it); @@ -2345,18 +2118,12 @@ bool NativeProcessLinux::StopTrackingThread(lldb::tid_t thread_id) { } SignalIfAllThreadsStopped(); - return found; } NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - - if (log) { - log->Printf("NativeProcessLinux::%s pid %" PRIu64 - " adding thread with tid %" PRIu64, - __FUNCTION__, GetID(), thread_id); - } + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); assert(!HasThreadNoLock(thread_id) && "attempted to add a thread by id that already exists"); @@ -2371,7 +2138,7 @@ NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) { } Error NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); Error error; @@ -2380,24 +2147,17 @@ Error NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { NativeRegisterContextSP context_sp = thread.GetRegisterContext(); if (!context_sp) { error.SetErrorString("cannot get a NativeRegisterContext for the thread"); - if (log) - log->Printf("NativeProcessLinux::%s failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOG(log, "failed: {0}", error); return error; } uint32_t breakpoint_size = 0; error = GetSoftwareBreakpointPCOffset(breakpoint_size); if (error.Fail()) { - if (log) - log->Printf("NativeProcessLinux::%s GetBreakpointSize() failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOG(log, "GetBreakpointSize() failed: {0}", error); return error; - } else { - if (log) - log->Printf("NativeProcessLinux::%s breakpoint size: %" PRIu32, - __FUNCTION__, breakpoint_size); - } + } else + LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size); // First try probing for a breakpoint at a software breakpoint location: PC - // breakpoint size. @@ -2415,21 +2175,19 @@ Error NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { error = m_breakpoint_list.GetBreakpoint(breakpoint_addr, breakpoint_sp); if (!error.Success() || !breakpoint_sp) { // We didn't find one at a software probe location. Nothing to do. - if (log) - log->Printf( - "NativeProcessLinux::%s pid %" PRIu64 - " no lldb breakpoint found at current pc with adjustment: 0x%" PRIx64, - __FUNCTION__, GetID(), breakpoint_addr); + LLDB_LOG(log, + "pid {0} no lldb breakpoint found at current pc with " + "adjustment: {1}", + GetID(), breakpoint_addr); return Error(); } // If the breakpoint is not a software breakpoint, nothing to do. if (!breakpoint_sp->IsSoftwareBreakpoint()) { - if (log) - log->Printf("NativeProcessLinux::%s pid %" PRIu64 - " breakpoint found at 0x%" PRIx64 - ", not software, nothing to adjust", - __FUNCTION__, GetID(), breakpoint_addr); + LLDB_LOG( + log, + "pid {0} breakpoint found at {1:x}, not software, nothing to adjust", + GetID(), breakpoint_addr); return Error(); } @@ -2440,28 +2198,21 @@ Error NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { // Sanity check. if (breakpoint_size == 0) { // Nothing to do! How did we get here? - if (log) - log->Printf( - "NativeProcessLinux::%s pid %" PRIu64 - " breakpoint found at 0x%" PRIx64 - ", it is software, but the size is zero, nothing to do (unexpected)", - __FUNCTION__, GetID(), breakpoint_addr); + LLDB_LOG(log, + "pid {0} breakpoint found at {1:x}, it is software, but the " + "size is zero, nothing to do (unexpected)", + GetID(), breakpoint_addr); return Error(); } // Change the program counter. - if (log) - log->Printf("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 - ": changing PC from 0x%" PRIx64 " to 0x%" PRIx64, - __FUNCTION__, GetID(), thread.GetID(), initial_pc_addr, - breakpoint_addr); + LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(), + thread.GetID(), initial_pc_addr, breakpoint_addr); error = context_sp->SetPC(breakpoint_addr); if (error.Fail()) { - if (log) - log->Printf("NativeProcessLinux::%s pid %" PRIu64 " tid %" PRIu64 - ": failed to set PC: %s", - __FUNCTION__, GetID(), thread.GetID(), error.AsCString()); + LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(), + thread.GetID(), error); return error; } @@ -2511,11 +2262,8 @@ NativeThreadLinuxSP NativeProcessLinux::GetThreadByID(lldb::tid_t tid) { Error NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, lldb::StateType state, int signo) { - Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD); - - if (log) - log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, - thread.GetID()); + Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); + LLDB_LOG(log, "tid: {0}", thread.GetID()); // Before we do the resume below, first check if we have a pending // stop notification that is currently waiting for @@ -2523,12 +2271,12 @@ Error NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, // we're ostensibly waiting for threads to stop before we send out the // pending notification, and here we are resuming one before we send // out the pending stop notification. - if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && log) { - log->Printf("NativeProcessLinux::%s about to resume tid %" PRIu64 - " per explicit request but we have a pending stop notification " - "(tid %" PRIu64 ") that is actively waiting for this thread to " - "stop. Valid sequence of events?", - __FUNCTION__, thread.GetID(), m_pending_notification_tid); + if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) { + LLDB_LOG(log, + "about to resume tid {0} per explicit request but we have a " + "pending stop notification (tid {1}) that is actively " + "waiting for this thread to stop. Valid sequence of events?", + thread.GetID(), m_pending_notification_tid); } // Request a resume. We expect this to be synchronous and the system @@ -2547,9 +2295,7 @@ Error NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, return step_result; } default: - if (log) - log->Printf("NativeProcessLinux::%s Unhandled state %s.", __FUNCTION__, - StateAsCString(state)); + LLDB_LOG(log, "Unhandled state {0}.", state); llvm_unreachable("Unhandled state for resume"); } } @@ -2557,13 +2303,9 @@ Error NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, //===----------------------------------------------------------------------===// void NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) { - Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD); - - if (log) { - log->Printf("NativeProcessLinux::%s about to process event: " - "(triggering_tid: %" PRIu64 ")", - __FUNCTION__, triggering_tid); - } + Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); + LLDB_LOG(log, "about to process event: (triggering_tid: {0})", + triggering_tid); m_pending_notification_tid = triggering_tid; @@ -2575,10 +2317,7 @@ void NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) { } SignalIfAllThreadsStopped(); - - if (log) { - log->Printf("NativeProcessLinux::%s event processing done", __FUNCTION__); - } + LLDB_LOG(log, "event processing done"); } void NativeProcessLinux::SignalIfAllThreadsStopped() { @@ -2599,10 +2338,8 @@ void NativeProcessLinux::SignalIfAllThreadsStopped() { for (const auto &thread_info : m_threads_stepping_with_breakpoint) { Error error = RemoveBreakpoint(thread_info.second); if (error.Fail()) - if (log) - log->Printf("NativeProcessLinux::%s() pid = %" PRIu64 - " remove stepping breakpoint: %s", - __FUNCTION__, thread_info.first, error.AsCString()); + LLDB_LOG(log, "pid = {0} remove stepping breakpoint: {1}", + thread_info.first, error); } m_threads_stepping_with_breakpoint.clear(); @@ -2613,11 +2350,8 @@ void NativeProcessLinux::SignalIfAllThreadsStopped() { } void NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) { - Log *const log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD); - - if (log) - log->Printf("NativeProcessLinux::%s (tid: %" PRIu64 ")", __FUNCTION__, - thread.GetID()); + Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); + LLDB_LOG(log, "tid: {0}", thread.GetID()); if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && StateIsRunningState(thread.GetState())) { @@ -2629,7 +2363,7 @@ void NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) { } void NativeProcessLinux::SigchldHandler() { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // Process all pending waitpid notifications. while (true) { int status = -1; @@ -2643,10 +2377,7 @@ void NativeProcessLinux::SigchldHandler() { continue; Error error(errno, eErrorTypePOSIX); - if (log) - log->Printf("NativeProcessLinux::%s waitpid (-1, &status, __WALL | " - "__WNOTHREAD | WNOHANG) failed: %s", - __FUNCTION__, error.AsCString()); + LLDB_LOG(log, "waitpid (-1, &status, _) failed: {0}", error); break; } @@ -2671,13 +2402,10 @@ void NativeProcessLinux::SigchldHandler() { } else status_cstr = "(\?\?\?)"; - if (log) - log->Printf("NativeProcessLinux::%s: waitpid (-1, &status, __WALL | " - "__WNOTHREAD | WNOHANG)" - "=> pid = %" PRIi32 - ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", - __FUNCTION__, wait_pid, status, status_cstr, signal, - exit_status); + LLDB_LOG(log, + "waitpid (-1, &status, _) => pid = {0}, status = {1:x} " + "({2}), signal = {3}, exit_state = {4}", + wait_pid, status, status_cstr, signal, exit_status); MonitorCallback(wait_pid, exited, signal, exit_status); } @@ -2710,32 +2438,13 @@ Error NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr, if (result) *result = ret; - if (log) - log->Printf("ptrace(%d, %" PRIu64 ", %p, %p, %zu)=%lX", req, pid, addr, - data, data_size, ret); + LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data, + data_size, ret); PtraceDisplayBytes(req, data, data_size); - if (log && error.GetError() != 0) { - const char *str; - switch (error.GetError()) { - case ESRCH: - str = "ESRCH"; - break; - case EINVAL: - str = "EINVAL"; - break; - case EBUSY: - str = "EBUSY"; - break; - case EPERM: - str = "EPERM"; - break; - default: - str = error.AsCString(); - } - log->Printf("ptrace() failed; errno=%d (%s)", error.GetError(), str); - } + if (error.Fail()) + LLDB_LOG(log, "ptrace() failed: {0}", error); return error; } diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h index 5f51a6bc138e..e4809d082b50 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -16,9 +16,10 @@ // Other libraries and framework includes #include "lldb/Core/ArchSpec.h" #include "lldb/Host/Debug.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Host/HostThread.h" +#include "lldb/Host/linux/Support.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/FileSpec.h" #include "lldb/lldb-types.h" #include "NativeThreadLinux.h" @@ -86,6 +87,8 @@ public: Error SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override; + Error RemoveBreakpoint(lldb::addr_t addr, bool hardware = false) override; + void DoStopIDBumped(uint32_t newBumpId) override; Error GetLoadedModuleFileSpec(const char *module_path, @@ -96,6 +99,11 @@ public: NativeThreadLinuxSP GetThreadByID(lldb::tid_t id); + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> + GetAuxvData() const override { + return getProcFile(GetID(), "auxv"); + } + // --------------------------------------------------------------------- // Interface used by NativeRegisterContext-derived classes. // --------------------------------------------------------------------- diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp index 580d2f952ad1..be256e972215 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp @@ -171,10 +171,7 @@ Error NativeRegisterContextLinux::DoReadRegisterValue(uint32_t offset, // First cast to an unsigned of the same size to avoid sign extension. value.SetUInt(static_cast<unsigned long>(data), size); - if (log) - log->Printf("NativeRegisterContextLinux::%s() reg %s: 0x%lx", __FUNCTION__, - reg_name, data); - + LLDB_LOG(log, "{0}: {1:x}", reg_name, data); return error; } @@ -183,10 +180,7 @@ Error NativeRegisterContextLinux::DoWriteRegisterValue( Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS)); void *buf = reinterpret_cast<void *>(value.GetAsUInt64()); - - if (log) - log->Printf("NativeRegisterContextLinux::%s() reg %s: %p", __FUNCTION__, - reg_name, buf); + LLDB_LOG(log, "{0}: {1}", reg_name, buf); return NativeProcessLinux::PtraceWrapper( PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), buf); diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux.h index a16c65b64a07..4dfc5365f357 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux.h @@ -10,10 +10,10 @@ #ifndef lldb_NativeRegisterContextLinux_h #define lldb_NativeRegisterContextLinux_h -#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h" #include "lldb/Host/common/NativeThreadProtocol.h" #include "Plugins/Process/Linux/NativeProcessLinux.h" +#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h" namespace lldb_private { namespace process_linux { diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp index 9e857139cfca..2dd23ad75a03 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp @@ -11,13 +11,14 @@ #include "NativeRegisterContextLinux_arm.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" #include "Plugins/Process/Linux/Procfs.h" -#include "Plugins/Process/Utility/RegisterContextLinux_arm.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" #include <elf.h> #include <sys/socket.h> @@ -108,7 +109,7 @@ NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm( const ArchSpec &target_arch, NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) : NativeRegisterContextLinux(native_thread, concrete_frame_idx, - new RegisterContextLinux_arm(target_arch)) { + new RegisterInfoPOSIX_arm(target_arch)) { switch (target_arch.GetMachine()) { case llvm::Triple::arm: m_reg_info.num_registers = k_num_registers_arm; @@ -129,6 +130,7 @@ NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm( ::memset(&m_fpr, 0, sizeof(m_fpr)); ::memset(&m_gpr_arm, 0, sizeof(m_gpr_arm)); ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); + ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs)); // 16 is just a maximum value, query hardware for actual watchpoint count m_max_hwp_supported = 16; @@ -353,10 +355,8 @@ bool NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const { return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } -uint32_t -NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr, - size_t size) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); +uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareBreakpoints() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); if (log) log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); @@ -367,77 +367,78 @@ NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr, error = ReadHardwareDebugInfo(); if (error.Fail()) - return LLDB_INVALID_INDEX32; + return 0; - uint32_t control_value = 0, bp_index = 0; + LLDB_LOG(log, "{0}", m_max_hbp_supported); + return m_max_hbp_supported; +} - // Check if size has a valid hardware breakpoint length. - // Thumb instructions are 2-bytes but we have no way here to determine - // if target address is a thumb or arm instruction. - // TODO: Add support for setting thumb mode hardware breakpoints - if (size != 4 && size != 2) - return LLDB_INVALID_INDEX32; +uint32_t +NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); + LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size); - // Setup control value - // Make the byte_mask into a valid Byte Address Select mask - control_value = 0xfu << 5; + // Read hardware breakpoint and watchpoint information. + Error error = ReadHardwareDebugInfo(); - // Enable this breakpoint and make it stop in privileged or user mode; - control_value |= 7; + if (error.Fail()) + return LLDB_INVALID_INDEX32; - // Make sure bits 1:0 are clear in our address - // This should be different once we support thumb here. - addr &= ~((lldb::addr_t)3); + uint32_t control_value = 0, bp_index = 0; - // Iterate over stored hardware breakpoints - // Find a free bp_index or update reference count if duplicate. - bp_index = LLDB_INVALID_INDEX32; + // Setup address and control values. + // Use size to get a hint of arm vs thumb modes. + switch (size) { + case 2: + control_value = (0x3 << 5) | 7; + addr &= ~1; + break; + case 4: + control_value = (0xfu << 5) | 7; + addr &= ~3; + break; + default: + return LLDB_INVALID_INDEX32; + } + // Iterate over stored breakpoints and find a free bp_index + bp_index = LLDB_INVALID_INDEX32; for (uint32_t i = 0; i < m_max_hbp_supported; i++) { if ((m_hbr_regs[i].control & 1) == 0) { bp_index = i; // Mark last free slot - } else if (m_hbr_regs[i].address == addr && - m_hbr_regs[i].control == control_value) { - bp_index = i; // Mark duplicate index - break; // Stop searching here + } else if (m_hbr_regs[i].address == addr) { + return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints. } } if (bp_index == LLDB_INVALID_INDEX32) return LLDB_INVALID_INDEX32; - // Add new or update existing breakpoint - if ((m_hbr_regs[bp_index].control & 1) == 0) { - m_hbr_regs[bp_index].address = addr; - m_hbr_regs[bp_index].control = control_value; - m_hbr_regs[bp_index].refcount = 1; + // Update breakpoint in local cache + m_hbr_regs[bp_index].real_addr = addr; + m_hbr_regs[bp_index].address = addr; + m_hbr_regs[bp_index].control = control_value; - // PTRACE call to set corresponding hardware breakpoint register. - error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index); + // PTRACE call to set corresponding hardware breakpoint register. + error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index); - if (error.Fail()) { - m_hbr_regs[bp_index].address = 0; - m_hbr_regs[bp_index].control &= ~1; - m_hbr_regs[bp_index].refcount = 0; + if (error.Fail()) { + m_hbr_regs[bp_index].address = 0; + m_hbr_regs[bp_index].control &= ~1; - return LLDB_INVALID_INDEX32; - } - } else - m_hbr_regs[bp_index].refcount++; + return LLDB_INVALID_INDEX32; + } return bp_index; } bool NativeRegisterContextLinux_arm::ClearHardwareBreakpoint(uint32_t hw_idx) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - - Error error; + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); + LLDB_LOG(log, "hw_idx: {0}", hw_idx); // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); + Error error = ReadHardwareDebugInfo(); if (error.Fail()) return false; @@ -445,39 +446,50 @@ bool NativeRegisterContextLinux_arm::ClearHardwareBreakpoint(uint32_t hw_idx) { if (hw_idx >= m_max_hbp_supported) return false; - // Update reference count if multiple references. - if (m_hbr_regs[hw_idx].refcount > 1) { - m_hbr_regs[hw_idx].refcount--; - return true; - } else if (m_hbr_regs[hw_idx].refcount == 1) { - // Create a backup we can revert to in case of failure. - lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; - uint32_t tempControl = m_hbr_regs[hw_idx].control; - uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount; + // Create a backup we can revert to in case of failure. + lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; + uint32_t tempControl = m_hbr_regs[hw_idx].control; - m_hbr_regs[hw_idx].control &= ~1; - m_hbr_regs[hw_idx].address = 0; - m_hbr_regs[hw_idx].refcount = 0; + m_hbr_regs[hw_idx].control &= ~1; + m_hbr_regs[hw_idx].address = 0; - // PTRACE call to clear corresponding hardware breakpoint register. - WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx); + // PTRACE call to clear corresponding hardware breakpoint register. + error = WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx); - if (error.Fail()) { - m_hbr_regs[hw_idx].control = tempControl; - m_hbr_regs[hw_idx].address = tempAddr; - m_hbr_regs[hw_idx].refcount = tempRefCount; + if (error.Fail()) { + m_hbr_regs[hw_idx].control = tempControl; + m_hbr_regs[hw_idx].address = tempAddr; - return false; - } + return false; + } - return true; + return true; +} + +Error NativeRegisterContextLinux_arm::GetHardwareBreakHitIndex( + uint32_t &bp_index, lldb::addr_t trap_addr) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); + + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + + lldb::addr_t break_addr; + + for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) { + break_addr = m_hbr_regs[bp_index].address; + + if ((m_hbr_regs[bp_index].control & 0x1) && (trap_addr == break_addr)) { + m_hbr_regs[bp_index].hit_addr = trap_addr; + return Error(); + } } - return false; + bp_index = LLDB_INVALID_INDEX32; + return Error(); } -uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints() { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); +Error NativeRegisterContextLinux_arm::ClearAllHardwareBreakpoints() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); if (log) log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); @@ -488,22 +500,57 @@ uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints() { error = ReadHardwareDebugInfo(); if (error.Fail()) + return error; + + lldb::addr_t tempAddr = 0; + uint32_t tempControl = 0; + + for (uint32_t i = 0; i < m_max_hbp_supported; i++) { + if (m_hbr_regs[i].control & 0x01) { + // Create a backup we can revert to in case of failure. + tempAddr = m_hbr_regs[i].address; + tempControl = m_hbr_regs[i].control; + + // Clear breakpoints in local cache + m_hbr_regs[i].control &= ~1; + m_hbr_regs[i].address = 0; + + // Ptrace call to update hardware debug registers + error = WriteHardwareDebugRegs(eDREGTypeBREAK, i); + + if (error.Fail()) { + m_hbr_regs[i].control = tempControl; + m_hbr_regs[i].address = tempAddr; + + return error; + } + } + } + + return Error(); +} + +uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + + // Read hardware breakpoint and watchpoint information. + Error error = ReadHardwareDebugInfo(); + + if (error.Fail()) return 0; + LLDB_LOG(log, "{0}", m_max_hwp_supported); return m_max_hwp_supported; } uint32_t NativeRegisterContextLinux_arm::SetHardwareWatchpoint( lldb::addr_t addr, size_t size, uint32_t watch_flags) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - - Error error; + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, + watch_flags); // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); + Error error = ReadHardwareDebugInfo(); if (error.Fail()) return LLDB_INVALID_INDEX32; @@ -603,15 +650,11 @@ uint32_t NativeRegisterContextLinux_arm::SetHardwareWatchpoint( bool NativeRegisterContextLinux_arm::ClearHardwareWatchpoint( uint32_t wp_index) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - - Error error; + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); + Error error = ReadHardwareDebugInfo(); if (error.Fail()) return false; @@ -641,15 +684,8 @@ bool NativeRegisterContextLinux_arm::ClearHardwareWatchpoint( } Error NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints() { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - - Error error; - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); + Error error = ReadHardwareDebugInfo(); if (error.Fail()) return error; @@ -683,10 +719,8 @@ Error NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints() { } uint32_t NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) { case 0x01: @@ -702,10 +736,8 @@ uint32_t NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index) { } } bool NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) return true; @@ -715,10 +747,8 @@ bool NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) { Error NativeRegisterContextLinux_arm::GetWatchpointHitIndex( uint32_t &wp_index, lldb::addr_t trap_addr) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); uint32_t watch_size; lldb::addr_t watch_addr; @@ -740,10 +770,8 @@ Error NativeRegisterContextLinux_arm::GetWatchpointHitIndex( lldb::addr_t NativeRegisterContextLinux_arm::GetWatchpointAddress(uint32_t wp_index) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); if (wp_index >= m_max_hwp_supported) return LLDB_INVALID_ADDRESS; @@ -756,10 +784,8 @@ NativeRegisterContextLinux_arm::GetWatchpointAddress(uint32_t wp_index) { lldb::addr_t NativeRegisterContextLinux_arm::GetWatchpointHitAddress(uint32_t wp_index) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); if (wp_index >= m_max_hwp_supported) return LLDB_INVALID_ADDRESS; @@ -817,8 +843,8 @@ Error NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, (PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 2), ctrl_buf, sizeof(unsigned int)); } else { - addr_buf = &m_hwp_regs[hwb_index].address; - ctrl_buf = &m_hwp_regs[hwb_index].control; + addr_buf = &m_hbr_regs[hwb_index].address; + ctrl_buf = &m_hbr_regs[hwb_index].control; error = NativeProcessLinux::PtraceWrapper( PTRACE_SETHBPREGS, m_thread.GetID(), diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h index f979811216dc..824ac88ad9ef 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h @@ -46,10 +46,17 @@ public: // Hardware breakpoints/watchpoint mangement functions //------------------------------------------------------------------ + uint32_t NumSupportedHardwareBreakpoints() override; + uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; bool ClearHardwareBreakpoint(uint32_t hw_idx) override; + Error ClearAllHardwareBreakpoints() override; + + Error GetHardwareBreakHitIndex(uint32_t &bp_index, + lldb::addr_t trap_addr) override; + uint32_t NumSupportedHardwareWatchpoints() override; uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index 786778e25a24..f3715147fa3e 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -16,11 +16,11 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" #include "Plugins/Process/Linux/NativeProcessLinux.h" #include "Plugins/Process/Linux/Procfs.h" @@ -116,7 +116,6 @@ NativeRegisterContextLinux * NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( const ArchSpec &target_arch, NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) { - Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS); switch (target_arch.GetMachine()) { case llvm::Triple::arm: return new NativeRegisterContextLinux_arm(target_arch, native_thread, @@ -125,12 +124,7 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx); default: - if (log) - log->Printf("NativeRegisterContextLinux::%s() have no register context " - "for architecture: %s\n", - __FUNCTION__, - target_arch.GetTriple().getArchName().str().c_str()); - return nullptr; + llvm_unreachable("have no register context for architecture"); } } @@ -152,13 +146,14 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( m_reg_info.gpr_flags = gpr_cpsr_arm64; break; default: - assert(false && "Unhandled target architecture."); + llvm_unreachable("Unhandled target architecture."); break; } ::memset(&m_fpr, 0, sizeof(m_fpr)); ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64)); ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); + ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs)); // 16 is just a maximum value, query hardware for actual watchpoint count m_max_hwp_supported = 16; @@ -366,10 +361,8 @@ bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } -uint32_t -NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr, - size_t size) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); +uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareBreakpoints() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); if (log) log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); @@ -380,6 +373,21 @@ NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr, error = ReadHardwareDebugInfo(); if (error.Fail()) + return 0; + + return m_max_hbp_supported; +} + +uint32_t +NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); + LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size); + + // Read hardware breakpoint and watchpoint information. + Error error = ReadHardwareDebugInfo(); + + if (error.Fail()) return LLDB_INVALID_INDEX32; uint32_t control_value = 0, bp_index = 0; @@ -398,55 +406,44 @@ NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr, control_value |= ((1 << size) - 1) << 5; control_value |= (2 << 1) | 1; - // Iterate over stored hardware breakpoints - // Find a free bp_index or update reference count if duplicate. + // Iterate over stored breakpoints and find a free bp_index bp_index = LLDB_INVALID_INDEX32; for (uint32_t i = 0; i < m_max_hbp_supported; i++) { if ((m_hbr_regs[i].control & 1) == 0) { bp_index = i; // Mark last free slot - } else if (m_hbr_regs[i].address == addr && - m_hbr_regs[i].control == control_value) { - bp_index = i; // Mark duplicate index - break; // Stop searching here + } else if (m_hbr_regs[i].address == addr) { + return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints. } } if (bp_index == LLDB_INVALID_INDEX32) return LLDB_INVALID_INDEX32; - // Add new or update existing breakpoint - if ((m_hbr_regs[bp_index].control & 1) == 0) { - m_hbr_regs[bp_index].address = addr; - m_hbr_regs[bp_index].control = control_value; - m_hbr_regs[bp_index].refcount = 1; + // Update breakpoint in local cache + m_hbr_regs[bp_index].real_addr = addr; + m_hbr_regs[bp_index].address = addr; + m_hbr_regs[bp_index].control = control_value; - // PTRACE call to set corresponding hardware breakpoint register. - error = WriteHardwareDebugRegs(eDREGTypeBREAK); + // PTRACE call to set corresponding hardware breakpoint register. + error = WriteHardwareDebugRegs(eDREGTypeBREAK); - if (error.Fail()) { - m_hbr_regs[bp_index].address = 0; - m_hbr_regs[bp_index].control &= ~1; - m_hbr_regs[bp_index].refcount = 0; + if (error.Fail()) { + m_hbr_regs[bp_index].address = 0; + m_hbr_regs[bp_index].control &= ~1; - return LLDB_INVALID_INDEX32; - } - } else - m_hbr_regs[bp_index].refcount++; + return LLDB_INVALID_INDEX32; + } return bp_index; } bool NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint( uint32_t hw_idx) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - - Error error; + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); + LLDB_LOG(log, "hw_idx: {0}", hw_idx); // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); + Error error = ReadHardwareDebugInfo(); if (error.Fail()) return false; @@ -454,39 +451,50 @@ bool NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint( if (hw_idx >= m_max_hbp_supported) return false; - // Update reference count if multiple references. - if (m_hbr_regs[hw_idx].refcount > 1) { - m_hbr_regs[hw_idx].refcount--; - return true; - } else if (m_hbr_regs[hw_idx].refcount == 1) { - // Create a backup we can revert to in case of failure. - lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; - uint32_t tempControl = m_hbr_regs[hw_idx].control; - uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount; + // Create a backup we can revert to in case of failure. + lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; + uint32_t tempControl = m_hbr_regs[hw_idx].control; - m_hbr_regs[hw_idx].control &= ~1; - m_hbr_regs[hw_idx].address = 0; - m_hbr_regs[hw_idx].refcount = 0; + m_hbr_regs[hw_idx].control &= ~1; + m_hbr_regs[hw_idx].address = 0; - // PTRACE call to clear corresponding hardware breakpoint register. - WriteHardwareDebugRegs(eDREGTypeBREAK); + // PTRACE call to clear corresponding hardware breakpoint register. + error = WriteHardwareDebugRegs(eDREGTypeBREAK); - if (error.Fail()) { - m_hbr_regs[hw_idx].control = tempControl; - m_hbr_regs[hw_idx].address = tempAddr; - m_hbr_regs[hw_idx].refcount = tempRefCount; + if (error.Fail()) { + m_hbr_regs[hw_idx].control = tempControl; + m_hbr_regs[hw_idx].address = tempAddr; - return false; - } + return false; + } - return true; + return true; +} + +Error NativeRegisterContextLinux_arm64::GetHardwareBreakHitIndex( + uint32_t &bp_index, lldb::addr_t trap_addr) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); + + if (log) + log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + + lldb::addr_t break_addr; + + for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) { + break_addr = m_hbr_regs[bp_index].address; + + if ((m_hbr_regs[bp_index].control & 0x1) && (trap_addr == break_addr)) { + m_hbr_regs[bp_index].hit_addr = trap_addr; + return Error(); + } } - return false; + bp_index = LLDB_INVALID_INDEX32; + return Error(); } -uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); +Error NativeRegisterContextLinux_arm64::ClearAllHardwareBreakpoints() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); if (log) log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); @@ -497,22 +505,57 @@ uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() { error = ReadHardwareDebugInfo(); if (error.Fail()) + return error; + + lldb::addr_t tempAddr = 0; + uint32_t tempControl = 0; + + for (uint32_t i = 0; i < m_max_hbp_supported; i++) { + if (m_hbr_regs[i].control & 0x01) { + // Create a backup we can revert to in case of failure. + tempAddr = m_hbr_regs[i].address; + tempControl = m_hbr_regs[i].control; + + // Clear watchpoints in local cache + m_hbr_regs[i].control &= ~1; + m_hbr_regs[i].address = 0; + + // Ptrace call to update hardware debug registers + error = WriteHardwareDebugRegs(eDREGTypeBREAK); + + if (error.Fail()) { + m_hbr_regs[i].control = tempControl; + m_hbr_regs[i].address = tempAddr; + + return error; + } + } + } + + return Error(); +} + +uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + + // Read hardware breakpoint and watchpoint information. + Error error = ReadHardwareDebugInfo(); + + if (error.Fail()) return 0; + LLDB_LOG(log, "{0}", m_max_hwp_supported); return m_max_hwp_supported; } uint32_t NativeRegisterContextLinux_arm64::SetHardwareWatchpoint( lldb::addr_t addr, size_t size, uint32_t watch_flags) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - - Error error; + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, + watch_flags); // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); + Error error = ReadHardwareDebugInfo(); if (error.Fail()) return LLDB_INVALID_INDEX32; @@ -595,15 +638,11 @@ uint32_t NativeRegisterContextLinux_arm64::SetHardwareWatchpoint( bool NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint( uint32_t wp_index) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - - Error error; + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); + Error error = ReadHardwareDebugInfo(); if (error.Fail()) return false; @@ -633,15 +672,8 @@ bool NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint( } Error NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - - Error error; - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); + Error error = ReadHardwareDebugInfo(); if (error.Fail()) return error; @@ -676,10 +708,9 @@ Error NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() { uint32_t NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) { case 0x01: return 1; @@ -694,10 +725,8 @@ NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) { } } bool NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) return true; @@ -707,10 +736,8 @@ bool NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) { Error NativeRegisterContextLinux_arm64::GetWatchpointHitIndex( uint32_t &wp_index, lldb::addr_t trap_addr) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); uint32_t watch_size; lldb::addr_t watch_addr; @@ -732,10 +759,8 @@ Error NativeRegisterContextLinux_arm64::GetWatchpointHitIndex( lldb::addr_t NativeRegisterContextLinux_arm64::GetWatchpointAddress(uint32_t wp_index) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); if (wp_index >= m_max_hwp_supported) return LLDB_INVALID_ADDRESS; @@ -748,10 +773,8 @@ NativeRegisterContextLinux_arm64::GetWatchpointAddress(uint32_t wp_index) { lldb::addr_t NativeRegisterContextLinux_arm64::GetWatchpointHitAddress(uint32_t wp_index) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); + LLDB_LOG(log, "wp_index: {0}", wp_index); if (wp_index >= m_max_hwp_supported) return LLDB_INVALID_ADDRESS; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h index c46c375acfe7..4ffbd97ee33a 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -46,10 +46,17 @@ public: // Hardware breakpoints/watchpoint mangement functions //------------------------------------------------------------------ + uint32_t NumSupportedHardwareBreakpoints() override; + uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; bool ClearHardwareBreakpoint(uint32_t hw_idx) override; + Error ClearAllHardwareBreakpoints() override; + + Error GetHardwareBreakHitIndex(uint32_t &bp_index, + lldb::addr_t trap_addr) override; + uint32_t NumSupportedHardwareWatchpoints() override; uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp index c050a2ec0cc6..7c5c42477170 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -17,16 +17,17 @@ // Other libraries and framework includes #include "Plugins/Process/Linux/NativeProcessLinux.h" #include "Plugins/Process/Linux/Procfs.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "Plugins/Process/Utility/RegisterContextLinux_mips.h" #include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" -#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/EmulateInstruction.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Error.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-private-enumerations.h" #define NT_MIPS_MSA 0x600 @@ -71,157 +72,14 @@ struct pt_watch_regs { #define IRW (I | R | W) +#ifndef PTRACE_GETREGSET +#define PTRACE_GETREGSET 0x4204 +#endif struct pt_watch_regs default_watch_regs; using namespace lldb_private; using namespace lldb_private::process_linux; -// ---------------------------------------------------------------------------- -// Private namespace. -// ---------------------------------------------------------------------------- - -namespace { -// mips general purpose registers. -const uint32_t g_gp_regnums_mips[] = { - gpr_zero_mips, gpr_r1_mips, gpr_r2_mips, gpr_r3_mips, - gpr_r4_mips, gpr_r5_mips, gpr_r6_mips, gpr_r7_mips, - gpr_r8_mips, gpr_r9_mips, gpr_r10_mips, gpr_r11_mips, - gpr_r12_mips, gpr_r13_mips, gpr_r14_mips, gpr_r15_mips, - gpr_r16_mips, gpr_r17_mips, gpr_r18_mips, gpr_r19_mips, - gpr_r20_mips, gpr_r21_mips, gpr_r22_mips, gpr_r23_mips, - gpr_r24_mips, gpr_r25_mips, gpr_r26_mips, gpr_r27_mips, - gpr_gp_mips, gpr_sp_mips, gpr_r30_mips, gpr_ra_mips, - gpr_sr_mips, gpr_mullo_mips, gpr_mulhi_mips, gpr_badvaddr_mips, - gpr_cause_mips, gpr_pc_mips, gpr_config5_mips, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_gp_regnums_mips) / sizeof(g_gp_regnums_mips[0])) - 1 == - k_num_gpr_registers_mips, - "g_gp_regnums_mips has wrong number of register infos"); - -// mips floating point registers. -const uint32_t g_fp_regnums_mips[] = { - fpr_f0_mips, fpr_f1_mips, fpr_f2_mips, fpr_f3_mips, - fpr_f4_mips, fpr_f5_mips, fpr_f6_mips, fpr_f7_mips, - fpr_f8_mips, fpr_f9_mips, fpr_f10_mips, fpr_f11_mips, - fpr_f12_mips, fpr_f13_mips, fpr_f14_mips, fpr_f15_mips, - fpr_f16_mips, fpr_f17_mips, fpr_f18_mips, fpr_f19_mips, - fpr_f20_mips, fpr_f21_mips, fpr_f22_mips, fpr_f23_mips, - fpr_f24_mips, fpr_f25_mips, fpr_f26_mips, fpr_f27_mips, - fpr_f28_mips, fpr_f29_mips, fpr_f30_mips, fpr_f31_mips, - fpr_fcsr_mips, fpr_fir_mips, fpr_config5_mips, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_fp_regnums_mips) / sizeof(g_fp_regnums_mips[0])) - 1 == - k_num_fpr_registers_mips, - "g_fp_regnums_mips has wrong number of register infos"); - -// mips MSA registers. -const uint32_t g_msa_regnums_mips[] = { - msa_w0_mips, msa_w1_mips, msa_w2_mips, msa_w3_mips, - msa_w4_mips, msa_w5_mips, msa_w6_mips, msa_w7_mips, - msa_w8_mips, msa_w9_mips, msa_w10_mips, msa_w11_mips, - msa_w12_mips, msa_w13_mips, msa_w14_mips, msa_w15_mips, - msa_w16_mips, msa_w17_mips, msa_w18_mips, msa_w19_mips, - msa_w20_mips, msa_w21_mips, msa_w22_mips, msa_w23_mips, - msa_w24_mips, msa_w25_mips, msa_w26_mips, msa_w27_mips, - msa_w28_mips, msa_w29_mips, msa_w30_mips, msa_w31_mips, - msa_fcsr_mips, msa_fir_mips, msa_mcsr_mips, msa_mir_mips, - msa_config5_mips, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_msa_regnums_mips) / sizeof(g_msa_regnums_mips[0])) - - 1 == - k_num_msa_registers_mips, - "g_msa_regnums_mips has wrong number of register infos"); - -// mips64 general purpose registers. -const uint32_t g_gp_regnums_mips64[] = { - gpr_zero_mips64, gpr_r1_mips64, gpr_r2_mips64, - gpr_r3_mips64, gpr_r4_mips64, gpr_r5_mips64, - gpr_r6_mips64, gpr_r7_mips64, gpr_r8_mips64, - gpr_r9_mips64, gpr_r10_mips64, gpr_r11_mips64, - gpr_r12_mips64, gpr_r13_mips64, gpr_r14_mips64, - gpr_r15_mips64, gpr_r16_mips64, gpr_r17_mips64, - gpr_r18_mips64, gpr_r19_mips64, gpr_r20_mips64, - gpr_r21_mips64, gpr_r22_mips64, gpr_r23_mips64, - gpr_r24_mips64, gpr_r25_mips64, gpr_r26_mips64, - gpr_r27_mips64, gpr_gp_mips64, gpr_sp_mips64, - gpr_r30_mips64, gpr_ra_mips64, gpr_sr_mips64, - gpr_mullo_mips64, gpr_mulhi_mips64, gpr_badvaddr_mips64, - gpr_cause_mips64, gpr_pc_mips64, gpr_config5_mips64, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_gp_regnums_mips64) / sizeof(g_gp_regnums_mips64[0])) - - 1 == - k_num_gpr_registers_mips64, - "g_gp_regnums_mips64 has wrong number of register infos"); - -// mips64 floating point registers. -const uint32_t g_fp_regnums_mips64[] = { - fpr_f0_mips64, fpr_f1_mips64, fpr_f2_mips64, fpr_f3_mips64, - fpr_f4_mips64, fpr_f5_mips64, fpr_f6_mips64, fpr_f7_mips64, - fpr_f8_mips64, fpr_f9_mips64, fpr_f10_mips64, fpr_f11_mips64, - fpr_f12_mips64, fpr_f13_mips64, fpr_f14_mips64, fpr_f15_mips64, - fpr_f16_mips64, fpr_f17_mips64, fpr_f18_mips64, fpr_f19_mips64, - fpr_f20_mips64, fpr_f21_mips64, fpr_f22_mips64, fpr_f23_mips64, - fpr_f24_mips64, fpr_f25_mips64, fpr_f26_mips64, fpr_f27_mips64, - fpr_f28_mips64, fpr_f29_mips64, fpr_f30_mips64, fpr_f31_mips64, - fpr_fcsr_mips64, fpr_fir_mips64, fpr_config5_mips64, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_fp_regnums_mips64) / sizeof(g_fp_regnums_mips64[0])) - - 1 == - k_num_fpr_registers_mips64, - "g_fp_regnums_mips64 has wrong number of register infos"); - -// mips64 MSA registers. -const uint32_t g_msa_regnums_mips64[] = { - msa_w0_mips64, msa_w1_mips64, msa_w2_mips64, msa_w3_mips64, - msa_w4_mips64, msa_w5_mips64, msa_w6_mips64, msa_w7_mips64, - msa_w8_mips64, msa_w9_mips64, msa_w10_mips64, msa_w11_mips64, - msa_w12_mips64, msa_w13_mips64, msa_w14_mips64, msa_w15_mips64, - msa_w16_mips64, msa_w17_mips64, msa_w18_mips64, msa_w19_mips64, - msa_w20_mips64, msa_w21_mips64, msa_w22_mips64, msa_w23_mips64, - msa_w24_mips64, msa_w25_mips64, msa_w26_mips64, msa_w27_mips64, - msa_w28_mips64, msa_w29_mips64, msa_w30_mips64, msa_w31_mips64, - msa_fcsr_mips64, msa_fir_mips64, msa_mcsr_mips64, msa_mir_mips64, - msa_config5_mips64, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_msa_regnums_mips64) / sizeof(g_msa_regnums_mips64[0])) - - 1 == - k_num_msa_registers_mips64, - "g_msa_regnums_mips64 has wrong number of register infos"); - -// Number of register sets provided by this context. -enum { k_num_register_sets = 3 }; - -// Register sets for mips. -static const RegisterSet g_reg_sets_mips[k_num_register_sets] = { - {"General Purpose Registers", "gpr", k_num_gpr_registers_mips, - g_gp_regnums_mips}, - {"Floating Point Registers", "fpu", k_num_fpr_registers_mips, - g_fp_regnums_mips}, - {"MSA Registers", "msa", k_num_msa_registers_mips, g_msa_regnums_mips}}; - -// Register sets for mips64. -static const RegisterSet g_reg_sets_mips64[k_num_register_sets] = { - {"General Purpose Registers", "gpr", k_num_gpr_registers_mips64, - g_gp_regnums_mips64}, - {"Floating Point Registers", "fpu", k_num_fpr_registers_mips64, - g_fp_regnums_mips64}, - {"MSA Registers", "msa", k_num_msa_registers_mips64, g_msa_regnums_mips64}, -}; - -} // end of anonymous namespace - NativeRegisterContextLinux * NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( const ArchSpec &target_arch, NativeThreadProtocol &native_thread, @@ -240,15 +98,12 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( static RegisterInfoInterface * CreateRegisterInfoInterface(const ArchSpec &target_arch) { - if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) { + if ((target_arch.GetMachine() == llvm::Triple::mips) || + (target_arch.GetMachine() == llvm::Triple::mipsel)) { // 32-bit hosts run with a RegisterContextLinux_mips context. return new RegisterContextLinux_mips( target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable()); } else { - assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && - "Register setting path assumes this is a 64-bit host"); - // mips64 hosts know how to work with 64-bit and 32-bit EXEs using the - // mips64 register context. return new RegisterContextLinux_mips64( target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable()); } @@ -303,7 +158,22 @@ NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64( } uint32_t NativeRegisterContextLinux_mips64::GetRegisterSetCount() const { - return k_num_register_sets; + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::mips64: + case llvm::Triple::mips64el: { + const auto context = static_cast<const RegisterContextLinux_mips64 &> + (GetRegisterInfoInterface()); + return context.GetRegisterSetCount(); + } + case llvm::Triple::mips: + case llvm::Triple::mipsel: { + const auto context = static_cast<const RegisterContextLinux_mips &> + (GetRegisterInfoInterface()); + return context.GetRegisterSetCount(); + } + default: + llvm_unreachable("Unhandled target architecture."); + } } lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation( @@ -311,12 +181,8 @@ lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation( Error error; RegisterValue pc_value; lldb::addr_t pc = fail_value; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_mips64::%s Reading PC from " - "breakpoint location", - __FUNCTION__); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); + LLDB_LOG(log, "Reading PC from breakpoint location"); // PC register is at index 34 of the register array const RegisterInfo *const pc_info_p = GetRegisterInfoAtIndex(gpr_pc_mips64); @@ -333,11 +199,7 @@ lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation( ReadRegister(cause_info_p, cause_value); uint64_t cause = cause_value.GetAsUInt64(); - - if (log) - log->Printf("NativeRegisterContextLinux_mips64::%s PC 0x%" PRIx64 - " Cause 0x%" PRIx64, - __FUNCTION__, pc, cause); + LLDB_LOG(log, "PC {0:x} cause {1:x}", pc, cause); /* * The breakpoint might be in a delay slot. In this case PC points @@ -352,10 +214,7 @@ lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation( pc = pc + branch_delay; pc_value.SetUInt64(pc); WriteRegister(pc_info_p, pc_value); - - if (log) - log->Printf("NativeRegisterContextLinux_mips64::%s New PC 0x%" PRIx64, - __FUNCTION__, pc); + LLDB_LOG(log, "New PC {0:x}", pc); } } @@ -364,22 +223,25 @@ lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation( const RegisterSet * NativeRegisterContextLinux_mips64::GetRegisterSet(uint32_t set_index) const { - if (set_index >= k_num_register_sets) + if (set_index >= GetRegisterSetCount()) return nullptr; switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { case llvm::Triple::mips64: - case llvm::Triple::mips64el: - return &g_reg_sets_mips64[set_index]; + case llvm::Triple::mips64el: { + const auto context = static_cast<const RegisterContextLinux_mips64 &> + (GetRegisterInfoInterface()); + return context.GetRegisterSet(set_index); + } case llvm::Triple::mips: - case llvm::Triple::mipsel: - return &g_reg_sets_mips[set_index]; + case llvm::Triple::mipsel: { + const auto context = static_cast<const RegisterContextLinux_mips &> + (GetRegisterInfoInterface()); + return context.GetRegisterSet(set_index); + } default: - assert(false && "Unhandled target architecture."); - return nullptr; + llvm_unreachable("Unhandled target architecture."); } - - return nullptr; } lldb_private::Error @@ -727,70 +589,64 @@ bool NativeRegisterContextLinux_mips64::IsFPR(uint32_t reg_index) const { } static uint32_t GetWatchHi(struct pt_watch_regs *regs, uint32_t index) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); if (regs->style == pt_watch_style_mips32) return regs->mips32.watchhi[index]; else if (regs->style == pt_watch_style_mips64) return regs->mips64.watchhi[index]; - if (log) - log->Printf("Invalid watch register style"); + LLDB_LOG(log, "Invalid watch register style"); return 0; } static void SetWatchHi(struct pt_watch_regs *regs, uint32_t index, uint16_t value) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); if (regs->style == pt_watch_style_mips32) regs->mips32.watchhi[index] = value; else if (regs->style == pt_watch_style_mips64) regs->mips64.watchhi[index] = value; - if (log) - log->Printf("Invalid watch register style"); + LLDB_LOG(log, "Invalid watch register style"); return; } static lldb::addr_t GetWatchLo(struct pt_watch_regs *regs, uint32_t index) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); if (regs->style == pt_watch_style_mips32) return regs->mips32.watchlo[index]; else if (regs->style == pt_watch_style_mips64) return regs->mips64.watchlo[index]; - if (log) - log->Printf("Invalid watch register style"); + LLDB_LOG(log, "Invalid watch register style"); return LLDB_INVALID_ADDRESS; } static void SetWatchLo(struct pt_watch_regs *regs, uint32_t index, uint64_t value) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); if (regs->style == pt_watch_style_mips32) regs->mips32.watchlo[index] = (uint32_t)value; else if (regs->style == pt_watch_style_mips64) regs->mips64.watchlo[index] = value; - if (log) - log->Printf("Invalid watch register style"); - return; + else + LLDB_LOG(log, "Invalid watch register style"); } static uint32_t GetIRWMask(struct pt_watch_regs *regs, uint32_t index) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); if (regs->style == pt_watch_style_mips32) return regs->mips32.watch_masks[index] & IRW; else if (regs->style == pt_watch_style_mips64) return regs->mips64.watch_masks[index] & IRW; - if (log) - log->Printf("Invalid watch register style"); + LLDB_LOG(log, "Invalid watch register style"); return 0; } static uint32_t GetRegMask(struct pt_watch_regs *regs, uint32_t index) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); if (regs->style == pt_watch_style_mips32) return regs->mips32.watch_masks[index] & ~IRW; else if (regs->style == pt_watch_style_mips64) return regs->mips64.watch_masks[index] & ~IRW; - if (log) - log->Printf("Invalid watch register style"); + LLDB_LOG(log, "Invalid watch register style"); return 0; } @@ -1114,7 +970,7 @@ NativeRegisterContextLinux_mips64::GetWatchpointHitAddress(uint32_t wp_index) { } uint32_t NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints() { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); struct pt_watch_regs regs; static int num_valid = 0; if (!num_valid) { @@ -1128,12 +984,8 @@ uint32_t NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints() { case pt_watch_style_mips64: num_valid = regs.mips64.num_valid; return num_valid; - default: - if (log) - log->Printf("NativeRegisterContextLinux_mips64::%s Error: Unrecognized " - "watch register style", - __FUNCTION__); } + LLDB_LOG(log, "Invalid watch register style"); return 0; } return num_valid; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp index 7ec4dc551fac..3e782d39f72e 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp @@ -11,11 +11,11 @@ #include "NativeRegisterContextLinux_s390x.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp index 2bd819b456ab..dd35705a8ae8 100755 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -11,11 +11,11 @@ #include "NativeRegisterContextLinux_x86_64.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/source/Plugins/Process/Linux/NativeThreadLinux.cpp index d18d3c16d2c9..04b6fe6d71e9 100644 --- a/source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ b/source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -16,11 +16,12 @@ #include "NativeRegisterContextLinux.h" #include "SingleStepCheck.h" -#include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Host/HostNativeThread.h" #include "lldb/Host/linux/Ptrace.h" +#include "lldb/Host/linux/Support.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" #include "lldb/lldb-enumerations.h" #include "llvm/ADT/SmallString.h" @@ -90,15 +91,12 @@ NativeThreadLinux::NativeThreadLinux(NativeProcessLinux *process, m_stop_info(), m_reg_context_sp(), m_stop_description() {} std::string NativeThreadLinux::GetName() { - NativeProcessProtocolSP process_sp = m_process_wp.lock(); - if (!process_sp) - return "<unknown: no process>"; + NativeProcessLinux &process = GetProcess(); - // const NativeProcessLinux *const process = - // reinterpret_cast<NativeProcessLinux*> (process_sp->get ()); - llvm::SmallString<32> thread_name; - HostNativeThread::GetName(GetID(), thread_name); - return thread_name.c_str(); + auto BufferOrError = getProcFile(process.GetID(), GetID(), "comm"); + if (!BufferOrError) + return ""; + return BufferOrError.get()->getBuffer().rtrim('\n'); } lldb::StateType NativeThreadLinux::GetState() { return m_state; } @@ -190,6 +188,38 @@ Error NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) { return Error("Clearing hardware watchpoint failed."); } +Error NativeThreadLinux::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) { + if (m_state == eStateLaunching) + return Error(); + + Error error = RemoveHardwareBreakpoint(addr); + if (error.Fail()) + return error; + + NativeRegisterContextSP reg_ctx = GetRegisterContext(); + uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size); + + if (bp_index == LLDB_INVALID_INDEX32) + return Error("Setting hardware breakpoint failed."); + + m_hw_break_index_map.insert({addr, bp_index}); + return Error(); +} + +Error NativeThreadLinux::RemoveHardwareBreakpoint(lldb::addr_t addr) { + auto bp = m_hw_break_index_map.find(addr); + if (bp == m_hw_break_index_map.end()) + return Error(); + + uint32_t bp_index = bp->second; + if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) { + m_hw_break_index_map.erase(bp); + return Error(); + } + + return Error("Clearing hardware breakpoint failed."); +} + Error NativeThreadLinux::Resume(uint32_t signo) { const StateType new_state = StateType::eStateRunning; MaybeLogStateChange(new_state); @@ -211,6 +241,18 @@ Error NativeThreadLinux::Resume(uint32_t signo) { } } + // Set all active hardware breakpoint on all threads. + if (m_hw_break_index_map.empty()) { + NativeProcessLinux &process = GetProcess(); + + const auto &hw_breakpoint_map = process.GetHardwareBreakpointMap(); + GetRegisterContext()->ClearAllHardwareBreakpoints(); + for (const auto &pair : hw_breakpoint_map) { + const auto &bp = pair.second; + SetHardwareBreakpoint(bp.m_addr, bp.m_size); + } + } + intptr_t data = 0; if (signo != LLDB_INVALID_SIGNAL_NUMBER) @@ -220,63 +262,18 @@ Error NativeThreadLinux::Resume(uint32_t signo) { reinterpret_cast<void *>(data)); } -void NativeThreadLinux::MaybePrepareSingleStepWorkaround() { - if (!SingleStepWorkaroundNeeded()) - return; - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - - if (sched_getaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set, - &m_original_cpu_set) != 0) { - // This should really not fail. But, just in case... - if (log) { - Error error(errno, eErrorTypePOSIX); - log->Printf( - "NativeThreadLinux::%s Unable to get cpu affinity for thread %" PRIx64 - ": %s", - __FUNCTION__, m_tid, error.AsCString()); - } - return; - } - - cpu_set_t set; - CPU_ZERO(&set); - CPU_SET(0, &set); - if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof set, &set) != 0 && - log) { - // This may fail in very locked down systems, if the thread is not allowed - // to run on - // cpu 0. If that happens, only thing we can do is it log it and continue... - Error error(errno, eErrorTypePOSIX); - log->Printf( - "NativeThreadLinux::%s Unable to set cpu affinity for thread %" PRIx64 - ": %s", - __FUNCTION__, m_tid, error.AsCString()); - } -} - -void NativeThreadLinux::MaybeCleanupSingleStepWorkaround() { - if (!SingleStepWorkaroundNeeded()) - return; - - if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set, - &m_original_cpu_set) != 0) { - Error error(errno, eErrorTypePOSIX); - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - log->Printf( - "NativeThreadLinux::%s Unable to reset cpu affinity for thread %" PRIx64 - ": %s", - __FUNCTION__, m_tid, error.AsCString()); - } -} - Error NativeThreadLinux::SingleStep(uint32_t signo) { const StateType new_state = StateType::eStateStepping; MaybeLogStateChange(new_state); m_state = new_state; m_stop_info.reason = StopReason::eStopReasonNone; - MaybePrepareSingleStepWorkaround(); + if(!m_step_workaround) { + // If we already hava a workaround inplace, don't reset it. Otherwise, the + // destructor of the existing instance will run after the new instance has + // fetched the cpu mask, and the thread will end up with the wrong mask. + m_step_workaround = SingleStepWorkaround::Get(m_tid); + } intptr_t data = 0; if (signo != LLDB_INVALID_SIGNAL_NUMBER) @@ -338,7 +335,7 @@ bool NativeThreadLinux::IsStopped(int *signo) { void NativeThreadLinux::SetStopped() { if (m_state == StateType::eStateStepping) - MaybeCleanupSingleStepWorkaround(); + m_step_workaround.reset(); const StateType new_state = StateType::eStateStopped; MaybeLogStateChange(new_state); diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.h b/source/Plugins/Process/Linux/NativeThreadLinux.h index f170bb1e8508..42697497c0af 100644 --- a/source/Plugins/Process/Linux/NativeThreadLinux.h +++ b/source/Plugins/Process/Linux/NativeThreadLinux.h @@ -10,11 +10,10 @@ #ifndef liblldb_NativeThreadLinux_H_ #define liblldb_NativeThreadLinux_H_ +#include "SingleStepCheck.h" #include "lldb/Host/common/NativeThreadProtocol.h" #include "lldb/lldb-private-forward.h" -#include <sched.h> - #include <map> #include <memory> #include <string> @@ -47,6 +46,10 @@ public: Error RemoveWatchpoint(lldb::addr_t addr) override; + Error SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; + + Error RemoveHardwareBreakpoint(lldb::addr_t addr) override; + private: // --------------------------------------------------------------------- // Interface for friend classes @@ -94,10 +97,6 @@ private: void SetStopped(); - inline void MaybePrepareSingleStepWorkaround(); - - inline void MaybeCleanupSingleStepWorkaround(); - // --------------------------------------------------------------------- // Member Variables // --------------------------------------------------------------------- @@ -107,7 +106,8 @@ private: std::string m_stop_description; using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>; WatchpointIndexMap m_watchpoint_index_map; - cpu_set_t m_original_cpu_set; // For single-step workaround. + WatchpointIndexMap m_hw_break_index_map; + std::unique_ptr<SingleStepWorkaround> m_step_workaround; }; typedef std::shared_ptr<NativeThreadLinux> NativeThreadLinuxSP; diff --git a/source/Plugins/Process/Linux/ProcFileReader.cpp b/source/Plugins/Process/Linux/ProcFileReader.cpp deleted file mode 100644 index a1bb7a6e09d5..000000000000 --- a/source/Plugins/Process/Linux/ProcFileReader.cpp +++ /dev/null @@ -1,103 +0,0 @@ -//===-- ProcFileReader.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "Plugins/Process/Linux/ProcFileReader.h" - -// C Headers -#include <fcntl.h> -#include <inttypes.h> -#include <limits.h> -#include <stdio.h> -#include <sys/stat.h> - -// C++ Headers -#include <fstream> - -// LLDB Headers -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" - -using namespace lldb_private; -using namespace lldb_private::process_linux; - -lldb::DataBufferSP ProcFileReader::ReadIntoDataBuffer(lldb::pid_t pid, - const char *name) { - int fd; - char path[PATH_MAX]; - - // Make sure we've got a nil terminated buffer for all the folks calling - // GetBytes() directly off our returned DataBufferSP if we hit an error. - lldb::DataBufferSP buf_sp(new DataBufferHeap(1, 0)); - - // Ideally, we would simply create a FileSpec and call ReadFileContents. - // However, files in procfs have zero size (since they are, in general, - // dynamically generated by the kernel) which is incompatible with the - // current ReadFileContents implementation. Therefore we simply stream the - // data into a DataBuffer ourselves. - if (snprintf(path, PATH_MAX, "/proc/%" PRIu64 "/%s", pid, name) > 0) { - if ((fd = open(path, O_RDONLY, 0)) >= 0) { - size_t bytes_read = 0; - std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0)); - - for (;;) { - size_t avail = buf_ap->GetByteSize() - bytes_read; - ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); - - if (status < 0) - break; - - if (status == 0) { - buf_ap->SetByteSize(bytes_read); - buf_sp.reset(buf_ap.release()); - break; - } - - bytes_read += status; - - if (avail - status == 0) - buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); - } - - close(fd); - } - } - - return buf_sp; -} - -Error ProcFileReader::ProcessLineByLine( - lldb::pid_t pid, const char *name, - std::function<bool(const std::string &line)> line_parser) { - Error error; - - // Try to open the /proc/{pid}/maps entry. - char filename[PATH_MAX]; - snprintf(filename, sizeof(filename), "/proc/%" PRIu64 "/%s", pid, name); - filename[sizeof(filename) - 1] = '\0'; - - std::ifstream proc_file(filename); - if (proc_file.fail()) { - error.SetErrorStringWithFormat("failed to open file '%s'", filename); - return error; - } - - // Read the file line by line, processing until either end of file or when the - // line_parser returns false. - std::string line; - bool should_continue = true; - - while (should_continue && std::getline(proc_file, line)) { - // Pass the line over to the line_parser for processing. If the line_parser - // returns false, we - // stop processing. - should_continue = line_parser(line); - } - - return error; -} diff --git a/source/Plugins/Process/Linux/ProcFileReader.h b/source/Plugins/Process/Linux/ProcFileReader.h deleted file mode 100644 index dcdb3553d8c3..000000000000 --- a/source/Plugins/Process/Linux/ProcFileReader.h +++ /dev/null @@ -1,37 +0,0 @@ -//===-- ProcFileReader.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcFileReader_h_ -#define liblldb_ProcFileReader_h_ - -#include <functional> - -#include "lldb/lldb-forward.h" -#include "lldb/lldb-types.h" - -namespace lldb_private { -namespace process_linux { - -class ProcFileReader { -public: - static lldb::DataBufferSP ReadIntoDataBuffer(lldb::pid_t pid, - const char *name); - - /// Parse the /proc/{@a pid}/{@a name} file line by line, passing each line to - /// line_parser, until - /// either end of file or until line_parser returns false. - static Error - ProcessLineByLine(lldb::pid_t pid, const char *name, - std::function<bool(const std::string &line)> line_parser); -}; - -} // namespace process_linux -} // namespace lldb_private - -#endif // #ifndef liblldb_ProcFileReader_h_ diff --git a/source/Plugins/Process/Linux/SingleStepCheck.cpp b/source/Plugins/Process/Linux/SingleStepCheck.cpp index b23c1bd245d5..4e979bd45532 100644 --- a/source/Plugins/Process/Linux/SingleStepCheck.cpp +++ b/source/Plugins/Process/Linux/SingleStepCheck.cpp @@ -18,10 +18,12 @@ #include "llvm/Support/Compiler.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "lldb/Host/linux/Ptrace.h" +#include "lldb/Utility/Error.h" +using namespace lldb; +using namespace lldb_private; using namespace lldb_private::process_linux; #if defined(__arm64__) || defined(__aarch64__) @@ -32,16 +34,14 @@ void LLVM_ATTRIBUTE_NORETURN Child() { _exit(1); // We just do an endless loop SIGSTOPPING ourselves until killed. The tracer - // will fiddle with our cpu - // affinities and monitor the behaviour. + // will fiddle with our cpu affinities and monitor the behaviour. for (;;) { raise(SIGSTOP); // Generate a bunch of instructions here, so that a single-step does not - // land in the - // raise() accidentally. If single-stepping works, we will be spinning in - // this loop. If - // it doesn't, we'll land in the raise() call above. + // land in the raise() accidentally. If single-stepping works, we will be + // spinning in this loop. If it doesn't, we'll land in the raise() call + // above. for (volatile unsigned i = 0; i < CPU_SETSIZE; ++i) ; } @@ -57,25 +57,16 @@ struct ChildDeleter { } }; -} // end anonymous namespace - -bool impl::SingleStepWorkaroundNeeded() { +bool WorkaroundNeeded() { // We shall spawn a child, and use it to verify the debug capabilities of the - // cpu. We shall - // iterate through the cpus, bind the child to each one in turn, and verify - // that - // single-stepping works on that cpu. A workaround is needed if we find at - // least one broken - // cpu. + // cpu. We shall iterate through the cpus, bind the child to each one in turn, + // and verify that single-stepping works on that cpu. A workaround is needed + // if we find at least one broken cpu. - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - Error error; + Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); ::pid_t child_pid = fork(); if (child_pid == -1) { - if (log) { - error.SetErrorToErrno(); - log->Printf("%s failed to fork(): %s", __FUNCTION__, error.AsCString()); - } + LLDB_LOG(log, "failed to fork(): {0}", Error(errno, eErrorTypePOSIX)); return false; } if (child_pid == 0) @@ -85,22 +76,16 @@ bool impl::SingleStepWorkaroundNeeded() { cpu_set_t available_cpus; if (sched_getaffinity(child_pid, sizeof available_cpus, &available_cpus) == -1) { - if (log) { - error.SetErrorToErrno(); - log->Printf("%s failed to get available cpus: %s", __FUNCTION__, - error.AsCString()); - } + LLDB_LOG(log, "failed to get available cpus: {0}", + Error(errno, eErrorTypePOSIX)); return false; } int status; ::pid_t wpid = waitpid(child_pid, &status, __WALL); if (wpid != child_pid || !WIFSTOPPED(status)) { - if (log) { - error.SetErrorToErrno(); - log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, status, - error.AsCString()); - } + LLDB_LOG(log, "waitpid() failed (status = {0:x}): {1}", status, + Error(errno, eErrorTypePOSIX)); return false; } @@ -113,46 +98,37 @@ bool impl::SingleStepWorkaroundNeeded() { CPU_ZERO(&cpus); CPU_SET(cpu, &cpus); if (sched_setaffinity(child_pid, sizeof cpus, &cpus) == -1) { - if (log) { - error.SetErrorToErrno(); - log->Printf("%s failed to switch to cpu %u: %s", __FUNCTION__, cpu, - error.AsCString()); - } + LLDB_LOG(log, "failed to switch to cpu {0}: {1}", cpu, + Error(errno, eErrorTypePOSIX)); continue; } int status; - error = NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid); + Error error = + NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid); if (error.Fail()) { - if (log) - log->Printf("%s single step failed: %s", __FUNCTION__, - error.AsCString()); + LLDB_LOG(log, "single step failed: {0}", error); break; } wpid = waitpid(child_pid, &status, __WALL); if (wpid != child_pid || !WIFSTOPPED(status)) { - if (log) { - error.SetErrorToErrno(); - log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, - status, error.AsCString()); - } + LLDB_LOG(log, "waitpid() failed (status = {0:x}): {1}", status, + Error(errno, eErrorTypePOSIX)); break; } if (WSTOPSIG(status) != SIGTRAP) { - if (log) - log->Printf("%s single stepping on cpu %d failed with status %x", - __FUNCTION__, cpu, status); + LLDB_LOG(log, "single stepping on cpu {0} failed with status {1:x}", cpu, + status); break; } } // cpu is either the index of the first broken cpu, or CPU_SETSIZE. if (cpu == 0) { - if (log) - log->Printf("%s SINGLE STEPPING ON FIRST CPU IS NOT WORKING. DEBUGGING " - "LIKELY TO BE UNRELIABLE.", - __FUNCTION__); + LLDB_LOG(log, + "SINGLE STEPPING ON FIRST CPU IS NOT WORKING. DEBUGGING " + "LIKELY TO BE UNRELIABLE."); // No point in trying to fiddle with the affinities, just give it our best // shot and see how it goes. return false; @@ -161,6 +137,46 @@ bool impl::SingleStepWorkaroundNeeded() { return cpu != CPU_SETSIZE; } -#else // !arm64 -bool impl::SingleStepWorkaroundNeeded() { return false; } +} // end anonymous namespace + +std::unique_ptr<SingleStepWorkaround> SingleStepWorkaround::Get(::pid_t tid) { + Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); + + static bool workaround_needed = WorkaroundNeeded(); + if (!workaround_needed) { + LLDB_LOG(log, "workaround for thread {0} not needed", tid); + return nullptr; + } + + cpu_set_t original_set; + if (sched_getaffinity(tid, sizeof original_set, &original_set) != 0) { + // This should really not fail. But, just in case... + LLDB_LOG(log, "Unable to get cpu affinity for thread {0}: {1}", tid, + Error(errno, eErrorTypePOSIX)); + return nullptr; + } + + cpu_set_t set; + CPU_ZERO(&set); + CPU_SET(0, &set); + if (sched_setaffinity(tid, sizeof set, &set) != 0) { + // This may fail in very locked down systems, if the thread is not allowed + // to run on cpu 0. If that happens, only thing we can do is it log it and + // continue... + LLDB_LOG(log, "Unable to set cpu affinity for thread {0}: {1}", tid, + Error(errno, eErrorTypePOSIX)); + } + + LLDB_LOG(log, "workaround for thread {0} prepared", tid); + return llvm::make_unique<SingleStepWorkaround>(tid, original_set); +} + +SingleStepWorkaround::~SingleStepWorkaround() { + Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); + LLDB_LOG(log, "Removing workaround"); + if (sched_setaffinity(m_tid, sizeof m_original_set, &m_original_set) != 0) { + LLDB_LOG(log, "Unable to reset cpu affinity for thread {0}: {1}", m_tid, + Error(errno, eErrorTypePOSIX)); + } +} #endif diff --git a/source/Plugins/Process/Linux/SingleStepCheck.h b/source/Plugins/Process/Linux/SingleStepCheck.h index 6e3310da840b..afeda7310349 100644 --- a/source/Plugins/Process/Linux/SingleStepCheck.h +++ b/source/Plugins/Process/Linux/SingleStepCheck.h @@ -10,30 +10,47 @@ #ifndef liblldb_SingleStepCheck_H_ #define liblldb_SingleStepCheck_H_ +#include <memory> +#include <sched.h> +#include <sys/types.h> + namespace lldb_private { namespace process_linux { -namespace impl { -extern bool SingleStepWorkaroundNeeded(); -} - // arm64 linux had a bug which prevented single-stepping and watchpoints from -// working on non-boot -// cpus, due to them being incorrectly initialized after coming out of suspend. -// This issue is -// particularly affecting android M, which uses suspend ("doze mode") quite -// aggressively. This -// code detects that situation and makes single-stepping work by doing all the -// step operations on +// working on non-boot cpus, due to them being incorrectly initialized after +// coming out of suspend. This issue is particularly affecting android M, which +// uses suspend ("doze mode") quite aggressively. This code detects that +// situation and makes single-stepping work by doing all the step operations on // the boot cpu. // // The underlying issue has been fixed in android N and linux 4.4. This code can -// be removed once -// these systems become obsolete. -inline bool SingleStepWorkaroundNeeded() { - static bool value = impl::SingleStepWorkaroundNeeded(); - return value; -} +// be removed once these systems become obsolete. + +#if defined(__arm64__) || defined(__aarch64__) +class SingleStepWorkaround { + ::pid_t m_tid; + cpu_set_t m_original_set; + + SingleStepWorkaround(const SingleStepWorkaround &) = delete; + void operator=(const SingleStepWorkaround &) = delete; + +public: + SingleStepWorkaround(::pid_t tid, cpu_set_t original_set) + : m_tid(tid), m_original_set(original_set) {} + ~SingleStepWorkaround(); + + static std::unique_ptr<SingleStepWorkaround> Get(::pid_t tid); +}; +#else +class SingleStepWorkaround { +public: + static std::unique_ptr<SingleStepWorkaround> Get(::pid_t tid) { + return nullptr; + } +}; +#endif + } // end namespace process_linux } // end namespace lldb_private diff --git a/source/Plugins/Process/MacOSX-Kernel/CMakeLists.txt b/source/Plugins/Process/MacOSX-Kernel/CMakeLists.txt index 681b7405e2b8..bed0e3b7ab37 100644 --- a/source/Plugins/Process/MacOSX-Kernel/CMakeLists.txt +++ b/source/Plugins/Process/MacOSX-Kernel/CMakeLists.txt @@ -1,4 +1,4 @@ -add_lldb_library(lldbPluginProcessMacOSXKernel +add_lldb_library(lldbPluginProcessMacOSXKernel PLUGIN CommunicationKDP.cpp ProcessKDP.cpp ProcessKDPLog.cpp @@ -7,4 +7,16 @@ add_lldb_library(lldbPluginProcessMacOSXKernel RegisterContextKDP_i386.cpp RegisterContextKDP_x86_64.cpp ThreadKDP.cpp + + LINK_LIBS + lldbBreakpoint + lldbCore + lldbHost + lldbInterpreter + lldbSymbol + lldbTarget + lldbUtility + lldbPluginDynamicLoaderDarwinKernel + lldbPluginDynamicLoaderStatic + lldbPluginProcessUtility ) diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp index 43e4617feafc..da0ed9aa0c6a 100644 --- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp +++ b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp @@ -17,14 +17,15 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" +#include "lldb/Core/DumpDataExtractor.h" #include "lldb/Core/State.h" -#include "lldb/Core/UUID.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/UUID.h" // Project includes #include "ProcessKDPLog.h" @@ -200,8 +201,7 @@ size_t CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock( uint8_t buffer[8192]; Error error; - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS | - KDP_LOG_VERBOSE)); + Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); // Check for a packet from our cache first without trying any reading... if (CheckForPacket(NULL, 0, packet)) @@ -216,12 +216,12 @@ size_t CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock( : std::chrono::microseconds(timeout_usec), status, &error); - if (log) - log->Printf("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, " - "status = %s, error = %s) => bytes_read = %" PRIu64, - LLVM_PRETTY_FUNCTION, timeout_usec, + LLDB_LOGV(log, + "Read (buffer, sizeof(buffer), timeout_usec = 0x{0:x}, " + "status = {1}, error = {2}) => bytes_read = {4}", + timeout_usec, Communication::ConnectionStatusAsCString(status), - error.AsCString(), (uint64_t)bytes_read); + error, bytes_read); if (bytes_read > 0) { if (CheckForPacket(buffer, bytes_read, packet)) @@ -260,8 +260,7 @@ bool CommunicationKDP::CheckForPacket(const uint8_t *src, size_t src_len, if (src && src_len > 0) { if (log && log->GetVerbose()) { PacketStreamType log_strm; - DataExtractor::DumpHexBytes(&log_strm, src, src_len, UINT32_MAX, - LLDB_INVALID_ADDRESS); + DumpHexBytes(&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS); log->Printf("CommunicationKDP::%s adding %u bytes: %s", __FUNCTION__, (uint32_t)src_len, log_strm.GetData()); } @@ -860,15 +859,17 @@ void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (error = 0x%8.8x:\n", error); if (count > 0) - packet.Dump(&s, // Stream to dump to - offset, // Offset within "packet" - eFormatBytesWithASCII, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - m_last_read_memory_addr, // Don't show addresses before - // each line - 0, 0); // No bitfields + DumpDataExtractor(packet, + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatBytesWithASCII, // Format to use + 1, // Size of each item + // in bytes + count, // Number of items + 16, // Number per line + m_last_read_memory_addr, // Don't show addresses + // before each line + 0, 0); // No bitfields } break; case KDP_READREGS: { @@ -876,15 +877,19 @@ void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (error = 0x%8.8x regs:\n", error); if (count > 0) - packet.Dump( - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - m_addr_byte_size, // Size of each item in bytes - count / m_addr_byte_size, // Number of items - 16 / m_addr_byte_size, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields + DumpDataExtractor(packet, + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + m_addr_byte_size, // Size of each item + // in bytes + count / m_addr_byte_size, // Number of items + 16 / m_addr_byte_size, // Number per line + LLDB_INVALID_ADDRESS, + // Don't + // show addresses before + // each line + 0, 0); // No bitfields } break; case KDP_KERNELVERSION: { @@ -907,29 +912,32 @@ void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (error = 0x%8.8x io:\n", error); if (count > 0) - packet.Dump( - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields + DumpDataExtractor(packet, + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in bytes + count, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses + // before each line + 0, 0); // No bitfields } break; case KDP_DUMPINFO: { const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (count = %u, bytes = \n", count); if (count > 0) - packet.Dump( - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields + DumpDataExtractor(packet, + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in + // bytes + count, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses + // before each line + 0, 0); // No bitfields } break; @@ -977,8 +985,7 @@ void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { const uint32_t size = packet.GetU32(&offset); s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size); if (size > 0) - DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, - 32, addr); + DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); } break; case KDP_READMEM64: { @@ -1003,8 +1010,7 @@ void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr, size); if (size > 0) - DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, - 32, addr); + DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); } break; case KDP_WRITEPHYSMEM64: { @@ -1014,8 +1020,7 @@ void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n", addr, size, lcpu); if (size > 0) - DataExtractor::DumpHexBytes(&s, packet.GetData(&offset, size), size, - 32, addr); + DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); } break; case KDP_READREGS: { @@ -1030,15 +1035,18 @@ void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { const uint32_t nbytes = packet.GetByteSize() - offset; s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor); if (nbytes > 0) - packet.Dump( - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - m_addr_byte_size, // Size of each item in bytes - nbytes / m_addr_byte_size, // Number of items - 16 / m_addr_byte_size, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields + DumpDataExtractor(packet, + &s, // Stream to dump to + offset, // Offset within + // "packet" + eFormatHex, // Format to use + m_addr_byte_size, // Size of each item in + // bytes + nbytes / m_addr_byte_size, // Number of items + 16 / m_addr_byte_size, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses + // before each line + 0, 0); // No bitfields } break; case KDP_BREAKPOINT_SET: @@ -1133,15 +1141,17 @@ void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu, address, nbytes); if (nbytes > 0) - packet.Dump( - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - nbytes, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields + DumpDataExtractor(packet, + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in + // bytes + nbytes, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses + // before each line + 0, 0); // No bitfields } break; case KDP_READIOPORT: { @@ -1159,22 +1169,24 @@ void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu, address, nbytes); if (nbytes > 0) - packet.Dump( - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - nbytes, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields + DumpDataExtractor(packet, + &s, // Stream to dump to + offset, // Offset within "packet" + eFormatHex, // Format to use + 1, // Size of each item in + // bytes + nbytes, // Number of items + 16, // Number per line + LLDB_INVALID_ADDRESS, // Don't show addresses + // before each line + 0, 0); // No bitfields } break; case KDP_DUMPINFO: { const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (count = %u, bytes = \n", count); if (count > 0) - packet.Dump( + DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use @@ -1195,14 +1207,17 @@ void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { if (error_desc) { s.PutCString(error_desc); - packet.Dump(&s, // Stream to dump to - 0, // Offset into "packet" - eFormatBytes, // Dump as hex bytes - 1, // Size of each item is 1 for single bytes - packet.GetByteSize(), // Number of bytes - UINT32_MAX, // Num bytes per line - LLDB_INVALID_ADDRESS, // Base address - 0, 0); // Bitfield info set to not do anything bitfield related + DumpDataExtractor(packet, + &s, // Stream to dump to + 0, // Offset into "packet" + eFormatBytes, // Dump as hex bytes + 1, // Size of each item is 1 for + // single bytes + packet.GetByteSize(), // Number of bytes + UINT32_MAX, // Num bytes per line + LLDB_INVALID_ADDRESS, // Base address + 0, 0); // Bitfield info set to not do + // anything bitfield related } } diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index a757bba70d16..6b2e675afaea 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -20,7 +20,7 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" -#include "lldb/Core/UUID.h" +#include "lldb/Utility/UUID.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Host.h" #include "lldb/Host/Symbols.h" @@ -39,6 +39,8 @@ #include "lldb/Target/Thread.h" #include "lldb/Utility/StringExtractor.h" +#include "llvm/Support/Threading.h" + #define USEC_PER_SEC 1000000 // Project includes @@ -516,8 +518,7 @@ bool ProcessKDP::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { // locker will keep a mutex locked until it goes out of scope Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD)); - if (log && log->GetMask().Test(KDP_LOG_VERBOSE)) - log->Printf("ProcessKDP::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID()); + LLDB_LOGV(log, "pid = {0}", GetID()); // Even though there is a CPU mask, it doesn't mean we can see each CPU // individually, there is really only one. Lets call this thread 1. @@ -718,18 +719,14 @@ Error ProcessKDP::DoSignal(int signo) { } void ProcessKDP::Initialize() { - static std::once_flag g_once_flag; + static llvm::once_flag g_once_flag; - std::call_once(g_once_flag, []() { + llvm::call_once(g_once_flag, []() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, DebuggerInitialize); - Log::Callbacks log_callbacks = {ProcessKDPLog::DisableLog, - ProcessKDPLog::EnableLog, - ProcessKDPLog::ListLogCategories}; - - Log::RegisterLogChannel(ProcessKDP::GetPluginNameStatic(), log_callbacks); + ProcessKDPLog::Initialize(); }); } diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h index fa5d2bd27feb..8f1033b9fd36 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h @@ -19,14 +19,14 @@ // Other libraries and framework includes #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Broadcaster.h" -#include "lldb/Core/ConstString.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Core/StringList.h" #include "lldb/Core/ThreadSafeValue.h" #include "lldb/Host/HostThread.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/StringList.h" #include "CommunicationKDP.h" diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp index 479f09aa8981..ffab3e5e23c7 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp +++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp @@ -9,184 +9,27 @@ #include "ProcessKDPLog.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Interpreter/Args.h" - -#include "ProcessKDP.h" - -using namespace lldb; using namespace lldb_private; -// We want to avoid global constructors where code needs to be run so here we -// control access to our static g_log_sp by hiding it in a singleton function -// 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; -} - -Log *ProcessKDPLog::GetLogIfAllCategoriesSet(uint32_t mask) { - Log *log(GetLog()); - if (log && mask) { - uint32_t log_mask = log->GetMask().Get(); - if ((log_mask & mask) != mask) - return NULL; - } - return log; -} - -void ProcessKDPLog::DisableLog(const char **categories, Stream *feedback_strm) { - Log *log(GetLog()); - if (log) { - uint32_t flag_bits = 0; - - if (categories[0] != NULL) { - flag_bits = log->GetMask().Get(); - for (size_t i = 0; categories[i] != NULL; ++i) { - const char *arg = categories[i]; - - if (::strcasecmp(arg, "all") == 0) - flag_bits &= ~KDP_LOG_ALL; - else if (::strcasecmp(arg, "async") == 0) - flag_bits &= ~KDP_LOG_ASYNC; - else if (::strncasecmp(arg, "break", 5) == 0) - flag_bits &= ~KDP_LOG_BREAKPOINTS; - else if (::strncasecmp(arg, "comm", 4) == 0) - flag_bits &= ~KDP_LOG_COMM; - else if (::strcasecmp(arg, "default") == 0) - flag_bits &= ~KDP_LOG_DEFAULT; - else if (::strcasecmp(arg, "packets") == 0) - flag_bits &= ~KDP_LOG_PACKETS; - else if (::strcasecmp(arg, "memory") == 0) - flag_bits &= ~KDP_LOG_MEMORY; - else if (::strcasecmp(arg, "data-short") == 0) - flag_bits &= ~KDP_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp(arg, "data-long") == 0) - flag_bits &= ~KDP_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp(arg, "process") == 0) - flag_bits &= ~KDP_LOG_PROCESS; - else if (::strcasecmp(arg, "step") == 0) - flag_bits &= ~KDP_LOG_STEP; - else if (::strcasecmp(arg, "thread") == 0) - flag_bits &= ~KDP_LOG_THREAD; - else if (::strcasecmp(arg, "verbose") == 0) - flag_bits &= ~KDP_LOG_VERBOSE; - else if (::strncasecmp(arg, "watch", 5) == 0) - flag_bits &= ~KDP_LOG_WATCHPOINTS; - else { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories(feedback_strm); - } - } - } - - log->GetMask().Reset(flag_bits); - if (flag_bits == 0) - g_log_enabled = false; - } - - return; -} - -Log *ProcessKDPLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, - const char **categories, Stream *feedback_strm) { - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the - // same. - uint32_t flag_bits = 0; - if (g_log) - flag_bits = g_log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) { - if (g_log) - g_log->SetStream(log_stream_sp); - else - g_log = new Log(log_stream_sp); - } - - if (g_log) { - bool got_unknown_category = false; - for (size_t i = 0; categories[i] != NULL; ++i) { - const char *arg = categories[i]; - - if (::strcasecmp(arg, "all") == 0) - flag_bits |= KDP_LOG_ALL; - else if (::strcasecmp(arg, "async") == 0) - flag_bits |= KDP_LOG_ASYNC; - else if (::strncasecmp(arg, "break", 5) == 0) - flag_bits |= KDP_LOG_BREAKPOINTS; - else if (::strncasecmp(arg, "comm", 4) == 0) - flag_bits |= KDP_LOG_COMM; - else if (::strcasecmp(arg, "default") == 0) - flag_bits |= KDP_LOG_DEFAULT; - else if (::strcasecmp(arg, "packets") == 0) - flag_bits |= KDP_LOG_PACKETS; - else if (::strcasecmp(arg, "memory") == 0) - flag_bits |= KDP_LOG_MEMORY; - else if (::strcasecmp(arg, "data-short") == 0) - flag_bits |= KDP_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp(arg, "data-long") == 0) - flag_bits |= KDP_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp(arg, "process") == 0) - flag_bits |= KDP_LOG_PROCESS; - else if (::strcasecmp(arg, "step") == 0) - flag_bits |= KDP_LOG_STEP; - else if (::strcasecmp(arg, "thread") == 0) - flag_bits |= KDP_LOG_THREAD; - else if (::strcasecmp(arg, "verbose") == 0) - flag_bits |= KDP_LOG_VERBOSE; - else if (::strncasecmp(arg, "watch", 5) == 0) - flag_bits |= KDP_LOG_WATCHPOINTS; - else { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) { - got_unknown_category = true; - ListLogCategories(feedback_strm); - } - } - } - if (flag_bits == 0) - flag_bits = KDP_LOG_DEFAULT; - g_log->GetMask().Reset(flag_bits); - g_log->GetOptions().Reset(log_options); - } - g_log_enabled = true; - return g_log; -} +static constexpr Log::Category g_categories[] = { + {{"async"}, {"log asynchronous activity"}, KDP_LOG_ASYNC}, + {{"break"}, {"log breakpoints"}, KDP_LOG_BREAKPOINTS}, + {{"comm"}, {"log communication activity"}, KDP_LOG_COMM}, + {{"data-long"}, + {"log memory bytes for memory reads and writes for all transactions"}, + KDP_LOG_MEMORY_DATA_LONG}, + {{"data-short"}, + {"log memory bytes for memory reads and writes for short transactions " + "only"}, + KDP_LOG_MEMORY_DATA_SHORT}, + {{"memory"}, {"log memory reads and writes"}, KDP_LOG_MEMORY}, + {{"packets"}, {"log gdb remote packets"}, KDP_LOG_PACKETS}, + {{"process"}, {"log process events and activities"}, KDP_LOG_PROCESS}, + {{"step"}, {"log step related activities"}, KDP_LOG_STEP}, + {{"thread"}, {"log thread events and activities"}, KDP_LOG_THREAD}, + {{"watch"}, {"log watchpoint related activities"}, KDP_LOG_WATCHPOINTS}, +}; -void ProcessKDPLog::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" - " communication - log communication activity\n" - " default - enable the default set of logging categories for liblldb\n" - " packets - log gdb remote packets\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" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n" - " watch - log watchpoint related activities\n", - ProcessKDP::GetPluginNameStatic().GetCString()); -} +Log::Channel ProcessKDPLog::g_channel(g_categories, KDP_LOG_DEFAULT); -void ProcessKDPLog::LogIf(uint32_t mask, const char *format, ...) { - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(mask)); - if (log) { - va_list args; - va_start(args, format); - log->VAPrintf(format, args); - va_end(args); - } -} +void ProcessKDPLog::Initialize() { Log::Register("kdp-remote", g_channel); } diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h b/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h index 703c775268d2..908754ec992b 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h +++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h @@ -10,14 +10,8 @@ #ifndef liblldb_ProcessKDPLog_h_ #define liblldb_ProcessKDPLog_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes +#include "lldb/Utility/Log.h" -// Project includes -#include "lldb/Core/Log.h" - -#define KDP_LOG_VERBOSE (1u << 0) #define KDP_LOG_PROCESS (1u << 1) #define KDP_LOG_THREAD (1u << 2) #define KDP_LOG_PACKETS (1u << 3) @@ -33,21 +27,17 @@ #define KDP_LOG_ALL (UINT32_MAX) #define KDP_LOG_DEFAULT KDP_LOG_PACKETS +namespace lldb_private { class ProcessKDPLog { -public: - static lldb_private::Log *GetLogIfAllCategoriesSet(uint32_t mask = 0); - - static void DisableLog(const char **categories, - lldb_private::Stream *feedback_strm); + static Log::Channel g_channel; - static lldb_private::Log *EnableLog(lldb::StreamSP &log_stream_sp, - uint32_t log_options, - const char **categories, - lldb_private::Stream *feedback_strm); - - static void ListLogCategories(lldb_private::Stream *strm); +public: + static void Initialize(); - static void LogIf(uint32_t mask, const char *format, ...); + static Log *GetLogIfAllCategoriesSet(uint32_t mask) { + return g_channel.GetLogIfAll(mask); + } }; +} #endif // liblldb_ProcessKDPLog_h_ diff --git a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp index 9f594f35d70d..ae2f11f38006 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp +++ b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp @@ -13,14 +13,14 @@ #include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/State.h" -#include "lldb/Core/StreamString.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Unwind.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/StreamString.h" #include "Plugins/Process/Utility/StopInfoMachException.h" #include "ProcessKDP.h" @@ -40,15 +40,13 @@ using namespace lldb_private; ThreadKDP::ThreadKDP(Process &process, lldb::tid_t tid) : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(), m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS) { - ProcessKDPLog::LogIf(KDP_LOG_THREAD, - "%p: ThreadKDP::ThreadKDP (tid = 0x%4.4x)", this, - GetID()); + Log *log = ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD); + LLDB_LOG(log, "this = {0}, tid = {1:x}", this, GetID()); } ThreadKDP::~ThreadKDP() { - ProcessKDPLog::LogIf(KDP_LOG_THREAD, - "%p: ThreadKDP::~ThreadKDP (tid = 0x%4.4x)", this, - GetID()); + Log *log = ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD); + LLDB_LOG(log, "this = {0}, tid = {1:x}", this, GetID()); DestroyThread(); } diff --git a/source/Plugins/Process/NetBSD/CMakeLists.txt b/source/Plugins/Process/NetBSD/CMakeLists.txt new file mode 100644 index 000000000000..5b2cef8b847b --- /dev/null +++ b/source/Plugins/Process/NetBSD/CMakeLists.txt @@ -0,0 +1,21 @@ +include_directories(.) +include_directories(../POSIX) +include_directories(../Utility) + +add_lldb_library(lldbPluginProcessNetBSD PLUGIN + NativeProcessNetBSD.cpp + NativeRegisterContextNetBSD.cpp + NativeRegisterContextNetBSD_x86_64.cpp + NativeThreadNetBSD.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + lldbTarget + lldbUtility + lldbPluginProcessPOSIX + lldbPluginProcessUtility + LINK_COMPONENTS + Support + ) diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp new file mode 100644 index 000000000000..298faa48e1c3 --- /dev/null +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -0,0 +1,1018 @@ +//===-- NativeProcessNetBSD.cpp ------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "NativeProcessNetBSD.h" + +// C Includes + +// C++ Includes + +// Other libraries and framework includes +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "lldb/Core/State.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/common/NativeBreakpoint.h" +#include "lldb/Host/common/NativeRegisterContext.h" +#include "lldb/Host/posix/ProcessLauncherPosixFork.h" +#include "lldb/Target/Process.h" + +// System includes - They have to be included after framework includes because +// they define some +// macros which collide with variable names in other modules +// clang-format off +#include <sys/types.h> +#include <sys/ptrace.h> +#include <sys/sysctl.h> +#include <sys/wait.h> +#include <uvm/uvm_prot.h> +#include <elf.h> +#include <util.h> +// clang-format on + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_netbsd; +using namespace llvm; + +static ExitType convert_pid_status_to_exit_type(int status) { + if (WIFEXITED(status)) + return ExitType::eExitTypeExit; + else if (WIFSIGNALED(status)) + return ExitType::eExitTypeSignal; + else if (WIFSTOPPED(status)) + return ExitType::eExitTypeStop; + else { + // We don't know what this is. + return ExitType::eExitTypeInvalid; + } +} + +static int convert_pid_status_to_return_code(int status) { + if (WIFEXITED(status)) + return WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + return WTERMSIG(status); + else if (WIFSTOPPED(status)) + return WSTOPSIG(status); + else { + // We don't know what this is. + return ExitType::eExitTypeInvalid; + } +} + +// Simple helper function to ensure flags are enabled on the given file +// descriptor. +static Error EnsureFDFlags(int fd, int flags) { + Error error; + + int status = fcntl(fd, F_GETFL); + if (status == -1) { + error.SetErrorToErrno(); + return error; + } + + if (fcntl(fd, F_SETFL, status | flags) == -1) { + error.SetErrorToErrno(); + return error; + } + + return error; +} + +// ----------------------------------------------------------------------------- +// Public Static Methods +// ----------------------------------------------------------------------------- + +Error NativeProcessProtocol::Launch( + ProcessLaunchInfo &launch_info, + NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, + NativeProcessProtocolSP &native_process_sp) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + Error error; + + // Verify the working directory is valid if one was specified. + FileSpec working_dir{launch_info.GetWorkingDirectory()}; + if (working_dir && (!working_dir.ResolvePath() || + !llvm::sys::fs::is_directory(working_dir.GetPath()))) { + error.SetErrorStringWithFormat("No such file or directory: %s", + working_dir.GetCString()); + return error; + } + + // Create the NativeProcessNetBSD in launch mode. + native_process_sp.reset(new NativeProcessNetBSD()); + + if (!native_process_sp->RegisterNativeDelegate(native_delegate)) { + native_process_sp.reset(); + error.SetErrorStringWithFormat("failed to register the native delegate"); + return error; + } + + error = std::static_pointer_cast<NativeProcessNetBSD>(native_process_sp) + ->LaunchInferior(mainloop, launch_info); + + if (error.Fail()) { + native_process_sp.reset(); + LLDB_LOG(log, "failed to launch process: {0}", error); + return error; + } + + launch_info.SetProcessID(native_process_sp->GetID()); + + return error; +} + +Error NativeProcessProtocol::Attach( + lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, + MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid = {0:x}", pid); + + // Retrieve the architecture for the running process. + ArchSpec process_arch; + Error error = ResolveProcessArchitecture(pid, process_arch); + if (!error.Success()) + return error; + + std::shared_ptr<NativeProcessNetBSD> native_process_netbsd_sp( + new NativeProcessNetBSD()); + + if (!native_process_netbsd_sp->RegisterNativeDelegate(native_delegate)) { + error.SetErrorStringWithFormat("failed to register the native delegate"); + return error; + } + + native_process_netbsd_sp->AttachToInferior(mainloop, pid, error); + if (!error.Success()) + return error; + + native_process_sp = native_process_netbsd_sp; + return error; +} + +// ----------------------------------------------------------------------------- +// Public Instance Methods +// ----------------------------------------------------------------------------- + +NativeProcessNetBSD::NativeProcessNetBSD() + : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(), + m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache() {} + +// Handles all waitpid events from the inferior process. +void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + switch (signal) { + case SIGTRAP: + return MonitorSIGTRAP(pid); + case SIGSTOP: + return MonitorSIGSTOP(pid); + default: + return MonitorSignal(pid, signal); + } +} + +void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, int signal, + int status) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + LLDB_LOG(log, "got exit signal({0}) , pid = {1}", signal, pid); + + /* Stop Tracking All Threads attached to Process */ + m_threads.clear(); + + 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); +} + +void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + ptrace_siginfo_t info; + + const auto siginfo_err = + PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); + + // Get details on the signal raised. + if (siginfo_err.Success()) { + // Handle SIGSTOP from LLGS (LLDB GDB Server) + if (info.psi_siginfo.si_code == SI_USER && + info.psi_siginfo.si_pid == ::getpid()) { + /* Stop Tracking All Threads attached to Process */ + for (const auto &thread_sp : m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( + SIGSTOP, &info.psi_siginfo); + } + } + } +} + +void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + ptrace_siginfo_t info; + + const auto siginfo_err = + PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); + + // Get details on the signal raised. + if (siginfo_err.Success()) { + switch (info.psi_siginfo.si_code) { + case TRAP_BRKPT: + for (const auto &thread_sp : m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp) + ->SetStoppedByBreakpoint(); + FixupBreakpointPCAsNeeded( + *static_pointer_cast<NativeThreadNetBSD>(thread_sp)); + } + SetState(StateType::eStateStopped, true); + break; + case TRAP_TRACE: + for (const auto &thread_sp : m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace(); + } + SetState(StateType::eStateStopped, true); + break; + case TRAP_EXEC: { + Error error = ReinitializeThreads(); + if (error.Fail()) { + SetState(StateType::eStateInvalid); + return; + } + + // Let our delegate know we have just exec'd. + NotifyDidExec(); + + SetState(StateType::eStateStopped, true); + } break; + } + } +} + +void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + ptrace_siginfo_t info; + const auto siginfo_err = + PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); + + for (const auto &thread_sp : m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( + info.psi_siginfo.si_signo, &info.psi_siginfo); + } + SetState(StateType::eStateStopped, true); +} + +Error NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr, + int data, int *result) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + Error error; + int ret; + + errno = 0; + ret = ptrace(req, static_cast<::pid_t>(pid), addr, data); + + if (ret == -1) + error.SetErrorToErrno(); + + if (result) + *result = ret; + + LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret); + + if (error.Fail()) + LLDB_LOG(log, "ptrace() failed: {0}", error); + + return error; +} + +Error NativeProcessNetBSD::GetSoftwareBreakpointPCOffset( + uint32_t &actual_opcode_size) { + // FIXME put this behind a breakpoint protocol class that can be + // set per architecture. Need ARM, MIPS support here. + static const uint8_t g_i386_opcode[] = {0xCC}; + switch (m_arch.GetMachine()) { + case llvm::Triple::x86_64: + actual_opcode_size = static_cast<uint32_t>(sizeof(g_i386_opcode)); + return Error(); + default: + assert(false && "CPU type not supported!"); + return Error("CPU type not supported"); + } +} + +Error NativeProcessNetBSD::FixupBreakpointPCAsNeeded( + NativeThreadNetBSD &thread) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); + Error error; + // Find out the size of a breakpoint (might depend on where we are in the + // code). + NativeRegisterContextSP context_sp = thread.GetRegisterContext(); + if (!context_sp) { + error.SetErrorString("cannot get a NativeRegisterContext for the thread"); + LLDB_LOG(log, "failed: {0}", error); + return error; + } + uint32_t breakpoint_size = 0; + error = GetSoftwareBreakpointPCOffset(breakpoint_size); + if (error.Fail()) { + LLDB_LOG(log, "GetBreakpointSize() failed: {0}", error); + return error; + } else + LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size); + // First try probing for a breakpoint at a software breakpoint location: PC - + // breakpoint size. + const lldb::addr_t initial_pc_addr = + context_sp->GetPCfromBreakpointLocation(); + lldb::addr_t breakpoint_addr = initial_pc_addr; + if (breakpoint_size > 0) { + // Do not allow breakpoint probe to wrap around. + if (breakpoint_addr >= breakpoint_size) + breakpoint_addr -= breakpoint_size; + } + // Check if we stopped because of a breakpoint. + NativeBreakpointSP breakpoint_sp; + error = m_breakpoint_list.GetBreakpoint(breakpoint_addr, breakpoint_sp); + if (!error.Success() || !breakpoint_sp) { + // We didn't find one at a software probe location. Nothing to do. + LLDB_LOG(log, + "pid {0} no lldb breakpoint found at current pc with " + "adjustment: {1}", + GetID(), breakpoint_addr); + return Error(); + } + // If the breakpoint is not a software breakpoint, nothing to do. + if (!breakpoint_sp->IsSoftwareBreakpoint()) { + LLDB_LOG( + log, + "pid {0} breakpoint found at {1:x}, not software, nothing to adjust", + GetID(), breakpoint_addr); + return Error(); + } + // + // We have a software breakpoint and need to adjust the PC. + // + // Sanity check. + if (breakpoint_size == 0) { + // Nothing to do! How did we get here? + LLDB_LOG(log, + "pid {0} breakpoint found at {1:x}, it is software, but the " + "size is zero, nothing to do (unexpected)", + GetID(), breakpoint_addr); + return Error(); + } + // + // We have a software breakpoint and need to adjust the PC. + // + // Sanity check. + if (breakpoint_size == 0) { + // Nothing to do! How did we get here? + LLDB_LOG(log, + "pid {0} breakpoint found at {1:x}, it is software, but the " + "size is zero, nothing to do (unexpected)", + GetID(), breakpoint_addr); + return Error(); + } + // Change the program counter. + LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(), + thread.GetID(), initial_pc_addr, breakpoint_addr); + error = context_sp->SetPC(breakpoint_addr); + if (error.Fail()) { + LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(), + thread.GetID(), error); + return error; + } + return error; +} + +Error NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid {0}", GetID()); + + const auto &thread_sp = m_threads[0]; + const ResumeAction *const action = + resume_actions.GetActionForThread(thread_sp->GetID(), true); + + if (action == nullptr) { + LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), + thread_sp->GetID()); + return Error(); + } + + Error error; + + switch (action->state) { + case eStateRunning: { + // Run the thread, possibly feeding it the signal. + error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1, + action->signal); + if (!error.Success()) + return error; + for (const auto &thread_sp : m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetRunning(); + } + SetState(eStateRunning, true); + break; + } + case eStateStepping: + // Run the thread, possibly feeding it the signal. + error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1, + action->signal); + if (!error.Success()) + return error; + for (const auto &thread_sp : m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStepping(); + } + SetState(eStateStepping, true); + break; + + case eStateSuspended: + case eStateStopped: + llvm_unreachable("Unexpected state"); + + default: + return Error("NativeProcessLinux::%s (): unexpected state %s specified " + "for pid %" PRIu64 ", tid %" PRIu64, + __FUNCTION__, StateAsCString(action->state), GetID(), + thread_sp->GetID()); + } + + return Error(); +} + +Error NativeProcessNetBSD::Halt() { + Error error; + + if (kill(GetID(), SIGSTOP) != 0) + error.SetErrorToErrno(); + + return error; +} + +Error NativeProcessNetBSD::Detach() { + Error error; + + // Stop monitoring the inferior. + m_sigchld_handle.reset(); + + // Tell ptrace to detach from the process. + if (GetID() == LLDB_INVALID_PROCESS_ID) + return error; + + return PtraceWrapper(PT_DETACH, GetID()); +} + +Error NativeProcessNetBSD::Signal(int signo) { + Error error; + + if (kill(GetID(), signo)) + error.SetErrorToErrno(); + + return error; +} + +Error NativeProcessNetBSD::Kill() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid {0}", GetID()); + + Error error; + + switch (m_state) { + case StateType::eStateInvalid: + case StateType::eStateExited: + case StateType::eStateCrashed: + case StateType::eStateDetached: + case StateType::eStateUnloaded: + // Nothing to do - the process is already dead. + LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(), + StateAsCString(m_state)); + return error; + + case StateType::eStateConnected: + case StateType::eStateAttaching: + case StateType::eStateLaunching: + case StateType::eStateStopped: + case StateType::eStateRunning: + case StateType::eStateStepping: + case StateType::eStateSuspended: + // We can try to kill a process in these states. + break; + } + + if (kill(GetID(), SIGKILL) != 0) { + error.SetErrorToErrno(); + return error; + } + + return error; +} + +Error NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) { + + if (m_supports_mem_region == LazyBool::eLazyBoolNo) { + // We're done. + return Error("unsupported"); + } + + Error error = PopulateMemoryRegionCache(); + if (error.Fail()) { + return error; + } + + lldb::addr_t prev_base_address = 0; + // FIXME start by finding the last region that is <= target address using + // binary search. Data is sorted. + // There can be a ton of regions on pthreads apps with lots of threads. + for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end(); + ++it) { + MemoryRegionInfo &proc_entry_info = it->first; + // Sanity check assumption that memory map entries are ascending. + assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) && + "descending memory map entries detected, unexpected"); + prev_base_address = proc_entry_info.GetRange().GetRangeBase(); + UNUSED_IF_ASSERT_DISABLED(prev_base_address); + // If the target address comes before this entry, indicate distance to next + // region. + if (load_addr < proc_entry_info.GetRange().GetRangeBase()) { + range_info.GetRange().SetRangeBase(load_addr); + range_info.GetRange().SetByteSize( + proc_entry_info.GetRange().GetRangeBase() - load_addr); + range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); + return error; + } else if (proc_entry_info.GetRange().Contains(load_addr)) { + // The target address is within the memory region we're processing here. + range_info = proc_entry_info; + return error; + } + // The target memory address comes somewhere after the region we just + // parsed. + } + // If we made it here, we didn't find an entry that contained the given + // address. Return the + // load_addr as start and the amount of bytes betwwen load address and the end + // of the memory as + // size. + range_info.GetRange().SetRangeBase(load_addr); + range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); + return error; +} + +Error NativeProcessNetBSD::PopulateMemoryRegionCache() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + // If our cache is empty, pull the latest. There should always be at least + // one memory region if memory region handling is supported. + if (!m_mem_region_cache.empty()) { + LLDB_LOG(log, "reusing {0} cached memory region entries", + m_mem_region_cache.size()); + return Error(); + } + + struct kinfo_vmentry *vm; + size_t count, i; + vm = kinfo_getvmmap(GetID(), &count); + if (vm == NULL) { + m_supports_mem_region = LazyBool::eLazyBoolNo; + Error error; + error.SetErrorString("not supported"); + return error; + } + for (i = 0; i < count; i++) { + MemoryRegionInfo info; + info.Clear(); + info.GetRange().SetRangeBase(vm[i].kve_start); + info.GetRange().SetRangeEnd(vm[i].kve_end); + info.SetMapped(MemoryRegionInfo::OptionalBool::eYes); + + if (vm[i].kve_protection & VM_PROT_READ) + info.SetReadable(MemoryRegionInfo::OptionalBool::eYes); + else + info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); + + if (vm[i].kve_protection & VM_PROT_WRITE) + info.SetWritable(MemoryRegionInfo::OptionalBool::eYes); + else + info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); + + if (vm[i].kve_protection & VM_PROT_EXECUTE) + info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes); + else + info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); + + if (vm[i].kve_path[0]) + info.SetName(vm[i].kve_path); + + m_mem_region_cache.emplace_back( + info, FileSpec(info.GetName().GetCString(), true)); + } + free(vm); + + if (m_mem_region_cache.empty()) { + // No entries after attempting to read them. This shouldn't happen. + // Assume we don't support map entries. + LLDB_LOG(log, "failed to find any vmmap entries, assuming no support " + "for memory region metadata retrieval"); + m_supports_mem_region = LazyBool::eLazyBoolNo; + Error error; + error.SetErrorString("not supported"); + return error; + } + LLDB_LOG(log, "read {0} memory region entries from process {1}", + m_mem_region_cache.size(), GetID()); + // We support memory retrieval, remember that. + m_supports_mem_region = LazyBool::eLazyBoolYes; + return Error(); +} + +Error NativeProcessNetBSD::AllocateMemory(size_t size, uint32_t permissions, + lldb::addr_t &addr) { + return Error("Unimplemented"); +} + +Error NativeProcessNetBSD::DeallocateMemory(lldb::addr_t addr) { + return Error("Unimplemented"); +} + +lldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() { + // punt on this for now + return LLDB_INVALID_ADDRESS; +} + +size_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); } + +bool NativeProcessNetBSD::GetArchitecture(ArchSpec &arch) const { + arch = m_arch; + return true; +} + +Error NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size, + bool hardware) { + if (hardware) + return Error("NativeProcessNetBSD does not support hardware breakpoints"); + else + return SetSoftwareBreakpoint(addr, size); +} + +Error NativeProcessNetBSD::GetSoftwareBreakpointTrapOpcode( + size_t trap_opcode_size_hint, size_t &actual_opcode_size, + const uint8_t *&trap_opcode_bytes) { + static const uint8_t g_i386_opcode[] = {0xCC}; + + switch (m_arch.GetMachine()) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + trap_opcode_bytes = g_i386_opcode; + actual_opcode_size = sizeof(g_i386_opcode); + return Error(); + default: + assert(false && "CPU type not supported!"); + return Error("CPU type not supported"); + } +} + +Error NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path, + FileSpec &file_spec) { + return Error("Unimplemented"); +} + +Error NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name, + lldb::addr_t &load_addr) { + load_addr = LLDB_INVALID_ADDRESS; + return Error(); +} + +Error NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop, + ProcessLaunchInfo &launch_info) { + Error error; + m_sigchld_handle = mainloop.RegisterSignal( + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); + if (!m_sigchld_handle) + return error; + + SetState(eStateLaunching); + + ::pid_t pid = ProcessLauncherPosixFork() + .LaunchProcess(launch_info, error) + .GetProcessId(); + if (error.Fail()) + return error; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + // Wait for the child process to trap on its call to execve. + ::pid_t wpid; + int status; + if ((wpid = waitpid(pid, &status, 0)) < 0) { + error.SetErrorToErrno(); + 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, + // using eStateInvalid. + SetState(StateType::eStateInvalid); + + return error; + } + assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) && + "Could not sync with inferior process."); + + LLDB_LOG(log, "inferior started, now in stopped state"); + + // Release the master terminal descriptor and pass it off to the + // NativeProcessNetBSD instance. Similarly stash the inferior pid. + m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); + m_pid = pid; + launch_info.SetProcessID(pid); + + if (m_terminal_fd != -1) { + error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); + if (error.Fail()) { + 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 + // now, using eStateInvalid. + SetState(StateType::eStateInvalid); + + return error; + } + } + + LLDB_LOG(log, "adding pid = {0}", pid); + + ResolveProcessArchitecture(m_pid, m_arch); + + error = ReinitializeThreads(); + if (error.Fail()) { + SetState(StateType::eStateInvalid); + return error; + } + + /* Set process stopped */ + SetState(StateType::eStateStopped); + + if (error.Fail()) + LLDB_LOG(log, "inferior launching failed {0}", error); + return error; +} + +void NativeProcessNetBSD::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, + Error &error) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid = {0:x}", pid); + + m_sigchld_handle = mainloop.RegisterSignal( + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); + if (!m_sigchld_handle) + return; + + error = ResolveProcessArchitecture(pid, m_arch); + if (!error.Success()) + return; + + // Set the architecture to the exe architecture. + LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, + m_arch.GetArchitectureName()); + + m_pid = pid; + SetState(eStateAttaching); + + Attach(pid, error); +} + +void NativeProcessNetBSD::SigchldHandler() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + // Process all pending waitpid notifications. + int status; + ::pid_t wait_pid = waitpid(GetID(), &status, WALLSIG | WNOHANG); + + if (wait_pid == 0) + return; // We are done. + + if (wait_pid == -1) { + if (errno == EINTR) + return; + + Error error(errno, eErrorTypePOSIX); + LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error); + } + + bool exited = false; + int signal = 0; + int exit_status = 0; + const char *status_cstr = nullptr; + if (WIFSTOPPED(status)) { + signal = WSTOPSIG(status); + status_cstr = "STOPPED"; + } else if (WIFEXITED(status)) { + exit_status = WEXITSTATUS(status); + status_cstr = "EXITED"; + exited = true; + } else if (WIFSIGNALED(status)) { + signal = WTERMSIG(status); + status_cstr = "SIGNALED"; + if (wait_pid == static_cast<::pid_t>(GetID())) { + exited = true; + exit_status = -1; + } + } else + status_cstr = "(\?\?\?)"; + + LLDB_LOG(log, + "waitpid ({0}, &status, _) => pid = {1}, status = {2:x} " + "({3}), signal = {4}, exit_state = {5}", + GetID(), wait_pid, status, status_cstr, signal, exit_status); + + if (exited) + MonitorExited(wait_pid, signal, exit_status); + else + MonitorCallback(wait_pid, signal); +} + +NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); + + assert(!HasThreadNoLock(thread_id) && + "attempted to add a thread by id that already exists"); + + // If this is the first thread, save it as the current thread + if (m_threads.empty()) + SetCurrentThreadID(thread_id); + + auto thread_sp = std::make_shared<NativeThreadNetBSD>(this, thread_id); + m_threads.push_back(thread_sp); + return thread_sp; +} + +::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Error &error) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + if (pid <= 1) { + error.SetErrorToGenericError(); + error.SetErrorString("Attaching to process 1 is not allowed."); + return -1; + } + + // Attach to the requested process. + // An attach will cause the thread to stop with a SIGSTOP. + error = PtraceWrapper(PT_ATTACH, pid); + if (error.Fail()) + return -1; + + int status; + // Need to use WALLSIG otherwise we receive an error with errno=ECHLD + // At this point we should have a thread stopped if waitpid succeeds. + if ((status = waitpid(pid, NULL, WALLSIG)) < 0) + return -1; + + m_pid = pid; + + /* Initialize threads */ + error = ReinitializeThreads(); + if (error.Fail()) { + SetState(StateType::eStateInvalid); + return -1; + } + + // Let our process instance know the thread has stopped. + SetState(StateType::eStateStopped); + + return pid; +} + +Error NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf, size_t size, + size_t &bytes_read) { + unsigned char *dst = static_cast<unsigned char *>(buf); + struct ptrace_io_desc io; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); + + bytes_read = 0; + io.piod_op = PIOD_READ_D; + io.piod_len = size; + + do { + io.piod_offs = (void *)(addr + bytes_read); + io.piod_addr = dst + bytes_read; + + Error error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io); + if (error.Fail()) + return error; + + bytes_read = io.piod_len; + io.piod_len = size - bytes_read; + } while (bytes_read < size); + + return Error(); +} + +Error NativeProcessNetBSD::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, + size_t size, + size_t &bytes_read) { + Error error = ReadMemory(addr, buf, size, bytes_read); + if (error.Fail()) + return error; + return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size); +} + +Error NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf, + size_t size, size_t &bytes_written) { + const unsigned char *src = static_cast<const unsigned char *>(buf); + Error error; + struct ptrace_io_desc io; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); + + bytes_written = 0; + io.piod_op = PIOD_WRITE_D; + io.piod_len = size; + + do { + io.piod_addr = (void *)(src + bytes_written); + io.piod_offs = (void *)(addr + bytes_written); + + Error error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io); + if (error.Fail()) + return error; + + bytes_written = io.piod_len; + io.piod_len = size - bytes_written; + } while (bytes_written < size); + + return error; +} + +llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> +NativeProcessNetBSD::GetAuxvData() const { + /* + * ELF_AUX_ENTRIES is currently restricted to kernel + * (<sys/exec_elf.h> r. 1.155 specifies 15) + * + * ptrace(2) returns the whole AUXV including extra fiels after AT_NULL this + * information isn't needed. + */ + size_t auxv_size = 100 * sizeof(AuxInfo); + + ErrorOr<std::unique_ptr<MemoryBuffer>> buf = + llvm::MemoryBuffer::getNewMemBuffer(auxv_size); + + struct ptrace_io_desc io = {.piod_op = PIOD_READ_AUXV, + .piod_offs = 0, + .piod_addr = (void *)buf.get()->getBufferStart(), + .piod_len = auxv_size}; + + Error error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io); + + if (error.Fail()) + return std::error_code(error.GetError(), std::generic_category()); + + if (io.piod_len < 1) + return std::error_code(ECANCELED, std::generic_category()); + + return buf; +} + +Error NativeProcessNetBSD::ReinitializeThreads() { + // Clear old threads + m_threads.clear(); + + // Initialize new thread + struct ptrace_lwpinfo info = {}; + Error error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info)); + if (error.Fail()) { + return error; + } + // Reinitialize from scratch threads and register them in process + while (info.pl_lwpid != 0) { + NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid); + thread_sp->SetStoppedByExec(); + error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info)); + if (error.Fail()) { + return error; + } + } + + return error; +} diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h new file mode 100644 index 000000000000..ae946a8e004d --- /dev/null +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -0,0 +1,141 @@ +//===-- NativeProcessNetBSD.h --------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_NativeProcessNetBSD_H_ +#define liblldb_NativeProcessNetBSD_H_ + +// C++ Includes + +// Other libraries and framework includes + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/FileSpec.h" + +#include "NativeThreadNetBSD.h" +#include "lldb/Host/common/NativeProcessProtocol.h" + +namespace lldb_private { +namespace process_netbsd { +/// @class NativeProcessNetBSD +/// @brief Manages communication with the inferior (debugee) process. +/// +/// Upon construction, this class prepares and launches an inferior process for +/// debugging. +/// +/// Changes in the inferior process state are broadcasted. +class NativeProcessNetBSD : public NativeProcessProtocol { + friend Error NativeProcessProtocol::Launch( + ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop, NativeProcessProtocolSP &process_sp); + + friend Error NativeProcessProtocol::Attach( + lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, + MainLoop &mainloop, NativeProcessProtocolSP &process_sp); + +public: + // --------------------------------------------------------------------- + // NativeProcessProtocol Interface + // --------------------------------------------------------------------- + Error Resume(const ResumeActionList &resume_actions) override; + + Error Halt() override; + + Error Detach() override; + + Error Signal(int signo) override; + + Error Kill() override; + + Error GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) override; + + Error ReadMemory(lldb::addr_t addr, void *buf, size_t size, + size_t &bytes_read) override; + + Error ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, + size_t &bytes_read) override; + + Error WriteMemory(lldb::addr_t addr, const void *buf, size_t size, + size_t &bytes_written) override; + + Error AllocateMemory(size_t size, uint32_t permissions, + lldb::addr_t &addr) override; + + Error DeallocateMemory(lldb::addr_t addr) override; + + lldb::addr_t GetSharedLibraryInfoAddress() override; + + size_t UpdateThreads() override; + + bool GetArchitecture(ArchSpec &arch) const override; + + Error SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override; + + Error GetLoadedModuleFileSpec(const char *module_path, + FileSpec &file_spec) override; + + Error GetFileLoadAddress(const llvm::StringRef &file_name, + lldb::addr_t &load_addr) override; + + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> + GetAuxvData() const override; + + // --------------------------------------------------------------------- + // Interface used by NativeRegisterContext-derived classes. + // --------------------------------------------------------------------- + static Error PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr, + int data = 0, int *result = nullptr); + +protected: + // --------------------------------------------------------------------- + // NativeProcessProtocol protected interface + // --------------------------------------------------------------------- + + Error + GetSoftwareBreakpointTrapOpcode(size_t trap_opcode_size_hint, + size_t &actual_opcode_size, + const uint8_t *&trap_opcode_bytes) override; + +private: + MainLoop::SignalHandleUP m_sigchld_handle; + ArchSpec m_arch; + LazyBool m_supports_mem_region; + std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache; + + // --------------------------------------------------------------------- + // Private Instance Methods + // --------------------------------------------------------------------- + NativeProcessNetBSD(); + + NativeThreadNetBSDSP AddThread(lldb::tid_t thread_id); + + Error LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info); + void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Error &error); + + void MonitorCallback(lldb::pid_t pid, int signal); + void MonitorExited(lldb::pid_t pid, int signal, int status); + void MonitorSIGSTOP(lldb::pid_t pid); + void MonitorSIGTRAP(lldb::pid_t pid); + void MonitorSignal(lldb::pid_t pid, int signal); + + Error GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size); + Error FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread); + Error PopulateMemoryRegionCache(); + void SigchldHandler(); + + ::pid_t Attach(lldb::pid_t pid, Error &error); + + Error ReinitializeThreads(); +}; + +} // namespace process_netbsd +} // namespace lldb_private + +#endif // #ifndef liblldb_NativeProcessNetBSD_H_ diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp new file mode 100644 index 000000000000..1bb6324c97fe --- /dev/null +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp @@ -0,0 +1,92 @@ +//===-- NativeRegisterContextNetBSD.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "NativeRegisterContextNetBSD.h" + +#include "lldb/Host/common/NativeProcessProtocol.h" + +using namespace lldb_private; +using namespace lldb_private::process_netbsd; + +// clang-format off +#include <sys/types.h> +#include <sys/ptrace.h> +// clang-format on + +NativeRegisterContextNetBSD::NativeRegisterContextNetBSD( + NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *reg_info_interface_p) + : NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, + reg_info_interface_p) {} + +Error NativeRegisterContextNetBSD::ReadGPR() { + void *buf = GetGPRBuffer(); + if (!buf) + return Error("GPR buffer is NULL"); + + return DoReadGPR(buf); +} + +Error NativeRegisterContextNetBSD::WriteGPR() { + void *buf = GetGPRBuffer(); + if (!buf) + return Error("GPR buffer is NULL"); + + return DoWriteGPR(buf); +} + +Error NativeRegisterContextNetBSD::ReadFPR() { + void *buf = GetFPRBuffer(); + if (!buf) + return Error("FPR buffer is NULL"); + + return DoReadFPR(buf); +} + +Error NativeRegisterContextNetBSD::WriteFPR() { + void *buf = GetFPRBuffer(); + if (!buf) + return Error("FPR buffer is NULL"); + + return DoWriteFPR(buf); +} + +Error NativeRegisterContextNetBSD::DoReadGPR(void *buf) { + return NativeProcessNetBSD::PtraceWrapper(PT_GETREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + +Error NativeRegisterContextNetBSD::DoWriteGPR(void *buf) { + return NativeProcessNetBSD::PtraceWrapper(PT_SETREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + +Error NativeRegisterContextNetBSD::DoReadFPR(void *buf) { + return NativeProcessNetBSD::PtraceWrapper(PT_GETFPREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + +Error NativeRegisterContextNetBSD::DoWriteFPR(void *buf) { + return NativeProcessNetBSD::PtraceWrapper(PT_SETFPREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + +NativeProcessNetBSD &NativeRegisterContextNetBSD::GetProcess() { + auto process_sp = + std::static_pointer_cast<NativeProcessNetBSD>(m_thread.GetProcess()); + assert(process_sp); + return *process_sp; +} + +::pid_t NativeRegisterContextNetBSD::GetProcessPid() { + NativeProcessNetBSD &process = GetProcess(); + lldb::pid_t pid = process.GetID(); + + return pid; +} diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h new file mode 100644 index 000000000000..5ff59bc87c98 --- /dev/null +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h @@ -0,0 +1,65 @@ +//===-- NativeRegisterContextNetBSD.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_NativeRegisterContextNetBSD_h +#define lldb_NativeRegisterContextNetBSD_h + +#include "lldb/Host/common/NativeThreadProtocol.h" + +#include "Plugins/Process/NetBSD/NativeProcessNetBSD.h" +#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h" + +namespace lldb_private { +namespace process_netbsd { + +class NativeRegisterContextNetBSD : public NativeRegisterContextRegisterInfo { +public: + NativeRegisterContextNetBSD(NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *reg_info_interface_p); + + // This function is implemented in the NativeRegisterContextNetBSD_* + // subclasses to create a new instance of the host specific + // NativeRegisterContextNetBSD. The implementations can't collide as only one + // NativeRegisterContextNetBSD_* variant should be compiled into the final + // executable. + static NativeRegisterContextNetBSD * + CreateHostNativeRegisterContextNetBSD(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); + +protected: + virtual Error ReadGPR(); + virtual Error WriteGPR(); + + virtual Error ReadFPR(); + virtual Error WriteFPR(); + + virtual void *GetGPRBuffer() { return nullptr; } + virtual size_t GetGPRSize() { + return GetRegisterInfoInterface().GetGPRSize(); + } + + virtual void *GetFPRBuffer() { return nullptr; } + virtual size_t GetFPRSize() { return 0; } + + virtual Error DoReadGPR(void *buf); + virtual Error DoWriteGPR(void *buf); + + virtual Error DoReadFPR(void *buf); + virtual Error DoWriteFPR(void *buf); + + virtual NativeProcessNetBSD &GetProcess(); + virtual ::pid_t GetProcessPid(); +}; + +} // namespace process_netbsd +} // namespace lldb_private + +#endif // #ifndef lldb_NativeRegisterContextNetBSD_h diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp new file mode 100644 index 000000000000..76e64ac48d66 --- /dev/null +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -0,0 +1,483 @@ +//===-- NativeRegisterContextNetBSD_x86_64.cpp ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#if defined(__x86_64__) + +#include "NativeRegisterContextNetBSD_x86_64.h" + +#include "lldb/Core/RegisterValue.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/Log.h" + +#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" + +#include <elf.h> + +using namespace lldb_private; +using namespace lldb_private::process_netbsd; + +// ---------------------------------------------------------------------------- +// Private namespace. +// ---------------------------------------------------------------------------- + +namespace { +// x86 64-bit general purpose registers. +static const uint32_t g_gpr_regnums_x86_64[] = { + lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, + lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64, + lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64, + lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64, + lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64, + lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64, + lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64, + lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64, + lldb_r8d_x86_64, // Low 32 bits or r8 + lldb_r9d_x86_64, // Low 32 bits or r9 + lldb_r10d_x86_64, // Low 32 bits or r10 + lldb_r11d_x86_64, // Low 32 bits or r11 + lldb_r12d_x86_64, // Low 32 bits or r12 + lldb_r13d_x86_64, // Low 32 bits or r13 + lldb_r14d_x86_64, // Low 32 bits or r14 + lldb_r15d_x86_64, // Low 32 bits or r15 + lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64, + lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64, + lldb_r8w_x86_64, // Low 16 bits or r8 + lldb_r9w_x86_64, // Low 16 bits or r9 + lldb_r10w_x86_64, // Low 16 bits or r10 + lldb_r11w_x86_64, // Low 16 bits or r11 + lldb_r12w_x86_64, // Low 16 bits or r12 + lldb_r13w_x86_64, // Low 16 bits or r13 + lldb_r14w_x86_64, // Low 16 bits or r14 + lldb_r15w_x86_64, // Low 16 bits or r15 + lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64, + lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64, + lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64, + lldb_r8l_x86_64, // Low 8 bits or r8 + lldb_r9l_x86_64, // Low 8 bits or r9 + lldb_r10l_x86_64, // Low 8 bits or r10 + lldb_r11l_x86_64, // Low 8 bits or r11 + lldb_r12l_x86_64, // Low 8 bits or r12 + lldb_r13l_x86_64, // Low 8 bits or r13 + lldb_r14l_x86_64, // Low 8 bits or r14 + lldb_r15l_x86_64, // Low 8 bits or r15 + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - + 1 == + k_num_gpr_registers_x86_64, + "g_gpr_regnums_x86_64 has wrong number of register infos"); + +// Number of register sets provided by this context. +enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 }; + +// Register sets for x86 64-bit. +static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, + g_gpr_regnums_x86_64}, +}; + +#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize()) + +} // namespace + +NativeRegisterContextNetBSD * +NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) { + return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread, + concrete_frame_idx); +} + +// ---------------------------------------------------------------------------- +// NativeRegisterContextNetBSD_x86_64 members. +// ---------------------------------------------------------------------------- + +static RegisterInfoInterface * +CreateRegisterInfoInterface(const ArchSpec &target_arch) { + assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && + "Register setting path assumes this is a 64-bit host"); + // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the + // x86_64 register context. + return new RegisterContextNetBSD_x86_64(target_arch); +} + +NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextNetBSD(native_thread, concrete_frame_idx, + CreateRegisterInfoInterface(target_arch)), + m_gpr_x86_64() {} + +// CONSIDER after local and llgs debugging are merged, register set support can +// be moved into a base x86-64 class with IsRegisterSetAvailable made virtual. +uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const { + uint32_t sets = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { + if (GetSetForNativeRegNum(set_index) != -1) + ++sets; + } + + return sets; +} + +const RegisterSet * +NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const { + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::x86_64: + return &g_reg_sets_x86_64[set_index]; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } + + return nullptr; +} + +int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( + int reg_num) const { + if (reg_num < lldb_fctrl_x86_64) + return GPRegSet; + else + return -1; +} + +int NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) { + switch (set) { + case GPRegSet: + ReadGPR(); + return 0; + case FPRegSet: + ReadFPR(); + return 0; + default: + break; + } + return -1; +} +int NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) { + switch (set) { + case GPRegSet: + WriteGPR(); + return 0; + case FPRegSet: + WriteFPR(); + return 0; + default: + break; + } + return -1; +} + +Error NativeRegisterContextNetBSD_x86_64::ReadRegister( + const RegisterInfo *reg_info, RegisterValue ®_value) { + Error error; + + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " + "register, cannot read directly", + reg_info->name); + return error; + } + + int set = GetSetForNativeRegNum(reg); + if (set == -1) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", + reg_info->name); + return error; + } + + if (ReadRegisterSet(set) != 0) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat( + "reading register set for register \"%s\" failed", reg_info->name); + return error; + } + + switch (reg) { + case lldb_rax_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RAX]; + break; + case lldb_rbx_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RBX]; + break; + case lldb_rcx_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RCX]; + break; + case lldb_rdx_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RDX]; + break; + case lldb_rdi_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RDI]; + break; + case lldb_rsi_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RSI]; + break; + case lldb_rbp_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RBP]; + break; + case lldb_rsp_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RSP]; + break; + case lldb_r8_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R8]; + break; + case lldb_r9_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R9]; + break; + case lldb_r10_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R10]; + break; + case lldb_r11_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R11]; + break; + case lldb_r12_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R12]; + break; + case lldb_r13_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R13]; + break; + case lldb_r14_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R14]; + break; + case lldb_r15_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R15]; + break; + case lldb_rip_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RIP]; + break; + case lldb_rflags_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RFLAGS]; + break; + case lldb_cs_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_CS]; + break; + case lldb_fs_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_FS]; + break; + case lldb_gs_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_GS]; + break; + case lldb_ss_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_SS]; + break; + case lldb_ds_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_DS]; + break; + case lldb_es_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_ES]; + break; + } + + return error; +} + +Error NativeRegisterContextNetBSD_x86_64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + + Error error; + + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " + "register, cannot read directly", + reg_info->name); + return error; + } + + int set = GetSetForNativeRegNum(reg); + if (set == -1) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", + reg_info->name); + return error; + } + + if (ReadRegisterSet(set) != 0) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat( + "reading register set for register \"%s\" failed", reg_info->name); + return error; + } + + switch (reg) { + case lldb_rax_x86_64: + m_gpr_x86_64.regs[_REG_RAX] = reg_value.GetAsUInt64(); + break; + case lldb_rbx_x86_64: + m_gpr_x86_64.regs[_REG_RBX] = reg_value.GetAsUInt64(); + break; + case lldb_rcx_x86_64: + m_gpr_x86_64.regs[_REG_RCX] = reg_value.GetAsUInt64(); + break; + case lldb_rdx_x86_64: + m_gpr_x86_64.regs[_REG_RDX] = reg_value.GetAsUInt64(); + break; + case lldb_rdi_x86_64: + m_gpr_x86_64.regs[_REG_RDI] = reg_value.GetAsUInt64(); + break; + case lldb_rsi_x86_64: + m_gpr_x86_64.regs[_REG_RSI] = reg_value.GetAsUInt64(); + break; + case lldb_rbp_x86_64: + m_gpr_x86_64.regs[_REG_RBP] = reg_value.GetAsUInt64(); + break; + case lldb_rsp_x86_64: + m_gpr_x86_64.regs[_REG_RSP] = reg_value.GetAsUInt64(); + break; + case lldb_r8_x86_64: + m_gpr_x86_64.regs[_REG_R8] = reg_value.GetAsUInt64(); + break; + case lldb_r9_x86_64: + m_gpr_x86_64.regs[_REG_R9] = reg_value.GetAsUInt64(); + break; + case lldb_r10_x86_64: + m_gpr_x86_64.regs[_REG_R10] = reg_value.GetAsUInt64(); + break; + case lldb_r11_x86_64: + m_gpr_x86_64.regs[_REG_R11] = reg_value.GetAsUInt64(); + break; + case lldb_r12_x86_64: + m_gpr_x86_64.regs[_REG_R12] = reg_value.GetAsUInt64(); + break; + case lldb_r13_x86_64: + m_gpr_x86_64.regs[_REG_R13] = reg_value.GetAsUInt64(); + break; + case lldb_r14_x86_64: + m_gpr_x86_64.regs[_REG_R14] = reg_value.GetAsUInt64(); + break; + case lldb_r15_x86_64: + m_gpr_x86_64.regs[_REG_R15] = reg_value.GetAsUInt64(); + break; + case lldb_rip_x86_64: + m_gpr_x86_64.regs[_REG_RIP] = reg_value.GetAsUInt64(); + break; + case lldb_rflags_x86_64: + m_gpr_x86_64.regs[_REG_RFLAGS] = reg_value.GetAsUInt64(); + break; + case lldb_cs_x86_64: + m_gpr_x86_64.regs[_REG_CS] = reg_value.GetAsUInt64(); + break; + case lldb_fs_x86_64: + m_gpr_x86_64.regs[_REG_FS] = reg_value.GetAsUInt64(); + break; + case lldb_gs_x86_64: + m_gpr_x86_64.regs[_REG_GS] = reg_value.GetAsUInt64(); + break; + case lldb_ss_x86_64: + m_gpr_x86_64.regs[_REG_SS] = reg_value.GetAsUInt64(); + break; + case lldb_ds_x86_64: + m_gpr_x86_64.regs[_REG_DS] = reg_value.GetAsUInt64(); + break; + case lldb_es_x86_64: + m_gpr_x86_64.regs[_REG_ES] = reg_value.GetAsUInt64(); + break; + } + + if (WriteRegisterSet(set) != 0) + error.SetErrorStringWithFormat("failed to write register set"); + + return error; +} + +Error NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + Error error; + + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (!data_sp) { + error.SetErrorStringWithFormat( + "failed to allocate DataBufferHeap instance of size %" PRIu64, + REG_CONTEXT_SIZE); + return error; + } + + error = ReadGPR(); + if (error.Fail()) + return error; + + uint8_t *dst = data_sp->GetBytes(); + if (dst == nullptr) { + error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 + " returned a null pointer", + REG_CONTEXT_SIZE); + return error; + } + + ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); + dst += GetRegisterInfoInterface().GetGPRSize(); + + RegisterValue value((uint64_t)-1); + const RegisterInfo *reg_info = + GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax"); + if (reg_info == nullptr) + reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax"); + return error; +} + +Error NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + Error error; + + if (!data_sp) { + error.SetErrorStringWithFormat( + "NativeRegisterContextNetBSD_x86_64::%s invalid data_sp provided", + __FUNCTION__); + return error; + } + + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { + error.SetErrorStringWithFormat( + "NativeRegisterContextNetBSD_x86_64::%s data_sp contained mismatched " + "data size, expected %" PRIu64 ", actual %" PRIu64, + __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) { + error.SetErrorStringWithFormat("NativeRegisterContextNetBSD_x86_64::%s " + "DataBuffer::GetBytes() returned a null " + "pointer", + __FUNCTION__); + return error; + } + ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize()); + + error = WriteGPR(); + if (error.Fail()) + return error; + src += GetRegisterInfoInterface().GetGPRSize(); + + return error; +} + +#endif // defined(__x86_64__) diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h new file mode 100644 index 000000000000..f6f7d7f0976a --- /dev/null +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h @@ -0,0 +1,72 @@ +//===-- NativeRegisterContextNetBSD_x86_64.h --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#if defined(__x86_64__) + +#ifndef lldb_NativeRegisterContextNetBSD_x86_64_h +#define lldb_NativeRegisterContextNetBSD_x86_64_h + +// clang-format off +#include <sys/param.h> +#include <sys/types.h> +#include <machine/reg.h> +// clang-format on + +#include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h" +#include "Plugins/Process/Utility/RegisterContext_x86.h" +#include "Plugins/Process/Utility/lldb-x86-register-enums.h" + +namespace lldb_private { +namespace process_netbsd { + +class NativeProcessNetBSD; + +class NativeRegisterContextNetBSD_x86_64 : public NativeRegisterContextNetBSD { +public: + NativeRegisterContextNetBSD_x86_64(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); + uint32_t GetRegisterSetCount() const override; + + const RegisterSet *GetRegisterSet(uint32_t set_index) const override; + + Error ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; + + Error WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; + + Error ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + +protected: + void *GetGPRBuffer() override { return &m_gpr_x86_64; } + void *GetFPRBuffer() override { return &m_fpr_x86_64; } + +private: + // Private member types. + enum { GPRegSet, FPRegSet }; + + // Private member variables. + struct reg m_gpr_x86_64; + struct fpreg m_fpr_x86_64; + + int GetSetForNativeRegNum(int reg_num) const; + + int ReadRegisterSet(uint32_t set); + int WriteRegisterSet(uint32_t set); +}; + +} // namespace process_netbsd +} // namespace lldb_private + +#endif // #ifndef lldb_NativeRegisterContextNetBSD_x86_64_h + +#endif // defined(__x86_64__) diff --git a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp new file mode 100644 index 000000000000..f23621e45aad --- /dev/null +++ b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp @@ -0,0 +1,159 @@ +//===-- NativeThreadNetBSD.cpp -------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "NativeThreadNetBSD.h" +#include "NativeRegisterContextNetBSD.h" + +#include "NativeProcessNetBSD.h" + +#include "Plugins/Process/POSIX/CrashReason.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/State.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_netbsd; + +NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD *process, + lldb::tid_t tid) + : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), + m_stop_info(), m_reg_context_sp(), m_stop_description() {} + +void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo, + const siginfo_t *info) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo); + + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonSignal; + m_stop_info.details.signal.signo = signo; + + m_stop_description.clear(); + if (info) { + switch (signo) { + case SIGSEGV: + case SIGBUS: + case SIGFPE: + case SIGILL: + const auto reason = GetCrashReason(*info); + m_stop_description = GetCrashReasonString(reason, *info); + break; + } + } +} + +void NativeThreadNetBSD::SetStoppedByBreakpoint() { + SetStopped(); + m_stop_info.reason = StopReason::eStopReasonBreakpoint; + m_stop_info.details.signal.signo = SIGTRAP; +} + +void NativeThreadNetBSD::SetStoppedByTrace() { + SetStopped(); + m_stop_info.reason = StopReason::eStopReasonTrace; + m_stop_info.details.signal.signo = SIGTRAP; +} + +void NativeThreadNetBSD::SetStoppedByExec() { + SetStopped(); + m_stop_info.reason = StopReason::eStopReasonExec; + m_stop_info.details.signal.signo = SIGTRAP; +} + +void NativeThreadNetBSD::SetStopped() { + const StateType new_state = StateType::eStateStopped; + m_state = new_state; + m_stop_description.clear(); +} + +void NativeThreadNetBSD::SetRunning() { + m_state = StateType::eStateRunning; + m_stop_info.reason = StopReason::eStopReasonNone; +} + +void NativeThreadNetBSD::SetStepping() { + m_state = StateType::eStateStepping; + m_stop_info.reason = StopReason::eStopReasonNone; +} + +std::string NativeThreadNetBSD::GetName() { return std::string(""); } + +lldb::StateType NativeThreadNetBSD::GetState() { return m_state; } + +bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info, + std::string &description) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + + description.clear(); + + switch (m_state) { + case eStateStopped: + case eStateCrashed: + case eStateExited: + case eStateSuspended: + case eStateUnloaded: + stop_info = m_stop_info; + description = m_stop_description; + + return true; + + case eStateInvalid: + case eStateConnected: + case eStateAttaching: + case eStateLaunching: + case eStateRunning: + case eStateStepping: + case eStateDetached: + LLDB_LOG(log, "tid = {0} in state {1} cannot answer stop reason", GetID(), + StateAsCString(m_state)); + return false; + } + llvm_unreachable("unhandled StateType!"); +} + +NativeRegisterContextSP NativeThreadNetBSD::GetRegisterContext() { + // Return the register context if we already created it. + if (m_reg_context_sp) + return m_reg_context_sp; + + NativeProcessProtocolSP m_process_sp = m_process_wp.lock(); + if (!m_process_sp) + return NativeRegisterContextSP(); + + ArchSpec target_arch; + if (!m_process_sp->GetArchitecture(target_arch)) + return NativeRegisterContextSP(); + + const uint32_t concrete_frame_idx = 0; + m_reg_context_sp.reset( + NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( + target_arch, *this, concrete_frame_idx)); + + return m_reg_context_sp; +} + +Error NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags, bool hardware) { + return Error("Unimplemented"); +} + +Error NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) { + return Error("Unimplemented"); +} + +Error NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + return Error("Unimplemented"); +} + +Error NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) { + return Error("Unimplemented"); +} diff --git a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h new file mode 100644 index 000000000000..85fff5d5653f --- /dev/null +++ b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h @@ -0,0 +1,73 @@ +//===-- NativeThreadNetBSD.h ---------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_NativeThreadNetBSD_H_ +#define liblldb_NativeThreadNetBSD_H_ + +#include "lldb/Host/common/NativeThreadProtocol.h" + +namespace lldb_private { +namespace process_netbsd { + +class NativeProcessNetBSD; + +class NativeThreadNetBSD : public NativeThreadProtocol { + friend class NativeProcessNetBSD; + +public: + NativeThreadNetBSD(NativeProcessNetBSD *process, lldb::tid_t tid); + + // --------------------------------------------------------------------- + // NativeThreadProtocol Interface + // --------------------------------------------------------------------- + std::string GetName() override; + + lldb::StateType GetState() override; + + bool GetStopReason(ThreadStopInfo &stop_info, + std::string &description) override; + + NativeRegisterContextSP GetRegisterContext() override; + + Error SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, + bool hardware) override; + + Error RemoveWatchpoint(lldb::addr_t addr) override; + + Error SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; + + Error RemoveHardwareBreakpoint(lldb::addr_t addr) override; + +private: + // --------------------------------------------------------------------- + // Interface for friend classes + // --------------------------------------------------------------------- + + void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr); + void SetStoppedByBreakpoint(); + void SetStoppedByTrace(); + void SetStoppedByExec(); + void SetStopped(); + void SetRunning(); + void SetStepping(); + + // --------------------------------------------------------------------- + // Member Variables + // --------------------------------------------------------------------- + lldb::StateType m_state; + ThreadStopInfo m_stop_info; + NativeRegisterContextSP m_reg_context_sp; + std::string m_stop_description; +}; + +typedef std::shared_ptr<NativeThreadNetBSD> NativeThreadNetBSDSP; +} // namespace process_netbsd +} // namespace lldb_private + +#endif // #ifndef liblldb_NativeThreadNetBSD_H_ diff --git a/source/Plugins/Process/POSIX/CMakeLists.txt b/source/Plugins/Process/POSIX/CMakeLists.txt index 2ed7326dbb71..66fb7aa155b4 100644 --- a/source/Plugins/Process/POSIX/CMakeLists.txt +++ b/source/Plugins/Process/POSIX/CMakeLists.txt @@ -1,8 +1,14 @@ include_directories(.) include_directories(../Utility) -add_lldb_library(lldbPluginProcessPOSIX +add_lldb_library(lldbPluginProcessPOSIX PLUGIN CrashReason.cpp ProcessMessage.cpp ProcessPOSIXLog.cpp + + LINK_LIBS + lldbCore + lldbInterpreter + LINK_COMPONENTS + Support ) diff --git a/source/Plugins/Process/POSIX/CrashReason.cpp b/source/Plugins/Process/POSIX/CrashReason.cpp index 77d6e287486c..864418c90031 100644 --- a/source/Plugins/Process/POSIX/CrashReason.cpp +++ b/source/Plugins/Process/POSIX/CrashReason.cpp @@ -62,7 +62,6 @@ CrashReason GetCrashReasonForSIGSEGV(const siginfo_t &info) { return CrashReason::eBoundViolation; } - assert(false && "unexpected si_code for SIGSEGV"); return CrashReason::eInvalidCrashReason; } @@ -88,7 +87,6 @@ CrashReason GetCrashReasonForSIGILL(const siginfo_t &info) { return CrashReason::eInternalStackError; } - assert(false && "unexpected si_code for SIGILL"); return CrashReason::eInvalidCrashReason; } @@ -114,7 +112,6 @@ CrashReason GetCrashReasonForSIGFPE(const siginfo_t &info) { return CrashReason::eFloatSubscriptRange; } - assert(false && "unexpected si_code for SIGFPE"); return CrashReason::eInvalidCrashReason; } @@ -130,7 +127,6 @@ CrashReason GetCrashReasonForSIGBUS(const siginfo_t &info) { return CrashReason::eHardwareError; } - assert(false && "unexpected si_code for SIGBUS"); return CrashReason::eInvalidCrashReason; } } @@ -158,7 +154,7 @@ std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) { switch (reason) { default: - assert(false && "invalid CrashReason"); + str = "unknown crash reason"; break; case CrashReason::eInvalidAddress: diff --git a/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp b/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp index 9ced11c7ca2a..f1beb0f7f738 100644 --- a/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp +++ b/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp @@ -10,188 +10,23 @@ #include "ProcessPOSIXLog.h" -#include <mutex> +#include "llvm/Support/Threading.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Interpreter/Args.h" - -#include "ProcessPOSIXLog.h" - -using namespace lldb; using namespace lldb_private; -// We want to avoid global constructors where code needs to be run so here we -// control access to our static g_log_sp by hiding it in a singleton function -// 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 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}, +}; -void ProcessPOSIXLog::Initialize(ConstString name) { - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, [name]() { - Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories}; - - Log::RegisterLogChannel(name, log_callbacks); - RegisterPluginName(name); - }); -} +Log::Channel ProcessPOSIXLog::g_channel(g_categories, POSIX_LOG_DEFAULT); -Log *ProcessPOSIXLog::GetLogIfAllCategoriesSet(uint32_t mask) { - Log *log(GetLog()); - if (log && mask) { - uint32_t log_mask = log->GetMask().Get(); - if ((log_mask & mask) != mask) - return NULL; - } - return log; +void ProcessPOSIXLog::Initialize() { + static llvm::once_flag g_once_flag; + llvm::call_once(g_once_flag, []() { Log::Register("posix", g_channel); }); } - -static uint32_t GetFlagBits(const char *arg) { - if (::strcasecmp(arg, "all") == 0) - return POSIX_LOG_ALL; - else if (::strcasecmp(arg, "async") == 0) - return POSIX_LOG_ASYNC; - else if (::strncasecmp(arg, "break", 5) == 0) - return POSIX_LOG_BREAKPOINTS; - else if (::strncasecmp(arg, "comm", 4) == 0) - return POSIX_LOG_COMM; - else if (::strcasecmp(arg, "default") == 0) - return POSIX_LOG_DEFAULT; - else if (::strcasecmp(arg, "packets") == 0) - return POSIX_LOG_PACKETS; - else if (::strcasecmp(arg, "memory") == 0) - return POSIX_LOG_MEMORY; - else if (::strcasecmp(arg, "data-short") == 0) - return POSIX_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp(arg, "data-long") == 0) - return POSIX_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp(arg, "process") == 0) - return POSIX_LOG_PROCESS; - else if (::strcasecmp(arg, "ptrace") == 0) - return POSIX_LOG_PTRACE; - else if (::strcasecmp(arg, "registers") == 0) - return POSIX_LOG_REGISTERS; - else if (::strcasecmp(arg, "step") == 0) - return POSIX_LOG_STEP; - else if (::strcasecmp(arg, "thread") == 0) - return POSIX_LOG_THREAD; - else if (::strcasecmp(arg, "verbose") == 0) - return POSIX_LOG_VERBOSE; - else if (::strncasecmp(arg, "watch", 5) == 0) - return POSIX_LOG_WATCHPOINTS; - return 0; -} - -void ProcessPOSIXLog::DisableLog(const char **args, Stream *feedback_strm) { - Log *log(GetLog()); - if (log) { - uint32_t flag_bits = 0; - - flag_bits = log->GetMask().Get(); - for (; args && args[0]; args++) { - const char *arg = args[0]; - uint32_t bits = GetFlagBits(arg); - - if (bits) { - flag_bits &= ~bits; - } else { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories(feedback_strm); - } - } - - log->GetMask().Reset(flag_bits); - if (flag_bits == 0) - g_log_enabled = false; - } - - return; -} - -Log *ProcessPOSIXLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, - const char **args, Stream *feedback_strm) { - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the - // same. - uint32_t flag_bits = 0; - if (g_log) - flag_bits = g_log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) { - if (g_log) - g_log->SetStream(log_stream_sp); - else - g_log = new Log(log_stream_sp); - } - - if (g_log) { - bool got_unknown_category = false; - for (; args && args[0]; args++) { - const char *arg = args[0]; - uint32_t bits = GetFlagBits(arg); - - if (bits) { - flag_bits |= bits; - } else { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) { - got_unknown_category = true; - ListLogCategories(feedback_strm); - } - } - } - if (flag_bits == 0) - flag_bits = POSIX_LOG_DEFAULT; - g_log->GetMask().Reset(flag_bits); - g_log->GetOptions().Reset(log_options); - g_log_enabled = true; - } - return g_log; -} - -void ProcessPOSIXLog::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" - " communication - log communication activity\n" - " default - enable the default set of logging categories for liblldb\n" - " packets - log gdb remote packets\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" -#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION - " ptrace - log all calls to ptrace\n" -#endif - " registers - log register read/writes\n" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n" - " watch - log watchpoint related activities\n", - ProcessPOSIXLog::m_pluginname); -} - -void ProcessPOSIXLog::LogIf(uint32_t mask, const char *format, ...) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(mask)); - if (log) { - va_list args; - va_start(args, format); - log->VAPrintf(format, args); - va_end(args); - } -} - -int ProcessPOSIXLog::m_nestinglevel; -const char *ProcessPOSIXLog::m_pluginname = ""; diff --git a/source/Plugins/Process/POSIX/ProcessPOSIXLog.h b/source/Plugins/Process/POSIX/ProcessPOSIXLog.h index 7d187da4e488..134013517a11 100644 --- a/source/Plugins/Process/POSIX/ProcessPOSIXLog.h +++ b/source/Plugins/Process/POSIX/ProcessPOSIXLog.h @@ -16,87 +16,29 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/Log.h" +#include "lldb/Utility/Log.h" -#define POSIX_LOG_VERBOSE (1u << 0) #define POSIX_LOG_PROCESS (1u << 1) #define POSIX_LOG_THREAD (1u << 2) -#define POSIX_LOG_PACKETS (1u << 3) #define POSIX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define POSIX_LOG_MEMORY_DATA_SHORT \ - (1u << 5) // Log short memory reads/writes bytes -#define POSIX_LOG_MEMORY_DATA_LONG \ - (1u << 6) // Log all memory reads/writes bytes +#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_STEP (1u << 9) -#define POSIX_LOG_COMM (1u << 10) -#define POSIX_LOG_ASYNC (1u << 11) -#define POSIX_LOG_PTRACE (1u << 12) -#define POSIX_LOG_REGISTERS (1u << 13) #define POSIX_LOG_ALL (UINT32_MAX) -#define POSIX_LOG_DEFAULT POSIX_LOG_PACKETS - -// The size which determines "short memory reads/writes". -#define POSIX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) +#define POSIX_LOG_DEFAULT POSIX_LOG_PROCESS +namespace lldb_private { class ProcessPOSIXLog { - static int m_nestinglevel; - static const char *m_pluginname; + static Log::Channel g_channel; public: - // --------------------------------------------------------------------- - // Public Static Methods - // --------------------------------------------------------------------- - static void Initialize(lldb_private::ConstString name); - - static void RegisterPluginName(const char *pluginName) { - m_pluginname = pluginName; - } - - static void RegisterPluginName(lldb_private::ConstString pluginName) { - m_pluginname = pluginName.GetCString(); - } - - static lldb_private::Log *GetLogIfAllCategoriesSet(uint32_t mask = 0); - - static void DisableLog(const char **args, - lldb_private::Stream *feedback_strm); - - static lldb_private::Log *EnableLog(lldb::StreamSP &log_stream_sp, - uint32_t log_options, const char **args, - lldb_private::Stream *feedback_strm); - - static void ListLogCategories(lldb_private::Stream *strm); - - static void LogIf(uint32_t mask, const char *format, ...); - - // The following functions can be used to enable the client to limit - // logging to only the top level function calls. This is useful for - // recursive functions. FIXME: not thread safe! - // Example: - // void NestingFunc() { - // LogSP log - // (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL)); - // if (log) - // { - // ProcessPOSIXLog::IncNestLevel(); - // if (ProcessPOSIXLog::AtTopNestLevel()) - // log->Print(msg); - // } - // NestingFunc(); - // if (log) - // ProcessPOSIXLog::DecNestLevel(); - // } - - static bool AtTopNestLevel() { return m_nestinglevel == 1; } - - static void IncNestLevel() { ++m_nestinglevel; } + static void Initialize(); - static void DecNestLevel() { - --m_nestinglevel; - assert(m_nestinglevel >= 0); + static Log *GetLogIfAllCategoriesSet(uint32_t mask) { + return g_channel.GetLogIfAll(mask); } }; +} #endif // liblldb_ProcessPOSIXLog_h_ diff --git a/source/Plugins/Process/Utility/CMakeLists.txt b/source/Plugins/Process/Utility/CMakeLists.txt index c557667e3910..bda0ad626f6f 100644 --- a/source/Plugins/Process/Utility/CMakeLists.txt +++ b/source/Plugins/Process/Utility/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(../../../Utility/) -add_lldb_library(lldbPluginProcessUtility +add_lldb_library(lldbPluginProcessUtility PLUGIN DynamicRegisterInfo.cpp FreeBSDSignals.cpp GDBRemoteSignals.cpp @@ -9,19 +9,18 @@ add_lldb_library(lldbPluginProcessUtility InferiorCallPOSIX.cpp LinuxSignals.cpp MipsLinuxSignals.cpp + NativeRegisterContextRegisterInfo.cpp NetBSDSignals.cpp RegisterContextDarwin_arm.cpp RegisterContextDarwin_arm64.cpp RegisterContextDarwin_i386.cpp RegisterContextDarwin_x86_64.cpp RegisterContextDummy.cpp - RegisterContextFreeBSD_arm.cpp RegisterContextFreeBSD_i386.cpp RegisterContextFreeBSD_mips64.cpp RegisterContextFreeBSD_powerpc.cpp RegisterContextFreeBSD_x86_64.cpp RegisterContextHistory.cpp - RegisterContextLinux_arm.cpp RegisterContextLinux_i386.cpp RegisterContextLinux_x86_64.cpp RegisterContextLinux_mips64.cpp @@ -34,6 +33,8 @@ add_lldb_library(lldbPluginProcessUtility RegisterContextMach_x86_64.cpp RegisterContextMemory.cpp RegisterContextNetBSD_x86_64.cpp + RegisterContextOpenBSD_i386.cpp + RegisterContextOpenBSD_x86_64.cpp RegisterContextPOSIX_arm.cpp RegisterContextPOSIX_arm64.cpp RegisterContextPOSIX_mips64.cpp @@ -41,9 +42,23 @@ add_lldb_library(lldbPluginProcessUtility RegisterContextPOSIX_s390x.cpp RegisterContextPOSIX_x86.cpp RegisterContextThreadMemory.cpp + RegisterInfoPOSIX_arm.cpp RegisterInfoPOSIX_arm64.cpp StopInfoMachException.cpp ThreadMemory.cpp UnwindLLDB.cpp UnwindMacOSXFrameBackchain.cpp + + LINK_LIBS + lldbBreakpoint + lldbCore + lldbDataFormatters + lldbExpression + lldbHost + lldbSymbol + lldbTarget + lldbUtility + lldbPluginProcessElfCore + LINK_COMPONENTS + Support ) diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 75f7251fb108..5e933d3b3dee 100644 --- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -14,11 +14,11 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/RegularExpression.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredData.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/StringExtractor.h" using namespace lldb; @@ -281,6 +281,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, // Swap "dwarf_opcode_string" over into "opcode_extractor" opcode_extractor.GetStringRef().swap(dwarf_opcode_string); uint32_t ret_val = opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes); + UNUSED_IF_ASSERT_DISABLED(ret_val); assert(ret_val == reg_info.dynamic_size_dwarf_len); for (j = 0; j < reg_info.dynamic_size_dwarf_len; ++j) diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/source/Plugins/Process/Utility/DynamicRegisterInfo.h index e5c22fe484e9..a30bfa1e1f16 100644 --- a/source/Plugins/Process/Utility/DynamicRegisterInfo.h +++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.h @@ -17,8 +17,8 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/ConstString.h" #include "lldb/Core/StructuredData.h" +#include "lldb/Utility/ConstString.h" #include "lldb/lldb-private.h" class DynamicRegisterInfo { diff --git a/source/Plugins/Process/Utility/HistoryThread.cpp b/source/Plugins/Process/Utility/HistoryThread.cpp index d27a7b0da943..4983dcdb5142 100644 --- a/source/Plugins/Process/Utility/HistoryThread.cpp +++ b/source/Plugins/Process/Utility/HistoryThread.cpp @@ -13,9 +13,9 @@ #include "Plugins/Process/Utility/HistoryUnwind.h" #include "Plugins/Process/Utility/RegisterContextHistory.h" -#include "lldb/Core/Log.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrameList.h" +#include "lldb/Utility/Log.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Plugins/Process/Utility/HistoryThread.h b/source/Plugins/Process/Utility/HistoryThread.h index 1a4898a95b7d..363ba2669637 100644 --- a/source/Plugins/Process/Utility/HistoryThread.h +++ b/source/Plugins/Process/Utility/HistoryThread.h @@ -18,11 +18,11 @@ // Project includes #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Event.h" -#include "lldb/Core/UserID.h" #include "lldb/Core/UserSettingsController.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/StackFrameList.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/UserID.h" #include "lldb/lldb-private.h" namespace lldb_private { diff --git a/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp new file mode 100644 index 000000000000..0b1814362425 --- /dev/null +++ b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp @@ -0,0 +1,43 @@ +//===-- NativeRegisterContextRegisterInfo.cpp -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "NativeRegisterContextRegisterInfo.h" +#include "lldb/lldb-private-forward.h" +#include "lldb/lldb-types.h" + +using namespace lldb_private; + +NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo( + NativeThreadProtocol &thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info_interface) + : NativeRegisterContext(thread, concrete_frame_idx), + m_register_info_interface_up(register_info_interface) { + assert(register_info_interface && "null register_info_interface"); +} + +uint32_t NativeRegisterContextRegisterInfo::GetRegisterCount() const { + return m_register_info_interface_up->GetRegisterCount(); +} + +uint32_t NativeRegisterContextRegisterInfo::GetUserRegisterCount() const { + return m_register_info_interface_up->GetUserRegisterCount(); +} + +const RegisterInfo *NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex( + uint32_t reg_index) const { + if (reg_index <= GetRegisterCount()) + return m_register_info_interface_up->GetRegisterInfo() + reg_index; + else + return nullptr; +} + +const RegisterInfoInterface & +NativeRegisterContextRegisterInfo::GetRegisterInfoInterface() const { + return *m_register_info_interface_up; +} diff --git a/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h new file mode 100644 index 000000000000..c1b597462b60 --- /dev/null +++ b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h @@ -0,0 +1,41 @@ +//===-- NativeRegisterContextRegisterInfo.h ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_PROCESS_UTIILTY_NATIVE_REGISTER_CONTEXT_REGISTER_INFO +#define LLDB_PLUGINS_PROCESS_UTIILTY_NATIVE_REGISTER_CONTEXT_REGISTER_INFO + +#include <memory> + +#include "RegisterInfoInterface.h" +#include "lldb/Host/common/NativeRegisterContext.h" + +namespace lldb_private { +class NativeRegisterContextRegisterInfo : public NativeRegisterContext { +public: + /// + /// Construct a NativeRegisterContextRegisterInfo, taking ownership + /// of the register_info_interface pointer. + /// + NativeRegisterContextRegisterInfo( + NativeThreadProtocol &thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info_interface); + + uint32_t GetRegisterCount() const override; + + uint32_t GetUserRegisterCount() const override; + + const RegisterInfo *GetRegisterInfoAtIndex(uint32_t reg_index) const override; + + const RegisterInfoInterface &GetRegisterInfoInterface() const; + +private: + std::unique_ptr<RegisterInfoInterface> m_register_info_interface_up; +}; +} +#endif diff --git a/source/Plugins/Process/Utility/NetBSDSignals.cpp b/source/Plugins/Process/Utility/NetBSDSignals.cpp index 9b9db51e5167..7ed7189d8048 100644 --- a/source/Plugins/Process/Utility/NetBSDSignals.cpp +++ b/source/Plugins/Process/Utility/NetBSDSignals.cpp @@ -24,7 +24,35 @@ void NetBSDSignals::Reset() { // =================================================== AddSignal(32, "SIGPWR", false, true, true, "power fail/restart (not reset when caught)"); -#ifdef SIGRTMIN /* SIGRTMAX */ - /* Kernel only; not exposed to userland yet */ -#endif + AddSignal(33, "SIGRTMIN", false, false, false, "real time signal 0"); + AddSignal(34, "SIGRTMIN+1", false, false, false, "real time signal 1"); + AddSignal(35, "SIGRTMIN+2", false, false, false, "real time signal 2"); + AddSignal(36, "SIGRTMIN+3", false, false, false, "real time signal 3"); + AddSignal(37, "SIGRTMIN+4", false, false, false, "real time signal 4"); + AddSignal(38, "SIGRTMIN+5", false, false, false, "real time signal 5"); + AddSignal(39, "SIGRTMIN+6", false, false, false, "real time signal 6"); + AddSignal(40, "SIGRTMIN+7", false, false, false, "real time signal 7"); + AddSignal(41, "SIGRTMIN+8", false, false, false, "real time signal 8"); + AddSignal(42, "SIGRTMIN+9", false, false, false, "real time signal 9"); + AddSignal(43, "SIGRTMIN+10", false, false, false, "real time signal 10"); + AddSignal(44, "SIGRTMIN+11", false, false, false, "real time signal 11"); + AddSignal(45, "SIGRTMIN+12", false, false, false, "real time signal 12"); + AddSignal(46, "SIGRTMIN+13", false, false, false, "real time signal 13"); + AddSignal(47, "SIGRTMIN+14", false, false, false, "real time signal 14"); + AddSignal(48, "SIGRTMIN+15", false, false, false, "real time signal 15"); + AddSignal(49, "SIGRTMIN-14", false, false, false, "real time signal 16"); + AddSignal(50, "SIGRTMAX-13", false, false, false, "real time signal 17"); + AddSignal(51, "SIGRTMAX-12", false, false, false, "real time signal 18"); + AddSignal(52, "SIGRTMAX-11", false, false, false, "real time signal 19"); + AddSignal(53, "SIGRTMAX-10", false, false, false, "real time signal 20"); + AddSignal(54, "SIGRTMAX-9", false, false, false, "real time signal 21"); + AddSignal(55, "SIGRTMAX-8", false, false, false, "real time signal 22"); + AddSignal(56, "SIGRTMAX-7", false, false, false, "real time signal 23"); + AddSignal(57, "SIGRTMAX-6", false, false, false, "real time signal 24"); + AddSignal(58, "SIGRTMAX-5", false, false, false, "real time signal 25"); + AddSignal(59, "SIGRTMAX-4", false, false, false, "real time signal 26"); + AddSignal(60, "SIGRTMAX-3", false, false, false, "real time signal 27"); + AddSignal(61, "SIGRTMAX-2", false, false, false, "real time signal 28"); + AddSignal(62, "SIGRTMAX-1", false, false, false, "real time signal 29"); + AddSignal(63, "SIGRTMAX", false, false, false, "real time signal 30"); } diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp index 52ace5602f49..64a697ff53c8 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp @@ -17,12 +17,12 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/Log.h" #include "llvm/Support/Compiler.h" #include "Plugins/Process/Utility/InstructionUtils.h" diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp index 64983a2404e6..0c36f1a8346c 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp @@ -19,14 +19,14 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/Log.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp index f42fb00b375f..c818fad9ac0e 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp @@ -12,12 +12,12 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/Log.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp index 7c0bafa68f9e..50e7292f86b1 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp @@ -14,12 +14,12 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/Log.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" diff --git a/source/Plugins/Process/Utility/RegisterContextDummy.cpp b/source/Plugins/Process/Utility/RegisterContextDummy.cpp index 93bb09b810ac..dd6ca92a74ee 100644 --- a/source/Plugins/Process/Utility/RegisterContextDummy.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDummy.cpp @@ -10,8 +10,6 @@ #include "lldb/Core/Address.h" #include "lldb/Core/AddressRange.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Value.h" @@ -28,6 +26,8 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Log.h" #include "lldb/lldb-private.h" #include "RegisterContextDummy.h" diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp deleted file mode 100644 index fecfae0b7e66..000000000000 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp +++ /dev/null @@ -1,97 +0,0 @@ -//===-- RegisterContextFreeBSD_arm.cpp -------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===---------------------------------------------------------------------===// - -#include <cassert> -#include <stddef.h> -#include <vector> - -#include "lldb/lldb-defines.h" -#include "llvm/Support/Compiler.h" - -#include "RegisterContextFreeBSD_arm.h" - -using namespace lldb; -using namespace lldb_private; - -// Based on RegisterContextLinux_arm.cpp and -// http://svnweb.freebsd.org/base/head/sys/arm/include/reg.h -#define GPR_OFFSET(idx) ((idx)*4) -#define FPU_OFFSET(idx) ((idx)*4 + sizeof(RegisterContextFreeBSD_arm::GPR)) -#define FPSCR_OFFSET \ - (LLVM_EXTENSION offsetof(RegisterContextFreeBSD_arm::FPU, fpscr) + \ - sizeof(RegisterContextFreeBSD_arm::GPR)) -#define EXC_OFFSET(idx) \ - ((idx)*4 + sizeof(RegisterContextFreeBSD_arm::GPR) + \ - sizeof(RegisterContextFreeBSD_arm::FPU)) -#define DBG_OFFSET(reg) \ - ((LLVM_EXTENSION offsetof(RegisterContextFreeBSD_arm::DBG, reg) + \ - sizeof(RegisterContextFreeBSD_arm::GPR) + \ - sizeof(RegisterContextFreeBSD_arm::FPU) + \ - sizeof(RegisterContextFreeBSD_arm::EXC))) - -#define DEFINE_DBG(reg, i) \ - #reg, NULL, sizeof(((RegisterContextFreeBSD_arm::DBG *) NULL)->reg[i]), \ - DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, \ - {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - dbg_##reg##i }, \ - NULL, NULL, NULL, 0 -#define REG_CONTEXT_SIZE \ - (sizeof(RegisterContextFreeBSD_arm::GPR) + \ - sizeof(RegisterContextFreeBSD_arm::FPU) + \ - sizeof(RegisterContextFreeBSD_arm::EXC)) - -//----------------------------------------------------------------------------- -// Include RegisterInfos_arm to declare our g_register_infos_arm structure. -//----------------------------------------------------------------------------- -#define DECLARE_REGISTER_INFOS_ARM_STRUCT -#include "RegisterInfos_arm.h" -#undef DECLARE_REGISTER_INFOS_ARM_STRUCT - -static const lldb_private::RegisterInfo * -GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { - switch (target_arch.GetMachine()) { - case llvm::Triple::arm: - return g_register_infos_arm; - default: - assert(false && "Unhandled target architecture."); - return NULL; - } -} - -static uint32_t -GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { - switch (target_arch.GetMachine()) { - case llvm::Triple::arm: - return static_cast<uint32_t>(sizeof(g_register_infos_arm) / - sizeof(g_register_infos_arm[0])); - default: - assert(false && "Unhandled target architecture."); - return 0; - } -} - -RegisterContextFreeBSD_arm::RegisterContextFreeBSD_arm( - const lldb_private::ArchSpec &target_arch) - : lldb_private::RegisterInfoInterface(target_arch), - m_register_info_p(GetRegisterInfoPtr(target_arch)), - m_register_info_count(GetRegisterInfoCount(target_arch)) {} - -size_t RegisterContextFreeBSD_arm::GetGPRSize() const { - return sizeof(struct RegisterContextFreeBSD_arm::GPR); -} - -const lldb_private::RegisterInfo * -RegisterContextFreeBSD_arm::GetRegisterInfo() const { - return m_register_info_p; -} - -uint32_t RegisterContextFreeBSD_arm::GetRegisterCount() const { - return m_register_info_count; -} diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp index c114cfb829f5..55a72b2a31b4 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.cpp @@ -9,11 +9,33 @@ #include "RegisterContextFreeBSD_mips64.h" #include "RegisterContextPOSIX_mips64.h" +#include "lldb-mips-freebsd-register-enums.h" #include <vector> using namespace lldb_private; using namespace lldb; +static const uint32_t g_gpr_regnums[] = { + gpr_zero_mips64, gpr_r1_mips64, gpr_r2_mips64, gpr_r3_mips64, + gpr_r4_mips64, gpr_r5_mips64, gpr_r6_mips64, gpr_r7_mips64, + gpr_r8_mips64, gpr_r9_mips64, gpr_r10_mips64, gpr_r11_mips64, + gpr_r12_mips64, gpr_r13_mips64, gpr_r14_mips64, gpr_r15_mips64, + gpr_r16_mips64, gpr_r17_mips64, gpr_r18_mips64, gpr_r19_mips64, + gpr_r20_mips64, gpr_r21_mips64, gpr_r22_mips64, gpr_r23_mips64, + gpr_r24_mips64, gpr_r25_mips64, gpr_r26_mips64, gpr_r27_mips64, + gpr_gp_mips64, gpr_sp_mips64, gpr_r30_mips64, gpr_ra_mips64, + gpr_sr_mips64, gpr_mullo_mips64, gpr_mulhi_mips64, gpr_badvaddr_mips64, + gpr_cause_mips64, gpr_pc_mips64, gpr_ic_mips64, gpr_dummy_mips64}; + +// Number of register sets provided by this context. +constexpr size_t k_num_register_sets = 1; + +static const RegisterSet g_reg_sets_mips64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_mips64, + g_gpr_regnums}, +}; + + // http://svnweb.freebsd.org/base/head/sys/mips/include/regnum.h typedef struct _GPR { uint64_t zero; @@ -74,6 +96,19 @@ size_t RegisterContextFreeBSD_mips64::GetGPRSize() const { return sizeof(GPR_freebsd_mips); } +const RegisterSet * +RegisterContextFreeBSD_mips64::GetRegisterSet(size_t set) const { + // Check if RegisterSet is available + if (set < k_num_register_sets) + return &g_reg_sets_mips64[set]; + return nullptr; +} + +size_t +RegisterContextFreeBSD_mips64::GetRegisterSetCount() const { + return k_num_register_sets; +} + const RegisterInfo *RegisterContextFreeBSD_mips64::GetRegisterInfo() const { assert(m_target_arch.GetCore() == ArchSpec::eCore_mips64); return g_register_infos_mips64; diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h index 043e638758da..5e5de71ad72e 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h @@ -19,6 +19,10 @@ public: size_t GetGPRSize() const override; + const lldb_private::RegisterSet *GetRegisterSet(size_t set) const; + + size_t GetRegisterSetCount() const; + const lldb_private::RegisterInfo *GetRegisterInfo() const override; uint32_t GetRegisterCount() const override; diff --git a/source/Plugins/Process/Utility/RegisterContextHistory.cpp b/source/Plugins/Process/Utility/RegisterContextHistory.cpp index 0fc47fcd8e3a..cc0d696b338a 100644 --- a/source/Plugins/Process/Utility/RegisterContextHistory.cpp +++ b/source/Plugins/Process/Utility/RegisterContextHistory.cpp @@ -10,8 +10,6 @@ #include "lldb/Core/Address.h" #include "lldb/Core/AddressRange.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Value.h" @@ -28,6 +26,8 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Log.h" #include "lldb/lldb-private.h" #include "RegisterContextHistory.h" diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index ba84c40e9767..485a39e6c9a5 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -9,8 +9,6 @@ #include "lldb/Core/Address.h" #include "lldb/Core/AddressRange.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Value.h" @@ -31,6 +29,8 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Log.h" #include "lldb/lldb-private.h" #include "RegisterContextLLDB.h" @@ -2015,7 +2015,18 @@ bool RegisterContextLLDB::GetStartPC(addr_t &start_pc) { return false; if (!m_start_pc.IsValid()) { - return ReadPC(start_pc); + bool read_successfully = ReadPC (start_pc); + if (read_successfully) + { + ProcessSP process_sp (m_thread.GetProcess()); + if (process_sp) + { + ABI *abi = process_sp->GetABI().get(); + if (abi) + start_pc = abi->FixCodeAddress(start_pc); + } + } + return read_successfully; } start_pc = m_start_pc.GetLoadAddress(CalculateTarget().get()); return true; @@ -2044,9 +2055,16 @@ bool RegisterContextLLDB::ReadPC(addr_t &pc) { if (m_all_registers_available == false && above_trap_handler == false && (pc == 0 || pc == 1)) { return false; - } else { - return true; } + + ProcessSP process_sp (m_thread.GetProcess()); + if (process_sp) + { + ABI *abi = process_sp->GetABI().get(); + if (abi) + pc = abi->FixCodeAddress(pc); + } + return true; } else { return false; } diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h index cb22eedd560a..7e9e77dcf06d 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -21,7 +21,7 @@ #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/RegisterContext.h" -#include "lldb/Utility/RegisterNumber.h" +#include "lldb/Target/RegisterNumber.h" #include "lldb/lldb-private.h" namespace lldb_private { diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm.h b/source/Plugins/Process/Utility/RegisterContextLinux_arm.h deleted file mode 100644 index 9065bc0e08d2..000000000000 --- a/source/Plugins/Process/Utility/RegisterContextLinux_arm.h +++ /dev/null @@ -1,62 +0,0 @@ -//===-- RegisterContextLinux_arm.h -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextLinux_arm_h_ -#define liblldb_RegisterContextLinux_arm_h_ - -#include "RegisterInfoInterface.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/lldb-private.h" - -class RegisterContextLinux_arm : public lldb_private::RegisterInfoInterface { -public: - struct GPR { - uint32_t r[16]; // R0-R15 - uint32_t cpsr; // CPSR - }; - - struct QReg { - uint8_t bytes[16]; - }; - - struct FPU { - union { - uint32_t s[32]; - uint64_t d[32]; - QReg q[16]; // the 128-bit NEON registers - } floats; - uint32_t fpscr; - }; - struct EXC { - uint32_t exception; - uint32_t fsr; /* Fault status */ - uint32_t far; /* Virtual Fault Address */ - }; - - struct DBG { - uint32_t bvr[16]; - uint32_t bcr[16]; - uint32_t wvr[16]; - uint32_t wcr[16]; - }; - - RegisterContextLinux_arm(const lldb_private::ArchSpec &target_arch); - - size_t GetGPRSize() const override; - - const lldb_private::RegisterInfo *GetRegisterInfo() const override; - - uint32_t GetRegisterCount() const override; - -private: - const lldb_private::RegisterInfo *m_register_info_p; - uint32_t m_register_info_count; -}; - -#endif // liblldb_RegisterContextLinux_arm_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp index 982eefea9ba6..7b16531dcc89 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp @@ -29,6 +29,73 @@ using namespace lldb; #include "RegisterInfos_mips.h" #undef DECLARE_REGISTER_INFOS_MIPS_STRUCT +// mips general purpose registers. +const uint32_t g_gp_regnums_mips[] = { + gpr_zero_mips, gpr_r1_mips, gpr_r2_mips, gpr_r3_mips, + gpr_r4_mips, gpr_r5_mips, gpr_r6_mips, gpr_r7_mips, + gpr_r8_mips, gpr_r9_mips, gpr_r10_mips, gpr_r11_mips, + gpr_r12_mips, gpr_r13_mips, gpr_r14_mips, gpr_r15_mips, + gpr_r16_mips, gpr_r17_mips, gpr_r18_mips, gpr_r19_mips, + gpr_r20_mips, gpr_r21_mips, gpr_r22_mips, gpr_r23_mips, + gpr_r24_mips, gpr_r25_mips, gpr_r26_mips, gpr_r27_mips, + gpr_gp_mips, gpr_sp_mips, gpr_r30_mips, gpr_ra_mips, + gpr_sr_mips, gpr_mullo_mips, gpr_mulhi_mips, gpr_badvaddr_mips, + gpr_cause_mips, gpr_pc_mips, gpr_config5_mips, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_gp_regnums_mips) / sizeof(g_gp_regnums_mips[0])) - 1 == + k_num_gpr_registers_mips, + "g_gp_regnums_mips has wrong number of register infos"); +// mips floating point registers. +const uint32_t g_fp_regnums_mips[] = { + fpr_f0_mips, fpr_f1_mips, fpr_f2_mips, fpr_f3_mips, + fpr_f4_mips, fpr_f5_mips, fpr_f6_mips, fpr_f7_mips, + fpr_f8_mips, fpr_f9_mips, fpr_f10_mips, fpr_f11_mips, + fpr_f12_mips, fpr_f13_mips, fpr_f14_mips, fpr_f15_mips, + fpr_f16_mips, fpr_f17_mips, fpr_f18_mips, fpr_f19_mips, + fpr_f20_mips, fpr_f21_mips, fpr_f22_mips, fpr_f23_mips, + fpr_f24_mips, fpr_f25_mips, fpr_f26_mips, fpr_f27_mips, + fpr_f28_mips, fpr_f29_mips, fpr_f30_mips, fpr_f31_mips, + fpr_fcsr_mips, fpr_fir_mips, fpr_config5_mips, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_fp_regnums_mips) / sizeof(g_fp_regnums_mips[0])) - 1 == + k_num_fpr_registers_mips, + "g_fp_regnums_mips has wrong number of register infos"); + +// mips MSA registers. +const uint32_t g_msa_regnums_mips[] = { + msa_w0_mips, msa_w1_mips, msa_w2_mips, msa_w3_mips, + msa_w4_mips, msa_w5_mips, msa_w6_mips, msa_w7_mips, + msa_w8_mips, msa_w9_mips, msa_w10_mips, msa_w11_mips, + msa_w12_mips, msa_w13_mips, msa_w14_mips, msa_w15_mips, + msa_w16_mips, msa_w17_mips, msa_w18_mips, msa_w19_mips, + msa_w20_mips, msa_w21_mips, msa_w22_mips, msa_w23_mips, + msa_w24_mips, msa_w25_mips, msa_w26_mips, msa_w27_mips, + msa_w28_mips, msa_w29_mips, msa_w30_mips, msa_w31_mips, + msa_fcsr_mips, msa_fir_mips, msa_mcsr_mips, msa_mir_mips, + msa_config5_mips, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_msa_regnums_mips) / sizeof(g_msa_regnums_mips[0])) - + 1 == + k_num_msa_registers_mips, + "g_msa_regnums_mips has wrong number of register infos"); + +// Number of register sets provided by this context. +constexpr size_t k_num_register_sets = 3; + +// Register sets for mips. +static const RegisterSet g_reg_sets_mips[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_mips, + g_gp_regnums_mips}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_mips, + g_fp_regnums_mips}, + {"MSA Registers", "msa", k_num_msa_registers_mips, g_msa_regnums_mips}}; + uint32_t GetUserRegisterInfoCount(bool msa_present) { if (msa_present) return static_cast<uint32_t>(k_num_user_registers_mips); @@ -56,6 +123,25 @@ const RegisterInfo *RegisterContextLinux_mips::GetRegisterInfo() const { } } +const RegisterSet * +RegisterContextLinux_mips::GetRegisterSet(size_t set) const { + if (set >= k_num_register_sets) + return nullptr; + switch (m_target_arch.GetMachine()) { + case llvm::Triple::mips: + case llvm::Triple::mipsel: + return &g_reg_sets_mips[set]; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } +} + +size_t +RegisterContextLinux_mips::GetRegisterSetCount() const { + return k_num_register_sets; +} + uint32_t RegisterContextLinux_mips::GetRegisterCount() const { return static_cast<uint32_t>(sizeof(g_register_infos_mips) / sizeof(g_register_infos_mips[0])); diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips.h b/source/Plugins/Process/Utility/RegisterContextLinux_mips.h index cba4ee6cd2b0..a16c4ecd15f8 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_mips.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips.h @@ -22,6 +22,10 @@ public: const lldb_private::RegisterInfo *GetRegisterInfo() const override; + const lldb_private::RegisterSet *GetRegisterSet(size_t set) const; + + size_t GetRegisterSetCount() const; + uint32_t GetRegisterCount() const override; uint32_t GetUserRegisterCount() const override; diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp index c40f69492624..1bb16c701126 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp @@ -7,7 +7,6 @@ // //===---------------------------------------------------------------------===// -#if defined(__mips__) #include <stddef.h> #include <vector> @@ -41,6 +40,101 @@ using namespace lldb_private; #include "RegisterInfos_mips.h" #undef DECLARE_REGISTER_INFOS_MIPS_STRUCT +// mips64 general purpose registers. +const uint32_t g_gp_regnums_mips64[] = { + gpr_zero_mips64, gpr_r1_mips64, gpr_r2_mips64, + gpr_r3_mips64, gpr_r4_mips64, gpr_r5_mips64, + gpr_r6_mips64, gpr_r7_mips64, gpr_r8_mips64, + gpr_r9_mips64, gpr_r10_mips64, gpr_r11_mips64, + gpr_r12_mips64, gpr_r13_mips64, gpr_r14_mips64, + gpr_r15_mips64, gpr_r16_mips64, gpr_r17_mips64, + gpr_r18_mips64, gpr_r19_mips64, gpr_r20_mips64, + gpr_r21_mips64, gpr_r22_mips64, gpr_r23_mips64, + gpr_r24_mips64, gpr_r25_mips64, gpr_r26_mips64, + gpr_r27_mips64, gpr_gp_mips64, gpr_sp_mips64, + gpr_r30_mips64, gpr_ra_mips64, gpr_sr_mips64, + gpr_mullo_mips64, gpr_mulhi_mips64, gpr_badvaddr_mips64, + gpr_cause_mips64, gpr_pc_mips64, gpr_config5_mips64, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_gp_regnums_mips64) / sizeof(g_gp_regnums_mips64[0])) - + 1 == + k_num_gpr_registers_mips64, + "g_gp_regnums_mips64 has wrong number of register infos"); + +// mips64 floating point registers. +const uint32_t g_fp_regnums_mips64[] = { + fpr_f0_mips64, fpr_f1_mips64, fpr_f2_mips64, fpr_f3_mips64, + fpr_f4_mips64, fpr_f5_mips64, fpr_f6_mips64, fpr_f7_mips64, + fpr_f8_mips64, fpr_f9_mips64, fpr_f10_mips64, fpr_f11_mips64, + fpr_f12_mips64, fpr_f13_mips64, fpr_f14_mips64, fpr_f15_mips64, + fpr_f16_mips64, fpr_f17_mips64, fpr_f18_mips64, fpr_f19_mips64, + fpr_f20_mips64, fpr_f21_mips64, fpr_f22_mips64, fpr_f23_mips64, + fpr_f24_mips64, fpr_f25_mips64, fpr_f26_mips64, fpr_f27_mips64, + fpr_f28_mips64, fpr_f29_mips64, fpr_f30_mips64, fpr_f31_mips64, + fpr_fcsr_mips64, fpr_fir_mips64, fpr_config5_mips64, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_fp_regnums_mips64) / sizeof(g_fp_regnums_mips64[0])) - + 1 == + k_num_fpr_registers_mips64, + "g_fp_regnums_mips64 has wrong number of register infos"); + +// mips64 MSA registers. +const uint32_t g_msa_regnums_mips64[] = { + msa_w0_mips64, msa_w1_mips64, msa_w2_mips64, msa_w3_mips64, + msa_w4_mips64, msa_w5_mips64, msa_w6_mips64, msa_w7_mips64, + msa_w8_mips64, msa_w9_mips64, msa_w10_mips64, msa_w11_mips64, + msa_w12_mips64, msa_w13_mips64, msa_w14_mips64, msa_w15_mips64, + msa_w16_mips64, msa_w17_mips64, msa_w18_mips64, msa_w19_mips64, + msa_w20_mips64, msa_w21_mips64, msa_w22_mips64, msa_w23_mips64, + msa_w24_mips64, msa_w25_mips64, msa_w26_mips64, msa_w27_mips64, + msa_w28_mips64, msa_w29_mips64, msa_w30_mips64, msa_w31_mips64, + msa_fcsr_mips64, msa_fir_mips64, msa_mcsr_mips64, msa_mir_mips64, + msa_config5_mips64, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static_assert((sizeof(g_msa_regnums_mips64) / sizeof(g_msa_regnums_mips64[0])) - + 1 == + k_num_msa_registers_mips64, + "g_msa_regnums_mips64 has wrong number of register infos"); + +// Number of register sets provided by this context. +constexpr size_t k_num_register_sets = 3; + +// Register sets for mips64. +static const RegisterSet g_reg_sets_mips64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_mips64, + g_gp_regnums_mips64}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_mips64, + g_fp_regnums_mips64}, + {"MSA Registers", "msa", k_num_msa_registers_mips64, g_msa_regnums_mips64}, +}; + +const RegisterSet * +RegisterContextLinux_mips64::GetRegisterSet(size_t set) const { + if (set >= k_num_register_sets) + return nullptr; + + switch (m_target_arch.GetMachine()) { + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + return &g_reg_sets_mips64[set]; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } + return nullptr; +} + +size_t +RegisterContextLinux_mips64::GetRegisterSetCount() const { + return k_num_register_sets; +} + static const RegisterInfo *GetRegisterInfoPtr(const ArchSpec &target_arch) { switch (target_arch.GetMachine()) { case llvm::Triple::mips64: @@ -116,4 +210,3 @@ uint32_t RegisterContextLinux_mips64::GetUserRegisterCount() const { return m_user_register_count; } -#endif diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h index 9669b0d84997..d3ca9d75300e 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#if defined(__mips__) - #ifndef liblldb_RegisterContextLinux_mips64_H_ #define liblldb_RegisterContextLinux_mips64_H_ @@ -24,6 +22,10 @@ public: const lldb_private::RegisterInfo *GetRegisterInfo() const override; + const lldb_private::RegisterSet *GetRegisterSet(size_t set) const; + + size_t GetRegisterSetCount() const; + uint32_t GetRegisterCount() const override; uint32_t GetUserRegisterCount() const override; @@ -36,4 +38,3 @@ private: #endif -#endif diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp index 95b106d68bb3..2d24bdaed2cd 100644 --- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp +++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp @@ -12,12 +12,12 @@ // C Includes // C++ Includes // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Core/StreamString.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/StreamString.h" // Project includes #include "Utility/StringExtractorGDBRemote.h" diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/source/Plugins/Process/Utility/RegisterContextMemory.cpp index 57966e1729a6..eed5eec8fae8 100644 --- a/source/Plugins/Process/Utility/RegisterContextMemory.cpp +++ b/source/Plugins/Process/Utility/RegisterContextMemory.cpp @@ -14,11 +14,11 @@ // Other libraries and framework includes // Project includes #include "DynamicRegisterInfo.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Error.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.h b/source/Plugins/Process/Utility/RegisterContextMemory.h index 55de0412b094..cad1592af5ba 100644 --- a/source/Plugins/Process/Utility/RegisterContextMemory.h +++ b/source/Plugins/Process/Utility/RegisterContextMemory.h @@ -16,8 +16,8 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/DataExtractor.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/DataExtractor.h" #include "lldb/lldb-private.h" class DynamicRegisterInfo; diff --git a/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp index 4f64a8c4f321..ca7a0139ccc0 100644 --- a/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp @@ -47,10 +47,14 @@ typedef struct _GPR { uint64_t ss; /* 25 */ } GPR; -/* - * As of NetBSD-7.99.25 there is no support for debug registers - * https://en.wikipedia.org/wiki/X86_debug_register - */ +struct DBG { + uint64_t dr[16]; /* debug registers */ + /* Index 0-3: debug address registers */ + /* Index 4-5: reserved */ + /* Index 6: debug status */ + /* Index 7: debug control */ + /* Index 8-15: reserved */ +}; /* * src/sys/arch/amd64/include/mcontext.h @@ -66,276 +70,21 @@ struct UserArea { GPR gpr; uint64_t mc_tlsbase; FPR fpr; + DBG dbg; }; -//--------------------------------------------------------------------------- -// Cherry-pick parts of RegisterInfos_x86_64.h, without debug registers -//--------------------------------------------------------------------------- -// Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname)) - -// Computes the offset of the given FPR in the extended data area. -#define FPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(FXSAVE, regname)) - -// Computes the offset of the YMM register assembled from register halves. -// Based on DNBArchImplX86_64.cpp from debugserver -#define YMM_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + (32 * reg_index)) - -// Number of bytes needed to represent a FPR. -#define FPR_SIZE(reg) sizeof(((FXSAVE *)nullptr)->reg) - -// Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((MMSReg *)nullptr)->bytes) - -// Number of bytes needed to represent an XMM register. -#define XMM_SIZE sizeof(XMMReg) - -// Number of bytes needed to represent a YMM register. -#define YMM_SIZE sizeof(YMMReg) - -// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB - -// Note that the size and offset will be updated by platform-specific classes. -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { \ - #reg, alt, sizeof(((GPR *)nullptr)->reg), \ - GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ - {kind1, kind2, kind3, kind4, \ - lldb_##reg##_x86_64 }, \ - nullptr, nullptr, nullptr, 0 \ - } - -#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ - { \ - #name, nullptr, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, eFormatHex, \ - {kind1, kind2, kind3, kind4, \ - lldb_##name##_x86_64 }, \ - nullptr, nullptr, nullptr, 0 \ - } - -#define DEFINE_FP_ST(reg, i) \ - { \ - #reg #i, nullptr, FP_SIZE, \ - LLVM_EXTENSION FPR_OFFSET( \ - stmm[i]), eEncodingVector, eFormatVectorOfUInt8, \ - {dwarf_st##i##_x86_64, dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM, lldb_st##i##_x86_64 }, \ - nullptr, nullptr, nullptr, 0 \ - } - -#define DEFINE_FP_MM(reg, i) \ - { \ - #reg #i, nullptr, sizeof(uint64_t), \ - LLVM_EXTENSION FPR_OFFSET( \ - stmm[i]), eEncodingUint, eFormatHex, \ - {dwarf_mm##i##_x86_64, dwarf_mm##i##_x86_64, \ - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - lldb_mm##i##_x86_64 }, \ - nullptr, nullptr, nullptr, 0 \ - } - -#define DEFINE_XMM(reg, i) \ - { \ - #reg #i, nullptr, XMM_SIZE, \ - LLVM_EXTENSION FPR_OFFSET( \ - reg[i]), eEncodingVector, eFormatVectorOfUInt8, \ - {dwarf_##reg##i##_x86_64, dwarf_##reg##i##_x86_64, \ - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - lldb_##reg##i##_x86_64 }, \ - nullptr, nullptr, nullptr, 0 \ - } - -#define DEFINE_YMM(reg, i) \ - { \ - #reg #i, nullptr, YMM_SIZE, \ - LLVM_EXTENSION YMM_OFFSET(i), eEncodingVector, eFormatVectorOfUInt8, \ - {dwarf_##reg##i##h_x86_64, \ - dwarf_##reg##i##h_x86_64, \ - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - lldb_##reg##i##_x86_64 }, \ - nullptr, nullptr, nullptr, 0 \ - } +#define DR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, dbg) + \ + LLVM_EXTENSION offsetof(DBG, dr[reg_index])) -#define DEFINE_GPR_PSEUDO_32(reg32, reg64) \ - { \ - #reg32, nullptr, 4, \ - GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ - {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - lldb_##reg32##_x86_64 }, \ - RegisterContextPOSIX_x86::g_contained_##reg64, \ - RegisterContextPOSIX_x86::g_invalidate_##reg64, nullptr, 0 \ - } - -#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ - { \ - #reg16, nullptr, 2, \ - GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ - {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - lldb_##reg16##_x86_64 }, \ - RegisterContextPOSIX_x86::g_contained_##reg64, \ - RegisterContextPOSIX_x86::g_invalidate_##reg64, nullptr, 0 \ - } - -#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ - { \ - #reg8, nullptr, 1, GPR_OFFSET(reg64) + 1, eEncodingUint, eFormatHex, \ - {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - lldb_##reg8##_x86_64 }, \ - RegisterContextPOSIX_x86::g_contained_##reg64, \ - RegisterContextPOSIX_x86::g_invalidate_##reg64,\ - nullptr, 0 \ - } - -#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ - { \ - #reg8, nullptr, 1, GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ - {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - lldb_##reg8##_x86_64 }, \ - RegisterContextPOSIX_x86::g_contained_##reg64, \ - RegisterContextPOSIX_x86::g_invalidate_##reg64,\ - nullptr, 0 \ - } - -static RegisterInfo g_register_infos_x86_64[] = { - // General purpose registers. EH_Frame, DWARF, - // Generic, Process Plugin - DEFINE_GPR(rax, nullptr, dwarf_rax_x86_64, dwarf_rax_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(rbx, nullptr, dwarf_rbx_x86_64, dwarf_rbx_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(rcx, "arg4", dwarf_rcx_x86_64, dwarf_rcx_x86_64, - LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), - DEFINE_GPR(rdx, "arg3", dwarf_rdx_x86_64, dwarf_rdx_x86_64, - LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), - DEFINE_GPR(rdi, "arg1", dwarf_rdi_x86_64, dwarf_rdi_x86_64, - LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), - DEFINE_GPR(rsi, "arg2", dwarf_rsi_x86_64, dwarf_rsi_x86_64, - LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), - DEFINE_GPR(rbp, "fp", dwarf_rbp_x86_64, dwarf_rbp_x86_64, - LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), - DEFINE_GPR(rsp, "sp", dwarf_rsp_x86_64, dwarf_rsp_x86_64, - LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), - DEFINE_GPR(r8, "arg5", dwarf_r8_x86_64, dwarf_r8_x86_64, - LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), - DEFINE_GPR(r9, "arg6", dwarf_r9_x86_64, dwarf_r9_x86_64, - LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), - DEFINE_GPR(r10, nullptr, dwarf_r10_x86_64, dwarf_r10_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r11, nullptr, dwarf_r11_x86_64, dwarf_r11_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r12, nullptr, dwarf_r12_x86_64, dwarf_r12_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r13, nullptr, dwarf_r13_x86_64, dwarf_r13_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r14, nullptr, dwarf_r14_x86_64, dwarf_r14_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(r15, nullptr, dwarf_r15_x86_64, dwarf_r15_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(rip, "pc", dwarf_rip_x86_64, dwarf_rip_x86_64, - LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), - DEFINE_GPR(rflags, "flags", dwarf_rflags_x86_64, dwarf_rflags_x86_64, - LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), - DEFINE_GPR(cs, nullptr, dwarf_cs_x86_64, dwarf_cs_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - - DEFINE_GPR_PSEUDO_32(eax, rax), DEFINE_GPR_PSEUDO_32(ebx, rbx), - DEFINE_GPR_PSEUDO_32(ecx, rcx), DEFINE_GPR_PSEUDO_32(edx, rdx), - DEFINE_GPR_PSEUDO_32(edi, rdi), DEFINE_GPR_PSEUDO_32(esi, rsi), - DEFINE_GPR_PSEUDO_32(ebp, rbp), DEFINE_GPR_PSEUDO_32(esp, rsp), - DEFINE_GPR_PSEUDO_32(r8d, r8), DEFINE_GPR_PSEUDO_32(r9d, r9), - DEFINE_GPR_PSEUDO_32(r10d, r10), DEFINE_GPR_PSEUDO_32(r11d, r11), - DEFINE_GPR_PSEUDO_32(r12d, r12), DEFINE_GPR_PSEUDO_32(r13d, r13), - DEFINE_GPR_PSEUDO_32(r14d, r14), DEFINE_GPR_PSEUDO_32(r15d, r15), - DEFINE_GPR_PSEUDO_16(ax, rax), DEFINE_GPR_PSEUDO_16(bx, rbx), - DEFINE_GPR_PSEUDO_16(cx, rcx), DEFINE_GPR_PSEUDO_16(dx, rdx), - DEFINE_GPR_PSEUDO_16(di, rdi), DEFINE_GPR_PSEUDO_16(si, rsi), - DEFINE_GPR_PSEUDO_16(bp, rbp), DEFINE_GPR_PSEUDO_16(sp, rsp), - DEFINE_GPR_PSEUDO_16(r8w, r8), DEFINE_GPR_PSEUDO_16(r9w, r9), - DEFINE_GPR_PSEUDO_16(r10w, r10), DEFINE_GPR_PSEUDO_16(r11w, r11), - DEFINE_GPR_PSEUDO_16(r12w, r12), DEFINE_GPR_PSEUDO_16(r13w, r13), - DEFINE_GPR_PSEUDO_16(r14w, r14), DEFINE_GPR_PSEUDO_16(r15w, r15), - DEFINE_GPR_PSEUDO_8H(ah, rax), DEFINE_GPR_PSEUDO_8H(bh, rbx), - DEFINE_GPR_PSEUDO_8H(ch, rcx), DEFINE_GPR_PSEUDO_8H(dh, rdx), - DEFINE_GPR_PSEUDO_8L(al, rax), DEFINE_GPR_PSEUDO_8L(bl, rbx), - DEFINE_GPR_PSEUDO_8L(cl, rcx), DEFINE_GPR_PSEUDO_8L(dl, rdx), - DEFINE_GPR_PSEUDO_8L(dil, rdi), DEFINE_GPR_PSEUDO_8L(sil, rsi), - DEFINE_GPR_PSEUDO_8L(bpl, rbp), DEFINE_GPR_PSEUDO_8L(spl, rsp), - DEFINE_GPR_PSEUDO_8L(r8l, r8), DEFINE_GPR_PSEUDO_8L(r9l, r9), - DEFINE_GPR_PSEUDO_8L(r10l, r10), DEFINE_GPR_PSEUDO_8L(r11l, r11), - DEFINE_GPR_PSEUDO_8L(r12l, r12), DEFINE_GPR_PSEUDO_8L(r13l, r13), - DEFINE_GPR_PSEUDO_8L(r14l, r14), DEFINE_GPR_PSEUDO_8L(r15l, r15), - - // i387 Floating point registers. EH_frame, - // DWARF, Generic, Process Plugin - DEFINE_FPR(fctrl, fctrl, dwarf_fctrl_x86_64, dwarf_fctrl_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fstat, fstat, dwarf_fstat_x86_64, dwarf_fstat_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(mxcsr, mxcsr, dwarf_mxcsr_x86_64, dwarf_mxcsr_x86_64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - - // FP registers. - DEFINE_FP_ST(st, 0), DEFINE_FP_ST(st, 1), DEFINE_FP_ST(st, 2), - DEFINE_FP_ST(st, 3), DEFINE_FP_ST(st, 4), DEFINE_FP_ST(st, 5), - DEFINE_FP_ST(st, 6), DEFINE_FP_ST(st, 7), DEFINE_FP_MM(mm, 0), - DEFINE_FP_MM(mm, 1), DEFINE_FP_MM(mm, 2), DEFINE_FP_MM(mm, 3), - DEFINE_FP_MM(mm, 4), DEFINE_FP_MM(mm, 5), DEFINE_FP_MM(mm, 6), - DEFINE_FP_MM(mm, 7), - - // XMM registers - DEFINE_XMM(xmm, 0), DEFINE_XMM(xmm, 1), DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), DEFINE_XMM(xmm, 4), DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), DEFINE_XMM(xmm, 7), DEFINE_XMM(xmm, 8), - DEFINE_XMM(xmm, 9), DEFINE_XMM(xmm, 10), DEFINE_XMM(xmm, 11), - DEFINE_XMM(xmm, 12), DEFINE_XMM(xmm, 13), DEFINE_XMM(xmm, 14), - DEFINE_XMM(xmm, 15), - - // Copy of YMM registers assembled from xmm and ymmh - DEFINE_YMM(ymm, 0), DEFINE_YMM(ymm, 1), DEFINE_YMM(ymm, 2), - DEFINE_YMM(ymm, 3), DEFINE_YMM(ymm, 4), DEFINE_YMM(ymm, 5), - DEFINE_YMM(ymm, 6), DEFINE_YMM(ymm, 7), DEFINE_YMM(ymm, 8), - DEFINE_YMM(ymm, 9), DEFINE_YMM(ymm, 10), DEFINE_YMM(ymm, 11), - DEFINE_YMM(ymm, 12), DEFINE_YMM(ymm, 13), DEFINE_YMM(ymm, 14), - DEFINE_YMM(ymm, 15), -}; //--------------------------------------------------------------------------- -// End of cherry-pick of RegisterInfos_x86_64.h +// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 +// structure. //--------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_X86_64_STRUCT +#include "RegisterInfos_x86_64.h" +#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT static const RegisterInfo * PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { diff --git a/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp b/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp new file mode 100644 index 000000000000..1f958105b10b --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp @@ -0,0 +1,80 @@ +//===-- RegisterContextOpenBSD_i386.cpp ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include "RegisterContextOpenBSD_i386.h" +#include "RegisterContextPOSIX_x86.h" + +using namespace lldb_private; +using namespace lldb; + +// /usr/include/machine/reg.h +struct GPR { + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t eip; + uint32_t eflags; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; +}; + +struct dbreg { + uint32_t dr[8]; /* debug registers */ + /* Index 0-3: debug address registers */ + /* Index 4-5: reserved */ + /* Index 6: debug status */ + /* Index 7: debug control */ +}; + +using FPR_i386 = FXSAVE; + +struct UserArea { + GPR gpr; + FPR_i386 i387; +}; + +#define DR_SIZE sizeof(uint32_t) +#define DR_OFFSET(reg_index) (LLVM_EXTENSION offsetof(dbreg, dr[reg_index])) + +//--------------------------------------------------------------------------- +// Include RegisterInfos_i386 to declare our g_register_infos_i386 structure. +//--------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_I386_STRUCT +#include "RegisterInfos_i386.h" +#undef DECLARE_REGISTER_INFOS_I386_STRUCT + +RegisterContextOpenBSD_i386::RegisterContextOpenBSD_i386( + const ArchSpec &target_arch) + : RegisterInfoInterface(target_arch) {} + +size_t RegisterContextOpenBSD_i386::GetGPRSize() const { return sizeof(GPR); } + +const RegisterInfo *RegisterContextOpenBSD_i386::GetRegisterInfo() const { + switch (m_target_arch.GetMachine()) { + case llvm::Triple::x86: + return g_register_infos_i386; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } +} + +uint32_t RegisterContextOpenBSD_i386::GetRegisterCount() const { + return static_cast<uint32_t>(sizeof(g_register_infos_i386) / + sizeof(g_register_infos_i386[0])); +} diff --git a/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.h b/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.h new file mode 100644 index 000000000000..d3c13008bece --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.h @@ -0,0 +1,26 @@ +//===-- RegisterContextOpenBSD_i386.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextOpenBSD_i386_H_ +#define liblldb_RegisterContextOpenBSD_i386_H_ + +#include "RegisterInfoInterface.h" + +class RegisterContextOpenBSD_i386 : public lldb_private::RegisterInfoInterface { +public: + RegisterContextOpenBSD_i386(const lldb_private::ArchSpec &target_arch); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.cpp new file mode 100644 index 000000000000..e7ff0732ffec --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.cpp @@ -0,0 +1,107 @@ +//===-- RegisterContextOpenBSD_x86_64.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include "RegisterContextOpenBSD_x86_64.h" +#include "RegisterContextPOSIX_x86.h" +#include <vector> + +using namespace lldb_private; +using namespace lldb; + +// /usr/include/machine/reg.h +typedef struct _GPR { + uint64_t rdi; + uint64_t rsi; + uint64_t rdx; + uint64_t rcx; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rbp; + uint64_t rbx; + uint64_t rax; + uint64_t rsp; + uint64_t rip; + uint64_t rflags; + uint64_t cs; + uint64_t ss; + uint64_t ds; + uint64_t es; + uint64_t fs; + uint64_t gs; +} GPR; + +struct DBG { + uint64_t dr[16]; /* debug registers */ + /* Index 0-3: debug address registers */ + /* Index 4-5: reserved */ + /* Index 6: debug status */ + /* Index 7: debug control */ + /* Index 8-15: reserved */ +}; + +struct UserArea { + GPR gpr; + FPR fpr; + DBG dbg; +}; + +#define DR_OFFSET(reg_index) (LLVM_EXTENSION offsetof(DBG, dr[reg_index])) + +//--------------------------------------------------------------------------- +// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 +// structure. +//--------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_X86_64_STRUCT +#include "RegisterInfos_x86_64.h" +#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT + +static const RegisterInfo * +PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::x86_64: + return g_register_infos_x86_64; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } +} + +static uint32_t +PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::x86_64: + return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) / + sizeof(g_register_infos_x86_64[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + +RegisterContextOpenBSD_x86_64::RegisterContextOpenBSD_x86_64( + const ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch), + m_register_info_p(PrivateGetRegisterInfoPtr(target_arch)), + m_register_count(PrivateGetRegisterCount(target_arch)) {} + +size_t RegisterContextOpenBSD_x86_64::GetGPRSize() const { return sizeof(GPR); } + +const RegisterInfo *RegisterContextOpenBSD_x86_64::GetRegisterInfo() const { + return m_register_info_p; +} + +uint32_t RegisterContextOpenBSD_x86_64::GetRegisterCount() const { + return m_register_count; +} diff --git a/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h b/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h new file mode 100644 index 000000000000..aa2b7733f389 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h @@ -0,0 +1,31 @@ +//===-- RegisterContextOpenBSD_x86_64.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextOpenBSD_x86_64_H_ +#define liblldb_RegisterContextOpenBSD_x86_64_H_ + +#include "RegisterInfoInterface.h" + +class RegisterContextOpenBSD_x86_64 + : public lldb_private::RegisterInfoInterface { +public: + RegisterContextOpenBSD_x86_64(const lldb_private::ArchSpec &target_arch); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; + +private: + const lldb_private::RegisterInfo *m_register_info_p; + const uint32_t m_register_count; +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp index 15d155e315fa..bb3509330eec 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp @@ -11,13 +11,13 @@ #include <errno.h> #include <stdint.h> -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" #include "llvm/Support/Compiler.h" #include "Plugins/Process/elf-core/ProcessElfCore.h" diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h index 817649e7c498..8c5fe9d2c2de 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h @@ -16,8 +16,8 @@ // Project includes #include "RegisterInfoInterface.h" #include "lldb-arm-register-enums.h" -#include "lldb/Core/Log.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" class ProcessMonitor; diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp index 17c9dc301b50..89384c8f5190 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp @@ -11,13 +11,13 @@ #include <errno.h> #include <stdint.h> -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" #include "llvm/Support/Compiler.h" #include "Plugins/Process/elf-core/ProcessElfCore.h" diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h index 923e786dd045..27251da2a9af 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h @@ -16,8 +16,8 @@ // Project includes #include "RegisterInfoInterface.h" #include "lldb-arm64-register-enums.h" -#include "lldb/Core/Log.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" class ProcessMonitor; diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp index 8c67fb89d08e..207c69313282 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp @@ -11,47 +11,33 @@ #include <errno.h> #include <stdint.h> -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" #include "llvm/Support/Compiler.h" #include "Plugins/Process/elf-core/ProcessElfCore.h" #include "RegisterContextPOSIX_mips64.h" +#include "RegisterContextFreeBSD_mips64.h" +#include "RegisterContextLinux_mips64.h" +#include "RegisterContextLinux_mips.h" using namespace lldb_private; using namespace lldb; -static const uint32_t g_gpr_regnums[] = { - gpr_zero_mips64, gpr_r1_mips64, gpr_r2_mips64, gpr_r3_mips64, - gpr_r4_mips64, gpr_r5_mips64, gpr_r6_mips64, gpr_r7_mips64, - gpr_r8_mips64, gpr_r9_mips64, gpr_r10_mips64, gpr_r11_mips64, - gpr_r12_mips64, gpr_r13_mips64, gpr_r14_mips64, gpr_r15_mips64, - gpr_r16_mips64, gpr_r17_mips64, gpr_r18_mips64, gpr_r19_mips64, - gpr_r20_mips64, gpr_r21_mips64, gpr_r22_mips64, gpr_r23_mips64, - gpr_r24_mips64, gpr_r25_mips64, gpr_r26_mips64, gpr_r27_mips64, - gpr_gp_mips64, gpr_sp_mips64, gpr_r30_mips64, gpr_ra_mips64, - gpr_sr_mips64, gpr_mullo_mips64, gpr_mulhi_mips64, gpr_badvaddr_mips64, - gpr_cause_mips64, gpr_pc_mips64, gpr_ic_mips64, gpr_dummy_mips64}; - -// Number of register sets provided by this context. -enum { k_num_register_sets = 1 }; - -static const RegisterSet g_reg_sets_mips64[k_num_register_sets] = { - {"General Purpose Registers", "gpr", k_num_gpr_registers_mips64, - g_gpr_regnums}, -}; - bool RegisterContextPOSIX_mips64::IsGPR(unsigned reg) { - return reg <= k_num_gpr_registers_mips64; // GPR's come first. + return reg < m_registers_count[gpr_registers_count]; // GPR's come first. } bool RegisterContextPOSIX_mips64::IsFPR(unsigned reg) { - // XXX + int set = GetRegisterSetCount(); + if (set > 1) + return reg < (m_registers_count[fpr_registers_count] + + m_registers_count[gpr_registers_count]); return false; } @@ -60,6 +46,18 @@ RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64( RegisterInfoInterface *register_info) : RegisterContext(thread, concrete_frame_idx) { m_register_info_ap.reset(register_info); + m_num_registers = GetRegisterCount(); + int set = GetRegisterSetCount(); + + const RegisterSet *reg_set_ptr; + for(int i = 0; i < set; ++i) { + reg_set_ptr = GetRegisterSet(i); + m_registers_count[i] = reg_set_ptr->num_registers; + } + + assert(m_num_registers == m_registers_count[gpr_registers_count] + + m_registers_count[fpr_registers_count] + + m_registers_count[msa_registers_count]); // elf-core yet to support ReadFPR() ProcessSP base = CalculateProcess(); @@ -74,18 +72,17 @@ void RegisterContextPOSIX_mips64::Invalidate() {} void RegisterContextPOSIX_mips64::InvalidateAllRegisters() {} unsigned RegisterContextPOSIX_mips64::GetRegisterOffset(unsigned reg) { - assert(reg < k_num_registers_mips64 && "Invalid register number."); + assert(reg < m_num_registers && "Invalid register number."); return GetRegisterInfo()[reg].byte_offset; } unsigned RegisterContextPOSIX_mips64::GetRegisterSize(unsigned reg) { - assert(reg < k_num_registers_mips64 && "Invalid register number."); + assert(reg < m_num_registers && "Invalid register number."); return GetRegisterInfo()[reg].byte_size; } size_t RegisterContextPOSIX_mips64::GetRegisterCount() { - size_t num_registers = k_num_registers_mips64; - return num_registers; + return m_register_info_ap->GetRegisterCount(); } size_t RegisterContextPOSIX_mips64::GetGPRSize() { @@ -101,31 +98,59 @@ const RegisterInfo *RegisterContextPOSIX_mips64::GetRegisterInfo() { const RegisterInfo * RegisterContextPOSIX_mips64::GetRegisterInfoAtIndex(size_t reg) { - if (reg < k_num_registers_mips64) + if (reg < m_num_registers) return &GetRegisterInfo()[reg]; else return NULL; } size_t RegisterContextPOSIX_mips64::GetRegisterSetCount() { - size_t sets = 0; - for (size_t set = 0; set < k_num_register_sets; ++set) { - if (IsRegisterSetAvailable(set)) - ++sets; + ArchSpec target_arch = m_register_info_ap->GetTargetArchitecture(); + switch (target_arch.GetTriple().getOS()) { + case llvm::Triple::Linux: { + if ((target_arch.GetMachine() == llvm::Triple::mipsel) || + (target_arch.GetMachine() == llvm::Triple::mips)) { + const auto *context = static_cast<const RegisterContextLinux_mips *> + (m_register_info_ap.get()); + return context->GetRegisterSetCount(); + } + const auto *context = static_cast<const RegisterContextLinux_mips64 *> + (m_register_info_ap.get()); + return context->GetRegisterSetCount(); + } + default: { + const auto *context = static_cast<const RegisterContextFreeBSD_mips64 *> + (m_register_info_ap.get()); + return context->GetRegisterSetCount(); + } + } - - return sets; } const RegisterSet *RegisterContextPOSIX_mips64::GetRegisterSet(size_t set) { - if (IsRegisterSetAvailable(set)) - return &g_reg_sets_mips64[set]; - else - return NULL; + ArchSpec target_arch = m_register_info_ap->GetTargetArchitecture(); + switch (target_arch.GetTriple().getOS()) { + case llvm::Triple::Linux: { + if ((target_arch.GetMachine() == llvm::Triple::mipsel) || + (target_arch.GetMachine() == llvm::Triple::mips)) { + const auto *context = static_cast<const RegisterContextLinux_mips *> + (m_register_info_ap.get()); + return context->GetRegisterSet(set); + } + const auto *context = static_cast<const RegisterContextLinux_mips64 *> + (m_register_info_ap.get()); + return context->GetRegisterSet(set); + } + default: { + const auto *context = static_cast<const RegisterContextFreeBSD_mips64 *> + (m_register_info_ap.get()); + return context->GetRegisterSet(set); + } + } } const char *RegisterContextPOSIX_mips64::GetRegisterName(unsigned reg) { - assert(reg < k_num_registers_mips64 && "Invalid register offset."); + assert(reg < m_num_registers && "Invalid register offset."); return GetRegisterInfo()[reg].name; } @@ -141,7 +166,7 @@ lldb::ByteOrder RegisterContextPOSIX_mips64::GetByteOrder() { } bool RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index) { - size_t num_sets = k_num_register_sets; + size_t num_sets = GetRegisterSetCount(); return (set_index < num_sets); } @@ -150,7 +175,7 @@ bool RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index) { // object file sections that contain register numbers in them. uint32_t RegisterContextPOSIX_mips64::ConvertRegisterKindToRegisterNumber( lldb::RegisterKind kind, uint32_t num) { - const uint32_t num_regs = GetRegisterCount(); + const uint32_t num_regs = m_num_registers; assert(kind < kNumRegisterKinds); for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h index 90ff9d659491..1695ec9a0bab 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h @@ -16,9 +16,8 @@ // Project includes #include "RegisterContext_mips.h" #include "RegisterInfoInterface.h" -#include "lldb-mips-freebsd-register-enums.h" -#include "lldb/Core/Log.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" using namespace lldb_private; @@ -26,6 +25,14 @@ class ProcessMonitor; class RegisterContextPOSIX_mips64 : public lldb_private::RegisterContext { public: + + enum Register_count{ + gpr_registers_count = 0, + fpr_registers_count, + msa_registers_count, + register_set_count + }; + RegisterContextPOSIX_mips64( lldb_private::Thread &thread, uint32_t concrete_frame_idx, lldb_private::RegisterInfoInterface *register_info); @@ -56,8 +63,8 @@ public: uint32_t num) override; protected: - uint64_t - m_gpr_mips64[k_num_gpr_registers_mips64]; // general purpose registers. + uint32_t m_num_registers; + uint8_t m_registers_count[register_set_count]; std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp index 6a9838a6fd0c..c2b73e226165 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp @@ -12,13 +12,13 @@ #include <errno.h> #include <stdint.h> -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" #include "llvm/Support/Compiler.h" #include "Plugins/Process/elf-core/ProcessElfCore.h" diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h index 79bb01f6740c..50f234680ca0 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h @@ -16,8 +16,8 @@ // Project includes #include "RegisterContext_powerpc.h" #include "RegisterInfoInterface.h" -#include "lldb/Core/Log.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" class ProcessMonitor; diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp index e4dbe333a22d..b3365ee2f098 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp @@ -11,14 +11,14 @@ #include <errno.h> #include <stdint.h> -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" #include "llvm/Support/Compiler.h" #include "RegisterContextPOSIX_s390x.h" diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h index 1ffc45c2d4b1..d5337630c32d 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h @@ -17,8 +17,8 @@ #include "RegisterContext_s390x.h" #include "RegisterInfoInterface.h" #include "lldb-s390x-register-enums.h" -#include "lldb/Core/Log.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" class ProcessMonitor; diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp index 99525b6c2df2..5e1bf35356b8 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp @@ -11,14 +11,14 @@ #include <errno.h> #include <stdint.h> -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Host/Endian.h" +#include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Target/Process.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" #include "llvm/Support/Compiler.h" #include "RegisterContextPOSIX_x86.h" diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h index c5afe089e476..aa689273f218 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h @@ -17,8 +17,8 @@ #include "RegisterContext_x86.h" #include "RegisterInfoInterface.h" #include "lldb-x86-register-enums.h" -#include "lldb/Core/Log.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" class ProcessMonitor; diff --git a/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp index 2b5cb00fa96a..7d990e73b5be 100644 --- a/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp +++ b/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/Error.h" #include "lldb/Target/OperatingSystem.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/Error.h" #include "lldb/lldb-private.h" #include "RegisterContextThreadMemory.h" diff --git a/source/Plugins/Process/Utility/RegisterInfoInterface.h b/source/Plugins/Process/Utility/RegisterInfoInterface.h index 12db366d7a57..74d5d6e50208 100644 --- a/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ b/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -13,6 +13,7 @@ #include <vector> #include "lldb/Core/ArchSpec.h" +#include "lldb/lldb-private-types.h" namespace lldb_private { diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp b/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp index afa105f25404..0111b842509b 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextLinux_arm.cpp ---------------------------*- C++ -*-===// +//===-- RegisterInfoPOSIX_arm.cpp ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,37 +14,35 @@ #include "lldb/lldb-defines.h" #include "llvm/Support/Compiler.h" -#include "RegisterContextLinux_arm.h" +#include "RegisterInfoPOSIX_arm.h" using namespace lldb; using namespace lldb_private; // Based on RegisterContextDarwin_arm.cpp #define GPR_OFFSET(idx) ((idx)*4) -#define FPU_OFFSET(idx) ((idx)*4 + sizeof(RegisterContextLinux_arm::GPR)) +#define FPU_OFFSET(idx) ((idx)*4 + sizeof(RegisterInfoPOSIX_arm::GPR)) #define FPSCR_OFFSET \ - (LLVM_EXTENSION offsetof(RegisterContextLinux_arm::FPU, fpscr) + \ - sizeof(RegisterContextLinux_arm::GPR)) + (LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm::FPU, fpscr) + \ + sizeof(RegisterInfoPOSIX_arm::GPR)) #define EXC_OFFSET(idx) \ - ((idx)*4 + sizeof(RegisterContextLinux_arm::GPR) + \ - sizeof(RegisterContextLinux_arm::FPU)) + ((idx)*4 + sizeof(RegisterInfoPOSIX_arm::GPR) + \ + sizeof(RegisterInfoPOSIX_arm::FPU)) #define DBG_OFFSET(reg) \ - ((LLVM_EXTENSION offsetof(RegisterContextLinux_arm::DBG, reg) + \ - sizeof(RegisterContextLinux_arm::GPR) + \ - sizeof(RegisterContextLinux_arm::FPU) + \ - sizeof(RegisterContextLinux_arm::EXC))) + ((LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm::DBG, reg) + \ + sizeof(RegisterInfoPOSIX_arm::GPR) + sizeof(RegisterInfoPOSIX_arm::FPU) + \ + sizeof(RegisterInfoPOSIX_arm::EXC))) #define DEFINE_DBG(reg, i) \ - #reg, NULL, sizeof(((RegisterContextLinux_arm::DBG *) NULL)->reg[i]), \ + #reg, NULL, sizeof(((RegisterInfoPOSIX_arm::DBG *) NULL)->reg[i]), \ DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, \ {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ dbg_##reg##i }, \ NULL, NULL, NULL, 0 #define REG_CONTEXT_SIZE \ - (sizeof(RegisterContextLinux_arm::GPR) + \ - sizeof(RegisterContextLinux_arm::FPU) + \ - sizeof(RegisterContextLinux_arm::EXC)) + (sizeof(RegisterInfoPOSIX_arm::GPR) + sizeof(RegisterInfoPOSIX_arm::FPU) + \ + sizeof(RegisterInfoPOSIX_arm::EXC)) //----------------------------------------------------------------------------- // Include RegisterInfos_arm to declare our g_register_infos_arm structure. @@ -76,21 +74,21 @@ GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { } } -RegisterContextLinux_arm::RegisterContextLinux_arm( +RegisterInfoPOSIX_arm::RegisterInfoPOSIX_arm( const lldb_private::ArchSpec &target_arch) : lldb_private::RegisterInfoInterface(target_arch), m_register_info_p(GetRegisterInfoPtr(target_arch)), m_register_info_count(GetRegisterInfoCount(target_arch)) {} -size_t RegisterContextLinux_arm::GetGPRSize() const { - return sizeof(struct RegisterContextLinux_arm::GPR); +size_t RegisterInfoPOSIX_arm::GetGPRSize() const { + return sizeof(struct RegisterInfoPOSIX_arm::GPR); } const lldb_private::RegisterInfo * -RegisterContextLinux_arm::GetRegisterInfo() const { +RegisterInfoPOSIX_arm::GetRegisterInfo() const { return m_register_info_p; } -uint32_t RegisterContextLinux_arm::GetRegisterCount() const { +uint32_t RegisterInfoPOSIX_arm::GetRegisterCount() const { return m_register_info_count; } diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h b/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.h index 422ecb7686dc..d90aec1c5116 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h +++ b/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.h @@ -1,4 +1,4 @@ -//===-- RegisterContextFreeBSD_arm.h ----------------------------*- C++ -*-===// +//===-- RegisterInfoPOSIX_arm.h ---------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextFreeBSD_arm_h_ -#define liblldb_RegisterContextFreeBSD_arm_h_ +#ifndef liblldb_RegisterInfoPOSIX_arm_h_ +#define liblldb_RegisterInfoPOSIX_arm_h_ #include "RegisterInfoInterface.h" #include "lldb/Target/RegisterContext.h" #include "lldb/lldb-private.h" -class RegisterContextFreeBSD_arm : public lldb_private::RegisterInfoInterface { +class RegisterInfoPOSIX_arm : public lldb_private::RegisterInfoInterface { public: struct GPR { uint32_t r[16]; // R0-R15 @@ -46,7 +46,7 @@ public: uint32_t wcr[16]; }; - RegisterContextFreeBSD_arm(const lldb_private::ArchSpec &target_arch); + RegisterInfoPOSIX_arm(const lldb_private::ArchSpec &target_arch); size_t GetGPRSize() const override; @@ -59,4 +59,4 @@ private: uint32_t m_register_info_count; }; -#endif // liblldb_RegisterContextFreeBSD_arm_h_ +#endif // liblldb_RegisterInfoPOSIX_arm_h_ diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp index 3b29a18dbe20..435f3d18c062 100644 --- a/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -15,7 +15,6 @@ // Project includes #include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/StreamString.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/ExecutionContext.h" @@ -25,6 +24,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/UnixSignals.h" +#include "lldb/Utility/StreamString.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp index 6e2a9a9ee100..2b34bddd90b2 100644 --- a/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/Function.h" @@ -17,6 +16,7 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/Log.h" #include "RegisterContextLLDB.h" #include "UnwindLLDB.h" diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h index b9323032180d..3f84649aa05f 100644 --- a/source/Plugins/Process/Utility/UnwindLLDB.h +++ b/source/Plugins/Process/Utility/UnwindLLDB.h @@ -16,11 +16,11 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/ConstString.h" #include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Unwind.h" +#include "lldb/Utility/ConstString.h" #include "lldb/lldb-public.h" namespace lldb_private { diff --git a/source/Plugins/Process/Windows/Common/CMakeLists.txt b/source/Plugins/Process/Windows/Common/CMakeLists.txt index 9386ed8a0e4c..009a289bae39 100644 --- a/source/Plugins/Process/Windows/Common/CMakeLists.txt +++ b/source/Plugins/Process/Windows/Common/CMakeLists.txt @@ -20,6 +20,17 @@ elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) ) endif() -add_lldb_library(lldbPluginProcessWindowsCommon +add_lldb_library(lldbPluginProcessWindowsCommon PLUGIN ${PROC_WINDOWS_COMMON_SOURCES} + + LINK_LIBS + lldbCore + lldbHost + lldbInterpreter + lldbSymbol + lldbTarget + ws2_32 + rpcrt4 + LINK_COMPONENTS + Support ) diff --git a/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/source/Plugins/Process/Windows/Common/DebuggerThread.cpp index be1462aa6602..b79359ba9667 100644 --- a/source/Plugins/Process/Windows/Common/DebuggerThread.cpp +++ b/source/Plugins/Process/Windows/Common/DebuggerThread.cpp @@ -11,23 +11,23 @@ #include "ExceptionRecord.h" #include "IDebugDelegate.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" #include "lldb/Core/ModuleSpec.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Host/Predicate.h" -#include "lldb/Host/ThisThread.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/windows/HostProcessWindows.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/ProcessLauncherWindows.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" using namespace lldb; @@ -61,9 +61,8 @@ DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate) DebuggerThread::~DebuggerThread() { ::CloseHandle(m_debugging_ended_event); } Error DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "DebuggerThread::DebugLaunch launching '%s'", - launch_info.GetExecutableFile().GetPath().c_str()); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); + LLDB_LOG(log, "launching '{0}'", launch_info.GetExecutableFile().GetPath()); Error error; DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); @@ -71,19 +70,16 @@ Error DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { "lldb.plugin.process-windows.slave[?]", DebuggerThreadLaunchRoutine, context, &error)); - if (!error.Success()) { - WINERR_IFALL(WINDOWS_LOG_PROCESS, - "DebugLaunch couldn't launch debugger thread. %s", - error.AsCString()); - } + if (!error.Success()) + LLDB_LOG(log, "couldn't launch debugger thread. {0}", error); return error; } Error DebuggerThread::DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info) { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "DebuggerThread::DebugAttach attaching to '%llu'", pid); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); + LLDB_LOG(log, "attaching to '{0}'", pid); Error error; DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info); @@ -91,11 +87,8 @@ Error DebuggerThread::DebugAttach(lldb::pid_t pid, "lldb.plugin.process-windows.slave[?]", DebuggerThreadAttachRoutine, context, &error)); - if (!error.Success()) { - WINERR_IFALL(WINDOWS_LOG_PROCESS, - "DebugAttach couldn't attach to process '%llu'. %s", pid, - error.AsCString()); - } + if (!error.Success()) + LLDB_LOG(log, "couldn't attach to process '{0}'. {1}", pid, error); return error; } @@ -123,9 +116,9 @@ lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine( // thread routine has exited. std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "DebuggerThread preparing to launch '%s' on background thread.", - launch_info.GetExecutableFile().GetPath().c_str()); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); + LLDB_LOG(log, "preparing to launch '{0}' on background thread.", + launch_info.GetExecutableFile().GetPath()); Error error; ProcessLauncherWindows launcher; @@ -154,9 +147,9 @@ lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( // thread routine has exited. std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to attach to " - "process '%llu' on background thread.", - pid); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); + LLDB_LOG(log, "preparing to attach to process '{0}' on background thread.", + pid); if (!DebugActiveProcess((DWORD)pid)) { Error error(::GetLastError(), eErrorTypeWin32); @@ -179,9 +172,8 @@ Error DebuggerThread::StopDebugging(bool terminate) { lldb::pid_t pid = m_process.GetProcessId(); - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "StopDebugging('%s') called (inferior=%I64u).", - (terminate ? "true" : "false"), pid); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); + LLDB_LOG(log, "terminate = {0}, inferior={1}.", terminate, pid); // Set m_is_shutting_down to true if it was false. Return if it was already // true. @@ -200,10 +192,9 @@ Error DebuggerThread::StopDebugging(bool terminate) { // 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")); + LLDB_LOG(log, + "calling TerminateProcess({0}, 0) (inferior={1}), success={2}", + handle, pid, terminate_suceeded); } // If we're stuck waiting for an exception to continue (e.g. the user is at a @@ -213,9 +204,7 @@ Error DebuggerThread::StopDebugging(bool terminate) { // to make sure that the very next call to WaitForDebugEvent is an exit // process event. if (m_active_exception.get()) { - WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION, - "StopDebugging masking active exception"); - + LLDB_LOG(log, "masking active exception"); ContinueAsyncException(ExceptionResult::MaskException); } @@ -231,26 +220,19 @@ Error DebuggerThread::StopDebugging(bool terminate) { } } - WINLOG_IFALL( - WINDOWS_LOG_PROCESS, - "StopDebugging waiting for detach from process %llu to complete.", pid); + LLDB_LOG(log, "waiting for detach from process {0} to complete.", pid); DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000); if (wait_result != WAIT_OBJECT_0) { error.SetError(GetLastError(), eErrorTypeWin32); - WINERR_IFALL(WINDOWS_LOG_PROCESS, - "StopDebugging WaitForSingleObject(0x%p, 5000) returned %lu", - m_debugging_ended_event, wait_result); - } else { - WINLOG_IFALL( - WINDOWS_LOG_PROCESS, - "StopDebugging detach from process %llu completed successfully.", pid); - } + LLDB_LOG(log, "error: WaitForSingleObject({0}, 5000) returned {1}", + m_debugging_ended_event, wait_result); + } else + LLDB_LOG(log, "detach from process {0} completed successfully.", pid); if (!error.Success()) { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging encountered an error " - "while trying to stop process %llu. %s", - pid, error.AsCString()); + LLDB_LOG(log, "encountered an error while trying to stop process {0}. {1}", + pid, error); } return error; } @@ -259,10 +241,10 @@ void DebuggerThread::ContinueAsyncException(ExceptionResult result) { if (!m_active_exception.get()) return; - WINLOG_IFANY( - WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION, - "ContinueAsyncException called for inferior process %I64u, broadcasting.", - m_process.GetProcessId()); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS | + WINDOWS_LOG_EXCEPTION); + LLDB_LOG(log, "broadcasting for inferior process {0}.", + m_process.GetProcessId()); m_active_exception.reset(); m_exception_pred.SetValue(result, eBroadcastAlways); @@ -278,11 +260,12 @@ void DebuggerThread::FreeProcessHandles() { } void DebuggerThread::DebugLoop() { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); DEBUG_EVENT dbe = {}; bool should_debug = true; - WINLOG_IFALL(WINDOWS_LOG_EVENT, "Entering WaitForDebugEvent loop"); + LLDB_LOGV(log, "Entering WaitForDebugEvent loop"); while (should_debug) { - WINLOGD_IFALL(WINDOWS_LOG_EVENT, "Calling WaitForDebugEvent"); + LLDB_LOGV(log, "Calling WaitForDebugEvent"); BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); if (wait_result) { DWORD continue_status = DBG_CONTINUE; @@ -331,11 +314,9 @@ void DebuggerThread::DebugLoop() { break; } - WINLOGD_IFALL( - WINDOWS_LOG_EVENT, - "DebugLoop calling ContinueDebugEvent(%lu, %lu, %lu) on thread %lu.", - dbe.dwProcessId, dbe.dwThreadId, continue_status, - ::GetCurrentThreadId()); + LLDB_LOGV(log, "calling ContinueDebugEvent({0}, {1}, {2}) on thread {3}.", + dbe.dwProcessId, dbe.dwThreadId, continue_status, + ::GetCurrentThreadId()); ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); @@ -343,23 +324,23 @@ void DebuggerThread::DebugLoop() { should_debug = false; } } else { - WINERR_IFALL( - WINDOWS_LOG_EVENT, - "DebugLoop returned FALSE from WaitForDebugEvent. Error = %lu", - ::GetLastError()); + LLDB_LOG(log, "returned FALSE from WaitForDebugEvent. Error = {0}", + ::GetLastError()); should_debug = false; } } FreeProcessHandles(); - WINLOG_IFALL(WINDOWS_LOG_EVENT, "WaitForDebugEvent loop completed, exiting."); + LLDB_LOG(log, "WaitForDebugEvent loop completed, exiting."); SetEvent(m_debugging_ended_event); } ExceptionResult DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id) { + Log *log = + ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION); if (m_is_shutting_down) { // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic // exception that @@ -367,10 +348,8 @@ DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, // debug loop. if (m_pid_to_detach != 0 && info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { - WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION | - WINDOWS_LOG_PROCESS, - "Breakpoint exception is cue to detach from process 0x%lx", - m_pid_to_detach.load()); + LLDB_LOG(log, "Breakpoint exception is cue to detach from process {0:x}", + m_pid_to_detach.load()); ::DebugActiveProcessStop(m_pid_to_detach); m_detached = true; } @@ -385,36 +364,29 @@ DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, m_active_exception.reset( new ExceptionRecord(info.ExceptionRecord, thread_id)); - WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, - "HandleExceptionEvent encountered %s chance exception 0x%lx on " - "thread 0x%lx", - first_chance ? "first" : "second", - info.ExceptionRecord.ExceptionCode, thread_id); + LLDB_LOG(log, "encountered {0} chance exception {1:x} on thread {2:x}", + first_chance ? "first" : "second", + info.ExceptionRecord.ExceptionCode, thread_id); 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"); - + LLDB_LOG(log, "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()); - + LLDB_LOG(log, "got ExceptionPred = {0}", (int)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 0x%lx spawned in process %llu", - thread_id, m_process.GetProcessId()); + Log *log = + ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD); + LLDB_LOG(log, "Thread {0:x} spawned in process {1}", thread_id, + m_process.GetProcessId()); HostThread thread(info.hThread); thread.GetNativeThread().SetOwnsHandle(false); m_debug_delegate->OnCreateThread(thread); @@ -424,16 +396,17 @@ DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id) { + Log *log = + ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS); uint32_t process_id = ::GetProcessId(info.hProcess); - WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS, - "HandleCreateProcessEvent process %u spawned", process_id); + LLDB_LOG(log, "process {0} spawned", process_id); std::string thread_name; llvm::raw_string_ostream name_stream(thread_name); name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]"; name_stream.flush(); - ThisThread::SetName(thread_name.c_str()); + llvm::set_thread_name(thread_name); // info.hProcess and info.hThread are closed automatically by Windows when // EXIT_PROCESS_DEBUG_EVENT is received. @@ -452,10 +425,10 @@ DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id) { - WINLOG_IFANY( - WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, - "HandleExitThreadEvent Thread %lu exited with code %lu in process %llu", - thread_id, info.dwExitCode, m_process.GetProcessId()); + Log *log = + ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD); + LLDB_LOG(log, "Thread {0} exited with code {1} in process {2}", thread_id, + info.dwExitCode, m_process.GetProcessId()); m_debug_delegate->OnExitThread(thread_id, info.dwExitCode); return DBG_CONTINUE; } @@ -463,9 +436,10 @@ DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id) { - WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, - "HandleExitProcessEvent process %llu exited with code %lu", - m_process.GetProcessId(), info.dwExitCode); + Log *log = + ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD); + LLDB_LOG(log, "process {0} exited with code {1}", m_process.GetProcessId(), + info.dwExitCode); m_debug_delegate->OnExitProcess(info.dwExitCode); @@ -476,11 +450,11 @@ DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id) { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); if (info.hFile == nullptr) { // Not sure what this is, so just ignore it. - WINWARN_IFALL(WINDOWS_LOG_EVENT, "Inferior %llu - HandleLoadDllEvent has " - "a NULL file handle, returning...", - m_process.GetProcessId()); + LLDB_LOG(log, "Warning: Inferior {0} has a NULL file handle, returning...", + m_process.GetProcessId()); return DBG_CONTINUE; } @@ -502,16 +476,15 @@ DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, 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); + LLDB_LOG(log, "Inferior {0} - DLL '{1}' loaded at address {2:x}...", + m_process.GetProcessId(), path, info.lpBaseOfDll); m_debug_delegate->OnLoadDll(module_spec, load_addr); } else { - WINERR_IFALL(WINDOWS_LOG_EVENT, "Inferior %llu - HandleLoadDllEvent Error " - "%lu occurred calling " - "GetFinalPathNameByHandle", - m_process.GetProcessId(), ::GetLastError()); + LLDB_LOG( + log, + "Inferior {0} - Error {1} occurred calling GetFinalPathNameByHandle", + m_process.GetProcessId(), ::GetLastError()); } // Windows does not automatically close info.hFile, so we need to do it. ::CloseHandle(info.hFile); @@ -521,9 +494,9 @@ DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id) { - WINLOG_IFALL(WINDOWS_LOG_EVENT, - "HandleUnloadDllEvent process %llu unloading DLL at addr 0x%p.", - m_process.GetProcessId(), info.lpBaseOfDll); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); + LLDB_LOG(log, "process {0} unloading DLL at addr {1:x}.", + m_process.GetProcessId(), info.lpBaseOfDll); m_debug_delegate->OnUnloadDll( reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); @@ -538,9 +511,9 @@ DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) { - WINERR_IFALL(WINDOWS_LOG_EVENT, "HandleRipEvent encountered error %lu " - "(type=%lu) in process %llu thread %lu", - info.dwError, info.dwType, m_process.GetProcessId(), thread_id); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); + LLDB_LOG(log, "encountered error {0} (type={1}) in process {2} thread {3}", + info.dwError, info.dwType, m_process.GetProcessId(), thread_id); Error error(info.dwError, eErrorTypeWin32); m_debug_delegate->OnDebuggerError(error, info.dwType); diff --git a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/source/Plugins/Process/Windows/Common/ProcessWindows.cpp index 50f787f78495..56a98a8eef63 100644 --- a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ b/source/Plugins/Process/Windows/Common/ProcessWindows.cpp @@ -23,6 +23,7 @@ #include "lldb/Host/HostProcess.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/StopInfo.h" @@ -30,6 +31,7 @@ #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Format.h" +#include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" #include "DebuggerThread.h" @@ -102,9 +104,9 @@ ProcessSP ProcessWindows::CreateInstance(lldb::TargetSP target_sp, } void ProcessWindows::Initialize() { - static std::once_flag g_once_flag; + static llvm::once_flag g_once_flag; - std::call_once(g_once_flag, []() { + llvm::call_once(g_once_flag, []() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); }); @@ -156,35 +158,30 @@ lldb_private::ConstString ProcessWindows::GetPluginName() { uint32_t ProcessWindows::GetPluginVersion() { return 1; } Error ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) { - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, - "EnableBreakpointSite called with bp_site 0x%p " - "(id=%d, addr=0x%llx)", - bp_site, bp_site->GetID(), bp_site->GetLoadAddress()); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_BREAKPOINTS); + LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site, + bp_site->GetID(), bp_site->GetLoadAddress()); Error error = EnableSoftwareBreakpoint(bp_site); - if (!error.Success()) { - WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed. %s", - error.AsCString()); - } + if (!error.Success()) + LLDB_LOG(log, "error: {0}", error); return error; } Error ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site) { - WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, - "DisableBreakpointSite called with bp_site 0x%p " - "(id=%d, addr=0x%llx)", - bp_site, bp_site->GetID(), bp_site->GetLoadAddress()); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_BREAKPOINTS); + LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site, + bp_site->GetID(), bp_site->GetLoadAddress()); Error error = DisableSoftwareBreakpoint(bp_site); - if (!error.Success()) { - WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite failed. %s", - error.AsCString()); - } + if (!error.Success()) + LLDB_LOG(log, "error: {0}", error); return error; } Error ProcessWindows::DoDetach(bool keep_stopped) { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); DebuggerThreadSP debugger_thread; StateType private_state; { @@ -197,10 +194,8 @@ Error ProcessWindows::DoDetach(bool keep_stopped) { private_state = GetPrivateState(); if (!m_session_data) { - WINWARN_IFALL( - WINDOWS_LOG_PROCESS, - "DoDetach called while state = %u, but there is no active session.", - private_state); + LLDB_LOG(log, "state = {0}, but there is no active session.", + private_state); return Error(); } @@ -209,11 +204,9 @@ Error ProcessWindows::DoDetach(bool keep_stopped) { Error error; if (private_state != eStateExited && private_state != eStateDetached) { - WINLOG_IFALL( - WINDOWS_LOG_PROCESS, - "DoDetach called for process %p while state = %d. Detaching...", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), - private_state); + LLDB_LOG(log, "detaching from process {0} while state = {1}.", + debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), + private_state); error = debugger_thread->StopDebugging(false); if (error.Success()) { SetPrivateState(eStateDetached); @@ -223,9 +216,9 @@ Error ProcessWindows::DoDetach(bool keep_stopped) { // we can be assured that no other thread will race for the session data. m_session_data.reset(); } else { - WINERR_IFALL( - WINDOWS_LOG_PROCESS, "DoDetach called for process %p while state = " - "%d, but cannot destroy in this state.", + LLDB_LOG( + log, + "error: process {0} in state = {1}, but cannot destroy in this state.", debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), private_state); } @@ -241,6 +234,7 @@ Error ProcessWindows::DoLaunch(Module *exe_module, // to acquire // the mutex. + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); Error result; if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) { StreamString stream; @@ -250,7 +244,7 @@ Error ProcessWindows::DoLaunch(Module *exe_module, std::string message = stream.GetString(); result.SetErrorString(message.c_str()); - WINERR_IFALL(WINDOWS_LOG_PROCESS, "%s", message.c_str()); + LLDB_LOG(log, "error: {0}", message); return result; } @@ -265,23 +259,21 @@ Error ProcessWindows::DoLaunch(Module *exe_module, // Kick off the DebugLaunch asynchronously and wait for it to complete. result = debugger->DebugLaunch(launch_info); if (result.Fail()) { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", - launch_info.GetExecutableFile().GetPath().c_str(), - result.AsCString()); + LLDB_LOG(log, "failed launching '{0}'. {1}", + launch_info.GetExecutableFile().GetPath(), result); return result; } HostProcess process; Error error = WaitForDebuggerConnection(debugger, process); if (error.Fail()) { - WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'. %s", - launch_info.GetExecutableFile().GetPath().c_str(), - error.AsCString()); + LLDB_LOG(log, "failed launching '{0}'. {1}", + launch_info.GetExecutableFile().GetPath(), error); return error; } - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'", - launch_info.GetExecutableFile().GetPath().c_str()); + LLDB_LOG(log, "successfully launched '{0}'", + launch_info.GetExecutableFile().GetPath()); // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the // private state @@ -298,6 +290,7 @@ Error ProcessWindows::DoLaunch(Module *exe_module, Error ProcessWindows::DoAttachToProcessWithID( lldb::pid_t pid, const ProcessAttachInfo &attach_info) { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); m_session_data.reset( new ProcessWindowsData(!attach_info.GetContinueOnceAttached())); @@ -309,27 +302,23 @@ Error ProcessWindows::DoAttachToProcessWithID( DWORD process_id = static_cast<DWORD>(pid); Error error = debugger->DebugAttach(process_id, attach_info); if (error.Fail()) { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an " - "error occurred initiating the " - "asynchronous attach. %s", - error.AsCString()); + LLDB_LOG( + log, + "encountered an error occurred initiating the asynchronous attach. {0}", + error); return error; } HostProcess process; error = WaitForDebuggerConnection(debugger, process); if (error.Fail()) { - WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an " - "error waiting for the debugger to " - "connect. %s", - error.AsCString()); + LLDB_LOG(log, + "encountered an error waiting for the debugger to connect. {0}", + error); return error; } - WINLOG_IFALL( - WINDOWS_LOG_PROCESS, - "DoAttachToProcessWithID successfully attached to process with pid=%lu", - process_id); + LLDB_LOG(log, "successfully attached to process with pid={0}", process_id); // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the // private state @@ -343,16 +332,15 @@ Error ProcessWindows::DoAttachToProcessWithID( } Error ProcessWindows::DoResume() { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); llvm::sys::ScopedLock lock(m_mutex); Error error; StateType private_state = GetPrivateState(); if (private_state == eStateStopped || private_state == eStateCrashed) { - WINLOG_IFALL( - WINDOWS_LOG_PROCESS, - "DoResume called for process %I64u while state is %u. Resuming...", - m_session_data->m_debugger->GetProcess().GetProcessId(), - GetPrivateState()); + LLDB_LOG(log, "process {0} is in state {1}. Resuming...", + m_session_data->m_debugger->GetProcess().GetProcessId(), + GetPrivateState()); ExceptionRecordSP active_exception = m_session_data->m_debugger->GetActiveException().lock(); @@ -364,8 +352,7 @@ Error ProcessWindows::DoResume() { ExceptionResult::MaskException); } - WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_THREAD, - "DoResume resuming %u threads.", m_thread_list.GetSize()); + LLDB_LOG(log, "resuming {0} threads.", m_thread_list.GetSize()); for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) { auto thread = std::static_pointer_cast<TargetThreadWindows>( @@ -375,16 +362,15 @@ Error ProcessWindows::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()); + LLDB_LOG(log, "error: process %I64u is in state %u. Returning...", + m_session_data->m_debugger->GetProcess().GetProcessId(), + GetPrivateState()); } return error; } Error ProcessWindows::DoDestroy() { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); DebuggerThreadSP debugger_thread; StateType private_state; { @@ -398,10 +384,8 @@ Error ProcessWindows::DoDestroy() { private_state = GetPrivateState(); if (!m_session_data) { - WINWARN_IFALL( - WINDOWS_LOG_PROCESS, - "DoDestroy called while state = %u, but there is no active session.", - private_state); + LLDB_LOG(log, "warning: state = {0}, but there is no active session.", + private_state); return Error(); } @@ -410,28 +394,25 @@ Error ProcessWindows::DoDestroy() { Error error; if (private_state != eStateExited && private_state != eStateDetached) { - WINLOG_IFALL( - WINDOWS_LOG_PROCESS, "DoDestroy called for process %p while state = " - "%u. Shutting down...", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), - private_state); + LLDB_LOG(log, "Shutting down process {0} while state = {1}.", + debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), + private_state); error = debugger_thread->StopDebugging(true); // By the time StopDebugging returns, there is no more debugger thread, so // we can be assured that no other thread will race for the session data. m_session_data.reset(); } else { - WINERR_IFALL( - WINDOWS_LOG_PROCESS, "DoDestroy called for process %p while state = " - "%d, but cannot destroy in this state.", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), - private_state); + LLDB_LOG(log, "cannot destroy process {0} while state = {1}", + debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), + private_state); } return error; } Error ProcessWindows::DoHalt(bool &caused_stop) { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); Error error; StateType state = GetPrivateState(); if (state == eStateStopped) @@ -443,10 +424,7 @@ Error ProcessWindows::DoHalt(bool &caused_stop) { .GetSystemHandle()); if (!caused_stop) { error.SetError(::GetLastError(), eErrorTypeWin32); - WINERR_IFALL( - WINDOWS_LOG_PROCESS, - "DoHalt called DebugBreakProcess, but it failed with error %u", - error.GetError()); + LLDB_LOG(log, "DebugBreakProcess failed with error {0}", error); } } return error; @@ -468,12 +446,11 @@ void ProcessWindows::DidAttach(ArchSpec &arch_spec) { } void ProcessWindows::RefreshStateAfterStop() { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION); llvm::sys::ScopedLock lock(m_mutex); if (!m_session_data) { - WINWARN_IFALL( - WINDOWS_LOG_PROCESS, - "RefreshStateAfterStop called with no active session. Returning..."); + LLDB_LOG(log, "no active session. Returning..."); return; } @@ -483,11 +460,9 @@ void ProcessWindows::RefreshStateAfterStop() { 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()); + LLDB_LOG(log, "there is no active exception in process {0}. Why is the " + "process stopped?", + m_session_data->m_debugger->GetProcess().GetProcessId()); return; } @@ -503,19 +478,15 @@ void ProcessWindows::RefreshStateAfterStop() { const uint64_t pc = register_context->GetPC(); BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); if (site && site->ValidForThisThread(stop_thread.get())) { - WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION | - WINDOWS_LOG_STEP, - "Single-stepped onto a breakpoint in process %I64u at " - "address 0x%I64x with breakpoint site %d", - m_session_data->m_debugger->GetProcess().GetProcessId(), pc, - site->GetID()); + LLDB_LOG(log, "Single-stepped onto a breakpoint in process {0} at " + "address {1:x} with breakpoint site {2}", + m_session_data->m_debugger->GetProcess().GetProcessId(), pc, + site->GetID()); stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, site->GetID()); stop_thread->SetStopInfo(stop_info); } else { - WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, - "RefreshStateAfterStop single stepping thread %llu", - stop_thread->GetID()); + LLDB_LOG(log, "single stepping thread {0}", stop_thread->GetID()); stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); stop_thread->SetStopInfo(stop_info); } @@ -530,37 +501,32 @@ void ProcessWindows::RefreshStateAfterStop() { BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); if (site) { - 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()); + LLDB_LOG(log, "detected breakpoint in process {0} at address {1:x} with " + "breakpoint site {2}", + 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 (0x%I64x), " - "creating stop info.", - site->GetID(), stop_thread->GetID()); + LLDB_LOG(log, "Breakpoint site {0} is valid for this thread ({1:x}), " + "creating stop info.", + site->GetID(), stop_thread->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()); + LLDB_LOG(log, "Breakpoint site {0} is not valid for this thread, " + "creating empty stop info.", + site->GetID()); } stop_thread->SetStopInfo(stop_info); return; } else { // The thread hit a hard-coded breakpoint like an `int 3` or // `__debugbreak()`. - WINLOG_IFALL( - WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION, - "No breakpoint site matches for this thread. __debugbreak()? " - "Creating stop info with the exception."); + LLDB_LOG(log, + "No breakpoint site matches for this thread. __debugbreak()? " + "Creating stop info with the exception."); // FALLTHROUGH: We'll treat this as a generic exception record in the // default case. } @@ -576,7 +542,7 @@ void ProcessWindows::RefreshStateAfterStop() { stop_info = StopInfo::CreateStopReasonWithException( *stop_thread, desc_stream.str().c_str()); stop_thread->SetStopInfo(stop_info); - WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, "%s", desc_stream.str().c_str()); + LLDB_LOG(log, "{0}", desc_stream.str()); return; } } @@ -598,6 +564,7 @@ bool ProcessWindows::CanDebug(lldb::TargetSP target_sp, bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_THREAD); // Add all the threads that were previously running and for which we did not // detect a thread exited event. int new_size = 0; @@ -613,15 +580,10 @@ bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list, new_thread_list.AddThread(old_thread); ++new_size; ++continued_threads; - WINLOGV_IFALL( - WINDOWS_LOG_THREAD, - "UpdateThreadList - Thread %llu was running and is still running.", - old_thread_id); + LLDB_LOGV(log, "Thread {0} was running and is still running.", + old_thread_id); } else { - WINLOGV_IFALL( - WINDOWS_LOG_THREAD, - "UpdateThreadList - Thread %llu was running and has exited.", - old_thread_id); + LLDB_LOGV(log, "Thread {0} was running and has exited.", old_thread_id); ++exited_threads; } } @@ -634,15 +596,11 @@ bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list, new_thread_list.AddThread(thread); ++new_size; ++new_threads; - WINLOGV_IFALL(WINDOWS_LOG_THREAD, - "UpdateThreadList - Thread %llu is new since last update.", - thread_info.first); + LLDB_LOGV(log, "Thread {0} 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); + LLDB_LOG(log, "{0} new threads, {1} old threads, {2} exited threads.", + new_threads, continued_threads, exited_threads); m_session_data->m_new_threads.clear(); m_session_data->m_exited_threads.clear(); @@ -666,14 +624,14 @@ bool ProcessWindows::IsAlive() { size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Error &error) { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); llvm::sys::ScopedLock lock(m_mutex); if (!m_session_data) return 0; - WINLOG_IFALL(WINDOWS_LOG_MEMORY, - "DoReadMemory attempting to read %u bytes from address 0x%I64x", - size, vm_addr); + LLDB_LOG(log, "attempting to read {0} bytes from address {1:x}", size, + vm_addr); HostProcess process = m_session_data->m_debugger->GetProcess(); void *addr = reinterpret_cast<void *>(vm_addr); @@ -681,24 +639,20 @@ size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf, 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()); + LLDB_LOG(log, "reading failed with error: {0}", error); } return bytes_read; } size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, Error &error) { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); llvm::sys::ScopedLock lock(m_mutex); - WINLOG_IFALL( - WINDOWS_LOG_MEMORY, - "DoWriteMemory attempting to write %u bytes into address 0x%I64x", size, - vm_addr); + LLDB_LOG(log, "attempting to write {0} bytes into address {1:x}", size, + vm_addr); if (!m_session_data) { - WINERR_IFANY( - WINDOWS_LOG_MEMORY, - "DoWriteMemory cannot write, there is no active debugger connection."); + LLDB_LOG(log, "cannot write, there is no active debugger connection."); return 0; } @@ -710,16 +664,14 @@ size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf, FlushInstructionCache(handle, addr, bytes_written); else { error.SetError(GetLastError(), eErrorTypeWin32); - WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory failed with error code %u", - error.GetError()); + LLDB_LOG(log, "writing failed with error: {0}", error); } return bytes_written; } -#define BOOL_STR(b) ((b) ? "true" : "false") - Error ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr, MemoryRegionInfo &info) { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); Error error; llvm::sys::ScopedLock lock(m_mutex); info.Clear(); @@ -727,7 +679,7 @@ Error ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr, if (!m_session_data) { error.SetErrorString( "GetMemoryRegionInfo called with no debugging session."); - WINERR_IFALL(WINDOWS_LOG_MEMORY, "%s", error.AsCString()); + LLDB_LOG(log, "error: {0}", error); return error; } HostProcess process = m_session_data->m_debugger->GetProcess(); @@ -735,12 +687,11 @@ Error ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr, if (handle == nullptr || handle == LLDB_INVALID_PROCESS) { error.SetErrorString( "GetMemoryRegionInfo called with an invalid target process."); - WINERR_IFALL(WINDOWS_LOG_MEMORY, "%s", error.AsCString()); + LLDB_LOG(log, "error: {0}", error); return error; } - WINLOG_IFALL(WINDOWS_LOG_MEMORY, - "GetMemoryRegionInfo getting info for address 0x%I64x", vm_addr); + LLDB_LOG(log, "getting info for address {0:x}", vm_addr); void *addr = reinterpret_cast<void *>(vm_addr); MEMORY_BASIC_INFORMATION mem_info = {}; @@ -761,10 +712,9 @@ Error ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr, return error; } else { 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); + LLDB_LOG(log, "VirtualQueryEx returned error {0} while getting memory " + "region info for address {1:x}", + error, vm_addr); return error; } } @@ -806,10 +756,10 @@ Error ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr, } error.SetError(::GetLastError(), eErrorTypeWin32); - WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address %llu: " - "readable=%s, executable=%s, writable=%s", - vm_addr, BOOL_STR(info.GetReadable()), - BOOL_STR(info.GetExecutable()), BOOL_STR(info.GetWritable())); + LLDB_LOGV(log, "Memory region info for address {0}: readable={1}, " + "executable={2}, writable={3}", + vm_addr, info.GetReadable(), info.GetExecutable(), + info.GetWritable()); return error; } @@ -825,8 +775,8 @@ lldb::addr_t ProcessWindows::GetImageInfoAddress() { 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 %llu exited with code %u", GetID(), - exit_code); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); + LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code); TargetSP target = m_target_sp.lock(); if (target) { @@ -842,10 +792,9 @@ void ProcessWindows::OnExitProcess(uint32_t exit_code) { void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) { DebuggerThreadSP debugger = m_session_data->m_debugger; - - WINLOG_IFALL(WINDOWS_LOG_PROCESS, - "Debugger connected to process %I64u. Image base = 0x%I64x", - debugger->GetProcess().GetProcessId(), image_base); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); + LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}", + debugger->GetProcess().GetProcessId(), image_base); ModuleSP module = GetTarget().GetExecutableModule(); if (!module) { @@ -889,6 +838,7 @@ void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) { ExceptionResult ProcessWindows::OnDebugException(bool first_chance, const ExceptionRecord &record) { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION); llvm::sys::ScopedLock lock(m_mutex); // FIXME: Without this check, occasionally when running the test suite there @@ -901,10 +851,9 @@ ProcessWindows::OnDebugException(bool first_chance, // 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%lx at address 0x%llu, but there is " - "no session.", - record.GetExceptionCode(), record.GetExceptionAddress()); + LLDB_LOG(log, "Debugger thread reported exception {0:x} at address {1:x}, " + "but there is no session.", + record.GetExceptionCode(), record.GetExceptionAddress()); return ExceptionResult::SendToApplication; } @@ -920,16 +869,15 @@ ProcessWindows::OnDebugException(bool first_chance, result = ExceptionResult::BreakInDebugger; if (!m_session_data->m_initial_stop_received) { - WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, "Hit loader breakpoint at address " - "0x%I64x, setting initial stop " - "event.", - record.GetExceptionAddress()); + LLDB_LOG( + log, + "Hit loader breakpoint at address {0:x}, setting initial stop event.", + record.GetExceptionAddress()); m_session_data->m_initial_stop_received = true; ::SetEvent(m_session_data->m_initial_stop_event); } else { - WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, - "Hit non-loader breakpoint at address 0x%I64x.", - record.GetExceptionAddress()); + LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.", + record.GetExceptionAddress()); } SetPrivateState(eStateStopped); break; @@ -938,11 +886,10 @@ ProcessWindows::OnDebugException(bool first_chance, SetPrivateState(eStateStopped); break; default: - WINLOG_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception " - "0x%lx at address 0x%llx " - "(first_chance=%s)", - record.GetExceptionCode(), record.GetExceptionAddress(), - BOOL_STR(first_chance)); + LLDB_LOG(log, "Debugger thread reported exception {0:x} at address {1:x} " + "(first_chance={2})", + record.GetExceptionCode(), record.GetExceptionAddress(), + first_chance); // For non-breakpoints, give the application a chance to handle the // exception first. if (first_chance) @@ -1010,14 +957,14 @@ void ProcessWindows::OnDebugString(const std::string &string) {} void ProcessWindows::OnDebuggerError(const Error &error, uint32_t type) { llvm::sys::ScopedLock lock(m_mutex); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); 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()); + // to continue, or do something else? + LLDB_LOG(log, "Error {0} occurred during debugging. Unexpected behavior " + "may result. {1}", + error.GetError(), error); } else { // If we haven't actually launched the process yet, this was an error // launching the @@ -1026,10 +973,10 @@ void ProcessWindows::OnDebuggerError(const Error &error, uint32_t type) { // 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()); + LLDB_LOG( + log, + "Error {0} occurred launching the process before the initial stop. {1}", + error.GetError(), error); return; } } @@ -1037,14 +984,14 @@ void ProcessWindows::OnDebuggerError(const Error &error, uint32_t type) { Error ProcessWindows::WaitForDebuggerConnection(DebuggerThreadSP debugger, HostProcess &process) { Error result; - WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS, - "WaitForDebuggerConnection Waiting for loader breakpoint."); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS | + WINDOWS_LOG_BREAKPOINTS); + LLDB_LOG(log, "Waiting for loader breakpoint."); // 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) { - WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS, - "WaitForDebuggerConnection hit loader breakpoint, returning."); + LLDB_LOG(log, "hit loader breakpoint, returning."); process = debugger->GetProcess(); return m_session_data->m_launch_error; diff --git a/source/Plugins/Process/Windows/Common/ProcessWindows.h b/source/Plugins/Process/Windows/Common/ProcessWindows.h index fac06c46b2ba..f2db102299ae 100644 --- a/source/Plugins/Process/Windows/Common/ProcessWindows.h +++ b/source/Plugins/Process/Windows/Common/ProcessWindows.h @@ -11,8 +11,8 @@ #define liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_ // Other libraries and framework includes -#include "lldb/Core/Error.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/Error.h" #include "lldb/lldb-forward.h" #include "llvm/Support/Mutex.h" diff --git a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp b/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp index 242c1996bdd4..386e9a5816c5 100644 --- a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp +++ b/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp @@ -9,160 +9,33 @@ #include "ProcessWindowsLog.h" -#include <mutex> - -#include "lldb/Core/StreamFile.h" -#include "lldb/Interpreter/Args.h" -#include "llvm/Support/ManagedStatic.h" - -using namespace lldb; using namespace lldb_private; -// We want to avoid global constructors where code needs to be run so here we -// control access to our static g_log_sp by hiding it in a singleton function -// 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 = nullptr; +static constexpr Log::Category g_categories[] = { + {{"break"}, {"log breakpoints"}, WINDOWS_LOG_BREAKPOINTS}, + {{"event"}, {"log low level debugger events"}, WINDOWS_LOG_EVENT}, + {{"exception"}, {"log exception information"}, WINDOWS_LOG_EXCEPTION}, + {{"memory"}, {"log memory reads and writes"}, WINDOWS_LOG_MEMORY}, + {{"process"}, {"log process events and activities"}, WINDOWS_LOG_PROCESS}, + {{"registers"}, {"log register read/writes"}, WINDOWS_LOG_REGISTERS}, + {{"step"}, {"log step related activities"}, WINDOWS_LOG_STEP}, + {{"thread"}, {"log thread events and activities"}, WINDOWS_LOG_THREAD}, +}; -static llvm::ManagedStatic<std::once_flag> g_once_flag; +Log::Channel ProcessWindowsLog::g_channel(g_categories, WINDOWS_LOG_PROCESS); void ProcessWindowsLog::Initialize() { - static ConstString g_name("windows"); - - std::call_once(*g_once_flag, []() { - Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories}; - - Log::RegisterLogChannel(g_name, log_callbacks); - RegisterPluginName(g_name); - }); + static llvm::once_flag g_once_flag; + llvm::call_once(g_once_flag, []() { Log::Register("windows", g_channel); }); } void ProcessWindowsLog::Terminate() {} -Log *ProcessWindowsLog::GetLog() { 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, "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; -} -void ProcessWindowsLog::DisableLog(const char **args, Stream *feedback_strm) { - Log *log(GetLog()); - if (log) { - uint32_t flag_bits = 0; - if (args[0] != nullptr) { - flag_bits = log->GetMask().Get(); - for (; args[0]; args++) { - const char *arg = args[0]; - uint32_t bits = GetFlagBits(arg); - if (bits) { - flag_bits &= ~bits; - } else { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories(feedback_strm); - } - } - } - log->GetMask().Reset(flag_bits); - if (flag_bits == 0) { - g_log_enabled = false; - log->SetStream(lldb::StreamSP()); - } - } - return; -} - -Log *ProcessWindowsLog::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, - const char **args, Stream *feedback_strm) { - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the - // same. - uint32_t flag_bits = 0; - if (g_log) - flag_bits = g_log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) { - if (g_log) - g_log->SetStream(log_stream_sp); - else - g_log = new Log(log_stream_sp); - } - - if (g_log) { - bool got_unknown_category = false; - for (; args[0]; args++) { - const char *arg = args[0]; - uint32_t bits = GetFlagBits(arg); - - if (bits) { - flag_bits |= bits; - } else { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) { - got_unknown_category = true; - ListLogCategories(feedback_strm); - } - } - } - if (flag_bits == 0) - flag_bits = WINDOWS_LOG_ALL; - g_log->GetMask().Reset(flag_bits); - g_log->GetOptions().Reset(log_options); - g_log_enabled = true; - } - return g_log; -} - -void ProcessWindowsLog::ListLogCategories(Stream *strm) { - 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); -} -const char *ProcessWindowsLog::m_pluginname = ""; diff --git a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h b/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h index cbb99e8d907e..b7f59c708143 100644 --- a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h +++ b/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h @@ -10,9 +10,8 @@ #ifndef liblldb_ProcessWindowsLog_h_ #define liblldb_ProcessWindowsLog_h_ -#include "lldb/Core/Log.h" +#include "lldb/Utility/Log.h" -#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 @@ -21,71 +20,17 @@ #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) - -enum class LogMaskReq { All, Any }; +namespace lldb_private { class ProcessWindowsLog { - static const char *m_pluginname; + static Log::Channel g_channel; public: - // --------------------------------------------------------------------- - // Public Static Methods - // --------------------------------------------------------------------- static void Initialize(); - static void Terminate(); - static void RegisterPluginName(const char *pluginName) { - m_pluginname = pluginName; - } - - static void RegisterPluginName(lldb_private::ConstString pluginName) { - m_pluginname = pluginName.GetCString(); - } - - static bool TestLogFlags(uint32_t mask, LogMaskReq req); - - static lldb_private::Log *GetLog(); - - static void DisableLog(const char **args, - lldb_private::Stream *feedback_strm); - - static lldb_private::Log *EnableLog(lldb::StreamSP &log_stream_sp, - uint32_t log_options, const char **args, - lldb_private::Stream *feedback_strm); - - static void ListLogCategories(lldb_private::Stream *strm); + static Log *GetLogIfAny(uint32_t mask) { return g_channel.GetLogIfAny(mask); } }; - -#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_ diff --git a/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp b/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp index 0ef3c77e47c1..bfed3044910d 100644 --- a/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp +++ b/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Error.h" #include "lldb/lldb-private-types.h" #include "ProcessWindowsLog.h" @@ -113,6 +113,7 @@ bool RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) { bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; } bool RegisterContextWindows::CacheAllRegisterValues() { + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS); if (!m_context_stale) return true; @@ -122,14 +123,13 @@ bool RegisterContextWindows::CacheAllRegisterValues() { if (!::GetThreadContext( wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context)) { - WINERR_IFALL( - WINDOWS_LOG_REGISTERS, - "GetThreadContext failed with error %lu while caching register values.", + LLDB_LOG( + log, + "GetThreadContext failed with error {0} while caching register values.", ::GetLastError()); return false; } - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, - "GetThreadContext successfully updated the register values."); + LLDB_LOG(log, "successfully updated the register values."); m_context_stale = false; return true; } diff --git a/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp b/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp index 8f2603c3365b..a4d60303877e 100644 --- a/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp +++ b/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/Log.h" -#include "lldb/Core/Logging.h" #include "lldb/Core/State.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/HostNativeThreadBase.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Logging.h" #include "ProcessWindows.h" #include "ProcessWindowsLog.h" diff --git a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp index 942b4e97c40d..53fe1d902494 100644 --- a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp +++ b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/Utility/Error.h" #include "lldb/lldb-private-types.h" #include "RegisterContextWindows_x64.h" diff --git a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp index 2938f77f3c2a..8127606583cd 100644 --- a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp +++ b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" +#include "lldb/Utility/Error.h" #include "lldb/lldb-private-types.h" #include "ProcessWindowsLog.h" @@ -203,7 +203,8 @@ bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info, return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags, reg_value); default: - WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Requested unknown register %u", reg); + Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS); + LLDB_LOG(log, "Requested unknown register {0}", reg); break; } return false; @@ -219,62 +220,52 @@ bool RegisterContextWindows_x86::WriteRegister(const RegisterInfo *reg_info, if (!CacheAllRegisterValues()) return false; + Log *log = ProcessWindowsLog::GetLogIfAny(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(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::WriteRegister(const RegisterInfo *reg_info, bool RegisterContextWindows_x86::ReadRegisterHelper( DWORD flags_required, const char *reg_name, DWORD value, RegisterValue ®_value) const { + Log *log = ProcessWindowsLog::GetLogIfAny(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; } diff --git a/source/Plugins/Process/elf-core/CMakeLists.txt b/source/Plugins/Process/elf-core/CMakeLists.txt index b9f0b6cdfb7c..b358697d25af 100644 --- a/source/Plugins/Process/elf-core/CMakeLists.txt +++ b/source/Plugins/Process/elf-core/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(../Utility) -add_lldb_library(lldbPluginProcessElfCore +add_lldb_library(lldbPluginProcessElfCore PLUGIN ProcessElfCore.cpp ThreadElfCore.cpp RegisterContextPOSIXCore_arm.cpp @@ -9,4 +9,13 @@ add_lldb_library(lldbPluginProcessElfCore RegisterContextPOSIXCore_powerpc.cpp RegisterContextPOSIXCore_s390x.cpp RegisterContextPOSIXCore_x86_64.cpp + + LINK_LIBS + lldbCore + lldbTarget + lldbPluginDynamicLoaderPosixDYLD + lldbPluginObjectFileELF + lldbPluginProcessUtility + LINK_COMPONENTS + Support ) diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 6ac308fe559c..6561d2a05828 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -14,8 +14,6 @@ #include <mutex> // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -25,8 +23,12 @@ #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/UnixSignals.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataBufferLLVM.h" +#include "lldb/Utility/Log.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/Threading.h" #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" @@ -56,9 +58,12 @@ lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp, lldb::ProcessSP process_sp; if (crash_file) { // Read enough data for a ELF32 header or ELF64 header + // Note: Here we care about e_type field only, so it is safe + // to ignore possible presence of the header extension. const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr); - lldb::DataBufferSP data_sp(crash_file->ReadFileContents(0, header_size)); + auto data_sp = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), + header_size, 0); if (data_sp && data_sp->GetByteSize() == header_size && elf::ELFHeader::MagicBytesMatch(data_sp->GetBytes())) { elf::ELFHeader elf_header; @@ -209,16 +214,19 @@ Error ProcessElfCore::DoLoadCore() { // Even if the architecture is set in the target, we need to override // it to match the core file which is always single arch. ArchSpec arch(m_core_module_sp->GetArchitecture()); - if (arch.IsValid()) - GetTarget().SetArchitecture(arch); + ArchSpec target_arch = GetTarget().GetArchitecture(); + ArchSpec core_arch(m_core_module_sp->GetArchitecture()); + target_arch.MergeFrom(core_arch); + GetTarget().SetArchitecture(target_arch); + SetUnixSignals(UnixSignals::Create(GetArchitecture())); // Ensure we found at least one thread that was stopped on a signal. bool siginfo_signal_found = false; bool prstatus_signal_found = false; // Check we found a signal in a SIGINFO note. - for (const auto &thread_data: m_thread_data) { + for (const auto &thread_data : m_thread_data) { if (thread_data.signo != 0) siginfo_signal_found = true; if (thread_data.prstatus_sig != 0) @@ -228,7 +236,7 @@ Error ProcessElfCore::DoLoadCore() { // If we don't have signal from SIGINFO use the signal from each threads // PRSTATUS note. if (prstatus_signal_found) { - for (auto &thread_data: m_thread_data) + for (auto &thread_data : m_thread_data) thread_data.signo = thread_data.prstatus_sig; } else if (m_thread_data.size() > 0) { // If all else fails force the first thread to be SIGSTOP @@ -365,6 +373,10 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb::addr_t bytes_left = 0; // Number of bytes available in the core file from the given address + // Don't proceed if core file doesn't contain the actual data for this address range. + if (file_start == file_end) + return 0; + // Figure out how many on-disk bytes remain in this segment // starting at the given offset if (file_end > file_start + offset) @@ -398,9 +410,9 @@ void ProcessElfCore::Clear() { } void ProcessElfCore::Initialize() { - static std::once_flag g_once_flag; + static llvm::once_flag g_once_flag; - std::call_once(g_once_flag, []() { + llvm::call_once(g_once_flag, []() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); }); @@ -426,6 +438,10 @@ enum { NT_FILE = 0x46494c45, NT_PRXFPREG = 0x46e62b7f, NT_SIGINFO = 0x53494749, + NT_OPENBSD_PROCINFO = 10, + NT_OPENBSD_AUXV = 11, + NT_OPENBSD_REGS = 20, + NT_OPENBSD_FPREGS = 21, }; namespace FREEBSD { @@ -440,6 +456,11 @@ enum { }; } +namespace NETBSD { + +enum { NT_PROCINFO = 1, NT_AUXV, NT_AMD64_REGS = 33, NT_AMD64_FPREGS = 35 }; +} + // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, ArchSpec &arch) { @@ -476,6 +497,28 @@ static void ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) { thread_data.name = data.GetCStr(&offset, 20); } +static void ParseNetBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { + lldb::offset_t offset = 0; + + int version = data.GetU32(&offset); + if (version != 1) + return; + + offset += 4; + thread_data.signo = data.GetU32(&offset); +} + +static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { + lldb::offset_t offset = 0; + + int version = data.GetU32(&offset); + if (version != 1) + return; + + offset += 4; + thread_data.signo = data.GetU32(&offset); +} + /// Parse Thread context from PT_NOTE segment and store it in the thread list /// Notes: /// 1) A PT_NOTE segment is composed of one or more NOTE entries. @@ -564,6 +607,39 @@ Error ProcessElfCore::ParseThreadContextsFromNoteSegment( default: break; } + } else if (note.n_name.substr(0, 11) == "NetBSD-CORE") { + // NetBSD per-thread information is stored in notes named + // "NetBSD-CORE@nnn" so match on the initial part of the string. + m_os = llvm::Triple::NetBSD; + if (note.n_type == NETBSD::NT_PROCINFO) { + ParseNetBSDProcInfo(*thread_data, note_data); + } else if (note.n_type == NETBSD::NT_AUXV) { + m_auxv = DataExtractor(note_data); + } else if (arch.GetMachine() == llvm::Triple::x86_64 && + note.n_type == NETBSD::NT_AMD64_REGS) { + thread_data->gpregset = note_data; + } else if (arch.GetMachine() == llvm::Triple::x86_64 && + note.n_type == NETBSD::NT_AMD64_FPREGS) { + thread_data->fpregset = note_data; + } + } else if (note.n_name.substr(0, 7) == "OpenBSD") { + // OpenBSD per-thread information is stored in notes named + // "OpenBSD@nnn" so match on the initial part of the string. + m_os = llvm::Triple::OpenBSD; + switch (note.n_type) { + case NT_OPENBSD_PROCINFO: + ParseOpenBSDProcInfo(*thread_data, note_data); + break; + case NT_OPENBSD_AUXV: + m_auxv = DataExtractor(note_data); + break; + case NT_OPENBSD_REGS: + thread_data->gpregset = note_data; + break; + case NT_OPENBSD_FPREGS: + thread_data->fpregset = note_data; + break; + } } else if (note.n_name == "CORE") { switch (note.n_type) { case NT_PRSTATUS: @@ -583,6 +659,8 @@ Error ProcessElfCore::ParseThreadContextsFromNoteSegment( // The result from FXSAVE is in NT_PRXFPREG for i386 core files if (arch.GetCore() == ArchSpec::eCore_x86_64_x86_64) thread_data->fpregset = note_data; + else if(arch.IsMIPS()) + thread_data->fpregset = note_data; break; case NT_PRPSINFO: have_prpsinfo = true; @@ -650,6 +728,12 @@ ArchSpec ProcessElfCore::GetArchitecture() { (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); ArchSpec arch; core_file->GetArchitecture(arch); + + ArchSpec target_arch = GetTarget().GetArchitecture(); + + if (target_arch.IsMIPS()) + return target_arch; + return arch; } diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.h b/source/Plugins/Process/elf-core/ProcessElfCore.h index a8dde47b3079..cb2f31bde4c5 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -24,9 +24,9 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/ConstString.h" -#include "lldb/Core/Error.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Error.h" #include "Plugins/ObjectFile/ELF/ELFHeader.h" diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h index c0850e5e414e..e095eac5eaf8 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h @@ -15,8 +15,8 @@ // Other libraries and framework includes // Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" class RegisterContextCorePOSIX_arm : public RegisterContextPOSIX_arm { public: diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h index da3e5bff605c..3a2bbdb0a2eb 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h @@ -15,8 +15,8 @@ // Other libraries and framework includes // Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 { public: diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp index 6a168d314fd7..7549cf074be7 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp @@ -22,6 +22,10 @@ RegisterContextCorePOSIX_mips64::RegisterContextCorePOSIX_mips64( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); m_gpr.SetData(m_gpr_buffer); m_gpr.SetByteOrder(gpregset.GetByteOrder()); + m_fpr_buffer.reset( + new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); + m_fpr.SetData(m_fpr_buffer); + m_fpr.SetByteOrder(fpregset.GetByteOrder()); } RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64() {} @@ -42,12 +46,24 @@ bool RegisterContextCorePOSIX_mips64::WriteFPR() { bool RegisterContextCorePOSIX_mips64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) { + lldb::offset_t offset = reg_info->byte_offset; - uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); - if (offset == reg_info->byte_offset + reg_info->byte_size) { + lldb_private::ArchSpec arch = m_register_info_ap->GetTargetArchitecture(); + uint64_t v; + if (IsGPR(reg_info->kinds[lldb::eRegisterKindLLDB])) { + if (reg_info->byte_size == 4 && !(arch.GetMachine() == llvm::Triple::mips64el)) + // In case of 32bit core file, the register data are placed at 4 byte + // offset. + offset = offset / 2; + v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); value = v; return true; - } + } else if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) { + offset = offset - sizeof(GPR_linux_mips); + v =m_fpr.GetMaxU64(&offset, reg_info->byte_size); + value = v; + return true; + } return false; } diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h index b1deca3d3178..2cb527a8de7c 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h @@ -15,8 +15,8 @@ // Other libraries and framework includes // Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" class RegisterContextCorePOSIX_mips64 : public RegisterContextPOSIX_mips64 { public: @@ -51,7 +51,9 @@ protected: private: lldb::DataBufferSP m_gpr_buffer; + lldb::DataBufferSP m_fpr_buffer; lldb_private::DataExtractor m_gpr; + lldb_private::DataExtractor m_fpr; }; #endif // liblldb_RegisterContextCorePOSIX_mips64_h_ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp index edfa1902c327..62f6413722f7 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp @@ -9,9 +9,9 @@ #include "RegisterContextPOSIXCore_powerpc.h" -#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" using namespace lldb_private; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h index 8e6315f06636..aaa95e5d2397 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h @@ -15,7 +15,7 @@ // Other libraries and framework includes // Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h" -#include "lldb/Core/DataExtractor.h" +#include "lldb/Utility/DataExtractor.h" class RegisterContextCorePOSIX_powerpc : public RegisterContextPOSIX_powerpc { public: diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp index 6db817789612..b3530a8d6a42 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp @@ -9,9 +9,9 @@ #include "RegisterContextPOSIXCore_s390x.h" -#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" using namespace lldb_private; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h index 516e5c57e2b9..2b4ae10a87bd 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h @@ -15,7 +15,7 @@ // Other libraries and framework includes // Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_s390x.h" -#include "lldb/Core/DataExtractor.h" +#include "lldb/Utility/DataExtractor.h" class RegisterContextCorePOSIX_s390x : public RegisterContextPOSIX_s390x { public: diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp index 7f8223f7752e..260ae15d7a54 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// #include "RegisterContextPOSIXCore_x86_64.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataExtractor.h" using namespace lldb_private; diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index bdf0c69bef24..13ad82d92c5d 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -7,22 +7,26 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Unwind.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Log.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" -#include "Plugins/Process/Utility/RegisterContextLinux_arm.h" +#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" +#include "Plugins/Process/Utility/RegisterContextLinux_mips.h" #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" +#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" +#include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h" +#include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" #include "ProcessElfCore.h" #include "RegisterContextPOSIXCore_arm.h" @@ -88,7 +92,7 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { reg_interface = new RegisterInfoPOSIX_arm64(arch); break; case llvm::Triple::arm: - reg_interface = new RegisterContextFreeBSD_arm(arch); + reg_interface = new RegisterInfoPOSIX_arm(arch); break; case llvm::Triple::ppc: reg_interface = new RegisterContextFreeBSD_powerpc32(arch); @@ -111,14 +115,33 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { break; } + case llvm::Triple::NetBSD: { + switch (arch.GetMachine()) { + case llvm::Triple::x86_64: + reg_interface = new RegisterContextNetBSD_x86_64(arch); + break; + default: + break; + } + break; + } + case llvm::Triple::Linux: { switch (arch.GetMachine()) { case llvm::Triple::arm: - reg_interface = new RegisterContextLinux_arm(arch); + reg_interface = new RegisterInfoPOSIX_arm(arch); break; case llvm::Triple::aarch64: reg_interface = new RegisterInfoPOSIX_arm64(arch); break; + case llvm::Triple::mipsel: + case llvm::Triple::mips: + reg_interface = new RegisterContextLinux_mips(arch); + break; + case llvm::Triple::mips64el: + case llvm::Triple::mips64: + reg_interface = new RegisterContextLinux_mips64(arch); + break; case llvm::Triple::systemz: reg_interface = new RegisterContextLinux_s390x(arch); break; @@ -134,6 +157,26 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { break; } + case llvm::Triple::OpenBSD: { + switch (arch.GetMachine()) { + case llvm::Triple::aarch64: + reg_interface = new RegisterInfoPOSIX_arm64(arch); + break; + case llvm::Triple::arm: + reg_interface = new RegisterInfoPOSIX_arm(arch); + break; + case llvm::Triple::x86: + reg_interface = new RegisterContextOpenBSD_i386(arch); + break; + case llvm::Triple::x86_64: + reg_interface = new RegisterContextOpenBSD_x86_64(arch); + break; + default: + break; + } + break; + } + default: break; } @@ -154,7 +197,13 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm( *this, reg_interface, m_gpregset_data, m_fpregset_data)); break; + case llvm::Triple::mipsel: + case llvm::Triple::mips: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64( + *this, reg_interface, m_gpregset_data, m_fpregset_data)); + break; case llvm::Triple::mips64: + case llvm::Triple::mips64el: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64( *this, reg_interface, m_gpregset_data, m_fpregset_data)); break; @@ -200,6 +249,31 @@ ELFLinuxPrStatus::ELFLinuxPrStatus() { memset(this, 0, sizeof(ELFLinuxPrStatus)); } +size_t ELFLinuxPrStatus::GetSize(lldb_private::ArchSpec &arch) { + constexpr size_t mips_linux_pr_status_size_o32 = 96; + constexpr size_t mips_linux_pr_status_size_n32 = 72; + if (arch.IsMIPS()) { + std::string abi = arch.GetTargetABI(); + assert(!abi.empty() && "ABI is not set"); + if (!abi.compare("n64")) + return sizeof(ELFLinuxPrStatus); + else if (!abi.compare("o32")) + return mips_linux_pr_status_size_o32; + // N32 ABI + return mips_linux_pr_status_size_n32; + } + switch (arch.GetCore()) { + case lldb_private::ArchSpec::eCore_s390x_generic: + case lldb_private::ArchSpec::eCore_x86_64_x86_64: + return sizeof(ELFLinuxPrStatus); + case lldb_private::ArchSpec::eCore_x86_32_i386: + case lldb_private::ArchSpec::eCore_x86_32_i486: + return 72; + default: + return 0; + } +} + Error ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) { Error error; if (GetSize(arch) > data.GetByteSize()) { @@ -239,7 +313,6 @@ Error ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) { pr_cstime.tv_sec = data.GetPointer(&offset); pr_cstime.tv_usec = data.GetPointer(&offset); - return error; } @@ -250,6 +323,27 @@ ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() { memset(this, 0, sizeof(ELFLinuxPrPsInfo)); } +size_t ELFLinuxPrPsInfo::GetSize(lldb_private::ArchSpec &arch) { + constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128; + if (arch.IsMIPS()) { + uint8_t address_byte_size = arch.GetAddressByteSize(); + if (address_byte_size == 8) + return sizeof(ELFLinuxPrPsInfo); + return mips_linux_pr_psinfo_size_o32_n32; + } + + switch (arch.GetCore()) { + case lldb_private::ArchSpec::eCore_s390x_generic: + case lldb_private::ArchSpec::eCore_x86_64_x86_64: + return sizeof(ELFLinuxPrPsInfo); + case lldb_private::ArchSpec::eCore_x86_32_i386: + case lldb_private::ArchSpec::eCore_x86_32_i486: + return 124; + default: + return 0; + } +} + Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) { Error error; ByteOrder byteorder = data.GetByteOrder(); @@ -273,9 +367,15 @@ Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) { pr_flag = data.GetPointer(&offset); + if (arch.IsMIPS()) { + // The pr_uid and pr_gid is always 32 bit irrespective of platforms + pr_uid = data.GetU32(&offset); + pr_gid = data.GetU32(&offset); + } else { // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1); pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1); + } pr_pid = data.GetU32(&offset); pr_ppid = data.GetU32(&offset); @@ -296,8 +396,21 @@ Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) { //---------------------------------------------------------------- // Parse SIGINFO from NOTE entry //---------------------------------------------------------------- -ELFLinuxSigInfo::ELFLinuxSigInfo() { - memset(this, 0, sizeof(ELFLinuxSigInfo)); +ELFLinuxSigInfo::ELFLinuxSigInfo() { memset(this, 0, sizeof(ELFLinuxSigInfo)); } + +size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) { + if (arch.IsMIPS()) + return sizeof(ELFLinuxSigInfo); + switch (arch.GetCore()) { + case lldb_private::ArchSpec::eCore_x86_64_x86_64: + return sizeof(ELFLinuxSigInfo); + case lldb_private::ArchSpec::eCore_s390x_generic: + case lldb_private::ArchSpec::eCore_x86_32_i386: + case lldb_private::ArchSpec::eCore_x86_32_i486: + return 12; + default: + return 0; + } } Error ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) { diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h index 1957ac243ceb..38c52658a23a 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -16,8 +16,8 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/DataExtractor.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataExtractor.h" struct compat_timeval { alignas(8) uint64_t tv_sec; @@ -65,18 +65,7 @@ struct ELFLinuxPrStatus { // 32 bit - hardcoded because we are reusing the struct, but some of the // members are smaller - // so the layout is not the same - static size_t GetSize(lldb_private::ArchSpec &arch) { - switch (arch.GetCore()) { - case lldb_private::ArchSpec::eCore_s390x_generic: - case lldb_private::ArchSpec::eCore_x86_64_x86_64: - return sizeof(ELFLinuxPrStatus); - case lldb_private::ArchSpec::eCore_x86_32_i386: - case lldb_private::ArchSpec::eCore_x86_32_i486: - return 72; - default: - return 0; - } - } + static size_t GetSize(lldb_private::ArchSpec &arch); }; static_assert(sizeof(ELFLinuxPrStatus) == 112, @@ -97,18 +86,7 @@ struct ELFLinuxSigInfo { // 32 bit - hardcoded because we are reusing the struct, but some of the // members are smaller - // so the layout is not the same - static size_t GetSize(const lldb_private::ArchSpec &arch) { - switch (arch.GetCore()) { - case lldb_private::ArchSpec::eCore_x86_64_x86_64: - return sizeof(ELFLinuxSigInfo); - case lldb_private::ArchSpec::eCore_s390x_generic: - case lldb_private::ArchSpec::eCore_x86_32_i386: - case lldb_private::ArchSpec::eCore_x86_32_i486: - return 12; - default: - return 0; - } - } + static size_t GetSize(const lldb_private::ArchSpec &arch); }; static_assert(sizeof(ELFLinuxSigInfo) == 12, @@ -143,18 +121,7 @@ struct ELFLinuxPrPsInfo { // 32 bit - hardcoded because we are reusing the struct, but some of the // members are smaller - // so the layout is not the same - static size_t GetSize(lldb_private::ArchSpec &arch) { - switch (arch.GetCore()) { - case lldb_private::ArchSpec::eCore_s390x_generic: - case lldb_private::ArchSpec::eCore_x86_64_x86_64: - return sizeof(ELFLinuxPrPsInfo); - case lldb_private::ArchSpec::eCore_x86_32_i386: - case lldb_private::ArchSpec::eCore_x86_32_i486: - return 124; - default: - return 0; - } - } + static size_t GetSize(lldb_private::ArchSpec &arch); }; static_assert(sizeof(ELFLinuxPrPsInfo) == 136, diff --git a/source/Plugins/Process/gdb-remote/CMakeLists.txt b/source/Plugins/Process/gdb-remote/CMakeLists.txt index b28522725868..3d008f42499d 100644 --- a/source/Plugins/Process/gdb-remote/CMakeLists.txt +++ b/source/Plugins/Process/gdb-remote/CMakeLists.txt @@ -2,7 +2,20 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") include_directories(${LIBXML2_INCLUDE_DIR}) endif() -add_lldb_library(lldbPluginProcessGDBRemote +set(LLDB_PLUGINS + lldbPluginProcessUtility + lldbPluginPlatformMacOSX +) + +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android") + list(APPEND LLDB_PLUGINS lldbPluginProcessLinux) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") + list(APPEND LLDB_PLUGINS lldbPluginProcessNetBSD) +endif() + +add_lldb_library(lldbPluginProcessGDBRemote PLUGIN GDBRemoteClientBase.cpp GDBRemoteCommunication.cpp GDBRemoteCommunicationClient.cpp @@ -14,4 +27,17 @@ add_lldb_library(lldbPluginProcessGDBRemote ProcessGDBRemote.cpp ProcessGDBRemoteLog.cpp ThreadGDBRemote.cpp + + LINK_LIBS + lldbBreakpoint + lldbCore + lldbDataFormatters + lldbHost + lldbInterpreter + lldbSymbol + lldbTarget + lldbUtility + ${LLDB_PLUGINS} + LINK_COMPONENTS + Support ) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index bd87521fe6e7..7ef253decad6 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -16,12 +16,8 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/Log.h" -#include "lldb/Core/RegularExpression.h" #include "lldb/Core/StreamFile.h" -#include "lldb/Core/StreamString.h" #include "lldb/Host/ConnectionFileDescriptor.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/Pipe.h" @@ -30,6 +26,10 @@ #include "lldb/Host/ThreadLauncher.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegularExpression.h" +#include "lldb/Utility/StreamString.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ScopedPrinter.h" @@ -72,7 +72,7 @@ void GDBRemoteCommunication::History::AddPacket(char packet_char, m_packets[idx].type = type; m_packets[idx].bytes_transmitted = bytes_transmitted; m_packets[idx].packet_idx = m_total_packet_count; - m_packets[idx].tid = Host::GetCurrentThreadID(); + m_packets[idx].tid = llvm::get_threadid(); } } @@ -87,7 +87,7 @@ void GDBRemoteCommunication::History::AddPacket(const std::string &src, m_packets[idx].type = type; m_packets[idx].bytes_transmitted = bytes_transmitted; m_packets[idx].packet_idx = m_total_packet_count; - m_packets[idx].tid = Host::GetCurrentThreadID(); + m_packets[idx].tid = llvm::get_threadid(); } } @@ -321,8 +321,7 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet, uint8_t buffer[8192]; Error error; - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS | - GDBR_LOG_VERBOSE)); + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); // Check for a packet from our cache first without trying any reading... if (CheckForPacket(NULL, 0, packet) != PacketType::Invalid) @@ -334,12 +333,11 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet, lldb::ConnectionStatus status = eConnectionStatusNoConnection; size_t bytes_read = Read(buffer, sizeof(buffer), timeout, status, &error); - if (log) - log->Printf("%s: Read (buffer, (sizeof(buffer), timeout = %ld us, " - "status = %s, error = %s) => bytes_read = %" PRIu64, - LLVM_PRETTY_FUNCTION, long(timeout ? timeout->count() : -1), - Communication::ConnectionStatusAsCString(status), - error.AsCString(), (uint64_t)bytes_read); + LLDB_LOGV(log, + "Read(buffer, sizeof(buffer), timeout = {0}, " + "status = {1}, error = {2}) => bytes_read = {3}", + timeout, Communication::ConnectionStatusAsCString(status), error, + bytes_read); if (bytes_read > 0) { if (CheckForPacket(buffer, bytes_read, packet) != PacketType::Invalid) @@ -607,10 +605,10 @@ bool GDBRemoteCommunication::DecompressPacket() { m_compression_type == CompressionType::LZFSE || m_compression_type == CompressionType::LZ4)) { compression_algorithm compression_type; - if (m_compression_type == CompressionType::ZlibDeflate) - compression_type = COMPRESSION_ZLIB; - else if (m_compression_type == CompressionType::LZFSE) + if (m_compression_type == CompressionType::LZFSE) compression_type = COMPRESSION_LZFSE; + else if (m_compression_type == CompressionType::ZlibDeflate) + compression_type = COMPRESSION_ZLIB; else if (m_compression_type == CompressionType::LZ4) compression_type = COMPRESSION_LZ4_RAW; else if (m_compression_type == CompressionType::LZMA) @@ -1085,8 +1083,7 @@ Error GDBRemoteCommunication::StartDebugserverProcess( // port is null when debug server should listen on domain socket - // we're not interested in port value but rather waiting for debug server // to become available. - if (pass_comm_fd == -1 && - ((port != nullptr && *port == 0) || port == nullptr)) { + if (pass_comm_fd == -1) { if (url) { // Create a temporary file to get the stdout/stderr and redirect the // output of the command into this file. We will later read this file @@ -1258,11 +1255,21 @@ Error GDBRemoteCommunication::StartDebugserverProcess( port_cstr, num_bytes, std::chrono::seconds{10}, num_bytes); if (error.Success() && (port != nullptr)) { assert(num_bytes > 0 && port_cstr[num_bytes - 1] == '\0'); - *port = StringConvert::ToUInt32(port_cstr, 0); - if (log) - log->Printf("GDBRemoteCommunication::%s() " - "debugserver listens %u port", - __FUNCTION__, *port); + uint16_t child_port = StringConvert::ToUInt32(port_cstr, 0); + if (*port == 0 || *port == child_port) { + *port = child_port; + if (log) + log->Printf("GDBRemoteCommunication::%s() " + "debugserver listens %u port", + __FUNCTION__, *port); + } else { + if (log) + log->Printf("GDBRemoteCommunication::%s() " + "debugserver listening on port " + "%d but requested port was %d", + __FUNCTION__, (uint32_t)child_port, + (uint32_t)(*port)); + } } else { if (log) log->Printf("GDBRemoteCommunication::%s() " diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index b70f0903dbd5..2e94fa94331d 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -18,21 +18,20 @@ #include <sstream> // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Log.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/State.h" -#include "lldb/Core/StreamGDBRemote.h" -#include "lldb/Core/StreamString.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Args.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/UnixSignals.h" +#include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/JSON.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamGDBRemote.h" +#include "lldb/Utility/StreamString.h" // Project includes #include "ProcessGDBRemote.h" @@ -87,6 +86,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() m_supports_jThreadExtendedInfo(eLazyBoolCalculate), m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), m_supports_jGetSharedCacheInfo(eLazyBoolCalculate), + m_supports_QPassSignals(eLazyBoolCalculate), m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true), m_supports_qUserName(true), m_supports_qGroupName(true), m_supports_qThreadStopInfo(true), m_supports_z0(true), @@ -150,6 +150,13 @@ bool GDBRemoteCommunicationClient::GetEchoSupported() { return m_supports_qEcho == eLazyBoolYes; } +bool GDBRemoteCommunicationClient::GetQPassSignalsSupported() { + if (m_supports_QPassSignals == eLazyBoolCalculate) { + GetRemoteQSupported(); + } + return m_supports_QPassSignals == eLazyBoolYes; +} + bool GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported() { if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) { GetRemoteQSupported(); @@ -419,6 +426,11 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { else m_supports_qEcho = eLazyBoolNo; + if (::strstr(response_cstr, "QPassSignals+")) + m_supports_QPassSignals = eLazyBoolYes; + else + m_supports_QPassSignals = eLazyBoolNo; + const char *packet_size_str = ::strstr(response_cstr, "PacketSize="); if (packet_size_str) { StringExtractorGDBRemote packet_response(packet_size_str + @@ -1491,13 +1503,18 @@ Error GDBRemoteCommunicationClient::GetMemoryRegionInfo( } } - // We got a valid address range back but no permissions -- which means - // this is an unmapped page - if (region_info.GetRange().IsValid() && saw_permissions == false) { - region_info.SetReadable(MemoryRegionInfo::eNo); - region_info.SetWritable(MemoryRegionInfo::eNo); - region_info.SetExecutable(MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eNo); + if (region_info.GetRange().IsValid()) { + // We got a valid address range back but no permissions -- which means + // this is an unmapped page + if (!saw_permissions) { + region_info.SetReadable(MemoryRegionInfo::eNo); + region_info.SetWritable(MemoryRegionInfo::eNo); + region_info.SetExecutable(MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); + } + } else { + // We got an invalid address range back + error.SetErrorString("Server returned invalid range"); } } else { m_supports_memory_region_info = eLazyBoolNo; @@ -1660,7 +1677,7 @@ bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) { return false; std::string cwd; response.GetHexByteString(cwd); - working_dir.SetFile(cwd, false, GetHostArchitecture()); + working_dir.SetFile(cwd, false, GetHostArchitecture().GetTriple()); return !cwd.empty(); } return false; @@ -1907,6 +1924,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name); assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat); + assert(triple.getObjectFormat() != llvm::Triple::Wasm); switch (triple.getObjectFormat()) { case llvm::Triple::MachO: m_process_arch.SetArchitecture(eArchTypeMachO, cpu, sub); @@ -1917,6 +1935,10 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { case llvm::Triple::COFF: m_process_arch.SetArchitecture(eArchTypeCOFF, cpu, sub); break; + case llvm::Triple::Wasm: + if (log) + log->Printf("error: not supported target architecture"); + return false; case llvm::Triple::UnknownObjectFormat: if (log) log->Printf("error: failed to determine target architecture"); @@ -1957,29 +1979,29 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses( bool has_name_match = false; if (name && name[0]) { has_name_match = true; - NameMatchType name_match_type = match_info.GetNameMatchType(); + NameMatch name_match_type = match_info.GetNameMatchType(); switch (name_match_type) { - case eNameMatchIgnore: + case NameMatch::Ignore: has_name_match = false; break; - case eNameMatchEquals: + case NameMatch::Equals: packet.PutCString("name_match:equals;"); break; - case eNameMatchContains: + case NameMatch::Contains: packet.PutCString("name_match:contains;"); break; - case eNameMatchStartsWith: + case NameMatch::StartsWith: packet.PutCString("name_match:starts_with;"); break; - case eNameMatchEndsWith: + case NameMatch::EndsWith: packet.PutCString("name_match:ends_with;"); break; - case eNameMatchRegularExpression: + case NameMatch::RegularExpression: packet.PutCString("name_match:regex;"); break; } @@ -2190,23 +2212,19 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, const duration<float> standard_deviation = calculate_standard_deviation(packet_times); if (json) { - strm.Printf("%s\n {\"send_size\" : %6" PRIu32 - ", \"recv_size\" : %6" PRIu32 - ", \"total_time_nsec\" : %12" PRIu64 - ", \"standard_deviation_nsec\" : %9" PRIu64 " }", + strm.Format("{0}\n {{\"send_size\" : {1,6}, \"recv_size\" : " + "{2,6}, \"total_time_nsec\" : {3,12:ns-}, " + "\"standard_deviation_nsec\" : {4,9:ns-f0}}", result_idx > 0 ? "," : "", send_size, recv_size, - duration_cast<nanoseconds>(total_time).count(), - duration_cast<nanoseconds>(standard_deviation).count()); + total_time, standard_deviation); ++result_idx; } else { - strm.Printf( - "qSpeedTest(send=%-7u, recv=%-7u) in %.9f" - " sec for %9.2f packets/sec (%10.6f ms per packet) with standard " - "deviation of %10.6f ms\n", - send_size, recv_size, duration<float>(total_time).count(), - packets_per_second, - duration<float, std::milli>(average_per_packet).count(), - duration<float, std::milli>(standard_deviation).count()); + strm.Format("qSpeedTest(send={0,7}, recv={1,7}) in {2:s+f9} for " + "{3,9:f2} packets/s ({4,10:ms+f6} per packet) with " + "standard deviation of {5,10:ms+f6}\n", + send_size, recv_size, duration<float>(total_time), + packets_per_second, duration<float>(average_per_packet), + standard_deviation); } strm.Flush(); } @@ -2249,21 +2267,18 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, const auto average_per_packet = total_time / packet_count; if (json) { - strm.Printf("%s\n {\"send_size\" : %6" PRIu32 - ", \"recv_size\" : %6" PRIu32 - ", \"total_time_nsec\" : %12" PRIu64 " }", + strm.Format("{0}\n {{\"send_size\" : {1,6}, \"recv_size\" : " + "{2,6}, \"total_time_nsec\" : {3,12:ns-}}", result_idx > 0 ? "," : "", send_size, recv_size, - duration_cast<nanoseconds>(total_time).count()); + total_time); ++result_idx; } else { - strm.Printf("qSpeedTest(send=%-7u, recv=%-7u) %6u packets needed to " - "receive %2.1fMB in %.9f" - " sec for %f MB/sec for %9.2f packets/sec (%10.6f ms per " - "packet)\n", + strm.Format("qSpeedTest(send={0,7}, recv={1,7}) {2,6} packets needed " + "to receive {3:f1}MB in {4:s+f9} for {5} MB/sec for " + "{6,9:f2} packets/sec ({7,10:ms+f6} per packet)\n", send_size, recv_size, packet_count, k_recv_amount_mb, - duration<float>(total_time).count(), mb_second, - packets_per_second, - duration<float, std::milli>(average_per_packet).count()); + duration<float>(total_time), mb_second, + packets_per_second, duration<float>(average_per_packet)); } strm.Flush(); } @@ -3193,7 +3208,7 @@ bool GDBRemoteCommunicationClient::GetModuleInfo( StringExtractor extractor(value); std::string path; extractor.GetHexByteString(path); - module_spec.GetFileSpec() = FileSpec(path, false, arch_spec); + module_spec.GetFileSpec() = FileSpec(path, false, arch_spec.GetTriple()); } } @@ -3227,7 +3242,8 @@ ParseModuleSpec(StructuredData::Dictionary *dict) { if (!dict->GetValueForKeyAsString("file_path", string)) return llvm::None; - result.GetFileSpec() = FileSpec(string, false, result.GetArchitecture()); + result.GetFileSpec() = + FileSpec(string, false, result.GetArchitecture().GetTriple()); return result; } @@ -3254,6 +3270,9 @@ GDBRemoteCommunicationClient::GetModulesInfo( payload.PutEscapedBytes(unescaped_payload.GetString().data(), unescaped_payload.GetSize()); + // Increase the timeout for jModulesInfo since this packet can take longer. + ScopedTimeout timeout(*this, std::chrono::seconds(10)); + StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(payload.GetString(), response, false) != PacketResult::Success || @@ -3571,6 +3590,26 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() { : nullptr; } +Error GDBRemoteCommunicationClient::SendSignalsToIgnore( + llvm::ArrayRef<int32_t> signals) { + // Format packet: + // QPassSignals:<hex_sig1>;<hex_sig2>...;<hex_sigN> + auto range = llvm::make_range(signals.begin(), signals.end()); + std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str(); + + StringExtractorGDBRemote response; + auto send_status = SendPacketAndWaitForResponse(packet, response, false); + + if (send_status != GDBRemoteCommunication::PacketResult::Success) + return Error("Sending QPassSignals packet failed"); + + if (response.IsOKResponse()) { + return Error(); + } else { + return Error("Unknown error happened during sending QPassSignals packet."); + } +} + Error GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( const ConstString &type_name, const StructuredData::ObjectSP &config_sp) { Error error; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 83162a662e06..63b9708cc9a0 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -347,6 +347,8 @@ public: bool GetEchoSupported(); + bool GetQPassSignalsSupported(); + bool GetAugmentedLibrariesSVR4ReadSupported(); bool GetQXferFeaturesReadSupported(); @@ -450,6 +452,9 @@ public: void ServeSymbolLookups(lldb_private::Process *process); + // Sends QPassSignals packet to the server with given signals to ignore. + Error SendSignalsToIgnore(llvm::ArrayRef<int32_t> signals); + //------------------------------------------------------------------ /// Return the feature set supported by the gdb-remote server. /// @@ -527,6 +532,7 @@ protected: LazyBool m_supports_jThreadExtendedInfo; LazyBool m_supports_jLoadedDynamicLibrariesInfos; LazyBool m_supports_jGetSharedCacheInfo; + LazyBool m_supports_QPassSignals; bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1, m_supports_qUserName : 1, m_supports_qGroupName : 1, diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index e4e6810f665c..66c1b15ff857 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -22,23 +22,22 @@ #include <cstring> // Other libraries and framework includes -#include "lldb/Core/Log.h" #include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/StreamGDBRemote.h" -#include "lldb/Core/StreamString.h" #include "lldb/Host/Config.h" -#include "lldb/Host/Endian.h" #include "lldb/Host/File.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Args.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/Endian.h" #include "lldb/Utility/JSON.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamGDBRemote.h" +#include "lldb/Utility/StreamString.h" #include "llvm/ADT/Triple.h" // Project includes @@ -360,16 +359,15 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo( extractor.GetHexByteString(file); match_info.GetProcessInfo().GetExecutableFile().SetFile(file, false); } else if (key.equals("name_match")) { - NameMatchType name_match = - llvm::StringSwitch<NameMatchType>(value) - .Case("equals", eNameMatchEquals) - .Case("starts_with", eNameMatchStartsWith) - .Case("ends_with", eNameMatchEndsWith) - .Case("contains", eNameMatchContains) - .Case("regex", eNameMatchRegularExpression) - .Default(eNameMatchIgnore); + NameMatch name_match = llvm::StringSwitch<NameMatch>(value) + .Case("equals", NameMatch::Equals) + .Case("starts_with", NameMatch::StartsWith) + .Case("ends_with", NameMatch::EndsWith) + .Case("contains", NameMatch::Contains) + .Case("regex", NameMatch::RegularExpression) + .Default(NameMatch::Ignore); match_info.SetNameMatchType(name_match); - if (name_match == eNameMatchIgnore) + if (name_match == NameMatch::Ignore) return SendErrorResponse(2); } else if (key.equals("pid")) { lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; @@ -643,14 +641,15 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Size( std::string path; packet.GetHexByteString(path); if (!path.empty()) { - lldb::user_id_t retcode = FileSystem::GetFileSize(FileSpec(path, false)); + uint64_t Size; + if (llvm::sys::fs::file_size(path, Size)) + return SendErrorResponse(5); StreamString response; response.PutChar('F'); - response.PutHex64(retcode); - if (retcode == UINT64_MAX) { + response.PutHex64(Size); + if (Size == UINT64_MAX) { response.PutChar(','); - response.PutHex64( - retcode); // TODO: replace with Host::GetSyswideErrorCode() + response.PutHex64(Size); // TODO: replace with Host::GetSyswideErrorCode() } return SendPacketNoLock(response.GetString()); } @@ -682,7 +681,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Exists( std::string path; packet.GetHexByteString(path); if (!path.empty()) { - bool retcode = FileSystem::GetFileExists(FileSpec(path, false)); + bool retcode = llvm::sys::fs::exists(path); StreamString response; response.PutChar('F'); response.PutChar(','); @@ -715,7 +714,7 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_unlink( packet.SetFilePos(::strlen("vFile:unlink:")); std::string path; packet.GetHexByteString(path); - Error error = FileSystem::Unlink(FileSpec{path, true}); + Error error(llvm::sys::fs::remove(path)); StreamString response; response.Printf("F%u,%u", error.GetError(), error.GetError()); return SendPacketNoLock(response.GetString()); @@ -772,15 +771,15 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_MD5( std::string path; packet.GetHexByteString(path); if (!path.empty()) { - uint64_t a, b; StreamGDBRemote response; - if (!FileSystem::CalculateMD5(FileSpec(path, false), a, b)) { + auto Result = llvm::sys::fs::md5_contents(path); + if (!Result) { response.PutCString("F,"); response.PutCString("x"); } else { response.PutCString("F,"); - response.PutHex64(a); - response.PutHex64(b); + response.PutHex64(Result->low()); + response.PutHex64(Result->high()); } return SendPacketNoLock(response.GetString()); } @@ -795,7 +794,7 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir( if (packet.GetChar() == ',') { std::string path; packet.GetHexByteString(path); - Error error = FileSystem::MakeDirectory(FileSpec{path, false}, mode); + Error error(llvm::sys::fs::create_directory(path, mode)); StreamGDBRemote response; response.Printf("F%u", error.GetError()); @@ -810,11 +809,12 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qPlatform_chmod:")); - mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); + auto perms = + static_cast<llvm::sys::fs::perms>(packet.GetHexMaxU32(false, UINT32_MAX)); if (packet.GetChar() == ',') { std::string path; packet.GetHexByteString(path); - Error error = FileSystem::SetFilePermissions(FileSpec{path, true}, mode); + Error error(llvm::sys::fs::setPermissions(path, perms)); StreamGDBRemote response; response.Printf("F%u", error.GetError()); @@ -838,7 +838,8 @@ GDBRemoteCommunicationServerCommon::Handle_qSupported( response.PutCString(";QThreadSuffixSupported+"); response.PutCString(";QListThreadsInStopReply+"); response.PutCString(";qEcho+"); -#if defined(__linux__) +#if defined(__linux__) || defined(__NetBSD__) + response.PutCString(";QPassSignals+"); response.PutCString(";qXfer:auxv:read+"); #endif @@ -1091,12 +1092,11 @@ GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( StreamGDBRemote response; if (uuid_str.empty()) { - std::string md5_hash; - if (!FileSystem::CalculateMD5AsString(matched_module_spec.GetFileSpec(), - file_offset, file_size, md5_hash)) + auto Result = llvm::sys::fs::md5_contents(matched_module_spec.GetFileSpec().GetPath()); + if (!Result) return SendErrorResponse(5); response.PutCString("md5:"); - response.PutCStringAsRawHex8(md5_hash.c_str()); + response.PutCStringAsRawHex8(Result->digest().c_str()); } else { response.PutCString("uuid:"); response.PutCStringAsRawHex8(uuid_str.c_str()); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index bf72673f1769..290889ec662a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -12,7 +12,7 @@ #include "lldb/Host/Config.h" #include "GDBRemoteCommunicationServerLLGS.h" -#include "lldb/Core/StreamGDBRemote.h" +#include "lldb/Utility/StreamGDBRemote.h" // C Includes // C++ Includes @@ -21,27 +21,27 @@ #include <thread> // Other libraries and framework includes -#include "lldb/Core/DataBuffer.h" -#include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/State.h" -#include "lldb/Core/StreamString.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Debug.h" -#include "lldb/Host/Endian.h" #include "lldb/Host/File.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Host/StringConvert.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/common/NativeThreadProtocol.h" #include "lldb/Interpreter/Args.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/Endian.h" #include "lldb/Utility/JSON.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/UriParser.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/ScopedPrinter.h" @@ -49,7 +49,6 @@ #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" #include "Utility/StringExtractorGDBRemote.h" -#include "Utility/UriParser.h" using namespace lldb; using namespace lldb_private; @@ -81,7 +80,6 @@ GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( m_continue_tid(LLDB_INVALID_THREAD_ID), m_debugged_process_mutex(), m_debugged_process_sp(), m_stdio_communication("process.stdio"), m_inferior_prev_state(StateType::eStateInvalid), - m_active_auxv_buffer_sp(), m_saved_registers_mutex(), m_saved_registers_map(), m_next_saved_registers_id(1), m_handshake_completed(false) { RegisterPacketHandlers(); @@ -181,6 +179,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { &GDBRemoteCommunicationServerLLGS::Handle_Z); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, &GDBRemoteCommunicationServerLLGS::Handle_z); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QPassSignals, + &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals); RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k, [this](StringExtractorGDBRemote packet, Error &error, @@ -415,7 +416,8 @@ static void AppendHexValue(StreamString &response, const uint8_t *buf, static void WriteRegisterValueInHexFixedWidth( StreamString &response, NativeRegisterContextSP ®_ctx_sp, - const RegisterInfo ®_info, const RegisterValue *reg_value_p) { + const RegisterInfo ®_info, const RegisterValue *reg_value_p, + lldb::ByteOrder byte_order) { RegisterValue reg_value; if (!reg_value_p) { Error error = reg_ctx_sp->ReadRegister(®_info, reg_value); @@ -426,7 +428,8 @@ static void WriteRegisterValueInHexFixedWidth( if (reg_value_p) { AppendHexValue(response, (const uint8_t *)reg_value_p->GetBytes(), - reg_value_p->GetByteSize(), false); + reg_value_p->GetByteSize(), + byte_order == lldb::eByteOrderLittle); } else { // Zero-out any unreadable values. if (reg_info.byte_size > 0) { @@ -436,8 +439,7 @@ static void WriteRegisterValueInHexFixedWidth( } } -static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread, - bool abridged) { +static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext(); @@ -462,11 +464,8 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread, static const uint32_t k_expedited_registers[] = { LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM}; - static const uint32_t k_abridged_expedited_registers[] = { - LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM}; - for (const uint32_t *generic_reg_p = abridged ? k_abridged_expedited_registers - : k_expedited_registers; + for (const uint32_t *generic_reg_p = k_expedited_registers; *generic_reg_p != LLDB_INVALID_REGNUM; ++generic_reg_p) { uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( eRegisterKindGeneric, *generic_reg_p); @@ -501,7 +500,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread, StreamString stream; WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, - ®_value); + ®_value, lldb::eByteOrderBig); register_object_sp->SetObject( llvm::to_string(reg_num), @@ -567,8 +566,10 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>(); threads_array_sp->AppendObject(thread_obj_sp); - if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp, abridged)) - thread_obj_sp->SetObject("registers", registers_sp); + if (!abridged) { + if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp)) + thread_obj_sp->SetObject("registers", registers_sp); + } thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid)); if (signum != 0) @@ -721,6 +722,41 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( "jstopinfo field for pid %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID()); } + + uint32_t i = 0; + response.PutCString("thread-pcs"); + char delimiter = ':'; + for (NativeThreadProtocolSP thread_sp; + (thread_sp = m_debugged_process_sp->GetThreadAtIndex(i)) != nullptr; + ++i) { + NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); + if (!reg_ctx_sp) + continue; + + uint32_t reg_to_read = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + const RegisterInfo *const reg_info_p = + reg_ctx_sp->GetRegisterInfoAtIndex(reg_to_read); + + RegisterValue reg_value; + Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); + if (error.Fail()) { + if (log) + log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", + __FUNCTION__, + reg_info_p->name ? reg_info_p->name + : "<unnamed-register>", + reg_to_read, error.AsCString()); + continue; + } + + response.PutChar(delimiter); + delimiter = ','; + WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p, + ®_value, endian::InlHostByteOrder()); + } + + response.PutChar(';'); } // @@ -761,7 +797,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( if (error.Success()) { response.Printf("%.02x:", *reg_num_p); WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p, - ®_value); + ®_value, lldb::eByteOrderBig); response.PutChar(';'); } else { if (log) @@ -2496,12 +2532,14 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { packet, "Too short z packet, missing software/hardware specifier"); bool want_breakpoint = true; + bool want_hardware = false; const GDBStoppointType stoppoint_type = GDBStoppointType(packet.GetS32(eStoppointInvalid)); switch (stoppoint_type) { case eBreakpointHardware: want_breakpoint = true; + want_hardware = true; break; case eBreakpointSoftware: want_breakpoint = true; @@ -2544,7 +2582,8 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { if (want_breakpoint) { // Try to clear the breakpoint. - const Error error = m_debugged_process_sp->RemoveBreakpoint(addr); + const Error error = + m_debugged_process_sp->RemoveBreakpoint(addr, want_hardware); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); @@ -2625,7 +2664,7 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read( StringExtractorGDBRemote &packet) { // *BSD impls should be able to do this too. -#if defined(__linux__) +#if defined(__linux__) || defined(__NetBSD__) Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Parse out the offset. @@ -2653,7 +2692,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read( "qXfer:auxv:read:: packet missing length"); // Grab the auxv data if we need it. - if (!m_active_auxv_buffer_sp) { + if (!m_active_auxv_buffer_up) { // Make sure we have a valid process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { @@ -2665,55 +2704,45 @@ GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read( } // Grab the auxv data. - m_active_auxv_buffer_sp = Host::GetAuxvData(m_debugged_process_sp->GetID()); - if (!m_active_auxv_buffer_sp || - m_active_auxv_buffer_sp->GetByteSize() == 0) { - // Hmm, no auxv data, call that an error. - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no auxv data " - "retrieved", - __FUNCTION__); - m_active_auxv_buffer_sp.reset(); - return SendErrorResponse(0x11); + auto buffer_or_error = m_debugged_process_sp->GetAuxvData(); + if (!buffer_or_error) { + std::error_code ec = buffer_or_error.getError(); + LLDB_LOG(log, "no auxv data retrieved: {0}", ec.message()); + return SendErrorResponse(ec.value()); } + m_active_auxv_buffer_up = std::move(*buffer_or_error); } - // FIXME find out if/how I lock the stream here. - StreamGDBRemote response; bool done_with_buffer = false; - if (auxv_offset >= m_active_auxv_buffer_sp->GetByteSize()) { + llvm::StringRef buffer = m_active_auxv_buffer_up->getBuffer(); + if (auxv_offset >= buffer.size()) { // We have nothing left to send. Mark the buffer as complete. response.PutChar('l'); done_with_buffer = true; } else { // Figure out how many bytes are available starting at the given offset. - const uint64_t bytes_remaining = - m_active_auxv_buffer_sp->GetByteSize() - auxv_offset; - - // Figure out how many bytes we're going to read. - const uint64_t bytes_to_read = - (auxv_length > bytes_remaining) ? bytes_remaining : auxv_length; + buffer = buffer.drop_front(auxv_offset); // Mark the response type according to whether we're reading the remainder // of the auxv data. - if (bytes_to_read >= bytes_remaining) { + if (auxv_length >= buffer.size()) { // There will be nothing left to read after this response.PutChar('l'); done_with_buffer = true; } else { // There will still be bytes to read after this request. response.PutChar('m'); + buffer = buffer.take_front(auxv_length); } // Now write the data in encoded binary form. - response.PutEscapedBytes(m_active_auxv_buffer_sp->GetBytes() + auxv_offset, - bytes_to_read); + response.PutEscapedBytes(buffer.data(), buffer.size()); } if (done_with_buffer) - m_active_auxv_buffer_sp.reset(); + m_active_auxv_buffer_up.reset(); return SendPacketNoLock(response.GetString()); #else @@ -3002,9 +3031,14 @@ GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo( if (packet.GetChar() != ':') return SendErrorResponse(67); - uint32_t num = m_debugged_process_sp->GetMaxWatchpoints(); + auto hw_debug_cap = m_debugged_process_sp->GetHardwareDebugSupportInfo(); + StreamGDBRemote response; - response.Printf("num:%d;", num); + if (hw_debug_cap == llvm::None) + response.Printf("num:0;"); + else + response.Printf("num:%d;", hw_debug_cap->second); + return SendPacketNoLock(response.GetString()); } @@ -3037,6 +3071,40 @@ GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress( return SendPacketNoLock(response.GetString()); } +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_QPassSignals( + StringExtractorGDBRemote &packet) { + std::vector<int> signals; + packet.SetFilePos(strlen("QPassSignals:")); + + // Read sequence of hex signal numbers divided by a semicolon and + // optionally spaces. + while (packet.GetBytesLeft() > 0) { + int signal = packet.GetS32(-1, 16); + if (signal < 0) + return SendIllFormedResponse(packet, "Failed to parse signal number."); + signals.push_back(signal); + + packet.SkipSpaces(); + char separator = packet.GetChar(); + if (separator == '\0') + break; // End of string + if (separator != ';') + return SendIllFormedResponse(packet, "Invalid separator," + " expected semicolon."); + } + + // Fail if we don't have a current process. + if (!m_debugged_process_sp) + return SendErrorResponse(68); + + Error error = m_debugged_process_sp->IgnoreSignals(signals); + if (error.Fail()) + return SendErrorResponse(69); + + return SendOKResponse(); +} + void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -3136,20 +3204,10 @@ uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() { } void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | GDBR_LOG_PROCESS)); - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s()", __FUNCTION__); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); -// Clear any auxv cached data. -// *BSD impls should be able to do this too. -#if defined(__linux__) - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s clearing auxv buffer " - "(previously %s)", - __FUNCTION__, - m_active_auxv_buffer_sp ? "was set" : "was not set"); - m_active_auxv_buffer_sp.reset(); -#endif + LLDB_LOG(log, "clearing auxv buffer: {0}", m_active_auxv_buffer_up.get()); + m_active_auxv_buffer_up.reset(); } FileSpec diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index fa52cdaab493..a47927e1c640 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -117,7 +117,7 @@ protected: MainLoop::ReadHandleUP m_stdio_handle_up; lldb::StateType m_inferior_prev_state; - lldb::DataBufferSP m_active_auxv_buffer_sp; + std::unique_ptr<llvm::MemoryBuffer> m_active_auxv_buffer_up; std::mutex m_saved_registers_mutex; std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map; uint32_t m_next_saved_registers_id; @@ -203,6 +203,8 @@ protected: PacketResult Handle_qFileLoadAddress(StringExtractorGDBRemote &packet); + PacketResult Handle_QPassSignals(StringExtractorGDBRemote &packet); + void SetCurrentThreadID(lldb::tid_t tid); lldb::tid_t GetCurrentThreadID() const; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 11069749186a..ae1c1adb5b45 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -20,25 +20,25 @@ // Other libraries and framework includes #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Threading.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/StreamGDBRemote.h" -#include "lldb/Core/StreamString.h" #include "lldb/Core/StructuredData.h" #include "lldb/Host/Config.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Host/StringConvert.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/JSON.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamGDBRemote.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/UriParser.h" // Project includes #include "Utility/StringExtractorGDBRemote.h" -#include "Utility/UriParser.h" using namespace lldb; using namespace lldb_private; @@ -82,8 +82,8 @@ GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo); RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt, - [this](StringExtractorGDBRemote packet, Error &error, - bool &interrupt, bool &quit) { + [](StringExtractorGDBRemote packet, Error &error, + bool &interrupt, bool &quit) { error.SetErrorString("interrupt received"); interrupt = true; return PacketResult::Success; @@ -353,15 +353,13 @@ GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir( StringExtractorGDBRemote &packet) { - // If this packet is sent to a platform, then change the current working - // directory - char cwd[PATH_MAX]; - if (getcwd(cwd, sizeof(cwd)) == NULL) - return SendErrorResponse(errno); + llvm::SmallString<64> cwd; + if (std::error_code ec = llvm::sys::fs::current_path(cwd)) + return SendErrorResponse(ec.value()); StreamString response; - response.PutBytesAsRawHex8(cwd, strlen(cwd)); + response.PutBytesAsRawHex8(cwd.data(), cwd.size()); return SendPacketNoLock(response.GetString()); } @@ -372,10 +370,8 @@ GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir( std::string path; packet.GetHexByteString(path); - // If this packet is sent to a platform, then change the current working - // directory - if (::chdir(path.c_str()) != 0) - return SendErrorResponse(errno); + if (std::error_code ec = llvm::sys::fs::set_current_path(path)) + return SendErrorResponse(ec.value()); return SendOKResponse(); } @@ -532,9 +528,9 @@ bool GDBRemoteCommunicationServerPlatform::FreePortForProcess(lldb::pid_t pid) { const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() { static FileSpec g_domainsocket_dir; - static std::once_flag g_once_flag; + static llvm::once_flag g_once_flag; - std::call_once(g_once_flag, []() { + llvm::call_once(g_once_flag, []() { const char *domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR"); if (domainsocket_dir_env != nullptr) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index 27ce67ded783..ea4acc74893a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -12,14 +12,13 @@ // C Includes // C++ Includes // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" -#include "lldb/Core/StreamString.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" -#include "lldb/Utility/Utils.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/StreamString.h" // Project includes #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h index 5b3e04eb588e..8ef91af55e0f 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -17,9 +17,9 @@ // Other libraries and framework includes // Project includes #include "Plugins/Process/Utility/DynamicRegisterInfo.h" -#include "lldb/Core/ConstString.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/DataExtractor.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-private.h" diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index fac52901e763..c4ae5e36d9ad 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -35,14 +35,13 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" -#include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Core/Value.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Host/ConnectionFileDescriptor.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/HostThread.h" +#include "lldb/Host/PseudoTerminal.h" #include "lldb/Host/StringConvert.h" #include "lldb/Host/Symbols.h" #include "lldb/Host/ThreadLauncher.h" @@ -65,7 +64,8 @@ #include "lldb/Target/TargetList.h" #include "lldb/Target/ThreadPlanCallFunction.h" #include "lldb/Utility/CleanUp.h" -#include "lldb/Utility/PseudoTerminal.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/StreamString.h" // Project includes #include "GDBRemoteRegisterContext.h" @@ -80,6 +80,7 @@ #include "lldb/Host/Host.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" #define DEBUGSERVER_BASENAME "debugserver" @@ -576,7 +577,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { uint32_t ret_val = opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes); assert(dwarf_opcode_len == ret_val); - + UNUSED_IF_ASSERT_DISABLED(ret_val); reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data(); } } @@ -1616,9 +1617,7 @@ bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { // locker will keep a mutex locked until it goes out of scope Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_THREAD)); - if (log && log->GetMask().Test(GDBR_LOG_VERBOSE)) - log->Printf("ProcessGDBRemote::%s (pid = %" PRIu64 ")", __FUNCTION__, - GetID()); + LLDB_LOGV(log, "pid = {0}", GetID()); size_t num_thread_ids = m_thread_ids.size(); // The "m_thread_ids" thread ID list should always be updated after each stop @@ -1637,39 +1636,14 @@ bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list, old_thread_list_copy.RemoveThreadByProtocolID(tid, false)); if (!thread_sp) { thread_sp.reset(new ThreadGDBRemote(*this, tid)); - if (log && log->GetMask().Test(GDBR_LOG_VERBOSE)) - log->Printf("ProcessGDBRemote::%s Making new thread: %p for thread " - "ID: 0x%" PRIx64 ".\n", - __FUNCTION__, static_cast<void *>(thread_sp.get()), - thread_sp->GetID()); + LLDB_LOGV(log, "Making new thread: {0} for thread ID: {1:x}.", + thread_sp.get(), thread_sp->GetID()); } else { - if (log && log->GetMask().Test(GDBR_LOG_VERBOSE)) - log->Printf("ProcessGDBRemote::%s Found old thread: %p for thread " - "ID: 0x%" PRIx64 ".\n", - __FUNCTION__, static_cast<void *>(thread_sp.get()), - thread_sp->GetID()); - } - // The m_thread_pcs vector has pc values in big-endian order, not - // target-endian, unlike most - // of the register read/write packets in gdb-remote protocol. - // Early in the process startup, we may not yet have set the process - // ByteOrder so we ignore these; - // they are a performance improvement over fetching thread register values - // individually, the - // method we will fall back to if needed. - if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && - GetByteOrder() != eByteOrderInvalid) { - ThreadGDBRemote *gdb_thread = - static_cast<ThreadGDBRemote *>(thread_sp.get()); - RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); - if (reg_ctx_sp) { - uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( - eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - if (pc_regnum != LLDB_INVALID_REGNUM) { - gdb_thread->PrivateSetRegisterValue(pc_regnum, m_thread_pcs[i]); - } - } + LLDB_LOGV(log, "Found old thread: {0} for thread ID: {1:x}.", + thread_sp.get(), thread_sp->GetID()); } + + SetThreadPc(thread_sp, i); new_thread_list.AddThreadSortedByIndexID(thread_sp); } } @@ -1689,6 +1663,22 @@ bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list, return true; } +void ProcessGDBRemote::SetThreadPc(const ThreadSP &thread_sp, uint64_t index) { + if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && + GetByteOrder() != eByteOrderInvalid) { + ThreadGDBRemote *gdb_thread = + static_cast<ThreadGDBRemote *>(thread_sp.get()); + RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); + if (reg_ctx_sp) { + uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + if (pc_regnum != LLDB_INVALID_REGNUM) { + gdb_thread->PrivateSetRegisterValue(pc_regnum, m_thread_pcs[index]); + } + } + } +} + bool ProcessGDBRemote::GetThreadStopInfoFromJSON( ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp) { // See if we got thread stop infos for all threads via the "jThreadsInfo" @@ -1774,6 +1764,11 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( static_cast<ThreadGDBRemote *>(thread_sp.get()); gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true); + auto iter = std::find(m_thread_ids.begin(), m_thread_ids.end(), tid); + if (iter != m_thread_ids.end()) { + SetThreadPc(thread_sp, iter - m_thread_ids.begin()); + } + for (const auto &pair : expedited_register_map) { StringExtractor reg_value_extractor; reg_value_extractor.GetStringRef() = pair.second; @@ -2729,16 +2724,19 @@ void ProcessGDBRemote::WillPublicStop() { size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, Error &error) { GetMaxMemorySize(); - if (size > m_max_memory_size) { + bool binary_memory_read = m_gdb_comm.GetxPacketSupported(); + // M and m packets take 2 bytes for 1 byte of memory + size_t max_memory_size = + binary_memory_read ? m_max_memory_size : m_max_memory_size / 2; + if (size > max_memory_size) { // Keep memory read sizes down to a sane limit. This function will be // called multiple times in order to complete the task by // lldb_private::Process so it is ok to do this. - size = m_max_memory_size; + size = max_memory_size; } char packet[64]; int packet_len; - bool binary_memory_read = m_gdb_comm.GetxPacketSupported(); packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64, binary_memory_read ? 'x' : 'm', (uint64_t)addr, (uint64_t)size); @@ -2785,11 +2783,13 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf, size_t size, Error &error) { GetMaxMemorySize(); - if (size > m_max_memory_size) { + // M and m packets take 2 bytes for 1 byte of memory + size_t max_memory_size = m_max_memory_size / 2; + if (size > max_memory_size) { // Keep memory read sizes down to a sane limit. This function will be // called multiple times in order to complete the task by // lldb_private::Process so it is ok to do this. - size = m_max_memory_size; + size = max_memory_size; } StreamString packet; @@ -3427,9 +3427,9 @@ void ProcessGDBRemote::KillDebugserverProcess() { } void ProcessGDBRemote::Initialize() { - static std::once_flag g_once_flag; + static llvm::once_flag g_once_flag; - std::call_once(g_once_flag, []() { + llvm::call_once(g_once_flag, []() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, DebuggerInitialize); @@ -3739,6 +3739,43 @@ bool ProcessGDBRemote::NewThreadNotifyBreakpointHit( return false; } +Error ProcessGDBRemote::UpdateAutomaticSignalFiltering() { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + LLDB_LOG(log, "Check if need to update ignored signals"); + + // QPassSignals package is not supported by the server, + // there is no way we can ignore any signals on server side. + if (!m_gdb_comm.GetQPassSignalsSupported()) + return Error(); + + // No signals, nothing to send. + if (m_unix_signals_sp == nullptr) + return Error(); + + // Signals' version hasn't changed, no need to send anything. + uint64_t new_signals_version = m_unix_signals_sp->GetVersion(); + if (new_signals_version == m_last_signals_version) { + LLDB_LOG(log, "Signals' version hasn't changed. version={0}", + m_last_signals_version); + return Error(); + } + + auto signals_to_ignore = + m_unix_signals_sp->GetFilteredSignals(false, false, false); + Error error = m_gdb_comm.SendSignalsToIgnore(signals_to_ignore); + + LLDB_LOG(log, + "Signals' version changed. old version={0}, new version={1}, " + "signals ignored={2}, update result={3}", + m_last_signals_version, new_signals_version, + signals_to_ignore.size(), error); + + if (error.Success()) + m_last_signals_version = new_signals_version; + + return error; +} + bool ProcessGDBRemote::StartNoticingNewThreads() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (m_thread_create_bp_sp) { @@ -3988,6 +4025,21 @@ void ProcessGDBRemote::GetMaxMemorySize() { stub_max_size = reasonable_largeish_default; } + // Memory packet have other overheads too like Maddr,size:#NN + // Instead of calculating the bytes taken by size and addr every + // time, we take a maximum guess here. + if (stub_max_size > 70) + stub_max_size -= 32 + 32 + 6; + else { + // In unlikely scenario that max packet size is less then 70, we will + // hope that data being written is small enough to fit. + Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( + GDBR_LOG_COMM | GDBR_LOG_MEMORY)); + if (log) + log->Warning("Packet size is too small. " + "LLDB may face problems while writing memory"); + } + m_max_memory_size = stub_max_size; } else { m_max_memory_size = conservative_default; @@ -4132,8 +4184,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, - ®_info, &cur_reg_num, ®_offset, - &dwarf_opcode_bytes]( + ®_info, ®_offset, &dwarf_opcode_bytes]( const llvm::StringRef &name, const llvm::StringRef &value) -> bool { if (name == "name") { @@ -4213,7 +4264,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, uint32_t ret_val = opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes); assert(dwarf_opcode_len == ret_val); - + UNUSED_IF_ASSERT_DISABLED(ret_val); reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data(); } else { printf("unhandled attribute %s = %s\n", name.data(), value.data()); @@ -4295,7 +4346,7 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { XMLNode target_node = xml_document.GetRootElement("target"); if (target_node) { XMLNode feature_node; - target_node.ForEachChildElement([&target_info, this, &feature_node]( + target_node.ForEachChildElement([&target_info, &feature_node]( const XMLNode &node) -> bool { llvm::StringRef name = node.GetName(); if (name == "architecture") { @@ -4421,8 +4472,8 @@ Error ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { LoadedModuleInfoList::LoadedModuleInfo module; library.ForEachAttribute( - [log, &module](const llvm::StringRef &name, - const llvm::StringRef &value) -> bool { + [&module](const llvm::StringRef &name, + const llvm::StringRef &value) -> bool { if (name == "name") module.set_name(value.str()); diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 6423abc55836..a1794d0f5050 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -22,18 +22,18 @@ // Project includes #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Broadcaster.h" -#include "lldb/Core/ConstString.h" -#include "lldb/Core/Error.h" #include "lldb/Core/LoadedModuleInfoList.h" #include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Core/StringList.h" #include "lldb/Core/StructuredData.h" #include "lldb/Core/ThreadSafeValue.h" #include "lldb/Host/HostThread.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringExtractor.h" +#include "lldb/Utility/StringList.h" #include "lldb/lldb-private-forward.h" #include "GDBRemoteCommunicationClient.h" @@ -397,12 +397,15 @@ protected: lldb::addr_t base_addr, bool value_is_offset); + Error UpdateAutomaticSignalFiltering() override; + private: //------------------------------------------------------------------ // For ProcessGDBRemote only //------------------------------------------------------------------ std::string m_partial_profile_data; std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map; + uint64_t m_last_signals_version = 0; static bool NewThreadNotifyBreakpointHit(void *baton, StoppointCallbackContext *context, @@ -417,6 +420,7 @@ private: void HandleStopReply() override; void HandleAsyncStructuredDataPacket(llvm::StringRef data) override; + void SetThreadPc(const lldb::ThreadSP &thread_sp, uint64_t index); using ModuleCacheKey = std::pair<std::string, std::string>; // KeyInfo for the cached module spec DenseMap. // The invariant is that all real keys will have the file and architecture diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp index 899037ae98aa..8f16b83907cf 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp @@ -8,210 +8,37 @@ //===----------------------------------------------------------------------===// #include "ProcessGDBRemoteLog.h" - -#include <mutex> - -#include "lldb/Core/StreamFile.h" -#include "lldb/Interpreter/Args.h" - #include "ProcessGDBRemote.h" +#include "llvm/Support/Threading.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; -// We want to avoid global constructors where code needs to be run so here we -// control access to our static g_log_sp by hiding it in a singleton function -// that will construct the static g_lob_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 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}, + {{"data-short"}, + {"log memory bytes for memory reads and writes for short transactions " + "only"}, + GDBR_LOG_MEMORY_DATA_SHORT}, + {{"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}, +}; -void ProcessGDBRemoteLog::Initialize() { - static ConstString g_name("gdb-remote"); - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, []() { - Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories}; +Log::Channel ProcessGDBRemoteLog::g_channel(g_categories, GDBR_LOG_DEFAULT); - Log::RegisterLogChannel(g_name, log_callbacks); +void ProcessGDBRemoteLog::Initialize() { + static llvm::once_flag g_once_flag; + llvm::call_once(g_once_flag, []() { + Log::Register("gdb-remote", g_channel); }); } - -Log *ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(uint32_t mask) { - Log *log(GetLog()); - if (log && mask) { - uint32_t log_mask = log->GetMask().Get(); - if ((log_mask & mask) != mask) - return NULL; - } - return log; -} - -Log *ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(uint32_t mask) { - Log *log(GetLog()); - if (log && log->GetMask().Get() & mask) - return log; - return NULL; -} - -void ProcessGDBRemoteLog::DisableLog(const char **categories, - Stream *feedback_strm) { - Log *log(GetLog()); - if (log) { - uint32_t flag_bits = 0; - - if (categories && categories[0]) { - flag_bits = log->GetMask().Get(); - for (size_t i = 0; categories[i] != NULL; ++i) { - const char *arg = categories[i]; - - if (::strcasecmp(arg, "all") == 0) - flag_bits &= ~GDBR_LOG_ALL; - else if (::strcasecmp(arg, "async") == 0) - flag_bits &= ~GDBR_LOG_ASYNC; - else if (::strncasecmp(arg, "break", 5) == 0) - flag_bits &= ~GDBR_LOG_BREAKPOINTS; - else if (::strncasecmp(arg, "comm", 4) == 0) - flag_bits &= ~GDBR_LOG_COMM; - else if (::strcasecmp(arg, "default") == 0) - flag_bits &= ~GDBR_LOG_DEFAULT; - else if (::strcasecmp(arg, "packets") == 0) - flag_bits &= ~GDBR_LOG_PACKETS; - else if (::strcasecmp(arg, "memory") == 0) - flag_bits &= ~GDBR_LOG_MEMORY; - else if (::strcasecmp(arg, "data-short") == 0) - flag_bits &= ~GDBR_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp(arg, "data-long") == 0) - flag_bits &= ~GDBR_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp(arg, "process") == 0) - flag_bits &= ~GDBR_LOG_PROCESS; - else if (::strcasecmp(arg, "step") == 0) - flag_bits &= ~GDBR_LOG_STEP; - else if (::strcasecmp(arg, "thread") == 0) - flag_bits &= ~GDBR_LOG_THREAD; - else if (::strcasecmp(arg, "verbose") == 0) - flag_bits &= ~GDBR_LOG_VERBOSE; - else if (::strncasecmp(arg, "watch", 5) == 0) - flag_bits &= ~GDBR_LOG_WATCHPOINTS; - else { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories(feedback_strm); - } - } - } - - if (flag_bits == 0) - g_log_enabled = false; - else - log->GetMask().Reset(flag_bits); - } - - return; -} - -Log *ProcessGDBRemoteLog::EnableLog(StreamSP &log_stream_sp, - uint32_t log_options, - const char **categories, - Stream *feedback_strm) { - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the - // same. - uint32_t flag_bits = 0; - if (g_log) - flag_bits = g_log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) { - if (g_log) - g_log->SetStream(log_stream_sp); - else - g_log = new Log(log_stream_sp); - } - - if (g_log) { - bool got_unknown_category = false; - for (size_t i = 0; categories[i] != NULL; ++i) { - const char *arg = categories[i]; - - if (::strcasecmp(arg, "all") == 0) - flag_bits |= GDBR_LOG_ALL; - else if (::strcasecmp(arg, "async") == 0) - flag_bits |= GDBR_LOG_ASYNC; - else if (::strncasecmp(arg, "break", 5) == 0) - flag_bits |= GDBR_LOG_BREAKPOINTS; - else if (::strncasecmp(arg, "comm", 4) == 0) - flag_bits |= GDBR_LOG_COMM; - else if (::strcasecmp(arg, "default") == 0) - flag_bits |= GDBR_LOG_DEFAULT; - else if (::strcasecmp(arg, "packets") == 0) - flag_bits |= GDBR_LOG_PACKETS; - else if (::strcasecmp(arg, "memory") == 0) - flag_bits |= GDBR_LOG_MEMORY; - else if (::strcasecmp(arg, "data-short") == 0) - flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp(arg, "data-long") == 0) - flag_bits |= GDBR_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp(arg, "process") == 0) - flag_bits |= GDBR_LOG_PROCESS; - else if (::strcasecmp(arg, "step") == 0) - flag_bits |= GDBR_LOG_STEP; - else if (::strcasecmp(arg, "thread") == 0) - flag_bits |= GDBR_LOG_THREAD; - else if (::strcasecmp(arg, "verbose") == 0) - flag_bits |= GDBR_LOG_VERBOSE; - else if (::strncasecmp(arg, "watch", 5) == 0) - flag_bits |= GDBR_LOG_WATCHPOINTS; - else { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) { - got_unknown_category = true; - ListLogCategories(feedback_strm); - } - } - } - if (flag_bits == 0) - flag_bits = GDBR_LOG_DEFAULT; - g_log->GetMask().Reset(flag_bits); - g_log->GetOptions().Reset(log_options); - } - g_log_enabled = true; - return g_log; -} - -void ProcessGDBRemoteLog::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" - " communication - log communication activity\n" - " default - enable the default set of logging categories for liblldb\n" - " packets - log gdb remote packets\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" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n" - " watch - log watchpoint related activities\n", - ProcessGDBRemote::GetPluginNameStatic().GetCString()); -} - -void ProcessGDBRemoteLog::LogIf(uint32_t mask, const char *format, ...) { - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(mask)); - if (log) { - va_list args; - va_start(args, format); - log->VAPrintf(format, args); - va_end(args); - } -} diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h index f5e92b450614..3c5801176690 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h @@ -15,9 +15,8 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/Log.h" +#include "lldb/Utility/Log.h" -#define GDBR_LOG_VERBOSE (1u << 0) #define GDBR_LOG_PROCESS (1u << 1) #define GDBR_LOG_THREAD (1u << 2) #define GDBR_LOG_PACKETS (1u << 3) @@ -37,21 +36,13 @@ namespace lldb_private { namespace process_gdb_remote { class ProcessGDBRemoteLog { + static Log::Channel g_channel; + public: static void Initialize(); - static Log *GetLogIfAllCategoriesSet(uint32_t mask = 0); - - static Log *GetLogIfAnyCategoryIsSet(uint32_t mask); - - static void DisableLog(const char **categories, Stream *feedback_strm); - - static Log *EnableLog(lldb::StreamSP &log_stream_sp, uint32_t log_options, - const char **categories, Stream *feedback_strm); - - static void ListLogCategories(Stream *strm); - - static void LogIf(uint32_t mask, const char *format, ...); + static Log *GetLogIfAllCategoriesSet(uint32_t mask) { return g_channel.GetLogIfAll(mask); } + static Log *GetLogIfAnyCategoryIsSet(uint32_t mask) { return g_channel.GetLogIfAny(mask); } }; } // namespace process_gdb_remote diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index ab552145a18b..5197e8f9adfc 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -11,9 +11,7 @@ #include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/State.h" -#include "lldb/Core/StreamString.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -22,6 +20,8 @@ #include "lldb/Target/Target.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Target/Unwind.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/StreamString.h" #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" @@ -41,18 +41,16 @@ ThreadGDBRemote::ThreadGDBRemote(Process &process, lldb::tid_t tid) 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) { - ProcessGDBRemoteLog::LogIf( - GDBR_LOG_THREAD, - "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this, - process.GetID(), GetID()); + Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this, process.GetID(), + GetID()); } ThreadGDBRemote::~ThreadGDBRemote() { ProcessSP process_sp(GetProcess()); - ProcessGDBRemoteLog::LogIf( - GDBR_LOG_THREAD, - "%p: ThreadGDBRemote::~ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this, - process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, GetID()); + Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD)); + LLDB_LOG(log, "this = {0}, pid = {1}, tid = {2}", this, + process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, GetID()); DestroyThread(); } diff --git a/source/Plugins/Process/mach-core/CMakeLists.txt b/source/Plugins/Process/mach-core/CMakeLists.txt index ac54658cf4dc..18f6ff581ea3 100644 --- a/source/Plugins/Process/mach-core/CMakeLists.txt +++ b/source/Plugins/Process/mach-core/CMakeLists.txt @@ -1,6 +1,19 @@ include_directories(../Utility) -add_lldb_library(lldbPluginProcessMachCore +add_lldb_library(lldbPluginProcessMachCore PLUGIN ProcessMachCore.cpp ThreadMachCore.cpp + + LINK_LIBS + lldbBreakpoint + lldbCore + lldbHost + lldbSymbol + lldbTarget + lldbUtility + lldbPluginDynamicLoaderDarwinKernel + lldbPluginDynamicLoaderMacOSXDYLD + lldbPluginObjectFileMachO + LINK_COMPONENTS + Support ) diff --git a/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/source/Plugins/Process/mach-core/ProcessMachCore.cpp index f83499cdb233..3b636b9795fd 100644 --- a/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -14,12 +14,11 @@ // C++ Includes #include "llvm/Support/MathExtras.h" +#include "llvm/Support/Threading.h" #include <mutex> // Other libraries and framework includes -#include "lldb/Core/DataBuffer.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -30,6 +29,9 @@ #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataBufferLLVM.h" +#include "lldb/Utility/Log.h" // Project includes #include "ProcessMachCore.h" @@ -65,7 +67,8 @@ lldb::ProcessSP ProcessMachCore::CreateInstance(lldb::TargetSP target_sp, lldb::ProcessSP process_sp; if (crash_file) { const size_t header_size = sizeof(llvm::MachO::mach_header); - lldb::DataBufferSP data_sp(crash_file->ReadFileContents(0, header_size)); + auto data_sp = + DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), header_size, 0); if (data_sp && data_sp->GetByteSize() == header_size) { DataExtractor data(data_sp, lldb::eByteOrderLittle, 4); @@ -288,8 +291,57 @@ Error ProcessMachCore::DoLoadCore() { m_core_range_infos.Sort(); } - if (m_dyld_addr == LLDB_INVALID_ADDRESS || - m_mach_kernel_addr == LLDB_INVALID_ADDRESS) { + + bool found_main_binary_definitively = false; + + addr_t objfile_binary_addr; + UUID objfile_binary_uuid; + if (core_objfile->GetCorefileMainBinaryInfo (objfile_binary_addr, objfile_binary_uuid)) + { + if (objfile_binary_addr != LLDB_INVALID_ADDRESS) + { + m_mach_kernel_addr = objfile_binary_addr; + found_main_binary_definitively = true; + if (log) + log->Printf ("ProcessMachCore::DoLoadCore: using kernel address 0x%" PRIx64 + " from LC_NOTE 'main bin spec' load command.", m_mach_kernel_addr); + } + } + + // This checks for the presence of an LC_IDENT string in a core file; + // LC_IDENT is very obsolete and should not be used in new code, but + // if the load command is present, let's use the contents. + std::string corefile_identifier = core_objfile->GetIdentifierString(); + if (found_main_binary_definitively == false + && corefile_identifier.find("Darwin Kernel") != std::string::npos) { + UUID uuid; + addr_t addr = LLDB_INVALID_ADDRESS; + if (corefile_identifier.find("UUID=") != std::string::npos) { + size_t p = corefile_identifier.find("UUID=") + strlen("UUID="); + std::string uuid_str = corefile_identifier.substr(p, 36); + uuid.SetFromCString(uuid_str.c_str()); + } + if (corefile_identifier.find("stext=") != std::string::npos) { + size_t p = corefile_identifier.find("stext=") + strlen("stext="); + if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') { + errno = 0; + addr = ::strtoul(corefile_identifier.c_str() + p, NULL, 16); + if (errno != 0 || addr == 0) + addr = LLDB_INVALID_ADDRESS; + } + } + if (uuid.IsValid() && addr != LLDB_INVALID_ADDRESS) { + m_mach_kernel_addr = addr; + found_main_binary_definitively = true; + if (log) + log->Printf("ProcessMachCore::DoLoadCore: Using the kernel address 0x%" PRIx64 + " from LC_IDENT/LC_NOTE 'kern ver str' string: '%s'", addr, corefile_identifier.c_str()); + } + } + + if (found_main_binary_definitively == false + && (m_dyld_addr == LLDB_INVALID_ADDRESS + || m_mach_kernel_addr == LLDB_INVALID_ADDRESS)) { // We need to locate the main executable in the memory ranges // we have in the core file. We need to search for both a user-process dyld // binary @@ -314,7 +366,8 @@ Error ProcessMachCore::DoLoadCore() { } } - if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { + if (found_main_binary_definitively == false + && m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { // In the case of multiple kernel images found in the core file via // exhaustive // search, we may not pick the correct one. See if the @@ -579,9 +632,9 @@ Error ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr, void ProcessMachCore::Clear() { m_thread_list.Clear(); } void ProcessMachCore::Initialize() { - static std::once_flag g_once_flag; + static llvm::once_flag g_once_flag; - std::call_once(g_once_flag, []() { + llvm::call_once(g_once_flag, []() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); }); diff --git a/source/Plugins/Process/mach-core/ProcessMachCore.h b/source/Plugins/Process/mach-core/ProcessMachCore.h index 7094eb33110b..99bb4a60ff39 100644 --- a/source/Plugins/Process/mach-core/ProcessMachCore.h +++ b/source/Plugins/Process/mach-core/ProcessMachCore.h @@ -17,9 +17,9 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/ConstString.h" -#include "lldb/Core/Error.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Error.h" class ThreadKDP; diff --git a/source/Plugins/Process/mach-core/ThreadMachCore.cpp b/source/Plugins/Process/mach-core/ThreadMachCore.cpp index 828b705edf57..3917b99bd63d 100644 --- a/source/Plugins/Process/mach-core/ThreadMachCore.cpp +++ b/source/Plugins/Process/mach-core/ThreadMachCore.cpp @@ -13,15 +13,15 @@ #include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/State.h" -#include "lldb/Core/StreamString.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Unwind.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/StreamString.h" #include "ProcessMachCore.h" //#include "RegisterContextKDP_arm.h" diff --git a/source/Plugins/Process/minidump/CMakeLists.txt b/source/Plugins/Process/minidump/CMakeLists.txt index ddc89cbd92c1..61ce16830c9b 100644 --- a/source/Plugins/Process/minidump/CMakeLists.txt +++ b/source/Plugins/Process/minidump/CMakeLists.txt @@ -1,10 +1,19 @@ include_directories(../Utility) -add_lldb_library(lldbPluginProcessMinidump +add_lldb_library(lldbPluginProcessMinidump PLUGIN MinidumpTypes.cpp MinidumpParser.cpp RegisterContextMinidump_x86_32.cpp RegisterContextMinidump_x86_64.cpp ProcessMinidump.cpp ThreadMinidump.cpp + + LINK_LIBS + lldbCore + lldbTarget + lldbUtility + lldbPluginProcessUtility + lldbPluginProcessElfCore + LINK_COMPONENTS + Support ) diff --git a/source/Plugins/Process/minidump/MinidumpParser.h b/source/Plugins/Process/minidump/MinidumpParser.h index 67523a72ad11..189aeb3d64e6 100644 --- a/source/Plugins/Process/minidump/MinidumpParser.h +++ b/source/Plugins/Process/minidump/MinidumpParser.h @@ -16,8 +16,8 @@ // Other libraries and framework includes #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataBuffer.h" -#include "lldb/Core/Error.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/Error.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" diff --git a/source/Plugins/Process/minidump/MinidumpTypes.h b/source/Plugins/Process/minidump/MinidumpTypes.h index 46871a1b84d8..42de7eaaca03 100644 --- a/source/Plugins/Process/minidump/MinidumpTypes.h +++ b/source/Plugins/Process/minidump/MinidumpTypes.h @@ -13,7 +13,7 @@ // Project includes // Other libraries and framework includes -#include "lldb/Core/Error.h" +#include "lldb/Utility/Error.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitmaskEnum.h" diff --git a/source/Plugins/Process/minidump/ProcessMinidump.cpp b/source/Plugins/Process/minidump/ProcessMinidump.cpp index 46d8df8b16f1..f3f4664ad6e1 100644 --- a/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -12,8 +12,6 @@ #include "ThreadMinidump.h" // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -23,7 +21,12 @@ #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/UnixSignals.h" +#include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" + +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Threading.h" // C includes // C++ includes @@ -48,20 +51,25 @@ lldb::ProcessSP ProcessMinidump::CreateInstance(lldb::TargetSP target_sp, lldb::ProcessSP process_sp; // Read enough data for the Minidump header - const size_t header_size = sizeof(MinidumpHeader); - lldb::DataBufferSP data_sp(crash_file->MemoryMapFileContents(0, header_size)); - if (!data_sp) + constexpr size_t header_size = sizeof(MinidumpHeader); + auto DataPtr = + DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), header_size, 0); + if (!DataPtr) return nullptr; + assert(DataPtr->GetByteSize() == header_size); + // first, only try to parse the header, beacuse we need to be fast - llvm::ArrayRef<uint8_t> header_data(data_sp->GetBytes(), header_size); - const MinidumpHeader *header = MinidumpHeader::Parse(header_data); + llvm::ArrayRef<uint8_t> HeaderBytes = DataPtr->GetData(); + const MinidumpHeader *header = MinidumpHeader::Parse(HeaderBytes); + if (header == nullptr) + return nullptr; - if (data_sp->GetByteSize() != header_size || header == nullptr) + auto AllData = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), -1, 0); + if (!AllData) return nullptr; - lldb::DataBufferSP all_data_sp(crash_file->MemoryMapFileContents()); - auto minidump_parser = MinidumpParser::Create(all_data_sp); + auto minidump_parser = MinidumpParser::Create(AllData); // check if the parser object is valid if (!minidump_parser) return nullptr; @@ -92,9 +100,9 @@ ProcessMinidump::~ProcessMinidump() { } void ProcessMinidump::Initialize() { - static std::once_flag g_once_flag; + static llvm::once_flag g_once_flag; - std::call_once(g_once_flag, []() { + llvm::call_once(g_once_flag, []() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), ProcessMinidump::CreateInstance); diff --git a/source/Plugins/Process/minidump/ProcessMinidump.h b/source/Plugins/Process/minidump/ProcessMinidump.h index 78eadc809a4d..62407f927551 100644 --- a/source/Plugins/Process/minidump/ProcessMinidump.h +++ b/source/Plugins/Process/minidump/ProcessMinidump.h @@ -15,11 +15,11 @@ #include "MinidumpTypes.h" // Other libraries and framework includes -#include "lldb/Core/ConstString.h" -#include "lldb/Core/Error.h" #include "lldb/Target/Process.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Error.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp index 7f3768216f3a..7605f8b143af 100644 --- a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp +++ b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp @@ -11,7 +11,7 @@ #include "RegisterContextMinidump_x86_32.h" // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Utility/DataBufferHeap.h" // C includes // C++ includes diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp index 881c26a5774a..ba1cb6dbf3ef 100644 --- a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp +++ b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp @@ -11,7 +11,7 @@ #include "RegisterContextMinidump_x86_64.h" // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Utility/DataBufferHeap.h" // C includes // C++ includes diff --git a/source/Plugins/Process/minidump/ThreadMinidump.cpp b/source/Plugins/Process/minidump/ThreadMinidump.cpp index e42108b9261a..9c21cc92376f 100644 --- a/source/Plugins/Process/minidump/ThreadMinidump.cpp +++ b/source/Plugins/Process/minidump/ThreadMinidump.cpp @@ -20,12 +20,12 @@ #include "Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Unwind.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Log.h" // C Includes // C++ Includes |
