[Lldb-commits] [lldb] r280751 - *** This commit represents a complete reformatting of the LLDB source code
Kate Stone via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 6 13:58:36 PDT 2016
Modified: lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp Tue Sep 6 15:57:50 2016
@@ -11,54 +11,46 @@
//
//===----------------------------------------------------------------------===//
-#if defined (__i386__) || defined (__x86_64__)
+#if defined(__i386__) || defined(__x86_64__)
#include <sys/cdefs.h>
-#include <sys/types.h>
#include <sys/sysctl.h>
+#include <sys/types.h>
-#include "MacOSX/x86_64/DNBArchImplX86_64.h"
#include "../HasAVX.h"
#include "DNBLog.h"
-#include "MachThread.h"
+#include "MacOSX/x86_64/DNBArchImplX86_64.h"
#include "MachProcess.h"
+#include "MachThread.h"
#include <mach/mach.h>
#include <stdlib.h>
-#if defined (LLDB_DEBUGSERVER_RELEASE) || defined (LLDB_DEBUGSERVER_DEBUG)
-enum debugState {
- debugStateUnknown,
- debugStateOff,
- debugStateOn
-};
+#if defined(LLDB_DEBUGSERVER_RELEASE) || defined(LLDB_DEBUGSERVER_DEBUG)
+enum debugState { debugStateUnknown, debugStateOff, debugStateOn };
static debugState sFPUDebugState = debugStateUnknown;
static debugState sAVXForceState = debugStateUnknown;
-static bool DebugFPURegs ()
-{
- if (sFPUDebugState == debugStateUnknown)
- {
- if (getenv("DNB_DEBUG_FPU_REGS"))
- sFPUDebugState = debugStateOn;
- else
- sFPUDebugState = debugStateOff;
- }
-
- return (sFPUDebugState == debugStateOn);
+static bool DebugFPURegs() {
+ if (sFPUDebugState == debugStateUnknown) {
+ if (getenv("DNB_DEBUG_FPU_REGS"))
+ sFPUDebugState = debugStateOn;
+ else
+ sFPUDebugState = debugStateOff;
+ }
+
+ return (sFPUDebugState == debugStateOn);
}
-static bool ForceAVXRegs ()
-{
- if (sFPUDebugState == debugStateUnknown)
- {
- if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS"))
- sAVXForceState = debugStateOn;
- else
- sAVXForceState = debugStateOff;
- }
-
- return (sAVXForceState == debugStateOn);
+static bool ForceAVXRegs() {
+ if (sFPUDebugState == debugStateUnknown) {
+ if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS"))
+ sAVXForceState = debugStateOn;
+ else
+ sAVXForceState = debugStateOff;
+ }
+
+ return (sAVXForceState == debugStateOn);
}
#define DEBUG_FPU_REGS (DebugFPURegs())
@@ -68,2222 +60,2501 @@ static bool ForceAVXRegs ()
#define FORCE_AVX_REGS (0)
#endif
+extern "C" bool CPUHasAVX() {
+ enum AVXPresence { eAVXUnknown = -1, eAVXNotPresent = 0, eAVXPresent = 1 };
-extern "C" bool
-CPUHasAVX()
-{
- enum AVXPresence
- {
- eAVXUnknown = -1,
- eAVXNotPresent = 0,
- eAVXPresent = 1
- };
-
- static AVXPresence g_has_avx = eAVXUnknown;
- if (g_has_avx == eAVXUnknown)
- {
- g_has_avx = eAVXNotPresent;
-
- // Only xnu-2020 or later has AVX support, any versions before
- // this have a busted thread_get_state RPC where it would truncate
- // the thread state buffer (<rdar://problem/10122874>). So we need to
- // verify the kernel version number manually or disable AVX support.
- int mib[2];
- char buffer[1024];
- size_t length = sizeof(buffer);
- uint64_t xnu_version = 0;
- mib[0] = CTL_KERN;
- mib[1] = KERN_VERSION;
- int err = ::sysctl(mib, 2, &buffer, &length, NULL, 0);
- if (err == 0)
- {
- const char *xnu = strstr (buffer, "xnu-");
- if (xnu)
- {
- const char *xnu_version_cstr = xnu + 4;
- xnu_version = strtoull (xnu_version_cstr, NULL, 0);
- if (xnu_version >= 2020 && xnu_version != ULLONG_MAX)
- {
- if (::HasAVX())
- {
- g_has_avx = eAVXPresent;
- }
- }
- }
- }
- DNBLogThreadedIf (LOG_THREAD, "CPUHasAVX(): g_has_avx = %i (err = %i, errno = %i, xnu_version = %llu)", g_has_avx, err, errno, xnu_version);
- }
-
- return (g_has_avx == eAVXPresent);
-}
-
-uint64_t
-DNBArchImplX86_64::GetPC(uint64_t failValue)
-{
- // Get program counter
- if (GetGPRState(false) == KERN_SUCCESS)
- return m_state.context.gpr.__rip;
- return failValue;
-}
-
-kern_return_t
-DNBArchImplX86_64::SetPC(uint64_t value)
-{
- // Get program counter
- kern_return_t err = GetGPRState(false);
- if (err == KERN_SUCCESS)
- {
- m_state.context.gpr.__rip = value;
- err = SetGPRState();
- }
- return err == KERN_SUCCESS;
-}
-
-uint64_t
-DNBArchImplX86_64::GetSP(uint64_t failValue)
-{
- // Get stack pointer
- if (GetGPRState(false) == KERN_SUCCESS)
- return m_state.context.gpr.__rsp;
- return failValue;
+ static AVXPresence g_has_avx = eAVXUnknown;
+ if (g_has_avx == eAVXUnknown) {
+ g_has_avx = eAVXNotPresent;
+
+ // Only xnu-2020 or later has AVX support, any versions before
+ // this have a busted thread_get_state RPC where it would truncate
+ // the thread state buffer (<rdar://problem/10122874>). So we need to
+ // verify the kernel version number manually or disable AVX support.
+ int mib[2];
+ char buffer[1024];
+ size_t length = sizeof(buffer);
+ uint64_t xnu_version = 0;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_VERSION;
+ int err = ::sysctl(mib, 2, &buffer, &length, NULL, 0);
+ if (err == 0) {
+ const char *xnu = strstr(buffer, "xnu-");
+ if (xnu) {
+ const char *xnu_version_cstr = xnu + 4;
+ xnu_version = strtoull(xnu_version_cstr, NULL, 0);
+ if (xnu_version >= 2020 && xnu_version != ULLONG_MAX) {
+ if (::HasAVX()) {
+ g_has_avx = eAVXPresent;
+ }
+ }
+ }
+ }
+ DNBLogThreadedIf(LOG_THREAD, "CPUHasAVX(): g_has_avx = %i (err = %i, errno "
+ "= %i, xnu_version = %llu)",
+ g_has_avx, err, errno, xnu_version);
+ }
+
+ return (g_has_avx == eAVXPresent);
+}
+
+uint64_t DNBArchImplX86_64::GetPC(uint64_t failValue) {
+ // Get program counter
+ if (GetGPRState(false) == KERN_SUCCESS)
+ return m_state.context.gpr.__rip;
+ return failValue;
+}
+
+kern_return_t DNBArchImplX86_64::SetPC(uint64_t value) {
+ // Get program counter
+ kern_return_t err = GetGPRState(false);
+ if (err == KERN_SUCCESS) {
+ m_state.context.gpr.__rip = value;
+ err = SetGPRState();
+ }
+ return err == KERN_SUCCESS;
+}
+
+uint64_t DNBArchImplX86_64::GetSP(uint64_t failValue) {
+ // Get stack pointer
+ if (GetGPRState(false) == KERN_SUCCESS)
+ return m_state.context.gpr.__rsp;
+ return failValue;
}
// Uncomment the value below to verify the values in the debugger.
//#define DEBUG_GPR_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED
-kern_return_t
-DNBArchImplX86_64::GetGPRState(bool force)
-{
- if (force || m_state.GetError(e_regSetGPR, Read))
- {
+kern_return_t DNBArchImplX86_64::GetGPRState(bool force) {
+ if (force || m_state.GetError(e_regSetGPR, Read)) {
#if DEBUG_GPR_VALUES
- m_state.context.gpr.__rax = ('a' << 8) + 'x';
- m_state.context.gpr.__rbx = ('b' << 8) + 'x';
- m_state.context.gpr.__rcx = ('c' << 8) + 'x';
- m_state.context.gpr.__rdx = ('d' << 8) + 'x';
- m_state.context.gpr.__rdi = ('d' << 8) + 'i';
- m_state.context.gpr.__rsi = ('s' << 8) + 'i';
- m_state.context.gpr.__rbp = ('b' << 8) + 'p';
- m_state.context.gpr.__rsp = ('s' << 8) + 'p';
- m_state.context.gpr.__r8 = ('r' << 8) + '8';
- m_state.context.gpr.__r9 = ('r' << 8) + '9';
- m_state.context.gpr.__r10 = ('r' << 8) + 'a';
- m_state.context.gpr.__r11 = ('r' << 8) + 'b';
- m_state.context.gpr.__r12 = ('r' << 8) + 'c';
- m_state.context.gpr.__r13 = ('r' << 8) + 'd';
- m_state.context.gpr.__r14 = ('r' << 8) + 'e';
- m_state.context.gpr.__r15 = ('r' << 8) + 'f';
- m_state.context.gpr.__rip = ('i' << 8) + 'p';
- m_state.context.gpr.__rflags = ('f' << 8) + 'l';
- m_state.context.gpr.__cs = ('c' << 8) + 's';
- m_state.context.gpr.__fs = ('f' << 8) + 's';
- m_state.context.gpr.__gs = ('g' << 8) + 's';
- m_state.SetError(e_regSetGPR, Read, 0);
+ m_state.context.gpr.__rax = ('a' << 8) + 'x';
+ m_state.context.gpr.__rbx = ('b' << 8) + 'x';
+ m_state.context.gpr.__rcx = ('c' << 8) + 'x';
+ m_state.context.gpr.__rdx = ('d' << 8) + 'x';
+ m_state.context.gpr.__rdi = ('d' << 8) + 'i';
+ m_state.context.gpr.__rsi = ('s' << 8) + 'i';
+ m_state.context.gpr.__rbp = ('b' << 8) + 'p';
+ m_state.context.gpr.__rsp = ('s' << 8) + 'p';
+ m_state.context.gpr.__r8 = ('r' << 8) + '8';
+ m_state.context.gpr.__r9 = ('r' << 8) + '9';
+ m_state.context.gpr.__r10 = ('r' << 8) + 'a';
+ m_state.context.gpr.__r11 = ('r' << 8) + 'b';
+ m_state.context.gpr.__r12 = ('r' << 8) + 'c';
+ m_state.context.gpr.__r13 = ('r' << 8) + 'd';
+ m_state.context.gpr.__r14 = ('r' << 8) + 'e';
+ m_state.context.gpr.__r15 = ('r' << 8) + 'f';
+ m_state.context.gpr.__rip = ('i' << 8) + 'p';
+ m_state.context.gpr.__rflags = ('f' << 8) + 'l';
+ m_state.context.gpr.__cs = ('c' << 8) + 's';
+ m_state.context.gpr.__fs = ('f' << 8) + 's';
+ m_state.context.gpr.__gs = ('g' << 8) + 's';
+ m_state.SetError(e_regSetGPR, Read, 0);
#else
- mach_msg_type_number_t count = e_regSetWordSizeGPR;
- m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count));
- DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x"
- "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx"
- "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx"
- "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx"
- "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx"
- "\n\trip = %16.16llx"
- "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx",
- m_thread->MachPortNumber(), x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT,
- m_state.GetError(e_regSetGPR, Read),
- m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx,
- m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi,
- m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8,
- m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11,
- m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14,
- m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags,
- m_state.context.gpr.__cs,m_state.context.gpr.__fs, m_state.context.gpr.__gs);
-
- // DNBLogThreadedIf (LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x"
- // "\n\trax = %16.16llx"
- // "\n\trbx = %16.16llx"
- // "\n\trcx = %16.16llx"
- // "\n\trdx = %16.16llx"
- // "\n\trdi = %16.16llx"
- // "\n\trsi = %16.16llx"
- // "\n\trbp = %16.16llx"
- // "\n\trsp = %16.16llx"
- // "\n\t r8 = %16.16llx"
- // "\n\t r9 = %16.16llx"
- // "\n\tr10 = %16.16llx"
- // "\n\tr11 = %16.16llx"
- // "\n\tr12 = %16.16llx"
- // "\n\tr13 = %16.16llx"
- // "\n\tr14 = %16.16llx"
- // "\n\tr15 = %16.16llx"
- // "\n\trip = %16.16llx"
- // "\n\tflg = %16.16llx"
- // "\n\t cs = %16.16llx"
- // "\n\t fs = %16.16llx"
- // "\n\t gs = %16.16llx",
- // m_thread->MachPortNumber(),
- // x86_THREAD_STATE64,
- // x86_THREAD_STATE64_COUNT,
- // m_state.GetError(e_regSetGPR, Read),
- // m_state.context.gpr.__rax,
- // m_state.context.gpr.__rbx,
- // m_state.context.gpr.__rcx,
- // m_state.context.gpr.__rdx,
- // m_state.context.gpr.__rdi,
- // m_state.context.gpr.__rsi,
- // m_state.context.gpr.__rbp,
- // m_state.context.gpr.__rsp,
- // m_state.context.gpr.__r8,
- // m_state.context.gpr.__r9,
- // m_state.context.gpr.__r10,
- // m_state.context.gpr.__r11,
- // m_state.context.gpr.__r12,
- // m_state.context.gpr.__r13,
- // m_state.context.gpr.__r14,
- // m_state.context.gpr.__r15,
- // m_state.context.gpr.__rip,
- // m_state.context.gpr.__rflags,
- // m_state.context.gpr.__cs,
- // m_state.context.gpr.__fs,
- // m_state.context.gpr.__gs);
+ mach_msg_type_number_t count = e_regSetWordSizeGPR;
+ m_state.SetError(
+ e_regSetGPR, Read,
+ ::thread_get_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE,
+ (thread_state_t)&m_state.context.gpr, &count));
+ DNBLogThreadedIf(
+ LOG_THREAD,
+ "::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x"
+ "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx"
+ "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx"
+ "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx"
+ "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx"
+ "\n\trip = %16.16llx"
+ "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx",
+ m_thread->MachPortNumber(), x86_THREAD_STATE64,
+ x86_THREAD_STATE64_COUNT, m_state.GetError(e_regSetGPR, Read),
+ m_state.context.gpr.__rax, m_state.context.gpr.__rbx,
+ m_state.context.gpr.__rcx, m_state.context.gpr.__rdx,
+ m_state.context.gpr.__rdi, m_state.context.gpr.__rsi,
+ m_state.context.gpr.__rbp, m_state.context.gpr.__rsp,
+ m_state.context.gpr.__r8, m_state.context.gpr.__r9,
+ m_state.context.gpr.__r10, m_state.context.gpr.__r11,
+ m_state.context.gpr.__r12, m_state.context.gpr.__r13,
+ m_state.context.gpr.__r14, m_state.context.gpr.__r15,
+ m_state.context.gpr.__rip, m_state.context.gpr.__rflags,
+ m_state.context.gpr.__cs, m_state.context.gpr.__fs,
+ m_state.context.gpr.__gs);
+
+// DNBLogThreadedIf (LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u)
+// => 0x%8.8x"
+// "\n\trax = %16.16llx"
+// "\n\trbx = %16.16llx"
+// "\n\trcx = %16.16llx"
+// "\n\trdx = %16.16llx"
+// "\n\trdi = %16.16llx"
+// "\n\trsi = %16.16llx"
+// "\n\trbp = %16.16llx"
+// "\n\trsp = %16.16llx"
+// "\n\t r8 = %16.16llx"
+// "\n\t r9 = %16.16llx"
+// "\n\tr10 = %16.16llx"
+// "\n\tr11 = %16.16llx"
+// "\n\tr12 = %16.16llx"
+// "\n\tr13 = %16.16llx"
+// "\n\tr14 = %16.16llx"
+// "\n\tr15 = %16.16llx"
+// "\n\trip = %16.16llx"
+// "\n\tflg = %16.16llx"
+// "\n\t cs = %16.16llx"
+// "\n\t fs = %16.16llx"
+// "\n\t gs = %16.16llx",
+// m_thread->MachPortNumber(),
+// x86_THREAD_STATE64,
+// x86_THREAD_STATE64_COUNT,
+// m_state.GetError(e_regSetGPR, Read),
+// m_state.context.gpr.__rax,
+// m_state.context.gpr.__rbx,
+// m_state.context.gpr.__rcx,
+// m_state.context.gpr.__rdx,
+// m_state.context.gpr.__rdi,
+// m_state.context.gpr.__rsi,
+// m_state.context.gpr.__rbp,
+// m_state.context.gpr.__rsp,
+// m_state.context.gpr.__r8,
+// m_state.context.gpr.__r9,
+// m_state.context.gpr.__r10,
+// m_state.context.gpr.__r11,
+// m_state.context.gpr.__r12,
+// m_state.context.gpr.__r13,
+// m_state.context.gpr.__r14,
+// m_state.context.gpr.__r15,
+// m_state.context.gpr.__rip,
+// m_state.context.gpr.__rflags,
+// m_state.context.gpr.__cs,
+// m_state.context.gpr.__fs,
+// m_state.context.gpr.__gs);
#endif
- }
- return m_state.GetError(e_regSetGPR, Read);
+ }
+ return m_state.GetError(e_regSetGPR, Read);
}
// Uncomment the value below to verify the values in the debugger.
//#define DEBUG_FPU_REGS 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED
-kern_return_t
-DNBArchImplX86_64::GetFPUState(bool force)
-{
- if (force || m_state.GetError(e_regSetFPU, Read))
- {
- if (DEBUG_FPU_REGS) {
- if (CPUHasAVX() || FORCE_AVX_REGS)
- {
- m_state.context.fpu.avx.__fpu_reserved[0] = -1;
- m_state.context.fpu.avx.__fpu_reserved[1] = -1;
- *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fcw) = 0x1234;
- *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fsw) = 0x5678;
- m_state.context.fpu.avx.__fpu_ftw = 1;
- m_state.context.fpu.avx.__fpu_rsrv1 = UINT8_MAX;
- m_state.context.fpu.avx.__fpu_fop = 2;
- m_state.context.fpu.avx.__fpu_ip = 3;
- m_state.context.fpu.avx.__fpu_cs = 4;
- m_state.context.fpu.avx.__fpu_rsrv2 = UINT8_MAX;
- m_state.context.fpu.avx.__fpu_dp = 5;
- m_state.context.fpu.avx.__fpu_ds = 6;
- m_state.context.fpu.avx.__fpu_rsrv3 = UINT16_MAX;
- m_state.context.fpu.avx.__fpu_mxcsr = 8;
- m_state.context.fpu.avx.__fpu_mxcsrmask = 9;
- int i;
- for (i=0; i<16; ++i)
- {
- if (i<10)
- {
- m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = 'a';
- m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = 'b';
- m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = 'c';
- m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = 'd';
- m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = 'e';
- m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = 'f';
- m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = 'g';
- m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = 'h';
- }
- else
- {
- m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
- }
-
- m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg[i] = '0' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg[i] = '1' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg[i] = '2' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg[i] = '3' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg[i] = '4' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg[i] = '5' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg[i] = '6' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg[i] = '7' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm8.__xmm_reg[i] = '8' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm9.__xmm_reg[i] = '9' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm10.__xmm_reg[i] = 'A' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm11.__xmm_reg[i] = 'B' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm12.__xmm_reg[i] = 'C' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm13.__xmm_reg[i] = 'D' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm14.__xmm_reg[i] = 'E' + 2 * i;
- m_state.context.fpu.avx.__fpu_xmm15.__xmm_reg[i] = 'F' + 2 * i;
-
- m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0' + i;
- m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1' + i;
- m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2' + i;
- m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3' + i;
- m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4' + i;
- m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5' + i;
- m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6' + i;
- m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7' + i;
- m_state.context.fpu.avx.__fpu_ymmh8.__xmm_reg[i] = '8' + i;
- m_state.context.fpu.avx.__fpu_ymmh9.__xmm_reg[i] = '9' + i;
- m_state.context.fpu.avx.__fpu_ymmh10.__xmm_reg[i] = 'A' + i;
- m_state.context.fpu.avx.__fpu_ymmh11.__xmm_reg[i] = 'B' + i;
- m_state.context.fpu.avx.__fpu_ymmh12.__xmm_reg[i] = 'C' + i;
- m_state.context.fpu.avx.__fpu_ymmh13.__xmm_reg[i] = 'D' + i;
- m_state.context.fpu.avx.__fpu_ymmh14.__xmm_reg[i] = 'E' + i;
- m_state.context.fpu.avx.__fpu_ymmh15.__xmm_reg[i] = 'F' + i;
- }
- for (i=0; i<sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i)
- m_state.context.fpu.avx.__fpu_rsrv4[i] = INT8_MIN;
- m_state.context.fpu.avx.__fpu_reserved1 = -1;
- for (i=0; i<sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i)
- m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN;
- m_state.SetError(e_regSetFPU, Read, 0);
- }
- else
- {
- m_state.context.fpu.no_avx.__fpu_reserved[0] = -1;
- m_state.context.fpu.no_avx.__fpu_reserved[1] = -1;
- *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234;
- *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678;
- m_state.context.fpu.no_avx.__fpu_ftw = 1;
- m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX;
- m_state.context.fpu.no_avx.__fpu_fop = 2;
- m_state.context.fpu.no_avx.__fpu_ip = 3;
- m_state.context.fpu.no_avx.__fpu_cs = 4;
- m_state.context.fpu.no_avx.__fpu_rsrv2 = 5;
- m_state.context.fpu.no_avx.__fpu_dp = 6;
- m_state.context.fpu.no_avx.__fpu_ds = 7;
- m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX;
- m_state.context.fpu.no_avx.__fpu_mxcsr = 8;
- m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9;
- int i;
- for (i=0; i<16; ++i)
- {
- if (i<10)
- {
- m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a';
- m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b';
- m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c';
- m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd';
- m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e';
- m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f';
- m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g';
- m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h';
- }
- else
- {
- m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
- m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
- }
-
- m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0';
- m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1';
- m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2';
- m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3';
- m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4';
- m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5';
- m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6';
- m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7';
- m_state.context.fpu.no_avx.__fpu_xmm8.__xmm_reg[i] = '8';
- m_state.context.fpu.no_avx.__fpu_xmm9.__xmm_reg[i] = '9';
- m_state.context.fpu.no_avx.__fpu_xmm10.__xmm_reg[i] = 'A';
- m_state.context.fpu.no_avx.__fpu_xmm11.__xmm_reg[i] = 'B';
- m_state.context.fpu.no_avx.__fpu_xmm12.__xmm_reg[i] = 'C';
- m_state.context.fpu.no_avx.__fpu_xmm13.__xmm_reg[i] = 'D';
- m_state.context.fpu.no_avx.__fpu_xmm14.__xmm_reg[i] = 'E';
- m_state.context.fpu.no_avx.__fpu_xmm15.__xmm_reg[i] = 'F';
- }
- for (i=0; i<sizeof(m_state.context.fpu.no_avx.__fpu_rsrv4); ++i)
- m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN;
- m_state.context.fpu.no_avx.__fpu_reserved1 = -1;
- m_state.SetError(e_regSetFPU, Read, 0);
- }
- }
- else
- {
- if (CPUHasAVX() || FORCE_AVX_REGS)
- {
- mach_msg_type_number_t count = e_regSetWordSizeAVX;
- m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, &count));
- DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &avx, %u (%u passed in) carp) => 0x%8.8x",
- m_thread->MachPortNumber(), __x86_64_AVX_STATE, (uint32_t)count,
- e_regSetWordSizeAVX, m_state.GetError(e_regSetFPU, Read));
- }
- else
- {
- mach_msg_type_number_t count = e_regSetWordSizeFPU;
- m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, &count));
- DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &fpu, %u (%u passed in) => 0x%8.8x",
- m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, (uint32_t)count,
- e_regSetWordSizeFPU, m_state.GetError(e_regSetFPU, Read));
- }
- }
- }
- return m_state.GetError(e_regSetFPU, Read);
-}
-
-kern_return_t
-DNBArchImplX86_64::GetEXCState(bool force)
-{
- if (force || m_state.GetError(e_regSetEXC, Read))
- {
- mach_msg_type_number_t count = e_regSetWordSizeEXC;
- m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count));
- }
- return m_state.GetError(e_regSetEXC, Read);
-}
-
-kern_return_t
-DNBArchImplX86_64::SetGPRState()
-{
- kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());
- DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());
-
- m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE, (thread_state_t)&m_state.context.gpr, e_regSetWordSizeGPR));
- DNBLogThreadedIf (LOG_THREAD, "::thread_set_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x"
- "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx"
- "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx"
- "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx"
- "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx"
- "\n\trip = %16.16llx"
- "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx",
- m_thread->MachPortNumber(), __x86_64_THREAD_STATE, e_regSetWordSizeGPR,
- m_state.GetError(e_regSetGPR, Write),
- m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx,
- m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi,
- m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8,
- m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11,
- m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14,
- m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags,
- m_state.context.gpr.__cs, m_state.context.gpr.__fs, m_state.context.gpr.__gs);
- return m_state.GetError(e_regSetGPR, Write);
-}
-
-kern_return_t
-DNBArchImplX86_64::SetFPUState()
-{
- if (DEBUG_FPU_REGS)
- {
- m_state.SetError(e_regSetFPU, Write, 0);
- return m_state.GetError(e_regSetFPU, Write);
- }
- else
- {
- if (CPUHasAVX() || FORCE_AVX_REGS)
- {
- m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, e_regSetWordSizeAVX));
- return m_state.GetError(e_regSetFPU, Write);
- }
- else
- {
- m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, e_regSetWordSizeFPU));
- return m_state.GetError(e_regSetFPU, Write);
- }
- }
-}
-
-kern_return_t
-DNBArchImplX86_64::SetEXCState()
-{
- m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, e_regSetWordSizeEXC));
- return m_state.GetError(e_regSetEXC, Write);
-}
-
-kern_return_t
-DNBArchImplX86_64::GetDBGState(bool force)
-{
- if (force || m_state.GetError(e_regSetDBG, Read))
- {
- mach_msg_type_number_t count = e_regSetWordSizeDBG;
- m_state.SetError(e_regSetDBG, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, &count));
- }
- return m_state.GetError(e_regSetDBG, Read);
-}
-
-kern_return_t
-DNBArchImplX86_64::SetDBGState(bool also_set_on_task)
-{
- m_state.SetError(e_regSetDBG, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG));
- if (also_set_on_task)
- {
- kern_return_t kret = ::task_set_state(m_thread->Process()->Task().TaskPort(), __x86_64_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG);
- if (kret != KERN_SUCCESS)
- DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::SetDBGState failed to set debug control register state: 0x%8.8x.", kret);
- }
- return m_state.GetError(e_regSetDBG, Write);
-}
-
-void
-DNBArchImplX86_64::ThreadWillResume()
-{
- // Do we need to step this thread? If so, let the mach thread tell us so.
- if (m_thread->IsStepping())
- {
- // This is the primary thread, let the arch do anything it needs
- EnableHardwareSingleStep(true);
- }
-
- // Reset the debug status register, if necessary, before we resume.
- kern_return_t kret = GetDBGState(false);
- DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret);
+kern_return_t DNBArchImplX86_64::GetFPUState(bool force) {
+ if (force || m_state.GetError(e_regSetFPU, Read)) {
+ if (DEBUG_FPU_REGS) {
+ if (CPUHasAVX() || FORCE_AVX_REGS) {
+ m_state.context.fpu.avx.__fpu_reserved[0] = -1;
+ m_state.context.fpu.avx.__fpu_reserved[1] = -1;
+ *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fcw) = 0x1234;
+ *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fsw) = 0x5678;
+ m_state.context.fpu.avx.__fpu_ftw = 1;
+ m_state.context.fpu.avx.__fpu_rsrv1 = UINT8_MAX;
+ m_state.context.fpu.avx.__fpu_fop = 2;
+ m_state.context.fpu.avx.__fpu_ip = 3;
+ m_state.context.fpu.avx.__fpu_cs = 4;
+ m_state.context.fpu.avx.__fpu_rsrv2 = UINT8_MAX;
+ m_state.context.fpu.avx.__fpu_dp = 5;
+ m_state.context.fpu.avx.__fpu_ds = 6;
+ m_state.context.fpu.avx.__fpu_rsrv3 = UINT16_MAX;
+ m_state.context.fpu.avx.__fpu_mxcsr = 8;
+ m_state.context.fpu.avx.__fpu_mxcsrmask = 9;
+ int i;
+ for (i = 0; i < 16; ++i) {
+ if (i < 10) {
+ m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = 'a';
+ m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = 'b';
+ m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = 'c';
+ m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = 'd';
+ m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = 'e';
+ m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = 'f';
+ m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = 'g';
+ m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = 'h';
+ } else {
+ m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
+ }
+
+ m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg[i] = '0' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg[i] = '1' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg[i] = '2' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg[i] = '3' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg[i] = '4' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg[i] = '5' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg[i] = '6' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg[i] = '7' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm8.__xmm_reg[i] = '8' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm9.__xmm_reg[i] = '9' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm10.__xmm_reg[i] = 'A' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm11.__xmm_reg[i] = 'B' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm12.__xmm_reg[i] = 'C' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm13.__xmm_reg[i] = 'D' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm14.__xmm_reg[i] = 'E' + 2 * i;
+ m_state.context.fpu.avx.__fpu_xmm15.__xmm_reg[i] = 'F' + 2 * i;
+
+ m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0' + i;
+ m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1' + i;
+ m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2' + i;
+ m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3' + i;
+ m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4' + i;
+ m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5' + i;
+ m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6' + i;
+ m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7' + i;
+ m_state.context.fpu.avx.__fpu_ymmh8.__xmm_reg[i] = '8' + i;
+ m_state.context.fpu.avx.__fpu_ymmh9.__xmm_reg[i] = '9' + i;
+ m_state.context.fpu.avx.__fpu_ymmh10.__xmm_reg[i] = 'A' + i;
+ m_state.context.fpu.avx.__fpu_ymmh11.__xmm_reg[i] = 'B' + i;
+ m_state.context.fpu.avx.__fpu_ymmh12.__xmm_reg[i] = 'C' + i;
+ m_state.context.fpu.avx.__fpu_ymmh13.__xmm_reg[i] = 'D' + i;
+ m_state.context.fpu.avx.__fpu_ymmh14.__xmm_reg[i] = 'E' + i;
+ m_state.context.fpu.avx.__fpu_ymmh15.__xmm_reg[i] = 'F' + i;
+ }
+ for (i = 0; i < sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i)
+ m_state.context.fpu.avx.__fpu_rsrv4[i] = INT8_MIN;
+ m_state.context.fpu.avx.__fpu_reserved1 = -1;
+ for (i = 0; i < sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i)
+ m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN;
+ m_state.SetError(e_regSetFPU, Read, 0);
+ } else {
+ m_state.context.fpu.no_avx.__fpu_reserved[0] = -1;
+ m_state.context.fpu.no_avx.__fpu_reserved[1] = -1;
+ *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234;
+ *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678;
+ m_state.context.fpu.no_avx.__fpu_ftw = 1;
+ m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX;
+ m_state.context.fpu.no_avx.__fpu_fop = 2;
+ m_state.context.fpu.no_avx.__fpu_ip = 3;
+ m_state.context.fpu.no_avx.__fpu_cs = 4;
+ m_state.context.fpu.no_avx.__fpu_rsrv2 = 5;
+ m_state.context.fpu.no_avx.__fpu_dp = 6;
+ m_state.context.fpu.no_avx.__fpu_ds = 7;
+ m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX;
+ m_state.context.fpu.no_avx.__fpu_mxcsr = 8;
+ m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9;
+ int i;
+ for (i = 0; i < 16; ++i) {
+ if (i < 10) {
+ m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a';
+ m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b';
+ m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c';
+ m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd';
+ m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e';
+ m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f';
+ m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g';
+ m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h';
+ } else {
+ m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
+ m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
+ }
+
+ m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0';
+ m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1';
+ m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2';
+ m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3';
+ m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4';
+ m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5';
+ m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6';
+ m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7';
+ m_state.context.fpu.no_avx.__fpu_xmm8.__xmm_reg[i] = '8';
+ m_state.context.fpu.no_avx.__fpu_xmm9.__xmm_reg[i] = '9';
+ m_state.context.fpu.no_avx.__fpu_xmm10.__xmm_reg[i] = 'A';
+ m_state.context.fpu.no_avx.__fpu_xmm11.__xmm_reg[i] = 'B';
+ m_state.context.fpu.no_avx.__fpu_xmm12.__xmm_reg[i] = 'C';
+ m_state.context.fpu.no_avx.__fpu_xmm13.__xmm_reg[i] = 'D';
+ m_state.context.fpu.no_avx.__fpu_xmm14.__xmm_reg[i] = 'E';
+ m_state.context.fpu.no_avx.__fpu_xmm15.__xmm_reg[i] = 'F';
+ }
+ for (i = 0; i < sizeof(m_state.context.fpu.no_avx.__fpu_rsrv4); ++i)
+ m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN;
+ m_state.context.fpu.no_avx.__fpu_reserved1 = -1;
+ m_state.SetError(e_regSetFPU, Read, 0);
+ }
+ } else {
+ if (CPUHasAVX() || FORCE_AVX_REGS) {
+ mach_msg_type_number_t count = e_regSetWordSizeAVX;
+ m_state.SetError(e_regSetFPU, Read,
+ ::thread_get_state(
+ m_thread->MachPortNumber(), __x86_64_AVX_STATE,
+ (thread_state_t)&m_state.context.fpu.avx, &count));
+ DNBLogThreadedIf(LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &avx, "
+ "%u (%u passed in) carp) => 0x%8.8x",
+ m_thread->MachPortNumber(), __x86_64_AVX_STATE,
+ (uint32_t)count, e_regSetWordSizeAVX,
+ m_state.GetError(e_regSetFPU, Read));
+ } else {
+ mach_msg_type_number_t count = e_regSetWordSizeFPU;
+ m_state.SetError(
+ e_regSetFPU, Read,
+ ::thread_get_state(m_thread->MachPortNumber(), __x86_64_FLOAT_STATE,
+ (thread_state_t)&m_state.context.fpu.no_avx,
+ &count));
+ DNBLogThreadedIf(LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &fpu, "
+ "%u (%u passed in) => 0x%8.8x",
+ m_thread->MachPortNumber(), __x86_64_FLOAT_STATE,
+ (uint32_t)count, e_regSetWordSizeFPU,
+ m_state.GetError(e_regSetFPU, Read));
+ }
+ }
+ }
+ return m_state.GetError(e_regSetFPU, Read);
+}
+
+kern_return_t DNBArchImplX86_64::GetEXCState(bool force) {
+ if (force || m_state.GetError(e_regSetEXC, Read)) {
+ mach_msg_type_number_t count = e_regSetWordSizeEXC;
+ m_state.SetError(
+ e_regSetEXC, Read,
+ ::thread_get_state(m_thread->MachPortNumber(), __x86_64_EXCEPTION_STATE,
+ (thread_state_t)&m_state.context.exc, &count));
+ }
+ return m_state.GetError(e_regSetEXC, Read);
+}
+
+kern_return_t DNBArchImplX86_64::SetGPRState() {
+ kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());
+ DNBLogThreadedIf(
+ LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u "
+ "(SetGPRState() for stop_count = %u)",
+ m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());
+
+ m_state.SetError(e_regSetGPR, Write,
+ ::thread_set_state(m_thread->MachPortNumber(),
+ __x86_64_THREAD_STATE,
+ (thread_state_t)&m_state.context.gpr,
+ e_regSetWordSizeGPR));
+ DNBLogThreadedIf(
+ LOG_THREAD,
+ "::thread_set_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x"
+ "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx"
+ "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx"
+ "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx"
+ "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx"
+ "\n\trip = %16.16llx"
+ "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx",
+ m_thread->MachPortNumber(), __x86_64_THREAD_STATE, e_regSetWordSizeGPR,
+ m_state.GetError(e_regSetGPR, Write), m_state.context.gpr.__rax,
+ m_state.context.gpr.__rbx, m_state.context.gpr.__rcx,
+ m_state.context.gpr.__rdx, m_state.context.gpr.__rdi,
+ m_state.context.gpr.__rsi, m_state.context.gpr.__rbp,
+ m_state.context.gpr.__rsp, m_state.context.gpr.__r8,
+ m_state.context.gpr.__r9, m_state.context.gpr.__r10,
+ m_state.context.gpr.__r11, m_state.context.gpr.__r12,
+ m_state.context.gpr.__r13, m_state.context.gpr.__r14,
+ m_state.context.gpr.__r15, m_state.context.gpr.__rip,
+ m_state.context.gpr.__rflags, m_state.context.gpr.__cs,
+ m_state.context.gpr.__fs, m_state.context.gpr.__gs);
+ return m_state.GetError(e_regSetGPR, Write);
+}
+
+kern_return_t DNBArchImplX86_64::SetFPUState() {
+ if (DEBUG_FPU_REGS) {
+ m_state.SetError(e_regSetFPU, Write, 0);
+ return m_state.GetError(e_regSetFPU, Write);
+ } else {
+ if (CPUHasAVX() || FORCE_AVX_REGS) {
+ m_state.SetError(
+ e_regSetFPU, Write,
+ ::thread_set_state(m_thread->MachPortNumber(), __x86_64_AVX_STATE,
+ (thread_state_t)&m_state.context.fpu.avx,
+ e_regSetWordSizeAVX));
+ return m_state.GetError(e_regSetFPU, Write);
+ } else {
+ m_state.SetError(
+ e_regSetFPU, Write,
+ ::thread_set_state(m_thread->MachPortNumber(), __x86_64_FLOAT_STATE,
+ (thread_state_t)&m_state.context.fpu.no_avx,
+ e_regSetWordSizeFPU));
+ return m_state.GetError(e_regSetFPU, Write);
+ }
+ }
+}
+
+kern_return_t DNBArchImplX86_64::SetEXCState() {
+ m_state.SetError(e_regSetEXC, Write,
+ ::thread_set_state(m_thread->MachPortNumber(),
+ __x86_64_EXCEPTION_STATE,
+ (thread_state_t)&m_state.context.exc,
+ e_regSetWordSizeEXC));
+ return m_state.GetError(e_regSetEXC, Write);
+}
+
+kern_return_t DNBArchImplX86_64::GetDBGState(bool force) {
+ if (force || m_state.GetError(e_regSetDBG, Read)) {
+ mach_msg_type_number_t count = e_regSetWordSizeDBG;
+ m_state.SetError(
+ e_regSetDBG, Read,
+ ::thread_get_state(m_thread->MachPortNumber(), __x86_64_DEBUG_STATE,
+ (thread_state_t)&m_state.context.dbg, &count));
+ }
+ return m_state.GetError(e_regSetDBG, Read);
+}
+
+kern_return_t DNBArchImplX86_64::SetDBGState(bool also_set_on_task) {
+ m_state.SetError(e_regSetDBG, Write,
+ ::thread_set_state(m_thread->MachPortNumber(),
+ __x86_64_DEBUG_STATE,
+ (thread_state_t)&m_state.context.dbg,
+ e_regSetWordSizeDBG));
+ if (also_set_on_task) {
+ kern_return_t kret = ::task_set_state(
+ m_thread->Process()->Task().TaskPort(), __x86_64_DEBUG_STATE,
+ (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG);
if (kret != KERN_SUCCESS)
- return;
-
- DBG &debug_state = m_state.context.dbg;
- bool need_reset = false;
- uint32_t i, num = NumSupportedHardwareWatchpoints();
- for (i = 0; i < num; ++i)
- if (IsWatchpointHit(debug_state, i))
- need_reset = true;
-
- if (need_reset)
- {
- ClearWatchpointHits(debug_state);
- kret = SetDBGState(false);
- DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret);
- }
-}
+ DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::SetDBGState failed "
+ "to set debug control register state: "
+ "0x%8.8x.",
+ kret);
+ }
+ return m_state.GetError(e_regSetDBG, Write);
+}
+
+void DNBArchImplX86_64::ThreadWillResume() {
+ // Do we need to step this thread? If so, let the mach thread tell us so.
+ if (m_thread->IsStepping()) {
+ // This is the primary thread, let the arch do anything it needs
+ EnableHardwareSingleStep(true);
+ }
+
+ // Reset the debug status register, if necessary, before we resume.
+ kern_return_t kret = GetDBGState(false);
+ DNBLogThreadedIf(
+ LOG_WATCHPOINTS,
+ "DNBArchImplX86_64::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret);
+ if (kret != KERN_SUCCESS)
+ return;
-bool
-DNBArchImplX86_64::ThreadDidStop()
-{
- bool success = true;
-
- m_state.InvalidateAllRegisterStates();
-
- // Are we stepping a single instruction?
- if (GetGPRState(true) == KERN_SUCCESS)
- {
- // We are single stepping, was this the primary thread?
- if (m_thread->IsStepping())
- {
- // This was the primary thread, we need to clear the trace
- // bit if so.
- success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
- }
- else
- {
- // The MachThread will automatically restore the suspend count
- // in ThreadDidStop(), so we don't need to do anything here if
- // we weren't the primary thread the last time
+ DBG &debug_state = m_state.context.dbg;
+ bool need_reset = false;
+ uint32_t i, num = NumSupportedHardwareWatchpoints();
+ for (i = 0; i < num; ++i)
+ if (IsWatchpointHit(debug_state, i))
+ need_reset = true;
+
+ if (need_reset) {
+ ClearWatchpointHits(debug_state);
+ kret = SetDBGState(false);
+ DNBLogThreadedIf(
+ LOG_WATCHPOINTS,
+ "DNBArchImplX86_64::ThreadWillResume() SetDBGState() => 0x%8.8x.",
+ kret);
+ }
+}
+
+bool DNBArchImplX86_64::ThreadDidStop() {
+ bool success = true;
+
+ m_state.InvalidateAllRegisterStates();
+
+ // Are we stepping a single instruction?
+ if (GetGPRState(true) == KERN_SUCCESS) {
+ // We are single stepping, was this the primary thread?
+ if (m_thread->IsStepping()) {
+ // This was the primary thread, we need to clear the trace
+ // bit if so.
+ success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
+ } else {
+ // The MachThread will automatically restore the suspend count
+ // in ThreadDidStop(), so we don't need to do anything here if
+ // we weren't the primary thread the last time
+ }
+ }
+ return success;
+}
+
+bool DNBArchImplX86_64::NotifyException(MachException::Data &exc) {
+ switch (exc.exc_type) {
+ case EXC_BAD_ACCESS:
+ break;
+ case EXC_BAD_INSTRUCTION:
+ break;
+ case EXC_ARITHMETIC:
+ break;
+ case EXC_EMULATION:
+ break;
+ case EXC_SOFTWARE:
+ break;
+ case EXC_BREAKPOINT:
+ if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) {
+ // exc_code = EXC_I386_BPT
+ //
+ nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS);
+ if (pc != INVALID_NUB_ADDRESS && pc > 0) {
+ pc -= 1;
+ // Check for a breakpoint at one byte prior to the current PC value
+ // since the PC will be just past the trap.
+
+ DNBBreakpoint *bp =
+ m_thread->Process()->Breakpoints().FindByAddress(pc);
+ if (bp) {
+ // Backup the PC for i386 since the trap was taken and the PC
+ // is at the address following the single byte trap instruction.
+ if (m_state.context.gpr.__rip > 0) {
+ m_state.context.gpr.__rip = pc;
+ // Write the new PC back out
+ SetGPRState();
+ }
}
- }
- return success;
-}
+ return true;
+ }
+ } else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) {
+ // exc_code = EXC_I386_SGL
+ //
+ // Check whether this corresponds to a watchpoint hit event.
+ // If yes, set the exc_sub_code to the data break address.
+ nub_addr_t addr = 0;
+ uint32_t hw_index = GetHardwareWatchpointHit(addr);
+ if (hw_index != INVALID_NUB_HW_INDEX) {
+ exc.exc_data[1] = addr;
+ // Piggyback the hw_index in the exc.data.
+ exc.exc_data.push_back(hw_index);
+ }
+
+ return true;
+ }
+ break;
+ case EXC_SYSCALL:
+ break;
+ case EXC_MACH_SYSCALL:
+ break;
+ case EXC_RPC_ALERT:
+ break;
+ }
+ return false;
+}
+
+uint32_t DNBArchImplX86_64::NumSupportedHardwareWatchpoints() {
+ // Available debug address registers: dr0, dr1, dr2, dr3.
+ return 4;
+}
+
+static uint32_t size_and_rw_bits(nub_size_t size, bool read, bool write) {
+ uint32_t rw;
+ if (read) {
+ rw = 0x3; // READ or READ/WRITE
+ } else if (write) {
+ rw = 0x1; // WRITE
+ } else {
+ assert(0 && "read and write cannot both be false");
+ }
+
+ switch (size) {
+ case 1:
+ return rw;
+ case 2:
+ return (0x1 << 2) | rw;
+ case 4:
+ return (0x3 << 2) | rw;
+ case 8:
+ return (0x2 << 2) | rw;
+ }
+ assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
+ return 0;
+}
+void DNBArchImplX86_64::SetWatchpoint(DBG &debug_state, uint32_t hw_index,
+ nub_addr_t addr, nub_size_t size,
+ bool read, bool write) {
+ // Set both dr7 (debug control register) and dri (debug address register).
+
+ // dr7{7-0} encodes the local/gloabl enable bits:
+ // global enable --. .-- local enable
+ // | |
+ // v v
+ // dr0 -> bits{1-0}
+ // dr1 -> bits{3-2}
+ // dr2 -> bits{5-4}
+ // dr3 -> bits{7-6}
+ //
+ // dr7{31-16} encodes the rw/len bits:
+ // b_x+3, b_x+2, b_x+1, b_x
+ // where bits{x+1, x} => rw
+ // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io
+ // read-or-write (unused)
+ // and bits{x+3, x+2} => len
+ // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
+ //
+ // dr0 -> bits{19-16}
+ // dr1 -> bits{23-20}
+ // dr2 -> bits{27-24}
+ // dr3 -> bits{31-28}
+ debug_state.__dr7 |=
+ (1 << (2 * hw_index) |
+ size_and_rw_bits(size, read, write) << (16 + 4 * hw_index));
+ switch (hw_index) {
+ case 0:
+ debug_state.__dr0 = addr;
+ break;
+ case 1:
+ debug_state.__dr1 = addr;
+ break;
+ case 2:
+ debug_state.__dr2 = addr;
+ break;
+ case 3:
+ debug_state.__dr3 = addr;
+ break;
+ default:
+ assert(0 &&
+ "invalid hardware register index, must be one of 0, 1, 2, or 3");
+ }
+ return;
+}
+
+void DNBArchImplX86_64::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) {
+ debug_state.__dr7 &= ~(3 << (2 * hw_index));
+ switch (hw_index) {
+ case 0:
+ debug_state.__dr0 = 0;
+ break;
+ case 1:
+ debug_state.__dr1 = 0;
+ break;
+ case 2:
+ debug_state.__dr2 = 0;
+ break;
+ case 3:
+ debug_state.__dr3 = 0;
+ break;
+ default:
+ assert(0 &&
+ "invalid hardware register index, must be one of 0, 1, 2, or 3");
+ }
+ return;
+}
+
+bool DNBArchImplX86_64::IsWatchpointVacant(const DBG &debug_state,
+ uint32_t hw_index) {
+ // Check dr7 (debug control register) for local/global enable bits:
+ // global enable --. .-- local enable
+ // | |
+ // v v
+ // dr0 -> bits{1-0}
+ // dr1 -> bits{3-2}
+ // dr2 -> bits{5-4}
+ // dr3 -> bits{7-6}
+ return (debug_state.__dr7 & (3 << (2 * hw_index))) == 0;
+}
+
+// Resets local copy of debug status register to wait for the next debug
+// exception.
+void DNBArchImplX86_64::ClearWatchpointHits(DBG &debug_state) {
+ // See also IsWatchpointHit().
+ debug_state.__dr6 = 0;
+ return;
+}
+
+bool DNBArchImplX86_64::IsWatchpointHit(const DBG &debug_state,
+ uint32_t hw_index) {
+ // Check dr6 (debug status register) whether a watchpoint hits:
+ // is watchpoint hit?
+ // |
+ // v
+ // dr0 -> bits{0}
+ // dr1 -> bits{1}
+ // dr2 -> bits{2}
+ // dr3 -> bits{3}
+ return (debug_state.__dr6 & (1 << hw_index));
+}
+
+nub_addr_t DNBArchImplX86_64::GetWatchAddress(const DBG &debug_state,
+ uint32_t hw_index) {
+ switch (hw_index) {
+ case 0:
+ return debug_state.__dr0;
+ case 1:
+ return debug_state.__dr1;
+ case 2:
+ return debug_state.__dr2;
+ case 3:
+ return debug_state.__dr3;
+ }
+ assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
+ return 0;
+}
+
+bool DNBArchImplX86_64::StartTransForHWP() {
+ if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back)
+ DNBLogError("%s inconsistent state detected, expected %d or %d, got: %d",
+ __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state);
+ m_2pc_dbg_checkpoint = m_state.context.dbg;
+ m_2pc_trans_state = Trans_Pending;
+ return true;
+}
+bool DNBArchImplX86_64::RollbackTransForHWP() {
+ m_state.context.dbg = m_2pc_dbg_checkpoint;
+ if (m_2pc_trans_state != Trans_Pending)
+ DNBLogError("%s inconsistent state detected, expected %d, got: %d",
+ __FUNCTION__, Trans_Pending, m_2pc_trans_state);
+ m_2pc_trans_state = Trans_Rolled_Back;
+ kern_return_t kret = SetDBGState(false);
+ DNBLogThreadedIf(
+ LOG_WATCHPOINTS,
+ "DNBArchImplX86_64::RollbackTransForHWP() SetDBGState() => 0x%8.8x.",
+ kret);
-bool
-DNBArchImplX86_64::NotifyException(MachException::Data& exc)
-{
- switch (exc.exc_type)
- {
- case EXC_BAD_ACCESS:
- break;
- case EXC_BAD_INSTRUCTION:
- break;
- case EXC_ARITHMETIC:
- break;
- case EXC_EMULATION:
- break;
- case EXC_SOFTWARE:
- break;
- case EXC_BREAKPOINT:
- if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2)
- {
- // exc_code = EXC_I386_BPT
- //
- nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS);
- if (pc != INVALID_NUB_ADDRESS && pc > 0)
- {
- pc -= 1;
- // Check for a breakpoint at one byte prior to the current PC value
- // since the PC will be just past the trap.
-
- DNBBreakpoint *bp = m_thread->Process()->Breakpoints().FindByAddress(pc);
- if (bp)
- {
- // Backup the PC for i386 since the trap was taken and the PC
- // is at the address following the single byte trap instruction.
- if (m_state.context.gpr.__rip > 0)
- {
- m_state.context.gpr.__rip = pc;
- // Write the new PC back out
- SetGPRState ();
- }
- }
- return true;
- }
- }
- else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1)
- {
- // exc_code = EXC_I386_SGL
- //
- // Check whether this corresponds to a watchpoint hit event.
- // If yes, set the exc_sub_code to the data break address.
- nub_addr_t addr = 0;
- uint32_t hw_index = GetHardwareWatchpointHit(addr);
- if (hw_index != INVALID_NUB_HW_INDEX)
- {
- exc.exc_data[1] = addr;
- // Piggyback the hw_index in the exc.data.
- exc.exc_data.push_back(hw_index);
- }
-
- return true;
- }
- break;
- case EXC_SYSCALL:
- break;
- case EXC_MACH_SYSCALL:
- break;
- case EXC_RPC_ALERT:
- break;
- }
+ if (kret == KERN_SUCCESS)
+ return true;
+ else
return false;
}
+bool DNBArchImplX86_64::FinishTransForHWP() {
+ m_2pc_trans_state = Trans_Done;
+ return true;
+}
+DNBArchImplX86_64::DBG DNBArchImplX86_64::GetDBGCheckpoint() {
+ return m_2pc_dbg_checkpoint;
+}
+
+uint32_t DNBArchImplX86_64::EnableHardwareWatchpoint(nub_addr_t addr,
+ nub_size_t size, bool read,
+ bool write,
+ bool also_set_on_task) {
+ DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::"
+ "EnableHardwareWatchpoint(addr = 0x%llx, "
+ "size = %llu, read = %u, write = %u)",
+ (uint64_t)addr, (uint64_t)size, read, write);
-uint32_t
-DNBArchImplX86_64::NumSupportedHardwareWatchpoints()
-{
- // Available debug address registers: dr0, dr1, dr2, dr3.
- return 4;
-}
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
-static uint32_t
-size_and_rw_bits(nub_size_t size, bool read, bool write)
-{
- uint32_t rw;
- if (read) {
- rw = 0x3; // READ or READ/WRITE
- } else if (write) {
- rw = 0x1; // WRITE
- } else {
- assert(0 && "read and write cannot both be false");
- }
+ // Can only watch 1, 2, 4, or 8 bytes.
+ if (!(size == 1 || size == 2 || size == 4 || size == 8))
+ return INVALID_NUB_HW_INDEX;
- switch (size) {
- case 1:
- return rw;
- case 2:
- return (0x1 << 2) | rw;
- case 4:
- return (0x3 << 2) | rw;
- case 8:
- return (0x2 << 2) | rw;
- }
- assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
- return 0;
-}
-void
-DNBArchImplX86_64::SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write)
-{
- // Set both dr7 (debug control register) and dri (debug address register).
-
- // dr7{7-0} encodes the local/gloabl enable bits:
- // global enable --. .-- local enable
- // | |
- // v v
- // dr0 -> bits{1-0}
- // dr1 -> bits{3-2}
- // dr2 -> bits{5-4}
- // dr3 -> bits{7-6}
- //
- // dr7{31-16} encodes the rw/len bits:
- // b_x+3, b_x+2, b_x+1, b_x
- // where bits{x+1, x} => rw
- // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io read-or-write (unused)
- // and bits{x+3, x+2} => len
- // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
- //
- // dr0 -> bits{19-16}
- // dr1 -> bits{23-20}
- // dr2 -> bits{27-24}
- // dr3 -> bits{31-28}
- debug_state.__dr7 |= (1 << (2*hw_index) |
- size_and_rw_bits(size, read, write) << (16+4*hw_index));
- switch (hw_index) {
- case 0:
- debug_state.__dr0 = addr; break;
- case 1:
- debug_state.__dr1 = addr; break;
- case 2:
- debug_state.__dr2 = addr; break;
- case 3:
- debug_state.__dr3 = addr; break;
- default:
- assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
- }
- return;
-}
+ // We must watch for either read or write
+ if (read == false && write == false)
+ return INVALID_NUB_HW_INDEX;
-void
-DNBArchImplX86_64::ClearWatchpoint(DBG &debug_state, uint32_t hw_index)
-{
- debug_state.__dr7 &= ~(3 << (2*hw_index));
- switch (hw_index) {
- case 0:
- debug_state.__dr0 = 0; break;
- case 1:
- debug_state.__dr1 = 0; break;
- case 2:
- debug_state.__dr2 = 0; break;
- case 3:
- debug_state.__dr3 = 0; break;
- default:
- assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
- }
- return;
-}
+ // Read the debug state
+ kern_return_t kret = GetDBGState(false);
-bool
-DNBArchImplX86_64::IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index)
-{
- // Check dr7 (debug control register) for local/global enable bits:
- // global enable --. .-- local enable
- // | |
- // v v
- // dr0 -> bits{1-0}
- // dr1 -> bits{3-2}
- // dr2 -> bits{5-4}
- // dr3 -> bits{7-6}
- return (debug_state.__dr7 & (3 << (2*hw_index))) == 0;
-}
-
-// Resets local copy of debug status register to wait for the next debug exception.
-void
-DNBArchImplX86_64::ClearWatchpointHits(DBG &debug_state)
-{
- // See also IsWatchpointHit().
- debug_state.__dr6 = 0;
- return;
-}
+ if (kret == KERN_SUCCESS) {
+ // Check to make sure we have the needed hardware support
+ uint32_t i = 0;
-bool
-DNBArchImplX86_64::IsWatchpointHit(const DBG &debug_state, uint32_t hw_index)
-{
- // Check dr6 (debug status register) whether a watchpoint hits:
- // is watchpoint hit?
- // |
- // v
- // dr0 -> bits{0}
- // dr1 -> bits{1}
- // dr2 -> bits{2}
- // dr3 -> bits{3}
- return (debug_state.__dr6 & (1 << hw_index));
-}
-
-nub_addr_t
-DNBArchImplX86_64::GetWatchAddress(const DBG &debug_state, uint32_t hw_index)
-{
- switch (hw_index) {
- case 0:
- return debug_state.__dr0;
- case 1:
- return debug_state.__dr1;
- case 2:
- return debug_state.__dr2;
- case 3:
- return debug_state.__dr3;
+ DBG &debug_state = m_state.context.dbg;
+ for (i = 0; i < num_hw_watchpoints; ++i) {
+ if (IsWatchpointVacant(debug_state, i))
+ break;
+ }
+
+ // See if we found an available hw breakpoint slot above
+ if (i < num_hw_watchpoints) {
+ StartTransForHWP();
+
+ // Modify our local copy of the debug state, first.
+ SetWatchpoint(debug_state, i, addr, size, read, write);
+ // Now set the watch point in the inferior.
+ kret = SetDBGState(also_set_on_task);
+ DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::"
+ "EnableHardwareWatchpoint() "
+ "SetDBGState() => 0x%8.8x.",
+ kret);
+
+ if (kret == KERN_SUCCESS)
+ return i;
+ else // Revert to the previous debug state voluntarily. The transaction
+ // coordinator knows that we have failed.
+ m_state.context.dbg = GetDBGCheckpoint();
+ } else {
+ DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::"
+ "EnableHardwareWatchpoint(): All "
+ "hardware resources (%u) are in use.",
+ num_hw_watchpoints);
}
- assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
- return 0;
-}
-
-bool
-DNBArchImplX86_64::StartTransForHWP()
-{
- if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back)
- DNBLogError ("%s inconsistent state detected, expected %d or %d, got: %d", __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state);
- m_2pc_dbg_checkpoint = m_state.context.dbg;
- m_2pc_trans_state = Trans_Pending;
- return true;
+ }
+ return INVALID_NUB_HW_INDEX;
}
-bool
-DNBArchImplX86_64::RollbackTransForHWP()
-{
- m_state.context.dbg = m_2pc_dbg_checkpoint;
- if (m_2pc_trans_state != Trans_Pending)
- DNBLogError ("%s inconsistent state detected, expected %d, got: %d", __FUNCTION__, Trans_Pending, m_2pc_trans_state);
- m_2pc_trans_state = Trans_Rolled_Back;
- kern_return_t kret = SetDBGState(false);
- DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret);
- if (kret == KERN_SUCCESS)
- return true;
- else
- return false;
-}
-bool
-DNBArchImplX86_64::FinishTransForHWP()
-{
- m_2pc_trans_state = Trans_Done;
- return true;
-}
-DNBArchImplX86_64::DBG
-DNBArchImplX86_64::GetDBGCheckpoint()
-{
- return m_2pc_dbg_checkpoint;
-}
-
-uint32_t
-DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task)
-{
- DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint(addr = 0x%llx, size = %llu, read = %u, write = %u)", (uint64_t)addr, (uint64_t)size, read, write);
-
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
-
- // Can only watch 1, 2, 4, or 8 bytes.
- if (!(size == 1 || size == 2 || size == 4 || size == 8))
- return INVALID_NUB_HW_INDEX;
-
- // We must watch for either read or write
- if (read == false && write == false)
- return INVALID_NUB_HW_INDEX;
-
- // Read the debug state
- kern_return_t kret = GetDBGState(false);
-
- if (kret == KERN_SUCCESS)
- {
- // Check to make sure we have the needed hardware support
- uint32_t i = 0;
-
- DBG &debug_state = m_state.context.dbg;
- for (i = 0; i < num_hw_watchpoints; ++i)
- {
- if (IsWatchpointVacant(debug_state, i))
- break;
- }
+bool DNBArchImplX86_64::DisableHardwareWatchpoint(uint32_t hw_index,
+ bool also_set_on_task) {
+ kern_return_t kret = GetDBGState(false);
- // See if we found an available hw breakpoint slot above
- if (i < num_hw_watchpoints)
- {
- StartTransForHWP();
-
- // Modify our local copy of the debug state, first.
- SetWatchpoint(debug_state, i, addr, size, read, write);
- // Now set the watch point in the inferior.
- kret = SetDBGState(also_set_on_task);
- DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret);
-
- if (kret == KERN_SUCCESS)
- return i;
- else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed.
- m_state.context.dbg = GetDBGCheckpoint();
- }
- else
- {
- DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
- }
- }
- return INVALID_NUB_HW_INDEX;
-}
+ const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
+ if (kret == KERN_SUCCESS) {
+ DBG &debug_state = m_state.context.dbg;
+ if (hw_index < num_hw_points &&
+ !IsWatchpointVacant(debug_state, hw_index)) {
+ StartTransForHWP();
+
+ // Modify our local copy of the debug state, first.
+ ClearWatchpoint(debug_state, hw_index);
+ // Now disable the watch point in the inferior.
+ kret = SetDBGState(also_set_on_task);
+ DNBLogThreadedIf(LOG_WATCHPOINTS,
+ "DNBArchImplX86_64::DisableHardwareWatchpoint( %u )",
+ hw_index);
-bool
-DNBArchImplX86_64::DisableHardwareWatchpoint (uint32_t hw_index, bool also_set_on_task)
-{
- kern_return_t kret = GetDBGState(false);
-
- const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
- if (kret == KERN_SUCCESS)
- {
- DBG &debug_state = m_state.context.dbg;
- if (hw_index < num_hw_points && !IsWatchpointVacant(debug_state, hw_index))
- {
- StartTransForHWP();
-
- // Modify our local copy of the debug state, first.
- ClearWatchpoint(debug_state, hw_index);
- // Now disable the watch point in the inferior.
- kret = SetDBGState(also_set_on_task);
- DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::DisableHardwareWatchpoint( %u )",
- hw_index);
-
- if (kret == KERN_SUCCESS)
- return true;
- else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed.
- m_state.context.dbg = GetDBGCheckpoint();
- }
+ if (kret == KERN_SUCCESS)
+ return true;
+ else // Revert to the previous debug state voluntarily. The transaction
+ // coordinator knows that we have failed.
+ m_state.context.dbg = GetDBGCheckpoint();
}
- return false;
+ }
+ return false;
}
// Iterate through the debug status register; return the index of the first hit.
-uint32_t
-DNBArchImplX86_64::GetHardwareWatchpointHit(nub_addr_t &addr)
-{
- // Read the debug state
- kern_return_t kret = GetDBGState(true);
- DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret);
- if (kret == KERN_SUCCESS)
- {
- DBG &debug_state = m_state.context.dbg;
- uint32_t i, num = NumSupportedHardwareWatchpoints();
- for (i = 0; i < num; ++i)
- {
- if (IsWatchpointHit(debug_state, i))
- {
- addr = GetWatchAddress(debug_state, i);
- DNBLogThreadedIf(LOG_WATCHPOINTS,
- "DNBArchImplX86_64::GetHardwareWatchpointHit() found => %u (addr = 0x%llx).",
- i,
- (uint64_t)addr);
- return i;
- }
- }
+uint32_t DNBArchImplX86_64::GetHardwareWatchpointHit(nub_addr_t &addr) {
+ // Read the debug state
+ kern_return_t kret = GetDBGState(true);
+ DNBLogThreadedIf(
+ LOG_WATCHPOINTS,
+ "DNBArchImplX86_64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.",
+ kret);
+ if (kret == KERN_SUCCESS) {
+ DBG &debug_state = m_state.context.dbg;
+ uint32_t i, num = NumSupportedHardwareWatchpoints();
+ for (i = 0; i < num; ++i) {
+ if (IsWatchpointHit(debug_state, i)) {
+ addr = GetWatchAddress(debug_state, i);
+ DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::"
+ "GetHardwareWatchpointHit() found => "
+ "%u (addr = 0x%llx).",
+ i, (uint64_t)addr);
+ return i;
+ }
}
- return INVALID_NUB_HW_INDEX;
+ }
+ return INVALID_NUB_HW_INDEX;
}
// Set the single step bit in the processor status register.
-kern_return_t
-DNBArchImplX86_64::EnableHardwareSingleStep (bool enable)
-{
- if (GetGPRState(false) == KERN_SUCCESS)
- {
- const uint32_t trace_bit = 0x100u;
- if (enable)
- m_state.context.gpr.__rflags |= trace_bit;
- else
- m_state.context.gpr.__rflags &= ~trace_bit;
- return SetGPRState();
- }
- return m_state.GetError(e_regSetGPR, Read);
+kern_return_t DNBArchImplX86_64::EnableHardwareSingleStep(bool enable) {
+ if (GetGPRState(false) == KERN_SUCCESS) {
+ const uint32_t trace_bit = 0x100u;
+ if (enable)
+ m_state.context.gpr.__rflags |= trace_bit;
+ else
+ m_state.context.gpr.__rflags &= ~trace_bit;
+ return SetGPRState();
+ }
+ return m_state.GetError(e_regSetGPR, Read);
}
-
//----------------------------------------------------------------------
// Register information definitions
//----------------------------------------------------------------------
-enum
-{
- gpr_rax = 0,
- gpr_rbx,
- gpr_rcx,
- gpr_rdx,
- gpr_rdi,
- gpr_rsi,
- gpr_rbp,
- gpr_rsp,
- gpr_r8,
- gpr_r9,
- gpr_r10,
- gpr_r11,
- gpr_r12,
- gpr_r13,
- gpr_r14,
- gpr_r15,
- gpr_rip,
- gpr_rflags,
- gpr_cs,
- gpr_fs,
- gpr_gs,
- gpr_eax,
- gpr_ebx,
- gpr_ecx,
- gpr_edx,
- gpr_edi,
- gpr_esi,
- gpr_ebp,
- gpr_esp,
- gpr_r8d, // Low 32 bits or r8
- gpr_r9d, // Low 32 bits or r9
- gpr_r10d, // Low 32 bits or r10
- gpr_r11d, // Low 32 bits or r11
- gpr_r12d, // Low 32 bits or r12
- gpr_r13d, // Low 32 bits or r13
- gpr_r14d, // Low 32 bits or r14
- gpr_r15d, // Low 32 bits or r15
- gpr_ax ,
- gpr_bx ,
- gpr_cx ,
- gpr_dx ,
- gpr_di ,
- gpr_si ,
- gpr_bp ,
- gpr_sp ,
- gpr_r8w, // Low 16 bits or r8
- gpr_r9w, // Low 16 bits or r9
- gpr_r10w, // Low 16 bits or r10
- gpr_r11w, // Low 16 bits or r11
- gpr_r12w, // Low 16 bits or r12
- gpr_r13w, // Low 16 bits or r13
- gpr_r14w, // Low 16 bits or r14
- gpr_r15w, // Low 16 bits or r15
- gpr_ah ,
- gpr_bh ,
- gpr_ch ,
- gpr_dh ,
- gpr_al ,
- gpr_bl ,
- gpr_cl ,
- gpr_dl ,
- gpr_dil,
- gpr_sil,
- gpr_bpl,
- gpr_spl,
- gpr_r8l, // Low 8 bits or r8
- gpr_r9l, // Low 8 bits or r9
- gpr_r10l, // Low 8 bits or r10
- gpr_r11l, // Low 8 bits or r11
- gpr_r12l, // Low 8 bits or r12
- gpr_r13l, // Low 8 bits or r13
- gpr_r14l, // Low 8 bits or r14
- gpr_r15l, // Low 8 bits or r15
- k_num_gpr_regs
+enum {
+ gpr_rax = 0,
+ gpr_rbx,
+ gpr_rcx,
+ gpr_rdx,
+ gpr_rdi,
+ gpr_rsi,
+ gpr_rbp,
+ gpr_rsp,
+ gpr_r8,
+ gpr_r9,
+ gpr_r10,
+ gpr_r11,
+ gpr_r12,
+ gpr_r13,
+ gpr_r14,
+ gpr_r15,
+ gpr_rip,
+ gpr_rflags,
+ gpr_cs,
+ gpr_fs,
+ gpr_gs,
+ gpr_eax,
+ gpr_ebx,
+ gpr_ecx,
+ gpr_edx,
+ gpr_edi,
+ gpr_esi,
+ gpr_ebp,
+ gpr_esp,
+ gpr_r8d, // Low 32 bits or r8
+ gpr_r9d, // Low 32 bits or r9
+ gpr_r10d, // Low 32 bits or r10
+ gpr_r11d, // Low 32 bits or r11
+ gpr_r12d, // Low 32 bits or r12
+ gpr_r13d, // Low 32 bits or r13
+ gpr_r14d, // Low 32 bits or r14
+ gpr_r15d, // Low 32 bits or r15
+ gpr_ax,
+ gpr_bx,
+ gpr_cx,
+ gpr_dx,
+ gpr_di,
+ gpr_si,
+ gpr_bp,
+ gpr_sp,
+ gpr_r8w, // Low 16 bits or r8
+ gpr_r9w, // Low 16 bits or r9
+ gpr_r10w, // Low 16 bits or r10
+ gpr_r11w, // Low 16 bits or r11
+ gpr_r12w, // Low 16 bits or r12
+ gpr_r13w, // Low 16 bits or r13
+ gpr_r14w, // Low 16 bits or r14
+ gpr_r15w, // Low 16 bits or r15
+ gpr_ah,
+ gpr_bh,
+ gpr_ch,
+ gpr_dh,
+ gpr_al,
+ gpr_bl,
+ gpr_cl,
+ gpr_dl,
+ gpr_dil,
+ gpr_sil,
+ gpr_bpl,
+ gpr_spl,
+ gpr_r8l, // Low 8 bits or r8
+ gpr_r9l, // Low 8 bits or r9
+ gpr_r10l, // Low 8 bits or r10
+ gpr_r11l, // Low 8 bits or r11
+ gpr_r12l, // Low 8 bits or r12
+ gpr_r13l, // Low 8 bits or r13
+ gpr_r14l, // Low 8 bits or r14
+ gpr_r15l, // Low 8 bits or r15
+ k_num_gpr_regs
};
enum {
- fpu_fcw,
- fpu_fsw,
- fpu_ftw,
- fpu_fop,
- fpu_ip,
- fpu_cs,
- fpu_dp,
- fpu_ds,
- fpu_mxcsr,
- fpu_mxcsrmask,
- fpu_stmm0,
- fpu_stmm1,
- fpu_stmm2,
- fpu_stmm3,
- fpu_stmm4,
- fpu_stmm5,
- fpu_stmm6,
- fpu_stmm7,
- fpu_xmm0,
- fpu_xmm1,
- fpu_xmm2,
- fpu_xmm3,
- fpu_xmm4,
- fpu_xmm5,
- fpu_xmm6,
- fpu_xmm7,
- fpu_xmm8,
- fpu_xmm9,
- fpu_xmm10,
- fpu_xmm11,
- fpu_xmm12,
- fpu_xmm13,
- fpu_xmm14,
- fpu_xmm15,
- fpu_ymm0,
- fpu_ymm1,
- fpu_ymm2,
- fpu_ymm3,
- fpu_ymm4,
- fpu_ymm5,
- fpu_ymm6,
- fpu_ymm7,
- fpu_ymm8,
- fpu_ymm9,
- fpu_ymm10,
- fpu_ymm11,
- fpu_ymm12,
- fpu_ymm13,
- fpu_ymm14,
- fpu_ymm15,
- k_num_fpu_regs,
-
- // Aliases
- fpu_fctrl = fpu_fcw,
- fpu_fstat = fpu_fsw,
- fpu_ftag = fpu_ftw,
- fpu_fiseg = fpu_cs,
- fpu_fioff = fpu_ip,
- fpu_foseg = fpu_ds,
- fpu_fooff = fpu_dp
+ fpu_fcw,
+ fpu_fsw,
+ fpu_ftw,
+ fpu_fop,
+ fpu_ip,
+ fpu_cs,
+ fpu_dp,
+ fpu_ds,
+ fpu_mxcsr,
+ fpu_mxcsrmask,
+ fpu_stmm0,
+ fpu_stmm1,
+ fpu_stmm2,
+ fpu_stmm3,
+ fpu_stmm4,
+ fpu_stmm5,
+ fpu_stmm6,
+ fpu_stmm7,
+ fpu_xmm0,
+ fpu_xmm1,
+ fpu_xmm2,
+ fpu_xmm3,
+ fpu_xmm4,
+ fpu_xmm5,
+ fpu_xmm6,
+ fpu_xmm7,
+ fpu_xmm8,
+ fpu_xmm9,
+ fpu_xmm10,
+ fpu_xmm11,
+ fpu_xmm12,
+ fpu_xmm13,
+ fpu_xmm14,
+ fpu_xmm15,
+ fpu_ymm0,
+ fpu_ymm1,
+ fpu_ymm2,
+ fpu_ymm3,
+ fpu_ymm4,
+ fpu_ymm5,
+ fpu_ymm6,
+ fpu_ymm7,
+ fpu_ymm8,
+ fpu_ymm9,
+ fpu_ymm10,
+ fpu_ymm11,
+ fpu_ymm12,
+ fpu_ymm13,
+ fpu_ymm14,
+ fpu_ymm15,
+ k_num_fpu_regs,
+
+ // Aliases
+ fpu_fctrl = fpu_fcw,
+ fpu_fstat = fpu_fsw,
+ fpu_ftag = fpu_ftw,
+ fpu_fiseg = fpu_cs,
+ fpu_fioff = fpu_ip,
+ fpu_foseg = fpu_ds,
+ fpu_fooff = fpu_dp
};
enum {
- exc_trapno,
- exc_err,
- exc_faultvaddr,
- k_num_exc_regs,
+ exc_trapno,
+ exc_err,
+ exc_faultvaddr,
+ k_num_exc_regs,
};
-
-enum ehframe_dwarf_regnums
-{
- ehframe_dwarf_rax = 0,
- ehframe_dwarf_rdx = 1,
- ehframe_dwarf_rcx = 2,
- ehframe_dwarf_rbx = 3,
- ehframe_dwarf_rsi = 4,
- ehframe_dwarf_rdi = 5,
- ehframe_dwarf_rbp = 6,
- ehframe_dwarf_rsp = 7,
- ehframe_dwarf_r8,
- ehframe_dwarf_r9,
- ehframe_dwarf_r10,
- ehframe_dwarf_r11,
- ehframe_dwarf_r12,
- ehframe_dwarf_r13,
- ehframe_dwarf_r14,
- ehframe_dwarf_r15,
- ehframe_dwarf_rip,
- ehframe_dwarf_xmm0,
- ehframe_dwarf_xmm1,
- ehframe_dwarf_xmm2,
- ehframe_dwarf_xmm3,
- ehframe_dwarf_xmm4,
- ehframe_dwarf_xmm5,
- ehframe_dwarf_xmm6,
- ehframe_dwarf_xmm7,
- ehframe_dwarf_xmm8,
- ehframe_dwarf_xmm9,
- ehframe_dwarf_xmm10,
- ehframe_dwarf_xmm11,
- ehframe_dwarf_xmm12,
- ehframe_dwarf_xmm13,
- ehframe_dwarf_xmm14,
- ehframe_dwarf_xmm15,
- ehframe_dwarf_stmm0,
- ehframe_dwarf_stmm1,
- ehframe_dwarf_stmm2,
- ehframe_dwarf_stmm3,
- ehframe_dwarf_stmm4,
- ehframe_dwarf_stmm5,
- ehframe_dwarf_stmm6,
- ehframe_dwarf_stmm7,
- ehframe_dwarf_ymm0 = ehframe_dwarf_xmm0,
- ehframe_dwarf_ymm1 = ehframe_dwarf_xmm1,
- ehframe_dwarf_ymm2 = ehframe_dwarf_xmm2,
- ehframe_dwarf_ymm3 = ehframe_dwarf_xmm3,
- ehframe_dwarf_ymm4 = ehframe_dwarf_xmm4,
- ehframe_dwarf_ymm5 = ehframe_dwarf_xmm5,
- ehframe_dwarf_ymm6 = ehframe_dwarf_xmm6,
- ehframe_dwarf_ymm7 = ehframe_dwarf_xmm7,
- ehframe_dwarf_ymm8 = ehframe_dwarf_xmm8,
- ehframe_dwarf_ymm9 = ehframe_dwarf_xmm9,
- ehframe_dwarf_ymm10 = ehframe_dwarf_xmm10,
- ehframe_dwarf_ymm11 = ehframe_dwarf_xmm11,
- ehframe_dwarf_ymm12 = ehframe_dwarf_xmm12,
- ehframe_dwarf_ymm13 = ehframe_dwarf_xmm13,
- ehframe_dwarf_ymm14 = ehframe_dwarf_xmm14,
- ehframe_dwarf_ymm15 = ehframe_dwarf_xmm15
+enum ehframe_dwarf_regnums {
+ ehframe_dwarf_rax = 0,
+ ehframe_dwarf_rdx = 1,
+ ehframe_dwarf_rcx = 2,
+ ehframe_dwarf_rbx = 3,
+ ehframe_dwarf_rsi = 4,
+ ehframe_dwarf_rdi = 5,
+ ehframe_dwarf_rbp = 6,
+ ehframe_dwarf_rsp = 7,
+ ehframe_dwarf_r8,
+ ehframe_dwarf_r9,
+ ehframe_dwarf_r10,
+ ehframe_dwarf_r11,
+ ehframe_dwarf_r12,
+ ehframe_dwarf_r13,
+ ehframe_dwarf_r14,
+ ehframe_dwarf_r15,
+ ehframe_dwarf_rip,
+ ehframe_dwarf_xmm0,
+ ehframe_dwarf_xmm1,
+ ehframe_dwarf_xmm2,
+ ehframe_dwarf_xmm3,
+ ehframe_dwarf_xmm4,
+ ehframe_dwarf_xmm5,
+ ehframe_dwarf_xmm6,
+ ehframe_dwarf_xmm7,
+ ehframe_dwarf_xmm8,
+ ehframe_dwarf_xmm9,
+ ehframe_dwarf_xmm10,
+ ehframe_dwarf_xmm11,
+ ehframe_dwarf_xmm12,
+ ehframe_dwarf_xmm13,
+ ehframe_dwarf_xmm14,
+ ehframe_dwarf_xmm15,
+ ehframe_dwarf_stmm0,
+ ehframe_dwarf_stmm1,
+ ehframe_dwarf_stmm2,
+ ehframe_dwarf_stmm3,
+ ehframe_dwarf_stmm4,
+ ehframe_dwarf_stmm5,
+ ehframe_dwarf_stmm6,
+ ehframe_dwarf_stmm7,
+ ehframe_dwarf_ymm0 = ehframe_dwarf_xmm0,
+ ehframe_dwarf_ymm1 = ehframe_dwarf_xmm1,
+ ehframe_dwarf_ymm2 = ehframe_dwarf_xmm2,
+ ehframe_dwarf_ymm3 = ehframe_dwarf_xmm3,
+ ehframe_dwarf_ymm4 = ehframe_dwarf_xmm4,
+ ehframe_dwarf_ymm5 = ehframe_dwarf_xmm5,
+ ehframe_dwarf_ymm6 = ehframe_dwarf_xmm6,
+ ehframe_dwarf_ymm7 = ehframe_dwarf_xmm7,
+ ehframe_dwarf_ymm8 = ehframe_dwarf_xmm8,
+ ehframe_dwarf_ymm9 = ehframe_dwarf_xmm9,
+ ehframe_dwarf_ymm10 = ehframe_dwarf_xmm10,
+ ehframe_dwarf_ymm11 = ehframe_dwarf_xmm11,
+ ehframe_dwarf_ymm12 = ehframe_dwarf_xmm12,
+ ehframe_dwarf_ymm13 = ehframe_dwarf_xmm13,
+ ehframe_dwarf_ymm14 = ehframe_dwarf_xmm14,
+ ehframe_dwarf_ymm15 = ehframe_dwarf_xmm15
};
-enum debugserver_regnums
-{
- debugserver_rax = 0,
- debugserver_rbx = 1,
- debugserver_rcx = 2,
- debugserver_rdx = 3,
- debugserver_rsi = 4,
- debugserver_rdi = 5,
- debugserver_rbp = 6,
- debugserver_rsp = 7,
- debugserver_r8 = 8,
- debugserver_r9 = 9,
- debugserver_r10 = 10,
- debugserver_r11 = 11,
- debugserver_r12 = 12,
- debugserver_r13 = 13,
- debugserver_r14 = 14,
- debugserver_r15 = 15,
- debugserver_rip = 16,
- debugserver_rflags = 17,
- debugserver_cs = 18,
- debugserver_ss = 19,
- debugserver_ds = 20,
- debugserver_es = 21,
- debugserver_fs = 22,
- debugserver_gs = 23,
- debugserver_stmm0 = 24,
- debugserver_stmm1 = 25,
- debugserver_stmm2 = 26,
- debugserver_stmm3 = 27,
- debugserver_stmm4 = 28,
- debugserver_stmm5 = 29,
- debugserver_stmm6 = 30,
- debugserver_stmm7 = 31,
- debugserver_fctrl = 32, debugserver_fcw = debugserver_fctrl,
- debugserver_fstat = 33, debugserver_fsw = debugserver_fstat,
- debugserver_ftag = 34, debugserver_ftw = debugserver_ftag,
- debugserver_fiseg = 35, debugserver_fpu_cs = debugserver_fiseg,
- debugserver_fioff = 36, debugserver_ip = debugserver_fioff,
- debugserver_foseg = 37, debugserver_fpu_ds = debugserver_foseg,
- debugserver_fooff = 38, debugserver_dp = debugserver_fooff,
- debugserver_fop = 39,
- debugserver_xmm0 = 40,
- debugserver_xmm1 = 41,
- debugserver_xmm2 = 42,
- debugserver_xmm3 = 43,
- debugserver_xmm4 = 44,
- debugserver_xmm5 = 45,
- debugserver_xmm6 = 46,
- debugserver_xmm7 = 47,
- debugserver_xmm8 = 48,
- debugserver_xmm9 = 49,
- debugserver_xmm10 = 50,
- debugserver_xmm11 = 51,
- debugserver_xmm12 = 52,
- debugserver_xmm13 = 53,
- debugserver_xmm14 = 54,
- debugserver_xmm15 = 55,
- debugserver_mxcsr = 56,
- debugserver_ymm0 = debugserver_xmm0,
- debugserver_ymm1 = debugserver_xmm1,
- debugserver_ymm2 = debugserver_xmm2,
- debugserver_ymm3 = debugserver_xmm3,
- debugserver_ymm4 = debugserver_xmm4,
- debugserver_ymm5 = debugserver_xmm5,
- debugserver_ymm6 = debugserver_xmm6,
- debugserver_ymm7 = debugserver_xmm7,
- debugserver_ymm8 = debugserver_xmm8,
- debugserver_ymm9 = debugserver_xmm9,
- debugserver_ymm10 = debugserver_xmm10,
- debugserver_ymm11 = debugserver_xmm11,
- debugserver_ymm12 = debugserver_xmm12,
- debugserver_ymm13 = debugserver_xmm13,
- debugserver_ymm14 = debugserver_xmm14,
- debugserver_ymm15 = debugserver_xmm15
+enum debugserver_regnums {
+ debugserver_rax = 0,
+ debugserver_rbx = 1,
+ debugserver_rcx = 2,
+ debugserver_rdx = 3,
+ debugserver_rsi = 4,
+ debugserver_rdi = 5,
+ debugserver_rbp = 6,
+ debugserver_rsp = 7,
+ debugserver_r8 = 8,
+ debugserver_r9 = 9,
+ debugserver_r10 = 10,
+ debugserver_r11 = 11,
+ debugserver_r12 = 12,
+ debugserver_r13 = 13,
+ debugserver_r14 = 14,
+ debugserver_r15 = 15,
+ debugserver_rip = 16,
+ debugserver_rflags = 17,
+ debugserver_cs = 18,
+ debugserver_ss = 19,
+ debugserver_ds = 20,
+ debugserver_es = 21,
+ debugserver_fs = 22,
+ debugserver_gs = 23,
+ debugserver_stmm0 = 24,
+ debugserver_stmm1 = 25,
+ debugserver_stmm2 = 26,
+ debugserver_stmm3 = 27,
+ debugserver_stmm4 = 28,
+ debugserver_stmm5 = 29,
+ debugserver_stmm6 = 30,
+ debugserver_stmm7 = 31,
+ debugserver_fctrl = 32,
+ debugserver_fcw = debugserver_fctrl,
+ debugserver_fstat = 33,
+ debugserver_fsw = debugserver_fstat,
+ debugserver_ftag = 34,
+ debugserver_ftw = debugserver_ftag,
+ debugserver_fiseg = 35,
+ debugserver_fpu_cs = debugserver_fiseg,
+ debugserver_fioff = 36,
+ debugserver_ip = debugserver_fioff,
+ debugserver_foseg = 37,
+ debugserver_fpu_ds = debugserver_foseg,
+ debugserver_fooff = 38,
+ debugserver_dp = debugserver_fooff,
+ debugserver_fop = 39,
+ debugserver_xmm0 = 40,
+ debugserver_xmm1 = 41,
+ debugserver_xmm2 = 42,
+ debugserver_xmm3 = 43,
+ debugserver_xmm4 = 44,
+ debugserver_xmm5 = 45,
+ debugserver_xmm6 = 46,
+ debugserver_xmm7 = 47,
+ debugserver_xmm8 = 48,
+ debugserver_xmm9 = 49,
+ debugserver_xmm10 = 50,
+ debugserver_xmm11 = 51,
+ debugserver_xmm12 = 52,
+ debugserver_xmm13 = 53,
+ debugserver_xmm14 = 54,
+ debugserver_xmm15 = 55,
+ debugserver_mxcsr = 56,
+ debugserver_ymm0 = debugserver_xmm0,
+ debugserver_ymm1 = debugserver_xmm1,
+ debugserver_ymm2 = debugserver_xmm2,
+ debugserver_ymm3 = debugserver_xmm3,
+ debugserver_ymm4 = debugserver_xmm4,
+ debugserver_ymm5 = debugserver_xmm5,
+ debugserver_ymm6 = debugserver_xmm6,
+ debugserver_ymm7 = debugserver_xmm7,
+ debugserver_ymm8 = debugserver_xmm8,
+ debugserver_ymm9 = debugserver_xmm9,
+ debugserver_ymm10 = debugserver_xmm10,
+ debugserver_ymm11 = debugserver_xmm11,
+ debugserver_ymm12 = debugserver_xmm12,
+ debugserver_ymm13 = debugserver_xmm13,
+ debugserver_ymm14 = debugserver_xmm14,
+ debugserver_ymm15 = debugserver_xmm15
};
-#define GPR_OFFSET(reg) (offsetof (DNBArchImplX86_64::GPR, __##reg))
-#define FPU_OFFSET(reg) (offsetof (DNBArchImplX86_64::FPU, __fpu_##reg) + offsetof (DNBArchImplX86_64::Context, fpu.no_avx))
-#define AVX_OFFSET(reg) (offsetof (DNBArchImplX86_64::AVX, __fpu_##reg) + offsetof (DNBArchImplX86_64::Context, fpu.avx))
-#define EXC_OFFSET(reg) (offsetof (DNBArchImplX86_64::EXC, __##reg) + offsetof (DNBArchImplX86_64::Context, exc))
-#define AVX_OFFSET_YMM(n) (AVX_OFFSET(ymmh0) + (32 * n))
-
-#define GPR_SIZE(reg) (sizeof(((DNBArchImplX86_64::GPR *)NULL)->__##reg))
-#define FPU_SIZE_UINT(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg))
-#define FPU_SIZE_MMST(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__mmst_reg))
-#define FPU_SIZE_XMM(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__xmm_reg))
-#define FPU_SIZE_YMM(reg) (32)
-#define EXC_SIZE(reg) (sizeof(((DNBArchImplX86_64::EXC *)NULL)->__##reg))
+#define GPR_OFFSET(reg) (offsetof(DNBArchImplX86_64::GPR, __##reg))
+#define FPU_OFFSET(reg) \
+ (offsetof(DNBArchImplX86_64::FPU, __fpu_##reg) + \
+ offsetof(DNBArchImplX86_64::Context, fpu.no_avx))
+#define AVX_OFFSET(reg) \
+ (offsetof(DNBArchImplX86_64::AVX, __fpu_##reg) + \
+ offsetof(DNBArchImplX86_64::Context, fpu.avx))
+#define EXC_OFFSET(reg) \
+ (offsetof(DNBArchImplX86_64::EXC, __##reg) + \
+ offsetof(DNBArchImplX86_64::Context, exc))
+#define AVX_OFFSET_YMM(n) (AVX_OFFSET(ymmh0) + (32 * n))
+
+#define GPR_SIZE(reg) (sizeof(((DNBArchImplX86_64::GPR *)NULL)->__##reg))
+#define FPU_SIZE_UINT(reg) \
+ (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg))
+#define FPU_SIZE_MMST(reg) \
+ (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__mmst_reg))
+#define FPU_SIZE_XMM(reg) \
+ (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__xmm_reg))
+#define FPU_SIZE_YMM(reg) (32)
+#define EXC_SIZE(reg) (sizeof(((DNBArchImplX86_64::EXC *)NULL)->__##reg))
// These macros will auto define the register name, alt name, register size,
// register offset, encoding, format and native register. This ensures that
// the register state structures are defined correctly and have the correct
// sizes and offsets.
-#define DEFINE_GPR(reg) { e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, INVALID_NUB_REGNUM, debugserver_##reg, NULL, g_invalidate_##reg }
-#define DEFINE_GPR_ALT(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, debugserver_##reg, NULL, g_invalidate_##reg }
-#define DEFINE_GPR_ALT2(reg, alt) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_##reg, NULL, NULL }
-#define DEFINE_GPR_ALT3(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gen, debugserver_##reg, NULL, NULL }
-#define DEFINE_GPR_ALT4(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, debugserver_##reg, NULL, NULL }
-
-#define DEFINE_GPR_PSEUDO_32(reg32,reg64) { e_regSetGPR, gpr_##reg32, #reg32, NULL, Uint, Hex, 4, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 }
-#define DEFINE_GPR_PSEUDO_16(reg16,reg64) { e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 }
-#define DEFINE_GPR_PSEUDO_8H(reg8,reg64) { e_regSetGPR, gpr_##reg8 , #reg8 , NULL, Uint, Hex, 1, 1,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 }
-#define DEFINE_GPR_PSEUDO_8L(reg8,reg64) { e_regSetGPR, gpr_##reg8 , #reg8 , NULL, Uint, Hex, 1, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 }
+#define DEFINE_GPR(reg) \
+ { \
+ e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, GPR_SIZE(reg), \
+ GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, \
+ INVALID_NUB_REGNUM, debugserver_##reg, NULL, g_invalidate_##reg \
+ }
+#define DEFINE_GPR_ALT(reg, alt, gen) \
+ { \
+ e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \
+ GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, \
+ debugserver_##reg, NULL, g_invalidate_##reg \
+ }
+#define DEFINE_GPR_ALT2(reg, alt) \
+ { \
+ e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \
+ GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \
+ INVALID_NUB_REGNUM, debugserver_##reg, NULL, NULL \
+ }
+#define DEFINE_GPR_ALT3(reg, alt, gen) \
+ { \
+ e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \
+ GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gen, \
+ debugserver_##reg, NULL, NULL \
+ }
+#define DEFINE_GPR_ALT4(reg, alt, gen) \
+ { \
+ e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \
+ GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, \
+ debugserver_##reg, NULL, NULL \
+ }
+
+#define DEFINE_GPR_PSEUDO_32(reg32, reg64) \
+ { \
+ e_regSetGPR, gpr_##reg32, #reg32, NULL, Uint, Hex, 4, 0, \
+ INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \
+ INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 \
+ }
+#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \
+ { \
+ e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0, \
+ INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \
+ INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 \
+ }
+#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \
+ { \
+ e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 1, INVALID_NUB_REGNUM, \
+ INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \
+ g_contained_##reg64, g_invalidate_##reg64 \
+ }
+#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \
+ { \
+ e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 0, INVALID_NUB_REGNUM, \
+ INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \
+ g_contained_##reg64, g_invalidate_##reg64 \
+ }
// General purpose registers for 64 bit
-const char *g_contained_rax[] = { "rax", NULL };
-const char *g_contained_rbx[] = { "rbx", NULL };
-const char *g_contained_rcx[] = { "rcx", NULL };
-const char *g_contained_rdx[] = { "rdx", NULL };
-const char *g_contained_rdi[] = { "rdi", NULL };
-const char *g_contained_rsi[] = { "rsi", NULL };
-const char *g_contained_rbp[] = { "rbp", NULL };
-const char *g_contained_rsp[] = { "rsp", NULL };
-const char *g_contained_r8[] = { "r8", NULL };
-const char *g_contained_r9[] = { "r9", NULL };
-const char *g_contained_r10[] = { "r10", NULL };
-const char *g_contained_r11[] = { "r11", NULL };
-const char *g_contained_r12[] = { "r12", NULL };
-const char *g_contained_r13[] = { "r13", NULL };
-const char *g_contained_r14[] = { "r14", NULL };
-const char *g_contained_r15[] = { "r15", NULL };
-
-const char *g_invalidate_rax[] = { "rax", "eax", "ax", "ah", "al", NULL };
-const char *g_invalidate_rbx[] = { "rbx", "ebx", "bx", "bh", "bl", NULL };
-const char *g_invalidate_rcx[] = { "rcx", "ecx", "cx", "ch", "cl", NULL };
-const char *g_invalidate_rdx[] = { "rdx", "edx", "dx", "dh", "dl", NULL };
-const char *g_invalidate_rdi[] = { "rdi", "edi", "di", "dil", NULL };
-const char *g_invalidate_rsi[] = { "rsi", "esi", "si", "sil", NULL };
-const char *g_invalidate_rbp[] = { "rbp", "ebp", "bp", "bpl", NULL };
-const char *g_invalidate_rsp[] = { "rsp", "esp", "sp", "spl", NULL };
-const char *g_invalidate_r8 [] = { "r8", "r8d", "r8w", "r8l", NULL };
-const char *g_invalidate_r9 [] = { "r9", "r9d", "r9w", "r9l", NULL };
-const char *g_invalidate_r10[] = { "r10", "r10d", "r10w", "r10l", NULL };
-const char *g_invalidate_r11[] = { "r11", "r11d", "r11w", "r11l", NULL };
-const char *g_invalidate_r12[] = { "r12", "r12d", "r12w", "r12l", NULL };
-const char *g_invalidate_r13[] = { "r13", "r13d", "r13w", "r13l", NULL };
-const char *g_invalidate_r14[] = { "r14", "r14d", "r14w", "r14l", NULL };
-const char *g_invalidate_r15[] = { "r15", "r15d", "r15w", "r15l", NULL };
-
-const DNBRegisterInfo
-DNBArchImplX86_64::g_gpr_registers[] =
-{
- DEFINE_GPR (rax),
- DEFINE_GPR (rbx),
- DEFINE_GPR_ALT (rcx , "arg4", GENERIC_REGNUM_ARG4),
- DEFINE_GPR_ALT (rdx , "arg3", GENERIC_REGNUM_ARG3),
- DEFINE_GPR_ALT (rdi , "arg1", GENERIC_REGNUM_ARG1),
- DEFINE_GPR_ALT (rsi , "arg2", GENERIC_REGNUM_ARG2),
- DEFINE_GPR_ALT (rbp , "fp" , GENERIC_REGNUM_FP),
- DEFINE_GPR_ALT (rsp , "sp" , GENERIC_REGNUM_SP),
- DEFINE_GPR_ALT (r8 , "arg5", GENERIC_REGNUM_ARG5),
- DEFINE_GPR_ALT (r9 , "arg6", GENERIC_REGNUM_ARG6),
- DEFINE_GPR (r10),
- DEFINE_GPR (r11),
- DEFINE_GPR (r12),
- DEFINE_GPR (r13),
- DEFINE_GPR (r14),
- DEFINE_GPR (r15),
- DEFINE_GPR_ALT4 (rip , "pc", GENERIC_REGNUM_PC),
- DEFINE_GPR_ALT3 (rflags, "flags", GENERIC_REGNUM_FLAGS),
- DEFINE_GPR_ALT2 (cs, NULL),
- DEFINE_GPR_ALT2 (fs, NULL),
- DEFINE_GPR_ALT2 (gs, NULL),
- DEFINE_GPR_PSEUDO_32 (eax, rax),
- DEFINE_GPR_PSEUDO_32 (ebx, rbx),
- DEFINE_GPR_PSEUDO_32 (ecx, rcx),
- DEFINE_GPR_PSEUDO_32 (edx, rdx),
- DEFINE_GPR_PSEUDO_32 (edi, rdi),
- DEFINE_GPR_PSEUDO_32 (esi, rsi),
- DEFINE_GPR_PSEUDO_32 (ebp, rbp),
- DEFINE_GPR_PSEUDO_32 (esp, rsp),
- DEFINE_GPR_PSEUDO_32 (r8d, r8),
- DEFINE_GPR_PSEUDO_32 (r9d, r9),
- DEFINE_GPR_PSEUDO_32 (r10d, r10),
- DEFINE_GPR_PSEUDO_32 (r11d, r11),
- DEFINE_GPR_PSEUDO_32 (r12d, r12),
- DEFINE_GPR_PSEUDO_32 (r13d, r13),
- DEFINE_GPR_PSEUDO_32 (r14d, r14),
- DEFINE_GPR_PSEUDO_32 (r15d, r15),
- DEFINE_GPR_PSEUDO_16 (ax , rax),
- DEFINE_GPR_PSEUDO_16 (bx , rbx),
- DEFINE_GPR_PSEUDO_16 (cx , rcx),
- DEFINE_GPR_PSEUDO_16 (dx , rdx),
- DEFINE_GPR_PSEUDO_16 (di , rdi),
- DEFINE_GPR_PSEUDO_16 (si , rsi),
- DEFINE_GPR_PSEUDO_16 (bp , rbp),
- DEFINE_GPR_PSEUDO_16 (sp , rsp),
- DEFINE_GPR_PSEUDO_16 (r8w, r8),
- DEFINE_GPR_PSEUDO_16 (r9w, r9),
- DEFINE_GPR_PSEUDO_16 (r10w, r10),
- DEFINE_GPR_PSEUDO_16 (r11w, r11),
- DEFINE_GPR_PSEUDO_16 (r12w, r12),
- DEFINE_GPR_PSEUDO_16 (r13w, r13),
- DEFINE_GPR_PSEUDO_16 (r14w, r14),
- DEFINE_GPR_PSEUDO_16 (r15w, r15),
- DEFINE_GPR_PSEUDO_8H (ah , rax),
- DEFINE_GPR_PSEUDO_8H (bh , rbx),
- DEFINE_GPR_PSEUDO_8H (ch , rcx),
- DEFINE_GPR_PSEUDO_8H (dh , rdx),
- DEFINE_GPR_PSEUDO_8L (al , rax),
- DEFINE_GPR_PSEUDO_8L (bl , rbx),
- DEFINE_GPR_PSEUDO_8L (cl , rcx),
- DEFINE_GPR_PSEUDO_8L (dl , rdx),
- DEFINE_GPR_PSEUDO_8L (dil, rdi),
- DEFINE_GPR_PSEUDO_8L (sil, rsi),
- DEFINE_GPR_PSEUDO_8L (bpl, rbp),
- DEFINE_GPR_PSEUDO_8L (spl, rsp),
- DEFINE_GPR_PSEUDO_8L (r8l, r8),
- DEFINE_GPR_PSEUDO_8L (r9l, r9),
- DEFINE_GPR_PSEUDO_8L (r10l, r10),
- DEFINE_GPR_PSEUDO_8L (r11l, r11),
- DEFINE_GPR_PSEUDO_8L (r12l, r12),
- DEFINE_GPR_PSEUDO_8L (r13l, r13),
- DEFINE_GPR_PSEUDO_8L (r14l, r14),
- DEFINE_GPR_PSEUDO_8L (r15l, r15)
-};
+const char *g_contained_rax[] = {"rax", NULL};
+const char *g_contained_rbx[] = {"rbx", NULL};
+const char *g_contained_rcx[] = {"rcx", NULL};
+const char *g_contained_rdx[] = {"rdx", NULL};
+const char *g_contained_rdi[] = {"rdi", NULL};
+const char *g_contained_rsi[] = {"rsi", NULL};
+const char *g_contained_rbp[] = {"rbp", NULL};
+const char *g_contained_rsp[] = {"rsp", NULL};
+const char *g_contained_r8[] = {"r8", NULL};
+const char *g_contained_r9[] = {"r9", NULL};
+const char *g_contained_r10[] = {"r10", NULL};
+const char *g_contained_r11[] = {"r11", NULL};
+const char *g_contained_r12[] = {"r12", NULL};
+const char *g_contained_r13[] = {"r13", NULL};
+const char *g_contained_r14[] = {"r14", NULL};
+const char *g_contained_r15[] = {"r15", NULL};
+
+const char *g_invalidate_rax[] = {"rax", "eax", "ax", "ah", "al", NULL};
+const char *g_invalidate_rbx[] = {"rbx", "ebx", "bx", "bh", "bl", NULL};
+const char *g_invalidate_rcx[] = {"rcx", "ecx", "cx", "ch", "cl", NULL};
+const char *g_invalidate_rdx[] = {"rdx", "edx", "dx", "dh", "dl", NULL};
+const char *g_invalidate_rdi[] = {"rdi", "edi", "di", "dil", NULL};
+const char *g_invalidate_rsi[] = {"rsi", "esi", "si", "sil", NULL};
+const char *g_invalidate_rbp[] = {"rbp", "ebp", "bp", "bpl", NULL};
+const char *g_invalidate_rsp[] = {"rsp", "esp", "sp", "spl", NULL};
+const char *g_invalidate_r8[] = {"r8", "r8d", "r8w", "r8l", NULL};
+const char *g_invalidate_r9[] = {"r9", "r9d", "r9w", "r9l", NULL};
+const char *g_invalidate_r10[] = {"r10", "r10d", "r10w", "r10l", NULL};
+const char *g_invalidate_r11[] = {"r11", "r11d", "r11w", "r11l", NULL};
+const char *g_invalidate_r12[] = {"r12", "r12d", "r12w", "r12l", NULL};
+const char *g_invalidate_r13[] = {"r13", "r13d", "r13w", "r13l", NULL};
+const char *g_invalidate_r14[] = {"r14", "r14d", "r14w", "r14l", NULL};
+const char *g_invalidate_r15[] = {"r15", "r15d", "r15w", "r15l", NULL};
+
+const DNBRegisterInfo DNBArchImplX86_64::g_gpr_registers[] = {
+ DEFINE_GPR(rax),
+ DEFINE_GPR(rbx),
+ DEFINE_GPR_ALT(rcx, "arg4", GENERIC_REGNUM_ARG4),
+ DEFINE_GPR_ALT(rdx, "arg3", GENERIC_REGNUM_ARG3),
+ DEFINE_GPR_ALT(rdi, "arg1", GENERIC_REGNUM_ARG1),
+ DEFINE_GPR_ALT(rsi, "arg2", GENERIC_REGNUM_ARG2),
+ DEFINE_GPR_ALT(rbp, "fp", GENERIC_REGNUM_FP),
+ DEFINE_GPR_ALT(rsp, "sp", GENERIC_REGNUM_SP),
+ DEFINE_GPR_ALT(r8, "arg5", GENERIC_REGNUM_ARG5),
+ DEFINE_GPR_ALT(r9, "arg6", GENERIC_REGNUM_ARG6),
+ DEFINE_GPR(r10),
+ DEFINE_GPR(r11),
+ DEFINE_GPR(r12),
+ DEFINE_GPR(r13),
+ DEFINE_GPR(r14),
+ DEFINE_GPR(r15),
+ DEFINE_GPR_ALT4(rip, "pc", GENERIC_REGNUM_PC),
+ DEFINE_GPR_ALT3(rflags, "flags", GENERIC_REGNUM_FLAGS),
+ DEFINE_GPR_ALT2(cs, NULL),
+ DEFINE_GPR_ALT2(fs, NULL),
+ DEFINE_GPR_ALT2(gs, NULL),
+ DEFINE_GPR_PSEUDO_32(eax, rax),
+ DEFINE_GPR_PSEUDO_32(ebx, rbx),
+ DEFINE_GPR_PSEUDO_32(ecx, rcx),
+ DEFINE_GPR_PSEUDO_32(edx, rdx),
+ DEFINE_GPR_PSEUDO_32(edi, rdi),
+ DEFINE_GPR_PSEUDO_32(esi, rsi),
+ DEFINE_GPR_PSEUDO_32(ebp, rbp),
+ DEFINE_GPR_PSEUDO_32(esp, rsp),
+ DEFINE_GPR_PSEUDO_32(r8d, r8),
+ DEFINE_GPR_PSEUDO_32(r9d, r9),
+ DEFINE_GPR_PSEUDO_32(r10d, r10),
+ DEFINE_GPR_PSEUDO_32(r11d, r11),
+ DEFINE_GPR_PSEUDO_32(r12d, r12),
+ DEFINE_GPR_PSEUDO_32(r13d, r13),
+ DEFINE_GPR_PSEUDO_32(r14d, r14),
+ DEFINE_GPR_PSEUDO_32(r15d, r15),
+ DEFINE_GPR_PSEUDO_16(ax, rax),
+ DEFINE_GPR_PSEUDO_16(bx, rbx),
+ DEFINE_GPR_PSEUDO_16(cx, rcx),
+ DEFINE_GPR_PSEUDO_16(dx, rdx),
+ DEFINE_GPR_PSEUDO_16(di, rdi),
+ DEFINE_GPR_PSEUDO_16(si, rsi),
+ DEFINE_GPR_PSEUDO_16(bp, rbp),
+ DEFINE_GPR_PSEUDO_16(sp, rsp),
+ DEFINE_GPR_PSEUDO_16(r8w, r8),
+ DEFINE_GPR_PSEUDO_16(r9w, r9),
+ DEFINE_GPR_PSEUDO_16(r10w, r10),
+ DEFINE_GPR_PSEUDO_16(r11w, r11),
+ DEFINE_GPR_PSEUDO_16(r12w, r12),
+ DEFINE_GPR_PSEUDO_16(r13w, r13),
+ DEFINE_GPR_PSEUDO_16(r14w, r14),
+ DEFINE_GPR_PSEUDO_16(r15w, r15),
+ DEFINE_GPR_PSEUDO_8H(ah, rax),
+ DEFINE_GPR_PSEUDO_8H(bh, rbx),
+ DEFINE_GPR_PSEUDO_8H(ch, rcx),
+ DEFINE_GPR_PSEUDO_8H(dh, rdx),
+ DEFINE_GPR_PSEUDO_8L(al, rax),
+ DEFINE_GPR_PSEUDO_8L(bl, rbx),
+ DEFINE_GPR_PSEUDO_8L(cl, rcx),
+ DEFINE_GPR_PSEUDO_8L(dl, rdx),
+ DEFINE_GPR_PSEUDO_8L(dil, rdi),
+ DEFINE_GPR_PSEUDO_8L(sil, rsi),
+ DEFINE_GPR_PSEUDO_8L(bpl, rbp),
+ DEFINE_GPR_PSEUDO_8L(spl, rsp),
+ DEFINE_GPR_PSEUDO_8L(r8l, r8),
+ DEFINE_GPR_PSEUDO_8L(r9l, r9),
+ DEFINE_GPR_PSEUDO_8L(r10l, r10),
+ DEFINE_GPR_PSEUDO_8L(r11l, r11),
+ DEFINE_GPR_PSEUDO_8L(r12l, r12),
+ DEFINE_GPR_PSEUDO_8L(r13l, r13),
+ DEFINE_GPR_PSEUDO_8L(r14l, r14),
+ DEFINE_GPR_PSEUDO_8L(r15l, r15)};
// Floating point registers 64 bit
-const DNBRegisterInfo
-DNBArchImplX86_64::g_fpu_registers_no_avx[] =
-{
- { e_regSetFPU, fpu_fcw , "fctrl" , NULL, Uint, Hex, FPU_SIZE_UINT(fcw) , FPU_OFFSET(fcw) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_fsw , "fstat" , NULL, Uint, Hex, FPU_SIZE_UINT(fsw) , FPU_OFFSET(fsw) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_ftw , "ftag" , NULL, Uint, Hex, FPU_SIZE_UINT(ftw) , FPU_OFFSET(ftw) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_fop , "fop" , NULL, Uint, Hex, FPU_SIZE_UINT(fop) , FPU_OFFSET(fop) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_ip , "fioff" , NULL, Uint, Hex, FPU_SIZE_UINT(ip) , FPU_OFFSET(ip) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_cs , "fiseg" , NULL, Uint, Hex, FPU_SIZE_UINT(cs) , FPU_OFFSET(cs) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_dp , "fooff" , NULL, Uint, Hex, FPU_SIZE_UINT(dp) , FPU_OFFSET(dp) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_ds , "foseg" , NULL, Uint, Hex, FPU_SIZE_UINT(ds) , FPU_OFFSET(ds) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_mxcsr , "mxcsr" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr) , FPU_OFFSET(mxcsr) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , FPU_OFFSET(mxcsrmask) , -1U, -1U, -1U, -1U, NULL, NULL },
-
- { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), ehframe_dwarf_stmm0, ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL },
- { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), ehframe_dwarf_stmm1, ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL },
- { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), ehframe_dwarf_stmm2, ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL },
- { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), ehframe_dwarf_stmm3, ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL },
- { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), ehframe_dwarf_stmm4, ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL },
- { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), ehframe_dwarf_stmm5, ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL },
- { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), ehframe_dwarf_stmm6, ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL },
- { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), ehframe_dwarf_stmm7, ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL },
-
- { e_regSetFPU, fpu_xmm0 , "xmm0" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0) , FPU_OFFSET(xmm0) , ehframe_dwarf_xmm0 , ehframe_dwarf_xmm0 , -1U, debugserver_xmm0 , NULL, NULL },
- { e_regSetFPU, fpu_xmm1 , "xmm1" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1) , FPU_OFFSET(xmm1) , ehframe_dwarf_xmm1 , ehframe_dwarf_xmm1 , -1U, debugserver_xmm1 , NULL, NULL },
- { e_regSetFPU, fpu_xmm2 , "xmm2" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2) , FPU_OFFSET(xmm2) , ehframe_dwarf_xmm2 , ehframe_dwarf_xmm2 , -1U, debugserver_xmm2 , NULL, NULL },
- { e_regSetFPU, fpu_xmm3 , "xmm3" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3) , FPU_OFFSET(xmm3) , ehframe_dwarf_xmm3 , ehframe_dwarf_xmm3 , -1U, debugserver_xmm3 , NULL, NULL },
- { e_regSetFPU, fpu_xmm4 , "xmm4" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4) , FPU_OFFSET(xmm4) , ehframe_dwarf_xmm4 , ehframe_dwarf_xmm4 , -1U, debugserver_xmm4 , NULL, NULL },
- { e_regSetFPU, fpu_xmm5 , "xmm5" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5) , FPU_OFFSET(xmm5) , ehframe_dwarf_xmm5 , ehframe_dwarf_xmm5 , -1U, debugserver_xmm5 , NULL, NULL },
- { e_regSetFPU, fpu_xmm6 , "xmm6" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6) , FPU_OFFSET(xmm6) , ehframe_dwarf_xmm6 , ehframe_dwarf_xmm6 , -1U, debugserver_xmm6 , NULL, NULL },
- { e_regSetFPU, fpu_xmm7 , "xmm7" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7) , FPU_OFFSET(xmm7) , ehframe_dwarf_xmm7 , ehframe_dwarf_xmm7 , -1U, debugserver_xmm7 , NULL, NULL },
- { e_regSetFPU, fpu_xmm8 , "xmm8" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm8) , FPU_OFFSET(xmm8) , ehframe_dwarf_xmm8 , ehframe_dwarf_xmm8 , -1U, debugserver_xmm8 , NULL, NULL },
- { e_regSetFPU, fpu_xmm9 , "xmm9" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm9) , FPU_OFFSET(xmm9) , ehframe_dwarf_xmm9 , ehframe_dwarf_xmm9 , -1U, debugserver_xmm9 , NULL, NULL },
- { e_regSetFPU, fpu_xmm10, "xmm10" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm10) , FPU_OFFSET(xmm10), ehframe_dwarf_xmm10, ehframe_dwarf_xmm10, -1U, debugserver_xmm10, NULL, NULL },
- { e_regSetFPU, fpu_xmm11, "xmm11" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm11) , FPU_OFFSET(xmm11), ehframe_dwarf_xmm11, ehframe_dwarf_xmm11, -1U, debugserver_xmm11, NULL, NULL },
- { e_regSetFPU, fpu_xmm12, "xmm12" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm12) , FPU_OFFSET(xmm12), ehframe_dwarf_xmm12, ehframe_dwarf_xmm12, -1U, debugserver_xmm12, NULL, NULL },
- { e_regSetFPU, fpu_xmm13, "xmm13" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm13) , FPU_OFFSET(xmm13), ehframe_dwarf_xmm13, ehframe_dwarf_xmm13, -1U, debugserver_xmm13, NULL, NULL },
- { e_regSetFPU, fpu_xmm14, "xmm14" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm14) , FPU_OFFSET(xmm14), ehframe_dwarf_xmm14, ehframe_dwarf_xmm14, -1U, debugserver_xmm14, NULL, NULL },
- { e_regSetFPU, fpu_xmm15, "xmm15" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm15) , FPU_OFFSET(xmm15), ehframe_dwarf_xmm15, ehframe_dwarf_xmm15, -1U, debugserver_xmm15, NULL, NULL },
+const DNBRegisterInfo DNBArchImplX86_64::g_fpu_registers_no_avx[] = {
+ {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw),
+ FPU_OFFSET(fcw), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw),
+ FPU_OFFSET(fsw), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, FPU_SIZE_UINT(ftw),
+ FPU_OFFSET(ftw), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop),
+ FPU_OFFSET(fop), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip),
+ FPU_OFFSET(ip), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs),
+ FPU_OFFSET(cs), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp),
+ FPU_OFFSET(dp), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds),
+ FPU_OFFSET(ds), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr),
+ FPU_OFFSET(mxcsr), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex,
+ FPU_SIZE_UINT(mxcsrmask), FPU_OFFSET(mxcsrmask), -1U, -1U, -1U, -1U, NULL,
+ NULL},
+
+ {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), ehframe_dwarf_stmm0,
+ ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL},
+ {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), ehframe_dwarf_stmm1,
+ ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL},
+ {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), ehframe_dwarf_stmm2,
+ ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL},
+ {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), ehframe_dwarf_stmm3,
+ ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL},
+ {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), ehframe_dwarf_stmm4,
+ ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL},
+ {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), ehframe_dwarf_stmm5,
+ ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL},
+ {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), ehframe_dwarf_stmm6,
+ ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL},
+ {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), ehframe_dwarf_stmm7,
+ ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL},
+
+ {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), ehframe_dwarf_xmm0,
+ ehframe_dwarf_xmm0, -1U, debugserver_xmm0, NULL, NULL},
+ {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), ehframe_dwarf_xmm1,
+ ehframe_dwarf_xmm1, -1U, debugserver_xmm1, NULL, NULL},
+ {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), ehframe_dwarf_xmm2,
+ ehframe_dwarf_xmm2, -1U, debugserver_xmm2, NULL, NULL},
+ {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), ehframe_dwarf_xmm3,
+ ehframe_dwarf_xmm3, -1U, debugserver_xmm3, NULL, NULL},
+ {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), ehframe_dwarf_xmm4,
+ ehframe_dwarf_xmm4, -1U, debugserver_xmm4, NULL, NULL},
+ {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), ehframe_dwarf_xmm5,
+ ehframe_dwarf_xmm5, -1U, debugserver_xmm5, NULL, NULL},
+ {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), ehframe_dwarf_xmm6,
+ ehframe_dwarf_xmm6, -1U, debugserver_xmm6, NULL, NULL},
+ {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), ehframe_dwarf_xmm7,
+ ehframe_dwarf_xmm7, -1U, debugserver_xmm7, NULL, NULL},
+ {e_regSetFPU, fpu_xmm8, "xmm8", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm8), FPU_OFFSET(xmm8), ehframe_dwarf_xmm8,
+ ehframe_dwarf_xmm8, -1U, debugserver_xmm8, NULL, NULL},
+ {e_regSetFPU, fpu_xmm9, "xmm9", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm9), FPU_OFFSET(xmm9), ehframe_dwarf_xmm9,
+ ehframe_dwarf_xmm9, -1U, debugserver_xmm9, NULL, NULL},
+ {e_regSetFPU, fpu_xmm10, "xmm10", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm10), FPU_OFFSET(xmm10), ehframe_dwarf_xmm10,
+ ehframe_dwarf_xmm10, -1U, debugserver_xmm10, NULL, NULL},
+ {e_regSetFPU, fpu_xmm11, "xmm11", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm11), FPU_OFFSET(xmm11), ehframe_dwarf_xmm11,
+ ehframe_dwarf_xmm11, -1U, debugserver_xmm11, NULL, NULL},
+ {e_regSetFPU, fpu_xmm12, "xmm12", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm12), FPU_OFFSET(xmm12), ehframe_dwarf_xmm12,
+ ehframe_dwarf_xmm12, -1U, debugserver_xmm12, NULL, NULL},
+ {e_regSetFPU, fpu_xmm13, "xmm13", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm13), FPU_OFFSET(xmm13), ehframe_dwarf_xmm13,
+ ehframe_dwarf_xmm13, -1U, debugserver_xmm13, NULL, NULL},
+ {e_regSetFPU, fpu_xmm14, "xmm14", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm14), FPU_OFFSET(xmm14), ehframe_dwarf_xmm14,
+ ehframe_dwarf_xmm14, -1U, debugserver_xmm14, NULL, NULL},
+ {e_regSetFPU, fpu_xmm15, "xmm15", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm15), FPU_OFFSET(xmm15), ehframe_dwarf_xmm15,
+ ehframe_dwarf_xmm15, -1U, debugserver_xmm15, NULL, NULL},
};
-static const char *g_contained_ymm0 [] = { "ymm0", NULL };
-static const char *g_contained_ymm1 [] = { "ymm1", NULL };
-static const char *g_contained_ymm2 [] = { "ymm2", NULL };
-static const char *g_contained_ymm3 [] = { "ymm3", NULL };
-static const char *g_contained_ymm4 [] = { "ymm4", NULL };
-static const char *g_contained_ymm5 [] = { "ymm5", NULL };
-static const char *g_contained_ymm6 [] = { "ymm6", NULL };
-static const char *g_contained_ymm7 [] = { "ymm7", NULL };
-static const char *g_contained_ymm8 [] = { "ymm8", NULL };
-static const char *g_contained_ymm9 [] = { "ymm9", NULL };
-static const char *g_contained_ymm10[] = { "ymm10", NULL };
-static const char *g_contained_ymm11[] = { "ymm11", NULL };
-static const char *g_contained_ymm12[] = { "ymm12", NULL };
-static const char *g_contained_ymm13[] = { "ymm13", NULL };
-static const char *g_contained_ymm14[] = { "ymm14", NULL };
-static const char *g_contained_ymm15[] = { "ymm15", NULL };
-
-const DNBRegisterInfo
-DNBArchImplX86_64::g_fpu_registers_avx[] =
-{
- { e_regSetFPU, fpu_fcw , "fctrl" , NULL, Uint, Hex, FPU_SIZE_UINT(fcw) , AVX_OFFSET(fcw) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_fsw , "fstat" , NULL, Uint, Hex, FPU_SIZE_UINT(fsw) , AVX_OFFSET(fsw) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_ftw , "ftag" , NULL, Uint, Hex, FPU_SIZE_UINT(ftw) , AVX_OFFSET(ftw) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_fop , "fop" , NULL, Uint, Hex, FPU_SIZE_UINT(fop) , AVX_OFFSET(fop) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_ip , "fioff" , NULL, Uint, Hex, FPU_SIZE_UINT(ip) , AVX_OFFSET(ip) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_cs , "fiseg" , NULL, Uint, Hex, FPU_SIZE_UINT(cs) , AVX_OFFSET(cs) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_dp , "fooff" , NULL, Uint, Hex, FPU_SIZE_UINT(dp) , AVX_OFFSET(dp) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_ds , "foseg" , NULL, Uint, Hex, FPU_SIZE_UINT(ds) , AVX_OFFSET(ds) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_mxcsr , "mxcsr" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr) , AVX_OFFSET(mxcsr) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , AVX_OFFSET(mxcsrmask) , -1U, -1U, -1U, -1U, NULL, NULL },
-
- { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), ehframe_dwarf_stmm0, ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL },
- { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), ehframe_dwarf_stmm1, ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL },
- { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), ehframe_dwarf_stmm2, ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL },
- { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), ehframe_dwarf_stmm3, ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL },
- { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), ehframe_dwarf_stmm4, ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL },
- { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), ehframe_dwarf_stmm5, ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL },
- { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), ehframe_dwarf_stmm6, ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL },
- { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), ehframe_dwarf_stmm7, ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL },
-
- { e_regSetFPU, fpu_ymm0 , "ymm0" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm0) , AVX_OFFSET_YMM(0) , ehframe_dwarf_ymm0 , ehframe_dwarf_ymm0 , -1U, debugserver_ymm0, NULL, NULL },
- { e_regSetFPU, fpu_ymm1 , "ymm1" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm1) , AVX_OFFSET_YMM(1) , ehframe_dwarf_ymm1 , ehframe_dwarf_ymm1 , -1U, debugserver_ymm1, NULL, NULL },
- { e_regSetFPU, fpu_ymm2 , "ymm2" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm2) , AVX_OFFSET_YMM(2) , ehframe_dwarf_ymm2 , ehframe_dwarf_ymm2 , -1U, debugserver_ymm2, NULL, NULL },
- { e_regSetFPU, fpu_ymm3 , "ymm3" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm3) , AVX_OFFSET_YMM(3) , ehframe_dwarf_ymm3 , ehframe_dwarf_ymm3 , -1U, debugserver_ymm3, NULL, NULL },
- { e_regSetFPU, fpu_ymm4 , "ymm4" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm4) , AVX_OFFSET_YMM(4) , ehframe_dwarf_ymm4 , ehframe_dwarf_ymm4 , -1U, debugserver_ymm4, NULL, NULL },
- { e_regSetFPU, fpu_ymm5 , "ymm5" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm5) , AVX_OFFSET_YMM(5) , ehframe_dwarf_ymm5 , ehframe_dwarf_ymm5 , -1U, debugserver_ymm5, NULL, NULL },
- { e_regSetFPU, fpu_ymm6 , "ymm6" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm6) , AVX_OFFSET_YMM(6) , ehframe_dwarf_ymm6 , ehframe_dwarf_ymm6 , -1U, debugserver_ymm6, NULL, NULL },
- { e_regSetFPU, fpu_ymm7 , "ymm7" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm7) , AVX_OFFSET_YMM(7) , ehframe_dwarf_ymm7 , ehframe_dwarf_ymm7 , -1U, debugserver_ymm7, NULL, NULL },
- { e_regSetFPU, fpu_ymm8 , "ymm8" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm8) , AVX_OFFSET_YMM(8) , ehframe_dwarf_ymm8 , ehframe_dwarf_ymm8 , -1U, debugserver_ymm8 , NULL, NULL },
- { e_regSetFPU, fpu_ymm9 , "ymm9" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm9) , AVX_OFFSET_YMM(9) , ehframe_dwarf_ymm9 , ehframe_dwarf_ymm9 , -1U, debugserver_ymm9 , NULL, NULL },
- { e_regSetFPU, fpu_ymm10, "ymm10" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm10) , AVX_OFFSET_YMM(10), ehframe_dwarf_ymm10, ehframe_dwarf_ymm10, -1U, debugserver_ymm10, NULL, NULL },
- { e_regSetFPU, fpu_ymm11, "ymm11" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm11) , AVX_OFFSET_YMM(11), ehframe_dwarf_ymm11, ehframe_dwarf_ymm11, -1U, debugserver_ymm11, NULL, NULL },
- { e_regSetFPU, fpu_ymm12, "ymm12" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm12) , AVX_OFFSET_YMM(12), ehframe_dwarf_ymm12, ehframe_dwarf_ymm12, -1U, debugserver_ymm12, NULL, NULL },
- { e_regSetFPU, fpu_ymm13, "ymm13" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm13) , AVX_OFFSET_YMM(13), ehframe_dwarf_ymm13, ehframe_dwarf_ymm13, -1U, debugserver_ymm13, NULL, NULL },
- { e_regSetFPU, fpu_ymm14, "ymm14" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm14) , AVX_OFFSET_YMM(14), ehframe_dwarf_ymm14, ehframe_dwarf_ymm14, -1U, debugserver_ymm14, NULL, NULL },
- { e_regSetFPU, fpu_ymm15, "ymm15" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm15) , AVX_OFFSET_YMM(15), ehframe_dwarf_ymm15, ehframe_dwarf_ymm15, -1U, debugserver_ymm15, NULL, NULL },
-
- { e_regSetFPU, fpu_xmm0 , "xmm0" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0) , 0, ehframe_dwarf_xmm0 , ehframe_dwarf_xmm0 , -1U, debugserver_xmm0 , g_contained_ymm0 , NULL },
- { e_regSetFPU, fpu_xmm1 , "xmm1" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1) , 0, ehframe_dwarf_xmm1 , ehframe_dwarf_xmm1 , -1U, debugserver_xmm1 , g_contained_ymm1 , NULL },
- { e_regSetFPU, fpu_xmm2 , "xmm2" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2) , 0, ehframe_dwarf_xmm2 , ehframe_dwarf_xmm2 , -1U, debugserver_xmm2 , g_contained_ymm2 , NULL },
- { e_regSetFPU, fpu_xmm3 , "xmm3" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3) , 0, ehframe_dwarf_xmm3 , ehframe_dwarf_xmm3 , -1U, debugserver_xmm3 , g_contained_ymm3 , NULL },
- { e_regSetFPU, fpu_xmm4 , "xmm4" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4) , 0, ehframe_dwarf_xmm4 , ehframe_dwarf_xmm4 , -1U, debugserver_xmm4 , g_contained_ymm4 , NULL },
- { e_regSetFPU, fpu_xmm5 , "xmm5" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5) , 0, ehframe_dwarf_xmm5 , ehframe_dwarf_xmm5 , -1U, debugserver_xmm5 , g_contained_ymm5 , NULL },
- { e_regSetFPU, fpu_xmm6 , "xmm6" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6) , 0, ehframe_dwarf_xmm6 , ehframe_dwarf_xmm6 , -1U, debugserver_xmm6 , g_contained_ymm6 , NULL },
- { e_regSetFPU, fpu_xmm7 , "xmm7" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7) , 0, ehframe_dwarf_xmm7 , ehframe_dwarf_xmm7 , -1U, debugserver_xmm7 , g_contained_ymm7 , NULL },
- { e_regSetFPU, fpu_xmm8 , "xmm8" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm8) , 0, ehframe_dwarf_xmm8 , ehframe_dwarf_xmm8 , -1U, debugserver_xmm8 , g_contained_ymm8 , NULL },
- { e_regSetFPU, fpu_xmm9 , "xmm9" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm9) , 0, ehframe_dwarf_xmm9 , ehframe_dwarf_xmm9 , -1U, debugserver_xmm9 , g_contained_ymm9 , NULL },
- { e_regSetFPU, fpu_xmm10, "xmm10" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm10) , 0, ehframe_dwarf_xmm10, ehframe_dwarf_xmm10, -1U, debugserver_xmm10, g_contained_ymm10, NULL },
- { e_regSetFPU, fpu_xmm11, "xmm11" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm11) , 0, ehframe_dwarf_xmm11, ehframe_dwarf_xmm11, -1U, debugserver_xmm11, g_contained_ymm11, NULL },
- { e_regSetFPU, fpu_xmm12, "xmm12" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm12) , 0, ehframe_dwarf_xmm12, ehframe_dwarf_xmm12, -1U, debugserver_xmm12, g_contained_ymm12, NULL },
- { e_regSetFPU, fpu_xmm13, "xmm13" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm13) , 0, ehframe_dwarf_xmm13, ehframe_dwarf_xmm13, -1U, debugserver_xmm13, g_contained_ymm13, NULL },
- { e_regSetFPU, fpu_xmm14, "xmm14" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm14) , 0, ehframe_dwarf_xmm14, ehframe_dwarf_xmm14, -1U, debugserver_xmm14, g_contained_ymm14, NULL },
- { e_regSetFPU, fpu_xmm15, "xmm15" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm15) , 0, ehframe_dwarf_xmm15, ehframe_dwarf_xmm15, -1U, debugserver_xmm15, g_contained_ymm15, NULL }
-
+static const char *g_contained_ymm0[] = {"ymm0", NULL};
+static const char *g_contained_ymm1[] = {"ymm1", NULL};
+static const char *g_contained_ymm2[] = {"ymm2", NULL};
+static const char *g_contained_ymm3[] = {"ymm3", NULL};
+static const char *g_contained_ymm4[] = {"ymm4", NULL};
+static const char *g_contained_ymm5[] = {"ymm5", NULL};
+static const char *g_contained_ymm6[] = {"ymm6", NULL};
+static const char *g_contained_ymm7[] = {"ymm7", NULL};
+static const char *g_contained_ymm8[] = {"ymm8", NULL};
+static const char *g_contained_ymm9[] = {"ymm9", NULL};
+static const char *g_contained_ymm10[] = {"ymm10", NULL};
+static const char *g_contained_ymm11[] = {"ymm11", NULL};
+static const char *g_contained_ymm12[] = {"ymm12", NULL};
+static const char *g_contained_ymm13[] = {"ymm13", NULL};
+static const char *g_contained_ymm14[] = {"ymm14", NULL};
+static const char *g_contained_ymm15[] = {"ymm15", NULL};
+
+const DNBRegisterInfo DNBArchImplX86_64::g_fpu_registers_avx[] = {
+ {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw),
+ AVX_OFFSET(fcw), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw),
+ AVX_OFFSET(fsw), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, FPU_SIZE_UINT(ftw),
+ AVX_OFFSET(ftw), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop),
+ AVX_OFFSET(fop), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip),
+ AVX_OFFSET(ip), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs),
+ AVX_OFFSET(cs), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp),
+ AVX_OFFSET(dp), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds),
+ AVX_OFFSET(ds), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr),
+ AVX_OFFSET(mxcsr), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex,
+ FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), -1U, -1U, -1U, -1U, NULL,
+ NULL},
+
+ {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), ehframe_dwarf_stmm0,
+ ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL},
+ {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), ehframe_dwarf_stmm1,
+ ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL},
+ {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), ehframe_dwarf_stmm2,
+ ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL},
+ {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), ehframe_dwarf_stmm3,
+ ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL},
+ {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), ehframe_dwarf_stmm4,
+ ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL},
+ {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), ehframe_dwarf_stmm5,
+ ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL},
+ {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), ehframe_dwarf_stmm6,
+ ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL},
+ {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), ehframe_dwarf_stmm7,
+ ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL},
+
+ {e_regSetFPU, fpu_ymm0, "ymm0", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm0), AVX_OFFSET_YMM(0), ehframe_dwarf_ymm0,
+ ehframe_dwarf_ymm0, -1U, debugserver_ymm0, NULL, NULL},
+ {e_regSetFPU, fpu_ymm1, "ymm1", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm1), AVX_OFFSET_YMM(1), ehframe_dwarf_ymm1,
+ ehframe_dwarf_ymm1, -1U, debugserver_ymm1, NULL, NULL},
+ {e_regSetFPU, fpu_ymm2, "ymm2", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm2), AVX_OFFSET_YMM(2), ehframe_dwarf_ymm2,
+ ehframe_dwarf_ymm2, -1U, debugserver_ymm2, NULL, NULL},
+ {e_regSetFPU, fpu_ymm3, "ymm3", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm3), AVX_OFFSET_YMM(3), ehframe_dwarf_ymm3,
+ ehframe_dwarf_ymm3, -1U, debugserver_ymm3, NULL, NULL},
+ {e_regSetFPU, fpu_ymm4, "ymm4", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm4), AVX_OFFSET_YMM(4), ehframe_dwarf_ymm4,
+ ehframe_dwarf_ymm4, -1U, debugserver_ymm4, NULL, NULL},
+ {e_regSetFPU, fpu_ymm5, "ymm5", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm5), AVX_OFFSET_YMM(5), ehframe_dwarf_ymm5,
+ ehframe_dwarf_ymm5, -1U, debugserver_ymm5, NULL, NULL},
+ {e_regSetFPU, fpu_ymm6, "ymm6", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm6), AVX_OFFSET_YMM(6), ehframe_dwarf_ymm6,
+ ehframe_dwarf_ymm6, -1U, debugserver_ymm6, NULL, NULL},
+ {e_regSetFPU, fpu_ymm7, "ymm7", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm7), AVX_OFFSET_YMM(7), ehframe_dwarf_ymm7,
+ ehframe_dwarf_ymm7, -1U, debugserver_ymm7, NULL, NULL},
+ {e_regSetFPU, fpu_ymm8, "ymm8", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm8), AVX_OFFSET_YMM(8), ehframe_dwarf_ymm8,
+ ehframe_dwarf_ymm8, -1U, debugserver_ymm8, NULL, NULL},
+ {e_regSetFPU, fpu_ymm9, "ymm9", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm9), AVX_OFFSET_YMM(9), ehframe_dwarf_ymm9,
+ ehframe_dwarf_ymm9, -1U, debugserver_ymm9, NULL, NULL},
+ {e_regSetFPU, fpu_ymm10, "ymm10", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm10), AVX_OFFSET_YMM(10), ehframe_dwarf_ymm10,
+ ehframe_dwarf_ymm10, -1U, debugserver_ymm10, NULL, NULL},
+ {e_regSetFPU, fpu_ymm11, "ymm11", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm11), AVX_OFFSET_YMM(11), ehframe_dwarf_ymm11,
+ ehframe_dwarf_ymm11, -1U, debugserver_ymm11, NULL, NULL},
+ {e_regSetFPU, fpu_ymm12, "ymm12", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm12), AVX_OFFSET_YMM(12), ehframe_dwarf_ymm12,
+ ehframe_dwarf_ymm12, -1U, debugserver_ymm12, NULL, NULL},
+ {e_regSetFPU, fpu_ymm13, "ymm13", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm13), AVX_OFFSET_YMM(13), ehframe_dwarf_ymm13,
+ ehframe_dwarf_ymm13, -1U, debugserver_ymm13, NULL, NULL},
+ {e_regSetFPU, fpu_ymm14, "ymm14", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm14), AVX_OFFSET_YMM(14), ehframe_dwarf_ymm14,
+ ehframe_dwarf_ymm14, -1U, debugserver_ymm14, NULL, NULL},
+ {e_regSetFPU, fpu_ymm15, "ymm15", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_YMM(ymm15), AVX_OFFSET_YMM(15), ehframe_dwarf_ymm15,
+ ehframe_dwarf_ymm15, -1U, debugserver_ymm15, NULL, NULL},
+
+ {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm0), 0, ehframe_dwarf_xmm0, ehframe_dwarf_xmm0, -1U,
+ debugserver_xmm0, g_contained_ymm0, NULL},
+ {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm1), 0, ehframe_dwarf_xmm1, ehframe_dwarf_xmm1, -1U,
+ debugserver_xmm1, g_contained_ymm1, NULL},
+ {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm2), 0, ehframe_dwarf_xmm2, ehframe_dwarf_xmm2, -1U,
+ debugserver_xmm2, g_contained_ymm2, NULL},
+ {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm3), 0, ehframe_dwarf_xmm3, ehframe_dwarf_xmm3, -1U,
+ debugserver_xmm3, g_contained_ymm3, NULL},
+ {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm4), 0, ehframe_dwarf_xmm4, ehframe_dwarf_xmm4, -1U,
+ debugserver_xmm4, g_contained_ymm4, NULL},
+ {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm5), 0, ehframe_dwarf_xmm5, ehframe_dwarf_xmm5, -1U,
+ debugserver_xmm5, g_contained_ymm5, NULL},
+ {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm6), 0, ehframe_dwarf_xmm6, ehframe_dwarf_xmm6, -1U,
+ debugserver_xmm6, g_contained_ymm6, NULL},
+ {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm7), 0, ehframe_dwarf_xmm7, ehframe_dwarf_xmm7, -1U,
+ debugserver_xmm7, g_contained_ymm7, NULL},
+ {e_regSetFPU, fpu_xmm8, "xmm8", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm8), 0, ehframe_dwarf_xmm8, ehframe_dwarf_xmm8, -1U,
+ debugserver_xmm8, g_contained_ymm8, NULL},
+ {e_regSetFPU, fpu_xmm9, "xmm9", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm9), 0, ehframe_dwarf_xmm9, ehframe_dwarf_xmm9, -1U,
+ debugserver_xmm9, g_contained_ymm9, NULL},
+ {e_regSetFPU, fpu_xmm10, "xmm10", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm10), 0, ehframe_dwarf_xmm10, ehframe_dwarf_xmm10, -1U,
+ debugserver_xmm10, g_contained_ymm10, NULL},
+ {e_regSetFPU, fpu_xmm11, "xmm11", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm11), 0, ehframe_dwarf_xmm11, ehframe_dwarf_xmm11, -1U,
+ debugserver_xmm11, g_contained_ymm11, NULL},
+ {e_regSetFPU, fpu_xmm12, "xmm12", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm12), 0, ehframe_dwarf_xmm12, ehframe_dwarf_xmm12, -1U,
+ debugserver_xmm12, g_contained_ymm12, NULL},
+ {e_regSetFPU, fpu_xmm13, "xmm13", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm13), 0, ehframe_dwarf_xmm13, ehframe_dwarf_xmm13, -1U,
+ debugserver_xmm13, g_contained_ymm13, NULL},
+ {e_regSetFPU, fpu_xmm14, "xmm14", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm14), 0, ehframe_dwarf_xmm14, ehframe_dwarf_xmm14, -1U,
+ debugserver_xmm14, g_contained_ymm14, NULL},
+ {e_regSetFPU, fpu_xmm15, "xmm15", NULL, Vector, VectorOfUInt8,
+ FPU_SIZE_XMM(xmm15), 0, ehframe_dwarf_xmm15, ehframe_dwarf_xmm15, -1U,
+ debugserver_xmm15, g_contained_ymm15, NULL}
};
// Exception registers
-const DNBRegisterInfo
-DNBArchImplX86_64::g_exc_registers[] =
-{
- { e_regSetEXC, exc_trapno, "trapno" , NULL, Uint, Hex, EXC_SIZE (trapno) , EXC_OFFSET (trapno) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetEXC, exc_err, "err" , NULL, Uint, Hex, EXC_SIZE (err) , EXC_OFFSET (err) , -1U, -1U, -1U, -1U, NULL, NULL },
- { e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, EXC_SIZE (faultvaddr), EXC_OFFSET (faultvaddr) , -1U, -1U, -1U, -1U, NULL, NULL }
-};
+const DNBRegisterInfo DNBArchImplX86_64::g_exc_registers[] = {
+ {e_regSetEXC, exc_trapno, "trapno", NULL, Uint, Hex, EXC_SIZE(trapno),
+ EXC_OFFSET(trapno), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetEXC, exc_err, "err", NULL, Uint, Hex, EXC_SIZE(err),
+ EXC_OFFSET(err), -1U, -1U, -1U, -1U, NULL, NULL},
+ {e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex,
+ EXC_SIZE(faultvaddr), EXC_OFFSET(faultvaddr), -1U, -1U, -1U, -1U, NULL,
+ NULL}};
// Number of registers in each register set
-const size_t DNBArchImplX86_64::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo);
-const size_t DNBArchImplX86_64::k_num_fpu_registers_no_avx = sizeof(g_fpu_registers_no_avx)/sizeof(DNBRegisterInfo);
-const size_t DNBArchImplX86_64::k_num_fpu_registers_avx = sizeof(g_fpu_registers_avx)/sizeof(DNBRegisterInfo);
-const size_t DNBArchImplX86_64::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo);
-const size_t DNBArchImplX86_64::k_num_all_registers_no_avx = k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers;
-const size_t DNBArchImplX86_64::k_num_all_registers_avx = k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers;
+const size_t DNBArchImplX86_64::k_num_gpr_registers =
+ sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo);
+const size_t DNBArchImplX86_64::k_num_fpu_registers_no_avx =
+ sizeof(g_fpu_registers_no_avx) / sizeof(DNBRegisterInfo);
+const size_t DNBArchImplX86_64::k_num_fpu_registers_avx =
+ sizeof(g_fpu_registers_avx) / sizeof(DNBRegisterInfo);
+const size_t DNBArchImplX86_64::k_num_exc_registers =
+ sizeof(g_exc_registers) / sizeof(DNBRegisterInfo);
+const size_t DNBArchImplX86_64::k_num_all_registers_no_avx =
+ k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers;
+const size_t DNBArchImplX86_64::k_num_all_registers_avx =
+ k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers;
//----------------------------------------------------------------------
// Register set definitions. The first definitions at register set index
// of zero is for all registers, followed by other registers sets. The
// register information for the all register set need not be filled in.
//----------------------------------------------------------------------
-const DNBRegisterSetInfo
-DNBArchImplX86_64::g_reg_sets_no_avx[] =
-{
- { "x86_64 Registers", NULL, k_num_all_registers_no_avx },
- { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers },
- { "Floating Point Registers", g_fpu_registers_no_avx, k_num_fpu_registers_no_avx },
- { "Exception State Registers", g_exc_registers, k_num_exc_registers }
-};
-
-const DNBRegisterSetInfo
-DNBArchImplX86_64::g_reg_sets_avx[] =
-{
- { "x86_64 Registers", NULL, k_num_all_registers_avx },
- { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers },
- { "Floating Point Registers", g_fpu_registers_avx, k_num_fpu_registers_avx },
- { "Exception State Registers", g_exc_registers, k_num_exc_registers }
-};
+const DNBRegisterSetInfo DNBArchImplX86_64::g_reg_sets_no_avx[] = {
+ {"x86_64 Registers", NULL, k_num_all_registers_no_avx},
+ {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers},
+ {"Floating Point Registers", g_fpu_registers_no_avx,
+ k_num_fpu_registers_no_avx},
+ {"Exception State Registers", g_exc_registers, k_num_exc_registers}};
+
+const DNBRegisterSetInfo DNBArchImplX86_64::g_reg_sets_avx[] = {
+ {"x86_64 Registers", NULL, k_num_all_registers_avx},
+ {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers},
+ {"Floating Point Registers", g_fpu_registers_avx, k_num_fpu_registers_avx},
+ {"Exception State Registers", g_exc_registers, k_num_exc_registers}};
// Total number of register sets for this architecture
-const size_t DNBArchImplX86_64::k_num_register_sets = sizeof(g_reg_sets_avx)/sizeof(DNBRegisterSetInfo);
+const size_t DNBArchImplX86_64::k_num_register_sets =
+ sizeof(g_reg_sets_avx) / sizeof(DNBRegisterSetInfo);
-
-DNBArchProtocol *
-DNBArchImplX86_64::Create (MachThread *thread)
-{
- DNBArchImplX86_64 *obj = new DNBArchImplX86_64 (thread);
- return obj;
+DNBArchProtocol *DNBArchImplX86_64::Create(MachThread *thread) {
+ DNBArchImplX86_64 *obj = new DNBArchImplX86_64(thread);
+ return obj;
}
const uint8_t *
-DNBArchImplX86_64::SoftwareBreakpointOpcode (nub_size_t byte_size)
-{
- static const uint8_t g_breakpoint_opcode[] = { 0xCC };
- if (byte_size == 1)
- return g_breakpoint_opcode;
- return NULL;
+DNBArchImplX86_64::SoftwareBreakpointOpcode(nub_size_t byte_size) {
+ static const uint8_t g_breakpoint_opcode[] = {0xCC};
+ if (byte_size == 1)
+ return g_breakpoint_opcode;
+ return NULL;
}
const DNBRegisterSetInfo *
-DNBArchImplX86_64::GetRegisterSetInfo(nub_size_t *num_reg_sets)
-{
- *num_reg_sets = k_num_register_sets;
-
- if (CPUHasAVX() || FORCE_AVX_REGS)
- return g_reg_sets_avx;
- else
- return g_reg_sets_no_avx;
-}
-
-void
-DNBArchImplX86_64::Initialize()
-{
- DNBArchPluginInfo arch_plugin_info =
- {
- CPU_TYPE_X86_64,
- DNBArchImplX86_64::Create,
- DNBArchImplX86_64::GetRegisterSetInfo,
- DNBArchImplX86_64::SoftwareBreakpointOpcode
- };
-
- // Register this arch plug-in with the main protocol class
- DNBArchProtocol::RegisterArchPlugin (arch_plugin_info);
-}
-
-bool
-DNBArchImplX86_64::GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value)
-{
- if (set == REGISTER_SET_GENERIC)
- {
- switch (reg)
- {
- case GENERIC_REGNUM_PC: // Program Counter
- set = e_regSetGPR;
- reg = gpr_rip;
- break;
-
- case GENERIC_REGNUM_SP: // Stack Pointer
- set = e_regSetGPR;
- reg = gpr_rsp;
- break;
-
- case GENERIC_REGNUM_FP: // Frame Pointer
- set = e_regSetGPR;
- reg = gpr_rbp;
- break;
-
- case GENERIC_REGNUM_FLAGS: // Processor flags register
- set = e_regSetGPR;
- reg = gpr_rflags;
- break;
-
- case GENERIC_REGNUM_RA: // Return Address
- default:
- return false;
- }
- }
-
- if (GetRegisterState(set, false) != KERN_SUCCESS)
- return false;
-
- const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
- if (regInfo)
- {
- value->info = *regInfo;
- switch (set)
- {
- case e_regSetGPR:
- if (reg < k_num_gpr_registers)
- {
- value->value.uint64 = ((uint64_t*)(&m_state.context.gpr))[reg];
- return true;
- }
- break;
-
- case e_regSetFPU:
- if (CPUHasAVX() || FORCE_AVX_REGS)
- {
- switch (reg)
- {
- case fpu_fcw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)); return true;
- case fpu_fsw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)); return true;
- case fpu_ftw: value->value.uint8 = m_state.context.fpu.avx.__fpu_ftw; return true;
- case fpu_fop: value->value.uint16 = m_state.context.fpu.avx.__fpu_fop; return true;
- case fpu_ip: value->value.uint32 = m_state.context.fpu.avx.__fpu_ip; return true;
- case fpu_cs: value->value.uint16 = m_state.context.fpu.avx.__fpu_cs; return true;
- case fpu_dp: value->value.uint32 = m_state.context.fpu.avx.__fpu_dp; return true;
- case fpu_ds: value->value.uint16 = m_state.context.fpu.avx.__fpu_ds; return true;
- case fpu_mxcsr: value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsr; return true;
- case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsrmask; return true;
-
- case fpu_stmm0:
- case fpu_stmm1:
- case fpu_stmm2:
- case fpu_stmm3:
- case fpu_stmm4:
- case fpu_stmm5:
- case fpu_stmm6:
- case fpu_stmm7:
- memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0), 10);
- return true;
-
- case fpu_xmm0:
- case fpu_xmm1:
- case fpu_xmm2:
- case fpu_xmm3:
- case fpu_xmm4:
- case fpu_xmm5:
- case fpu_xmm6:
- case fpu_xmm7:
- case fpu_xmm8:
- case fpu_xmm9:
- case fpu_xmm10:
- case fpu_xmm11:
- case fpu_xmm12:
- case fpu_xmm13:
- case fpu_xmm14:
- case fpu_xmm15:
- memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0), 16);
- return true;
-
- case fpu_ymm0:
- case fpu_ymm1:
- case fpu_ymm2:
- case fpu_ymm3:
- case fpu_ymm4:
- case fpu_ymm5:
- case fpu_ymm6:
- case fpu_ymm7:
- case fpu_ymm8:
- case fpu_ymm9:
- case fpu_ymm10:
- case fpu_ymm11:
- case fpu_ymm12:
- case fpu_ymm13:
- case fpu_ymm14:
- case fpu_ymm15:
- memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), 16);
- memcpy((&value->value.uint8) + 16, &m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), 16);
- return true;
- }
- }
- else
- {
- switch (reg)
- {
- case fpu_fcw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)); return true;
- case fpu_fsw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)); return true;
- case fpu_ftw: value->value.uint8 = m_state.context.fpu.no_avx.__fpu_ftw; return true;
- case fpu_fop: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop; return true;
- case fpu_ip: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip; return true;
- case fpu_cs: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs; return true;
- case fpu_dp: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp; return true;
- case fpu_ds: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds; return true;
- case fpu_mxcsr: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr; return true;
- case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask; return true;
-
- case fpu_stmm0:
- case fpu_stmm1:
- case fpu_stmm2:
- case fpu_stmm3:
- case fpu_stmm4:
- case fpu_stmm5:
- case fpu_stmm6:
- case fpu_stmm7:
- memcpy(&value->value.uint8, &m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), 10);
- return true;
-
- case fpu_xmm0:
- case fpu_xmm1:
- case fpu_xmm2:
- case fpu_xmm3:
- case fpu_xmm4:
- case fpu_xmm5:
- case fpu_xmm6:
- case fpu_xmm7:
- case fpu_xmm8:
- case fpu_xmm9:
- case fpu_xmm10:
- case fpu_xmm11:
- case fpu_xmm12:
- case fpu_xmm13:
- case fpu_xmm14:
- case fpu_xmm15:
- memcpy(&value->value.uint8, &m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), 16);
- return true;
- }
- }
- break;
-
- case e_regSetEXC:
- switch (reg)
- {
- case exc_trapno: value->value.uint32 = m_state.context.exc.__trapno; return true;
- case exc_err: value->value.uint32 = m_state.context.exc.__err; return true;
- case exc_faultvaddr:value->value.uint64 = m_state.context.exc.__faultvaddr; return true;
- }
- break;
- }
- }
- return false;
-}
+DNBArchImplX86_64::GetRegisterSetInfo(nub_size_t *num_reg_sets) {
+ *num_reg_sets = k_num_register_sets;
+ if (CPUHasAVX() || FORCE_AVX_REGS)
+ return g_reg_sets_avx;
+ else
+ return g_reg_sets_no_avx;
+}
+
+void DNBArchImplX86_64::Initialize() {
+ DNBArchPluginInfo arch_plugin_info = {
+ CPU_TYPE_X86_64, DNBArchImplX86_64::Create,
+ DNBArchImplX86_64::GetRegisterSetInfo,
+ DNBArchImplX86_64::SoftwareBreakpointOpcode};
+
+ // Register this arch plug-in with the main protocol class
+ DNBArchProtocol::RegisterArchPlugin(arch_plugin_info);
+}
+
+bool DNBArchImplX86_64::GetRegisterValue(uint32_t set, uint32_t reg,
+ DNBRegisterValue *value) {
+ if (set == REGISTER_SET_GENERIC) {
+ switch (reg) {
+ case GENERIC_REGNUM_PC: // Program Counter
+ set = e_regSetGPR;
+ reg = gpr_rip;
+ break;
+
+ case GENERIC_REGNUM_SP: // Stack Pointer
+ set = e_regSetGPR;
+ reg = gpr_rsp;
+ break;
+
+ case GENERIC_REGNUM_FP: // Frame Pointer
+ set = e_regSetGPR;
+ reg = gpr_rbp;
+ break;
+
+ case GENERIC_REGNUM_FLAGS: // Processor flags register
+ set = e_regSetGPR;
+ reg = gpr_rflags;
+ break;
-bool
-DNBArchImplX86_64::SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value)
-{
- if (set == REGISTER_SET_GENERIC)
- {
- switch (reg)
- {
- case GENERIC_REGNUM_PC: // Program Counter
- set = e_regSetGPR;
- reg = gpr_rip;
- break;
-
- case GENERIC_REGNUM_SP: // Stack Pointer
- set = e_regSetGPR;
- reg = gpr_rsp;
- break;
-
- case GENERIC_REGNUM_FP: // Frame Pointer
- set = e_regSetGPR;
- reg = gpr_rbp;
- break;
-
- case GENERIC_REGNUM_FLAGS: // Processor flags register
- set = e_regSetGPR;
- reg = gpr_rflags;
- break;
-
- case GENERIC_REGNUM_RA: // Return Address
- default:
- return false;
- }
- }
-
- if (GetRegisterState(set, false) != KERN_SUCCESS)
- return false;
-
- bool success = false;
- const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
- if (regInfo)
- {
- switch (set)
- {
- case e_regSetGPR:
- if (reg < k_num_gpr_registers)
- {
- ((uint64_t*)(&m_state.context.gpr))[reg] = value->value.uint64;
- success = true;
- }
- break;
-
- case e_regSetFPU:
- if (CPUHasAVX() || FORCE_AVX_REGS)
- {
- switch (reg)
- {
- case fpu_fcw: *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)) = value->value.uint16; success = true; break;
- case fpu_fsw: *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)) = value->value.uint16; success = true; break;
- case fpu_ftw: m_state.context.fpu.avx.__fpu_ftw = value->value.uint8; success = true; break;
- case fpu_fop: m_state.context.fpu.avx.__fpu_fop = value->value.uint16; success = true; break;
- case fpu_ip: m_state.context.fpu.avx.__fpu_ip = value->value.uint32; success = true; break;
- case fpu_cs: m_state.context.fpu.avx.__fpu_cs = value->value.uint16; success = true; break;
- case fpu_dp: m_state.context.fpu.avx.__fpu_dp = value->value.uint32; success = true; break;
- case fpu_ds: m_state.context.fpu.avx.__fpu_ds = value->value.uint16; success = true; break;
- case fpu_mxcsr: m_state.context.fpu.avx.__fpu_mxcsr = value->value.uint32; success = true; break;
- case fpu_mxcsrmask: m_state.context.fpu.avx.__fpu_mxcsrmask = value->value.uint32; success = true; break;
-
- case fpu_stmm0:
- case fpu_stmm1:
- case fpu_stmm2:
- case fpu_stmm3:
- case fpu_stmm4:
- case fpu_stmm5:
- case fpu_stmm6:
- case fpu_stmm7:
- memcpy (&m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0), &value->value.uint8, 10);
- success = true;
- break;
-
- case fpu_xmm0:
- case fpu_xmm1:
- case fpu_xmm2:
- case fpu_xmm3:
- case fpu_xmm4:
- case fpu_xmm5:
- case fpu_xmm6:
- case fpu_xmm7:
- case fpu_xmm8:
- case fpu_xmm9:
- case fpu_xmm10:
- case fpu_xmm11:
- case fpu_xmm12:
- case fpu_xmm13:
- case fpu_xmm14:
- case fpu_xmm15:
- memcpy (&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0), &value->value.uint8, 16);
- success = true;
- break;
-
- case fpu_ymm0:
- case fpu_ymm1:
- case fpu_ymm2:
- case fpu_ymm3:
- case fpu_ymm4:
- case fpu_ymm5:
- case fpu_ymm6:
- case fpu_ymm7:
- case fpu_ymm8:
- case fpu_ymm9:
- case fpu_ymm10:
- case fpu_ymm11:
- case fpu_ymm12:
- case fpu_ymm13:
- case fpu_ymm14:
- case fpu_ymm15:
- memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), &value->value.uint8, 16);
- memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), (&value->value.uint8) + 16, 16);
- return true;
- }
- }
- else
- {
- switch (reg)
- {
- case fpu_fcw: *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) = value->value.uint16; success = true; break;
- case fpu_fsw: *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) = value->value.uint16; success = true; break;
- case fpu_ftw: m_state.context.fpu.no_avx.__fpu_ftw = value->value.uint8; success = true; break;
- case fpu_fop: m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16; success = true; break;
- case fpu_ip: m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32; success = true; break;
- case fpu_cs: m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16; success = true; break;
- case fpu_dp: m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32; success = true; break;
- case fpu_ds: m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16; success = true; break;
- case fpu_mxcsr: m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32; success = true; break;
- case fpu_mxcsrmask: m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32; success = true; break;
-
- case fpu_stmm0:
- case fpu_stmm1:
- case fpu_stmm2:
- case fpu_stmm3:
- case fpu_stmm4:
- case fpu_stmm5:
- case fpu_stmm6:
- case fpu_stmm7:
- memcpy (&m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), &value->value.uint8, 10);
- success = true;
- break;
-
- case fpu_xmm0:
- case fpu_xmm1:
- case fpu_xmm2:
- case fpu_xmm3:
- case fpu_xmm4:
- case fpu_xmm5:
- case fpu_xmm6:
- case fpu_xmm7:
- case fpu_xmm8:
- case fpu_xmm9:
- case fpu_xmm10:
- case fpu_xmm11:
- case fpu_xmm12:
- case fpu_xmm13:
- case fpu_xmm14:
- case fpu_xmm15:
- memcpy (&m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), &value->value.uint8, 16);
- success = true;
- break;
- }
- }
- break;
-
- case e_regSetEXC:
- switch (reg)
- {
- case exc_trapno: m_state.context.exc.__trapno = value->value.uint32; success = true; break;
- case exc_err: m_state.context.exc.__err = value->value.uint32; success = true; break;
- case exc_faultvaddr:m_state.context.exc.__faultvaddr = value->value.uint64; success = true; break;
- }
- break;
- }
+ case GENERIC_REGNUM_RA: // Return Address
+ default:
+ return false;
}
-
- if (success)
- return SetRegisterState(set) == KERN_SUCCESS;
+ }
+
+ if (GetRegisterState(set, false) != KERN_SUCCESS)
return false;
-}
-uint32_t
-DNBArchImplX86_64::GetRegisterContextSize()
-{
- static uint32_t g_cached_size = 0;
- if (g_cached_size == 0)
- {
- if (CPUHasAVX() || FORCE_AVX_REGS)
- {
- for (size_t i=0; i<k_num_fpu_registers_avx; ++i)
- {
- if (g_fpu_registers_avx[i].value_regs == NULL)
- g_cached_size += g_fpu_registers_avx[i].size;
- }
- }
- else
- {
- for (size_t i=0; i<k_num_fpu_registers_no_avx; ++i)
- {
- if (g_fpu_registers_no_avx[i].value_regs == NULL)
- g_cached_size += g_fpu_registers_no_avx[i].size;
- }
- }
- DNBLogThreaded ("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, FPU = %u, EXC = %zu", sizeof(GPR), g_cached_size, sizeof(EXC));
- g_cached_size += sizeof(GPR);
- g_cached_size += sizeof(EXC);
- DNBLogThreaded ("DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u", g_cached_size);
+ const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
+ if (regInfo) {
+ value->info = *regInfo;
+ switch (set) {
+ case e_regSetGPR:
+ if (reg < k_num_gpr_registers) {
+ value->value.uint64 = ((uint64_t *)(&m_state.context.gpr))[reg];
+ return true;
+ }
+ break;
+
+ case e_regSetFPU:
+ if (CPUHasAVX() || FORCE_AVX_REGS) {
+ switch (reg) {
+ case fpu_fcw:
+ value->value.uint16 =
+ *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw));
+ return true;
+ case fpu_fsw:
+ value->value.uint16 =
+ *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw));
+ return true;
+ case fpu_ftw:
+ value->value.uint8 = m_state.context.fpu.avx.__fpu_ftw;
+ return true;
+ case fpu_fop:
+ value->value.uint16 = m_state.context.fpu.avx.__fpu_fop;
+ return true;
+ case fpu_ip:
+ value->value.uint32 = m_state.context.fpu.avx.__fpu_ip;
+ return true;
+ case fpu_cs:
+ value->value.uint16 = m_state.context.fpu.avx.__fpu_cs;
+ return true;
+ case fpu_dp:
+ value->value.uint32 = m_state.context.fpu.avx.__fpu_dp;
+ return true;
+ case fpu_ds:
+ value->value.uint16 = m_state.context.fpu.avx.__fpu_ds;
+ return true;
+ case fpu_mxcsr:
+ value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsr;
+ return true;
+ case fpu_mxcsrmask:
+ value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsrmask;
+ return true;
+
+ case fpu_stmm0:
+ case fpu_stmm1:
+ case fpu_stmm2:
+ case fpu_stmm3:
+ case fpu_stmm4:
+ case fpu_stmm5:
+ case fpu_stmm6:
+ case fpu_stmm7:
+ memcpy(&value->value.uint8,
+ &m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0), 10);
+ return true;
+
+ case fpu_xmm0:
+ case fpu_xmm1:
+ case fpu_xmm2:
+ case fpu_xmm3:
+ case fpu_xmm4:
+ case fpu_xmm5:
+ case fpu_xmm6:
+ case fpu_xmm7:
+ case fpu_xmm8:
+ case fpu_xmm9:
+ case fpu_xmm10:
+ case fpu_xmm11:
+ case fpu_xmm12:
+ case fpu_xmm13:
+ case fpu_xmm14:
+ case fpu_xmm15:
+ memcpy(&value->value.uint8,
+ &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0), 16);
+ return true;
+
+ case fpu_ymm0:
+ case fpu_ymm1:
+ case fpu_ymm2:
+ case fpu_ymm3:
+ case fpu_ymm4:
+ case fpu_ymm5:
+ case fpu_ymm6:
+ case fpu_ymm7:
+ case fpu_ymm8:
+ case fpu_ymm9:
+ case fpu_ymm10:
+ case fpu_ymm11:
+ case fpu_ymm12:
+ case fpu_ymm13:
+ case fpu_ymm14:
+ case fpu_ymm15:
+ memcpy(&value->value.uint8,
+ &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), 16);
+ memcpy((&value->value.uint8) + 16,
+ &m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), 16);
+ return true;
+ }
+ } else {
+ switch (reg) {
+ case fpu_fcw:
+ value->value.uint16 =
+ *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw));
+ return true;
+ case fpu_fsw:
+ value->value.uint16 =
+ *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw));
+ return true;
+ case fpu_ftw:
+ value->value.uint8 = m_state.context.fpu.no_avx.__fpu_ftw;
+ return true;
+ case fpu_fop:
+ value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop;
+ return true;
+ case fpu_ip:
+ value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip;
+ return true;
+ case fpu_cs:
+ value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs;
+ return true;
+ case fpu_dp:
+ value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp;
+ return true;
+ case fpu_ds:
+ value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds;
+ return true;
+ case fpu_mxcsr:
+ value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr;
+ return true;
+ case fpu_mxcsrmask:
+ value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask;
+ return true;
+
+ case fpu_stmm0:
+ case fpu_stmm1:
+ case fpu_stmm2:
+ case fpu_stmm3:
+ case fpu_stmm4:
+ case fpu_stmm5:
+ case fpu_stmm6:
+ case fpu_stmm7:
+ memcpy(&value->value.uint8,
+ &m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0),
+ 10);
+ return true;
+
+ case fpu_xmm0:
+ case fpu_xmm1:
+ case fpu_xmm2:
+ case fpu_xmm3:
+ case fpu_xmm4:
+ case fpu_xmm5:
+ case fpu_xmm6:
+ case fpu_xmm7:
+ case fpu_xmm8:
+ case fpu_xmm9:
+ case fpu_xmm10:
+ case fpu_xmm11:
+ case fpu_xmm12:
+ case fpu_xmm13:
+ case fpu_xmm14:
+ case fpu_xmm15:
+ memcpy(&value->value.uint8,
+ &m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), 16);
+ return true;
+ }
+ }
+ break;
+
+ case e_regSetEXC:
+ switch (reg) {
+ case exc_trapno:
+ value->value.uint32 = m_state.context.exc.__trapno;
+ return true;
+ case exc_err:
+ value->value.uint32 = m_state.context.exc.__err;
+ return true;
+ case exc_faultvaddr:
+ value->value.uint64 = m_state.context.exc.__faultvaddr;
+ return true;
+ }
+ break;
}
- return g_cached_size;
+ }
+ return false;
}
-nub_size_t
-DNBArchImplX86_64::GetRegisterContext (void *buf, nub_size_t buf_len)
-{
- uint32_t size = GetRegisterContextSize();
-
- if (buf && buf_len)
- {
- bool force = false;
- kern_return_t kret;
-
- if ((kret = GetGPRState(force)) != KERN_SUCCESS)
- {
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) error: GPR regs failed to read: %u ", buf, (uint64_t)buf_len, kret);
- size = 0;
- }
- else
- if ((kret = GetFPUState(force)) != KERN_SUCCESS)
- {
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) error: %s regs failed to read: %u", buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
- size = 0;
- }
- else
- if ((kret = GetEXCState(force)) != KERN_SUCCESS)
- {
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) error: EXC regs failed to read: %u", buf, (uint64_t)buf_len, kret);
- size = 0;
- }
- else
- {
- uint8_t *p = (uint8_t *)buf;
- // Copy the GPR registers
- memcpy(p, &m_state.context.gpr, sizeof(GPR));
- p += sizeof(GPR);
-
- if (CPUHasAVX() || FORCE_AVX_REGS)
- {
- // Walk around the gaps in the FPU regs
- memcpy(p, &m_state.context.fpu.avx.__fpu_fcw, 5);
- p += 5;
- memcpy(p, &m_state.context.fpu.avx.__fpu_fop, 8);
- p += 8;
- memcpy(p, &m_state.context.fpu.avx.__fpu_dp, 6);
- p += 6;
- memcpy(p, &m_state.context.fpu.avx.__fpu_mxcsr, 8);
- p += 8;
-
- // Work around the padding between the stmm registers as they are 16
- // byte structs with 10 bytes of the value in each
- for (size_t i=0; i<8; ++i)
- {
- memcpy(p, &m_state.context.fpu.avx.__fpu_stmm0 + i, 10);
- p += 10;
- }
-
- // Interleave the XMM and YMMH registers to make the YMM registers
- for (size_t i=0; i<16; ++i)
- {
- memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16);
- p += 16;
- memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16);
- p += 16;
- }
- }
- else
- {
- // Walk around the gaps in the FPU regs
- memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5);
- p += 5;
- memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8);
- p += 8;
- memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6);
- p += 6;
- memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8);
- p += 8;
-
- // Work around the padding between the stmm registers as they are 16
- // byte structs with 10 bytes of the value in each
- for (size_t i=0; i<8; ++i)
- {
- memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10);
- p += 10;
- }
-
- // Copy the XMM registers in a single block
- memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 16 * 16);
- p += 16 * 16;
- }
-
- // Copy the exception registers
- memcpy(p, &m_state.context.exc, sizeof(EXC));
- p += sizeof(EXC);
-
- // make sure we end up with exactly what we think we should have
- size_t bytes_written = p - (uint8_t *)buf;
- UNUSED_IF_ASSERT_DISABLED(bytes_written);
- assert (bytes_written == size);
- }
-
- }
+bool DNBArchImplX86_64::SetRegisterValue(uint32_t set, uint32_t reg,
+ const DNBRegisterValue *value) {
+ if (set == REGISTER_SET_GENERIC) {
+ switch (reg) {
+ case GENERIC_REGNUM_PC: // Program Counter
+ set = e_regSetGPR;
+ reg = gpr_rip;
+ break;
+
+ case GENERIC_REGNUM_SP: // Stack Pointer
+ set = e_regSetGPR;
+ reg = gpr_rsp;
+ break;
+
+ case GENERIC_REGNUM_FP: // Frame Pointer
+ set = e_regSetGPR;
+ reg = gpr_rbp;
+ break;
+
+ case GENERIC_REGNUM_FLAGS: // Processor flags register
+ set = e_regSetGPR;
+ reg = gpr_rflags;
+ break;
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) => %u", buf, (uint64_t)buf_len, size);
- // Return the size of the register context even if NULL was passed in
- return size;
-}
-
-nub_size_t
-DNBArchImplX86_64::SetRegisterContext (const void *buf, nub_size_t buf_len)
-{
- uint32_t size = GetRegisterContextSize();
- if (buf == NULL || buf_len == 0)
- size = 0;
-
- if (size)
- {
- if (size > buf_len)
- size = static_cast<uint32_t>(buf_len);
-
- uint8_t *p = (uint8_t *)buf;
- // Copy the GPR registers
- memcpy(&m_state.context.gpr, p, sizeof(GPR));
- p += sizeof(GPR);
-
- if (CPUHasAVX() || FORCE_AVX_REGS)
- {
- // Walk around the gaps in the FPU regs
- memcpy(&m_state.context.fpu.avx.__fpu_fcw, p, 5);
- p += 5;
- memcpy(&m_state.context.fpu.avx.__fpu_fop, p, 8);
- p += 8;
- memcpy(&m_state.context.fpu.avx.__fpu_dp, p, 6);
- p += 6;
- memcpy(&m_state.context.fpu.avx.__fpu_mxcsr, p, 8);
- p += 8;
-
- // Work around the padding between the stmm registers as they are 16
- // byte structs with 10 bytes of the value in each
- for (size_t i=0; i<8; ++i)
- {
- memcpy(&m_state.context.fpu.avx.__fpu_stmm0 + i, p, 10);
- p += 10;
- }
-
- // Interleave the XMM and YMMH registers to make the YMM registers
- for (size_t i=0; i<16; ++i)
- {
- memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16);
- p += 16;
- memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16);
- p += 16;
- }
- }
- else
- {
- // Copy fcw through mxcsrmask as there is no padding
- memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5);
- p += 5;
- memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8);
- p += 8;
- memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6);
- p += 6;
- memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8);
- p += 8;
-
- // Work around the padding between the stmm registers as they are 16
- // byte structs with 10 bytes of the value in each
- for (size_t i=0; i<8; ++i)
- {
- memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10);
- p += 10;
- }
-
- // Copy the XMM registers in a single block
- memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 16 * 16);
- p += 16 * 16;
- }
-
- // Copy the exception registers
- memcpy(&m_state.context.exc, p, sizeof(EXC));
- p += sizeof(EXC);
-
- // make sure we end up with exactly what we think we should have
- size_t bytes_written = p - (uint8_t *)buf;
- UNUSED_IF_ASSERT_DISABLED(bytes_written);
- assert (bytes_written == size);
-
- kern_return_t kret;
- if ((kret = SetGPRState()) != KERN_SUCCESS)
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) error: GPR regs failed to write: %u", buf, (uint64_t)buf_len, kret);
- if ((kret = SetFPUState()) != KERN_SUCCESS)
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) error: %s regs failed to write: %u", buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
- if ((kret = SetEXCState()) != KERN_SUCCESS)
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) error: EXP regs failed to write: %u", buf, (uint64_t)buf_len, kret);
+ case GENERIC_REGNUM_RA: // Return Address
+ default:
+ return false;
}
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size);
- return size;
-}
+ }
-uint32_t
-DNBArchImplX86_64::SaveRegisterState ()
-{
- kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());
- DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());
-
- // Always re-read the registers because above we call thread_abort_safely();
- bool force = true;
-
- if ((kret = GetGPRState(force)) != KERN_SUCCESS)
- {
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () error: GPR regs failed to read: %u ", kret);
- }
- else if ((kret = GetFPUState(force)) != KERN_SUCCESS)
- {
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () error: %s regs failed to read: %u", CPUHasAVX() ? "AVX" : "FPU", kret);
- }
- else
- {
- const uint32_t save_id = GetNextRegisterStateSaveID ();
- m_saved_register_states[save_id] = m_state.context;
- return save_id;
- }
- return 0;
-}
-bool
-DNBArchImplX86_64::RestoreRegisterState (uint32_t save_id)
-{
- SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id);
- if (pos != m_saved_register_states.end())
- {
- m_state.context.gpr = pos->second.gpr;
- m_state.context.fpu = pos->second.fpu;
- m_state.SetError(e_regSetGPR, Read, 0);
- m_state.SetError(e_regSetFPU, Read, 0);
- kern_return_t kret;
- bool success = true;
- if ((kret = SetGPRState()) != KERN_SUCCESS)
- {
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState (save_id = %u) error: GPR regs failed to write: %u", save_id, kret);
- success = false;
- }
- else if ((kret = SetFPUState()) != KERN_SUCCESS)
- {
- DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState (save_id = %u) error: %s regs failed to write: %u", save_id, CPUHasAVX() ? "AVX" : "FPU", kret);
- success = false;
- }
- m_saved_register_states.erase(pos);
- return success;
- }
+ if (GetRegisterState(set, false) != KERN_SUCCESS)
return false;
-}
-
-kern_return_t
-DNBArchImplX86_64::GetRegisterState(int set, bool force)
-{
- switch (set)
- {
- case e_regSetALL: return GetGPRState(force) | GetFPUState(force) | GetEXCState(force);
- case e_regSetGPR: return GetGPRState(force);
- case e_regSetFPU: return GetFPUState(force);
- case e_regSetEXC: return GetEXCState(force);
- default: break;
+ bool success = false;
+ const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
+ if (regInfo) {
+ switch (set) {
+ case e_regSetGPR:
+ if (reg < k_num_gpr_registers) {
+ ((uint64_t *)(&m_state.context.gpr))[reg] = value->value.uint64;
+ success = true;
+ }
+ break;
+
+ case e_regSetFPU:
+ if (CPUHasAVX() || FORCE_AVX_REGS) {
+ switch (reg) {
+ case fpu_fcw:
+ *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)) =
+ value->value.uint16;
+ success = true;
+ break;
+ case fpu_fsw:
+ *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)) =
+ value->value.uint16;
+ success = true;
+ break;
+ case fpu_ftw:
+ m_state.context.fpu.avx.__fpu_ftw = value->value.uint8;
+ success = true;
+ break;
+ case fpu_fop:
+ m_state.context.fpu.avx.__fpu_fop = value->value.uint16;
+ success = true;
+ break;
+ case fpu_ip:
+ m_state.context.fpu.avx.__fpu_ip = value->value.uint32;
+ success = true;
+ break;
+ case fpu_cs:
+ m_state.context.fpu.avx.__fpu_cs = value->value.uint16;
+ success = true;
+ break;
+ case fpu_dp:
+ m_state.context.fpu.avx.__fpu_dp = value->value.uint32;
+ success = true;
+ break;
+ case fpu_ds:
+ m_state.context.fpu.avx.__fpu_ds = value->value.uint16;
+ success = true;
+ break;
+ case fpu_mxcsr:
+ m_state.context.fpu.avx.__fpu_mxcsr = value->value.uint32;
+ success = true;
+ break;
+ case fpu_mxcsrmask:
+ m_state.context.fpu.avx.__fpu_mxcsrmask = value->value.uint32;
+ success = true;
+ break;
+
+ case fpu_stmm0:
+ case fpu_stmm1:
+ case fpu_stmm2:
+ case fpu_stmm3:
+ case fpu_stmm4:
+ case fpu_stmm5:
+ case fpu_stmm6:
+ case fpu_stmm7:
+ memcpy(&m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0),
+ &value->value.uint8, 10);
+ success = true;
+ break;
+
+ case fpu_xmm0:
+ case fpu_xmm1:
+ case fpu_xmm2:
+ case fpu_xmm3:
+ case fpu_xmm4:
+ case fpu_xmm5:
+ case fpu_xmm6:
+ case fpu_xmm7:
+ case fpu_xmm8:
+ case fpu_xmm9:
+ case fpu_xmm10:
+ case fpu_xmm11:
+ case fpu_xmm12:
+ case fpu_xmm13:
+ case fpu_xmm14:
+ case fpu_xmm15:
+ memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0),
+ &value->value.uint8, 16);
+ success = true;
+ break;
+
+ case fpu_ymm0:
+ case fpu_ymm1:
+ case fpu_ymm2:
+ case fpu_ymm3:
+ case fpu_ymm4:
+ case fpu_ymm5:
+ case fpu_ymm6:
+ case fpu_ymm7:
+ case fpu_ymm8:
+ case fpu_ymm9:
+ case fpu_ymm10:
+ case fpu_ymm11:
+ case fpu_ymm12:
+ case fpu_ymm13:
+ case fpu_ymm14:
+ case fpu_ymm15:
+ memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0),
+ &value->value.uint8, 16);
+ memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0),
+ (&value->value.uint8) + 16, 16);
+ return true;
+ }
+ } else {
+ switch (reg) {
+ case fpu_fcw:
+ *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) =
+ value->value.uint16;
+ success = true;
+ break;
+ case fpu_fsw:
+ *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) =
+ value->value.uint16;
+ success = true;
+ break;
+ case fpu_ftw:
+ m_state.context.fpu.no_avx.__fpu_ftw = value->value.uint8;
+ success = true;
+ break;
+ case fpu_fop:
+ m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16;
+ success = true;
+ break;
+ case fpu_ip:
+ m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32;
+ success = true;
+ break;
+ case fpu_cs:
+ m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16;
+ success = true;
+ break;
+ case fpu_dp:
+ m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32;
+ success = true;
+ break;
+ case fpu_ds:
+ m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16;
+ success = true;
+ break;
+ case fpu_mxcsr:
+ m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32;
+ success = true;
+ break;
+ case fpu_mxcsrmask:
+ m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32;
+ success = true;
+ break;
+
+ case fpu_stmm0:
+ case fpu_stmm1:
+ case fpu_stmm2:
+ case fpu_stmm3:
+ case fpu_stmm4:
+ case fpu_stmm5:
+ case fpu_stmm6:
+ case fpu_stmm7:
+ memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0),
+ &value->value.uint8, 10);
+ success = true;
+ break;
+
+ case fpu_xmm0:
+ case fpu_xmm1:
+ case fpu_xmm2:
+ case fpu_xmm3:
+ case fpu_xmm4:
+ case fpu_xmm5:
+ case fpu_xmm6:
+ case fpu_xmm7:
+ case fpu_xmm8:
+ case fpu_xmm9:
+ case fpu_xmm10:
+ case fpu_xmm11:
+ case fpu_xmm12:
+ case fpu_xmm13:
+ case fpu_xmm14:
+ case fpu_xmm15:
+ memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0),
+ &value->value.uint8, 16);
+ success = true;
+ break;
+ }
+ }
+ break;
+
+ case e_regSetEXC:
+ switch (reg) {
+ case exc_trapno:
+ m_state.context.exc.__trapno = value->value.uint32;
+ success = true;
+ break;
+ case exc_err:
+ m_state.context.exc.__err = value->value.uint32;
+ success = true;
+ break;
+ case exc_faultvaddr:
+ m_state.context.exc.__faultvaddr = value->value.uint64;
+ success = true;
+ break;
+ }
+ break;
+ }
+ }
+
+ if (success)
+ return SetRegisterState(set) == KERN_SUCCESS;
+ return false;
+}
+
+uint32_t DNBArchImplX86_64::GetRegisterContextSize() {
+ static uint32_t g_cached_size = 0;
+ if (g_cached_size == 0) {
+ if (CPUHasAVX() || FORCE_AVX_REGS) {
+ for (size_t i = 0; i < k_num_fpu_registers_avx; ++i) {
+ if (g_fpu_registers_avx[i].value_regs == NULL)
+ g_cached_size += g_fpu_registers_avx[i].size;
+ }
+ } else {
+ for (size_t i = 0; i < k_num_fpu_registers_no_avx; ++i) {
+ if (g_fpu_registers_no_avx[i].value_regs == NULL)
+ g_cached_size += g_fpu_registers_no_avx[i].size;
+ }
+ }
+ DNBLogThreaded("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, "
+ "FPU = %u, EXC = %zu",
+ sizeof(GPR), g_cached_size, sizeof(EXC));
+ g_cached_size += sizeof(GPR);
+ g_cached_size += sizeof(EXC);
+ DNBLogThreaded(
+ "DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u",
+ g_cached_size);
+ }
+ return g_cached_size;
+}
+
+nub_size_t DNBArchImplX86_64::GetRegisterContext(void *buf,
+ nub_size_t buf_len) {
+ uint32_t size = GetRegisterContextSize();
+
+ if (buf && buf_len) {
+ bool force = false;
+ kern_return_t kret;
+
+ if ((kret = GetGPRState(force)) != KERN_SUCCESS) {
+ DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf "
+ "= %p, len = %llu) error: GPR regs failed "
+ "to read: %u ",
+ buf, (uint64_t)buf_len, kret);
+ size = 0;
+ } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) {
+ DNBLogThreadedIf(
+ LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = "
+ "%llu) error: %s regs failed to read: %u",
+ buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
+ size = 0;
+ } else if ((kret = GetEXCState(force)) != KERN_SUCCESS) {
+ DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf "
+ "= %p, len = %llu) error: EXC regs failed "
+ "to read: %u",
+ buf, (uint64_t)buf_len, kret);
+ size = 0;
+ } else {
+ uint8_t *p = (uint8_t *)buf;
+ // Copy the GPR registers
+ memcpy(p, &m_state.context.gpr, sizeof(GPR));
+ p += sizeof(GPR);
+
+ if (CPUHasAVX() || FORCE_AVX_REGS) {
+ // Walk around the gaps in the FPU regs
+ memcpy(p, &m_state.context.fpu.avx.__fpu_fcw, 5);
+ p += 5;
+ memcpy(p, &m_state.context.fpu.avx.__fpu_fop, 8);
+ p += 8;
+ memcpy(p, &m_state.context.fpu.avx.__fpu_dp, 6);
+ p += 6;
+ memcpy(p, &m_state.context.fpu.avx.__fpu_mxcsr, 8);
+ p += 8;
+
+ // Work around the padding between the stmm registers as they are 16
+ // byte structs with 10 bytes of the value in each
+ for (size_t i = 0; i < 8; ++i) {
+ memcpy(p, &m_state.context.fpu.avx.__fpu_stmm0 + i, 10);
+ p += 10;
+ }
+
+ // Interleave the XMM and YMMH registers to make the YMM registers
+ for (size_t i = 0; i < 16; ++i) {
+ memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16);
+ p += 16;
+ memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16);
+ p += 16;
+ }
+ } else {
+ // Walk around the gaps in the FPU regs
+ memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5);
+ p += 5;
+ memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8);
+ p += 8;
+ memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6);
+ p += 6;
+ memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8);
+ p += 8;
+
+ // Work around the padding between the stmm registers as they are 16
+ // byte structs with 10 bytes of the value in each
+ for (size_t i = 0; i < 8; ++i) {
+ memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10);
+ p += 10;
+ }
+
+ // Copy the XMM registers in a single block
+ memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 16 * 16);
+ p += 16 * 16;
+ }
+
+ // Copy the exception registers
+ memcpy(p, &m_state.context.exc, sizeof(EXC));
+ p += sizeof(EXC);
+
+ // make sure we end up with exactly what we think we should have
+ size_t bytes_written = p - (uint8_t *)buf;
+ UNUSED_IF_ASSERT_DISABLED(bytes_written);
+ assert(bytes_written == size);
+ }
+ }
+
+ DNBLogThreadedIf(
+ LOG_THREAD,
+ "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) => %u", buf,
+ (uint64_t)buf_len, size);
+ // Return the size of the register context even if NULL was passed in
+ return size;
+}
+
+nub_size_t DNBArchImplX86_64::SetRegisterContext(const void *buf,
+ nub_size_t buf_len) {
+ uint32_t size = GetRegisterContextSize();
+ if (buf == NULL || buf_len == 0)
+ size = 0;
+
+ if (size) {
+ if (size > buf_len)
+ size = static_cast<uint32_t>(buf_len);
+
+ uint8_t *p = (uint8_t *)buf;
+ // Copy the GPR registers
+ memcpy(&m_state.context.gpr, p, sizeof(GPR));
+ p += sizeof(GPR);
+
+ if (CPUHasAVX() || FORCE_AVX_REGS) {
+ // Walk around the gaps in the FPU regs
+ memcpy(&m_state.context.fpu.avx.__fpu_fcw, p, 5);
+ p += 5;
+ memcpy(&m_state.context.fpu.avx.__fpu_fop, p, 8);
+ p += 8;
+ memcpy(&m_state.context.fpu.avx.__fpu_dp, p, 6);
+ p += 6;
+ memcpy(&m_state.context.fpu.avx.__fpu_mxcsr, p, 8);
+ p += 8;
+
+ // Work around the padding between the stmm registers as they are 16
+ // byte structs with 10 bytes of the value in each
+ for (size_t i = 0; i < 8; ++i) {
+ memcpy(&m_state.context.fpu.avx.__fpu_stmm0 + i, p, 10);
+ p += 10;
+ }
+
+ // Interleave the XMM and YMMH registers to make the YMM registers
+ for (size_t i = 0; i < 16; ++i) {
+ memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16);
+ p += 16;
+ memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16);
+ p += 16;
+ }
+ } else {
+ // Copy fcw through mxcsrmask as there is no padding
+ memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5);
+ p += 5;
+ memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8);
+ p += 8;
+ memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6);
+ p += 6;
+ memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8);
+ p += 8;
+
+ // Work around the padding between the stmm registers as they are 16
+ // byte structs with 10 bytes of the value in each
+ for (size_t i = 0; i < 8; ++i) {
+ memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10);
+ p += 10;
+ }
+
+ // Copy the XMM registers in a single block
+ memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 16 * 16);
+ p += 16 * 16;
+ }
+
+ // Copy the exception registers
+ memcpy(&m_state.context.exc, p, sizeof(EXC));
+ p += sizeof(EXC);
+
+ // make sure we end up with exactly what we think we should have
+ size_t bytes_written = p - (uint8_t *)buf;
+ UNUSED_IF_ASSERT_DISABLED(bytes_written);
+ assert(bytes_written == size);
+
+ kern_return_t kret;
+ if ((kret = SetGPRState()) != KERN_SUCCESS)
+ DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf "
+ "= %p, len = %llu) error: GPR regs failed "
+ "to write: %u",
+ buf, (uint64_t)buf_len, kret);
+ if ((kret = SetFPUState()) != KERN_SUCCESS)
+ DNBLogThreadedIf(
+ LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = "
+ "%llu) error: %s regs failed to write: %u",
+ buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
+ if ((kret = SetEXCState()) != KERN_SUCCESS)
+ DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf "
+ "= %p, len = %llu) error: EXP regs failed "
+ "to write: %u",
+ buf, (uint64_t)buf_len, kret);
+ }
+ DNBLogThreadedIf(
+ LOG_THREAD,
+ "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) => %llu",
+ buf, (uint64_t)buf_len, (uint64_t)size);
+ return size;
+}
+
+uint32_t DNBArchImplX86_64::SaveRegisterState() {
+ kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());
+ DNBLogThreadedIf(
+ LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u "
+ "(SetGPRState() for stop_count = %u)",
+ m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());
+
+ // Always re-read the registers because above we call thread_abort_safely();
+ bool force = true;
+
+ if ((kret = GetGPRState(force)) != KERN_SUCCESS) {
+ DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () "
+ "error: GPR regs failed to read: %u ",
+ kret);
+ } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) {
+ DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () "
+ "error: %s regs failed to read: %u",
+ CPUHasAVX() ? "AVX" : "FPU", kret);
+ } else {
+ const uint32_t save_id = GetNextRegisterStateSaveID();
+ m_saved_register_states[save_id] = m_state.context;
+ return save_id;
+ }
+ return 0;
+}
+bool DNBArchImplX86_64::RestoreRegisterState(uint32_t save_id) {
+ SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id);
+ if (pos != m_saved_register_states.end()) {
+ m_state.context.gpr = pos->second.gpr;
+ m_state.context.fpu = pos->second.fpu;
+ m_state.SetError(e_regSetGPR, Read, 0);
+ m_state.SetError(e_regSetFPU, Read, 0);
+ kern_return_t kret;
+ bool success = true;
+ if ((kret = SetGPRState()) != KERN_SUCCESS) {
+ DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState "
+ "(save_id = %u) error: GPR regs failed to "
+ "write: %u",
+ save_id, kret);
+ success = false;
+ } else if ((kret = SetFPUState()) != KERN_SUCCESS) {
+ DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState "
+ "(save_id = %u) error: %s regs failed to "
+ "write: %u",
+ save_id, CPUHasAVX() ? "AVX" : "FPU", kret);
+ success = false;
}
- return KERN_INVALID_ARGUMENT;
+ m_saved_register_states.erase(pos);
+ return success;
+ }
+ return false;
}
-kern_return_t
-DNBArchImplX86_64::SetRegisterState(int set)
-{
- // Make sure we have a valid context to set.
- if (RegisterSetStateIsValid(set))
- {
- switch (set)
- {
- case e_regSetALL: return SetGPRState() | SetFPUState() | SetEXCState();
- case e_regSetGPR: return SetGPRState();
- case e_regSetFPU: return SetFPUState();
- case e_regSetEXC: return SetEXCState();
- default: break;
- }
+kern_return_t DNBArchImplX86_64::GetRegisterState(int set, bool force) {
+ switch (set) {
+ case e_regSetALL:
+ return GetGPRState(force) | GetFPUState(force) | GetEXCState(force);
+ case e_regSetGPR:
+ return GetGPRState(force);
+ case e_regSetFPU:
+ return GetFPUState(force);
+ case e_regSetEXC:
+ return GetEXCState(force);
+ default:
+ break;
+ }
+ return KERN_INVALID_ARGUMENT;
+}
+
+kern_return_t DNBArchImplX86_64::SetRegisterState(int set) {
+ // Make sure we have a valid context to set.
+ if (RegisterSetStateIsValid(set)) {
+ switch (set) {
+ case e_regSetALL:
+ return SetGPRState() | SetFPUState() | SetEXCState();
+ case e_regSetGPR:
+ return SetGPRState();
+ case e_regSetFPU:
+ return SetFPUState();
+ case e_regSetEXC:
+ return SetEXCState();
+ default:
+ break;
}
- return KERN_INVALID_ARGUMENT;
+ }
+ return KERN_INVALID_ARGUMENT;
}
-bool
-DNBArchImplX86_64::RegisterSetStateIsValid (int set) const
-{
- return m_state.RegsAreValid(set);
+bool DNBArchImplX86_64::RegisterSetStateIsValid(int set) const {
+ return m_state.RegsAreValid(set);
}
-
-
-#endif // #if defined (__i386__) || defined (__x86_64__)
+#endif // #if defined (__i386__) || defined (__x86_64__)
Modified: lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h Tue Sep 6 15:57:50 2016
@@ -14,7 +14,7 @@
#ifndef __DNBArchImplX86_64_h__
#define __DNBArchImplX86_64_h__
-#if defined (__i386__) || defined (__x86_64__)
+#if defined(__i386__) || defined(__x86_64__)
#include "DNBArch.h"
#include "MachRegisterStatesX86_64.h"
@@ -22,239 +22,213 @@
class MachThread;
-class DNBArchImplX86_64 : public DNBArchProtocol
-{
+class DNBArchImplX86_64 : public DNBArchProtocol {
public:
- DNBArchImplX86_64(MachThread *thread) :
- DNBArchProtocol(),
- m_thread(thread),
- m_state(),
- m_2pc_dbg_checkpoint(),
- m_2pc_trans_state(Trans_Done),
- m_saved_register_states()
- {
- }
- virtual ~DNBArchImplX86_64()
- {
- }
-
- static void Initialize();
-
- virtual bool GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value);
- virtual bool SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value);
- virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len);
- virtual nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len);
- virtual uint32_t SaveRegisterState ();
- virtual bool RestoreRegisterState (uint32_t save_id);
-
- virtual kern_return_t GetRegisterState (int set, bool force);
- virtual kern_return_t SetRegisterState (int set);
- virtual bool RegisterSetStateIsValid (int set) const;
-
- virtual uint64_t GetPC(uint64_t failValue); // Get program counter
- virtual kern_return_t SetPC(uint64_t value);
- virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer
- virtual void ThreadWillResume();
- virtual bool ThreadDidStop();
- virtual bool NotifyException(MachException::Data& exc);
-
- virtual uint32_t NumSupportedHardwareWatchpoints();
- virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task);
- virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index, bool also_set_on_task);
- virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr);
+ DNBArchImplX86_64(MachThread *thread)
+ : DNBArchProtocol(), m_thread(thread), m_state(), m_2pc_dbg_checkpoint(),
+ m_2pc_trans_state(Trans_Done), m_saved_register_states() {}
+ virtual ~DNBArchImplX86_64() {}
+
+ static void Initialize();
+
+ virtual bool GetRegisterValue(uint32_t set, uint32_t reg,
+ DNBRegisterValue *value);
+ virtual bool SetRegisterValue(uint32_t set, uint32_t reg,
+ const DNBRegisterValue *value);
+ virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len);
+ virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len);
+ virtual uint32_t SaveRegisterState();
+ virtual bool RestoreRegisterState(uint32_t save_id);
+
+ virtual kern_return_t GetRegisterState(int set, bool force);
+ virtual kern_return_t SetRegisterState(int set);
+ virtual bool RegisterSetStateIsValid(int set) const;
+
+ virtual uint64_t GetPC(uint64_t failValue); // Get program counter
+ virtual kern_return_t SetPC(uint64_t value);
+ virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer
+ virtual void ThreadWillResume();
+ virtual bool ThreadDidStop();
+ virtual bool NotifyException(MachException::Data &exc);
+
+ virtual uint32_t NumSupportedHardwareWatchpoints();
+ virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size,
+ bool read, bool write,
+ bool also_set_on_task);
+ virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index,
+ bool also_set_on_task);
+ virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr);
protected:
- kern_return_t EnableHardwareSingleStep (bool enable);
+ kern_return_t EnableHardwareSingleStep(bool enable);
- typedef __x86_64_thread_state_t GPR;
- typedef __x86_64_float_state_t FPU;
- typedef __x86_64_exception_state_t EXC;
- typedef __x86_64_avx_state_t AVX;
- typedef __x86_64_debug_state_t DBG;
-
- static const DNBRegisterInfo g_gpr_registers[];
- static const DNBRegisterInfo g_fpu_registers_no_avx[];
- static const DNBRegisterInfo g_fpu_registers_avx[];
- static const DNBRegisterInfo g_exc_registers[];
- static const DNBRegisterSetInfo g_reg_sets_no_avx[];
- static const DNBRegisterSetInfo g_reg_sets_avx[];
- static const size_t k_num_gpr_registers;
- static const size_t k_num_fpu_registers_no_avx;
- static const size_t k_num_fpu_registers_avx;
- static const size_t k_num_exc_registers;
- static const size_t k_num_all_registers_no_avx;
- static const size_t k_num_all_registers_avx;
- static const size_t k_num_register_sets;
-
- typedef enum RegisterSetTag
- {
- e_regSetALL = REGISTER_SET_ALL,
- e_regSetGPR,
- e_regSetFPU,
- e_regSetEXC,
- e_regSetDBG,
- kNumRegisterSets
- } RegisterSet;
-
- typedef enum RegisterSetWordSizeTag
- {
- e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int),
- e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int),
- e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int),
- e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int),
- e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int)
- } RegisterSetWordSize;
-
- enum
- {
- Read = 0,
- Write = 1,
- kNumErrors = 2
- };
-
- struct Context
- {
- GPR gpr;
- union {
- FPU no_avx;
- AVX avx;
- } fpu;
- EXC exc;
- DBG dbg;
- };
-
- struct State
- {
- Context context;
- kern_return_t gpr_errs[2]; // Read/Write errors
- kern_return_t fpu_errs[2]; // Read/Write errors
- kern_return_t exc_errs[2]; // Read/Write errors
- kern_return_t dbg_errs[2]; // Read/Write errors
-
- State()
- {
- uint32_t i;
- for (i=0; i<kNumErrors; i++)
- {
- gpr_errs[i] = -1;
- fpu_errs[i] = -1;
- exc_errs[i] = -1;
- dbg_errs[i] = -1;
- }
- }
-
- void
- InvalidateAllRegisterStates()
- {
- SetError (e_regSetALL, Read, -1);
- }
+ typedef __x86_64_thread_state_t GPR;
+ typedef __x86_64_float_state_t FPU;
+ typedef __x86_64_exception_state_t EXC;
+ typedef __x86_64_avx_state_t AVX;
+ typedef __x86_64_debug_state_t DBG;
+
+ static const DNBRegisterInfo g_gpr_registers[];
+ static const DNBRegisterInfo g_fpu_registers_no_avx[];
+ static const DNBRegisterInfo g_fpu_registers_avx[];
+ static const DNBRegisterInfo g_exc_registers[];
+ static const DNBRegisterSetInfo g_reg_sets_no_avx[];
+ static const DNBRegisterSetInfo g_reg_sets_avx[];
+ static const size_t k_num_gpr_registers;
+ static const size_t k_num_fpu_registers_no_avx;
+ static const size_t k_num_fpu_registers_avx;
+ static const size_t k_num_exc_registers;
+ static const size_t k_num_all_registers_no_avx;
+ static const size_t k_num_all_registers_avx;
+ static const size_t k_num_register_sets;
+
+ typedef enum RegisterSetTag {
+ e_regSetALL = REGISTER_SET_ALL,
+ e_regSetGPR,
+ e_regSetFPU,
+ e_regSetEXC,
+ e_regSetDBG,
+ kNumRegisterSets
+ } RegisterSet;
+
+ typedef enum RegisterSetWordSizeTag {
+ e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int),
+ e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int),
+ e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int),
+ e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int),
+ e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int)
+ } RegisterSetWordSize;
+
+ enum { Read = 0, Write = 1, kNumErrors = 2 };
+
+ struct Context {
+ GPR gpr;
+ union {
+ FPU no_avx;
+ AVX avx;
+ } fpu;
+ EXC exc;
+ DBG dbg;
+ };
+
+ struct State {
+ Context context;
+ kern_return_t gpr_errs[2]; // Read/Write errors
+ kern_return_t fpu_errs[2]; // Read/Write errors
+ kern_return_t exc_errs[2]; // Read/Write errors
+ kern_return_t dbg_errs[2]; // Read/Write errors
+
+ State() {
+ uint32_t i;
+ for (i = 0; i < kNumErrors; i++) {
+ gpr_errs[i] = -1;
+ fpu_errs[i] = -1;
+ exc_errs[i] = -1;
+ dbg_errs[i] = -1;
+ }
+ }
- kern_return_t
- GetError (int flavor, uint32_t err_idx) const
- {
- if (err_idx < kNumErrors)
- {
- switch (flavor)
- {
- // When getting all errors, just OR all values together to see if
- // we got any kind of error.
- case e_regSetALL: return gpr_errs[err_idx] |
- fpu_errs[err_idx] |
- exc_errs[err_idx];
- case e_regSetGPR: return gpr_errs[err_idx];
- case e_regSetFPU: return fpu_errs[err_idx];
- case e_regSetEXC: return exc_errs[err_idx];
- case e_regSetDBG: return dbg_errs[err_idx];
- default: break;
- }
- }
- return -1;
- }
+ void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); }
- bool
- SetError (int flavor, uint32_t err_idx, kern_return_t err)
- {
- if (err_idx < kNumErrors)
- {
- switch (flavor)
- {
- case e_regSetALL:
- gpr_errs[err_idx] =
- fpu_errs[err_idx] =
- exc_errs[err_idx] =
- dbg_errs[err_idx] = err;
- return true;
-
- case e_regSetGPR:
- gpr_errs[err_idx] = err;
- return true;
-
- case e_regSetFPU:
- fpu_errs[err_idx] = err;
- return true;
-
- case e_regSetEXC:
- exc_errs[err_idx] = err;
- return true;
-
- case e_regSetDBG:
- dbg_errs[err_idx] = err;
- return true;
-
- default: break;
- }
- }
- return false;
+ kern_return_t GetError(int flavor, uint32_t err_idx) const {
+ if (err_idx < kNumErrors) {
+ switch (flavor) {
+ // When getting all errors, just OR all values together to see if
+ // we got any kind of error.
+ case e_regSetALL:
+ return gpr_errs[err_idx] | fpu_errs[err_idx] | exc_errs[err_idx];
+ case e_regSetGPR:
+ return gpr_errs[err_idx];
+ case e_regSetFPU:
+ return fpu_errs[err_idx];
+ case e_regSetEXC:
+ return exc_errs[err_idx];
+ case e_regSetDBG:
+ return dbg_errs[err_idx];
+ default:
+ break;
}
+ }
+ return -1;
+ }
+
+ bool SetError(int flavor, uint32_t err_idx, kern_return_t err) {
+ if (err_idx < kNumErrors) {
+ switch (flavor) {
+ case e_regSetALL:
+ gpr_errs[err_idx] = fpu_errs[err_idx] = exc_errs[err_idx] =
+ dbg_errs[err_idx] = err;
+ return true;
+
+ case e_regSetGPR:
+ gpr_errs[err_idx] = err;
+ return true;
+
+ case e_regSetFPU:
+ fpu_errs[err_idx] = err;
+ return true;
+
+ case e_regSetEXC:
+ exc_errs[err_idx] = err;
+ return true;
+
+ case e_regSetDBG:
+ dbg_errs[err_idx] = err;
+ return true;
- bool
- RegsAreValid (int flavor) const
- {
- return GetError(flavor, Read) == KERN_SUCCESS;
+ default:
+ break;
}
- };
+ }
+ return false;
+ }
+
+ bool RegsAreValid(int flavor) const {
+ return GetError(flavor, Read) == KERN_SUCCESS;
+ }
+ };
- kern_return_t GetGPRState (bool force);
- kern_return_t GetFPUState (bool force);
- kern_return_t GetEXCState (bool force);
- kern_return_t GetDBGState (bool force);
-
- kern_return_t SetGPRState ();
- kern_return_t SetFPUState ();
- kern_return_t SetEXCState ();
- kern_return_t SetDBGState (bool also_set_on_task);
-
- static DNBArchProtocol *
- Create (MachThread *thread);
-
- static const uint8_t *
- SoftwareBreakpointOpcode (nub_size_t byte_size);
-
- static const DNBRegisterSetInfo *
- GetRegisterSetInfo(nub_size_t *num_reg_sets);
-
- static uint32_t GetRegisterContextSize();
-
- // Helper functions for watchpoint manipulations.
- static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write);
- static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index);
- static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index);
- static void ClearWatchpointHits(DBG &debug_state);
- static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index);
- static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index);
-
- virtual bool StartTransForHWP();
- virtual bool RollbackTransForHWP();
- virtual bool FinishTransForHWP();
- DBG GetDBGCheckpoint();
-
- MachThread *m_thread;
- State m_state;
- DBG m_2pc_dbg_checkpoint;
- uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning (0), Done (1), or Rolled Back (2)?
- typedef std::map<uint32_t, Context> SaveRegisterStates;
- SaveRegisterStates m_saved_register_states;
+ kern_return_t GetGPRState(bool force);
+ kern_return_t GetFPUState(bool force);
+ kern_return_t GetEXCState(bool force);
+ kern_return_t GetDBGState(bool force);
+
+ kern_return_t SetGPRState();
+ kern_return_t SetFPUState();
+ kern_return_t SetEXCState();
+ kern_return_t SetDBGState(bool also_set_on_task);
+
+ static DNBArchProtocol *Create(MachThread *thread);
+
+ static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size);
+
+ static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets);
+
+ static uint32_t GetRegisterContextSize();
+
+ // Helper functions for watchpoint manipulations.
+ static void SetWatchpoint(DBG &debug_state, uint32_t hw_index,
+ nub_addr_t addr, nub_size_t size, bool read,
+ bool write);
+ static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index);
+ static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index);
+ static void ClearWatchpointHits(DBG &debug_state);
+ static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index);
+ static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index);
+
+ virtual bool StartTransForHWP();
+ virtual bool RollbackTransForHWP();
+ virtual bool FinishTransForHWP();
+ DBG GetDBGCheckpoint();
+
+ MachThread *m_thread;
+ State m_state;
+ DBG m_2pc_dbg_checkpoint;
+ uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning
+ // (0), Done (1), or Rolled Back (2)?
+ typedef std::map<uint32_t, Context> SaveRegisterStates;
+ SaveRegisterStates m_saved_register_states;
};
-#endif // #if defined (__i386__) || defined (__x86_64__)
-#endif // #ifndef __DNBArchImplX86_64_h__
+#endif // #if defined (__i386__) || defined (__x86_64__)
+#endif // #ifndef __DNBArchImplX86_64_h__
Modified: lldb/trunk/tools/debugserver/source/MacOSX/x86_64/MachRegisterStatesX86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/x86_64/MachRegisterStatesX86_64.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/x86_64/MachRegisterStatesX86_64.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/x86_64/MachRegisterStatesX86_64.h Tue Sep 6 15:57:50 2016
@@ -1,4 +1,5 @@
-//===-- MachRegisterStatesX86_64.h --------------------------------*- C++ -*-===//
+//===-- MachRegisterStatesX86_64.h --------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,195 +17,192 @@
#include <inttypes.h>
-#define __x86_64_THREAD_STATE 4
-#define __x86_64_FLOAT_STATE 5
-#define __x86_64_EXCEPTION_STATE 6
-#define __x86_64_DEBUG_STATE 11
-#define __x86_64_AVX_STATE 17
-
-typedef struct {
- uint64_t __rax;
- uint64_t __rbx;
- uint64_t __rcx;
- uint64_t __rdx;
- uint64_t __rdi;
- uint64_t __rsi;
- uint64_t __rbp;
- uint64_t __rsp;
- uint64_t __r8;
- uint64_t __r9;
- uint64_t __r10;
- uint64_t __r11;
- uint64_t __r12;
- uint64_t __r13;
- uint64_t __r14;
- uint64_t __r15;
- uint64_t __rip;
- uint64_t __rflags;
- uint64_t __cs;
- uint64_t __fs;
- uint64_t __gs;
+#define __x86_64_THREAD_STATE 4
+#define __x86_64_FLOAT_STATE 5
+#define __x86_64_EXCEPTION_STATE 6
+#define __x86_64_DEBUG_STATE 11
+#define __x86_64_AVX_STATE 17
+
+typedef struct {
+ uint64_t __rax;
+ uint64_t __rbx;
+ uint64_t __rcx;
+ uint64_t __rdx;
+ uint64_t __rdi;
+ uint64_t __rsi;
+ uint64_t __rbp;
+ uint64_t __rsp;
+ uint64_t __r8;
+ uint64_t __r9;
+ uint64_t __r10;
+ uint64_t __r11;
+ uint64_t __r12;
+ uint64_t __r13;
+ uint64_t __r14;
+ uint64_t __r15;
+ uint64_t __rip;
+ uint64_t __rflags;
+ uint64_t __cs;
+ uint64_t __fs;
+ uint64_t __gs;
} __x86_64_thread_state_t;
typedef struct {
- uint16_t __invalid : 1;
- uint16_t __denorm : 1;
- uint16_t __zdiv : 1;
- uint16_t __ovrfl : 1;
- uint16_t __undfl : 1;
- uint16_t __precis : 1;
- uint16_t __PAD1 : 2;
- uint16_t __pc : 2;
- uint16_t __rc : 2;
- uint16_t __PAD2 : 1;
- uint16_t __PAD3 : 3;
+ uint16_t __invalid : 1;
+ uint16_t __denorm : 1;
+ uint16_t __zdiv : 1;
+ uint16_t __ovrfl : 1;
+ uint16_t __undfl : 1;
+ uint16_t __precis : 1;
+ uint16_t __PAD1 : 2;
+ uint16_t __pc : 2;
+ uint16_t __rc : 2;
+ uint16_t __PAD2 : 1;
+ uint16_t __PAD3 : 3;
} __x86_64_fp_control_t;
typedef struct {
- uint16_t __invalid : 1;
- uint16_t __denorm : 1;
- uint16_t __zdiv : 1;
- uint16_t __ovrfl : 1;
- uint16_t __undfl : 1;
- uint16_t __precis : 1;
- uint16_t __stkflt : 1;
- uint16_t __errsumm : 1;
- uint16_t __c0 : 1;
- uint16_t __c1 : 1;
- uint16_t __c2 : 1;
- uint16_t __tos : 3;
- uint16_t __c3 : 1;
- uint16_t __busy : 1;
+ uint16_t __invalid : 1;
+ uint16_t __denorm : 1;
+ uint16_t __zdiv : 1;
+ uint16_t __ovrfl : 1;
+ uint16_t __undfl : 1;
+ uint16_t __precis : 1;
+ uint16_t __stkflt : 1;
+ uint16_t __errsumm : 1;
+ uint16_t __c0 : 1;
+ uint16_t __c1 : 1;
+ uint16_t __c2 : 1;
+ uint16_t __tos : 3;
+ uint16_t __c3 : 1;
+ uint16_t __busy : 1;
} __x86_64_fp_status_t;
typedef struct {
- uint8_t __mmst_reg[10];
- uint8_t __mmst_rsrv[6];
+ uint8_t __mmst_reg[10];
+ uint8_t __mmst_rsrv[6];
} __x86_64_mmst_reg;
-typedef struct {
- uint8_t __xmm_reg[16];
-} __x86_64_xmm_reg;
+typedef struct { uint8_t __xmm_reg[16]; } __x86_64_xmm_reg;
typedef struct {
- int32_t __fpu_reserved[2];
- __x86_64_fp_control_t __fpu_fcw;
- __x86_64_fp_status_t __fpu_fsw;
- uint8_t __fpu_ftw;
- uint8_t __fpu_rsrv1;
- uint16_t __fpu_fop;
- uint32_t __fpu_ip;
- uint16_t __fpu_cs;
- uint16_t __fpu_rsrv2;
- uint32_t __fpu_dp;
- uint16_t __fpu_ds;
- uint16_t __fpu_rsrv3;
- uint32_t __fpu_mxcsr;
- uint32_t __fpu_mxcsrmask;
- __x86_64_mmst_reg __fpu_stmm0;
- __x86_64_mmst_reg __fpu_stmm1;
- __x86_64_mmst_reg __fpu_stmm2;
- __x86_64_mmst_reg __fpu_stmm3;
- __x86_64_mmst_reg __fpu_stmm4;
- __x86_64_mmst_reg __fpu_stmm5;
- __x86_64_mmst_reg __fpu_stmm6;
- __x86_64_mmst_reg __fpu_stmm7;
- __x86_64_xmm_reg __fpu_xmm0;
- __x86_64_xmm_reg __fpu_xmm1;
- __x86_64_xmm_reg __fpu_xmm2;
- __x86_64_xmm_reg __fpu_xmm3;
- __x86_64_xmm_reg __fpu_xmm4;
- __x86_64_xmm_reg __fpu_xmm5;
- __x86_64_xmm_reg __fpu_xmm6;
- __x86_64_xmm_reg __fpu_xmm7;
- __x86_64_xmm_reg __fpu_xmm8;
- __x86_64_xmm_reg __fpu_xmm9;
- __x86_64_xmm_reg __fpu_xmm10;
- __x86_64_xmm_reg __fpu_xmm11;
- __x86_64_xmm_reg __fpu_xmm12;
- __x86_64_xmm_reg __fpu_xmm13;
- __x86_64_xmm_reg __fpu_xmm14;
- __x86_64_xmm_reg __fpu_xmm15;
- uint8_t __fpu_rsrv4[6*16];
- int32_t __fpu_reserved1;
+ int32_t __fpu_reserved[2];
+ __x86_64_fp_control_t __fpu_fcw;
+ __x86_64_fp_status_t __fpu_fsw;
+ uint8_t __fpu_ftw;
+ uint8_t __fpu_rsrv1;
+ uint16_t __fpu_fop;
+ uint32_t __fpu_ip;
+ uint16_t __fpu_cs;
+ uint16_t __fpu_rsrv2;
+ uint32_t __fpu_dp;
+ uint16_t __fpu_ds;
+ uint16_t __fpu_rsrv3;
+ uint32_t __fpu_mxcsr;
+ uint32_t __fpu_mxcsrmask;
+ __x86_64_mmst_reg __fpu_stmm0;
+ __x86_64_mmst_reg __fpu_stmm1;
+ __x86_64_mmst_reg __fpu_stmm2;
+ __x86_64_mmst_reg __fpu_stmm3;
+ __x86_64_mmst_reg __fpu_stmm4;
+ __x86_64_mmst_reg __fpu_stmm5;
+ __x86_64_mmst_reg __fpu_stmm6;
+ __x86_64_mmst_reg __fpu_stmm7;
+ __x86_64_xmm_reg __fpu_xmm0;
+ __x86_64_xmm_reg __fpu_xmm1;
+ __x86_64_xmm_reg __fpu_xmm2;
+ __x86_64_xmm_reg __fpu_xmm3;
+ __x86_64_xmm_reg __fpu_xmm4;
+ __x86_64_xmm_reg __fpu_xmm5;
+ __x86_64_xmm_reg __fpu_xmm6;
+ __x86_64_xmm_reg __fpu_xmm7;
+ __x86_64_xmm_reg __fpu_xmm8;
+ __x86_64_xmm_reg __fpu_xmm9;
+ __x86_64_xmm_reg __fpu_xmm10;
+ __x86_64_xmm_reg __fpu_xmm11;
+ __x86_64_xmm_reg __fpu_xmm12;
+ __x86_64_xmm_reg __fpu_xmm13;
+ __x86_64_xmm_reg __fpu_xmm14;
+ __x86_64_xmm_reg __fpu_xmm15;
+ uint8_t __fpu_rsrv4[6 * 16];
+ int32_t __fpu_reserved1;
} __x86_64_float_state_t;
typedef struct {
- uint32_t __fpu_reserved[2];
- __x86_64_fp_control_t __fpu_fcw;
- __x86_64_fp_status_t __fpu_fsw;
- uint8_t __fpu_ftw;
- uint8_t __fpu_rsrv1;
- uint16_t __fpu_fop;
- uint32_t __fpu_ip;
- uint16_t __fpu_cs;
- uint16_t __fpu_rsrv2;
- uint32_t __fpu_dp;
- uint16_t __fpu_ds;
- uint16_t __fpu_rsrv3;
- uint32_t __fpu_mxcsr;
- uint32_t __fpu_mxcsrmask;
- __x86_64_mmst_reg __fpu_stmm0;
- __x86_64_mmst_reg __fpu_stmm1;
- __x86_64_mmst_reg __fpu_stmm2;
- __x86_64_mmst_reg __fpu_stmm3;
- __x86_64_mmst_reg __fpu_stmm4;
- __x86_64_mmst_reg __fpu_stmm5;
- __x86_64_mmst_reg __fpu_stmm6;
- __x86_64_mmst_reg __fpu_stmm7;
- __x86_64_xmm_reg __fpu_xmm0;
- __x86_64_xmm_reg __fpu_xmm1;
- __x86_64_xmm_reg __fpu_xmm2;
- __x86_64_xmm_reg __fpu_xmm3;
- __x86_64_xmm_reg __fpu_xmm4;
- __x86_64_xmm_reg __fpu_xmm5;
- __x86_64_xmm_reg __fpu_xmm6;
- __x86_64_xmm_reg __fpu_xmm7;
- __x86_64_xmm_reg __fpu_xmm8;
- __x86_64_xmm_reg __fpu_xmm9;
- __x86_64_xmm_reg __fpu_xmm10;
- __x86_64_xmm_reg __fpu_xmm11;
- __x86_64_xmm_reg __fpu_xmm12;
- __x86_64_xmm_reg __fpu_xmm13;
- __x86_64_xmm_reg __fpu_xmm14;
- __x86_64_xmm_reg __fpu_xmm15;
- uint8_t __fpu_rsrv4[6*16];
- uint32_t __fpu_reserved1;
- uint8_t __avx_reserved1[64];
- __x86_64_xmm_reg __fpu_ymmh0;
- __x86_64_xmm_reg __fpu_ymmh1;
- __x86_64_xmm_reg __fpu_ymmh2;
- __x86_64_xmm_reg __fpu_ymmh3;
- __x86_64_xmm_reg __fpu_ymmh4;
- __x86_64_xmm_reg __fpu_ymmh5;
- __x86_64_xmm_reg __fpu_ymmh6;
- __x86_64_xmm_reg __fpu_ymmh7;
- __x86_64_xmm_reg __fpu_ymmh8;
- __x86_64_xmm_reg __fpu_ymmh9;
- __x86_64_xmm_reg __fpu_ymmh10;
- __x86_64_xmm_reg __fpu_ymmh11;
- __x86_64_xmm_reg __fpu_ymmh12;
- __x86_64_xmm_reg __fpu_ymmh13;
- __x86_64_xmm_reg __fpu_ymmh14;
- __x86_64_xmm_reg __fpu_ymmh15;
+ uint32_t __fpu_reserved[2];
+ __x86_64_fp_control_t __fpu_fcw;
+ __x86_64_fp_status_t __fpu_fsw;
+ uint8_t __fpu_ftw;
+ uint8_t __fpu_rsrv1;
+ uint16_t __fpu_fop;
+ uint32_t __fpu_ip;
+ uint16_t __fpu_cs;
+ uint16_t __fpu_rsrv2;
+ uint32_t __fpu_dp;
+ uint16_t __fpu_ds;
+ uint16_t __fpu_rsrv3;
+ uint32_t __fpu_mxcsr;
+ uint32_t __fpu_mxcsrmask;
+ __x86_64_mmst_reg __fpu_stmm0;
+ __x86_64_mmst_reg __fpu_stmm1;
+ __x86_64_mmst_reg __fpu_stmm2;
+ __x86_64_mmst_reg __fpu_stmm3;
+ __x86_64_mmst_reg __fpu_stmm4;
+ __x86_64_mmst_reg __fpu_stmm5;
+ __x86_64_mmst_reg __fpu_stmm6;
+ __x86_64_mmst_reg __fpu_stmm7;
+ __x86_64_xmm_reg __fpu_xmm0;
+ __x86_64_xmm_reg __fpu_xmm1;
+ __x86_64_xmm_reg __fpu_xmm2;
+ __x86_64_xmm_reg __fpu_xmm3;
+ __x86_64_xmm_reg __fpu_xmm4;
+ __x86_64_xmm_reg __fpu_xmm5;
+ __x86_64_xmm_reg __fpu_xmm6;
+ __x86_64_xmm_reg __fpu_xmm7;
+ __x86_64_xmm_reg __fpu_xmm8;
+ __x86_64_xmm_reg __fpu_xmm9;
+ __x86_64_xmm_reg __fpu_xmm10;
+ __x86_64_xmm_reg __fpu_xmm11;
+ __x86_64_xmm_reg __fpu_xmm12;
+ __x86_64_xmm_reg __fpu_xmm13;
+ __x86_64_xmm_reg __fpu_xmm14;
+ __x86_64_xmm_reg __fpu_xmm15;
+ uint8_t __fpu_rsrv4[6 * 16];
+ uint32_t __fpu_reserved1;
+ uint8_t __avx_reserved1[64];
+ __x86_64_xmm_reg __fpu_ymmh0;
+ __x86_64_xmm_reg __fpu_ymmh1;
+ __x86_64_xmm_reg __fpu_ymmh2;
+ __x86_64_xmm_reg __fpu_ymmh3;
+ __x86_64_xmm_reg __fpu_ymmh4;
+ __x86_64_xmm_reg __fpu_ymmh5;
+ __x86_64_xmm_reg __fpu_ymmh6;
+ __x86_64_xmm_reg __fpu_ymmh7;
+ __x86_64_xmm_reg __fpu_ymmh8;
+ __x86_64_xmm_reg __fpu_ymmh9;
+ __x86_64_xmm_reg __fpu_ymmh10;
+ __x86_64_xmm_reg __fpu_ymmh11;
+ __x86_64_xmm_reg __fpu_ymmh12;
+ __x86_64_xmm_reg __fpu_ymmh13;
+ __x86_64_xmm_reg __fpu_ymmh14;
+ __x86_64_xmm_reg __fpu_ymmh15;
} __x86_64_avx_state_t;
typedef struct {
- uint32_t __trapno;
- uint32_t __err;
- uint64_t __faultvaddr;
+ uint32_t __trapno;
+ uint32_t __err;
+ uint64_t __faultvaddr;
} __x86_64_exception_state_t;
-
typedef struct {
- uint64_t __dr0;
- uint64_t __dr1;
- uint64_t __dr2;
- uint64_t __dr3;
- uint64_t __dr4;
- uint64_t __dr5;
- uint64_t __dr6;
- uint64_t __dr7;
+ uint64_t __dr0;
+ uint64_t __dr1;
+ uint64_t __dr2;
+ uint64_t __dr3;
+ uint64_t __dr4;
+ uint64_t __dr5;
+ uint64_t __dr6;
+ uint64_t __dr7;
} __x86_64_debug_state_t;
#endif
Modified: lldb/trunk/tools/debugserver/source/PThreadCondition.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/PThreadCondition.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/PThreadCondition.h (original)
+++ lldb/trunk/tools/debugserver/source/PThreadCondition.h Tue Sep 6 15:57:50 2016
@@ -16,38 +16,20 @@
#include <pthread.h>
-class PThreadCondition
-{
+class PThreadCondition {
public:
+ PThreadCondition() { ::pthread_cond_init(&m_condition, NULL); }
- PThreadCondition()
- {
- ::pthread_cond_init (&m_condition, NULL);
- }
-
- ~PThreadCondition()
- {
- ::pthread_cond_destroy (&m_condition);
- }
-
- pthread_cond_t *Condition()
- {
- return &m_condition;
- }
-
- int Broadcast()
- {
- return ::pthread_cond_broadcast (&m_condition);
- }
-
- int Signal()
- {
- return ::pthread_cond_signal (&m_condition);
- }
+ ~PThreadCondition() { ::pthread_cond_destroy(&m_condition); }
+
+ pthread_cond_t *Condition() { return &m_condition; }
+
+ int Broadcast() { return ::pthread_cond_broadcast(&m_condition); }
+
+ int Signal() { return ::pthread_cond_signal(&m_condition); }
protected:
- pthread_cond_t m_condition;
+ pthread_cond_t m_condition;
};
#endif
-
Modified: lldb/trunk/tools/debugserver/source/PThreadEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/PThreadEvent.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/PThreadEvent.cpp (original)
+++ lldb/trunk/tools/debugserver/source/PThreadEvent.cpp Tue Sep 6 15:57:50 2016
@@ -12,117 +12,98 @@
//===----------------------------------------------------------------------===//
#include "PThreadEvent.h"
-#include "errno.h"
#include "DNBLog.h"
+#include "errno.h"
-PThreadEvent::PThreadEvent(uint32_t bits, uint32_t validBits) :
- m_mutex(),
- m_set_condition(),
- m_reset_condition(),
- m_bits(bits),
- m_validBits(validBits),
- m_reset_ack_mask(0)
-{
- // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, 0x%8.8x)", this, __FUNCTION__, bits, validBits);
-}
-
-PThreadEvent::~PThreadEvent()
-{
- // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION);
-}
-
-
-uint32_t
-PThreadEvent::NewEventBit()
-{
- // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION);
- PTHREAD_MUTEX_LOCKER (locker, m_mutex);
- uint32_t mask = 1;
- while (mask & m_validBits)
- mask <<= 1;
- m_validBits |= mask;
- return mask;
-}
-
-void
-PThreadEvent::FreeEventBits(const uint32_t mask)
-{
- // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask);
- if (mask)
- {
- PTHREAD_MUTEX_LOCKER (locker, m_mutex);
- m_bits &= ~mask;
- m_validBits &= ~mask;
- }
-}
-
-
-uint32_t
-PThreadEvent::GetEventBits() const
-{
- // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION);
- PTHREAD_MUTEX_LOCKER (locker, m_mutex);
- uint32_t bits = m_bits;
- return bits;
+PThreadEvent::PThreadEvent(uint32_t bits, uint32_t validBits)
+ : m_mutex(), m_set_condition(), m_reset_condition(), m_bits(bits),
+ m_validBits(validBits), m_reset_ack_mask(0) {
+ // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, 0x%8.8x)",
+ // this, __FUNCTION__, bits, validBits);
+}
+
+PThreadEvent::~PThreadEvent() {
+ // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION);
+}
+
+uint32_t PThreadEvent::NewEventBit() {
+ // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION);
+ PTHREAD_MUTEX_LOCKER(locker, m_mutex);
+ uint32_t mask = 1;
+ while (mask & m_validBits)
+ mask <<= 1;
+ m_validBits |= mask;
+ return mask;
+}
+
+void PThreadEvent::FreeEventBits(const uint32_t mask) {
+ // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this,
+ // __FUNCTION__, mask);
+ if (mask) {
+ PTHREAD_MUTEX_LOCKER(locker, m_mutex);
+ m_bits &= ~mask;
+ m_validBits &= ~mask;
+ }
+}
+
+uint32_t PThreadEvent::GetEventBits() const {
+ // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION);
+ PTHREAD_MUTEX_LOCKER(locker, m_mutex);
+ uint32_t bits = m_bits;
+ return bits;
}
// Replace the event bits with a new bitmask value
-void
-PThreadEvent::ReplaceEventBits(const uint32_t bits)
-{
- // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, bits);
- PTHREAD_MUTEX_LOCKER (locker, m_mutex);
- // Make sure we have some bits and that they aren't already set...
- if (m_bits != bits)
- {
- // Figure out which bits are changing
- uint32_t changed_bits = m_bits ^ bits;
- // Set the new bit values
- m_bits = bits;
- // If any new bits are set, then broadcast
- if (changed_bits & m_bits)
- m_set_condition.Broadcast();
- }
+void PThreadEvent::ReplaceEventBits(const uint32_t bits) {
+ // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this,
+ // __FUNCTION__, bits);
+ PTHREAD_MUTEX_LOCKER(locker, m_mutex);
+ // Make sure we have some bits and that they aren't already set...
+ if (m_bits != bits) {
+ // Figure out which bits are changing
+ uint32_t changed_bits = m_bits ^ bits;
+ // Set the new bit values
+ m_bits = bits;
+ // If any new bits are set, then broadcast
+ if (changed_bits & m_bits)
+ m_set_condition.Broadcast();
+ }
}
// Set one or more event bits and broadcast if any new event bits get set
// that weren't already set.
-void
-PThreadEvent::SetEvents(const uint32_t mask)
-{
- // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask);
- // Make sure we have some bits to set
- if (mask)
- {
- PTHREAD_MUTEX_LOCKER (locker, m_mutex);
- // Save the old event bit state so we can tell if things change
- uint32_t old = m_bits;
- // Set the all event bits that are set in 'mask'
- m_bits |= mask;
- // Broadcast only if any extra bits got set.
- if (old != m_bits)
- m_set_condition.Broadcast();
- }
+void PThreadEvent::SetEvents(const uint32_t mask) {
+ // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this,
+ // __FUNCTION__, mask);
+ // Make sure we have some bits to set
+ if (mask) {
+ PTHREAD_MUTEX_LOCKER(locker, m_mutex);
+ // Save the old event bit state so we can tell if things change
+ uint32_t old = m_bits;
+ // Set the all event bits that are set in 'mask'
+ m_bits |= mask;
+ // Broadcast only if any extra bits got set.
+ if (old != m_bits)
+ m_set_condition.Broadcast();
+ }
}
// Reset one or more event bits
-void
-PThreadEvent::ResetEvents(const uint32_t mask)
-{
- // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask);
- if (mask)
- {
- PTHREAD_MUTEX_LOCKER (locker, m_mutex);
-
- // Save the old event bit state so we can tell if things change
- uint32_t old = m_bits;
- // Clear the all event bits that are set in 'mask'
- m_bits &= ~mask;
- // Broadcast only if any extra bits got reset.
- if (old != m_bits)
- m_reset_condition.Broadcast();
- }
+void PThreadEvent::ResetEvents(const uint32_t mask) {
+ // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this,
+ // __FUNCTION__, mask);
+ if (mask) {
+ PTHREAD_MUTEX_LOCKER(locker, m_mutex);
+
+ // Save the old event bit state so we can tell if things change
+ uint32_t old = m_bits;
+ // Clear the all event bits that are set in 'mask'
+ m_bits &= ~mask;
+ // Broadcast only if any extra bits got reset.
+ if (old != m_bits)
+ m_reset_condition.Broadcast();
+ }
}
//----------------------------------------------------------------------
@@ -130,98 +111,90 @@ PThreadEvent::ResetEvents(const uint32_t
// 'mask'. If 'timeout_abstime' is NULL, then wait forever.
//----------------------------------------------------------------------
uint32_t
-PThreadEvent::WaitForSetEvents(const uint32_t mask, const struct timespec *timeout_abstime) const
-{
- // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime);
- int err = 0;
- // pthread_cond_timedwait() or pthread_cond_wait() will atomically
- // unlock the mutex and wait for the condition to be set. When either
- // function returns, they will re-lock the mutex. We use an auto lock/unlock
- // class (PThreadMutex::Locker) to allow us to return at any point in this
- // function and not have to worry about unlocking the mutex.
- PTHREAD_MUTEX_LOCKER (locker, m_mutex);
- do
- {
- // Check our predicate (event bits) in case any are already set
- if (mask & m_bits)
- {
- uint32_t bits_set = mask & m_bits;
- // Our PThreadMutex::Locker will automatically unlock our mutex
- return bits_set;
- }
- if (timeout_abstime)
- {
- // Wait for condition to get broadcast, or for a timeout. If we get
- // a timeout we will drop out of the do loop and return false which
- // is what we want.
- err = ::pthread_cond_timedwait (m_set_condition.Condition(), m_mutex.Mutex(), timeout_abstime);
- // Retest our predicate in case of a race condition right at the end
- // of the timeout.
- if (err == ETIMEDOUT)
- {
- uint32_t bits_set = mask & m_bits;
- return bits_set;
- }
- }
- else
- {
- // Wait for condition to get broadcast. The only error this function
- // should return is if
- err = ::pthread_cond_wait (m_set_condition.Condition(), m_mutex.Mutex());
- }
- } while (err == 0);
- return 0;
+PThreadEvent::WaitForSetEvents(const uint32_t mask,
+ const struct timespec *timeout_abstime) const {
+ // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this,
+ // __FUNCTION__, mask, timeout_abstime);
+ int err = 0;
+ // pthread_cond_timedwait() or pthread_cond_wait() will atomically
+ // unlock the mutex and wait for the condition to be set. When either
+ // function returns, they will re-lock the mutex. We use an auto lock/unlock
+ // class (PThreadMutex::Locker) to allow us to return at any point in this
+ // function and not have to worry about unlocking the mutex.
+ PTHREAD_MUTEX_LOCKER(locker, m_mutex);
+ do {
+ // Check our predicate (event bits) in case any are already set
+ if (mask & m_bits) {
+ uint32_t bits_set = mask & m_bits;
+ // Our PThreadMutex::Locker will automatically unlock our mutex
+ return bits_set;
+ }
+ if (timeout_abstime) {
+ // Wait for condition to get broadcast, or for a timeout. If we get
+ // a timeout we will drop out of the do loop and return false which
+ // is what we want.
+ err = ::pthread_cond_timedwait(m_set_condition.Condition(),
+ m_mutex.Mutex(), timeout_abstime);
+ // Retest our predicate in case of a race condition right at the end
+ // of the timeout.
+ if (err == ETIMEDOUT) {
+ uint32_t bits_set = mask & m_bits;
+ return bits_set;
+ }
+ } else {
+ // Wait for condition to get broadcast. The only error this function
+ // should return is if
+ err = ::pthread_cond_wait(m_set_condition.Condition(), m_mutex.Mutex());
+ }
+ } while (err == 0);
+ return 0;
}
//----------------------------------------------------------------------
// Wait until 'timeout_abstime' for any events in 'mask' to reset.
// If 'timeout_abstime' is NULL, then wait forever.
//----------------------------------------------------------------------
-uint32_t
-PThreadEvent::WaitForEventsToReset(const uint32_t mask, const struct timespec *timeout_abstime) const
-{
- // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime);
- int err = 0;
- // pthread_cond_timedwait() or pthread_cond_wait() will atomically
- // unlock the mutex and wait for the condition to be set. When either
- // function returns, they will re-lock the mutex. We use an auto lock/unlock
- // class (PThreadMutex::Locker) to allow us to return at any point in this
- // function and not have to worry about unlocking the mutex.
- PTHREAD_MUTEX_LOCKER (locker, m_mutex);
- do
- {
- // Check our predicate (event bits) each time through this do loop
- if ((mask & m_bits) == 0)
- {
- // All the bits requested have been reset, return zero indicating
- // which bits from the mask were still set (none of them)
- return 0;
- }
- if (timeout_abstime)
- {
- // Wait for condition to get broadcast, or for a timeout. If we get
- // a timeout we will drop out of the do loop and return false which
- // is what we want.
- err = ::pthread_cond_timedwait (m_reset_condition.Condition(), m_mutex.Mutex(), timeout_abstime);
- }
- else
- {
- // Wait for condition to get broadcast. The only error this function
- // should return is if
- err = ::pthread_cond_wait (m_reset_condition.Condition(), m_mutex.Mutex());
- }
- } while (err == 0);
- // Return a mask indicating which bits (if any) were still set
- return mask & m_bits;
+uint32_t PThreadEvent::WaitForEventsToReset(
+ const uint32_t mask, const struct timespec *timeout_abstime) const {
+ // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this,
+ // __FUNCTION__, mask, timeout_abstime);
+ int err = 0;
+ // pthread_cond_timedwait() or pthread_cond_wait() will atomically
+ // unlock the mutex and wait for the condition to be set. When either
+ // function returns, they will re-lock the mutex. We use an auto lock/unlock
+ // class (PThreadMutex::Locker) to allow us to return at any point in this
+ // function and not have to worry about unlocking the mutex.
+ PTHREAD_MUTEX_LOCKER(locker, m_mutex);
+ do {
+ // Check our predicate (event bits) each time through this do loop
+ if ((mask & m_bits) == 0) {
+ // All the bits requested have been reset, return zero indicating
+ // which bits from the mask were still set (none of them)
+ return 0;
+ }
+ if (timeout_abstime) {
+ // Wait for condition to get broadcast, or for a timeout. If we get
+ // a timeout we will drop out of the do loop and return false which
+ // is what we want.
+ err = ::pthread_cond_timedwait(m_reset_condition.Condition(),
+ m_mutex.Mutex(), timeout_abstime);
+ } else {
+ // Wait for condition to get broadcast. The only error this function
+ // should return is if
+ err = ::pthread_cond_wait(m_reset_condition.Condition(), m_mutex.Mutex());
+ }
+ } while (err == 0);
+ // Return a mask indicating which bits (if any) were still set
+ return mask & m_bits;
}
uint32_t
-PThreadEvent::WaitForResetAck (const uint32_t mask, const struct timespec *timeout_abstime) const
-{
- if (mask & m_reset_ack_mask)
- {
- // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime);
- return WaitForEventsToReset (mask & m_reset_ack_mask, timeout_abstime);
- }
- return 0;
+PThreadEvent::WaitForResetAck(const uint32_t mask,
+ const struct timespec *timeout_abstime) const {
+ if (mask & m_reset_ack_mask) {
+ // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this,
+ // __FUNCTION__, mask, timeout_abstime);
+ return WaitForEventsToReset(mask & m_reset_ack_mask, timeout_abstime);
+ }
+ return 0;
}
Modified: lldb/trunk/tools/debugserver/source/PThreadEvent.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/PThreadEvent.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/PThreadEvent.h (original)
+++ lldb/trunk/tools/debugserver/source/PThreadEvent.h Tue Sep 6 15:57:50 2016
@@ -13,47 +13,52 @@
#ifndef __PThreadEvent_h__
#define __PThreadEvent_h__
-#include "PThreadMutex.h"
#include "PThreadCondition.h"
+#include "PThreadMutex.h"
#include <stdint.h>
#include <time.h>
-class PThreadEvent
-{
+class PThreadEvent {
public:
- PThreadEvent (uint32_t bits = 0, uint32_t validBits = 0);
- ~PThreadEvent ();
+ PThreadEvent(uint32_t bits = 0, uint32_t validBits = 0);
+ ~PThreadEvent();
+
+ uint32_t NewEventBit();
+ void FreeEventBits(const uint32_t mask);
- uint32_t NewEventBit ();
- void FreeEventBits (const uint32_t mask);
+ void ReplaceEventBits(const uint32_t bits);
+ uint32_t GetEventBits() const;
+ void SetEvents(const uint32_t mask);
+ void ResetEvents(const uint32_t mask);
+ // Wait for events to be set or reset. These functions take an optional
+ // timeout value. If timeout is NULL an infinite timeout will be used.
+ uint32_t
+ WaitForSetEvents(const uint32_t mask,
+ const struct timespec *timeout_abstime = NULL) const;
+ uint32_t
+ WaitForEventsToReset(const uint32_t mask,
+ const struct timespec *timeout_abstime = NULL) const;
+
+ uint32_t GetResetAckMask() const { return m_reset_ack_mask; }
+ uint32_t SetResetAckMask(uint32_t mask) { return m_reset_ack_mask = mask; }
+ uint32_t WaitForResetAck(const uint32_t mask,
+ const struct timespec *timeout_abstime = NULL) const;
- void ReplaceEventBits (const uint32_t bits);
- uint32_t GetEventBits () const;
- void SetEvents (const uint32_t mask);
- void ResetEvents (const uint32_t mask);
- // Wait for events to be set or reset. These functions take an optional
- // timeout value. If timeout is NULL an infinite timeout will be used.
- uint32_t WaitForSetEvents (const uint32_t mask, const struct timespec *timeout_abstime = NULL) const;
- uint32_t WaitForEventsToReset(const uint32_t mask, const struct timespec *timeout_abstime = NULL) const;
-
- uint32_t GetResetAckMask () const { return m_reset_ack_mask; }
- uint32_t SetResetAckMask (uint32_t mask) { return m_reset_ack_mask = mask; }
- uint32_t WaitForResetAck (const uint32_t mask, const struct timespec *timeout_abstime = NULL) const;
protected:
- //----------------------------------------------------------------------
- // pthread condition and mutex variable to control access and allow
- // blocking between the main thread and the spotlight index thread.
- //----------------------------------------------------------------------
- mutable PThreadMutex m_mutex;
- mutable PThreadCondition m_set_condition;
- mutable PThreadCondition m_reset_condition;
- uint32_t m_bits;
- uint32_t m_validBits;
- uint32_t m_reset_ack_mask;
-private:
- PThreadEvent(const PThreadEvent&); // Outlaw copy constructor
- PThreadEvent& operator=(const PThreadEvent& rhs);
+ //----------------------------------------------------------------------
+ // pthread condition and mutex variable to control access and allow
+ // blocking between the main thread and the spotlight index thread.
+ //----------------------------------------------------------------------
+ mutable PThreadMutex m_mutex;
+ mutable PThreadCondition m_set_condition;
+ mutable PThreadCondition m_reset_condition;
+ uint32_t m_bits;
+ uint32_t m_validBits;
+ uint32_t m_reset_ack_mask;
+private:
+ PThreadEvent(const PThreadEvent &); // Outlaw copy constructor
+ PThreadEvent &operator=(const PThreadEvent &rhs);
};
#endif // #ifndef __PThreadEvent_h__
Modified: lldb/trunk/tools/debugserver/source/PThreadMutex.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/PThreadMutex.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/PThreadMutex.cpp (original)
+++ lldb/trunk/tools/debugserver/source/PThreadMutex.cpp Tue Sep 6 15:57:50 2016
@@ -19,66 +19,53 @@
// Project includes
#include "DNBTimer.h"
-#if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS)
+#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS)
-PThreadMutex::Locker::Locker(PThreadMutex& m, const char *function, const char *file, const int line) :
- m_pMutex(m.Mutex()),
- m_function(function),
- m_file(file),
- m_line(line),
- m_lock_time(0)
-{
- Lock();
-}
-
-PThreadMutex::Locker::Locker(PThreadMutex* m, const char *function, const char *file, const int line) :
- m_pMutex(m ? m->Mutex() : NULL),
- m_function(function),
- m_file(file),
- m_line(line),
- m_lock_time(0)
-{
- Lock();
-}
-
-PThreadMutex::Locker::Locker(pthread_mutex_t *mutex, const char *function, const char *file, const int line) :
- m_pMutex(mutex),
- m_function(function),
- m_file(file),
- m_line(line),
- m_lock_time(0)
-{
- Lock();
-}
-
-
-PThreadMutex::Locker::~Locker()
-{
- Unlock();
-}
-
-
-void
-PThreadMutex::Locker::Lock()
-{
- if (m_pMutex)
- {
- m_lock_time = DNBTimer::GetTimeOfDay();
- if (::pthread_mutex_trylock (m_pMutex) != 0)
- {
- fprintf(stdout, "::pthread_mutex_trylock (%8.8p) mutex is locked (function %s in %s:%i), waiting...\n", m_pMutex, m_function, m_file, m_line);
- ::pthread_mutex_lock (m_pMutex);
- fprintf(stdout, "::pthread_mutex_lock (%8.8p) succeeded after %6llu usecs (function %s in %s:%i)\n", m_pMutex, DNBTimer::GetTimeOfDay() - m_lock_time, m_function, m_file, m_line);
- }
+PThreadMutex::Locker::Locker(PThreadMutex &m, const char *function,
+ const char *file, const int line)
+ : m_pMutex(m.Mutex()), m_function(function), m_file(file), m_line(line),
+ m_lock_time(0) {
+ Lock();
+}
+
+PThreadMutex::Locker::Locker(PThreadMutex *m, const char *function,
+ const char *file, const int line)
+ : m_pMutex(m ? m->Mutex() : NULL), m_function(function), m_file(file),
+ m_line(line), m_lock_time(0) {
+ Lock();
+}
+
+PThreadMutex::Locker::Locker(pthread_mutex_t *mutex, const char *function,
+ const char *file, const int line)
+ : m_pMutex(mutex), m_function(function), m_file(file), m_line(line),
+ m_lock_time(0) {
+ Lock();
+}
+
+PThreadMutex::Locker::~Locker() { Unlock(); }
+
+void PThreadMutex::Locker::Lock() {
+ if (m_pMutex) {
+ m_lock_time = DNBTimer::GetTimeOfDay();
+ if (::pthread_mutex_trylock(m_pMutex) != 0) {
+ fprintf(stdout, "::pthread_mutex_trylock (%8.8p) mutex is locked "
+ "(function %s in %s:%i), waiting...\n",
+ m_pMutex, m_function, m_file, m_line);
+ ::pthread_mutex_lock(m_pMutex);
+ fprintf(stdout, "::pthread_mutex_lock (%8.8p) succeeded after %6llu "
+ "usecs (function %s in %s:%i)\n",
+ m_pMutex, DNBTimer::GetTimeOfDay() - m_lock_time, m_function,
+ m_file, m_line);
}
+ }
}
-
-void
-PThreadMutex::Locker::Unlock()
-{
- fprintf(stdout, "::pthread_mutex_unlock (%8.8p) had lock for %6llu usecs in %s in %s:%i\n", m_pMutex, DNBTimer::GetTimeOfDay() - m_lock_time, m_function, m_file, m_line);
- ::pthread_mutex_unlock (m_pMutex);
+void PThreadMutex::Locker::Unlock() {
+ fprintf(stdout, "::pthread_mutex_unlock (%8.8p) had lock for %6llu usecs in "
+ "%s in %s:%i\n",
+ m_pMutex, DNBTimer::GetTimeOfDay() - m_lock_time, m_function, m_file,
+ m_line);
+ ::pthread_mutex_unlock(m_pMutex);
}
#endif
Modified: lldb/trunk/tools/debugserver/source/PThreadMutex.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/PThreadMutex.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/PThreadMutex.h (original)
+++ lldb/trunk/tools/debugserver/source/PThreadMutex.h Tue Sep 6 15:57:50 2016
@@ -14,135 +14,107 @@
#ifndef __PThreadMutex_h__
#define __PThreadMutex_h__
-#include <pthread.h>
#include <assert.h>
+#include <pthread.h>
#include <stdint.h>
//#define DEBUG_PTHREAD_MUTEX_DEADLOCKS 1
-#if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS)
-#define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex, __FUNCTION__, __FILE__, __LINE__)
+#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS)
+#define PTHREAD_MUTEX_LOCKER(var, mutex) \
+ PThreadMutex::Locker var(mutex, __FUNCTION__, __FILE__, __LINE__)
#else
#define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex)
#endif
-class PThreadMutex
-{
+class PThreadMutex {
public:
-
- class Locker
- {
- public:
-#if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS)
-
- Locker(PThreadMutex& m, const char *function, const char *file, int line);
- Locker(PThreadMutex* m, const char *function, const char *file, int line);
- Locker(pthread_mutex_t *mutex, const char *function, const char *file, int line);
- ~Locker();
- void Lock();
- void Unlock();
+ class Locker {
+ public:
+#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS)
+
+ Locker(PThreadMutex &m, const char *function, const char *file, int line);
+ Locker(PThreadMutex *m, const char *function, const char *file, int line);
+ Locker(pthread_mutex_t *mutex, const char *function, const char *file,
+ int line);
+ ~Locker();
+ void Lock();
+ void Unlock();
#else
- Locker(PThreadMutex& m) :
- m_pMutex(m.Mutex())
- {
- Lock();
- }
-
- Locker(PThreadMutex* m) :
- m_pMutex(m ? m->Mutex() : NULL)
- {
- Lock();
- }
-
- Locker(pthread_mutex_t *mutex) :
- m_pMutex(mutex)
- {
- Lock();
- }
-
- void Lock()
- {
- if (m_pMutex)
- ::pthread_mutex_lock (m_pMutex);
- }
-
- void Unlock()
- {
- if (m_pMutex)
- ::pthread_mutex_unlock (m_pMutex);
- }
-
- ~Locker()
- {
- Unlock();
- }
+ Locker(PThreadMutex &m) : m_pMutex(m.Mutex()) { Lock(); }
-#endif
-
- // unlock any the current mutex and lock the new one if it is valid
- void Reset(pthread_mutex_t *pMutex = NULL)
- {
- Unlock();
- m_pMutex = pMutex;
- Lock();
- }
- pthread_mutex_t *m_pMutex;
-#if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS)
- const char *m_function;
- const char *m_file;
- int m_line;
- uint64_t m_lock_time;
-#endif
- };
+ Locker(PThreadMutex *m) : m_pMutex(m ? m->Mutex() : NULL) { Lock(); }
+ Locker(pthread_mutex_t *mutex) : m_pMutex(mutex) { Lock(); }
- PThreadMutex()
- {
- int err;
- err = ::pthread_mutex_init (&m_mutex, NULL); assert(err == 0);
+ void Lock() {
+ if (m_pMutex)
+ ::pthread_mutex_lock(m_pMutex);
}
- PThreadMutex(int type)
- {
- int err;
- ::pthread_mutexattr_t attr;
- err = ::pthread_mutexattr_init (&attr); assert(err == 0);
- err = ::pthread_mutexattr_settype (&attr, type); assert(err == 0);
- err = ::pthread_mutex_init (&m_mutex, &attr); assert(err == 0);
- err = ::pthread_mutexattr_destroy (&attr); assert(err == 0);
+ void Unlock() {
+ if (m_pMutex)
+ ::pthread_mutex_unlock(m_pMutex);
}
- ~PThreadMutex()
- {
- int err;
- err = ::pthread_mutex_destroy (&m_mutex);
- if (err != 0)
- {
- err = Unlock();
- if (err == 0)
- ::pthread_mutex_destroy (&m_mutex);
- }
- }
+ ~Locker() { Unlock(); }
- pthread_mutex_t *Mutex()
- {
- return &m_mutex;
- }
+#endif
- int Lock()
- {
- return ::pthread_mutex_lock (&m_mutex);
- }
+ // unlock any the current mutex and lock the new one if it is valid
+ void Reset(pthread_mutex_t *pMutex = NULL) {
+ Unlock();
+ m_pMutex = pMutex;
+ Lock();
+ }
+ pthread_mutex_t *m_pMutex;
+#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS)
+ const char *m_function;
+ const char *m_file;
+ int m_line;
+ uint64_t m_lock_time;
+#endif
+ };
- int Unlock()
- {
- return ::pthread_mutex_unlock (&m_mutex);
+ PThreadMutex() {
+ int err;
+ err = ::pthread_mutex_init(&m_mutex, NULL);
+ assert(err == 0);
+ }
+
+ PThreadMutex(int type) {
+ int err;
+ ::pthread_mutexattr_t attr;
+ err = ::pthread_mutexattr_init(&attr);
+ assert(err == 0);
+ err = ::pthread_mutexattr_settype(&attr, type);
+ assert(err == 0);
+ err = ::pthread_mutex_init(&m_mutex, &attr);
+ assert(err == 0);
+ err = ::pthread_mutexattr_destroy(&attr);
+ assert(err == 0);
+ }
+
+ ~PThreadMutex() {
+ int err;
+ err = ::pthread_mutex_destroy(&m_mutex);
+ if (err != 0) {
+ err = Unlock();
+ if (err == 0)
+ ::pthread_mutex_destroy(&m_mutex);
}
+ }
+
+ pthread_mutex_t *Mutex() { return &m_mutex; }
+
+ int Lock() { return ::pthread_mutex_lock(&m_mutex); }
+
+ int Unlock() { return ::pthread_mutex_unlock(&m_mutex); }
protected:
- pthread_mutex_t m_mutex;
+ pthread_mutex_t m_mutex;
};
#endif
Modified: lldb/trunk/tools/debugserver/source/PseudoTerminal.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/PseudoTerminal.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/PseudoTerminal.cpp (original)
+++ lldb/trunk/tools/debugserver/source/PseudoTerminal.cpp Tue Sep 6 15:57:50 2016
@@ -19,11 +19,8 @@
//----------------------------------------------------------------------
// PseudoTerminal constructor
//----------------------------------------------------------------------
-PseudoTerminal::PseudoTerminal() :
- m_master_fd(invalid_fd),
- m_slave_fd(invalid_fd)
-{
-}
+PseudoTerminal::PseudoTerminal()
+ : m_master_fd(invalid_fd), m_slave_fd(invalid_fd) {}
//----------------------------------------------------------------------
// Destructor
@@ -32,36 +29,29 @@ PseudoTerminal::PseudoTerminal() :
// to release any file descriptors that are needed beyond the lifespan
// of this object.
//----------------------------------------------------------------------
-PseudoTerminal::~PseudoTerminal()
-{
- CloseMaster();
- CloseSlave();
+PseudoTerminal::~PseudoTerminal() {
+ CloseMaster();
+ CloseSlave();
}
//----------------------------------------------------------------------
// Close the master file descriptor if it is valid.
//----------------------------------------------------------------------
-void
-PseudoTerminal::CloseMaster()
-{
- if (m_master_fd > 0)
- {
- ::close (m_master_fd);
- m_master_fd = invalid_fd;
- }
+void PseudoTerminal::CloseMaster() {
+ if (m_master_fd > 0) {
+ ::close(m_master_fd);
+ m_master_fd = invalid_fd;
+ }
}
//----------------------------------------------------------------------
// Close the slave file descriptor if it is valid.
//----------------------------------------------------------------------
-void
-PseudoTerminal::CloseSlave()
-{
- if (m_slave_fd > 0)
- {
- ::close (m_slave_fd);
- m_slave_fd = invalid_fd;
- }
+void PseudoTerminal::CloseSlave() {
+ if (m_slave_fd > 0) {
+ ::close(m_slave_fd);
+ m_slave_fd = invalid_fd;
+ }
}
//----------------------------------------------------------------------
@@ -75,31 +65,26 @@ PseudoTerminal::CloseSlave()
// RETURNS:
// Zero when successful, non-zero indicating an error occurred.
//----------------------------------------------------------------------
-PseudoTerminal::Error
-PseudoTerminal::OpenFirstAvailableMaster(int oflag)
-{
- // Open the master side of a pseudo terminal
- m_master_fd = ::posix_openpt (oflag);
- if (m_master_fd < 0)
- {
- return err_posix_openpt_failed;
- }
+PseudoTerminal::Error PseudoTerminal::OpenFirstAvailableMaster(int oflag) {
+ // Open the master side of a pseudo terminal
+ m_master_fd = ::posix_openpt(oflag);
+ if (m_master_fd < 0) {
+ return err_posix_openpt_failed;
+ }
- // Grant access to the slave pseudo terminal
- if (::grantpt (m_master_fd) < 0)
- {
- CloseMaster();
- return err_grantpt_failed;
- }
+ // Grant access to the slave pseudo terminal
+ if (::grantpt(m_master_fd) < 0) {
+ CloseMaster();
+ return err_grantpt_failed;
+ }
- // Clear the lock flag on the slave pseudo terminal
- if (::unlockpt (m_master_fd) < 0)
- {
- CloseMaster();
- return err_unlockpt_failed;
- }
+ // Clear the lock flag on the slave pseudo terminal
+ if (::unlockpt(m_master_fd) < 0) {
+ CloseMaster();
+ return err_unlockpt_failed;
+ }
- return success;
+ return success;
}
//----------------------------------------------------------------------
@@ -112,27 +97,23 @@ PseudoTerminal::OpenFirstAvailableMaster
// RETURNS:
// Zero when successful, non-zero indicating an error occurred.
//----------------------------------------------------------------------
-PseudoTerminal::Error
-PseudoTerminal::OpenSlave(int oflag)
-{
- CloseSlave();
+PseudoTerminal::Error PseudoTerminal::OpenSlave(int oflag) {
+ CloseSlave();
- // Open the master side of a pseudo terminal
- const char *slave_name = SlaveName();
+ // Open the master side of a pseudo terminal
+ const char *slave_name = SlaveName();
- if (slave_name == NULL)
- return err_ptsname_failed;
+ if (slave_name == NULL)
+ return err_ptsname_failed;
- m_slave_fd = ::open (slave_name, oflag);
+ m_slave_fd = ::open(slave_name, oflag);
- if (m_slave_fd < 0)
- return err_open_slave_failed;
+ if (m_slave_fd < 0)
+ return err_open_slave_failed;
- return success;
+ return success;
}
-
-
//----------------------------------------------------------------------
// Get the name of the slave pseudo terminal. A master pseudo terminal
// should already be valid prior to calling this function (see
@@ -144,15 +125,12 @@ PseudoTerminal::OpenSlave(int oflag)
// that comes from static memory, so a copy of the string should be
// made as subsequent calls can change this value.
//----------------------------------------------------------------------
-const char*
-PseudoTerminal::SlaveName() const
-{
- if (m_master_fd < 0)
- return NULL;
- return ::ptsname (m_master_fd);
+const char *PseudoTerminal::SlaveName() const {
+ if (m_master_fd < 0)
+ return NULL;
+ return ::ptsname(m_master_fd);
}
-
//----------------------------------------------------------------------
// Fork a child process that and have its stdio routed to a pseudo
// terminal.
@@ -175,53 +153,44 @@ PseudoTerminal::SlaveName() const
// in the child process: zero
//----------------------------------------------------------------------
-pid_t
-PseudoTerminal::Fork(PseudoTerminal::Error& error)
-{
- pid_t pid = invalid_pid;
- error = OpenFirstAvailableMaster (O_RDWR|O_NOCTTY);
-
- if (error == 0)
- {
- // Successfully opened our master pseudo terminal
-
- pid = ::fork ();
- if (pid < 0)
- {
- // Fork failed
- error = err_fork_failed;
- }
- else if (pid == 0)
- {
- // Child Process
- ::setsid();
-
- error = OpenSlave (O_RDWR);
- if (error == 0)
- {
- // Successfully opened slave
- // We are done with the master in the child process so lets close it
- CloseMaster ();
-
-#if defined (TIOCSCTTY)
- // Acquire the controlling terminal
- if (::ioctl (m_slave_fd, TIOCSCTTY, (char *)0) < 0)
- error = err_failed_to_acquire_controlling_terminal;
+pid_t PseudoTerminal::Fork(PseudoTerminal::Error &error) {
+ pid_t pid = invalid_pid;
+ error = OpenFirstAvailableMaster(O_RDWR | O_NOCTTY);
+
+ if (error == 0) {
+ // Successfully opened our master pseudo terminal
+
+ pid = ::fork();
+ if (pid < 0) {
+ // Fork failed
+ error = err_fork_failed;
+ } else if (pid == 0) {
+ // Child Process
+ ::setsid();
+
+ error = OpenSlave(O_RDWR);
+ if (error == 0) {
+ // Successfully opened slave
+ // We are done with the master in the child process so lets close it
+ CloseMaster();
+
+#if defined(TIOCSCTTY)
+ // Acquire the controlling terminal
+ if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0)
+ error = err_failed_to_acquire_controlling_terminal;
#endif
- // Duplicate all stdio file descriptors to the slave pseudo terminal
- if (::dup2 (m_slave_fd, STDIN_FILENO) != STDIN_FILENO)
- error = error ? error : err_dup2_failed_on_stdin;
- if (::dup2 (m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO)
- error = error ? error : err_dup2_failed_on_stdout;
- if (::dup2 (m_slave_fd, STDERR_FILENO) != STDERR_FILENO)
- error = error ? error : err_dup2_failed_on_stderr;
- }
- }
- else
- {
- // Parent Process
- // Do nothing and let the pid get returned!
- }
+ // Duplicate all stdio file descriptors to the slave pseudo terminal
+ if (::dup2(m_slave_fd, STDIN_FILENO) != STDIN_FILENO)
+ error = error ? error : err_dup2_failed_on_stdin;
+ if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO)
+ error = error ? error : err_dup2_failed_on_stdout;
+ if (::dup2(m_slave_fd, STDERR_FILENO) != STDERR_FILENO)
+ error = error ? error : err_dup2_failed_on_stderr;
+ }
+ } else {
+ // Parent Process
+ // Do nothing and let the pid get returned!
}
- return pid;
+ }
+ return pid;
}
Modified: lldb/trunk/tools/debugserver/source/PseudoTerminal.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/PseudoTerminal.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/PseudoTerminal.h (original)
+++ lldb/trunk/tools/debugserver/source/PseudoTerminal.h Tue Sep 6 15:57:50 2016
@@ -15,80 +15,73 @@
#define __PseudoTerminal_h__
#include <fcntl.h>
-#include <termios.h>
#include <string>
+#include <termios.h>
-class PseudoTerminal
-{
+class PseudoTerminal {
public:
- enum {
- invalid_fd = -1,
- invalid_pid = -1
- };
-
- enum Error
- {
- success = 0,
- err_posix_openpt_failed = -2,
- err_grantpt_failed = -3,
- err_unlockpt_failed = -4,
- err_ptsname_failed = -5,
- err_open_slave_failed = -6,
- err_fork_failed = -7,
- err_setsid_failed = -8,
- err_failed_to_acquire_controlling_terminal = -9,
- err_dup2_failed_on_stdin = -10,
- err_dup2_failed_on_stdout = -11,
- err_dup2_failed_on_stderr = -12
- };
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- PseudoTerminal ();
- ~PseudoTerminal ();
-
- void CloseMaster ();
- void CloseSlave ();
- Error OpenFirstAvailableMaster (int oflag);
- Error OpenSlave (int oflag);
- int MasterFD () const { return m_master_fd; }
- int SlaveFD () const { return m_slave_fd; }
- int ReleaseMasterFD ()
- {
- // Release ownership of the master pseudo terminal file
- // descriptor without closing it. (the destructor for this
- // class will close it otherwise!)
- int fd = m_master_fd;
- m_master_fd = invalid_fd;
- return fd;
- }
- int ReleaseSlaveFD ()
- {
- // Release ownership of the slave pseudo terminal file
- // descriptor without closing it (the destructor for this
- // class will close it otherwise!)
- int fd = m_slave_fd;
- m_slave_fd = invalid_fd;
- return fd;
- }
+ enum { invalid_fd = -1, invalid_pid = -1 };
+
+ enum Error {
+ success = 0,
+ err_posix_openpt_failed = -2,
+ err_grantpt_failed = -3,
+ err_unlockpt_failed = -4,
+ err_ptsname_failed = -5,
+ err_open_slave_failed = -6,
+ err_fork_failed = -7,
+ err_setsid_failed = -8,
+ err_failed_to_acquire_controlling_terminal = -9,
+ err_dup2_failed_on_stdin = -10,
+ err_dup2_failed_on_stdout = -11,
+ err_dup2_failed_on_stderr = -12
+ };
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ PseudoTerminal();
+ ~PseudoTerminal();
+
+ void CloseMaster();
+ void CloseSlave();
+ Error OpenFirstAvailableMaster(int oflag);
+ Error OpenSlave(int oflag);
+ int MasterFD() const { return m_master_fd; }
+ int SlaveFD() const { return m_slave_fd; }
+ int ReleaseMasterFD() {
+ // Release ownership of the master pseudo terminal file
+ // descriptor without closing it. (the destructor for this
+ // class will close it otherwise!)
+ int fd = m_master_fd;
+ m_master_fd = invalid_fd;
+ return fd;
+ }
+ int ReleaseSlaveFD() {
+ // Release ownership of the slave pseudo terminal file
+ // descriptor without closing it (the destructor for this
+ // class will close it otherwise!)
+ int fd = m_slave_fd;
+ m_slave_fd = invalid_fd;
+ return fd;
+ }
- const char* SlaveName () const;
+ const char *SlaveName() const;
+
+ pid_t Fork(Error &error);
- pid_t Fork(Error& error);
protected:
- //------------------------------------------------------------------
- // Classes that inherit from PseudoTerminal can see and modify these
- //------------------------------------------------------------------
- int m_master_fd;
- int m_slave_fd;
+ //------------------------------------------------------------------
+ // Classes that inherit from PseudoTerminal can see and modify these
+ //------------------------------------------------------------------
+ int m_master_fd;
+ int m_slave_fd;
private:
- //------------------------------------------------------------------
- // Outlaw copy and assignment constructors
- //------------------------------------------------------------------
- PseudoTerminal(const PseudoTerminal& rhs);
- PseudoTerminal& operator=(const PseudoTerminal& rhs);
-
+ //------------------------------------------------------------------
+ // Outlaw copy and assignment constructors
+ //------------------------------------------------------------------
+ PseudoTerminal(const PseudoTerminal &rhs);
+ PseudoTerminal &operator=(const PseudoTerminal &rhs);
};
#endif // #ifndef __PseudoTerminal_h__
Modified: lldb/trunk/tools/debugserver/source/RNBContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBContext.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBContext.cpp (original)
+++ lldb/trunk/tools/debugserver/source/RNBContext.cpp Tue Sep 6 15:57:50 2016
@@ -13,269 +13,266 @@
#include "RNBContext.h"
-#include <sys/stat.h>
#include <sstream>
+#include <sys/stat.h>
-#if defined (__APPLE__)
+#if defined(__APPLE__)
#include <pthread.h>
#include <sched.h>
#endif
-#include "RNBRemote.h"
+#include "CFString.h"
#include "DNB.h"
#include "DNBLog.h"
-#include "CFString.h"
-
+#include "RNBRemote.h"
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-RNBContext::~RNBContext()
-{
- SetProcessID (INVALID_NUB_PROCESS);
-}
+RNBContext::~RNBContext() { SetProcessID(INVALID_NUB_PROCESS); }
//----------------------------------------------------------------------
// RNBContext constructor
//----------------------------------------------------------------------
-const char *
-RNBContext::EnvironmentAtIndex (size_t index)
-{
- if (index < m_env_vec.size())
- return m_env_vec[index].c_str();
- else
- return NULL;
-}
-
-
-const char *
-RNBContext::ArgumentAtIndex (size_t index)
-{
- if (index < m_arg_vec.size())
- return m_arg_vec[index].c_str();
- else
- return NULL;
-}
-
-bool
-RNBContext::SetWorkingDirectory (const char *path)
-{
- struct stat working_directory_stat;
- if (::stat (path, &working_directory_stat) != 0)
- {
- m_working_directory.clear();
- return false;
- }
- m_working_directory.assign(path);
- return true;
+const char *RNBContext::EnvironmentAtIndex(size_t index) {
+ if (index < m_env_vec.size())
+ return m_env_vec[index].c_str();
+ else
+ return NULL;
}
-
-void
-RNBContext::SetProcessID (nub_process_t pid)
-{
- // Delete and events we created
- if (m_pid != INVALID_NUB_PROCESS)
- {
- StopProcessStatusThread ();
- // Unregister this context as a client of the process's events.
- }
- // Assign our new process ID
- m_pid = pid;
-
- if (pid != INVALID_NUB_PROCESS)
- {
- StartProcessStatusThread ();
- }
+const char *RNBContext::ArgumentAtIndex(size_t index) {
+ if (index < m_arg_vec.size())
+ return m_arg_vec[index].c_str();
+ else
+ return NULL;
}
-void
-RNBContext::StartProcessStatusThread()
-{
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__);
- if ((m_events.GetEventBits() & event_proc_thread_running) == 0)
- {
- int err = ::pthread_create (&m_pid_pthread, NULL, ThreadFunctionProcessStatus, this);
- if (err == 0)
- {
- // Our thread was successfully kicked off, wait for it to
- // set the started event so we can safely continue
- m_events.WaitForSetEvents (event_proc_thread_running);
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread got started!", __FUNCTION__);
- }
- else
- {
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread failed to start: err = %i", __FUNCTION__, err);
- m_events.ResetEvents (event_proc_thread_running);
- m_events.SetEvents (event_proc_thread_exiting);
- }
+bool RNBContext::SetWorkingDirectory(const char *path) {
+ struct stat working_directory_stat;
+ if (::stat(path, &working_directory_stat) != 0) {
+ m_working_directory.clear();
+ return false;
+ }
+ m_working_directory.assign(path);
+ return true;
+}
+
+void RNBContext::SetProcessID(nub_process_t pid) {
+ // Delete and events we created
+ if (m_pid != INVALID_NUB_PROCESS) {
+ StopProcessStatusThread();
+ // Unregister this context as a client of the process's events.
+ }
+ // Assign our new process ID
+ m_pid = pid;
+
+ if (pid != INVALID_NUB_PROCESS) {
+ StartProcessStatusThread();
+ }
+}
+
+void RNBContext::StartProcessStatusThread() {
+ DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__);
+ if ((m_events.GetEventBits() & event_proc_thread_running) == 0) {
+ int err = ::pthread_create(&m_pid_pthread, NULL,
+ ThreadFunctionProcessStatus, this);
+ if (err == 0) {
+ // Our thread was successfully kicked off, wait for it to
+ // set the started event so we can safely continue
+ m_events.WaitForSetEvents(event_proc_thread_running);
+ DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread got started!",
+ __FUNCTION__);
+ } else {
+ DNBLogThreadedIf(LOG_RNB_PROC,
+ "RNBContext::%s thread failed to start: err = %i",
+ __FUNCTION__, err);
+ m_events.ResetEvents(event_proc_thread_running);
+ m_events.SetEvents(event_proc_thread_exiting);
}
+ }
}
-void
-RNBContext::StopProcessStatusThread()
-{
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__);
- if ((m_events.GetEventBits() & event_proc_thread_running) == event_proc_thread_running)
- {
- struct timespec timeout_abstime;
- DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0);
- // Wait for 2 seconds for the rx thread to exit
- if (m_events.WaitForSetEvents(RNBContext::event_proc_thread_exiting, &timeout_abstime) == RNBContext::event_proc_thread_exiting)
- {
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread stopped as requeseted", __FUNCTION__);
- }
- else
- {
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread did not stop in 2 seconds...", __FUNCTION__);
- // Kill the RX thread???
- }
+void RNBContext::StopProcessStatusThread() {
+ DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__);
+ if ((m_events.GetEventBits() & event_proc_thread_running) ==
+ event_proc_thread_running) {
+ struct timespec timeout_abstime;
+ DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0);
+ // Wait for 2 seconds for the rx thread to exit
+ if (m_events.WaitForSetEvents(RNBContext::event_proc_thread_exiting,
+ &timeout_abstime) ==
+ RNBContext::event_proc_thread_exiting) {
+ DNBLogThreadedIf(LOG_RNB_PROC,
+ "RNBContext::%s thread stopped as requeseted",
+ __FUNCTION__);
+ } else {
+ DNBLogThreadedIf(LOG_RNB_PROC,
+ "RNBContext::%s thread did not stop in 2 seconds...",
+ __FUNCTION__);
+ // Kill the RX thread???
}
+ }
}
//----------------------------------------------------------------------
// This thread's sole purpose is to watch for any status changes in the
// child process.
//----------------------------------------------------------------------
-void*
-RNBContext::ThreadFunctionProcessStatus(void *arg)
-{
- RNBRemoteSP remoteSP(g_remoteSP);
- RNBRemote* remote = remoteSP.get();
- if (remote == NULL)
- return NULL;
- RNBContext& ctx = remote->Context();
-
- nub_process_t pid = ctx.ProcessID();
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (arg=%p, pid=%4.4x): thread starting...", __FUNCTION__, arg, pid);
- ctx.Events().SetEvents (RNBContext::event_proc_thread_running);
-
-#if defined (__APPLE__)
- pthread_setname_np ("child process status watcher thread");
-#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
- struct sched_param thread_param;
- int thread_sched_policy;
- if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0)
- {
- thread_param.sched_priority = 47;
- pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
- }
+void *RNBContext::ThreadFunctionProcessStatus(void *arg) {
+ RNBRemoteSP remoteSP(g_remoteSP);
+ RNBRemote *remote = remoteSP.get();
+ if (remote == NULL)
+ return NULL;
+ RNBContext &ctx = remote->Context();
+
+ nub_process_t pid = ctx.ProcessID();
+ DNBLogThreadedIf(LOG_RNB_PROC,
+ "RNBContext::%s (arg=%p, pid=%4.4x): thread starting...",
+ __FUNCTION__, arg, pid);
+ ctx.Events().SetEvents(RNBContext::event_proc_thread_running);
+
+#if defined(__APPLE__)
+ pthread_setname_np("child process status watcher thread");
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+ struct sched_param thread_param;
+ int thread_sched_policy;
+ if (pthread_getschedparam(pthread_self(), &thread_sched_policy,
+ &thread_param) == 0) {
+ thread_param.sched_priority = 47;
+ pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
+ }
#endif
#endif
- bool done = false;
- while (!done)
- {
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s calling DNBProcessWaitForEvent(pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable | eEventProfileDataAvailable, true)...", __FUNCTION__);
- nub_event_t pid_status_event = DNBProcessWaitForEvents (pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable | eEventProfileDataAvailable, true, NULL);
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s calling DNBProcessWaitForEvent(pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable | eEventProfileDataAvailable, true) => 0x%8.8x", __FUNCTION__, pid_status_event);
-
- if (pid_status_event == 0)
- {
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got ZERO back from DNBProcessWaitForEvent....", __FUNCTION__, pid);
- // done = true;
+ bool done = false;
+ while (!done) {
+ DNBLogThreadedIf(LOG_RNB_PROC,
+ "RNBContext::%s calling DNBProcessWaitForEvent(pid, "
+ "eEventProcessRunningStateChanged | "
+ "eEventProcessStoppedStateChanged | eEventStdioAvailable "
+ "| eEventProfileDataAvailable, true)...",
+ __FUNCTION__);
+ nub_event_t pid_status_event = DNBProcessWaitForEvents(
+ pid,
+ eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged |
+ eEventStdioAvailable | eEventProfileDataAvailable,
+ true, NULL);
+ DNBLogThreadedIf(LOG_RNB_PROC,
+ "RNBContext::%s calling DNBProcessWaitForEvent(pid, "
+ "eEventProcessRunningStateChanged | "
+ "eEventProcessStoppedStateChanged | eEventStdioAvailable "
+ "| eEventProfileDataAvailable, true) => 0x%8.8x",
+ __FUNCTION__, pid_status_event);
+
+ if (pid_status_event == 0) {
+ DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got ZERO back "
+ "from DNBProcessWaitForEvent....",
+ __FUNCTION__, pid);
+ // done = true;
+ } else {
+ if (pid_status_event & eEventStdioAvailable) {
+ DNBLogThreadedIf(
+ LOG_RNB_PROC,
+ "RNBContext::%s (pid=%4.4x) got stdio available event....",
+ __FUNCTION__, pid);
+ ctx.Events().SetEvents(RNBContext::event_proc_stdio_available);
+ // Wait for the main thread to consume this notification if it requested
+ // we wait for it
+ ctx.Events().WaitForResetAck(RNBContext::event_proc_stdio_available);
+ }
+
+ if (pid_status_event & eEventProfileDataAvailable) {
+ DNBLogThreadedIf(
+ LOG_RNB_PROC,
+ "RNBContext::%s (pid=%4.4x) got profile data event....",
+ __FUNCTION__, pid);
+ ctx.Events().SetEvents(RNBContext::event_proc_profile_data);
+ // Wait for the main thread to consume this notification if it requested
+ // we wait for it
+ ctx.Events().WaitForResetAck(RNBContext::event_proc_profile_data);
+ }
+
+ if (pid_status_event & (eEventProcessRunningStateChanged |
+ eEventProcessStoppedStateChanged)) {
+ nub_state_t pid_state = DNBProcessGetState(pid);
+ DNBLogThreadedIf(
+ LOG_RNB_PROC,
+ "RNBContext::%s (pid=%4.4x) got process state change: %s",
+ __FUNCTION__, pid, DNBStateAsString(pid_state));
+
+ // Let the main thread know there is a process state change to see
+ ctx.Events().SetEvents(RNBContext::event_proc_state_changed);
+ // Wait for the main thread to consume this notification if it requested
+ // we wait for it
+ ctx.Events().WaitForResetAck(RNBContext::event_proc_state_changed);
+
+ switch (pid_state) {
+ case eStateStopped:
+ break;
+
+ case eStateInvalid:
+ case eStateExited:
+ case eStateDetached:
+ done = true;
+ break;
+ default:
+ break;
}
- else
- {
- if (pid_status_event & eEventStdioAvailable)
- {
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got stdio available event....", __FUNCTION__, pid);
- ctx.Events().SetEvents (RNBContext::event_proc_stdio_available);
- // Wait for the main thread to consume this notification if it requested we wait for it
- ctx.Events().WaitForResetAck(RNBContext::event_proc_stdio_available);
- }
-
- if (pid_status_event & eEventProfileDataAvailable)
- {
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got profile data event....", __FUNCTION__, pid);
- ctx.Events().SetEvents (RNBContext::event_proc_profile_data);
- // Wait for the main thread to consume this notification if it requested we wait for it
- ctx.Events().WaitForResetAck(RNBContext::event_proc_profile_data);
- }
-
- if (pid_status_event & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged))
- {
- nub_state_t pid_state = DNBProcessGetState(pid);
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got process state change: %s", __FUNCTION__, pid, DNBStateAsString(pid_state));
-
- // Let the main thread know there is a process state change to see
- ctx.Events().SetEvents (RNBContext::event_proc_state_changed);
- // Wait for the main thread to consume this notification if it requested we wait for it
- ctx.Events().WaitForResetAck(RNBContext::event_proc_state_changed);
-
- switch (pid_state)
- {
- case eStateStopped:
- break;
-
- case eStateInvalid:
- case eStateExited:
- case eStateDetached:
- done = true;
- break;
- default:
- break;
- }
- }
+ }
- // Reset any events that we consumed.
- DNBProcessResetEvents(pid, pid_status_event);
-
- }
+ // Reset any events that we consumed.
+ DNBProcessResetEvents(pid, pid_status_event);
}
- DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (arg=%p, pid=%4.4x): thread exiting...", __FUNCTION__, arg, pid);
- ctx.Events().ResetEvents(event_proc_thread_running);
- ctx.Events().SetEvents(event_proc_thread_exiting);
- return NULL;
-}
-
-
-const char*
-RNBContext::EventsAsString (nub_event_t events, std::string& s)
-{
- s.clear();
- if (events & event_proc_state_changed)
- s += "proc_state_changed ";
- if (events & event_proc_thread_running)
- s += "proc_thread_running ";
- if (events & event_proc_thread_exiting)
- s += "proc_thread_exiting ";
- if (events & event_proc_stdio_available)
- s += "proc_stdio_available ";
- if (events & event_proc_profile_data)
- s += "proc_profile_data ";
- if (events & event_darwin_log_data_available)
- s += "darwin_log_data_available ";
- if (events & event_read_packet_available)
- s += "read_packet_available ";
- if (events & event_read_thread_running)
- s += "read_thread_running ";
- if (events & event_read_thread_running)
- s += "read_thread_running ";
- return s.c_str();
-}
-
-const char *
-RNBContext::LaunchStatusAsString (std::string& s)
-{
- s.clear();
-
- const char *err_str = m_launch_status.AsString();
- if (err_str)
- s = err_str;
- else
- {
- char error_num_str[64];
- snprintf(error_num_str, sizeof(error_num_str), "%u", m_launch_status.Error());
- s = error_num_str;
- }
- return s.c_str();
-}
-
-bool
-RNBContext::ProcessStateRunning() const
-{
- nub_state_t pid_state = DNBProcessGetState(m_pid);
- return pid_state == eStateRunning || pid_state == eStateStepping;
+ }
+ DNBLogThreadedIf(LOG_RNB_PROC,
+ "RNBContext::%s (arg=%p, pid=%4.4x): thread exiting...",
+ __FUNCTION__, arg, pid);
+ ctx.Events().ResetEvents(event_proc_thread_running);
+ ctx.Events().SetEvents(event_proc_thread_exiting);
+ return NULL;
+}
+
+const char *RNBContext::EventsAsString(nub_event_t events, std::string &s) {
+ s.clear();
+ if (events & event_proc_state_changed)
+ s += "proc_state_changed ";
+ if (events & event_proc_thread_running)
+ s += "proc_thread_running ";
+ if (events & event_proc_thread_exiting)
+ s += "proc_thread_exiting ";
+ if (events & event_proc_stdio_available)
+ s += "proc_stdio_available ";
+ if (events & event_proc_profile_data)
+ s += "proc_profile_data ";
+ if (events & event_darwin_log_data_available)
+ s += "darwin_log_data_available ";
+ if (events & event_read_packet_available)
+ s += "read_packet_available ";
+ if (events & event_read_thread_running)
+ s += "read_thread_running ";
+ if (events & event_read_thread_running)
+ s += "read_thread_running ";
+ return s.c_str();
+}
+
+const char *RNBContext::LaunchStatusAsString(std::string &s) {
+ s.clear();
+
+ const char *err_str = m_launch_status.AsString();
+ if (err_str)
+ s = err_str;
+ else {
+ char error_num_str[64];
+ snprintf(error_num_str, sizeof(error_num_str), "%u",
+ m_launch_status.Error());
+ s = error_num_str;
+ }
+ return s.c_str();
+}
+
+bool RNBContext::ProcessStateRunning() const {
+ nub_state_t pid_state = DNBProcessGetState(m_pid);
+ return pid_state == eStateRunning || pid_state == eStateStepping;
}
Modified: lldb/trunk/tools/debugserver/source/RNBContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBContext.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBContext.h (original)
+++ lldb/trunk/tools/debugserver/source/RNBContext.h Tue Sep 6 15:57:50 2016
@@ -14,148 +14,150 @@
#ifndef __RNBContext_h__
#define __RNBContext_h__
-#include "RNBDefs.h"
#include "DNBError.h"
#include "PThreadEvent.h"
-#include <vector>
+#include "RNBDefs.h"
#include <string>
+#include <vector>
-class RNBContext
-{
+class RNBContext {
public:
- enum
- {
- event_proc_state_changed = 0x001,
- event_proc_thread_running = 0x002, // Sticky
- event_proc_thread_exiting = 0x004,
- event_proc_stdio_available = 0x008,
- event_proc_profile_data = 0x010,
- event_read_packet_available = 0x020,
- event_read_thread_running = 0x040, // Sticky
- event_read_thread_exiting = 0x080,
- event_darwin_log_data_available = 0x100,
-
- normal_event_bits = event_proc_state_changed |
- event_proc_thread_exiting |
- event_proc_stdio_available |
- event_proc_profile_data |
- event_read_packet_available |
- event_read_thread_exiting |
- event_darwin_log_data_available,
-
- sticky_event_bits = event_proc_thread_running |
- event_read_thread_running,
-
-
- all_event_bits = sticky_event_bits | normal_event_bits
- } event_t;
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- RNBContext () :
- m_pid(INVALID_NUB_PROCESS),
- m_pid_stop_count(0),
- m_events(0, all_event_bits),
- m_pid_pthread(),
- m_launch_status(),
- m_arg_vec (),
- m_env_vec (),
- m_detach_on_error(false)
- {
- }
-
- virtual ~RNBContext();
-
-
- nub_process_t ProcessID() const { return m_pid; }
- bool HasValidProcessID() const { return m_pid != INVALID_NUB_PROCESS; }
- void SetProcessID (nub_process_t pid);
- nub_size_t GetProcessStopCount () const { return m_pid_stop_count; }
- bool SetProcessStopCount (nub_size_t count)
- {
- // Returns true if this class' notion of the PID state changed
- if (m_pid_stop_count == count)
- return false; // Didn't change
- m_pid_stop_count = count;
- return true; // The stop count has changed.
- }
-
- bool ProcessStateRunning() const;
- PThreadEvent& Events( ) { return m_events; }
- nub_event_t AllEventBits() const { return all_event_bits; }
- nub_event_t NormalEventBits() const { return normal_event_bits; }
- nub_event_t StickyEventBits() const { return sticky_event_bits; }
- const char* EventsAsString (nub_event_t events, std::string& s);
-
- size_t ArgumentCount () const { return m_arg_vec.size(); }
- const char * ArgumentAtIndex (size_t index);
- void PushArgument (const char *arg) { if (arg) m_arg_vec.push_back (arg); }
- void ClearArgv () { m_arg_vec.erase (m_arg_vec.begin(), m_arg_vec.end()); }
-
- size_t EnvironmentCount () const { return m_env_vec.size(); }
- const char * EnvironmentAtIndex (size_t index);
- void PushEnvironment (const char *arg) { if (arg) m_env_vec.push_back (arg); }
- void ClearEnvironment () { m_env_vec.erase (m_env_vec.begin(), m_env_vec.end()); }
- DNBError& LaunchStatus () { return m_launch_status; }
- const char * LaunchStatusAsString (std::string& s);
- nub_launch_flavor_t LaunchFlavor () const { return m_launch_flavor; }
- void SetLaunchFlavor (nub_launch_flavor_t flavor) { m_launch_flavor = flavor; }
-
- const char * GetWorkingDirectory () const
- {
- if (!m_working_directory.empty())
- return m_working_directory.c_str();
- return NULL;
- }
-
- bool SetWorkingDirectory (const char *path);
-
- std::string& GetSTDIN () { return m_stdin; }
- std::string& GetSTDOUT () { return m_stdout; }
- std::string& GetSTDERR () { return m_stderr; }
- std::string& GetWorkingDir () { return m_working_dir; }
-
- const char * GetSTDINPath() { return m_stdin.empty() ? NULL : m_stdin.c_str(); }
- const char * GetSTDOUTPath() { return m_stdout.empty() ? NULL : m_stdout.c_str(); }
- const char * GetSTDERRPath() { return m_stderr.empty() ? NULL : m_stderr.c_str(); }
- const char * GetWorkingDirPath() { return m_working_dir.empty() ? NULL : m_working_dir.c_str(); }
-
- void PushProcessEvent (const char *p) { m_process_event.assign(p); }
- const char * GetProcessEvent () { return m_process_event.c_str(); }
-
- void SetDetachOnError(bool detach) { m_detach_on_error = detach; }
- bool GetDetachOnError () { return m_detach_on_error; }
-
+ enum {
+ event_proc_state_changed = 0x001,
+ event_proc_thread_running = 0x002, // Sticky
+ event_proc_thread_exiting = 0x004,
+ event_proc_stdio_available = 0x008,
+ event_proc_profile_data = 0x010,
+ event_read_packet_available = 0x020,
+ event_read_thread_running = 0x040, // Sticky
+ event_read_thread_exiting = 0x080,
+ event_darwin_log_data_available = 0x100,
+
+ normal_event_bits = event_proc_state_changed | event_proc_thread_exiting |
+ event_proc_stdio_available | event_proc_profile_data |
+ event_read_packet_available |
+ event_read_thread_exiting |
+ event_darwin_log_data_available,
+
+ sticky_event_bits = event_proc_thread_running | event_read_thread_running,
+
+ all_event_bits = sticky_event_bits | normal_event_bits
+ } event_t;
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ RNBContext()
+ : m_pid(INVALID_NUB_PROCESS), m_pid_stop_count(0),
+ m_events(0, all_event_bits), m_pid_pthread(), m_launch_status(),
+ m_arg_vec(), m_env_vec(), m_detach_on_error(false) {}
+
+ virtual ~RNBContext();
+
+ nub_process_t ProcessID() const { return m_pid; }
+ bool HasValidProcessID() const { return m_pid != INVALID_NUB_PROCESS; }
+ void SetProcessID(nub_process_t pid);
+ nub_size_t GetProcessStopCount() const { return m_pid_stop_count; }
+ bool SetProcessStopCount(nub_size_t count) {
+ // Returns true if this class' notion of the PID state changed
+ if (m_pid_stop_count == count)
+ return false; // Didn't change
+ m_pid_stop_count = count;
+ return true; // The stop count has changed.
+ }
+
+ bool ProcessStateRunning() const;
+ PThreadEvent &Events() { return m_events; }
+ nub_event_t AllEventBits() const { return all_event_bits; }
+ nub_event_t NormalEventBits() const { return normal_event_bits; }
+ nub_event_t StickyEventBits() const { return sticky_event_bits; }
+ const char *EventsAsString(nub_event_t events, std::string &s);
+
+ size_t ArgumentCount() const { return m_arg_vec.size(); }
+ const char *ArgumentAtIndex(size_t index);
+ void PushArgument(const char *arg) {
+ if (arg)
+ m_arg_vec.push_back(arg);
+ }
+ void ClearArgv() { m_arg_vec.erase(m_arg_vec.begin(), m_arg_vec.end()); }
+
+ size_t EnvironmentCount() const { return m_env_vec.size(); }
+ const char *EnvironmentAtIndex(size_t index);
+ void PushEnvironment(const char *arg) {
+ if (arg)
+ m_env_vec.push_back(arg);
+ }
+ void ClearEnvironment() {
+ m_env_vec.erase(m_env_vec.begin(), m_env_vec.end());
+ }
+ DNBError &LaunchStatus() { return m_launch_status; }
+ const char *LaunchStatusAsString(std::string &s);
+ nub_launch_flavor_t LaunchFlavor() const { return m_launch_flavor; }
+ void SetLaunchFlavor(nub_launch_flavor_t flavor) { m_launch_flavor = flavor; }
+
+ const char *GetWorkingDirectory() const {
+ if (!m_working_directory.empty())
+ return m_working_directory.c_str();
+ return NULL;
+ }
+
+ bool SetWorkingDirectory(const char *path);
+
+ std::string &GetSTDIN() { return m_stdin; }
+ std::string &GetSTDOUT() { return m_stdout; }
+ std::string &GetSTDERR() { return m_stderr; }
+ std::string &GetWorkingDir() { return m_working_dir; }
+
+ const char *GetSTDINPath() {
+ return m_stdin.empty() ? NULL : m_stdin.c_str();
+ }
+ const char *GetSTDOUTPath() {
+ return m_stdout.empty() ? NULL : m_stdout.c_str();
+ }
+ const char *GetSTDERRPath() {
+ return m_stderr.empty() ? NULL : m_stderr.c_str();
+ }
+ const char *GetWorkingDirPath() {
+ return m_working_dir.empty() ? NULL : m_working_dir.c_str();
+ }
+
+ void PushProcessEvent(const char *p) { m_process_event.assign(p); }
+ const char *GetProcessEvent() { return m_process_event.c_str(); }
+
+ void SetDetachOnError(bool detach) { m_detach_on_error = detach; }
+ bool GetDetachOnError() { return m_detach_on_error; }
+
protected:
- //------------------------------------------------------------------
- // Classes that inherit from RNBContext can see and modify these
- //------------------------------------------------------------------
- nub_process_t m_pid;
- std::string m_stdin;
- std::string m_stdout;
- std::string m_stderr;
- std::string m_working_dir;
- nub_size_t m_pid_stop_count;
- PThreadEvent m_events; // Threaded events that we can wait for
- pthread_t m_pid_pthread;
- nub_launch_flavor_t m_launch_flavor; // How to launch our inferior process
- DNBError m_launch_status; // This holds the status from the last launch attempt.
- std::vector<std::string> m_arg_vec;
- std::vector<std::string> m_env_vec; // This will be unparsed - entries FOO=value
- std::string m_working_directory;
- std::string m_process_event;
- bool m_detach_on_error;
-
- void StartProcessStatusThread();
- void StopProcessStatusThread();
- static void* ThreadFunctionProcessStatus(void *arg);
+ //------------------------------------------------------------------
+ // Classes that inherit from RNBContext can see and modify these
+ //------------------------------------------------------------------
+ nub_process_t m_pid;
+ std::string m_stdin;
+ std::string m_stdout;
+ std::string m_stderr;
+ std::string m_working_dir;
+ nub_size_t m_pid_stop_count;
+ PThreadEvent m_events; // Threaded events that we can wait for
+ pthread_t m_pid_pthread;
+ nub_launch_flavor_t m_launch_flavor; // How to launch our inferior process
+ DNBError
+ m_launch_status; // This holds the status from the last launch attempt.
+ std::vector<std::string> m_arg_vec;
+ std::vector<std::string>
+ m_env_vec; // This will be unparsed - entries FOO=value
+ std::string m_working_directory;
+ std::string m_process_event;
+ bool m_detach_on_error;
+
+ void StartProcessStatusThread();
+ void StopProcessStatusThread();
+ static void *ThreadFunctionProcessStatus(void *arg);
private:
- //------------------------------------------------------------------
- // Outlaw copy and assignment operators
- //------------------------------------------------------------------
- RNBContext(const RNBContext& rhs);
- RNBContext& operator=(const RNBContext& rhs);
+ //------------------------------------------------------------------
+ // Outlaw copy and assignment operators
+ //------------------------------------------------------------------
+ RNBContext(const RNBContext &rhs);
+ RNBContext &operator=(const RNBContext &rhs);
};
#endif // #ifndef __RNBContext_h__
Modified: lldb/trunk/tools/debugserver/source/RNBDefs.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBDefs.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBDefs.h (original)
+++ lldb/trunk/tools/debugserver/source/RNBDefs.h Tue Sep 6 15:57:50 2016
@@ -17,52 +17,55 @@
#include "DNBDefs.h"
#include <memory>
-#define CONCAT2(a,b) a ## b
-#define CONCAT(a,b) CONCAT2(a,b)
+#define CONCAT2(a, b) a##b
+#define CONCAT(a, b) CONCAT2(a, b)
#define STRINGIZE2(x) #x
#define STRINGIZE(x) STRINGIZE2(x)
-#if !defined (DEBUGSERVER_PROGRAM_SYMBOL)
+#if !defined(DEBUGSERVER_PROGRAM_SYMBOL)
#define DEBUGSERVER_PROGRAM_SYMBOL debugserver
#endif
-#if !defined (DEBUGSERVER_PROGRAM_NAME)
+#if !defined(DEBUGSERVER_PROGRAM_NAME)
#define DEBUGSERVER_PROGRAM_NAME STRINGIZE(DEBUGSERVER_PROGRAM_SYMBOL)
#endif
#ifndef DEBUGSERVER_VERSION_NUM
-extern "C" const unsigned char CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionString)[];
-#define DEBUGSERVER_VERSION_NUM CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionNumber)
+extern "C" const unsigned char CONCAT(DEBUGSERVER_PROGRAM_SYMBOL,
+ VersionString)[];
+#define DEBUGSERVER_VERSION_NUM \
+ CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionNumber)
#endif
#ifndef DEBUGSERVER_VERSION_STR
extern "C" const double CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionNumber);
-#define DEBUGSERVER_VERSION_STR CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionString)
+#define DEBUGSERVER_VERSION_STR \
+ CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionString)
#endif
-#if defined (__i386__)
+#if defined(__i386__)
-#define RNB_ARCH "i386"
+#define RNB_ARCH "i386"
-#elif defined (__x86_64__)
+#elif defined(__x86_64__)
-#define RNB_ARCH "x86_64"
+#define RNB_ARCH "x86_64"
-#elif defined (__ppc64__)
+#elif defined(__ppc64__)
-#define RNB_ARCH "ppc64"
+#define RNB_ARCH "ppc64"
-#elif defined (__powerpc__) || defined (__ppc__)
+#elif defined(__powerpc__) || defined(__ppc__)
-#define RNB_ARCH "ppc"
+#define RNB_ARCH "ppc"
-#elif defined (__arm64__) || defined (__aarch64__)
+#elif defined(__arm64__) || defined(__aarch64__)
-#define RNB_ARCH "arm64"
+#define RNB_ARCH "arm64"
-#elif defined (__arm__)
+#elif defined(__arm__)
-#define RNB_ARCH "armv7"
+#define RNB_ARCH "armv7"
#else
@@ -73,25 +76,23 @@ extern "C" const double CONCAT(DEBUGSERV
class RNBRemote;
typedef std::shared_ptr<RNBRemote> RNBRemoteSP;
-typedef enum
-{
- rnb_success = 0,
- rnb_err = 1,
- rnb_not_connected = 2
-} rnb_err_t;
+typedef enum { rnb_success = 0, rnb_err = 1, rnb_not_connected = 2 } rnb_err_t;
// Log bits
// reserve low bits for DNB
-#define LOG_RNB_MINIMAL ((LOG_LO_USER) << 0) // Minimal logging (min verbosity)
-#define LOG_RNB_MEDIUM ((LOG_LO_USER) << 1) // Medium logging (med verbosity)
-#define LOG_RNB_MAX ((LOG_LO_USER) << 2) // Max logging (max verbosity)
-#define LOG_RNB_COMM ((LOG_LO_USER) << 3) // Log communications (RNBSocket)
-#define LOG_RNB_REMOTE ((LOG_LO_USER) << 4) // Log remote (RNBRemote)
-#define LOG_RNB_EVENTS ((LOG_LO_USER) << 5) // Log events (PThreadEvents)
-#define LOG_RNB_PROC ((LOG_LO_USER) << 6) // Log process state (Process thread)
-#define LOG_RNB_PACKETS ((LOG_LO_USER) << 7) // Log gdb remote packets
-#define LOG_RNB_ALL (~((LOG_LO_USER) - 1))
-#define LOG_RNB_DEFAULT (LOG_RNB_ALL)
+#define LOG_RNB_MINIMAL \
+ ((LOG_LO_USER) << 0) // Minimal logging (min verbosity)
+#define LOG_RNB_MEDIUM \
+ ((LOG_LO_USER) << 1) // Medium logging (med verbosity)
+#define LOG_RNB_MAX ((LOG_LO_USER) << 2) // Max logging (max verbosity)
+#define LOG_RNB_COMM ((LOG_LO_USER) << 3) // Log communications (RNBSocket)
+#define LOG_RNB_REMOTE ((LOG_LO_USER) << 4) // Log remote (RNBRemote)
+#define LOG_RNB_EVENTS \
+ ((LOG_LO_USER) << 5) // Log events (PThreadEvents)
+#define LOG_RNB_PROC ((LOG_LO_USER) << 6) // Log process state (Process thread)
+#define LOG_RNB_PACKETS ((LOG_LO_USER) << 7) // Log gdb remote packets
+#define LOG_RNB_ALL (~((LOG_LO_USER)-1))
+#define LOG_RNB_DEFAULT (LOG_RNB_ALL)
extern RNBRemoteSP g_remoteSP;
Modified: lldb/trunk/tools/debugserver/source/RNBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBRemote.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBRemote.cpp (original)
+++ lldb/trunk/tools/debugserver/source/RNBRemote.cpp Tue Sep 6 15:57:50 2016
@@ -14,46 +14,46 @@
#include "RNBRemote.h"
#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-#include <mach/exception_types.h>
#include <mach-o/loader.h>
+#include <mach/exception_types.h>
+#include <signal.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
+#include <unistd.h>
-#if defined (__APPLE__)
+#if defined(__APPLE__)
#include <pthread.h>
#include <sched.h>
#endif
-#include "DarwinLogCollector.h"
-#include "DarwinLogEvent.h"
#include "DNB.h"
#include "DNBDataRef.h"
#include "DNBLog.h"
#include "DNBThreadResumeActions.h"
+#include "DarwinLogCollector.h"
+#include "DarwinLogEvent.h"
+#include "JSON.h"
+#include "JSONGenerator.h"
#include "JSONGenerator.h"
+#include "MacOSX/Genealogy.h"
#include "OsLogger.h"
#include "RNBContext.h"
#include "RNBServices.h"
#include "RNBSocket.h"
-#include "JSON.h"
#include "lldb/Utility/StdStringExtractor.h"
-#include "MacOSX/Genealogy.h"
-#include "JSONGenerator.h"
-#if defined (HAVE_LIBCOMPRESSION)
+#if defined(HAVE_LIBCOMPRESSION)
#include <compression.h>
#endif
-#if defined (HAVE_LIBZ)
+#if defined(HAVE_LIBZ)
#include <zlib.h>
#endif
+#include <TargetConditionals.h> // for endianness predefines
#include <iomanip>
#include <sstream>
#include <unordered_set>
-#include <TargetConditionals.h> // for endianness predefines
//----------------------------------------------------------------------
// constants
@@ -61,3360 +61,3266 @@
static const std::string OS_LOG_EVENTS_KEY_NAME("events");
static const std::string JSON_ASYNC_TYPE_KEY_NAME("type");
-static const DarwinLogEventVector::size_type
- DARWIN_LOG_MAX_EVENTS_PER_PACKET = 10;
+static const DarwinLogEventVector::size_type DARWIN_LOG_MAX_EVENTS_PER_PACKET =
+ 10;
//----------------------------------------------------------------------
// std::iostream formatting macros
//----------------------------------------------------------------------
-#define RAW_HEXBASE std::setfill('0') << std::hex << std::right
-#define HEXBASE '0' << 'x' << RAW_HEXBASE
-#define RAWHEX8(x) RAW_HEXBASE << std::setw(2) << ((uint32_t)((uint8_t)x))
-#define RAWHEX16 RAW_HEXBASE << std::setw(4)
-#define RAWHEX32 RAW_HEXBASE << std::setw(8)
-#define RAWHEX64 RAW_HEXBASE << std::setw(16)
-#define HEX8(x) HEXBASE << std::setw(2) << ((uint32_t)(x))
-#define HEX16 HEXBASE << std::setw(4)
-#define HEX32 HEXBASE << std::setw(8)
-#define HEX64 HEXBASE << std::setw(16)
-#define RAW_HEX(x) RAW_HEXBASE << std::setw(sizeof(x)*2) << (x)
-#define HEX(x) HEXBASE << std::setw(sizeof(x)*2) << (x)
-#define RAWHEX_SIZE(x, sz) RAW_HEXBASE << std::setw((sz)) << (x)
+#define RAW_HEXBASE std::setfill('0') << std::hex << std::right
+#define HEXBASE '0' << 'x' << RAW_HEXBASE
+#define RAWHEX8(x) RAW_HEXBASE << std::setw(2) << ((uint32_t)((uint8_t)x))
+#define RAWHEX16 RAW_HEXBASE << std::setw(4)
+#define RAWHEX32 RAW_HEXBASE << std::setw(8)
+#define RAWHEX64 RAW_HEXBASE << std::setw(16)
+#define HEX8(x) HEXBASE << std::setw(2) << ((uint32_t)(x))
+#define HEX16 HEXBASE << std::setw(4)
+#define HEX32 HEXBASE << std::setw(8)
+#define HEX64 HEXBASE << std::setw(16)
+#define RAW_HEX(x) RAW_HEXBASE << std::setw(sizeof(x) * 2) << (x)
+#define HEX(x) HEXBASE << std::setw(sizeof(x) * 2) << (x)
+#define RAWHEX_SIZE(x, sz) RAW_HEXBASE << std::setw((sz)) << (x)
#define HEX_SIZE(x, sz) HEXBASE << std::setw((sz)) << (x)
#define STRING_WIDTH(w) std::setfill(' ') << std::setw(w)
-#define LEFT_STRING_WIDTH(s, w) std::left << std::setfill(' ') << std::setw(w) << (s) << std::right
-#define DECIMAL std::dec << std::setfill(' ')
+#define LEFT_STRING_WIDTH(s, w) \
+ std::left << std::setfill(' ') << std::setw(w) << (s) << std::right
+#define DECIMAL std::dec << std::setfill(' ')
#define DECIMAL_WIDTH(w) DECIMAL << std::setw(w)
-#define FLOAT(n, d) std::setfill(' ') << std::setw((n)+(d)+1) << std::setprecision(d) << std::showpoint << std::fixed
-#define INDENT_WITH_SPACES(iword_idx) std::setfill(' ') << std::setw((iword_idx)) << ""
-#define INDENT_WITH_TABS(iword_idx) std::setfill('\t') << std::setw((iword_idx)) << ""
+#define FLOAT(n, d) \
+ std::setfill(' ') << std::setw((n) + (d) + 1) << std::setprecision(d) \
+ << std::showpoint << std::fixed
+#define INDENT_WITH_SPACES(iword_idx) \
+ std::setfill(' ') << std::setw((iword_idx)) << ""
+#define INDENT_WITH_TABS(iword_idx) \
+ std::setfill('\t') << std::setw((iword_idx)) << ""
// Class to handle communications via gdb remote protocol.
//----------------------------------------------------------------------
// Prototypes
//----------------------------------------------------------------------
-static std::string
-binary_encode_string (const std::string &s);
+static std::string binary_encode_string(const std::string &s);
//----------------------------------------------------------------------
// Decode a single hex character and return the hex value as a number or
// -1 if "ch" is not a hex character.
//----------------------------------------------------------------------
-static inline int
-xdigit_to_sint (char ch)
-{
- if (ch >= 'a' && ch <= 'f')
- return 10 + ch - 'a';
- if (ch >= 'A' && ch <= 'F')
- return 10 + ch - 'A';
- if (ch >= '0' && ch <= '9')
- return ch - '0';
- return -1;
+static inline int xdigit_to_sint(char ch) {
+ if (ch >= 'a' && ch <= 'f')
+ return 10 + ch - 'a';
+ if (ch >= 'A' && ch <= 'F')
+ return 10 + ch - 'A';
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ return -1;
}
//----------------------------------------------------------------------
// Decode a single hex ASCII byte. Return -1 on failure, a value 0-255
// on success.
//----------------------------------------------------------------------
-static inline int
-decoded_hex_ascii_char(const char *p)
-{
- const int hi_nibble = xdigit_to_sint(p[0]);
- if (hi_nibble == -1)
- return -1;
- const int lo_nibble = xdigit_to_sint(p[1]);
- if (lo_nibble == -1)
- return -1;
- return (uint8_t)((hi_nibble << 4) + lo_nibble);
+static inline int decoded_hex_ascii_char(const char *p) {
+ const int hi_nibble = xdigit_to_sint(p[0]);
+ if (hi_nibble == -1)
+ return -1;
+ const int lo_nibble = xdigit_to_sint(p[1]);
+ if (lo_nibble == -1)
+ return -1;
+ return (uint8_t)((hi_nibble << 4) + lo_nibble);
}
//----------------------------------------------------------------------
// Decode a hex ASCII string back into a string
//----------------------------------------------------------------------
-static std::string
-decode_hex_ascii_string(const char *p, uint32_t max_length = UINT32_MAX)
-{
- std::string arg;
- if (p)
- {
- for (const char *c = p; ((c - p)/2) < max_length; c += 2)
- {
- int ch = decoded_hex_ascii_char(c);
- if (ch == -1)
- break;
- else
- arg.push_back(ch);
- }
+static std::string decode_hex_ascii_string(const char *p,
+ uint32_t max_length = UINT32_MAX) {
+ std::string arg;
+ if (p) {
+ for (const char *c = p; ((c - p) / 2) < max_length; c += 2) {
+ int ch = decoded_hex_ascii_char(c);
+ if (ch == -1)
+ break;
+ else
+ arg.push_back(ch);
}
- return arg;
+ }
+ return arg;
}
-uint64_t
-decode_uint64 (const char *p, int base, char **end = nullptr, uint64_t fail_value = 0)
-{
- nub_addr_t addr = strtoull (p, end, 16);
- if (addr == 0 && errno != 0)
- return fail_value;
- return addr;
+uint64_t decode_uint64(const char *p, int base, char **end = nullptr,
+ uint64_t fail_value = 0) {
+ nub_addr_t addr = strtoull(p, end, 16);
+ if (addr == 0 && errno != 0)
+ return fail_value;
+ return addr;
}
-extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
+extern void ASLLogCallback(void *baton, uint32_t flags, const char *format,
+ va_list args);
-#if defined (__APPLE__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000)
+#if defined(__APPLE__) && \
+ (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000)
// from System.framework/Versions/B/PrivateHeaders/sys/codesign.h
extern "C" {
-#define CS_OPS_STATUS 0 /* return status */
-#define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */
-int csops(pid_t pid, unsigned int ops, void * useraddr, size_t usersize);
+#define CS_OPS_STATUS 0 /* return status */
+#define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */
+int csops(pid_t pid, unsigned int ops, void *useraddr, size_t usersize);
// from rootless.h
-bool rootless_allows_task_for_pid (pid_t pid);
+bool rootless_allows_task_for_pid(pid_t pid);
// from sys/csr.h
typedef uint32_t csr_config_t;
-#define CSR_ALLOW_TASK_FOR_PID (1 << 2)
+#define CSR_ALLOW_TASK_FOR_PID (1 << 2)
int csr_check(csr_config_t mask);
}
#endif
-RNBRemote::RNBRemote () :
- m_ctx (),
- m_comm (),
- m_arch (),
- m_continue_thread(-1),
- m_thread(-1),
- m_mutex(),
- m_dispatch_queue_offsets (),
- m_dispatch_queue_offsets_addr (INVALID_NUB_ADDRESS),
- m_qSymbol_index (UINT32_MAX),
- m_packets_recvd(0),
- m_packets(),
- m_rx_packets(),
- m_rx_partial_data(),
- m_rx_pthread(0),
- m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4),
- m_extended_mode(false),
- m_noack_mode(false),
- m_thread_suffix_supported (false),
- m_list_threads_in_stop_reply (false),
- m_compression_minsize (384),
- m_enable_compression_next_send_packet (false),
- m_compression_mode (compression_types::none)
-{
- DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
- CreatePacketTable ();
-}
-
-
-RNBRemote::~RNBRemote()
-{
- DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
- StopReadRemoteDataThread();
-}
-
-void
-RNBRemote::CreatePacketTable ()
-{
- // Step required to add new packets:
- // 1 - Add new enumeration to RNBRemote::PacketEnum
- // 2 - Create the RNBRemote::HandlePacket_ function if a new function is needed
- // 3 - Register the Packet definition with any needed callbacks in this function
- // - If no response is needed for a command, then use NULL for the normal callback
- // - If the packet is not supported while the target is running, use NULL for the async callback
- // 4 - If the packet is a standard packet (starts with a '$' character
- // followed by the payload and then '#' and checksum, then you are done
- // else go on to step 5
- // 5 - if the packet is a fixed length packet:
- // - modify the switch statement for the first character in the payload
- // in RNBRemote::CommDataReceived so it doesn't reject the new packet
- // type as invalid
- // - modify the switch statement for the first character in the payload
- // in RNBRemote::GetPacketPayload and make sure the payload of the packet
- // is returned correctly
-
- std::vector <Packet> &t = m_packets;
- t.push_back (Packet (ack, NULL, NULL, "+", "ACK"));
- t.push_back (Packet (nack, NULL, NULL, "-", "!ACK"));
- t.push_back (Packet (read_memory, &RNBRemote::HandlePacket_m, NULL, "m", "Read memory"));
- t.push_back (Packet (read_register, &RNBRemote::HandlePacket_p, NULL, "p", "Read one register"));
- t.push_back (Packet (read_general_regs, &RNBRemote::HandlePacket_g, NULL, "g", "Read registers"));
- t.push_back (Packet (write_memory, &RNBRemote::HandlePacket_M, NULL, "M", "Write memory"));
- t.push_back (Packet (write_register, &RNBRemote::HandlePacket_P, NULL, "P", "Write one register"));
- t.push_back (Packet (write_general_regs, &RNBRemote::HandlePacket_G, NULL, "G", "Write registers"));
- t.push_back (Packet (insert_mem_bp, &RNBRemote::HandlePacket_z, NULL, "Z0", "Insert memory breakpoint"));
- t.push_back (Packet (remove_mem_bp, &RNBRemote::HandlePacket_z, NULL, "z0", "Remove memory breakpoint"));
- t.push_back (Packet (single_step, &RNBRemote::HandlePacket_s, NULL, "s", "Single step"));
- t.push_back (Packet (cont, &RNBRemote::HandlePacket_c, NULL, "c", "continue"));
- t.push_back (Packet (single_step_with_sig, &RNBRemote::HandlePacket_S, NULL, "S", "Single step with signal"));
- t.push_back (Packet (set_thread, &RNBRemote::HandlePacket_H, NULL, "H", "Set thread"));
- t.push_back (Packet (halt, &RNBRemote::HandlePacket_last_signal, &RNBRemote::HandlePacket_stop_process, "\x03", "^C"));
-// t.push_back (Packet (use_extended_mode, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "!", "Use extended mode"));
- t.push_back (Packet (why_halted, &RNBRemote::HandlePacket_last_signal, NULL, "?", "Why did target halt"));
- t.push_back (Packet (set_argv, &RNBRemote::HandlePacket_A, NULL, "A", "Set argv"));
-// t.push_back (Packet (set_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "B", "Set/clear breakpoint"));
- t.push_back (Packet (continue_with_sig, &RNBRemote::HandlePacket_C, NULL, "C", "Continue with signal"));
- t.push_back (Packet (detach, &RNBRemote::HandlePacket_D, NULL, "D", "Detach gdb from remote system"));
-// t.push_back (Packet (step_inferior_one_cycle, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "i", "Step inferior by one clock cycle"));
-// t.push_back (Packet (signal_and_step_inf_one_cycle, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "I", "Signal inferior, then step one clock cycle"));
- t.push_back (Packet (kill, &RNBRemote::HandlePacket_k, NULL, "k", "Kill"));
-// t.push_back (Packet (restart, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "R", "Restart inferior"));
-// t.push_back (Packet (search_mem_backwards, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "t", "Search memory backwards"));
- t.push_back (Packet (thread_alive_p, &RNBRemote::HandlePacket_T, NULL, "T", "Is thread alive"));
- t.push_back (Packet (query_supported_features, &RNBRemote::HandlePacket_qSupported, NULL, "qSupported", "Query about supported features"));
- t.push_back (Packet (vattach, &RNBRemote::HandlePacket_v, NULL, "vAttach", "Attach to a new process"));
- t.push_back (Packet (vattachwait, &RNBRemote::HandlePacket_v, NULL, "vAttachWait", "Wait for a process to start up then attach to it"));
- t.push_back (Packet (vattachorwait, &RNBRemote::HandlePacket_v, NULL, "vAttachOrWait", "Attach to the process or if it doesn't exist, wait for the process to start up then attach to it"));
- t.push_back (Packet (vattachname, &RNBRemote::HandlePacket_v, NULL, "vAttachName", "Attach to an existing process by name"));
- t.push_back (Packet (vcont_list_actions, &RNBRemote::HandlePacket_v, NULL, "vCont;", "Verbose resume with thread actions"));
- t.push_back (Packet (vcont_list_actions, &RNBRemote::HandlePacket_v, NULL, "vCont?", "List valid continue-with-thread-actions actions"));
- t.push_back (Packet (read_data_from_memory, &RNBRemote::HandlePacket_x, NULL, "x", "Read data from memory"));
- t.push_back (Packet (write_data_to_memory, &RNBRemote::HandlePacket_X, NULL, "X", "Write data to memory"));
-// t.push_back (Packet (insert_hardware_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z1", "Insert hardware breakpoint"));
-// t.push_back (Packet (remove_hardware_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z1", "Remove hardware breakpoint"));
- t.push_back (Packet (insert_write_watch_bp, &RNBRemote::HandlePacket_z, NULL, "Z2", "Insert write watchpoint"));
- t.push_back (Packet (remove_write_watch_bp, &RNBRemote::HandlePacket_z, NULL, "z2", "Remove write watchpoint"));
- t.push_back (Packet (insert_read_watch_bp, &RNBRemote::HandlePacket_z, NULL, "Z3", "Insert read watchpoint"));
- t.push_back (Packet (remove_read_watch_bp, &RNBRemote::HandlePacket_z, NULL, "z3", "Remove read watchpoint"));
- t.push_back (Packet (insert_access_watch_bp, &RNBRemote::HandlePacket_z, NULL, "Z4", "Insert access watchpoint"));
- t.push_back (Packet (remove_access_watch_bp, &RNBRemote::HandlePacket_z, NULL, "z4", "Remove access watchpoint"));
- t.push_back (Packet (query_monitor, &RNBRemote::HandlePacket_qRcmd, NULL, "qRcmd", "Monitor command"));
- t.push_back (Packet (query_current_thread_id, &RNBRemote::HandlePacket_qC, NULL, "qC", "Query current thread ID"));
- t.push_back (Packet (query_echo, &RNBRemote::HandlePacket_qEcho, NULL, "qEcho:", "Echo the packet back to allow the debugger to sync up with this server"));
- t.push_back (Packet (query_get_pid, &RNBRemote::HandlePacket_qGetPid, NULL, "qGetPid", "Query process id"));
- t.push_back (Packet (query_thread_ids_first, &RNBRemote::HandlePacket_qThreadInfo, NULL, "qfThreadInfo", "Get list of active threads (first req)"));
- t.push_back (Packet (query_thread_ids_subsequent, &RNBRemote::HandlePacket_qThreadInfo, NULL, "qsThreadInfo", "Get list of active threads (subsequent req)"));
- // APPLE LOCAL: qThreadStopInfo
- // syntax: qThreadStopInfoTTTT
- // TTTT is hex thread ID
- t.push_back (Packet (query_thread_stop_info, &RNBRemote::HandlePacket_qThreadStopInfo, NULL, "qThreadStopInfo", "Get detailed info on why the specified thread stopped"));
- t.push_back (Packet (query_thread_extra_info, &RNBRemote::HandlePacket_qThreadExtraInfo,NULL, "qThreadExtraInfo", "Get printable status of a thread"));
-// t.push_back (Packet (query_image_offsets, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qOffsets", "Report offset of loaded program"));
- t.push_back (Packet (query_launch_success, &RNBRemote::HandlePacket_qLaunchSuccess,NULL, "qLaunchSuccess", "Report the success or failure of the launch attempt"));
- t.push_back (Packet (query_register_info, &RNBRemote::HandlePacket_qRegisterInfo, NULL, "qRegisterInfo", "Dynamically discover remote register context information."));
- t.push_back (Packet (query_shlib_notify_info_addr, &RNBRemote::HandlePacket_qShlibInfoAddr,NULL, "qShlibInfoAddr", "Returns the address that contains info needed for getting shared library notifications"));
- t.push_back (Packet (query_step_packet_supported, &RNBRemote::HandlePacket_qStepPacketSupported,NULL, "qStepPacketSupported", "Replys with OK if the 's' packet is supported."));
- t.push_back (Packet (query_vattachorwait_supported, &RNBRemote::HandlePacket_qVAttachOrWaitSupported,NULL, "qVAttachOrWaitSupported", "Replys with OK if the 'vAttachOrWait' packet is supported."));
- t.push_back (Packet (query_sync_thread_state_supported, &RNBRemote::HandlePacket_qSyncThreadStateSupported,NULL, "qSyncThreadStateSupported", "Replys with OK if the 'QSyncThreadState:' packet is supported."));
- t.push_back (Packet (query_host_info, &RNBRemote::HandlePacket_qHostInfo , NULL, "qHostInfo", "Replies with multiple 'key:value;' tuples appended to each other."));
- t.push_back (Packet (query_gdb_server_version, &RNBRemote::HandlePacket_qGDBServerVersion , NULL, "qGDBServerVersion", "Replies with multiple 'key:value;' tuples appended to each other."));
- t.push_back (Packet (query_process_info, &RNBRemote::HandlePacket_qProcessInfo , NULL, "qProcessInfo", "Replies with multiple 'key:value;' tuples appended to each other."));
- t.push_back (Packet (query_symbol_lookup, &RNBRemote::HandlePacket_qSymbol , NULL, "qSymbol:", "Notify that host debugger is ready to do symbol lookups"));
- t.push_back (Packet (json_query_thread_extended_info,&RNBRemote::HandlePacket_jThreadExtendedInfo , NULL, "jThreadExtendedInfo", "Replies with JSON data of thread extended information."));
- t.push_back (Packet (json_query_get_loaded_dynamic_libraries_infos, &RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos, NULL, "jGetLoadedDynamicLibrariesInfos", "Replies with JSON data of all the shared libraries loaded in this process."));
- t.push_back (Packet (json_query_threads_info, &RNBRemote::HandlePacket_jThreadsInfo , NULL, "jThreadsInfo", "Replies with JSON data with information about all threads."));
- t.push_back (Packet (json_query_get_shared_cache_info, &RNBRemote::HandlePacket_jGetSharedCacheInfo, NULL, "jGetSharedCacheInfo", "Replies with JSON data about the location and uuid of the shared cache in the inferior process."));
- t.push_back (Packet (start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets"));
- t.push_back (Packet (prefix_reg_packets_with_tid, &RNBRemote::HandlePacket_QThreadSuffixSupported , NULL, "QThreadSuffixSupported", "Check if thread specific packets (register packets 'g', 'G', 'p', and 'P') support having the thread ID appended to the end of the command"));
- t.push_back (Packet (set_logging_mode, &RNBRemote::HandlePacket_QSetLogging , NULL, "QSetLogging:", "Check if register packets ('g', 'G', 'p', and 'P' support having the thread ID prefix"));
- t.push_back (Packet (set_max_packet_size, &RNBRemote::HandlePacket_QSetMaxPacketSize , NULL, "QSetMaxPacketSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle"));
- t.push_back (Packet (set_max_payload_size, &RNBRemote::HandlePacket_QSetMaxPayloadSize , NULL, "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized payload gdb can handle"));
- t.push_back (Packet (set_environment_variable, &RNBRemote::HandlePacket_QEnvironment , NULL, "QEnvironment:", "Add an environment variable to the inferior's environment"));
- t.push_back (Packet (set_environment_variable_hex, &RNBRemote::HandlePacket_QEnvironmentHexEncoded , NULL, "QEnvironmentHexEncoded:", "Add an environment variable to the inferior's environment"));
- t.push_back (Packet (set_launch_arch, &RNBRemote::HandlePacket_QLaunchArch , NULL, "QLaunchArch:", "Set the architecture to use when launching a process for hosts that can run multiple architecture slices from universal files."));
- t.push_back (Packet (set_disable_aslr, &RNBRemote::HandlePacket_QSetDisableASLR , NULL, "QSetDisableASLR:", "Set whether to disable ASLR when launching the process with the set argv ('A') packet"));
- t.push_back (Packet (set_stdin, &RNBRemote::HandlePacket_QSetSTDIO , NULL, "QSetSTDIN:", "Set the standard input for a process to be launched with the 'A' packet"));
- t.push_back (Packet (set_stdout, &RNBRemote::HandlePacket_QSetSTDIO , NULL, "QSetSTDOUT:", "Set the standard output for a process to be launched with the 'A' packet"));
- t.push_back (Packet (set_stderr, &RNBRemote::HandlePacket_QSetSTDIO , NULL, "QSetSTDERR:", "Set the standard error for a process to be launched with the 'A' packet"));
- t.push_back (Packet (set_working_dir, &RNBRemote::HandlePacket_QSetWorkingDir , NULL, "QSetWorkingDir:", "Set the working directory for a process to be launched with the 'A' packet"));
- t.push_back (Packet (set_list_threads_in_stop_reply,&RNBRemote::HandlePacket_QListThreadsInStopReply , NULL, "QListThreadsInStopReply", "Set if the 'threads' key should be added to the stop reply packets with a list of all thread IDs."));
- t.push_back (Packet (sync_thread_state, &RNBRemote::HandlePacket_QSyncThreadState , NULL, "QSyncThreadState:", "Do whatever is necessary to make sure 'thread' is in a safe state to call functions on."));
-// t.push_back (Packet (pass_signals_to_inferior, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify which signals are passed to the inferior"));
- t.push_back (Packet (allocate_memory, &RNBRemote::HandlePacket_AllocateMemory, NULL, "_M", "Allocate memory in the inferior process."));
- t.push_back (Packet (deallocate_memory, &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", "Deallocate memory in the inferior process."));
- t.push_back (Packet (save_register_state, &RNBRemote::HandlePacket_SaveRegisterState, NULL, "QSaveRegisterState", "Save the register state for the current thread and return a decimal save ID."));
- t.push_back (Packet (restore_register_state, &RNBRemote::HandlePacket_RestoreRegisterState, NULL, "QRestoreRegisterState:", "Restore the register state given a save ID previously returned from a call to QSaveRegisterState."));
- t.push_back (Packet (memory_region_info, &RNBRemote::HandlePacket_MemoryRegionInfo, NULL, "qMemoryRegionInfo", "Return size and attributes of a memory region that contains the given address"));
- t.push_back (Packet (get_profile_data, &RNBRemote::HandlePacket_GetProfileData, NULL, "qGetProfileData", "Return profiling data of the current target."));
- t.push_back (Packet (set_enable_profiling, &RNBRemote::HandlePacket_SetEnableAsyncProfiling, NULL, "QSetEnableAsyncProfiling", "Enable or disable the profiling of current target."));
- t.push_back (Packet (enable_compression, &RNBRemote::HandlePacket_QEnableCompression, NULL, "QEnableCompression:", "Enable compression for the remainder of the connection"));
- t.push_back (Packet (watchpoint_support_info, &RNBRemote::HandlePacket_WatchpointSupportInfo, NULL, "qWatchpointSupportInfo", "Return the number of supported hardware watchpoints"));
- t.push_back (Packet (set_process_event, &RNBRemote::HandlePacket_QSetProcessEvent, NULL, "QSetProcessEvent:", "Set a process event, to be passed to the process, can be set before the process is started, or after."));
- t.push_back (Packet (set_detach_on_error, &RNBRemote::HandlePacket_QSetDetachOnError, NULL, "QSetDetachOnError:", "Set whether debugserver will detach (1) or kill (0) from the process it is controlling if it loses connection to lldb."));
- t.push_back (Packet (speed_test, &RNBRemote::HandlePacket_qSpeedTest, NULL, "qSpeedTest:", "Test the maximum speed at which packet can be sent/received."));
- t.push_back (Packet (query_transfer, &RNBRemote::HandlePacket_qXfer, NULL, "qXfer:", "Support the qXfer packet."));
- t.push_back (Packet (query_supported_async_json_packets, &RNBRemote::HandlePacket_qStructuredDataPlugins, NULL, "qStructuredDataPlugins", "Query for the structured data plugins supported by the remote."));
- t.push_back (Packet (configure_darwin_log, &RNBRemote::HandlePacket_QConfigureDarwinLog, NULL, "QConfigureDarwinLog:", "Configure the DarwinLog structured data plugin support."));
-}
-
-void
-RNBRemote::FlushSTDIO ()
-{
- if (m_ctx.HasValidProcessID())
- {
- nub_process_t pid = m_ctx.ProcessID();
- char buf[256];
- nub_size_t count;
- do
- {
- count = DNBProcessGetAvailableSTDOUT(pid, buf, sizeof(buf));
- if (count > 0)
- {
- SendSTDOUTPacket (buf, count);
- }
- } while (count > 0);
+RNBRemote::RNBRemote()
+ : m_ctx(), m_comm(), m_arch(), m_continue_thread(-1), m_thread(-1),
+ m_mutex(), m_dispatch_queue_offsets(),
+ m_dispatch_queue_offsets_addr(INVALID_NUB_ADDRESS),
+ m_qSymbol_index(UINT32_MAX), m_packets_recvd(0), m_packets(),
+ m_rx_packets(), m_rx_partial_data(), m_rx_pthread(0),
+ m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4),
+ m_extended_mode(false), m_noack_mode(false),
+ m_thread_suffix_supported(false), m_list_threads_in_stop_reply(false),
+ m_compression_minsize(384), m_enable_compression_next_send_packet(false),
+ m_compression_mode(compression_types::none) {
+ DNBLogThreadedIf(LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
+ CreatePacketTable();
+}
+
+RNBRemote::~RNBRemote() {
+ DNBLogThreadedIf(LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
+ StopReadRemoteDataThread();
+}
+
+void RNBRemote::CreatePacketTable() {
+ // Step required to add new packets:
+ // 1 - Add new enumeration to RNBRemote::PacketEnum
+ // 2 - Create the RNBRemote::HandlePacket_ function if a new function is
+ // needed
+ // 3 - Register the Packet definition with any needed callbacks in this
+ // function
+ // - If no response is needed for a command, then use NULL for the
+ // normal callback
+ // - If the packet is not supported while the target is running, use
+ // NULL for the async callback
+ // 4 - If the packet is a standard packet (starts with a '$' character
+ // followed by the payload and then '#' and checksum, then you are done
+ // else go on to step 5
+ // 5 - if the packet is a fixed length packet:
+ // - modify the switch statement for the first character in the payload
+ // in RNBRemote::CommDataReceived so it doesn't reject the new packet
+ // type as invalid
+ // - modify the switch statement for the first character in the payload
+ // in RNBRemote::GetPacketPayload and make sure the payload of the
+ // packet
+ // is returned correctly
+
+ std::vector<Packet> &t = m_packets;
+ t.push_back(Packet(ack, NULL, NULL, "+", "ACK"));
+ t.push_back(Packet(nack, NULL, NULL, "-", "!ACK"));
+ t.push_back(Packet(read_memory, &RNBRemote::HandlePacket_m, NULL, "m",
+ "Read memory"));
+ t.push_back(Packet(read_register, &RNBRemote::HandlePacket_p, NULL, "p",
+ "Read one register"));
+ t.push_back(Packet(read_general_regs, &RNBRemote::HandlePacket_g, NULL, "g",
+ "Read registers"));
+ t.push_back(Packet(write_memory, &RNBRemote::HandlePacket_M, NULL, "M",
+ "Write memory"));
+ t.push_back(Packet(write_register, &RNBRemote::HandlePacket_P, NULL, "P",
+ "Write one register"));
+ t.push_back(Packet(write_general_regs, &RNBRemote::HandlePacket_G, NULL, "G",
+ "Write registers"));
+ t.push_back(Packet(insert_mem_bp, &RNBRemote::HandlePacket_z, NULL, "Z0",
+ "Insert memory breakpoint"));
+ t.push_back(Packet(remove_mem_bp, &RNBRemote::HandlePacket_z, NULL, "z0",
+ "Remove memory breakpoint"));
+ t.push_back(Packet(single_step, &RNBRemote::HandlePacket_s, NULL, "s",
+ "Single step"));
+ t.push_back(Packet(cont, &RNBRemote::HandlePacket_c, NULL, "c", "continue"));
+ t.push_back(Packet(single_step_with_sig, &RNBRemote::HandlePacket_S, NULL,
+ "S", "Single step with signal"));
+ t.push_back(
+ Packet(set_thread, &RNBRemote::HandlePacket_H, NULL, "H", "Set thread"));
+ t.push_back(Packet(halt, &RNBRemote::HandlePacket_last_signal,
+ &RNBRemote::HandlePacket_stop_process, "\x03", "^C"));
+ // t.push_back (Packet (use_extended_mode,
+ // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "!", "Use extended mode"));
+ t.push_back(Packet(why_halted, &RNBRemote::HandlePacket_last_signal, NULL,
+ "?", "Why did target halt"));
+ t.push_back(
+ Packet(set_argv, &RNBRemote::HandlePacket_A, NULL, "A", "Set argv"));
+ // t.push_back (Packet (set_bp,
+ // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "B", "Set/clear
+ // breakpoint"));
+ t.push_back(Packet(continue_with_sig, &RNBRemote::HandlePacket_C, NULL, "C",
+ "Continue with signal"));
+ t.push_back(Packet(detach, &RNBRemote::HandlePacket_D, NULL, "D",
+ "Detach gdb from remote system"));
+ // t.push_back (Packet (step_inferior_one_cycle,
+ // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "i", "Step inferior by one
+ // clock cycle"));
+ // t.push_back (Packet (signal_and_step_inf_one_cycle,
+ // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "I", "Signal inferior, then
+ // step one clock cycle"));
+ t.push_back(Packet(kill, &RNBRemote::HandlePacket_k, NULL, "k", "Kill"));
+ // t.push_back (Packet (restart,
+ // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "R", "Restart inferior"));
+ // t.push_back (Packet (search_mem_backwards,
+ // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "t", "Search memory
+ // backwards"));
+ t.push_back(Packet(thread_alive_p, &RNBRemote::HandlePacket_T, NULL, "T",
+ "Is thread alive"));
+ t.push_back(Packet(query_supported_features,
+ &RNBRemote::HandlePacket_qSupported, NULL, "qSupported",
+ "Query about supported features"));
+ t.push_back(Packet(vattach, &RNBRemote::HandlePacket_v, NULL, "vAttach",
+ "Attach to a new process"));
+ t.push_back(Packet(vattachwait, &RNBRemote::HandlePacket_v, NULL,
+ "vAttachWait",
+ "Wait for a process to start up then attach to it"));
+ t.push_back(Packet(vattachorwait, &RNBRemote::HandlePacket_v, NULL,
+ "vAttachOrWait", "Attach to the process or if it doesn't "
+ "exist, wait for the process to start up "
+ "then attach to it"));
+ t.push_back(Packet(vattachname, &RNBRemote::HandlePacket_v, NULL,
+ "vAttachName", "Attach to an existing process by name"));
+ t.push_back(Packet(vcont_list_actions, &RNBRemote::HandlePacket_v, NULL,
+ "vCont;", "Verbose resume with thread actions"));
+ t.push_back(Packet(vcont_list_actions, &RNBRemote::HandlePacket_v, NULL,
+ "vCont?",
+ "List valid continue-with-thread-actions actions"));
+ t.push_back(Packet(read_data_from_memory, &RNBRemote::HandlePacket_x, NULL,
+ "x", "Read data from memory"));
+ t.push_back(Packet(write_data_to_memory, &RNBRemote::HandlePacket_X, NULL,
+ "X", "Write data to memory"));
+ // t.push_back (Packet (insert_hardware_bp,
+ // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z1", "Insert hardware
+ // breakpoint"));
+ // t.push_back (Packet (remove_hardware_bp,
+ // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z1", "Remove hardware
+ // breakpoint"));
+ t.push_back(Packet(insert_write_watch_bp, &RNBRemote::HandlePacket_z, NULL,
+ "Z2", "Insert write watchpoint"));
+ t.push_back(Packet(remove_write_watch_bp, &RNBRemote::HandlePacket_z, NULL,
+ "z2", "Remove write watchpoint"));
+ t.push_back(Packet(insert_read_watch_bp, &RNBRemote::HandlePacket_z, NULL,
+ "Z3", "Insert read watchpoint"));
+ t.push_back(Packet(remove_read_watch_bp, &RNBRemote::HandlePacket_z, NULL,
+ "z3", "Remove read watchpoint"));
+ t.push_back(Packet(insert_access_watch_bp, &RNBRemote::HandlePacket_z, NULL,
+ "Z4", "Insert access watchpoint"));
+ t.push_back(Packet(remove_access_watch_bp, &RNBRemote::HandlePacket_z, NULL,
+ "z4", "Remove access watchpoint"));
+ t.push_back(Packet(query_monitor, &RNBRemote::HandlePacket_qRcmd, NULL,
+ "qRcmd", "Monitor command"));
+ t.push_back(Packet(query_current_thread_id, &RNBRemote::HandlePacket_qC, NULL,
+ "qC", "Query current thread ID"));
+ t.push_back(Packet(query_echo, &RNBRemote::HandlePacket_qEcho, NULL, "qEcho:",
+ "Echo the packet back to allow the debugger to sync up "
+ "with this server"));
+ t.push_back(Packet(query_get_pid, &RNBRemote::HandlePacket_qGetPid, NULL,
+ "qGetPid", "Query process id"));
+ t.push_back(Packet(query_thread_ids_first,
+ &RNBRemote::HandlePacket_qThreadInfo, NULL, "qfThreadInfo",
+ "Get list of active threads (first req)"));
+ t.push_back(Packet(query_thread_ids_subsequent,
+ &RNBRemote::HandlePacket_qThreadInfo, NULL, "qsThreadInfo",
+ "Get list of active threads (subsequent req)"));
+ // APPLE LOCAL: qThreadStopInfo
+ // syntax: qThreadStopInfoTTTT
+ // TTTT is hex thread ID
+ t.push_back(Packet(query_thread_stop_info,
+ &RNBRemote::HandlePacket_qThreadStopInfo, NULL,
+ "qThreadStopInfo",
+ "Get detailed info on why the specified thread stopped"));
+ t.push_back(Packet(query_thread_extra_info,
+ &RNBRemote::HandlePacket_qThreadExtraInfo, NULL,
+ "qThreadExtraInfo", "Get printable status of a thread"));
+ // t.push_back (Packet (query_image_offsets,
+ // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qOffsets", "Report offset
+ // of loaded program"));
+ t.push_back(Packet(
+ query_launch_success, &RNBRemote::HandlePacket_qLaunchSuccess, NULL,
+ "qLaunchSuccess", "Report the success or failure of the launch attempt"));
+ t.push_back(
+ Packet(query_register_info, &RNBRemote::HandlePacket_qRegisterInfo, NULL,
+ "qRegisterInfo",
+ "Dynamically discover remote register context information."));
+ t.push_back(Packet(
+ query_shlib_notify_info_addr, &RNBRemote::HandlePacket_qShlibInfoAddr,
+ NULL, "qShlibInfoAddr", "Returns the address that contains info needed "
+ "for getting shared library notifications"));
+ t.push_back(Packet(query_step_packet_supported,
+ &RNBRemote::HandlePacket_qStepPacketSupported, NULL,
+ "qStepPacketSupported",
+ "Replys with OK if the 's' packet is supported."));
+ t.push_back(
+ Packet(query_vattachorwait_supported,
+ &RNBRemote::HandlePacket_qVAttachOrWaitSupported, NULL,
+ "qVAttachOrWaitSupported",
+ "Replys with OK if the 'vAttachOrWait' packet is supported."));
+ t.push_back(
+ Packet(query_sync_thread_state_supported,
+ &RNBRemote::HandlePacket_qSyncThreadStateSupported, NULL,
+ "qSyncThreadStateSupported",
+ "Replys with OK if the 'QSyncThreadState:' packet is supported."));
+ t.push_back(Packet(
+ query_host_info, &RNBRemote::HandlePacket_qHostInfo, NULL, "qHostInfo",
+ "Replies with multiple 'key:value;' tuples appended to each other."));
+ t.push_back(Packet(
+ query_gdb_server_version, &RNBRemote::HandlePacket_qGDBServerVersion,
+ NULL, "qGDBServerVersion",
+ "Replies with multiple 'key:value;' tuples appended to each other."));
+ t.push_back(Packet(
+ query_process_info, &RNBRemote::HandlePacket_qProcessInfo, NULL,
+ "qProcessInfo",
+ "Replies with multiple 'key:value;' tuples appended to each other."));
+ t.push_back(Packet(
+ query_symbol_lookup, &RNBRemote::HandlePacket_qSymbol, NULL, "qSymbol:",
+ "Notify that host debugger is ready to do symbol lookups"));
+ t.push_back(Packet(json_query_thread_extended_info,
+ &RNBRemote::HandlePacket_jThreadExtendedInfo, NULL,
+ "jThreadExtendedInfo",
+ "Replies with JSON data of thread extended information."));
+ t.push_back(Packet(json_query_get_loaded_dynamic_libraries_infos,
+ &RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos,
+ NULL, "jGetLoadedDynamicLibrariesInfos",
+ "Replies with JSON data of all the shared libraries "
+ "loaded in this process."));
+ t.push_back(
+ Packet(json_query_threads_info, &RNBRemote::HandlePacket_jThreadsInfo,
+ NULL, "jThreadsInfo",
+ "Replies with JSON data with information about all threads."));
+ t.push_back(Packet(json_query_get_shared_cache_info,
+ &RNBRemote::HandlePacket_jGetSharedCacheInfo, NULL,
+ "jGetSharedCacheInfo", "Replies with JSON data about the "
+ "location and uuid of the shared "
+ "cache in the inferior process."));
+ t.push_back(Packet(start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode,
+ NULL, "QStartNoAckMode",
+ "Request that " DEBUGSERVER_PROGRAM_NAME
+ " stop acking remote protocol packets"));
+ t.push_back(Packet(prefix_reg_packets_with_tid,
+ &RNBRemote::HandlePacket_QThreadSuffixSupported, NULL,
+ "QThreadSuffixSupported",
+ "Check if thread specific packets (register packets 'g', "
+ "'G', 'p', and 'P') support having the thread ID appended "
+ "to the end of the command"));
+ t.push_back(Packet(set_logging_mode, &RNBRemote::HandlePacket_QSetLogging,
+ NULL, "QSetLogging:", "Check if register packets ('g', "
+ "'G', 'p', and 'P' support having "
+ "the thread ID prefix"));
+ t.push_back(Packet(
+ set_max_packet_size, &RNBRemote::HandlePacket_QSetMaxPacketSize, NULL,
+ "QSetMaxPacketSize:",
+ "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle"));
+ t.push_back(Packet(
+ set_max_payload_size, &RNBRemote::HandlePacket_QSetMaxPayloadSize, NULL,
+ "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME
+ " the max sized payload gdb can handle"));
+ t.push_back(
+ Packet(set_environment_variable, &RNBRemote::HandlePacket_QEnvironment,
+ NULL, "QEnvironment:",
+ "Add an environment variable to the inferior's environment"));
+ t.push_back(
+ Packet(set_environment_variable_hex,
+ &RNBRemote::HandlePacket_QEnvironmentHexEncoded, NULL,
+ "QEnvironmentHexEncoded:",
+ "Add an environment variable to the inferior's environment"));
+ t.push_back(Packet(set_launch_arch, &RNBRemote::HandlePacket_QLaunchArch,
+ NULL, "QLaunchArch:", "Set the architecture to use when "
+ "launching a process for hosts that "
+ "can run multiple architecture "
+ "slices from universal files."));
+ t.push_back(Packet(set_disable_aslr, &RNBRemote::HandlePacket_QSetDisableASLR,
+ NULL, "QSetDisableASLR:",
+ "Set whether to disable ASLR when launching the process "
+ "with the set argv ('A') packet"));
+ t.push_back(Packet(set_stdin, &RNBRemote::HandlePacket_QSetSTDIO, NULL,
+ "QSetSTDIN:", "Set the standard input for a process to be "
+ "launched with the 'A' packet"));
+ t.push_back(Packet(set_stdout, &RNBRemote::HandlePacket_QSetSTDIO, NULL,
+ "QSetSTDOUT:", "Set the standard output for a process to "
+ "be launched with the 'A' packet"));
+ t.push_back(Packet(set_stderr, &RNBRemote::HandlePacket_QSetSTDIO, NULL,
+ "QSetSTDERR:", "Set the standard error for a process to "
+ "be launched with the 'A' packet"));
+ t.push_back(Packet(set_working_dir, &RNBRemote::HandlePacket_QSetWorkingDir,
+ NULL, "QSetWorkingDir:", "Set the working directory for a "
+ "process to be launched with the "
+ "'A' packet"));
+ t.push_back(Packet(set_list_threads_in_stop_reply,
+ &RNBRemote::HandlePacket_QListThreadsInStopReply, NULL,
+ "QListThreadsInStopReply",
+ "Set if the 'threads' key should be added to the stop "
+ "reply packets with a list of all thread IDs."));
+ t.push_back(Packet(
+ sync_thread_state, &RNBRemote::HandlePacket_QSyncThreadState, NULL,
+ "QSyncThreadState:", "Do whatever is necessary to make sure 'thread' is "
+ "in a safe state to call functions on."));
+ // t.push_back (Packet (pass_signals_to_inferior,
+ // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify
+ // which signals are passed to the inferior"));
+ t.push_back(Packet(allocate_memory, &RNBRemote::HandlePacket_AllocateMemory,
+ NULL, "_M", "Allocate memory in the inferior process."));
+ t.push_back(Packet(deallocate_memory,
+ &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m",
+ "Deallocate memory in the inferior process."));
+ t.push_back(Packet(
+ save_register_state, &RNBRemote::HandlePacket_SaveRegisterState, NULL,
+ "QSaveRegisterState", "Save the register state for the current thread "
+ "and return a decimal save ID."));
+ t.push_back(Packet(restore_register_state,
+ &RNBRemote::HandlePacket_RestoreRegisterState, NULL,
+ "QRestoreRegisterState:",
+ "Restore the register state given a save ID previously "
+ "returned from a call to QSaveRegisterState."));
+ t.push_back(Packet(
+ memory_region_info, &RNBRemote::HandlePacket_MemoryRegionInfo, NULL,
+ "qMemoryRegionInfo", "Return size and attributes of a memory region that "
+ "contains the given address"));
+ t.push_back(Packet(get_profile_data, &RNBRemote::HandlePacket_GetProfileData,
+ NULL, "qGetProfileData",
+ "Return profiling data of the current target."));
+ t.push_back(Packet(set_enable_profiling,
+ &RNBRemote::HandlePacket_SetEnableAsyncProfiling, NULL,
+ "QSetEnableAsyncProfiling",
+ "Enable or disable the profiling of current target."));
+ t.push_back(Packet(enable_compression,
+ &RNBRemote::HandlePacket_QEnableCompression, NULL,
+ "QEnableCompression:",
+ "Enable compression for the remainder of the connection"));
+ t.push_back(Packet(watchpoint_support_info,
+ &RNBRemote::HandlePacket_WatchpointSupportInfo, NULL,
+ "qWatchpointSupportInfo",
+ "Return the number of supported hardware watchpoints"));
+ t.push_back(Packet(set_process_event,
+ &RNBRemote::HandlePacket_QSetProcessEvent, NULL,
+ "QSetProcessEvent:", "Set a process event, to be passed "
+ "to the process, can be set before "
+ "the process is started, or after."));
+ t.push_back(
+ Packet(set_detach_on_error, &RNBRemote::HandlePacket_QSetDetachOnError,
+ NULL, "QSetDetachOnError:",
+ "Set whether debugserver will detach (1) or kill (0) from the "
+ "process it is controlling if it loses connection to lldb."));
+ t.push_back(Packet(
+ speed_test, &RNBRemote::HandlePacket_qSpeedTest, NULL, "qSpeedTest:",
+ "Test the maximum speed at which packet can be sent/received."));
+ t.push_back(Packet(query_transfer, &RNBRemote::HandlePacket_qXfer, NULL,
+ "qXfer:", "Support the qXfer packet."));
+ t.push_back(
+ Packet(query_supported_async_json_packets,
+ &RNBRemote::HandlePacket_qStructuredDataPlugins, NULL,
+ "qStructuredDataPlugins",
+ "Query for the structured data plugins supported by the remote."));
+ t.push_back(
+ Packet(configure_darwin_log, &RNBRemote::HandlePacket_QConfigureDarwinLog,
+ NULL, "QConfigureDarwinLog:",
+ "Configure the DarwinLog structured data plugin support."));
+}
- do
- {
- count = DNBProcessGetAvailableSTDERR(pid, buf, sizeof(buf));
- if (count > 0)
- {
- SendSTDERRPacket (buf, count);
- }
- } while (count > 0);
- }
+void RNBRemote::FlushSTDIO() {
+ if (m_ctx.HasValidProcessID()) {
+ nub_process_t pid = m_ctx.ProcessID();
+ char buf[256];
+ nub_size_t count;
+ do {
+ count = DNBProcessGetAvailableSTDOUT(pid, buf, sizeof(buf));
+ if (count > 0) {
+ SendSTDOUTPacket(buf, count);
+ }
+ } while (count > 0);
+
+ do {
+ count = DNBProcessGetAvailableSTDERR(pid, buf, sizeof(buf));
+ if (count > 0) {
+ SendSTDERRPacket(buf, count);
+ }
+ } while (count > 0);
+ }
}
-void
-RNBRemote::SendAsyncProfileData ()
-{
- if (m_ctx.HasValidProcessID())
- {
- nub_process_t pid = m_ctx.ProcessID();
- char buf[1024];
- nub_size_t count;
- do
- {
- count = DNBProcessGetAvailableProfileData(pid, buf, sizeof(buf));
- if (count > 0)
- {
- SendAsyncProfileDataPacket (buf, count);
- }
- } while (count > 0);
- }
+void RNBRemote::SendAsyncProfileData() {
+ if (m_ctx.HasValidProcessID()) {
+ nub_process_t pid = m_ctx.ProcessID();
+ char buf[1024];
+ nub_size_t count;
+ do {
+ count = DNBProcessGetAvailableProfileData(pid, buf, sizeof(buf));
+ if (count > 0) {
+ SendAsyncProfileDataPacket(buf, count);
+ }
+ } while (count > 0);
+ }
}
-void
-RNBRemote::SendAsyncDarwinLogData ()
-{
- DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): enter",
+void RNBRemote::SendAsyncDarwinLogData() {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): enter", __FUNCTION__);
+
+ if (!m_ctx.HasValidProcessID()) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): ignoring due to"
+ "invalid process id",
__FUNCTION__);
+ return;
+ }
- if (!m_ctx.HasValidProcessID())
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): ignoring due to"
- "invalid process id", __FUNCTION__);
- return;
- }
+ nub_process_t pid = m_ctx.ProcessID();
+ DarwinLogEventVector::size_type entry_count = 0;
- nub_process_t pid = m_ctx.ProcessID();
- DarwinLogEventVector::size_type entry_count = 0;
+ // NOTE: the current looping structure here does nothing
+ // to guarantee that we can send off async packets faster
+ // than we generate them. It will keep sending as long
+ // as there's data to send.
+ do {
+ DarwinLogEventVector events = DNBProcessGetAvailableDarwinLogEvents(pid);
+ entry_count = events.size();
- // NOTE: the current looping structure here does nothing
- // to guarantee that we can send off async packets faster
- // than we generate them. It will keep sending as long
- // as there's data to send.
- do
- {
- DarwinLogEventVector events =
- DNBProcessGetAvailableDarwinLogEvents(pid);
- entry_count = events.size();
-
- DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop enter",
- __FUNCTION__);
-
- for (DarwinLogEventVector::size_type base_entry = 0;
- base_entry < entry_count;
- base_entry += DARWIN_LOG_MAX_EVENTS_PER_PACKET)
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): inner loop enter",
- __FUNCTION__);
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop enter",
+ __FUNCTION__);
- // We limit the total number of entries we pack
- // into a single JSON async packet just so it
- // doesn't get too large.
- JSONGenerator::Dictionary async_dictionary;
-
- // Specify the type of the JSON async data we're sending.
- async_dictionary.AddStringItem(
- JSON_ASYNC_TYPE_KEY_NAME, "DarwinLog");
-
- // Create an array entry in the dictionary to hold all
- // the events going in this packet.
- JSONGenerator::ArraySP events_array(new JSONGenerator::Array());
- async_dictionary.AddItem(OS_LOG_EVENTS_KEY_NAME, events_array);
-
- // We bundle up to DARWIN_LOG_MAX_EVENTS_PER_PACKET events in
- // a single packet.
- const auto inner_loop_bound =
- std::min(base_entry + DARWIN_LOG_MAX_EVENTS_PER_PACKET,
- entry_count);
- for (DarwinLogEventVector::size_type i = base_entry;
- i < inner_loop_bound; ++i)
- {
- DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): adding "
- "entry index %lu to the JSON packet",
- __FUNCTION__, i);
- events_array->AddItem(events[i]);
- }
+ for (DarwinLogEventVector::size_type base_entry = 0;
+ base_entry < entry_count;
+ base_entry += DARWIN_LOG_MAX_EVENTS_PER_PACKET) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): inner loop enter",
+ __FUNCTION__);
+
+ // We limit the total number of entries we pack
+ // into a single JSON async packet just so it
+ // doesn't get too large.
+ JSONGenerator::Dictionary async_dictionary;
+
+ // Specify the type of the JSON async data we're sending.
+ async_dictionary.AddStringItem(JSON_ASYNC_TYPE_KEY_NAME, "DarwinLog");
+
+ // Create an array entry in the dictionary to hold all
+ // the events going in this packet.
+ JSONGenerator::ArraySP events_array(new JSONGenerator::Array());
+ async_dictionary.AddItem(OS_LOG_EVENTS_KEY_NAME, events_array);
+
+ // We bundle up to DARWIN_LOG_MAX_EVENTS_PER_PACKET events in
+ // a single packet.
+ const auto inner_loop_bound =
+ std::min(base_entry + DARWIN_LOG_MAX_EVENTS_PER_PACKET, entry_count);
+ for (DarwinLogEventVector::size_type i = base_entry; i < inner_loop_bound;
+ ++i) {
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): adding "
+ "entry index %lu to the JSON packet",
+ __FUNCTION__, i);
+ events_array->AddItem(events[i]);
+ }
- // Send off the packet.
- DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): sending JSON "
- "packet, %lu entries remain", __FUNCTION__,
- entry_count - inner_loop_bound);
- SendAsyncJSONPacket(async_dictionary);
- }
+ // Send off the packet.
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): sending JSON "
+ "packet, %lu entries remain",
+ __FUNCTION__, entry_count - inner_loop_bound);
+ SendAsyncJSONPacket(async_dictionary);
+ }
- DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop exit",
- __FUNCTION__);
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop exit",
+ __FUNCTION__);
- } while (entry_count > 0);
+ } while (entry_count > 0);
- DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): exit",
- __PRETTY_FUNCTION__);
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): exit",
+ __PRETTY_FUNCTION__);
}
-rnb_err_t
-RNBRemote::SendHexEncodedBytePacket (const char *header, const void *buf, size_t buf_len, const char *footer)
-{
- std::ostringstream packet_sstrm;
- // Append the header cstr if there was one
- if (header && header[0])
- packet_sstrm << header;
- nub_size_t i;
- const uint8_t *ubuf8 = (const uint8_t *)buf;
- for (i=0; i<buf_len; i++)
- {
- packet_sstrm << RAWHEX8(ubuf8[i]);
- }
- // Append the footer cstr if there was one
- if (footer && footer[0])
- packet_sstrm << footer;
+rnb_err_t RNBRemote::SendHexEncodedBytePacket(const char *header,
+ const void *buf, size_t buf_len,
+ const char *footer) {
+ std::ostringstream packet_sstrm;
+ // Append the header cstr if there was one
+ if (header && header[0])
+ packet_sstrm << header;
+ nub_size_t i;
+ const uint8_t *ubuf8 = (const uint8_t *)buf;
+ for (i = 0; i < buf_len; i++) {
+ packet_sstrm << RAWHEX8(ubuf8[i]);
+ }
+ // Append the footer cstr if there was one
+ if (footer && footer[0])
+ packet_sstrm << footer;
- return SendPacket(packet_sstrm.str());
+ return SendPacket(packet_sstrm.str());
}
-rnb_err_t
-RNBRemote::SendSTDOUTPacket (char *buf, nub_size_t buf_size)
-{
- if (buf_size == 0)
- return rnb_success;
- return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
+rnb_err_t RNBRemote::SendSTDOUTPacket(char *buf, nub_size_t buf_size) {
+ if (buf_size == 0)
+ return rnb_success;
+ return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
}
-rnb_err_t
-RNBRemote::SendSTDERRPacket (char *buf, nub_size_t buf_size)
-{
- if (buf_size == 0)
- return rnb_success;
- return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
+rnb_err_t RNBRemote::SendSTDERRPacket(char *buf, nub_size_t buf_size) {
+ if (buf_size == 0)
+ return rnb_success;
+ return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
}
// This makes use of asynchronous bit 'A' in the gdb remote protocol.
-rnb_err_t
-RNBRemote::SendAsyncProfileDataPacket (char *buf, nub_size_t buf_size)
-{
- if (buf_size == 0)
- return rnb_success;
-
- std::string packet("A");
- packet.append(buf, buf_size);
- return SendPacket(packet);
+rnb_err_t RNBRemote::SendAsyncProfileDataPacket(char *buf,
+ nub_size_t buf_size) {
+ if (buf_size == 0)
+ return rnb_success;
+
+ std::string packet("A");
+ packet.append(buf, buf_size);
+ return SendPacket(packet);
}
rnb_err_t
-RNBRemote::SendAsyncJSONPacket(const JSONGenerator::Dictionary &dictionary)
-{
- std::ostringstream stream;
- // We're choosing something that is easy to spot if we somehow get one
- // of these coming out at the wrong time (i.e. when the remote side
- // is not waiting for a process control completion response).
- stream << "JSON-async:";
- dictionary.Dump(stream);
- const std::string payload = binary_encode_string(stream.str());
- return SendPacket(payload);
+RNBRemote::SendAsyncJSONPacket(const JSONGenerator::Dictionary &dictionary) {
+ std::ostringstream stream;
+ // We're choosing something that is easy to spot if we somehow get one
+ // of these coming out at the wrong time (i.e. when the remote side
+ // is not waiting for a process control completion response).
+ stream << "JSON-async:";
+ dictionary.Dump(stream);
+ const std::string payload = binary_encode_string(stream.str());
+ return SendPacket(payload);
}
// Given a std::string packet contents to send, possibly encode/compress it.
// If compression is enabled, the returned std::string will be in one of two
// forms:
-//
+//
// N<original packet contents uncompressed>
-// C<size of original decompressed packet>:<packet compressed with the requested compression scheme>
+// C<size of original decompressed packet>:<packet compressed with the
+// requested compression scheme>
//
// If compression is not requested, the original packet contents are returned
-std::string
-RNBRemote::CompressString (const std::string &orig)
-{
- std::string compressed;
- compression_types compression_type = GetCompressionType();
- if (compression_type != compression_types::none)
- {
- bool compress_this_packet = false;
-
- if (orig.size() > m_compression_minsize)
- {
- compress_this_packet = true;
- }
-
- if (compress_this_packet)
- {
- const size_t encoded_data_buf_size = orig.size() + 128;
- std::vector<uint8_t> encoded_data (encoded_data_buf_size);
- size_t compressed_size = 0;
-
-#if defined (HAVE_LIBCOMPRESSION)
- if (compression_decode_buffer && compression_type == compression_types::lz4)
- {
- compressed_size = compression_encode_buffer (encoded_data.data(),
- encoded_data_buf_size,
- (uint8_t*) orig.c_str(),
- orig.size(),
- nullptr,
- COMPRESSION_LZ4_RAW);
- }
- if (compression_decode_buffer && compression_type == compression_types::zlib_deflate)
- {
- compressed_size = compression_encode_buffer (encoded_data.data(),
- encoded_data_buf_size,
- (uint8_t*) orig.c_str(),
- orig.size(),
- nullptr,
- COMPRESSION_ZLIB);
- }
- if (compression_decode_buffer && compression_type == compression_types::lzma)
- {
- compressed_size = compression_encode_buffer (encoded_data.data(),
- encoded_data_buf_size,
- (uint8_t*) orig.c_str(),
- orig.size(),
- nullptr,
- COMPRESSION_LZMA);
- }
- if (compression_decode_buffer && compression_type == compression_types::lzfse)
- {
- compressed_size = compression_encode_buffer (encoded_data.data(),
- encoded_data_buf_size,
- (uint8_t*) orig.c_str(),
- orig.size(),
- nullptr,
- COMPRESSION_LZFSE);
- }
+std::string RNBRemote::CompressString(const std::string &orig) {
+ std::string compressed;
+ compression_types compression_type = GetCompressionType();
+ if (compression_type != compression_types::none) {
+ bool compress_this_packet = false;
+
+ if (orig.size() > m_compression_minsize) {
+ compress_this_packet = true;
+ }
+
+ if (compress_this_packet) {
+ const size_t encoded_data_buf_size = orig.size() + 128;
+ std::vector<uint8_t> encoded_data(encoded_data_buf_size);
+ size_t compressed_size = 0;
+
+#if defined(HAVE_LIBCOMPRESSION)
+ if (compression_decode_buffer &&
+ compression_type == compression_types::lz4) {
+ compressed_size = compression_encode_buffer(
+ encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(),
+ orig.size(), nullptr, COMPRESSION_LZ4_RAW);
+ }
+ if (compression_decode_buffer &&
+ compression_type == compression_types::zlib_deflate) {
+ compressed_size = compression_encode_buffer(
+ encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(),
+ orig.size(), nullptr, COMPRESSION_ZLIB);
+ }
+ if (compression_decode_buffer &&
+ compression_type == compression_types::lzma) {
+ compressed_size = compression_encode_buffer(
+ encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(),
+ orig.size(), nullptr, COMPRESSION_LZMA);
+ }
+ if (compression_decode_buffer &&
+ compression_type == compression_types::lzfse) {
+ compressed_size = compression_encode_buffer(
+ encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(),
+ orig.size(), nullptr, COMPRESSION_LZFSE);
+ }
#endif
-#if defined (HAVE_LIBZ)
- if (compressed_size == 0 && compression_type == compression_types::zlib_deflate)
- {
- z_stream stream;
- memset (&stream, 0, sizeof (z_stream));
- stream.next_in = (Bytef *) orig.c_str();
- stream.avail_in = (uInt) orig.size();
- stream.next_out = (Bytef *) encoded_data.data();
- stream.avail_out = (uInt) encoded_data_buf_size;
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
- deflateInit2 (&stream, 5, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
- int compress_status = deflate (&stream, Z_FINISH);
- deflateEnd (&stream);
- if (compress_status == Z_STREAM_END && stream.total_out > 0)
- {
- compressed_size = stream.total_out;
- }
- }
+#if defined(HAVE_LIBZ)
+ if (compressed_size == 0 &&
+ compression_type == compression_types::zlib_deflate) {
+ z_stream stream;
+ memset(&stream, 0, sizeof(z_stream));
+ stream.next_in = (Bytef *)orig.c_str();
+ stream.avail_in = (uInt)orig.size();
+ stream.next_out = (Bytef *)encoded_data.data();
+ stream.avail_out = (uInt)encoded_data_buf_size;
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+ deflateInit2(&stream, 5, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
+ int compress_status = deflate(&stream, Z_FINISH);
+ deflateEnd(&stream);
+ if (compress_status == Z_STREAM_END && stream.total_out > 0) {
+ compressed_size = stream.total_out;
+ }
+ }
#endif
- if (compressed_size > 0)
- {
- compressed.clear ();
- compressed.reserve (compressed_size);
- compressed = "C";
- char numbuf[16];
- snprintf (numbuf, sizeof (numbuf), "%zu:", orig.size());
- numbuf[sizeof (numbuf) - 1] = '\0';
- compressed.append (numbuf);
-
- for (size_t i = 0; i < compressed_size; i++)
- {
- uint8_t byte = encoded_data[i];
- if (byte == '#' || byte == '$' || byte == '}' || byte == '*' || byte == '\0')
- {
- compressed.push_back (0x7d);
- compressed.push_back (byte ^ 0x20);
- }
- else
- {
- compressed.push_back (byte);
- }
- }
- }
- else
- {
- compressed = "N" + orig;
- }
- }
- else
- {
- compressed = "N" + orig;
+ if (compressed_size > 0) {
+ compressed.clear();
+ compressed.reserve(compressed_size);
+ compressed = "C";
+ char numbuf[16];
+ snprintf(numbuf, sizeof(numbuf), "%zu:", orig.size());
+ numbuf[sizeof(numbuf) - 1] = '\0';
+ compressed.append(numbuf);
+
+ for (size_t i = 0; i < compressed_size; i++) {
+ uint8_t byte = encoded_data[i];
+ if (byte == '#' || byte == '$' || byte == '}' || byte == '*' ||
+ byte == '\0') {
+ compressed.push_back(0x7d);
+ compressed.push_back(byte ^ 0x20);
+ } else {
+ compressed.push_back(byte);
+ }
}
+ } else {
+ compressed = "N" + orig;
+ }
+ } else {
+ compressed = "N" + orig;
}
- else
- {
- compressed = orig;
- }
+ } else {
+ compressed = orig;
+ }
+
+ return compressed;
+}
+
+rnb_err_t RNBRemote::SendPacket(const std::string &s) {
+ DNBLogThreadedIf(LOG_RNB_MAX, "%8d RNBRemote::%s (%s) called",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ __FUNCTION__, s.c_str());
+
+ std::string s_compressed = CompressString(s);
+
+ std::string sendpacket = "$" + s_compressed + "#";
+ int cksum = 0;
+ char hexbuf[5];
+
+ if (m_noack_mode) {
+ sendpacket += "00";
+ } else {
+ for (size_t i = 0; i != s_compressed.size(); ++i)
+ cksum += s_compressed[i];
+ snprintf(hexbuf, sizeof hexbuf, "%02x", cksum & 0xff);
+ sendpacket += hexbuf;
+ }
- return compressed;
-}
+ rnb_err_t err = m_comm.Write(sendpacket.c_str(), sendpacket.size());
+ if (err != rnb_success)
+ return err;
-rnb_err_t
-RNBRemote::SendPacket (const std::string &s)
-{
- DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s (%s) called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, s.c_str());
+ if (m_noack_mode)
+ return rnb_success;
- std::string s_compressed = CompressString (s);
+ std::string reply;
+ RNBRemote::Packet packet;
+ err = GetPacket(reply, packet, true);
+
+ if (err != rnb_success) {
+ DNBLogThreadedIf(LOG_RNB_REMOTE,
+ "%8d RNBRemote::%s (%s) got error trying to get reply...",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ __FUNCTION__, sendpacket.c_str());
+ return err;
+ }
- std::string sendpacket = "$" + s_compressed + "#";
- int cksum = 0;
- char hexbuf[5];
+ DNBLogThreadedIf(LOG_RNB_MAX, "%8d RNBRemote::%s (%s) got reply: '%s'",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ __FUNCTION__, sendpacket.c_str(), reply.c_str());
- if (m_noack_mode)
- {
- sendpacket += "00";
- }
- else
- {
- for (size_t i = 0; i != s_compressed.size(); ++i)
- cksum += s_compressed[i];
- snprintf (hexbuf, sizeof hexbuf, "%02x", cksum & 0xff);
- sendpacket += hexbuf;
- }
+ if (packet.type == ack)
+ return rnb_success;
- rnb_err_t err = m_comm.Write (sendpacket.c_str(), sendpacket.size());
- if (err != rnb_success)
- return err;
+ // Should we try to resend the packet at this layer?
+ // if (packet.command == nack)
+ return rnb_err;
+}
- if (m_noack_mode)
- return rnb_success;
+/* Get a packet via gdb remote protocol.
+ Strip off the prefix/suffix, verify the checksum to make sure
+ a valid packet was received, send an ACK if they match. */
- std::string reply;
- RNBRemote::Packet packet;
- err = GetPacket (reply, packet, true);
+rnb_err_t RNBRemote::GetPacketPayload(std::string &return_packet) {
+ // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s called",
+ // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
+
+ PThreadMutex::Locker locker(m_mutex);
+ if (m_rx_packets.empty()) {
+ // Only reset the remote command available event if we have no more packets
+ m_ctx.Events().ResetEvents(RNBContext::event_read_packet_available);
+ // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s error: no packets
+ // available...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ // __FUNCTION__);
+ return rnb_err;
+ }
- if (err != rnb_success)
- {
- DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s (%s) got error trying to get reply...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, sendpacket.c_str());
- return err;
+ // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s has %u queued packets",
+ // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__,
+ // m_rx_packets.size());
+ return_packet.swap(m_rx_packets.front());
+ m_rx_packets.pop_front();
+ locker.Reset(); // Release our lock on the mutex
+
+ if (m_rx_packets.empty()) {
+ // Reset the remote command available event if we have no more packets
+ m_ctx.Events().ResetEvents(RNBContext::event_read_packet_available);
+ }
+
+ // DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s: '%s'",
+ // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__,
+ // return_packet.c_str());
+
+ switch (return_packet[0]) {
+ case '+':
+ case '-':
+ case '\x03':
+ break;
+
+ case '$': {
+ long packet_checksum = 0;
+ if (!m_noack_mode) {
+ for (size_t i = return_packet.size() - 2; i < return_packet.size(); ++i) {
+ char checksum_char = tolower(return_packet[i]);
+ if (!isxdigit(checksum_char)) {
+ m_comm.Write("-", 1);
+ DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s error: packet "
+ "with invalid checksum characters: "
+ "%s",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ __FUNCTION__, return_packet.c_str());
+ return rnb_err;
+ }
+ }
+ packet_checksum =
+ strtol(&return_packet[return_packet.size() - 2], NULL, 16);
}
- DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s (%s) got reply: '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, sendpacket.c_str(), reply.c_str());
+ return_packet.erase(0, 1); // Strip the leading '$'
+ return_packet.erase(return_packet.size() - 3); // Strip the #XX checksum
+
+ if (!m_noack_mode) {
+ // Compute the checksum
+ int computed_checksum = 0;
+ for (std::string::iterator it = return_packet.begin();
+ it != return_packet.end(); ++it) {
+ computed_checksum += *it;
+ }
- if (packet.type == ack)
- return rnb_success;
+ if (packet_checksum == (computed_checksum & 0xff)) {
+ // DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for
+ // '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ // __FUNCTION__, return_packet.c_str());
+ m_comm.Write("+", 1);
+ } else {
+ DNBLogThreadedIf(
+ LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s' (error: "
+ "packet checksum mismatch (0x%2.2lx != 0x%2.2x))",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__,
+ return_packet.c_str(), packet_checksum, computed_checksum);
+ m_comm.Write("-", 1);
+ return rnb_err;
+ }
+ }
+ } break;
- // Should we try to resend the packet at this layer?
- // if (packet.command == nack)
+ default:
+ DNBLogThreadedIf(LOG_RNB_REMOTE,
+ "%8u RNBRemote::%s tossing unexpected packet???? %s",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ __FUNCTION__, return_packet.c_str());
+ if (!m_noack_mode)
+ m_comm.Write("-", 1);
return rnb_err;
+ }
+
+ return rnb_success;
}
-/* Get a packet via gdb remote protocol.
- Strip off the prefix/suffix, verify the checksum to make sure
- a valid packet was received, send an ACK if they match. */
+rnb_err_t RNBRemote::HandlePacket_UNIMPLEMENTED(const char *p) {
+ DNBLogThreadedIf(LOG_RNB_MAX, "%8u RNBRemote::%s(\"%s\")",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ __FUNCTION__, p ? p : "NULL");
+ return SendPacket("");
+}
+
+rnb_err_t RNBRemote::HandlePacket_ILLFORMED(const char *file, int line,
+ const char *p,
+ const char *description) {
+ DNBLogThreadedIf(LOG_RNB_PACKETS, "%8u %s:%i ILLFORMED: '%s' (%s)",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), file,
+ line, __FUNCTION__, p);
+ return SendPacket("E03");
+}
+
+rnb_err_t RNBRemote::GetPacket(std::string &packet_payload,
+ RNBRemote::Packet &packet_info, bool wait) {
+ std::string payload;
+ rnb_err_t err = GetPacketPayload(payload);
+ if (err != rnb_success) {
+ PThreadEvent &events = m_ctx.Events();
+ nub_event_t set_events = events.GetEventBits();
+ // TODO: add timeout version of GetPacket?? We would then need to pass
+ // that timeout value along to DNBProcessTimedWaitForEvent.
+ if (!wait || ((set_events & RNBContext::event_read_thread_running) == 0))
+ return err;
+
+ const nub_event_t events_to_wait_for =
+ RNBContext::event_read_packet_available |
+ RNBContext::event_read_thread_exiting;
+
+ while ((set_events = events.WaitForSetEvents(events_to_wait_for)) != 0) {
+ if (set_events & RNBContext::event_read_packet_available) {
+ // Try the queue again now that we got an event
+ err = GetPacketPayload(payload);
+ if (err == rnb_success)
+ break;
+ }
-rnb_err_t
-RNBRemote::GetPacketPayload (std::string &return_packet)
-{
- //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
+ if (set_events & RNBContext::event_read_thread_exiting)
+ err = rnb_not_connected;
- PThreadMutex::Locker locker(m_mutex);
- if (m_rx_packets.empty())
- {
- // Only reset the remote command available event if we have no more packets
- m_ctx.Events().ResetEvents ( RNBContext::event_read_packet_available );
- //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s error: no packets available...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
- return rnb_err;
+ if (err == rnb_not_connected)
+ return err;
+ }
+ while (err == rnb_err)
+ ;
+
+ if (set_events == 0)
+ err = rnb_not_connected;
+ }
+
+ if (err == rnb_success) {
+ Packet::iterator it;
+ for (it = m_packets.begin(); it != m_packets.end(); ++it) {
+ if (payload.compare(0, it->abbrev.size(), it->abbrev) == 0)
+ break;
}
- //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s has %u queued packets", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, m_rx_packets.size());
- return_packet.swap(m_rx_packets.front());
- m_rx_packets.pop_front();
- locker.Reset(); // Release our lock on the mutex
+ // A packet we don't have an entry for. This can happen when we
+ // get a packet that we don't know about or support. We just reply
+ // accordingly and go on.
+ if (it == m_packets.end()) {
+ DNBLogThreadedIf(LOG_RNB_PACKETS, "unimplemented packet: '%s'",
+ payload.c_str());
+ HandlePacket_UNIMPLEMENTED(payload.c_str());
+ return rnb_err;
+ } else {
+ packet_info = *it;
+ packet_payload = payload;
+ }
+ }
+ return err;
+}
+
+rnb_err_t RNBRemote::HandleAsyncPacket(PacketEnum *type) {
+ DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ __FUNCTION__);
+ static DNBTimer g_packetTimer(true);
+ rnb_err_t err = rnb_err;
+ std::string packet_data;
+ RNBRemote::Packet packet_info;
+ err = GetPacket(packet_data, packet_info, false);
+
+ if (err == rnb_success) {
+ if (!packet_data.empty() && isprint(packet_data[0]))
+ DNBLogThreadedIf(LOG_RNB_REMOTE | LOG_RNB_PACKETS,
+ "HandleAsyncPacket (\"%s\");", packet_data.c_str());
+ else
+ DNBLogThreadedIf(LOG_RNB_REMOTE | LOG_RNB_PACKETS,
+ "HandleAsyncPacket (%s);",
+ packet_info.printable_name.c_str());
+
+ HandlePacketCallback packet_callback = packet_info.async;
+ if (packet_callback != NULL) {
+ if (type != NULL)
+ *type = packet_info.type;
+ return (this->*packet_callback)(packet_data.c_str());
+ }
+ }
+
+ return err;
+}
+
+rnb_err_t RNBRemote::HandleReceivedPacket(PacketEnum *type) {
+ static DNBTimer g_packetTimer(true);
+
+ // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s",
+ // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
+ rnb_err_t err = rnb_err;
+ std::string packet_data;
+ RNBRemote::Packet packet_info;
+ err = GetPacket(packet_data, packet_info, false);
+
+ if (err == rnb_success) {
+ DNBLogThreadedIf(LOG_RNB_REMOTE, "HandleReceivedPacket (\"%s\");",
+ packet_data.c_str());
+ HandlePacketCallback packet_callback = packet_info.normal;
+ if (packet_callback != NULL) {
+ if (type != NULL)
+ *type = packet_info.type;
+ return (this->*packet_callback)(packet_data.c_str());
+ } else {
+ // Do not fall through to end of this function, if we have valid
+ // packet_info and it has a NULL callback, then we need to respect
+ // that it may not want any response or anything to be done.
+ return err;
+ }
+ }
+ return rnb_err;
+}
+
+void RNBRemote::CommDataReceived(const std::string &new_data) {
+ // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called",
+ // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
+ {
+ // Put the packet data into the buffer in a thread safe fashion
+ PThreadMutex::Locker locker(m_mutex);
- if (m_rx_packets.empty())
- {
- // Reset the remote command available event if we have no more packets
- m_ctx.Events().ResetEvents ( RNBContext::event_read_packet_available );
+ std::string data;
+ // See if we have any left over data from a previous call to this
+ // function?
+ if (!m_rx_partial_data.empty()) {
+ // We do, so lets start with that data
+ data.swap(m_rx_partial_data);
+ }
+ // Append the new incoming data
+ data += new_data;
+
+ // Parse up the packets into gdb remote packets
+ size_t idx = 0;
+ const size_t data_size = data.size();
+
+ while (idx < data_size) {
+ // end_idx must be one past the last valid packet byte. Start
+ // it off with an invalid value that is the same as the current
+ // index.
+ size_t end_idx = idx;
+
+ switch (data[idx]) {
+ case '+': // Look for ack
+ case '-': // Look for cancel
+ case '\x03': // ^C to halt target
+ end_idx = idx + 1; // The command is one byte long...
+ break;
+
+ case '$':
+ // Look for a standard gdb packet?
+ end_idx = data.find('#', idx + 1);
+ if (end_idx == std::string::npos || end_idx + 3 > data_size) {
+ end_idx = std::string::npos;
+ } else {
+ // Add two for the checksum bytes and 1 to point to the
+ // byte just past the end of this packet
+ end_idx += 3;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (end_idx == std::string::npos) {
+ // Not all data may be here for the packet yet, save it for
+ // next time through this function.
+ m_rx_partial_data += data.substr(idx);
+ // DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s saving data for
+ // later[%u, npos):
+ // '%s'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ // __FUNCTION__, idx, m_rx_partial_data.c_str());
+ idx = end_idx;
+ } else if (idx < end_idx) {
+ m_packets_recvd++;
+ // Hack to get rid of initial '+' ACK???
+ if (m_packets_recvd == 1 && (end_idx == idx + 1) && data[idx] == '+') {
+ // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s throwing first
+ // ACK away....[%u, npos):
+ // '+'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ // __FUNCTION__, idx);
+ } else {
+ // We have a valid packet...
+ m_rx_packets.push_back(data.substr(idx, end_idx - idx));
+ DNBLogThreadedIf(LOG_RNB_PACKETS, "getpkt: %s",
+ m_rx_packets.back().c_str());
+ }
+ idx = end_idx;
+ } else {
+ DNBLogThreadedIf(LOG_RNB_MAX,
+ "%8d RNBRemote::%s tossing junk byte at %c",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ __FUNCTION__, data[idx]);
+ idx = idx + 1;
+ }
}
+ }
- //DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s: '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
+ if (!m_rx_packets.empty()) {
+ // Let the main thread know we have received a packet
- switch (return_packet[0])
- {
- case '+':
- case '-':
- case '\x03':
- break;
+ // DNBLogThreadedIf (LOG_RNB_EVENTS, "%8d RNBRemote::%s called
+ // events.SetEvent(RNBContext::event_read_packet_available)",
+ // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
+ PThreadEvent &events = m_ctx.Events();
+ events.SetEvents(RNBContext::event_read_packet_available);
+ }
+}
+
+rnb_err_t RNBRemote::GetCommData() {
+ // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called",
+ // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
+ std::string comm_data;
+ rnb_err_t err = m_comm.Read(comm_data);
+ if (err == rnb_success) {
+ if (!comm_data.empty())
+ CommDataReceived(comm_data);
+ }
+ return err;
+}
+
+void RNBRemote::StartReadRemoteDataThread() {
+ DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s called",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ __FUNCTION__);
+ PThreadEvent &events = m_ctx.Events();
+ if ((events.GetEventBits() & RNBContext::event_read_thread_running) == 0) {
+ events.ResetEvents(RNBContext::event_read_thread_exiting);
+ int err = ::pthread_create(&m_rx_pthread, NULL,
+ ThreadFunctionReadRemoteData, this);
+ if (err == 0) {
+ // Our thread was successfully kicked off, wait for it to
+ // set the started event so we can safely continue
+ events.WaitForSetEvents(RNBContext::event_read_thread_running);
+ } else {
+ events.ResetEvents(RNBContext::event_read_thread_running);
+ events.SetEvents(RNBContext::event_read_thread_exiting);
+ }
+ }
+}
+
+void RNBRemote::StopReadRemoteDataThread() {
+ DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s called",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ __FUNCTION__);
+ PThreadEvent &events = m_ctx.Events();
+ if ((events.GetEventBits() & RNBContext::event_read_thread_running) ==
+ RNBContext::event_read_thread_running) {
+ m_comm.Disconnect(true);
+ struct timespec timeout_abstime;
+ DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0);
- case '$':
- {
- long packet_checksum = 0;
- if (!m_noack_mode)
- {
- for (size_t i = return_packet.size() - 2; i < return_packet.size(); ++i)
- {
- char checksum_char = tolower (return_packet[i]);
- if (!isxdigit (checksum_char))
- {
- m_comm.Write ("-", 1);
- DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s error: packet with invalid checksum characters: %s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
- return rnb_err;
- }
- }
- packet_checksum = strtol (&return_packet[return_packet.size() - 2], NULL, 16);
- }
+ // Wait for 2 seconds for the remote data thread to exit
+ if (events.WaitForSetEvents(RNBContext::event_read_thread_exiting,
+ &timeout_abstime) == 0) {
+ // Kill the remote data thread???
+ }
+ }
+}
+
+void *RNBRemote::ThreadFunctionReadRemoteData(void *arg) {
+ // Keep a shared pointer reference so this doesn't go away on us before the
+ // thread is killed.
+ DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread starting...",
+ __FUNCTION__, arg);
+ RNBRemoteSP remoteSP(g_remoteSP);
+ if (remoteSP.get() != NULL) {
+
+#if defined(__APPLE__)
+ pthread_setname_np("read gdb-remote packets thread");
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+ struct sched_param thread_param;
+ int thread_sched_policy;
+ if (pthread_getschedparam(pthread_self(), &thread_sched_policy,
+ &thread_param) == 0) {
+ thread_param.sched_priority = 47;
+ pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
+ }
+#endif
+#endif
- return_packet.erase(0,1); // Strip the leading '$'
- return_packet.erase(return_packet.size() - 3);// Strip the #XX checksum
+ RNBRemote *remote = remoteSP.get();
+ PThreadEvent &events = remote->Context().Events();
+ events.SetEvents(RNBContext::event_read_thread_running);
+ // START: main receive remote command thread loop
+ bool done = false;
+ while (!done) {
+ rnb_err_t err = remote->GetCommData();
- if (!m_noack_mode)
- {
- // Compute the checksum
- int computed_checksum = 0;
- for (std::string::iterator it = return_packet.begin ();
- it != return_packet.end ();
- ++it)
- {
- computed_checksum += *it;
- }
+ switch (err) {
+ case rnb_success:
+ break;
- if (packet_checksum == (computed_checksum & 0xff))
- {
- //DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
- m_comm.Write ("+", 1);
- }
- else
- {
- DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s' (error: packet checksum mismatch (0x%2.2lx != 0x%2.2x))",
- (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
- __FUNCTION__,
- return_packet.c_str(),
- packet_checksum,
- computed_checksum);
- m_comm.Write ("-", 1);
- return rnb_err;
- }
- }
- }
+ case rnb_err:
+ DNBLogThreadedIf(LOG_RNB_REMOTE,
+ "RNBSocket::GetCommData returned error %u", err);
+ done = true;
break;
- default:
- DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s tossing unexpected packet???? %s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
- if (!m_noack_mode)
- m_comm.Write ("-", 1);
- return rnb_err;
+ case rnb_not_connected:
+ DNBLogThreadedIf(LOG_RNB_REMOTE,
+ "RNBSocket::GetCommData returned not connected...");
+ done = true;
+ break;
+ }
}
+ // START: main receive remote command thread loop
+ events.ResetEvents(RNBContext::event_read_thread_running);
+ events.SetEvents(RNBContext::event_read_thread_exiting);
+ }
+ DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread exiting...",
+ __FUNCTION__, arg);
+ return NULL;
+}
- return rnb_success;
+// If we fail to get back a valid CPU type for the remote process,
+// make a best guess for the CPU type based on the currently running
+// debugserver binary -- the debugger may not handle the case of an
+// un-specified process CPU type correctly.
+
+static cpu_type_t best_guess_cpu_type() {
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+ if (sizeof(char *) == 8) {
+ return CPU_TYPE_ARM64;
+ } else {
+ return CPU_TYPE_ARM;
+ }
+#elif defined(__i386__) || defined(__x86_64__)
+ if (sizeof(char *) == 8) {
+ return CPU_TYPE_X86_64;
+ } else {
+ return CPU_TYPE_I386;
+ }
+#endif
+ return 0;
}
-rnb_err_t
-RNBRemote::HandlePacket_UNIMPLEMENTED (const char* p)
-{
- DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s(\"%s\")", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p ? p : "NULL");
- return SendPacket ("");
+/* Read the bytes in STR which are GDB Remote Protocol binary encoded bytes
+ (8-bit bytes).
+ This encoding uses 0x7d ('}') as an escape character for
+ 0x7d ('}'), 0x23 ('#'), 0x24 ('$'), 0x2a ('*').
+ LEN is the number of bytes to be processed. If a character is escaped,
+ it is 2 characters for LEN. A LEN of -1 means decode-until-nul-byte
+ (end of string). */
+
+std::vector<uint8_t> decode_binary_data(const char *str, size_t len) {
+ std::vector<uint8_t> bytes;
+ if (len == 0) {
+ return bytes;
+ }
+ if (len == (size_t)-1)
+ len = strlen(str);
+
+ while (len--) {
+ unsigned char c = *str++;
+ if (c == 0x7d && len > 0) {
+ len--;
+ c = *str++ ^ 0x20;
+ }
+ bytes.push_back(c);
+ }
+ return bytes;
}
-rnb_err_t
-RNBRemote::HandlePacket_ILLFORMED (const char *file, int line, const char *p, const char *description)
-{
- DNBLogThreadedIf (LOG_RNB_PACKETS, "%8u %s:%i ILLFORMED: '%s' (%s)", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), file, line, __FUNCTION__, p);
- return SendPacket ("E03");
+// Quote any meta characters in a std::string as per the binary
+// packet convention in the gdb-remote protocol.
+
+static std::string binary_encode_string(const std::string &s) {
+ std::string output;
+ const size_t s_size = s.size();
+ const char *s_chars = s.c_str();
+
+ for (size_t i = 0; i < s_size; i++) {
+ unsigned char ch = *(s_chars + i);
+ if (ch == '#' || ch == '$' || ch == '}' || ch == '*') {
+ output.push_back('}'); // 0x7d
+ output.push_back(ch ^ 0x20);
+ } else {
+ output.push_back(ch);
+ }
+ }
+ return output;
}
-rnb_err_t
-RNBRemote::GetPacket (std::string &packet_payload, RNBRemote::Packet& packet_info, bool wait)
-{
- std::string payload;
- rnb_err_t err = GetPacketPayload (payload);
- if (err != rnb_success)
- {
- PThreadEvent& events = m_ctx.Events();
- nub_event_t set_events = events.GetEventBits();
- // TODO: add timeout version of GetPacket?? We would then need to pass
- // that timeout value along to DNBProcessTimedWaitForEvent.
- if (!wait || ((set_events & RNBContext::event_read_thread_running) == 0))
- return err;
+// If the value side of a key-value pair in JSON is a string,
+// and that string has a " character in it, the " character must
+// be escaped.
- const nub_event_t events_to_wait_for = RNBContext::event_read_packet_available | RNBContext::event_read_thread_exiting;
+std::string json_string_quote_metachars(const std::string &s) {
+ if (s.find('"') == std::string::npos)
+ return s;
+
+ std::string output;
+ const size_t s_size = s.size();
+ const char *s_chars = s.c_str();
+ for (size_t i = 0; i < s_size; i++) {
+ unsigned char ch = *(s_chars + i);
+ if (ch == '"') {
+ output.push_back('\\');
+ }
+ output.push_back(ch);
+ }
+ return output;
+}
+
+typedef struct register_map_entry {
+ uint32_t debugserver_regnum; // debugserver register number
+ uint32_t offset; // Offset in bytes into the register context data with no
+ // padding between register values
+ DNBRegisterInfo nub_info; // debugnub register info
+ std::vector<uint32_t> value_regnums;
+ std::vector<uint32_t> invalidate_regnums;
+} register_map_entry_t;
- while ((set_events = events.WaitForSetEvents(events_to_wait_for)) != 0)
- {
- if (set_events & RNBContext::event_read_packet_available)
- {
- // Try the queue again now that we got an event
- err = GetPacketPayload (payload);
- if (err == rnb_success)
- break;
- }
+// If the notion of registers differs from what is handed out by the
+// architecture, then flavors can be defined here.
+
+static std::vector<register_map_entry_t> g_dynamic_register_map;
+static register_map_entry_t *g_reg_entries = NULL;
+static size_t g_num_reg_entries = 0;
- if (set_events & RNBContext::event_read_thread_exiting)
- err = rnb_not_connected;
+void RNBRemote::Initialize() { DNBInitialize(); }
+
+bool RNBRemote::InitializeRegisters(bool force) {
+ pid_t pid = m_ctx.ProcessID();
+ if (pid == INVALID_NUB_PROCESS)
+ return false;
+
+ DNBLogThreadedIf(
+ LOG_RNB_PROC,
+ "RNBRemote::%s() getting native registers from DNB interface",
+ __FUNCTION__);
+ // Discover the registers by querying the DNB interface and letting it
+ // state the registers that it would like to export. This allows the
+ // registers to be discovered using multiple qRegisterInfo calls to get
+ // all register information after the architecture for the process is
+ // determined.
+ if (force) {
+ g_dynamic_register_map.clear();
+ g_reg_entries = NULL;
+ g_num_reg_entries = 0;
+ }
+
+ if (g_dynamic_register_map.empty()) {
+ nub_size_t num_reg_sets = 0;
+ const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets);
+
+ assert(num_reg_sets > 0 && reg_sets != NULL);
+
+ uint32_t regnum = 0;
+ uint32_t reg_data_offset = 0;
+ typedef std::map<std::string, uint32_t> NameToRegNum;
+ NameToRegNum name_to_regnum;
+ for (nub_size_t set = 0; set < num_reg_sets; ++set) {
+ if (reg_sets[set].registers == NULL)
+ continue;
+
+ for (uint32_t reg = 0; reg < reg_sets[set].num_registers; ++reg) {
+ register_map_entry_t reg_entry = {
+ regnum++, // register number starts at zero and goes up with no gaps
+ reg_data_offset, // Offset into register context data, no gaps
+ // between registers
+ reg_sets[set].registers[reg], // DNBRegisterInfo
+ {},
+ {},
+ };
- if (err == rnb_not_connected)
- return err;
+ name_to_regnum[reg_entry.nub_info.name] = reg_entry.debugserver_regnum;
- } while (err == rnb_err);
+ if (reg_entry.nub_info.value_regs == NULL) {
+ reg_data_offset += reg_entry.nub_info.size;
+ }
- if (set_events == 0)
- err = rnb_not_connected;
+ g_dynamic_register_map.push_back(reg_entry);
+ }
}
- if (err == rnb_success)
- {
- Packet::iterator it;
- for (it = m_packets.begin (); it != m_packets.end (); ++it)
- {
- if (payload.compare (0, it->abbrev.size(), it->abbrev) == 0)
- break;
+ // Now we must find any registers whose values are in other registers and
+ // fix up
+ // the offsets since we removed all gaps...
+ for (auto ®_entry : g_dynamic_register_map) {
+ if (reg_entry.nub_info.value_regs) {
+ uint32_t new_offset = UINT32_MAX;
+ for (size_t i = 0; reg_entry.nub_info.value_regs[i] != NULL; ++i) {
+ const char *name = reg_entry.nub_info.value_regs[i];
+ auto pos = name_to_regnum.find(name);
+ if (pos != name_to_regnum.end()) {
+ regnum = pos->second;
+ reg_entry.value_regnums.push_back(regnum);
+ if (regnum < g_dynamic_register_map.size()) {
+ // The offset for value_regs registers is the offset within the
+ // register with the lowest offset
+ const uint32_t reg_offset =
+ g_dynamic_register_map[regnum].offset +
+ reg_entry.nub_info.offset;
+ if (new_offset > reg_offset)
+ new_offset = reg_offset;
+ }
+ }
}
- // A packet we don't have an entry for. This can happen when we
- // get a packet that we don't know about or support. We just reply
- // accordingly and go on.
- if (it == m_packets.end ())
- {
- DNBLogThreadedIf (LOG_RNB_PACKETS, "unimplemented packet: '%s'", payload.c_str());
- HandlePacket_UNIMPLEMENTED(payload.c_str());
- return rnb_err;
+ if (new_offset != UINT32_MAX) {
+ reg_entry.offset = new_offset;
+ } else {
+ DNBLogThreaded("no offset was calculated entry for register %s",
+ reg_entry.nub_info.name);
+ reg_entry.offset = UINT32_MAX;
}
- else
- {
- packet_info = *it;
- packet_payload = payload;
+ }
+
+ if (reg_entry.nub_info.update_regs) {
+ for (size_t i = 0; reg_entry.nub_info.update_regs[i] != NULL; ++i) {
+ const char *name = reg_entry.nub_info.update_regs[i];
+ auto pos = name_to_regnum.find(name);
+ if (pos != name_to_regnum.end()) {
+ regnum = pos->second;
+ reg_entry.invalidate_regnums.push_back(regnum);
+ }
}
+ }
}
- return err;
+
+ // for (auto ®_entry: g_dynamic_register_map)
+ // {
+ // DNBLogThreaded("%4i: size = %3u, pseudo = %i, name = %s",
+ // reg_entry.offset,
+ // reg_entry.nub_info.size,
+ // reg_entry.nub_info.value_regs != NULL,
+ // reg_entry.nub_info.name);
+ // }
+
+ g_reg_entries = g_dynamic_register_map.data();
+ g_num_reg_entries = g_dynamic_register_map.size();
+ }
+ return true;
}
-rnb_err_t
-RNBRemote::HandleAsyncPacket(PacketEnum *type)
-{
- DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
- static DNBTimer g_packetTimer(true);
- rnb_err_t err = rnb_err;
- std::string packet_data;
- RNBRemote::Packet packet_info;
- err = GetPacket (packet_data, packet_info, false);
-
- if (err == rnb_success)
- {
- if (!packet_data.empty() && isprint(packet_data[0]))
- DNBLogThreadedIf (LOG_RNB_REMOTE | LOG_RNB_PACKETS, "HandleAsyncPacket (\"%s\");", packet_data.c_str());
- else
- DNBLogThreadedIf (LOG_RNB_REMOTE | LOG_RNB_PACKETS, "HandleAsyncPacket (%s);", packet_info.printable_name.c_str());
-
- HandlePacketCallback packet_callback = packet_info.async;
- if (packet_callback != NULL)
- {
- if (type != NULL)
- *type = packet_info.type;
- return (this->*packet_callback)(packet_data.c_str());
- }
- }
+/* The inferior has stopped executing; send a packet
+ to gdb to let it know. */
- return err;
+void RNBRemote::NotifyThatProcessStopped(void) {
+ RNBRemote::HandlePacket_last_signal(NULL);
+ return;
}
-rnb_err_t
-RNBRemote::HandleReceivedPacket(PacketEnum *type)
-{
- static DNBTimer g_packetTimer(true);
-
- // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
- rnb_err_t err = rnb_err;
- std::string packet_data;
- RNBRemote::Packet packet_info;
- err = GetPacket (packet_data, packet_info, false);
-
- if (err == rnb_success)
- {
- DNBLogThreadedIf (LOG_RNB_REMOTE, "HandleReceivedPacket (\"%s\");", packet_data.c_str());
- HandlePacketCallback packet_callback = packet_info.normal;
- if (packet_callback != NULL)
- {
- if (type != NULL)
- *type = packet_info.type;
- return (this->*packet_callback)(packet_data.c_str());
- }
- else
- {
- // Do not fall through to end of this function, if we have valid
- // packet_info and it has a NULL callback, then we need to respect
- // that it may not want any response or anything to be done.
- return err;
- }
- }
- return rnb_err;
-}
+/* 'A arglen,argnum,arg,...'
+ Update the inferior context CTX with the program name and arg
+ list.
+ The documentation for this packet is underwhelming but my best reading
+ of this is that it is a series of (len, position #, arg)'s, one for
+ each argument with "arg" hex encoded (two 0-9a-f chars?).
+ Why we need BOTH a "len" and a hex encoded "arg" is beyond me - either
+ is sufficient to get around the "," position separator escape issue.
-void
-RNBRemote::CommDataReceived(const std::string& new_data)
-{
- // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
- {
- // Put the packet data into the buffer in a thread safe fashion
- PThreadMutex::Locker locker(m_mutex);
+ e.g. our best guess for a valid 'A' packet for "gdb -q a.out" is
- std::string data;
- // See if we have any left over data from a previous call to this
- // function?
- if (!m_rx_partial_data.empty())
- {
- // We do, so lets start with that data
- data.swap(m_rx_partial_data);
- }
- // Append the new incoming data
- data += new_data;
+ 6,0,676462,4,1,2d71,10,2,612e6f7574
- // Parse up the packets into gdb remote packets
- size_t idx = 0;
- const size_t data_size = data.size();
+ Note that "argnum" and "arglen" are numbers in base 10. Again, that's
+ not documented either way but I'm assuming it's so. */
- while (idx < data_size)
- {
- // end_idx must be one past the last valid packet byte. Start
- // it off with an invalid value that is the same as the current
- // index.
- size_t end_idx = idx;
+rnb_err_t RNBRemote::HandlePacket_A(const char *p) {
+ if (p == NULL || *p == '\0') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Null packet for 'A' pkt");
+ }
+ p++;
+ if (*p == '\0' || !isdigit(*p)) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "arglen not specified on 'A' pkt");
+ }
+
+ /* I promise I don't modify it anywhere in this function. strtoul()'s
+ 2nd arg has to be non-const which makes it problematic to step
+ through the string easily. */
+ char *buf = const_cast<char *>(p);
- switch (data[idx])
- {
- case '+': // Look for ack
- case '-': // Look for cancel
- case '\x03': // ^C to halt target
- end_idx = idx + 1; // The command is one byte long...
- break;
-
- case '$':
- // Look for a standard gdb packet?
- end_idx = data.find('#', idx + 1);
- if (end_idx == std::string::npos || end_idx + 3 > data_size)
- {
- end_idx = std::string::npos;
- }
- else
- {
- // Add two for the checksum bytes and 1 to point to the
- // byte just past the end of this packet
- end_idx += 3;
- }
- break;
+ RNBContext &ctx = Context();
- default:
- break;
- }
+ while (*buf != '\0') {
+ unsigned long arglen, argnum;
+ std::string arg;
+ char *c;
- if (end_idx == std::string::npos)
- {
- // Not all data may be here for the packet yet, save it for
- // next time through this function.
- m_rx_partial_data += data.substr(idx);
- //DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s saving data for later[%u, npos): '%s'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, idx, m_rx_partial_data.c_str());
- idx = end_idx;
- }
- else
- if (idx < end_idx)
- {
- m_packets_recvd++;
- // Hack to get rid of initial '+' ACK???
- if (m_packets_recvd == 1 && (end_idx == idx + 1) && data[idx] == '+')
- {
- //DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s throwing first ACK away....[%u, npos): '+'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, idx);
- }
- else
- {
- // We have a valid packet...
- m_rx_packets.push_back(data.substr(idx, end_idx - idx));
- DNBLogThreadedIf (LOG_RNB_PACKETS, "getpkt: %s", m_rx_packets.back().c_str());
- }
- idx = end_idx;
- }
- else
- {
- DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s tossing junk byte at %c",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, data[idx]);
- idx = idx + 1;
- }
- }
+ errno = 0;
+ arglen = strtoul(buf, &c, 10);
+ if (errno != 0 && arglen == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "arglen not a number on 'A' pkt");
+ }
+ if (*c != ',') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "arglen not followed by comma on 'A' pkt");
}
+ buf = c + 1;
- if (!m_rx_packets.empty())
- {
- // Let the main thread know we have received a packet
+ errno = 0;
+ argnum = strtoul(buf, &c, 10);
+ if (errno != 0 && argnum == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "argnum not a number on 'A' pkt");
+ }
+ if (*c != ',') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "arglen not followed by comma on 'A' pkt");
+ }
+ buf = c + 1;
+
+ c = buf;
+ buf = buf + arglen;
+ while (c < buf && *c != '\0' && c + 1 < buf && *(c + 1) != '\0') {
+ char smallbuf[3];
+ smallbuf[0] = *c;
+ smallbuf[1] = *(c + 1);
+ smallbuf[2] = '\0';
+
+ errno = 0;
+ int ch = static_cast<int>(strtoul(smallbuf, NULL, 16));
+ if (errno != 0 && ch == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "non-hex char in arg on 'A' pkt");
+ }
- //DNBLogThreadedIf (LOG_RNB_EVENTS, "%8d RNBRemote::%s called events.SetEvent(RNBContext::event_read_packet_available)", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
- PThreadEvent& events = m_ctx.Events();
- events.SetEvents (RNBContext::event_read_packet_available);
+ arg.push_back(ch);
+ c += 2;
}
-}
-rnb_err_t
-RNBRemote::GetCommData ()
-{
- // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
- std::string comm_data;
- rnb_err_t err = m_comm.Read (comm_data);
- if (err == rnb_success)
- {
- if (!comm_data.empty())
- CommDataReceived (comm_data);
- }
- return err;
-}
+ ctx.PushArgument(arg.c_str());
+ if (*buf == ',')
+ buf++;
+ }
+ SendPacket("OK");
-void
-RNBRemote::StartReadRemoteDataThread()
-{
- DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
- PThreadEvent& events = m_ctx.Events();
- if ((events.GetEventBits() & RNBContext::event_read_thread_running) == 0)
- {
- events.ResetEvents (RNBContext::event_read_thread_exiting);
- int err = ::pthread_create (&m_rx_pthread, NULL, ThreadFunctionReadRemoteData, this);
- if (err == 0)
- {
- // Our thread was successfully kicked off, wait for it to
- // set the started event so we can safely continue
- events.WaitForSetEvents (RNBContext::event_read_thread_running);
- }
- else
- {
- events.ResetEvents (RNBContext::event_read_thread_running);
- events.SetEvents (RNBContext::event_read_thread_exiting);
- }
- }
+ return rnb_success;
}
-void
-RNBRemote::StopReadRemoteDataThread()
-{
- DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
- PThreadEvent& events = m_ctx.Events();
- if ((events.GetEventBits() & RNBContext::event_read_thread_running) == RNBContext::event_read_thread_running)
- {
- m_comm.Disconnect(true);
- struct timespec timeout_abstime;
- DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0);
+/* 'H c t'
+ Set the thread for subsequent actions; 'c' for step/continue ops,
+ 'g' for other ops. -1 means all threads, 0 means any thread. */
- // Wait for 2 seconds for the remote data thread to exit
- if (events.WaitForSetEvents(RNBContext::event_read_thread_exiting, &timeout_abstime) == 0)
- {
- // Kill the remote data thread???
- }
- }
-}
+rnb_err_t RNBRemote::HandlePacket_H(const char *p) {
+ p++; // skip 'H'
+ if (*p != 'c' && *p != 'g') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Missing 'c' or 'g' type in H packet");
+ }
+ if (!m_ctx.HasValidProcessID()) {
+ // We allow gdb to connect to a server that hasn't started running
+ // the target yet. gdb still wants to ask questions about it and
+ // freaks out if it gets an error. So just return OK here.
+ }
-void*
-RNBRemote::ThreadFunctionReadRemoteData(void *arg)
-{
- // Keep a shared pointer reference so this doesn't go away on us before the thread is killed.
- DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread starting...", __FUNCTION__, arg);
- RNBRemoteSP remoteSP(g_remoteSP);
- if (remoteSP.get() != NULL)
- {
+ errno = 0;
+ nub_thread_t tid = strtoul(p + 1, NULL, 16);
+ if (errno != 0 && tid == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid thread number in H packet");
+ }
+ if (*p == 'c')
+ SetContinueThread(tid);
+ if (*p == 'g')
+ SetCurrentThread(tid);
-#if defined (__APPLE__)
- pthread_setname_np ("read gdb-remote packets thread");
-#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
- struct sched_param thread_param;
- int thread_sched_policy;
- if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0)
- {
- thread_param.sched_priority = 47;
- pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
- }
-#endif
-#endif
+ return SendPacket("OK");
+}
- RNBRemote* remote = remoteSP.get();
- PThreadEvent& events = remote->Context().Events();
- events.SetEvents (RNBContext::event_read_thread_running);
- // START: main receive remote command thread loop
- bool done = false;
- while (!done)
- {
- rnb_err_t err = remote->GetCommData();
+rnb_err_t RNBRemote::HandlePacket_qLaunchSuccess(const char *p) {
+ if (m_ctx.HasValidProcessID() || m_ctx.LaunchStatus().Error() == 0)
+ return SendPacket("OK");
+ std::ostringstream ret_str;
+ std::string status_str;
+ ret_str << "E" << m_ctx.LaunchStatusAsString(status_str);
- switch (err)
- {
- case rnb_success:
- break;
+ return SendPacket(ret_str.str());
+}
- case rnb_err:
- DNBLogThreadedIf (LOG_RNB_REMOTE, "RNBSocket::GetCommData returned error %u", err);
- done = true;
- break;
-
- case rnb_not_connected:
- DNBLogThreadedIf (LOG_RNB_REMOTE, "RNBSocket::GetCommData returned not connected...");
- done = true;
- break;
- }
- }
- // START: main receive remote command thread loop
- events.ResetEvents (RNBContext::event_read_thread_running);
- events.SetEvents (RNBContext::event_read_thread_exiting);
+rnb_err_t RNBRemote::HandlePacket_qShlibInfoAddr(const char *p) {
+ if (m_ctx.HasValidProcessID()) {
+ nub_addr_t shlib_info_addr =
+ DNBProcessGetSharedLibraryInfoAddress(m_ctx.ProcessID());
+ if (shlib_info_addr != INVALID_NUB_ADDRESS) {
+ std::ostringstream ostrm;
+ ostrm << RAW_HEXBASE << shlib_info_addr;
+ return SendPacket(ostrm.str());
}
- DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread exiting...", __FUNCTION__, arg);
- return NULL;
+ }
+ return SendPacket("E44");
}
+rnb_err_t RNBRemote::HandlePacket_qStepPacketSupported(const char *p) {
+ // Normally the "s" packet is mandatory, yet in gdb when using ARM, they
+ // get around the need for this packet by implementing software single
+ // stepping from gdb. Current versions of debugserver do support the "s"
+ // packet, yet some older versions do not. We need a way to tell if this
+ // packet is supported so we can disable software single stepping in gdb
+ // for remote targets (so the "s" packet will get used).
+ return SendPacket("OK");
+}
-// If we fail to get back a valid CPU type for the remote process,
-// make a best guess for the CPU type based on the currently running
-// debugserver binary -- the debugger may not handle the case of an
-// un-specified process CPU type correctly.
-
-static cpu_type_t
-best_guess_cpu_type ()
-{
-#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
- if (sizeof (char *) == 8)
- {
- return CPU_TYPE_ARM64;
- }
- else
- {
- return CPU_TYPE_ARM;
- }
-#elif defined (__i386__) || defined (__x86_64__)
- if (sizeof (char*) == 8)
- {
- return CPU_TYPE_X86_64;
- }
- else
- {
- return CPU_TYPE_I386;
- }
-#endif
- return 0;
+rnb_err_t RNBRemote::HandlePacket_qSyncThreadStateSupported(const char *p) {
+ // We support attachOrWait meaning attach if the process exists, otherwise
+ // wait to attach.
+ return SendPacket("OK");
}
+rnb_err_t RNBRemote::HandlePacket_qVAttachOrWaitSupported(const char *p) {
+ // We support attachOrWait meaning attach if the process exists, otherwise
+ // wait to attach.
+ return SendPacket("OK");
+}
-/* Read the bytes in STR which are GDB Remote Protocol binary encoded bytes
- (8-bit bytes).
- This encoding uses 0x7d ('}') as an escape character for
- 0x7d ('}'), 0x23 ('#'), 0x24 ('$'), 0x2a ('*').
- LEN is the number of bytes to be processed. If a character is escaped,
- it is 2 characters for LEN. A LEN of -1 means decode-until-nul-byte
- (end of string). */
+rnb_err_t RNBRemote::HandlePacket_qThreadStopInfo(const char *p) {
+ p += strlen("qThreadStopInfo");
+ nub_thread_t tid = strtoul(p, 0, 16);
+ return SendStopReplyPacketForThread(tid);
+}
-std::vector<uint8_t>
-decode_binary_data (const char *str, size_t len)
-{
- std::vector<uint8_t> bytes;
- if (len == 0)
- {
- return bytes;
- }
- if (len == (size_t)-1)
- len = strlen (str);
+rnb_err_t RNBRemote::HandlePacket_qThreadInfo(const char *p) {
+ // We allow gdb to connect to a server that hasn't started running
+ // the target yet. gdb still wants to ask questions about it and
+ // freaks out if it gets an error. So just return OK here.
+ nub_process_t pid = m_ctx.ProcessID();
+ if (pid == INVALID_NUB_PROCESS)
+ return SendPacket("OK");
- while (len--)
- {
- unsigned char c = *str++;
- if (c == 0x7d && len > 0)
- {
- len--;
- c = *str++ ^ 0x20;
- }
- bytes.push_back (c);
- }
- return bytes;
-}
+ // Only "qfThreadInfo" and "qsThreadInfo" get into this function so
+ // we only need to check the second byte to tell which is which
+ if (p[1] == 'f') {
+ nub_size_t numthreads = DNBProcessGetNumThreads(pid);
+ std::ostringstream ostrm;
+ ostrm << "m";
+ bool first = true;
+ for (nub_size_t i = 0; i < numthreads; ++i) {
+ if (first)
+ first = false;
+ else
+ ostrm << ",";
+ nub_thread_t th = DNBProcessGetThreadAtIndex(pid, i);
+ ostrm << std::hex << th;
+ }
+ return SendPacket(ostrm.str());
+ } else {
+ return SendPacket("l");
+ }
+}
+
+rnb_err_t RNBRemote::HandlePacket_qThreadExtraInfo(const char *p) {
+ // We allow gdb to connect to a server that hasn't started running
+ // the target yet. gdb still wants to ask questions about it and
+ // freaks out if it gets an error. So just return OK here.
+ nub_process_t pid = m_ctx.ProcessID();
+ if (pid == INVALID_NUB_PROCESS)
+ return SendPacket("OK");
-// Quote any meta characters in a std::string as per the binary
-// packet convention in the gdb-remote protocol.
+ /* This is supposed to return a string like 'Runnable' or
+ 'Blocked on Mutex'.
+ The returned string is formatted like the "A" packet - a
+ sequence of letters encoded in as 2-hex-chars-per-letter. */
+ p += strlen("qThreadExtraInfo");
+ if (*p++ != ',')
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Illformed qThreadExtraInfo packet");
+ errno = 0;
+ nub_thread_t tid = strtoul(p, NULL, 16);
+ if (errno != 0 && tid == 0) {
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p,
+ "Invalid thread number in qThreadExtraInfo packet");
+ }
+
+ const char *threadInfo = DNBThreadGetInfo(pid, tid);
+ if (threadInfo != NULL && threadInfo[0]) {
+ return SendHexEncodedBytePacket(NULL, threadInfo, strlen(threadInfo), NULL);
+ } else {
+ // "OK" == 4f6b
+ // Return "OK" as a ASCII hex byte stream if things go wrong
+ return SendPacket("4f6b");
+ }
-static std::string
-binary_encode_string (const std::string &s)
-{
- std::string output;
- const size_t s_size = s.size();
- const char *s_chars = s.c_str();
+ return SendPacket("");
+}
- for (size_t i = 0; i < s_size; i++)
- {
- unsigned char ch = *(s_chars + i);
- if (ch == '#' || ch == '$' || ch == '}' || ch == '*')
- {
- output.push_back ('}'); // 0x7d
- output.push_back (ch ^ 0x20);
+const char *k_space_delimiters = " \t";
+static void skip_spaces(std::string &line) {
+ if (!line.empty()) {
+ size_t space_pos = line.find_first_not_of(k_space_delimiters);
+ if (space_pos > 0)
+ line.erase(0, space_pos);
+ }
+}
+
+static std::string get_identifier(std::string &line) {
+ std::string word;
+ skip_spaces(line);
+ const size_t line_size = line.size();
+ size_t end_pos;
+ for (end_pos = 0; end_pos < line_size; ++end_pos) {
+ if (end_pos == 0) {
+ if (isalpha(line[end_pos]) || line[end_pos] == '_')
+ continue;
+ } else if (isalnum(line[end_pos]) || line[end_pos] == '_')
+ continue;
+ break;
+ }
+ word.assign(line, 0, end_pos);
+ line.erase(0, end_pos);
+ return word;
+}
+
+static std::string get_operator(std::string &line) {
+ std::string op;
+ skip_spaces(line);
+ if (!line.empty()) {
+ if (line[0] == '=') {
+ op = '=';
+ line.erase(0, 1);
+ }
+ }
+ return op;
+}
+
+static std::string get_value(std::string &line) {
+ std::string value;
+ skip_spaces(line);
+ if (!line.empty()) {
+ value.swap(line);
+ }
+ return value;
+}
+
+extern void FileLogCallback(void *baton, uint32_t flags, const char *format,
+ va_list args);
+extern void ASLLogCallback(void *baton, uint32_t flags, const char *format,
+ va_list args);
+
+rnb_err_t RNBRemote::HandlePacket_qRcmd(const char *p) {
+ const char *c = p + strlen("qRcmd,");
+ std::string line;
+ while (c[0] && c[1]) {
+ char smallbuf[3] = {c[0], c[1], '\0'};
+ errno = 0;
+ int ch = static_cast<int>(strtoul(smallbuf, NULL, 16));
+ if (errno != 0 && ch == 0)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "non-hex char in payload of qRcmd packet");
+ line.push_back(ch);
+ c += 2;
+ }
+ if (*c == '\0') {
+ std::string command = get_identifier(line);
+ if (command.compare("set") == 0) {
+ std::string variable = get_identifier(line);
+ std::string op = get_operator(line);
+ std::string value = get_value(line);
+ if (variable.compare("logfile") == 0) {
+ FILE *log_file = fopen(value.c_str(), "w");
+ if (log_file) {
+ DNBLogSetLogCallback(FileLogCallback, log_file);
+ return SendPacket("OK");
+ }
+ return SendPacket("E71");
+ } else if (variable.compare("logmask") == 0) {
+ char *end;
+ errno = 0;
+ uint32_t logmask =
+ static_cast<uint32_t>(strtoul(value.c_str(), &end, 0));
+ if (errno == 0 && end && *end == '\0') {
+ DNBLogSetLogMask(logmask);
+ if (!DNBLogGetLogCallback())
+ DNBLogSetLogCallback(ASLLogCallback, NULL);
+ return SendPacket("OK");
}
- else
- {
- output.push_back (ch);
+ errno = 0;
+ logmask = static_cast<uint32_t>(strtoul(value.c_str(), &end, 16));
+ if (errno == 0 && end && *end == '\0') {
+ DNBLogSetLogMask(logmask);
+ return SendPacket("OK");
}
+ return SendPacket("E72");
+ }
+ return SendPacket("E70");
}
- return output;
+ return SendPacket("E69");
+ }
+ return SendPacket("E73");
+}
+
+rnb_err_t RNBRemote::HandlePacket_qC(const char *p) {
+ nub_thread_t tid;
+ std::ostringstream rep;
+ // If we haven't run the process yet, we tell the debugger the
+ // pid is 0. That way it can know to tell use to run later on.
+ if (!m_ctx.HasValidProcessID())
+ tid = 0;
+ else {
+ // Grab the current thread.
+ tid = DNBProcessGetCurrentThread(m_ctx.ProcessID());
+ // Make sure we set the current thread so g and p packets return
+ // the data the gdb will expect.
+ SetCurrentThread(tid);
+ }
+ rep << "QC" << std::hex << tid;
+ return SendPacket(rep.str());
+}
+
+rnb_err_t RNBRemote::HandlePacket_qEcho(const char *p) {
+ // Just send the exact same packet back that we received to
+ // synchronize the response packets after a previous packet
+ // timed out. This allows the debugger to get back on track
+ // with responses after a packet timeout.
+ return SendPacket(p);
+}
+
+rnb_err_t RNBRemote::HandlePacket_qGetPid(const char *p) {
+ nub_process_t pid;
+ std::ostringstream rep;
+ // If we haven't run the process yet, we tell the debugger the
+ // pid is 0. That way it can know to tell use to run later on.
+ if (m_ctx.HasValidProcessID())
+ pid = m_ctx.ProcessID();
+ else
+ pid = 0;
+ rep << std::hex << pid;
+ return SendPacket(rep.str());
}
-// If the value side of a key-value pair in JSON is a string,
-// and that string has a " character in it, the " character must
-// be escaped.
-
-std::string
-json_string_quote_metachars (const std::string &s)
-{
- if (s.find('"') == std::string::npos)
- return s;
-
- std::string output;
- const size_t s_size = s.size();
- const char *s_chars = s.c_str();
- for (size_t i = 0; i < s_size; i++)
- {
- unsigned char ch = *(s_chars + i);
- if (ch == '"')
- {
- output.push_back ('\\');
- }
- output.push_back (ch);
- }
- return output;
-}
+rnb_err_t RNBRemote::HandlePacket_qRegisterInfo(const char *p) {
+ if (g_num_reg_entries == 0)
+ InitializeRegisters();
-typedef struct register_map_entry
-{
- uint32_t debugserver_regnum; // debugserver register number
- uint32_t offset; // Offset in bytes into the register context data with no padding between register values
- DNBRegisterInfo nub_info; // debugnub register info
- std::vector<uint32_t> value_regnums;
- std::vector<uint32_t> invalidate_regnums;
-} register_map_entry_t;
+ p += strlen("qRegisterInfo");
+ nub_size_t num_reg_sets = 0;
+ const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo(&num_reg_sets);
+ uint32_t reg_num = static_cast<uint32_t>(strtoul(p, 0, 16));
+ if (reg_num < g_num_reg_entries) {
+ const register_map_entry_t *reg_entry = &g_reg_entries[reg_num];
+ std::ostringstream ostrm;
+ if (reg_entry->nub_info.name)
+ ostrm << "name:" << reg_entry->nub_info.name << ';';
+ if (reg_entry->nub_info.alt)
+ ostrm << "alt-name:" << reg_entry->nub_info.alt << ';';
+
+ ostrm << "bitsize:" << std::dec << reg_entry->nub_info.size * 8 << ';';
+ ostrm << "offset:" << std::dec << reg_entry->offset << ';';
+
+ switch (reg_entry->nub_info.type) {
+ case Uint:
+ ostrm << "encoding:uint;";
+ break;
+ case Sint:
+ ostrm << "encoding:sint;";
+ break;
+ case IEEE754:
+ ostrm << "encoding:ieee754;";
+ break;
+ case Vector:
+ ostrm << "encoding:vector;";
+ break;
+ }
+
+ switch (reg_entry->nub_info.format) {
+ case Binary:
+ ostrm << "format:binary;";
+ break;
+ case Decimal:
+ ostrm << "format:decimal;";
+ break;
+ case Hex:
+ ostrm << "format:hex;";
+ break;
+ case Float:
+ ostrm << "format:float;";
+ break;
+ case VectorOfSInt8:
+ ostrm << "format:vector-sint8;";
+ break;
+ case VectorOfUInt8:
+ ostrm << "format:vector-uint8;";
+ break;
+ case VectorOfSInt16:
+ ostrm << "format:vector-sint16;";
+ break;
+ case VectorOfUInt16:
+ ostrm << "format:vector-uint16;";
+ break;
+ case VectorOfSInt32:
+ ostrm << "format:vector-sint32;";
+ break;
+ case VectorOfUInt32:
+ ostrm << "format:vector-uint32;";
+ break;
+ case VectorOfFloat32:
+ ostrm << "format:vector-float32;";
+ break;
+ case VectorOfUInt128:
+ ostrm << "format:vector-uint128;";
+ break;
+ };
-// If the notion of registers differs from what is handed out by the
-// architecture, then flavors can be defined here.
+ if (reg_set_info && reg_entry->nub_info.set < num_reg_sets)
+ ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';';
-static std::vector<register_map_entry_t> g_dynamic_register_map;
-static register_map_entry_t *g_reg_entries = NULL;
-static size_t g_num_reg_entries = 0;
+ if (reg_entry->nub_info.reg_ehframe != INVALID_NUB_REGNUM)
+ ostrm << "ehframe:" << std::dec << reg_entry->nub_info.reg_ehframe << ';';
-void
-RNBRemote::Initialize()
-{
- DNBInitialize();
-}
+ if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM)
+ ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';';
+ switch (reg_entry->nub_info.reg_generic) {
+ case GENERIC_REGNUM_FP:
+ ostrm << "generic:fp;";
+ break;
+ case GENERIC_REGNUM_PC:
+ ostrm << "generic:pc;";
+ break;
+ case GENERIC_REGNUM_SP:
+ ostrm << "generic:sp;";
+ break;
+ case GENERIC_REGNUM_RA:
+ ostrm << "generic:ra;";
+ break;
+ case GENERIC_REGNUM_FLAGS:
+ ostrm << "generic:flags;";
+ break;
+ case GENERIC_REGNUM_ARG1:
+ ostrm << "generic:arg1;";
+ break;
+ case GENERIC_REGNUM_ARG2:
+ ostrm << "generic:arg2;";
+ break;
+ case GENERIC_REGNUM_ARG3:
+ ostrm << "generic:arg3;";
+ break;
+ case GENERIC_REGNUM_ARG4:
+ ostrm << "generic:arg4;";
+ break;
+ case GENERIC_REGNUM_ARG5:
+ ostrm << "generic:arg5;";
+ break;
+ case GENERIC_REGNUM_ARG6:
+ ostrm << "generic:arg6;";
+ break;
+ case GENERIC_REGNUM_ARG7:
+ ostrm << "generic:arg7;";
+ break;
+ case GENERIC_REGNUM_ARG8:
+ ostrm << "generic:arg8;";
+ break;
+ default:
+ break;
+ }
-bool
-RNBRemote::InitializeRegisters (bool force)
-{
- pid_t pid = m_ctx.ProcessID();
- if (pid == INVALID_NUB_PROCESS)
- return false;
-
- DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting native registers from DNB interface", __FUNCTION__);
- // Discover the registers by querying the DNB interface and letting it
- // state the registers that it would like to export. This allows the
- // registers to be discovered using multiple qRegisterInfo calls to get
- // all register information after the architecture for the process is
- // determined.
- if (force)
- {
- g_dynamic_register_map.clear();
- g_reg_entries = NULL;
- g_num_reg_entries = 0;
+ if (!reg_entry->value_regnums.empty()) {
+ ostrm << "container-regs:";
+ for (size_t i = 0, n = reg_entry->value_regnums.size(); i < n; ++i) {
+ if (i > 0)
+ ostrm << ',';
+ ostrm << RAW_HEXBASE << reg_entry->value_regnums[i];
+ }
+ ostrm << ';';
}
- if (g_dynamic_register_map.empty())
- {
- nub_size_t num_reg_sets = 0;
- const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets);
+ if (!reg_entry->invalidate_regnums.empty()) {
+ ostrm << "invalidate-regs:";
+ for (size_t i = 0, n = reg_entry->invalidate_regnums.size(); i < n; ++i) {
+ if (i > 0)
+ ostrm << ',';
+ ostrm << RAW_HEXBASE << reg_entry->invalidate_regnums[i];
+ }
+ ostrm << ';';
+ }
- assert (num_reg_sets > 0 && reg_sets != NULL);
+ return SendPacket(ostrm.str());
+ }
+ return SendPacket("E45");
+}
- uint32_t regnum = 0;
- uint32_t reg_data_offset = 0;
- typedef std::map<std::string, uint32_t> NameToRegNum;
- NameToRegNum name_to_regnum;
- for (nub_size_t set = 0; set < num_reg_sets; ++set)
- {
- if (reg_sets[set].registers == NULL)
- continue;
+/* This expects a packet formatted like
- for (uint32_t reg=0; reg < reg_sets[set].num_registers; ++reg)
- {
- register_map_entry_t reg_entry = {
- regnum++, // register number starts at zero and goes up with no gaps
- reg_data_offset, // Offset into register context data, no gaps between registers
- reg_sets[set].registers[reg], // DNBRegisterInfo
- {},
- {},
- };
+ QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE;
- name_to_regnum[reg_entry.nub_info.name] = reg_entry.debugserver_regnum;
+ with the "QSetLogging:" already removed from the start. Maybe in the
+ future this packet will include other keyvalue pairs like
- if (reg_entry.nub_info.value_regs == NULL)
- {
- reg_data_offset += reg_entry.nub_info.size;
- }
+ QSetLogging:bitmask=LOG_ALL;mode=asl;
+ */
- g_dynamic_register_map.push_back (reg_entry);
+rnb_err_t set_logging(const char *p) {
+ int bitmask = 0;
+ while (p && *p != '\0') {
+ if (strncmp(p, "bitmask=", sizeof("bitmask=") - 1) == 0) {
+ p += sizeof("bitmask=") - 1;
+ while (p && *p != '\0' && *p != ';') {
+ if (*p == '|')
+ p++;
+
+ // to regenerate the LOG_ entries (not including the LOG_RNB entries)
+ // $ for logname in `grep '^#define LOG_' DNBDefs.h | egrep -v
+ // 'LOG_HI|LOG_LO' | awk '{print $2}'`
+ // do
+ // echo " else if (strncmp (p, \"$logname\", sizeof
+ // (\"$logname\") - 1) == 0)"
+ // echo " {"
+ // echo " p += sizeof (\"$logname\") - 1;"
+ // echo " bitmask |= $logname;"
+ // echo " }"
+ // done
+ if (strncmp(p, "LOG_VERBOSE", sizeof("LOG_VERBOSE") - 1) == 0) {
+ p += sizeof("LOG_VERBOSE") - 1;
+ bitmask |= LOG_VERBOSE;
+ } else if (strncmp(p, "LOG_PROCESS", sizeof("LOG_PROCESS") - 1) == 0) {
+ p += sizeof("LOG_PROCESS") - 1;
+ bitmask |= LOG_PROCESS;
+ } else if (strncmp(p, "LOG_THREAD", sizeof("LOG_THREAD") - 1) == 0) {
+ p += sizeof("LOG_THREAD") - 1;
+ bitmask |= LOG_THREAD;
+ } else if (strncmp(p, "LOG_EXCEPTIONS", sizeof("LOG_EXCEPTIONS") - 1) ==
+ 0) {
+ p += sizeof("LOG_EXCEPTIONS") - 1;
+ bitmask |= LOG_EXCEPTIONS;
+ } else if (strncmp(p, "LOG_SHLIB", sizeof("LOG_SHLIB") - 1) == 0) {
+ p += sizeof("LOG_SHLIB") - 1;
+ bitmask |= LOG_SHLIB;
+ } else if (strncmp(p, "LOG_MEMORY", sizeof("LOG_MEMORY") - 1) == 0) {
+ p += sizeof("LOG_MEMORY") - 1;
+ bitmask |= LOG_MEMORY;
+ } else if (strncmp(p, "LOG_MEMORY_DATA_SHORT",
+ sizeof("LOG_MEMORY_DATA_SHORT") - 1) == 0) {
+ p += sizeof("LOG_MEMORY_DATA_SHORT") - 1;
+ bitmask |= LOG_MEMORY_DATA_SHORT;
+ } else if (strncmp(p, "LOG_MEMORY_DATA_LONG",
+ sizeof("LOG_MEMORY_DATA_LONG") - 1) == 0) {
+ p += sizeof("LOG_MEMORY_DATA_LONG") - 1;
+ bitmask |= LOG_MEMORY_DATA_LONG;
+ } else if (strncmp(p, "LOG_MEMORY_PROTECTIONS",
+ sizeof("LOG_MEMORY_PROTECTIONS") - 1) == 0) {
+ p += sizeof("LOG_MEMORY_PROTECTIONS") - 1;
+ bitmask |= LOG_MEMORY_PROTECTIONS;
+ } else if (strncmp(p, "LOG_BREAKPOINTS",
+ sizeof("LOG_BREAKPOINTS") - 1) == 0) {
+ p += sizeof("LOG_BREAKPOINTS") - 1;
+ bitmask |= LOG_BREAKPOINTS;
+ } else if (strncmp(p, "LOG_EVENTS", sizeof("LOG_EVENTS") - 1) == 0) {
+ p += sizeof("LOG_EVENTS") - 1;
+ bitmask |= LOG_EVENTS;
+ } else if (strncmp(p, "LOG_WATCHPOINTS",
+ sizeof("LOG_WATCHPOINTS") - 1) == 0) {
+ p += sizeof("LOG_WATCHPOINTS") - 1;
+ bitmask |= LOG_WATCHPOINTS;
+ } else if (strncmp(p, "LOG_STEP", sizeof("LOG_STEP") - 1) == 0) {
+ p += sizeof("LOG_STEP") - 1;
+ bitmask |= LOG_STEP;
+ } else if (strncmp(p, "LOG_TASK", sizeof("LOG_TASK") - 1) == 0) {
+ p += sizeof("LOG_TASK") - 1;
+ bitmask |= LOG_TASK;
+ } else if (strncmp(p, "LOG_ALL", sizeof("LOG_ALL") - 1) == 0) {
+ p += sizeof("LOG_ALL") - 1;
+ bitmask |= LOG_ALL;
+ } else if (strncmp(p, "LOG_DEFAULT", sizeof("LOG_DEFAULT") - 1) == 0) {
+ p += sizeof("LOG_DEFAULT") - 1;
+ bitmask |= LOG_DEFAULT;
+ }
+ // end of auto-generated entries
+
+ else if (strncmp(p, "LOG_NONE", sizeof("LOG_NONE") - 1) == 0) {
+ p += sizeof("LOG_NONE") - 1;
+ bitmask = 0;
+ } else if (strncmp(p, "LOG_RNB_MINIMAL",
+ sizeof("LOG_RNB_MINIMAL") - 1) == 0) {
+ p += sizeof("LOG_RNB_MINIMAL") - 1;
+ bitmask |= LOG_RNB_MINIMAL;
+ } else if (strncmp(p, "LOG_RNB_MEDIUM", sizeof("LOG_RNB_MEDIUM") - 1) ==
+ 0) {
+ p += sizeof("LOG_RNB_MEDIUM") - 1;
+ bitmask |= LOG_RNB_MEDIUM;
+ } else if (strncmp(p, "LOG_RNB_MAX", sizeof("LOG_RNB_MAX") - 1) == 0) {
+ p += sizeof("LOG_RNB_MAX") - 1;
+ bitmask |= LOG_RNB_MAX;
+ } else if (strncmp(p, "LOG_RNB_COMM", sizeof("LOG_RNB_COMM") - 1) ==
+ 0) {
+ p += sizeof("LOG_RNB_COMM") - 1;
+ bitmask |= LOG_RNB_COMM;
+ } else if (strncmp(p, "LOG_RNB_REMOTE", sizeof("LOG_RNB_REMOTE") - 1) ==
+ 0) {
+ p += sizeof("LOG_RNB_REMOTE") - 1;
+ bitmask |= LOG_RNB_REMOTE;
+ } else if (strncmp(p, "LOG_RNB_EVENTS", sizeof("LOG_RNB_EVENTS") - 1) ==
+ 0) {
+ p += sizeof("LOG_RNB_EVENTS") - 1;
+ bitmask |= LOG_RNB_EVENTS;
+ } else if (strncmp(p, "LOG_RNB_PROC", sizeof("LOG_RNB_PROC") - 1) ==
+ 0) {
+ p += sizeof("LOG_RNB_PROC") - 1;
+ bitmask |= LOG_RNB_PROC;
+ } else if (strncmp(p, "LOG_RNB_PACKETS",
+ sizeof("LOG_RNB_PACKETS") - 1) == 0) {
+ p += sizeof("LOG_RNB_PACKETS") - 1;
+ bitmask |= LOG_RNB_PACKETS;
+ } else if (strncmp(p, "LOG_RNB_ALL", sizeof("LOG_RNB_ALL") - 1) == 0) {
+ p += sizeof("LOG_RNB_ALL") - 1;
+ bitmask |= LOG_RNB_ALL;
+ } else if (strncmp(p, "LOG_RNB_DEFAULT",
+ sizeof("LOG_RNB_DEFAULT") - 1) == 0) {
+ p += sizeof("LOG_RNB_DEFAULT") - 1;
+ bitmask |= LOG_RNB_DEFAULT;
+ } else if (strncmp(p, "LOG_DARWIN_LOG", sizeof("LOG_DARWIN_LOG") - 1) ==
+ 0) {
+ p += sizeof("LOG_DARWIN_LOG") - 1;
+ bitmask |= LOG_DARWIN_LOG;
+ } else if (strncmp(p, "LOG_RNB_NONE", sizeof("LOG_RNB_NONE") - 1) ==
+ 0) {
+ p += sizeof("LOG_RNB_NONE") - 1;
+ bitmask = 0;
+ } else {
+ /* Unrecognized logging bit; ignore it. */
+ const char *c = strchr(p, '|');
+ if (c) {
+ p = c;
+ } else {
+ c = strchr(p, ';');
+ if (c) {
+ p = c;
+ } else {
+ // Improperly terminated word; just go to end of str
+ p = strchr(p, '\0');
}
+ }
}
-
- // Now we must find any registers whose values are in other registers and fix up
- // the offsets since we removed all gaps...
- for (auto ®_entry: g_dynamic_register_map)
+ }
+ // Did we get a properly formatted logging bitmask?
+ if (p && *p == ';') {
+ // Enable DNB logging.
+ // Use the existing log callback if one was already configured.
+ if (!DNBLogGetLogCallback()) {
+ // Use the os_log()-based logger if available; otherwise,
+ // fallback to ASL.
+ auto log_callback = OsLogger::GetLogFunction();
+ if (log_callback)
+ DNBLogSetLogCallback(log_callback, nullptr);
+ else
+ DNBLogSetLogCallback(ASLLogCallback, nullptr);
+ }
+
+ // Update logging to use the configured log channel bitmask.
+ DNBLogSetLogMask(bitmask);
+ p++;
+ }
+ }
+// We're not going to support logging to a file for now. All logging
+// goes through ASL or the previously arranged log callback.
+#if 0
+ else if (strncmp (p, "mode=", sizeof ("mode=") - 1) == 0)
{
- if (reg_entry.nub_info.value_regs)
+ p += sizeof ("mode=") - 1;
+ if (strncmp (p, "asl;", sizeof ("asl;") - 1) == 0)
{
- uint32_t new_offset = UINT32_MAX;
- for (size_t i=0; reg_entry.nub_info.value_regs[i] != NULL; ++i)
- {
- const char *name = reg_entry.nub_info.value_regs[i];
- auto pos = name_to_regnum.find(name);
- if (pos != name_to_regnum.end())
- {
- regnum = pos->second;
- reg_entry.value_regnums.push_back(regnum);
- if (regnum < g_dynamic_register_map.size())
- {
- // The offset for value_regs registers is the offset within the register with the lowest offset
- const uint32_t reg_offset = g_dynamic_register_map[regnum].offset + reg_entry.nub_info.offset;
- if (new_offset > reg_offset)
- new_offset = reg_offset;
- }
- }
- }
-
- if (new_offset != UINT32_MAX)
- {
- reg_entry.offset = new_offset;
- }
+ DNBLogToASL ();
+ p += sizeof ("asl;") - 1;
+ }
+ else if (strncmp (p, "file;", sizeof ("file;") - 1) == 0)
+ {
+ DNBLogToFile ();
+ p += sizeof ("file;") - 1;
+ }
+ else
+ {
+ // Ignore unknown argument
+ const char *c = strchr (p, ';');
+ if (c)
+ p = c + 1;
else
- {
- DNBLogThreaded("no offset was calculated entry for register %s", reg_entry.nub_info.name);
- reg_entry.offset = UINT32_MAX;
- }
+ p = strchr (p, '\0');
+ }
+ }
+ else if (strncmp (p, "filename=", sizeof ("filename=") - 1) == 0)
+ {
+ p += sizeof ("filename=") - 1;
+ const char *c = strchr (p, ';');
+ if (c == NULL)
+ {
+ c = strchr (p, '\0');
+ continue;
}
+ char *fn = (char *) alloca (c - p + 1);
+ strncpy (fn, p, c - p);
+ fn[c - p] = '\0';
- if (reg_entry.nub_info.update_regs)
+ // A file name of "asl" is special and is another way to indicate
+ // that logging should be done via ASL, not by file.
+ if (strcmp (fn, "asl") == 0)
+ {
+ DNBLogToASL ();
+ }
+ else
{
- for (size_t i=0; reg_entry.nub_info.update_regs[i] != NULL; ++i)
+ FILE *f = fopen (fn, "w");
+ if (f)
{
- const char *name = reg_entry.nub_info.update_regs[i];
- auto pos = name_to_regnum.find(name);
- if (pos != name_to_regnum.end())
- {
- regnum = pos->second;
- reg_entry.invalidate_regnums.push_back(regnum);
- }
+ DNBLogSetLogFile (f);
+ DNBEnableLogging (f, DNBLogGetLogMask ());
+ DNBLogToFile ();
}
}
+ p = c + 1;
}
-
-
-// for (auto ®_entry: g_dynamic_register_map)
-// {
-// DNBLogThreaded("%4i: size = %3u, pseudo = %i, name = %s",
-// reg_entry.offset,
-// reg_entry.nub_info.size,
-// reg_entry.nub_info.value_regs != NULL,
-// reg_entry.nub_info.name);
-// }
-
- g_reg_entries = g_dynamic_register_map.data();
- g_num_reg_entries = g_dynamic_register_map.size();
+#endif /* #if 0 to enforce ASL logging only. */
+ else {
+ // Ignore unknown argument
+ const char *c = strchr(p, ';');
+ if (c)
+ p = c + 1;
+ else
+ p = strchr(p, '\0');
}
- return true;
-}
-
-/* The inferior has stopped executing; send a packet
- to gdb to let it know. */
+ }
-void
-RNBRemote::NotifyThatProcessStopped (void)
-{
- RNBRemote::HandlePacket_last_signal (NULL);
- return;
+ return rnb_success;
}
+rnb_err_t RNBRemote::HandlePacket_QThreadSuffixSupported(const char *p) {
+ m_thread_suffix_supported = true;
+ return SendPacket("OK");
+}
-/* 'A arglen,argnum,arg,...'
- Update the inferior context CTX with the program name and arg
- list.
- The documentation for this packet is underwhelming but my best reading
- of this is that it is a series of (len, position #, arg)'s, one for
- each argument with "arg" hex encoded (two 0-9a-f chars?).
- Why we need BOTH a "len" and a hex encoded "arg" is beyond me - either
- is sufficient to get around the "," position separator escape issue.
-
- e.g. our best guess for a valid 'A' packet for "gdb -q a.out" is
+rnb_err_t RNBRemote::HandlePacket_QStartNoAckMode(const char *p) {
+ // Send the OK packet first so the correct checksum is appended...
+ rnb_err_t result = SendPacket("OK");
+ m_noack_mode = true;
+ return result;
+}
- 6,0,676462,4,1,2d71,10,2,612e6f7574
+rnb_err_t RNBRemote::HandlePacket_QSetLogging(const char *p) {
+ p += sizeof("QSetLogging:") - 1;
+ rnb_err_t result = set_logging(p);
+ if (result == rnb_success)
+ return SendPacket("OK");
+ else
+ return SendPacket("E35");
+}
- Note that "argnum" and "arglen" are numbers in base 10. Again, that's
- not documented either way but I'm assuming it's so. */
+rnb_err_t RNBRemote::HandlePacket_QSetDisableASLR(const char *p) {
+ extern int g_disable_aslr;
+ p += sizeof("QSetDisableASLR:") - 1;
+ switch (*p) {
+ case '0':
+ g_disable_aslr = 0;
+ break;
+ case '1':
+ g_disable_aslr = 1;
+ break;
+ default:
+ return SendPacket("E56");
+ }
+ return SendPacket("OK");
+}
+
+rnb_err_t RNBRemote::HandlePacket_QSetSTDIO(const char *p) {
+ // Only set stdin/out/err if we don't already have a process
+ if (!m_ctx.HasValidProcessID()) {
+ bool success = false;
+ // Check the seventh character since the packet will be one of:
+ // QSetSTDIN
+ // QSetSTDOUT
+ // QSetSTDERR
+ StdStringExtractor packet(p);
+ packet.SetFilePos(7);
+ char ch = packet.GetChar();
+ while (packet.GetChar() != ':')
+ /* Do nothing. */;
+
+ switch (ch) {
+ case 'I': // STDIN
+ packet.GetHexByteString(m_ctx.GetSTDIN());
+ success = !m_ctx.GetSTDIN().empty();
+ break;
+
+ case 'O': // STDOUT
+ packet.GetHexByteString(m_ctx.GetSTDOUT());
+ success = !m_ctx.GetSTDOUT().empty();
+ break;
+
+ case 'E': // STDERR
+ packet.GetHexByteString(m_ctx.GetSTDERR());
+ success = !m_ctx.GetSTDERR().empty();
+ break;
-rnb_err_t
-RNBRemote::HandlePacket_A (const char *p)
-{
- if (p == NULL || *p == '\0')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Null packet for 'A' pkt");
+ default:
+ break;
}
- p++;
- if (*p == '\0' || !isdigit (*p))
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not specified on 'A' pkt");
- }
-
- /* I promise I don't modify it anywhere in this function. strtoul()'s
- 2nd arg has to be non-const which makes it problematic to step
- through the string easily. */
- char *buf = const_cast<char *>(p);
-
- RNBContext& ctx = Context();
-
- while (*buf != '\0')
- {
- unsigned long arglen, argnum;
- std::string arg;
- char *c;
-
- errno = 0;
- arglen = strtoul (buf, &c, 10);
- if (errno != 0 && arglen == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not a number on 'A' pkt");
- }
- if (*c != ',')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt");
- }
- buf = c + 1;
-
- errno = 0;
- argnum = strtoul (buf, &c, 10);
- if (errno != 0 && argnum == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "argnum not a number on 'A' pkt");
- }
- if (*c != ',')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt");
- }
- buf = c + 1;
-
- c = buf;
- buf = buf + arglen;
- while (c < buf && *c != '\0' && c + 1 < buf && *(c + 1) != '\0')
- {
- char smallbuf[3];
- smallbuf[0] = *c;
- smallbuf[1] = *(c + 1);
- smallbuf[2] = '\0';
-
- errno = 0;
- int ch = static_cast<int>(strtoul (smallbuf, NULL, 16));
- if (errno != 0 && ch == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'A' pkt");
- }
-
- arg.push_back(ch);
- c += 2;
- }
-
- ctx.PushArgument (arg.c_str());
- if (*buf == ',')
- buf++;
- }
- SendPacket ("OK");
-
- return rnb_success;
-}
-
-/* 'H c t'
- Set the thread for subsequent actions; 'c' for step/continue ops,
- 'g' for other ops. -1 means all threads, 0 means any thread. */
-
-rnb_err_t
-RNBRemote::HandlePacket_H (const char *p)
-{
- p++; // skip 'H'
- if (*p != 'c' && *p != 'g')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing 'c' or 'g' type in H packet");
- }
-
- if (!m_ctx.HasValidProcessID())
- {
- // We allow gdb to connect to a server that hasn't started running
- // the target yet. gdb still wants to ask questions about it and
- // freaks out if it gets an error. So just return OK here.
- }
-
- errno = 0;
- nub_thread_t tid = strtoul (p + 1, NULL, 16);
- if (errno != 0 && tid == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in H packet");
- }
- if (*p == 'c')
- SetContinueThread (tid);
- if (*p == 'g')
- SetCurrentThread (tid);
-
- return SendPacket ("OK");
-}
-
-
-rnb_err_t
-RNBRemote::HandlePacket_qLaunchSuccess (const char *p)
-{
- if (m_ctx.HasValidProcessID() || m_ctx.LaunchStatus().Error() == 0)
+ if (success)
+ return SendPacket("OK");
+ return SendPacket("E57");
+ }
+ return SendPacket("E58");
+}
+
+rnb_err_t RNBRemote::HandlePacket_QSetWorkingDir(const char *p) {
+ // Only set the working directory if we don't already have a process
+ if (!m_ctx.HasValidProcessID()) {
+ StdStringExtractor packet(p += sizeof("QSetWorkingDir:") - 1);
+ if (packet.GetHexByteString(m_ctx.GetWorkingDir())) {
+ struct stat working_dir_stat;
+ if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1) {
+ m_ctx.GetWorkingDir().clear();
+ return SendPacket("E61"); // Working directory doesn't exist...
+ } else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR) {
return SendPacket("OK");
- std::ostringstream ret_str;
- std::string status_str;
- ret_str << "E" << m_ctx.LaunchStatusAsString(status_str);
-
- return SendPacket (ret_str.str());
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qShlibInfoAddr (const char *p)
-{
- if (m_ctx.HasValidProcessID())
- {
- nub_addr_t shlib_info_addr = DNBProcessGetSharedLibraryInfoAddress(m_ctx.ProcessID());
- if (shlib_info_addr != INVALID_NUB_ADDRESS)
- {
- std::ostringstream ostrm;
- ostrm << RAW_HEXBASE << shlib_info_addr;
- return SendPacket (ostrm.str ());
- }
+ } else {
+ m_ctx.GetWorkingDir().clear();
+ return SendPacket("E62"); // Working directory isn't a directory...
+ }
}
- return SendPacket ("E44");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qStepPacketSupported (const char *p)
-{
- // Normally the "s" packet is mandatory, yet in gdb when using ARM, they
- // get around the need for this packet by implementing software single
- // stepping from gdb. Current versions of debugserver do support the "s"
- // packet, yet some older versions do not. We need a way to tell if this
- // packet is supported so we can disable software single stepping in gdb
- // for remote targets (so the "s" packet will get used).
- return SendPacket("OK");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qSyncThreadStateSupported (const char *p)
-{
- // We support attachOrWait meaning attach if the process exists, otherwise wait to attach.
- return SendPacket("OK");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qVAttachOrWaitSupported (const char *p)
-{
- // We support attachOrWait meaning attach if the process exists, otherwise wait to attach.
- return SendPacket("OK");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qThreadStopInfo (const char *p)
-{
- p += strlen ("qThreadStopInfo");
- nub_thread_t tid = strtoul(p, 0, 16);
- return SendStopReplyPacketForThread (tid);
+ return SendPacket("E59"); // Invalid path
+ }
+ return SendPacket(
+ "E60"); // Already had a process, too late to set working dir
}
-rnb_err_t
-RNBRemote::HandlePacket_qThreadInfo (const char *p)
-{
+rnb_err_t RNBRemote::HandlePacket_QSyncThreadState(const char *p) {
+ if (!m_ctx.HasValidProcessID()) {
// We allow gdb to connect to a server that hasn't started running
// the target yet. gdb still wants to ask questions about it and
// freaks out if it gets an error. So just return OK here.
- nub_process_t pid = m_ctx.ProcessID();
- if (pid == INVALID_NUB_PROCESS)
- return SendPacket ("OK");
+ return SendPacket("OK");
+ }
- // Only "qfThreadInfo" and "qsThreadInfo" get into this function so
- // we only need to check the second byte to tell which is which
- if (p[1] == 'f')
- {
- nub_size_t numthreads = DNBProcessGetNumThreads (pid);
- std::ostringstream ostrm;
- ostrm << "m";
- bool first = true;
- for (nub_size_t i = 0; i < numthreads; ++i)
- {
- if (first)
- first = false;
- else
- ostrm << ",";
- nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i);
- ostrm << std::hex << th;
- }
- return SendPacket (ostrm.str ());
- }
- else
- {
- return SendPacket ("l");
- }
+ errno = 0;
+ p += strlen("QSyncThreadState:");
+ nub_thread_t tid = strtoul(p, NULL, 16);
+ if (errno != 0 && tid == 0) {
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p,
+ "Invalid thread number in QSyncThreadState packet");
+ }
+ if (DNBProcessSyncThreadState(m_ctx.ProcessID(), tid))
+ return SendPacket("OK");
+ else
+ return SendPacket("E61");
}
-rnb_err_t
-RNBRemote::HandlePacket_qThreadExtraInfo (const char *p)
-{
- // We allow gdb to connect to a server that hasn't started running
- // the target yet. gdb still wants to ask questions about it and
- // freaks out if it gets an error. So just return OK here.
- nub_process_t pid = m_ctx.ProcessID();
- if (pid == INVALID_NUB_PROCESS)
- return SendPacket ("OK");
-
- /* This is supposed to return a string like 'Runnable' or
- 'Blocked on Mutex'.
- The returned string is formatted like the "A" packet - a
- sequence of letters encoded in as 2-hex-chars-per-letter. */
- p += strlen ("qThreadExtraInfo");
- if (*p++ != ',')
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Illformed qThreadExtraInfo packet");
+rnb_err_t RNBRemote::HandlePacket_QSetDetachOnError(const char *p) {
+ p += sizeof("QSetDetachOnError:") - 1;
+ bool should_detach = true;
+ switch (*p) {
+ case '0':
+ should_detach = false;
+ break;
+ case '1':
+ should_detach = true;
+ break;
+ default:
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p,
+ "Invalid value for QSetDetachOnError - should be 0 or 1");
+ break;
+ }
+
+ m_ctx.SetDetachOnError(should_detach);
+ return SendPacket("OK");
+}
+
+rnb_err_t RNBRemote::HandlePacket_qStructuredDataPlugins(const char *p) {
+ // We'll return a JSON array of supported packet types.
+ // The type is significant. For each of the supported
+ // packet types that have been enabled, there will be a
+ // 'J' async packet sent to the client with payload data.
+ // This payload data will be a JSON dictionary, and the
+ // top level dictionary will contain a string field with
+ // its value set to the relevant packet type from this list.
+ JSONGenerator::Array supported_json_packets;
+
+ // Check for DarwinLog (libtrace os_log/activity support).
+ if (DarwinLogCollector::IsSupported())
+ supported_json_packets.AddItem(
+ JSONGenerator::StringSP(new JSONGenerator::String("DarwinLog")));
+
+ // Send back the array.
+ std::ostringstream stream;
+ supported_json_packets.Dump(stream);
+ return SendPacket(stream.str());
+}
+
+rnb_err_t RNBRemote::HandlePacket_QConfigureDarwinLog(const char *p) {
+ if (!DarwinLogCollector::IsSupported()) {
+ // We should never have been given this request.
+ return SendPacket("E89");
+ }
+
+ // Ensure we have a process. We expect a separate configure request for
+ // each process launched/attached.
+ const nub_process_t pid = m_ctx.ProcessID();
+ if (pid == INVALID_NUB_PROCESS)
+ return SendPacket("E94");
+
+ // Get the configuration dictionary.
+ p += strlen("QConfigureDarwinLog:");
+
+ // The configuration dictionary is binary encoded.
+ std::vector<uint8_t> unescaped_config_data = decode_binary_data(p, -1);
+ std::string unescaped_config_string((const char *)&unescaped_config_data[0],
+ unescaped_config_data.size());
+ DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLog: received config data: \"%s\"",
+ unescaped_config_string.c_str());
+ auto configuration_sp =
+ JSONParser(unescaped_config_string.c_str()).ParseJSONValue();
+ if (!configuration_sp) {
+ // Malformed request - we require configuration data
+ // indicating whether we're enabling or disabling.
+ return SendPacket("E90");
+ }
+
+ if (!JSONObject::classof(configuration_sp.get())) {
+ // Configuration data is not of the right type.
+ return SendPacket("E91");
+ }
+ JSONObject &config_dict = *static_cast<JSONObject *>(configuration_sp.get());
+
+ // Check if we're enabling or disabling.
+ auto enabled_sp = config_dict.GetObject("enabled");
+ if (!enabled_sp) {
+ // Missing required "enabled" field.
+ return SendPacket("E92");
+ }
+ if (!JSONTrue::classof(enabled_sp.get()) &&
+ !JSONFalse::classof(enabled_sp.get())) {
+ // Should be a boolean type, but wasn't.
+ return SendPacket("E93");
+ }
+ const bool enabling = JSONTrue::classof(enabled_sp.get());
+
+ // TODO - handle other configuration parameters here.
+
+ // Shut down any active activity stream for the process.
+ DarwinLogCollector::CancelStreamForProcess(pid);
+
+ if (enabling) {
+ // Look up the procecess.
+ if (!DarwinLogCollector::StartCollectingForProcess(pid, config_dict))
+ return SendPacket("E95");
+ }
+
+ return SendPacket("OK");
+}
+
+rnb_err_t RNBRemote::HandlePacket_QListThreadsInStopReply(const char *p) {
+ // If this packet is received, it allows us to send an extra key/value
+ // pair in the stop reply packets where we will list all of the thread IDs
+ // separated by commas:
+ //
+ // "threads:10a,10b,10c;"
+ //
+ // This will get included in the stop reply packet as something like:
+ //
+ // "T11thread:10a;00:00000000;01:00010203:threads:10a,10b,10c;"
+ //
+ // This can save two packets on each stop: qfThreadInfo/qsThreadInfo and
+ // speed things up a bit.
+ //
+ // Send the OK packet first so the correct checksum is appended...
+ rnb_err_t result = SendPacket("OK");
+ m_list_threads_in_stop_reply = true;
+
+ return result;
+}
+
+rnb_err_t RNBRemote::HandlePacket_QSetMaxPayloadSize(const char *p) {
+ /* The number of characters in a packet payload that gdb is
+ prepared to accept. The packet-start char, packet-end char,
+ 2 checksum chars and terminating null character are not included
+ in this size. */
+ p += sizeof("QSetMaxPayloadSize:") - 1;
+ errno = 0;
+ uint32_t size = static_cast<uint32_t>(strtoul(p, NULL, 16));
+ if (errno != 0 && size == 0) {
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet");
+ }
+ m_max_payload_size = size;
+ return SendPacket("OK");
+}
+
+rnb_err_t RNBRemote::HandlePacket_QSetMaxPacketSize(const char *p) {
+ /* This tells us the largest packet that gdb can handle.
+ i.e. the size of gdb's packet-reading buffer.
+ QSetMaxPayloadSize is preferred because it is less ambiguous. */
+ p += sizeof("QSetMaxPacketSize:") - 1;
+ errno = 0;
+ uint32_t size = static_cast<uint32_t>(strtoul(p, NULL, 16));
+ if (errno != 0 && size == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid length in QSetMaxPacketSize packet");
+ }
+ m_max_payload_size = size - 5;
+ return SendPacket("OK");
+}
+
+rnb_err_t RNBRemote::HandlePacket_QEnvironment(const char *p) {
+ /* This sets the environment for the target program. The packet is of the
+ form:
+
+ QEnvironment:VARIABLE=VALUE
+
+ */
+
+ DNBLogThreadedIf(
+ LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
+
+ p += sizeof("QEnvironment:") - 1;
+ RNBContext &ctx = Context();
+
+ ctx.PushEnvironment(p);
+ return SendPacket("OK");
+}
+
+rnb_err_t RNBRemote::HandlePacket_QEnvironmentHexEncoded(const char *p) {
+ /* This sets the environment for the target program. The packet is of the
+ form:
+
+ QEnvironmentHexEncoded:VARIABLE=VALUE
+
+ The VARIABLE=VALUE part is sent hex-encoded so characters like '#' with
+ special
+ meaning in the remote protocol won't break it.
+ */
+
+ DNBLogThreadedIf(LOG_RNB_REMOTE,
+ "%8u RNBRemote::%s Handling QEnvironmentHexEncoded: \"%s\"",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
+ __FUNCTION__, p);
+
+ p += sizeof("QEnvironmentHexEncoded:") - 1;
+
+ std::string arg;
+ const char *c;
+ c = p;
+ while (*c != '\0') {
+ if (*(c + 1) == '\0') {
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p,
+ "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
+ }
+ char smallbuf[3];
+ smallbuf[0] = *c;
+ smallbuf[1] = *(c + 1);
+ smallbuf[2] = '\0';
errno = 0;
- nub_thread_t tid = strtoul (p, NULL, 16);
- if (errno != 0 && tid == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in qThreadExtraInfo packet");
- }
-
- const char * threadInfo = DNBThreadGetInfo(pid, tid);
- if (threadInfo != NULL && threadInfo[0])
- {
- return SendHexEncodedBytePacket(NULL, threadInfo, strlen(threadInfo), NULL);
- }
- else
- {
- // "OK" == 4f6b
- // Return "OK" as a ASCII hex byte stream if things go wrong
- return SendPacket ("4f6b");
- }
-
- return SendPacket ("");
-}
-
-
-const char *k_space_delimiters = " \t";
-static void
-skip_spaces (std::string &line)
-{
- if (!line.empty())
- {
- size_t space_pos = line.find_first_not_of (k_space_delimiters);
- if (space_pos > 0)
- line.erase(0, space_pos);
- }
-}
-
-static std::string
-get_identifier (std::string &line)
-{
- std::string word;
- skip_spaces (line);
- const size_t line_size = line.size();
- size_t end_pos;
- for (end_pos = 0; end_pos < line_size; ++end_pos)
- {
- if (end_pos == 0)
- {
- if (isalpha(line[end_pos]) || line[end_pos] == '_')
- continue;
- }
- else if (isalnum(line[end_pos]) || line[end_pos] == '_')
- continue;
- break;
- }
- word.assign (line, 0, end_pos);
- line.erase(0, end_pos);
- return word;
-}
-
-static std::string
-get_operator (std::string &line)
-{
- std::string op;
- skip_spaces (line);
- if (!line.empty())
- {
- if (line[0] == '=')
- {
- op = '=';
- line.erase(0,1);
- }
- }
- return op;
-}
-
-static std::string
-get_value (std::string &line)
-{
- std::string value;
- skip_spaces (line);
- if (!line.empty())
- {
- value.swap(line);
- }
- return value;
-}
-
-extern void FileLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
-extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
-
-rnb_err_t
-RNBRemote::HandlePacket_qRcmd (const char *p)
-{
- const char *c = p + strlen("qRcmd,");
- std::string line;
- while (c[0] && c[1])
- {
- char smallbuf[3] = { c[0], c[1], '\0' };
- errno = 0;
- int ch = static_cast<int>(strtoul (smallbuf, NULL, 16));
- if (errno != 0 && ch == 0)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in payload of qRcmd packet");
- line.push_back(ch);
- c += 2;
- }
- if (*c == '\0')
- {
- std::string command = get_identifier(line);
- if (command.compare("set") == 0)
- {
- std::string variable = get_identifier (line);
- std::string op = get_operator (line);
- std::string value = get_value (line);
- if (variable.compare("logfile") == 0)
- {
- FILE *log_file = fopen(value.c_str(), "w");
- if (log_file)
- {
- DNBLogSetLogCallback(FileLogCallback, log_file);
- return SendPacket ("OK");
- }
- return SendPacket ("E71");
- }
- else if (variable.compare("logmask") == 0)
- {
- char *end;
- errno = 0;
- uint32_t logmask = static_cast<uint32_t>(strtoul (value.c_str(), &end, 0));
- if (errno == 0 && end && *end == '\0')
- {
- DNBLogSetLogMask (logmask);
- if (!DNBLogGetLogCallback())
- DNBLogSetLogCallback(ASLLogCallback, NULL);
- return SendPacket ("OK");
- }
- errno = 0;
- logmask = static_cast<uint32_t>(strtoul (value.c_str(), &end, 16));
- if (errno == 0 && end && *end == '\0')
- {
- DNBLogSetLogMask (logmask);
- return SendPacket ("OK");
- }
- return SendPacket ("E72");
- }
- return SendPacket ("E70");
- }
- return SendPacket ("E69");
- }
- return SendPacket ("E73");
+ int ch = static_cast<int>(strtoul(smallbuf, NULL, 16));
+ if (errno != 0 && ch == 0) {
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p,
+ "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
+ }
+ arg.push_back(ch);
+ c += 2;
+ }
+
+ RNBContext &ctx = Context();
+ if (arg.length() > 0)
+ ctx.PushEnvironment(arg.c_str());
+
+ return SendPacket("OK");
+}
+
+rnb_err_t RNBRemote::HandlePacket_QLaunchArch(const char *p) {
+ p += sizeof("QLaunchArch:") - 1;
+ if (DNBSetArchitecture(p))
+ return SendPacket("OK");
+ return SendPacket("E63");
}
-rnb_err_t
-RNBRemote::HandlePacket_qC (const char *p)
-{
- nub_thread_t tid;
- std::ostringstream rep;
- // If we haven't run the process yet, we tell the debugger the
- // pid is 0. That way it can know to tell use to run later on.
- if (!m_ctx.HasValidProcessID())
- tid = 0;
+rnb_err_t RNBRemote::HandlePacket_QSetProcessEvent(const char *p) {
+ p += sizeof("QSetProcessEvent:") - 1;
+ // If the process is running, then send the event to the process, otherwise
+ // store it in the context.
+ if (Context().HasValidProcessID()) {
+ if (DNBProcessSendEvent(Context().ProcessID(), p))
+ return SendPacket("OK");
else
- {
- // Grab the current thread.
- tid = DNBProcessGetCurrentThread (m_ctx.ProcessID());
- // Make sure we set the current thread so g and p packets return
- // the data the gdb will expect.
- SetCurrentThread (tid);
+ return SendPacket("E80");
+ } else {
+ Context().PushProcessEvent(p);
+ }
+ return SendPacket("OK");
+}
+
+void append_hex_value(std::ostream &ostrm, const void *buf, size_t buf_size,
+ bool swap) {
+ int i;
+ const uint8_t *p = (const uint8_t *)buf;
+ if (swap) {
+ for (i = static_cast<int>(buf_size) - 1; i >= 0; i--)
+ ostrm << RAWHEX8(p[i]);
+ } else {
+ for (size_t i = 0; i < buf_size; i++)
+ ostrm << RAWHEX8(p[i]);
+ }
+}
+
+void append_hexified_string(std::ostream &ostrm, const std::string &string) {
+ size_t string_size = string.size();
+ const char *string_buf = string.c_str();
+ for (size_t i = 0; i < string_size; i++) {
+ ostrm << RAWHEX8(*(string_buf + i));
+ }
+}
+
+void register_value_in_hex_fixed_width(std::ostream &ostrm, nub_process_t pid,
+ nub_thread_t tid,
+ const register_map_entry_t *reg,
+ const DNBRegisterValue *reg_value_ptr) {
+ if (reg != NULL) {
+ DNBRegisterValue reg_value;
+ if (reg_value_ptr == NULL) {
+ if (DNBThreadGetRegisterValueByID(pid, tid, reg->nub_info.set,
+ reg->nub_info.reg, ®_value))
+ reg_value_ptr = ®_value;
+ }
+
+ if (reg_value_ptr) {
+ append_hex_value(ostrm, reg_value_ptr->value.v_uint8, reg->nub_info.size,
+ false);
+ } else {
+ // If we fail to read a register value, check if it has a default
+ // fail value. If it does, return this instead in case some of
+ // the registers are not available on the current system.
+ if (reg->nub_info.size > 0) {
+ std::basic_string<uint8_t> zeros(reg->nub_info.size, '\0');
+ append_hex_value(ostrm, zeros.data(), zeros.size(), false);
+ }
}
- rep << "QC" << std::hex << tid;
- return SendPacket (rep.str());
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qEcho (const char *p)
-{
- // Just send the exact same packet back that we received to
- // synchronize the response packets after a previous packet
- // timed out. This allows the debugger to get back on track
- // with responses after a packet timeout.
- return SendPacket (p);
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qGetPid (const char *p)
-{
- nub_process_t pid;
- std::ostringstream rep;
- // If we haven't run the process yet, we tell the debugger the
- // pid is 0. That way it can know to tell use to run later on.
- if (m_ctx.HasValidProcessID())
- pid = m_ctx.ProcessID();
- else
- pid = 0;
- rep << std::hex << pid;
- return SendPacket (rep.str());
+ }
}
-rnb_err_t
-RNBRemote::HandlePacket_qRegisterInfo (const char *p)
-{
- if (g_num_reg_entries == 0)
- InitializeRegisters ();
-
- p += strlen ("qRegisterInfo");
-
- nub_size_t num_reg_sets = 0;
- const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo (&num_reg_sets);
- uint32_t reg_num = static_cast<uint32_t>(strtoul(p, 0, 16));
-
- if (reg_num < g_num_reg_entries)
- {
- const register_map_entry_t *reg_entry = &g_reg_entries[reg_num];
- std::ostringstream ostrm;
- if (reg_entry->nub_info.name)
- ostrm << "name:" << reg_entry->nub_info.name << ';';
- if (reg_entry->nub_info.alt)
- ostrm << "alt-name:" << reg_entry->nub_info.alt << ';';
-
- ostrm << "bitsize:" << std::dec << reg_entry->nub_info.size * 8 << ';';
- ostrm << "offset:" << std::dec << reg_entry->offset << ';';
-
- switch (reg_entry->nub_info.type)
- {
- case Uint: ostrm << "encoding:uint;"; break;
- case Sint: ostrm << "encoding:sint;"; break;
- case IEEE754: ostrm << "encoding:ieee754;"; break;
- case Vector: ostrm << "encoding:vector;"; break;
- }
-
- switch (reg_entry->nub_info.format)
- {
- case Binary: ostrm << "format:binary;"; break;
- case Decimal: ostrm << "format:decimal;"; break;
- case Hex: ostrm << "format:hex;"; break;
- case Float: ostrm << "format:float;"; break;
- case VectorOfSInt8: ostrm << "format:vector-sint8;"; break;
- case VectorOfUInt8: ostrm << "format:vector-uint8;"; break;
- case VectorOfSInt16: ostrm << "format:vector-sint16;"; break;
- case VectorOfUInt16: ostrm << "format:vector-uint16;"; break;
- case VectorOfSInt32: ostrm << "format:vector-sint32;"; break;
- case VectorOfUInt32: ostrm << "format:vector-uint32;"; break;
- case VectorOfFloat32: ostrm << "format:vector-float32;"; break;
- case VectorOfUInt128: ostrm << "format:vector-uint128;"; break;
- };
-
- if (reg_set_info && reg_entry->nub_info.set < num_reg_sets)
- ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';';
-
- if (reg_entry->nub_info.reg_ehframe != INVALID_NUB_REGNUM)
- ostrm << "ehframe:" << std::dec << reg_entry->nub_info.reg_ehframe << ';';
-
- if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM)
- ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';';
-
- switch (reg_entry->nub_info.reg_generic)
- {
- case GENERIC_REGNUM_FP: ostrm << "generic:fp;"; break;
- case GENERIC_REGNUM_PC: ostrm << "generic:pc;"; break;
- case GENERIC_REGNUM_SP: ostrm << "generic:sp;"; break;
- case GENERIC_REGNUM_RA: ostrm << "generic:ra;"; break;
- case GENERIC_REGNUM_FLAGS: ostrm << "generic:flags;"; break;
- case GENERIC_REGNUM_ARG1: ostrm << "generic:arg1;"; break;
- case GENERIC_REGNUM_ARG2: ostrm << "generic:arg2;"; break;
- case GENERIC_REGNUM_ARG3: ostrm << "generic:arg3;"; break;
- case GENERIC_REGNUM_ARG4: ostrm << "generic:arg4;"; break;
- case GENERIC_REGNUM_ARG5: ostrm << "generic:arg5;"; break;
- case GENERIC_REGNUM_ARG6: ostrm << "generic:arg6;"; break;
- case GENERIC_REGNUM_ARG7: ostrm << "generic:arg7;"; break;
- case GENERIC_REGNUM_ARG8: ostrm << "generic:arg8;"; break;
- default: break;
- }
-
- if (!reg_entry->value_regnums.empty())
- {
- ostrm << "container-regs:";
- for (size_t i=0, n=reg_entry->value_regnums.size(); i < n; ++i)
- {
- if (i > 0)
- ostrm << ',';
- ostrm << RAW_HEXBASE << reg_entry->value_regnums[i];
- }
- ostrm << ';';
- }
-
- if (!reg_entry->invalidate_regnums.empty())
- {
- ostrm << "invalidate-regs:";
- for (size_t i=0, n=reg_entry->invalidate_regnums.size(); i < n; ++i)
- {
- if (i > 0)
- ostrm << ',';
- ostrm << RAW_HEXBASE << reg_entry->invalidate_regnums[i];
- }
- ostrm << ';';
- }
-
- return SendPacket (ostrm.str ());
+void debugserver_regnum_with_fixed_width_hex_register_value(
+ std::ostream &ostrm, nub_process_t pid, nub_thread_t tid,
+ const register_map_entry_t *reg, const DNBRegisterValue *reg_value_ptr) {
+ // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX
+ // gdb register number, and VVVVVVVV is the correct number of hex bytes
+ // as ASCII for the register value.
+ if (reg != NULL) {
+ ostrm << RAWHEX8(reg->debugserver_regnum) << ':';
+ register_value_in_hex_fixed_width(ostrm, pid, tid, reg, reg_value_ptr);
+ ostrm << ';';
+ }
+}
+
+void RNBRemote::DispatchQueueOffsets::GetThreadQueueInfo(
+ nub_process_t pid, nub_addr_t dispatch_qaddr, nub_addr_t &dispatch_queue_t,
+ std::string &queue_name, uint64_t &queue_width,
+ uint64_t &queue_serialnum) const {
+ queue_name.clear();
+ queue_width = 0;
+ queue_serialnum = 0;
+
+ if (IsValid() && dispatch_qaddr != INVALID_NUB_ADDRESS &&
+ dispatch_qaddr != 0) {
+ dispatch_queue_t = DNBProcessMemoryReadPointer(pid, dispatch_qaddr);
+ if (dispatch_queue_t) {
+ queue_width = DNBProcessMemoryReadInteger(
+ pid, dispatch_queue_t + dqo_width, dqo_width_size, 0);
+ queue_serialnum = DNBProcessMemoryReadInteger(
+ pid, dispatch_queue_t + dqo_serialnum, dqo_serialnum_size, 0);
+
+ if (dqo_version >= 4) {
+ // libdispatch versions 4+, pointer to dispatch name is in the
+ // queue structure.
+ nub_addr_t pointer_to_label_address = dispatch_queue_t + dqo_label;
+ nub_addr_t label_addr =
+ DNBProcessMemoryReadPointer(pid, pointer_to_label_address);
+ if (label_addr)
+ queue_name = DNBProcessMemoryReadCString(pid, label_addr);
+ } else {
+ // libdispatch versions 1-3, dispatch name is a fixed width char array
+ // in the queue structure.
+ queue_name = DNBProcessMemoryReadCStringFixed(
+ pid, dispatch_queue_t + dqo_label, dqo_label_size);
+ }
}
- return SendPacket ("E45");
+ }
}
+struct StackMemory {
+ uint8_t bytes[2 * sizeof(nub_addr_t)];
+ nub_size_t length;
+};
+typedef std::map<nub_addr_t, StackMemory> StackMemoryMap;
-/* This expects a packet formatted like
-
- QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE;
-
- with the "QSetLogging:" already removed from the start. Maybe in the
- future this packet will include other keyvalue pairs like
-
- QSetLogging:bitmask=LOG_ALL;mode=asl;
- */
-
-rnb_err_t
-set_logging (const char *p)
-{
- int bitmask = 0;
- while (p && *p != '\0')
- {
- if (strncmp (p, "bitmask=", sizeof ("bitmask=") - 1) == 0)
- {
- p += sizeof ("bitmask=") - 1;
- while (p && *p != '\0' && *p != ';')
- {
- if (*p == '|')
- p++;
-
-// to regenerate the LOG_ entries (not including the LOG_RNB entries)
-// $ for logname in `grep '^#define LOG_' DNBDefs.h | egrep -v 'LOG_HI|LOG_LO' | awk '{print $2}'`
-// do
-// echo " else if (strncmp (p, \"$logname\", sizeof (\"$logname\") - 1) == 0)"
-// echo " {"
-// echo " p += sizeof (\"$logname\") - 1;"
-// echo " bitmask |= $logname;"
-// echo " }"
-// done
- if (strncmp (p, "LOG_VERBOSE", sizeof ("LOG_VERBOSE") - 1) == 0)
- {
- p += sizeof ("LOG_VERBOSE") - 1;
- bitmask |= LOG_VERBOSE;
- }
- else if (strncmp (p, "LOG_PROCESS", sizeof ("LOG_PROCESS") - 1) == 0)
- {
- p += sizeof ("LOG_PROCESS") - 1;
- bitmask |= LOG_PROCESS;
- }
- else if (strncmp (p, "LOG_THREAD", sizeof ("LOG_THREAD") - 1) == 0)
- {
- p += sizeof ("LOG_THREAD") - 1;
- bitmask |= LOG_THREAD;
- }
- else if (strncmp (p, "LOG_EXCEPTIONS", sizeof ("LOG_EXCEPTIONS") - 1) == 0)
- {
- p += sizeof ("LOG_EXCEPTIONS") - 1;
- bitmask |= LOG_EXCEPTIONS;
- }
- else if (strncmp (p, "LOG_SHLIB", sizeof ("LOG_SHLIB") - 1) == 0)
- {
- p += sizeof ("LOG_SHLIB") - 1;
- bitmask |= LOG_SHLIB;
- }
- else if (strncmp (p, "LOG_MEMORY", sizeof ("LOG_MEMORY") - 1) == 0)
- {
- p += sizeof ("LOG_MEMORY") - 1;
- bitmask |= LOG_MEMORY;
- }
- else if (strncmp (p, "LOG_MEMORY_DATA_SHORT", sizeof ("LOG_MEMORY_DATA_SHORT") - 1) == 0)
- {
- p += sizeof ("LOG_MEMORY_DATA_SHORT") - 1;
- bitmask |= LOG_MEMORY_DATA_SHORT;
- }
- else if (strncmp (p, "LOG_MEMORY_DATA_LONG", sizeof ("LOG_MEMORY_DATA_LONG") - 1) == 0)
- {
- p += sizeof ("LOG_MEMORY_DATA_LONG") - 1;
- bitmask |= LOG_MEMORY_DATA_LONG;
- }
- else if (strncmp (p, "LOG_MEMORY_PROTECTIONS", sizeof ("LOG_MEMORY_PROTECTIONS") - 1) == 0)
- {
- p += sizeof ("LOG_MEMORY_PROTECTIONS") - 1;
- bitmask |= LOG_MEMORY_PROTECTIONS;
- }
- else if (strncmp (p, "LOG_BREAKPOINTS", sizeof ("LOG_BREAKPOINTS") - 1) == 0)
- {
- p += sizeof ("LOG_BREAKPOINTS") - 1;
- bitmask |= LOG_BREAKPOINTS;
- }
- else if (strncmp (p, "LOG_EVENTS", sizeof ("LOG_EVENTS") - 1) == 0)
- {
- p += sizeof ("LOG_EVENTS") - 1;
- bitmask |= LOG_EVENTS;
- }
- else if (strncmp (p, "LOG_WATCHPOINTS", sizeof ("LOG_WATCHPOINTS") - 1) == 0)
- {
- p += sizeof ("LOG_WATCHPOINTS") - 1;
- bitmask |= LOG_WATCHPOINTS;
- }
- else if (strncmp (p, "LOG_STEP", sizeof ("LOG_STEP") - 1) == 0)
- {
- p += sizeof ("LOG_STEP") - 1;
- bitmask |= LOG_STEP;
- }
- else if (strncmp (p, "LOG_TASK", sizeof ("LOG_TASK") - 1) == 0)
- {
- p += sizeof ("LOG_TASK") - 1;
- bitmask |= LOG_TASK;
- }
- else if (strncmp (p, "LOG_ALL", sizeof ("LOG_ALL") - 1) == 0)
- {
- p += sizeof ("LOG_ALL") - 1;
- bitmask |= LOG_ALL;
- }
- else if (strncmp (p, "LOG_DEFAULT", sizeof ("LOG_DEFAULT") - 1) == 0)
- {
- p += sizeof ("LOG_DEFAULT") - 1;
- bitmask |= LOG_DEFAULT;
- }
-// end of auto-generated entries
+static void ReadStackMemory(nub_process_t pid, nub_thread_t tid,
+ StackMemoryMap &stack_mmap,
+ uint32_t backtrace_limit = 256) {
+ DNBRegisterValue reg_value;
+ if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC,
+ GENERIC_REGNUM_FP, ®_value)) {
+ uint32_t frame_count = 0;
+ uint64_t fp = 0;
+ if (reg_value.info.size == 4)
+ fp = reg_value.value.uint32;
+ else
+ fp = reg_value.value.uint64;
+ while (fp != 0) {
+ // Make sure we never recurse more than 256 times so we don't recurse too
+ // far or
+ // store up too much memory in the expedited cache
+ if (++frame_count > backtrace_limit)
+ break;
- else if (strncmp (p, "LOG_NONE", sizeof ("LOG_NONE") - 1) == 0)
- {
- p += sizeof ("LOG_NONE") - 1;
- bitmask = 0;
- }
- else if (strncmp (p, "LOG_RNB_MINIMAL", sizeof ("LOG_RNB_MINIMAL") - 1) == 0)
- {
- p += sizeof ("LOG_RNB_MINIMAL") - 1;
- bitmask |= LOG_RNB_MINIMAL;
- }
- else if (strncmp (p, "LOG_RNB_MEDIUM", sizeof ("LOG_RNB_MEDIUM") - 1) == 0)
- {
- p += sizeof ("LOG_RNB_MEDIUM") - 1;
- bitmask |= LOG_RNB_MEDIUM;
- }
- else if (strncmp (p, "LOG_RNB_MAX", sizeof ("LOG_RNB_MAX") - 1) == 0)
- {
- p += sizeof ("LOG_RNB_MAX") - 1;
- bitmask |= LOG_RNB_MAX;
- }
- else if (strncmp (p, "LOG_RNB_COMM", sizeof ("LOG_RNB_COMM") - 1) == 0)
- {
- p += sizeof ("LOG_RNB_COMM") - 1;
- bitmask |= LOG_RNB_COMM;
- }
- else if (strncmp (p, "LOG_RNB_REMOTE", sizeof ("LOG_RNB_REMOTE") - 1) == 0)
- {
- p += sizeof ("LOG_RNB_REMOTE") - 1;
- bitmask |= LOG_RNB_REMOTE;
- }
- else if (strncmp (p, "LOG_RNB_EVENTS", sizeof ("LOG_RNB_EVENTS") - 1) == 0)
- {
- p += sizeof ("LOG_RNB_EVENTS") - 1;
- bitmask |= LOG_RNB_EVENTS;
- }
- else if (strncmp (p, "LOG_RNB_PROC", sizeof ("LOG_RNB_PROC") - 1) == 0)
- {
- p += sizeof ("LOG_RNB_PROC") - 1;
- bitmask |= LOG_RNB_PROC;
- }
- else if (strncmp (p, "LOG_RNB_PACKETS", sizeof ("LOG_RNB_PACKETS") - 1) == 0)
- {
- p += sizeof ("LOG_RNB_PACKETS") - 1;
- bitmask |= LOG_RNB_PACKETS;
- }
- else if (strncmp (p, "LOG_RNB_ALL", sizeof ("LOG_RNB_ALL") - 1) == 0)
- {
- p += sizeof ("LOG_RNB_ALL") - 1;
- bitmask |= LOG_RNB_ALL;
- }
- else if (strncmp (p, "LOG_RNB_DEFAULT", sizeof ("LOG_RNB_DEFAULT") - 1) == 0)
- {
- p += sizeof ("LOG_RNB_DEFAULT") - 1;
- bitmask |= LOG_RNB_DEFAULT;
- }
- else if (strncmp (p, "LOG_DARWIN_LOG", sizeof ("LOG_DARWIN_LOG") - 1) == 0)
- {
- p += sizeof ("LOG_DARWIN_LOG") - 1;
- bitmask |= LOG_DARWIN_LOG;
- }
- else if (strncmp (p, "LOG_RNB_NONE", sizeof ("LOG_RNB_NONE") - 1) == 0)
- {
- p += sizeof ("LOG_RNB_NONE") - 1;
- bitmask = 0;
- }
- else
- {
- /* Unrecognized logging bit; ignore it. */
- const char *c = strchr (p, '|');
- if (c)
- {
- p = c;
- }
- else
- {
- c = strchr (p, ';');
- if (c)
- {
- p = c;
- }
- else
- {
- // Improperly terminated word; just go to end of str
- p = strchr (p, '\0');
- }
- }
- }
- }
- // Did we get a properly formatted logging bitmask?
- if (p && *p == ';')
- {
- // Enable DNB logging.
- // Use the existing log callback if one was already configured.
- if (!DNBLogGetLogCallback())
- {
- // Use the os_log()-based logger if available; otherwise,
- // fallback to ASL.
- auto log_callback = OsLogger::GetLogFunction();
- if (log_callback)
- DNBLogSetLogCallback(log_callback, nullptr);
- else
- DNBLogSetLogCallback(ASLLogCallback, nullptr);
- }
-
- // Update logging to use the configured log channel bitmask.
- DNBLogSetLogMask (bitmask);
- p++;
- }
- }
- // We're not going to support logging to a file for now. All logging
- // goes through ASL or the previously arranged log callback.
-#if 0
- else if (strncmp (p, "mode=", sizeof ("mode=") - 1) == 0)
- {
- p += sizeof ("mode=") - 1;
- if (strncmp (p, "asl;", sizeof ("asl;") - 1) == 0)
- {
- DNBLogToASL ();
- p += sizeof ("asl;") - 1;
- }
- else if (strncmp (p, "file;", sizeof ("file;") - 1) == 0)
- {
- DNBLogToFile ();
- p += sizeof ("file;") - 1;
- }
- else
- {
- // Ignore unknown argument
- const char *c = strchr (p, ';');
- if (c)
- p = c + 1;
- else
- p = strchr (p, '\0');
- }
- }
- else if (strncmp (p, "filename=", sizeof ("filename=") - 1) == 0)
- {
- p += sizeof ("filename=") - 1;
- const char *c = strchr (p, ';');
- if (c == NULL)
- {
- c = strchr (p, '\0');
- continue;
- }
- char *fn = (char *) alloca (c - p + 1);
- strncpy (fn, p, c - p);
- fn[c - p] = '\0';
-
- // A file name of "asl" is special and is another way to indicate
- // that logging should be done via ASL, not by file.
- if (strcmp (fn, "asl") == 0)
- {
- DNBLogToASL ();
- }
- else
- {
- FILE *f = fopen (fn, "w");
- if (f)
- {
- DNBLogSetLogFile (f);
- DNBEnableLogging (f, DNBLogGetLogMask ());
- DNBLogToFile ();
- }
- }
- p = c + 1;
- }
-#endif /* #if 0 to enforce ASL logging only. */
- else
- {
- // Ignore unknown argument
- const char *c = strchr (p, ';');
- if (c)
- p = c + 1;
- else
- p = strchr (p, '\0');
- }
- }
-
- return rnb_success;
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QThreadSuffixSupported (const char *p)
-{
- m_thread_suffix_supported = true;
- return SendPacket ("OK");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QStartNoAckMode (const char *p)
-{
- // Send the OK packet first so the correct checksum is appended...
- rnb_err_t result = SendPacket ("OK");
- m_noack_mode = true;
- return result;
-}
-
-
-rnb_err_t
-RNBRemote::HandlePacket_QSetLogging (const char *p)
-{
- p += sizeof ("QSetLogging:") - 1;
- rnb_err_t result = set_logging (p);
- if (result == rnb_success)
- return SendPacket ("OK");
- else
- return SendPacket ("E35");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QSetDisableASLR (const char *p)
-{
- extern int g_disable_aslr;
- p += sizeof ("QSetDisableASLR:") - 1;
- switch (*p)
- {
- case '0': g_disable_aslr = 0; break;
- case '1': g_disable_aslr = 1; break;
- default:
- return SendPacket ("E56");
- }
- return SendPacket ("OK");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QSetSTDIO (const char *p)
-{
- // Only set stdin/out/err if we don't already have a process
- if (!m_ctx.HasValidProcessID())
- {
- bool success = false;
- // Check the seventh character since the packet will be one of:
- // QSetSTDIN
- // QSetSTDOUT
- // QSetSTDERR
- StdStringExtractor packet(p);
- packet.SetFilePos (7);
- char ch = packet.GetChar();
- while (packet.GetChar() != ':')
- /* Do nothing. */;
-
- switch (ch)
- {
- case 'I': // STDIN
- packet.GetHexByteString (m_ctx.GetSTDIN());
- success = !m_ctx.GetSTDIN().empty();
- break;
-
- case 'O': // STDOUT
- packet.GetHexByteString (m_ctx.GetSTDOUT());
- success = !m_ctx.GetSTDOUT().empty();
- break;
-
- case 'E': // STDERR
- packet.GetHexByteString (m_ctx.GetSTDERR());
- success = !m_ctx.GetSTDERR().empty();
- break;
-
- default:
- break;
- }
- if (success)
- return SendPacket ("OK");
- return SendPacket ("E57");
- }
- return SendPacket ("E58");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QSetWorkingDir (const char *p)
-{
- // Only set the working directory if we don't already have a process
- if (!m_ctx.HasValidProcessID())
- {
- StdStringExtractor packet(p += sizeof ("QSetWorkingDir:") - 1);
- if (packet.GetHexByteString (m_ctx.GetWorkingDir()))
- {
- struct stat working_dir_stat;
- if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1)
- {
- m_ctx.GetWorkingDir().clear();
- return SendPacket ("E61"); // Working directory doesn't exist...
- }
- else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR)
- {
- return SendPacket ("OK");
- }
- else
- {
- m_ctx.GetWorkingDir().clear();
- return SendPacket ("E62"); // Working directory isn't a directory...
- }
- }
- return SendPacket ("E59"); // Invalid path
- }
- return SendPacket ("E60"); // Already had a process, too late to set working dir
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QSyncThreadState (const char *p)
-{
- if (!m_ctx.HasValidProcessID())
- {
- // We allow gdb to connect to a server that hasn't started running
- // the target yet. gdb still wants to ask questions about it and
- // freaks out if it gets an error. So just return OK here.
- return SendPacket ("OK");
- }
-
- errno = 0;
- p += strlen("QSyncThreadState:");
- nub_thread_t tid = strtoul (p, NULL, 16);
- if (errno != 0 && tid == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in QSyncThreadState packet");
- }
- if (DNBProcessSyncThreadState(m_ctx.ProcessID(), tid))
- return SendPacket("OK");
- else
- return SendPacket ("E61");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QSetDetachOnError (const char *p)
-{
- p += sizeof ("QSetDetachOnError:") - 1;
- bool should_detach = true;
- switch (*p)
- {
- case '0': should_detach = false; break;
- case '1': should_detach = true; break;
- default:
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid value for QSetDetachOnError - should be 0 or 1");
- break;
- }
-
- m_ctx.SetDetachOnError(should_detach);
- return SendPacket ("OK");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qStructuredDataPlugins(const char *p)
-{
- // We'll return a JSON array of supported packet types.
- // The type is significant. For each of the supported
- // packet types that have been enabled, there will be a
- // 'J' async packet sent to the client with payload data.
- // This payload data will be a JSON dictionary, and the
- // top level dictionary will contain a string field with
- // its value set to the relevant packet type from this list.
- JSONGenerator::Array supported_json_packets;
-
- // Check for DarwinLog (libtrace os_log/activity support).
- if (DarwinLogCollector::IsSupported())
- supported_json_packets.AddItem(JSONGenerator::StringSP(
- new JSONGenerator::String("DarwinLog")));
-
- // Send back the array.
- std::ostringstream stream;
- supported_json_packets.Dump(stream);
- return SendPacket(stream.str());
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QConfigureDarwinLog(const char *p)
-{
- if (!DarwinLogCollector::IsSupported())
- {
- // We should never have been given this request.
- return SendPacket ("E89");
- }
-
- // Ensure we have a process. We expect a separate configure request for
- // each process launched/attached.
- const nub_process_t pid = m_ctx.ProcessID();
- if (pid == INVALID_NUB_PROCESS)
- return SendPacket ("E94");
-
- // Get the configuration dictionary.
- p += strlen("QConfigureDarwinLog:");
-
- // The configuration dictionary is binary encoded.
- std::vector<uint8_t> unescaped_config_data = decode_binary_data(p, -1);
- std::string unescaped_config_string((const char*)&unescaped_config_data[0],
- unescaped_config_data.size());
- DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLog: received config data: \"%s\"",
- unescaped_config_string.c_str());
- auto configuration_sp =
- JSONParser(unescaped_config_string.c_str()).ParseJSONValue();
- if (!configuration_sp)
- {
- // Malformed request - we require configuration data
- // indicating whether we're enabling or disabling.
- return SendPacket("E90");
- }
-
- if (!JSONObject::classof(configuration_sp.get()))
- {
- // Configuration data is not of the right type.
- return SendPacket("E91");
- }
- JSONObject &config_dict = *static_cast<JSONObject*>(configuration_sp.get());
-
- // Check if we're enabling or disabling.
- auto enabled_sp = config_dict.GetObject("enabled");
- if (!enabled_sp)
- {
- // Missing required "enabled" field.
- return SendPacket("E92");
- }
- if (!JSONTrue::classof(enabled_sp.get()) &&
- !JSONFalse::classof(enabled_sp.get()))
- {
- // Should be a boolean type, but wasn't.
- return SendPacket("E93");
- }
- const bool enabling = JSONTrue::classof(enabled_sp.get());
-
- // TODO - handle other configuration parameters here.
-
- // Shut down any active activity stream for the process.
- DarwinLogCollector::CancelStreamForProcess(pid);
-
- if (enabling)
- {
- // Look up the procecess.
- if (!DarwinLogCollector::StartCollectingForProcess(pid, config_dict))
- return SendPacket("E95");
- }
-
- return SendPacket("OK");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QListThreadsInStopReply (const char *p)
-{
- // If this packet is received, it allows us to send an extra key/value
- // pair in the stop reply packets where we will list all of the thread IDs
- // separated by commas:
- //
- // "threads:10a,10b,10c;"
- //
- // This will get included in the stop reply packet as something like:
- //
- // "T11thread:10a;00:00000000;01:00010203:threads:10a,10b,10c;"
- //
- // This can save two packets on each stop: qfThreadInfo/qsThreadInfo and
- // speed things up a bit.
- //
- // Send the OK packet first so the correct checksum is appended...
- rnb_err_t result = SendPacket ("OK");
- m_list_threads_in_stop_reply = true;
-
- return result;
-}
-
-
-rnb_err_t
-RNBRemote::HandlePacket_QSetMaxPayloadSize (const char *p)
-{
- /* The number of characters in a packet payload that gdb is
- prepared to accept. The packet-start char, packet-end char,
- 2 checksum chars and terminating null character are not included
- in this size. */
- p += sizeof ("QSetMaxPayloadSize:") - 1;
- errno = 0;
- uint32_t size = static_cast<uint32_t>(strtoul (p, NULL, 16));
- if (errno != 0 && size == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet");
- }
- m_max_payload_size = size;
- return SendPacket ("OK");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QSetMaxPacketSize (const char *p)
-{
- /* This tells us the largest packet that gdb can handle.
- i.e. the size of gdb's packet-reading buffer.
- QSetMaxPayloadSize is preferred because it is less ambiguous. */
- p += sizeof ("QSetMaxPacketSize:") - 1;
- errno = 0;
- uint32_t size = static_cast<uint32_t>(strtoul (p, NULL, 16));
- if (errno != 0 && size == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPacketSize packet");
- }
- m_max_payload_size = size - 5;
- return SendPacket ("OK");
-}
-
-
-
-
-rnb_err_t
-RNBRemote::HandlePacket_QEnvironment (const char *p)
-{
- /* This sets the environment for the target program. The packet is of the form:
-
- QEnvironment:VARIABLE=VALUE
-
- */
-
- DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"",
- (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
-
- p += sizeof ("QEnvironment:") - 1;
- RNBContext& ctx = Context();
-
- ctx.PushEnvironment (p);
- return SendPacket ("OK");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QEnvironmentHexEncoded (const char *p)
-{
- /* This sets the environment for the target program. The packet is of the form:
-
- QEnvironmentHexEncoded:VARIABLE=VALUE
-
- The VARIABLE=VALUE part is sent hex-encoded so characters like '#' with special
- meaning in the remote protocol won't break it.
- */
-
- DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironmentHexEncoded: \"%s\"",
- (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
-
- p += sizeof ("QEnvironmentHexEncoded:") - 1;
-
- std::string arg;
- const char *c;
- c = p;
- while (*c != '\0')
- {
- if (*(c + 1) == '\0')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
- }
- char smallbuf[3];
- smallbuf[0] = *c;
- smallbuf[1] = *(c + 1);
- smallbuf[2] = '\0';
- errno = 0;
- int ch = static_cast<int>(strtoul (smallbuf, NULL, 16));
- if (errno != 0 && ch == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
- }
- arg.push_back(ch);
- c += 2;
- }
-
- RNBContext& ctx = Context();
- if (arg.length() > 0)
- ctx.PushEnvironment (arg.c_str());
-
- return SendPacket ("OK");
-}
-
-
-rnb_err_t
-RNBRemote::HandlePacket_QLaunchArch (const char *p)
-{
- p += sizeof ("QLaunchArch:") - 1;
- if (DNBSetArchitecture(p))
- return SendPacket ("OK");
- return SendPacket ("E63");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_QSetProcessEvent (const char *p)
-{
- p += sizeof ("QSetProcessEvent:") - 1;
- // If the process is running, then send the event to the process, otherwise
- // store it in the context.
- if (Context().HasValidProcessID())
- {
- if (DNBProcessSendEvent (Context().ProcessID(), p))
- return SendPacket("OK");
- else
- return SendPacket ("E80");
- }
- else
- {
- Context().PushProcessEvent(p);
- }
- return SendPacket ("OK");
-}
-
-void
-append_hex_value (std::ostream& ostrm, const void *buf, size_t buf_size, bool swap)
-{
- int i;
- const uint8_t *p = (const uint8_t *)buf;
- if (swap)
- {
- for (i = static_cast<int>(buf_size)-1; i >= 0; i--)
- ostrm << RAWHEX8(p[i]);
- }
- else
- {
- for (size_t i = 0; i < buf_size; i++)
- ostrm << RAWHEX8(p[i]);
- }
-}
-
-void
-append_hexified_string (std::ostream& ostrm, const std::string &string)
-{
- size_t string_size = string.size();
- const char *string_buf = string.c_str();
- for (size_t i = 0; i < string_size; i++)
- {
- ostrm << RAWHEX8(*(string_buf + i));
- }
-}
-
-
-
-void
-register_value_in_hex_fixed_width (std::ostream& ostrm,
- nub_process_t pid,
- nub_thread_t tid,
- const register_map_entry_t* reg,
- const DNBRegisterValue *reg_value_ptr)
-{
- if (reg != NULL)
- {
- DNBRegisterValue reg_value;
- if (reg_value_ptr == NULL)
- {
- if (DNBThreadGetRegisterValueByID (pid, tid, reg->nub_info.set, reg->nub_info.reg, ®_value))
- reg_value_ptr = ®_value;
- }
-
- if (reg_value_ptr)
- {
- append_hex_value (ostrm, reg_value_ptr->value.v_uint8, reg->nub_info.size, false);
- }
- else
- {
- // If we fail to read a register value, check if it has a default
- // fail value. If it does, return this instead in case some of
- // the registers are not available on the current system.
- if (reg->nub_info.size > 0)
- {
- std::basic_string<uint8_t> zeros(reg->nub_info.size, '\0');
- append_hex_value (ostrm, zeros.data(), zeros.size(), false);
- }
- }
- }
-}
-
-
-void
-debugserver_regnum_with_fixed_width_hex_register_value (std::ostream& ostrm,
- nub_process_t pid,
- nub_thread_t tid,
- const register_map_entry_t* reg,
- const DNBRegisterValue *reg_value_ptr)
-{
- // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX
- // gdb register number, and VVVVVVVV is the correct number of hex bytes
- // as ASCII for the register value.
- if (reg != NULL)
- {
- ostrm << RAWHEX8(reg->debugserver_regnum) << ':';
- register_value_in_hex_fixed_width (ostrm, pid, tid, reg, reg_value_ptr);
- ostrm << ';';
- }
-}
-
-
-void
-RNBRemote::DispatchQueueOffsets::GetThreadQueueInfo (nub_process_t pid,
- nub_addr_t dispatch_qaddr,
- nub_addr_t &dispatch_queue_t,
- std::string &queue_name,
- uint64_t &queue_width,
- uint64_t &queue_serialnum) const
-{
- queue_name.clear();
- queue_width = 0;
- queue_serialnum = 0;
-
- if (IsValid() && dispatch_qaddr != INVALID_NUB_ADDRESS && dispatch_qaddr != 0)
- {
- dispatch_queue_t = DNBProcessMemoryReadPointer (pid, dispatch_qaddr);
- if (dispatch_queue_t)
- {
- queue_width = DNBProcessMemoryReadInteger (pid, dispatch_queue_t + dqo_width, dqo_width_size, 0);
- queue_serialnum = DNBProcessMemoryReadInteger (pid, dispatch_queue_t + dqo_serialnum, dqo_serialnum_size, 0);
-
- if (dqo_version >= 4)
- {
- // libdispatch versions 4+, pointer to dispatch name is in the
- // queue structure.
- nub_addr_t pointer_to_label_address = dispatch_queue_t + dqo_label;
- nub_addr_t label_addr = DNBProcessMemoryReadPointer (pid, pointer_to_label_address);
- if (label_addr)
- queue_name = DNBProcessMemoryReadCString(pid, label_addr);
- }
- else
- {
- // libdispatch versions 1-3, dispatch name is a fixed width char array
- // in the queue structure.
- queue_name = DNBProcessMemoryReadCStringFixed(pid, dispatch_queue_t + dqo_label, dqo_label_size);
- }
- }
- }
-}
-
-struct StackMemory
-{
- uint8_t bytes[2*sizeof(nub_addr_t)];
- nub_size_t length;
-};
-typedef std::map<nub_addr_t, StackMemory> StackMemoryMap;
-
-
-static void
-ReadStackMemory (nub_process_t pid, nub_thread_t tid, StackMemoryMap &stack_mmap, uint32_t backtrace_limit = 256)
-{
- DNBRegisterValue reg_value;
- if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_FP, ®_value))
- {
- uint32_t frame_count = 0;
- uint64_t fp = 0;
- if (reg_value.info.size == 4)
- fp = reg_value.value.uint32;
- else
- fp = reg_value.value.uint64;
- while (fp != 0)
- {
- // Make sure we never recurse more than 256 times so we don't recurse too far or
- // store up too much memory in the expedited cache
- if (++frame_count > backtrace_limit)
- break;
-
- const nub_size_t read_size = reg_value.info.size*2;
- StackMemory stack_memory;
- stack_memory.length = read_size;
- if (DNBProcessMemoryRead(pid, fp, read_size, stack_memory.bytes) != read_size)
- break;
- // Make sure we don't try to put the same stack memory in more than once
- if (stack_mmap.find(fp) != stack_mmap.end())
- break;
- // Put the entry into the cache
- stack_mmap[fp] = stack_memory;
- // Dereference the frame pointer to get to the previous frame pointer
- if (reg_value.info.size == 4)
- fp = ((uint32_t *)stack_memory.bytes)[0];
- else
- fp = ((uint64_t *)stack_memory.bytes)[0];
- }
- }
-}
-
-rnb_err_t
-RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
-{
- const nub_process_t pid = m_ctx.ProcessID();
- if (pid == INVALID_NUB_PROCESS)
- return SendPacket("E50");
-
- struct DNBThreadStopInfo tid_stop_info;
-
- /* Fill the remaining space in this packet with as many registers
- as we can stuff in there. */
-
- if (DNBThreadGetStopReason (pid, tid, &tid_stop_info))
- {
- const bool did_exec = tid_stop_info.reason == eStopTypeExec;
- if (did_exec)
- {
- RNBRemote::InitializeRegisters(true);
-
- // Reset any symbols that need resetting when we exec
- m_dispatch_queue_offsets_addr = INVALID_NUB_ADDRESS;
- m_dispatch_queue_offsets.Clear();
- }
-
- std::ostringstream ostrm;
- // Output the T packet with the thread
- ostrm << 'T';
- int signum = tid_stop_info.details.signal.signo;
- DNBLogThreadedIf (LOG_RNB_PROC, "%8d %s got signal signo = %u, exc_type = %u", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, signum, tid_stop_info.details.exception.type);
-
- // Translate any mach exceptions to gdb versions, unless they are
- // common exceptions like a breakpoint or a soft signal.
- switch (tid_stop_info.details.exception.type)
- {
- default: signum = 0; break;
- case EXC_BREAKPOINT: signum = SIGTRAP; break;
- case EXC_BAD_ACCESS: signum = TARGET_EXC_BAD_ACCESS; break;
- case EXC_BAD_INSTRUCTION: signum = TARGET_EXC_BAD_INSTRUCTION; break;
- case EXC_ARITHMETIC: signum = TARGET_EXC_ARITHMETIC; break;
- case EXC_EMULATION: signum = TARGET_EXC_EMULATION; break;
- case EXC_SOFTWARE:
- if (tid_stop_info.details.exception.data_count == 2 &&
- tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL)
- signum = static_cast<int>(tid_stop_info.details.exception.data[1]);
- else
- signum = TARGET_EXC_SOFTWARE;
- break;
- }
-
- ostrm << RAWHEX8(signum & 0xff);
-
- ostrm << std::hex << "thread:" << tid << ';';
-
- const char *thread_name = DNBThreadGetName (pid, tid);
- if (thread_name && thread_name[0])
- {
- size_t thread_name_len = strlen(thread_name);
-
-
- if (::strcspn (thread_name, "$#+-;:") == thread_name_len)
- ostrm << std::hex << "name:" << thread_name << ';';
- else
- {
- // the thread name contains special chars, send as hex bytes
- ostrm << std::hex << "hexname:";
- uint8_t *u_thread_name = (uint8_t *)thread_name;
- for (size_t i = 0; i < thread_name_len; i++)
- ostrm << RAWHEX8(u_thread_name[i]);
- ostrm << ';';
- }
- }
-
- // 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:
- // "threads:10a,10b,10c;"
- // This will save the debugger from having to send a pair of qfThreadInfo
- // and qsThreadInfo packets, but it also might take a lot of room in the
- // stop reply packet, so it must be enabled only on systems where there
- // are no limits on packet lengths.
- if (m_list_threads_in_stop_reply)
- {
- const nub_size_t numthreads = DNBProcessGetNumThreads (pid);
- if (numthreads > 0)
- {
- std::vector<uint64_t> pc_values;
- ostrm << std::hex << "threads:";
- for (nub_size_t i = 0; i < numthreads; ++i)
- {
- nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i);
- if (i > 0)
- ostrm << ',';
- ostrm << std::hex << th;
- DNBRegisterValue pc_regval;
- if (DNBThreadGetRegisterValueByID (pid, th, REGISTER_SET_GENERIC, GENERIC_REGNUM_PC, &pc_regval))
- {
- uint64_t pc = INVALID_NUB_ADDRESS;
- if (pc_regval.value.uint64 != INVALID_NUB_ADDRESS)
- {
- if (pc_regval.info.size == 4)
- {
- pc = pc_regval.value.uint32;
- }
- else if (pc_regval.info.size == 8)
- {
- pc = pc_regval.value.uint64;
- }
- if (pc != INVALID_NUB_ADDRESS)
- {
- pc_values.push_back (pc);
- }
- }
- }
- }
- ostrm << ';';
-
- // If we failed to get any of the thread pc values, the size of our vector will not
- // be the same as the # of threads. Don't provide any expedited thread pc values in
- // that case. This should not happen.
- if (pc_values.size() == numthreads)
- {
- ostrm << std::hex << "thread-pcs:";
- for (nub_size_t i = 0; i < numthreads; ++i)
- {
- if (i > 0)
- ostrm << ',';
- ostrm << std::hex << pc_values[i];
- }
- ostrm << ';';
- }
- }
-
- // Include JSON info that describes the stop reason for any threads
- // that actually have stop reasons. We use the new "jstopinfo" key
- // whose values is hex ascii JSON that contains the thread IDs
- // thread stop info only for threads that have stop reasons. Only send
- // this if we have more than one thread otherwise this packet has all
- // the info it needs.
- if (numthreads > 1)
- {
- const bool threads_with_valid_stop_info_only = true;
- JSONGenerator::ObjectSP threads_info_sp = GetJSONThreadsInfo(threads_with_valid_stop_info_only);
- if (threads_info_sp)
- {
- ostrm << std::hex << "jstopinfo:";
- std::ostringstream json_strm;
- threads_info_sp->Dump (json_strm);
- append_hexified_string (ostrm, json_strm.str());
- ostrm << ';';
- }
- }
- }
-
- if (g_num_reg_entries == 0)
- InitializeRegisters ();
-
- if (g_reg_entries != NULL)
- {
- DNBRegisterValue reg_value;
- for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
- {
- // Expedite all registers in the first register set that aren't
- // contained in other registers
- if (g_reg_entries[reg].nub_info.set == 1 &&
- g_reg_entries[reg].nub_info.value_regs == NULL)
- {
- if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, ®_value))
- continue;
-
- debugserver_regnum_with_fixed_width_hex_register_value (ostrm, pid, tid, &g_reg_entries[reg], ®_value);
- }
- }
- }
-
- if (did_exec)
- {
- ostrm << "reason:exec;";
- }
- else if (tid_stop_info.details.exception.type)
- {
- ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ';';
- ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ';';
- for (nub_size_t i = 0; i < tid_stop_info.details.exception.data_count; ++i)
- ostrm << "medata:" << std::hex << tid_stop_info.details.exception.data[i] << ';';
- }
-
- // Add expedited stack memory so stack backtracing doesn't need to read anything from the
- // frame pointer chain.
- StackMemoryMap stack_mmap;
- ReadStackMemory (pid, tid, stack_mmap, 2);
- if (!stack_mmap.empty())
- {
- for (const auto &stack_memory : stack_mmap)
- {
- ostrm << "memory:" << HEXBASE << stack_memory.first << '=';
- append_hex_value (ostrm, stack_memory.second.bytes, stack_memory.second.length, false);
- ostrm << ';';
- }
- }
-
- return SendPacket (ostrm.str ());
- }
- return SendPacket("E51");
-}
-
-/* '?'
- The stop reply packet - tell gdb what the status of the inferior is.
- Often called the questionmark_packet. */
-
-rnb_err_t
-RNBRemote::HandlePacket_last_signal (const char *unused)
-{
- if (!m_ctx.HasValidProcessID())
- {
- // Inferior is not yet specified/running
- return SendPacket ("E02");
- }
-
- nub_process_t pid = m_ctx.ProcessID();
- nub_state_t pid_state = DNBProcessGetState (pid);
-
- switch (pid_state)
- {
- case eStateAttaching:
- case eStateLaunching:
- case eStateRunning:
- case eStateStepping:
- case eStateDetached:
- return rnb_success; // Ignore
-
- case eStateSuspended:
- case eStateStopped:
- case eStateCrashed:
- {
- nub_thread_t tid = DNBProcessGetCurrentThread (pid);
- // Make sure we set the current thread so g and p packets return
- // the data the gdb will expect.
- SetCurrentThread (tid);
-
- SendStopReplyPacketForThread (tid);
- }
- break;
-
- case eStateInvalid:
- case eStateUnloaded:
- case eStateExited:
- {
- char pid_exited_packet[16] = "";
- int pid_status = 0;
- // Process exited with exit status
- if (!DNBProcessGetExitStatus(pid, &pid_status))
- pid_status = 0;
-
- if (pid_status)
- {
- if (WIFEXITED (pid_status))
- snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status));
- else if (WIFSIGNALED (pid_status))
- snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status));
- else if (WIFSTOPPED (pid_status))
- snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status));
- }
-
- // If we have an empty exit packet, lets fill one in to be safe.
- if (!pid_exited_packet[0])
- {
- strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1);
- pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0';
- }
-
- const char *exit_info = DNBProcessGetExitInfo (pid);
- if (exit_info != NULL && *exit_info != '\0')
- {
- std::ostringstream exit_packet;
- exit_packet << pid_exited_packet;
- exit_packet << ';';
- exit_packet << RAW_HEXBASE << "description";
- exit_packet << ':';
- for (size_t i = 0; exit_info[i] != '\0'; i++)
- exit_packet << RAWHEX8(exit_info[i]);
- exit_packet << ';';
- return SendPacket (exit_packet.str());
- }
- else
- return SendPacket (pid_exited_packet);
- }
- break;
- }
- return rnb_success;
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_M (const char *p)
-{
- if (p == NULL || p[0] == '\0' || strlen (p) < 3)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short M packet");
- }
-
- char *c;
- p++;
- errno = 0;
- nub_addr_t addr = strtoull (p, &c, 16);
- if (errno != 0 && addr == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in M packet");
- }
- if (*c != ',')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in M packet");
- }
-
- /* Advance 'p' to the length part of the packet. */
- p += (c - p) + 1;
-
- errno = 0;
- unsigned long length = strtoul (p, &c, 16);
- if (errno != 0 && length == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in M packet");
- }
- if (length == 0)
- {
- return SendPacket ("OK");
- }
-
- if (*c != ':')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing colon in M packet");
- }
- /* Advance 'p' to the data part of the packet. */
- p += (c - p) + 1;
-
- size_t datalen = strlen (p);
- if (datalen & 0x1)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Uneven # of hex chars for data in M packet");
- }
- if (datalen == 0)
- {
- return SendPacket ("OK");
- }
-
- uint8_t *buf = (uint8_t *) alloca (datalen / 2);
- uint8_t *i = buf;
-
- while (*p != '\0' && *(p + 1) != '\0')
- {
- char hexbuf[3];
- hexbuf[0] = *p;
- hexbuf[1] = *(p + 1);
- hexbuf[2] = '\0';
- errno = 0;
- uint8_t byte = strtoul (hexbuf, NULL, 16);
- if (errno != 0 && byte == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid hex byte in M packet");
- }
- *i++ = byte;
- p += 2;
- }
-
- nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, length, buf);
- if (wrote != length)
- return SendPacket ("E09");
- else
- return SendPacket ("OK");
-}
-
-
-rnb_err_t
-RNBRemote::HandlePacket_m (const char *p)
-{
- if (p == NULL || p[0] == '\0' || strlen (p) < 3)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short m packet");
- }
-
- char *c;
- p++;
- errno = 0;
- nub_addr_t addr = strtoull (p, &c, 16);
- if (errno != 0 && addr == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in m packet");
- }
- if (*c != ',')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in m packet");
- }
-
- /* Advance 'p' to the length part of the packet. */
- p += (c - p) + 1;
-
- errno = 0;
- auto length = strtoul (p, NULL, 16);
- if (errno != 0 && length == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
- }
- if (length == 0)
- {
- return SendPacket ("");
- }
-
- std::string buf(length, '\0');
- if (buf.empty())
- {
- return SendPacket ("E78");
- }
- nub_size_t bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, buf.size(), &buf[0]);
- if (bytes_read == 0)
- {
- return SendPacket ("E08");
- }
-
- // "The reply may contain fewer bytes than requested if the server was able
- // to read only part of the region of memory."
- length = bytes_read;
-
- std::ostringstream ostrm;
- for (unsigned long i = 0; i < length; i++)
- ostrm << RAWHEX8(buf[i]);
- return SendPacket (ostrm.str ());
-}
-
-// Read memory, sent it up as binary data.
-// Usage: xADDR,LEN
-// ADDR and LEN are both base 16.
-
-// Responds with 'OK' for zero-length request
-// or
-//
-// DATA
-//
-// where DATA is the binary data payload.
-
-rnb_err_t
-RNBRemote::HandlePacket_x (const char *p)
-{
- if (p == NULL || p[0] == '\0' || strlen (p) < 3)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet");
- }
-
- char *c;
- p++;
- errno = 0;
- nub_addr_t addr = strtoull (p, &c, 16);
- if (errno != 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet");
+ const nub_size_t read_size = reg_value.info.size * 2;
+ StackMemory stack_memory;
+ stack_memory.length = read_size;
+ if (DNBProcessMemoryRead(pid, fp, read_size, stack_memory.bytes) !=
+ read_size)
+ break;
+ // Make sure we don't try to put the same stack memory in more than once
+ if (stack_mmap.find(fp) != stack_mmap.end())
+ break;
+ // Put the entry into the cache
+ stack_mmap[fp] = stack_memory;
+ // Dereference the frame pointer to get to the previous frame pointer
+ if (reg_value.info.size == 4)
+ fp = ((uint32_t *)stack_memory.bytes)[0];
+ else
+ fp = ((uint64_t *)stack_memory.bytes)[0];
+ }
+ }
+}
+
+rnb_err_t RNBRemote::SendStopReplyPacketForThread(nub_thread_t tid) {
+ const nub_process_t pid = m_ctx.ProcessID();
+ if (pid == INVALID_NUB_PROCESS)
+ return SendPacket("E50");
+
+ struct DNBThreadStopInfo tid_stop_info;
+
+ /* Fill the remaining space in this packet with as many registers
+ as we can stuff in there. */
+
+ if (DNBThreadGetStopReason(pid, tid, &tid_stop_info)) {
+ const bool did_exec = tid_stop_info.reason == eStopTypeExec;
+ if (did_exec) {
+ RNBRemote::InitializeRegisters(true);
+
+ // Reset any symbols that need resetting when we exec
+ m_dispatch_queue_offsets_addr = INVALID_NUB_ADDRESS;
+ m_dispatch_queue_offsets.Clear();
}
- if (*c != ',')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet");
+
+ std::ostringstream ostrm;
+ // Output the T packet with the thread
+ ostrm << 'T';
+ int signum = tid_stop_info.details.signal.signo;
+ DNBLogThreadedIf(
+ LOG_RNB_PROC, "%8d %s got signal signo = %u, exc_type = %u",
+ (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__,
+ signum, tid_stop_info.details.exception.type);
+
+ // Translate any mach exceptions to gdb versions, unless they are
+ // common exceptions like a breakpoint or a soft signal.
+ switch (tid_stop_info.details.exception.type) {
+ default:
+ signum = 0;
+ break;
+ case EXC_BREAKPOINT:
+ signum = SIGTRAP;
+ break;
+ case EXC_BAD_ACCESS:
+ signum = TARGET_EXC_BAD_ACCESS;
+ break;
+ case EXC_BAD_INSTRUCTION:
+ signum = TARGET_EXC_BAD_INSTRUCTION;
+ break;
+ case EXC_ARITHMETIC:
+ signum = TARGET_EXC_ARITHMETIC;
+ break;
+ case EXC_EMULATION:
+ signum = TARGET_EXC_EMULATION;
+ break;
+ case EXC_SOFTWARE:
+ if (tid_stop_info.details.exception.data_count == 2 &&
+ tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL)
+ signum = static_cast<int>(tid_stop_info.details.exception.data[1]);
+ else
+ signum = TARGET_EXC_SOFTWARE;
+ break;
+ }
+
+ ostrm << RAWHEX8(signum & 0xff);
+
+ ostrm << std::hex << "thread:" << tid << ';';
+
+ const char *thread_name = DNBThreadGetName(pid, tid);
+ if (thread_name && thread_name[0]) {
+ size_t thread_name_len = strlen(thread_name);
+
+ if (::strcspn(thread_name, "$#+-;:") == thread_name_len)
+ ostrm << std::hex << "name:" << thread_name << ';';
+ else {
+ // the thread name contains special chars, send as hex bytes
+ ostrm << std::hex << "hexname:";
+ uint8_t *u_thread_name = (uint8_t *)thread_name;
+ for (size_t i = 0; i < thread_name_len; i++)
+ ostrm << RAWHEX8(u_thread_name[i]);
+ ostrm << ';';
+ }
}
- /* Advance 'p' to the number of bytes to be read. */
- p += (c - p) + 1;
+ // 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:
+ // "threads:10a,10b,10c;"
+ // This will save the debugger from having to send a pair of qfThreadInfo
+ // and qsThreadInfo packets, but it also might take a lot of room in the
+ // stop reply packet, so it must be enabled only on systems where there
+ // are no limits on packet lengths.
+ if (m_list_threads_in_stop_reply) {
+ const nub_size_t numthreads = DNBProcessGetNumThreads(pid);
+ if (numthreads > 0) {
+ std::vector<uint64_t> pc_values;
+ ostrm << std::hex << "threads:";
+ for (nub_size_t i = 0; i < numthreads; ++i) {
+ nub_thread_t th = DNBProcessGetThreadAtIndex(pid, i);
+ if (i > 0)
+ ostrm << ',';
+ ostrm << std::hex << th;
+ DNBRegisterValue pc_regval;
+ if (DNBThreadGetRegisterValueByID(pid, th, REGISTER_SET_GENERIC,
+ GENERIC_REGNUM_PC, &pc_regval)) {
+ uint64_t pc = INVALID_NUB_ADDRESS;
+ if (pc_regval.value.uint64 != INVALID_NUB_ADDRESS) {
+ if (pc_regval.info.size == 4) {
+ pc = pc_regval.value.uint32;
+ } else if (pc_regval.info.size == 8) {
+ pc = pc_regval.value.uint64;
+ }
+ if (pc != INVALID_NUB_ADDRESS) {
+ pc_values.push_back(pc);
+ }
+ }
+ }
+ }
+ ostrm << ';';
- errno = 0;
- auto length = strtoul (p, NULL, 16);
- if (errno != 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in x packet");
- }
+ // If we failed to get any of the thread pc values, the size of our
+ // vector will not
+ // be the same as the # of threads. Don't provide any expedited thread
+ // pc values in
+ // that case. This should not happen.
+ if (pc_values.size() == numthreads) {
+ ostrm << std::hex << "thread-pcs:";
+ for (nub_size_t i = 0; i < numthreads; ++i) {
+ if (i > 0)
+ ostrm << ',';
+ ostrm << std::hex << pc_values[i];
+ }
+ ostrm << ';';
+ }
+ }
- // zero length read means this is a test of whether that packet is implemented or not.
- if (length == 0)
- {
- return SendPacket ("OK");
+ // Include JSON info that describes the stop reason for any threads
+ // that actually have stop reasons. We use the new "jstopinfo" key
+ // whose values is hex ascii JSON that contains the thread IDs
+ // thread stop info only for threads that have stop reasons. Only send
+ // this if we have more than one thread otherwise this packet has all
+ // the info it needs.
+ if (numthreads > 1) {
+ const bool threads_with_valid_stop_info_only = true;
+ JSONGenerator::ObjectSP threads_info_sp =
+ GetJSONThreadsInfo(threads_with_valid_stop_info_only);
+ if (threads_info_sp) {
+ ostrm << std::hex << "jstopinfo:";
+ std::ostringstream json_strm;
+ threads_info_sp->Dump(json_strm);
+ append_hexified_string(ostrm, json_strm.str());
+ ostrm << ';';
+ }
+ }
}
- std::vector<uint8_t> buf (length);
+ if (g_num_reg_entries == 0)
+ InitializeRegisters();
- if (buf.capacity() != length)
- {
- return SendPacket ("E79");
- }
- nub_size_t bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, buf.size(), &buf[0]);
- if (bytes_read == 0)
- {
- return SendPacket ("E80");
- }
+ if (g_reg_entries != NULL) {
+ DNBRegisterValue reg_value;
+ for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) {
+ // Expedite all registers in the first register set that aren't
+ // contained in other registers
+ if (g_reg_entries[reg].nub_info.set == 1 &&
+ g_reg_entries[reg].nub_info.value_regs == NULL) {
+ if (!DNBThreadGetRegisterValueByID(
+ pid, tid, g_reg_entries[reg].nub_info.set,
+ g_reg_entries[reg].nub_info.reg, ®_value))
+ continue;
- std::vector<uint8_t> buf_quoted;
- buf_quoted.reserve (bytes_read + 30);
- for (nub_size_t i = 0; i < bytes_read; i++)
- {
- if (buf[i] == '#' || buf[i] == '$' || buf[i] == '}' || buf[i] == '*')
- {
- buf_quoted.push_back(0x7d);
- buf_quoted.push_back(buf[i] ^ 0x20);
- }
- else
- {
- buf_quoted.push_back(buf[i]);
+ debugserver_regnum_with_fixed_width_hex_register_value(
+ ostrm, pid, tid, &g_reg_entries[reg], ®_value);
}
+ }
}
- length = buf_quoted.size();
- std::ostringstream ostrm;
- for (unsigned long i = 0; i < length; i++)
- ostrm << buf_quoted[i];
+ if (did_exec) {
+ ostrm << "reason:exec;";
+ } else if (tid_stop_info.details.exception.type) {
+ ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type
+ << ';';
+ ostrm << "mecount:" << std::hex
+ << tid_stop_info.details.exception.data_count << ';';
+ for (nub_size_t i = 0; i < tid_stop_info.details.exception.data_count;
+ ++i)
+ ostrm << "medata:" << std::hex
+ << tid_stop_info.details.exception.data[i] << ';';
+ }
+
+ // Add expedited stack memory so stack backtracing doesn't need to read
+ // anything from the
+ // frame pointer chain.
+ StackMemoryMap stack_mmap;
+ ReadStackMemory(pid, tid, stack_mmap, 2);
+ if (!stack_mmap.empty()) {
+ for (const auto &stack_memory : stack_mmap) {
+ ostrm << "memory:" << HEXBASE << stack_memory.first << '=';
+ append_hex_value(ostrm, stack_memory.second.bytes,
+ stack_memory.second.length, false);
+ ostrm << ';';
+ }
+ }
- return SendPacket (ostrm.str ());
+ return SendPacket(ostrm.str());
+ }
+ return SendPacket("E51");
}
-rnb_err_t
-RNBRemote::HandlePacket_X (const char *p)
-{
- if (p == NULL || p[0] == '\0' || strlen (p) < 3)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet");
- }
+/* '?'
+ The stop reply packet - tell gdb what the status of the inferior is.
+ Often called the questionmark_packet. */
- char *c;
- p++;
- errno = 0;
- nub_addr_t addr = strtoull (p, &c, 16);
- if (errno != 0 && addr == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet");
- }
- if (*c != ',')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet");
- }
+rnb_err_t RNBRemote::HandlePacket_last_signal(const char *unused) {
+ if (!m_ctx.HasValidProcessID()) {
+ // Inferior is not yet specified/running
+ return SendPacket("E02");
+ }
+
+ nub_process_t pid = m_ctx.ProcessID();
+ nub_state_t pid_state = DNBProcessGetState(pid);
+
+ switch (pid_state) {
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateRunning:
+ case eStateStepping:
+ case eStateDetached:
+ return rnb_success; // Ignore
+
+ case eStateSuspended:
+ case eStateStopped:
+ case eStateCrashed: {
+ nub_thread_t tid = DNBProcessGetCurrentThread(pid);
+ // Make sure we set the current thread so g and p packets return
+ // the data the gdb will expect.
+ SetCurrentThread(tid);
+
+ SendStopReplyPacketForThread(tid);
+ } break;
+
+ case eStateInvalid:
+ case eStateUnloaded:
+ case eStateExited: {
+ char pid_exited_packet[16] = "";
+ int pid_status = 0;
+ // Process exited with exit status
+ if (!DNBProcessGetExitStatus(pid, &pid_status))
+ pid_status = 0;
+
+ if (pid_status) {
+ if (WIFEXITED(pid_status))
+ snprintf(pid_exited_packet, sizeof(pid_exited_packet), "W%02x",
+ WEXITSTATUS(pid_status));
+ else if (WIFSIGNALED(pid_status))
+ snprintf(pid_exited_packet, sizeof(pid_exited_packet), "X%02x",
+ WEXITSTATUS(pid_status));
+ else if (WIFSTOPPED(pid_status))
+ snprintf(pid_exited_packet, sizeof(pid_exited_packet), "S%02x",
+ WSTOPSIG(pid_status));
+ }
+
+ // If we have an empty exit packet, lets fill one in to be safe.
+ if (!pid_exited_packet[0]) {
+ strncpy(pid_exited_packet, "W00", sizeof(pid_exited_packet) - 1);
+ pid_exited_packet[sizeof(pid_exited_packet) - 1] = '\0';
+ }
+
+ const char *exit_info = DNBProcessGetExitInfo(pid);
+ if (exit_info != NULL && *exit_info != '\0') {
+ std::ostringstream exit_packet;
+ exit_packet << pid_exited_packet;
+ exit_packet << ';';
+ exit_packet << RAW_HEXBASE << "description";
+ exit_packet << ':';
+ for (size_t i = 0; exit_info[i] != '\0'; i++)
+ exit_packet << RAWHEX8(exit_info[i]);
+ exit_packet << ';';
+ return SendPacket(exit_packet.str());
+ } else
+ return SendPacket(pid_exited_packet);
+ } break;
+ }
+ return rnb_success;
+}
+
+rnb_err_t RNBRemote::HandlePacket_M(const char *p) {
+ if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short M packet");
+ }
+
+ char *c;
+ p++;
+ errno = 0;
+ nub_addr_t addr = strtoull(p, &c, 16);
+ if (errno != 0 && addr == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid address in M packet");
+ }
+ if (*c != ',') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Comma sep missing in M packet");
+ }
+
+ /* Advance 'p' to the length part of the packet. */
+ p += (c - p) + 1;
+
+ errno = 0;
+ unsigned long length = strtoul(p, &c, 16);
+ if (errno != 0 && length == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid length in M packet");
+ }
+ if (length == 0) {
+ return SendPacket("OK");
+ }
+
+ if (*c != ':') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Missing colon in M packet");
+ }
+ /* Advance 'p' to the data part of the packet. */
+ p += (c - p) + 1;
+
+ size_t datalen = strlen(p);
+ if (datalen & 0x1) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Uneven # of hex chars for data in M packet");
+ }
+ if (datalen == 0) {
+ return SendPacket("OK");
+ }
- /* Advance 'p' to the length part of the packet. NB this is the length of the packet
- including any escaped chars. The data payload may be a little bit smaller after
- decoding. */
- p += (c - p) + 1;
+ uint8_t *buf = (uint8_t *)alloca(datalen / 2);
+ uint8_t *i = buf;
+ while (*p != '\0' && *(p + 1) != '\0') {
+ char hexbuf[3];
+ hexbuf[0] = *p;
+ hexbuf[1] = *(p + 1);
+ hexbuf[2] = '\0';
errno = 0;
- auto length = strtoul (p, NULL, 16);
- if (errno != 0 && length == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in X packet");
- }
+ uint8_t byte = strtoul(hexbuf, NULL, 16);
+ if (errno != 0 && byte == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid hex byte in M packet");
+ }
+ *i++ = byte;
+ p += 2;
+ }
+
+ nub_size_t wrote =
+ DNBProcessMemoryWrite(m_ctx.ProcessID(), addr, length, buf);
+ if (wrote != length)
+ return SendPacket("E09");
+ else
+ return SendPacket("OK");
+}
- // I think gdb sends a zero length write request to test whether this
- // packet is accepted.
- if (length == 0)
- {
- return SendPacket ("OK");
- }
+rnb_err_t RNBRemote::HandlePacket_m(const char *p) {
+ if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short m packet");
+ }
+
+ char *c;
+ p++;
+ errno = 0;
+ nub_addr_t addr = strtoull(p, &c, 16);
+ if (errno != 0 && addr == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid address in m packet");
+ }
+ if (*c != ',') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Comma sep missing in m packet");
+ }
+
+ /* Advance 'p' to the length part of the packet. */
+ p += (c - p) + 1;
+
+ errno = 0;
+ auto length = strtoul(p, NULL, 16);
+ if (errno != 0 && length == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid length in m packet");
+ }
+ if (length == 0) {
+ return SendPacket("");
+ }
+
+ std::string buf(length, '\0');
+ if (buf.empty()) {
+ return SendPacket("E78");
+ }
+ nub_size_t bytes_read =
+ DNBProcessMemoryRead(m_ctx.ProcessID(), addr, buf.size(), &buf[0]);
+ if (bytes_read == 0) {
+ return SendPacket("E08");
+ }
+
+ // "The reply may contain fewer bytes than requested if the server was able
+ // to read only part of the region of memory."
+ length = bytes_read;
+
+ std::ostringstream ostrm;
+ for (unsigned long i = 0; i < length; i++)
+ ostrm << RAWHEX8(buf[i]);
+ return SendPacket(ostrm.str());
+}
- std::vector<uint8_t> data = decode_binary_data (c, -1);
- std::vector<uint8_t>::const_iterator it;
- uint8_t *buf = (uint8_t *) alloca (data.size ());
- uint8_t *i = buf;
- for (it = data.begin (); it != data.end (); ++it)
- {
- *i++ = *it;
- }
+// Read memory, sent it up as binary data.
+// Usage: xADDR,LEN
+// ADDR and LEN are both base 16.
- nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, data.size(), buf);
- if (wrote != data.size ())
- return SendPacket ("E08");
- return SendPacket ("OK");
+// Responds with 'OK' for zero-length request
+// or
+//
+// DATA
+//
+// where DATA is the binary data payload.
+
+rnb_err_t RNBRemote::HandlePacket_x(const char *p) {
+ if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short X packet");
+ }
+
+ char *c;
+ p++;
+ errno = 0;
+ nub_addr_t addr = strtoull(p, &c, 16);
+ if (errno != 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid address in X packet");
+ }
+ if (*c != ',') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Comma sep missing in X packet");
+ }
+
+ /* Advance 'p' to the number of bytes to be read. */
+ p += (c - p) + 1;
+
+ errno = 0;
+ auto length = strtoul(p, NULL, 16);
+ if (errno != 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid length in x packet");
+ }
+
+ // zero length read means this is a test of whether that packet is implemented
+ // or not.
+ if (length == 0) {
+ return SendPacket("OK");
+ }
+
+ std::vector<uint8_t> buf(length);
+
+ if (buf.capacity() != length) {
+ return SendPacket("E79");
+ }
+ nub_size_t bytes_read =
+ DNBProcessMemoryRead(m_ctx.ProcessID(), addr, buf.size(), &buf[0]);
+ if (bytes_read == 0) {
+ return SendPacket("E80");
+ }
+
+ std::vector<uint8_t> buf_quoted;
+ buf_quoted.reserve(bytes_read + 30);
+ for (nub_size_t i = 0; i < bytes_read; i++) {
+ if (buf[i] == '#' || buf[i] == '$' || buf[i] == '}' || buf[i] == '*') {
+ buf_quoted.push_back(0x7d);
+ buf_quoted.push_back(buf[i] ^ 0x20);
+ } else {
+ buf_quoted.push_back(buf[i]);
+ }
+ }
+ length = buf_quoted.size();
+
+ std::ostringstream ostrm;
+ for (unsigned long i = 0; i < length; i++)
+ ostrm << buf_quoted[i];
+
+ return SendPacket(ostrm.str());
+}
+
+rnb_err_t RNBRemote::HandlePacket_X(const char *p) {
+ if (p == NULL || p[0] == '\0' || strlen(p) < 3) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short X packet");
+ }
+
+ char *c;
+ p++;
+ errno = 0;
+ nub_addr_t addr = strtoull(p, &c, 16);
+ if (errno != 0 && addr == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid address in X packet");
+ }
+ if (*c != ',') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Comma sep missing in X packet");
+ }
+
+ /* Advance 'p' to the length part of the packet. NB this is the length of the
+ packet
+ including any escaped chars. The data payload may be a little bit smaller
+ after
+ decoding. */
+ p += (c - p) + 1;
+
+ errno = 0;
+ auto length = strtoul(p, NULL, 16);
+ if (errno != 0 && length == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid length in X packet");
+ }
+
+ // I think gdb sends a zero length write request to test whether this
+ // packet is accepted.
+ if (length == 0) {
+ return SendPacket("OK");
+ }
+
+ std::vector<uint8_t> data = decode_binary_data(c, -1);
+ std::vector<uint8_t>::const_iterator it;
+ uint8_t *buf = (uint8_t *)alloca(data.size());
+ uint8_t *i = buf;
+ for (it = data.begin(); it != data.end(); ++it) {
+ *i++ = *it;
+ }
+
+ nub_size_t wrote =
+ DNBProcessMemoryWrite(m_ctx.ProcessID(), addr, data.size(), buf);
+ if (wrote != data.size())
+ return SendPacket("E08");
+ return SendPacket("OK");
}
/* 'g' -- read registers
@@ -3423,108 +3329,99 @@ RNBRemote::HandlePacket_X (const char *p
Should the setting of the Hg packet determine which thread's registers
are returned? */
-rnb_err_t
-RNBRemote::HandlePacket_g (const char *p)
-{
- std::ostringstream ostrm;
- if (!m_ctx.HasValidProcessID())
- {
- return SendPacket ("E11");
- }
-
- if (g_num_reg_entries == 0)
- InitializeRegisters ();
-
- nub_process_t pid = m_ctx.ProcessID ();
- nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p + 1);
- if (tid == INVALID_NUB_THREAD)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
-
- // Get the register context size first by calling with NULL buffer
- nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
- if (reg_ctx_size)
- {
- // Now allocate enough space for the entire register context
- std::vector<uint8_t> reg_ctx;
- reg_ctx.resize(reg_ctx_size);
- // Now read the register context
- reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, ®_ctx[0], reg_ctx.size());
- if (reg_ctx_size)
- {
- append_hex_value (ostrm, reg_ctx.data(), reg_ctx.size(), false);
- return SendPacket (ostrm.str ());
- }
+rnb_err_t RNBRemote::HandlePacket_g(const char *p) {
+ std::ostringstream ostrm;
+ if (!m_ctx.HasValidProcessID()) {
+ return SendPacket("E11");
+ }
+
+ if (g_num_reg_entries == 0)
+ InitializeRegisters();
+
+ nub_process_t pid = m_ctx.ProcessID();
+ nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p + 1);
+ if (tid == INVALID_NUB_THREAD)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "No thread specified in p packet");
+
+ // Get the register context size first by calling with NULL buffer
+ nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
+ if (reg_ctx_size) {
+ // Now allocate enough space for the entire register context
+ std::vector<uint8_t> reg_ctx;
+ reg_ctx.resize(reg_ctx_size);
+ // Now read the register context
+ reg_ctx_size =
+ DNBThreadGetRegisterContext(pid, tid, ®_ctx[0], reg_ctx.size());
+ if (reg_ctx_size) {
+ append_hex_value(ostrm, reg_ctx.data(), reg_ctx.size(), false);
+ return SendPacket(ostrm.str());
}
- return SendPacket ("E74");
+ }
+ return SendPacket("E74");
}
/* 'G XXX...' -- write registers
How is the thread for these specified, beyond "the current thread"?
Does gdb actually use the Hg packet to set this? */
-rnb_err_t
-RNBRemote::HandlePacket_G (const char *p)
-{
- if (!m_ctx.HasValidProcessID())
- {
- return SendPacket ("E11");
- }
-
- if (g_num_reg_entries == 0)
- InitializeRegisters ();
-
- StdStringExtractor packet(p);
- packet.SetFilePos(1); // Skip the 'G'
-
- nub_process_t pid = m_ctx.ProcessID();
- nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
- if (tid == INVALID_NUB_THREAD)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
-
- // Get the register context size first by calling with NULL buffer
- nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
- if (reg_ctx_size)
- {
- // Now allocate enough space for the entire register context
- std::vector<uint8_t> reg_ctx;
- reg_ctx.resize(reg_ctx_size);
-
- const nub_size_t bytes_extracted = packet.GetHexBytes (®_ctx[0], reg_ctx.size(), 0xcc);
- if (bytes_extracted == reg_ctx.size())
- {
- // Now write the register context
- reg_ctx_size = DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size());
- if (reg_ctx_size == reg_ctx.size())
- return SendPacket ("OK");
- else
- return SendPacket ("E55");
- }
- else
- {
- DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu bytes, size mismatch\n", p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size);
- return SendPacket ("E64");
- }
- }
- return SendPacket ("E65");
-}
-
-static bool
-RNBRemoteShouldCancelCallback (void *not_used)
-{
- RNBRemoteSP remoteSP(g_remoteSP);
- if (remoteSP.get() != NULL)
- {
- RNBRemote* remote = remoteSP.get();
- if (remote->Comm().IsConnected())
- return false;
- else
- return true;
- }
- return true;
+rnb_err_t RNBRemote::HandlePacket_G(const char *p) {
+ if (!m_ctx.HasValidProcessID()) {
+ return SendPacket("E11");
+ }
+
+ if (g_num_reg_entries == 0)
+ InitializeRegisters();
+
+ StdStringExtractor packet(p);
+ packet.SetFilePos(1); // Skip the 'G'
+
+ nub_process_t pid = m_ctx.ProcessID();
+ nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
+ if (tid == INVALID_NUB_THREAD)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "No thread specified in p packet");
+
+ // Get the register context size first by calling with NULL buffer
+ nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
+ if (reg_ctx_size) {
+ // Now allocate enough space for the entire register context
+ std::vector<uint8_t> reg_ctx;
+ reg_ctx.resize(reg_ctx_size);
+
+ const nub_size_t bytes_extracted =
+ packet.GetHexBytes(®_ctx[0], reg_ctx.size(), 0xcc);
+ if (bytes_extracted == reg_ctx.size()) {
+ // Now write the register context
+ reg_ctx_size =
+ DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size());
+ if (reg_ctx_size == reg_ctx.size())
+ return SendPacket("OK");
+ else
+ return SendPacket("E55");
+ } else {
+ DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu "
+ "bytes, size mismatch\n",
+ p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size);
+ return SendPacket("E64");
+ }
+ }
+ return SendPacket("E65");
+}
+
+static bool RNBRemoteShouldCancelCallback(void *not_used) {
+ RNBRemoteSP remoteSP(g_remoteSP);
+ if (remoteSP.get() != NULL) {
+ RNBRemote *remote = remoteSP.get();
+ if (remote->Comm().IsConnected())
+ return false;
+ else
+ return true;
+ }
+ return true;
}
-
-// FORMAT: _MXXXXXX,PPP
+// FORMAT: _MXXXXXX,PPP
// XXXXXX: big endian hex chars
// PPP: permissions can be any combo of r w x chars
//
@@ -3537,74 +3434,73 @@ RNBRemoteShouldCancelCallback (void *not
// _M123000,rwx
// _M123000,xw
-rnb_err_t
-RNBRemote::HandlePacket_AllocateMemory (const char *p)
-{
- StdStringExtractor packet (p);
- packet.SetFilePos(2); // Skip the "_M"
-
- nub_addr_t size = packet.GetHexMaxU64 (StdStringExtractor::BigEndian, 0);
- if (size != 0)
- {
- if (packet.GetChar() == ',')
- {
- uint32_t permissions = 0;
- char ch;
- bool success = true;
- while (success && (ch = packet.GetChar()) != '\0')
- {
- switch (ch)
- {
- case 'r': permissions |= eMemoryPermissionsReadable; break;
- case 'w': permissions |= eMemoryPermissionsWritable; break;
- case 'x': permissions |= eMemoryPermissionsExecutable; break;
- default: success = false; break;
- }
- }
-
- if (success)
- {
- nub_addr_t addr = DNBProcessMemoryAllocate (m_ctx.ProcessID(), size, permissions);
- if (addr != INVALID_NUB_ADDRESS)
- {
- std::ostringstream ostrm;
- ostrm << RAW_HEXBASE << addr;
- return SendPacket (ostrm.str ());
- }
- }
+rnb_err_t RNBRemote::HandlePacket_AllocateMemory(const char *p) {
+ StdStringExtractor packet(p);
+ packet.SetFilePos(2); // Skip the "_M"
+
+ nub_addr_t size = packet.GetHexMaxU64(StdStringExtractor::BigEndian, 0);
+ if (size != 0) {
+ if (packet.GetChar() == ',') {
+ uint32_t permissions = 0;
+ char ch;
+ bool success = true;
+ while (success && (ch = packet.GetChar()) != '\0') {
+ switch (ch) {
+ case 'r':
+ permissions |= eMemoryPermissionsReadable;
+ break;
+ case 'w':
+ permissions |= eMemoryPermissionsWritable;
+ break;
+ case 'x':
+ permissions |= eMemoryPermissionsExecutable;
+ break;
+ default:
+ success = false;
+ break;
+ }
+ }
+
+ if (success) {
+ nub_addr_t addr =
+ DNBProcessMemoryAllocate(m_ctx.ProcessID(), size, permissions);
+ if (addr != INVALID_NUB_ADDRESS) {
+ std::ostringstream ostrm;
+ ostrm << RAW_HEXBASE << addr;
+ return SendPacket(ostrm.str());
}
+ }
}
- return SendPacket ("E53");
+ }
+ return SendPacket("E53");
}
-// FORMAT: _mXXXXXX
+// FORMAT: _mXXXXXX
// XXXXXX: address that was previously allocated
//
// RESPONSE: XXXXXX
// OK: address was deallocated
// EXX: error code
//
-// EXAMPLES:
+// EXAMPLES:
// _m123000
-rnb_err_t
-RNBRemote::HandlePacket_DeallocateMemory (const char *p)
-{
- StdStringExtractor packet (p);
- packet.SetFilePos(2); // Skip the "_m"
- nub_addr_t addr = packet.GetHexMaxU64 (StdStringExtractor::BigEndian, INVALID_NUB_ADDRESS);
-
- if (addr != INVALID_NUB_ADDRESS)
- {
- if (DNBProcessMemoryDeallocate (m_ctx.ProcessID(), addr))
- return SendPacket ("OK");
- }
- return SendPacket ("E54");
+rnb_err_t RNBRemote::HandlePacket_DeallocateMemory(const char *p) {
+ StdStringExtractor packet(p);
+ packet.SetFilePos(2); // Skip the "_m"
+ nub_addr_t addr =
+ packet.GetHexMaxU64(StdStringExtractor::BigEndian, INVALID_NUB_ADDRESS);
+
+ if (addr != INVALID_NUB_ADDRESS) {
+ if (DNBProcessMemoryDeallocate(m_ctx.ProcessID(), addr))
+ return SendPacket("OK");
+ }
+ return SendPacket("E54");
}
-
// FORMAT: QSaveRegisterState;thread:TTTT; (when thread suffix is supported)
-// FORMAT: QSaveRegisterState (when thread suffix is NOT supported)
+// FORMAT: QSaveRegisterState (when thread suffix is NOT
+// supported)
// TTTT: thread ID in hex
//
// RESPONSE:
@@ -3614,36 +3510,36 @@ RNBRemote::HandlePacket_DeallocateMemory
//
// EXAMPLES:
// QSaveRegisterState;thread:1E34; (when thread suffix is supported)
-// QSaveRegisterState (when thread suffix is NOT supported)
+// QSaveRegisterState (when thread suffix is NOT
+// supported)
-rnb_err_t
-RNBRemote::HandlePacket_SaveRegisterState (const char *p)
-{
- nub_process_t pid = m_ctx.ProcessID ();
- nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
- if (tid == INVALID_NUB_THREAD)
- {
- if (m_thread_suffix_supported)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in QSaveRegisterState packet");
- else
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread was is set with the Hg packet");
- }
-
- // Get the register context size first by calling with NULL buffer
- const uint32_t save_id = DNBThreadSaveRegisterState(pid, tid);
- if (save_id != 0)
- {
- char response[64];
- snprintf (response, sizeof(response), "%u", save_id);
- return SendPacket (response);
- }
+rnb_err_t RNBRemote::HandlePacket_SaveRegisterState(const char *p) {
+ nub_process_t pid = m_ctx.ProcessID();
+ nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
+ if (tid == INVALID_NUB_THREAD) {
+ if (m_thread_suffix_supported)
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p,
+ "No thread specified in QSaveRegisterState packet");
else
- {
- return SendPacket ("E75");
- }
-}
-// FORMAT: QRestoreRegisterState:SAVEID;thread:TTTT; (when thread suffix is supported)
-// FORMAT: QRestoreRegisterState:SAVEID (when thread suffix is NOT supported)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "No thread was is set with the Hg packet");
+ }
+
+ // Get the register context size first by calling with NULL buffer
+ const uint32_t save_id = DNBThreadSaveRegisterState(pid, tid);
+ if (save_id != 0) {
+ char response[64];
+ snprintf(response, sizeof(response), "%u", save_id);
+ return SendPacket(response);
+ } else {
+ return SendPacket("E75");
+ }
+}
+// FORMAT: QRestoreRegisterState:SAVEID;thread:TTTT; (when thread suffix is
+// supported)
+// FORMAT: QRestoreRegisterState:SAVEID (when thread suffix is NOT
+// supported)
// TTTT: thread ID in hex
// SAVEID: a decimal number that represents the save ID that was
// returned from a call to "QSaveRegisterState"
@@ -3653,1461 +3549,1431 @@ RNBRemote::HandlePacket_SaveRegisterStat
// EXX: error code
//
// EXAMPLES:
-// QRestoreRegisterState:1;thread:1E34; (when thread suffix is supported)
-// QRestoreRegisterState:1 (when thread suffix is NOT supported)
-
-rnb_err_t
-RNBRemote::HandlePacket_RestoreRegisterState (const char *p)
-{
- nub_process_t pid = m_ctx.ProcessID ();
- nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
- if (tid == INVALID_NUB_THREAD)
- {
- if (m_thread_suffix_supported)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in QSaveRegisterState packet");
- else
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread was is set with the Hg packet");
- }
-
- StdStringExtractor packet (p);
- packet.SetFilePos(strlen("QRestoreRegisterState:")); // Skip the "QRestoreRegisterState:"
- const uint32_t save_id = packet.GetU32(0);
-
- if (save_id != 0)
- {
- // Get the register context size first by calling with NULL buffer
- if (DNBThreadRestoreRegisterState(pid, tid, save_id))
- return SendPacket ("OK");
- else
- return SendPacket ("E77");
- }
- return SendPacket ("E76");
-}
-
-static bool
-GetProcessNameFrom_vAttach (const char *&p, std::string &attach_name)
-{
- bool return_val = true;
- while (*p != '\0')
- {
- char smallbuf[3];
- smallbuf[0] = *p;
- smallbuf[1] = *(p + 1);
- smallbuf[2] = '\0';
-
- errno = 0;
- int ch = static_cast<int>(strtoul (smallbuf, NULL, 16));
- if (errno != 0 && ch == 0)
- {
- return_val = false;
- break;
- }
-
- attach_name.push_back(ch);
- p += 2;
- }
- return return_val;
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qSupported (const char *p)
-{
- uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet size--debugger can always use less
- char buf[256];
- snprintf (buf, sizeof(buf), "qXfer:features:read+;PacketSize=%x;qEcho+", max_packet_size);
-
- // By default, don't enable compression. It's only worth doing when we are working
- // with a low speed communication channel.
- bool enable_compression = false;
- (void)enable_compression;
-
- // Enable compression when debugserver is running on a watchOS device where communication may be over Bluetooth.
-#if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
- enable_compression = true;
-#endif
-
-#if defined (HAVE_LIBCOMPRESSION)
- // libcompression is weak linked so test if compression_decode_buffer() is available
- if (enable_compression && compression_decode_buffer != NULL)
- {
- strcat (buf, ";SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;DefaultCompressionMinSize=");
- char numbuf[16];
- snprintf (numbuf, sizeof (numbuf), "%zu", m_compression_minsize);
- numbuf[sizeof (numbuf) - 1] = '\0';
- strcat (buf, numbuf);
- }
-#elif defined (HAVE_LIBZ)
- if (enable_compression)
- {
- strcat (buf, ";SupportedCompressions=zlib-deflate;DefaultCompressionMinSize=");
- char numbuf[16];
- snprintf (numbuf, sizeof (numbuf), "%zu", m_compression_minsize);
- numbuf[sizeof (numbuf) - 1] = '\0';
- strcat (buf, numbuf);
- }
-#endif
-
- return SendPacket (buf);
-}
-
-/*
- vAttach;pid
-
- Attach to a new process with the specified process ID. pid is a hexadecimal integer
- identifying the process. If the stub is currently controlling a process, it is
- killed. The attached process is stopped.This packet is only available in extended
- mode (see extended mode).
-
- Reply:
- "ENN" for an error
- "Any Stop Reply Packet" for success
- */
-
-rnb_err_t
-RNBRemote::HandlePacket_v (const char *p)
-{
- if (strcmp (p, "vCont;c") == 0)
- {
- // Simple continue
- return RNBRemote::HandlePacket_c("c");
- }
- else if (strcmp (p, "vCont;s") == 0)
- {
- // Simple step
- return RNBRemote::HandlePacket_s("s");
- }
- else if (strstr (p, "vCont") == p)
- {
- DNBThreadResumeActions thread_actions;
- char *c = (char *)(p += strlen("vCont"));
- char *c_end = c + strlen(c);
- if (*c == '?')
- return SendPacket ("vCont;c;C;s;S");
-
- while (c < c_end && *c == ';')
- {
- ++c; // Skip the semi-colon
- DNBThreadResumeAction thread_action;
- thread_action.tid = INVALID_NUB_THREAD;
- thread_action.state = eStateInvalid;
- thread_action.signal = 0;
- thread_action.addr = INVALID_NUB_ADDRESS;
-
- char action = *c++;
-
- switch (action)
- {
- case 'C':
- errno = 0;
- thread_action.signal = static_cast<int>(strtoul (c, &c, 16));
- if (errno != 0)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
- // Fall through to next case...
-
- case 'c':
- // Continue
- thread_action.state = eStateRunning;
- break;
-
- case 'S':
- errno = 0;
- thread_action.signal = static_cast<int>(strtoul (c, &c, 16));
- if (errno != 0)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
- // Fall through to next case...
-
- case 's':
- // Step
- thread_action.state = eStateStepping;
- break;
-
- default:
- HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Unsupported action in vCont packet");
- break;
- }
- if (*c == ':')
- {
- errno = 0;
- thread_action.tid = strtoul (++c, &c, 16);
- if (errno != 0)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in vCont 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);
- DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst (), thread_actions.GetSize());
- return rnb_success;
- }
- else if (strstr (p, "vAttach") == p)
- {
- nub_process_t attach_pid = INVALID_NUB_PROCESS; // attach_pid will be set to 0 if the attach fails
- nub_process_t pid_attaching_to = INVALID_NUB_PROCESS; // pid_attaching_to is the original pid specified
- char err_str[1024]={'\0'};
- std::string attach_name;
-
- if (strstr (p, "vAttachWait;") == p)
- {
- p += strlen("vAttachWait;");
- if (!GetProcessNameFrom_vAttach(p, attach_name))
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
- }
- const bool ignore_existing = true;
- attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
-
- }
- else if (strstr (p, "vAttachOrWait;") == p)
- {
- p += strlen("vAttachOrWait;");
- if (!GetProcessNameFrom_vAttach(p, attach_name))
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachOrWait' pkt");
- }
- const bool ignore_existing = false;
- attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
- }
- else if (strstr (p, "vAttachName;") == p)
- {
- p += strlen("vAttachName;");
- if (!GetProcessNameFrom_vAttach(p, attach_name))
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt");
- }
-
- attach_pid = DNBProcessAttachByName (attach_name.c_str(), NULL, err_str, sizeof(err_str));
-
- }
- else if (strstr (p, "vAttach;") == p)
- {
- p += strlen("vAttach;");
- char *end = NULL;
- pid_attaching_to = static_cast<int>(strtoul (p, &end, 16)); // PID will be in hex, so use base 16 to decode
- if (p != end && *end == '\0')
- {
- // Wait at most 30 second for attach
- struct timespec attach_timeout_abstime;
- DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
- attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime, err_str, sizeof(err_str));
- }
- }
- else
- {
- return HandlePacket_UNIMPLEMENTED(p);
- }
-
-
- if (attach_pid != INVALID_NUB_PROCESS)
- {
- if (m_ctx.ProcessID() != attach_pid)
- m_ctx.SetProcessID(attach_pid);
- // Send a stop reply packet to indicate we successfully attached!
- NotifyThatProcessStopped ();
- return rnb_success;
- }
- else
- {
- m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
- if (err_str[0])
- m_ctx.LaunchStatus().SetErrorString(err_str);
- else
- m_ctx.LaunchStatus().SetErrorString("attach failed");
-
-#if defined (__APPLE__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000)
- if (pid_attaching_to == INVALID_NUB_PROCESS && !attach_name.empty())
- {
- pid_attaching_to = DNBProcessGetPIDByName (attach_name.c_str());
- }
- if (pid_attaching_to != INVALID_NUB_PROCESS && strcmp (err_str, "No such process") != 0)
- {
- // csr_check(CSR_ALLOW_TASK_FOR_PID) will be nonzero if System Integrity Protection is in effect.
- if (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0)
- {
- bool attach_failed_due_to_sip = false;
-
- if (rootless_allows_task_for_pid (pid_attaching_to) == 0)
- {
- attach_failed_due_to_sip = true;
- }
-
- if (attach_failed_due_to_sip == false)
- {
- int csops_flags = 0;
- int retval = ::csops (pid_attaching_to, CS_OPS_STATUS, &csops_flags, sizeof (csops_flags));
- if (retval != -1 && (csops_flags & CS_RESTRICT))
- {
- attach_failed_due_to_sip = true;
- }
- }
- if (attach_failed_due_to_sip)
- {
- SendPacket ("E87"); // E87 is the magic value which says that we are not allowed to attach
- DNBLogError ("Attach failed because process does not allow attaching: \"%s\".", err_str);
- return rnb_err;
- }
- }
- }
-
-#endif
-
- SendPacket ("E01"); // E01 is our magic error value for attach failed.
- DNBLogError ("Attach failed: \"%s\".", err_str);
- return rnb_err;
- }
- }
-
- // All other failures come through here
- return HandlePacket_UNIMPLEMENTED(p);
-}
+// QRestoreRegisterState:1;thread:1E34; (when thread suffix is
+// supported)
+// QRestoreRegisterState:1 (when thread suffix is NOT
+// supported)
+
+rnb_err_t RNBRemote::HandlePacket_RestoreRegisterState(const char *p) {
+ nub_process_t pid = m_ctx.ProcessID();
+ nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
+ if (tid == INVALID_NUB_THREAD) {
+ if (m_thread_suffix_supported)
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p,
+ "No thread specified in QSaveRegisterState packet");
+ else
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "No thread was is set with the Hg packet");
+ }
+
+ StdStringExtractor packet(p);
+ packet.SetFilePos(
+ strlen("QRestoreRegisterState:")); // Skip the "QRestoreRegisterState:"
+ const uint32_t save_id = packet.GetU32(0);
-/* 'T XX' -- status of thread
- Check if the specified thread is alive.
- The thread number is in hex? */
+ if (save_id != 0) {
+ // Get the register context size first by calling with NULL buffer
+ if (DNBThreadRestoreRegisterState(pid, tid, save_id))
+ return SendPacket("OK");
+ else
+ return SendPacket("E77");
+ }
+ return SendPacket("E76");
+}
+
+static bool GetProcessNameFrom_vAttach(const char *&p,
+ std::string &attach_name) {
+ bool return_val = true;
+ while (*p != '\0') {
+ char smallbuf[3];
+ smallbuf[0] = *p;
+ smallbuf[1] = *(p + 1);
+ smallbuf[2] = '\0';
-rnb_err_t
-RNBRemote::HandlePacket_T (const char *p)
-{
- p++;
- if (p == NULL || *p == '\0')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in T packet");
- }
- if (!m_ctx.HasValidProcessID())
- {
- return SendPacket ("E15");
- }
errno = 0;
- nub_thread_t tid = strtoul (p, NULL, 16);
- if (errno != 0 && tid == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in T packet");
- }
+ int ch = static_cast<int>(strtoul(smallbuf, NULL, 16));
+ if (errno != 0 && ch == 0) {
+ return_val = false;
+ break;
+ }
+
+ attach_name.push_back(ch);
+ p += 2;
+ }
+ return return_val;
+}
+
+rnb_err_t RNBRemote::HandlePacket_qSupported(const char *p) {
+ uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet
+ // size--debugger can always use less
+ char buf[256];
+ snprintf(buf, sizeof(buf), "qXfer:features:read+;PacketSize=%x;qEcho+",
+ max_packet_size);
+
+ // By default, don't enable compression. It's only worth doing when we are
+ // working
+ // with a low speed communication channel.
+ bool enable_compression = false;
+ (void)enable_compression;
+
+// Enable compression when debugserver is running on a watchOS device where
+// communication may be over Bluetooth.
+#if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+ enable_compression = true;
+#endif
- nub_state_t state = DNBThreadGetState (m_ctx.ProcessID(), tid);
- if (state == eStateInvalid || state == eStateExited || state == eStateCrashed)
- {
- return SendPacket ("E16");
- }
+#if defined(HAVE_LIBCOMPRESSION)
+ // libcompression is weak linked so test if compression_decode_buffer() is
+ // available
+ if (enable_compression && compression_decode_buffer != NULL) {
+ strcat(buf, ";SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;"
+ "DefaultCompressionMinSize=");
+ char numbuf[16];
+ snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize);
+ numbuf[sizeof(numbuf) - 1] = '\0';
+ strcat(buf, numbuf);
+ }
+#elif defined(HAVE_LIBZ)
+ if (enable_compression) {
+ strcat(buf,
+ ";SupportedCompressions=zlib-deflate;DefaultCompressionMinSize=");
+ char numbuf[16];
+ snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize);
+ numbuf[sizeof(numbuf) - 1] = '\0';
+ strcat(buf, numbuf);
+ }
+#endif
- return SendPacket ("OK");
+ return SendPacket(buf);
}
+/*
+ vAttach;pid
-rnb_err_t
-RNBRemote::HandlePacket_z (const char *p)
-{
- if (p == NULL || *p == '\0')
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in z packet");
+ Attach to a new process with the specified process ID. pid is a hexadecimal
+ integer
+ identifying the process. If the stub is currently controlling a process, it is
+ killed. The attached process is stopped.This packet is only available in
+ extended
+ mode (see extended mode).
- if (!m_ctx.HasValidProcessID())
- return SendPacket ("E15");
+ Reply:
+ "ENN" for an error
+ "Any Stop Reply Packet" for success
+ */
- char packet_cmd = *p++;
- char break_type = *p++;
+rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
+ if (strcmp(p, "vCont;c") == 0) {
+ // Simple continue
+ return RNBRemote::HandlePacket_c("c");
+ } else if (strcmp(p, "vCont;s") == 0) {
+ // Simple step
+ return RNBRemote::HandlePacket_s("s");
+ } else if (strstr(p, "vCont") == p) {
+ DNBThreadResumeActions thread_actions;
+ char *c = (char *)(p += strlen("vCont"));
+ char *c_end = c + strlen(c);
+ if (*c == '?')
+ return SendPacket("vCont;c;C;s;S");
+
+ while (c < c_end && *c == ';') {
+ ++c; // Skip the semi-colon
+ DNBThreadResumeAction thread_action;
+ thread_action.tid = INVALID_NUB_THREAD;
+ thread_action.state = eStateInvalid;
+ thread_action.signal = 0;
+ thread_action.addr = INVALID_NUB_ADDRESS;
- if (*p++ != ',')
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
+ char action = *c++;
- char *c = NULL;
- nub_process_t pid = m_ctx.ProcessID();
- errno = 0;
- nub_addr_t addr = strtoull (p, &c, 16);
- if (errno != 0 && addr == 0)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in z packet");
- p = c;
- if (*p++ != ',')
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
+ switch (action) {
+ case 'C':
+ errno = 0;
+ thread_action.signal = static_cast<int>(strtoul(c, &c, 16));
+ if (errno != 0)
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p, "Could not parse signal in vCont packet");
+ // Fall through to next case...
+
+ case 'c':
+ // Continue
+ thread_action.state = eStateRunning;
+ break;
- errno = 0;
- auto byte_size = strtoul (p, &c, 16);
- if (errno != 0 && byte_size == 0)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in z packet");
+ case 'S':
+ errno = 0;
+ thread_action.signal = static_cast<int>(strtoul(c, &c, 16));
+ if (errno != 0)
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p, "Could not parse signal in vCont packet");
+ // Fall through to next case...
+
+ case 's':
+ // Step
+ thread_action.state = eStateStepping;
+ break;
- if (packet_cmd == 'Z')
- {
- // set
- switch (break_type)
- {
- case '0': // set software breakpoint
- case '1': // set hardware breakpoint
- {
- // gdb can send multiple Z packets for the same address and
- // these calls must be ref counted.
- bool hardware = (break_type == '1');
-
- if (DNBBreakpointSet (pid, addr, byte_size, hardware))
- {
- // We successfully created a breakpoint, now lets full out
- // a ref count structure with the breakID and add it to our
- // map.
- return SendPacket ("OK");
- }
- else
- {
- // We failed to set the software breakpoint
- return SendPacket ("E09");
- }
- }
- break;
+ default:
+ HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Unsupported action in vCont packet");
+ break;
+ }
+ if (*c == ':') {
+ errno = 0;
+ thread_action.tid = strtoul(++c, &c, 16);
+ if (errno != 0)
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p,
+ "Could not parse thread number in vCont packet");
+ }
- case '2': // set write watchpoint
- case '3': // set read watchpoint
- case '4': // set access watchpoint
- {
- bool hardware = true;
- uint32_t watch_flags = 0;
- if (break_type == '2')
- watch_flags = WATCH_TYPE_WRITE;
- else if (break_type == '3')
- watch_flags = WATCH_TYPE_READ;
- else
- watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
+ thread_actions.Append(thread_action);
+ }
- if (DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware))
- {
- return SendPacket ("OK");
- }
- else
- {
- // We failed to set the watchpoint
- return SendPacket ("E09");
- }
- }
- break;
+ // If a default action for all other threads wasn't mentioned
+ // then we should stop the threads
+ thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
+ DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst(),
+ thread_actions.GetSize());
+ return rnb_success;
+ } else if (strstr(p, "vAttach") == p) {
+ nub_process_t attach_pid =
+ INVALID_NUB_PROCESS; // attach_pid will be set to 0 if the attach fails
+ nub_process_t pid_attaching_to =
+ INVALID_NUB_PROCESS; // pid_attaching_to is the original pid specified
+ char err_str[1024] = {'\0'};
+ std::string attach_name;
+
+ if (strstr(p, "vAttachWait;") == p) {
+ p += strlen("vAttachWait;");
+ if (!GetProcessNameFrom_vAttach(p, attach_name)) {
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
+ }
+ const bool ignore_existing = true;
+ attach_pid = DNBProcessAttachWait(
+ attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL,
+ 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
+
+ } else if (strstr(p, "vAttachOrWait;") == p) {
+ p += strlen("vAttachOrWait;");
+ if (!GetProcessNameFrom_vAttach(p, attach_name)) {
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p,
+ "non-hex char in arg on 'vAttachOrWait' pkt");
+ }
+ const bool ignore_existing = false;
+ attach_pid = DNBProcessAttachWait(
+ attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL,
+ 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
+ } else if (strstr(p, "vAttachName;") == p) {
+ p += strlen("vAttachName;");
+ if (!GetProcessNameFrom_vAttach(p, attach_name)) {
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt");
+ }
- default:
- break;
- }
+ attach_pid = DNBProcessAttachByName(attach_name.c_str(), NULL, err_str,
+ sizeof(err_str));
+
+ } else if (strstr(p, "vAttach;") == p) {
+ p += strlen("vAttach;");
+ char *end = NULL;
+ pid_attaching_to = static_cast<int>(
+ strtoul(p, &end, 16)); // PID will be in hex, so use base 16 to decode
+ if (p != end && *end == '\0') {
+ // Wait at most 30 second for attach
+ struct timespec attach_timeout_abstime;
+ DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
+ attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime,
+ err_str, sizeof(err_str));
+ }
+ } else {
+ return HandlePacket_UNIMPLEMENTED(p);
}
- else if (packet_cmd == 'z')
- {
- // remove
- switch (break_type)
- {
- case '0': // remove software breakpoint
- case '1': // remove hardware breakpoint
- if (DNBBreakpointClear (pid, addr))
- {
- return SendPacket ("OK");
- }
- else
- {
- return SendPacket ("E08");
- }
- break;
- case '2': // remove write watchpoint
- case '3': // remove read watchpoint
- case '4': // remove access watchpoint
- if (DNBWatchpointClear (pid, addr))
- {
- return SendPacket ("OK");
- }
- else
- {
- return SendPacket ("E08");
- }
- break;
+ if (attach_pid != INVALID_NUB_PROCESS) {
+ if (m_ctx.ProcessID() != attach_pid)
+ m_ctx.SetProcessID(attach_pid);
+ // Send a stop reply packet to indicate we successfully attached!
+ NotifyThatProcessStopped();
+ return rnb_success;
+ } else {
+ m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
+ if (err_str[0])
+ m_ctx.LaunchStatus().SetErrorString(err_str);
+ else
+ m_ctx.LaunchStatus().SetErrorString("attach failed");
+
+#if defined(__APPLE__) && \
+ (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000)
+ if (pid_attaching_to == INVALID_NUB_PROCESS && !attach_name.empty()) {
+ pid_attaching_to = DNBProcessGetPIDByName(attach_name.c_str());
+ }
+ if (pid_attaching_to != INVALID_NUB_PROCESS &&
+ strcmp(err_str, "No such process") != 0) {
+ // csr_check(CSR_ALLOW_TASK_FOR_PID) will be nonzero if System Integrity
+ // Protection is in effect.
+ if (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0) {
+ bool attach_failed_due_to_sip = false;
- default:
- break;
- }
- }
- return HandlePacket_UNIMPLEMENTED(p);
-}
+ if (rootless_allows_task_for_pid(pid_attaching_to) == 0) {
+ attach_failed_due_to_sip = true;
+ }
-// Extract the thread number from the thread suffix that might be appended to
-// thread specific packets. This will only be enabled if m_thread_suffix_supported
-// is true.
-nub_thread_t
-RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p)
-{
- if (m_thread_suffix_supported)
- {
- nub_thread_t tid = INVALID_NUB_THREAD;
- if (p)
- {
- const char *tid_cstr = strstr (p, "thread:");
- if (tid_cstr)
- {
- tid_cstr += strlen ("thread:");
- tid = strtoul(tid_cstr, NULL, 16);
+ if (attach_failed_due_to_sip == false) {
+ int csops_flags = 0;
+ int retval = ::csops(pid_attaching_to, CS_OPS_STATUS, &csops_flags,
+ sizeof(csops_flags));
+ if (retval != -1 && (csops_flags & CS_RESTRICT)) {
+ attach_failed_due_to_sip = true;
}
+ }
+ if (attach_failed_due_to_sip) {
+ SendPacket("E87"); // E87 is the magic value which says that we are
+ // not allowed to attach
+ DNBLogError("Attach failed because process does not allow "
+ "attaching: \"%s\".",
+ err_str);
+ return rnb_err;
+ }
}
- return tid;
+ }
+
+#endif
+
+ SendPacket("E01"); // E01 is our magic error value for attach failed.
+ DNBLogError("Attach failed: \"%s\".", err_str);
+ return rnb_err;
}
- return GetCurrentThread();
+ }
+ // All other failures come through here
+ return HandlePacket_UNIMPLEMENTED(p);
}
-/* 'p XX'
- print the contents of register X */
+/* 'T XX' -- status of thread
+ Check if the specified thread is alive.
+ The thread number is in hex? */
-rnb_err_t
-RNBRemote::HandlePacket_p (const char *p)
-{
- if (g_num_reg_entries == 0)
- InitializeRegisters ();
+rnb_err_t RNBRemote::HandlePacket_T(const char *p) {
+ p++;
+ if (p == NULL || *p == '\0') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "No thread specified in T packet");
+ }
+ if (!m_ctx.HasValidProcessID()) {
+ return SendPacket("E15");
+ }
+ errno = 0;
+ nub_thread_t tid = strtoul(p, NULL, 16);
+ if (errno != 0 && tid == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Could not parse thread number in T packet");
+ }
+
+ nub_state_t state = DNBThreadGetState(m_ctx.ProcessID(), tid);
+ if (state == eStateInvalid || state == eStateExited ||
+ state == eStateCrashed) {
+ return SendPacket("E16");
+ }
+
+ return SendPacket("OK");
+}
+
+rnb_err_t RNBRemote::HandlePacket_z(const char *p) {
+ if (p == NULL || *p == '\0')
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "No thread specified in z packet");
+
+ if (!m_ctx.HasValidProcessID())
+ return SendPacket("E15");
+
+ char packet_cmd = *p++;
+ char break_type = *p++;
+
+ if (*p++ != ',')
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Comma separator missing in z packet");
+
+ char *c = NULL;
+ nub_process_t pid = m_ctx.ProcessID();
+ errno = 0;
+ nub_addr_t addr = strtoull(p, &c, 16);
+ if (errno != 0 && addr == 0)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid address in z packet");
+ p = c;
+ if (*p++ != ',')
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Comma separator missing in z packet");
+
+ errno = 0;
+ auto byte_size = strtoul(p, &c, 16);
+ if (errno != 0 && byte_size == 0)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Invalid length in z packet");
+
+ if (packet_cmd == 'Z') {
+ // set
+ switch (break_type) {
+ case '0': // set software breakpoint
+ case '1': // set hardware breakpoint
+ {
+ // gdb can send multiple Z packets for the same address and
+ // these calls must be ref counted.
+ bool hardware = (break_type == '1');
+
+ if (DNBBreakpointSet(pid, addr, byte_size, hardware)) {
+ // We successfully created a breakpoint, now lets full out
+ // a ref count structure with the breakID and add it to our
+ // map.
+ return SendPacket("OK");
+ } else {
+ // We failed to set the software breakpoint
+ return SendPacket("E09");
+ }
+ } break;
- if (p == NULL || *p == '\0')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
- }
- if (!m_ctx.HasValidProcessID())
- {
- return SendPacket ("E15");
- }
- nub_process_t pid = m_ctx.ProcessID();
- errno = 0;
- char *tid_cstr = NULL;
- uint32_t reg = static_cast<uint32_t>(strtoul (p + 1, &tid_cstr, 16));
- if (errno != 0 && reg == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse register number in p packet");
- }
+ case '2': // set write watchpoint
+ case '3': // set read watchpoint
+ case '4': // set access watchpoint
+ {
+ bool hardware = true;
+ uint32_t watch_flags = 0;
+ if (break_type == '2')
+ watch_flags = WATCH_TYPE_WRITE;
+ else if (break_type == '3')
+ watch_flags = WATCH_TYPE_READ;
+ else
+ watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
- nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr);
- if (tid == INVALID_NUB_THREAD)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
+ if (DNBWatchpointSet(pid, addr, byte_size, watch_flags, hardware)) {
+ return SendPacket("OK");
+ } else {
+ // We failed to set the watchpoint
+ return SendPacket("E09");
+ }
+ } break;
- const register_map_entry_t *reg_entry;
+ default:
+ break;
+ }
+ } else if (packet_cmd == 'z') {
+ // remove
+ switch (break_type) {
+ case '0': // remove software breakpoint
+ case '1': // remove hardware breakpoint
+ if (DNBBreakpointClear(pid, addr)) {
+ return SendPacket("OK");
+ } else {
+ return SendPacket("E08");
+ }
+ break;
- if (reg < g_num_reg_entries)
- reg_entry = &g_reg_entries[reg];
- else
- reg_entry = NULL;
+ case '2': // remove write watchpoint
+ case '3': // remove read watchpoint
+ case '4': // remove access watchpoint
+ if (DNBWatchpointClear(pid, addr)) {
+ return SendPacket("OK");
+ } else {
+ return SendPacket("E08");
+ }
+ break;
- std::ostringstream ostrm;
- if (reg_entry == NULL)
- {
- DNBLogError("RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", p, reg);
- ostrm << "00000000";
- }
- else if (reg_entry->nub_info.reg == (uint32_t)-1)
- {
- if (reg_entry->nub_info.size > 0)
- {
- std::basic_string<uint8_t> zeros(reg_entry->nub_info.size, '\0');
- append_hex_value(ostrm, zeros.data(), zeros.size(), false);
- }
- }
- else
- {
- register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry, NULL);
+ default:
+ break;
}
- return SendPacket (ostrm.str());
+ }
+ return HandlePacket_UNIMPLEMENTED(p);
}
-/* 'Pnn=rrrrr'
- Set register number n to value r.
- n and r are hex strings. */
-
-rnb_err_t
-RNBRemote::HandlePacket_P (const char *p)
-{
- if (g_num_reg_entries == 0)
- InitializeRegisters ();
-
- if (p == NULL || *p == '\0')
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Empty P packet");
- }
- if (!m_ctx.HasValidProcessID())
- {
- return SendPacket ("E28");
+// Extract the thread number from the thread suffix that might be appended to
+// thread specific packets. This will only be enabled if
+// m_thread_suffix_supported
+// is true.
+nub_thread_t RNBRemote::ExtractThreadIDFromThreadSuffix(const char *p) {
+ if (m_thread_suffix_supported) {
+ nub_thread_t tid = INVALID_NUB_THREAD;
+ if (p) {
+ const char *tid_cstr = strstr(p, "thread:");
+ if (tid_cstr) {
+ tid_cstr += strlen("thread:");
+ tid = strtoul(tid_cstr, NULL, 16);
+ }
}
+ return tid;
+ }
+ return GetCurrentThread();
+}
- nub_process_t pid = m_ctx.ProcessID();
-
- StdStringExtractor packet (p);
-
- const char cmd_char = packet.GetChar();
- // Register ID is always in big endian
- const uint32_t reg = packet.GetHexMaxU32 (false, UINT32_MAX);
- const char equal_char = packet.GetChar();
-
- if (cmd_char != 'P')
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Improperly formed P packet");
-
- if (reg == UINT32_MAX)
- return SendPacket ("E29");
-
- if (equal_char != '=')
- return SendPacket ("E30");
+/* 'p XX'
+ print the contents of register X */
- const register_map_entry_t *reg_entry;
+rnb_err_t RNBRemote::HandlePacket_p(const char *p) {
+ if (g_num_reg_entries == 0)
+ InitializeRegisters();
+
+ if (p == NULL || *p == '\0') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "No thread specified in p packet");
+ }
+ if (!m_ctx.HasValidProcessID()) {
+ return SendPacket("E15");
+ }
+ nub_process_t pid = m_ctx.ProcessID();
+ errno = 0;
+ char *tid_cstr = NULL;
+ uint32_t reg = static_cast<uint32_t>(strtoul(p + 1, &tid_cstr, 16));
+ if (errno != 0 && reg == 0) {
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p, "Could not parse register number in p packet");
+ }
+
+ nub_thread_t tid = ExtractThreadIDFromThreadSuffix(tid_cstr);
+ if (tid == INVALID_NUB_THREAD)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "No thread specified in p packet");
- if (reg >= g_num_reg_entries)
- return SendPacket("E47");
+ const register_map_entry_t *reg_entry;
+ if (reg < g_num_reg_entries)
reg_entry = &g_reg_entries[reg];
+ else
+ reg_entry = NULL;
- if (reg_entry->nub_info.set == (uint32_t)-1 && reg_entry->nub_info.reg == (uint32_t)-1)
- {
- DNBLogError("RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", p, reg);
- return SendPacket("E48");
- }
-
- DNBRegisterValue reg_value;
- reg_value.info = reg_entry->nub_info;
- packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->nub_info.size, 0xcc);
+ std::ostringstream ostrm;
+ if (reg_entry == NULL) {
+ DNBLogError(
+ "RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n",
+ p, reg);
+ ostrm << "00000000";
+ } else if (reg_entry->nub_info.reg == (uint32_t)-1) {
+ if (reg_entry->nub_info.size > 0) {
+ std::basic_string<uint8_t> zeros(reg_entry->nub_info.size, '\0');
+ append_hex_value(ostrm, zeros.data(), zeros.size(), false);
+ }
+ } else {
+ register_value_in_hex_fixed_width(ostrm, pid, tid, reg_entry, NULL);
+ }
+ return SendPacket(ostrm.str());
+}
- nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
- if (tid == INVALID_NUB_THREAD)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
+/* 'Pnn=rrrrr'
+ Set register number n to value r.
+ n and r are hex strings. */
- if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, ®_value))
- {
- return SendPacket ("E32");
- }
- return SendPacket ("OK");
+rnb_err_t RNBRemote::HandlePacket_P(const char *p) {
+ if (g_num_reg_entries == 0)
+ InitializeRegisters();
+
+ if (p == NULL || *p == '\0') {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Empty P packet");
+ }
+ if (!m_ctx.HasValidProcessID()) {
+ return SendPacket("E28");
+ }
+
+ nub_process_t pid = m_ctx.ProcessID();
+
+ StdStringExtractor packet(p);
+
+ const char cmd_char = packet.GetChar();
+ // Register ID is always in big endian
+ const uint32_t reg = packet.GetHexMaxU32(false, UINT32_MAX);
+ const char equal_char = packet.GetChar();
+
+ if (cmd_char != 'P')
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Improperly formed P packet");
+
+ if (reg == UINT32_MAX)
+ return SendPacket("E29");
+
+ if (equal_char != '=')
+ return SendPacket("E30");
+
+ const register_map_entry_t *reg_entry;
+
+ if (reg >= g_num_reg_entries)
+ return SendPacket("E47");
+
+ reg_entry = &g_reg_entries[reg];
+
+ if (reg_entry->nub_info.set == (uint32_t)-1 &&
+ reg_entry->nub_info.reg == (uint32_t)-1) {
+ DNBLogError(
+ "RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n",
+ p, reg);
+ return SendPacket("E48");
+ }
+
+ DNBRegisterValue reg_value;
+ reg_value.info = reg_entry->nub_info;
+ packet.GetHexBytes(reg_value.value.v_sint8, reg_entry->nub_info.size, 0xcc);
+
+ nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
+ if (tid == INVALID_NUB_THREAD)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "No thread specified in p packet");
+
+ if (!DNBThreadSetRegisterValueByID(pid, tid, reg_entry->nub_info.set,
+ reg_entry->nub_info.reg, ®_value)) {
+ return SendPacket("E32");
+ }
+ return SendPacket("OK");
}
/* 'c [addr]'
Continue, optionally from a specified address. */
-rnb_err_t
-RNBRemote::HandlePacket_c (const char *p)
-{
- const nub_process_t pid = m_ctx.ProcessID();
-
- if (pid == INVALID_NUB_PROCESS)
- return SendPacket ("E23");
-
- DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
-
- if (*(p + 1) != '\0')
- {
- action.tid = GetContinueThread();
- errno = 0;
- action.addr = strtoull (p + 1, NULL, 16);
- if (errno != 0 && action.addr == 0)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in c packet");
- }
+rnb_err_t RNBRemote::HandlePacket_c(const char *p) {
+ const nub_process_t pid = m_ctx.ProcessID();
- DNBThreadResumeActions thread_actions;
- thread_actions.Append(action);
- thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
- if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
- return SendPacket ("E25");
- // Don't send an "OK" packet; response is the stopped/exited message.
- return rnb_success;
-}
+ if (pid == INVALID_NUB_PROCESS)
+ return SendPacket("E23");
-rnb_err_t
-RNBRemote::HandlePacket_MemoryRegionInfo (const char *p)
-{
- /* This packet will find memory attributes (e.g. readable, writable, executable, stack, jitted code)
- for the memory region containing a given address and return that information.
-
- Users of this packet must be prepared for three results:
-
- Region information is returned
- Region information is unavailable for this address because the address is in unmapped memory
- Region lookup cannot be performed on this platform or process is not yet launched
- This packet isn't implemented
-
- Examples of use:
- qMemoryRegionInfo:3a55140
- start:3a50000,size:100000,permissions:rwx
-
- qMemoryRegionInfo:0
- error:address in unmapped region
-
- qMemoryRegionInfo:3a551140 (on a different platform)
- error:region lookup cannot be performed
-
- qMemoryRegionInfo
- OK // this packet is implemented by the remote nub
- */
-
- p += sizeof ("qMemoryRegionInfo") - 1;
- if (*p == '\0')
- return SendPacket ("OK");
- if (*p++ != ':')
- return SendPacket ("E67");
- if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
- p += 2;
+ DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
+ INVALID_NUB_ADDRESS};
+ if (*(p + 1) != '\0') {
+ action.tid = GetContinueThread();
errno = 0;
- uint64_t address = strtoul (p, NULL, 16);
- if (errno != 0 && address == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet");
- }
+ action.addr = strtoull(p + 1, NULL, 16);
+ if (errno != 0 && action.addr == 0)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Could not parse address in c packet");
+ }
+
+ DNBThreadResumeActions thread_actions;
+ thread_actions.Append(action);
+ thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
+ if (!DNBProcessResume(pid, thread_actions.GetFirst(),
+ thread_actions.GetSize()))
+ return SendPacket("E25");
+ // Don't send an "OK" packet; response is the stopped/exited message.
+ return rnb_success;
+}
+
+rnb_err_t RNBRemote::HandlePacket_MemoryRegionInfo(const char *p) {
+ /* This packet will find memory attributes (e.g. readable, writable,
+ executable, stack, jitted code)
+ for the memory region containing a given address and return that
+ information.
+
+ Users of this packet must be prepared for three results:
+
+ Region information is returned
+ Region information is unavailable for this address because the address
+ is in unmapped memory
+ Region lookup cannot be performed on this platform or process is not
+ yet launched
+ This packet isn't implemented
+
+ Examples of use:
+ qMemoryRegionInfo:3a55140
+ start:3a50000,size:100000,permissions:rwx
+
+ qMemoryRegionInfo:0
+ error:address in unmapped region
+
+ qMemoryRegionInfo:3a551140 (on a different platform)
+ error:region lookup cannot be performed
+
+ qMemoryRegionInfo
+ OK // this packet is implemented by the remote nub
+ */
- DNBRegionInfo region_info = { 0, 0, 0 };
- DNBProcessMemoryRegionInfo (m_ctx.ProcessID(), address, ®ion_info);
- std::ostringstream ostrm;
-
- // start:3a50000,size:100000,permissions:rwx
- ostrm << "start:" << std::hex << region_info.addr << ';';
-
- if (region_info.size > 0)
- ostrm << "size:" << std::hex << region_info.size << ';';
-
- if (region_info.permissions)
- {
- ostrm << "permissions:";
-
- if (region_info.permissions & eMemoryPermissionsReadable)
- ostrm << 'r';
- if (region_info.permissions & eMemoryPermissionsWritable)
- ostrm << 'w';
- if (region_info.permissions & eMemoryPermissionsExecutable)
- ostrm << 'x';
- ostrm << ';';
- }
- return SendPacket (ostrm.str());
+ p += sizeof("qMemoryRegionInfo") - 1;
+ if (*p == '\0')
+ return SendPacket("OK");
+ if (*p++ != ':')
+ return SendPacket("E67");
+ if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
+ p += 2;
+
+ errno = 0;
+ uint64_t address = strtoul(p, NULL, 16);
+ if (errno != 0 && address == 0) {
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet");
+ }
+
+ DNBRegionInfo region_info = {0, 0, 0};
+ DNBProcessMemoryRegionInfo(m_ctx.ProcessID(), address, ®ion_info);
+ std::ostringstream ostrm;
+
+ // start:3a50000,size:100000,permissions:rwx
+ ostrm << "start:" << std::hex << region_info.addr << ';';
+
+ if (region_info.size > 0)
+ ostrm << "size:" << std::hex << region_info.size << ';';
+
+ if (region_info.permissions) {
+ ostrm << "permissions:";
+
+ if (region_info.permissions & eMemoryPermissionsReadable)
+ ostrm << 'r';
+ if (region_info.permissions & eMemoryPermissionsWritable)
+ ostrm << 'w';
+ if (region_info.permissions & eMemoryPermissionsExecutable)
+ ostrm << 'x';
+ ostrm << ';';
+ }
+ return SendPacket(ostrm.str());
}
// qGetProfileData;scan_type:0xYYYYYYY
-rnb_err_t
-RNBRemote::HandlePacket_GetProfileData (const char *p)
-{
- nub_process_t pid = m_ctx.ProcessID();
- if (pid == INVALID_NUB_PROCESS)
- return SendPacket ("OK");
-
- StdStringExtractor packet(p += sizeof ("qGetProfileData"));
- DNBProfileDataScanType scan_type = eProfileAll;
- std::string name;
- std::string value;
- while (packet.GetNameColonValue(name, value))
- {
- if (name.compare ("scan_type") == 0)
- {
- std::istringstream iss(value);
- uint32_t int_value = 0;
- if (iss >> std::hex >> int_value)
- {
- scan_type = (DNBProfileDataScanType)int_value;
- }
- }
- }
-
- std::string data = DNBProcessGetProfileData(pid, scan_type);
- if (!data.empty())
- {
- return SendPacket (data.c_str());
- }
- else
- {
- return SendPacket ("OK");
+rnb_err_t RNBRemote::HandlePacket_GetProfileData(const char *p) {
+ nub_process_t pid = m_ctx.ProcessID();
+ if (pid == INVALID_NUB_PROCESS)
+ return SendPacket("OK");
+
+ StdStringExtractor packet(p += sizeof("qGetProfileData"));
+ DNBProfileDataScanType scan_type = eProfileAll;
+ std::string name;
+ std::string value;
+ while (packet.GetNameColonValue(name, value)) {
+ if (name.compare("scan_type") == 0) {
+ std::istringstream iss(value);
+ uint32_t int_value = 0;
+ if (iss >> std::hex >> int_value) {
+ scan_type = (DNBProfileDataScanType)int_value;
+ }
}
+ }
+
+ std::string data = DNBProcessGetProfileData(pid, scan_type);
+ if (!data.empty()) {
+ return SendPacket(data.c_str());
+ } else {
+ return SendPacket("OK");
+ }
}
// QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY
-rnb_err_t
-RNBRemote::HandlePacket_SetEnableAsyncProfiling (const char *p)
-{
- nub_process_t pid = m_ctx.ProcessID();
- if (pid == INVALID_NUB_PROCESS)
- return SendPacket ("OK");
+rnb_err_t RNBRemote::HandlePacket_SetEnableAsyncProfiling(const char *p) {
+ nub_process_t pid = m_ctx.ProcessID();
+ if (pid == INVALID_NUB_PROCESS)
+ return SendPacket("OK");
- StdStringExtractor packet(p += sizeof ("QSetEnableAsyncProfiling"));
- bool enable = false;
- uint64_t interval_usec = 0;
- DNBProfileDataScanType scan_type = eProfileAll;
- std::string name;
- std::string value;
- while (packet.GetNameColonValue(name, value))
- {
- if (name.compare ("enable") == 0)
- {
- enable = strtoul(value.c_str(), NULL, 10) > 0;
- }
- else if (name.compare ("interval_usec") == 0)
- {
- interval_usec = strtoul(value.c_str(), NULL, 10);
- }
- else if (name.compare ("scan_type") == 0)
- {
- std::istringstream iss(value);
- uint32_t int_value = 0;
- if (iss >> std::hex >> int_value)
- {
- scan_type = (DNBProfileDataScanType)int_value;
- }
- }
- }
-
- if (interval_usec == 0)
- {
- enable = 0;
+ StdStringExtractor packet(p += sizeof("QSetEnableAsyncProfiling"));
+ bool enable = false;
+ uint64_t interval_usec = 0;
+ DNBProfileDataScanType scan_type = eProfileAll;
+ std::string name;
+ std::string value;
+ while (packet.GetNameColonValue(name, value)) {
+ if (name.compare("enable") == 0) {
+ enable = strtoul(value.c_str(), NULL, 10) > 0;
+ } else if (name.compare("interval_usec") == 0) {
+ interval_usec = strtoul(value.c_str(), NULL, 10);
+ } else if (name.compare("scan_type") == 0) {
+ std::istringstream iss(value);
+ uint32_t int_value = 0;
+ if (iss >> std::hex >> int_value) {
+ scan_type = (DNBProfileDataScanType)int_value;
+ }
}
-
- DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type);
- return SendPacket ("OK");
+ }
+
+ if (interval_usec == 0) {
+ enable = 0;
+ }
+
+ DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type);
+ return SendPacket("OK");
}
-// QEnableCompression:type:<COMPRESSION-TYPE>;minsize:<MINIMUM PACKET SIZE TO COMPRESS>;
+// QEnableCompression:type:<COMPRESSION-TYPE>;minsize:<MINIMUM PACKET SIZE TO
+// COMPRESS>;
//
-// type: must be a type previously reported by the qXfer:features: SupportedCompressions list
+// type: must be a type previously reported by the qXfer:features:
+// SupportedCompressions list
//
-// minsize: is optional; by default the qXfer:features: DefaultCompressionMinSize value is used
-// debugserver may have a better idea of what a good minimum packet size to compress is than lldb.
-
-rnb_err_t
-RNBRemote::HandlePacket_QEnableCompression (const char *p)
-{
- p += sizeof ("QEnableCompression:") - 1;
-
- size_t new_compression_minsize = m_compression_minsize;
- const char *new_compression_minsize_str = strstr (p, "minsize:");
- if (new_compression_minsize_str)
- {
- new_compression_minsize_str += strlen ("minsize:");
- errno = 0;
- new_compression_minsize = strtoul (new_compression_minsize_str, NULL, 10);
- if (errno != 0 || new_compression_minsize == ULONG_MAX)
- {
- new_compression_minsize = m_compression_minsize;
- }
- }
-
-#if defined (HAVE_LIBCOMPRESSION)
- if (compression_decode_buffer != NULL)
- {
- if (strstr (p, "type:zlib-deflate;") != nullptr)
- {
- EnableCompressionNextSendPacket (compression_types::zlib_deflate);
- m_compression_minsize = new_compression_minsize;
- return SendPacket ("OK");
- }
- else if (strstr (p, "type:lz4;") != nullptr)
- {
- EnableCompressionNextSendPacket (compression_types::lz4);
- m_compression_minsize = new_compression_minsize;
- return SendPacket ("OK");
- }
- else if (strstr (p, "type:lzma;") != nullptr)
- {
- EnableCompressionNextSendPacket (compression_types::lzma);
- m_compression_minsize = new_compression_minsize;
- return SendPacket ("OK");
- }
- else if (strstr (p, "type:lzfse;") != nullptr)
- {
- EnableCompressionNextSendPacket (compression_types::lzfse);
- m_compression_minsize = new_compression_minsize;
- return SendPacket ("OK");
- }
+// minsize: is optional; by default the qXfer:features:
+// DefaultCompressionMinSize value is used
+// debugserver may have a better idea of what a good minimum packet size to
+// compress is than lldb.
+
+rnb_err_t RNBRemote::HandlePacket_QEnableCompression(const char *p) {
+ p += sizeof("QEnableCompression:") - 1;
+
+ size_t new_compression_minsize = m_compression_minsize;
+ const char *new_compression_minsize_str = strstr(p, "minsize:");
+ if (new_compression_minsize_str) {
+ new_compression_minsize_str += strlen("minsize:");
+ errno = 0;
+ new_compression_minsize = strtoul(new_compression_minsize_str, NULL, 10);
+ if (errno != 0 || new_compression_minsize == ULONG_MAX) {
+ new_compression_minsize = m_compression_minsize;
+ }
+ }
+
+#if defined(HAVE_LIBCOMPRESSION)
+ if (compression_decode_buffer != NULL) {
+ if (strstr(p, "type:zlib-deflate;") != nullptr) {
+ EnableCompressionNextSendPacket(compression_types::zlib_deflate);
+ m_compression_minsize = new_compression_minsize;
+ return SendPacket("OK");
+ } else if (strstr(p, "type:lz4;") != nullptr) {
+ EnableCompressionNextSendPacket(compression_types::lz4);
+ m_compression_minsize = new_compression_minsize;
+ return SendPacket("OK");
+ } else if (strstr(p, "type:lzma;") != nullptr) {
+ EnableCompressionNextSendPacket(compression_types::lzma);
+ m_compression_minsize = new_compression_minsize;
+ return SendPacket("OK");
+ } else if (strstr(p, "type:lzfse;") != nullptr) {
+ EnableCompressionNextSendPacket(compression_types::lzfse);
+ m_compression_minsize = new_compression_minsize;
+ return SendPacket("OK");
}
+ }
#endif
-#if defined (HAVE_LIBZ)
- if (strstr (p, "type:zlib-deflate;") != nullptr)
- {
- EnableCompressionNextSendPacket (compression_types::zlib_deflate);
- m_compression_minsize = new_compression_minsize;
- return SendPacket ("OK");
- }
+#if defined(HAVE_LIBZ)
+ if (strstr(p, "type:zlib-deflate;") != nullptr) {
+ EnableCompressionNextSendPacket(compression_types::zlib_deflate);
+ m_compression_minsize = new_compression_minsize;
+ return SendPacket("OK");
+ }
#endif
- return SendPacket ("E88");
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qSpeedTest (const char *p)
-{
- p += strlen ("qSpeedTest:response_size:");
- char *end = NULL;
- errno = 0;
- uint64_t response_size = ::strtoul (p, &end, 16);
- if (errno != 0)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Didn't find response_size value at right offset");
- else if (*end == ';')
- {
- static char g_data[4*1024*1024+16] = "data:";
- memset(g_data + 5, 'a', response_size);
- g_data[response_size + 5] = '\0';
- return SendPacket (g_data);
- }
- else
- {
- return SendPacket ("E79");
- }
+ return SendPacket("E88");
}
-rnb_err_t
-RNBRemote::HandlePacket_WatchpointSupportInfo (const char *p)
-{
- /* This packet simply returns the number of supported hardware watchpoints.
-
- Examples of use:
- qWatchpointSupportInfo:
- num:4
-
- qWatchpointSupportInfo
- OK // this packet is implemented by the remote nub
- */
-
- p += sizeof ("qWatchpointSupportInfo") - 1;
- if (*p == '\0')
- return SendPacket ("OK");
- if (*p++ != ':')
- return SendPacket ("E67");
+rnb_err_t RNBRemote::HandlePacket_qSpeedTest(const char *p) {
+ p += strlen("qSpeedTest:response_size:");
+ char *end = NULL;
+ errno = 0;
+ uint64_t response_size = ::strtoul(p, &end, 16);
+ if (errno != 0)
+ return HandlePacket_ILLFORMED(
+ __FILE__, __LINE__, p,
+ "Didn't find response_size value at right offset");
+ else if (*end == ';') {
+ static char g_data[4 * 1024 * 1024 + 16] = "data:";
+ memset(g_data + 5, 'a', response_size);
+ g_data[response_size + 5] = '\0';
+ return SendPacket(g_data);
+ } else {
+ return SendPacket("E79");
+ }
+}
+
+rnb_err_t RNBRemote::HandlePacket_WatchpointSupportInfo(const char *p) {
+ /* This packet simply returns the number of supported hardware watchpoints.
+
+ Examples of use:
+ qWatchpointSupportInfo:
+ num:4
+
+ qWatchpointSupportInfo
+ OK // this packet is implemented by the remote nub
+ */
- errno = 0;
- uint32_t num = DNBWatchpointGetNumSupportedHWP (m_ctx.ProcessID());
- std::ostringstream ostrm;
+ p += sizeof("qWatchpointSupportInfo") - 1;
+ if (*p == '\0')
+ return SendPacket("OK");
+ if (*p++ != ':')
+ return SendPacket("E67");
- // size:4
- ostrm << "num:" << std::dec << num << ';';
- return SendPacket (ostrm.str());
+ errno = 0;
+ uint32_t num = DNBWatchpointGetNumSupportedHWP(m_ctx.ProcessID());
+ std::ostringstream ostrm;
+
+ // size:4
+ ostrm << "num:" << std::dec << num << ';';
+ return SendPacket(ostrm.str());
}
/* 'C sig [;addr]'
Resume with signal sig, optionally at address addr. */
-rnb_err_t
-RNBRemote::HandlePacket_C (const char *p)
-{
- const nub_process_t pid = m_ctx.ProcessID();
-
- if (pid == INVALID_NUB_PROCESS)
- return SendPacket ("E36");
-
- DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
- int process_signo = -1;
- if (*(p + 1) != '\0')
- {
- action.tid = GetContinueThread();
- char *end = NULL;
- errno = 0;
- process_signo = static_cast<int>(strtoul (p + 1, &end, 16));
- if (errno != 0)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in C packet");
- else if (*end == ';')
- {
- errno = 0;
- action.addr = strtoull (end + 1, NULL, 16);
- if (errno != 0 && action.addr == 0)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in C packet");
- }
- }
+rnb_err_t RNBRemote::HandlePacket_C(const char *p) {
+ const nub_process_t pid = m_ctx.ProcessID();
- DNBThreadResumeActions thread_actions;
- thread_actions.Append (action);
- thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, action.signal);
- if (!DNBProcessSignal(pid, process_signo))
- return SendPacket ("E52");
- if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
- return SendPacket ("E38");
- /* Don't send an "OK" packet; response is the stopped/exited message. */
- return rnb_success;
+ if (pid == INVALID_NUB_PROCESS)
+ return SendPacket("E36");
+
+ DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0,
+ INVALID_NUB_ADDRESS};
+ int process_signo = -1;
+ if (*(p + 1) != '\0') {
+ action.tid = GetContinueThread();
+ char *end = NULL;
+ errno = 0;
+ process_signo = static_cast<int>(strtoul(p + 1, &end, 16));
+ if (errno != 0)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Could not parse signal in C packet");
+ else if (*end == ';') {
+ errno = 0;
+ action.addr = strtoull(end + 1, NULL, 16);
+ if (errno != 0 && action.addr == 0)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Could not parse address in C packet");
+ }
+ }
+
+ DNBThreadResumeActions thread_actions;
+ thread_actions.Append(action);
+ thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, action.signal);
+ if (!DNBProcessSignal(pid, process_signo))
+ return SendPacket("E52");
+ if (!DNBProcessResume(pid, thread_actions.GetFirst(),
+ thread_actions.GetSize()))
+ return SendPacket("E38");
+ /* Don't send an "OK" packet; response is the stopped/exited message. */
+ return rnb_success;
}
//----------------------------------------------------------------------
// 'D' packet
// Detach from gdb.
//----------------------------------------------------------------------
-rnb_err_t
-RNBRemote::HandlePacket_D (const char *p)
-{
- if (m_ctx.HasValidProcessID())
- {
- if (DNBProcessDetach(m_ctx.ProcessID()))
- SendPacket ("OK");
- else
- SendPacket ("E");
- }
+rnb_err_t RNBRemote::HandlePacket_D(const char *p) {
+ if (m_ctx.HasValidProcessID()) {
+ if (DNBProcessDetach(m_ctx.ProcessID()))
+ SendPacket("OK");
else
- {
- SendPacket ("E");
- }
- return rnb_success;
+ SendPacket("E");
+ } else {
+ SendPacket("E");
+ }
+ return rnb_success;
}
/* 'k'
Kill the inferior process. */
-rnb_err_t
-RNBRemote::HandlePacket_k (const char *p)
-{
- DNBLog ("Got a 'k' packet, killing the inferior process.");
- // No response to should be sent to the kill packet
- if (m_ctx.HasValidProcessID())
- DNBProcessKill (m_ctx.ProcessID());
- SendPacket ("X09");
- return rnb_success;
+rnb_err_t RNBRemote::HandlePacket_k(const char *p) {
+ DNBLog("Got a 'k' packet, killing the inferior process.");
+ // No response to should be sent to the kill packet
+ if (m_ctx.HasValidProcessID())
+ DNBProcessKill(m_ctx.ProcessID());
+ SendPacket("X09");
+ return rnb_success;
}
-rnb_err_t
-RNBRemote::HandlePacket_stop_process (const char *p)
-{
-//#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test exiting on interrupt
+rnb_err_t RNBRemote::HandlePacket_stop_process(const char *p) {
+//#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test
+//exiting on interrupt
#if defined(TEST_EXIT_ON_INTERRUPT)
- rnb_err_t err = HandlePacket_k (p);
- m_comm.Disconnect(true);
- return err;
+ rnb_err_t err = HandlePacket_k(p);
+ m_comm.Disconnect(true);
+ return err;
#else
- if (!DNBProcessInterrupt(m_ctx.ProcessID()))
- {
- // If we failed to interrupt the process, then send a stop
- // reply packet as the process was probably already stopped
- DNBLogThreaded ("RNBRemote::HandlePacket_stop_process() sending extra stop reply because DNBProcessInterrupt returned false");
- HandlePacket_last_signal (NULL);
- }
- return rnb_success;
+ if (!DNBProcessInterrupt(m_ctx.ProcessID())) {
+ // If we failed to interrupt the process, then send a stop
+ // reply packet as the process was probably already stopped
+ DNBLogThreaded("RNBRemote::HandlePacket_stop_process() sending extra stop "
+ "reply because DNBProcessInterrupt returned false");
+ HandlePacket_last_signal(NULL);
+ }
+ return rnb_success;
#endif
}
/* 's'
Step the inferior process. */
-rnb_err_t
-RNBRemote::HandlePacket_s (const char *p)
-{
- const nub_process_t pid = m_ctx.ProcessID();
- if (pid == INVALID_NUB_PROCESS)
- return SendPacket ("E32");
-
- // Hardware supported stepping not supported on arm
- nub_thread_t tid = GetContinueThread ();
- if (tid == 0 || tid == (nub_thread_t)-1)
- tid = GetCurrentThread();
-
- if (tid == INVALID_NUB_THREAD)
- return SendPacket ("E33");
-
- DNBThreadResumeActions thread_actions;
- thread_actions.AppendAction(tid, eStateStepping);
-
- // Make all other threads stop when we are stepping
- thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
- if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
- return SendPacket ("E49");
- // Don't send an "OK" packet; response is the stopped/exited message.
- return rnb_success;
+rnb_err_t RNBRemote::HandlePacket_s(const char *p) {
+ const nub_process_t pid = m_ctx.ProcessID();
+ if (pid == INVALID_NUB_PROCESS)
+ return SendPacket("E32");
+
+ // Hardware supported stepping not supported on arm
+ nub_thread_t tid = GetContinueThread();
+ if (tid == 0 || tid == (nub_thread_t)-1)
+ tid = GetCurrentThread();
+
+ if (tid == INVALID_NUB_THREAD)
+ return SendPacket("E33");
+
+ DNBThreadResumeActions thread_actions;
+ thread_actions.AppendAction(tid, eStateStepping);
+
+ // Make all other threads stop when we are stepping
+ thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
+ if (!DNBProcessResume(pid, thread_actions.GetFirst(),
+ thread_actions.GetSize()))
+ return SendPacket("E49");
+ // Don't send an "OK" packet; response is the stopped/exited message.
+ return rnb_success;
}
/* 'S sig [;addr]'
Step with signal sig, optionally at address addr. */
-rnb_err_t
-RNBRemote::HandlePacket_S (const char *p)
-{
- const nub_process_t pid = m_ctx.ProcessID();
- if (pid == INVALID_NUB_PROCESS)
- return SendPacket ("E36");
+rnb_err_t RNBRemote::HandlePacket_S(const char *p) {
+ const nub_process_t pid = m_ctx.ProcessID();
+ if (pid == INVALID_NUB_PROCESS)
+ return SendPacket("E36");
- DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS };
+ DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateStepping, 0,
+ INVALID_NUB_ADDRESS};
- if (*(p + 1) != '\0')
- {
- char *end = NULL;
- errno = 0;
- action.signal = static_cast<int>(strtoul (p + 1, &end, 16));
- if (errno != 0)
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet");
- else if (*end == ';')
- {
- errno = 0;
- action.addr = strtoull (end + 1, NULL, 16);
- if (errno != 0 && action.addr == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet");
- }
- }
+ if (*(p + 1) != '\0') {
+ char *end = NULL;
+ errno = 0;
+ action.signal = static_cast<int>(strtoul(p + 1, &end, 16));
+ if (errno != 0)
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Could not parse signal in S packet");
+ else if (*end == ';') {
+ errno = 0;
+ action.addr = strtoull(end + 1, NULL, 16);
+ if (errno != 0 && action.addr == 0) {
+ return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
+ "Could not parse address in S packet");
+ }
}
+ }
- action.tid = GetContinueThread ();
- if (action.tid == 0 || action.tid == (nub_thread_t)-1)
- return SendPacket ("E40");
-
- nub_state_t tstate = DNBThreadGetState (pid, action.tid);
- if (tstate == eStateInvalid || tstate == eStateExited)
- return SendPacket ("E37");
-
-
- DNBThreadResumeActions thread_actions;
- thread_actions.Append (action);
-
- // Make all other threads stop when we are stepping
- thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
- if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
- return SendPacket ("E39");
-
- // Don't send an "OK" packet; response is the stopped/exited message.
- return rnb_success;
-}
-
-static const char *
-GetArchName (const uint32_t cputype, const uint32_t cpusubtype)
-{
- switch (cputype)
- {
- case CPU_TYPE_ARM:
- switch (cpusubtype)
- {
- case 5: return "armv4";
- case 6: return "armv6";
- case 7: return "armv5t";
- case 8: return "xscale";
- case 9: return "armv7";
- case 10: return "armv7f";
- case 11: return "armv7s";
- case 12: return "armv7k";
- case 14: return "armv6m";
- case 15: return "armv7m";
- case 16: return "armv7em";
- default: return "arm";
- }
- break;
- case CPU_TYPE_ARM64: return "arm64";
- case CPU_TYPE_I386: return "i386";
- case CPU_TYPE_X86_64:
- switch (cpusubtype)
- {
- default: return "x86_64";
- case 8: return "x86_64h";
- }
- break;
+ action.tid = GetContinueThread();
+ if (action.tid == 0 || action.tid == (nub_thread_t)-1)
+ return SendPacket("E40");
+
+ nub_state_t tstate = DNBThreadGetState(pid, action.tid);
+ if (tstate == eStateInvalid || tstate == eStateExited)
+ return SendPacket("E37");
+
+ DNBThreadResumeActions thread_actions;
+ thread_actions.Append(action);
+
+ // Make all other threads stop when we are stepping
+ thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
+ if (!DNBProcessResume(pid, thread_actions.GetFirst(),
+ thread_actions.GetSize()))
+ return SendPacket("E39");
+
+ // Don't send an "OK" packet; response is the stopped/exited message.
+ return rnb_success;
+}
+
+static const char *GetArchName(const uint32_t cputype,
+ const uint32_t cpusubtype) {
+ switch (cputype) {
+ case CPU_TYPE_ARM:
+ switch (cpusubtype) {
+ case 5:
+ return "armv4";
+ case 6:
+ return "armv6";
+ case 7:
+ return "armv5t";
+ case 8:
+ return "xscale";
+ case 9:
+ return "armv7";
+ case 10:
+ return "armv7f";
+ case 11:
+ return "armv7s";
+ case 12:
+ return "armv7k";
+ case 14:
+ return "armv6m";
+ case 15:
+ return "armv7m";
+ case 16:
+ return "armv7em";
+ default:
+ return "arm";
}
- return NULL;
-}
-
-static bool
-GetHostCPUType (uint32_t &cputype, uint32_t &cpusubtype, uint32_t &is_64_bit_capable, bool &promoted_to_64)
-{
- static uint32_t g_host_cputype = 0;
- static uint32_t g_host_cpusubtype = 0;
- static uint32_t g_is_64_bit_capable = 0;
- static bool g_promoted_to_64 = false;
-
- if (g_host_cputype == 0)
- {
- g_promoted_to_64 = false;
- size_t len = sizeof(uint32_t);
- if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0)
- {
- len = sizeof (uint32_t);
- if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len, NULL, 0) == 0)
- {
- if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0))
- {
- g_promoted_to_64 = true;
- g_host_cputype |= CPU_ARCH_ABI64;
- }
- }
- }
-
- len = sizeof(uint32_t);
- if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) == 0)
- {
- if (g_promoted_to_64 &&
- g_host_cputype == CPU_TYPE_X86_64 && g_host_cpusubtype == CPU_SUBTYPE_486)
- g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL;
+ break;
+ case CPU_TYPE_ARM64:
+ return "arm64";
+ case CPU_TYPE_I386:
+ return "i386";
+ case CPU_TYPE_X86_64:
+ switch (cpusubtype) {
+ default:
+ return "x86_64";
+ case 8:
+ return "x86_64h";
+ }
+ break;
+ }
+ return NULL;
+}
+
+static bool GetHostCPUType(uint32_t &cputype, uint32_t &cpusubtype,
+ uint32_t &is_64_bit_capable, bool &promoted_to_64) {
+ static uint32_t g_host_cputype = 0;
+ static uint32_t g_host_cpusubtype = 0;
+ static uint32_t g_is_64_bit_capable = 0;
+ static bool g_promoted_to_64 = false;
+
+ if (g_host_cputype == 0) {
+ g_promoted_to_64 = false;
+ size_t len = sizeof(uint32_t);
+ if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0) {
+ len = sizeof(uint32_t);
+ if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len,
+ NULL, 0) == 0) {
+ if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0)) {
+ g_promoted_to_64 = true;
+ g_host_cputype |= CPU_ARCH_ABI64;
}
- }
-
- cputype = g_host_cputype;
- cpusubtype = g_host_cpusubtype;
- is_64_bit_capable = g_is_64_bit_capable;
- promoted_to_64 = g_promoted_to_64;
- return g_host_cputype != 0;
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qHostInfo (const char *p)
-{
- std::ostringstream strm;
-
- uint32_t cputype = 0;
- uint32_t cpusubtype = 0;
- uint32_t is_64_bit_capable = 0;
- bool promoted_to_64 = false;
- if (GetHostCPUType (cputype, cpusubtype, is_64_bit_capable, promoted_to_64))
- {
- strm << "cputype:" << std::dec << cputype << ';';
- strm << "cpusubtype:" << std::dec << cpusubtype << ';';
+ }
}
- // The OS in the triple should be "ios" or "macosx" which doesn't match our
- // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
- // this for now.
- if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
- {
-#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1
- strm << "ostype:tvos;";
-#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
- strm << "ostype:watchos;";
+ len = sizeof(uint32_t);
+ if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) ==
+ 0) {
+ if (g_promoted_to_64 && g_host_cputype == CPU_TYPE_X86_64 &&
+ g_host_cpusubtype == CPU_SUBTYPE_486)
+ g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL;
+ }
+ }
+
+ cputype = g_host_cputype;
+ cpusubtype = g_host_cpusubtype;
+ is_64_bit_capable = g_is_64_bit_capable;
+ promoted_to_64 = g_promoted_to_64;
+ return g_host_cputype != 0;
+}
+
+rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) {
+ std::ostringstream strm;
+
+ uint32_t cputype = 0;
+ uint32_t cpusubtype = 0;
+ uint32_t is_64_bit_capable = 0;
+ bool promoted_to_64 = false;
+ if (GetHostCPUType(cputype, cpusubtype, is_64_bit_capable, promoted_to_64)) {
+ strm << "cputype:" << std::dec << cputype << ';';
+ strm << "cpusubtype:" << std::dec << cpusubtype << ';';
+ }
+
+ // The OS in the triple should be "ios" or "macosx" which doesn't match our
+ // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
+ // this for now.
+ if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) {
+#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
+ strm << "ostype:tvos;";
+#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+ strm << "ostype:watchos;";
#else
- strm << "ostype:ios;";
+ strm << "ostype:ios;";
#endif
- // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
- strm << "watchpoint_exceptions_received:before;";
- }
- else
- {
- strm << "ostype:macosx;";
- strm << "watchpoint_exceptions_received:after;";
- }
-// char ostype[64];
-// len = sizeof(ostype);
-// if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
-// {
-// len = strlen(ostype);
-// std::transform (ostype, ostype + len, ostype, tolower);
-// strm << "ostype:" << std::dec << ostype << ';';
-// }
-
- strm << "vendor:apple;";
-
- uint64_t major, minor, patch;
- if (DNBGetOSVersionNumbers (&major, &minor, &patch))
- {
- strm << "os_version:" << major << "." << minor;
- if (patch != UINT64_MAX)
- strm << "." << patch;
- strm << ";";
- }
-
-#if defined (__LITTLE_ENDIAN__)
- strm << "endian:little;";
-#elif defined (__BIG_ENDIAN__)
- strm << "endian:big;";
-#elif defined (__PDP_ENDIAN__)
- strm << "endian:pdp;";
+ // On armv7 we use "synchronous" watchpoints which means the exception is
+ // delivered before the instruction executes.
+ strm << "watchpoint_exceptions_received:before;";
+ } else {
+ strm << "ostype:macosx;";
+ strm << "watchpoint_exceptions_received:after;";
+ }
+ // char ostype[64];
+ // len = sizeof(ostype);
+ // if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
+ // {
+ // len = strlen(ostype);
+ // std::transform (ostype, ostype + len, ostype, tolower);
+ // strm << "ostype:" << std::dec << ostype << ';';
+ // }
+
+ strm << "vendor:apple;";
+
+ uint64_t major, minor, patch;
+ if (DNBGetOSVersionNumbers(&major, &minor, &patch)) {
+ strm << "os_version:" << major << "." << minor;
+ if (patch != UINT64_MAX)
+ strm << "." << patch;
+ strm << ";";
+ }
+
+#if defined(__LITTLE_ENDIAN__)
+ strm << "endian:little;";
+#elif defined(__BIG_ENDIAN__)
+ strm << "endian:big;";
+#elif defined(__PDP_ENDIAN__)
+ strm << "endian:pdp;";
#endif
- if (promoted_to_64)
- strm << "ptrsize:8;";
- else
- strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
+ if (promoted_to_64)
+ strm << "ptrsize:8;";
+ else
+ strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
-#if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
- strm << "default_packet_timeout:10;";
+#if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+ strm << "default_packet_timeout:10;";
#endif
- return SendPacket (strm.str());
-}
-
-void
-XMLElementStart (std::ostringstream &s, uint32_t indent, const char *name, bool has_attributes)
-{
- if (indent)
- s << INDENT_WITH_SPACES(indent);
- s << '<' << name;
- if (!has_attributes)
- s << '>' << std::endl;
+ return SendPacket(strm.str());
}
-void
-XMLElementStartEndAttributes (std::ostringstream &s, bool empty)
-{
- if (empty)
- s << '/';
+void XMLElementStart(std::ostringstream &s, uint32_t indent, const char *name,
+ bool has_attributes) {
+ if (indent)
+ s << INDENT_WITH_SPACES(indent);
+ s << '<' << name;
+ if (!has_attributes)
s << '>' << std::endl;
}
-void
-XMLElementEnd (std::ostringstream &s, uint32_t indent, const char *name)
-{
- if (indent)
- s << INDENT_WITH_SPACES(indent);
- s << '<' << '/' << name << '>' << std::endl;
-}
-
-void
-XMLElementWithStringValue (std::ostringstream &s, uint32_t indent, const char *name, const char *value, bool close = true)
-{
- if (value)
- {
- if (indent)
- s << INDENT_WITH_SPACES(indent);
- s << '<' << name << '>' << value;
- if (close)
- XMLElementEnd(s, 0, name);
- }
-}
-
-void
-XMLElementWithUnsignedValue (std::ostringstream &s, uint32_t indent, const char *name, uint64_t value, bool close = true)
-{
+void XMLElementStartEndAttributes(std::ostringstream &s, bool empty) {
+ if (empty)
+ s << '/';
+ s << '>' << std::endl;
+}
+
+void XMLElementEnd(std::ostringstream &s, uint32_t indent, const char *name) {
+ if (indent)
+ s << INDENT_WITH_SPACES(indent);
+ s << '<' << '/' << name << '>' << std::endl;
+}
+
+void XMLElementWithStringValue(std::ostringstream &s, uint32_t indent,
+ const char *name, const char *value,
+ bool close = true) {
+ if (value) {
if (indent)
- s << INDENT_WITH_SPACES(indent);
-
- s << '<' << name << '>' << DECIMAL << value;
+ s << INDENT_WITH_SPACES(indent);
+ s << '<' << name << '>' << value;
if (close)
- XMLElementEnd(s, 0, name);
-}
-
-void
-XMLAttributeString (std::ostringstream &s, const char *name, const char *value, const char *default_value = NULL)
-{
- if (value)
- {
- if (default_value && strcmp(value, default_value) == 0)
- return; // No need to emit the attribute because it matches the default value
- s <<' ' << name << "=\"" << value << "\"";
- }
+ XMLElementEnd(s, 0, name);
+ }
}
-void
-XMLAttributeUnsignedDecimal (std::ostringstream &s, const char *name, uint64_t value)
-{
- s <<' ' << name << "=\"" << DECIMAL << value << "\"";
-}
-
-void
-GenerateTargetXMLRegister (std::ostringstream &s,
- const uint32_t reg_num,
- nub_size_t num_reg_sets,
- const DNBRegisterSetInfo *reg_set_info,
- const register_map_entry_t ®)
-{
- const char *default_lldb_encoding = "uint";
- const char *lldb_encoding = default_lldb_encoding;
- const char *gdb_group = "general";
- const char *default_gdb_type = "int";
- const char *gdb_type = default_gdb_type;
- const char *default_lldb_format = "hex";
- const char *lldb_format = default_lldb_format;
- const char *lldb_set = NULL;
-
- switch (reg.nub_info.type)
- {
- case Uint: lldb_encoding = "uint"; break;
- case Sint: lldb_encoding = "sint"; break;
- case IEEE754: lldb_encoding = "ieee754"; if (reg.nub_info.set > 0) gdb_group = "float"; break;
- case Vector: lldb_encoding = "vector"; if (reg.nub_info.set > 0) gdb_group = "vector"; break;
- }
-
- switch (reg.nub_info.format)
- {
- case Binary: lldb_format = "binary"; break;
- case Decimal: lldb_format = "decimal"; break;
- case Hex: lldb_format = "hex"; break;
- case Float: gdb_type = "float"; lldb_format = "float"; break;
- case VectorOfSInt8: gdb_type = "float"; lldb_format = "vector-sint8"; break;
- case VectorOfUInt8: gdb_type = "float"; lldb_format = "vector-uint8"; break;
- case VectorOfSInt16: gdb_type = "float"; lldb_format = "vector-sint16"; break;
- case VectorOfUInt16: gdb_type = "float"; lldb_format = "vector-uint16"; break;
- case VectorOfSInt32: gdb_type = "float"; lldb_format = "vector-sint32"; break;
- case VectorOfUInt32: gdb_type = "float"; lldb_format = "vector-uint32"; break;
- case VectorOfFloat32: gdb_type = "float"; lldb_format = "vector-float32"; break;
- case VectorOfUInt128: gdb_type = "float"; lldb_format = "vector-uint128"; break;
- };
- if (reg_set_info && reg.nub_info.set < num_reg_sets)
- lldb_set = reg_set_info[reg.nub_info.set].name;
-
- uint32_t indent = 2;
-
- XMLElementStart(s, indent, "reg", true);
- XMLAttributeString(s, "name", reg.nub_info.name);
- XMLAttributeUnsignedDecimal(s, "regnum", reg_num);
- XMLAttributeUnsignedDecimal(s, "offset", reg.offset);
- XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8);
- XMLAttributeString(s, "group", gdb_group);
- XMLAttributeString(s, "type", gdb_type, default_gdb_type);
- XMLAttributeString (s, "altname", reg.nub_info.alt);
- XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding);
- XMLAttributeString(s, "format", lldb_format, default_lldb_format);
- XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set);
- if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM)
- XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe);
- if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM)
- XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf);
-
- const char *lldb_generic = NULL;
- switch (reg.nub_info.reg_generic)
- {
- case GENERIC_REGNUM_FP: lldb_generic = "fp"; break;
- case GENERIC_REGNUM_PC: lldb_generic = "pc"; break;
- case GENERIC_REGNUM_SP: lldb_generic = "sp"; break;
- case GENERIC_REGNUM_RA: lldb_generic = "ra"; break;
- case GENERIC_REGNUM_FLAGS: lldb_generic = "flags"; break;
- case GENERIC_REGNUM_ARG1: lldb_generic = "arg1"; break;
- case GENERIC_REGNUM_ARG2: lldb_generic = "arg2"; break;
- case GENERIC_REGNUM_ARG3: lldb_generic = "arg3"; break;
- case GENERIC_REGNUM_ARG4: lldb_generic = "arg4"; break;
- case GENERIC_REGNUM_ARG5: lldb_generic = "arg5"; break;
- case GENERIC_REGNUM_ARG6: lldb_generic = "arg6"; break;
- case GENERIC_REGNUM_ARG7: lldb_generic = "arg7"; break;
- case GENERIC_REGNUM_ARG8: lldb_generic = "arg8"; break;
- default: break;
+void XMLElementWithUnsignedValue(std::ostringstream &s, uint32_t indent,
+ const char *name, uint64_t value,
+ bool close = true) {
+ if (indent)
+ s << INDENT_WITH_SPACES(indent);
+
+ s << '<' << name << '>' << DECIMAL << value;
+ if (close)
+ XMLElementEnd(s, 0, name);
+}
+
+void XMLAttributeString(std::ostringstream &s, const char *name,
+ const char *value, const char *default_value = NULL) {
+ if (value) {
+ if (default_value && strcmp(value, default_value) == 0)
+ return; // No need to emit the attribute because it matches the default
+ // value
+ s << ' ' << name << "=\"" << value << "\"";
+ }
+}
+
+void XMLAttributeUnsignedDecimal(std::ostringstream &s, const char *name,
+ uint64_t value) {
+ s << ' ' << name << "=\"" << DECIMAL << value << "\"";
+}
+
+void GenerateTargetXMLRegister(std::ostringstream &s, const uint32_t reg_num,
+ nub_size_t num_reg_sets,
+ const DNBRegisterSetInfo *reg_set_info,
+ const register_map_entry_t ®) {
+ const char *default_lldb_encoding = "uint";
+ const char *lldb_encoding = default_lldb_encoding;
+ const char *gdb_group = "general";
+ const char *default_gdb_type = "int";
+ const char *gdb_type = default_gdb_type;
+ const char *default_lldb_format = "hex";
+ const char *lldb_format = default_lldb_format;
+ const char *lldb_set = NULL;
+
+ switch (reg.nub_info.type) {
+ case Uint:
+ lldb_encoding = "uint";
+ break;
+ case Sint:
+ lldb_encoding = "sint";
+ break;
+ case IEEE754:
+ lldb_encoding = "ieee754";
+ if (reg.nub_info.set > 0)
+ gdb_group = "float";
+ break;
+ case Vector:
+ lldb_encoding = "vector";
+ if (reg.nub_info.set > 0)
+ gdb_group = "vector";
+ break;
+ }
+
+ switch (reg.nub_info.format) {
+ case Binary:
+ lldb_format = "binary";
+ break;
+ case Decimal:
+ lldb_format = "decimal";
+ break;
+ case Hex:
+ lldb_format = "hex";
+ break;
+ case Float:
+ gdb_type = "float";
+ lldb_format = "float";
+ break;
+ case VectorOfSInt8:
+ gdb_type = "float";
+ lldb_format = "vector-sint8";
+ break;
+ case VectorOfUInt8:
+ gdb_type = "float";
+ lldb_format = "vector-uint8";
+ break;
+ case VectorOfSInt16:
+ gdb_type = "float";
+ lldb_format = "vector-sint16";
+ break;
+ case VectorOfUInt16:
+ gdb_type = "float";
+ lldb_format = "vector-uint16";
+ break;
+ case VectorOfSInt32:
+ gdb_type = "float";
+ lldb_format = "vector-sint32";
+ break;
+ case VectorOfUInt32:
+ gdb_type = "float";
+ lldb_format = "vector-uint32";
+ break;
+ case VectorOfFloat32:
+ gdb_type = "float";
+ lldb_format = "vector-float32";
+ break;
+ case VectorOfUInt128:
+ gdb_type = "float";
+ lldb_format = "vector-uint128";
+ break;
+ };
+ if (reg_set_info && reg.nub_info.set < num_reg_sets)
+ lldb_set = reg_set_info[reg.nub_info.set].name;
+
+ uint32_t indent = 2;
+
+ XMLElementStart(s, indent, "reg", true);
+ XMLAttributeString(s, "name", reg.nub_info.name);
+ XMLAttributeUnsignedDecimal(s, "regnum", reg_num);
+ XMLAttributeUnsignedDecimal(s, "offset", reg.offset);
+ XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8);
+ XMLAttributeString(s, "group", gdb_group);
+ XMLAttributeString(s, "type", gdb_type, default_gdb_type);
+ XMLAttributeString(s, "altname", reg.nub_info.alt);
+ XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding);
+ XMLAttributeString(s, "format", lldb_format, default_lldb_format);
+ XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set);
+ if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM)
+ XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe);
+ if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM)
+ XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf);
+
+ const char *lldb_generic = NULL;
+ switch (reg.nub_info.reg_generic) {
+ case GENERIC_REGNUM_FP:
+ lldb_generic = "fp";
+ break;
+ case GENERIC_REGNUM_PC:
+ lldb_generic = "pc";
+ break;
+ case GENERIC_REGNUM_SP:
+ lldb_generic = "sp";
+ break;
+ case GENERIC_REGNUM_RA:
+ lldb_generic = "ra";
+ break;
+ case GENERIC_REGNUM_FLAGS:
+ lldb_generic = "flags";
+ break;
+ case GENERIC_REGNUM_ARG1:
+ lldb_generic = "arg1";
+ break;
+ case GENERIC_REGNUM_ARG2:
+ lldb_generic = "arg2";
+ break;
+ case GENERIC_REGNUM_ARG3:
+ lldb_generic = "arg3";
+ break;
+ case GENERIC_REGNUM_ARG4:
+ lldb_generic = "arg4";
+ break;
+ case GENERIC_REGNUM_ARG5:
+ lldb_generic = "arg5";
+ break;
+ case GENERIC_REGNUM_ARG6:
+ lldb_generic = "arg6";
+ break;
+ case GENERIC_REGNUM_ARG7:
+ lldb_generic = "arg7";
+ break;
+ case GENERIC_REGNUM_ARG8:
+ lldb_generic = "arg8";
+ break;
+ default:
+ break;
+ }
+ XMLAttributeString(s, "generic", lldb_generic);
+
+ bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty();
+ if (!empty) {
+ if (!reg.value_regnums.empty()) {
+ std::ostringstream regnums;
+ bool first = true;
+ regnums << DECIMAL;
+ for (auto regnum : reg.value_regnums) {
+ if (!first)
+ regnums << ',';
+ regnums << regnum;
+ first = false;
+ }
+ XMLAttributeString(s, "value_regnums", regnums.str().c_str());
}
- XMLAttributeString(s, "generic", lldb_generic);
-
- bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty();
- if (!empty)
- {
- if (!reg.value_regnums.empty())
- {
- std::ostringstream regnums;
- bool first = true;
- regnums << DECIMAL;
- for (auto regnum : reg.value_regnums)
- {
- if (!first)
- regnums << ',';
- regnums << regnum;
- first = false;
- }
- XMLAttributeString(s, "value_regnums", regnums.str().c_str());
- }
-
- if (!reg.invalidate_regnums.empty())
- {
- std::ostringstream regnums;
- bool first = true;
- regnums << DECIMAL;
- for (auto regnum : reg.invalidate_regnums)
- {
- if (!first)
- regnums << ',';
- regnums << regnum;
- first = false;
- }
- XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str());
- }
+ if (!reg.invalidate_regnums.empty()) {
+ std::ostringstream regnums;
+ bool first = true;
+ regnums << DECIMAL;
+ for (auto regnum : reg.invalidate_regnums) {
+ if (!first)
+ regnums << ',';
+ regnums << regnum;
+ first = false;
+ }
+ XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str());
}
- XMLElementStartEndAttributes(s, true);
+ }
+ XMLElementStartEndAttributes(s, true);
}
-void
-GenerateTargetXMLRegisters (std::ostringstream &s)
-{
- nub_size_t num_reg_sets = 0;
- const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets);
-
-
- uint32_t cputype = DNBGetRegisterCPUType();
- if (cputype)
- {
- XMLElementStart(s, 0, "feature", true);
- std::ostringstream name_strm;
- name_strm << "com.apple.debugserver." << GetArchName (cputype, 0);
- XMLAttributeString(s, "name", name_strm.str().c_str());
- XMLElementStartEndAttributes(s, false);
- for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num)
-// for (const auto ®: g_dynamic_register_map)
- {
- GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets, g_reg_entries[reg_num]);
- }
- XMLElementEnd(s, 0, "feature");
-
- if (num_reg_sets > 0)
- {
- XMLElementStart(s, 0, "groups", false);
- for (uint32_t set=1; set<num_reg_sets; ++set)
- {
- XMLElementStart(s, 2, "group", true);
- XMLAttributeUnsignedDecimal(s, "id", set);
- XMLAttributeString(s, "name", reg_sets[set].name);
- XMLElementStartEndAttributes(s, true);
- }
- XMLElementEnd(s, 0, "groups");
- }
+void GenerateTargetXMLRegisters(std::ostringstream &s) {
+ nub_size_t num_reg_sets = 0;
+ const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets);
+
+ uint32_t cputype = DNBGetRegisterCPUType();
+ if (cputype) {
+ XMLElementStart(s, 0, "feature", true);
+ std::ostringstream name_strm;
+ name_strm << "com.apple.debugserver." << GetArchName(cputype, 0);
+ XMLAttributeString(s, "name", name_strm.str().c_str());
+ XMLElementStartEndAttributes(s, false);
+ for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num)
+ // for (const auto ®: g_dynamic_register_map)
+ {
+ GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets,
+ g_reg_entries[reg_num]);
+ }
+ XMLElementEnd(s, 0, "feature");
+
+ if (num_reg_sets > 0) {
+ XMLElementStart(s, 0, "groups", false);
+ for (uint32_t set = 1; set < num_reg_sets; ++set) {
+ XMLElementStart(s, 2, "group", true);
+ XMLAttributeUnsignedDecimal(s, "id", set);
+ XMLAttributeString(s, "name", reg_sets[set].name);
+ XMLElementStartEndAttributes(s, true);
+ }
+ XMLElementEnd(s, 0, "groups");
}
+ }
}
static const char *g_target_xml_header = R"(<?xml version="1.0"?>
@@ -5117,171 +4983,146 @@ static const char *g_target_xml_footer =
static std::string g_target_xml;
-void
-UpdateTargetXML ()
-{
- std::ostringstream s;
- s << g_target_xml_header << std::endl;
-
- // Set the architecture
- //s << "<architecture>" << arch "</architecture>" << std::endl;
-
- // Set the OSABI
- //s << "<osabi>abi-name</osabi>"
-
- GenerateTargetXMLRegisters(s);
-
- s << g_target_xml_footer << std::endl;
+void UpdateTargetXML() {
+ std::ostringstream s;
+ s << g_target_xml_header << std::endl;
- // Save the XML output in case it gets retrieved in chunks
- g_target_xml = s.str();
+ // Set the architecture
+ // s << "<architecture>" << arch "</architecture>" << std::endl;
+
+ // Set the OSABI
+ // s << "<osabi>abi-name</osabi>"
+
+ GenerateTargetXMLRegisters(s);
+
+ s << g_target_xml_footer << std::endl;
+
+ // Save the XML output in case it gets retrieved in chunks
+ g_target_xml = s.str();
}
-rnb_err_t
-RNBRemote::HandlePacket_qXfer (const char *command)
-{
- const char *p = command;
- p += strlen ("qXfer:");
- const char *sep = strchr(p, ':');
- if (sep)
- {
- std::string object(p, sep - p); // "auxv", "backtrace", "features", etc
- p = sep + 1;
- sep = strchr(p, ':');
- if (sep)
- {
- std::string rw(p, sep - p); // "read" or "write"
- p = sep + 1;
- sep = strchr(p, ':');
- if (sep)
- {
- std::string annex(p, sep - p); // "read" or "write"
+rnb_err_t RNBRemote::HandlePacket_qXfer(const char *command) {
+ const char *p = command;
+ p += strlen("qXfer:");
+ const char *sep = strchr(p, ':');
+ if (sep) {
+ std::string object(p, sep - p); // "auxv", "backtrace", "features", etc
+ p = sep + 1;
+ sep = strchr(p, ':');
+ if (sep) {
+ std::string rw(p, sep - p); // "read" or "write"
+ p = sep + 1;
+ sep = strchr(p, ':');
+ if (sep) {
+ std::string annex(p, sep - p); // "read" or "write"
- p = sep + 1;
- sep = strchr(p, ',');
- if (sep)
- {
- std::string offset_str(p, sep - p); // read the length as a string
- p = sep + 1;
- std::string length_str(p); // read the offset as a string
- char *end = nullptr;
- const uint64_t offset = strtoul(offset_str.c_str(), &end, 16); // convert offset_str to a offset
- if (*end == '\0')
- {
- const uint64_t length = strtoul(length_str.c_str(), &end, 16); // convert length_str to a length
- if (*end == '\0')
- {
- if (object == "features" &&
- rw == "read" &&
- annex == "target.xml")
- {
- std::ostringstream xml_out;
-
- if (offset == 0)
- {
- InitializeRegisters (true);
-
- UpdateTargetXML();
- if (g_target_xml.empty())
- return SendPacket("E83");
-
- if (length > g_target_xml.size())
- {
- xml_out << 'l'; // No more data
- xml_out << binary_encode_string(g_target_xml);
- }
- else
- {
- xml_out << 'm'; // More data needs to be read with a subsequent call
- xml_out << binary_encode_string(std::string(g_target_xml, offset, length));
- }
- }
- else
- {
- // Retrieving target XML in chunks
- if (offset < g_target_xml.size())
- {
- std::string chunk(g_target_xml, offset, length);
- if (chunk.size() < length)
- xml_out << 'l'; // No more data
- else
- xml_out << 'm'; // More data needs to be read with a subsequent call
- xml_out << binary_encode_string(chunk.data());
- }
- }
- return SendPacket(xml_out.str());
- }
- // Well formed, put not supported
- return HandlePacket_UNIMPLEMENTED (command);
- }
- }
- }
- }
- else
- {
- SendPacket ("E85");
+ p = sep + 1;
+ sep = strchr(p, ',');
+ if (sep) {
+ std::string offset_str(p, sep - p); // read the length as a string
+ p = sep + 1;
+ std::string length_str(p); // read the offset as a string
+ char *end = nullptr;
+ const uint64_t offset = strtoul(offset_str.c_str(), &end,
+ 16); // convert offset_str to a offset
+ if (*end == '\0') {
+ const uint64_t length = strtoul(
+ length_str.c_str(), &end, 16); // convert length_str to a length
+ if (*end == '\0') {
+ if (object == "features" && rw == "read" &&
+ annex == "target.xml") {
+ std::ostringstream xml_out;
+
+ if (offset == 0) {
+ InitializeRegisters(true);
+
+ UpdateTargetXML();
+ if (g_target_xml.empty())
+ return SendPacket("E83");
+
+ if (length > g_target_xml.size()) {
+ xml_out << 'l'; // No more data
+ xml_out << binary_encode_string(g_target_xml);
+ } else {
+ xml_out << 'm'; // More data needs to be read with a
+ // subsequent call
+ xml_out << binary_encode_string(
+ std::string(g_target_xml, offset, length));
+ }
+ } else {
+ // Retrieving target XML in chunks
+ if (offset < g_target_xml.size()) {
+ std::string chunk(g_target_xml, offset, length);
+ if (chunk.size() < length)
+ xml_out << 'l'; // No more data
+ else
+ xml_out << 'm'; // More data needs to be read with a
+ // subsequent call
+ xml_out << binary_encode_string(chunk.data());
+ }
+ }
+ return SendPacket(xml_out.str());
+ }
+ // Well formed, put not supported
+ return HandlePacket_UNIMPLEMENTED(command);
}
+ }
}
- else
- {
- SendPacket ("E86");
- }
+ } else {
+ SendPacket("E85");
+ }
+ } else {
+ SendPacket("E86");
}
- return SendPacket ("E82");
+ }
+ return SendPacket("E82");
}
+rnb_err_t RNBRemote::HandlePacket_qGDBServerVersion(const char *p) {
+ std::ostringstream strm;
-rnb_err_t
-RNBRemote::HandlePacket_qGDBServerVersion (const char *p)
-{
- std::ostringstream strm;
-
#if defined(DEBUGSERVER_PROGRAM_NAME)
- strm << "name:" DEBUGSERVER_PROGRAM_NAME ";";
+ strm << "name:" DEBUGSERVER_PROGRAM_NAME ";";
#else
- strm << "name:debugserver;";
+ strm << "name:debugserver;";
#endif
- strm << "version:" << DEBUGSERVER_VERSION_NUM << ";";
+ strm << "version:" << DEBUGSERVER_VERSION_NUM << ";";
- return SendPacket (strm.str());
+ return SendPacket(strm.str());
}
// A helper function that retrieves a single integer value from
// a one-level-deep JSON dictionary of key-value pairs. e.g.
// jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}]
//
-uint64_t
-get_integer_value_for_key_name_from_json (const char *key, const char *json_string)
-{
- uint64_t retval = INVALID_NUB_ADDRESS;
- std::string key_with_quotes = "\"";
- key_with_quotes += key;
- key_with_quotes += "\"";
- const char *c = strstr (json_string, key_with_quotes.c_str());
- if (c)
- {
- c += key_with_quotes.size();
-
- while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
- c++;
-
- if (*c == ':')
- {
- c++;
-
- while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
- c++;
-
- errno = 0;
- retval = strtoul (c, NULL, 10);
- if (errno != 0)
- {
- retval = INVALID_NUB_ADDRESS;
- }
- }
+uint64_t get_integer_value_for_key_name_from_json(const char *key,
+ const char *json_string) {
+ uint64_t retval = INVALID_NUB_ADDRESS;
+ std::string key_with_quotes = "\"";
+ key_with_quotes += key;
+ key_with_quotes += "\"";
+ const char *c = strstr(json_string, key_with_quotes.c_str());
+ if (c) {
+ c += key_with_quotes.size();
+
+ while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+
+ if (*c == ':') {
+ c++;
+
+ while (*c != '\0' &&
+ (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+
+ errno = 0;
+ retval = strtoul(c, NULL, 10);
+ if (errno != 0) {
+ retval = INVALID_NUB_ADDRESS;
+ }
}
- return retval;
-
+ }
+ return retval;
}
// A helper function that retrieves a boolean value from
@@ -5291,39 +5132,36 @@ get_integer_value_for_key_name_from_json
// Returns true if it was able to find the key name, and sets the 'value'
// argument to the value found.
-bool
-get_boolean_value_for_key_name_from_json (const char *key, const char *json_string, bool &value)
-{
- std::string key_with_quotes = "\"";
- key_with_quotes += key;
- key_with_quotes += "\"";
- const char *c = strstr (json_string, key_with_quotes.c_str());
- if (c)
- {
- c += key_with_quotes.size();
-
- while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
- c++;
-
- if (*c == ':')
- {
- c++;
-
- while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
- c++;
-
- if (strncmp (c, "true", 4) == 0)
- {
- value = true;
- return true;
- } else if (strncmp (c, "false", 5) == 0)
- {
- value = false;
- return true;
- }
- }
+bool get_boolean_value_for_key_name_from_json(const char *key,
+ const char *json_string,
+ bool &value) {
+ std::string key_with_quotes = "\"";
+ key_with_quotes += key;
+ key_with_quotes += "\"";
+ const char *c = strstr(json_string, key_with_quotes.c_str());
+ if (c) {
+ c += key_with_quotes.size();
+
+ while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+
+ if (*c == ':') {
+ c++;
+
+ while (*c != '\0' &&
+ (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+
+ if (strncmp(c, "true", 4) == 0) {
+ value = true;
+ return true;
+ } else if (strncmp(c, "false", 5) == 0) {
+ value = false;
+ return true;
+ }
}
- return false;
+ }
+ return false;
}
// A helper function that reads an array of uint64_t's from
@@ -5333,577 +5171,582 @@ get_boolean_value_for_key_name_from_json
// Returns true if it was able to find the key name, false if it did not.
// "ints" will have all integers found in the array appended to it.
-bool
-get_array_of_ints_value_for_key_name_from_json (const char *key, const char *json_string, std::vector<uint64_t> &ints)
-{
- std::string key_with_quotes = "\"";
- key_with_quotes += key;
- key_with_quotes += "\"";
- const char *c = strstr (json_string, key_with_quotes.c_str());
- if (c)
- {
- c += key_with_quotes.size();
+bool get_array_of_ints_value_for_key_name_from_json(
+ const char *key, const char *json_string, std::vector<uint64_t> &ints) {
+ std::string key_with_quotes = "\"";
+ key_with_quotes += key;
+ key_with_quotes += "\"";
+ const char *c = strstr(json_string, key_with_quotes.c_str());
+ if (c) {
+ c += key_with_quotes.size();
+
+ while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+
+ if (*c == ':') {
+ c++;
+
+ while (*c != '\0' &&
+ (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+
+ if (*c == '[') {
+ c++;
+ while (*c != '\0' &&
+ (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+ while (1) {
+ if (!isdigit(*c)) {
+ return true;
+ }
- while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
- c++;
+ errno = 0;
+ char *endptr;
+ uint64_t value = strtoul(c, &endptr, 10);
+ if (errno == 0) {
+ ints.push_back(value);
+ } else {
+ break;
+ }
+ if (endptr == c || endptr == nullptr || *endptr == '\0') {
+ break;
+ }
+ c = endptr;
- if (*c == ':')
- {
+ while (*c != '\0' &&
+ (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
c++;
-
- while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
- c++;
-
- if (*c == '[')
- {
- c++;
- while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
- c++;
- while (1)
- {
- if (!isdigit (*c))
- {
- return true;
- }
-
- errno = 0;
- char *endptr;
- uint64_t value = strtoul (c, &endptr, 10);
- if (errno == 0)
- {
- ints.push_back (value);
- }
- else
- {
- break;
- }
- if (endptr == c || endptr == nullptr || *endptr == '\0')
- {
- break;
- }
- c = endptr;
-
- while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
- c++;
- if (*c == ',')
- c++;
- while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
- c++;
- if (*c == ']')
- {
- return true;
- }
- }
- }
+ if (*c == ',')
+ c++;
+ while (*c != '\0' &&
+ (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+ if (*c == ']') {
+ return true;
+ }
}
+ }
}
- return false;
+ }
+ return false;
}
JSONGenerator::ObjectSP
-RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only)
-{
- JSONGenerator::ArraySP threads_array_sp;
- if (m_ctx.HasValidProcessID())
- {
- threads_array_sp.reset(new JSONGenerator::Array());
-
- nub_process_t pid = m_ctx.ProcessID();
-
- nub_size_t numthreads = DNBProcessGetNumThreads (pid);
- for (nub_size_t i = 0; i < numthreads; ++i)
- {
- nub_thread_t tid = DNBProcessGetThreadAtIndex (pid, i);
-
- struct DNBThreadStopInfo tid_stop_info;
-
- const bool stop_info_valid = DNBThreadGetStopReason (pid, tid, &tid_stop_info);
-
- // If we are doing stop info only, then we only show threads that have a
- // valid stop reason
- if (threads_with_valid_stop_info_only)
- {
- if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid)
- continue;
- }
-
- JSONGenerator::DictionarySP thread_dict_sp(new JSONGenerator::Dictionary());
- thread_dict_sp->AddIntegerItem("tid", tid);
-
- std::string reason_value("none");
-
- if (stop_info_valid)
- {
- switch (tid_stop_info.reason)
- {
- case eStopTypeInvalid:
- break;
-
- case eStopTypeSignal:
- if (tid_stop_info.details.signal.signo != 0)
- {
- thread_dict_sp->AddIntegerItem("signal", tid_stop_info.details.signal.signo);
- reason_value = "signal";
- }
- break;
-
- case eStopTypeException:
- if (tid_stop_info.details.exception.type != 0)
- {
- reason_value = "exception";
- thread_dict_sp->AddIntegerItem("metype", tid_stop_info.details.exception.type);
- JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array());
- for (nub_size_t i=0; i<tid_stop_info.details.exception.data_count; ++i)
- {
- medata_array_sp->AddItem(JSONGenerator::IntegerSP(new JSONGenerator::Integer(tid_stop_info.details.exception.data[i])));
- }
- thread_dict_sp->AddItem("medata", medata_array_sp);
- }
- break;
-
- case eStopTypeExec:
- reason_value = "exec";
- break;
- }
- }
+RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) {
+ JSONGenerator::ArraySP threads_array_sp;
+ if (m_ctx.HasValidProcessID()) {
+ threads_array_sp.reset(new JSONGenerator::Array());
- thread_dict_sp->AddStringItem("reason", reason_value);
-
- if (threads_with_valid_stop_info_only == false)
- {
- const char *thread_name = DNBThreadGetName (pid, tid);
- if (thread_name && thread_name[0])
- thread_dict_sp->AddStringItem("name", thread_name);
-
- thread_identifier_info_data_t thread_ident_info;
- if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info))
- {
- if (thread_ident_info.dispatch_qaddr != 0)
- {
- thread_dict_sp->AddIntegerItem("qaddr", thread_ident_info.dispatch_qaddr);
-
- const DispatchQueueOffsets *dispatch_queue_offsets = GetDispatchQueueOffsets();
- if (dispatch_queue_offsets)
- {
- std::string queue_name;
- uint64_t queue_width = 0;
- uint64_t queue_serialnum = 0;
- nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS;
- dispatch_queue_offsets->GetThreadQueueInfo(pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t, queue_name, queue_width, queue_serialnum);
- if (dispatch_queue_t == 0 && queue_name.empty() && queue_serialnum == 0)
- {
- thread_dict_sp->AddBooleanItem ("associated_with_dispatch_queue", false);
- }
- else
- {
- thread_dict_sp->AddBooleanItem ("associated_with_dispatch_queue", true);
- }
- if (dispatch_queue_t != INVALID_NUB_ADDRESS && dispatch_queue_t != 0)
- thread_dict_sp->AddIntegerItem("dispatch_queue_t", dispatch_queue_t);
- if (!queue_name.empty())
- thread_dict_sp->AddStringItem("qname", queue_name);
- if (queue_width == 1)
- thread_dict_sp->AddStringItem("qkind", "serial");
- else if (queue_width > 1)
- thread_dict_sp->AddStringItem("qkind", "concurrent");
- if (queue_serialnum > 0)
- thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum);
- }
- }
- }
-
- DNBRegisterValue reg_value;
-
- if (g_reg_entries != NULL)
- {
- JSONGenerator::DictionarySP registers_dict_sp(new JSONGenerator::Dictionary());
-
- for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
- {
- // Expedite all registers in the first register set that aren't
- // contained in other registers
- if (g_reg_entries[reg].nub_info.set == 1 &&
- g_reg_entries[reg].nub_info.value_regs == NULL)
- {
- if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, ®_value))
- continue;
-
- std::ostringstream reg_num;
- reg_num << std::dec << g_reg_entries[reg].debugserver_regnum;
- // Encode native byte ordered bytes as hex ascii
- registers_dict_sp->AddBytesAsHexASCIIString(reg_num.str(), reg_value.value.v_uint8, g_reg_entries[reg].nub_info.size);
- }
- }
- thread_dict_sp->AddItem("registers", registers_dict_sp);
- }
-
- // Add expedited stack memory so stack backtracing doesn't need to read anything from the
- // frame pointer chain.
- StackMemoryMap stack_mmap;
- ReadStackMemory (pid, tid, stack_mmap);
- if (!stack_mmap.empty())
- {
- JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array());
-
- for (const auto &stack_memory : stack_mmap)
- {
- JSONGenerator::DictionarySP stack_memory_sp(new JSONGenerator::Dictionary());
- stack_memory_sp->AddIntegerItem("address", stack_memory.first);
- stack_memory_sp->AddBytesAsHexASCIIString("bytes", stack_memory.second.bytes, stack_memory.second.length);
- memory_array_sp->AddItem(stack_memory_sp);
- }
- thread_dict_sp->AddItem("memory", memory_array_sp);
- }
- }
-
- threads_array_sp->AddItem(thread_dict_sp);
- }
- }
- return threads_array_sp;
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_jThreadsInfo (const char *p)
-{
- JSONGenerator::ObjectSP threads_info_sp;
- std::ostringstream json;
- std::ostringstream reply_strm;
- // If we haven't run the process yet, return an error.
- if (m_ctx.HasValidProcessID())
- {
- const bool threads_with_valid_stop_info_only = false;
- JSONGenerator::ObjectSP threads_info_sp = GetJSONThreadsInfo(threads_with_valid_stop_info_only);
+ nub_process_t pid = m_ctx.ProcessID();
- if (threads_info_sp)
- {
- std::ostringstream strm;
- threads_info_sp->Dump (strm);
- std::string binary_packet = binary_encode_string (strm.str());
- if (!binary_packet.empty())
- return SendPacket (binary_packet.c_str());
- }
- }
- return SendPacket ("E85");
+ nub_size_t numthreads = DNBProcessGetNumThreads(pid);
+ for (nub_size_t i = 0; i < numthreads; ++i) {
+ nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, i);
+
+ struct DNBThreadStopInfo tid_stop_info;
+
+ const bool stop_info_valid =
+ DNBThreadGetStopReason(pid, tid, &tid_stop_info);
+
+ // If we are doing stop info only, then we only show threads that have a
+ // valid stop reason
+ if (threads_with_valid_stop_info_only) {
+ if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid)
+ continue;
+ }
-}
+ JSONGenerator::DictionarySP thread_dict_sp(
+ new JSONGenerator::Dictionary());
+ thread_dict_sp->AddIntegerItem("tid", tid);
+
+ std::string reason_value("none");
+
+ if (stop_info_valid) {
+ switch (tid_stop_info.reason) {
+ case eStopTypeInvalid:
+ break;
-rnb_err_t
-RNBRemote::HandlePacket_jThreadExtendedInfo (const char *p)
-{
- nub_process_t pid;
- std::ostringstream json;
- // If we haven't run the process yet, return an error.
- if (!m_ctx.HasValidProcessID())
- {
- return SendPacket ("E81");
- }
+ case eStopTypeSignal:
+ if (tid_stop_info.details.signal.signo != 0) {
+ thread_dict_sp->AddIntegerItem("signal",
+ tid_stop_info.details.signal.signo);
+ reason_value = "signal";
+ }
+ break;
- pid = m_ctx.ProcessID();
+ case eStopTypeException:
+ if (tid_stop_info.details.exception.type != 0) {
+ reason_value = "exception";
+ thread_dict_sp->AddIntegerItem(
+ "metype", tid_stop_info.details.exception.type);
+ JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array());
+ for (nub_size_t i = 0;
+ i < tid_stop_info.details.exception.data_count; ++i) {
+ medata_array_sp->AddItem(
+ JSONGenerator::IntegerSP(new JSONGenerator::Integer(
+ tid_stop_info.details.exception.data[i])));
+ }
+ thread_dict_sp->AddItem("medata", medata_array_sp);
+ }
+ break;
- const char thread_extended_info_str[] = { "jThreadExtendedInfo:{" };
- if (strncmp (p, thread_extended_info_str, sizeof (thread_extended_info_str) - 1) == 0)
- {
- p += strlen (thread_extended_info_str);
+ case eStopTypeExec:
+ reason_value = "exec";
+ break;
+ }
+ }
- uint64_t tid = get_integer_value_for_key_name_from_json ("thread", p);
- uint64_t plo_pthread_tsd_base_address_offset = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_base_address_offset", p);
- uint64_t plo_pthread_tsd_base_offset = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_base_offset", p);
- uint64_t plo_pthread_tsd_entry_size = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_entry_size", p);
- uint64_t dti_qos_class_index = get_integer_value_for_key_name_from_json ("dti_qos_class_index", p);
- // Commented out the two variables below as they are not being used
-// uint64_t dti_queue_index = get_integer_value_for_key_name_from_json ("dti_queue_index", p);
-// uint64_t dti_voucher_index = get_integer_value_for_key_name_from_json ("dti_voucher_index", p);
+ thread_dict_sp->AddStringItem("reason", reason_value);
- if (tid != INVALID_NUB_ADDRESS)
- {
- nub_addr_t pthread_t_value = DNBGetPThreadT (pid, tid);
+ if (threads_with_valid_stop_info_only == false) {
+ const char *thread_name = DNBThreadGetName(pid, tid);
+ if (thread_name && thread_name[0])
+ thread_dict_sp->AddStringItem("name", thread_name);
- uint64_t tsd_address = INVALID_NUB_ADDRESS;
- if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS
- && plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS
- && plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS)
- {
- tsd_address = DNBGetTSDAddressForThread (pid, tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
+ thread_identifier_info_data_t thread_ident_info;
+ if (DNBThreadGetIdentifierInfo(pid, tid, &thread_ident_info)) {
+ if (thread_ident_info.dispatch_qaddr != 0) {
+ thread_dict_sp->AddIntegerItem("qaddr",
+ thread_ident_info.dispatch_qaddr);
+
+ const DispatchQueueOffsets *dispatch_queue_offsets =
+ GetDispatchQueueOffsets();
+ if (dispatch_queue_offsets) {
+ std::string queue_name;
+ uint64_t queue_width = 0;
+ uint64_t queue_serialnum = 0;
+ nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS;
+ dispatch_queue_offsets->GetThreadQueueInfo(
+ pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t,
+ queue_name, queue_width, queue_serialnum);
+ if (dispatch_queue_t == 0 && queue_name.empty() &&
+ queue_serialnum == 0) {
+ thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
+ false);
+ } else {
+ thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue",
+ true);
+ }
+ if (dispatch_queue_t != INVALID_NUB_ADDRESS &&
+ dispatch_queue_t != 0)
+ thread_dict_sp->AddIntegerItem("dispatch_queue_t",
+ dispatch_queue_t);
+ if (!queue_name.empty())
+ thread_dict_sp->AddStringItem("qname", queue_name);
+ if (queue_width == 1)
+ thread_dict_sp->AddStringItem("qkind", "serial");
+ else if (queue_width > 1)
+ thread_dict_sp->AddStringItem("qkind", "concurrent");
+ if (queue_serialnum > 0)
+ thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum);
}
+ }
+ }
- bool timed_out = false;
- Genealogy::ThreadActivitySP thread_activity_sp;
+ DNBRegisterValue reg_value;
- // If the pthread_t value is invalid, or if we were able to fetch the thread's TSD base
- // and got an invalid value back, then we have a thread in early startup or shutdown and
- // it's possible that gathering the genealogy information for this thread go badly.
- // Ideally fetching this info for a thread in these odd states shouldn't matter - but
- // we've seen some problems with these new SPI and threads in edge-casey states.
+ if (g_reg_entries != NULL) {
+ JSONGenerator::DictionarySP registers_dict_sp(
+ new JSONGenerator::Dictionary());
+
+ for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) {
+ // Expedite all registers in the first register set that aren't
+ // contained in other registers
+ if (g_reg_entries[reg].nub_info.set == 1 &&
+ g_reg_entries[reg].nub_info.value_regs == NULL) {
+ if (!DNBThreadGetRegisterValueByID(
+ pid, tid, g_reg_entries[reg].nub_info.set,
+ g_reg_entries[reg].nub_info.reg, ®_value))
+ continue;
- double genealogy_fetch_time = 0;
- if (pthread_t_value != INVALID_NUB_ADDRESS && tsd_address != INVALID_NUB_ADDRESS)
- {
- DNBTimer timer(false);
- thread_activity_sp = DNBGetGenealogyInfoForThread (pid, tid, timed_out);
- genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0;
+ std::ostringstream reg_num;
+ reg_num << std::dec << g_reg_entries[reg].debugserver_regnum;
+ // Encode native byte ordered bytes as hex ascii
+ registers_dict_sp->AddBytesAsHexASCIIString(
+ reg_num.str(), reg_value.value.v_uint8,
+ g_reg_entries[reg].nub_info.size);
}
+ }
+ thread_dict_sp->AddItem("registers", registers_dict_sp);
+ }
- std::unordered_set<uint32_t> process_info_indexes; // an array of the process info #'s seen
+ // Add expedited stack memory so stack backtracing doesn't need to read
+ // anything from the
+ // frame pointer chain.
+ StackMemoryMap stack_mmap;
+ ReadStackMemory(pid, tid, stack_mmap);
+ if (!stack_mmap.empty()) {
+ JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array());
+
+ for (const auto &stack_memory : stack_mmap) {
+ JSONGenerator::DictionarySP stack_memory_sp(
+ new JSONGenerator::Dictionary());
+ stack_memory_sp->AddIntegerItem("address", stack_memory.first);
+ stack_memory_sp->AddBytesAsHexASCIIString(
+ "bytes", stack_memory.second.bytes, stack_memory.second.length);
+ memory_array_sp->AddItem(stack_memory_sp);
+ }
+ thread_dict_sp->AddItem("memory", memory_array_sp);
+ }
+ }
- json << "{";
+ threads_array_sp->AddItem(thread_dict_sp);
+ }
+ }
+ return threads_array_sp;
+}
- bool need_to_print_comma = false;
+rnb_err_t RNBRemote::HandlePacket_jThreadsInfo(const char *p) {
+ JSONGenerator::ObjectSP threads_info_sp;
+ std::ostringstream json;
+ std::ostringstream reply_strm;
+ // If we haven't run the process yet, return an error.
+ if (m_ctx.HasValidProcessID()) {
+ const bool threads_with_valid_stop_info_only = false;
+ JSONGenerator::ObjectSP threads_info_sp =
+ GetJSONThreadsInfo(threads_with_valid_stop_info_only);
+
+ if (threads_info_sp) {
+ std::ostringstream strm;
+ threads_info_sp->Dump(strm);
+ std::string binary_packet = binary_encode_string(strm.str());
+ if (!binary_packet.empty())
+ return SendPacket(binary_packet.c_str());
+ }
+ }
+ return SendPacket("E85");
+}
+
+rnb_err_t RNBRemote::HandlePacket_jThreadExtendedInfo(const char *p) {
+ nub_process_t pid;
+ std::ostringstream json;
+ // If we haven't run the process yet, return an error.
+ if (!m_ctx.HasValidProcessID()) {
+ return SendPacket("E81");
+ }
+
+ pid = m_ctx.ProcessID();
+
+ const char thread_extended_info_str[] = {"jThreadExtendedInfo:{"};
+ if (strncmp(p, thread_extended_info_str,
+ sizeof(thread_extended_info_str) - 1) == 0) {
+ p += strlen(thread_extended_info_str);
+
+ uint64_t tid = get_integer_value_for_key_name_from_json("thread", p);
+ uint64_t plo_pthread_tsd_base_address_offset =
+ get_integer_value_for_key_name_from_json(
+ "plo_pthread_tsd_base_address_offset", p);
+ uint64_t plo_pthread_tsd_base_offset =
+ get_integer_value_for_key_name_from_json("plo_pthread_tsd_base_offset",
+ p);
+ uint64_t plo_pthread_tsd_entry_size =
+ get_integer_value_for_key_name_from_json("plo_pthread_tsd_entry_size",
+ p);
+ uint64_t dti_qos_class_index =
+ get_integer_value_for_key_name_from_json("dti_qos_class_index", p);
+ // Commented out the two variables below as they are not being used
+ // uint64_t dti_queue_index =
+ // get_integer_value_for_key_name_from_json ("dti_queue_index", p);
+ // uint64_t dti_voucher_index =
+ // get_integer_value_for_key_name_from_json ("dti_voucher_index", p);
+
+ if (tid != INVALID_NUB_ADDRESS) {
+ nub_addr_t pthread_t_value = DNBGetPThreadT(pid, tid);
+
+ uint64_t tsd_address = INVALID_NUB_ADDRESS;
+ if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS &&
+ plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS &&
+ plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS) {
+ tsd_address = DNBGetTSDAddressForThread(
+ pid, tid, plo_pthread_tsd_base_address_offset,
+ plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
+ }
- if (thread_activity_sp && timed_out == false)
- {
- const Genealogy::Activity *activity = &thread_activity_sp->current_activity;
- bool need_vouchers_comma_sep = false;
- json << "\"activity_query_timed_out\":false,";
- if (genealogy_fetch_time != 0)
- {
- // If we append the floating point value with << we'll get it in scientific
- // notation.
- char floating_point_ascii_buffer[64];
- floating_point_ascii_buffer[0] = '\0';
- snprintf (floating_point_ascii_buffer, sizeof (floating_point_ascii_buffer), "%f", genealogy_fetch_time);
- if (strlen (floating_point_ascii_buffer) > 0)
- {
- if (need_to_print_comma)
- json << ",";
- need_to_print_comma = true;
- json << "\"activity_query_duration\":" << floating_point_ascii_buffer;
- }
- }
- if (activity->activity_id != 0)
- {
- if (need_to_print_comma)
- json << ",";
- need_to_print_comma = true;
- need_vouchers_comma_sep = true;
- json << "\"activity\":{";
- json << "\"start\":" << activity->activity_start << ",";
- json << "\"id\":" << activity->activity_id << ",";
- json << "\"parent_id\":" << activity->parent_id << ",";
- json << "\"name\":\"" << json_string_quote_metachars (activity->activity_name) << "\",";
- json << "\"reason\":\"" << json_string_quote_metachars (activity->reason) << "\"";
- json << "}";
- }
- if (thread_activity_sp->messages.size() > 0)
- {
- need_to_print_comma = true;
- if (need_vouchers_comma_sep)
- json << ",";
- need_vouchers_comma_sep = true;
- json << "\"trace_messages\":[";
- bool printed_one_message = false;
- for (auto iter = thread_activity_sp->messages.begin() ; iter != thread_activity_sp->messages.end(); ++iter)
- {
- if (printed_one_message)
- json << ",";
- else
- printed_one_message = true;
- json << "{";
- json << "\"timestamp\":" << iter->timestamp << ",";
- json << "\"activity_id\":" << iter->activity_id << ",";
- json << "\"trace_id\":" << iter->trace_id << ",";
- json << "\"thread\":" << iter->thread << ",";
- json << "\"type\":" << (int) iter->type << ",";
- json << "\"process_info_index\":" << iter->process_info_index << ",";
- process_info_indexes.insert (iter->process_info_index);
- json << "\"message\":\"" << json_string_quote_metachars (iter->message) << "\"";
- json << "}";
- }
- json << "]";
- }
- if (thread_activity_sp->breadcrumbs.size() == 1)
- {
- need_to_print_comma = true;
- if (need_vouchers_comma_sep)
- json << ",";
- need_vouchers_comma_sep = true;
- json << "\"breadcrumb\":{";
- for (auto iter = thread_activity_sp->breadcrumbs.begin() ; iter != thread_activity_sp->breadcrumbs.end(); ++iter)
- {
- json << "\"breadcrumb_id\":" << iter->breadcrumb_id << ",";
- json << "\"activity_id\":" << iter->activity_id << ",";
- json << "\"timestamp\":" << iter->timestamp << ",";
- json << "\"name\":\"" << json_string_quote_metachars (iter->name) << "\"";
- }
- json << "}";
- }
- if (process_info_indexes.size() > 0)
- {
- need_to_print_comma = true;
- if (need_vouchers_comma_sep)
- json << ",";
- need_vouchers_comma_sep = true;
- bool printed_one_process_info = false;
- for (auto iter = process_info_indexes.begin(); iter != process_info_indexes.end(); ++iter)
- {
- if (printed_one_process_info)
- json << ",";
- Genealogy::ProcessExecutableInfoSP image_info_sp;
- uint32_t idx = *iter;
- image_info_sp = DNBGetGenealogyImageInfo (pid, idx);
- if (image_info_sp)
- {
- if (!printed_one_process_info)
- {
- json << "\"process_infos\":[";
- printed_one_process_info = true;
- }
-
- json << "{";
- char uuid_buf[37];
- uuid_unparse_upper (image_info_sp->image_uuid, uuid_buf);
- json << "\"process_info_index\":" << idx << ",";
- json << "\"image_path\":\"" << json_string_quote_metachars (image_info_sp->image_path) << "\",";
- json << "\"image_uuid\":\"" << uuid_buf <<"\"";
- json << "}";
- }
- }
- if (printed_one_process_info)
- json << "]";
- }
- }
- else
- {
- if (timed_out)
- {
- if (need_to_print_comma)
- json << ",";
- need_to_print_comma = true;
- json << "\"activity_query_timed_out\":true";
- if (genealogy_fetch_time != 0)
- {
- // If we append the floating point value with << we'll get it in scientific
- // notation.
- char floating_point_ascii_buffer[64];
- floating_point_ascii_buffer[0] = '\0';
- snprintf (floating_point_ascii_buffer, sizeof (floating_point_ascii_buffer), "%f", genealogy_fetch_time);
- if (strlen (floating_point_ascii_buffer) > 0)
- {
- json << ",";
- json << "\"activity_query_duration\":" << floating_point_ascii_buffer;
- }
- }
- }
- }
+ bool timed_out = false;
+ Genealogy::ThreadActivitySP thread_activity_sp;
- if (tsd_address != INVALID_NUB_ADDRESS)
- {
- if (need_to_print_comma)
- json << ",";
- need_to_print_comma = true;
- json << "\"tsd_address\":" << tsd_address;
+ // If the pthread_t value is invalid, or if we were able to fetch the
+ // thread's TSD base
+ // and got an invalid value back, then we have a thread in early startup
+ // or shutdown and
+ // it's possible that gathering the genealogy information for this thread
+ // go badly.
+ // Ideally fetching this info for a thread in these odd states shouldn't
+ // matter - but
+ // we've seen some problems with these new SPI and threads in edge-casey
+ // states.
+
+ double genealogy_fetch_time = 0;
+ if (pthread_t_value != INVALID_NUB_ADDRESS &&
+ tsd_address != INVALID_NUB_ADDRESS) {
+ DNBTimer timer(false);
+ thread_activity_sp = DNBGetGenealogyInfoForThread(pid, tid, timed_out);
+ genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0;
+ }
- if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX)
- {
- ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread (pid, tid, tsd_address, dti_qos_class_index);
- if (requested_qos.IsValid())
- {
- if (need_to_print_comma)
- json << ",";
- need_to_print_comma = true;
- json << "\"requested_qos\":{";
- json << "\"enum_value\":" << requested_qos.enum_value << ",";
- json << "\"constant_name\":\"" << json_string_quote_metachars (requested_qos.constant_name) << "\",";
- json << "\"printable_name\":\"" << json_string_quote_metachars (requested_qos.printable_name) << "\"";
- json << "}";
- }
- }
- }
+ std::unordered_set<uint32_t>
+ process_info_indexes; // an array of the process info #'s seen
- if (pthread_t_value != INVALID_NUB_ADDRESS)
- {
- if (need_to_print_comma)
- json << ",";
- need_to_print_comma = true;
- json << "\"pthread_t\":" << pthread_t_value;
- }
+ json << "{";
- nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT (pid, tid);
- if (dispatch_queue_t_value != INVALID_NUB_ADDRESS)
- {
- if (need_to_print_comma)
- json << ",";
- need_to_print_comma = true;
- json << "\"dispatch_queue_t\":" << dispatch_queue_t_value;
+ bool need_to_print_comma = false;
+
+ if (thread_activity_sp && timed_out == false) {
+ const Genealogy::Activity *activity =
+ &thread_activity_sp->current_activity;
+ bool need_vouchers_comma_sep = false;
+ json << "\"activity_query_timed_out\":false,";
+ if (genealogy_fetch_time != 0) {
+ // If we append the floating point value with << we'll get it in
+ // scientific
+ // notation.
+ char floating_point_ascii_buffer[64];
+ floating_point_ascii_buffer[0] = '\0';
+ snprintf(floating_point_ascii_buffer,
+ sizeof(floating_point_ascii_buffer), "%f",
+ genealogy_fetch_time);
+ if (strlen(floating_point_ascii_buffer) > 0) {
+ if (need_to_print_comma)
+ json << ",";
+ need_to_print_comma = true;
+ json << "\"activity_query_duration\":"
+ << floating_point_ascii_buffer;
+ }
+ }
+ if (activity->activity_id != 0) {
+ if (need_to_print_comma)
+ json << ",";
+ need_to_print_comma = true;
+ need_vouchers_comma_sep = true;
+ json << "\"activity\":{";
+ json << "\"start\":" << activity->activity_start << ",";
+ json << "\"id\":" << activity->activity_id << ",";
+ json << "\"parent_id\":" << activity->parent_id << ",";
+ json << "\"name\":\""
+ << json_string_quote_metachars(activity->activity_name) << "\",";
+ json << "\"reason\":\""
+ << json_string_quote_metachars(activity->reason) << "\"";
+ json << "}";
+ }
+ if (thread_activity_sp->messages.size() > 0) {
+ need_to_print_comma = true;
+ if (need_vouchers_comma_sep)
+ json << ",";
+ need_vouchers_comma_sep = true;
+ json << "\"trace_messages\":[";
+ bool printed_one_message = false;
+ for (auto iter = thread_activity_sp->messages.begin();
+ iter != thread_activity_sp->messages.end(); ++iter) {
+ if (printed_one_message)
+ json << ",";
+ else
+ printed_one_message = true;
+ json << "{";
+ json << "\"timestamp\":" << iter->timestamp << ",";
+ json << "\"activity_id\":" << iter->activity_id << ",";
+ json << "\"trace_id\":" << iter->trace_id << ",";
+ json << "\"thread\":" << iter->thread << ",";
+ json << "\"type\":" << (int)iter->type << ",";
+ json << "\"process_info_index\":" << iter->process_info_index
+ << ",";
+ process_info_indexes.insert(iter->process_info_index);
+ json << "\"message\":\""
+ << json_string_quote_metachars(iter->message) << "\"";
+ json << "}";
+ }
+ json << "]";
+ }
+ if (thread_activity_sp->breadcrumbs.size() == 1) {
+ need_to_print_comma = true;
+ if (need_vouchers_comma_sep)
+ json << ",";
+ need_vouchers_comma_sep = true;
+ json << "\"breadcrumb\":{";
+ for (auto iter = thread_activity_sp->breadcrumbs.begin();
+ iter != thread_activity_sp->breadcrumbs.end(); ++iter) {
+ json << "\"breadcrumb_id\":" << iter->breadcrumb_id << ",";
+ json << "\"activity_id\":" << iter->activity_id << ",";
+ json << "\"timestamp\":" << iter->timestamp << ",";
+ json << "\"name\":\"" << json_string_quote_metachars(iter->name)
+ << "\"";
+ }
+ json << "}";
+ }
+ if (process_info_indexes.size() > 0) {
+ need_to_print_comma = true;
+ if (need_vouchers_comma_sep)
+ json << ",";
+ need_vouchers_comma_sep = true;
+ bool printed_one_process_info = false;
+ for (auto iter = process_info_indexes.begin();
+ iter != process_info_indexes.end(); ++iter) {
+ if (printed_one_process_info)
+ json << ",";
+ Genealogy::ProcessExecutableInfoSP image_info_sp;
+ uint32_t idx = *iter;
+ image_info_sp = DNBGetGenealogyImageInfo(pid, idx);
+ if (image_info_sp) {
+ if (!printed_one_process_info) {
+ json << "\"process_infos\":[";
+ printed_one_process_info = true;
+ }
+
+ json << "{";
+ char uuid_buf[37];
+ uuid_unparse_upper(image_info_sp->image_uuid, uuid_buf);
+ json << "\"process_info_index\":" << idx << ",";
+ json << "\"image_path\":\""
+ << json_string_quote_metachars(image_info_sp->image_path)
+ << "\",";
+ json << "\"image_uuid\":\"" << uuid_buf << "\"";
+ json << "}";
}
+ }
+ if (printed_one_process_info)
+ json << "]";
+ }
+ } else {
+ if (timed_out) {
+ if (need_to_print_comma)
+ json << ",";
+ need_to_print_comma = true;
+ json << "\"activity_query_timed_out\":true";
+ if (genealogy_fetch_time != 0) {
+ // If we append the floating point value with << we'll get it in
+ // scientific
+ // notation.
+ char floating_point_ascii_buffer[64];
+ floating_point_ascii_buffer[0] = '\0';
+ snprintf(floating_point_ascii_buffer,
+ sizeof(floating_point_ascii_buffer), "%f",
+ genealogy_fetch_time);
+ if (strlen(floating_point_ascii_buffer) > 0) {
+ json << ",";
+ json << "\"activity_query_duration\":"
+ << floating_point_ascii_buffer;
+ }
+ }
+ }
+ }
+ if (tsd_address != INVALID_NUB_ADDRESS) {
+ if (need_to_print_comma)
+ json << ",";
+ need_to_print_comma = true;
+ json << "\"tsd_address\":" << tsd_address;
+
+ if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX) {
+ ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread(
+ pid, tid, tsd_address, dti_qos_class_index);
+ if (requested_qos.IsValid()) {
+ if (need_to_print_comma)
+ json << ",";
+ need_to_print_comma = true;
+ json << "\"requested_qos\":{";
+ json << "\"enum_value\":" << requested_qos.enum_value << ",";
+ json << "\"constant_name\":\""
+ << json_string_quote_metachars(requested_qos.constant_name)
+ << "\",";
+ json << "\"printable_name\":\""
+ << json_string_quote_metachars(requested_qos.printable_name)
+ << "\"";
json << "}";
- std::string json_quoted = binary_encode_string (json.str());
- return SendPacket (json_quoted);
+ }
}
+ }
+
+ if (pthread_t_value != INVALID_NUB_ADDRESS) {
+ if (need_to_print_comma)
+ json << ",";
+ need_to_print_comma = true;
+ json << "\"pthread_t\":" << pthread_t_value;
+ }
+
+ nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT(pid, tid);
+ if (dispatch_queue_t_value != INVALID_NUB_ADDRESS) {
+ if (need_to_print_comma)
+ json << ",";
+ need_to_print_comma = true;
+ json << "\"dispatch_queue_t\":" << dispatch_queue_t_value;
+ }
+
+ json << "}";
+ std::string json_quoted = binary_encode_string(json.str());
+ return SendPacket(json_quoted);
}
- return SendPacket ("OK");
+ }
+ return SendPacket("OK");
}
// This packet may be called in one of three ways:
//
// jGetLoadedDynamicLibrariesInfos:{"image_count":40,"image_list_address":4295244704}
-// Look for an array of the old dyld_all_image_infos style of binary infos at the image_list_address.
-// This an array of {void* load_addr, void* mod_date, void* pathname}
+// Look for an array of the old dyld_all_image_infos style of binary infos
+// at the image_list_address.
+// This an array of {void* load_addr, void* mod_date, void* pathname}
//
// jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}
-// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to get a list of all the
+// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
+// get a list of all the
// libraries loaded
//
// jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]}
-// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to get the information
+// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to
+// get the information
// about the libraries loaded at these addresses.
//
rnb_err_t
-RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos (const char *p)
-{
- nub_process_t pid;
- // If we haven't run the process yet, return an error.
- if (!m_ctx.HasValidProcessID())
- {
- return SendPacket ("E83");
+RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p) {
+ nub_process_t pid;
+ // If we haven't run the process yet, return an error.
+ if (!m_ctx.HasValidProcessID()) {
+ return SendPacket("E83");
+ }
+
+ pid = m_ctx.ProcessID();
+
+ const char get_loaded_dynamic_libraries_infos_str[] = {
+ "jGetLoadedDynamicLibrariesInfos:{"};
+ if (strncmp(p, get_loaded_dynamic_libraries_infos_str,
+ sizeof(get_loaded_dynamic_libraries_infos_str) - 1) == 0) {
+ p += strlen(get_loaded_dynamic_libraries_infos_str);
+
+ JSONGenerator::ObjectSP json_sp;
+
+ std::vector<uint64_t> macho_addresses;
+ bool fetch_all_solibs = false;
+ if (get_boolean_value_for_key_name_from_json("fetch_all_solibs", p,
+ fetch_all_solibs) &&
+ fetch_all_solibs) {
+ json_sp = DNBGetAllLoadedLibrariesInfos(pid);
+ } else if (get_array_of_ints_value_for_key_name_from_json(
+ "solib_addresses", p, macho_addresses)) {
+ json_sp = DNBGetLibrariesInfoForAddresses(pid, macho_addresses);
+ } else {
+ nub_addr_t image_list_address =
+ get_integer_value_for_key_name_from_json("image_list_address", p);
+ nub_addr_t image_count =
+ get_integer_value_for_key_name_from_json("image_count", p);
+
+ if (image_list_address != INVALID_NUB_ADDRESS &&
+ image_count != INVALID_NUB_ADDRESS) {
+ json_sp = DNBGetLoadedDynamicLibrariesInfos(pid, image_list_address,
+ image_count);
+ }
}
- pid = m_ctx.ProcessID();
-
- const char get_loaded_dynamic_libraries_infos_str[] = { "jGetLoadedDynamicLibrariesInfos:{" };
- if (strncmp (p, get_loaded_dynamic_libraries_infos_str, sizeof (get_loaded_dynamic_libraries_infos_str) - 1) == 0)
- {
- p += strlen (get_loaded_dynamic_libraries_infos_str);
-
- JSONGenerator::ObjectSP json_sp;
-
- std::vector<uint64_t> macho_addresses;
- bool fetch_all_solibs = false;
- if (get_boolean_value_for_key_name_from_json ("fetch_all_solibs", p, fetch_all_solibs) && fetch_all_solibs)
- {
- json_sp = DNBGetAllLoadedLibrariesInfos (pid);
- }
- else if (get_array_of_ints_value_for_key_name_from_json ("solib_addresses", p, macho_addresses))
- {
- json_sp = DNBGetLibrariesInfoForAddresses (pid, macho_addresses);
- }
- else
- {
- nub_addr_t image_list_address = get_integer_value_for_key_name_from_json ("image_list_address", p);
- nub_addr_t image_count = get_integer_value_for_key_name_from_json ("image_count", p);
-
- if (image_list_address != INVALID_NUB_ADDRESS && image_count != INVALID_NUB_ADDRESS)
- {
- json_sp = DNBGetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count);
- }
- }
-
- if (json_sp.get())
- {
- std::ostringstream json_str;
- json_sp->Dump (json_str);
- if (json_str.str().size() > 0)
- {
- std::string json_str_quoted = binary_encode_string (json_str.str());
- return SendPacket (json_str_quoted.c_str());
- }
- else
- {
- SendPacket ("E84");
- }
- }
+ if (json_sp.get()) {
+ std::ostringstream json_str;
+ json_sp->Dump(json_str);
+ if (json_str.str().size() > 0) {
+ std::string json_str_quoted = binary_encode_string(json_str.str());
+ return SendPacket(json_str_quoted.c_str());
+ } else {
+ SendPacket("E84");
+ }
}
- return SendPacket ("OK");
+ }
+ return SendPacket("OK");
}
// This packet does not currently take any arguments. So the behavior is
@@ -5911,556 +5754,539 @@ RNBRemote::HandlePacket_jGetLoadedDynami
// send information about the inferior's shared cache
// jGetSharedCacheInfo:
// send "OK" to indicate that this packet is supported
-rnb_err_t
-RNBRemote::HandlePacket_jGetSharedCacheInfo (const char *p)
-{
- nub_process_t pid;
- // If we haven't run the process yet, return an error.
- if (!m_ctx.HasValidProcessID())
- {
- return SendPacket ("E85");
- }
-
- pid = m_ctx.ProcessID();
-
- const char get_shared_cache_info_str[] = { "jGetSharedCacheInfo:{" };
- if (strncmp (p, get_shared_cache_info_str, sizeof (get_shared_cache_info_str) - 1) == 0)
- {
- JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo (pid);
-
- if (json_sp.get())
- {
- std::ostringstream json_str;
- json_sp->Dump (json_str);
- if (json_str.str().size() > 0)
- {
- std::string json_str_quoted = binary_encode_string (json_str.str());
- return SendPacket (json_str_quoted.c_str());
- }
- else
- {
- SendPacket ("E86");
- }
- }
+rnb_err_t RNBRemote::HandlePacket_jGetSharedCacheInfo(const char *p) {
+ nub_process_t pid;
+ // If we haven't run the process yet, return an error.
+ if (!m_ctx.HasValidProcessID()) {
+ return SendPacket("E85");
+ }
+
+ pid = m_ctx.ProcessID();
+
+ const char get_shared_cache_info_str[] = {"jGetSharedCacheInfo:{"};
+ if (strncmp(p, get_shared_cache_info_str,
+ sizeof(get_shared_cache_info_str) - 1) == 0) {
+ JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo(pid);
+
+ if (json_sp.get()) {
+ std::ostringstream json_str;
+ json_sp->Dump(json_str);
+ if (json_str.str().size() > 0) {
+ std::string json_str_quoted = binary_encode_string(json_str.str());
+ return SendPacket(json_str_quoted.c_str());
+ } else {
+ SendPacket("E86");
+ }
}
- return SendPacket ("OK");
+ }
+ return SendPacket("OK");
}
-static bool
-MachHeaderIsMainExecutable (nub_process_t pid, uint32_t addr_size, nub_addr_t mach_header_addr, mach_header &mh)
-{
- DNBLogThreadedIf (LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = %u, mach_header_addr = 0x%16.16llx)", pid, addr_size, mach_header_addr);
- const nub_size_t bytes_read = DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh);
- if (bytes_read == sizeof(mh))
- {
- DNBLogThreadedIf (LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = %u, mach_header_addr = 0x%16.16llx): mh = {\n magic = 0x%8.8x\n cpu = 0x%8.8x\n sub = 0x%8.8x\n filetype = %u\n ncmds = %u\n sizeofcmds = 0x%8.8x\n flags = 0x%8.8x }", pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype, mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags);
- if ((addr_size == 4 && mh.magic == MH_MAGIC) ||
- (addr_size == 8 && mh.magic == MH_MAGIC_64))
- {
- if (mh.filetype == MH_EXECUTE)
- {
- DNBLogThreadedIf (LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = %u, mach_header_addr = 0x%16.16llx) -> this is the executable!!!", pid, addr_size, mach_header_addr);
- return true;
- }
- }
+static bool MachHeaderIsMainExecutable(nub_process_t pid, uint32_t addr_size,
+ nub_addr_t mach_header_addr,
+ mach_header &mh) {
+ DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, "
+ "addr_size = %u, mach_header_addr = "
+ "0x%16.16llx)",
+ pid, addr_size, mach_header_addr);
+ const nub_size_t bytes_read =
+ DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh);
+ if (bytes_read == sizeof(mh)) {
+ DNBLogThreadedIf(
+ LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = "
+ "%u, mach_header_addr = 0x%16.16llx): mh = {\n magic = "
+ "0x%8.8x\n cpu = 0x%8.8x\n sub = 0x%8.8x\n filetype = "
+ "%u\n ncmds = %u\n sizeofcmds = 0x%8.8x\n flags = "
+ "0x%8.8x }",
+ pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype,
+ mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags);
+ if ((addr_size == 4 && mh.magic == MH_MAGIC) ||
+ (addr_size == 8 && mh.magic == MH_MAGIC_64)) {
+ if (mh.filetype == MH_EXECUTE) {
+ DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = "
+ "%u, addr_size = %u, mach_header_addr = "
+ "0x%16.16llx) -> this is the "
+ "executable!!!",
+ pid, addr_size, mach_header_addr);
+ return true;
+ }
}
- return false;
+ }
+ return false;
}
-static nub_addr_t
-GetMachHeaderForMainExecutable (const nub_process_t pid, const uint32_t addr_size, mach_header &mh)
-{
- struct AllImageInfos
- {
- uint32_t version;
- uint32_t dylib_info_count;
- uint64_t dylib_info_addr;
- };
-
- uint64_t mach_header_addr = 0;
-
- const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress (pid);
- uint8_t bytes[256];
- nub_size_t bytes_read = 0;
- DNBDataRef data (bytes, sizeof(bytes), false);
- DNBDataRef::offset_t offset = 0;
- data.SetPointerSize(addr_size);
-
- //----------------------------------------------------------------------
- // When we are sitting at __dyld_start, the kernel has placed the
- // address of the mach header of the main executable on the stack. If we
- // read the SP and dereference a pointer, we might find the mach header
- // for the executable. We also just make sure there is only 1 thread
- // since if we are at __dyld_start we shouldn't have multiple threads.
- //----------------------------------------------------------------------
- if (DNBProcessGetNumThreads(pid) == 1)
- {
- nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0);
- if (tid != INVALID_NUB_THREAD)
- {
- DNBRegisterValue sp_value;
- if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_SP, &sp_value))
- {
- uint64_t sp = addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32;
- bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes);
- if (bytes_read == addr_size)
- {
- offset = 0;
- mach_header_addr = data.GetPointer(&offset);
- if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
- return mach_header_addr;
- }
- }
+static nub_addr_t GetMachHeaderForMainExecutable(const nub_process_t pid,
+ const uint32_t addr_size,
+ mach_header &mh) {
+ struct AllImageInfos {
+ uint32_t version;
+ uint32_t dylib_info_count;
+ uint64_t dylib_info_addr;
+ };
+
+ uint64_t mach_header_addr = 0;
+
+ const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress(pid);
+ uint8_t bytes[256];
+ nub_size_t bytes_read = 0;
+ DNBDataRef data(bytes, sizeof(bytes), false);
+ DNBDataRef::offset_t offset = 0;
+ data.SetPointerSize(addr_size);
+
+ //----------------------------------------------------------------------
+ // When we are sitting at __dyld_start, the kernel has placed the
+ // address of the mach header of the main executable on the stack. If we
+ // read the SP and dereference a pointer, we might find the mach header
+ // for the executable. We also just make sure there is only 1 thread
+ // since if we are at __dyld_start we shouldn't have multiple threads.
+ //----------------------------------------------------------------------
+ if (DNBProcessGetNumThreads(pid) == 1) {
+ nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0);
+ if (tid != INVALID_NUB_THREAD) {
+ DNBRegisterValue sp_value;
+ if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC,
+ GENERIC_REGNUM_SP, &sp_value)) {
+ uint64_t sp =
+ addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32;
+ bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes);
+ if (bytes_read == addr_size) {
+ offset = 0;
+ mach_header_addr = data.GetPointer(&offset);
+ if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
+ return mach_header_addr;
}
+ }
}
+ }
- //----------------------------------------------------------------------
- // Check the dyld_all_image_info structure for a list of mach header
- // since it is a very easy thing to check
- //----------------------------------------------------------------------
- if (shlib_addr != INVALID_NUB_ADDRESS)
- {
- bytes_read = DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes);
- if (bytes_read > 0)
- {
- AllImageInfos aii;
+ //----------------------------------------------------------------------
+ // Check the dyld_all_image_info structure for a list of mach header
+ // since it is a very easy thing to check
+ //----------------------------------------------------------------------
+ if (shlib_addr != INVALID_NUB_ADDRESS) {
+ bytes_read =
+ DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes);
+ if (bytes_read > 0) {
+ AllImageInfos aii;
+ offset = 0;
+ aii.version = data.Get32(&offset);
+ aii.dylib_info_count = data.Get32(&offset);
+ if (aii.dylib_info_count > 0) {
+ aii.dylib_info_addr = data.GetPointer(&offset);
+ if (aii.dylib_info_addr != 0) {
+ const size_t image_info_byte_size = 3 * addr_size;
+ for (uint32_t i = 0; i < aii.dylib_info_count; ++i) {
+ bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr +
+ i * image_info_byte_size,
+ image_info_byte_size, bytes);
+ if (bytes_read != image_info_byte_size)
+ break;
offset = 0;
- aii.version = data.Get32(&offset);
- aii.dylib_info_count = data.Get32(&offset);
- if (aii.dylib_info_count > 0)
- {
- aii.dylib_info_addr = data.GetPointer(&offset);
- if (aii.dylib_info_addr != 0)
- {
- const size_t image_info_byte_size = 3 * addr_size;
- for (uint32_t i=0; i<aii.dylib_info_count; ++i)
- {
- bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr + i * image_info_byte_size, image_info_byte_size, bytes);
- if (bytes_read != image_info_byte_size)
- break;
- offset = 0;
- mach_header_addr = data.GetPointer(&offset);
- if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
- return mach_header_addr;
- }
- }
- }
- }
- }
-
- //----------------------------------------------------------------------
- // We failed to find the executable's mach header from the all image
- // infos and by dereferencing the stack pointer. Now we fall back to
- // enumerating the memory regions and looking for regions that are
- // executable.
- //----------------------------------------------------------------------
- DNBRegionInfo region_info;
- mach_header_addr = 0;
- while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, ®ion_info))
- {
- if (region_info.size == 0)
- break;
-
- if (region_info.permissions & eMemoryPermissionsExecutable)
- {
- DNBLogThreadedIf (LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: checking region for executable mach header", region_info.addr, region_info.addr + region_info.size, (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-', (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-', (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
- if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
- return mach_header_addr;
- }
- else
- {
- DNBLogThreadedIf (LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region", region_info.addr, region_info.addr + region_info.size, (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-', (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-', (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
+ mach_header_addr = data.GetPointer(&offset);
+ if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr,
+ mh))
+ return mach_header_addr;
+ }
}
- // Set the address to the next mapped region
- mach_header_addr = region_info.addr + region_info.size;
+ }
}
- bzero (&mh, sizeof(mh));
- return INVALID_NUB_ADDRESS;
-}
-
-rnb_err_t
-RNBRemote::HandlePacket_qSymbol (const char *command)
-{
- const char *p = command;
- p += strlen ("qSymbol:");
- const char *sep = strchr(p, ':');
-
- std::string symbol_name;
- std::string symbol_value_str;
- // Extract the symbol value if there is one
- if (sep > p)
- symbol_value_str.assign(p, sep - p);
- p = sep + 1;
+ }
- if (*p)
- {
- // We have a symbol name
- symbol_name = decode_hex_ascii_string(p);
- if (!symbol_value_str.empty())
- {
- nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16);
- if (symbol_name == "dispatch_queue_offsets")
- m_dispatch_queue_offsets_addr = symbol_value;
- }
- ++m_qSymbol_index;
- }
+ //----------------------------------------------------------------------
+ // We failed to find the executable's mach header from the all image
+ // infos and by dereferencing the stack pointer. Now we fall back to
+ // enumerating the memory regions and looking for regions that are
+ // executable.
+ //----------------------------------------------------------------------
+ DNBRegionInfo region_info;
+ mach_header_addr = 0;
+ while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, ®ion_info)) {
+ if (region_info.size == 0)
+ break;
+
+ if (region_info.permissions & eMemoryPermissionsExecutable) {
+ DNBLogThreadedIf(
+ LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: "
+ "checking region for executable mach header",
+ region_info.addr, region_info.addr + region_info.size,
+ (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
+ (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
+ (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
+ if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh))
+ return mach_header_addr;
+ } else {
+ DNBLogThreadedIf(
+ LOG_RNB_PROC,
+ "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region",
+ region_info.addr, region_info.addr + region_info.size,
+ (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-',
+ (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-',
+ (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-');
+ }
+ // Set the address to the next mapped region
+ mach_header_addr = region_info.addr + region_info.size;
+ }
+ bzero(&mh, sizeof(mh));
+ return INVALID_NUB_ADDRESS;
+}
+
+rnb_err_t RNBRemote::HandlePacket_qSymbol(const char *command) {
+ const char *p = command;
+ p += strlen("qSymbol:");
+ const char *sep = strchr(p, ':');
+
+ std::string symbol_name;
+ std::string symbol_value_str;
+ // Extract the symbol value if there is one
+ if (sep > p)
+ symbol_value_str.assign(p, sep - p);
+ p = sep + 1;
+
+ if (*p) {
+ // We have a symbol name
+ symbol_name = decode_hex_ascii_string(p);
+ if (!symbol_value_str.empty()) {
+ nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16);
+ if (symbol_name == "dispatch_queue_offsets")
+ m_dispatch_queue_offsets_addr = symbol_value;
+ }
+ ++m_qSymbol_index;
+ } else {
+ // No symbol name, set our symbol index to zero so we can
+ // read any symbols that we need
+ m_qSymbol_index = 0;
+ }
+
+ symbol_name.clear();
+
+ if (m_qSymbol_index == 0) {
+ if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS)
+ symbol_name = "dispatch_queue_offsets";
else
- {
- // No symbol name, set our symbol index to zero so we can
- // read any symbols that we need
- m_qSymbol_index = 0;
- }
-
- symbol_name.clear();
-
- if (m_qSymbol_index == 0)
- {
- if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS)
- symbol_name = "dispatch_queue_offsets";
- else
- ++m_qSymbol_index;
- }
-
-// // Lookup next symbol when we have one...
-// if (m_qSymbol_index == 1)
-// {
-// }
+ ++m_qSymbol_index;
+ }
+ // // Lookup next symbol when we have one...
+ // if (m_qSymbol_index == 1)
+ // {
+ // }
- if (symbol_name.empty())
- {
- // Done with symbol lookups
- return SendPacket ("OK");
- }
- else
- {
- std::ostringstream reply;
- reply << "qSymbol:";
- for (size_t i = 0; i < symbol_name.size(); ++i)
- reply << RAWHEX8(symbol_name[i]);
- return SendPacket (reply.str().c_str());
- }
+ if (symbol_name.empty()) {
+ // Done with symbol lookups
+ return SendPacket("OK");
+ } else {
+ std::ostringstream reply;
+ reply << "qSymbol:";
+ for (size_t i = 0; i < symbol_name.size(); ++i)
+ reply << RAWHEX8(symbol_name[i]);
+ return SendPacket(reply.str().c_str());
+ }
}
// Note that all numeric values returned by qProcessInfo are hex encoded,
// including the pid and the cpu type.
-rnb_err_t
-RNBRemote::HandlePacket_qProcessInfo (const char *p)
-{
- nub_process_t pid;
- std::ostringstream rep;
-
- // If we haven't run the process yet, return an error.
- if (!m_ctx.HasValidProcessID())
- return SendPacket ("E68");
-
- pid = m_ctx.ProcessID();
-
- rep << "pid:" << std::hex << pid << ';';
-
- int procpid_mib[4];
- procpid_mib[0] = CTL_KERN;
- procpid_mib[1] = KERN_PROC;
- procpid_mib[2] = KERN_PROC_PID;
- procpid_mib[3] = pid;
- struct kinfo_proc proc_kinfo;
- size_t proc_kinfo_size = sizeof(struct kinfo_proc);
+rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) {
+ nub_process_t pid;
+ std::ostringstream rep;
+
+ // If we haven't run the process yet, return an error.
+ if (!m_ctx.HasValidProcessID())
+ return SendPacket("E68");
+
+ pid = m_ctx.ProcessID();
+
+ rep << "pid:" << std::hex << pid << ';';
+
+ int procpid_mib[4];
+ procpid_mib[0] = CTL_KERN;
+ procpid_mib[1] = KERN_PROC;
+ procpid_mib[2] = KERN_PROC_PID;
+ procpid_mib[3] = pid;
+ struct kinfo_proc proc_kinfo;
+ size_t proc_kinfo_size = sizeof(struct kinfo_proc);
+
+ if (::sysctl(procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
+ if (proc_kinfo_size > 0) {
+ rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
+ rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid
+ << ';';
+ rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid
+ << ';';
+ rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid
+ << ';';
+ if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
+ rep << "effective-gid:" << std::hex
+ << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
+ }
+ }
+
+ cpu_type_t cputype = DNBProcessGetCPUType(pid);
+ if (cputype == 0) {
+ DNBLog("Unable to get the process cpu_type, making a best guess.");
+ cputype = best_guess_cpu_type();
+ }
+
+ uint32_t addr_size = 0;
+ if (cputype != 0) {
+ rep << "cputype:" << std::hex << cputype << ";";
+ if (cputype & CPU_ARCH_ABI64)
+ addr_size = 8;
+ else
+ addr_size = 4;
+ }
- if (::sysctl (procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
- {
- if (proc_kinfo_size > 0)
- {
- rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
- rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ';';
- rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ';';
- rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ';';
- if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
- rep << "effective-gid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
- }
- }
-
- cpu_type_t cputype = DNBProcessGetCPUType (pid);
- if (cputype == 0)
- {
- DNBLog ("Unable to get the process cpu_type, making a best guess.");
- cputype = best_guess_cpu_type();
+ bool host_cpu_is_64bit = false;
+ uint32_t is64bit_capable;
+ size_t is64bit_capable_len = sizeof(is64bit_capable);
+ if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable,
+ &is64bit_capable_len, NULL, 0) == 0)
+ host_cpu_is_64bit = is64bit_capable != 0;
+
+ uint32_t cpusubtype;
+ size_t cpusubtype_len = sizeof(cpusubtype);
+ if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) ==
+ 0) {
+ // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected
+ // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the
+ // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu
+ // subtype
+ // for i386...
+ if (host_cpu_is_64bit) {
+ if (cputype == CPU_TYPE_X86) {
+ cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
+ } else if (cputype == CPU_TYPE_ARM) {
+ // We can query a process' cputype but we cannot query a process'
+ // cpusubtype.
+ // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit
+ // process) and we
+ // need to override the host cpusubtype (which is in the
+ // CPU_SUBTYPE_ARM64 subtype namespace)
+ // with a reasonable CPU_SUBTYPE_ARMV7 subtype.
+ cpusubtype = 11; // CPU_SUBTYPE_ARM_V7S
+ }
}
+ rep << "cpusubtype:" << std::hex << cpusubtype << ';';
+ }
- uint32_t addr_size = 0;
- if (cputype != 0)
- {
- rep << "cputype:" << std::hex << cputype << ";";
- if (cputype & CPU_ARCH_ABI64)
- addr_size = 8;
- else
- addr_size = 4;
- }
-
- bool host_cpu_is_64bit = false;
- uint32_t is64bit_capable;
- size_t is64bit_capable_len = sizeof (is64bit_capable);
- if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable, &is64bit_capable_len, NULL, 0) == 0)
- host_cpu_is_64bit = is64bit_capable != 0;
-
- uint32_t cpusubtype;
- size_t cpusubtype_len = sizeof(cpusubtype);
- if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) == 0)
- {
- // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected
- // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the
- // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu subtype
- // for i386...
- if (host_cpu_is_64bit)
- {
- if (cputype == CPU_TYPE_X86)
- {
- cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
- }
- else if (cputype == CPU_TYPE_ARM)
- {
- // We can query a process' cputype but we cannot query a process' cpusubtype.
- // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit process) and we
- // need to override the host cpusubtype (which is in the CPU_SUBTYPE_ARM64 subtype namespace)
- // with a reasonable CPU_SUBTYPE_ARMV7 subtype.
- cpusubtype = 11; // CPU_SUBTYPE_ARM_V7S
- }
- }
- rep << "cpusubtype:" << std::hex << cpusubtype << ';';
- }
+ bool os_handled = false;
+ if (addr_size > 0) {
+ rep << "ptrsize:" << std::dec << addr_size << ';';
+
+#if (defined(__x86_64__) || defined(__i386__))
+ // Try and get the OS type by looking at the load commands in the main
+ // executable and looking for a LC_VERSION_MIN load command. This is the
+ // most reliable way to determine the "ostype" value when on desktop.
+
+ mach_header mh;
+ nub_addr_t exe_mach_header_addr =
+ GetMachHeaderForMainExecutable(pid, addr_size, mh);
+ if (exe_mach_header_addr != INVALID_NUB_ADDRESS) {
+ uint64_t load_command_addr =
+ exe_mach_header_addr +
+ ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header));
+ load_command lc;
+ for (uint32_t i = 0; i < mh.ncmds && !os_handled; ++i) {
+ const nub_size_t bytes_read =
+ DNBProcessMemoryRead(pid, load_command_addr, sizeof(lc), &lc);
+ uint32_t raw_cmd = lc.cmd & ~LC_REQ_DYLD;
+ if (bytes_read != sizeof(lc))
+ break;
+ switch (raw_cmd) {
+ case LC_VERSION_MIN_IPHONEOS:
+ os_handled = true;
+ rep << "ostype:ios;";
+ DNBLogThreadedIf(LOG_RNB_PROC,
+ "LC_VERSION_MIN_IPHONEOS -> 'ostype:ios;'");
+ break;
- bool os_handled = false;
- if (addr_size > 0)
- {
- rep << "ptrsize:" << std::dec << addr_size << ';';
+ case LC_VERSION_MIN_MACOSX:
+ os_handled = true;
+ rep << "ostype:macosx;";
+ DNBLogThreadedIf(LOG_RNB_PROC,
+ "LC_VERSION_MIN_MACOSX -> 'ostype:macosx;'");
+ break;
-#if (defined (__x86_64__) || defined (__i386__))
- // Try and get the OS type by looking at the load commands in the main
- // executable and looking for a LC_VERSION_MIN load command. This is the
- // most reliable way to determine the "ostype" value when on desktop.
-
- mach_header mh;
- nub_addr_t exe_mach_header_addr = GetMachHeaderForMainExecutable (pid, addr_size, mh);
- if (exe_mach_header_addr != INVALID_NUB_ADDRESS)
- {
- uint64_t load_command_addr = exe_mach_header_addr + ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header));
- load_command lc;
- for (uint32_t i=0; i<mh.ncmds && !os_handled; ++i)
- {
- const nub_size_t bytes_read = DNBProcessMemoryRead (pid, load_command_addr, sizeof(lc), &lc);
- uint32_t raw_cmd = lc.cmd & ~LC_REQ_DYLD;
- if (bytes_read != sizeof(lc))
- break;
- switch (raw_cmd)
- {
- case LC_VERSION_MIN_IPHONEOS:
- os_handled = true;
- rep << "ostype:ios;";
- DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_IPHONEOS -> 'ostype:ios;'");
- break;
-
- case LC_VERSION_MIN_MACOSX:
- os_handled = true;
- rep << "ostype:macosx;";
- DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_MACOSX -> 'ostype:macosx;'");
- break;
-
-#if defined (LC_VERSION_MIN_TVOS)
- case LC_VERSION_MIN_TVOS:
- os_handled = true;
- rep << "ostype:tvos;";
- DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_TVOS -> 'ostype:tvos;'");
- break;
+#if defined(LC_VERSION_MIN_TVOS)
+ case LC_VERSION_MIN_TVOS:
+ os_handled = true;
+ rep << "ostype:tvos;";
+ DNBLogThreadedIf(LOG_RNB_PROC,
+ "LC_VERSION_MIN_TVOS -> 'ostype:tvos;'");
+ break;
#endif
-#if defined (LC_VERSION_MIN_WATCHOS)
- case LC_VERSION_MIN_WATCHOS:
- os_handled = true;
- rep << "ostype:watchos;";
- DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_WATCHOS -> 'ostype:watchos;'");
- break;
+#if defined(LC_VERSION_MIN_WATCHOS)
+ case LC_VERSION_MIN_WATCHOS:
+ os_handled = true;
+ rep << "ostype:watchos;";
+ DNBLogThreadedIf(LOG_RNB_PROC,
+ "LC_VERSION_MIN_WATCHOS -> 'ostype:watchos;'");
+ break;
#endif
- default:
- break;
- }
- load_command_addr = load_command_addr + lc.cmdsize;
- }
+ default:
+ break;
}
-#endif
+ load_command_addr = load_command_addr + lc.cmdsize;
+ }
}
+#endif
+ }
- // If we weren't able to find the OS in a LC_VERSION_MIN load command, try
- // to set it correctly by using the cpu type and other tricks
- if (!os_handled)
- {
- // The OS in the triple should be "ios" or "macosx" which doesn't match our
- // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
- // this for now.
- if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
- {
-#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1
- rep << "ostype:tvos;";
-#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
- rep << "ostype:watchos;";
+ // If we weren't able to find the OS in a LC_VERSION_MIN load command, try
+ // to set it correctly by using the cpu type and other tricks
+ if (!os_handled) {
+ // The OS in the triple should be "ios" or "macosx" which doesn't match our
+ // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
+ // this for now.
+ if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) {
+#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
+ rep << "ostype:tvos;";
+#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+ rep << "ostype:watchos;";
#else
- rep << "ostype:ios;";
+ rep << "ostype:ios;";
#endif
- }
- else
- {
- bool is_ios_simulator = false;
- if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64)
- {
- // Check for iOS simulator binaries by getting the process argument
- // and environment and checking for SIMULATOR_UDID in the environment
- int proc_args_mib[3] = { CTL_KERN, KERN_PROCARGS2, (int)pid };
-
- uint8_t arg_data[8192];
- size_t arg_data_size = sizeof(arg_data);
- if (::sysctl (proc_args_mib, 3, arg_data, &arg_data_size , NULL, 0) == 0)
- {
- DNBDataRef data (arg_data, arg_data_size, false);
- DNBDataRef::offset_t offset = 0;
- uint32_t argc = data.Get32 (&offset);
- const char *cstr;
-
- cstr = data.GetCStr (&offset);
- if (cstr)
- {
- // Skip NULLs
- while (1)
- {
- const char *p = data.PeekCStr(offset);
- if ((p == NULL) || (*p != '\0'))
- break;
- ++offset;
- }
- // Now skip all arguments
- for (uint32_t i = 0; i < argc; ++i)
- {
- data.GetCStr(&offset);
- }
-
- // Now iterate across all environment variables
- while ((cstr = data.GetCStr(&offset)))
- {
- if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) == 0)
- {
- is_ios_simulator = true;
- break;
- }
- if (cstr[0] == '\0')
- break;
-
- }
- }
- }
+ } else {
+ bool is_ios_simulator = false;
+ if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64) {
+ // Check for iOS simulator binaries by getting the process argument
+ // and environment and checking for SIMULATOR_UDID in the environment
+ int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2, (int)pid};
+
+ uint8_t arg_data[8192];
+ size_t arg_data_size = sizeof(arg_data);
+ if (::sysctl(proc_args_mib, 3, arg_data, &arg_data_size, NULL, 0) ==
+ 0) {
+ DNBDataRef data(arg_data, arg_data_size, false);
+ DNBDataRef::offset_t offset = 0;
+ uint32_t argc = data.Get32(&offset);
+ const char *cstr;
+
+ cstr = data.GetCStr(&offset);
+ if (cstr) {
+ // Skip NULLs
+ while (1) {
+ const char *p = data.PeekCStr(offset);
+ if ((p == NULL) || (*p != '\0'))
+ break;
+ ++offset;
}
- if (is_ios_simulator)
- {
-#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1
- rep << "ostype:tvos;";
-#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
- rep << "ostype:watchos;";
-#else
- rep << "ostype:ios;";
-#endif
+ // Now skip all arguments
+ for (uint32_t i = 0; i < argc; ++i) {
+ data.GetCStr(&offset);
}
- else
- {
- rep << "ostype:macosx;";
+
+ // Now iterate across all environment variables
+ while ((cstr = data.GetCStr(&offset))) {
+ if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) ==
+ 0) {
+ is_ios_simulator = true;
+ break;
+ }
+ if (cstr[0] == '\0')
+ break;
}
+ }
}
+ }
+ if (is_ios_simulator) {
+#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
+ rep << "ostype:tvos;";
+#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+ rep << "ostype:watchos;";
+#else
+ rep << "ostype:ios;";
+#endif
+ } else {
+ rep << "ostype:macosx;";
+ }
}
+ }
- rep << "vendor:apple;";
+ rep << "vendor:apple;";
-#if defined (__LITTLE_ENDIAN__)
- rep << "endian:little;";
-#elif defined (__BIG_ENDIAN__)
- rep << "endian:big;";
-#elif defined (__PDP_ENDIAN__)
- rep << "endian:pdp;";
+#if defined(__LITTLE_ENDIAN__)
+ rep << "endian:little;";
+#elif defined(__BIG_ENDIAN__)
+ rep << "endian:big;";
+#elif defined(__PDP_ENDIAN__)
+ rep << "endian:pdp;";
#endif
- if (addr_size == 0)
- {
-#if (defined (__x86_64__) || defined (__i386__)) && defined (x86_THREAD_STATE)
- nub_thread_t thread = DNBProcessGetCurrentThreadMachPort (pid);
- kern_return_t kr;
- x86_thread_state_t gp_regs;
- mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
- kr = thread_get_state (static_cast<thread_act_t>(thread),
- x86_THREAD_STATE,
- (thread_state_t) &gp_regs,
- &gp_count);
- if (kr == KERN_SUCCESS)
- {
- if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
- rep << "ptrsize:8;";
- else
- rep << "ptrsize:4;";
- }
-#elif defined (__arm__)
+ if (addr_size == 0) {
+#if (defined(__x86_64__) || defined(__i386__)) && defined(x86_THREAD_STATE)
+ nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
+ kern_return_t kr;
+ x86_thread_state_t gp_regs;
+ mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
+ kr = thread_get_state(static_cast<thread_act_t>(thread), x86_THREAD_STATE,
+ (thread_state_t)&gp_regs, &gp_count);
+ if (kr == KERN_SUCCESS) {
+ if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
+ rep << "ptrsize:8;";
+ else
rep << "ptrsize:4;";
-#elif (defined (__arm64__) || defined (__aarch64__)) && defined (ARM_UNIFIED_THREAD_STATE)
- nub_thread_t thread = DNBProcessGetCurrentThreadMachPort (pid);
- kern_return_t kr;
- arm_unified_thread_state_t gp_regs;
- mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT;
- kr = thread_get_state (thread, ARM_UNIFIED_THREAD_STATE,
- (thread_state_t) &gp_regs, &gp_count);
- if (kr == KERN_SUCCESS)
- {
- if (gp_regs.ash.flavor == ARM_THREAD_STATE64)
- rep << "ptrsize:8;";
- else
- rep << "ptrsize:4;";
- }
-#endif
}
-
- return SendPacket (rep.str());
-}
-
-const RNBRemote::DispatchQueueOffsets *
-RNBRemote::GetDispatchQueueOffsets()
-{
- if (!m_dispatch_queue_offsets.IsValid() && m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS && m_ctx.HasValidProcessID())
- {
- nub_process_t pid = m_ctx.ProcessID();
- nub_size_t bytes_read = DNBProcessMemoryRead(pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets), &m_dispatch_queue_offsets);
- if (bytes_read != sizeof(m_dispatch_queue_offsets))
- m_dispatch_queue_offsets.Clear();
+#elif defined(__arm__)
+ rep << "ptrsize:4;";
+#elif (defined(__arm64__) || defined(__aarch64__)) && \
+ defined(ARM_UNIFIED_THREAD_STATE)
+ nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid);
+ kern_return_t kr;
+ arm_unified_thread_state_t gp_regs;
+ mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT;
+ kr = thread_get_state(thread, ARM_UNIFIED_THREAD_STATE,
+ (thread_state_t)&gp_regs, &gp_count);
+ if (kr == KERN_SUCCESS) {
+ if (gp_regs.ash.flavor == ARM_THREAD_STATE64)
+ rep << "ptrsize:8;";
+ else
+ rep << "ptrsize:4;";
}
+#endif
+ }
- if (m_dispatch_queue_offsets.IsValid())
- return &m_dispatch_queue_offsets;
- else
- return nullptr;
-}
-
-void
-RNBRemote::EnableCompressionNextSendPacket (compression_types type)
-{
- m_compression_mode = type;
- m_enable_compression_next_send_packet = true;
+ return SendPacket(rep.str());
}
-compression_types
-RNBRemote::GetCompressionType ()
-{
- // The first packet we send back to the debugger after a QEnableCompression request
- // should be uncompressed -- so we can indicate whether the compression was enabled
- // or not via OK / Enn returns. After that, all packets sent will be using the
- // compression protocol.
-
- if (m_enable_compression_next_send_packet)
- {
- // One time, we send back "None" as our compression type
- m_enable_compression_next_send_packet = false;
- return compression_types::none;
- }
- return m_compression_mode;
+const RNBRemote::DispatchQueueOffsets *RNBRemote::GetDispatchQueueOffsets() {
+ if (!m_dispatch_queue_offsets.IsValid() &&
+ m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS &&
+ m_ctx.HasValidProcessID()) {
+ nub_process_t pid = m_ctx.ProcessID();
+ nub_size_t bytes_read = DNBProcessMemoryRead(
+ pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets),
+ &m_dispatch_queue_offsets);
+ if (bytes_read != sizeof(m_dispatch_queue_offsets))
+ m_dispatch_queue_offsets.Clear();
+ }
+
+ if (m_dispatch_queue_offsets.IsValid())
+ return &m_dispatch_queue_offsets;
+ else
+ return nullptr;
+}
+
+void RNBRemote::EnableCompressionNextSendPacket(compression_types type) {
+ m_compression_mode = type;
+ m_enable_compression_next_send_packet = true;
+}
+
+compression_types RNBRemote::GetCompressionType() {
+ // The first packet we send back to the debugger after a QEnableCompression
+ // request
+ // should be uncompressed -- so we can indicate whether the compression was
+ // enabled
+ // or not via OK / Enn returns. After that, all packets sent will be using
+ // the
+ // compression protocol.
+
+ if (m_enable_compression_next_send_packet) {
+ // One time, we send back "None" as our compression type
+ m_enable_compression_next_send_packet = false;
+ return compression_types::none;
+ }
+ return m_compression_mode;
}
Modified: lldb/trunk/tools/debugserver/source/RNBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBRemote.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBRemote.h (original)
+++ lldb/trunk/tools/debugserver/source/RNBRemote.h Tue Sep 6 15:57:50 2016
@@ -14,15 +14,15 @@
#ifndef __RNBRemote_h__
#define __RNBRemote_h__
-#include "RNBDefs.h"
#include "DNB.h"
+#include "PThreadMutex.h"
#include "RNBContext.h"
+#include "RNBDefs.h"
#include "RNBSocket.h"
-#include "PThreadMutex.h"
-#include <string>
-#include <vector>
#include <deque>
#include <map>
+#include <string>
+#include <vector>
class RNBSocket;
class RNBContext;
@@ -32,411 +32,383 @@ enum event_loop_mode { debug_nub, gdb_re
enum class compression_types { zlib_deflate, lz4, lzma, lzfse, none };
-class RNBRemote
-{
+class RNBRemote {
public:
+ typedef enum {
+ invalid_packet = 0,
+ ack, // '+'
+ nack, // '-'
+ halt, // ^C (async halt)
+ use_extended_mode, // '!'
+ why_halted, // '?'
+ set_argv, // 'A'
+ set_bp, // 'B'
+ cont, // 'c'
+ continue_with_sig, // 'C'
+ detach, // 'D'
+ read_general_regs, // 'g'
+ write_general_regs, // 'G'
+ set_thread, // 'H'
+ step_inferior_one_cycle, // 'i'
+ signal_and_step_inf_one_cycle, // 'I'
+ kill, // 'k'
+ read_memory, // 'm'
+ write_memory, // 'M'
+ read_register, // 'p'
+ write_register, // 'P'
+ restart, // 'R'
+ single_step, // 's'
+ single_step_with_sig, // 'S'
+ search_mem_backwards, // 't'
+ thread_alive_p, // 'T'
+ vattach, // 'vAttach;pid'
+ vattachwait, // 'vAttachWait:XX...' where XX is one or more hex encoded
+ // process name ASCII bytes
+ vattachorwait, // 'vAttachOrWait:XX...' where XX is one or more hex encoded
+ // process name ASCII bytes
+ vattachname, // 'vAttachName:XX...' where XX is one or more hex encoded
+ // process name ASCII bytes
+ vcont, // 'vCont'
+ vcont_list_actions, // 'vCont?'
+ read_data_from_memory, // 'x'
+ write_data_to_memory, // 'X'
+ insert_mem_bp, // 'Z0'
+ remove_mem_bp, // 'z0'
+ insert_hardware_bp, // 'Z1'
+ remove_hardware_bp, // 'z1'
+ insert_write_watch_bp, // 'Z2'
+ remove_write_watch_bp, // 'z2'
+ insert_read_watch_bp, // 'Z3'
+ remove_read_watch_bp, // 'z3'
+ insert_access_watch_bp, // 'Z4'
+ remove_access_watch_bp, // 'z4'
+
+ query_monitor, // 'qRcmd'
+ query_current_thread_id, // 'qC'
+ query_get_pid, // 'qGetPid'
+ query_echo, // 'qEcho'
+ query_thread_ids_first, // 'qfThreadInfo'
+ query_thread_ids_subsequent, // 'qsThreadInfo'
+ query_thread_extra_info, // 'qThreadExtraInfo'
+ query_thread_stop_info, // 'qThreadStopInfo'
+ query_image_offsets, // 'qOffsets'
+ query_symbol_lookup, // 'qSymbol'
+ query_launch_success, // 'qLaunchSuccess'
+ query_register_info, // 'qRegisterInfo'
+ query_shlib_notify_info_addr, // 'qShlibInfoAddr'
+ query_step_packet_supported, // 'qStepPacketSupported'
+ query_supported_features, // 'qSupported'
+ query_vattachorwait_supported, // 'qVAttachOrWaitSupported'
+ query_sync_thread_state_supported, // 'QSyncThreadState'
+ query_host_info, // 'qHostInfo'
+ query_gdb_server_version, // 'qGDBServerVersion'
+ query_process_info, // 'qProcessInfo'
+ json_query_thread_extended_info, // 'jThreadExtendedInfo'
+ json_query_get_loaded_dynamic_libraries_infos, // 'jGetLoadedDynamicLibrariesInfos'
+ json_query_threads_info, // 'jThreadsInfo'
+ json_query_get_shared_cache_info, // 'jGetSharedCacheInfo'
+ pass_signals_to_inferior, // 'QPassSignals'
+ start_noack_mode, // 'QStartNoAckMode'
+ prefix_reg_packets_with_tid, // 'QPrefixRegisterPacketsWithThreadID
+ set_logging_mode, // 'QSetLogging:'
+ set_max_packet_size, // 'QSetMaxPacketSize:'
+ set_max_payload_size, // 'QSetMaxPayloadSize:'
+ set_environment_variable, // 'QEnvironment:'
+ set_environment_variable_hex, // 'QEnvironmentHexEncoded:'
+ set_launch_arch, // 'QLaunchArch:'
+ set_disable_aslr, // 'QSetDisableASLR:'
+ set_stdin, // 'QSetSTDIN:'
+ set_stdout, // 'QSetSTDOUT:'
+ set_stderr, // 'QSetSTDERR:'
+ set_working_dir, // 'QSetWorkingDir:'
+ set_list_threads_in_stop_reply, // 'QListThreadsInStopReply:'
+ sync_thread_state, // 'QSyncThreadState:'
+ memory_region_info, // 'qMemoryRegionInfo:'
+ get_profile_data, // 'qGetProfileData'
+ set_enable_profiling, // 'QSetEnableAsyncProfiling'
+ enable_compression, // 'QEnableCompression:'
+ watchpoint_support_info, // 'qWatchpointSupportInfo:'
+ allocate_memory, // '_M'
+ deallocate_memory, // '_m'
+ set_process_event, // 'QSetProcessEvent:'
+ save_register_state, // '_g'
+ restore_register_state, // '_G'
+ speed_test, // 'qSpeedTest:'
+ set_detach_on_error, // 'QSetDetachOnError:'
+ query_transfer, // 'qXfer:'
+ query_supported_async_json_packets, // 'QSupportedAsyncJSONPackets'
+ configure_darwin_log, // 'ConfigureDarwinLog:'
+ unknown_type
+ } PacketEnum;
+
+ typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p);
+
+ RNBRemote();
+ ~RNBRemote();
+
+ void Initialize();
+
+ bool InitializeRegisters(bool force = false);
+
+ rnb_err_t HandleAsyncPacket(PacketEnum *type = NULL);
+ rnb_err_t HandleReceivedPacket(PacketEnum *type = NULL);
+
+ nub_thread_t GetContinueThread() const { return m_continue_thread; }
+
+ void SetContinueThread(nub_thread_t tid) { m_continue_thread = tid; }
+
+ nub_thread_t GetCurrentThread() const {
+ if (m_thread == 0 || m_thread == (nub_thread_t)-1)
+ return DNBProcessGetCurrentThread(m_ctx.ProcessID());
+ return m_thread;
+ }
+
+ void SetCurrentThread(nub_thread_t tid) {
+ DNBProcessSetCurrentThread(m_ctx.ProcessID(), tid);
+ m_thread = tid;
+ }
+
+ static void *ThreadFunctionReadRemoteData(void *arg);
+ void StartReadRemoteDataThread();
+ void StopReadRemoteDataThread();
+
+ void NotifyThatProcessStopped(void);
+
+ rnb_err_t HandlePacket_A(const char *p);
+ rnb_err_t HandlePacket_H(const char *p);
+ rnb_err_t HandlePacket_qC(const char *p);
+ rnb_err_t HandlePacket_qRcmd(const char *p);
+ rnb_err_t HandlePacket_qGetPid(const char *p);
+ rnb_err_t HandlePacket_qEcho(const char *p);
+ rnb_err_t HandlePacket_qLaunchSuccess(const char *p);
+ rnb_err_t HandlePacket_qRegisterInfo(const char *p);
+ rnb_err_t HandlePacket_qShlibInfoAddr(const char *p);
+ rnb_err_t HandlePacket_qStepPacketSupported(const char *p);
+ rnb_err_t HandlePacket_qVAttachOrWaitSupported(const char *p);
+ rnb_err_t HandlePacket_qSyncThreadStateSupported(const char *p);
+ rnb_err_t HandlePacket_qThreadInfo(const char *p);
+ rnb_err_t HandlePacket_jThreadExtendedInfo(const char *p);
+ rnb_err_t HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p);
+ rnb_err_t HandlePacket_jThreadsInfo(const char *p);
+ rnb_err_t HandlePacket_jGetSharedCacheInfo(const char *p);
+ rnb_err_t HandlePacket_qThreadExtraInfo(const char *p);
+ rnb_err_t HandlePacket_qThreadStopInfo(const char *p);
+ rnb_err_t HandlePacket_qHostInfo(const char *p);
+ rnb_err_t HandlePacket_qGDBServerVersion(const char *p);
+ rnb_err_t HandlePacket_qProcessInfo(const char *p);
+ rnb_err_t HandlePacket_qSymbol(const char *p);
+ rnb_err_t HandlePacket_QStartNoAckMode(const char *p);
+ rnb_err_t HandlePacket_QThreadSuffixSupported(const char *p);
+ rnb_err_t HandlePacket_QSetLogging(const char *p);
+ rnb_err_t HandlePacket_QSetDisableASLR(const char *p);
+ rnb_err_t HandlePacket_QSetSTDIO(const char *p);
+ rnb_err_t HandlePacket_QSetWorkingDir(const char *p);
+ rnb_err_t HandlePacket_QSetMaxPayloadSize(const char *p);
+ rnb_err_t HandlePacket_QSetMaxPacketSize(const char *p);
+ rnb_err_t HandlePacket_QEnvironment(const char *p);
+ rnb_err_t HandlePacket_QEnvironmentHexEncoded(const char *p);
+ rnb_err_t HandlePacket_QLaunchArch(const char *p);
+ rnb_err_t HandlePacket_QListThreadsInStopReply(const char *p);
+ rnb_err_t HandlePacket_QSyncThreadState(const char *p);
+ rnb_err_t HandlePacket_QPrefixRegisterPacketsWithThreadID(const char *p);
+ rnb_err_t HandlePacket_QSetProcessEvent(const char *p);
+ rnb_err_t HandlePacket_last_signal(const char *p);
+ rnb_err_t HandlePacket_m(const char *p);
+ rnb_err_t HandlePacket_M(const char *p);
+ rnb_err_t HandlePacket_x(const char *p);
+ rnb_err_t HandlePacket_X(const char *p);
+ rnb_err_t HandlePacket_g(const char *p);
+ rnb_err_t HandlePacket_G(const char *p);
+ rnb_err_t HandlePacket_z(const char *p);
+ rnb_err_t HandlePacket_T(const char *p);
+ rnb_err_t HandlePacket_p(const char *p);
+ rnb_err_t HandlePacket_P(const char *p);
+ rnb_err_t HandlePacket_c(const char *p);
+ rnb_err_t HandlePacket_C(const char *p);
+ rnb_err_t HandlePacket_D(const char *p);
+ rnb_err_t HandlePacket_k(const char *p);
+ rnb_err_t HandlePacket_s(const char *p);
+ rnb_err_t HandlePacket_S(const char *p);
+ rnb_err_t HandlePacket_qSupported(const char *p);
+ rnb_err_t HandlePacket_v(const char *p);
+ rnb_err_t HandlePacket_UNIMPLEMENTED(const char *p);
+ rnb_err_t HandlePacket_ILLFORMED(const char *file, int line, const char *p,
+ const char *description);
+ rnb_err_t HandlePacket_AllocateMemory(const char *p);
+ rnb_err_t HandlePacket_DeallocateMemory(const char *p);
+ rnb_err_t HandlePacket_SaveRegisterState(const char *p);
+ rnb_err_t HandlePacket_RestoreRegisterState(const char *p);
+ rnb_err_t HandlePacket_MemoryRegionInfo(const char *p);
+ rnb_err_t HandlePacket_GetProfileData(const char *p);
+ rnb_err_t HandlePacket_SetEnableAsyncProfiling(const char *p);
+ rnb_err_t HandlePacket_QEnableCompression(const char *p);
+ rnb_err_t HandlePacket_WatchpointSupportInfo(const char *p);
+ rnb_err_t HandlePacket_qSpeedTest(const char *p);
+ rnb_err_t HandlePacket_qXfer(const char *p);
+ rnb_err_t HandlePacket_stop_process(const char *p);
+ rnb_err_t HandlePacket_QSetDetachOnError(const char *p);
+ rnb_err_t HandlePacket_qStructuredDataPlugins(const char *p);
+ rnb_err_t HandlePacket_QConfigureDarwinLog(const char *p);
+
+ rnb_err_t SendStopReplyPacketForThread(nub_thread_t tid);
+ rnb_err_t SendHexEncodedBytePacket(const char *header, const void *buf,
+ size_t buf_len, const char *footer);
+ rnb_err_t SendSTDOUTPacket(char *buf, nub_size_t buf_size);
+ rnb_err_t SendSTDERRPacket(char *buf, nub_size_t buf_size);
+ void FlushSTDIO();
+ void SendAsyncProfileData();
+ rnb_err_t SendAsyncProfileDataPacket(char *buf, nub_size_t buf_size);
+ void SendAsyncDarwinLogData();
+ rnb_err_t SendAsyncJSONPacket(const JSONGenerator::Dictionary &dictionary);
- typedef enum {
- invalid_packet = 0,
- ack, // '+'
- nack, // '-'
- halt, // ^C (async halt)
- use_extended_mode, // '!'
- why_halted, // '?'
- set_argv, // 'A'
- set_bp, // 'B'
- cont, // 'c'
- continue_with_sig, // 'C'
- detach, // 'D'
- read_general_regs, // 'g'
- write_general_regs, // 'G'
- set_thread, // 'H'
- step_inferior_one_cycle, // 'i'
- signal_and_step_inf_one_cycle, // 'I'
- kill, // 'k'
- read_memory, // 'm'
- write_memory, // 'M'
- read_register, // 'p'
- write_register, // 'P'
- restart, // 'R'
- single_step, // 's'
- single_step_with_sig, // 'S'
- search_mem_backwards, // 't'
- thread_alive_p, // 'T'
- vattach, // 'vAttach;pid'
- vattachwait, // 'vAttachWait:XX...' where XX is one or more hex encoded process name ASCII bytes
- vattachorwait, // 'vAttachOrWait:XX...' where XX is one or more hex encoded process name ASCII bytes
- vattachname, // 'vAttachName:XX...' where XX is one or more hex encoded process name ASCII bytes
- vcont, // 'vCont'
- vcont_list_actions, // 'vCont?'
- read_data_from_memory, // 'x'
- write_data_to_memory, // 'X'
- insert_mem_bp, // 'Z0'
- remove_mem_bp, // 'z0'
- insert_hardware_bp, // 'Z1'
- remove_hardware_bp, // 'z1'
- insert_write_watch_bp, // 'Z2'
- remove_write_watch_bp, // 'z2'
- insert_read_watch_bp, // 'Z3'
- remove_read_watch_bp, // 'z3'
- insert_access_watch_bp, // 'Z4'
- remove_access_watch_bp, // 'z4'
-
- query_monitor, // 'qRcmd'
- query_current_thread_id, // 'qC'
- query_get_pid, // 'qGetPid'
- query_echo, // 'qEcho'
- query_thread_ids_first, // 'qfThreadInfo'
- query_thread_ids_subsequent, // 'qsThreadInfo'
- query_thread_extra_info, // 'qThreadExtraInfo'
- query_thread_stop_info, // 'qThreadStopInfo'
- query_image_offsets, // 'qOffsets'
- query_symbol_lookup, // 'qSymbol'
- query_launch_success, // 'qLaunchSuccess'
- query_register_info, // 'qRegisterInfo'
- query_shlib_notify_info_addr, // 'qShlibInfoAddr'
- query_step_packet_supported, // 'qStepPacketSupported'
- query_supported_features, // 'qSupported'
- query_vattachorwait_supported, // 'qVAttachOrWaitSupported'
- query_sync_thread_state_supported,// 'QSyncThreadState'
- query_host_info, // 'qHostInfo'
- query_gdb_server_version, // 'qGDBServerVersion'
- query_process_info, // 'qProcessInfo'
- json_query_thread_extended_info,// 'jThreadExtendedInfo'
- json_query_get_loaded_dynamic_libraries_infos, // 'jGetLoadedDynamicLibrariesInfos'
- json_query_threads_info, // 'jThreadsInfo'
- json_query_get_shared_cache_info, // 'jGetSharedCacheInfo'
- pass_signals_to_inferior, // 'QPassSignals'
- start_noack_mode, // 'QStartNoAckMode'
- prefix_reg_packets_with_tid, // 'QPrefixRegisterPacketsWithThreadID
- set_logging_mode, // 'QSetLogging:'
- set_max_packet_size, // 'QSetMaxPacketSize:'
- set_max_payload_size, // 'QSetMaxPayloadSize:'
- set_environment_variable, // 'QEnvironment:'
- set_environment_variable_hex, // 'QEnvironmentHexEncoded:'
- set_launch_arch, // 'QLaunchArch:'
- set_disable_aslr, // 'QSetDisableASLR:'
- set_stdin, // 'QSetSTDIN:'
- set_stdout, // 'QSetSTDOUT:'
- set_stderr, // 'QSetSTDERR:'
- set_working_dir, // 'QSetWorkingDir:'
- set_list_threads_in_stop_reply, // 'QListThreadsInStopReply:'
- sync_thread_state, // 'QSyncThreadState:'
- memory_region_info, // 'qMemoryRegionInfo:'
- get_profile_data, // 'qGetProfileData'
- set_enable_profiling, // 'QSetEnableAsyncProfiling'
- enable_compression, // 'QEnableCompression:'
- watchpoint_support_info, // 'qWatchpointSupportInfo:'
- allocate_memory, // '_M'
- deallocate_memory, // '_m'
- set_process_event, // 'QSetProcessEvent:'
- save_register_state, // '_g'
- restore_register_state, // '_G'
- speed_test, // 'qSpeedTest:'
- set_detach_on_error, // 'QSetDetachOnError:'
- query_transfer, // 'qXfer:'
- query_supported_async_json_packets, // 'QSupportedAsyncJSONPackets'
- configure_darwin_log, // 'ConfigureDarwinLog:'
- unknown_type
- } PacketEnum;
-
- typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p);
-
- RNBRemote ();
- ~RNBRemote ();
-
- void Initialize();
-
- bool InitializeRegisters (bool force = false);
-
- rnb_err_t HandleAsyncPacket(PacketEnum *type = NULL);
- rnb_err_t HandleReceivedPacket(PacketEnum *type = NULL);
-
- nub_thread_t GetContinueThread () const
- {
- return m_continue_thread;
- }
-
- void SetContinueThread (nub_thread_t tid)
- {
- m_continue_thread = tid;
- }
-
- nub_thread_t GetCurrentThread () const
- {
- if (m_thread == 0 || m_thread == (nub_thread_t)-1)
- return DNBProcessGetCurrentThread (m_ctx.ProcessID());
- return m_thread;
- }
-
- void SetCurrentThread (nub_thread_t tid)
- {
- DNBProcessSetCurrentThread (m_ctx.ProcessID(), tid);
- m_thread = tid;
- }
-
- static void* ThreadFunctionReadRemoteData(void *arg);
- void StartReadRemoteDataThread ();
- void StopReadRemoteDataThread ();
-
- void NotifyThatProcessStopped (void);
-
- rnb_err_t HandlePacket_A (const char *p);
- rnb_err_t HandlePacket_H (const char *p);
- rnb_err_t HandlePacket_qC (const char *p);
- rnb_err_t HandlePacket_qRcmd (const char *p);
- rnb_err_t HandlePacket_qGetPid (const char *p);
- rnb_err_t HandlePacket_qEcho (const char *p);
- rnb_err_t HandlePacket_qLaunchSuccess (const char *p);
- rnb_err_t HandlePacket_qRegisterInfo (const char *p);
- rnb_err_t HandlePacket_qShlibInfoAddr (const char *p);
- rnb_err_t HandlePacket_qStepPacketSupported (const char *p);
- rnb_err_t HandlePacket_qVAttachOrWaitSupported (const char *p);
- rnb_err_t HandlePacket_qSyncThreadStateSupported (const char *p);
- rnb_err_t HandlePacket_qThreadInfo (const char *p);
- rnb_err_t HandlePacket_jThreadExtendedInfo (const char *p);
- rnb_err_t HandlePacket_jGetLoadedDynamicLibrariesInfos (const char *p);
- rnb_err_t HandlePacket_jThreadsInfo (const char *p);
- rnb_err_t HandlePacket_jGetSharedCacheInfo (const char *p);
- rnb_err_t HandlePacket_qThreadExtraInfo (const char *p);
- rnb_err_t HandlePacket_qThreadStopInfo (const char *p);
- rnb_err_t HandlePacket_qHostInfo (const char *p);
- rnb_err_t HandlePacket_qGDBServerVersion (const char *p);
- rnb_err_t HandlePacket_qProcessInfo (const char *p);
- rnb_err_t HandlePacket_qSymbol (const char *p);
- rnb_err_t HandlePacket_QStartNoAckMode (const char *p);
- rnb_err_t HandlePacket_QThreadSuffixSupported (const char *p);
- rnb_err_t HandlePacket_QSetLogging (const char *p);
- rnb_err_t HandlePacket_QSetDisableASLR (const char *p);
- rnb_err_t HandlePacket_QSetSTDIO (const char *p);
- rnb_err_t HandlePacket_QSetWorkingDir (const char *p);
- rnb_err_t HandlePacket_QSetMaxPayloadSize (const char *p);
- rnb_err_t HandlePacket_QSetMaxPacketSize (const char *p);
- rnb_err_t HandlePacket_QEnvironment (const char *p);
- rnb_err_t HandlePacket_QEnvironmentHexEncoded (const char *p);
- rnb_err_t HandlePacket_QLaunchArch (const char *p);
- rnb_err_t HandlePacket_QListThreadsInStopReply (const char *p);
- rnb_err_t HandlePacket_QSyncThreadState (const char *p);
- rnb_err_t HandlePacket_QPrefixRegisterPacketsWithThreadID (const char *p);
- rnb_err_t HandlePacket_QSetProcessEvent (const char *p);
- rnb_err_t HandlePacket_last_signal (const char *p);
- rnb_err_t HandlePacket_m (const char *p);
- rnb_err_t HandlePacket_M (const char *p);
- rnb_err_t HandlePacket_x (const char *p);
- rnb_err_t HandlePacket_X (const char *p);
- rnb_err_t HandlePacket_g (const char *p);
- rnb_err_t HandlePacket_G (const char *p);
- rnb_err_t HandlePacket_z (const char *p);
- rnb_err_t HandlePacket_T (const char *p);
- rnb_err_t HandlePacket_p (const char *p);
- rnb_err_t HandlePacket_P (const char *p);
- rnb_err_t HandlePacket_c (const char *p);
- rnb_err_t HandlePacket_C (const char *p);
- rnb_err_t HandlePacket_D (const char *p);
- rnb_err_t HandlePacket_k (const char *p);
- rnb_err_t HandlePacket_s (const char *p);
- rnb_err_t HandlePacket_S (const char *p);
- rnb_err_t HandlePacket_qSupported (const char *p);
- rnb_err_t HandlePacket_v (const char *p);
- rnb_err_t HandlePacket_UNIMPLEMENTED (const char *p);
- rnb_err_t HandlePacket_ILLFORMED (const char *file, int line, const char *p, const char *description);
- rnb_err_t HandlePacket_AllocateMemory (const char *p);
- rnb_err_t HandlePacket_DeallocateMemory (const char *p);
- rnb_err_t HandlePacket_SaveRegisterState (const char *p);
- rnb_err_t HandlePacket_RestoreRegisterState (const char *p);
- rnb_err_t HandlePacket_MemoryRegionInfo (const char *p);
- rnb_err_t HandlePacket_GetProfileData(const char *p);
- rnb_err_t HandlePacket_SetEnableAsyncProfiling(const char *p);
- rnb_err_t HandlePacket_QEnableCompression(const char *p);
- rnb_err_t HandlePacket_WatchpointSupportInfo (const char *p);
- rnb_err_t HandlePacket_qSpeedTest (const char *p);
- rnb_err_t HandlePacket_qXfer (const char *p);
- rnb_err_t HandlePacket_stop_process (const char *p);
- rnb_err_t HandlePacket_QSetDetachOnError (const char *p);
- rnb_err_t HandlePacket_qStructuredDataPlugins (const char *p);
- rnb_err_t HandlePacket_QConfigureDarwinLog (const char *p);
-
- rnb_err_t SendStopReplyPacketForThread (nub_thread_t tid);
- rnb_err_t SendHexEncodedBytePacket (const char *header, const void *buf, size_t buf_len, const char *footer);
- rnb_err_t SendSTDOUTPacket (char *buf, nub_size_t buf_size);
- rnb_err_t SendSTDERRPacket (char *buf, nub_size_t buf_size);
- void FlushSTDIO ();
- void SendAsyncProfileData ();
- rnb_err_t SendAsyncProfileDataPacket (char *buf, nub_size_t buf_size);
- void SendAsyncDarwinLogData ();
- rnb_err_t SendAsyncJSONPacket (const JSONGenerator::Dictionary &dictionary);
-
- RNBContext& Context() { return m_ctx; }
- RNBSocket& Comm() { return m_comm; }
+ RNBContext &Context() { return m_ctx; }
+ RNBSocket &Comm() { return m_comm; }
private:
- // Outlaw some constructors
- RNBRemote (const RNBRemote &);
+ // Outlaw some constructors
+ RNBRemote(const RNBRemote &);
protected:
+ rnb_err_t GetCommData();
+ void CommDataReceived(const std::string &data);
+ struct Packet {
+ typedef std::vector<Packet> collection;
+ typedef collection::iterator iterator;
+ typedef collection::const_iterator const_iterator;
+ PacketEnum type;
+ HandlePacketCallback normal; // Function to call when inferior is halted
+ HandlePacketCallback async; // Function to call when inferior is running
+ std::string abbrev;
+ std::string printable_name;
+
+ bool IsPlatformPacket() const {
+ switch (type) {
+ case set_logging_mode:
+ case query_host_info:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+ Packet()
+ : type(invalid_packet), normal(NULL), async(NULL), abbrev(),
+ printable_name() {}
+
+ Packet(PacketEnum in_type, HandlePacketCallback in_normal,
+ HandlePacketCallback in_async, const char *in_abbrev,
+ const char *in_printable_name)
+ : type(in_type), normal(in_normal), async(in_async), abbrev(in_abbrev),
+ printable_name(in_printable_name) {}
+ };
+
+ struct DispatchQueueOffsets {
+ uint16_t dqo_version;
+ uint16_t dqo_label;
+ uint16_t dqo_label_size;
+ uint16_t dqo_flags;
+ uint16_t dqo_flags_size;
+ uint16_t dqo_serialnum;
+ uint16_t dqo_serialnum_size;
+ uint16_t dqo_width;
+ uint16_t dqo_width_size;
+ uint16_t dqo_running;
+ uint16_t dqo_running_size;
+ uint16_t dqo_suspend_cnt; // version 5 and later, starting with Mac OS X
+ // 10.10/iOS 8
+ uint16_t dqo_suspend_cnt_size; // version 5 and later, starting with Mac OS
+ // X 10.10/iOS 8
+ uint16_t dqo_target_queue; // version 5 and later, starting with Mac OS X
+ // 10.10/iOS 8
+ uint16_t dqo_target_queue_size; // version 5 and later, starting with Mac OS
+ // X 10.10/iOS 8
+ uint16_t
+ dqo_priority; // version 5 and later, starting with Mac OS X 10.10/iOS 8
+ uint16_t dqo_priority_size; // version 5 and later, starting with Mac OS X
+ // 10.10/iOS 8
+
+ DispatchQueueOffsets() { Clear(); }
+
+ void Clear() {
+ dqo_version = UINT16_MAX;
+ dqo_label = UINT16_MAX;
+ dqo_label_size = UINT16_MAX;
+ dqo_flags = UINT16_MAX;
+ dqo_flags_size = UINT16_MAX;
+ dqo_serialnum = UINT16_MAX;
+ dqo_serialnum_size = UINT16_MAX;
+ dqo_width = UINT16_MAX;
+ dqo_width_size = UINT16_MAX;
+ dqo_running = UINT16_MAX;
+ dqo_running_size = UINT16_MAX;
+ dqo_suspend_cnt = UINT16_MAX;
+ dqo_suspend_cnt_size = UINT16_MAX;
+ dqo_target_queue = UINT16_MAX;
+ dqo_target_queue_size = UINT16_MAX;
+ dqo_priority = UINT16_MAX;
+ dqo_priority_size = UINT16_MAX;
+ }
- rnb_err_t GetCommData ();
- void CommDataReceived(const std::string& data);
- struct Packet
- {
- typedef std::vector<Packet> collection;
- typedef collection::iterator iterator;
- typedef collection::const_iterator const_iterator;
- PacketEnum type;
- HandlePacketCallback normal; // Function to call when inferior is halted
- HandlePacketCallback async; // Function to call when inferior is running
- std::string abbrev;
- std::string printable_name;
-
- bool
- IsPlatformPacket () const
- {
- switch (type)
- {
- case set_logging_mode:
- case query_host_info:
- return true;
- default:
- break;
- }
- return false;
- }
- Packet() :
- type(invalid_packet),
- normal (NULL),
- async (NULL),
- abbrev (),
- printable_name ()
- {
- }
-
- Packet( PacketEnum in_type,
- HandlePacketCallback in_normal,
- HandlePacketCallback in_async,
- const char *in_abbrev,
- const char *in_printable_name) :
- type (in_type),
- normal (in_normal),
- async (in_async),
- abbrev (in_abbrev),
- printable_name (in_printable_name)
- {
- }
- };
-
-
- struct DispatchQueueOffsets
- {
- uint16_t dqo_version;
- uint16_t dqo_label;
- uint16_t dqo_label_size;
- uint16_t dqo_flags;
- uint16_t dqo_flags_size;
- uint16_t dqo_serialnum;
- uint16_t dqo_serialnum_size;
- uint16_t dqo_width;
- uint16_t dqo_width_size;
- uint16_t dqo_running;
- uint16_t dqo_running_size;
- uint16_t dqo_suspend_cnt; // version 5 and later, starting with Mac OS X 10.10/iOS 8
- uint16_t dqo_suspend_cnt_size; // version 5 and later, starting with Mac OS X 10.10/iOS 8
- uint16_t dqo_target_queue; // version 5 and later, starting with Mac OS X 10.10/iOS 8
- uint16_t dqo_target_queue_size; // version 5 and later, starting with Mac OS X 10.10/iOS 8
- uint16_t dqo_priority; // version 5 and later, starting with Mac OS X 10.10/iOS 8
- uint16_t dqo_priority_size; // version 5 and later, starting with Mac OS X 10.10/iOS 8
-
- DispatchQueueOffsets ()
- {
- Clear();
- }
-
- void
- Clear()
- {
- dqo_version = UINT16_MAX;
- dqo_label = UINT16_MAX;
- dqo_label_size = UINT16_MAX;
- dqo_flags = UINT16_MAX;
- dqo_flags_size = UINT16_MAX;
- dqo_serialnum = UINT16_MAX;
- dqo_serialnum_size = UINT16_MAX;
- dqo_width = UINT16_MAX;
- dqo_width_size = UINT16_MAX;
- dqo_running = UINT16_MAX;
- dqo_running_size = UINT16_MAX;
- dqo_suspend_cnt = UINT16_MAX;
- dqo_suspend_cnt_size = UINT16_MAX;
- dqo_target_queue = UINT16_MAX;
- dqo_target_queue_size = UINT16_MAX;
- dqo_priority = UINT16_MAX;
- dqo_priority_size = UINT16_MAX;
- }
-
- bool
- IsValid () const
- {
- return dqo_version != UINT16_MAX;
- }
-
- void
- GetThreadQueueInfo (nub_process_t pid,
- nub_addr_t dispatch_qaddr,
+ bool IsValid() const { return dqo_version != UINT16_MAX; }
+
+ void GetThreadQueueInfo(nub_process_t pid, nub_addr_t dispatch_qaddr,
nub_addr_t &dispatch_queue_t,
- std::string &queue_name,
- uint64_t &queue_width,
+ std::string &queue_name, uint64_t &queue_width,
uint64_t &queue_serialnum) const;
- };
-
- rnb_err_t GetPacket (std::string &packet_data, RNBRemote::Packet& packet_info, bool wait);
- rnb_err_t SendPacket (const std::string &);
- std::string CompressString (const std::string &);
-
- void CreatePacketTable ();
- rnb_err_t GetPacketPayload (std::string &);
-
- nub_thread_t
- ExtractThreadIDFromThreadSuffix (const char *p);
-
- void
- EnableCompressionNextSendPacket (compression_types);
-
- compression_types
- GetCompressionType ();
-
- const DispatchQueueOffsets *
- GetDispatchQueueOffsets();
-
- JSONGenerator::ObjectSP
- GetJSONThreadsInfo (bool threads_with_valid_stop_info_only);
-
- RNBContext m_ctx; // process context
- RNBSocket m_comm; // communication port
- std::string m_arch;
- nub_thread_t m_continue_thread; // thread to continue; 0 for any, -1 for all
- nub_thread_t m_thread; // thread for other ops; 0 for any, -1 for all
- PThreadMutex m_mutex; // Mutex that protects
- DispatchQueueOffsets m_dispatch_queue_offsets;
- nub_addr_t m_dispatch_queue_offsets_addr;
- uint32_t m_qSymbol_index;
- uint32_t m_packets_recvd;
- Packet::collection m_packets;
- std::deque<std::string> m_rx_packets;
- std::string m_rx_partial_data; // For packets that may come in more than one batch, anything left over can be left here
- pthread_t m_rx_pthread;
- uint32_t m_max_payload_size; // the maximum sized payload we should send to gdb
- bool m_extended_mode; // are we in extended mode?
- bool m_noack_mode; // are we in no-ack mode?
- bool m_thread_suffix_supported; // Set to true if the 'p', 'P', 'g', and 'G' packets should be prefixed with the thread ID and colon:
- // "$pRR;thread:TTTT;" instead of "$pRR"
- // "$PRR=VVVVVVVV;thread:TTTT;" instead of "$PRR=VVVVVVVV"
- // "$g;thread:TTTT" instead of "$g"
- // "$GVVVVVVVVVVVVVV;thread:TTTT;#00 instead of "$GVVVVVVVVVVVVVV"
- bool m_list_threads_in_stop_reply;
+ };
- size_t m_compression_minsize; // only packets larger than this size will be compressed
- bool m_enable_compression_next_send_packet;
+ rnb_err_t GetPacket(std::string &packet_data, RNBRemote::Packet &packet_info,
+ bool wait);
+ rnb_err_t SendPacket(const std::string &);
+ std::string CompressString(const std::string &);
+
+ void CreatePacketTable();
+ rnb_err_t GetPacketPayload(std::string &);
+
+ nub_thread_t ExtractThreadIDFromThreadSuffix(const char *p);
+
+ void EnableCompressionNextSendPacket(compression_types);
+
+ compression_types GetCompressionType();
+
+ const DispatchQueueOffsets *GetDispatchQueueOffsets();
+
+ JSONGenerator::ObjectSP
+ GetJSONThreadsInfo(bool threads_with_valid_stop_info_only);
+
+ RNBContext m_ctx; // process context
+ RNBSocket m_comm; // communication port
+ std::string m_arch;
+ nub_thread_t m_continue_thread; // thread to continue; 0 for any, -1 for all
+ nub_thread_t m_thread; // thread for other ops; 0 for any, -1 for all
+ PThreadMutex m_mutex; // Mutex that protects
+ DispatchQueueOffsets m_dispatch_queue_offsets;
+ nub_addr_t m_dispatch_queue_offsets_addr;
+ uint32_t m_qSymbol_index;
+ uint32_t m_packets_recvd;
+ Packet::collection m_packets;
+ std::deque<std::string> m_rx_packets;
+ std::string m_rx_partial_data; // For packets that may come in more than one
+ // batch, anything left over can be left here
+ pthread_t m_rx_pthread;
+ uint32_t
+ m_max_payload_size; // the maximum sized payload we should send to gdb
+ bool m_extended_mode; // are we in extended mode?
+ bool m_noack_mode; // are we in no-ack mode?
+ bool m_thread_suffix_supported; // Set to true if the 'p', 'P', 'g', and 'G'
+ // packets should be prefixed with the thread
+ // ID and colon:
+ // "$pRR;thread:TTTT;" instead of "$pRR"
+ // "$PRR=VVVVVVVV;thread:TTTT;" instead of "$PRR=VVVVVVVV"
+ // "$g;thread:TTTT" instead of "$g"
+ // "$GVVVVVVVVVVVVVV;thread:TTTT;#00 instead of "$GVVVVVVVVVVVVVV"
+ bool m_list_threads_in_stop_reply;
+
+ size_t m_compression_minsize; // only packets larger than this size will be
+ // compressed
+ bool m_enable_compression_next_send_packet;
- compression_types m_compression_mode;
+ compression_types m_compression_mode;
};
/* We translate the /usr/include/mach/exception_types.h exception types
@@ -445,12 +417,12 @@ protected:
coded values for TARGET_EXC_BAD_ACCESS et al must match the gdb
values in its include/gdb/signals.h. */
-#define TARGET_EXC_BAD_ACCESS 0x91
+#define TARGET_EXC_BAD_ACCESS 0x91
#define TARGET_EXC_BAD_INSTRUCTION 0x92
-#define TARGET_EXC_ARITHMETIC 0x93
-#define TARGET_EXC_EMULATION 0x94
-#define TARGET_EXC_SOFTWARE 0x95
-#define TARGET_EXC_BREAKPOINT 0x96
+#define TARGET_EXC_ARITHMETIC 0x93
+#define TARGET_EXC_EMULATION 0x94
+#define TARGET_EXC_SOFTWARE 0x95
+#define TARGET_EXC_BREAKPOINT 0x96
/* Generally speaking, you can't assume gdb can receive more than 399 bytes
at a time with a random gdb. This bufsize constant is only specifying
Modified: lldb/trunk/tools/debugserver/source/RNBServices.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBServices.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBServices.cpp (original)
+++ lldb/trunk/tools/debugserver/source/RNBServices.cpp Tue Sep 6 15:57:50 2016
@@ -13,214 +13,223 @@
#include "RNBServices.h"
+#include "CFString.h"
+#include "DNBLog.h"
+#include "MacOSX/CFUtils.h"
#include <CoreFoundation/CoreFoundation.h>
#include <libproc.h>
-#include <unistd.h>
#include <sys/sysctl.h>
-#include "CFString.h"
+#include <unistd.h>
#include <vector>
-#include "DNBLog.h"
-#include "MacOSX/CFUtils.h"
-// For now only SpringBoard has a notion of "Applications" that it can list for us.
+// For now only SpringBoard has a notion of "Applications" that it can list for
+// us.
// So we have to use the SpringBoard API's here.
-#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS)
+#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS)
#include <SpringBoardServices/SpringBoardServices.h>
#endif
// From DNB.cpp
-size_t GetAllInfos (std::vector<struct kinfo_proc>& proc_infos);
+size_t GetAllInfos(std::vector<struct kinfo_proc> &proc_infos);
-int
-GetProcesses (CFMutableArrayRef plistMutableArray, bool all_users)
-{
- if (plistMutableArray == NULL)
- return -1;
-
- // Running as root, get all processes
- std::vector<struct kinfo_proc> proc_infos;
- const size_t num_proc_infos = GetAllInfos(proc_infos);
- if (num_proc_infos > 0)
- {
- const pid_t our_pid = getpid();
- const uid_t our_uid = getuid();
- uint32_t i;
- CFAllocatorRef alloc = kCFAllocatorDefault;
-
- for (i=0; i<num_proc_infos; i++)
- {
- struct kinfo_proc &proc_info = proc_infos[i];
-
- bool kinfo_user_matches;
- // Special case, if lldb is being run as root we can attach to anything.
- if (all_users)
- kinfo_user_matches = true;
- else
- kinfo_user_matches = proc_info.kp_eproc.e_pcred.p_ruid == our_uid;
-
-
- const pid_t pid = proc_info.kp_proc.p_pid;
- // Skip zombie processes and processes with unset status
- if (kinfo_user_matches == false || // User is acceptable
- pid == our_pid || // Skip this process
- pid == 0 || // Skip kernel (kernel pid is zero)
- proc_info.kp_proc.p_stat == SZOMB || // Zombies are bad, they like brains...
- proc_info.kp_proc.p_flag & P_TRACED || // Being debugged?
- proc_info.kp_proc.p_flag & P_WEXIT || // Working on exiting?
- proc_info.kp_proc.p_flag & P_TRANSLATED) // Skip translated ppc (Rosetta)
- continue;
-
- // Create a new mutable dictionary for each application
- CFReleaser<CFMutableDictionaryRef> appInfoDict (::CFDictionaryCreateMutable (alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
-
- // Get the process id for the app (if there is one)
- const int32_t pid_int32 = pid;
- CFReleaser<CFNumberRef> pidCFNumber (::CFNumberCreate (alloc, kCFNumberSInt32Type, &pid_int32));
- ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PID_KEY, pidCFNumber.get());
-
- // Set the a boolean to indicate if this is the front most
- ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanFalse);
-
- const char *pid_basename = proc_info.kp_proc.p_comm;
- char proc_path_buf[PATH_MAX];
-
- int return_val = proc_pidpath (pid, proc_path_buf, PATH_MAX);
- if (return_val > 0)
- {
- // Okay, now search backwards from that to see if there is a
- // slash in the name. Note, even though we got all the args we don't care
- // because the list data is just a bunch of concatenated null terminated strings
- // so strrchr will start from the end of argv0.
-
- pid_basename = strrchr(proc_path_buf, '/');
- if (pid_basename)
- {
- // Skip the '/'
- ++pid_basename;
- }
- else
- {
- // We didn't find a directory delimiter in the process argv[0], just use what was in there
- pid_basename = proc_path_buf;
- }
- CFString cf_pid_path (proc_path_buf);
- if (cf_pid_path.get())
- ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PATH_KEY, cf_pid_path.get());
- }
-
- if (pid_basename && pid_basename[0])
- {
- CFString pid_name (pid_basename);
- ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_DISPLAY_NAME_KEY, pid_name.get());
- }
-
- // Append the application info to the plist array
- ::CFArrayAppendValue (plistMutableArray, appInfoDict.get());
- }
- }
- return 0;
-}
-int
-ListApplications(std::string& plist, bool opt_runningApps, bool opt_debuggable)
-{
- int result = -1;
-
+int GetProcesses(CFMutableArrayRef plistMutableArray, bool all_users) {
+ if (plistMutableArray == NULL)
+ return -1;
+
+ // Running as root, get all processes
+ std::vector<struct kinfo_proc> proc_infos;
+ const size_t num_proc_infos = GetAllInfos(proc_infos);
+ if (num_proc_infos > 0) {
+ const pid_t our_pid = getpid();
+ const uid_t our_uid = getuid();
+ uint32_t i;
CFAllocatorRef alloc = kCFAllocatorDefault;
-
- // Create a mutable array that we can populate. Specify zero so it can be of any size.
- CFReleaser<CFMutableArrayRef> plistMutableArray (::CFArrayCreateMutable (alloc, 0, &kCFTypeArrayCallBacks));
- const uid_t our_uid = getuid();
+ for (i = 0; i < num_proc_infos; i++) {
+ struct kinfo_proc &proc_info = proc_infos[i];
+
+ bool kinfo_user_matches;
+ // Special case, if lldb is being run as root we can attach to anything.
+ if (all_users)
+ kinfo_user_matches = true;
+ else
+ kinfo_user_matches = proc_info.kp_eproc.e_pcred.p_ruid == our_uid;
+
+ const pid_t pid = proc_info.kp_proc.p_pid;
+ // Skip zombie processes and processes with unset status
+ if (kinfo_user_matches == false || // User is acceptable
+ pid == our_pid || // Skip this process
+ pid == 0 || // Skip kernel (kernel pid is zero)
+ proc_info.kp_proc.p_stat ==
+ SZOMB || // Zombies are bad, they like brains...
+ proc_info.kp_proc.p_flag & P_TRACED || // Being debugged?
+ proc_info.kp_proc.p_flag & P_WEXIT || // Working on exiting?
+ proc_info.kp_proc.p_flag &
+ P_TRANSLATED) // Skip translated ppc (Rosetta)
+ continue;
+
+ // Create a new mutable dictionary for each application
+ CFReleaser<CFMutableDictionaryRef> appInfoDict(
+ ::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ // Get the process id for the app (if there is one)
+ const int32_t pid_int32 = pid;
+ CFReleaser<CFNumberRef> pidCFNumber(
+ ::CFNumberCreate(alloc, kCFNumberSInt32Type, &pid_int32));
+ ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PID_KEY,
+ pidCFNumber.get());
+
+ // Set the a boolean to indicate if this is the front most
+ ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY,
+ kCFBooleanFalse);
+
+ const char *pid_basename = proc_info.kp_proc.p_comm;
+ char proc_path_buf[PATH_MAX];
+
+ int return_val = proc_pidpath(pid, proc_path_buf, PATH_MAX);
+ if (return_val > 0) {
+ // Okay, now search backwards from that to see if there is a
+ // slash in the name. Note, even though we got all the args we don't
+ // care
+ // because the list data is just a bunch of concatenated null terminated
+ // strings
+ // so strrchr will start from the end of argv0.
+
+ pid_basename = strrchr(proc_path_buf, '/');
+ if (pid_basename) {
+ // Skip the '/'
+ ++pid_basename;
+ } else {
+ // We didn't find a directory delimiter in the process argv[0], just
+ // use what was in there
+ pid_basename = proc_path_buf;
+ }
+ CFString cf_pid_path(proc_path_buf);
+ if (cf_pid_path.get())
+ ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PATH_KEY,
+ cf_pid_path.get());
+ }
+
+ if (pid_basename && pid_basename[0]) {
+ CFString pid_name(pid_basename);
+ ::CFDictionarySetValue(appInfoDict.get(),
+ DTSERVICES_APP_DISPLAY_NAME_KEY, pid_name.get());
+ }
-#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS)
-
- if (our_uid == 0)
- {
- bool all_users = true;
- result = GetProcesses (plistMutableArray.get(), all_users);
+ // Append the application info to the plist array
+ ::CFArrayAppendValue(plistMutableArray, appInfoDict.get());
}
- else
- {
- CFReleaser<CFStringRef> sbsFrontAppID (::SBSCopyFrontmostApplicationDisplayIdentifier ());
- CFReleaser<CFArrayRef> sbsAppIDs (::SBSCopyApplicationDisplayIdentifiers (opt_runningApps, opt_debuggable));
-
- // Need to check the return value from SBSCopyApplicationDisplayIdentifiers.
- CFIndex count = sbsAppIDs.get() ? ::CFArrayGetCount (sbsAppIDs.get()) : 0;
- CFIndex i = 0;
- for (i = 0; i < count; i++)
- {
- CFStringRef displayIdentifier = (CFStringRef)::CFArrayGetValueAtIndex (sbsAppIDs.get(), i);
-
- // Create a new mutable dictionary for each application
- CFReleaser<CFMutableDictionaryRef> appInfoDict (::CFDictionaryCreateMutable (alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
-
- // Get the process id for the app (if there is one)
- pid_t pid = INVALID_NUB_PROCESS;
- if (::SBSProcessIDForDisplayIdentifier ((CFStringRef)displayIdentifier, &pid) == true)
- {
- CFReleaser<CFNumberRef> pidCFNumber (::CFNumberCreate (alloc, kCFNumberSInt32Type, &pid));
- ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PID_KEY, pidCFNumber.get());
- }
-
- // Set the a boolean to indicate if this is the front most
- if (sbsFrontAppID.get() && displayIdentifier && (::CFStringCompare (sbsFrontAppID.get(), displayIdentifier, 0) == kCFCompareEqualTo))
- ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanTrue);
- else
- ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanFalse);
-
-
- CFReleaser<CFStringRef> executablePath (::SBSCopyExecutablePathForDisplayIdentifier (displayIdentifier));
- if (executablePath.get() != NULL)
- {
- ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PATH_KEY, executablePath.get());
- }
-
- CFReleaser<CFStringRef> iconImagePath (::SBSCopyIconImagePathForDisplayIdentifier (displayIdentifier)) ;
- if (iconImagePath.get() != NULL)
- {
- ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_ICON_PATH_KEY, iconImagePath.get());
- }
-
- CFReleaser<CFStringRef> localizedDisplayName (::SBSCopyLocalizedApplicationNameForDisplayIdentifier (displayIdentifier));
- if (localizedDisplayName.get() != NULL)
- {
- ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_DISPLAY_NAME_KEY, localizedDisplayName.get());
- }
+ }
+ return 0;
+}
+int ListApplications(std::string &plist, bool opt_runningApps,
+ bool opt_debuggable) {
+ int result = -1;
+
+ CFAllocatorRef alloc = kCFAllocatorDefault;
+
+ // Create a mutable array that we can populate. Specify zero so it can be of
+ // any size.
+ CFReleaser<CFMutableArrayRef> plistMutableArray(
+ ::CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks));
+
+ const uid_t our_uid = getuid();
+
+#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS)
+
+ if (our_uid == 0) {
+ bool all_users = true;
+ result = GetProcesses(plistMutableArray.get(), all_users);
+ } else {
+ CFReleaser<CFStringRef> sbsFrontAppID(
+ ::SBSCopyFrontmostApplicationDisplayIdentifier());
+ CFReleaser<CFArrayRef> sbsAppIDs(::SBSCopyApplicationDisplayIdentifiers(
+ opt_runningApps, opt_debuggable));
+
+ // Need to check the return value from SBSCopyApplicationDisplayIdentifiers.
+ CFIndex count = sbsAppIDs.get() ? ::CFArrayGetCount(sbsAppIDs.get()) : 0;
+ CFIndex i = 0;
+ for (i = 0; i < count; i++) {
+ CFStringRef displayIdentifier =
+ (CFStringRef)::CFArrayGetValueAtIndex(sbsAppIDs.get(), i);
+
+ // Create a new mutable dictionary for each application
+ CFReleaser<CFMutableDictionaryRef> appInfoDict(
+ ::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ // Get the process id for the app (if there is one)
+ pid_t pid = INVALID_NUB_PROCESS;
+ if (::SBSProcessIDForDisplayIdentifier((CFStringRef)displayIdentifier,
+ &pid) == true) {
+ CFReleaser<CFNumberRef> pidCFNumber(
+ ::CFNumberCreate(alloc, kCFNumberSInt32Type, &pid));
+ ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PID_KEY,
+ pidCFNumber.get());
+ }
+
+ // Set the a boolean to indicate if this is the front most
+ if (sbsFrontAppID.get() && displayIdentifier &&
+ (::CFStringCompare(sbsFrontAppID.get(), displayIdentifier, 0) ==
+ kCFCompareEqualTo))
+ ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY,
+ kCFBooleanTrue);
+ else
+ ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY,
+ kCFBooleanFalse);
+
+ CFReleaser<CFStringRef> executablePath(
+ ::SBSCopyExecutablePathForDisplayIdentifier(displayIdentifier));
+ if (executablePath.get() != NULL) {
+ ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PATH_KEY,
+ executablePath.get());
+ }
+
+ CFReleaser<CFStringRef> iconImagePath(
+ ::SBSCopyIconImagePathForDisplayIdentifier(displayIdentifier));
+ if (iconImagePath.get() != NULL) {
+ ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_ICON_PATH_KEY,
+ iconImagePath.get());
+ }
+
+ CFReleaser<CFStringRef> localizedDisplayName(
+ ::SBSCopyLocalizedApplicationNameForDisplayIdentifier(
+ displayIdentifier));
+ if (localizedDisplayName.get() != NULL) {
+ ::CFDictionarySetValue(appInfoDict.get(),
+ DTSERVICES_APP_DISPLAY_NAME_KEY,
+ localizedDisplayName.get());
+ }
- // Append the application info to the plist array
- ::CFArrayAppendValue (plistMutableArray.get(), appInfoDict.get());
- }
+ // Append the application info to the plist array
+ ::CFArrayAppendValue(plistMutableArray.get(), appInfoDict.get());
}
+ }
#else // #if defined (WITH_SPRINGBOARD) || defined (WITH_BKS)
- // When root, show all processes
- bool all_users = (our_uid == 0);
- GetProcesses (plistMutableArray.get(), all_users);
+ // When root, show all processes
+ bool all_users = (our_uid == 0);
+ GetProcesses(plistMutableArray.get(), all_users);
#endif
-
- CFReleaser<CFDataRef> plistData (::CFPropertyListCreateXMLData (alloc, plistMutableArray.get()));
-
- // write plist to service port
- if (plistData.get() != NULL)
- {
- CFIndex size = ::CFDataGetLength (plistData.get());
- const UInt8 *bytes = ::CFDataGetBytePtr (plistData.get());
- if (bytes != NULL && size > 0)
- {
- plist.assign((char *)bytes, size);
- return 0; // Success
- }
- else
- {
- DNBLogError("empty application property list.");
- result = -2;
- }
- }
- else
- {
- DNBLogError("serializing task list.");
- result = -3;
+
+ CFReleaser<CFDataRef> plistData(
+ ::CFPropertyListCreateXMLData(alloc, plistMutableArray.get()));
+
+ // write plist to service port
+ if (plistData.get() != NULL) {
+ CFIndex size = ::CFDataGetLength(plistData.get());
+ const UInt8 *bytes = ::CFDataGetBytePtr(plistData.get());
+ if (bytes != NULL && size > 0) {
+ plist.assign((char *)bytes, size);
+ return 0; // Success
+ } else {
+ DNBLogError("empty application property list.");
+ result = -2;
}
-
- return result;
+ } else {
+ DNBLogError("serializing task list.");
+ result = -3;
+ }
+ return result;
}
Modified: lldb/trunk/tools/debugserver/source/RNBServices.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBServices.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBServices.h (original)
+++ lldb/trunk/tools/debugserver/source/RNBServices.h Tue Sep 6 15:57:50 2016
@@ -14,15 +14,16 @@
#ifndef __RNBServices_h__
#define __RNBServices_h__
-#include <string>
#include "RNBDefs.h"
+#include <string>
-#define DTSERVICES_APP_FRONTMOST_KEY CFSTR("isFrontApp")
-#define DTSERVICES_APP_PATH_KEY CFSTR("executablePath")
-#define DTSERVICES_APP_ICON_PATH_KEY CFSTR("iconPath")
+#define DTSERVICES_APP_FRONTMOST_KEY CFSTR("isFrontApp")
+#define DTSERVICES_APP_PATH_KEY CFSTR("executablePath")
+#define DTSERVICES_APP_ICON_PATH_KEY CFSTR("iconPath")
#define DTSERVICES_APP_DISPLAY_NAME_KEY CFSTR("displayName")
-#define DTSERVICES_APP_PID_KEY CFSTR("pid")
+#define DTSERVICES_APP_PID_KEY CFSTR("pid")
-int ListApplications (std::string &plist, bool opt_runningApps, bool opt_debuggable);
+int ListApplications(std::string &plist, bool opt_runningApps,
+ bool opt_debuggable);
-#endif // __RNBServices_h__
+#endif // __RNBServices_h__
Modified: lldb/trunk/tools/debugserver/source/RNBSocket.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBSocket.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBSocket.cpp (original)
+++ lldb/trunk/tools/debugserver/source/RNBSocket.cpp Tue Sep 6 15:57:50 2016
@@ -12,6 +12,8 @@
//===----------------------------------------------------------------------===//
#include "RNBSocket.h"
+#include "DNBError.h"
+#include "DNBLog.h"
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
@@ -19,8 +21,6 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <termios.h>
-#include "DNBLog.h"
-#include "DNBError.h"
#ifdef WITH_LOCKDOWN
#include "lockdown.h"
@@ -30,392 +30,357 @@
this function is called to wait for an incoming connection.
This function blocks while waiting for that connection. */
-bool
-ResolveIPV4HostName (const char *hostname, in_addr_t &addr)
-{
- if (hostname == NULL ||
- hostname[0] == '\0' ||
- strcmp(hostname, "localhost") == 0 ||
- strcmp(hostname, "127.0.0.1") == 0)
- {
- addr = htonl (INADDR_LOOPBACK);
- return true;
- }
- else if (strcmp(hostname, "*") == 0)
- {
- addr = htonl (INADDR_ANY);
+bool ResolveIPV4HostName(const char *hostname, in_addr_t &addr) {
+ if (hostname == NULL || hostname[0] == '\0' ||
+ strcmp(hostname, "localhost") == 0 ||
+ strcmp(hostname, "127.0.0.1") == 0) {
+ addr = htonl(INADDR_LOOPBACK);
+ return true;
+ } else if (strcmp(hostname, "*") == 0) {
+ addr = htonl(INADDR_ANY);
+ return true;
+ } else {
+ // See if an IP address was specified as numbers
+ int inet_pton_result = ::inet_pton(AF_INET, hostname, &addr);
+
+ if (inet_pton_result == 1)
+ return true;
+
+ struct hostent *host_entry = gethostbyname(hostname);
+ if (host_entry) {
+ std::string ip_str(
+ ::inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list));
+ inet_pton_result = ::inet_pton(AF_INET, ip_str.c_str(), &addr);
+ if (inet_pton_result == 1)
return true;
}
- else
- {
- // See if an IP address was specified as numbers
- int inet_pton_result = ::inet_pton (AF_INET, hostname, &addr);
-
- if (inet_pton_result == 1)
- return true;
-
- struct hostent *host_entry = gethostbyname (hostname);
- if (host_entry)
- {
- std::string ip_str (::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list));
- inet_pton_result = ::inet_pton (AF_INET, ip_str.c_str(), &addr);
- if (inet_pton_result == 1)
- return true;
- }
- }
- return false;
+ }
+ return false;
}
-rnb_err_t
-RNBSocket::Listen (const char *listen_host, uint16_t port, PortBoundCallback callback, const void *callback_baton)
-{
- //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__);
- // Disconnect without saving errno
- Disconnect (false);
-
- // Now figure out the hostname that will be attaching and palce it into
- struct sockaddr_in listen_addr;
- ::memset (&listen_addr, 0, sizeof listen_addr);
- listen_addr.sin_len = sizeof listen_addr;
- listen_addr.sin_family = AF_INET;
- listen_addr.sin_port = htons (port);
- listen_addr.sin_addr.s_addr = INADDR_ANY;
-
- if (!ResolveIPV4HostName(listen_host, listen_addr.sin_addr.s_addr))
- {
- DNBLogThreaded("error: failed to resolve connecting host '%s'", listen_host);
- return rnb_err;
- }
-
- DNBError err;
- int listen_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (listen_fd == -1)
- err.SetError(errno, DNBError::POSIX);
+rnb_err_t RNBSocket::Listen(const char *listen_host, uint16_t port,
+ PortBoundCallback callback,
+ const void *callback_baton) {
+ // DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called",
+ // (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__);
+ // Disconnect without saving errno
+ Disconnect(false);
+
+ // Now figure out the hostname that will be attaching and palce it into
+ struct sockaddr_in listen_addr;
+ ::memset(&listen_addr, 0, sizeof listen_addr);
+ listen_addr.sin_len = sizeof listen_addr;
+ listen_addr.sin_family = AF_INET;
+ listen_addr.sin_port = htons(port);
+ listen_addr.sin_addr.s_addr = INADDR_ANY;
+
+ if (!ResolveIPV4HostName(listen_host, listen_addr.sin_addr.s_addr)) {
+ DNBLogThreaded("error: failed to resolve connecting host '%s'",
+ listen_host);
+ return rnb_err;
+ }
+
+ DNBError err;
+ int listen_fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (listen_fd == -1)
+ err.SetError(errno, DNBError::POSIX);
+
+ if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
+ err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol "
+ "= IPPROTO_TCP ) => socket = %i",
+ listen_fd);
+
+ if (err.Fail())
+ return rnb_err;
+
+ // enable local address reuse
+ SetSocketOption(listen_fd, SOL_SOCKET, SO_REUSEADDR, 1);
+
+ struct sockaddr_in sa;
+ ::memset(&sa, 0, sizeof sa);
+ sa.sin_len = sizeof sa;
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons(port);
+ sa.sin_addr.s_addr = INADDR_ANY; // Let incoming connections bind to any host
+ // network interface (this is NOT who can
+ // connect to us)
+ int error = ::bind(listen_fd, (struct sockaddr *)&sa, sizeof(sa));
+ if (error == -1)
+ err.SetError(errno, DNBError::POSIX);
+
+ if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
+ err.LogThreaded(
+ "::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )",
+ listen_fd);
+
+ if (err.Fail()) {
+ ClosePort(listen_fd, false);
+ return rnb_err;
+ }
+
+ error = ::listen(listen_fd, 5);
+ if (error == -1)
+ err.SetError(errno, DNBError::POSIX);
+
+ if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
+ err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd);
+
+ if (err.Fail()) {
+ ClosePort(listen_fd, false);
+ return rnb_err;
+ }
+
+ if (callback) {
+ // We were asked to listen on port zero which means we
+ // must now read the actual port that was given to us
+ // as port zero is a special code for "find an open port
+ // for me".
+ if (port == 0) {
+ socklen_t sa_len = sizeof(sa);
+ if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0) {
+ port = ntohs(sa.sin_port);
+ callback(callback_baton, port);
+ }
+ } else {
+ callback(callback_baton, port);
+ }
+ }
+
+ struct sockaddr_in accept_addr;
+ ::memset(&accept_addr, 0, sizeof accept_addr);
+ accept_addr.sin_len = sizeof accept_addr;
+
+ bool accept_connection = false;
+
+ // Loop until we are happy with our connection
+ while (!accept_connection) {
+ socklen_t accept_addr_len = sizeof accept_addr;
+ m_fd =
+ ::accept(listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len);
- if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_fd);
-
- if (err.Fail())
- return rnb_err;
-
- // enable local address reuse
- SetSocketOption (listen_fd, SOL_SOCKET, SO_REUSEADDR, 1);
-
- struct sockaddr_in sa;
- ::memset (&sa, 0, sizeof sa);
- sa.sin_len = sizeof sa;
- sa.sin_family = AF_INET;
- sa.sin_port = htons (port);
- sa.sin_addr.s_addr = INADDR_ANY; // Let incoming connections bind to any host network interface (this is NOT who can connect to us)
- int error = ::bind (listen_fd, (struct sockaddr *) &sa, sizeof(sa));
- if (error == -1)
- err.SetError(errno, DNBError::POSIX);
+ if (m_fd == -1)
+ err.SetError(errno, DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_fd);
+ err.LogThreaded(
+ "::accept ( socket = %i, address = %p, address_len = %u )", listen_fd,
+ &accept_addr, accept_addr_len);
if (err.Fail())
- {
- ClosePort (listen_fd, false);
- return rnb_err;
- }
+ break;
- error = ::listen (listen_fd, 5);
- if (error == -1)
- err.SetError(errno, DNBError::POSIX);
+ if (listen_addr.sin_addr.s_addr == INADDR_ANY)
+ accept_connection = true;
+ else {
+ if (accept_addr_len == listen_addr.sin_len &&
+ accept_addr.sin_addr.s_addr == listen_addr.sin_addr.s_addr) {
+ accept_connection = true;
+ } else {
+ ::close(m_fd);
+ m_fd = -1;
+ const uint8_t *accept_ip =
+ (const uint8_t *)&accept_addr.sin_addr.s_addr;
+ const uint8_t *listen_ip =
+ (const uint8_t *)&listen_addr.sin_addr.s_addr;
+ ::fprintf(stderr, "error: rejecting incoming connection from "
+ "%u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
+ accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
+ listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
+ DNBLogThreaded("error: rejecting connection from %u.%u.%u.%u "
+ "(expecting %u.%u.%u.%u)",
+ accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
+ listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
+ }
+ }
+ }
+
+ ClosePort(listen_fd, false);
+
+ if (err.Fail()) {
+ return rnb_err;
+ } else {
+ // Keep our TCP packets coming without any delays.
+ SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
+ }
- if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd);
+ return rnb_success;
+}
- if (err.Fail())
- {
- ClosePort (listen_fd, false);
- return rnb_err;
- }
-
- if (callback)
- {
- // We were asked to listen on port zero which means we
- // must now read the actual port that was given to us
- // as port zero is a special code for "find an open port
- // for me".
- if (port == 0)
- {
- socklen_t sa_len = sizeof (sa);
- if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0)
- {
- port = ntohs (sa.sin_port);
- callback (callback_baton, port);
- }
- }
- else
- {
- callback (callback_baton, port);
- }
- }
+rnb_err_t RNBSocket::Connect(const char *host, uint16_t port) {
+ Disconnect(false);
- struct sockaddr_in accept_addr;
- ::memset (&accept_addr, 0, sizeof accept_addr);
- accept_addr.sin_len = sizeof accept_addr;
-
- bool accept_connection = false;
-
- // Loop until we are happy with our connection
- while (!accept_connection)
- {
- socklen_t accept_addr_len = sizeof accept_addr;
- m_fd = ::accept (listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len);
-
- if (m_fd == -1)
- err.SetError(errno, DNBError::POSIX);
-
- if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::accept ( socket = %i, address = %p, address_len = %u )", listen_fd, &accept_addr, accept_addr_len);
-
- if (err.Fail())
- break;
-
- if (listen_addr.sin_addr.s_addr == INADDR_ANY)
- accept_connection = true;
- else
- {
- if (accept_addr_len == listen_addr.sin_len &&
- accept_addr.sin_addr.s_addr == listen_addr.sin_addr.s_addr)
- {
- accept_connection = true;
- }
- else
- {
- ::close (m_fd);
- m_fd = -1;
- const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
- const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sin_addr.s_addr;
- ::fprintf (stderr,
- "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
- accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
- listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
- DNBLogThreaded ("error: rejecting connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)",
- accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
- listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
- }
- }
- }
+ // Create the socket
+ m_fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (m_fd == -1)
+ return rnb_err;
- ClosePort (listen_fd, false);
+ // Enable local address reuse
+ SetSocketOption(m_fd, SOL_SOCKET, SO_REUSEADDR, 1);
- if (err.Fail())
- {
- return rnb_err;
- }
- else
- {
- // Keep our TCP packets coming without any delays.
- SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
- }
+ struct sockaddr_in sa;
+ ::memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons(port);
- return rnb_success;
-}
+ if (!ResolveIPV4HostName(host, sa.sin_addr.s_addr)) {
+ DNBLogThreaded("error: failed to resolve host '%s'", host);
+ Disconnect(false);
+ return rnb_err;
+ }
-rnb_err_t
-RNBSocket::Connect (const char *host, uint16_t port)
-{
- Disconnect (false);
+ if (-1 == ::connect(m_fd, (const struct sockaddr *)&sa, sizeof(sa))) {
+ Disconnect(false);
+ return rnb_err;
+ }
- // Create the socket
- m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (m_fd == -1)
- return rnb_err;
-
- // Enable local address reuse
- SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1);
-
- struct sockaddr_in sa;
- ::memset (&sa, 0, sizeof (sa));
- sa.sin_family = AF_INET;
- sa.sin_port = htons (port);
-
- if (!ResolveIPV4HostName(host, sa.sin_addr.s_addr))
- {
- DNBLogThreaded("error: failed to resolve host '%s'", host);
- Disconnect (false);
- return rnb_err;
- }
-
- if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa)))
- {
- Disconnect (false);
- return rnb_err;
- }
-
- // Keep our TCP packets coming without any delays.
- SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
- return rnb_success;
-}
+ // Keep our TCP packets coming without any delays.
+ SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
+ return rnb_success;
+}
+
+rnb_err_t RNBSocket::useFD(int fd) {
+ if (fd < 0) {
+ DNBLogThreadedIf(LOG_RNB_COMM, "Bad file descriptor passed in.");
+ return rnb_err;
+ }
-rnb_err_t
-RNBSocket::useFD(int fd)
-{
- if (fd < 0) {
- DNBLogThreadedIf(LOG_RNB_COMM, "Bad file descriptor passed in.");
- return rnb_err;
- }
-
- m_fd = fd;
- return rnb_success;
+ m_fd = fd;
+ return rnb_success;
}
#ifdef WITH_LOCKDOWN
-rnb_err_t
-RNBSocket::ConnectToService()
-{
- DNBLog("Connecting to com.apple.%s service...", DEBUGSERVER_PROGRAM_NAME);
- // Disconnect from any previous connections
- Disconnect(false);
- if (::secure_lockdown_checkin (&m_ld_conn, NULL, NULL) != kLDESuccess)
- {
- DNBLogThreadedIf(LOG_RNB_COMM, "::secure_lockdown_checkin(&m_fd, NULL, NULL) failed");
- m_fd = -1;
- return rnb_not_connected;
- }
- m_fd = ::lockdown_get_socket (m_ld_conn);
- if (m_fd == -1)
- {
- DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_get_socket() failed");
- return rnb_not_connected;
- }
- m_fd_from_lockdown = true;
- return rnb_success;
+rnb_err_t RNBSocket::ConnectToService() {
+ DNBLog("Connecting to com.apple.%s service...", DEBUGSERVER_PROGRAM_NAME);
+ // Disconnect from any previous connections
+ Disconnect(false);
+ if (::secure_lockdown_checkin(&m_ld_conn, NULL, NULL) != kLDESuccess) {
+ DNBLogThreadedIf(LOG_RNB_COMM,
+ "::secure_lockdown_checkin(&m_fd, NULL, NULL) failed");
+ m_fd = -1;
+ return rnb_not_connected;
+ }
+ m_fd = ::lockdown_get_socket(m_ld_conn);
+ if (m_fd == -1) {
+ DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_get_socket() failed");
+ return rnb_not_connected;
+ }
+ m_fd_from_lockdown = true;
+ return rnb_success;
}
#endif
-rnb_err_t
-RNBSocket::OpenFile (const char *path)
-{
- DNBError err;
- m_fd = open (path, O_RDWR);
- if (m_fd == -1)
- {
- err.SetError(errno, DNBError::POSIX);
- err.LogThreaded ("can't open file '%s'", path);
- return rnb_not_connected;
- }
- else
- {
- struct termios stdin_termios;
-
- if (::tcgetattr (m_fd, &stdin_termios) == 0)
- {
- stdin_termios.c_lflag &= ~ECHO; // Turn off echoing
- stdin_termios.c_lflag &= ~ICANON; // Get one char at a time
- ::tcsetattr (m_fd, TCSANOW, &stdin_termios);
- }
- }
- return rnb_success;
+rnb_err_t RNBSocket::OpenFile(const char *path) {
+ DNBError err;
+ m_fd = open(path, O_RDWR);
+ if (m_fd == -1) {
+ err.SetError(errno, DNBError::POSIX);
+ err.LogThreaded("can't open file '%s'", path);
+ return rnb_not_connected;
+ } else {
+ struct termios stdin_termios;
+
+ if (::tcgetattr(m_fd, &stdin_termios) == 0) {
+ stdin_termios.c_lflag &= ~ECHO; // Turn off echoing
+ stdin_termios.c_lflag &= ~ICANON; // Get one char at a time
+ ::tcsetattr(m_fd, TCSANOW, &stdin_termios);
+ }
+ }
+ return rnb_success;
+}
+
+int RNBSocket::SetSocketOption(int fd, int level, int option_name,
+ int option_value) {
+ return ::setsockopt(fd, level, option_name, &option_value,
+ sizeof(option_value));
}
-int
-RNBSocket::SetSocketOption(int fd, int level, int option_name, int option_value)
-{
- return ::setsockopt(fd, level, option_name, &option_value, sizeof(option_value));
-}
-
-rnb_err_t
-RNBSocket::Disconnect (bool save_errno)
-{
+rnb_err_t RNBSocket::Disconnect(bool save_errno) {
#ifdef WITH_LOCKDOWN
- if (m_fd_from_lockdown)
- {
- m_fd_from_lockdown = false;
- m_fd = -1;
- lockdown_disconnect (m_ld_conn);
- return rnb_success;
- }
-#endif
- return ClosePort (m_fd, save_errno);
-}
-
-
-rnb_err_t
-RNBSocket::Read (std::string &p)
-{
- char buf[1024];
- p.clear();
-
- // Note that BUF is on the stack so we must be careful to keep any
- // writes to BUF from overflowing or we'll have security issues.
-
- if (m_fd == -1)
- return rnb_err;
-
- //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__);
- DNBError err;
- ssize_t bytesread = read (m_fd, buf, sizeof (buf));
- if (bytesread <= 0)
- err.SetError(errno, DNBError::POSIX);
- else
- p.append(buf, bytesread);
-
- if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::read ( %i, %p, %llu ) => %i", m_fd, buf, sizeof (buf), (uint64_t)bytesread);
-
- // Our port went away - we have to mark this so IsConnected will return the truth.
- if (bytesread == 0)
- {
- m_fd = -1;
- return rnb_not_connected;
- }
- else if (bytesread == -1)
- {
- m_fd = -1;
- return rnb_err;
- }
- // Strip spaces from the end of the buffer
- while (!p.empty() && isspace (p[p.size() - 1]))
- p.erase (p.size () - 1);
-
- // Most data in the debugserver packets valid printable characters...
- DNBLogThreadedIf(LOG_RNB_COMM, "read: %s", p.c_str());
- return rnb_success;
-}
-
-rnb_err_t
-RNBSocket::Write (const void *buffer, size_t length)
-{
- if (m_fd == -1)
- return rnb_err;
-
- DNBError err;
- ssize_t bytessent = write (m_fd, buffer, length);
- if (bytessent < 0)
- err.SetError(errno, DNBError::POSIX);
-
- if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::write ( socket = %i, buffer = %p, length = %llu) => %i", m_fd, buffer, length, (uint64_t)bytessent);
-
- if (bytessent < 0)
- return rnb_err;
-
- if ((size_t)bytessent != length)
- return rnb_err;
-
- DNBLogThreadedIf(LOG_RNB_PACKETS, "putpkt: %*s", (int)length, (char *)buffer); // All data is string based in debugserver, so this is safe
- DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", (int)length, (char *)buffer);
-
+ if (m_fd_from_lockdown) {
+ m_fd_from_lockdown = false;
+ m_fd = -1;
+ lockdown_disconnect(m_ld_conn);
return rnb_success;
+ }
+#endif
+ return ClosePort(m_fd, save_errno);
}
-
-rnb_err_t
-RNBSocket::ClosePort (int& fd, bool save_errno)
-{
- int close_err = 0;
- if (fd > 0)
- {
- errno = 0;
- close_err = close (fd);
- fd = -1;
- }
- return close_err != 0 ? rnb_err : rnb_success;
+rnb_err_t RNBSocket::Read(std::string &p) {
+ char buf[1024];
+ p.clear();
+
+ // Note that BUF is on the stack so we must be careful to keep any
+ // writes to BUF from overflowing or we'll have security issues.
+
+ if (m_fd == -1)
+ return rnb_err;
+
+ // DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()",
+ // (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__);
+ DNBError err;
+ ssize_t bytesread = read(m_fd, buf, sizeof(buf));
+ if (bytesread <= 0)
+ err.SetError(errno, DNBError::POSIX);
+ else
+ p.append(buf, bytesread);
+
+ if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
+ err.LogThreaded("::read ( %i, %p, %llu ) => %i", m_fd, buf, sizeof(buf),
+ (uint64_t)bytesread);
+
+ // Our port went away - we have to mark this so IsConnected will return the
+ // truth.
+ if (bytesread == 0) {
+ m_fd = -1;
+ return rnb_not_connected;
+ } else if (bytesread == -1) {
+ m_fd = -1;
+ return rnb_err;
+ }
+ // Strip spaces from the end of the buffer
+ while (!p.empty() && isspace(p[p.size() - 1]))
+ p.erase(p.size() - 1);
+
+ // Most data in the debugserver packets valid printable characters...
+ DNBLogThreadedIf(LOG_RNB_COMM, "read: %s", p.c_str());
+ return rnb_success;
+}
+
+rnb_err_t RNBSocket::Write(const void *buffer, size_t length) {
+ if (m_fd == -1)
+ return rnb_err;
+
+ DNBError err;
+ ssize_t bytessent = write(m_fd, buffer, length);
+ if (bytessent < 0)
+ err.SetError(errno, DNBError::POSIX);
+
+ if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
+ err.LogThreaded("::write ( socket = %i, buffer = %p, length = %llu) => %i",
+ m_fd, buffer, length, (uint64_t)bytessent);
+
+ if (bytessent < 0)
+ return rnb_err;
+
+ if ((size_t)bytessent != length)
+ return rnb_err;
+
+ DNBLogThreadedIf(
+ LOG_RNB_PACKETS, "putpkt: %*s", (int)length,
+ (char *)
+ buffer); // All data is string based in debugserver, so this is safe
+ DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", (int)length, (char *)buffer);
+
+ return rnb_success;
+}
+
+rnb_err_t RNBSocket::ClosePort(int &fd, bool save_errno) {
+ int close_err = 0;
+ if (fd > 0) {
+ errno = 0;
+ close_err = close(fd);
+ fd = -1;
+ }
+ return close_err != 0 ? rnb_err : rnb_success;
}
-
-
Modified: lldb/trunk/tools/debugserver/source/RNBSocket.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBSocket.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBSocket.h (original)
+++ lldb/trunk/tools/debugserver/source/RNBSocket.h Tue Sep 6 15:57:50 2016
@@ -14,72 +14,66 @@
#ifndef __RNBSocket_h__
#define __RNBSocket_h__
+#include "DNBTimer.h"
#include "RNBDefs.h"
+#include <string>
#include <sys/socket.h>
#include <sys/types.h>
-#include <string>
-#include "DNBTimer.h"
#ifdef WITH_LOCKDOWN
#include "lockdown.h"
#endif
-class RNBSocket
-{
+class RNBSocket {
public:
- typedef void (*PortBoundCallback) (const void *baton, uint16_t port);
+ typedef void (*PortBoundCallback)(const void *baton, uint16_t port);
- RNBSocket () :
- m_fd (-1),
+ RNBSocket()
+ : m_fd(-1),
#ifdef WITH_LOCKDOWN
- m_fd_from_lockdown (false),
- m_ld_conn (),
+ m_fd_from_lockdown(false), m_ld_conn(),
#endif
- m_timer (true) // Make a thread safe timer
- {
- }
- ~RNBSocket (void)
- {
- Disconnect (false);
- }
-
- rnb_err_t Listen (const char *listen_host,
- uint16_t port,
- PortBoundCallback callback,
- const void *callback_baton);
- rnb_err_t Connect (const char *host, uint16_t port);
+ m_timer(true) // Make a thread safe timer
+ {
+ }
+ ~RNBSocket(void) { Disconnect(false); }
+
+ rnb_err_t Listen(const char *listen_host, uint16_t port,
+ PortBoundCallback callback, const void *callback_baton);
+ rnb_err_t Connect(const char *host, uint16_t port);
- rnb_err_t useFD(int fd);
+ rnb_err_t useFD(int fd);
#ifdef WITH_LOCKDOWN
- rnb_err_t ConnectToService();
+ rnb_err_t ConnectToService();
#endif
- rnb_err_t OpenFile (const char *path);
- rnb_err_t Disconnect (bool save_errno);
- rnb_err_t Read (std::string &p);
- rnb_err_t Write (const void *buffer, size_t length);
-
- bool IsConnected () const { return m_fd != -1; }
- void SaveErrno (int curr_errno);
- DNBTimer& Timer() { return m_timer; }
+ rnb_err_t OpenFile(const char *path);
+ rnb_err_t Disconnect(bool save_errno);
+ rnb_err_t Read(std::string &p);
+ rnb_err_t Write(const void *buffer, size_t length);
+
+ bool IsConnected() const { return m_fd != -1; }
+ void SaveErrno(int curr_errno);
+ DNBTimer &Timer() { return m_timer; }
+
+ static int SetSocketOption(int fd, int level, int option_name,
+ int option_value);
- static int SetSocketOption(int fd, int level, int option_name, int option_value);
private:
- // Outlaw some constructors
- RNBSocket (const RNBSocket &);
+ // Outlaw some constructors
+ RNBSocket(const RNBSocket &);
protected:
- rnb_err_t ClosePort (int& fd, bool save_errno);
+ rnb_err_t ClosePort(int &fd, bool save_errno);
- int m_fd; // Socket we use to communicate once conn established
+ int m_fd; // Socket we use to communicate once conn established
#ifdef WITH_LOCKDOWN
- bool m_fd_from_lockdown;
- lockdown_connection m_ld_conn;
+ bool m_fd_from_lockdown;
+ lockdown_connection m_ld_conn;
#endif
- DNBTimer m_timer;
+ DNBTimer m_timer;
};
-
#endif // #ifndef __RNBSocket_h__
Modified: lldb/trunk/tools/debugserver/source/SysSignal.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/SysSignal.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/SysSignal.cpp (original)
+++ lldb/trunk/tools/debugserver/source/SysSignal.cpp Tue Sep 6 15:57:50 2016
@@ -15,52 +15,81 @@
#include <signal.h>
#include <stddef.h>
-const char *
-SysSignal::Name(int signal)
-{
- switch (signal)
- {
- case SIGHUP: return "SIGHUP"; // 1 hangup
- case SIGINT: return "SIGINT"; // 2 interrupt
- case SIGQUIT: return "SIGQUIT"; // 3 quit
- case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught)
- case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught)
- case SIGABRT: return "SIGABRT"; // 6 abort()
-#if defined(_POSIX_C_SOURCE)
- case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported)
-#else // !_POSIX_C_SOURCE
- case SIGEMT: return "SIGEMT"; // 7 EMT instruction
-#endif // !_POSIX_C_SOURCE
- case SIGFPE: return "SIGFPE"; // 8 floating point exception
- case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored)
- case SIGBUS: return "SIGBUS"; // 10 bus error
- case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation
- case SIGSYS: return "SIGSYS"; // 12 bad argument to system call
- case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it
- case SIGALRM: return "SIGALRM"; // 14 alarm clock
- case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill
- case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel
- case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty
- case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty
- case SIGCONT: return "SIGCONT"; // 19 continue a stopped process
- case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit
- case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read
- case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP)
-#if !defined(_POSIX_C_SOURCE)
- case SIGIO: return "SIGIO"; // 23 input/output possible signal
+const char *SysSignal::Name(int signal) {
+ switch (signal) {
+ case SIGHUP:
+ return "SIGHUP"; // 1 hangup
+ case SIGINT:
+ return "SIGINT"; // 2 interrupt
+ case SIGQUIT:
+ return "SIGQUIT"; // 3 quit
+ case SIGILL:
+ return "SIGILL"; // 4 illegal instruction (not reset when caught)
+ case SIGTRAP:
+ return "SIGTRAP"; // 5 trace trap (not reset when caught)
+ case SIGABRT:
+ return "SIGABRT"; // 6 abort()
+#if defined(_POSIX_C_SOURCE)
+ case SIGPOLL:
+ return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported)
+#else // !_POSIX_C_SOURCE
+ case SIGEMT:
+ return "SIGEMT"; // 7 EMT instruction
+#endif // !_POSIX_C_SOURCE
+ case SIGFPE:
+ return "SIGFPE"; // 8 floating point exception
+ case SIGKILL:
+ return "SIGKILL"; // 9 kill (cannot be caught or ignored)
+ case SIGBUS:
+ return "SIGBUS"; // 10 bus error
+ case SIGSEGV:
+ return "SIGSEGV"; // 11 segmentation violation
+ case SIGSYS:
+ return "SIGSYS"; // 12 bad argument to system call
+ case SIGPIPE:
+ return "SIGPIPE"; // 13 write on a pipe with no one to read it
+ case SIGALRM:
+ return "SIGALRM"; // 14 alarm clock
+ case SIGTERM:
+ return "SIGTERM"; // 15 software termination signal from kill
+ case SIGURG:
+ return "SIGURG"; // 16 urgent condition on IO channel
+ case SIGSTOP:
+ return "SIGSTOP"; // 17 sendable stop signal not from tty
+ case SIGTSTP:
+ return "SIGTSTP"; // 18 stop signal from tty
+ case SIGCONT:
+ return "SIGCONT"; // 19 continue a stopped process
+ case SIGCHLD:
+ return "SIGCHLD"; // 20 to parent on child stop or exit
+ case SIGTTIN:
+ return "SIGTTIN"; // 21 to readers pgrp upon background tty read
+ case SIGTTOU:
+ return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP)
+#if !defined(_POSIX_C_SOURCE)
+ case SIGIO:
+ return "SIGIO"; // 23 input/output possible signal
#endif
- case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit
- case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit
- case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm
- case SIGPROF: return "SIGPROF"; // 27 profiling time alarm
-#if !defined(_POSIX_C_SOURCE)
- case SIGWINCH: return "SIGWINCH"; // 28 window size changes
- case SIGINFO: return "SIGINFO"; // 29 information request
+ case SIGXCPU:
+ return "SIGXCPU"; // 24 exceeded CPU time limit
+ case SIGXFSZ:
+ return "SIGXFSZ"; // 25 exceeded file size limit
+ case SIGVTALRM:
+ return "SIGVTALRM"; // 26 virtual time alarm
+ case SIGPROF:
+ return "SIGPROF"; // 27 profiling time alarm
+#if !defined(_POSIX_C_SOURCE)
+ case SIGWINCH:
+ return "SIGWINCH"; // 28 window size changes
+ case SIGINFO:
+ return "SIGINFO"; // 29 information request
#endif
- case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1
- case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2
- default:
- break;
- }
- return NULL;
+ case SIGUSR1:
+ return "SIGUSR1"; // 30 user defined signal 1
+ case SIGUSR2:
+ return "SIGUSR2"; // 31 user defined signal 2
+ default:
+ break;
+ }
+ return NULL;
}
Modified: lldb/trunk/tools/debugserver/source/SysSignal.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/SysSignal.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/SysSignal.h (original)
+++ lldb/trunk/tools/debugserver/source/SysSignal.h Tue Sep 6 15:57:50 2016
@@ -14,10 +14,9 @@
#ifndef __SysSignal_h__
#define __SysSignal_h__
-class SysSignal
-{
+class SysSignal {
public:
- static const char *Name(int signal);
+ static const char *Name(int signal);
};
#endif
Modified: lldb/trunk/tools/debugserver/source/TTYState.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/TTYState.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/TTYState.cpp (original)
+++ lldb/trunk/tools/debugserver/source/TTYState.cpp Tue Sep 6 15:57:50 2016
@@ -13,110 +13,82 @@
#include "TTYState.h"
#include <fcntl.h>
-#include <unistd.h>
#include <sys/signal.h>
+#include <unistd.h>
-TTYState::TTYState() :
- m_fd(-1),
- m_tflags(-1),
- m_ttystateErr(-1),
- m_processGroup(-1)
-{
-}
+TTYState::TTYState()
+ : m_fd(-1), m_tflags(-1), m_ttystateErr(-1), m_processGroup(-1) {}
-TTYState::~TTYState()
-{
-}
+TTYState::~TTYState() {}
-bool
-TTYState::GetTTYState (int fd, bool saveProcessGroup)
-{
- if (fd >= 0 && ::isatty (fd))
- {
- m_fd = fd;
- m_tflags = fcntl (fd, F_GETFL, 0);
- m_ttystateErr = tcgetattr (fd, &m_ttystate);
- if (saveProcessGroup)
- m_processGroup = tcgetpgrp (0);
- else
- m_processGroup = -1;
- }
+bool TTYState::GetTTYState(int fd, bool saveProcessGroup) {
+ if (fd >= 0 && ::isatty(fd)) {
+ m_fd = fd;
+ m_tflags = fcntl(fd, F_GETFL, 0);
+ m_ttystateErr = tcgetattr(fd, &m_ttystate);
+ if (saveProcessGroup)
+ m_processGroup = tcgetpgrp(0);
else
- {
- m_fd = -1;
- m_tflags = -1;
- m_ttystateErr = -1;
- m_processGroup = -1;
- }
- return m_ttystateErr == 0;
-}
-
-bool
-TTYState::SetTTYState () const
-{
- int result = 0;
- if (IsValid())
- {
- if (TFlagsValid())
- result = fcntl (m_fd, F_SETFL, m_tflags);
-
- if (TTYStateValid())
- result = tcsetattr (m_fd, TCSANOW, &m_ttystate);
-
- if (ProcessGroupValid())
- {
- // Save the original signal handler.
- void (*saved_sigttou_callback) (int) = NULL;
- saved_sigttou_callback = (void (*)(int)) signal (SIGTTOU, SIG_IGN);
- // Set the process group
- result = tcsetpgrp (m_fd, m_processGroup);
- // Restore the original signal handler.
- signal (SIGTTOU, saved_sigttou_callback);
- }
- return true;
+ m_processGroup = -1;
+ } else {
+ m_fd = -1;
+ m_tflags = -1;
+ m_ttystateErr = -1;
+ m_processGroup = -1;
+ }
+ return m_ttystateErr == 0;
+}
+
+bool TTYState::SetTTYState() const {
+ int result = 0;
+ if (IsValid()) {
+ if (TFlagsValid())
+ result = fcntl(m_fd, F_SETFL, m_tflags);
+
+ if (TTYStateValid())
+ result = tcsetattr(m_fd, TCSANOW, &m_ttystate);
+
+ if (ProcessGroupValid()) {
+ // Save the original signal handler.
+ void (*saved_sigttou_callback)(int) = NULL;
+ saved_sigttou_callback = (void (*)(int))signal(SIGTTOU, SIG_IGN);
+ // Set the process group
+ result = tcsetpgrp(m_fd, m_processGroup);
+ // Restore the original signal handler.
+ signal(SIGTTOU, saved_sigttou_callback);
}
- return false;
+ return true;
+ }
+ return false;
}
+TTYStateSwitcher::TTYStateSwitcher() : m_currentState(~0) {}
+TTYStateSwitcher::~TTYStateSwitcher() {}
-TTYStateSwitcher::TTYStateSwitcher() :
- m_currentState(~0)
-{
-}
-
-TTYStateSwitcher::~TTYStateSwitcher()
-{
+bool TTYStateSwitcher::GetState(uint32_t idx, int fd, bool saveProcessGroup) {
+ if (ValidStateIndex(idx))
+ return m_ttystates[idx].GetTTYState(fd, saveProcessGroup);
+ return false;
}
-bool
-TTYStateSwitcher::GetState(uint32_t idx, int fd, bool saveProcessGroup)
-{
- if (ValidStateIndex(idx))
- return m_ttystates[idx].GetTTYState(fd, saveProcessGroup);
+bool TTYStateSwitcher::SetState(uint32_t idx) const {
+ if (!ValidStateIndex(idx))
return false;
-}
-bool
-TTYStateSwitcher::SetState(uint32_t idx) const
-{
- if (!ValidStateIndex(idx))
- return false;
-
- // See if we already are in this state?
- if (ValidStateIndex(m_currentState) && (idx == m_currentState) && m_ttystates[idx].IsValid())
- return true;
-
- // Set the state to match the index passed in and only update the
- // current state if there are no errors.
- if (m_ttystates[idx].SetTTYState())
- {
- m_currentState = idx;
- return true;
- }
-
- // We failed to set the state. The tty state was invalid or not
- // initialized.
- return false;
+ // See if we already are in this state?
+ if (ValidStateIndex(m_currentState) && (idx == m_currentState) &&
+ m_ttystates[idx].IsValid())
+ return true;
+
+ // Set the state to match the index passed in and only update the
+ // current state if there are no errors.
+ if (m_ttystates[idx].SetTTYState()) {
+ m_currentState = idx;
+ return true;
+ }
+
+ // We failed to set the state. The tty state was invalid or not
+ // initialized.
+ return false;
}
-
Modified: lldb/trunk/tools/debugserver/source/TTYState.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/TTYState.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/TTYState.h (original)
+++ lldb/trunk/tools/debugserver/source/TTYState.h Tue Sep 6 15:57:50 2016
@@ -14,48 +14,46 @@
#ifndef __TTYState_h__
#define __TTYState_h__
-#include <termios.h>
#include <stdint.h>
+#include <termios.h>
-class TTYState
-{
+class TTYState {
public:
- TTYState();
- ~TTYState();
+ TTYState();
+ ~TTYState();
- bool GetTTYState (int fd, bool saveProcessGroup);
- bool SetTTYState () const;
+ bool GetTTYState(int fd, bool saveProcessGroup);
+ bool SetTTYState() const;
- bool IsValid() const { return FileDescriptorValid() && TFlagsValid() && TTYStateValid(); }
- bool FileDescriptorValid() const { return m_fd >= 0; }
- bool TFlagsValid() const { return m_tflags != -1; }
- bool TTYStateValid() const { return m_ttystateErr == 0; }
- bool ProcessGroupValid() const { return m_processGroup != -1; }
+ bool IsValid() const {
+ return FileDescriptorValid() && TFlagsValid() && TTYStateValid();
+ }
+ bool FileDescriptorValid() const { return m_fd >= 0; }
+ bool TFlagsValid() const { return m_tflags != -1; }
+ bool TTYStateValid() const { return m_ttystateErr == 0; }
+ bool ProcessGroupValid() const { return m_processGroup != -1; }
protected:
- int m_fd; // File descriptor
- int m_tflags;
- int m_ttystateErr;
- struct termios m_ttystate;
- pid_t m_processGroup;
-
+ int m_fd; // File descriptor
+ int m_tflags;
+ int m_ttystateErr;
+ struct termios m_ttystate;
+ pid_t m_processGroup;
};
-
-class TTYStateSwitcher
-{
+class TTYStateSwitcher {
public:
- TTYStateSwitcher();
- ~TTYStateSwitcher();
+ TTYStateSwitcher();
+ ~TTYStateSwitcher();
- bool GetState(uint32_t idx, int fd, bool saveProcessGroup);
- bool SetState(uint32_t idx) const;
- uint32_t NumStates() const { return sizeof(m_ttystates)/sizeof(TTYState); }
- bool ValidStateIndex(uint32_t idx) const { return idx < NumStates(); }
+ bool GetState(uint32_t idx, int fd, bool saveProcessGroup);
+ bool SetState(uint32_t idx) const;
+ uint32_t NumStates() const { return sizeof(m_ttystates) / sizeof(TTYState); }
+ bool ValidStateIndex(uint32_t idx) const { return idx < NumStates(); }
protected:
- mutable uint32_t m_currentState;
- TTYState m_ttystates[2];
+ mutable uint32_t m_currentState;
+ TTYState m_ttystates[2];
};
#endif
\ No newline at end of file
More information about the lldb-commits
mailing list