aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/Process
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Process')
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp183
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h15
-rw-r--r--source/Plugins/Process/POSIX/CrashReason.cpp315
-rw-r--r--source/Plugins/Process/POSIX/CrashReason.h62
-rw-r--r--source/Plugins/Process/POSIX/POSIXStopInfo.cpp15
-rw-r--r--source/Plugins/Process/POSIX/POSIXStopInfo.h22
-rw-r--r--source/Plugins/Process/POSIX/ProcessMessage.cpp190
-rw-r--r--source/Plugins/Process/POSIX/ProcessMessage.h51
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIX.cpp11
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp53
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h9
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.cpp6
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp39
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp7
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp5
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_i386.h3
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp24
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp51
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h45
-rw-r--r--source/Plugins/Process/Utility/RegisterContext_powerpc.h79
-rw-r--r--source/Plugins/Process/Utility/RegisterInfoInterface.h11
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_powerpc.h42
-rw-r--r--source/Plugins/Process/Utility/lldb-x86-register-enums.h6
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp6
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp29
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h11
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.cpp5
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.h2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp49
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h13
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp86
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h32
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp420
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h8
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp62
36 files changed, 1267 insertions, 704 deletions
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 84e35ba22644..b33f83303971 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 935fd85ed37a..4ae963c89a2f 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 000000000000..4dd91a6f1de8
--- /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 000000000000..f6d9ba553e4a
--- /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 6e2c140682ba..3b8cea737bcb 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 cbf309e53506..a1ee2ea68524 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 5c53627f9e0b..02049a2af953 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 40462d0f0e13..f932e9fff278 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 0e5ab5a8d8b1..882fac75c9a0 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 b542db4779db..80e1c1984225 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 92a331285515..5c686df4836f 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 1088924bfeac..25a195e11a03 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 5170e6d2accb..5133d6088bd3 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 f47d687702ec..1b3a9491d1c8 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 b9b9dca07be4..b38d6cc60cac 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 f8b21fc8e87d..cb71d7993e17 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 74f016bd744d..5c93ebf88faa 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 7b6828661c1e..0cdfae9ac943 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 a9477d583517..828fb2571f79 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 3194c3968c98..c7a2451d7811 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 cf54cc0c2145..7438b88971b3 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 382475f4523a..94cb5cc791c6 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 045426648105..fe145e99588b 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 99fca3005820..63027b4451b8 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 fb39d7318a5a..ead959508d88 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 15b1b44182d7..d12df21a8664 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 e6575581b360..a3590601fa7e 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 d62bcfcff600..b16335fb8e1e 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 f1f00cf019b3..50502c101daf 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 919fa5405117..d633b3eaf34c 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 ac203a62788a..ee2f3276513d 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 52750de5a25f..0f99688fc823 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 fddcd6cd1426..d90614bce88b 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 a7149505e869..dd920c0df0ca 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 07ce98e29ac6..dcf07844527e 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 fe99706969c8..cb0b4bb51007 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());