Add a call to "sync" a thread state before checkpointing registers in preparation for
calling functions. This is necessary on Mac OS X, since bad things can happen if you set
the registers of a thread that's sitting in a kernel trap.
<rdar://problem/11145013>
llvm-svn: 160756
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index b4263d1..8225e69 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -51,6 +51,7 @@
m_supports_watchpoint_support_info (eLazyBoolCalculate),
m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
m_attach_or_wait_reply(eLazyBoolCalculate),
+ m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
m_supports_qProcessInfoPID (true),
m_supports_qfProcessInfo (true),
m_supports_qUserName (true),
@@ -154,6 +155,26 @@
return false;
}
+bool
+GDBRemoteCommunicationClient::GetSyncThreadStateSupported ()
+{
+ if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate)
+ {
+ m_prepare_for_reg_writing_reply = eLazyBoolNo;
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response, false))
+ {
+ if (response.IsOKResponse())
+ m_prepare_for_reg_writing_reply = eLazyBoolYes;
+ }
+ }
+ if (m_prepare_for_reg_writing_reply == eLazyBoolYes)
+ return true;
+ else
+ return false;
+}
+
void
GDBRemoteCommunicationClient::ResetDiscoverableSettings()
@@ -168,6 +189,8 @@
m_qHostInfo_is_valid = eLazyBoolCalculate;
m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
m_supports_memory_region_info = eLazyBoolCalculate;
+ m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
+ m_attach_or_wait_reply = eLazyBoolCalculate;
m_supports_qProcessInfoPID = true;
m_supports_qfProcessInfo = true;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index eee3aa5..adfec5b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -224,6 +224,9 @@
bool
GetVAttachOrWaitSupported ();
+ bool
+ GetSyncThreadStateSupported();
+
void
ResetDiscoverableSettings();
@@ -369,6 +372,7 @@
lldb_private::LazyBool m_supports_watchpoint_support_info;
lldb_private::LazyBool m_watchpoints_trigger_after_instruction;
lldb_private::LazyBool m_attach_or_wait_reply;
+ lldb_private::LazyBool m_prepare_for_reg_writing_reply;
bool
m_supports_qProcessInfoPID:1,
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 4247add..a1cac21 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -286,7 +286,6 @@
return true;
}
-
bool
GDBRemoteRegisterContext::WriteRegister (const RegisterInfo *reg_info,
const RegisterValue &value)
@@ -326,6 +325,29 @@
}
return false;
}
+
+void
+GDBRemoteRegisterContext::SyncThreadState(Process *process)
+{
+ // NB. We assume our caller has locked the sequence mutex.
+
+ GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *) process)->GetGDBRemote());
+ if (!gdb_comm.GetSyncThreadStateSupported())
+ return;
+
+ StreamString packet;
+ StringExtractorGDBRemote response;
+ packet.Printf ("QSyncThreadState:%4.4llx;", m_thread.GetID());
+ if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
+ packet.GetString().size(),
+ response,
+ false))
+ {
+ if (response.IsOKResponse())
+ InvalidateAllRegisters();
+ }
+}
+
bool
GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo *reg_info, DataExtractor &data, uint32_t data_offset)
{
@@ -479,6 +501,8 @@
Mutex::Locker locker;
if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for read all registers."))
{
+ SyncThreadState(process);
+
char packet[32];
const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
ProcessSP process_sp (m_thread.GetProcess());
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index e39815a..e314176 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -243,6 +243,9 @@
void
SetAllRegisterValid (bool b);
+ void
+ SyncThreadState(lldb_private::Process *process); // Assumes the sequence mutex has already been acquired.
+
GDBRemoteDynamicRegisterInfo &m_reg_info;
std::vector<bool> m_reg_valid;
lldb_private::DataExtractor m_reg_data;