[Lldb-commits] [lldb] r300548 - Introduce FPR and Debug Registers/NetBSD/amd64 support
Kamil Rytarowski via lldb-commits
lldb-commits at lists.llvm.org
Tue Apr 18 05:53:36 PDT 2017
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 \
}
More information about the lldb-commits
mailing list