Skip to content

Commit

Permalink
Introduce FPR and Debug Registers/NetBSD/amd64 support
Browse files Browse the repository at this point in the history
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

llvm-svn: 300548
  • Loading branch information
krytarowski committed Apr 18, 2017
1 parent 7ad2e8a commit 36e23ec
Show file tree
Hide file tree
Showing 8 changed files with 678 additions and 39 deletions.
117 changes: 86 additions & 31 deletions lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
Expand Up @@ -224,36 +224,83 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
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;
}
}

Expand Down Expand Up @@ -328,8 +375,8 @@ Error NativeProcessNetBSD::FixupBreakpointPCAsNeeded(
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;
Expand Down Expand Up @@ -439,7 +486,7 @@ Error NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
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());
Expand Down Expand Up @@ -540,8 +587,8 @@ Error NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
"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(
Expand All @@ -561,9 +608,8 @@ Error NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
}
// 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);
Expand Down Expand Up @@ -722,8 +768,8 @@ Error NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop,
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;
Expand Down Expand Up @@ -766,6 +812,11 @@ Error NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop,
return error;
}

for (const auto &thread_sp : m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
SIGSTOP);
}

/* Set process stopped */
SetState(StateType::eStateStopped);

Expand Down Expand Up @@ -894,6 +945,11 @@ ::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Error &error) {
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);

Expand Down Expand Up @@ -1007,7 +1063,6 @@ Error NativeProcessNetBSD::ReinitializeThreads() {
// 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;
Expand Down
26 changes: 26 additions & 0 deletions lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
Expand Up @@ -57,6 +57,22 @@ Error NativeRegisterContextNetBSD::WriteFPR() {
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());
Expand All @@ -77,6 +93,16 @@ Error NativeRegisterContextNetBSD::DoWriteFPR(void *buf) {
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());
Expand Down
Expand Up @@ -41,6 +41,9 @@ class NativeRegisterContextNetBSD : public NativeRegisterContextRegisterInfo {
virtual Error ReadFPR();
virtual Error WriteFPR();

virtual Error ReadDBR();
virtual Error WriteDBR();

virtual void *GetGPRBuffer() { return nullptr; }
virtual size_t GetGPRSize() {
return GetRegisterInfoInterface().GetGPRSize();
Expand All @@ -49,12 +52,18 @@ class NativeRegisterContextNetBSD : public NativeRegisterContextRegisterInfo {
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();
};
Expand Down

0 comments on commit 36e23ec

Please sign in to comment.