<rdar://problem/9959501>
More KDP debugging process. We can not set breakpoints, hit them, resume, step and detach while running.
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@164584 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index dea16f2..c5be914 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -28,7 +28,6 @@
#include "ProcessKDP.h"
#include "ProcessKDPLog.h"
#include "ThreadKDP.h"
-#include "StopInfoMachException.h"
using namespace lldb;
using namespace lldb_private;
@@ -102,7 +101,8 @@
Process (target, listener),
m_comm("lldb.process.kdp-remote.communication"),
m_async_broadcaster (NULL, "lldb.process.kdp-remote.async-broadcaster"),
- m_async_thread (LLDB_INVALID_HOST_THREAD)
+ m_async_thread (LLDB_INVALID_HOST_THREAD),
+ m_destroy_in_process (false)
{
m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
@@ -214,6 +214,8 @@
ArchSpec kernel_arch;
kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
m_target.SetArchitecture(kernel_arch);
+ // Set the thread ID
+ UpdateThreadListIfNeeded ();
SetID (1);
GetThreadList ();
SetPrivateState (eStateStopped);
@@ -233,10 +235,16 @@
// }
}
}
+ else
+ {
+ puts ("KDP_CONNECT failed"); // REMOVE THIS
+ error.SetErrorString("KDP_REATTACH failed");
+ }
}
else
{
- error.SetErrorString("KDP reattach failed");
+ puts ("KDP_REATTACH failed"); // REMOVE THIS
+ error.SetErrorString("KDP_REATTACH failed");
}
}
else
@@ -320,42 +328,46 @@
if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread))
StartAsyncThread ();
- const uint32_t num_threads = m_thread_list.GetSize();
- uint32_t resume_cpu_mask = 0;
+ bool resume = false;
- for (uint32_t idx = 0; idx < num_threads; ++idx)
+ // With KDP there is only one thread we can tell what to do
+ ThreadSP kernel_thread_sp (GetKernelThread(m_thread_list, m_thread_list));
+ if (kernel_thread_sp)
{
- ThreadSP thread_sp (m_thread_list.GetThreadAtIndex(idx));
- const StateType thread_resume_state = thread_sp->GetState();
+ const StateType thread_resume_state = kernel_thread_sp->GetTemporaryResumeState();
switch (thread_resume_state)
{
- case eStateStopped:
case eStateSuspended:
// Nothing to do here when a thread will stay suspended
// we just leave the CPU mask bit set to zero for the thread
+ puts("REMOVE THIS: ProcessKDP::DoResume () -- thread suspended");
break;
case eStateStepping:
+ puts("REMOVE THIS: ProcessKDP::DoResume () -- thread stepping");
+ kernel_thread_sp->GetRegisterContext()->HardwareSingleStep (true);
+ resume = true;
+ break;
+
case eStateRunning:
- thread_sp->GetRegisterContext()->HardwareSingleStep (thread_resume_state == eStateStepping);
- // Thread ID is the bit we need for the CPU mask
- resume_cpu_mask |= thread_sp->GetID();
+ puts("REMOVE THIS: ProcessKDP::DoResume () -- thread running");
+ kernel_thread_sp->GetRegisterContext()->HardwareSingleStep (false);
+ resume = true;
break;
-
- break;
-
+
default:
+ // The only valid thread resume states are listed above
assert (!"invalid thread resume state");
break;
}
}
- if (log)
- log->Printf ("ProcessKDP::DoResume () sending resume with cpu_mask = 0x%8.8x",
- resume_cpu_mask);
- if (resume_cpu_mask)
+
+ if (resume)
{
+ if (log)
+ log->Printf ("ProcessKDP::DoResume () sending resume");
- if (m_comm.SendRequestResume (resume_cpu_mask))
+ if (m_comm.SendRequestResume ())
{
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue);
SetPrivateState(eStateRunning);
@@ -365,12 +377,30 @@
}
else
{
- error.SetErrorString ("all threads suspended");
+ error.SetErrorString ("kernel thread is suspended");
}
return error;
}
+lldb::ThreadSP
+ProcessKDP::GetKernelThread(ThreadList &old_thread_list, ThreadList &new_thread_list)
+{
+ // KDP only tells us about one thread/core. Any other threads will usually
+ // be the ones that are read from memory by the OS plug-ins.
+ const lldb::tid_t kernel_tid = 1;
+ ThreadSP thread_sp (old_thread_list.FindThreadByID (kernel_tid, false));
+ if (!thread_sp)
+ {
+ thread_sp.reset(new ThreadKDP (shared_from_this(), kernel_tid));
+ new_thread_list.AddThread(thread_sp);
+ }
+ return thread_sp;
+}
+
+
+
+
bool
ProcessKDP::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
{
@@ -379,20 +409,10 @@
if (log && log->GetMask().Test(KDP_LOG_VERBOSE))
log->Printf ("ProcessKDP::%s (pid = %llu)", __FUNCTION__, GetID());
- // We currently are making only one thread per core and we
- // actually don't know about actual threads. Eventually we
- // want to get the thread list from memory and note which
- // threads are on CPU as those are the only ones that we
- // will be able to resume.
- const uint32_t cpu_mask = m_comm.GetCPUMask();
- for (uint32_t cpu_mask_bit = 1; cpu_mask_bit & cpu_mask; cpu_mask_bit <<= 1)
- {
- lldb::tid_t tid = cpu_mask_bit;
- ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
- if (!thread_sp)
- thread_sp.reset(new ThreadKDP (shared_from_this(), tid));
- new_thread_list.AddThread(thread_sp);
- }
+ // Even though there is a CPU mask, it doesn't mean to can see each CPU
+ // indivudually, there is really only one. Lets call this thread 1.
+ GetKernelThread (old_thread_list, new_thread_list);
+
return new_thread_list.GetSize(false) > 0;
}
@@ -409,112 +429,24 @@
{
Error error;
-// bool timed_out = false;
- Mutex::Locker locker;
-
- if (m_public_state.GetValue() == eStateAttaching)
+ if (m_comm.IsRunning())
{
- // We are being asked to halt during an attach. We need to just close
- // our file handle and debugserver will go away, and we can be done...
- m_comm.Disconnect();
- }
- else
- {
- if (!m_comm.SendRequestSuspend ())
- error.SetErrorString ("KDP halt failed");
- }
- return error;
-}
-
-Error
-ProcessKDP::InterruptIfRunning (bool discard_thread_plans,
- bool catch_stop_event,
- EventSP &stop_event_sp)
-{
- Error error;
-
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
-
- bool paused_private_state_thread = false;
- const bool is_running = m_comm.IsRunning();
- if (log)
- log->Printf ("ProcessKDP::InterruptIfRunning(discard_thread_plans=%i, catch_stop_event=%i) is_running=%i",
- discard_thread_plans,
- catch_stop_event,
- is_running);
-
- if (discard_thread_plans)
- {
- if (log)
- log->Printf ("ProcessKDP::InterruptIfRunning() discarding all thread plans");
- m_thread_list.DiscardThreadPlans();
- }
- if (is_running)
- {
- if (catch_stop_event)
+ if (m_destroy_in_process)
{
- if (log)
- log->Printf ("ProcessKDP::InterruptIfRunning() pausing private state thread");
- PausePrivateStateThread();
- paused_private_state_thread = true;
+ // If we are attemping to destroy, we need to not return an error to
+ // Halt or DoDestroy won't get called.
+ // We are also currently running, so send a process stopped event
+ SetPrivateState (eStateStopped);
}
-
- bool timed_out = false;
-// bool sent_interrupt = false;
- Mutex::Locker locker;
-
- // TODO: implement halt in CommunicationKDP
-// if (!m_comm.SendInterrupt (locker, 1, sent_interrupt, timed_out))
-// {
-// if (timed_out)
-// error.SetErrorString("timed out sending interrupt packet");
-// else
-// error.SetErrorString("unknown error sending interrupt packet");
-// if (paused_private_state_thread)
-// ResumePrivateStateThread();
-// return error;
-// }
-
- if (catch_stop_event)
+ else
{
- // LISTEN HERE
- TimeValue timeout_time;
- timeout_time = TimeValue::Now();
- timeout_time.OffsetWithSeconds(5);
- StateType state = WaitForStateChangedEventsPrivate (&timeout_time, stop_event_sp);
-
- timed_out = state == eStateInvalid;
- if (log)
- log->Printf ("ProcessKDP::InterruptIfRunning() catch stop event: state = %s, timed-out=%i", StateAsCString(state), timed_out);
-
- if (timed_out)
- error.SetErrorString("unable to verify target stopped");
- }
-
- if (paused_private_state_thread)
- {
- if (log)
- log->Printf ("ProcessKDP::InterruptIfRunning() resuming private state thread");
- ResumePrivateStateThread();
+ error.SetErrorString ("KDP cannot interrupt a running kernel");
}
}
return error;
}
Error
-ProcessKDP::WillDetach ()
-{
- LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessKDP::WillDetach()");
-
- bool discard_thread_plans = true;
- bool catch_stop_event = true;
- EventSP event_sp;
- return InterruptIfRunning (discard_thread_plans, catch_stop_event, event_sp);
-}
-
-Error
ProcessKDP::DoDetach()
{
Error error;
@@ -522,27 +454,33 @@
if (log)
log->Printf ("ProcessKDP::DoDetach()");
- DisableAllBreakpointSites ();
-
- m_thread_list.DiscardThreadPlans();
-
- if (m_comm.IsConnected())
+ if (m_comm.IsRunning())
{
-
- m_comm.SendRequestDisconnect();
-
- size_t response_size = m_comm.Disconnect ();
- if (log)
+ // We are running and we can't interrupt a running kernel, so we need
+ // to just close the connection to the kernel and hope for the best
+ }
+ else
+ {
+ DisableAllBreakpointSites ();
+
+ m_thread_list.DiscardThreadPlans();
+
+ if (m_comm.IsConnected())
{
- if (response_size)
- log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
- else
- log->PutCString ("ProcessKDP::DoDetach() detach packet send failed");
+
+ m_comm.SendRequestDisconnect();
+
+ size_t response_size = m_comm.Disconnect ();
+ if (log)
+ {
+ if (response_size)
+ log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
+ else
+ log->PutCString ("ProcessKDP::DoDetach() detach packet send failed");
+ }
}
}
- // Sleep for one second to let the process get all detached...
- StopAsyncThread ();
-
+ StopAsyncThread ();
m_comm.Clear();
SetPrivateState (eStateDetached);
@@ -553,6 +491,14 @@
}
Error
+ProcessKDP::WillDestroy ()
+{
+ Error error;
+ m_destroy_in_process = true;
+ return error;
+}
+
+Error
ProcessKDP::DoDestroy ()
{
// For KDP there really is no difference between destroy and detach
@@ -639,10 +585,18 @@
BreakpointSite::Type bp_type = bp_site->GetType();
if (bp_type == BreakpointSite::eExternal)
{
- if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
+ if (m_destroy_in_process && m_comm.IsRunning())
+ {
+ // We are trying to destroy our connection and we are running
bp_site->SetEnabled(false);
+ }
else
- error.SetErrorString ("KDP remove breakpoint failed");
+ {
+ if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
+ bp_site->SetEnabled(false);
+ else
+ error.SetErrorString ("KDP remove breakpoint failed");
+ }
}
else
{
@@ -787,8 +741,12 @@
is_running = true;
if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds (exc_reply_packet, 1 * USEC_PER_SEC))
{
+ ThreadSP thread_sp (process->GetKernelThread(process->GetThreadList(), process->GetThreadList()));
+ thread_sp->GetRegisterContext()->InvalidateAllRegisters();
+ static_cast<ThreadKDP *>(thread_sp.get())->SetStopInfoFrom_KDP_EXCEPTION (exc_reply_packet);
+
// TODO: parse the stop reply packet
- is_running = false;
+ is_running = false;
process->SetPrivateState(eStateStopped);
}
else