Don't use AVX/XSTATE API on Windows.

CopyContext is necessary to safely get the XState, but LLDB doesn't currently
use the XState. CopyContext is available as of Windows 7 SP1, so it can't be
used on Vista.  Furthermore, it requires the Windows 8 SDK it compile,
making the baseline for compiling and running LLDB higher than necessary.

Patch by: Adrian McCarthy
Reviewed by: Zachary Turner
Differential Revision: http://reviews.llvm.org/D7572

llvm-svn: 229710
This commit is contained in:
Zachary Turner 2015-02-18 18:04:50 +00:00
parent 1d29c08095
commit 39cc7d4437
3 changed files with 34 additions and 70 deletions

View File

@ -19,8 +19,6 @@
#undef GetUserName #undef GetUserName
#undef LoadImage #undef LoadImage
#undef CreateProcess #undef CreateProcess
#undef LoadImage
#undef GetUserName
#undef far #undef far
#undef near #undef near
#undef FAR #undef FAR

View File

@ -94,7 +94,7 @@ RegisterSet g_register_sets[] = {
RegisterContextWindows_x86::RegisterContextWindows_x86(Thread &thread, uint32_t concrete_frame_idx) RegisterContextWindows_x86::RegisterContextWindows_x86(Thread &thread, uint32_t concrete_frame_idx)
: RegisterContext(thread, concrete_frame_idx) : RegisterContext(thread, concrete_frame_idx)
, m_context_stale(true) , m_context_stale(true)
, m_context_ptr(nullptr) , m_context()
{ {
} }
@ -141,34 +141,34 @@ RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info, RegisterV
switch (reg_info->kinds[eRegisterKindLLDB]) switch (reg_info->kinds[eRegisterKindLLDB])
{ {
case lldb_eax_i386: case lldb_eax_i386:
reg_value.SetUInt32(m_context_ptr->Eax); reg_value.SetUInt32(m_context.Eax);
break; break;
case lldb_ebx_i386: case lldb_ebx_i386:
reg_value.SetUInt32(m_context_ptr->Ebx); reg_value.SetUInt32(m_context.Ebx);
break; break;
case lldb_ecx_i386: case lldb_ecx_i386:
reg_value.SetUInt32(m_context_ptr->Ecx); reg_value.SetUInt32(m_context.Ecx);
break; break;
case lldb_edx_i386: case lldb_edx_i386:
reg_value.SetUInt32(m_context_ptr->Edx); reg_value.SetUInt32(m_context.Edx);
break; break;
case lldb_edi_i386: case lldb_edi_i386:
reg_value.SetUInt32(m_context_ptr->Edi); reg_value.SetUInt32(m_context.Edi);
break; break;
case lldb_esi_i386: case lldb_esi_i386:
reg_value.SetUInt32(m_context_ptr->Esi); reg_value.SetUInt32(m_context.Esi);
break; break;
case lldb_ebp_i386: case lldb_ebp_i386:
reg_value.SetUInt32(m_context_ptr->Ebp); reg_value.SetUInt32(m_context.Ebp);
break; break;
case lldb_esp_i386: case lldb_esp_i386:
reg_value.SetUInt32(m_context_ptr->Esp); reg_value.SetUInt32(m_context.Esp);
break; break;
case lldb_eip_i386: case lldb_eip_i386:
reg_value.SetUInt32(m_context_ptr->Eip); reg_value.SetUInt32(m_context.Eip);
break; break;
case lldb_eflags_i386: case lldb_eflags_i386:
reg_value.SetUInt32(m_context_ptr->EFlags); reg_value.SetUInt32(m_context.EFlags);
break; break;
} }
return true; return true;
@ -186,40 +186,40 @@ RegisterContextWindows_x86::WriteRegister(const RegisterInfo *reg_info, const Re
switch (reg_info->kinds[eRegisterKindLLDB]) switch (reg_info->kinds[eRegisterKindLLDB])
{ {
case lldb_eax_i386: case lldb_eax_i386:
m_context_ptr->Eax = reg_value.GetAsUInt32(); m_context.Eax = reg_value.GetAsUInt32();
break; break;
case lldb_ebx_i386: case lldb_ebx_i386:
m_context_ptr->Ebx = reg_value.GetAsUInt32(); m_context.Ebx = reg_value.GetAsUInt32();
break; break;
case lldb_ecx_i386: case lldb_ecx_i386:
m_context_ptr->Ecx = reg_value.GetAsUInt32(); m_context.Ecx = reg_value.GetAsUInt32();
break; break;
case lldb_edx_i386: case lldb_edx_i386:
m_context_ptr->Edx = reg_value.GetAsUInt32(); m_context.Edx = reg_value.GetAsUInt32();
break; break;
case lldb_edi_i386: case lldb_edi_i386:
m_context_ptr->Edi = reg_value.GetAsUInt32(); m_context.Edi = reg_value.GetAsUInt32();
break; break;
case lldb_esi_i386: case lldb_esi_i386:
m_context_ptr->Esi = reg_value.GetAsUInt32(); m_context.Esi = reg_value.GetAsUInt32();
break; break;
case lldb_ebp_i386: case lldb_ebp_i386:
m_context_ptr->Ebp = reg_value.GetAsUInt32(); m_context.Ebp = reg_value.GetAsUInt32();
break; break;
case lldb_esp_i386: case lldb_esp_i386:
m_context_ptr->Esp = reg_value.GetAsUInt32(); m_context.Esp = reg_value.GetAsUInt32();
break; break;
case lldb_eip_i386: case lldb_eip_i386:
m_context_ptr->Eip = reg_value.GetAsUInt32(); m_context.Eip = reg_value.GetAsUInt32();
break; break;
case lldb_eflags_i386: case lldb_eflags_i386:
m_context_ptr->EFlags = reg_value.GetAsUInt32(); m_context.EFlags = reg_value.GetAsUInt32();
break; break;
} }
// Physically update the registers in the target process. // Physically update the registers in the target process.
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), m_context_ptr); return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);
} }
bool bool
@ -227,32 +227,22 @@ RegisterContextWindows_x86::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
{ {
if (!CacheAllRegisterValues()) if (!CacheAllRegisterValues())
return false; return false;
if (data_sp->GetByteSize() < sizeof(m_context))
CONTEXT *dest_context = nullptr; {
if (!InitializeContextDataBuffer(data_sp, &dest_context)) data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0));
return false; }
memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context));
// Write the OS's internal CONTEXT structure into the buffer.
if (!CopyContext(dest_context, kWinContextFlags, m_context_ptr))
return false;
return true; return true;
} }
bool bool
RegisterContextWindows_x86::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) RegisterContextWindows_x86::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
{ {
// data_sp could only ever have been generated by a call to ReadAllRegisterValues(), so assert(data_sp->GetByteSize() >= sizeof(m_context));
// m_cached_context should already have the correct size and alignment properties. memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context));
assert(m_cached_context->GetByteSize() == data_sp->GetByteSize());
// As a result, we can simply memcpy the entire buffer and assume that the alignment remains
// the same.
memcpy(m_cached_context->GetBytes(), data_sp->GetBytes(), data_sp->GetByteSize());
// m_context_ptr still points to the beginning of the CONTEXT structure, so use that for
// updating the thread state.
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
if (!::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), m_context_ptr)) if (!::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context))
return false; return false;
return true; return true;
@ -322,33 +312,16 @@ RegisterContextWindows_x86::HardwareSingleStep(bool enable)
return false; return false;
} }
bool
RegisterContextWindows_x86::InitializeContextDataBuffer(DataBufferSP &buffer, CONTEXT **context_ptr)
{
DWORD length = 0;
if (!::InitializeContext(nullptr, kWinContextFlags, nullptr, &length) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return false;
buffer.reset(new DataBufferHeap(length, 0));
if (!::InitializeContext(buffer->GetBytes(), kWinContextFlags, context_ptr, &length))
{
buffer.reset();
return false;
}
return true;
}
bool bool
RegisterContextWindows_x86::CacheAllRegisterValues() RegisterContextWindows_x86::CacheAllRegisterValues()
{ {
if (!m_context_stale) if (!m_context_stale)
return true; return true;
if (!m_cached_context && !InitializeContextDataBuffer(m_cached_context, &m_context_ptr))
return false;
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
if (!::GetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), m_context_ptr)) memset(&m_context, 0, sizeof(m_context));
m_context.ContextFlags = kWinContextFlags;
if (!::GetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context))
return false; return false;
m_context_stale = false; m_context_stale = false;
return true; return true;

View File

@ -69,16 +69,9 @@ class RegisterContextWindows_x86 : public lldb_private::RegisterContext
bool HardwareSingleStep(bool enable) override; bool HardwareSingleStep(bool enable) override;
private: private:
bool InitializeContextDataBuffer(lldb::DataBufferSP &buffer, CONTEXT **context_ptr);
bool CacheAllRegisterValues(); bool CacheAllRegisterValues();
// The system CONTEXT structure. m_context_ptr is backed by m_cached_context, but CONTEXT m_context;
// m_context_ptr may not point to the beginning of the buffer allocated in m_cached_context,
// due to alignment requirements of CONTEXT structures.
lldb::DataBufferSP m_cached_context;
CONTEXT *m_context_ptr;
bool m_context_stale; bool m_context_stale;
}; };
} }