Author: kamil Date: Tue Apr 18 07:53:35 2017 New Revision: 300548 URL: http://llvm.org/viewvc/llvm-project?rev=300548&view=rev Log: Introduce FPR and Debug Registers/NetBSD/amd64 support
Summary: This code offers Debug Registers (80386) model in LLDB/amd64. This is initial support and has one issue that will be addressed later, Debug Register trap (TRAP_DBREG) is registered as (TRAP_TRACE) for unknown reason. On the other hand this works good enough to move on and leave this bug to be squashed later. Improve the NativeProcessNetBSD::ReinitializeThreads() function, stop setting inside it SetStoppedByExec(). This fixes incorrect stop reason on attaching (SetStoppedBySignal(SIGSTOP)). This commits also has no functional style improvements from clang-format. This code also ships with FXSAVE support on NetBSD. Demo: ``` $ lldb ./watch (lldb) target create "./watch" Current executable set to './watch' (x86_64). (lldb) b main Breakpoint 1: where = watch`main + 15 at watch.c:8, address = 0x000000000040087f (lldb) r Process 1573 launched: './watch' (x86_64) Process 1573 stopped * thread #1, stop reason = breakpoint 1.1 frame #0: 0x000000000040087f watch`main(argc=1, argv=0x00007f7fffa12b88) at watch.c:8 5 { 6 int i, j, k; 7 -> 8 for (i = 0; i < 3; i++) 9 for (j = 0; j < 3; j++) 10 for (k = 0; k < 3; k++) 11 printf("Hello world! i=%d j=%d k=%d\n", i, j, k); (lldb) watch set var i Watchpoint created: Watchpoint 1: addr = 0x7f7fffa12b4c size = 4 state = enabled type = w declare @ '/public/lldb_devel/watch.c:6' watchpoint spec = 'i' new value: 0 (lldb) c Process 1573 resuming Hello world! i=0 j=0 k=0 Hello world! i=0 j=0 k=1 Hello world! i=0 j=0 k=2 Hello world! i=0 j=1 k=0 Hello world! i=0 j=1 k=1 Hello world! i=0 j=1 k=2 Hello world! i=0 j=2 k=0 Hello world! i=0 j=2 k=1 Hello world! i=0 j=2 k=2 Process 1573 stopped * thread #1, stop reason = trace frame #0: 0x00000000004008cc watch`main(argc=1, argv=0x00007f7fffa12b88) at watch.c:8 5 { 6 int i, j, k; 7 -> 8 for (i = 0; i < 3; i++) 9 for (j = 0; j < 3; j++) 10 for (k = 0; k < 3; k++) 11 printf("Hello world! i=%d j=%d k=%d\n", i, j, k) ``` FPR (in another program using libm) ``` (lldb) register read --all General Purpose Registers: rax = 0x000000000000001c rbx = 0x00007f7fff1d4fe0 rcx = 0x000000000000000c rdx = 0x0000000000000002 rdi = 0x0000746711d5b018 __sF + 152 rsi = 0x0000000000000001 rbp = 0x00007f7fff1d3d80 rsp = 0x00007f7fff1d3d60 r8 = 0x00007f7fff1d3470 r9 = 0x0000000000000000 r10 = 0x0000000000000001 r11 = 0x0000000000000202 r12 = 0x00007f7fff1d3da0 r13 = 0x00007d8ad2d88500 r14 = 0x0000000000000002 r15 = 0x00007f7fffa627e0 rip = 0x00000000004009e9 fpr`main + 217 at fpr.c:15 rflags = 0x0000000000000202 cs = 0x0000000000000047 fs = 0x0000000000000000 gs = 0x0000000000000000 ss = 0x000000000000003f ds = 0x000000000000003f es = 0x000000000000003f eax = 0x0000001c ebx = 0xff1d4fe0 ecx = 0x0000000c edx = 0x00000002 edi = 0x11d5b018 esi = 0x00000001 ebp = 0xff1d3d80 esp = 0xff1d3d60 r8d = 0xff1d3470 r9d = 0x00000000 r10d = 0x00000001 r11d = 0x00000202 r12d = 0xff1d3da0 r13d = 0xd2d88500 r14d = 0x00000002 r15d = 0xffa627e0 ax = 0x001c bx = 0x4fe0 cx = 0x000c dx = 0x0002 di = 0xb018 si = 0x0001 bp = 0x3d80 sp = 0x3d60 r8w = 0x3470 r9w = 0x0000 r10w = 0x0001 r11w = 0x0202 r12w = 0x3da0 r13w = 0x8500 r14w = 0x0002 r15w = 0x27e0 ah = 0x00 bh = 0x4f ch = 0x00 dh = 0x00 al = 0x1c bl = 0xe0 cl = 0x0c dl = 0x02 dil = 0x18 sil = 0x01 bpl = 0x80 spl = 0x60 r8l = 0x70 r9l = 0x00 r10l = 0x01 r11l = 0x02 r12l = 0xa0 r13l = 0x00 r14l = 0x02 r15l = 0xe0 unknown: fctrl = 0x037f fstat = 0x0220 ftag = 0x00 fop = 0x0000 fiseg = 0x11e1a52c fioff = 0x11e1a52c foseg = 0xff1d3d54 fooff = 0xff1d3d54 mxcsr = 0x00001fa0 mxcsrmask = 0x0000ffff st0 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st1 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st2 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st3 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st4 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st5 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st6 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st7 = {0xa5 0xdb 0x2d 0xbd 0x93 0xae 0xb9 0xfe 0xfe 0x3f} mm0 = 0x3fe9d13800000000 mm1 = 0x3e0485fcce89c000 mm2 = 0x3fefd735e0000000 mm3 = 0x0000000000000000 mm4 = 0x3fe0000000000000 mm5 = 0x3fe00000005217f3 mm6 = 0x0000000000000000 mm7 = 0x3fefd735e0000000 xmm0 = {0x00 0x00 0x00 0x00 0x38 0xd1 0xe9 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm1 = {0x00 0xc0 0x89 0xce 0xfc 0x85 0x04 0x3e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm2 = {0x00 0x00 0x00 0xe0 0x35 0xd7 0xef 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm3 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm4 = {0x00 0x00 0x00 0x00 0x00 0x00 0xe0 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm5 = {0xf3 0x17 0x52 0x00 0x00 0x00 0xe0 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm6 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm7 = {0x00 0x00 0x00 0xe0 0x35 0xd7 0xef 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm8 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm9 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm10 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm11 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm12 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm13 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm14 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm15 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} dr0 = 0x0000000000000000 dr1 = 0x0000000000000000 dr2 = 0x0000000000000000 dr3 = 0x0000000000000000 dr4 = 0x0000000000000000 dr5 = 0x0000000000000000 dr6 = 0x00000000ffff0ff0 dr7 = 0x0000000000000400 22 registers were unavailable. ``` Sponsored by <The NetBSD Foundation> Reviewers: labath, emaste, joerg, kettenis Reviewed By: labath Subscribers: #lldb Tags: #lldb Differential Revision: https://reviews.llvm.org/D32080 Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_x86_64.h Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp?rev=300548&r1=300547&r2=300548&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp (original) +++ lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp Tue Apr 18 07:53:35 2017 @@ -224,36 +224,83 @@ void NativeProcessNetBSD::MonitorSIGTRAP PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); // Get details on the signal raised. - if (siginfo_err.Success()) { - switch (info.psi_siginfo.si_code) { - case TRAP_BRKPT: + if (siginfo_err.Fail()) { + return; + } + + switch (info.psi_siginfo.si_code) { + case TRAP_BRKPT: + for (const auto &thread_sp : m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp) + ->SetStoppedByBreakpoint(); + FixupBreakpointPCAsNeeded( + *static_pointer_cast<NativeThreadNetBSD>(thread_sp)); + } + SetState(StateType::eStateStopped, true); + break; + case TRAP_TRACE: + for (const auto &thread_sp : m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace(); + } + SetState(StateType::eStateStopped, true); + break; + case TRAP_EXEC: { + Error error = ReinitializeThreads(); + if (error.Fail()) { + SetState(StateType::eStateInvalid); + return; + } + + // Let our delegate know we have just exec'd. + NotifyDidExec(); + + for (const auto &thread_sp : m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByExec(); + } + SetState(StateType::eStateStopped, true); + } break; + case TRAP_DBREG: { + // If a watchpoint was hit, report it + uint32_t wp_index; + Error error = + static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid]) + ->GetRegisterContext() + ->GetWatchpointHitIndex(wp_index, + (uintptr_t)info.psi_siginfo.si_addr); + if (error.Fail()) + LLDB_LOG(log, + "received error while checking for watchpoint hits, pid = " + "{0}, LWP = {1}, error = {2}", + GetID(), info.psi_lwpid, error); + if (wp_index != LLDB_INVALID_INDEX32) { for (const auto &thread_sp : m_threads) { static_pointer_cast<NativeThreadNetBSD>(thread_sp) - ->SetStoppedByBreakpoint(); - FixupBreakpointPCAsNeeded( - *static_pointer_cast<NativeThreadNetBSD>(thread_sp)); + ->SetStoppedByWatchpoint(wp_index); } SetState(StateType::eStateStopped, true); break; - case TRAP_TRACE: + } + + // If a breakpoint was hit, report it + uint32_t bp_index; + error = static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid]) + ->GetRegisterContext() + ->GetHardwareBreakHitIndex(bp_index, + (uintptr_t)info.psi_siginfo.si_addr); + if (error.Fail()) + LLDB_LOG(log, + "received error while checking for hardware " + "breakpoint hits, pid = {0}, LWP = {1}, error = {2}", + GetID(), info.psi_lwpid, error); + if (bp_index != LLDB_INVALID_INDEX32) { for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace(); + static_pointer_cast<NativeThreadNetBSD>(thread_sp) + ->SetStoppedByBreakpoint(); } SetState(StateType::eStateStopped, true); break; - case TRAP_EXEC: { - Error error = ReinitializeThreads(); - if (error.Fail()) { - SetState(StateType::eStateInvalid); - return; - } - - // Let our delegate know we have just exec'd. - NotifyDidExec(); - - SetState(StateType::eStateStopped, true); - } break; } + } break; } } @@ -328,8 +375,8 @@ Error NativeProcessNetBSD::FixupBreakpoi return error; } else LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size); - // First try probing for a breakpoint at a software breakpoint location: PC - - // breakpoint size. + // First try probing for a breakpoint at a software breakpoint location: PC + // - breakpoint size. const lldb::addr_t initial_pc_addr = context_sp->GetPCfromBreakpointLocation(); lldb::addr_t breakpoint_addr = initial_pc_addr; @@ -439,7 +486,7 @@ Error NativeProcessNetBSD::Resume(const llvm_unreachable("Unexpected state"); default: - return Error("NativeProcessLinux::%s (): unexpected state %s specified " + return Error("NativeProcessNetBSD::%s (): unexpected state %s specified " "for pid %" PRIu64 ", tid %" PRIu64, __FUNCTION__, StateAsCString(action->state), GetID(), thread_sp->GetID()); @@ -540,8 +587,8 @@ Error NativeProcessNetBSD::GetMemoryRegi "descending memory map entries detected, unexpected"); prev_base_address = proc_entry_info.GetRange().GetRangeBase(); UNUSED_IF_ASSERT_DISABLED(prev_base_address); - // If the target address comes before this entry, indicate distance to next - // region. + // If the target address comes before this entry, indicate distance to + // next region. if (load_addr < proc_entry_info.GetRange().GetRangeBase()) { range_info.GetRange().SetRangeBase(load_addr); range_info.GetRange().SetByteSize( @@ -561,9 +608,8 @@ Error NativeProcessNetBSD::GetMemoryRegi } // If we made it here, we didn't find an entry that contained the given // address. Return the - // load_addr as start and the amount of bytes betwwen load address and the end - // of the memory as - // size. + // load_addr as start and the amount of bytes betwwen load address and the + // end of the memory as size. range_info.GetRange().SetRangeBase(load_addr); range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); @@ -722,8 +768,8 @@ Error NativeProcessNetBSD::LaunchInferio LLDB_LOG(log, "waitpid for inferior failed with %s", error); // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For now, - // using eStateInvalid. + // FIXME this could really use a new state - eStateLaunchFailure. For + // now, using eStateInvalid. SetState(StateType::eStateInvalid); return error; @@ -766,6 +812,11 @@ Error NativeProcessNetBSD::LaunchInferio return error; } + for (const auto &thread_sp : m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( + SIGSTOP); + } + /* Set process stopped */ SetState(StateType::eStateStopped); @@ -894,6 +945,11 @@ NativeThreadNetBSDSP NativeProcessNetBSD return -1; } + for (const auto &thread_sp : m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( + SIGSTOP); + } + // Let our process instance know the thread has stopped. SetState(StateType::eStateStopped); @@ -1007,7 +1063,6 @@ Error NativeProcessNetBSD::ReinitializeT // Reinitialize from scratch threads and register them in process while (info.pl_lwpid != 0) { NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid); - thread_sp->SetStoppedByExec(); error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info)); if (error.Fail()) { return error; Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp?rev=300548&r1=300547&r2=300548&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp (original) +++ lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp Tue Apr 18 07:53:35 2017 @@ -57,6 +57,22 @@ Error NativeRegisterContextNetBSD::Write return DoWriteFPR(buf); } +Error NativeRegisterContextNetBSD::ReadDBR() { + void *buf = GetDBRBuffer(); + if (!buf) + return Error("DBR buffer is NULL"); + + return DoReadDBR(buf); +} + +Error NativeRegisterContextNetBSD::WriteDBR() { + void *buf = GetDBRBuffer(); + if (!buf) + return Error("DBR buffer is NULL"); + + return DoWriteDBR(buf); +} + Error NativeRegisterContextNetBSD::DoReadGPR(void *buf) { return NativeProcessNetBSD::PtraceWrapper(PT_GETREGS, GetProcessPid(), buf, m_thread.GetID()); @@ -77,6 +93,16 @@ Error NativeRegisterContextNetBSD::DoWri m_thread.GetID()); } +Error NativeRegisterContextNetBSD::DoReadDBR(void *buf) { + return NativeProcessNetBSD::PtraceWrapper(PT_GETDBREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + +Error NativeRegisterContextNetBSD::DoWriteDBR(void *buf) { + return NativeProcessNetBSD::PtraceWrapper(PT_SETDBREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + NativeProcessNetBSD &NativeRegisterContextNetBSD::GetProcess() { auto process_sp = std::static_pointer_cast<NativeProcessNetBSD>(m_thread.GetProcess()); Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h?rev=300548&r1=300547&r2=300548&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h (original) +++ lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h Tue Apr 18 07:53:35 2017 @@ -41,6 +41,9 @@ protected: virtual Error ReadFPR(); virtual Error WriteFPR(); + virtual Error ReadDBR(); + virtual Error WriteDBR(); + virtual void *GetGPRBuffer() { return nullptr; } virtual size_t GetGPRSize() { return GetRegisterInfoInterface().GetGPRSize(); @@ -49,12 +52,18 @@ protected: virtual void *GetFPRBuffer() { return nullptr; } virtual size_t GetFPRSize() { return 0; } + virtual void *GetDBRBuffer() { return nullptr; } + virtual size_t GetDBRSize() { return 0; } + virtual Error DoReadGPR(void *buf); virtual Error DoWriteGPR(void *buf); virtual Error DoReadFPR(void *buf); virtual Error DoWriteFPR(void *buf); + virtual Error DoReadDBR(void *buf); + virtual Error DoWriteDBR(void *buf); + virtual NativeProcessNetBSD &GetProcess(); virtual ::pid_t GetProcessPid(); }; Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp?rev=300548&r1=300547&r2=300548&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp (original) +++ lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp Tue Apr 18 07:53:35 2017 @@ -19,7 +19,15 @@ #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" +// clang-format off +#include <sys/types.h> +#include <sys/sysctl.h> +#include <x86/cpu.h> #include <elf.h> +#include <err.h> +#include <stdint.h> +#include <stdlib.h> +// clang-format on using namespace lldb_private; using namespace lldb_private::process_netbsd; @@ -86,6 +94,57 @@ static const RegisterSet g_reg_sets_x86_ #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize()) +const int fpu_present = []() -> int { + int mib[2]; + int error; + size_t len; + int val; + + len = sizeof(val); + mib[0] = CTL_MACHDEP; + mib[1] = CPU_FPU_PRESENT; + + error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0); + if (error) + errx(EXIT_FAILURE, "sysctl"); + + return val; +}(); + +const int osfxsr = []() -> int { + int mib[2]; + int error; + size_t len; + int val; + + len = sizeof(val); + mib[0] = CTL_MACHDEP; + mib[1] = CPU_OSFXSR; + + error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0); + if (error) + errx(EXIT_FAILURE, "sysctl"); + + return val; +}(); + +const int fpu_save = []() -> int { + int mib[2]; + int error; + size_t len; + int val; + + len = sizeof(val); + mib[0] = CTL_MACHDEP; + mib[1] = CPU_FPU_SAVE; + + error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0); + if (error) + errx(EXIT_FAILURE, "sysctl"); + + return val; +}(); + } // namespace NativeRegisterContextNetBSD * @@ -114,7 +173,7 @@ NativeRegisterContextNetBSD_x86_64::Nati uint32_t concrete_frame_idx) : NativeRegisterContextNetBSD(native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)), - m_gpr_x86_64() {} + m_gpr_x86_64(), m_fpr_x86_64(), m_dbr_x86_64() {} // CONSIDER after local and llgs debugging are merged, register set support can // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual. @@ -143,8 +202,18 @@ NativeRegisterContextNetBSD_x86_64::GetR int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( int reg_num) const { - if (reg_num < lldb_fctrl_x86_64) + if (reg_num <= k_last_gpr_x86_64) return GPRegSet; + else if (reg_num <= k_last_fpr_x86_64) + return (fpu_present == 1 && osfxsr == 1 && fpu_save >= 1) ? FPRegSet : -1; + else if (reg_num <= k_last_avx_x86_64) + return -1; // AVX + else if (reg_num <= k_last_mpxr_x86_64) + return -1; // MPXR + else if (reg_num <= k_last_mpxc_x86_64) + return -1; // MPXC + else if (reg_num <= lldb_dr7_x86_64) + return DBRegSet; // DBR else return -1; } @@ -157,6 +226,9 @@ int NativeRegisterContextNetBSD_x86_64:: case FPRegSet: ReadFPR(); return 0; + case DBRegSet: + ReadDBR(); + return 0; default: break; } @@ -170,6 +242,9 @@ int NativeRegisterContextNetBSD_x86_64:: case FPRegSet: WriteFPR(); return 0; + case DBRegSet: + WriteDBR(); + return 0; default: break; } @@ -285,6 +360,87 @@ Error NativeRegisterContextNetBSD_x86_64 case lldb_es_x86_64: reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_ES]; break; + case lldb_fctrl_x86_64: + reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_cw; + break; + case lldb_fstat_x86_64: + reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_sw; + break; + case lldb_ftag_x86_64: + reg_value = (uint8_t)m_fpr_x86_64.fxstate.fx_tw; + break; + case lldb_fop_x86_64: + reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_opcode; + break; + case lldb_fiseg_x86_64: + reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_ip.fa_64; + break; + case lldb_fioff_x86_64: + reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off; + break; + case lldb_foseg_x86_64: + reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_dp.fa_64; + break; + case lldb_fooff_x86_64: + reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off; + break; + case lldb_mxcsr_x86_64: + reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr; + break; + case lldb_mxcsrmask_x86_64: + reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr_mask; + break; + case lldb_st0_x86_64: + case lldb_st1_x86_64: + case lldb_st2_x86_64: + case lldb_st3_x86_64: + case lldb_st4_x86_64: + case lldb_st5_x86_64: + case lldb_st6_x86_64: + case lldb_st7_x86_64: + reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64], + reg_info->byte_size, endian::InlHostByteOrder()); + break; + case lldb_mm0_x86_64: + case lldb_mm1_x86_64: + case lldb_mm2_x86_64: + case lldb_mm3_x86_64: + case lldb_mm4_x86_64: + case lldb_mm5_x86_64: + case lldb_mm6_x86_64: + case lldb_mm7_x86_64: + reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64], + reg_info->byte_size, endian::InlHostByteOrder()); + break; + case lldb_xmm0_x86_64: + case lldb_xmm1_x86_64: + case lldb_xmm2_x86_64: + case lldb_xmm3_x86_64: + case lldb_xmm4_x86_64: + case lldb_xmm5_x86_64: + case lldb_xmm6_x86_64: + case lldb_xmm7_x86_64: + case lldb_xmm8_x86_64: + case lldb_xmm9_x86_64: + case lldb_xmm10_x86_64: + case lldb_xmm11_x86_64: + case lldb_xmm12_x86_64: + case lldb_xmm13_x86_64: + case lldb_xmm14_x86_64: + case lldb_xmm15_x86_64: + reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], + reg_info->byte_size, endian::InlHostByteOrder()); + break; + case lldb_dr0_x86_64: + case lldb_dr1_x86_64: + case lldb_dr2_x86_64: + case lldb_dr3_x86_64: + case lldb_dr4_x86_64: + case lldb_dr5_x86_64: + case lldb_dr6_x86_64: + case lldb_dr7_x86_64: + reg_value = (uint64_t)m_dbr_x86_64.dr[reg - lldb_dr0_x86_64]; + break; } return error; @@ -400,6 +556,87 @@ Error NativeRegisterContextNetBSD_x86_64 case lldb_es_x86_64: m_gpr_x86_64.regs[_REG_ES] = reg_value.GetAsUInt64(); break; + case lldb_fctrl_x86_64: + m_fpr_x86_64.fxstate.fx_cw = reg_value.GetAsUInt16(); + break; + case lldb_fstat_x86_64: + m_fpr_x86_64.fxstate.fx_sw = reg_value.GetAsUInt16(); + break; + case lldb_ftag_x86_64: + m_fpr_x86_64.fxstate.fx_tw = reg_value.GetAsUInt8(); + break; + case lldb_fop_x86_64: + m_fpr_x86_64.fxstate.fx_opcode = reg_value.GetAsUInt16(); + break; + case lldb_fiseg_x86_64: + m_fpr_x86_64.fxstate.fx_ip.fa_64 = reg_value.GetAsUInt64(); + break; + case lldb_fioff_x86_64: + m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off = reg_value.GetAsUInt32(); + break; + case lldb_foseg_x86_64: + m_fpr_x86_64.fxstate.fx_dp.fa_64 = reg_value.GetAsUInt64(); + break; + case lldb_fooff_x86_64: + m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off = reg_value.GetAsUInt32(); + break; + case lldb_mxcsr_x86_64: + m_fpr_x86_64.fxstate.fx_mxcsr = reg_value.GetAsUInt32(); + break; + case lldb_mxcsrmask_x86_64: + m_fpr_x86_64.fxstate.fx_mxcsr_mask = reg_value.GetAsUInt32(); + break; + case lldb_st0_x86_64: + case lldb_st1_x86_64: + case lldb_st2_x86_64: + case lldb_st3_x86_64: + case lldb_st4_x86_64: + case lldb_st5_x86_64: + case lldb_st6_x86_64: + case lldb_st7_x86_64: + ::memcpy(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64], + reg_value.GetBytes(), reg_value.GetByteSize()); + break; + case lldb_mm0_x86_64: + case lldb_mm1_x86_64: + case lldb_mm2_x86_64: + case lldb_mm3_x86_64: + case lldb_mm4_x86_64: + case lldb_mm5_x86_64: + case lldb_mm6_x86_64: + case lldb_mm7_x86_64: + ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64], + reg_value.GetBytes(), reg_value.GetByteSize()); + break; + case lldb_xmm0_x86_64: + case lldb_xmm1_x86_64: + case lldb_xmm2_x86_64: + case lldb_xmm3_x86_64: + case lldb_xmm4_x86_64: + case lldb_xmm5_x86_64: + case lldb_xmm6_x86_64: + case lldb_xmm7_x86_64: + case lldb_xmm8_x86_64: + case lldb_xmm9_x86_64: + case lldb_xmm10_x86_64: + case lldb_xmm11_x86_64: + case lldb_xmm12_x86_64: + case lldb_xmm13_x86_64: + case lldb_xmm14_x86_64: + case lldb_xmm15_x86_64: + ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], + reg_value.GetBytes(), reg_value.GetByteSize()); + break; + case lldb_dr0_x86_64: + case lldb_dr1_x86_64: + case lldb_dr2_x86_64: + case lldb_dr3_x86_64: + case lldb_dr4_x86_64: + case lldb_dr5_x86_64: + case lldb_dr6_x86_64: + case lldb_dr7_x86_64: + m_dbr_x86_64.dr[reg - lldb_dr0_x86_64] = reg_value.GetAsUInt64(); + break; } if (WriteRegisterSet(set) != 0) @@ -480,4 +717,223 @@ Error NativeRegisterContextNetBSD_x86_64 return error; } +Error NativeRegisterContextNetBSD_x86_64::IsWatchpointHit(uint32_t wp_index, + bool &is_hit) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); + + RegisterValue reg_value; + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr6_x86_64); + Error error = ReadRegister(reg_info, reg_value); + if (error.Fail()) { + is_hit = false; + return error; + } + + uint64_t status_bits = reg_value.GetAsUInt64(); + + is_hit = status_bits & (1 << wp_index); + + return error; +} + +Error NativeRegisterContextNetBSD_x86_64::GetWatchpointHitIndex( + uint32_t &wp_index, lldb::addr_t trap_addr) { + uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); + for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { + bool is_hit; + Error error = IsWatchpointHit(wp_index, is_hit); + if (error.Fail()) { + wp_index = LLDB_INVALID_INDEX32; + return error; + } else if (is_hit) { + return error; + } + } + wp_index = LLDB_INVALID_INDEX32; + return Error(); +} + +Error NativeRegisterContextNetBSD_x86_64::IsWatchpointVacant(uint32_t wp_index, + bool &is_vacant) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); + + RegisterValue reg_value; + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr7_x86_64); + Error error = ReadRegister(reg_info, reg_value); + if (error.Fail()) { + is_vacant = false; + return error; + } + + uint64_t control_bits = reg_value.GetAsUInt64(); + + is_vacant = !(control_bits & (1 << (2 * wp_index))); + + return error; +} + +Error NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex( + lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) { + + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); + + // Read only watchpoints aren't supported on x86_64. Fall back to read/write + // waitchpoints instead. + // TODO: Add logic to detect when a write happens and ignore that watchpoint + // hit. + if (watch_flags == 0x2) + watch_flags = 0x3; + + if (watch_flags != 0x1 && watch_flags != 0x3) + return Error("Invalid read/write bits for watchpoint"); + + if (size != 1 && size != 2 && size != 4 && size != 8) + return Error("Invalid size for watchpoint"); + + bool is_vacant; + Error error = IsWatchpointVacant(wp_index, is_vacant); + if (error.Fail()) + return error; + if (!is_vacant) + return Error("Watchpoint index not vacant"); + + RegisterValue reg_value; + const RegisterInfo *const reg_info_dr7 = + GetRegisterInfoAtIndex(lldb_dr7_x86_64); + error = ReadRegister(reg_info_dr7, reg_value); + if (error.Fail()) + return error; + + // for watchpoints 0, 1, 2, or 3, respectively, + // set bits 1, 3, 5, or 7 + uint64_t enable_bit = 1 << (2 * wp_index); + + // set bits 16-17, 20-21, 24-25, or 28-29 + // with 0b01 for write, and 0b11 for read/write + uint64_t rw_bits = watch_flags << (16 + 4 * wp_index); + + // set bits 18-19, 22-23, 26-27, or 30-31 + // with 0b00, 0b01, 0b10, or 0b11 + // for 1, 2, 8 (if supported), or 4 bytes, respectively + uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index); + + uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); + + uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; + + control_bits |= enable_bit | rw_bits | size_bits; + + const RegisterInfo *const reg_info_drN = + GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index); + error = WriteRegister(reg_info_drN, RegisterValue(addr)); + if (error.Fail()) + return error; + + error = WriteRegister(reg_info_dr7, RegisterValue(control_bits)); + if (error.Fail()) + return error; + + error.Clear(); + return error; +} + +bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint( + uint32_t wp_index) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return false; + + RegisterValue reg_value; + + // for watchpoints 0, 1, 2, or 3, respectively, + // clear bits 0, 1, 2, or 3 of the debug status register (DR6) + const RegisterInfo *const reg_info_dr6 = + GetRegisterInfoAtIndex(lldb_dr6_x86_64); + Error error = ReadRegister(reg_info_dr6, reg_value); + if (error.Fail()) + return false; + uint64_t bit_mask = 1 << wp_index; + uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; + error = WriteRegister(reg_info_dr6, RegisterValue(status_bits)); + if (error.Fail()) + return false; + + // for watchpoints 0, 1, 2, or 3, respectively, + // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} + // of the debug control register (DR7) + const RegisterInfo *const reg_info_dr7 = + GetRegisterInfoAtIndex(lldb_dr7_x86_64); + error = ReadRegister(reg_info_dr7, reg_value); + if (error.Fail()) + return false; + bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); + uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; + return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success(); +} + +Error NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() { + RegisterValue reg_value; + + // clear bits {0-4} of the debug status register (DR6) + const RegisterInfo *const reg_info_dr6 = + GetRegisterInfoAtIndex(lldb_dr6_x86_64); + Error error = ReadRegister(reg_info_dr6, reg_value); + if (error.Fail()) + return error; + uint64_t bit_mask = 0xF; + uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; + error = WriteRegister(reg_info_dr6, RegisterValue(status_bits)); + if (error.Fail()) + return error; + + // clear bits {0-7,16-31} of the debug control register (DR7) + const RegisterInfo *const reg_info_dr7 = + GetRegisterInfoAtIndex(lldb_dr7_x86_64); + error = ReadRegister(reg_info_dr7, reg_value); + if (error.Fail()) + return error; + bit_mask = 0xFF | (0xFFFF << 16); + uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; + return WriteRegister(reg_info_dr7, RegisterValue(control_bits)); +} + +uint32_t NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpoint( + lldb::addr_t addr, size_t size, uint32_t watch_flags) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) { + bool is_vacant; + Error error = IsWatchpointVacant(wp_index, is_vacant); + if (is_vacant) { + error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index); + if (error.Success()) + return wp_index; + } + if (error.Fail() && log) { + log->Printf("NativeRegisterContextNetBSD_x86_64::%s Error: %s", + __FUNCTION__, error.AsCString()); + } + } + return LLDB_INVALID_INDEX32; +} + +lldb::addr_t +NativeRegisterContextNetBSD_x86_64::GetWatchpointAddress(uint32_t wp_index) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return LLDB_INVALID_ADDRESS; + RegisterValue reg_value; + const RegisterInfo *const reg_info_drN = + GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index); + if (ReadRegister(reg_info_drN, reg_value).Fail()) + return LLDB_INVALID_ADDRESS; + return reg_value.GetAsUInt64(); +} + +uint32_t NativeRegisterContextNetBSD_x86_64::NumSupportedHardwareWatchpoints() { + // Available debug address registers: dr0, dr1, dr2, dr3 + return 4; +} + #endif // defined(__x86_64__) Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h?rev=300548&r1=300547&r2=300548&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h (original) +++ lldb/trunk/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h Tue Apr 18 07:53:35 2017 @@ -46,17 +46,40 @@ public: Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + Error IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; + + Error GetWatchpointHitIndex(uint32_t &wp_index, + lldb::addr_t trap_addr) override; + + Error IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; + + bool ClearHardwareWatchpoint(uint32_t wp_index) override; + + Error ClearAllHardwareWatchpoints() override; + + Error SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, + uint32_t watch_flags, uint32_t wp_index); + + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags) override; + + lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; + + uint32_t NumSupportedHardwareWatchpoints() override; + protected: void *GetGPRBuffer() override { return &m_gpr_x86_64; } void *GetFPRBuffer() override { return &m_fpr_x86_64; } + void *GetDBRBuffer() override { return &m_dbr_x86_64; } private: // Private member types. - enum { GPRegSet, FPRegSet }; + enum { GPRegSet, FPRegSet, DBRegSet }; // Private member variables. struct reg m_gpr_x86_64; struct fpreg m_fpr_x86_64; + struct dbreg m_dbr_x86_64; int GetSetForNativeRegNum(int reg_num) const; Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp?rev=300548&r1=300547&r2=300548&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp (original) +++ lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp Tue Apr 18 07:53:35 2017 @@ -16,6 +16,9 @@ #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/State.h" +#include "lldb/Utility/LLDBAssert.h" + +#include <sstream> using namespace lldb; using namespace lldb_private; @@ -68,6 +71,23 @@ void NativeThreadNetBSD::SetStoppedByExe m_stop_info.details.signal.signo = SIGTRAP; } +void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) { + SetStopped(); + + lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); + + std::ostringstream ostr; + ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " "; + ostr << wp_index; + + ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index); + + m_stop_description = ostr.str(); + + m_stop_info.reason = StopReason::eStopReasonWatchpoint; + m_stop_info.details.signal.signo = SIGTRAP; +} + void NativeThreadNetBSD::SetStopped() { const StateType new_state = StateType::eStateStopped; m_state = new_state; @@ -142,18 +162,61 @@ NativeRegisterContextSP NativeThreadNetB Error NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) { - return Error("Unimplemented"); + if (!hardware) + return Error("not implemented"); + if (m_state == eStateLaunching) + return Error(); + Error error = RemoveWatchpoint(addr); + if (error.Fail()) + return error; + NativeRegisterContextSP reg_ctx = GetRegisterContext(); + uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags); + if (wp_index == LLDB_INVALID_INDEX32) + return Error("Setting hardware watchpoint failed."); + m_watchpoint_index_map.insert({addr, wp_index}); + return Error(); } Error NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) { - return Error("Unimplemented"); + auto wp = m_watchpoint_index_map.find(addr); + if (wp == m_watchpoint_index_map.end()) + return Error(); + uint32_t wp_index = wp->second; + m_watchpoint_index_map.erase(wp); + if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index)) + return Error(); + return Error("Clearing hardware watchpoint failed."); } Error NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) { - return Error("Unimplemented"); + if (m_state == eStateLaunching) + return Error(); + + Error error = RemoveHardwareBreakpoint(addr); + if (error.Fail()) + return error; + + NativeRegisterContextSP reg_ctx = GetRegisterContext(); + uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size); + + if (bp_index == LLDB_INVALID_INDEX32) + return Error("Setting hardware breakpoint failed."); + + m_hw_break_index_map.insert({addr, bp_index}); + return Error(); } Error NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) { - return Error("Unimplemented"); + auto bp = m_hw_break_index_map.find(addr); + if (bp == m_hw_break_index_map.end()) + return Error(); + + uint32_t bp_index = bp->second; + if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) { + m_hw_break_index_map.erase(bp); + return Error(); + } + + return Error("Clearing hardware breakpoint failed."); } Modified: lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h?rev=300548&r1=300547&r2=300548&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h (original) +++ lldb/trunk/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h Tue Apr 18 07:53:35 2017 @@ -12,6 +12,9 @@ #include "lldb/Host/common/NativeThreadProtocol.h" +#include <map> +#include <string> + namespace lldb_private { namespace process_netbsd { @@ -53,6 +56,7 @@ private: void SetStoppedByBreakpoint(); void SetStoppedByTrace(); void SetStoppedByExec(); + void SetStoppedByWatchpoint(uint32_t wp_index); void SetStopped(); void SetRunning(); void SetStepping(); @@ -64,6 +68,9 @@ private: ThreadStopInfo m_stop_info; NativeRegisterContextSP m_reg_context_sp; std::string m_stop_description; + using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>; + WatchpointIndexMap m_watchpoint_index_map; + WatchpointIndexMap m_hw_break_index_map; }; typedef std::shared_ptr<NativeThreadNetBSD> NativeThreadNetBSDSP; Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_x86_64.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_x86_64.h?rev=300548&r1=300547&r2=300548&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_x86_64.h (original) +++ lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_x86_64.h Tue Apr 18 07:53:35 2017 @@ -148,7 +148,7 @@ DR_OFFSET(i), eEncodingUint, eFormatHex, \ {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM }, \ + lldb_##reg##i##_x86_64 }, \ nullptr, nullptr, nullptr, 0 \ } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits