diff options
Diffstat (limited to 'source/Plugins/Process')
36 files changed, 1267 insertions, 704 deletions
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 84e35ba..b33f833 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -30,7 +30,7 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Utility/PseudoTerminal.h" - +#include "Plugins/Process/POSIX/CrashReason.h" #include "POSIXThread.h" #include "ProcessFreeBSD.h" #include "ProcessPOSIXLog.h" @@ -994,6 +994,11 @@ ProcessMonitor::Launch(LaunchArgs *args) if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0) exit(ePtraceFailed); + // terminal has already dupped the tty descriptors to stdin/out/err. + // This closes original fd from which they were copied (and avoids + // leaking descriptors to the debugged process. + terminal.CloseSlaveFileDescriptor(); + // Do not inherit setgid powers. if (setgid(getgid()) != 0) exit(eSetGidFailed); @@ -1306,27 +1311,14 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, if (log) log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals().GetSignalAsCString (signo)); - if (signo == SIGSEGV) { - lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); - } - - if (signo == SIGILL) { - lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); - } - - if (signo == SIGFPE) { - lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); - } - - if (signo == SIGBUS) { + switch (signo) + { + case SIGSEGV: + case SIGILL: + case SIGFPE: + case SIGBUS: lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info); + const auto reason = GetCrashReason(*info); return ProcessMessage::Crash(tid, reason, signo, fault_addr); } @@ -1335,141 +1327,6 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, return ProcessMessage::Signal(tid, signo); } -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGSEGV); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGSEGV"); - break; - case SEGV_MAPERR: - reason = ProcessMessage::eInvalidAddress; - break; - case SEGV_ACCERR: - reason = ProcessMessage::ePrivilegedAddress; - break; - } - - return reason; -} - -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGILL); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGILL"); - break; - case ILL_ILLOPC: - reason = ProcessMessage::eIllegalOpcode; - break; - case ILL_ILLOPN: - reason = ProcessMessage::eIllegalOperand; - break; - case ILL_ILLADR: - reason = ProcessMessage::eIllegalAddressingMode; - break; - case ILL_ILLTRP: - reason = ProcessMessage::eIllegalTrap; - break; - case ILL_PRVOPC: - reason = ProcessMessage::ePrivilegedOpcode; - break; - case ILL_PRVREG: - reason = ProcessMessage::ePrivilegedRegister; - break; - case ILL_COPROC: - reason = ProcessMessage::eCoprocessorError; - break; - case ILL_BADSTK: - reason = ProcessMessage::eInternalStackError; - break; - } - - return reason; -} - -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGFPE(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGFPE); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGFPE"); - break; - case FPE_INTDIV: - reason = ProcessMessage::eIntegerDivideByZero; - break; - case FPE_INTOVF: - reason = ProcessMessage::eIntegerOverflow; - break; - case FPE_FLTDIV: - reason = ProcessMessage::eFloatDivideByZero; - break; - case FPE_FLTOVF: - reason = ProcessMessage::eFloatOverflow; - break; - case FPE_FLTUND: - reason = ProcessMessage::eFloatUnderflow; - break; - case FPE_FLTRES: - reason = ProcessMessage::eFloatInexactResult; - break; - case FPE_FLTINV: - reason = ProcessMessage::eFloatInvalidOperation; - break; - case FPE_FLTSUB: - reason = ProcessMessage::eFloatSubscriptRange; - break; - } - - return reason; -} - -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGBUS); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGBUS"); - break; - case BUS_ADRALN: - reason = ProcessMessage::eIllegalAlignment; - break; - case BUS_ADRERR: - reason = ProcessMessage::eIllegalAddress; - break; - case BUS_OBJERR: - reason = ProcessMessage::eHardwareError; - break; - } - - return reason; -} - void ProcessMonitor::ServeOperation(OperationArgs *args) { @@ -1706,7 +1563,10 @@ ProcessMonitor::DupDescriptor(const char *path, int fd, int flags) if (target_fd == -1) return false; - return (dup2(target_fd, fd) == -1) ? false : true; + if (dup2(target_fd, fd) == -1) + return false; + + return (close(target_fd) == -1) ? false : true; } void @@ -1727,11 +1587,10 @@ ProcessMonitor::StopMonitor() StopOpThread(); sem_destroy(&m_operation_pending); sem_destroy(&m_operation_done); - - // Note: ProcessPOSIX passes the m_terminal_fd file descriptor to - // Process::SetSTDIOFileDescriptor, which in turn transfers ownership of - // the descriptor to a ConnectionFileDescriptor object. Consequently - // even though still has the file descriptor, we shouldn't close it here. + if (m_terminal_fd >= 0) { + close(m_terminal_fd); + m_terminal_fd = -1; + } } // FIXME: On Linux, when a new thread is created, we receive to notifications, diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h index 935fd85..4ae963c 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -79,7 +79,8 @@ public: /// Reads from this file descriptor yield both the standard output and /// standard error of this debugee. Even if stderr and stdout were /// redirected on launch it may still happen that data is available on this - /// descriptor (if the inferior process opens /dev/tty, for example). + /// descriptor (if the inferior process opens /dev/tty, for example). This descriptor is + /// closed after a call to StopMonitor(). /// /// If this monitor was attached to an existing process this method returns /// -1. @@ -311,18 +312,6 @@ private: MonitorSignal(ProcessMonitor *monitor, const siginfo_t *info, lldb::pid_t pid); - static ProcessMessage::CrashReason - GetCrashReasonForSIGSEGV(const siginfo_t *info); - - static ProcessMessage::CrashReason - GetCrashReasonForSIGILL(const siginfo_t *info); - - static ProcessMessage::CrashReason - GetCrashReasonForSIGFPE(const siginfo_t *info); - - static ProcessMessage::CrashReason - GetCrashReasonForSIGBUS(const siginfo_t *info); - void DoOperation(Operation *op); diff --git a/source/Plugins/Process/POSIX/CrashReason.cpp b/source/Plugins/Process/POSIX/CrashReason.cpp new file mode 100644 index 0000000..4dd91a6 --- /dev/null +++ b/source/Plugins/Process/POSIX/CrashReason.cpp @@ -0,0 +1,315 @@ +//===-- CrashReason.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CrashReason.h" + +#include <sstream> + +namespace { + +void +AppendFaultAddr (std::string& str, lldb::addr_t addr) +{ + std::stringstream ss; + ss << " (fault address: 0x" << std::hex << addr << ")"; + str += ss.str(); +} + +CrashReason +GetCrashReasonForSIGSEGV(const siginfo_t& info) +{ + assert(info.si_signo == SIGSEGV); + + switch (info.si_code) + { + case SI_KERNEL: + // Linux will occasionally send spurious SI_KERNEL codes. + // (this is poorly documented in sigaction) + // One way to get this is via unaligned SIMD loads. + return CrashReason::eInvalidAddress; // for lack of anything better + case SEGV_MAPERR: + return CrashReason::eInvalidAddress; + case SEGV_ACCERR: + return CrashReason::ePrivilegedAddress; + } + + assert(false && "unexpected si_code for SIGSEGV"); + return CrashReason::eInvalidCrashReason; +} + +CrashReason +GetCrashReasonForSIGILL(const siginfo_t& info) +{ + assert(info.si_signo == SIGILL); + + switch (info.si_code) + { + case ILL_ILLOPC: + return CrashReason::eIllegalOpcode; + case ILL_ILLOPN: + return CrashReason::eIllegalOperand; + case ILL_ILLADR: + return CrashReason::eIllegalAddressingMode; + case ILL_ILLTRP: + return CrashReason::eIllegalTrap; + case ILL_PRVOPC: + return CrashReason::ePrivilegedOpcode; + case ILL_PRVREG: + return CrashReason::ePrivilegedRegister; + case ILL_COPROC: + return CrashReason::eCoprocessorError; + case ILL_BADSTK: + return CrashReason::eInternalStackError; + } + + assert(false && "unexpected si_code for SIGILL"); + return CrashReason::eInvalidCrashReason; +} + +CrashReason +GetCrashReasonForSIGFPE(const siginfo_t& info) +{ + assert(info.si_signo == SIGFPE); + + switch (info.si_code) + { + case FPE_INTDIV: + return CrashReason::eIntegerDivideByZero; + case FPE_INTOVF: + return CrashReason::eIntegerOverflow; + case FPE_FLTDIV: + return CrashReason::eFloatDivideByZero; + case FPE_FLTOVF: + return CrashReason::eFloatOverflow; + case FPE_FLTUND: + return CrashReason::eFloatUnderflow; + case FPE_FLTRES: + return CrashReason::eFloatInexactResult; + case FPE_FLTINV: + return CrashReason::eFloatInvalidOperation; + case FPE_FLTSUB: + return CrashReason::eFloatSubscriptRange; + } + + assert(false && "unexpected si_code for SIGFPE"); + return CrashReason::eInvalidCrashReason; +} + +CrashReason +GetCrashReasonForSIGBUS(const siginfo_t& info) +{ + assert(info.si_signo == SIGBUS); + + switch (info.si_code) + { + case BUS_ADRALN: + return CrashReason::eIllegalAlignment; + case BUS_ADRERR: + return CrashReason::eIllegalAddress; + case BUS_OBJERR: + return CrashReason::eHardwareError; + } + + assert(false && "unexpected si_code for SIGBUS"); + return CrashReason::eInvalidCrashReason; +} + +} + +std::string +GetCrashReasonString (CrashReason reason, lldb::addr_t fault_addr) +{ + std::string str; + + switch (reason) + { + default: + assert(false && "invalid CrashReason"); + break; + + case CrashReason::eInvalidAddress: + str = "invalid address"; + AppendFaultAddr (str, fault_addr); + break; + case CrashReason::ePrivilegedAddress: + str = "address access protected"; + AppendFaultAddr (str, fault_addr); + break; + case CrashReason::eIllegalOpcode: + str = "illegal instruction"; + break; + case CrashReason::eIllegalOperand: + str = "illegal instruction operand"; + break; + case CrashReason::eIllegalAddressingMode: + str = "illegal addressing mode"; + break; + case CrashReason::eIllegalTrap: + str = "illegal trap"; + break; + case CrashReason::ePrivilegedOpcode: + str = "privileged instruction"; + break; + case CrashReason::ePrivilegedRegister: + str = "privileged register"; + break; + case CrashReason::eCoprocessorError: + str = "coprocessor error"; + break; + case CrashReason::eInternalStackError: + str = "internal stack error"; + break; + case CrashReason::eIllegalAlignment: + str = "illegal alignment"; + break; + case CrashReason::eIllegalAddress: + str = "illegal address"; + break; + case CrashReason::eHardwareError: + str = "hardware error"; + break; + case CrashReason::eIntegerDivideByZero: + str = "integer divide by zero"; + break; + case CrashReason::eIntegerOverflow: + str = "integer overflow"; + break; + case CrashReason::eFloatDivideByZero: + str = "floating point divide by zero"; + break; + case CrashReason::eFloatOverflow: + str = "floating point overflow"; + break; + case CrashReason::eFloatUnderflow: + str = "floating point underflow"; + break; + case CrashReason::eFloatInexactResult: + str = "inexact floating point result"; + break; + case CrashReason::eFloatInvalidOperation: + str = "invalid floating point operation"; + break; + case CrashReason::eFloatSubscriptRange: + str = "invalid floating point subscript range"; + break; + } + + return str; +} + +const char * +CrashReasonAsString (CrashReason reason) +{ +#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION + // Just return the code in ascii for integration builds. + chcar str[8]; + sprintf(str, "%d", reason); +#else + const char *str = nullptr; + + switch (reason) + { + case CrashReason::eInvalidCrashReason: + str = "eInvalidCrashReason"; + break; + + // SIGSEGV crash reasons. + case CrashReason::eInvalidAddress: + str = "eInvalidAddress"; + break; + case CrashReason::ePrivilegedAddress: + str = "ePrivilegedAddress"; + break; + + // SIGILL crash reasons. + case CrashReason::eIllegalOpcode: + str = "eIllegalOpcode"; + break; + case CrashReason::eIllegalOperand: + str = "eIllegalOperand"; + break; + case CrashReason::eIllegalAddressingMode: + str = "eIllegalAddressingMode"; + break; + case CrashReason::eIllegalTrap: + str = "eIllegalTrap"; + break; + case CrashReason::ePrivilegedOpcode: + str = "ePrivilegedOpcode"; + break; + case CrashReason::ePrivilegedRegister: + str = "ePrivilegedRegister"; + break; + case CrashReason::eCoprocessorError: + str = "eCoprocessorError"; + break; + case CrashReason::eInternalStackError: + str = "eInternalStackError"; + break; + + // SIGBUS crash reasons: + case CrashReason::eIllegalAlignment: + str = "eIllegalAlignment"; + break; + case CrashReason::eIllegalAddress: + str = "eIllegalAddress"; + break; + case CrashReason::eHardwareError: + str = "eHardwareError"; + break; + + // SIGFPE crash reasons: + case CrashReason::eIntegerDivideByZero: + str = "eIntegerDivideByZero"; + break; + case CrashReason::eIntegerOverflow: + str = "eIntegerOverflow"; + break; + case CrashReason::eFloatDivideByZero: + str = "eFloatDivideByZero"; + break; + case CrashReason::eFloatOverflow: + str = "eFloatOverflow"; + break; + case CrashReason::eFloatUnderflow: + str = "eFloatUnderflow"; + break; + case CrashReason::eFloatInexactResult: + str = "eFloatInexactResult"; + break; + case CrashReason::eFloatInvalidOperation: + str = "eFloatInvalidOperation"; + break; + case CrashReason::eFloatSubscriptRange: + str = "eFloatSubscriptRange"; + break; + } +#endif + + return str; +} + +CrashReason +GetCrashReason(const siginfo_t& info) +{ + switch(info.si_signo) + { + case SIGSEGV: + return GetCrashReasonForSIGSEGV(info); + case SIGBUS: + return GetCrashReasonForSIGBUS(info); + case SIGFPE: + return GetCrashReasonForSIGFPE(info); + case SIGILL: + return GetCrashReasonForSIGILL(info); + } + + assert(false && "unexpected signal"); + return CrashReason::eInvalidCrashReason; +} diff --git a/source/Plugins/Process/POSIX/CrashReason.h b/source/Plugins/Process/POSIX/CrashReason.h new file mode 100644 index 0000000..f6d9ba5 --- /dev/null +++ b/source/Plugins/Process/POSIX/CrashReason.h @@ -0,0 +1,62 @@ +//===-- CrashReason.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_CrashReason_H_ +#define liblldb_CrashReason_H_ + +#include "lldb/lldb-types.h" + +#include <signal.h> + +#include <string> + +enum class CrashReason +{ + eInvalidCrashReason, + + // SIGSEGV crash reasons. + eInvalidAddress, + ePrivilegedAddress, + + // SIGILL crash reasons. + eIllegalOpcode, + eIllegalOperand, + eIllegalAddressingMode, + eIllegalTrap, + ePrivilegedOpcode, + ePrivilegedRegister, + eCoprocessorError, + eInternalStackError, + + // SIGBUS crash reasons, + eIllegalAlignment, + eIllegalAddress, + eHardwareError, + + // SIGFPE crash reasons, + eIntegerDivideByZero, + eIntegerOverflow, + eFloatDivideByZero, + eFloatOverflow, + eFloatUnderflow, + eFloatInexactResult, + eFloatInvalidOperation, + eFloatSubscriptRange +}; + +std::string +GetCrashReasonString (CrashReason reason, lldb::addr_t fault_addr); + +const char * +CrashReasonAsString (CrashReason reason); + +CrashReason +GetCrashReason(const siginfo_t& info); + +#endif // #ifndef liblldb_CrashReason_H_ diff --git a/source/Plugins/Process/POSIX/POSIXStopInfo.cpp b/source/Plugins/Process/POSIX/POSIXStopInfo.cpp index 6e2c140..3b8cea7 100644 --- a/source/Plugins/Process/POSIX/POSIXStopInfo.cpp +++ b/source/Plugins/Process/POSIX/POSIXStopInfo.cpp @@ -45,6 +45,15 @@ POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) //===----------------------------------------------------------------------===// // POSIXCrashStopInfo +POSIXCrashStopInfo::POSIXCrashStopInfo(POSIXThread &thread, + uint32_t status, + CrashReason reason, + lldb::addr_t fault_addr) + : POSIXStopInfo(thread, status) +{ + m_description = ::GetCrashReasonString(reason, fault_addr); +} + POSIXCrashStopInfo::~POSIXCrashStopInfo() { } lldb::StopReason @@ -53,12 +62,6 @@ POSIXCrashStopInfo::GetStopReason() const return lldb::eStopReasonException; } -const char * -POSIXCrashStopInfo::GetDescription() -{ - return ProcessMessage::GetCrashReasonString(m_crash_reason, m_fault_addr); -} - //===----------------------------------------------------------------------===// // POSIXNewThreadStopInfo diff --git a/source/Plugins/Process/POSIX/POSIXStopInfo.h b/source/Plugins/Process/POSIX/POSIXStopInfo.h index cbf309e..a1ee2ea 100644 --- a/source/Plugins/Process/POSIX/POSIXStopInfo.h +++ b/source/Plugins/Process/POSIX/POSIXStopInfo.h @@ -16,8 +16,10 @@ // Project includes #include "lldb/Target/StopInfo.h" +#include "CrashReason.h" #include "POSIXThread.h" -#include "ProcessMessage.h" + +#include <string> //===----------------------------------------------------------------------===// /// @class POSIXStopInfo @@ -69,25 +71,13 @@ class POSIXCrashStopInfo { public: POSIXCrashStopInfo(POSIXThread &thread, uint32_t status, - ProcessMessage::CrashReason reason, - lldb::addr_t fault_addr) - : POSIXStopInfo(thread, status), - m_crash_reason(reason), - m_fault_addr(fault_addr) - { } - + CrashReason reason, + lldb::addr_t fault_addr); ~POSIXCrashStopInfo(); lldb::StopReason GetStopReason() const; - - const char * - GetDescription(); - -private: - ProcessMessage::CrashReason m_crash_reason; - lldb::addr_t m_fault_addr; -}; +}; //===----------------------------------------------------------------------===// /// @class POSIXNewThreadStopInfo diff --git a/source/Plugins/Process/POSIX/ProcessMessage.cpp b/source/Plugins/Process/POSIX/ProcessMessage.cpp index 5c53627..02049a2 100644 --- a/source/Plugins/Process/POSIX/ProcessMessage.cpp +++ b/source/Plugins/Process/POSIX/ProcessMessage.cpp @@ -9,205 +9,19 @@ #include "ProcessMessage.h" -#include <sstream> - using namespace lldb_private; -namespace { - -inline void AppendFaultAddr(std::string& str, lldb::addr_t addr) -{ - std::stringstream ss; - ss << " (fault address: 0x" << std::hex << addr << ")"; - str += ss.str(); -} - -} - -const char * -ProcessMessage::GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) -{ - static std::string str; - - switch (reason) - { - default: - assert(false && "invalid CrashReason"); - break; - - case eInvalidAddress: - str = "invalid address"; - AppendFaultAddr(str, fault_addr); - break; - case ePrivilegedAddress: - str = "address access protected"; - AppendFaultAddr(str, fault_addr); - break; - case eIllegalOpcode: - str = "illegal instruction"; - break; - case eIllegalOperand: - str = "illegal instruction operand"; - break; - case eIllegalAddressingMode: - str = "illegal addressing mode"; - break; - case eIllegalTrap: - str = "illegal trap"; - break; - case ePrivilegedOpcode: - str = "privileged instruction"; - break; - case ePrivilegedRegister: - str = "privileged register"; - break; - case eCoprocessorError: - str = "coprocessor error"; - break; - case eInternalStackError: - str = "internal stack error"; - break; - case eIllegalAlignment: - str = "illegal alignment"; - break; - case eIllegalAddress: - str = "illegal address"; - break; - case eHardwareError: - str = "hardware error"; - break; - case eIntegerDivideByZero: - str = "integer divide by zero"; - break; - case eIntegerOverflow: - str = "integer overflow"; - break; - case eFloatDivideByZero: - str = "floating point divide by zero"; - break; - case eFloatOverflow: - str = "floating point overflow"; - break; - case eFloatUnderflow: - str = "floating point underflow"; - break; - case eFloatInexactResult: - str = "inexact floating point result"; - break; - case eFloatInvalidOperation: - str = "invalid floating point operation"; - break; - case eFloatSubscriptRange: - str = "invalid floating point subscript range"; - break; - } - - return str.c_str(); -} - -const char * -ProcessMessage::PrintCrashReason(CrashReason reason) -{ -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else - const char *str = NULL; - - switch (reason) - { - case eInvalidCrashReason: - str = "eInvalidCrashReason"; - break; - - // SIGSEGV crash reasons. - case eInvalidAddress: - str = "eInvalidAddress"; - break; - case ePrivilegedAddress: - str = "ePrivilegedAddress"; - break; - - // SIGILL crash reasons. - case eIllegalOpcode: - str = "eIllegalOpcode"; - break; - case eIllegalOperand: - str = "eIllegalOperand"; - break; - case eIllegalAddressingMode: - str = "eIllegalAddressingMode"; - break; - case eIllegalTrap: - str = "eIllegalTrap"; - break; - case ePrivilegedOpcode: - str = "ePrivilegedOpcode"; - break; - case ePrivilegedRegister: - str = "ePrivilegedRegister"; - break; - case eCoprocessorError: - str = "eCoprocessorError"; - break; - case eInternalStackError: - str = "eInternalStackError"; - break; - - // SIGBUS crash reasons: - case eIllegalAlignment: - str = "eIllegalAlignment"; - break; - case eIllegalAddress: - str = "eIllegalAddress"; - break; - case eHardwareError: - str = "eHardwareError"; - break; - - // SIGFPE crash reasons: - case eIntegerDivideByZero: - str = "eIntegerDivideByZero"; - break; - case eIntegerOverflow: - str = "eIntegerOverflow"; - break; - case eFloatDivideByZero: - str = "eFloatDivideByZero"; - break; - case eFloatOverflow: - str = "eFloatOverflow"; - break; - case eFloatUnderflow: - str = "eFloatUnderflow"; - break; - case eFloatInexactResult: - str = "eFloatInexactResult"; - break; - case eFloatInvalidOperation: - str = "eFloatInvalidOperation"; - break; - case eFloatSubscriptRange: - str = "eFloatSubscriptRange"; - break; - } -#endif - - return str; -} - const char * ProcessMessage::PrintCrashReason() const { - return PrintCrashReason(m_crash_reason); + return CrashReasonAsString(m_crash_reason); } const char * ProcessMessage::PrintKind(Kind kind) { #ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. + // Just return the code in ascii for integration builds. chcar str[8]; sprintf(str, "%d", reason); #else diff --git a/source/Plugins/Process/POSIX/ProcessMessage.h b/source/Plugins/Process/POSIX/ProcessMessage.h index 40462d0..f932e9f 100644 --- a/source/Plugins/Process/POSIX/ProcessMessage.h +++ b/source/Plugins/Process/POSIX/ProcessMessage.h @@ -10,7 +10,10 @@ #ifndef liblldb_ProcessMessage_H_ #define liblldb_ProcessMessage_H_ +#include "CrashReason.h" + #include <cassert> +#include <string> #include "lldb/lldb-defines.h" #include "lldb/lldb-types.h" @@ -36,44 +39,10 @@ public: eExecMessage }; - enum CrashReason - { - eInvalidCrashReason, - - // SIGSEGV crash reasons. - eInvalidAddress, - ePrivilegedAddress, - - // SIGILL crash reasons. - eIllegalOpcode, - eIllegalOperand, - eIllegalAddressingMode, - eIllegalTrap, - ePrivilegedOpcode, - ePrivilegedRegister, - eCoprocessorError, - eInternalStackError, - - // SIGBUS crash reasons, - eIllegalAlignment, - eIllegalAddress, - eHardwareError, - - // SIGFPE crash reasons, - eIntegerDivideByZero, - eIntegerOverflow, - eFloatDivideByZero, - eFloatOverflow, - eFloatUnderflow, - eFloatInexactResult, - eFloatInvalidOperation, - eFloatSubscriptRange - }; - ProcessMessage() : m_tid(LLDB_INVALID_PROCESS_ID), m_kind(eInvalidMessage), - m_crash_reason(eInvalidCrashReason), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(0), m_addr(0) { } @@ -175,15 +144,9 @@ public: return m_child_tid; } - static const char * - GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr); - const char * PrintCrashReason() const; - static const char * - PrintCrashReason(CrashReason reason); - const char * PrintKind() const; @@ -195,7 +158,7 @@ private: int status = 0, lldb::addr_t addr = 0) : m_tid(tid), m_kind(kind), - m_crash_reason(eInvalidCrashReason), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(status), m_addr(addr), m_child_tid(0) { } @@ -203,14 +166,14 @@ private: ProcessMessage(lldb::tid_t tid, Kind kind, lldb::tid_t child_tid) : m_tid(tid), m_kind(kind), - m_crash_reason(eInvalidCrashReason), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(0), m_addr(0), m_child_tid(child_tid) { } lldb::tid_t m_tid; Kind m_kind : 8; - CrashReason m_crash_reason : 8; + CrashReason m_crash_reason; int m_status; lldb::addr_t m_addr; lldb::tid_t m_child_tid; diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp index 0e5ab5a..882fac7 100644 --- a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp +++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp @@ -252,7 +252,16 @@ ProcessPOSIX::DoLaunch (Module *module, if (!error.Success()) return error; - SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); + int terminal = m_monitor->GetTerminalFD(); + if (terminal >= 0) { + // The reader thread will close the file descriptor when done, so we pass it a copy. + int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0); + if (stdio == -1) { + error.SetErrorToErrno(); + return error; + } + SetSTDIOFileDescriptor(stdio); + } SetID(m_monitor->GetPID()); return error; diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp index b542db4..80e1c19 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp @@ -38,14 +38,21 @@ RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() bool RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR() { - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); } bool RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR() { - // XXX not yet implemented + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc)); +} + +bool +RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX() +{ + // XXX: Need a way to read/write process VMX registers with ptrace. return false; } @@ -59,7 +66,14 @@ RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() bool RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() { - // XXX not yet implemented + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc)); +} + +bool +RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX() +{ + // XXX: Need a way to read/write process VMX registers with ptrace. return false; } @@ -146,26 +160,15 @@ RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const RegisterInfo *reg { if (!ReadFPR()) return false; + uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; + value.SetUInt64(*(uint64_t*)src); } - else + else if (IsGPR(reg)) { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) - { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - - bool success = ReadRegister(full_reg, value); + bool success = ReadRegister(reg, value); if (success) { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - value.SetUInt64(value.GetAsUInt64() >> 8); - // If our return byte size was greater than the return value reg size, then // use the type specified by reg_info rather than the uint64_t default if (value.GetByteSize() > reg_info->byte_size) @@ -183,7 +186,16 @@ RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const RegisterInfo *re const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; if (IsGPR(reg)) + { return WriteRegister(reg, value); + } + else if (IsFPR(reg)) + { + assert (reg_info->byte_offset < sizeof(m_fpr_powerpc)); + uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; + *(uint64_t *)dst = value.GetAsUInt64(); + return WriteFPR(); + } return false; } @@ -221,6 +233,9 @@ RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(const DataBuf if (WriteGPR()) { src += GetGPRSize(); + ::memcpy (&m_fpr_powerpc, src, sizeof(m_fpr_powerpc)); + + success = WriteFPR(); } } } diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h index 92a3312..5c686df 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h @@ -23,17 +23,26 @@ public: protected: bool + IsVMX(); + + bool ReadGPR(); bool ReadFPR(); bool + ReadVMX(); + + bool WriteGPR(); bool WriteFPR(); + bool + WriteVMX(); + // lldb_private::RegisterContext bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 1088924..25a195e 100644 --- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -15,7 +15,7 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/Args.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/StreamFile.h" #include "lldb/DataFormatters/FormatManager.h" @@ -158,8 +158,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict regex_match.GetMatchAtIndex(slice_cstr, 2, msbit_str) && regex_match.GetMatchAtIndex(slice_cstr, 3, lsbit_str)) { - const uint32_t msbit = Args::StringToUInt32(msbit_str.c_str(), UINT32_MAX); - const uint32_t lsbit = Args::StringToUInt32(lsbit_str.c_str(), UINT32_MAX); + const uint32_t msbit = StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX); + const uint32_t lsbit = StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX); if (msbit != UINT32_MAX && lsbit != UINT32_MAX) { if (msbit > lsbit) diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp index 5170e6d..5133d60 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp @@ -134,6 +134,45 @@ typedef struct _FPR uint64_t fpscr; } FPR; +typedef struct _VMX +{ + uint32_t v0[4]; + uint32_t v1[4]; + uint32_t v2[4]; + uint32_t v3[4]; + uint32_t v4[4]; + uint32_t v5[4]; + uint32_t v6[4]; + uint32_t v7[4]; + uint32_t v8[4]; + uint32_t v9[4]; + uint32_t v10[4]; + uint32_t v11[4]; + uint32_t v12[4]; + uint32_t v13[4]; + uint32_t v14[4]; + uint32_t v15[4]; + uint32_t v16[4]; + uint32_t v17[4]; + uint32_t v18[4]; + uint32_t v19[4]; + uint32_t v20[4]; + uint32_t v21[4]; + uint32_t v22[4]; + uint32_t v23[4]; + uint32_t v24[4]; + uint32_t v25[4]; + uint32_t v26[4]; + uint32_t v27[4]; + uint32_t v28[4]; + uint32_t v29[4]; + uint32_t v30[4]; + uint32_t v31[4]; + uint32_t pad[2]; + uint32_t vrsave; + uint32_t vscr; +} VMX; + //--------------------------------------------------------------------------- // Include RegisterInfos_powerpc to declare our g_register_infos_powerpc structure. //--------------------------------------------------------------------------- diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index f47d687..1b3a949 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -811,7 +811,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () if (m_frame_type == eTrapHandlerFrame && process) { m_fast_unwind_plan_sp.reset(); - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); + unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc) && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) { return unwind_plan_sp; @@ -826,7 +826,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () // But there is not. if (process && process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx)) { - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); + // We must specifically call the GetEHFrameUnwindPlan() method here -- normally we would + // call GetUnwindPlanAtCallSite() -- because CallSite may return an unwind plan sourced from + // either eh_frame (that's what we intend) or compact unwind (this won't work) + unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) { UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it", diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp index b9b9dca..b38d6cc 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp @@ -125,3 +125,8 @@ RegisterContextLinux_i386::GetRegisterCount () const return static_cast<uint32_t> (sizeof (g_register_infos_i386) / sizeof (g_register_infos_i386 [0])); } +uint32_t +RegisterContextLinux_i386::GetUserRegisterCount () const +{ + return static_cast<uint32_t> (k_num_user_registers_i386); +} diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_i386.h b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h index f8b21fc..cb71d79 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_i386.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h @@ -26,6 +26,9 @@ public: uint32_t GetRegisterCount () const override; + + uint32_t + GetUserRegisterCount () const override; }; #endif diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp index 74f016b..5c93ebf 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp @@ -145,10 +145,26 @@ GetRegisterInfoCount (const ArchSpec &target_arch) } } +static uint32_t +GetUserRegisterInfoCount (const ArchSpec &target_arch) +{ + switch (target_arch.GetMachine()) + { + case llvm::Triple::x86: + return static_cast<uint32_t> (k_num_user_registers_i386); + case llvm::Triple::x86_64: + return static_cast<uint32_t> (k_num_user_registers_x86_64); + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) : lldb_private::RegisterInfoInterface(target_arch), m_register_info_p (GetRegisterInfoPtr (target_arch)), - m_register_info_count (GetRegisterInfoCount (target_arch)) + m_register_info_count (GetRegisterInfoCount (target_arch)), + m_user_register_count (GetUserRegisterInfoCount (target_arch)) { } @@ -169,3 +185,9 @@ RegisterContextLinux_x86_64::GetRegisterCount () const { return m_register_info_count; } + +uint32_t +RegisterContextLinux_x86_64::GetUserRegisterCount () const +{ + return m_user_register_count; +} diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h index 7b68286..0cdfae9 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h @@ -27,9 +27,13 @@ public: uint32_t GetRegisterCount () const override; + uint32_t + GetUserRegisterCount () const override; + private: const lldb_private::RegisterInfo *m_register_info_p; uint32_t m_register_info_count; + uint32_t m_user_register_count; }; #endif diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp index a9477d5..828fb25 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp @@ -106,10 +106,49 @@ uint32_t g_fpr_regnums[] = fpr_fpscr_powerpc, }; +static const +uint32_t g_vmx_regnums[] = +{ + vmx_v0_powerpc, + vmx_v1_powerpc, + vmx_v2_powerpc, + vmx_v3_powerpc, + vmx_v4_powerpc, + vmx_v5_powerpc, + vmx_v6_powerpc, + vmx_v7_powerpc, + vmx_v8_powerpc, + vmx_v9_powerpc, + vmx_v10_powerpc, + vmx_v11_powerpc, + vmx_v12_powerpc, + vmx_v13_powerpc, + vmx_v14_powerpc, + vmx_v15_powerpc, + vmx_v16_powerpc, + vmx_v17_powerpc, + vmx_v18_powerpc, + vmx_v19_powerpc, + vmx_v20_powerpc, + vmx_v21_powerpc, + vmx_v22_powerpc, + vmx_v23_powerpc, + vmx_v24_powerpc, + vmx_v25_powerpc, + vmx_v26_powerpc, + vmx_v27_powerpc, + vmx_v28_powerpc, + vmx_v29_powerpc, + vmx_v30_powerpc, + vmx_v31_powerpc, + vmx_vrsave_powerpc, + vmx_vscr_powerpc, +}; + // Number of register sets provided by this context. enum { - k_num_register_sets = 2 + k_num_register_sets = 3 }; static const RegisterSet @@ -117,20 +156,26 @@ g_reg_sets_powerpc[k_num_register_sets] = { { "General Purpose Registers", "gpr", k_num_gpr_registers_powerpc, g_gpr_regnums }, { "Floating Point Registers", "fpr", k_num_fpr_registers_powerpc, g_fpr_regnums }, + { "Altivec/VMX Registers", "vmx", k_num_vmx_registers_powerpc, g_vmx_regnums }, }; bool RegisterContextPOSIX_powerpc::IsGPR(unsigned reg) { - return reg <= k_num_gpr_registers_powerpc; // GPR's come first. + return (reg >= k_first_gpr_powerpc) && (reg <= k_last_gpr_powerpc); // GPR's come first. } bool RegisterContextPOSIX_powerpc::IsFPR(unsigned reg) { - // XXX return (reg >= k_first_fpr) && (reg <= k_last_fpr); } +bool +RegisterContextPOSIX_powerpc::IsVMX(unsigned reg) +{ + return (reg >= k_first_vmx) && (reg <= k_last_vmx); +} + RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc(Thread &thread, uint32_t concrete_frame_idx, RegisterInfoInterface *register_info) diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h index 3194c39..c7a2451 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h @@ -97,9 +97,47 @@ enum fpr_fpscr_powerpc, k_last_fpr = fpr_fpscr_powerpc, + k_first_vmx, + vmx_v0_powerpc = k_first_vmx, + vmx_v1_powerpc, + vmx_v2_powerpc, + vmx_v3_powerpc, + vmx_v4_powerpc, + vmx_v5_powerpc, + vmx_v6_powerpc, + vmx_v7_powerpc, + vmx_v8_powerpc, + vmx_v9_powerpc, + vmx_v10_powerpc, + vmx_v11_powerpc, + vmx_v12_powerpc, + vmx_v13_powerpc, + vmx_v14_powerpc, + vmx_v15_powerpc, + vmx_v16_powerpc, + vmx_v17_powerpc, + vmx_v18_powerpc, + vmx_v19_powerpc, + vmx_v20_powerpc, + vmx_v21_powerpc, + vmx_v22_powerpc, + vmx_v23_powerpc, + vmx_v24_powerpc, + vmx_v25_powerpc, + vmx_v26_powerpc, + vmx_v27_powerpc, + vmx_v28_powerpc, + vmx_v29_powerpc, + vmx_v30_powerpc, + vmx_v31_powerpc, + vmx_vrsave_powerpc, + vmx_vscr_powerpc, + k_last_vmx = vmx_vscr_powerpc, + k_num_registers_powerpc, k_num_gpr_registers_powerpc = k_last_gpr_powerpc - k_first_gpr_powerpc + 1, k_num_fpr_registers_powerpc = k_last_fpr - k_first_fpr + 1, + k_num_vmx_registers_powerpc = k_last_vmx - k_first_vmx + 1, }; class RegisterContextPOSIX_powerpc @@ -147,6 +185,8 @@ public: protected: uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc]; // general purpose registers. + uint64_t m_fpr_powerpc[k_num_fpr_registers_powerpc]; // floating point registers. + uint32_t m_vmx_powerpc[k_num_vmx_registers_powerpc][4]; std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) // Determines if an extended register set is supported on the processor running the inferior process. @@ -162,12 +202,17 @@ protected: bool IsFPR(unsigned reg); + bool + IsVMX(unsigned reg); + lldb::ByteOrder GetByteOrder(); virtual bool ReadGPR() = 0; virtual bool ReadFPR() = 0; + virtual bool ReadVMX() = 0; virtual bool WriteGPR() = 0; virtual bool WriteFPR() = 0; + virtual bool WriteVMX() = 0; }; #endif // #ifndef liblldb_RegisterContextPOSIX_powerpc_H_ diff --git a/source/Plugins/Process/Utility/RegisterContext_powerpc.h b/source/Plugins/Process/Utility/RegisterContext_powerpc.h index cf54cc0..7438b88 100644 --- a/source/Plugins/Process/Utility/RegisterContext_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterContext_powerpc.h @@ -79,10 +79,45 @@ enum gcc_dwarf_f31_powerpc, gcc_dwarf_cr_powerpc, gcc_dwarf_fpscr_powerpc, + gcc_dwarf_msr_powerpc, + gcc_dwarf_vscr_powerpc, gcc_dwarf_xer_powerpc = 101, gcc_dwarf_lr_powerpc = 108, gcc_dwarf_ctr_powerpc, gcc_dwarf_pc_powerpc, + gcc_dwarf_vrsave_powerpc = 356, + gcc_dwarf_v0_powerpc = 1124, + gcc_dwarf_v1_powerpc, + gcc_dwarf_v2_powerpc, + gcc_dwarf_v3_powerpc, + gcc_dwarf_v4_powerpc, + gcc_dwarf_v5_powerpc, + gcc_dwarf_v6_powerpc, + gcc_dwarf_v7_powerpc, + gcc_dwarf_v8_powerpc, + gcc_dwarf_v9_powerpc, + gcc_dwarf_v10_powerpc, + gcc_dwarf_v11_powerpc, + gcc_dwarf_v12_powerpc, + gcc_dwarf_v13_powerpc, + gcc_dwarf_v14_powerpc, + gcc_dwarf_v15_powerpc, + gcc_dwarf_v16_powerpc, + gcc_dwarf_v17_powerpc, + gcc_dwarf_v18_powerpc, + gcc_dwarf_v19_powerpc, + gcc_dwarf_v20_powerpc, + gcc_dwarf_v21_powerpc, + gcc_dwarf_v22_powerpc, + gcc_dwarf_v23_powerpc, + gcc_dwarf_v24_powerpc, + gcc_dwarf_v25_powerpc, + gcc_dwarf_v26_powerpc, + gcc_dwarf_v27_powerpc, + gcc_dwarf_v28_powerpc, + gcc_dwarf_v29_powerpc, + gcc_dwarf_v30_powerpc, + gcc_dwarf_v31_powerpc, }; // GDB Register numbers (eRegisterKindGDB) @@ -152,12 +187,46 @@ enum gdb_f29_powerpc, gdb_f30_powerpc, gdb_f31_powerpc, - gdb_cr_powerpc, - gdb_fpscr_powerpc, - gdb_xer_powerpc = 101, - gdb_lr_powerpc = 108, - gdb_ctr_powerpc, gdb_pc_powerpc, + gdb_cr_powerpc = 66, + gdb_lr_powerpc, + gdb_ctr_powerpc, + gdb_xer_powerpc, + gdb_fpscr_powerpc, + gdb_v0_powerpc = 106, + gdb_v1_powerpc, + gdb_v2_powerpc, + gdb_v3_powerpc, + gdb_v4_powerpc, + gdb_v5_powerpc, + gdb_v6_powerpc, + gdb_v7_powerpc, + gdb_v8_powerpc, + gdb_v9_powerpc, + gdb_v10_powerpc, + gdb_v11_powerpc, + gdb_v12_powerpc, + gdb_v13_powerpc, + gdb_v14_powerpc, + gdb_v15_powerpc, + gdb_v16_powerpc, + gdb_v17_powerpc, + gdb_v18_powerpc, + gdb_v19_powerpc, + gdb_v20_powerpc, + gdb_v21_powerpc, + gdb_v22_powerpc, + gdb_v23_powerpc, + gdb_v24_powerpc, + gdb_v25_powerpc, + gdb_v26_powerpc, + gdb_v27_powerpc, + gdb_v28_powerpc, + gdb_v29_powerpc, + gdb_v30_powerpc, + gdb_v31_powerpc, + gdb_vscr_powerpc, + gdb_vrsave_powerpc, }; #endif // liblldb_RegisterContext_powerpc_H_ diff --git a/source/Plugins/Process/Utility/RegisterInfoInterface.h b/source/Plugins/Process/Utility/RegisterInfoInterface.h index 382475f..94cb5cc 100644 --- a/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ b/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -32,9 +32,20 @@ namespace lldb_private virtual const lldb_private::RegisterInfo * GetRegisterInfo () const = 0; + // Returns the number of registers including the user registers and the + // lldb internal registers also virtual uint32_t GetRegisterCount () const = 0; + // Returns the number of the user registers (excluding the registers + // kept for lldb internal use only). Subclasses should override it if + // they belongs to an architecture with lldb internal registers. + virtual uint32_t + GetUserRegisterCount () const + { + return GetRegisterCount(); + } + const lldb_private::ArchSpec& GetTargetArchitecture() const { return m_target_arch; } diff --git a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h index 0454266..fe145e9 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h @@ -14,6 +14,8 @@ (offsetof(GPR, regname)) #define FPR_OFFSET(regname) \ (offsetof(FPR, regname)) +#define VMX_OFFSET(regname) \ + (offsetof(VMX, regname)) #define GPR_SIZE(regname) \ (sizeof(((GPR*)NULL)->regname)) @@ -26,6 +28,9 @@ #define DEFINE_FPR(reg, lldb_kind) \ { #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, \ eFormatFloat, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, fpr_##reg##_powerpc }, NULL, NULL } +#define DEFINE_VMX(reg, lldb_kind) \ + { #reg, NULL, 16, VMX_OFFSET(reg), eEncodingVector, \ + eFormatVectorOfUInt32, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, vmx_##reg##_powerpc }, NULL, NULL } // General purpose registers. GCC, DWARF, Generic, GDB #define POWERPC_REGS \ @@ -98,7 +103,42 @@ DEFINE_FPR(f29, LLDB_INVALID_REGNUM), \ DEFINE_FPR(f30, LLDB_INVALID_REGNUM), \ DEFINE_FPR(f31, LLDB_INVALID_REGNUM), \ - { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL }, + { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL }, \ + DEFINE_VMX(v0, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v1, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v2, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v3, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v4, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v5, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v6, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v7, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v8, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v9, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v10, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v11, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v12, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v13, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v14, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v15, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v16, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v17, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v18, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v19, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v20, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v21, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v22, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v23, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v24, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v25, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v26, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v27, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v28, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v29, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v30, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v31, LLDB_INVALID_REGNUM), \ + { "vrsave", NULL, 4, VMX_OFFSET(vrsave), eEncodingUint, eFormatHex, { gcc_dwarf_vrsave_powerpc, gcc_dwarf_vrsave_powerpc, LLDB_INVALID_REGNUM, gdb_vrsave_powerpc, vmx_vrsave_powerpc }, NULL, NULL }, \ + { "vscr", NULL, 4, VMX_OFFSET(vscr), eEncodingUint, eFormatHex, { gcc_dwarf_vscr_powerpc, gcc_dwarf_vscr_powerpc, LLDB_INVALID_REGNUM, gdb_vscr_powerpc, vmx_vscr_powerpc }, NULL, NULL }, + static RegisterInfo g_register_infos_powerpc64[] = { diff --git a/source/Plugins/Process/Utility/lldb-x86-register-enums.h b/source/Plugins/Process/Utility/lldb-x86-register-enums.h index 99fca30..63027b4 100644 --- a/source/Plugins/Process/Utility/lldb-x86-register-enums.h +++ b/source/Plugins/Process/Utility/lldb-x86-register-enums.h @@ -118,7 +118,8 @@ namespace lldb_private k_num_registers_i386, k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1, k_num_fpr_registers_i386 = k_last_fpr_i386 - k_first_fpr_i386 + 1, - k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1 + k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1, + k_num_user_registers_i386 = k_num_gpr_registers_i386 + k_num_fpr_registers_i386 + k_num_avx_registers_i386, }; //--------------------------------------------------------------------------- @@ -285,7 +286,8 @@ namespace lldb_private k_num_registers_x86_64, k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1, k_num_fpr_registers_x86_64 = k_last_fpr_x86_64 - k_first_fpr_x86_64 + 1, - k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1 + k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1, + k_num_user_registers_x86_64 = k_num_gpr_registers_x86_64 + k_num_fpr_registers_x86_64 + k_num_avx_registers_x86_64, }; } diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index fb39d73..ead9595 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -412,7 +412,8 @@ enum { NT_FPREGSET, NT_PRPSINFO, NT_THRMISC = 7, - NT_PROCSTAT_AUXV = 16 + NT_PROCSTAT_AUXV = 16, + NT_PPC_VMX = 0x100 }; } @@ -538,6 +539,9 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * // FIXME: FreeBSD sticks an int at the beginning of the note m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4); break; + case FREEBSD::NT_PPC_VMX: + thread_data->vregset = note_data; + break; default: break; } diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp index 15b1b44..d12df21 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp @@ -18,7 +18,8 @@ using namespace lldb_private; RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &thread, RegisterInfoInterface *register_info, const DataExtractor &gpregset, - const DataExtractor &fpregset) + const DataExtractor &fpregset, + const DataExtractor &vregset) : RegisterContextPOSIX_powerpc(thread, 0, register_info) { m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); @@ -27,6 +28,9 @@ RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &threa m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); m_fpr.SetData(m_fpr_buffer); m_fpr.SetByteOrder(fpregset.GetByteOrder()); + m_vec_buffer.reset(new DataBufferHeap(vregset.GetDataStart(), vregset.GetByteSize())); + m_vec.SetData(m_vec_buffer); + m_vec.SetByteOrder(fpregset.GetByteOrder()); } RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() @@ -46,6 +50,12 @@ RegisterContextCorePOSIX_powerpc::ReadFPR() } bool +RegisterContextCorePOSIX_powerpc::ReadVMX() +{ + return true; +} + +bool RegisterContextCorePOSIX_powerpc::WriteGPR() { assert(0); @@ -60,16 +70,31 @@ RegisterContextCorePOSIX_powerpc::WriteFPR() } bool +RegisterContextCorePOSIX_powerpc::WriteVMX() +{ + assert(0); + return false; +} + +bool RegisterContextCorePOSIX_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) { lldb::offset_t offset = reg_info->byte_offset; - if (reg_info->name[0] == 'f') { + if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) { uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size); if (offset == reg_info->byte_offset + reg_info->byte_size) { value = v; return true; } + } else if (IsVMX(reg_info->kinds[lldb::eRegisterKindLLDB])) { + uint32_t v[4]; + offset = m_vec.CopyData(offset, reg_info->byte_size, &v); + if (offset == reg_info->byte_size) + { + value.SetBytes(v, reg_info->byte_size, m_vec.GetByteOrder()); + return true; + } } else { uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); if (offset == reg_info->byte_offset + reg_info->byte_size) diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h index e657558..a359060 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h @@ -20,7 +20,8 @@ public: RegisterContextCorePOSIX_powerpc (lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + const lldb_private::DataExtractor &fpregset, + const lldb_private::DataExtractor &vregset); ~RegisterContextCorePOSIX_powerpc(); @@ -47,16 +48,24 @@ protected: ReadFPR(); bool + ReadVMX(); + + bool WriteGPR(); bool WriteFPR(); + bool + WriteVMX(); + private: lldb::DataBufferSP m_gpr_buffer; lldb::DataBufferSP m_fpr_buffer; + lldb::DataBufferSP m_vec_buffer; lldb_private::DataExtractor m_gpr; lldb_private::DataExtractor m_fpr; + lldb_private::DataExtractor m_vec; }; #endif // #ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_ diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index d62bcfc..b16335f 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -38,7 +38,8 @@ ThreadElfCore::ThreadElfCore (Process &process, tid_t tid, m_thread_reg_ctx_sp (), m_signo(td.signo), m_gpregset_data(td.gpregset), - m_fpregset_data(td.fpregset) + m_fpregset_data(td.fpregset), + m_vregset_data(td.vregset) { } @@ -148,7 +149,7 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame) break; case llvm::Triple::ppc: case llvm::Triple::ppc64: - m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data)); + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data, m_vregset_data)); break; case llvm::Triple::x86: case llvm::Triple::x86_64: diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h index f1f00cf..50502c1 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -111,6 +111,7 @@ struct ThreadData { lldb_private::DataExtractor gpregset; lldb_private::DataExtractor fpregset; + lldb_private::DataExtractor vregset; int signo; std::string name; }; @@ -170,6 +171,7 @@ protected: lldb_private::DataExtractor m_gpregset_data; lldb_private::DataExtractor m_fpregset_data; + lldb_private::DataExtractor m_vregset_data; virtual bool CalculateStopInfo(); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 919fa54..d633b3e 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -26,9 +26,11 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Host/Pipe.h" #include "lldb/Host/Socket.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Process.h" +#include "llvm/ADT/SmallString.h" // Project includes #include "ProcessGDBRemoteLog.h" @@ -756,13 +758,14 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, } // use native registers, not the GDB registers - debugserver_args.AppendArgument("--native-regs"); - // make debugserver run in its own session so signals generated by - // special terminal key sequences (^C) don't affect debugserver - debugserver_args.AppendArgument("--setsid"); + debugserver_args.AppendArgument("--native-regs"); - char named_pipe_path[PATH_MAX]; - named_pipe_path[0] = '\0'; + if (launch_info.GetLaunchInSeparateProcessGroup()) + { + debugserver_args.AppendArgument("--setsid"); + } + + llvm::SmallString<PATH_MAX> named_pipe_path; Pipe port_named_pipe; bool listen = false; @@ -776,25 +779,11 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, { // Binding to port zero, we need to figure out what port it ends up // using using a named pipe... - FileSpec tmpdir_file_spec; - if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - { - tmpdir_file_spec.AppendPathComponent("debugserver-named-pipe.XXXXXX"); - strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path)); - } - else - { - strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path)); - } - - if (::mktemp (named_pipe_path)) - { - error = port_named_pipe.CreateNew(named_pipe_path, false); - if (error.Fail()) - return error; - debugserver_args.AppendArgument("--named-pipe"); - debugserver_args.AppendArgument(named_pipe_path); - } + error = port_named_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); + if (error.Fail()) + return error; + debugserver_args.AppendArgument("--named-pipe"); + debugserver_args.AppendArgument(named_pipe_path.c_str()); } else { @@ -874,7 +863,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { - if (named_pipe_path[0]) + if (named_pipe_path.size() > 0) { error = port_named_pipe.OpenAsReader(named_pipe_path, false); if (error.Success()) @@ -887,14 +876,14 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, if (error.Success()) { assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); - out_port = Args::StringToUInt32(port_cstr, 0); + out_port = StringConvert::ToUInt32(port_cstr, 0); if (log) log->Printf("GDBRemoteCommunication::%s() debugserver listens %u port", __FUNCTION__, out_port); } else { if (log) - log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } port_named_pipe.Close(); @@ -902,13 +891,13 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, else { if (log) - log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } const auto err = port_named_pipe.Delete(named_pipe_path); if (err.Fail()) { if (log) - log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path, err.AsCString()); + log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path.c_str(), err.AsCString()); } } else if (listen) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index ac203a6..ee2f327 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -27,6 +27,16 @@ #include "Utility/StringExtractorGDBRemote.h" +typedef enum +{ + eStoppointInvalid = -1, + eBreakpointSoftware = 0, + eBreakpointHardware, + eWatchpointWrite, + eWatchpointRead, + eWatchpointReadWrite +} GDBStoppointType; + class ProcessGDBRemote; class GDBRemoteCommunication : public lldb_private::Communication @@ -282,9 +292,8 @@ protected: ListenThread (lldb::thread_arg_t arg); private: - lldb_private::HostThread m_listen_thread; + lldb_private::HostThread m_listen_thread; std::string m_listen_url; - //------------------------------------------------------------------ // For GDBRemoteCommunication only diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 52750de..0f99688 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -28,6 +28,7 @@ #include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Target.h" @@ -1210,13 +1211,13 @@ GDBRemoteCommunicationClient::SendInterrupt } lldb::pid_t -GDBRemoteCommunicationClient::GetCurrentProcessID () +GDBRemoteCommunicationClient::GetCurrentProcessID (bool allow_lazy) { - if (m_curr_pid_is_valid == eLazyBoolYes) + if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes) return m_curr_pid; // First try to retrieve the pid via the qProcessInfo request. - GetCurrentProcessInfo (); + GetCurrentProcessInfo (allow_lazy); if (m_curr_pid_is_valid == eLazyBoolYes) { // We really got it. @@ -1559,7 +1560,7 @@ GDBRemoteCommunicationClient::GetGDBServerVersion() size_t dot_pos = value.find('.'); if (dot_pos != std::string::npos) value[dot_pos] = '\0'; - const uint32_t version = Args::StringToUInt32(value.c_str(), UINT32_MAX, 0); + const uint32_t version = StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0); if (version != UINT32_MAX) { success = true; @@ -1625,14 +1626,14 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) if (name.compare("cputype") == 0) { // exception type in big endian hex - cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0); + cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0); if (cpu != LLDB_INVALID_CPUTYPE) ++num_keys_decoded; } else if (name.compare("cpusubtype") == 0) { // exception count in big endian hex - sub = Args::StringToUInt32 (value.c_str(), 0, 0); + sub = StringConvert::ToUInt32 (value.c_str(), 0, 0); if (sub != 0) ++num_keys_decoded; } @@ -1700,7 +1701,7 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) } else if (name.compare("ptrsize") == 0) { - pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0); + pointer_byte_size = StringConvert::ToUInt32 (value.c_str(), 0, 0); if (pointer_byte_size != 0) ++num_keys_decoded; } @@ -1725,7 +1726,7 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) } else if (name.compare("default_packet_timeout") == 0) { - m_default_packet_timeout = Args::StringToUInt32(value.c_str(), 0); + m_default_packet_timeout = StringConvert::ToUInt32(value.c_str(), 0); if (m_default_packet_timeout > 0) { SetPacketTimeout(m_default_packet_timeout); @@ -1865,6 +1866,21 @@ GDBRemoteCommunicationClient::SendAttach return -1; } +int +GDBRemoteCommunicationClient::SendStdinNotification (const char* data, size_t data_len) +{ + StreamString packet; + packet.PutCString("I"); + packet.PutBytesAsRawHex8(data, data_len); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) + { + return 0; + } + return response.GetError(); + +} + const lldb_private::ArchSpec & GDBRemoteCommunicationClient::GetHostArchitecture () { @@ -2006,13 +2022,13 @@ GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, { if (name.compare ("start") == 0) { - addr_value = Args::StringToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16, &success); + addr_value = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16, &success); if (success) region_info.GetRange().SetRangeBase(addr_value); } else if (name.compare ("size") == 0) { - addr_value = Args::StringToUInt64(value.c_str(), 0, 16, &success); + addr_value = StringConvert::ToUInt64(value.c_str(), 0, 16, &success); if (success) region_info.GetRange().SetByteSize (addr_value); } @@ -2107,7 +2123,7 @@ GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num) { if (name.compare ("num") == 0) { - num = Args::StringToUInt32(value.c_str(), 0, 0); + num = StringConvert::ToUInt32(value.c_str(), 0, 0); m_num_supported_hardware_watchpoints = num; } } @@ -2309,27 +2325,27 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot { if (name.compare("pid") == 0) { - process_info.SetProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); + process_info.SetProcessID (StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); } else if (name.compare("ppid") == 0) { - process_info.SetParentProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); + process_info.SetParentProcessID (StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); } else if (name.compare("uid") == 0) { - process_info.SetUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetUserID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("euid") == 0) { - process_info.SetEffectiveUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetEffectiveUserID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("gid") == 0) { - process_info.SetGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetGroupID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("egid") == 0) { - process_info.SetEffectiveGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetEffectiveGroupID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("triple") == 0) { @@ -2351,11 +2367,11 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot } else if (name.compare("cputype") == 0) { - cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); + cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); } else if (name.compare("cpusubtype") == 0) { - sub = Args::StringToUInt32 (value.c_str(), 0, 16); + sub = StringConvert::ToUInt32 (value.c_str(), 0, 16); } else if (name.compare("vendor") == 0) { @@ -2408,14 +2424,17 @@ GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceIn } bool -GDBRemoteCommunicationClient::GetCurrentProcessInfo () +GDBRemoteCommunicationClient::GetCurrentProcessInfo (bool allow_lazy) { Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - if (m_qProcessInfo_is_valid == eLazyBoolYes) - return true; - if (m_qProcessInfo_is_valid == eLazyBoolNo) - return false; + if (allow_lazy) + { + if (m_qProcessInfo_is_valid == eLazyBoolYes) + return true; + if (m_qProcessInfo_is_valid == eLazyBoolNo) + return false; + } GetHostInfo (); @@ -2441,13 +2460,13 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () { if (name.compare("cputype") == 0) { - cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); + cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); if (cpu != LLDB_INVALID_CPUTYPE) ++num_keys_decoded; } else if (name.compare("cpusubtype") == 0) { - sub = Args::StringToUInt32 (value.c_str(), 0, 16); + sub = StringConvert::ToUInt32 (value.c_str(), 0, 16); if (sub != 0) ++num_keys_decoded; } @@ -2483,13 +2502,13 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () } else if (name.compare("ptrsize") == 0) { - pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 16); + pointer_byte_size = StringConvert::ToUInt32 (value.c_str(), 0, 16); if (pointer_byte_size != 0) ++num_keys_decoded; } else if (name.compare("pid") == 0) { - pid = Args::StringToUInt64(value.c_str(), 0, 16); + pid = StringConvert::ToUInt64(value.c_str(), 0, 16); if (pid != LLDB_INVALID_PROCESS_ID) ++num_keys_decoded; } @@ -2849,7 +2868,11 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const const char *packet = stream.GetData(); int packet_len = stream.GetSize(); - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) + // give the process a few seconds to startup + const uint32_t old_packet_timeout = SetPacketTimeout (10); + auto result = SendPacketAndWaitForResponse(packet, packet_len, response, false); + SetPacketTimeout (old_packet_timeout); + if (result == PacketResult::Success) { std::string name; std::string value; @@ -2857,9 +2880,9 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const while (response.GetNameColonValue(name, value)) { if (name.compare("port") == 0) - port = Args::StringToUInt32(value.c_str(), 0, 0); + port = StringConvert::ToUInt32(value.c_str(), 0, 0); else if (name.compare("pid") == 0) - pid = Args::StringToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0); + pid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0); } return port; } @@ -3013,6 +3036,7 @@ GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, case eWatchpointWrite: m_supports_z2 = false; break; case eWatchpointRead: m_supports_z3 = false; break; case eWatchpointReadWrite: m_supports_z4 = false; break; + case eStoppointInvalid: return UINT8_MAX; } } } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index fddcd6c..d90614b 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -21,15 +21,6 @@ #include "GDBRemoteCommunication.h" -typedef enum -{ - eBreakpointSoftware = 0, - eBreakpointHardware, - eWatchpointWrite, - eWatchpointRead, - eWatchpointReadWrite -} GDBStoppointType; - class GDBRemoteCommunicationClient : public GDBRemoteCommunication { public: @@ -109,7 +100,7 @@ public: bool &timed_out); lldb::pid_t - GetCurrentProcessID (); + GetCurrentProcessID (bool allow_lazy = true); bool GetLaunchSuccess (std::string &error_str); @@ -184,6 +175,23 @@ public: //------------------------------------------------------------------ + /// Sends a GDB remote protocol 'I' packet that delivers stdin + /// data to the remote process. + /// + /// @param[in] data + /// A pointer to stdin data. + /// + /// @param[in] data_len + /// The number of bytes available at \a data. + /// + /// @return + /// Zero if the attach was successful, or an error indicating + /// an error code. + //------------------------------------------------------------------ + int + SendStdinNotification(const char* data, size_t data_len); + + //------------------------------------------------------------------ /// Sets the path to use for stdin/out/err for a process /// that will be launched with the 'A' packet. /// @@ -375,8 +383,8 @@ public: case eWatchpointWrite: return m_supports_z2; case eWatchpointRead: return m_supports_z3; case eWatchpointReadWrite: return m_supports_z4; + case eStoppointInvalid: return false; } - return false; } uint8_t SendGDBStoppointTypePacket (GDBStoppointType type, // Type of breakpoint or watchpoint @@ -534,7 +542,7 @@ protected: StringExtractorGDBRemote &response); bool - GetCurrentProcessInfo (); + GetCurrentProcessInfo (bool allow_lazy_pid = true); bool GetGDBServerVersion(); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index a714950..dd920c0 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -34,16 +34,18 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" -#include "lldb/Target/NativeRegisterContext.h" -#include "Host/common/NativeProcessProtocol.h" -#include "Host/common/NativeThreadProtocol.h" +#include "lldb/Host/common/NativeRegisterContext.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeThreadProtocol.h" // Project includes #include "Utility/StringExtractorGDBRemote.h" +#include "Utility/UriParser.h" #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" @@ -276,6 +278,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, packet_result = Handle_qPlatform_shell (packet); break; + case StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo: + packet_result = Handle_qWatchpointSupportInfo (packet); + break; + case StringExtractorGDBRemote::eServerPacketType_C: packet_result = Handle_C (packet); break; @@ -364,6 +370,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, packet_result = Handle_H (packet); break; + case StringExtractorGDBRemote::eServerPacketType_I: + packet_result = Handle_I (packet); + break; + case StringExtractorGDBRemote::eServerPacketType_m: packet_result = Handle_m (packet); break; @@ -601,14 +611,12 @@ GDBRemoteCommunicationServer::LaunchPlatformProcess () // add to list of spawned processes. On an lldb-gdbserver, we // would expect there to be only one. - lldb::pid_t pid; - if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID ) + const auto pid = m_process_launch_info.GetProcessID(); + if (pid != LLDB_INVALID_PROCESS_ID) { // add to spawned pids - { - Mutex::Locker locker (m_spawned_pids_mutex); - m_spawned_pids.insert(pid); - } + Mutex::Locker locker (m_spawned_pids_mutex); + m_spawned_pids.insert(pid); } return error; @@ -835,12 +843,12 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) // Grab the reason this thread stopped. struct ThreadStopInfo tid_stop_info; - if (!thread_sp->GetStopReason (tid_stop_info)) + std::string description; + if (!thread_sp->GetStopReason (tid_stop_info, description)) return SendErrorResponse (52); - const bool did_exec = tid_stop_info.reason == eStopReasonExec; // FIXME implement register handling for exec'd inferiors. - // if (did_exec) + // if (tid_stop_info.reason == eStopReasonExec) // { // const bool force = true; // InitializeRegisters(force); @@ -861,25 +869,6 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) tid_stop_info.details.exception.type); } - switch (tid_stop_info.reason) - { - case eStopReasonSignal: - case eStopReasonException: - signum = thread_sp->TranslateStopInfoToGdbSignal (tid_stop_info); - break; - default: - signum = 0; - if (log) - { - log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " tid %" PRIu64 " has stop reason %d, using signo = 0 in stop reply response", - __FUNCTION__, - m_debugged_process_sp->GetID (), - tid, - tid_stop_info.reason); - } - break; - } - // Print the signal number. response.PutHex8 (signum & 0xff); @@ -906,14 +895,6 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) response.PutChar (';'); } - // FIXME look for analog - // thread_identifier_info_data_t thread_ident_info; - // if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info)) - // { - // if (thread_ident_info.dispatch_qaddr != 0) - // ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';'; - // } - // If a 'QListThreadsInStopReply' was sent to enable this feature, we // will send all thread IDs back in the "threads" key whose value is // a list of hex thread IDs separated by commas: @@ -978,9 +959,45 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) } } - if (did_exec) + const char* reason_str = nullptr; + switch (tid_stop_info.reason) + { + case eStopReasonTrace: + reason_str = "trace"; + break; + case eStopReasonBreakpoint: + reason_str = "breakpoint"; + break; + case eStopReasonWatchpoint: + reason_str = "watchpoint"; + break; + case eStopReasonSignal: + reason_str = "signal"; + break; + case eStopReasonException: + reason_str = "exception"; + break; + case eStopReasonExec: + reason_str = "exec"; + break; + case eStopReasonInstrumentation: + case eStopReasonInvalid: + case eStopReasonPlanComplete: + case eStopReasonThreadExiting: + case eStopReasonNone: + break; + } + if (reason_str != nullptr) + { + response.Printf ("reason:%s;", reason_str); + } + + if (!description.empty()) { - response.PutCString ("reason:exec;"); + // Description may contains special chars, send as hex bytes. + response.PutCString ("description:"); + response.PutCStringAsRawHex8 (description.c_str ()); + response.PutChar (';'); } else if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) { @@ -1422,23 +1439,34 @@ CreateProcessInfoResponse_DebugServerStyle (const ProcessInstanceInfo &proc_info GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::Handle_qProcessInfo (StringExtractorGDBRemote &packet) { - // Only the gdb server handles this. - if (!IsGdbServer ()) - return SendUnimplementedResponse (packet.GetStringRef ().c_str ()); - - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse (68); - - ProcessInstanceInfo proc_info; - if (Host::GetProcessInfo (m_debugged_process_sp->GetID (), proc_info)) + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + + if (IsGdbServer ()) { - StreamString response; - CreateProcessInfoResponse_DebugServerStyle(proc_info, response); - return SendPacketNoLock (response.GetData (), response.GetSize ()); + // Fail if we don't have a current process. + if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse (68); + + pid = m_debugged_process_sp->GetID (); } - - return SendErrorResponse (1); + else if (m_is_platform) + { + pid = m_process_launch_info.GetProcessID (); + m_process_launch_info.Clear (); + } + else + return SendUnimplementedResponse (packet.GetStringRef ().c_str ()); + + if (pid == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse (1); + + ProcessInstanceInfo proc_info; + if (!Host::GetProcessInfo (pid, proc_info)) + return SendErrorResponse (1); + + StreamString response; + CreateProcessInfoResponse_DebugServerStyle(proc_info, response); + return SendPacketNoLock (response.GetData (), response.GetSize ()); } GDBRemoteCommunication::PacketResult @@ -1512,27 +1540,27 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa } else if (key.compare("pid") == 0) { - match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); + match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); } else if (key.compare("parent_pid") == 0) { - match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); + match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); } else if (key.compare("uid") == 0) { - match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("gid") == 0) { - match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("euid") == 0) { - match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("egid") == 0) { - match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("all_users") == 0) { @@ -1627,7 +1655,7 @@ GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packe bool success = packet.GetNameColonValue(key, value); if (success && key.compare("response_size") == 0) { - uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success); + uint32_t response_size = StringConvert::ToUInt32(value.c_str(), 0, 0, &success); if (success) { if (response_size == 0) @@ -1901,7 +1929,7 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote if (name.compare ("host") == 0) hostname.swap(value); else if (name.compare ("port") == 0) - port = Args::StringToUInt32(value.c_str(), 0, 0); + port = StringConvert::ToUInt32(value.c_str(), 0, 0); } if (port == UINT16_MAX) port = GetNextAvailablePort(); @@ -1909,6 +1937,9 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote // Spawn a new thread to accept the port that gets bound after // binding to port 0 (zero). + // ignore the hostname send from the remote end, just use the ip address + // that we're currently communicating with as the hostname + // Spawn a debugserver and try to get the port it listens to. ProcessLaunchInfo debugserver_launch_info; if (hostname.empty()) @@ -1916,9 +1947,19 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote if (log) log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port); + // Do not run in a new session so that it can not linger after the + // platform closes. + debugserver_launch_info.SetLaunchInSeparateProcessGroup(false); debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); - Error error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(), + std::string platform_scheme; + std::string platform_ip; + int platform_port; + std::string platform_path; + bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path); + assert(ok); + Error error = StartDebugserverProcess ( + platform_ip.c_str(), port, debugserver_launch_info, port); @@ -2502,10 +2543,6 @@ GDBRemoteCommunicationServer::Handle_vCont (StringExtractorGDBRemote &packet) thread_actions.Append (thread_action); } - // If a default action for all other threads wasn't mentioned - // then we should stop the threads. - thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); - Error error = m_debugged_process_sp->Resume (thread_actions); if (error.Fail ()) { @@ -2983,7 +3020,7 @@ GDBRemoteCommunicationServer::Handle_qRegisterInfo (StringExtractorGDBRemote &pa return SendErrorResponse (69); // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetRegisterCount ()) + if (reg_index >= reg_context_sp->GetUserRegisterCount ()) return SendErrorResponse (69); const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index); @@ -3184,10 +3221,10 @@ GDBRemoteCommunicationServer::Handle_p (StringExtractorGDBRemote &packet) } // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetRegisterCount ()) + if (reg_index >= reg_context_sp->GetUserRegisterCount ()) { if (log) - log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetRegisterCount ()); + log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ()); return SendErrorResponse (0x15); } @@ -3264,7 +3301,8 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet) } // Parse out the value. - const uint64_t raw_value = packet.GetHexMaxU64 (process_arch.GetByteOrder () == lldb::eByteOrderLittle, std::numeric_limits<uint64_t>::max ()); + uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register + size_t reg_size = packet.GetHexBytesAvail (reg_bytes, sizeof(reg_bytes)); // Get the thread to use. NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet); @@ -3284,7 +3322,7 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet) return SendErrorResponse (0x15); } - const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index); + const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex (reg_index); if (!reg_info) { if (log) @@ -3293,20 +3331,23 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet) } // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetRegisterCount ()) + if (reg_index >= reg_context_sp->GetUserRegisterCount ()) { if (log) - log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetRegisterCount ()); + log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ()); return SendErrorResponse (0x47); } + if (reg_size != reg_info->byte_size) + { + return SendIllFormedResponse (packet, "P packet register size is incorrect"); + } // Build the reginfos response. StreamGDBRemote response; - // FIXME Could be suffixed with a thread: parameter. - // That thread then needs to be fed back into the reg context retrieval above. - Error error = reg_context_sp->WriteRegisterFromUnsigned (reg_info, raw_value); + RegisterValue reg_value (reg_bytes, reg_size, process_arch.GetByteOrder ()); + Error error = reg_context_sp->WriteRegister (reg_info, reg_value); if (error.Fail ()) { if (log) @@ -3394,6 +3435,46 @@ GDBRemoteCommunicationServer::Handle_H (StringExtractorGDBRemote &packet) } GDBRemoteCommunicationServer::PacketResult +GDBRemoteCommunicationServer::Handle_I (StringExtractorGDBRemote &packet) +{ + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // Ensure we're llgs. + if (!IsGdbServer()) + return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_I() unimplemented"); + + // Fail if we don't have a current process. + if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); + return SendErrorResponse (0x15); + } + + packet.SetFilePos (::strlen("I")); + char tmp[4096]; + for (;;) + { + size_t read = packet.GetHexBytesAvail(tmp, sizeof(tmp)); + if (read == 0) + { + break; + } + // write directly to stdin *this might block if stdin buffer is full* + // TODO: enqueue this block in circular buffer and send window size to remote host + ConnectionStatus status; + Error error; + m_stdio_communication.Write(tmp, read, status, &error); + if (error.Fail()) + { + return SendErrorResponse (0x15); + } + } + + return SendOKResponse(); +} + +GDBRemoteCommunicationServer::PacketResult GDBRemoteCommunicationServer::Handle_interrupt (StringExtractorGDBRemote &packet) { Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); @@ -3704,8 +3785,6 @@ GDBRemoteCommunicationServer::Handle_qMemoryRegionInfo (StringExtractorGDBRemote GDBRemoteCommunicationServer::PacketResult GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet) { - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - // We don't support if we're not llgs. if (!IsGdbServer()) return SendUnimplementedResponse (""); @@ -3713,12 +3792,13 @@ GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet) // Ensure we have a process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) { + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); return SendErrorResponse (0x15); } - // Parse out software or hardware breakpoint requested. + // Parse out software or hardware breakpoint or watchpoint requested. packet.SetFilePos (strlen("Z")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short Z packet, missing software/hardware specifier"); @@ -3726,61 +3806,82 @@ GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet) bool want_breakpoint = true; bool want_hardware = false; - const char breakpoint_type_char = packet.GetChar (); - switch (breakpoint_type_char) - { - case '0': want_hardware = false; want_breakpoint = true; break; - case '1': want_hardware = true; want_breakpoint = true; break; - case '2': want_breakpoint = false; break; - case '3': want_breakpoint = false; break; - default: + const GDBStoppointType stoppoint_type = + GDBStoppointType(packet.GetS32 (eStoppointInvalid)); + switch (stoppoint_type) + { + case eBreakpointSoftware: + want_hardware = false; want_breakpoint = true; break; + case eBreakpointHardware: + want_hardware = true; want_breakpoint = true; break; + case eWatchpointWrite: + want_hardware = true; want_breakpoint = false; break; + case eWatchpointRead: + want_hardware = true; want_breakpoint = false; break; + case eWatchpointReadWrite: + want_hardware = true; want_breakpoint = false; break; + case eStoppointInvalid: return SendIllFormedResponse(packet, "Z packet had invalid software/hardware specifier"); } if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') - return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after breakpoint type"); + return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after stoppoint type"); - // FIXME implement watchpoint support. - if (!want_breakpoint) - return SendUnimplementedResponse ("watchpoint support not yet implemented"); - - // Parse out the breakpoint address. + // Parse out the stoppoint address. if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short Z packet, missing address"); - const lldb::addr_t breakpoint_addr = packet.GetHexMaxU64(false, 0); + const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after address"); - // Parse out the breakpoint kind (i.e. size hint for opcode size). - const uint32_t kind = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); - if (kind == std::numeric_limits<uint32_t>::max ()) - return SendIllFormedResponse(packet, "Malformed Z packet, failed to parse kind argument"); + // Parse out the stoppoint size (i.e. size hint for opcode size). + const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); + if (size == std::numeric_limits<uint32_t>::max ()) + return SendIllFormedResponse(packet, "Malformed Z packet, failed to parse size argument"); if (want_breakpoint) { // Try to set the breakpoint. - const Error error = m_debugged_process_sp->SetBreakpoint (breakpoint_addr, kind, want_hardware); + const Error error = m_debugged_process_sp->SetBreakpoint (addr, size, want_hardware); if (error.Success ()) return SendOKResponse (); - else - { - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to set breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ()); - return SendErrorResponse (0x09); - } + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to set breakpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); } + else + { + uint32_t watch_flags = + stoppoint_type == eWatchpointWrite + ? watch_flags = 0x1 // Write + : watch_flags = 0x3; // ReadWrite - // FIXME fix up after watchpoints are handled. - return SendUnimplementedResponse (""); + // Try to set the watchpoint. + const Error error = m_debugged_process_sp->SetWatchpoint ( + addr, size, watch_flags, want_hardware); + if (error.Success ()) + return SendOKResponse (); + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to set watchpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); + } } GDBRemoteCommunicationServer::PacketResult GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet) { - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - // We don't support if we're not llgs. if (!IsGdbServer()) return SendUnimplementedResponse (""); @@ -3788,66 +3889,81 @@ GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet) // Ensure we have a process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) { + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); return SendErrorResponse (0x15); } - // Parse out software or hardware breakpoint requested. + // Parse out software or hardware breakpoint or watchpoint requested. packet.SetFilePos (strlen("z")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short z packet, missing software/hardware specifier"); bool want_breakpoint = true; - const char breakpoint_type_char = packet.GetChar (); - switch (breakpoint_type_char) + const GDBStoppointType stoppoint_type = + GDBStoppointType(packet.GetS32 (eStoppointInvalid)); + switch (stoppoint_type) { - case '0': want_breakpoint = true; break; - case '1': want_breakpoint = true; break; - case '2': want_breakpoint = false; break; - case '3': want_breakpoint = false; break; + case eBreakpointHardware: want_breakpoint = true; break; + case eBreakpointSoftware: want_breakpoint = true; break; + case eWatchpointWrite: want_breakpoint = false; break; + case eWatchpointRead: want_breakpoint = false; break; + case eWatchpointReadWrite: want_breakpoint = false; break; default: return SendIllFormedResponse(packet, "z packet had invalid software/hardware specifier"); } if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') - return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after breakpoint type"); - - // FIXME implement watchpoint support. - if (!want_breakpoint) - return SendUnimplementedResponse ("watchpoint support not yet implemented"); + return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after stoppoint type"); - // Parse out the breakpoint address. + // Parse out the stoppoint address. if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short z packet, missing address"); - const lldb::addr_t breakpoint_addr = packet.GetHexMaxU64(false, 0); + const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after address"); - // Parse out the breakpoint kind (i.e. size hint for opcode size). - const uint32_t kind = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); - if (kind == std::numeric_limits<uint32_t>::max ()) - return SendIllFormedResponse(packet, "Malformed z packet, failed to parse kind argument"); + /* + // Parse out the stoppoint size (i.e. size hint for opcode size). + const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ()); + if (size == std::numeric_limits<uint32_t>::max ()) + return SendIllFormedResponse(packet, "Malformed z packet, failed to parse size argument"); + */ if (want_breakpoint) { // Try to clear the breakpoint. - const Error error = m_debugged_process_sp->RemoveBreakpoint (breakpoint_addr); + const Error error = m_debugged_process_sp->RemoveBreakpoint (addr); if (error.Success ()) return SendOKResponse (); - else - { - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to remove breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ()); - return SendErrorResponse (0x09); - } + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to remove breakpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); + } + else + { + // Try to clear the watchpoint. + const Error error = m_debugged_process_sp->RemoveWatchpoint (addr); + if (error.Success ()) + return SendOKResponse (); + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to remove watchpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); } - - // FIXME fix up after watchpoints are handled. - return SendUnimplementedResponse (""); } GDBRemoteCommunicationServer::PacketResult @@ -4283,6 +4399,30 @@ GDBRemoteCommunicationServer::Handle_qThreadStopInfo (StringExtractorGDBRemote & return SendStopReplyPacketForThread (tid); } +GDBRemoteCommunicationServer::PacketResult +GDBRemoteCommunicationServer::Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet) +{ + // Only the gdb server handles this. + if (!IsGdbServer ()) + return SendUnimplementedResponse (packet.GetStringRef ().c_str ()); + + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse (68); + + packet.SetFilePos(strlen("qWatchpointSupportInfo")); + if (packet.GetBytesLeft() == 0) + return SendOKResponse(); + if (packet.GetChar() != ':') + return SendErrorResponse(67); + + uint32_t num = m_debugged_process_sp->GetMaxWatchpoints(); + StreamGDBRemote response; + response.Printf ("num:%d;", num); + return SendPacketNoLock(response.GetData(), response.GetSize()); +} + void GDBRemoteCommunicationServer::FlushInferiorOutput () { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 07ce98e..dcf0784 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -23,7 +23,7 @@ #include "lldb/Target/Process.h" #include "GDBRemoteCommunication.h" -#include "../../../Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeProcessProtocol.h" class ProcessGDBRemote; class StringExtractorGDBRemote; @@ -415,6 +415,9 @@ protected: Handle_H (StringExtractorGDBRemote &packet); PacketResult + Handle_I (StringExtractorGDBRemote &packet); + + PacketResult Handle_interrupt (StringExtractorGDBRemote &packet); PacketResult @@ -465,6 +468,9 @@ protected: PacketResult Handle_qThreadStopInfo (StringExtractorGDBRemote &packet); + PacketResult + Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet); + void SetCurrentThreadID (lldb::tid_t tid); diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index fe99706..cb0b4bb 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -42,6 +42,7 @@ #include "lldb/Core/Timer.h" #include "lldb/Core/Value.h" #include "lldb/Host/HostThread.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/Symbols.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" @@ -431,11 +432,11 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) } else if (name.compare("bitsize") == 0) { - reg_info.byte_size = Args::StringToUInt32(value.c_str(), 0, 0) / CHAR_BIT; + reg_info.byte_size = StringConvert::ToUInt32(value.c_str(), 0, 0) / CHAR_BIT; } else if (name.compare("offset") == 0) { - uint32_t offset = Args::StringToUInt32(value.c_str(), UINT32_MAX, 0); + uint32_t offset = StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0); if (reg_offset != offset) { reg_offset = offset; @@ -483,11 +484,11 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) } else if (name.compare("gcc") == 0) { - reg_info.kinds[eRegisterKindGCC] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); + reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); } else if (name.compare("dwarf") == 0) { - reg_info.kinds[eRegisterKindDWARF] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); + reg_info.kinds[eRegisterKindDWARF] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); } else if (name.compare("generic") == 0) { @@ -502,7 +503,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) value_pair = value_pair.second.split(','); if (!value_pair.first.empty()) { - uint32_t reg = Args::StringToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); + uint32_t reg = StringConvert::ToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); if (reg != LLDB_INVALID_REGNUM) value_regs.push_back (reg); } @@ -517,7 +518,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) value_pair = value_pair.second.split(','); if (!value_pair.first.empty()) { - uint32_t reg = Args::StringToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); + uint32_t reg = StringConvert::ToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); if (reg != LLDB_INVALID_REGNUM) invalidate_regs.push_back (reg); } @@ -941,6 +942,7 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) SetPrivateState (SetThreadStopInfo (m_last_stop_packet)); + m_stdio_disable = disable_stdio; if (!disable_stdio) { if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd) @@ -972,9 +974,12 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url) { Error error; // Only connect if we have a valid connect URL + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (connect_url && connect_url[0]) { + if (log) + log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, connect_url); std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor()); if (conn_ap.get()) { @@ -1656,17 +1661,17 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) if (name.compare("metype") == 0) { // exception type in big endian hex - exc_type = Args::StringToUInt32 (value.c_str(), 0, 16); + exc_type = StringConvert::ToUInt32 (value.c_str(), 0, 16); } else if (name.compare("medata") == 0) { // exception data in big endian hex - exc_data.push_back(Args::StringToUInt64 (value.c_str(), 0, 16)); + exc_data.push_back(StringConvert::ToUInt64 (value.c_str(), 0, 16)); } else if (name.compare("thread") == 0) { // thread in big endian hex - lldb::tid_t tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); + lldb::tid_t tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); // m_thread_list_real does have its own mutex, but we need to // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...) // and the m_thread_list_real.AddThread(...) so it doesn't change on us @@ -1702,12 +1707,12 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) { value[comma_pos] = '\0'; // thread in big endian hex - tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); + tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); if (tid != LLDB_INVALID_THREAD_ID) m_thread_ids.push_back (tid); value.erase(0, comma_pos + 1); } - tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); + tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); if (tid != LLDB_INVALID_THREAD_ID) m_thread_ids.push_back (tid); } @@ -1726,7 +1731,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) } else if (name.compare("qaddr") == 0) { - thread_dispatch_qaddr = Args::StringToUInt64 (value.c_str(), 0, 16); + thread_dispatch_qaddr = StringConvert::ToUInt64 (value.c_str(), 0, 16); } else if (name.compare("reason") == 0) { @@ -1738,7 +1743,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) // Swap "value" over into "name_extractor" desc_extractor.GetStringRef().swap(value); // Now convert the HEX bytes into a string value - desc_extractor.GetHexByteString (thread_name); + desc_extractor.GetHexByteString (value); + description.swap(value); } else if (name.size() == 2 && ::isxdigit(name[0]) && ::isxdigit(name[1])) { @@ -1747,7 +1753,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) // so it won't have to go and read it. if (gdb_thread) { - uint32_t reg = Args::StringToUInt32 (name.c_str(), UINT32_MAX, 16); + uint32_t reg = StringConvert::ToUInt32 (name.c_str(), UINT32_MAX, 16); if (reg != UINT32_MAX) { @@ -1839,8 +1845,24 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) } else if (reason.compare("watchpoint") == 0) { - break_id_t watch_id = LLDB_INVALID_WATCH_ID; - // TODO: locate the watchpoint somehow... + StringExtractor desc_extractor(description.c_str()); + addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); + uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); + watch_id_t watch_id = LLDB_INVALID_WATCH_ID; + if (wp_addr != LLDB_INVALID_ADDRESS) + { + WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); + if (wp_sp) + { + wp_sp->SetHardwareIndex(wp_index); + watch_id = wp_sp->GetID(); + } + } + if (watch_id == LLDB_INVALID_WATCH_ID) + { + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS)); + if (log) log->Printf ("failed to find watchpoint"); + } thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id)); handled = true; } @@ -2456,6 +2478,10 @@ ProcessGDBRemote::PutSTDIN (const char *src, size_t src_len, Error &error) ConnectionStatus status; m_stdio_communication.Write(src, src_len, status, NULL); } + else if (!m_stdio_disable) + { + m_gdb_comm.SendStdinNotification(src, src_len); + } return 0; } @@ -2760,6 +2786,10 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info static FileSpec g_debugserver_file_spec; ProcessLaunchInfo debugserver_launch_info; + // Make debugserver run in its own session so signals generated by + // special terminal key sequences (^C) don't affect debugserver. + debugserver_launch_info.SetLaunchInSeparateProcessGroup(true); + debugserver_launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false); debugserver_launch_info.SetUserID(process_info.GetUserID()); |