diff options
Diffstat (limited to 'source/Plugins/Process/POSIX')
34 files changed, 4607 insertions, 3018 deletions
diff --git a/source/Plugins/Process/POSIX/POSIXThread.cpp b/source/Plugins/Process/POSIX/POSIXThread.cpp index 93c296679df2..16399748c544 100644 --- a/source/Plugins/Process/POSIX/POSIXThread.cpp +++ b/source/Plugins/Process/POSIX/POSIXThread.cpp @@ -29,10 +29,12 @@ #include "ProcessPOSIX.h" #include "ProcessPOSIXLog.h" #include "ProcessMonitor.h" -#include "RegisterContext_i386.h" -#include "RegisterContext_x86_64.h" -#include "RegisterContextPOSIX.h" +#include "RegisterContextPOSIXProcessMonitor_mips64.h" +#include "RegisterContextPOSIXProcessMonitor_x86.h" +#include "RegisterContextLinux_i386.h" #include "RegisterContextLinux_x86_64.h" +#include "RegisterContextFreeBSD_i386.h" +#include "RegisterContextFreeBSD_mips64.h" #include "RegisterContextFreeBSD_x86_64.h" #include "UnwindLLDB.h" @@ -46,7 +48,8 @@ POSIXThread::POSIXThread(Process &process, lldb::tid_t tid) m_frame_ap (), m_breakpoint (), m_thread_name_valid (false), - m_thread_name () + m_thread_name (), + m_posix_thread(NULL) { Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) @@ -138,34 +141,66 @@ POSIXThread::GetRegisterContext() { if (!m_reg_context_sp) { - ArchSpec arch = Host::GetArchitecture(); + m_posix_thread = NULL; - switch (arch.GetCore()) + RegisterInfoInterface *reg_interface = NULL; + const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture(); + + switch (target_arch.GetCore()) { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - case ArchSpec::eCore_x86_32_i486sx: - m_reg_context_sp.reset(new RegisterContext_i386(*this, 0)); - break; - - case ArchSpec::eCore_x86_64_x86_64: - switch (arch.GetTriple().getOS()) + case ArchSpec::eCore_mips64: { - case llvm::Triple::FreeBSD: - m_reg_context_sp.reset(new RegisterContextFreeBSD_x86_64(*this, 0)); - break; - case llvm::Triple::Linux: - m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0)); - break; - default: - assert(false && "OS not supported"); - break; + RegisterInfoInterface *reg_interface = NULL; + + switch (target_arch.GetTriple().getOS()) + { + case llvm::Triple::FreeBSD: + reg_interface = new RegisterContextFreeBSD_mips64(target_arch); + break; + default: + assert(false && "OS not supported"); + break; + } + + if (reg_interface) + { + RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface); + m_posix_thread = reg_ctx; + m_reg_context_sp.reset(reg_ctx); + } + break; } - break; + + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + case ArchSpec::eCore_x86_64_x86_64: + { + switch (target_arch.GetTriple().getOS()) + { + case llvm::Triple::FreeBSD: + reg_interface = new RegisterContextFreeBSD_x86_64(target_arch); + break; + case llvm::Triple::Linux: + reg_interface = new RegisterContextLinux_x86_64(target_arch); + break; + default: + assert(false && "OS not supported"); + break; + } + + if (reg_interface) + { + RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface); + m_posix_thread = reg_ctx; + m_reg_context_sp.reset(reg_ctx); + } + break; + } + + default: + assert(false && "CPU type not supported!"); + break; } } return m_reg_context_sp; @@ -195,6 +230,17 @@ POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) return reg_ctx_sp; } +lldb::addr_t +POSIXThread::GetThreadPointer () +{ + ProcessMonitor &monitor = GetMonitor(); + addr_t addr; + if (monitor.ReadThreadPointer (GetID(), addr)) + return addr; + else + return LLDB_INVALID_ADDRESS; +} + bool POSIXThread::CalculateStopInfo() { @@ -314,6 +360,10 @@ POSIXThread::Notify(const ProcessMessage &message) case ProcessMessage::eNewThreadMessage: ThreadNotify(message); break; + + case ProcessMessage::eExecMessage: + ExecNotify(message); + break; } } @@ -328,7 +378,7 @@ POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp) bool wp_read = wp->WatchpointRead(); bool wp_write = wp->WatchpointWrite(); uint32_t wp_hw_index = wp->GetHardwareIndex(); - RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX(); + POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); if (reg_ctx) wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size, wp_read, wp_write, @@ -365,7 +415,7 @@ POSIXThread::FindVacantWatchpointIndex() uint32_t hw_index = LLDB_INVALID_INDEX32; uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); uint32_t wp_idx; - RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX(); + POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); if (reg_ctx) { for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) @@ -387,7 +437,7 @@ POSIXThread::BreakNotify(const ProcessMessage &message) Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); assert(GetRegisterContext()); - status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint(); + status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint(); assert(status && "Breakpoint update failed!"); // With our register state restored, resolve the breakpoint object @@ -399,31 +449,22 @@ POSIXThread::BreakNotify(const ProcessMessage &message) lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, - // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that - // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. - if (bp_site && bp_site->ValidForThisThread(this)) + // we create a stop reason with should_stop=false. If there is no breakpoint location, then report + // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will + // be taken care of when the thread resumes and notices that there's a breakpoint under the pc. + if (bp_site) { lldb::break_id_t bp_id = bp_site->GetID(); - if (GetProcess()->GetThreadList().SetSelectedThreadByID(GetID())) + if (bp_site->ValidForThisThread(this)) SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id)); else - assert(false && "Invalid thread ID during BreakNotify."); - } - else - { - const ThreadSpec *spec = bp_site ? - bp_site->GetOwnerAtIndex(0)->GetOptionsNoCreate()->GetThreadSpecNoCreate() : 0; - - if (spec && spec->TIDMatches(*this)) - assert(false && "BreakpointSite is invalid for the current ThreadSpec."); - else { - if (!m_stop_info_sp) { - StopInfoSP invalid_stop_info_sp; - SetStopInfo (invalid_stop_info_sp); - } + const bool should_stop = false; + SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop)); } } + else + SetStopInfo(StopInfoSP()); } void @@ -436,7 +477,7 @@ POSIXThread::WatchNotify(const ProcessMessage &message) log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8" PRIx64, __FUNCTION__, halt_addr); - RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX(); + POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); if (reg_ctx) { uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); @@ -532,22 +573,26 @@ POSIXThread::GetRegisterIndexFromOffset(unsigned offset) llvm_unreachable("CPU type not supported!"); break; + case ArchSpec::eCore_mips64: case ArchSpec::eCore_x86_32_i386: case ArchSpec::eCore_x86_32_i486: case ArchSpec::eCore_x86_32_i486sx: case ArchSpec::eCore_x86_64_x86_64: { - RegisterContextSP base = GetRegisterContext(); - if (base) { - RegisterContextPOSIX &context = static_cast<RegisterContextPOSIX &>(*base); - reg = context.GetRegisterIndexFromOffset(offset); - } + POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); + reg = reg_ctx->GetRegisterIndexFromOffset(offset); } break; } return reg; } +void +POSIXThread::ExecNotify(const ProcessMessage &message) +{ + SetStopInfo (StopInfo::CreateStopReasonWithExec(*this)); +} + const char * POSIXThread::GetRegisterName(unsigned reg) { @@ -560,6 +605,7 @@ POSIXThread::GetRegisterName(unsigned reg) assert(false && "CPU type not supported!"); break; + case ArchSpec::eCore_mips64: case ArchSpec::eCore_x86_32_i386: case ArchSpec::eCore_x86_32_i486: case ArchSpec::eCore_x86_32_i486sx: diff --git a/source/Plugins/Process/POSIX/POSIXThread.h b/source/Plugins/Process/POSIX/POSIXThread.h index d051d23860df..51d6645f209d 100644 --- a/source/Plugins/Process/POSIX/POSIXThread.h +++ b/source/Plugins/Process/POSIX/POSIXThread.h @@ -21,7 +21,7 @@ class ProcessMessage; class ProcessMonitor; -class RegisterContextPOSIX; +class POSIXBreakpointProtocol; //------------------------------------------------------------------------------ // @class POSIXThread @@ -59,6 +59,9 @@ public: virtual lldb::RegisterContextSP CreateRegisterContextForFrame (lldb_private::StackFrame *frame); + virtual lldb::addr_t + GetThreadPointer (); + //-------------------------------------------------------------------------- // These functions provide a mapping from the register offset // back to the register index or name for use in debugging or log @@ -92,15 +95,12 @@ public: uint32_t FindVacantWatchpointIndex(); protected: - RegisterContextPOSIX * - GetRegisterContextPOSIX () + POSIXBreakpointProtocol * + GetPOSIXBreakpointProtocol () { if (!m_reg_context_sp) m_reg_context_sp = GetRegisterContext(); -#if 0 - return dynamic_cast<RegisterContextPOSIX*>(m_reg_context_sp.get()); -#endif - return (RegisterContextPOSIX *)m_reg_context_sp.get(); + return m_posix_thread; } std::unique_ptr<lldb_private::StackFrame> m_frame_ap; @@ -109,6 +109,7 @@ protected: bool m_thread_name_valid; std::string m_thread_name; + POSIXBreakpointProtocol *m_posix_thread; ProcessMonitor & GetMonitor(); @@ -125,6 +126,7 @@ protected: void CrashNotify(const ProcessMessage &message); void ThreadNotify(const ProcessMessage &message); void ExitNotify(const ProcessMessage &message); + void ExecNotify(const ProcessMessage &message); lldb_private::Unwind * GetUnwinder(); diff --git a/source/Plugins/Process/POSIX/ProcessMessage.cpp b/source/Plugins/Process/POSIX/ProcessMessage.cpp index 60a29e07cea8..5c53627f9e0b 100644 --- a/source/Plugins/Process/POSIX/ProcessMessage.cpp +++ b/source/Plugins/Process/POSIX/ProcessMessage.cpp @@ -218,6 +218,9 @@ ProcessMessage::PrintKind(Kind kind) case eInvalidMessage: str = "eInvalidMessage"; break; + case eAttachMessage: + str = "eAttachMessage"; + break; case eExitMessage: str = "eExitMessage"; break; @@ -245,6 +248,9 @@ ProcessMessage::PrintKind(Kind kind) case eNewThreadMessage: str = "eNewThreadMessage"; break; + case eExecMessage: + str = "eExecMessage"; + break; } #endif diff --git a/source/Plugins/Process/POSIX/ProcessMessage.h b/source/Plugins/Process/POSIX/ProcessMessage.h index c6c460c13445..40462d0f0e13 100644 --- a/source/Plugins/Process/POSIX/ProcessMessage.h +++ b/source/Plugins/Process/POSIX/ProcessMessage.h @@ -23,6 +23,7 @@ public: enum Kind { eInvalidMessage, + eAttachMessage, eExitMessage, eLimboMessage, eSignalMessage, @@ -31,7 +32,8 @@ public: eBreakpointMessage, eWatchpointMessage, eCrashMessage, - eNewThreadMessage + eNewThreadMessage, + eExecMessage }; enum CrashReason @@ -79,6 +81,11 @@ public: lldb::tid_t GetTID() const { return m_tid; } + /// Indicates that the process @p pid has successfully attached. + static ProcessMessage Attach(lldb::pid_t pid) { + return ProcessMessage(pid, eAttachMessage); + } + /// Indicates that the thread @p tid is about to exit with status @p status. static ProcessMessage Limbo(lldb::tid_t tid, int status) { return ProcessMessage(tid, eLimboMessage, status); @@ -127,6 +134,11 @@ public: return ProcessMessage(tid, eExitMessage, status); } + /// Indicates that the thread @p pid has exec'd. + static ProcessMessage Exec(lldb::tid_t tid) { + return ProcessMessage(tid, eExecMessage); + } + int GetExitStatus() const { assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); return m_status; diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp index f04631ddf914..70ad3a66d9ef 100644 --- a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp +++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp @@ -289,12 +289,11 @@ ProcessPOSIX::GetImageInfoAddress() { Target *target = &GetTarget(); ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(); + Address addr = obj_file->GetImageInfoAddress(target); - if (addr.IsValid()) + if (addr.IsValid()) return addr.GetLoadAddress(target); - else - return LLDB_INVALID_ADDRESS; + return LLDB_INVALID_ADDRESS; } Error @@ -319,34 +318,6 @@ ProcessPOSIX::DoHalt(bool &caused_stop) } Error -ProcessPOSIX::DoDetach(bool keep_stopped) -{ - Error error; - if (keep_stopped) - { - // FIXME: If you want to implement keep_stopped, - // this would be the place to do it. - error.SetErrorString("Detaching with keep_stopped true is not currently supported on this platform."); - return error; - } - - Mutex::Locker lock(m_thread_list.GetMutex()); - - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) - { - POSIXThread *thread = static_cast<POSIXThread*>( - m_thread_list.GetThreadAtIndex(i, false).get()); - error = m_monitor->Detach(thread->GetID()); - } - - if (error.Success()) - SetPrivateState(eStateDetached); - - return error; -} - -Error ProcessPOSIX::DoSignal(int signal) { Error error; @@ -381,6 +352,31 @@ ProcessPOSIX::DoDestroy() } void +ProcessPOSIX::DoDidExec() +{ + Target *target = &GetTarget(); + if (target) + { + PlatformSP platform_sp (target->GetPlatform()); + assert (platform_sp.get()); + if (platform_sp) + { + ProcessInstanceInfo process_info; + platform_sp->GetProcessInfo(GetID(), process_info); + ModuleSP exe_module_sp; + FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); + Error error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(), + target->GetArchitecture(), + exe_module_sp, + executable_search_paths.GetSize() ? &executable_search_paths : NULL); + if (!error.Success()) + return; + target->SetExecutableModule(exe_module_sp, true); + } + } +} + +void ProcessPOSIX::SendMessage(const ProcessMessage &message) { Mutex::Locker lock(m_message_mutex); @@ -395,6 +391,10 @@ ProcessPOSIX::SendMessage(const ProcessMessage &message) case ProcessMessage::eInvalidMessage: return; + case ProcessMessage::eAttachMessage: + SetPrivateState(eStateStopped); + return; + case ProcessMessage::eLimboMessage: assert(thread); thread->SetState(eStateStopped); @@ -442,15 +442,38 @@ ProcessPOSIX::SendMessage(const ProcessMessage &message) case ProcessMessage::eBreakpointMessage: case ProcessMessage::eTraceMessage: case ProcessMessage::eWatchpointMessage: - case ProcessMessage::eNewThreadMessage: case ProcessMessage::eCrashMessage: assert(thread); thread->SetState(eStateStopped); StopAllThreads(message.GetTID()); SetPrivateState(eStateStopped); break; + + case ProcessMessage::eNewThreadMessage: + { + lldb::tid_t new_tid = message.GetChildTID(); + if (WaitingForInitialStop(new_tid)) + { + m_monitor->WaitForInitialTIDStop(new_tid); + } + assert(thread); + thread->SetState(eStateStopped); + StopAllThreads(message.GetTID()); + SetPrivateState(eStateStopped); + break; } + case ProcessMessage::eExecMessage: + { + assert(thread); + thread->SetState(eStateStopped); + StopAllThreads(message.GetTID()); + SetPrivateState(eStateStopped); + break; + } + } + + m_message_queue.push(message); } @@ -473,6 +496,12 @@ ProcessPOSIX::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid) return added_to_set; } +bool +ProcessPOSIX::WaitingForInitialStop(lldb::tid_t stop_tid) +{ + return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end()); +} + POSIXThread * ProcessPOSIX::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid) { @@ -499,8 +528,6 @@ ProcessPOSIX::RefreshStateAfterStop() lldb::tid_t tid = message.GetTID(); if (log) log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid); - POSIXThread *thread = static_cast<POSIXThread*>( - GetThreadList().FindThreadByID(tid, false).get()); if (message.GetKind() == ProcessMessage::eNewThreadMessage) { @@ -517,6 +544,8 @@ ProcessPOSIX::RefreshStateAfterStop() m_thread_list.RefreshStateAfterStop(); + POSIXThread *thread = static_cast<POSIXThread*>( + GetThreadList().FindThreadByID(tid, false).get()); if (thread) thread->Notify(message); @@ -813,19 +842,21 @@ ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thre if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) log->Printf ("ProcessPOSIX::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID()); + bool has_updated = false; // Update the process thread list with this new thread. // FIXME: We should be using tid, not pid. assert(m_monitor); ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); if (!thread_sp) { thread_sp.reset(CreateNewPOSIXThread(*this, GetID())); + has_updated = true; } if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) log->Printf ("ProcessPOSIX::%s() updated pid = %" PRIi64, __FUNCTION__, GetID()); new_thread_list.AddThread(thread_sp); - return new_thread_list.GetSize(false) > 0; + return has_updated; // the list has been updated } ByteOrder diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.h b/source/Plugins/Process/POSIX/ProcessPOSIX.h index 48b19bac47e7..790041be321a 100644 --- a/source/Plugins/Process/POSIX/ProcessPOSIX.h +++ b/source/Plugins/Process/POSIX/ProcessPOSIX.h @@ -70,7 +70,7 @@ public: DoHalt(bool &caused_stop); virtual lldb_private::Error - DoDetach(bool keep_stopped); + DoDetach(bool keep_stopped) = 0; virtual lldb_private::Error DoSignal(int signal); @@ -79,6 +79,9 @@ public: DoDestroy(); virtual void + DoDidExec(); + + virtual void RefreshStateAfterStop(); virtual bool @@ -167,6 +170,9 @@ public: bool AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid); + bool + WaitingForInitialStop(lldb::tid_t stop_tid); + virtual POSIXThread * CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid); diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp new file mode 100644 index 000000000000..50ec8d414a12 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.cpp @@ -0,0 +1,78 @@ +//===-- RegisterContextFreeBSD_i386.cpp ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include "RegisterContextPOSIX_x86.h" +#include "RegisterContextFreeBSD_i386.h" + +using namespace lldb_private; +using namespace lldb; + +// http://svnweb.freebsd.org/base/head/sys/x86/include/reg.h +struct GPR +{ + uint32_t fs; + uint32_t es; + uint32_t ds; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t isp; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint32_t trapno; + uint32_t err; + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t esp; + uint32_t ss; + uint32_t gs; +}; + +#define DR_SIZE 0 +#define DR_OFFSET(reg_index) 0 + +//--------------------------------------------------------------------------- +// Include RegisterInfos_i386 to declare our g_register_infos_i386 structure. +//--------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_I386_STRUCT +#include "RegisterInfos_i386.h" +#undef DECLARE_REGISTER_INFOS_I386_STRUCT + +RegisterContextFreeBSD_i386::RegisterContextFreeBSD_i386(const ArchSpec &target_arch) : + RegisterInfoInterface(target_arch) +{ +} + +RegisterContextFreeBSD_i386::~RegisterContextFreeBSD_i386() +{ +} + +size_t +RegisterContextFreeBSD_i386::GetGPRSize() +{ + return sizeof(GPR); +} + +const RegisterInfo * +RegisterContextFreeBSD_i386::GetRegisterInfo() +{ + switch (m_target_arch.GetCore()) + { + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + return g_register_infos_i386; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } +} diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h new file mode 100644 index 000000000000..4ec2ad3e9706 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_i386.h @@ -0,0 +1,29 @@ +//===-- RegisterContextFreeBSD_i386.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextFreeBSD_i386_H_ +#define liblldb_RegisterContextFreeBSD_i386_H_ + +#include "RegisterContextPOSIX.h" + +class RegisterContextFreeBSD_i386 + : public RegisterInfoInterface +{ +public: + RegisterContextFreeBSD_i386(const lldb_private::ArchSpec &target_arch); + virtual ~RegisterContextFreeBSD_i386(); + + size_t + GetGPRSize(); + + const lldb_private::RegisterInfo * + GetRegisterInfo(); +}; + +#endif diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp new file mode 100644 index 000000000000..4714251fd2dc --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.cpp @@ -0,0 +1,90 @@ +//===-- RegisterContextFreeBSD_mips64.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include <vector> +#include "RegisterContextPOSIX_mips64.h" +#include "RegisterContextFreeBSD_mips64.h" + +using namespace lldb_private; +using namespace lldb; + +// http://svnweb.freebsd.org/base/head/sys/mips/include/regnum.h +typedef struct _GPR +{ + uint64_t zero; + uint64_t r1; + uint64_t r2; + uint64_t r3; + uint64_t r4; + uint64_t r5; + uint64_t r6; + uint64_t r7; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t r16; + uint64_t r17; + uint64_t r18; + uint64_t r19; + uint64_t r20; + uint64_t r21; + uint64_t r22; + uint64_t r23; + uint64_t r24; + uint64_t r25; + uint64_t r26; + uint64_t r27; + uint64_t gp; + uint64_t sp; + uint64_t r30; + uint64_t ra; + uint64_t sr; + uint64_t mullo; + uint64_t mulhi; + uint64_t badvaddr; + uint64_t cause; + uint64_t pc; + uint64_t ic; + uint64_t dummy; +} GPR; + +//--------------------------------------------------------------------------- +// Include RegisterInfos_mips64 to declare our g_register_infos_mips64 structure. +//--------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_MIPS64_STRUCT +#include "RegisterInfos_mips64.h" +#undef DECLARE_REGISTER_INFOS_MIPS64_STRUCT + +RegisterContextFreeBSD_mips64::RegisterContextFreeBSD_mips64(const ArchSpec &target_arch) : + RegisterInfoInterface(target_arch) +{ +} + +RegisterContextFreeBSD_mips64::~RegisterContextFreeBSD_mips64() +{ +} + +size_t +RegisterContextFreeBSD_mips64::GetGPRSize() +{ + return sizeof(GPR); +} + +const RegisterInfo * +RegisterContextFreeBSD_mips64::GetRegisterInfo() +{ + assert (m_target_arch.GetCore() == ArchSpec::eCore_mips64); + return g_register_infos_mips64; +} + diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h new file mode 100644 index 000000000000..9ee767955347 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_mips64.h @@ -0,0 +1,29 @@ +//===-- RegisterContextFreeBSD_mips64.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextFreeBSD_mips64_H_ +#define liblldb_RegisterContextFreeBSD_mips64_H_ + +#include "RegisterContextPOSIX.h" + +class RegisterContextFreeBSD_mips64: + public RegisterInfoInterface +{ +public: + RegisterContextFreeBSD_mips64(const lldb_private::ArchSpec &target_arch); + virtual ~RegisterContextFreeBSD_mips64(); + + size_t + GetGPRSize(); + + const lldb_private::RegisterInfo * + GetRegisterInfo(); +}; + +#endif diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp index 0fb9dc1cb3dc..471734580fff 100644 --- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp +++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextFreeBSD_x86_64.h ------------------------*- C++ -*-===// +//===-- RegisterContextFreeBSD_x86_64.cpp ----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,27 +7,15 @@ // //===---------------------------------------------------------------------===// -#include "RegisterContextFreeBSD_x86_64.h" #include <vector> +#include "RegisterContextPOSIX_x86.h" +#include "RegisterContextFreeBSD_i386.h" +#include "RegisterContextFreeBSD_x86_64.h" using namespace lldb_private; +using namespace lldb; -// Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (offsetof(GPR, regname)) - -// Update the FreeBSD specific information (offset and size). -#define UPDATE_GPR_INFO(reg) \ -do { \ - GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg); \ - GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg); \ -} while(false); - -#define UPDATE_I386_GPR_INFO(i386_reg, reg) \ -do { \ - GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \ -} while(false); - +// http://svnweb.freebsd.org/base/head/sys/x86/include/reg.h typedef struct _GPR { uint64_t r15; @@ -58,15 +46,47 @@ typedef struct _GPR uint64_t ss; } GPR; -// Use a singleton function to avoid global constructors in shared libraries. -static std::vector<RegisterInfo> & GetRegisterContext () { - static std::vector<RegisterInfo> g_register_infos; - return g_register_infos; +#define DR_SIZE 0 +#define DR_OFFSET(reg_index) 0 + +//--------------------------------------------------------------------------- +// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure. +//--------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_X86_64_STRUCT +#include "RegisterInfos_x86_64.h" +#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT + +static const RegisterInfo * +GetRegisterInfo_i386(const lldb_private::ArchSpec& arch) +{ + static std::vector<lldb_private::RegisterInfo> g_register_infos; + + // Allocate RegisterInfo only once + if (g_register_infos.empty()) + { + // Copy the register information from base class + std::unique_ptr<RegisterContextFreeBSD_i386> reg_interface(new RegisterContextFreeBSD_i386 (arch)); + const RegisterInfo *base_info = reg_interface->GetRegisterInfo(); + g_register_infos.insert(g_register_infos.end(), &base_info[0], &base_info[k_num_registers_i386]); + + //--------------------------------------------------------------------------- + // Include RegisterInfos_x86_64 to update the g_register_infos structure + // with x86_64 offsets. + //--------------------------------------------------------------------------- + #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS + #include "RegisterInfos_x86_64.h" + #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS + } + + return &g_register_infos[0]; } +RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(const ArchSpec &target_arch) : + RegisterInfoInterface(target_arch) +{ +} -RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(Thread &thread, uint32_t concrete_frame_idx): - RegisterContext_x86_64(thread, concrete_frame_idx) +RegisterContextFreeBSD_x86_64::~RegisterContextFreeBSD_x86_64() { } @@ -79,58 +99,17 @@ RegisterContextFreeBSD_x86_64::GetGPRSize() const RegisterInfo * RegisterContextFreeBSD_x86_64::GetRegisterInfo() { - // Allocate RegisterInfo only once - if (GetRegisterContext().empty()) + switch (m_target_arch.GetCore()) { - // Copy the register information from base class - const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo(); - if (base_info) - { - GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]); - // Update the FreeBSD specific register information (offset and size). - UpdateRegisterInfo(); - } + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + return GetRegisterInfo_i386 (m_target_arch); + case ArchSpec::eCore_x86_64_x86_64: + return g_register_infos_x86_64; + default: + assert(false && "Unhandled target architecture."); + return NULL; } - return &GetRegisterContext()[0]; -} - -void -RegisterContextFreeBSD_x86_64::UpdateRegisterInfo() -{ - UPDATE_GPR_INFO(rax); - UPDATE_GPR_INFO(rbx); - UPDATE_GPR_INFO(rcx); - UPDATE_GPR_INFO(rdx); - UPDATE_GPR_INFO(rdi); - UPDATE_GPR_INFO(rsi); - UPDATE_GPR_INFO(rbp); - UPDATE_GPR_INFO(rsp); - UPDATE_GPR_INFO(r8); - UPDATE_GPR_INFO(r9); - UPDATE_GPR_INFO(r10); - UPDATE_GPR_INFO(r11); - UPDATE_GPR_INFO(r12); - UPDATE_GPR_INFO(r13); - UPDATE_GPR_INFO(r14); - UPDATE_GPR_INFO(r15); - UPDATE_GPR_INFO(rip); - UPDATE_GPR_INFO(rflags); - UPDATE_GPR_INFO(cs); - UPDATE_GPR_INFO(fs); - UPDATE_GPR_INFO(gs); - UPDATE_GPR_INFO(ss); - UPDATE_GPR_INFO(ds); - UPDATE_GPR_INFO(es); - - UPDATE_I386_GPR_INFO(eax, rax); - UPDATE_I386_GPR_INFO(ebx, rbx); - UPDATE_I386_GPR_INFO(ecx, rcx); - UPDATE_I386_GPR_INFO(edx, rdx); - UPDATE_I386_GPR_INFO(edi, rdi); - UPDATE_I386_GPR_INFO(esi, rsi); - UPDATE_I386_GPR_INFO(ebp, rbp); - UPDATE_I386_GPR_INFO(esp, rsp); - UPDATE_I386_GPR_INFO(eip, rip); - UPDATE_I386_GPR_INFO(eflags, rflags); } diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h index ffff40a9c65b..731bb0ea6bcc 100644 --- a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h +++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h @@ -1,4 +1,4 @@ -//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===// +//===-- RegisterContextFreeBSD_x86_64.h -------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,23 +10,20 @@ #ifndef liblldb_RegisterContextFreeBSD_x86_64_H_ #define liblldb_RegisterContextFreeBSD_x86_64_H_ -#include "Plugins/Process/POSIX/RegisterContext_x86_64.h" +#include "RegisterContextPOSIX.h" class RegisterContextFreeBSD_x86_64: - public RegisterContext_x86_64 + public RegisterInfoInterface { public: - RegisterContextFreeBSD_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx); + RegisterContextFreeBSD_x86_64(const lldb_private::ArchSpec &target_arch); + virtual ~RegisterContextFreeBSD_x86_64(); size_t GetGPRSize(); -protected: - virtual const lldb_private::RegisterInfo * + const lldb_private::RegisterInfo * GetRegisterInfo(); - - virtual void - UpdateRegisterInfo(); }; #endif diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp new file mode 100644 index 000000000000..0828efbc6c3c --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.cpp @@ -0,0 +1,96 @@ +//===-- RegisterContextLinux_i386.cpp --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include "RegisterContextPOSIX_x86.h" +#include "RegisterContextLinux_i386.h" + +using namespace lldb_private; +using namespace lldb; + +struct GPR +{ + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t esi; + uint32_t edi; + uint32_t ebp; + uint32_t eax; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; + uint32_t orig_ax; + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t esp; + uint32_t ss; +}; + +struct UserArea +{ + GPR regs; // General purpose registers. + int32_t fpvalid; // True if FPU is being used. + FXSAVE i387; // FPU registers. + uint32_t tsize; // Text segment size. + uint32_t dsize; // Data segment size. + uint32_t ssize; // Stack segment size. + uint32_t start_code; // VM address of text. + uint32_t start_stack; // VM address of stack bottom (top in rsp). + int32_t signal; // Signal causing core dump. + int32_t reserved; // Unused. + uint32_t ar0; // Location of GPR's. + uint32_t fpstate; // Location of FPR's. Should be a FXSTATE *, but this + // has to be 32-bits even on 64-bit systems. + uint32_t magic; // Identifier for core dumps. + char u_comm[32]; // Command causing core dump. + uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). +}; + +#define DR_SIZE sizeof(UserArea::u_debugreg[0]) +#define DR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index])) + +//--------------------------------------------------------------------------- +// Include RegisterInfos_i386 to declare our g_register_infos_i386 structure. +//--------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_I386_STRUCT +#include "RegisterInfos_i386.h" +#undef DECLARE_REGISTER_INFOS_I386_STRUCT + +RegisterContextLinux_i386::RegisterContextLinux_i386(const ArchSpec &target_arch) : + RegisterInfoInterface(target_arch) +{ +} + +RegisterContextLinux_i386::~RegisterContextLinux_i386() +{ +} + +size_t +RegisterContextLinux_i386::GetGPRSize() +{ + return sizeof(GPR); +} + +const RegisterInfo * +RegisterContextLinux_i386::GetRegisterInfo() +{ + switch (m_target_arch.GetCore()) + { + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + return g_register_infos_i386; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } +} diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_i386.h b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.h new file mode 100644 index 000000000000..81afdbf8b1cf --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextLinux_i386.h @@ -0,0 +1,29 @@ +//===-- RegisterContextLinux_i386.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextLinux_i386_H_ +#define liblldb_RegisterContextLinux_i386_H_ + +#include "RegisterContextPOSIX.h" + +class RegisterContextLinux_i386 + : public RegisterInfoInterface +{ +public: + RegisterContextLinux_i386(const lldb_private::ArchSpec &target_arch); + virtual ~RegisterContextLinux_i386(); + + size_t + GetGPRSize(); + + const lldb_private::RegisterInfo * + GetRegisterInfo(); +}; + +#endif diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp index c1aea2a41a1f..5434ddfcf38b 100644 --- a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp +++ b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp @@ -1,4 +1,4 @@ -//===-- RegisterContextLinux_x86_64.h --------------------------*- C++ -*-===// +//===-- RegisterContextLinux_x86_64.cpp ------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,36 +7,13 @@ // //===---------------------------------------------------------------------===// -#include "llvm/Support/Compiler.h" -#include "RegisterContextLinux_x86_64.h" #include <vector> +#include "RegisterContextPOSIX_x86.h" +#include "RegisterContextLinux_i386.h" +#include "RegisterContextLinux_x86_64.h" using namespace lldb_private; - -// Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (offsetof(GPR, regname)) - -// Update the Linux specific information (offset and size). -#define UPDATE_GPR_INFO(reg) \ -do { \ - GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg); \ - GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg); \ -} while(false); - -#define UPDATE_I386_GPR_INFO(i386_reg, reg) \ -do { \ - GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \ -} while(false); - -#define DR_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index])) - -#define UPDATE_DR_INFO(reg_index) \ -do { \ - GetRegisterContext()[dr##reg_index].byte_size = sizeof(UserArea::u_debugreg[0]); \ - GetRegisterContext()[dr##reg_index].byte_offset = DR_OFFSET(reg_index); \ -} while(false); +using namespace lldb; typedef struct _GPR { @@ -69,8 +46,6 @@ typedef struct _GPR uint64_t gs; } GPR; -typedef RegisterContext_x86_64::FXSAVE FXSAVE; - struct UserArea { GPR gpr; // General purpose registers. @@ -94,14 +69,48 @@ struct UserArea uint64_t fault_address; // Control register CR3. }; -// Use a singleton function to avoid global constructors in shared libraries. -static std::vector<RegisterInfo> & GetRegisterContext () { - static std::vector<RegisterInfo> g_register_infos; - return g_register_infos; +#define DR_SIZE sizeof(UserArea::u_debugreg[0]) +#define DR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index])) + +//--------------------------------------------------------------------------- +// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64 structure. +//--------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_X86_64_STRUCT +#include "RegisterInfos_x86_64.h" +#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT + +static const RegisterInfo * +GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) +{ + static std::vector<lldb_private::RegisterInfo> g_register_infos; + + // Allocate RegisterInfo only once + if (g_register_infos.empty()) + { + // Copy the register information from base class + std::unique_ptr<RegisterContextLinux_i386> reg_interface(new RegisterContextLinux_i386 (arch)); + const RegisterInfo *base_info = reg_interface->GetRegisterInfo(); + g_register_infos.insert(g_register_infos.end(), &base_info[0], &base_info[k_num_registers_i386]); + + //--------------------------------------------------------------------------- + // Include RegisterInfos_x86_64 to update the g_register_infos structure + // with x86_64 offsets. + //--------------------------------------------------------------------------- + #define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS + #include "RegisterInfos_x86_64.h" + #undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS + } + + return &g_register_infos[0]; +} + +RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) : + RegisterInfoInterface(target_arch) +{ } -RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, uint32_t concrete_frame_idx): - RegisterContext_x86_64(thread, concrete_frame_idx) +RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64() { } @@ -114,67 +123,17 @@ RegisterContextLinux_x86_64::GetGPRSize() const RegisterInfo * RegisterContextLinux_x86_64::GetRegisterInfo() { - // Allocate RegisterInfo only once - if (GetRegisterContext().empty()) + switch (m_target_arch.GetCore()) { - // Copy the register information from base class - const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo(); - if (base_info) - { - GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]); - // Update the Linux specific register information (offset and size). - UpdateRegisterInfo(); - } + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + return GetRegisterInfo_i386 (m_target_arch); + case ArchSpec::eCore_x86_64_x86_64: + return g_register_infos_x86_64; + default: + assert(false && "Unhandled target architecture."); + return NULL; } - return &GetRegisterContext()[0]; -} - -void -RegisterContextLinux_x86_64::UpdateRegisterInfo() -{ - UPDATE_GPR_INFO(rax); - UPDATE_GPR_INFO(rbx); - UPDATE_GPR_INFO(rcx); - UPDATE_GPR_INFO(rdx); - UPDATE_GPR_INFO(rdi); - UPDATE_GPR_INFO(rsi); - UPDATE_GPR_INFO(rbp); - UPDATE_GPR_INFO(rsp); - UPDATE_GPR_INFO(r8); - UPDATE_GPR_INFO(r9); - UPDATE_GPR_INFO(r10); - UPDATE_GPR_INFO(r11); - UPDATE_GPR_INFO(r12); - UPDATE_GPR_INFO(r13); - UPDATE_GPR_INFO(r14); - UPDATE_GPR_INFO(r15); - UPDATE_GPR_INFO(rip); - UPDATE_GPR_INFO(rflags); - UPDATE_GPR_INFO(cs); - UPDATE_GPR_INFO(fs); - UPDATE_GPR_INFO(gs); - UPDATE_GPR_INFO(ss); - UPDATE_GPR_INFO(ds); - UPDATE_GPR_INFO(es); - - UPDATE_I386_GPR_INFO(eax, rax); - UPDATE_I386_GPR_INFO(ebx, rbx); - UPDATE_I386_GPR_INFO(ecx, rcx); - UPDATE_I386_GPR_INFO(edx, rdx); - UPDATE_I386_GPR_INFO(edi, rdi); - UPDATE_I386_GPR_INFO(esi, rsi); - UPDATE_I386_GPR_INFO(ebp, rbp); - UPDATE_I386_GPR_INFO(esp, rsp); - UPDATE_I386_GPR_INFO(eip, rip); - UPDATE_I386_GPR_INFO(eflags, rflags); - - UPDATE_DR_INFO(0); - UPDATE_DR_INFO(1); - UPDATE_DR_INFO(2); - UPDATE_DR_INFO(3); - UPDATE_DR_INFO(4); - UPDATE_DR_INFO(5); - UPDATE_DR_INFO(6); - UPDATE_DR_INFO(7); } diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h index 1509ef55b8dc..21c809b5dc33 100644 --- a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h +++ b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h @@ -10,23 +10,20 @@ #ifndef liblldb_RegisterContextLinux_x86_64_H_ #define liblldb_RegisterContextLinux_x86_64_H_ -#include "Plugins/Process/POSIX/RegisterContext_x86_64.h" +#include "RegisterContextPOSIX.h" -class RegisterContextLinux_x86_64: - public RegisterContext_x86_64 +class RegisterContextLinux_x86_64 + : public RegisterInfoInterface { public: - RegisterContextLinux_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx); + RegisterContextLinux_x86_64(const lldb_private::ArchSpec &target_arch); + virtual ~RegisterContextLinux_x86_64(); size_t GetGPRSize(); -protected: - virtual const lldb_private::RegisterInfo * + const lldb_private::RegisterInfo * GetRegisterInfo(); - - virtual void - UpdateRegisterInfo(); }; #endif diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX.h b/source/Plugins/Process/POSIX/RegisterContextPOSIX.h index 63ae01e83a90..e48c528403e3 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIX.h +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX.h @@ -13,20 +13,19 @@ // C Includes // C++ Includes // Other libraries and framework includes +#include "lldb/Core/ArchSpec.h" #include "lldb/Target/RegisterContext.h" //------------------------------------------------------------------------------ -/// @class RegisterContextPOSIX +/// @class POSIXBreakpointProtocol /// /// @brief Extends RegisterClass with a few virtual operations useful on POSIX. -class RegisterContextPOSIX - : public lldb_private::RegisterContext +class POSIXBreakpointProtocol { public: - RegisterContextPOSIX(lldb_private::Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContext(thread, concrete_frame_idx) + POSIXBreakpointProtocol() { m_watchpoints_initialized = false; } + virtual ~POSIXBreakpointProtocol() {} /// Updates the register state of the associated thread after hitting a /// breakpoint (if that make sense for the architecture). Default @@ -35,36 +34,61 @@ public: /// /// @return /// True if the operation succeeded and false otherwise. - virtual bool UpdateAfterBreakpoint() { return true; } + virtual bool UpdateAfterBreakpoint() = 0; /// Determines the index in lldb's register file given a kernel byte offset. virtual unsigned - GetRegisterIndexFromOffset(unsigned offset) { return LLDB_INVALID_REGNUM; } + GetRegisterIndexFromOffset(unsigned offset) = 0; // Checks to see if a watchpoint specified by hw_index caused the inferior // to stop. virtual bool - IsWatchpointHit (uint32_t hw_index) { return false; } + IsWatchpointHit (uint32_t hw_index) = 0; // Resets any watchpoints that have been hit. virtual bool - ClearWatchpointHits () { return false; } + ClearWatchpointHits () = 0; // Returns the watchpoint address associated with a watchpoint hardware // index. virtual lldb::addr_t - GetWatchpointAddress (uint32_t hw_index) { return LLDB_INVALID_ADDRESS; } + GetWatchpointAddress (uint32_t hw_index) = 0; virtual bool - IsWatchpointVacant (uint32_t hw_index) { return false; } + IsWatchpointVacant (uint32_t hw_index) = 0; virtual bool SetHardwareWatchpointWithIndex (lldb::addr_t addr, size_t size, bool read, bool write, - uint32_t hw_index) { return false; } + uint32_t hw_index) = 0; + + // From lldb_private::RegisterContext + virtual uint32_t + NumSupportedHardwareWatchpoints () = 0; protected: bool m_watchpoints_initialized; }; +//------------------------------------------------------------------------------ +/// @class RegisterInfoInterface +/// +/// @brief RegisterInfo interface to patch RegisterInfo structure for archs. +class RegisterInfoInterface +{ +public: + RegisterInfoInterface(const lldb_private::ArchSpec& target_arch) : m_target_arch(target_arch) {} + virtual ~RegisterInfoInterface () {} + + virtual size_t + GetGPRSize () = 0; + + virtual const lldb_private::RegisterInfo * + GetRegisterInfo () = 0; + +public: + lldb_private::ArchSpec m_target_arch; +}; + #endif // #ifndef liblldb_RegisterContextPOSIX_H_ + diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp new file mode 100644 index 000000000000..f70d00e98a3e --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.cpp @@ -0,0 +1,318 @@ +//===-- RegisterContextPOSIXProcessMonitor_mips64.h ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include "lldb/Target/Thread.h" +#include "lldb/Core/RegisterValue.h" + +#include "RegisterContextPOSIX_mips64.h" +#include "ProcessPOSIX.h" +#include "RegisterContextPOSIXProcessMonitor_mips64.h" +#include "ProcessMonitor.h" + +using namespace lldb_private; +using namespace lldb; + +#define REG_CONTEXT_SIZE (GetGPRSize()) + +RegisterContextPOSIXProcessMonitor_mips64::RegisterContextPOSIXProcessMonitor_mips64(Thread &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info) +{ +} + +ProcessMonitor & +RegisterContextPOSIXProcessMonitor_mips64::GetMonitor() +{ + ProcessSP base = CalculateProcess(); + ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get()); + return process->GetMonitor(); +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::ReadGPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize()); +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::ReadFPR() +{ + // XXX not yet implemented + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::WriteGPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize()); +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::WriteFPR() +{ + // XXX not yet implemented + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const unsigned reg, + RegisterValue &value) +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadRegisterValue(m_thread.GetID(), + GetRegisterOffset(reg), + GetRegisterName(reg), + GetRegisterSize(reg), + value); +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const unsigned reg, + const RegisterValue &value) +{ + unsigned reg_to_write = reg; + RegisterValue value_to_write = value; + + // Check if this is a subregister of a full register. + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) + { + RegisterValue full_value; + uint32_t full_reg = reg_info->invalidate_regs[0]; + const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); + + // Read the full register. + if (ReadRegister(full_reg_info, full_value)) + { + Error error; + ByteOrder byte_order = GetByteOrder(); + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the full register. + const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, + dst, + sizeof(dst), + byte_order, + error); + if (error.Success() && dest_size) + { + uint8_t src[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the source data. + const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); + if (error.Success() && src_size && (src_size < dest_size)) + { + // Copy the src bytes to the destination. + memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); + // Set this full register as the value to write. + value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); + value_to_write.SetType(full_reg_info); + reg_to_write = full_reg; + } + } + } + } + + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteRegisterValue(m_thread.GetID(), + GetRegisterOffset(reg_to_write), + GetRegisterName(reg_to_write), + value_to_write); +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) +{ + if (!reg_info) + return false; + + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + + if (IsFPR(reg)) + { + if (!ReadFPR()) + return false; + } + else + { + uint32_t full_reg = reg; + bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); + + if (is_subreg) + { + // Read the full aligned 64-bit register. + full_reg = reg_info->invalidate_regs[0]; + } + + bool success = ReadRegister(full_reg, value); + + if (success) + { + // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. + if (is_subreg && (reg_info->byte_offset & 0x1)) + value.SetUInt64(value.GetAsUInt64() >> 8); + + // If our return byte size was greater than the return value reg size, then + // use the type specified by reg_info rather than the uint64_t default + if (value.GetByteSize() > reg_info->byte_size) + value.SetType(reg_info); + } + return success; + } + + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + + if (IsGPR(reg)) + return WriteRegister(reg, value); + + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues(DataBufferSP &data_sp) +{ + bool success = false; + data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR () && ReadFPR ()) + { + uint8_t *dst = data_sp->GetBytes(); + success = dst != 0; + + if (success) + { + ::memcpy (dst, &m_gpr_mips64, GetGPRSize()); + dst += GetGPRSize(); + } + } + return success; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::WriteAllRegisterValues(const DataBufferSP &data_sp) +{ + bool success = false; + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) + { + uint8_t *src = data_sp->GetBytes(); + if (src) + { + ::memcpy (&m_gpr_mips64, src, GetGPRSize()); + + if (WriteGPR()) + { + src += GetGPRSize(); + } + } + } + return success; +} + +uint32_t +RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpoint(addr_t addr, size_t size, + bool read, bool write) +{ + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + uint32_t hw_index; + + for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) + { + if (IsWatchpointVacant(hw_index)) + return SetHardwareWatchpointWithIndex(addr, size, + read, write, + hw_index); + } + + return LLDB_INVALID_INDEX32; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::ClearHardwareWatchpoint(uint32_t hw_index) +{ + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::HardwareSingleStep(bool enable) +{ + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::UpdateAfterBreakpoint() +{ + // PC points one byte past the int3 responsible for the breakpoint. + lldb::addr_t pc; + + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) + return false; + + SetPC(pc - 1); + return true; +} + +unsigned +RegisterContextPOSIXProcessMonitor_mips64::GetRegisterIndexFromOffset(unsigned offset) +{ + unsigned reg; + for (reg = 0; reg < k_num_registers_mips64; reg++) + { + if (GetRegisterInfo()[reg].byte_offset == offset) + break; + } + assert(reg < k_num_registers_mips64 && "Invalid register offset."); + return reg; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointHit(uint32_t hw_index) +{ + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::ClearWatchpointHits() +{ + return false; +} + +addr_t +RegisterContextPOSIXProcessMonitor_mips64::GetWatchpointAddress(uint32_t hw_index) +{ + return LLDB_INVALID_ADDRESS; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointVacant(uint32_t hw_index) +{ + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size, + bool read, bool write, + uint32_t hw_index) +{ + return false; +} + +uint32_t +RegisterContextPOSIXProcessMonitor_mips64::NumSupportedHardwareWatchpoints() +{ + return 0; +} + diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h new file mode 100644 index 000000000000..8f545eef0d5e --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_mips64.h @@ -0,0 +1,95 @@ +//===-- RegisterContextPOSIXProcessMonitor_mips64.h -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_ +#define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_ + +#include "Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h" + +class RegisterContextPOSIXProcessMonitor_mips64: + public RegisterContextPOSIX_mips64, + public POSIXBreakpointProtocol +{ +public: + RegisterContextPOSIXProcessMonitor_mips64(lldb_private::Thread &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info); + +protected: + bool + ReadGPR(); + + bool + ReadFPR(); + + bool + WriteGPR(); + + bool + WriteFPR(); + + // lldb_private::RegisterContext + bool + ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); + + bool + WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); + + bool + ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); + + bool + WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); + + bool + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + + bool + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + + uint32_t + SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); + + bool + ClearHardwareWatchpoint(uint32_t hw_index); + + bool + HardwareSingleStep(bool enable); + + // POSIXBreakpointProtocol + bool + UpdateAfterBreakpoint(); + + unsigned + GetRegisterIndexFromOffset(unsigned offset); + + bool + IsWatchpointHit(uint32_t hw_index); + + bool + ClearWatchpointHits(); + + lldb::addr_t + GetWatchpointAddress(uint32_t hw_index); + + bool + IsWatchpointVacant(uint32_t hw_index); + + bool + SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); + + uint32_t + NumSupportedHardwareWatchpoints(); + +private: + ProcessMonitor & + GetMonitor(); +}; + +#endif diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp new file mode 100644 index 000000000000..98e0bce68678 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp @@ -0,0 +1,634 @@ +//===-- RegisterContextPOSIXProcessMonitor_x86.h ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include "lldb/Target/Thread.h" +#include "lldb/Core/RegisterValue.h" + +#include "ProcessPOSIX.h" +#include "RegisterContextPOSIXProcessMonitor_x86.h" +#include "ProcessMonitor.h" + +using namespace lldb_private; +using namespace lldb; + +// Support ptrace extensions even when compiled without required kernel support +#ifndef NT_X86_XSTATE + #define NT_X86_XSTATE 0x202 +#endif + +#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(FPR)) + +static uint32_t +size_and_rw_bits(size_t size, bool read, bool write) +{ + uint32_t rw; + + if (read) + rw = 0x3; // READ or READ/WRITE + else if (write) + rw = 0x1; // WRITE + else + assert(0 && "read and write cannot both be false"); + + switch (size) + { + case 1: + return rw; + case 2: + return (0x1 << 2) | rw; + case 4: + return (0x3 << 2) | rw; + case 8: + return (0x2 << 2) | rw; + default: + assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); + } +} + +RegisterContextPOSIXProcessMonitor_x86_64::RegisterContextPOSIXProcessMonitor_x86_64(Thread &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info) +{ +} + +ProcessMonitor & +RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor() +{ + ProcessSP base = CalculateProcess(); + ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get()); + return process->GetMonitor(); +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::ReadGPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize()); +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::ReadFPR() +{ + ProcessMonitor &monitor = GetMonitor(); + if (GetFPRType() == eFXSAVE) + return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); + + if (GetFPRType() == eXSAVE) + return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::WriteGPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize()); +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::WriteFPR() +{ + ProcessMonitor &monitor = GetMonitor(); + if (GetFPRType() == eFXSAVE) + return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); + + if (GetFPRType() == eXSAVE) + return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const unsigned reg, + RegisterValue &value) +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadRegisterValue(m_thread.GetID(), + GetRegisterOffset(reg), + GetRegisterName(reg), + GetRegisterSize(reg), + value); +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const unsigned reg, + const RegisterValue &value) +{ + unsigned reg_to_write = reg; + RegisterValue value_to_write = value; + + // Check if this is a subregister of a full register. + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) + { + RegisterValue full_value; + uint32_t full_reg = reg_info->invalidate_regs[0]; + const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); + + // Read the full register. + if (ReadRegister(full_reg_info, full_value)) + { + Error error; + ByteOrder byte_order = GetByteOrder(); + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the full register. + const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, + dst, + sizeof(dst), + byte_order, + error); + if (error.Success() && dest_size) + { + uint8_t src[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the source data. + const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); + if (error.Success() && src_size && (src_size < dest_size)) + { + // Copy the src bytes to the destination. + memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); + // Set this full register as the value to write. + value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); + value_to_write.SetType(full_reg_info); + reg_to_write = full_reg; + } + } + } + } + + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteRegisterValue(m_thread.GetID(), + GetRegisterOffset(reg_to_write), + GetRegisterName(reg_to_write), + value_to_write); +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) +{ + if (!reg_info) + return false; + + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + + if (IsFPR(reg, GetFPRType())) + { + if (!ReadFPR()) + return false; + } + else + { + uint32_t full_reg = reg; + bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); + + if (is_subreg) + { + // Read the full aligned 64-bit register. + full_reg = reg_info->invalidate_regs[0]; + } + + bool success = ReadRegister(full_reg, value); + + if (success) + { + // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. + if (is_subreg && (reg_info->byte_offset & 0x1)) + value.SetUInt64(value.GetAsUInt64() >> 8); + + // If our return byte size was greater than the return value reg size, then + // use the type specified by reg_info rather than the uint64_t default + if (value.GetByteSize() > reg_info->byte_size) + value.SetType(reg_info); + } + return success; + } + + if (reg_info->encoding == eEncodingVector) + { + ByteOrder byte_order = GetByteOrder(); + + if (byte_order != ByteOrder::eByteOrderInvalid) + { + if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) + value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, reg_info->byte_size, byte_order); + if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) + value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, reg_info->byte_size, byte_order); + if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) + value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, reg_info->byte_size, byte_order); + if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) + { + // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes + if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order)) + value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, reg_info->byte_size, byte_order); + else + return false; + } + return value.GetType() == RegisterValue::eTypeBytes; + } + return false; + } + + // Get pointer to m_fpr.xstate.fxsave variable and set the data from it. + assert (reg_info->byte_offset < sizeof(m_fpr)); + uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; + switch (reg_info->byte_size) + { + case 2: + value.SetUInt16(*(uint16_t *)src); + return true; + case 4: + value.SetUInt32(*(uint32_t *)src); + return true; + case 8: + value.SetUInt64(*(uint64_t *)src); + return true; + default: + assert(false && "Unhandled data size."); + return false; + } +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + + if (IsGPR(reg)) + return WriteRegister(reg, value); + + if (IsFPR(reg, GetFPRType())) + { + if (reg_info->encoding == eEncodingVector) + { + if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) + ::memcpy (m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, value.GetBytes(), value.GetByteSize()); + + if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) + ::memcpy (m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, value.GetBytes(), value.GetByteSize()); + + if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) + ::memcpy (m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, value.GetBytes(), value.GetByteSize()); + + if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) + { + if (GetFPRType() != eXSAVE) + return false; // the target processor does not support AVX + + // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes + ::memcpy (m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, value.GetBytes(), value.GetByteSize()); + if (false == CopyYMMtoXSTATE(reg, GetByteOrder())) + return false; + } + } + else + { + // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. + assert (reg_info->byte_offset < sizeof(m_fpr)); + uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset; + switch (reg_info->byte_size) + { + case 2: + *(uint16_t *)dst = value.GetAsUInt16(); + break; + case 4: + *(uint32_t *)dst = value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = value.GetAsUInt64(); + break; + default: + assert(false && "Unhandled data size."); + return false; + } + } + + if (WriteFPR()) + { + if (IsAVX(reg)) + return CopyYMMtoXSTATE(reg, GetByteOrder()); + return true; + } + } + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) +{ + bool success = false; + data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR () && ReadFPR ()) + { + uint8_t *dst = data_sp->GetBytes(); + success = dst != 0; + + if (success) + { + ::memcpy (dst, &m_gpr_x86_64, GetGPRSize()); + dst += GetGPRSize(); + } + if (GetFPRType() == eFXSAVE) + ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); + + if (GetFPRType() == eXSAVE) + { + ByteOrder byte_order = GetByteOrder(); + + // Assemble the YMM register content from the register halves. + for (uint32_t reg = m_reg_info.first_ymm; success && reg <= m_reg_info.last_ymm; ++reg) + success = CopyXSTATEtoYMM(reg, byte_order); + + if (success) + { + // Copy the extended register state including the assembled ymm registers. + ::memcpy (dst, &m_fpr, sizeof(m_fpr)); + } + } + } + return success; +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) +{ + bool success = false; + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) + { + uint8_t *src = data_sp->GetBytes(); + if (src) + { + ::memcpy (&m_gpr_x86_64, src, GetGPRSize()); + + if (WriteGPR()) + { + src += GetGPRSize(); + if (GetFPRType() == eFXSAVE) + ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave)); + if (GetFPRType() == eXSAVE) + ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); + + success = WriteFPR(); + if (success) + { + success = true; + + if (GetFPRType() == eXSAVE) + { + ByteOrder byte_order = GetByteOrder(); + + // Parse the YMM register content from the register halves. + for (uint32_t reg = m_reg_info.first_ymm; success && reg <= m_reg_info.last_ymm; ++reg) + success = CopyYMMtoXSTATE(reg, byte_order); + } + } + } + } + } + return success; +} + +uint32_t +RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpoint(addr_t addr, size_t size, + bool read, bool write) +{ + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + uint32_t hw_index; + + for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) + { + if (IsWatchpointVacant(hw_index)) + return SetHardwareWatchpointWithIndex(addr, size, + read, write, + hw_index); + } + + return LLDB_INVALID_INDEX32; +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::ClearHardwareWatchpoint(uint32_t hw_index) +{ + if (hw_index < NumSupportedHardwareWatchpoints()) + { + RegisterValue current_dr7_bits; + + if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) + { + uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() & ~(3 << (2*hw_index)); + + if (WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits))) + return true; + } + } + + return false; +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::HardwareSingleStep(bool enable) +{ + enum { TRACE_BIT = 0x100 }; + uint64_t rflags; + + if ((rflags = ReadRegisterAsUnsigned(m_reg_info.gpr_flags, -1UL)) == -1UL) + return false; + + if (enable) + { + if (rflags & TRACE_BIT) + return true; + + rflags |= TRACE_BIT; + } + else + { + if (!(rflags & TRACE_BIT)) + return false; + + rflags &= ~TRACE_BIT; + } + + return WriteRegisterFromUnsigned(m_reg_info.gpr_flags, rflags); +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::UpdateAfterBreakpoint() +{ + // PC points one byte past the int3 responsible for the breakpoint. + lldb::addr_t pc; + + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) + return false; + + SetPC(pc - 1); + return true; +} + +unsigned +RegisterContextPOSIXProcessMonitor_x86_64::GetRegisterIndexFromOffset(unsigned offset) +{ + unsigned reg; + for (reg = 0; reg < m_reg_info.num_registers; reg++) + { + if (GetRegisterInfo()[reg].byte_offset == offset) + break; + } + assert(reg < m_reg_info.num_registers && "Invalid register offset."); + return reg; +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointHit(uint32_t hw_index) +{ + bool is_hit = false; + + if (m_watchpoints_initialized == false) + { + // Reset the debug status and debug control registers + RegisterValue zero_bits = RegisterValue(uint64_t(0)); + if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || !WriteRegister(m_reg_info.first_dr + 7, zero_bits)) + assert(false && "Could not initialize watchpoint registers"); + m_watchpoints_initialized = true; + } + + if (hw_index < NumSupportedHardwareWatchpoints()) + { + RegisterValue value; + + if (ReadRegister(m_reg_info.first_dr + 6, value)) + { + uint64_t val = value.GetAsUInt64(); + is_hit = val & (1 << hw_index); + } + } + + return is_hit; +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::ClearWatchpointHits() +{ + return WriteRegister(m_reg_info.first_dr + 6, RegisterValue((uint64_t)0)); +} + +addr_t +RegisterContextPOSIXProcessMonitor_x86_64::GetWatchpointAddress(uint32_t hw_index) +{ + addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS; + + if (hw_index < NumSupportedHardwareWatchpoints()) + { + if (!IsWatchpointVacant(hw_index)) + { + RegisterValue value; + + if (ReadRegister(m_reg_info.first_dr + hw_index, value)) + wp_monitor_addr = value.GetAsUInt64(); + } + } + + return wp_monitor_addr; +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointVacant(uint32_t hw_index) +{ + bool is_vacant = false; + RegisterValue value; + + assert(hw_index < NumSupportedHardwareWatchpoints()); + + if (m_watchpoints_initialized == false) + { + // Reset the debug status and debug control registers + RegisterValue zero_bits = RegisterValue(uint64_t(0)); + if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) || !WriteRegister(m_reg_info.first_dr + 7, zero_bits)) + assert(false && "Could not initialize watchpoint registers"); + m_watchpoints_initialized = true; + } + + if (ReadRegister(m_reg_info.first_dr + 7, value)) + { + uint64_t val = value.GetAsUInt64(); + is_vacant = (val & (3 << 2*hw_index)) == 0; + } + + return is_vacant; +} + +bool +RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size, + bool read, bool write, + uint32_t hw_index) +{ + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + + if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints) + return false; + + if (!(size == 1 || size == 2 || size == 4 || size == 8)) + return false; + + if (read == false && write == false) + return false; + + if (!IsWatchpointVacant(hw_index)) + return false; + + // Set both dr7 (debug control register) and dri (debug address register). + + // dr7{7-0} encodes the local/global enable bits: + // global enable --. .-- local enable + // | | + // v v + // dr0 -> bits{1-0} + // dr1 -> bits{3-2} + // dr2 -> bits{5-4} + // dr3 -> bits{7-6} + // + // dr7{31-16} encodes the rw/len bits: + // b_x+3, b_x+2, b_x+1, b_x + // where bits{x+1, x} => rw + // 0b00: execute, 0b01: write, 0b11: read-or-write, + // 0b10: io read-or-write (unused) + // and bits{x+3, x+2} => len + // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte + // + // dr0 -> bits{19-16} + // dr1 -> bits{23-20} + // dr2 -> bits{27-24} + // dr3 -> bits{31-28} + if (hw_index < num_hw_watchpoints) + { + RegisterValue current_dr7_bits; + + if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) + { + uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() | + (1 << (2*hw_index) | + size_and_rw_bits(size, read, write) << + (16+4*hw_index)); + + if (WriteRegister(m_reg_info.first_dr + hw_index, RegisterValue(addr)) && + WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits))) + return true; + } + } + + return false; +} + +uint32_t +RegisterContextPOSIXProcessMonitor_x86_64::NumSupportedHardwareWatchpoints() +{ + // Available debug address registers: dr0, dr1, dr2, dr3 + return 4; +} + diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h new file mode 100644 index 000000000000..2b64fa8003a2 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.h @@ -0,0 +1,95 @@ +//===-- RegisterContextPOSIXProcessMonitor_x86.h ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextPOSIXProcessMonitor_x86_H_ +#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_ + +#include "Plugins/Process/POSIX/RegisterContextPOSIX_x86.h" + +class RegisterContextPOSIXProcessMonitor_x86_64: + public RegisterContextPOSIX_x86, + public POSIXBreakpointProtocol +{ +public: + RegisterContextPOSIXProcessMonitor_x86_64(lldb_private::Thread &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info); + +protected: + bool + ReadGPR(); + + bool + ReadFPR(); + + bool + WriteGPR(); + + bool + WriteFPR(); + + // lldb_private::RegisterContext + bool + ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); + + bool + WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); + + bool + ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); + + bool + WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); + + bool + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + + bool + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + + uint32_t + SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write); + + bool + ClearHardwareWatchpoint(uint32_t hw_index); + + bool + HardwareSingleStep(bool enable); + + // POSIXBreakpointProtocol + bool + UpdateAfterBreakpoint(); + + unsigned + GetRegisterIndexFromOffset(unsigned offset); + + bool + IsWatchpointHit(uint32_t hw_index); + + bool + ClearWatchpointHits(); + + lldb::addr_t + GetWatchpointAddress(uint32_t hw_index); + + bool + IsWatchpointVacant(uint32_t hw_index); + + bool + SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index); + + uint32_t + NumSupportedHardwareWatchpoints(); + +private: + ProcessMonitor & + GetMonitor(); +}; + +#endif diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp new file mode 100644 index 000000000000..45c99aec1657 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.cpp @@ -0,0 +1,238 @@ +//===-- RegisterContextPOSIX_mips64.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <cstring> +#include <errno.h> +#include <stdint.h> + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Host/Endian.h" +#include "llvm/Support/Compiler.h" + +#include "ProcessPOSIX.h" +#include "RegisterContextPOSIX_mips64.h" +#include "Plugins/Process/elf-core/ProcessElfCore.h" + +using namespace lldb_private; +using namespace lldb; + +static const +uint32_t g_gpr_regnums[] = +{ + gpr_zero_mips64, + gpr_r1_mips64, + gpr_r2_mips64, + gpr_r3_mips64, + gpr_r4_mips64, + gpr_r5_mips64, + gpr_r6_mips64, + gpr_r7_mips64, + gpr_r8_mips64, + gpr_r9_mips64, + gpr_r10_mips64, + gpr_r11_mips64, + gpr_r12_mips64, + gpr_r13_mips64, + gpr_r14_mips64, + gpr_r15_mips64, + gpr_r16_mips64, + gpr_r17_mips64, + gpr_r18_mips64, + gpr_r19_mips64, + gpr_r20_mips64, + gpr_r21_mips64, + gpr_r22_mips64, + gpr_r23_mips64, + gpr_r24_mips64, + gpr_r25_mips64, + gpr_r26_mips64, + gpr_r27_mips64, + gpr_gp_mips64, + gpr_sp_mips64, + gpr_r30_mips64, + gpr_ra_mips64, + gpr_sr_mips64, + gpr_mullo_mips64, + gpr_mulhi_mips64, + gpr_badvaddr_mips64, + gpr_cause_mips64, + gpr_pc_mips64, + gpr_ic_mips64, + gpr_dummy_mips64 +}; + +// Number of register sets provided by this context. +enum +{ + k_num_register_sets = 1 +}; + +static const RegisterSet +g_reg_sets_mips64[k_num_register_sets] = +{ + { "General Purpose Registers", "gpr", k_num_gpr_registers_mips64, g_gpr_regnums }, +}; + +bool RegisterContextPOSIX_mips64::IsGPR(unsigned reg) +{ + return reg <= k_num_gpr_registers_mips64; // GPR's come first. +} + +bool +RegisterContextPOSIX_mips64::IsFPR(unsigned reg) +{ + // XXX + return false; +} + +RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64(Thread &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContext(thread, concrete_frame_idx) +{ + m_register_info_ap.reset(register_info); + + // elf-core yet to support ReadFPR() + ProcessSP base = CalculateProcess(); + if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) + return; +} + +RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() +{ +} + +void +RegisterContextPOSIX_mips64::Invalidate() +{ +} + +void +RegisterContextPOSIX_mips64::InvalidateAllRegisters() +{ +} + +unsigned +RegisterContextPOSIX_mips64::GetRegisterOffset(unsigned reg) +{ + assert(reg < k_num_registers_mips64 && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; +} + +unsigned +RegisterContextPOSIX_mips64::GetRegisterSize(unsigned reg) +{ + assert(reg < k_num_registers_mips64 && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; +} + +size_t +RegisterContextPOSIX_mips64::GetRegisterCount() +{ + size_t num_registers = k_num_registers_mips64; + return num_registers; +} + +size_t +RegisterContextPOSIX_mips64::GetGPRSize() +{ + return m_register_info_ap->GetGPRSize(); +} + +const RegisterInfo * +RegisterContextPOSIX_mips64::GetRegisterInfo() +{ + // Commonly, this method is overridden and g_register_infos is copied and specialized. + // So, use GetRegisterInfo() rather than g_register_infos in this scope. + return m_register_info_ap->GetRegisterInfo (); +} + +const RegisterInfo * +RegisterContextPOSIX_mips64::GetRegisterInfoAtIndex(size_t reg) +{ + if (reg < k_num_registers_mips64) + return &GetRegisterInfo()[reg]; + else + return NULL; +} + +size_t +RegisterContextPOSIX_mips64::GetRegisterSetCount() +{ + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) + { + if (IsRegisterSetAvailable(set)) + ++sets; + } + + return sets; +} + +const RegisterSet * +RegisterContextPOSIX_mips64::GetRegisterSet(size_t set) +{ + if (IsRegisterSetAvailable(set)) + return &g_reg_sets_mips64[set]; + else + return NULL; +} + +const char * +RegisterContextPOSIX_mips64::GetRegisterName(unsigned reg) +{ + assert(reg < k_num_registers_mips64 && "Invalid register offset."); + return GetRegisterInfo()[reg].name; +} + +lldb::ByteOrder +RegisterContextPOSIX_mips64::GetByteOrder() +{ + // Get the target process whose privileged thread was used for the register read. + lldb::ByteOrder byte_order = eByteOrderInvalid; + Process *process = CalculateProcess().get(); + + if (process) + byte_order = process->GetByteOrder(); + return byte_order; +} + +bool +RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index) +{ + size_t num_sets = k_num_register_sets; + + return (set_index < num_sets); +} + +// Used when parsing DWARF and EH frame information and any other +// object file sections that contain register numbers in them. +uint32_t +RegisterContextPOSIX_mips64::ConvertRegisterKindToRegisterNumber(uint32_t kind, + uint32_t num) +{ + const uint32_t num_regs = GetRegisterCount(); + + assert (kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) + { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); + + if (reg_info->kinds[kind] == num) + return reg_idx; + } + + return LLDB_INVALID_REGNUM; +} + diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h new file mode 100644 index 000000000000..a2a7d1f45271 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_mips64.h @@ -0,0 +1,138 @@ +//===-- RegisterContextPOSIX_mips64.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextPOSIX_mips64_H_ +#define liblldb_RegisterContextPOSIX_mips64_H_ + +#include "lldb/Core/Log.h" +#include "RegisterContextPOSIX.h" +#include "RegisterContext_mips64.h" + +class ProcessMonitor; + +// --------------------------------------------------------------------------- +// Internal codes for all mips64 registers. +// --------------------------------------------------------------------------- +enum +{ + k_first_gpr_mips64, + gpr_zero_mips64 = k_first_gpr_mips64, + gpr_r1_mips64, + gpr_r2_mips64, + gpr_r3_mips64, + gpr_r4_mips64, + gpr_r5_mips64, + gpr_r6_mips64, + gpr_r7_mips64, + gpr_r8_mips64, + gpr_r9_mips64, + gpr_r10_mips64, + gpr_r11_mips64, + gpr_r12_mips64, + gpr_r13_mips64, + gpr_r14_mips64, + gpr_r15_mips64, + gpr_r16_mips64, + gpr_r17_mips64, + gpr_r18_mips64, + gpr_r19_mips64, + gpr_r20_mips64, + gpr_r21_mips64, + gpr_r22_mips64, + gpr_r23_mips64, + gpr_r24_mips64, + gpr_r25_mips64, + gpr_r26_mips64, + gpr_r27_mips64, + gpr_gp_mips64, + gpr_sp_mips64, + gpr_r30_mips64, + gpr_ra_mips64, + gpr_sr_mips64, + gpr_mullo_mips64, + gpr_mulhi_mips64, + gpr_badvaddr_mips64, + gpr_cause_mips64, + gpr_pc_mips64, + gpr_ic_mips64, + gpr_dummy_mips64, + + k_num_registers_mips64, + k_num_gpr_registers_mips64 = k_num_registers_mips64 +}; + +class RegisterContextPOSIX_mips64 + : public lldb_private::RegisterContext +{ +public: + RegisterContextPOSIX_mips64 (lldb_private::Thread &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info); + + ~RegisterContextPOSIX_mips64(); + + void + Invalidate(); + + void + InvalidateAllRegisters(); + + size_t + GetRegisterCount(); + + virtual size_t + GetGPRSize(); + + virtual unsigned + GetRegisterSize(unsigned reg); + + virtual unsigned + GetRegisterOffset(unsigned reg); + + const lldb_private::RegisterInfo * + GetRegisterInfoAtIndex(size_t reg); + + size_t + GetRegisterSetCount(); + + const lldb_private::RegisterSet * + GetRegisterSet(size_t set); + + const char * + GetRegisterName(unsigned reg); + + uint32_t + ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); + +protected: + uint64_t m_gpr_mips64[k_num_gpr_registers_mips64]; // general purpose registers. + std::unique_ptr<RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) + + // Determines if an extended register set is supported on the processor running the inferior process. + virtual bool + IsRegisterSetAvailable(size_t set_index); + + virtual const lldb_private::RegisterInfo * + GetRegisterInfo(); + + bool + IsGPR(unsigned reg); + + bool + IsFPR(unsigned reg); + + lldb::ByteOrder GetByteOrder(); + + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; +}; + +#endif // #ifndef liblldb_RegisterContextPOSIX_mips64_H_ diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp new file mode 100644 index 000000000000..9ae541a6309b --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.cpp @@ -0,0 +1,666 @@ +//===-- RegisterContextPOSIX_x86.cpp ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <cstring> +#include <errno.h> +#include <stdint.h> + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Host/Endian.h" +#include "llvm/Support/Compiler.h" + +#include "ProcessPOSIX.h" +#include "RegisterContext_x86.h" +#include "RegisterContextPOSIX_x86.h" +#include "Plugins/Process/elf-core/ProcessElfCore.h" + +using namespace lldb_private; +using namespace lldb; + +const uint32_t +g_gpr_regnums_i386[] = +{ + gpr_eax_i386, + gpr_ebx_i386, + gpr_ecx_i386, + gpr_edx_i386, + gpr_edi_i386, + gpr_esi_i386, + gpr_ebp_i386, + gpr_esp_i386, + gpr_eip_i386, + gpr_eflags_i386, + gpr_cs_i386, + gpr_fs_i386, + gpr_gs_i386, + gpr_ss_i386, + gpr_ds_i386, + gpr_es_i386, + gpr_ax_i386, + gpr_bx_i386, + gpr_cx_i386, + gpr_dx_i386, + gpr_di_i386, + gpr_si_i386, + gpr_bp_i386, + gpr_sp_i386, + gpr_ah_i386, + gpr_bh_i386, + gpr_ch_i386, + gpr_dh_i386, + gpr_al_i386, + gpr_bl_i386, + gpr_cl_i386, + gpr_dl_i386 +}; +static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) == k_num_gpr_registers_i386, + "g_gpr_regnums_i386 has wrong number of register infos"); + +const uint32_t +g_fpu_regnums_i386[] = +{ + fpu_fctrl_i386, + fpu_fstat_i386, + fpu_ftag_i386, + fpu_fop_i386, + fpu_fiseg_i386, + fpu_fioff_i386, + fpu_foseg_i386, + fpu_fooff_i386, + fpu_mxcsr_i386, + fpu_mxcsrmask_i386, + fpu_st0_i386, + fpu_st1_i386, + fpu_st2_i386, + fpu_st3_i386, + fpu_st4_i386, + fpu_st5_i386, + fpu_st6_i386, + fpu_st7_i386, + fpu_mm0_i386, + fpu_mm1_i386, + fpu_mm2_i386, + fpu_mm3_i386, + fpu_mm4_i386, + fpu_mm5_i386, + fpu_mm6_i386, + fpu_mm7_i386, + fpu_xmm0_i386, + fpu_xmm1_i386, + fpu_xmm2_i386, + fpu_xmm3_i386, + fpu_xmm4_i386, + fpu_xmm5_i386, + fpu_xmm6_i386, + fpu_xmm7_i386 +}; +static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) == k_num_fpr_registers_i386, + "g_fpu_regnums_i386 has wrong number of register infos"); + +const uint32_t +g_avx_regnums_i386[] = +{ + fpu_ymm0_i386, + fpu_ymm1_i386, + fpu_ymm2_i386, + fpu_ymm3_i386, + fpu_ymm4_i386, + fpu_ymm5_i386, + fpu_ymm6_i386, + fpu_ymm7_i386 +}; +static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) == k_num_avx_registers_i386, + " g_avx_regnums_i386 has wrong number of register infos"); + +static const +uint32_t g_gpr_regnums_x86_64[] = +{ + gpr_rax_x86_64, + gpr_rbx_x86_64, + gpr_rcx_x86_64, + gpr_rdx_x86_64, + gpr_rdi_x86_64, + gpr_rsi_x86_64, + gpr_rbp_x86_64, + gpr_rsp_x86_64, + gpr_r8_x86_64, + gpr_r9_x86_64, + gpr_r10_x86_64, + gpr_r11_x86_64, + gpr_r12_x86_64, + gpr_r13_x86_64, + gpr_r14_x86_64, + gpr_r15_x86_64, + gpr_rip_x86_64, + gpr_rflags_x86_64, + gpr_cs_x86_64, + gpr_fs_x86_64, + gpr_gs_x86_64, + gpr_ss_x86_64, + gpr_ds_x86_64, + gpr_es_x86_64, + gpr_eax_x86_64, + gpr_ebx_x86_64, + gpr_ecx_x86_64, + gpr_edx_x86_64, + gpr_edi_x86_64, + gpr_esi_x86_64, + gpr_ebp_x86_64, + gpr_esp_x86_64, + gpr_r8d_x86_64, // Low 32 bits or r8 + gpr_r9d_x86_64, // Low 32 bits or r9 + gpr_r10d_x86_64, // Low 32 bits or r10 + gpr_r11d_x86_64, // Low 32 bits or r11 + gpr_r12d_x86_64, // Low 32 bits or r12 + gpr_r13d_x86_64, // Low 32 bits or r13 + gpr_r14d_x86_64, // Low 32 bits or r14 + gpr_r15d_x86_64, // Low 32 bits or r15 + gpr_ax_x86_64, + gpr_bx_x86_64, + gpr_cx_x86_64, + gpr_dx_x86_64, + gpr_di_x86_64, + gpr_si_x86_64, + gpr_bp_x86_64, + gpr_sp_x86_64, + gpr_r8w_x86_64, // Low 16 bits or r8 + gpr_r9w_x86_64, // Low 16 bits or r9 + gpr_r10w_x86_64, // Low 16 bits or r10 + gpr_r11w_x86_64, // Low 16 bits or r11 + gpr_r12w_x86_64, // Low 16 bits or r12 + gpr_r13w_x86_64, // Low 16 bits or r13 + gpr_r14w_x86_64, // Low 16 bits or r14 + gpr_r15w_x86_64, // Low 16 bits or r15 + gpr_ah_x86_64, + gpr_bh_x86_64, + gpr_ch_x86_64, + gpr_dh_x86_64, + gpr_al_x86_64, + gpr_bl_x86_64, + gpr_cl_x86_64, + gpr_dl_x86_64, + gpr_dil_x86_64, + gpr_sil_x86_64, + gpr_bpl_x86_64, + gpr_spl_x86_64, + gpr_r8l_x86_64, // Low 8 bits or r8 + gpr_r9l_x86_64, // Low 8 bits or r9 + gpr_r10l_x86_64, // Low 8 bits or r10 + gpr_r11l_x86_64, // Low 8 bits or r11 + gpr_r12l_x86_64, // Low 8 bits or r12 + gpr_r13l_x86_64, // Low 8 bits or r13 + gpr_r14l_x86_64, // Low 8 bits or r14 + gpr_r15l_x86_64, // Low 8 bits or r15 +}; +static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) == k_num_gpr_registers_x86_64, + "g_gpr_regnums_x86_64 has wrong number of register infos"); + +static const uint32_t +g_fpu_regnums_x86_64[] = +{ + fpu_fctrl_x86_64, + fpu_fstat_x86_64, + fpu_ftag_x86_64, + fpu_fop_x86_64, + fpu_fiseg_x86_64, + fpu_fioff_x86_64, + fpu_foseg_x86_64, + fpu_fooff_x86_64, + fpu_mxcsr_x86_64, + fpu_mxcsrmask_x86_64, + fpu_st0_x86_64, + fpu_st1_x86_64, + fpu_st2_x86_64, + fpu_st3_x86_64, + fpu_st4_x86_64, + fpu_st5_x86_64, + fpu_st6_x86_64, + fpu_st7_x86_64, + fpu_mm0_x86_64, + fpu_mm1_x86_64, + fpu_mm2_x86_64, + fpu_mm3_x86_64, + fpu_mm4_x86_64, + fpu_mm5_x86_64, + fpu_mm6_x86_64, + fpu_mm7_x86_64, + fpu_xmm0_x86_64, + fpu_xmm1_x86_64, + fpu_xmm2_x86_64, + fpu_xmm3_x86_64, + fpu_xmm4_x86_64, + fpu_xmm5_x86_64, + fpu_xmm6_x86_64, + fpu_xmm7_x86_64, + fpu_xmm8_x86_64, + fpu_xmm9_x86_64, + fpu_xmm10_x86_64, + fpu_xmm11_x86_64, + fpu_xmm12_x86_64, + fpu_xmm13_x86_64, + fpu_xmm14_x86_64, + fpu_xmm15_x86_64 +}; +static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) == k_num_fpr_registers_x86_64, + "g_fpu_regnums_x86_64 has wrong number of register infos"); + +static const uint32_t +g_avx_regnums_x86_64[] = +{ + fpu_ymm0_x86_64, + fpu_ymm1_x86_64, + fpu_ymm2_x86_64, + fpu_ymm3_x86_64, + fpu_ymm4_x86_64, + fpu_ymm5_x86_64, + fpu_ymm6_x86_64, + fpu_ymm7_x86_64, + fpu_ymm8_x86_64, + fpu_ymm9_x86_64, + fpu_ymm10_x86_64, + fpu_ymm11_x86_64, + fpu_ymm12_x86_64, + fpu_ymm13_x86_64, + fpu_ymm14_x86_64, + fpu_ymm15_x86_64 +}; +static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) == k_num_avx_registers_x86_64, + "g_avx_regnums_x86_64 has wrong number of register infos"); + +uint32_t RegisterContextPOSIX_x86::g_contained_eax[] = { gpr_eax_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_ebx[] = { gpr_ebx_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_ecx[] = { gpr_ecx_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_edx[] = { gpr_edx_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_edi[] = { gpr_edi_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_esi[] = { gpr_esi_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_ebp[] = { gpr_ebp_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_esp[] = { gpr_esp_i386, LLDB_INVALID_REGNUM }; + +uint32_t RegisterContextPOSIX_x86::g_invalidate_eax[] = { gpr_eax_i386, gpr_ax_i386, gpr_ah_i386, gpr_al_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_ebx[] = { gpr_ebx_i386, gpr_bx_i386, gpr_bh_i386, gpr_bl_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_ecx[] = { gpr_ecx_i386, gpr_cx_i386, gpr_ch_i386, gpr_cl_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_edx[] = { gpr_edx_i386, gpr_dx_i386, gpr_dh_i386, gpr_dl_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_edi[] = { gpr_edi_i386, gpr_di_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_esi[] = { gpr_esi_i386, gpr_si_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_ebp[] = { gpr_ebp_i386, gpr_bp_i386, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_esp[] = { gpr_esp_i386, gpr_sp_i386, LLDB_INVALID_REGNUM }; + +uint32_t RegisterContextPOSIX_x86::g_contained_rax[] = { gpr_rax_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rbx[] = { gpr_rbx_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rcx[] = { gpr_rcx_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rdx[] = { gpr_rdx_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rdi[] = { gpr_rdi_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rsi[] = { gpr_rsi_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rbp[] = { gpr_rbp_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_rsp[] = { gpr_rsp_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r8[] = { gpr_r8_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r9[] = { gpr_r9_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r10[] = { gpr_r10_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r11[] = { gpr_r11_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r12[] = { gpr_r12_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r13[] = { gpr_r13_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r14[] = { gpr_r14_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_contained_r15[] = { gpr_r15_x86_64, LLDB_INVALID_REGNUM }; + +uint32_t RegisterContextPOSIX_x86::g_invalidate_rax[] = { gpr_rax_x86_64, gpr_eax_x86_64, gpr_ax_x86_64, gpr_ah_x86_64, gpr_al_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rbx[] = { gpr_rbx_x86_64, gpr_ebx_x86_64, gpr_bx_x86_64, gpr_bh_x86_64, gpr_bl_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rcx[] = { gpr_rcx_x86_64, gpr_ecx_x86_64, gpr_cx_x86_64, gpr_ch_x86_64, gpr_cl_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rdx[] = { gpr_rdx_x86_64, gpr_edx_x86_64, gpr_dx_x86_64, gpr_dh_x86_64, gpr_dl_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rdi[] = { gpr_rdi_x86_64, gpr_edi_x86_64, gpr_di_x86_64, gpr_dil_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rsi[] = { gpr_rsi_x86_64, gpr_esi_x86_64, gpr_si_x86_64, gpr_sil_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rbp[] = { gpr_rbp_x86_64, gpr_ebp_x86_64, gpr_bp_x86_64, gpr_bpl_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_rsp[] = { gpr_rsp_x86_64, gpr_esp_x86_64, gpr_sp_x86_64, gpr_spl_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r8[] = { gpr_r8_x86_64, gpr_r8d_x86_64, gpr_r8w_x86_64, gpr_r8l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r9[] = { gpr_r9_x86_64, gpr_r9d_x86_64, gpr_r9w_x86_64, gpr_r9l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r10[] = { gpr_r10_x86_64, gpr_r10d_x86_64, gpr_r10w_x86_64, gpr_r10l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r11[] = { gpr_r11_x86_64, gpr_r11d_x86_64, gpr_r11w_x86_64, gpr_r11l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r12[] = { gpr_r12_x86_64, gpr_r12d_x86_64, gpr_r12w_x86_64, gpr_r12l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r13[] = { gpr_r13_x86_64, gpr_r13d_x86_64, gpr_r13w_x86_64, gpr_r13l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r14[] = { gpr_r14_x86_64, gpr_r14d_x86_64, gpr_r14w_x86_64, gpr_r14l_x86_64, LLDB_INVALID_REGNUM }; +uint32_t RegisterContextPOSIX_x86::g_invalidate_r15[] = { gpr_r15_x86_64, gpr_r15d_x86_64, gpr_r15w_x86_64, gpr_r15l_x86_64, LLDB_INVALID_REGNUM }; + +// Number of register sets provided by this context. +enum +{ + k_num_extended_register_sets = 1, + k_num_register_sets = 3 +}; + +static const RegisterSet +g_reg_sets_i386[k_num_register_sets] = +{ + { "General Purpose Registers", "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386 }, + { "Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_fpu_regnums_i386 }, + { "Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386 } +}; + +static const RegisterSet +g_reg_sets_x86_64[k_num_register_sets] = +{ + { "General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, g_gpr_regnums_x86_64 }, + { "Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_fpu_regnums_x86_64 }, + { "Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64 } +}; + +bool RegisterContextPOSIX_x86::IsGPR(unsigned reg) +{ + return reg <= m_reg_info.last_gpr; // GPR's come first. +} + +bool RegisterContextPOSIX_x86::IsFPR(unsigned reg) +{ + return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); +} + +bool RegisterContextPOSIX_x86::IsAVX(unsigned reg) +{ + return (m_reg_info.first_ymm <= reg && reg <= m_reg_info.last_ymm); +} + +bool RegisterContextPOSIX_x86::IsFPR(unsigned reg, FPRType fpr_type) +{ + bool generic_fpr = IsFPR(reg); + + if (fpr_type == eXSAVE) + return generic_fpr || IsAVX(reg); + return generic_fpr; +} + +RegisterContextPOSIX_x86::RegisterContextPOSIX_x86(Thread &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContext(thread, concrete_frame_idx) +{ + m_register_info_ap.reset(register_info); + + switch (register_info->m_target_arch.GetCore()) + { + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + m_reg_info.num_registers = k_num_registers_i386; + m_reg_info.num_gpr_registers = k_num_gpr_registers_i386; + m_reg_info.num_fpr_registers = k_num_fpr_registers_i386; + m_reg_info.num_avx_registers = k_num_avx_registers_i386; + m_reg_info.last_gpr = k_last_gpr_i386; + m_reg_info.first_fpr = k_first_fpr_i386; + m_reg_info.last_fpr = k_last_fpr_i386; + m_reg_info.first_st = fpu_st0_i386; + m_reg_info.last_st = fpu_st7_i386; + m_reg_info.first_mm = fpu_mm0_i386; + m_reg_info.last_mm = fpu_mm7_i386; + m_reg_info.first_xmm = fpu_xmm0_i386; + m_reg_info.last_xmm = fpu_xmm7_i386; + m_reg_info.first_ymm = fpu_ymm0_i386; + m_reg_info.last_ymm = fpu_ymm7_i386; + m_reg_info.first_dr = dr0_i386; + m_reg_info.gpr_flags = gpr_eflags_i386; + break; + case ArchSpec::eCore_x86_64_x86_64: + m_reg_info.num_registers = k_num_registers_x86_64; + m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64; + m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64; + m_reg_info.num_avx_registers = k_num_avx_registers_x86_64; + m_reg_info.last_gpr = k_last_gpr_x86_64; + m_reg_info.first_fpr = k_first_fpr_x86_64; + m_reg_info.last_fpr = k_last_fpr_x86_64; + m_reg_info.first_st = fpu_st0_x86_64; + m_reg_info.last_st = fpu_st7_x86_64; + m_reg_info.first_mm = fpu_mm0_x86_64; + m_reg_info.last_mm = fpu_mm7_x86_64; + m_reg_info.first_xmm = fpu_xmm0_x86_64; + m_reg_info.last_xmm = fpu_xmm15_x86_64; + m_reg_info.first_ymm = fpu_ymm0_x86_64; + m_reg_info.last_ymm = fpu_ymm15_x86_64; + m_reg_info.first_dr = dr0_x86_64; + m_reg_info.gpr_flags = gpr_rflags_x86_64; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } + + // Initialize m_iovec to point to the buffer and buffer size + // using the conventions of Berkeley style UIO structures, as required + // by PTRACE extensions. + m_iovec.iov_base = &m_fpr.xstate.xsave; + m_iovec.iov_len = sizeof(m_fpr.xstate.xsave); + + ::memset(&m_fpr, 0, sizeof(FPR)); + + // elf-core yet to support ReadFPR() + ProcessSP base = CalculateProcess(); + if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) + return; + + m_fpr_type = eNotValid; +} + +RegisterContextPOSIX_x86::~RegisterContextPOSIX_x86() +{ +} + +RegisterContextPOSIX_x86::FPRType RegisterContextPOSIX_x86::GetFPRType() +{ + if (m_fpr_type == eNotValid) + { + // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx + m_fpr_type = eXSAVE; // extended floating-point registers, if available + if (false == ReadFPR()) + m_fpr_type = eFXSAVE; // assume generic floating-point registers + } + return m_fpr_type; +} + +void +RegisterContextPOSIX_x86::Invalidate() +{ +} + +void +RegisterContextPOSIX_x86::InvalidateAllRegisters() +{ +} + +unsigned +RegisterContextPOSIX_x86::GetRegisterOffset(unsigned reg) +{ + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; +} + +unsigned +RegisterContextPOSIX_x86::GetRegisterSize(unsigned reg) +{ + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; +} + +size_t +RegisterContextPOSIX_x86::GetRegisterCount() +{ + size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers; + if (GetFPRType() == eXSAVE) + return num_registers + m_reg_info.num_avx_registers; + return num_registers; +} + +size_t +RegisterContextPOSIX_x86::GetGPRSize() +{ + return m_register_info_ap->GetGPRSize (); +} + +const RegisterInfo * +RegisterContextPOSIX_x86::GetRegisterInfo() +{ + // Commonly, this method is overridden and g_register_infos is copied and specialized. + // So, use GetRegisterInfo() rather than g_register_infos in this scope. + return m_register_info_ap->GetRegisterInfo (); +} + +const RegisterInfo * +RegisterContextPOSIX_x86::GetRegisterInfoAtIndex(size_t reg) +{ + if (reg < m_reg_info.num_registers) + return &GetRegisterInfo()[reg]; + else + return NULL; +} + +size_t +RegisterContextPOSIX_x86::GetRegisterSetCount() +{ + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) + { + if (IsRegisterSetAvailable(set)) + ++sets; + } + + return sets; +} + +const RegisterSet * +RegisterContextPOSIX_x86::GetRegisterSet(size_t set) +{ + if (IsRegisterSetAvailable(set)) + { + switch (m_register_info_ap->m_target_arch.GetCore()) + { + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + return &g_reg_sets_i386[set]; + case ArchSpec::eCore_x86_64_x86_64: + return &g_reg_sets_x86_64[set]; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } + } + return NULL; +} + +const char * +RegisterContextPOSIX_x86::GetRegisterName(unsigned reg) +{ + assert(reg < m_reg_info.num_registers && "Invalid register offset."); + return GetRegisterInfo()[reg].name; +} + +lldb::ByteOrder +RegisterContextPOSIX_x86::GetByteOrder() +{ + // Get the target process whose privileged thread was used for the register read. + lldb::ByteOrder byte_order = eByteOrderInvalid; + Process *process = CalculateProcess().get(); + + if (process) + byte_order = process->GetByteOrder(); + return byte_order; +} + +// Parse ymm registers and into xmm.bytes and ymmh.bytes. +bool RegisterContextPOSIX_x86::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order) +{ + if (!IsAVX(reg)) + return false; + + if (byte_order == eByteOrderLittle) + { + ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, + sizeof(XMMReg)); + ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), + sizeof(YMMHReg)); + return true; + } + + if (byte_order == eByteOrderBig) + { + ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), + sizeof(XMMReg)); + ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, + sizeof(YMMHReg)); + return true; + } + return false; // unsupported or invalid byte order +} + +// Concatenate xmm.bytes with ymmh.bytes +bool RegisterContextPOSIX_x86::CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order) +{ + if (!IsAVX(reg)) + return false; + + if (byte_order == eByteOrderLittle) + { + ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, + m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + sizeof(XMMReg)); + ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), + m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + sizeof(YMMHReg)); + return true; + } + + if (byte_order == eByteOrderBig) + { + ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), + m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + sizeof(XMMReg)); + ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, + m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + sizeof(YMMHReg)); + return true; + } + return false; // unsupported or invalid byte order +} + +bool +RegisterContextPOSIX_x86::IsRegisterSetAvailable(size_t set_index) +{ + // Note: Extended register sets are assumed to be at the end of g_reg_sets... + size_t num_sets = k_num_register_sets - k_num_extended_register_sets; + + if (GetFPRType() == eXSAVE) // ...and to start with AVX registers. + ++num_sets; + return (set_index < num_sets); +} + + +// Used when parsing DWARF and EH frame information and any other +// object file sections that contain register numbers in them. +uint32_t +RegisterContextPOSIX_x86::ConvertRegisterKindToRegisterNumber(uint32_t kind, + uint32_t num) +{ + const uint32_t num_regs = GetRegisterCount(); + + assert (kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) + { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); + + if (reg_info->kinds[kind] == num) + return reg_idx; + } + + return LLDB_INVALID_REGNUM; +} + diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h new file mode 100644 index 000000000000..5e922025b830 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX_x86.h @@ -0,0 +1,462 @@ +//===-- RegisterContextPOSIX_x86.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextPOSIX_x86_H_ +#define liblldb_RegisterContextPOSIX_x86_H_ + +#include "lldb/Core/Log.h" +#include "RegisterContextPOSIX.h" +#include "RegisterContext_x86.h" + +class ProcessMonitor; + +//--------------------------------------------------------------------------- +// Internal codes for all i386 registers. +//--------------------------------------------------------------------------- +enum +{ + k_first_gpr_i386, + gpr_eax_i386 = k_first_gpr_i386, + gpr_ebx_i386, + gpr_ecx_i386, + gpr_edx_i386, + gpr_edi_i386, + gpr_esi_i386, + gpr_ebp_i386, + gpr_esp_i386, + gpr_eip_i386, + gpr_eflags_i386, + gpr_cs_i386, + gpr_fs_i386, + gpr_gs_i386, + gpr_ss_i386, + gpr_ds_i386, + gpr_es_i386, + + k_first_alias_i386, + gpr_ax_i386 = k_first_alias_i386, + gpr_bx_i386, + gpr_cx_i386, + gpr_dx_i386, + gpr_di_i386, + gpr_si_i386, + gpr_bp_i386, + gpr_sp_i386, + gpr_ah_i386, + gpr_bh_i386, + gpr_ch_i386, + gpr_dh_i386, + gpr_al_i386, + gpr_bl_i386, + gpr_cl_i386, + gpr_dl_i386, + k_last_alias_i386 = gpr_dl_i386, + + k_last_gpr_i386 = k_last_alias_i386, + + k_first_fpr_i386, + fpu_fctrl_i386 = k_first_fpr_i386, + fpu_fstat_i386, + fpu_ftag_i386, + fpu_fop_i386, + fpu_fiseg_i386, + fpu_fioff_i386, + fpu_foseg_i386, + fpu_fooff_i386, + fpu_mxcsr_i386, + fpu_mxcsrmask_i386, + fpu_st0_i386, + fpu_st1_i386, + fpu_st2_i386, + fpu_st3_i386, + fpu_st4_i386, + fpu_st5_i386, + fpu_st6_i386, + fpu_st7_i386, + fpu_mm0_i386, + fpu_mm1_i386, + fpu_mm2_i386, + fpu_mm3_i386, + fpu_mm4_i386, + fpu_mm5_i386, + fpu_mm6_i386, + fpu_mm7_i386, + fpu_xmm0_i386, + fpu_xmm1_i386, + fpu_xmm2_i386, + fpu_xmm3_i386, + fpu_xmm4_i386, + fpu_xmm5_i386, + fpu_xmm6_i386, + fpu_xmm7_i386, + k_last_fpr_i386 = fpu_xmm7_i386, + + k_first_avx_i386, + fpu_ymm0_i386 = k_first_avx_i386, + fpu_ymm1_i386, + fpu_ymm2_i386, + fpu_ymm3_i386, + fpu_ymm4_i386, + fpu_ymm5_i386, + fpu_ymm6_i386, + fpu_ymm7_i386, + k_last_avx_i386 = fpu_ymm7_i386, + + dr0_i386, + dr1_i386, + dr2_i386, + dr3_i386, + dr4_i386, + dr5_i386, + dr6_i386, + dr7_i386, + + k_num_registers_i386, + k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1, + k_num_fpr_registers_i386 = k_last_fpr_i386 - k_first_fpr_i386 + 1, + k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1 +}; + +//--------------------------------------------------------------------------- +// Internal codes for all x86_64 registers. +//--------------------------------------------------------------------------- +enum +{ + k_first_gpr_x86_64, + gpr_rax_x86_64 = k_first_gpr_x86_64, + gpr_rbx_x86_64, + gpr_rcx_x86_64, + gpr_rdx_x86_64, + gpr_rdi_x86_64, + gpr_rsi_x86_64, + gpr_rbp_x86_64, + gpr_rsp_x86_64, + gpr_r8_x86_64, + gpr_r9_x86_64, + gpr_r10_x86_64, + gpr_r11_x86_64, + gpr_r12_x86_64, + gpr_r13_x86_64, + gpr_r14_x86_64, + gpr_r15_x86_64, + gpr_rip_x86_64, + gpr_rflags_x86_64, + gpr_cs_x86_64, + gpr_fs_x86_64, + gpr_gs_x86_64, + gpr_ss_x86_64, + gpr_ds_x86_64, + gpr_es_x86_64, + + k_first_alias_x86_64, + gpr_eax_x86_64 = k_first_alias_x86_64, + gpr_ebx_x86_64, + gpr_ecx_x86_64, + gpr_edx_x86_64, + gpr_edi_x86_64, + gpr_esi_x86_64, + gpr_ebp_x86_64, + gpr_esp_x86_64, + gpr_r8d_x86_64, // Low 32 bits of r8 + gpr_r9d_x86_64, // Low 32 bits of r9 + gpr_r10d_x86_64, // Low 32 bits of r10 + gpr_r11d_x86_64, // Low 32 bits of r11 + gpr_r12d_x86_64, // Low 32 bits of r12 + gpr_r13d_x86_64, // Low 32 bits of r13 + gpr_r14d_x86_64, // Low 32 bits of r14 + gpr_r15d_x86_64, // Low 32 bits of r15 + gpr_ax_x86_64, + gpr_bx_x86_64, + gpr_cx_x86_64, + gpr_dx_x86_64, + gpr_di_x86_64, + gpr_si_x86_64, + gpr_bp_x86_64, + gpr_sp_x86_64, + gpr_r8w_x86_64, // Low 16 bits of r8 + gpr_r9w_x86_64, // Low 16 bits of r9 + gpr_r10w_x86_64, // Low 16 bits of r10 + gpr_r11w_x86_64, // Low 16 bits of r11 + gpr_r12w_x86_64, // Low 16 bits of r12 + gpr_r13w_x86_64, // Low 16 bits of r13 + gpr_r14w_x86_64, // Low 16 bits of r14 + gpr_r15w_x86_64, // Low 16 bits of r15 + gpr_ah_x86_64, + gpr_bh_x86_64, + gpr_ch_x86_64, + gpr_dh_x86_64, + gpr_al_x86_64, + gpr_bl_x86_64, + gpr_cl_x86_64, + gpr_dl_x86_64, + gpr_dil_x86_64, + gpr_sil_x86_64, + gpr_bpl_x86_64, + gpr_spl_x86_64, + gpr_r8l_x86_64, // Low 8 bits of r8 + gpr_r9l_x86_64, // Low 8 bits of r9 + gpr_r10l_x86_64, // Low 8 bits of r10 + gpr_r11l_x86_64, // Low 8 bits of r11 + gpr_r12l_x86_64, // Low 8 bits of r12 + gpr_r13l_x86_64, // Low 8 bits of r13 + gpr_r14l_x86_64, // Low 8 bits of r14 + gpr_r15l_x86_64, // Low 8 bits of r15 + k_last_alias_x86_64 = gpr_r15l_x86_64, + + k_last_gpr_x86_64 = k_last_alias_x86_64, + + k_first_fpr_x86_64, + fpu_fctrl_x86_64 = k_first_fpr_x86_64, + fpu_fstat_x86_64, + fpu_ftag_x86_64, + fpu_fop_x86_64, + fpu_fiseg_x86_64, + fpu_fioff_x86_64, + fpu_foseg_x86_64, + fpu_fooff_x86_64, + fpu_mxcsr_x86_64, + fpu_mxcsrmask_x86_64, + fpu_st0_x86_64, + fpu_st1_x86_64, + fpu_st2_x86_64, + fpu_st3_x86_64, + fpu_st4_x86_64, + fpu_st5_x86_64, + fpu_st6_x86_64, + fpu_st7_x86_64, + fpu_mm0_x86_64, + fpu_mm1_x86_64, + fpu_mm2_x86_64, + fpu_mm3_x86_64, + fpu_mm4_x86_64, + fpu_mm5_x86_64, + fpu_mm6_x86_64, + fpu_mm7_x86_64, + fpu_xmm0_x86_64, + fpu_xmm1_x86_64, + fpu_xmm2_x86_64, + fpu_xmm3_x86_64, + fpu_xmm4_x86_64, + fpu_xmm5_x86_64, + fpu_xmm6_x86_64, + fpu_xmm7_x86_64, + fpu_xmm8_x86_64, + fpu_xmm9_x86_64, + fpu_xmm10_x86_64, + fpu_xmm11_x86_64, + fpu_xmm12_x86_64, + fpu_xmm13_x86_64, + fpu_xmm14_x86_64, + fpu_xmm15_x86_64, + k_last_fpr_x86_64 = fpu_xmm15_x86_64, + + k_first_avx_x86_64, + fpu_ymm0_x86_64 = k_first_avx_x86_64, + fpu_ymm1_x86_64, + fpu_ymm2_x86_64, + fpu_ymm3_x86_64, + fpu_ymm4_x86_64, + fpu_ymm5_x86_64, + fpu_ymm6_x86_64, + fpu_ymm7_x86_64, + fpu_ymm8_x86_64, + fpu_ymm9_x86_64, + fpu_ymm10_x86_64, + fpu_ymm11_x86_64, + fpu_ymm12_x86_64, + fpu_ymm13_x86_64, + fpu_ymm14_x86_64, + fpu_ymm15_x86_64, + k_last_avx_x86_64 = fpu_ymm15_x86_64, + + dr0_x86_64, + dr1_x86_64, + dr2_x86_64, + dr3_x86_64, + dr4_x86_64, + dr5_x86_64, + dr6_x86_64, + dr7_x86_64, + + k_num_registers_x86_64, + k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1, + k_num_fpr_registers_x86_64 = k_last_fpr_x86_64 - k_first_fpr_x86_64 + 1, + k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1 +}; + +class RegisterContextPOSIX_x86 + : public lldb_private::RegisterContext +{ +public: + RegisterContextPOSIX_x86 (lldb_private::Thread &thread, + uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info); + + ~RegisterContextPOSIX_x86(); + + void + Invalidate(); + + void + InvalidateAllRegisters(); + + size_t + GetRegisterCount(); + + virtual size_t + GetGPRSize(); + + virtual unsigned + GetRegisterSize(unsigned reg); + + virtual unsigned + GetRegisterOffset(unsigned reg); + + const lldb_private::RegisterInfo * + GetRegisterInfoAtIndex(size_t reg); + + size_t + GetRegisterSetCount(); + + const lldb_private::RegisterSet * + GetRegisterSet(size_t set); + + const char * + GetRegisterName(unsigned reg); + + uint32_t + ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); + + //--------------------------------------------------------------------------- + // Note: prefer kernel definitions over user-land + //--------------------------------------------------------------------------- + enum FPRType + { + eNotValid = 0, + eFSAVE, // TODO + eFXSAVE, + eSOFT, // TODO + eXSAVE + }; + + static uint32_t g_contained_eax[]; + static uint32_t g_contained_ebx[]; + static uint32_t g_contained_ecx[]; + static uint32_t g_contained_edx[]; + static uint32_t g_contained_edi[]; + static uint32_t g_contained_esi[]; + static uint32_t g_contained_ebp[]; + static uint32_t g_contained_esp[]; + + static uint32_t g_invalidate_eax[]; + static uint32_t g_invalidate_ebx[]; + static uint32_t g_invalidate_ecx[]; + static uint32_t g_invalidate_edx[]; + static uint32_t g_invalidate_edi[]; + static uint32_t g_invalidate_esi[]; + static uint32_t g_invalidate_ebp[]; + static uint32_t g_invalidate_esp[]; + + static uint32_t g_contained_rax[]; + static uint32_t g_contained_rbx[]; + static uint32_t g_contained_rcx[]; + static uint32_t g_contained_rdx[]; + static uint32_t g_contained_rdi[]; + static uint32_t g_contained_rsi[]; + static uint32_t g_contained_rbp[]; + static uint32_t g_contained_rsp[]; + static uint32_t g_contained_r8[]; + static uint32_t g_contained_r9[]; + static uint32_t g_contained_r10[]; + static uint32_t g_contained_r11[]; + static uint32_t g_contained_r12[]; + static uint32_t g_contained_r13[]; + static uint32_t g_contained_r14[]; + static uint32_t g_contained_r15[]; + + static uint32_t g_invalidate_rax[]; + static uint32_t g_invalidate_rbx[]; + static uint32_t g_invalidate_rcx[]; + static uint32_t g_invalidate_rdx[]; + static uint32_t g_invalidate_rdi[]; + static uint32_t g_invalidate_rsi[]; + static uint32_t g_invalidate_rbp[]; + static uint32_t g_invalidate_rsp[]; + static uint32_t g_invalidate_r8[]; + static uint32_t g_invalidate_r9[]; + static uint32_t g_invalidate_r10[]; + static uint32_t g_invalidate_r11[]; + static uint32_t g_invalidate_r12[]; + static uint32_t g_invalidate_r13[]; + static uint32_t g_invalidate_r14[]; + static uint32_t g_invalidate_r15[]; + +protected: + struct RegInfo + { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; + uint32_t num_avx_registers; + + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; + + uint32_t first_st; + uint32_t last_st; + uint32_t first_mm; + uint32_t last_mm; + uint32_t first_xmm; + uint32_t last_xmm; + uint32_t first_ymm; + uint32_t last_ymm; + + uint32_t first_dr; + uint32_t gpr_flags; + }; + + uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64]; // 64-bit general purpose registers. + RegInfo m_reg_info; + FPRType m_fpr_type; // determines the type of data stored by union FPR, if any. + FPR m_fpr; // floating-point registers including extended register sets. + IOVEC m_iovec; // wrapper for xsave. + YMM m_ymm_set; // copy of ymmh and xmm register halves. + std::unique_ptr<RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) + + // Determines if an extended register set is supported on the processor running the inferior process. + virtual bool + IsRegisterSetAvailable(size_t set_index); + + virtual const lldb_private::RegisterInfo * + GetRegisterInfo(); + + bool + IsGPR(unsigned reg); + + bool + IsFPR(unsigned reg); + + bool + IsAVX(unsigned reg); + + lldb::ByteOrder GetByteOrder(); + + bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order); + bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order); + bool IsFPR(unsigned reg, FPRType fpr_type); + FPRType GetFPRType(); + + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; +}; + +#endif // #ifndef liblldb_RegisterContextPOSIX_x86_H_ diff --git a/source/Plugins/Process/POSIX/RegisterContext_i386.cpp b/source/Plugins/Process/POSIX/RegisterContext_i386.cpp deleted file mode 100644 index 49676bd3fc73..000000000000 --- a/source/Plugins/Process/POSIX/RegisterContext_i386.cpp +++ /dev/null @@ -1,551 +0,0 @@ -//===-- RegisterContextPOSIX_i386.cpp ---------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Core/DataExtractor.h" -#include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" -#include "llvm/Support/Compiler.h" - -#include "ProcessPOSIX.h" -#include "ProcessPOSIXLog.h" -#include "ProcessMonitor.h" -#include "RegisterContext_i386.h" -#include "RegisterContext_x86.h" - -using namespace lldb_private; -using namespace lldb; - -enum -{ - k_first_gpr, - gpr_eax = k_first_gpr, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_ss, - gpr_eflags, -#ifdef __FreeBSD__ - gpr_orig_ax, -#endif - gpr_eip, - gpr_cs, - gpr_ds, - gpr_es, - gpr_fs, - gpr_gs, - k_last_gpr = gpr_gs, - - k_first_fpr, - fpu_fcw = k_first_fpr, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_foo, - fpu_fos, - fpu_mxcsr, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - k_last_fpr = fpu_xmm7, - - k_num_registers, - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, - k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 -}; - -// Number of register sets provided by this context. -enum -{ - k_num_register_sets = 2 -}; - -static const -uint32_t g_gpr_regnums[k_num_gpr_registers] = -{ - gpr_eax, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_ss, - gpr_eflags, -#ifdef __FreeBSD__ - gpr_orig_ax, -#endif - gpr_eip, - gpr_cs, - gpr_ds, - gpr_es, - gpr_fs, - gpr_gs, -}; - -static const uint32_t -g_fpu_regnums[k_num_fpu_registers] = -{ - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_foo, - fpu_fos, - fpu_mxcsr, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, -}; - -static const RegisterSet -g_reg_sets[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } -}; - -// Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (offsetof(RegisterContext_i386::UserArea, regs) + \ - offsetof(RegisterContext_i386::GPR, regname)) - -// Computes the offset of the given FPR in the user data area. -#define FPR_OFFSET(regname) \ - (offsetof(RegisterContext_i386::UserArea, i387) + \ - offsetof(RegisterContext_i386::FPU, regname)) - -// Number of bytes needed to represent a GPR. -#define GPR_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg) - -// Number of bytes needed to represent a FPR. -#define FPR_SIZE(reg) sizeof(((RegisterContext_i386::FPU*)NULL)->reg) - -// Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((RegisterContext_i386::MMSReg*)NULL)->bytes) - -// Number of bytes needed to represent an XMM register. -#define XMM_SIZE sizeof(RegisterContext_i386::XMMReg) - -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg }, NULL, NULL } - -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg }, NULL, NULL } - -#define DEFINE_FP(reg, i) \ - { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { dwarf_##reg##i, dwarf_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL } - -#define DEFINE_XMM(reg, i) \ - { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { dwarf_##reg##i, dwarf_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL } - -static RegisterInfo -g_register_infos[k_num_registers] = -{ - // General purpose registers. - DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax), - DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx), - DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx), - DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx), - DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi), - DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi), - DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp), - DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp), - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss), - DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags), - DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip), - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs), - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds), - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es), - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs), - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs), - - // Floating point registers. - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw), - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw), - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw), - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop), - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip), - DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), - DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp), - DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr), - - DEFINE_FP(stmm, 0), - DEFINE_FP(stmm, 1), - DEFINE_FP(stmm, 2), - DEFINE_FP(stmm, 3), - DEFINE_FP(stmm, 4), - DEFINE_FP(stmm, 5), - DEFINE_FP(stmm, 6), - DEFINE_FP(stmm, 7), - - // XMM registers - DEFINE_XMM(xmm, 0), - DEFINE_XMM(xmm, 1), - DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), - DEFINE_XMM(xmm, 4), - DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), - DEFINE_XMM(xmm, 7), - -}; - -#ifndef NDEBUG -static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); -#endif - -static unsigned GetRegOffset(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_offset; -} - -static unsigned GetRegSize(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_size; -} - -RegisterContext_i386::RegisterContext_i386(Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContextPOSIX(thread, concrete_frame_idx) -{ -} - -RegisterContext_i386::~RegisterContext_i386() -{ -} - -ProcessMonitor & -RegisterContext_i386::GetMonitor() -{ - ProcessSP base = CalculateProcess(); - ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get()); - return process->GetMonitor(); -} - -void -RegisterContext_i386::Invalidate() -{ -} - -void -RegisterContext_i386::InvalidateAllRegisters() -{ -} - -size_t -RegisterContext_i386::GetRegisterCount() -{ - assert(k_num_register_infos == k_num_registers); - return k_num_registers; -} - -const RegisterInfo * -RegisterContext_i386::GetRegisterInfoAtIndex(size_t reg) -{ - assert(k_num_register_infos == k_num_registers); - if (reg < k_num_registers) - return &g_register_infos[reg]; - else - return NULL; -} - -size_t -RegisterContext_i386::GetRegisterSetCount() -{ - return k_num_register_sets; -} - -const RegisterSet * -RegisterContext_i386::GetRegisterSet(size_t set) -{ - if (set < k_num_register_sets) - return &g_reg_sets[set]; - else - return NULL; -} - -unsigned -RegisterContext_i386::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers; reg++) - { - if (g_register_infos[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers && "Invalid register offset."); - return reg; -} - -const char * -RegisterContext_i386::GetRegisterName(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register offset."); - return g_register_infos[reg].name; -} - -bool -RegisterContext_i386::ReadRegister(const RegisterInfo *reg_info, - RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(m_thread.GetID(), GetRegOffset(reg), - GetRegisterName(reg), GetRegSize(reg), value); -} - -bool -RegisterContext_i386::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - return false; -} - -bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info, - const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(m_thread.GetID(), GetRegOffset(reg), - GetRegisterName(reg), value); -} - -bool -RegisterContext_i386::WriteAllRegisterValues(const DataBufferSP &data) -{ - return false; -} - -bool -RegisterContext_i386::UpdateAfterBreakpoint() -{ - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - SetPC(pc - 1); - return true; -} - -uint32_t -RegisterContext_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind, - uint32_t num) -{ - if (kind == eRegisterKindGeneric) - { - switch (num) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_eip; - case LLDB_REGNUM_GENERIC_SP: return gpr_esp; - case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; - case LLDB_REGNUM_GENERIC_RA: - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) - { - switch (num) - { - case dwarf_eax: return gpr_eax; - case dwarf_edx: return gpr_edx; - case dwarf_ecx: return gpr_ecx; - case dwarf_ebx: return gpr_ebx; - case dwarf_esi: return gpr_esi; - case dwarf_edi: return gpr_edi; - case dwarf_ebp: return gpr_ebp; - case dwarf_esp: return gpr_esp; - case dwarf_eip: return gpr_eip; - case dwarf_xmm0: return fpu_xmm0; - case dwarf_xmm1: return fpu_xmm1; - case dwarf_xmm2: return fpu_xmm2; - case dwarf_xmm3: return fpu_xmm3; - case dwarf_xmm4: return fpu_xmm4; - case dwarf_xmm5: return fpu_xmm5; - case dwarf_xmm6: return fpu_xmm6; - case dwarf_xmm7: return fpu_xmm7; - case dwarf_stmm0: return fpu_stmm0; - case dwarf_stmm1: return fpu_stmm1; - case dwarf_stmm2: return fpu_stmm2; - case dwarf_stmm3: return fpu_stmm3; - case dwarf_stmm4: return fpu_stmm4; - case dwarf_stmm5: return fpu_stmm5; - case dwarf_stmm6: return fpu_stmm6; - case dwarf_stmm7: return fpu_stmm7; - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGDB) - { - switch (num) - { - case gdb_eax : return gpr_eax; - case gdb_ebx : return gpr_ebx; - case gdb_ecx : return gpr_ecx; - case gdb_edx : return gpr_edx; - case gdb_esi : return gpr_esi; - case gdb_edi : return gpr_edi; - case gdb_ebp : return gpr_ebp; - case gdb_esp : return gpr_esp; - case gdb_eip : return gpr_eip; - case gdb_eflags : return gpr_eflags; - case gdb_cs : return gpr_cs; - case gdb_ss : return gpr_ss; - case gdb_ds : return gpr_ds; - case gdb_es : return gpr_es; - case gdb_fs : return gpr_fs; - case gdb_gs : return gpr_gs; - case gdb_stmm0 : return fpu_stmm0; - case gdb_stmm1 : return fpu_stmm1; - case gdb_stmm2 : return fpu_stmm2; - case gdb_stmm3 : return fpu_stmm3; - case gdb_stmm4 : return fpu_stmm4; - case gdb_stmm5 : return fpu_stmm5; - case gdb_stmm6 : return fpu_stmm6; - case gdb_stmm7 : return fpu_stmm7; - case gdb_fcw : return fpu_fcw; - case gdb_fsw : return fpu_fsw; - case gdb_ftw : return fpu_ftw; - case gdb_fpu_cs : return fpu_cs; - case gdb_ip : return fpu_ip; - case gdb_fpu_ds : return fpu_fos; - case gdb_dp : return fpu_foo; - case gdb_fop : return fpu_fop; - case gdb_xmm0 : return fpu_xmm0; - case gdb_xmm1 : return fpu_xmm1; - case gdb_xmm2 : return fpu_xmm2; - case gdb_xmm3 : return fpu_xmm3; - case gdb_xmm4 : return fpu_xmm4; - case gdb_xmm5 : return fpu_xmm5; - case gdb_xmm6 : return fpu_xmm6; - case gdb_xmm7 : return fpu_xmm7; - case gdb_mxcsr : return fpu_mxcsr; - default: - return LLDB_INVALID_REGNUM; - } - } - else if (kind == eRegisterKindLLDB) - { - return num; - } - - return LLDB_INVALID_REGNUM; -} - -bool -RegisterContext_i386::HardwareSingleStep(bool enable) -{ - enum { TRACE_BIT = 0x100 }; - uint64_t eflags; - - if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL) - return false; - - if (enable) - { - if (eflags & TRACE_BIT) - return true; - - eflags |= TRACE_BIT; - } - else - { - if (!(eflags & TRACE_BIT)) - return false; - - eflags &= ~TRACE_BIT; - } - - return WriteRegisterFromUnsigned(gpr_eflags, eflags); -} - -void -RegisterContext_i386::LogGPR(const char *title) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); - if (log) - { - if (title) - log->Printf ("%s", title); - for (uint32_t i=0; i<k_num_gpr_registers; i++) - { - uint32_t reg = gpr_eax + i; - log->Printf("%12s = 0x%8.8" PRIx64, g_register_infos[reg].name, ((uint64_t*)&user.regs)[reg]); - } - } -} - -bool -RegisterContext_i386::ReadGPR() -{ - bool result; - - ProcessMonitor &monitor = GetMonitor(); - result = monitor.ReadGPR(m_thread.GetID(), &user.regs, sizeof(user.regs)); - LogGPR("RegisterContext_i386::ReadGPR()"); - return result; -} - -bool -RegisterContext_i386::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(m_thread.GetID(), &user.i387, sizeof(user.i387)); -} diff --git a/source/Plugins/Process/POSIX/RegisterContext_i386.h b/source/Plugins/Process/POSIX/RegisterContext_i386.h deleted file mode 100644 index 96066c47b815..000000000000 --- a/source/Plugins/Process/POSIX/RegisterContext_i386.h +++ /dev/null @@ -1,169 +0,0 @@ -//===-- RegisterContext_i386.h ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContext_i386_h_ -#define liblldb_RegisterContext_i386_h_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/Log.h" -#include "RegisterContextPOSIX.h" - -class RegisterContext_i386 : public RegisterContextPOSIX -{ -public: - RegisterContext_i386(lldb_private::Thread &thread, - uint32_t concreate_frame_idx); - - ~RegisterContext_i386(); - - void - Invalidate(); - - void - InvalidateAllRegisters(); - - size_t - GetRegisterCount(); - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg); - - size_t - GetRegisterSetCount(); - - const lldb_private::RegisterSet * - GetRegisterSet(size_t set); - - unsigned - GetRegisterIndexFromOffset(unsigned offset); - - const char * - GetRegisterName(unsigned reg); - - bool - ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value); - - bool - ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data); - - virtual bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - - bool - WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value); - - bool - WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data, - uint32_t data_offset = 0); - - virtual bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); - - bool - HardwareSingleStep(bool enable); - - bool - UpdateAfterBreakpoint(); - - struct GPR - { - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t esi; - uint32_t edi; - uint32_t ebp; - uint32_t eax; - uint32_t ds; - uint32_t es; - uint32_t fs; - uint32_t gs; - uint32_t orig_ax; - uint32_t eip; - uint32_t cs; - uint32_t eflags; - uint32_t esp; - uint32_t ss; - }; - - struct MMSReg - { - uint8_t bytes[8]; - }; - - struct XMMReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - uint16_t fcw; - uint16_t fsw; - uint16_t ftw; - uint16_t fop; - uint32_t ip; - uint32_t cs; - uint32_t foo; - uint32_t fos; - uint32_t mxcsr; - uint32_t reserved; - MMSReg stmm[8]; - XMMReg xmm[8]; - uint32_t pad[56]; - }; - - // A user area like this no longer exists on FreeBSD - // making this a Linux artifact. Nonetheless, it is safe - // leaving it here while the code is being cleaned up and generalized. - - struct UserArea - { - GPR regs; // General purpose registers. - int32_t fpvalid; // True if FPU is being used. - FPU i387; // FPU registers. - uint32_t tsize; // Text segment size. - uint32_t dsize; // Data segment size. - uint32_t ssize; // Stack segment size. - uint32_t start_code; // VM address of text. - uint32_t start_stack; // VM address of stack bottom (top in rsp). - int32_t signal; // Signal causing core dump. - int32_t reserved; // Unused. - uint32_t ar0; // Location of GPR's. - FPU* fpstate; // Location of FPR's. - uint32_t magic; // Identifier for core dumps. - char u_comm[32]; // Command causing core dump. - uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). - }; -private: - UserArea user; - - ProcessMonitor &GetMonitor(); - - void LogGPR(const char *title); - - bool ReadGPR(); - bool ReadFPR(); -}; - -#endif // #ifndef liblldb_RegisterContext_i386_h_ diff --git a/source/Plugins/Process/POSIX/RegisterContext_mips64.h b/source/Plugins/Process/POSIX/RegisterContext_mips64.h new file mode 100644 index 000000000000..dfd473d7cbec --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterContext_mips64.h @@ -0,0 +1,104 @@ +//===-- RegisterContext_mips64.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContext_mips64_H_ +#define liblldb_RegisterContext_mips64_H_ + +// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF) +enum +{ + // GP Registers + gcc_dwarf_zero_mips64 = 0, + gcc_dwarf_r1_mips64, + gcc_dwarf_r2_mips64, + gcc_dwarf_r3_mips64, + gcc_dwarf_r4_mips64, + gcc_dwarf_r5_mips64, + gcc_dwarf_r6_mips64, + gcc_dwarf_r7_mips64, + gcc_dwarf_r8_mips64, + gcc_dwarf_r9_mips64, + gcc_dwarf_r10_mips64, + gcc_dwarf_r11_mips64, + gcc_dwarf_r12_mips64, + gcc_dwarf_r13_mips64, + gcc_dwarf_r14_mips64, + gcc_dwarf_r15_mips64, + gcc_dwarf_r16_mips64, + gcc_dwarf_r17_mips64, + gcc_dwarf_r18_mips64, + gcc_dwarf_r19_mips64, + gcc_dwarf_r20_mips64, + gcc_dwarf_r21_mips64, + gcc_dwarf_r22_mips64, + gcc_dwarf_r23_mips64, + gcc_dwarf_r24_mips64, + gcc_dwarf_r25_mips64, + gcc_dwarf_r26_mips64, + gcc_dwarf_r27_mips64, + gcc_dwarf_gp_mips64, + gcc_dwarf_sp_mips64, + gcc_dwarf_r30_mips64, + gcc_dwarf_ra_mips64, + gcc_dwarf_sr_mips64, + gcc_dwarf_lo_mips64, + gcc_dwarf_hi_mips64, + gcc_dwarf_bad_mips64, + gcc_dwarf_cause_mips64, + gcc_dwarf_pc_mips64, + gcc_dwarf_ic_mips64, + gcc_dwarf_dummy_mips64 +}; + +// GDB Register numbers (eRegisterKindGDB) +enum +{ + gdb_zero_mips64 = 0, + gdb_r1_mips64, + gdb_r2_mips64, + gdb_r3_mips64, + gdb_r4_mips64, + gdb_r5_mips64, + gdb_r6_mips64, + gdb_r7_mips64, + gdb_r8_mips64, + gdb_r9_mips64, + gdb_r10_mips64, + gdb_r11_mips64, + gdb_r12_mips64, + gdb_r13_mips64, + gdb_r14_mips64, + gdb_r15_mips64, + gdb_r16_mips64, + gdb_r17_mips64, + gdb_r18_mips64, + gdb_r19_mips64, + gdb_r20_mips64, + gdb_r21_mips64, + gdb_r22_mips64, + gdb_r23_mips64, + gdb_r24_mips64, + gdb_r25_mips64, + gdb_r26_mips64, + gdb_r27_mips64, + gdb_gp_mips64, + gdb_sp_mips64, + gdb_r30_mips64, + gdb_ra_mips64, + gdb_sr_mips64, + gdb_lo_mips64, + gdb_hi_mips64, + gdb_bad_mips64, + gdb_cause_mips64, + gdb_pc_mips64, + gdb_ic_mips64, + gdb_dummy_mips64 +}; + +#endif // liblldb_RegisterContext_mips64_H_ diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86.h b/source/Plugins/Process/POSIX/RegisterContext_x86.h index 61a25c407758..df3e1e5a84bf 100644 --- a/source/Plugins/Process/POSIX/RegisterContext_x86.h +++ b/source/Plugins/Process/POSIX/RegisterContext_x86.h @@ -1,4 +1,4 @@ -//===-- RegisterContext_x86.h ---------------------------*- C++ -*-===// +//===-- RegisterContext_x86.h -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,101 +10,470 @@ #ifndef liblldb_RegisterContext_x86_H_ #define liblldb_RegisterContext_x86_H_ +//--------------------------------------------------------------------------- +// i386 gcc, dwarf, gdb enums +//--------------------------------------------------------------------------- + +// Register numbers seen in eh_frame (eRegisterKindGCC) +// +// From Jason Molenda: "gcc registers" is the register numbering used in the eh_frame +// CFI. The only registers that are described in eh_frame CFI are those that are +// preserved across function calls aka callee-saved aka non-volatile. And none +// of the floating point registers on x86 are preserved across function calls. +// +// The only reason there is a "gcc register" and a "dwarf register" is because of a +// mistake years and years ago with i386 where they got esp and ebp +// backwards when they emitted the eh_frame instructions. Once there were +// binaries In The Wild using the reversed numbering, we had to stick with it +// forever. +enum +{ + // 2nd parameter in DwarfRegNum() is regnum for exception handling on x86-32. + // See http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register + gcc_eax_i386 = 0, + gcc_ecx_i386, + gcc_edx_i386, + gcc_ebx_i386, + gcc_ebp_i386, // Warning: these are switched from dwarf values + gcc_esp_i386, // + gcc_esi_i386, + gcc_edi_i386, + gcc_eip_i386, + gcc_eflags_i386, + gcc_st0_i386 = 12, + gcc_st1_i386, + gcc_st2_i386, + gcc_st3_i386, + gcc_st4_i386, + gcc_st5_i386, + gcc_st6_i386, + gcc_st7_i386, + gcc_xmm0_i386 = 21, + gcc_xmm1_i386, + gcc_xmm2_i386, + gcc_xmm3_i386, + gcc_xmm4_i386, + gcc_xmm5_i386, + gcc_xmm6_i386, + gcc_xmm7_i386, + gcc_mm0_i386 = 29, + gcc_mm1_i386, + gcc_mm2_i386, + gcc_mm3_i386, + gcc_mm4_i386, + gcc_mm5_i386, + gcc_mm6_i386, + gcc_mm7_i386, +}; + +// DWARF register numbers (eRegisterKindDWARF) +// Intel's x86 or IA-32 enum { - gcc_eax = 0, - gcc_ecx, - gcc_edx, - gcc_ebx, - gcc_ebp, - gcc_esp, - gcc_esi, - gcc_edi, - gcc_eip, - gcc_eflags + // General Purpose Registers. + dwarf_eax_i386 = 0, + dwarf_ecx_i386, + dwarf_edx_i386, + dwarf_ebx_i386, + dwarf_esp_i386, + dwarf_ebp_i386, + dwarf_esi_i386, + dwarf_edi_i386, + dwarf_eip_i386, + dwarf_eflags_i386, + // Floating Point Registers + dwarf_st0_i386 = 11, + dwarf_st1_i386, + dwarf_st2_i386, + dwarf_st3_i386, + dwarf_st4_i386, + dwarf_st5_i386, + dwarf_st6_i386, + dwarf_st7_i386, + // SSE Registers + dwarf_xmm0_i386 = 21, + dwarf_xmm1_i386, + dwarf_xmm2_i386, + dwarf_xmm3_i386, + dwarf_xmm4_i386, + dwarf_xmm5_i386, + dwarf_xmm6_i386, + dwarf_xmm7_i386, + // MMX Registers + dwarf_mm0_i386 = 29, + dwarf_mm1_i386, + dwarf_mm2_i386, + dwarf_mm3_i386, + dwarf_mm4_i386, + dwarf_mm5_i386, + dwarf_mm6_i386, + dwarf_mm7_i386, + dwarf_fctrl_i386 = 37, // x87 control word + dwarf_fstat_i386 = 38, // x87 status word + dwarf_mxcsr_i386 = 39, + dwarf_es_i386 = 40, + dwarf_cs_i386 = 41, + dwarf_ss_i386 = 42, + dwarf_ds_i386 = 43, + dwarf_fs_i386 = 44, + dwarf_gs_i386 = 45 + + // I believe the ymm registers use the dwarf_xmm%_i386 register numbers and + // then differentiate based on size of the register. }; +// Register numbers GDB uses (eRegisterKindGDB) +// +// From Jason Molenda: The "gdb numbers" are what you would see in the stabs debug format. enum { - dwarf_eax = 0, - dwarf_ecx, - dwarf_edx, - dwarf_ebx, - dwarf_esp, - dwarf_ebp, - dwarf_esi, - dwarf_edi, - dwarf_eip, - dwarf_eflags, - dwarf_stmm0 = 11, - dwarf_stmm1, - dwarf_stmm2, - dwarf_stmm3, - dwarf_stmm4, - dwarf_stmm5, - dwarf_stmm6, - dwarf_stmm7, - dwarf_xmm0 = 21, - dwarf_xmm1, - dwarf_xmm2, - dwarf_xmm3, - dwarf_xmm4, - dwarf_xmm5, - dwarf_xmm6, - dwarf_xmm7 + gdb_eax_i386, + gdb_ecx_i386, + gdb_edx_i386, + gdb_ebx_i386, + gdb_esp_i386, + gdb_ebp_i386, + gdb_esi_i386, + gdb_edi_i386, + gdb_eip_i386, + gdb_eflags_i386, + gdb_cs_i386, + gdb_ss_i386, + gdb_ds_i386, + gdb_es_i386, + gdb_fs_i386, + gdb_gs_i386, + gdb_st0_i386 = 16, + gdb_st1_i386, + gdb_st2_i386, + gdb_st3_i386, + gdb_st4_i386, + gdb_st5_i386, + gdb_st6_i386, + gdb_st7_i386, + gdb_fctrl_i386, // FPU Control Word + gdb_fstat_i386, // FPU Status Word + gdb_ftag_i386, // FPU Tag Word + gdb_fiseg_i386, // FPU IP Selector + gdb_fioff_i386, // FPU IP Offset + gdb_foseg_i386, // FPU Operand Pointer Selector + gdb_fooff_i386, // FPU Operand Pointer Offset + gdb_fop_i386, // Last Instruction Opcode + gdb_xmm0_i386 = 32, + gdb_xmm1_i386, + gdb_xmm2_i386, + gdb_xmm3_i386, + gdb_xmm4_i386, + gdb_xmm5_i386, + gdb_xmm6_i386, + gdb_xmm7_i386, + gdb_mxcsr_i386 = 40, + gdb_ymm0h_i386, + gdb_ymm1h_i386, + gdb_ymm2h_i386, + gdb_ymm3h_i386, + gdb_ymm4h_i386, + gdb_ymm5h_i386, + gdb_ymm6h_i386, + gdb_ymm7h_i386, + gdb_mm0_i386, + gdb_mm1_i386, + gdb_mm2_i386, + gdb_mm3_i386, + gdb_mm4_i386, + gdb_mm5_i386, + gdb_mm6_i386, + gdb_mm7_i386, }; +//--------------------------------------------------------------------------- +// AMD x86_64, AMD64, Intel EM64T, or Intel 64 gcc, dwarf, gdb enums +//--------------------------------------------------------------------------- + +// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF) +// This is the spec I used (as opposed to x86-64-abi-0.99.pdf): +// http://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf enum { - gdb_eax = 0, - gdb_ecx = 1, - gdb_edx = 2, - gdb_ebx = 3, - gdb_esp = 4, - gdb_ebp = 5, - gdb_esi = 6, - gdb_edi = 7, - gdb_eip = 8, - gdb_eflags = 9, - gdb_cs = 10, - gdb_ss = 11, - gdb_ds = 12, - gdb_es = 13, - gdb_fs = 14, - gdb_gs = 15, - gdb_stmm0 = 16, - gdb_stmm1 = 17, - gdb_stmm2 = 18, - gdb_stmm3 = 19, - gdb_stmm4 = 20, - gdb_stmm5 = 21, - gdb_stmm6 = 22, - gdb_stmm7 = 23, - gdb_fcw = 24, - gdb_fsw = 25, - gdb_ftw = 26, - gdb_fpu_cs = 27, - gdb_ip = 28, - gdb_fpu_ds = 29, - gdb_dp = 30, - gdb_fop = 31, - gdb_xmm0 = 32, - gdb_xmm1 = 33, - gdb_xmm2 = 34, - gdb_xmm3 = 35, - gdb_xmm4 = 36, - gdb_xmm5 = 37, - gdb_xmm6 = 38, - gdb_xmm7 = 39, - gdb_mxcsr = 40, - gdb_mm0 = 41, - gdb_mm1 = 42, - gdb_mm2 = 43, - gdb_mm3 = 44, - gdb_mm4 = 45, - gdb_mm5 = 46, - gdb_mm6 = 47, - gdb_mm7 = 48 + // GP Registers + gcc_dwarf_rax_x86_64 = 0, + gcc_dwarf_rdx_x86_64, + gcc_dwarf_rcx_x86_64, + gcc_dwarf_rbx_x86_64, + gcc_dwarf_rsi_x86_64, + gcc_dwarf_rdi_x86_64, + gcc_dwarf_rbp_x86_64, + gcc_dwarf_rsp_x86_64, + // Extended GP Registers + gcc_dwarf_r8_x86_64 = 8, + gcc_dwarf_r9_x86_64, + gcc_dwarf_r10_x86_64, + gcc_dwarf_r11_x86_64, + gcc_dwarf_r12_x86_64, + gcc_dwarf_r13_x86_64, + gcc_dwarf_r14_x86_64, + gcc_dwarf_r15_x86_64, + // Return Address (RA) mapped to RIP + gcc_dwarf_rip_x86_64 = 16, + // SSE Vector Registers + gcc_dwarf_xmm0_x86_64 = 17, + gcc_dwarf_xmm1_x86_64, + gcc_dwarf_xmm2_x86_64, + gcc_dwarf_xmm3_x86_64, + gcc_dwarf_xmm4_x86_64, + gcc_dwarf_xmm5_x86_64, + gcc_dwarf_xmm6_x86_64, + gcc_dwarf_xmm7_x86_64, + gcc_dwarf_xmm8_x86_64, + gcc_dwarf_xmm9_x86_64, + gcc_dwarf_xmm10_x86_64, + gcc_dwarf_xmm11_x86_64, + gcc_dwarf_xmm12_x86_64, + gcc_dwarf_xmm13_x86_64, + gcc_dwarf_xmm14_x86_64, + gcc_dwarf_xmm15_x86_64, + // Floating Point Registers + gcc_dwarf_st0_x86_64 = 33, + gcc_dwarf_st1_x86_64, + gcc_dwarf_st2_x86_64, + gcc_dwarf_st3_x86_64, + gcc_dwarf_st4_x86_64, + gcc_dwarf_st5_x86_64, + gcc_dwarf_st6_x86_64, + gcc_dwarf_st7_x86_64, + // MMX Registers + gcc_dwarf_mm0_x86_64 = 41, + gcc_dwarf_mm1_x86_64, + gcc_dwarf_mm2_x86_64, + gcc_dwarf_mm3_x86_64, + gcc_dwarf_mm4_x86_64, + gcc_dwarf_mm5_x86_64, + gcc_dwarf_mm6_x86_64, + gcc_dwarf_mm7_x86_64, + // Control and Status Flags Register + gcc_dwarf_rflags_x86_64 = 49, + // selector registers + gcc_dwarf_es_x86_64 = 50, + gcc_dwarf_cs_x86_64, + gcc_dwarf_ss_x86_64, + gcc_dwarf_ds_x86_64, + gcc_dwarf_fs_x86_64, + gcc_dwarf_gs_x86_64, + // Floating point control registers + gcc_dwarf_mxcsr_x86_64 = 64, // Media Control and Status + gcc_dwarf_fctrl_x86_64, // x87 control word + gcc_dwarf_fstat_x86_64, // x87 status word + // Upper Vector Registers + gcc_dwarf_ymm0h_x86_64 = 67, + gcc_dwarf_ymm1h_x86_64, + gcc_dwarf_ymm2h_x86_64, + gcc_dwarf_ymm3h_x86_64, + gcc_dwarf_ymm4h_x86_64, + gcc_dwarf_ymm5h_x86_64, + gcc_dwarf_ymm6h_x86_64, + gcc_dwarf_ymm7h_x86_64, + gcc_dwarf_ymm8h_x86_64, + gcc_dwarf_ymm9h_x86_64, + gcc_dwarf_ymm10h_x86_64, + gcc_dwarf_ymm11h_x86_64, + gcc_dwarf_ymm12h_x86_64, + gcc_dwarf_ymm13h_x86_64, + gcc_dwarf_ymm14h_x86_64, + gcc_dwarf_ymm15h_x86_64, + // AVX2 Vector Mask Registers + // gcc_dwarf_k0_x86_64 = 118, + // gcc_dwarf_k1_x86_64, + // gcc_dwarf_k2_x86_64, + // gcc_dwarf_k3_x86_64, + // gcc_dwarf_k4_x86_64, + // gcc_dwarf_k5_x86_64, + // gcc_dwarf_k6_x86_64, + // gcc_dwarf_k7_x86_64, +}; + +// GDB Register numbers (eRegisterKindGDB) +enum +{ + // GP Registers + gdb_rax_x86_64 = 0, + gdb_rbx_x86_64, + gdb_rcx_x86_64, + gdb_rdx_x86_64, + gdb_rsi_x86_64, + gdb_rdi_x86_64, + gdb_rbp_x86_64, + gdb_rsp_x86_64, + // Extended GP Registers + gdb_r8_x86_64, + gdb_r9_x86_64, + gdb_r10_x86_64, + gdb_r11_x86_64, + gdb_r12_x86_64, + gdb_r13_x86_64, + gdb_r14_x86_64, + gdb_r15_x86_64, + // Return Address (RA) mapped to RIP + gdb_rip_x86_64, + // Control and Status Flags Register + gdb_rflags_x86_64, + gdb_cs_x86_64, + gdb_ss_x86_64, + gdb_ds_x86_64, + gdb_es_x86_64, + gdb_fs_x86_64, + gdb_gs_x86_64, + // Floating Point Registers + gdb_st0_x86_64, + gdb_st1_x86_64, + gdb_st2_x86_64, + gdb_st3_x86_64, + gdb_st4_x86_64, + gdb_st5_x86_64, + gdb_st6_x86_64, + gdb_st7_x86_64, + gdb_fctrl_x86_64, + gdb_fstat_x86_64, + gdb_ftag_x86_64, + gdb_fiseg_x86_64, + gdb_fioff_x86_64, + gdb_foseg_x86_64, + gdb_fooff_x86_64, + gdb_fop_x86_64, + // SSE Vector Registers + gdb_xmm0_x86_64 = 40, + gdb_xmm1_x86_64, + gdb_xmm2_x86_64, + gdb_xmm3_x86_64, + gdb_xmm4_x86_64, + gdb_xmm5_x86_64, + gdb_xmm6_x86_64, + gdb_xmm7_x86_64, + gdb_xmm8_x86_64, + gdb_xmm9_x86_64, + gdb_xmm10_x86_64, + gdb_xmm11_x86_64, + gdb_xmm12_x86_64, + gdb_xmm13_x86_64, + gdb_xmm14_x86_64, + gdb_xmm15_x86_64, + // Floating point control registers + gdb_mxcsr_x86_64 = 56, + gdb_ymm0h_x86_64, + gdb_ymm1h_x86_64, + gdb_ymm2h_x86_64, + gdb_ymm3h_x86_64, + gdb_ymm4h_x86_64, + gdb_ymm5h_x86_64, + gdb_ymm6h_x86_64, + gdb_ymm7h_x86_64, + gdb_ymm8h_x86_64, + gdb_ymm9h_x86_64, + gdb_ymm10h_x86_64, + gdb_ymm11h_x86_64, + gdb_ymm12h_x86_64, + gdb_ymm13h_x86_64, + gdb_ymm14h_x86_64, + gdb_ymm15h_x86_64 +}; + +//--------------------------------------------------------------------------- +// Generic floating-point registers +//--------------------------------------------------------------------------- + +struct MMSReg +{ + uint8_t bytes[10]; + uint8_t pad[6]; +}; + +struct XMMReg +{ + uint8_t bytes[16]; // 128-bits for each XMM register +}; + +// i387_fxsave_struct +struct FXSAVE +{ + uint16_t fctrl; // FPU Control Word (fcw) + uint16_t fstat; // FPU Status Word (fsw) + uint16_t ftag; // FPU Tag Word (ftw) + uint16_t fop; // Last Instruction Opcode (fop) + union + { + struct + { + uint64_t fip; // Instruction Pointer + uint64_t fdp; // Data Pointer + } x86_64; + struct + { + uint32_t fioff; // FPU IP Offset (fip) + uint32_t fiseg; // FPU IP Selector (fcs) + uint32_t fooff; // FPU Operand Pointer Offset (foo) + uint32_t foseg; // FPU Operand Pointer Selector (fos) + } i386; + } ptr; + uint32_t mxcsr; // MXCSR Register State + uint32_t mxcsrmask; // MXCSR Mask + MMSReg stmm[8]; // 8*16 bytes for each FP-reg = 128 bytes + XMMReg xmm[16]; // 16*16 bytes for each XMM-reg = 256 bytes + uint32_t padding[24]; +}; + +//--------------------------------------------------------------------------- +// Extended floating-point registers +//--------------------------------------------------------------------------- + +struct YMMHReg +{ + uint8_t bytes[16]; // 16 * 8 bits for the high bytes of each YMM register +}; + +struct YMMReg +{ + uint8_t bytes[32]; // 16 * 16 bits for each YMM register +}; + +struct YMM +{ + YMMReg ymm[16]; // assembled from ymmh and xmm registers +}; + +struct XSAVE_HDR +{ + uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states supported by the processor + uint64_t reserved1[2]; + uint64_t reserved2[5]; +} __attribute__((packed)); + +// x86 extensions to FXSAVE (i.e. for AVX processors) +struct XSAVE +{ + FXSAVE i387; // floating point registers typical in i387_fxsave_struct + XSAVE_HDR header; // The xsave_hdr_struct can be used to determine if the following extensions are usable + YMMHReg ymmh[16]; // High 16 bytes of each of 16 YMM registers (the low bytes are in FXSAVE.xmm for compatibility with SSE) + // Slot any extensions to the register file here +} __attribute__((packed, aligned (64))); + +// Floating-point registers +struct FPR +{ + // Thread state for the floating-point unit of the processor read by ptrace. + union XSTATE + { + FXSAVE fxsave; // Generic floating-point registers. + XSAVE xsave; // x86 extended processor state. + } xstate; +}; + +//--------------------------------------------------------------------------- +// ptrace PTRACE_GETREGSET, PTRACE_SETREGSET structure +//--------------------------------------------------------------------------- + +struct IOVEC +{ + void *iov_base; // pointer to XSAVE + size_t iov_len; // sizeof(XSAVE) }; #endif diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp deleted file mode 100644 index 617b18484e5a..000000000000 --- a/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp +++ /dev/null @@ -1,1563 +0,0 @@ -//===-- RegisterContext_x86_64.cpp -------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <cstring> -#include <errno.h> -#include <stdint.h> - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/RegisterValue.h" -#include "lldb/Core/Scalar.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" -#include "llvm/Support/Compiler.h" - -#include "ProcessPOSIX.h" -#if defined(__linux__) or defined(__FreeBSD__) -#include "ProcessMonitor.h" -#endif -#include "RegisterContext_i386.h" -#include "RegisterContext_x86.h" -#include "RegisterContext_x86_64.h" -#include "Plugins/Process/elf-core/ProcessElfCore.h" - -using namespace lldb_private; -using namespace lldb; - -// Support ptrace extensions even when compiled without required kernel support -#ifndef NT_X86_XSTATE - #define NT_X86_XSTATE 0x202 -#endif - -enum -{ - gcc_dwarf_gpr_rax = 0, - gcc_dwarf_gpr_rdx, - gcc_dwarf_gpr_rcx, - gcc_dwarf_gpr_rbx, - gcc_dwarf_gpr_rsi, - gcc_dwarf_gpr_rdi, - gcc_dwarf_gpr_rbp, - gcc_dwarf_gpr_rsp, - gcc_dwarf_gpr_r8, - gcc_dwarf_gpr_r9, - gcc_dwarf_gpr_r10, - gcc_dwarf_gpr_r11, - gcc_dwarf_gpr_r12, - gcc_dwarf_gpr_r13, - gcc_dwarf_gpr_r14, - gcc_dwarf_gpr_r15, - gcc_dwarf_gpr_rip, - gcc_dwarf_fpu_xmm0, - gcc_dwarf_fpu_xmm1, - gcc_dwarf_fpu_xmm2, - gcc_dwarf_fpu_xmm3, - gcc_dwarf_fpu_xmm4, - gcc_dwarf_fpu_xmm5, - gcc_dwarf_fpu_xmm6, - gcc_dwarf_fpu_xmm7, - gcc_dwarf_fpu_xmm8, - gcc_dwarf_fpu_xmm9, - gcc_dwarf_fpu_xmm10, - gcc_dwarf_fpu_xmm11, - gcc_dwarf_fpu_xmm12, - gcc_dwarf_fpu_xmm13, - gcc_dwarf_fpu_xmm14, - gcc_dwarf_fpu_xmm15, - gcc_dwarf_fpu_stmm0, - gcc_dwarf_fpu_stmm1, - gcc_dwarf_fpu_stmm2, - gcc_dwarf_fpu_stmm3, - gcc_dwarf_fpu_stmm4, - gcc_dwarf_fpu_stmm5, - gcc_dwarf_fpu_stmm6, - gcc_dwarf_fpu_stmm7, - gcc_dwarf_fpu_ymm0, - gcc_dwarf_fpu_ymm1, - gcc_dwarf_fpu_ymm2, - gcc_dwarf_fpu_ymm3, - gcc_dwarf_fpu_ymm4, - gcc_dwarf_fpu_ymm5, - gcc_dwarf_fpu_ymm6, - gcc_dwarf_fpu_ymm7, - gcc_dwarf_fpu_ymm8, - gcc_dwarf_fpu_ymm9, - gcc_dwarf_fpu_ymm10, - gcc_dwarf_fpu_ymm11, - gcc_dwarf_fpu_ymm12, - gcc_dwarf_fpu_ymm13, - gcc_dwarf_fpu_ymm14, - gcc_dwarf_fpu_ymm15 -}; - -enum -{ - gdb_gpr_rax = 0, - gdb_gpr_rbx = 1, - gdb_gpr_rcx = 2, - gdb_gpr_rdx = 3, - gdb_gpr_rsi = 4, - gdb_gpr_rdi = 5, - gdb_gpr_rbp = 6, - gdb_gpr_rsp = 7, - gdb_gpr_r8 = 8, - gdb_gpr_r9 = 9, - gdb_gpr_r10 = 10, - gdb_gpr_r11 = 11, - gdb_gpr_r12 = 12, - gdb_gpr_r13 = 13, - gdb_gpr_r14 = 14, - gdb_gpr_r15 = 15, - gdb_gpr_rip = 16, - gdb_gpr_rflags = 17, - gdb_gpr_cs = 18, - gdb_gpr_ss = 19, - gdb_gpr_ds = 20, - gdb_gpr_es = 21, - gdb_gpr_fs = 22, - gdb_gpr_gs = 23, - gdb_fpu_stmm0 = 24, - gdb_fpu_stmm1 = 25, - gdb_fpu_stmm2 = 26, - gdb_fpu_stmm3 = 27, - gdb_fpu_stmm4 = 28, - gdb_fpu_stmm5 = 29, - gdb_fpu_stmm6 = 30, - gdb_fpu_stmm7 = 31, - gdb_fpu_fcw = 32, - gdb_fpu_fsw = 33, - gdb_fpu_ftw = 34, - gdb_fpu_cs_64 = 35, - gdb_fpu_ip = 36, - gdb_fpu_ds_64 = 37, - gdb_fpu_dp = 38, - gdb_fpu_fop = 39, - gdb_fpu_xmm0 = 40, - gdb_fpu_xmm1 = 41, - gdb_fpu_xmm2 = 42, - gdb_fpu_xmm3 = 43, - gdb_fpu_xmm4 = 44, - gdb_fpu_xmm5 = 45, - gdb_fpu_xmm6 = 46, - gdb_fpu_xmm7 = 47, - gdb_fpu_xmm8 = 48, - gdb_fpu_xmm9 = 49, - gdb_fpu_xmm10 = 50, - gdb_fpu_xmm11 = 51, - gdb_fpu_xmm12 = 52, - gdb_fpu_xmm13 = 53, - gdb_fpu_xmm14 = 54, - gdb_fpu_xmm15 = 55, - gdb_fpu_mxcsr = 56, - gdb_fpu_ymm0 = 57, - gdb_fpu_ymm1 = 58, - gdb_fpu_ymm2 = 59, - gdb_fpu_ymm3 = 60, - gdb_fpu_ymm4 = 61, - gdb_fpu_ymm5 = 62, - gdb_fpu_ymm6 = 63, - gdb_fpu_ymm7 = 64, - gdb_fpu_ymm8 = 65, - gdb_fpu_ymm9 = 66, - gdb_fpu_ymm10 = 67, - gdb_fpu_ymm11 = 68, - gdb_fpu_ymm12 = 69, - gdb_fpu_ymm13 = 70, - gdb_fpu_ymm14 = 71, - gdb_fpu_ymm15 = 72 -}; - -static const -uint32_t g_gpr_regnums[k_num_gpr_registers] = -{ - gpr_rax, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs, - gpr_ss, - gpr_ds, - gpr_es, - gpr_eax, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_eip, - gpr_eflags -}; - -static const uint32_t -g_fpu_regnums[k_num_fpr_registers] = -{ - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15 -}; - -static const uint32_t -g_avx_regnums[k_num_avx_registers] = -{ - fpu_ymm0, - fpu_ymm1, - fpu_ymm2, - fpu_ymm3, - fpu_ymm4, - fpu_ymm5, - fpu_ymm6, - fpu_ymm7, - fpu_ymm8, - fpu_ymm9, - fpu_ymm10, - fpu_ymm11, - fpu_ymm12, - fpu_ymm13, - fpu_ymm14, - fpu_ymm15 -}; - -// Number of register sets provided by this context. -enum -{ - k_num_extended_register_sets = 1, - k_num_register_sets = 3 -}; - -static const RegisterSet -g_reg_sets[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, - { "Floating Point Registers", "fpu", k_num_fpr_registers, g_fpu_regnums }, - { "Advanced Vector Extensions", "avx", k_num_avx_registers, g_avx_regnums } -}; - -// Computes the offset of the given FPR in the extended data area. -#define FPR_OFFSET(regname) \ - (offsetof(RegisterContext_x86_64::FPR, xstate) + \ - offsetof(RegisterContext_x86_64::FXSAVE, regname)) - -// Computes the offset of the YMM register assembled from register halves. -#define YMM_OFFSET(regname) \ - (offsetof(RegisterContext_x86_64::YMM, regname)) - -// Number of bytes needed to represent a i386 GPR -#define GPR_i386_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg) - -// Number of bytes needed to represent a FPR. -#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FXSAVE*)NULL)->reg) - -// Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes) - -// Number of bytes needed to represent an XMM register. -#define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg) - -// Number of bytes needed to represent a YMM register. -#define YMM_SIZE sizeof(RegisterContext_x86_64::YMMReg) - -// Note that the size and offset will be updated by platform-specific classes. -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, 0, 0, eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg }, NULL, NULL } - -// Dummy data for RegisterInfo::value_regs as expected by DumpRegisterSet. -static uint32_t value_regs = LLDB_INVALID_REGNUM; - -#define DEFINE_GPR_i386(reg_i386, reg_x86_64, alt, kind1, kind2, kind3, kind4) \ - { #reg_i386, alt, GPR_i386_SIZE(reg_i386), 0, eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg_i386 }, &value_regs, NULL } - -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg }, NULL, NULL } - -#define DEFINE_FP(reg, i) \ - { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL } - -#define DEFINE_XMM(reg, i) \ - { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL } - -#define DEFINE_YMM(reg, i) \ - { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(reg[i]), \ - eEncodingVector, eFormatVectorOfUInt8, \ - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL } - -#define DEFINE_DR(reg, i) \ - { #reg#i, NULL, 0, 0, eEncodingUint, eFormatHex, \ - { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL } - -#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(RegisterContext_x86_64::FPR)) - -static RegisterInfo -g_register_infos[k_num_registers] = -{ - // General purpose registers. - DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax), - DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx), - DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx), - DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx), - DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi), - DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi), - DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp), - DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp), - DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8), - DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9), - DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10), - DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11), - DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12), - DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13), - DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14), - DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15), - DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip), - DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags), - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs), - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs), - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs), - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss), - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds), - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es), - // i386 registers - DEFINE_GPR_i386(eax, rax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax), - DEFINE_GPR_i386(ebx, rbx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx), - DEFINE_GPR_i386(ecx, rcx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx), - DEFINE_GPR_i386(edx, rdx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx), - DEFINE_GPR_i386(edi, rdi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi), - DEFINE_GPR_i386(esi, rsi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi), - DEFINE_GPR_i386(ebp, rbp, "fp", gcc_ebp, dwarf_ebp, LLDB_REGNUM_GENERIC_FP, gdb_ebp), - DEFINE_GPR_i386(esp, rsp, "sp", gcc_esp, dwarf_esp, LLDB_REGNUM_GENERIC_SP, gdb_esp), - DEFINE_GPR_i386(eip, rip, "pc", gcc_eip, dwarf_eip, LLDB_REGNUM_GENERIC_PC, gdb_eip), - DEFINE_GPR_i386(eflags, rflags, "flags", gcc_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags), - // i387 Floating point registers. - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw), - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw), - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw), - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop), - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip), - // FIXME: Extract segment from ip. - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs_64), - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp), - // FIXME: Extract segment from dp. - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds_64), - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr), - DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - - // FP registers. - DEFINE_FP(stmm, 0), - DEFINE_FP(stmm, 1), - DEFINE_FP(stmm, 2), - DEFINE_FP(stmm, 3), - DEFINE_FP(stmm, 4), - DEFINE_FP(stmm, 5), - DEFINE_FP(stmm, 6), - DEFINE_FP(stmm, 7), - - // XMM registers - DEFINE_XMM(xmm, 0), - DEFINE_XMM(xmm, 1), - DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), - DEFINE_XMM(xmm, 4), - DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), - DEFINE_XMM(xmm, 7), - DEFINE_XMM(xmm, 8), - DEFINE_XMM(xmm, 9), - DEFINE_XMM(xmm, 10), - DEFINE_XMM(xmm, 11), - DEFINE_XMM(xmm, 12), - DEFINE_XMM(xmm, 13), - DEFINE_XMM(xmm, 14), - DEFINE_XMM(xmm, 15), - - // Copy of YMM registers assembled from xmm and ymmh - DEFINE_YMM(ymm, 0), - DEFINE_YMM(ymm, 1), - DEFINE_YMM(ymm, 2), - DEFINE_YMM(ymm, 3), - DEFINE_YMM(ymm, 4), - DEFINE_YMM(ymm, 5), - DEFINE_YMM(ymm, 6), - DEFINE_YMM(ymm, 7), - DEFINE_YMM(ymm, 8), - DEFINE_YMM(ymm, 9), - DEFINE_YMM(ymm, 10), - DEFINE_YMM(ymm, 11), - DEFINE_YMM(ymm, 12), - DEFINE_YMM(ymm, 13), - DEFINE_YMM(ymm, 14), - DEFINE_YMM(ymm, 15), - - // Debug registers for lldb internal use - DEFINE_DR(dr, 0), - DEFINE_DR(dr, 1), - DEFINE_DR(dr, 2), - DEFINE_DR(dr, 3), - DEFINE_DR(dr, 4), - DEFINE_DR(dr, 5), - DEFINE_DR(dr, 6), - DEFINE_DR(dr, 7) -}; - -static bool IsGPR(unsigned reg) -{ - return reg <= k_last_gpr; // GPR's come first. -} - -static bool IsAVX(unsigned reg) -{ - return (k_first_avx <= reg && reg <= k_last_avx); -} -static bool IsFPR(unsigned reg) -{ - return (k_first_fpr <= reg && reg <= k_last_fpr); -} - - -bool RegisterContext_x86_64::IsFPR(unsigned reg, FPRType fpr_type) -{ - bool generic_fpr = ::IsFPR(reg); - if (fpr_type == eXSAVE) - return generic_fpr || IsAVX(reg); - - return generic_fpr; -} - -RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContextPOSIX(thread, concrete_frame_idx) -{ - // Initialize m_iovec to point to the buffer and buffer size - // using the conventions of Berkeley style UIO structures, as required - // by PTRACE extensions. - m_iovec.iov_base = &m_fpr.xstate.xsave; - m_iovec.iov_len = sizeof(m_fpr.xstate.xsave); - - ::memset(&m_fpr, 0, sizeof(RegisterContext_x86_64::FPR)); - - // elf-core yet to support ReadFPR() - ProcessSP base = CalculateProcess(); - if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) - return; - - // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx - m_fpr_type = eXSAVE; // extended floating-point registers, if available - if (false == ReadFPR()) - m_fpr_type = eFXSAVE; // assume generic floating-point registers -} - -RegisterContext_x86_64::~RegisterContext_x86_64() -{ -} - -void -RegisterContext_x86_64::Invalidate() -{ -} - -void -RegisterContext_x86_64::InvalidateAllRegisters() -{ -} - -unsigned -RegisterContext_x86_64::GetRegisterOffset(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return GetRegisterInfo()[reg].byte_offset; -} - -unsigned -RegisterContext_x86_64::GetRegisterSize(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return GetRegisterInfo()[reg].byte_size; -} - -size_t -RegisterContext_x86_64::GetRegisterCount() -{ - size_t num_registers = k_num_gpr_registers + k_num_fpr_registers; - if (m_fpr_type == eXSAVE) - return num_registers + k_num_avx_registers; - return num_registers; -} - -const RegisterInfo * -RegisterContext_x86_64::GetRegisterInfo() -{ - // Commonly, this method is overridden and g_register_infos is copied and specialized. - // So, use GetRegisterInfo() rather than g_register_infos in this scope. - return g_register_infos; -} - -const RegisterInfo * -RegisterContext_x86_64::GetRegisterInfoAtIndex(size_t reg) -{ - if (reg < k_num_registers) - return &GetRegisterInfo()[reg]; - else - return NULL; -} - -size_t -RegisterContext_x86_64::GetRegisterSetCount() -{ - size_t sets = 0; - for (size_t set = 0; set < k_num_register_sets; ++set) - if (IsRegisterSetAvailable(set)) - ++sets; - - return sets; -} - -const RegisterSet * -RegisterContext_x86_64::GetRegisterSet(size_t set) -{ - if (IsRegisterSetAvailable(set)) - return &g_reg_sets[set]; - else - return NULL; -} - -unsigned -RegisterContext_x86_64::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers; reg++) - { - if (GetRegisterInfo()[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers && "Invalid register offset."); - return reg; -} - -const char * -RegisterContext_x86_64::GetRegisterName(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register offset."); - return GetRegisterInfo()[reg].name; -} - -lldb::ByteOrder -RegisterContext_x86_64::GetByteOrder() -{ - // Get the target process whose privileged thread was used for the register read. - lldb::ByteOrder byte_order = eByteOrderInvalid; - Process *process = CalculateProcess().get(); - - if (process) - byte_order = process->GetByteOrder(); - return byte_order; -} - -// Parse ymm registers and into xmm.bytes and ymmh.bytes. -bool RegisterContext_x86_64::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order) -{ - if (!IsAVX(reg)) - return false; - - if (byte_order == eByteOrderLittle) { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes, - m_ymm_set.ymm[reg - fpu_ymm0].bytes, - sizeof(RegisterContext_x86_64::XMMReg)); - ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes, - m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg), - sizeof(RegisterContext_x86_64::YMMHReg)); - return true; - } - - if (byte_order == eByteOrderBig) { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes, - m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg), - sizeof(RegisterContext_x86_64::XMMReg)); - ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes, - m_ymm_set.ymm[reg - fpu_ymm0].bytes, - sizeof(RegisterContext_x86_64::YMMHReg)); - return true; - } - return false; // unsupported or invalid byte order -} - -// Concatenate xmm.bytes with ymmh.bytes -bool RegisterContext_x86_64::CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order) -{ - if (!IsAVX(reg)) - return false; - - if (byte_order == eByteOrderLittle) { - ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes, - m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes, - sizeof(RegisterContext_x86_64::XMMReg)); - ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg), - m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes, - sizeof(RegisterContext_x86_64::YMMHReg)); - return true; - } - if (byte_order == eByteOrderBig) { - ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg), - m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes, - sizeof(RegisterContext_x86_64::XMMReg)); - ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes, - m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes, - sizeof(RegisterContext_x86_64::YMMHReg)); - return true; - } - return false; // unsupported or invalid byte order -} - -bool -RegisterContext_x86_64::IsRegisterSetAvailable(size_t set_index) -{ - // Note: Extended register sets are assumed to be at the end of g_reg_sets... - size_t num_sets = k_num_register_sets - k_num_extended_register_sets; - if (m_fpr_type == eXSAVE) // ...and to start with AVX registers. - ++num_sets; - - return (set_index < num_sets); -} - -bool -RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) -{ - if (!reg_info) - return false; - - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - - if (IsFPR(reg, m_fpr_type)) { - if (!ReadFPR()) - return false; - } - else { - bool success = ReadRegister(reg, value); - - // If an i386 register should be parsed from an x86_64 register... - if (success && reg >= k_first_i386 && reg <= k_last_i386) - if (value.GetByteSize() > reg_info->byte_size) - value.SetType(reg_info); // ...use the type specified by reg_info rather than the uint64_t default - return success; - } - - if (reg_info->encoding == eEncodingVector) { - ByteOrder byte_order = GetByteOrder(); - - if (byte_order != ByteOrder::eByteOrderInvalid) { - if (reg >= fpu_stmm0 && reg <= fpu_stmm7) { - value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, byte_order); - } - if (reg >= fpu_xmm0 && reg <= fpu_xmm15) { - value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, byte_order); - } - if (reg >= fpu_ymm0 && reg <= fpu_ymm15) { - // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes - if (m_fpr_type == eXSAVE && CopyXSTATEtoYMM(reg, byte_order)) - value.SetBytes(m_ymm_set.ymm[reg - fpu_ymm0].bytes, reg_info->byte_size, byte_order); - else - return false; - } - return value.GetType() == RegisterValue::eTypeBytes; - } - return false; - } - - // Note that lldb uses slightly different naming conventions from sys/user.h - switch (reg) - { - default: - return false; - case fpu_dp: - value = m_fpr.xstate.fxsave.dp; - break; - case fpu_fcw: - value = m_fpr.xstate.fxsave.fcw; - break; - case fpu_fsw: - value = m_fpr.xstate.fxsave.fsw; - break; - case fpu_ip: - value = m_fpr.xstate.fxsave.ip; - break; - case fpu_fop: - value = m_fpr.xstate.fxsave.fop; - break; - case fpu_ftw: - value = m_fpr.xstate.fxsave.ftw; - break; - case fpu_mxcsr: - value = m_fpr.xstate.fxsave.mxcsr; - break; - case fpu_mxcsrmask: - value = m_fpr.xstate.fxsave.mxcsrmask; - break; - } - return true; -} - -bool -RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - bool success = false; - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && ReadGPR () && ReadFPR ()) - { - uint8_t *dst = data_sp->GetBytes(); - success = dst != 0; - - if (success) { - ::memcpy (dst, &m_gpr, GetGPRSize()); - dst += GetGPRSize(); - } - if (m_fpr_type == eFXSAVE) - ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); - - if (m_fpr_type == eXSAVE) { - ByteOrder byte_order = GetByteOrder(); - - // Assemble the YMM register content from the register halves. - for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg) - success = CopyXSTATEtoYMM(reg, byte_order); - - if (success) { - // Copy the extended register state including the assembled ymm registers. - ::memcpy (dst, &m_fpr, sizeof(m_fpr)); - } - } - } - return success; -} - -bool -RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - if (IsGPR(reg)) { - return WriteRegister(reg, value); - } - - if (IsFPR(reg, m_fpr_type)) { - switch (reg) - { - default: - if (reg_info->encoding != eEncodingVector) - return false; - - if (reg >= fpu_stmm0 && reg <= fpu_stmm7) - ::memcpy (m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize()); - - if (reg >= fpu_xmm0 && reg <= fpu_xmm15) - ::memcpy (m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize()); - - if (reg >= fpu_ymm0 && reg <= fpu_ymm15) { - if (m_fpr_type != eXSAVE) - return false; // the target processor does not support AVX - - // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes - ::memcpy (m_ymm_set.ymm[reg - fpu_ymm0].bytes, value.GetBytes(), value.GetByteSize()); - if (false == CopyYMMtoXSTATE(reg, GetByteOrder())) - return false; - } - break; - case fpu_dp: - m_fpr.xstate.fxsave.dp = value.GetAsUInt64(); - break; - case fpu_fcw: - m_fpr.xstate.fxsave.fcw = value.GetAsUInt16(); - break; - case fpu_fsw: - m_fpr.xstate.fxsave.fsw = value.GetAsUInt16(); - break; - case fpu_ip: - m_fpr.xstate.fxsave.ip = value.GetAsUInt64(); - break; - case fpu_fop: - m_fpr.xstate.fxsave.fop = value.GetAsUInt16(); - break; - case fpu_ftw: - m_fpr.xstate.fxsave.ftw = value.GetAsUInt16(); - break; - case fpu_mxcsr: - m_fpr.xstate.fxsave.mxcsr = value.GetAsUInt32(); - break; - case fpu_mxcsrmask: - m_fpr.xstate.fxsave.mxcsrmask = value.GetAsUInt32(); - break; - } - if (WriteFPR()) { - if (IsAVX(reg)) - return CopyYMMtoXSTATE(reg, GetByteOrder()); - return true; - } - } - return false; -} - -bool -RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) -{ - bool success = false; - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - uint8_t *src = data_sp->GetBytes(); - if (src) { - ::memcpy (&m_gpr, src, GetGPRSize()); - - if (WriteGPR()) { - src += GetGPRSize(); - if (m_fpr_type == eFXSAVE) - ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave)); - if (m_fpr_type == eXSAVE) - ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); - - success = WriteFPR(); - if (success) { - success = true; - - if (m_fpr_type == eXSAVE) { - ByteOrder byte_order = GetByteOrder(); - - // Parse the YMM register content from the register halves. - for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg) - success = CopyYMMtoXSTATE(reg, byte_order); - } - } - } - } - } - return success; -} - -bool -RegisterContext_x86_64::UpdateAfterBreakpoint() -{ - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - SetPC(pc - 1); - return true; -} - -uint32_t -RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind, - uint32_t num) -{ - const Process *process = CalculateProcess().get(); - if (process) - { - const ArchSpec arch = process->GetTarget().GetArchitecture();; - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - case ArchSpec::eCore_x86_32_i486sx: - { - if (kind == eRegisterKindGeneric) - { - switch (num) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_eip; - case LLDB_REGNUM_GENERIC_SP: return gpr_esp; - case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; - case LLDB_REGNUM_GENERIC_RA: - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) - { - switch (num) - { - case dwarf_eax: return gpr_eax; - case dwarf_edx: return gpr_edx; - case dwarf_ecx: return gpr_ecx; - case dwarf_ebx: return gpr_ebx; - case dwarf_esi: return gpr_esi; - case dwarf_edi: return gpr_edi; - case dwarf_ebp: return gpr_ebp; - case dwarf_esp: return gpr_esp; - case dwarf_eip: return gpr_eip; - case dwarf_xmm0: return fpu_xmm0; - case dwarf_xmm1: return fpu_xmm1; - case dwarf_xmm2: return fpu_xmm2; - case dwarf_xmm3: return fpu_xmm3; - case dwarf_xmm4: return fpu_xmm4; - case dwarf_xmm5: return fpu_xmm5; - case dwarf_xmm6: return fpu_xmm6; - case dwarf_xmm7: return fpu_xmm7; - case dwarf_stmm0: return fpu_stmm0; - case dwarf_stmm1: return fpu_stmm1; - case dwarf_stmm2: return fpu_stmm2; - case dwarf_stmm3: return fpu_stmm3; - case dwarf_stmm4: return fpu_stmm4; - case dwarf_stmm5: return fpu_stmm5; - case dwarf_stmm6: return fpu_stmm6; - case dwarf_stmm7: return fpu_stmm7; - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGDB) - { - switch (num) - { - case gdb_eax : return gpr_eax; - case gdb_ebx : return gpr_ebx; - case gdb_ecx : return gpr_ecx; - case gdb_edx : return gpr_edx; - case gdb_esi : return gpr_esi; - case gdb_edi : return gpr_edi; - case gdb_ebp : return gpr_ebp; - case gdb_esp : return gpr_esp; - case gdb_eip : return gpr_eip; - case gdb_eflags : return gpr_eflags; - case gdb_cs : return gpr_cs; - case gdb_ss : return gpr_ss; - case gdb_ds : return gpr_ds; - case gdb_es : return gpr_es; - case gdb_fs : return gpr_fs; - case gdb_gs : return gpr_gs; - case gdb_stmm0 : return fpu_stmm0; - case gdb_stmm1 : return fpu_stmm1; - case gdb_stmm2 : return fpu_stmm2; - case gdb_stmm3 : return fpu_stmm3; - case gdb_stmm4 : return fpu_stmm4; - case gdb_stmm5 : return fpu_stmm5; - case gdb_stmm6 : return fpu_stmm6; - case gdb_stmm7 : return fpu_stmm7; - case gdb_fcw : return fpu_fcw; - case gdb_fsw : return fpu_fsw; - case gdb_ftw : return fpu_ftw; - case gdb_fpu_cs : return fpu_cs; - case gdb_ip : return fpu_ip; - case gdb_fpu_ds : return fpu_ds; //fpu_fos - case gdb_dp : return fpu_dp; //fpu_foo - case gdb_fop : return fpu_fop; - case gdb_xmm0 : return fpu_xmm0; - case gdb_xmm1 : return fpu_xmm1; - case gdb_xmm2 : return fpu_xmm2; - case gdb_xmm3 : return fpu_xmm3; - case gdb_xmm4 : return fpu_xmm4; - case gdb_xmm5 : return fpu_xmm5; - case gdb_xmm6 : return fpu_xmm6; - case gdb_xmm7 : return fpu_xmm7; - case gdb_mxcsr : return fpu_mxcsr; - default: - return LLDB_INVALID_REGNUM; - } - } - else if (kind == eRegisterKindLLDB) - { - return num; - } - - break; - } - - case ArchSpec::eCore_x86_64_x86_64: - { - if (kind == eRegisterKindGeneric) - { - switch (num) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_rip; - case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; - case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; - case LLDB_REGNUM_GENERIC_RA: - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) - { - switch (num) - { - case gcc_dwarf_gpr_rax: return gpr_rax; - case gcc_dwarf_gpr_rdx: return gpr_rdx; - case gcc_dwarf_gpr_rcx: return gpr_rcx; - case gcc_dwarf_gpr_rbx: return gpr_rbx; - case gcc_dwarf_gpr_rsi: return gpr_rsi; - case gcc_dwarf_gpr_rdi: return gpr_rdi; - case gcc_dwarf_gpr_rbp: return gpr_rbp; - case gcc_dwarf_gpr_rsp: return gpr_rsp; - case gcc_dwarf_gpr_r8: return gpr_r8; - case gcc_dwarf_gpr_r9: return gpr_r9; - case gcc_dwarf_gpr_r10: return gpr_r10; - case gcc_dwarf_gpr_r11: return gpr_r11; - case gcc_dwarf_gpr_r12: return gpr_r12; - case gcc_dwarf_gpr_r13: return gpr_r13; - case gcc_dwarf_gpr_r14: return gpr_r14; - case gcc_dwarf_gpr_r15: return gpr_r15; - case gcc_dwarf_gpr_rip: return gpr_rip; - case gcc_dwarf_fpu_xmm0: return fpu_xmm0; - case gcc_dwarf_fpu_xmm1: return fpu_xmm1; - case gcc_dwarf_fpu_xmm2: return fpu_xmm2; - case gcc_dwarf_fpu_xmm3: return fpu_xmm3; - case gcc_dwarf_fpu_xmm4: return fpu_xmm4; - case gcc_dwarf_fpu_xmm5: return fpu_xmm5; - case gcc_dwarf_fpu_xmm6: return fpu_xmm6; - case gcc_dwarf_fpu_xmm7: return fpu_xmm7; - case gcc_dwarf_fpu_xmm8: return fpu_xmm8; - case gcc_dwarf_fpu_xmm9: return fpu_xmm9; - case gcc_dwarf_fpu_xmm10: return fpu_xmm10; - case gcc_dwarf_fpu_xmm11: return fpu_xmm11; - case gcc_dwarf_fpu_xmm12: return fpu_xmm12; - case gcc_dwarf_fpu_xmm13: return fpu_xmm13; - case gcc_dwarf_fpu_xmm14: return fpu_xmm14; - case gcc_dwarf_fpu_xmm15: return fpu_xmm15; - case gcc_dwarf_fpu_stmm0: return fpu_stmm0; - case gcc_dwarf_fpu_stmm1: return fpu_stmm1; - case gcc_dwarf_fpu_stmm2: return fpu_stmm2; - case gcc_dwarf_fpu_stmm3: return fpu_stmm3; - case gcc_dwarf_fpu_stmm4: return fpu_stmm4; - case gcc_dwarf_fpu_stmm5: return fpu_stmm5; - case gcc_dwarf_fpu_stmm6: return fpu_stmm6; - case gcc_dwarf_fpu_stmm7: return fpu_stmm7; - case gcc_dwarf_fpu_ymm0: return fpu_ymm0; - case gcc_dwarf_fpu_ymm1: return fpu_ymm1; - case gcc_dwarf_fpu_ymm2: return fpu_ymm2; - case gcc_dwarf_fpu_ymm3: return fpu_ymm3; - case gcc_dwarf_fpu_ymm4: return fpu_ymm4; - case gcc_dwarf_fpu_ymm5: return fpu_ymm5; - case gcc_dwarf_fpu_ymm6: return fpu_ymm6; - case gcc_dwarf_fpu_ymm7: return fpu_ymm7; - case gcc_dwarf_fpu_ymm8: return fpu_ymm8; - case gcc_dwarf_fpu_ymm9: return fpu_ymm9; - case gcc_dwarf_fpu_ymm10: return fpu_ymm10; - case gcc_dwarf_fpu_ymm11: return fpu_ymm11; - case gcc_dwarf_fpu_ymm12: return fpu_ymm12; - case gcc_dwarf_fpu_ymm13: return fpu_ymm13; - case gcc_dwarf_fpu_ymm14: return fpu_ymm14; - case gcc_dwarf_fpu_ymm15: return fpu_ymm15; - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGDB) - { - switch (num) - { - case gdb_gpr_rax : return gpr_rax; - case gdb_gpr_rbx : return gpr_rbx; - case gdb_gpr_rcx : return gpr_rcx; - case gdb_gpr_rdx : return gpr_rdx; - case gdb_gpr_rsi : return gpr_rsi; - case gdb_gpr_rdi : return gpr_rdi; - case gdb_gpr_rbp : return gpr_rbp; - case gdb_gpr_rsp : return gpr_rsp; - case gdb_gpr_r8 : return gpr_r8; - case gdb_gpr_r9 : return gpr_r9; - case gdb_gpr_r10 : return gpr_r10; - case gdb_gpr_r11 : return gpr_r11; - case gdb_gpr_r12 : return gpr_r12; - case gdb_gpr_r13 : return gpr_r13; - case gdb_gpr_r14 : return gpr_r14; - case gdb_gpr_r15 : return gpr_r15; - case gdb_gpr_rip : return gpr_rip; - case gdb_gpr_rflags : return gpr_rflags; - case gdb_gpr_cs : return gpr_cs; - case gdb_gpr_ss : return gpr_ss; - case gdb_gpr_ds : return gpr_ds; - case gdb_gpr_es : return gpr_es; - case gdb_gpr_fs : return gpr_fs; - case gdb_gpr_gs : return gpr_gs; - case gdb_fpu_stmm0 : return fpu_stmm0; - case gdb_fpu_stmm1 : return fpu_stmm1; - case gdb_fpu_stmm2 : return fpu_stmm2; - case gdb_fpu_stmm3 : return fpu_stmm3; - case gdb_fpu_stmm4 : return fpu_stmm4; - case gdb_fpu_stmm5 : return fpu_stmm5; - case gdb_fpu_stmm6 : return fpu_stmm6; - case gdb_fpu_stmm7 : return fpu_stmm7; - case gdb_fpu_fcw : return fpu_fcw; - case gdb_fpu_fsw : return fpu_fsw; - case gdb_fpu_ftw : return fpu_ftw; - case gdb_fpu_cs_64 : return fpu_cs; - case gdb_fpu_ip : return fpu_ip; - case gdb_fpu_ds_64 : return fpu_ds; - case gdb_fpu_dp : return fpu_dp; - case gdb_fpu_fop : return fpu_fop; - case gdb_fpu_xmm0 : return fpu_xmm0; - case gdb_fpu_xmm1 : return fpu_xmm1; - case gdb_fpu_xmm2 : return fpu_xmm2; - case gdb_fpu_xmm3 : return fpu_xmm3; - case gdb_fpu_xmm4 : return fpu_xmm4; - case gdb_fpu_xmm5 : return fpu_xmm5; - case gdb_fpu_xmm6 : return fpu_xmm6; - case gdb_fpu_xmm7 : return fpu_xmm7; - case gdb_fpu_xmm8 : return fpu_xmm8; - case gdb_fpu_xmm9 : return fpu_xmm9; - case gdb_fpu_xmm10 : return fpu_xmm10; - case gdb_fpu_xmm11 : return fpu_xmm11; - case gdb_fpu_xmm12 : return fpu_xmm12; - case gdb_fpu_xmm13 : return fpu_xmm13; - case gdb_fpu_xmm14 : return fpu_xmm14; - case gdb_fpu_xmm15 : return fpu_xmm15; - case gdb_fpu_mxcsr : return fpu_mxcsr; - case gdb_fpu_ymm0 : return fpu_ymm0; - case gdb_fpu_ymm1 : return fpu_ymm1; - case gdb_fpu_ymm2 : return fpu_ymm2; - case gdb_fpu_ymm3 : return fpu_ymm3; - case gdb_fpu_ymm4 : return fpu_ymm4; - case gdb_fpu_ymm5 : return fpu_ymm5; - case gdb_fpu_ymm6 : return fpu_ymm6; - case gdb_fpu_ymm7 : return fpu_ymm7; - case gdb_fpu_ymm8 : return fpu_ymm8; - case gdb_fpu_ymm9 : return fpu_ymm9; - case gdb_fpu_ymm10 : return fpu_ymm10; - case gdb_fpu_ymm11 : return fpu_ymm11; - case gdb_fpu_ymm12 : return fpu_ymm12; - case gdb_fpu_ymm13 : return fpu_ymm13; - case gdb_fpu_ymm14 : return fpu_ymm14; - case gdb_fpu_ymm15 : return fpu_ymm15; - default: - return LLDB_INVALID_REGNUM; - } - } - else if (kind == eRegisterKindLLDB) - { - return num; - } - } - } - } - - return LLDB_INVALID_REGNUM; -} - -uint32_t -RegisterContext_x86_64::NumSupportedHardwareWatchpoints() -{ - // Available debug address registers: dr0, dr1, dr2, dr3 - return 4; -} - -bool -RegisterContext_x86_64::IsWatchpointVacant(uint32_t hw_index) -{ - bool is_vacant = false; - RegisterValue value; - - assert(hw_index < NumSupportedHardwareWatchpoints()); - - if (m_watchpoints_initialized == false) - { - // Reset the debug status and debug control registers - RegisterValue zero_bits = RegisterValue(uint64_t(0)); - if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits)) - assert(false && "Could not initialize watchpoint registers"); - m_watchpoints_initialized = true; - } - - if (ReadRegister(dr7, value)) - { - uint64_t val = value.GetAsUInt64(); - is_vacant = (val & (3 << 2*hw_index)) == 0; - } - - return is_vacant; -} - -static uint32_t -size_and_rw_bits(size_t size, bool read, bool write) -{ - uint32_t rw; - if (read) { - rw = 0x3; // READ or READ/WRITE - } else if (write) { - rw = 0x1; // WRITE - } else { - assert(0 && "read and write cannot both be false"); - } - - switch (size) { - case 1: - return rw; - case 2: - return (0x1 << 2) | rw; - case 4: - return (0x3 << 2) | rw; - case 8: - return (0x2 << 2) | rw; - default: - assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); - } -} - -uint32_t -RegisterContext_x86_64::SetHardwareWatchpoint(addr_t addr, size_t size, - bool read, bool write) -{ - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - uint32_t hw_index; - - for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) - { - if (IsWatchpointVacant(hw_index)) - return SetHardwareWatchpointWithIndex(addr, size, - read, write, - hw_index); - } - - return LLDB_INVALID_INDEX32; -} - -bool -RegisterContext_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size, - bool read, bool write, - uint32_t hw_index) -{ - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - - if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints) - return false; - - if (!(size == 1 || size == 2 || size == 4 || size == 8)) - return false; - - if (read == false && write == false) - return false; - - if (!IsWatchpointVacant(hw_index)) - return false; - - // Set both dr7 (debug control register) and dri (debug address register). - - // dr7{7-0} encodes the local/gloabl enable bits: - // global enable --. .-- local enable - // | | - // v v - // dr0 -> bits{1-0} - // dr1 -> bits{3-2} - // dr2 -> bits{5-4} - // dr3 -> bits{7-6} - // - // dr7{31-16} encodes the rw/len bits: - // b_x+3, b_x+2, b_x+1, b_x - // where bits{x+1, x} => rw - // 0b00: execute, 0b01: write, 0b11: read-or-write, - // 0b10: io read-or-write (unused) - // and bits{x+3, x+2} => len - // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte - // - // dr0 -> bits{19-16} - // dr1 -> bits{23-20} - // dr2 -> bits{27-24} - // dr3 -> bits{31-28} - if (hw_index < num_hw_watchpoints) - { - RegisterValue current_dr7_bits; - - if (ReadRegister(dr7, current_dr7_bits)) - { - uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() | - (1 << (2*hw_index) | - size_and_rw_bits(size, read, write) << - (16+4*hw_index)); - - if (WriteRegister(dr0 + hw_index, RegisterValue(addr)) && - WriteRegister(dr7, RegisterValue(new_dr7_bits))) - return true; - } - } - - return false; -} - -bool -RegisterContext_x86_64::ClearHardwareWatchpoint(uint32_t hw_index) -{ - if (hw_index < NumSupportedHardwareWatchpoints()) - { - RegisterValue current_dr7_bits; - - if (ReadRegister(dr7, current_dr7_bits)) - { - uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() & ~(3 << (2*hw_index)); - - if (WriteRegister(dr7, RegisterValue(new_dr7_bits))) - return true; - } - } - - return false; -} - -bool -RegisterContext_x86_64::IsWatchpointHit(uint32_t hw_index) -{ - bool is_hit = false; - - if (m_watchpoints_initialized == false) - { - // Reset the debug status and debug control registers - RegisterValue zero_bits = RegisterValue(uint64_t(0)); - if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits)) - assert(false && "Could not initialize watchpoint registers"); - m_watchpoints_initialized = true; - } - - if (hw_index < NumSupportedHardwareWatchpoints()) - { - RegisterValue value; - - if (ReadRegister(dr6, value)) - { - uint64_t val = value.GetAsUInt64(); - is_hit = val & (1 << hw_index); - } - } - - return is_hit; -} - -addr_t -RegisterContext_x86_64::GetWatchpointAddress(uint32_t hw_index) -{ - addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS; - - if (hw_index < NumSupportedHardwareWatchpoints()) - { - if (!IsWatchpointVacant(hw_index)) - { - RegisterValue value; - - if (ReadRegister(dr0 + hw_index, value)) - wp_monitor_addr = value.GetAsUInt64(); - } - } - - return wp_monitor_addr; -} - - -bool -RegisterContext_x86_64::ClearWatchpointHits() -{ - return WriteRegister(dr6, RegisterValue((uint64_t)0)); -} - -bool -RegisterContext_x86_64::HardwareSingleStep(bool enable) -{ - enum { TRACE_BIT = 0x100 }; - uint64_t rflags; - - if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL) - return false; - - if (enable) - { - if (rflags & TRACE_BIT) - return true; - - rflags |= TRACE_BIT; - } - else - { - if (!(rflags & TRACE_BIT)) - return false; - - rflags &= ~TRACE_BIT; - } - - return WriteRegisterFromUnsigned(gpr_rflags, rflags); -} - -#if defined(__linux__) or defined(__FreeBSD__) - -ProcessMonitor & -RegisterContext_x86_64::GetMonitor() -{ - ProcessSP base = CalculateProcess(); - ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get()); - return process->GetMonitor(); -} - -bool -RegisterContext_x86_64::ReadGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr, GetGPRSize()); -} - -bool -RegisterContext_x86_64::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - if (m_fpr_type == eFXSAVE) - return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); - - if (m_fpr_type == eXSAVE) - return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); - return false; -} - -bool -RegisterContext_x86_64::WriteGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(m_thread.GetID(), &m_gpr, GetGPRSize()); -} - -bool -RegisterContext_x86_64::WriteFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - if (m_fpr_type == eFXSAVE) - return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); - - if (m_fpr_type == eXSAVE) - return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); - return false; -} - -bool -RegisterContext_x86_64::ReadRegister(const unsigned reg, - RegisterValue &value) -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg), - GetRegisterName(reg), - GetRegisterSize(reg), - value); -} - -bool -RegisterContext_x86_64::WriteRegister(const unsigned reg, - const RegisterValue &value) -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(m_thread.GetID(), - GetRegisterOffset(reg), - GetRegisterName(reg), - value); -} - -#else - -bool -RegisterContext_x86_64::ReadGPR() -{ - llvm_unreachable("not implemented"); - return false; -} - -bool -RegisterContext_x86_64::ReadFPR() -{ - llvm_unreachable("not implemented"); - return false; -} - -bool -RegisterContext_x86_64::WriteGPR() -{ - llvm_unreachable("not implemented"); - return false; -} - -bool -RegisterContext_x86_64::WriteFPR() -{ - llvm_unreachable("not implemented"); - return false; -} - -bool -RegisterContext_x86_64::ReadRegister(const unsigned reg, - RegisterValue &value) -{ - llvm_unreachable("not implemented"); - return false; -} - -bool -RegisterContext_x86_64::WriteRegister(const unsigned reg, - const RegisterValue &value) -{ - llvm_unreachable("not implemented"); - return false; -} - -#endif diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86_64.h b/source/Plugins/Process/POSIX/RegisterContext_x86_64.h deleted file mode 100644 index 9d59bd78e547..000000000000 --- a/source/Plugins/Process/POSIX/RegisterContext_x86_64.h +++ /dev/null @@ -1,347 +0,0 @@ -//===-- RegisterContext_x86_64.h ---------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContext_x86_64_H_ -#define liblldb_RegisterContext_x86_64_H_ - -#include "lldb/Core/Log.h" -#include "RegisterContextPOSIX.h" - -class ProcessMonitor; - -// Internal codes for all x86_64 registers. -enum -{ - k_first_gpr, - gpr_rax = k_first_gpr, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs, - gpr_ss, - gpr_ds, - gpr_es, - k_first_i386, - gpr_eax = k_first_i386, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_eip, - gpr_eflags, // eRegisterKindLLDB == 33 - k_last_i386 = gpr_eflags, - k_last_gpr = gpr_eflags, - - k_first_fpr, - fpu_fcw = k_first_fpr, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15, - k_last_fpr = fpu_xmm15, - k_first_avx, - fpu_ymm0 = k_first_avx, - fpu_ymm1, - fpu_ymm2, - fpu_ymm3, - fpu_ymm4, - fpu_ymm5, - fpu_ymm6, - fpu_ymm7, - fpu_ymm8, - fpu_ymm9, - fpu_ymm10, - fpu_ymm11, - fpu_ymm12, - fpu_ymm13, - fpu_ymm14, - fpu_ymm15, - k_last_avx = fpu_ymm15, - - dr0, - dr1, - dr2, - dr3, - dr4, - dr5, - dr6, - dr7, - - k_num_registers, - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, - k_num_fpr_registers = k_last_fpr - k_first_fpr + 1, - k_num_avx_registers = k_last_avx - k_first_avx + 1 -}; - -class RegisterContext_x86_64 - : public RegisterContextPOSIX -{ -public: - RegisterContext_x86_64 (lldb_private::Thread &thread, - uint32_t concrete_frame_idx); - - ~RegisterContext_x86_64(); - - void - Invalidate(); - - void - InvalidateAllRegisters(); - - size_t - GetRegisterCount(); - - virtual size_t - GetGPRSize() = 0; - - virtual unsigned - GetRegisterSize(unsigned reg); - - virtual unsigned - GetRegisterOffset(unsigned reg); - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(size_t reg); - - size_t - GetRegisterSetCount(); - - const lldb_private::RegisterSet * - GetRegisterSet(size_t set); - - unsigned - GetRegisterIndexFromOffset(unsigned offset); - - const char * - GetRegisterName(unsigned reg); - - virtual bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - - virtual bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); - - uint32_t - NumSupportedHardwareWatchpoints(); - - uint32_t - SetHardwareWatchpoint(lldb::addr_t, size_t size, bool read, bool write); - - bool - SetHardwareWatchpointWithIndex(lldb::addr_t, size_t size, bool read, - bool write, uint32_t hw_index); - - bool - ClearHardwareWatchpoint(uint32_t hw_index); - - bool - HardwareSingleStep(bool enable); - - bool - UpdateAfterBreakpoint(); - - bool - IsWatchpointVacant(uint32_t hw_index); - - bool - IsWatchpointHit (uint32_t hw_index); - - lldb::addr_t - GetWatchpointAddress (uint32_t hw_index); - - bool - ClearWatchpointHits(); - - //--------------------------------------------------------------------------- - // Generic floating-point registers - //--------------------------------------------------------------------------- - - struct MMSReg - { - uint8_t bytes[10]; - uint8_t pad[6]; - }; - - struct XMMReg - { - uint8_t bytes[16]; // 128-bits for each XMM register - }; - - struct FXSAVE - { - uint16_t fcw; - uint16_t fsw; - uint16_t ftw; - uint16_t fop; - uint64_t ip; - uint64_t dp; - uint32_t mxcsr; - uint32_t mxcsrmask; - MMSReg stmm[8]; - XMMReg xmm[16]; - uint32_t padding[24]; - }; - - //--------------------------------------------------------------------------- - // Extended floating-point registers - //--------------------------------------------------------------------------- - struct YMMHReg - { - uint8_t bytes[16]; // 16 * 8 bits for the high bytes of each YMM register - }; - - struct YMMReg - { - uint8_t bytes[32]; // 16 * 16 bits for each YMM register - }; - - struct YMM - { - YMMReg ymm[16]; // assembled from ymmh and xmm registers - }; - - struct XSAVE_HDR - { - uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states supported by the processor - uint64_t reserved1[2]; - uint64_t reserved2[5]; - } __attribute__((packed)); - - // x86 extensions to FXSAVE (i.e. for AVX processors) - struct XSAVE - { - FXSAVE i387; // floating point registers typical in i387_fxsave_struct - XSAVE_HDR header; // The xsave_hdr_struct can be used to determine if the following extensions are usable - YMMHReg ymmh[16]; // High 16 bytes of each of 16 YMM registers (the low bytes are in FXSAVE.xmm for compatibility with SSE) - // Slot any extensions to the register file here - } __attribute__((packed, aligned (64))); - - struct IOVEC - { - void *iov_base; // pointer to XSAVE - size_t iov_len; // sizeof(XSAVE) - }; - - //--------------------------------------------------------------------------- - // Note: prefer kernel definitions over user-land - //--------------------------------------------------------------------------- - enum FPRType - { - eNotValid = 0, - eFSAVE, // TODO - eFXSAVE, - eSOFT, // TODO - eXSAVE - }; - - // Floating-point registers - struct FPR - { - // Thread state for the floating-point unit of the processor read by ptrace. - union XSTATE { - FXSAVE fxsave; // Generic floating-point registers. - XSAVE xsave; // x86 extended processor state. - } xstate; - }; - -protected: - // Determines if an extended register set is supported on the processor running the inferior process. - virtual bool - IsRegisterSetAvailable(size_t set_index); - - virtual const lldb_private::RegisterInfo * - GetRegisterInfo(); - - virtual bool - ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); - - virtual bool - WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value); - -private: - uint64_t m_gpr[k_num_gpr_registers]; // general purpose registers. - FPRType m_fpr_type; // determines the type of data stored by union FPR, if any. - FPR m_fpr; // floating-point registers including extended register sets. - IOVEC m_iovec; // wrapper for xsave. - YMM m_ymm_set; // copy of ymmh and xmm register halves. - - ProcessMonitor &GetMonitor(); - lldb::ByteOrder GetByteOrder(); - - bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order); - bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order); - bool IsFPR(unsigned reg, FPRType fpr_type); - - bool ReadGPR(); - bool ReadFPR(); - - bool WriteGPR(); - bool WriteFPR(); -}; - -#endif // #ifndef liblldb_RegisterContext_x86_64_H_ diff --git a/source/Plugins/Process/POSIX/RegisterInfos_i386.h b/source/Plugins/Process/POSIX/RegisterInfos_i386.h new file mode 100644 index 000000000000..7c516568cd62 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterInfos_i386.h @@ -0,0 +1,207 @@ +//===-- RegisterInfos_i386.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +#include "llvm/Support/Compiler.h" + +#ifdef DECLARE_REGISTER_INFOS_I386_STRUCT + +// Computes the offset of the given GPR in the user data area. +#define GPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(GPR, regname)) + +// Computes the offset of the given FPR in the extended data area. +#define FPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FXSAVE, regname)) + +// Computes the offset of the YMM register assembled from register halves. +#define YMM_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(YMM, regname)) + +// Number of bytes needed to represent a FPR. +#define FPR_SIZE(reg) sizeof(((FXSAVE*)NULL)->reg) + +// Number of bytes needed to represent the i'th FP register. +#define FP_SIZE sizeof(((MMSReg*)NULL)->bytes) + +// Number of bytes needed to represent an XMM register. +#define XMM_SIZE sizeof(XMMReg) + +// Number of bytes needed to represent a YMM register. +#define YMM_SIZE sizeof(YMMReg) + +// Note that the size and offset will be updated by platform-specific classes. +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { #reg, alt, sizeof(GPR::reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_i386 }, NULL, NULL } + +#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ + { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, fpu_##name##_i386 }, NULL, NULL } + +// RegisterKind: GCC, DWARF, Generic, GDB, LLDB + +#define DEFINE_FP_ST(reg, i) \ + { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ + eEncodingVector, eFormatVectorOfUInt8, \ + { gcc_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, gdb_st##i##_i386, fpu_st##i##_i386 }, \ + NULL, NULL } + +#define DEFINE_FP_MM(reg, i) \ + { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ + eEncodingUint, eFormatHex, \ + { gcc_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, gdb_mm##i##_i386, fpu_mm##i##_i386 }, \ + NULL, NULL } + +#define DEFINE_XMM(reg, i) \ + { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \ + eEncodingVector, eFormatVectorOfUInt8, \ + { gcc_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##_i386, fpu_##reg##i##_i386}, \ + NULL, NULL } + +// I believe the YMM registers use dwarf_xmm_%_i386 register numbers and then differentiate based on register size. +#define DEFINE_YMM(reg, i) \ + { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(reg[i]), \ + eEncodingVector, eFormatVectorOfUInt8, \ + { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##h_i386, fpu_##reg##i##_i386 }, \ + NULL, NULL } + +#define DEFINE_DR(reg, i) \ + { #reg#i, NULL, DR_SIZE, DR_OFFSET(i), eEncodingUint, eFormatHex, \ + { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL } + +#define DEFINE_GPR_PSEUDO_16(reg16, reg32) \ + { #reg16, NULL, 2, GPR_OFFSET(reg32), eEncodingUint, \ + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg16##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 } +#define DEFINE_GPR_PSEUDO_8H(reg8, reg32) \ + { #reg8, NULL, 1, GPR_OFFSET(reg32)+1, eEncodingUint, \ + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 } +#define DEFINE_GPR_PSEUDO_8L(reg8, reg32) \ + { #reg8, NULL, 1, GPR_OFFSET(reg32), eEncodingUint, \ + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_i386 }, RegisterContextPOSIX_x86::g_contained_##reg32, RegisterContextPOSIX_x86::g_invalidate_##reg32 } + +static RegisterInfo +g_register_infos_i386[] = +{ + // General purpose registers. + DEFINE_GPR(eax, NULL, gcc_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, gdb_eax_i386), + DEFINE_GPR(ebx, NULL, gcc_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, gdb_ebx_i386), + DEFINE_GPR(ecx, NULL, gcc_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, gdb_ecx_i386), + DEFINE_GPR(edx, NULL, gcc_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, gdb_edx_i386), + DEFINE_GPR(edi, NULL, gcc_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, gdb_edi_i386), + DEFINE_GPR(esi, NULL, gcc_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, gdb_esi_i386), + DEFINE_GPR(ebp, "fp", gcc_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, gdb_ebp_i386), + DEFINE_GPR(esp, "sp", gcc_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, gdb_esp_i386), + DEFINE_GPR(eip, "pc", gcc_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, gdb_eip_i386), + DEFINE_GPR(eflags, "flags", gcc_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags_i386), + DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, dwarf_cs_i386, LLDB_INVALID_REGNUM, gdb_cs_i386), + DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, dwarf_fs_i386, LLDB_INVALID_REGNUM, gdb_fs_i386), + DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, dwarf_gs_i386, LLDB_INVALID_REGNUM, gdb_gs_i386), + DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, dwarf_ss_i386, LLDB_INVALID_REGNUM, gdb_ss_i386), + DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, dwarf_ds_i386, LLDB_INVALID_REGNUM, gdb_ds_i386), + DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, dwarf_es_i386, LLDB_INVALID_REGNUM, gdb_es_i386), + + DEFINE_GPR_PSEUDO_16(ax, eax), + DEFINE_GPR_PSEUDO_16(bx, ebx), + DEFINE_GPR_PSEUDO_16(cx, ecx), + DEFINE_GPR_PSEUDO_16(dx, edx), + DEFINE_GPR_PSEUDO_16(di, edi), + DEFINE_GPR_PSEUDO_16(si, esi), + DEFINE_GPR_PSEUDO_16(bp, ebp), + DEFINE_GPR_PSEUDO_16(sp, esp), + DEFINE_GPR_PSEUDO_8H(ah, eax), + DEFINE_GPR_PSEUDO_8H(bh, ebx), + DEFINE_GPR_PSEUDO_8H(ch, ecx), + DEFINE_GPR_PSEUDO_8H(dh, edx), + DEFINE_GPR_PSEUDO_8L(al, eax), + DEFINE_GPR_PSEUDO_8L(bl, ebx), + DEFINE_GPR_PSEUDO_8L(cl, ecx), + DEFINE_GPR_PSEUDO_8L(dl, edx), + + // i387 Floating point registers. + DEFINE_FPR(fctrl, fctrl, LLDB_INVALID_REGNUM, dwarf_fctrl_i386, LLDB_INVALID_REGNUM, gdb_fctrl_i386), + DEFINE_FPR(fstat, fstat, LLDB_INVALID_REGNUM, dwarf_fstat_i386, LLDB_INVALID_REGNUM, gdb_fstat_i386), + DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftag_i386), + DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop_i386), + DEFINE_FPR(fiseg, ptr.i386.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_i386), + DEFINE_FPR(fioff, ptr.i386.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_i386), + DEFINE_FPR(foseg, ptr.i386.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_i386), + DEFINE_FPR(fooff, ptr.i386.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_i386), + DEFINE_FPR(mxcsr, mxcsr, LLDB_INVALID_REGNUM, dwarf_mxcsr_i386, LLDB_INVALID_REGNUM, gdb_mxcsr_i386), + DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + + // FP registers. + DEFINE_FP_ST(st, 0), + DEFINE_FP_ST(st, 1), + DEFINE_FP_ST(st, 2), + DEFINE_FP_ST(st, 3), + DEFINE_FP_ST(st, 4), + DEFINE_FP_ST(st, 5), + DEFINE_FP_ST(st, 6), + DEFINE_FP_ST(st, 7), + DEFINE_FP_MM(mm, 0), + DEFINE_FP_MM(mm, 1), + DEFINE_FP_MM(mm, 2), + DEFINE_FP_MM(mm, 3), + DEFINE_FP_MM(mm, 4), + DEFINE_FP_MM(mm, 5), + DEFINE_FP_MM(mm, 6), + DEFINE_FP_MM(mm, 7), + + // XMM registers + DEFINE_XMM(xmm, 0), + DEFINE_XMM(xmm, 1), + DEFINE_XMM(xmm, 2), + DEFINE_XMM(xmm, 3), + DEFINE_XMM(xmm, 4), + DEFINE_XMM(xmm, 5), + DEFINE_XMM(xmm, 6), + DEFINE_XMM(xmm, 7), + + // Copy of YMM registers assembled from xmm and ymmh + DEFINE_YMM(ymm, 0), + DEFINE_YMM(ymm, 1), + DEFINE_YMM(ymm, 2), + DEFINE_YMM(ymm, 3), + DEFINE_YMM(ymm, 4), + DEFINE_YMM(ymm, 5), + DEFINE_YMM(ymm, 6), + DEFINE_YMM(ymm, 7), + + // Debug registers for lldb internal use + DEFINE_DR(dr, 0), + DEFINE_DR(dr, 1), + DEFINE_DR(dr, 2), + DEFINE_DR(dr, 3), + DEFINE_DR(dr, 4), + DEFINE_DR(dr, 5), + DEFINE_DR(dr, 6), + DEFINE_DR(dr, 7) +}; +static_assert((sizeof(g_register_infos_i386) / sizeof(g_register_infos_i386[0])) == k_num_registers_i386, + "g_register_infos_x86_64 has wrong number of register infos"); + +#undef GPR_OFFSET +#undef FPR_OFFSET +#undef YMM_OFFSET +#undef FPR_SIZE +#undef FP_SIZE +#undef XMM_SIZE +#undef YMM_SIZE +#undef DEFINE_GPR +#undef DEFINE_FPR +#undef DEFINE_FP +#undef DEFINE_XMM +#undef DEFINE_YMM +#undef DEFINE_DR +#undef DEFINE_GPR_PSEUDO_16 +#undef DEFINE_GPR_PSEUDO_8H +#undef DEFINE_GPR_PSEUDO_8L + +#endif // DECLARE_REGISTER_INFOS_I386_STRUCT diff --git a/source/Plugins/Process/POSIX/RegisterInfos_mips64.h b/source/Plugins/Process/POSIX/RegisterInfos_mips64.h new file mode 100644 index 000000000000..13526e3680b7 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterInfos_mips64.h @@ -0,0 +1,74 @@ +//===-- RegisterInfos_mips64.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +// Computes the offset of the given GPR in the user data area. +#define GPR_OFFSET(regname) \ + (offsetof(GPR, regname)) + +#ifdef DECLARE_REGISTER_INFOS_MIPS64_STRUCT + +// Note that the size and offset will be updated by platform-specific classes. +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { #reg, alt, sizeof(GPR::reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL } + +static RegisterInfo +g_register_infos_mips64[] = +{ + // General purpose registers. GCC, DWARF, Generic, GDB + DEFINE_GPR(zero, "r0", gcc_dwarf_zero_mips64, gcc_dwarf_zero_mips64, LLDB_INVALID_REGNUM, gdb_zero_mips64), + DEFINE_GPR(r1, NULL, gcc_dwarf_r1_mips64, gcc_dwarf_r1_mips64, LLDB_INVALID_REGNUM, gdb_r1_mips64), + DEFINE_GPR(r2, NULL, gcc_dwarf_r2_mips64, gcc_dwarf_r2_mips64, LLDB_INVALID_REGNUM, gdb_r2_mips64), + DEFINE_GPR(r3, NULL, gcc_dwarf_r3_mips64, gcc_dwarf_r3_mips64, LLDB_INVALID_REGNUM, gdb_r3_mips64), + DEFINE_GPR(r4, NULL, gcc_dwarf_r4_mips64, gcc_dwarf_r4_mips64, LLDB_INVALID_REGNUM, gdb_r4_mips64), + DEFINE_GPR(r5, NULL, gcc_dwarf_r5_mips64, gcc_dwarf_r5_mips64, LLDB_INVALID_REGNUM, gdb_r5_mips64), + DEFINE_GPR(r6, NULL, gcc_dwarf_r6_mips64, gcc_dwarf_r6_mips64, LLDB_INVALID_REGNUM, gdb_r6_mips64), + DEFINE_GPR(r7, NULL, gcc_dwarf_r7_mips64, gcc_dwarf_r7_mips64, LLDB_INVALID_REGNUM, gdb_r7_mips64), + DEFINE_GPR(r8, NULL, gcc_dwarf_r8_mips64, gcc_dwarf_r8_mips64, LLDB_INVALID_REGNUM, gdb_r8_mips64), + DEFINE_GPR(r9, NULL, gcc_dwarf_r9_mips64, gcc_dwarf_r9_mips64, LLDB_INVALID_REGNUM, gdb_r9_mips64), + DEFINE_GPR(r10, NULL, gcc_dwarf_r10_mips64, gcc_dwarf_r10_mips64, LLDB_INVALID_REGNUM, gdb_r10_mips64), + DEFINE_GPR(r11, NULL, gcc_dwarf_r11_mips64, gcc_dwarf_r11_mips64, LLDB_INVALID_REGNUM, gdb_r11_mips64), + DEFINE_GPR(r12, NULL, gcc_dwarf_r12_mips64, gcc_dwarf_r12_mips64, LLDB_INVALID_REGNUM, gdb_r12_mips64), + DEFINE_GPR(r13, NULL, gcc_dwarf_r13_mips64, gcc_dwarf_r13_mips64, LLDB_INVALID_REGNUM, gdb_r13_mips64), + DEFINE_GPR(r14, NULL, gcc_dwarf_r14_mips64, gcc_dwarf_r14_mips64, LLDB_INVALID_REGNUM, gdb_r14_mips64), + DEFINE_GPR(r15, NULL, gcc_dwarf_r15_mips64, gcc_dwarf_r15_mips64, LLDB_INVALID_REGNUM, gdb_r15_mips64), + DEFINE_GPR(r16, NULL, gcc_dwarf_r16_mips64, gcc_dwarf_r16_mips64, LLDB_INVALID_REGNUM, gdb_r16_mips64), + DEFINE_GPR(r17, NULL, gcc_dwarf_r17_mips64, gcc_dwarf_r17_mips64, LLDB_INVALID_REGNUM, gdb_r17_mips64), + DEFINE_GPR(r18, NULL, gcc_dwarf_r18_mips64, gcc_dwarf_r18_mips64, LLDB_INVALID_REGNUM, gdb_r18_mips64), + DEFINE_GPR(r19, NULL, gcc_dwarf_r19_mips64, gcc_dwarf_r19_mips64, LLDB_INVALID_REGNUM, gdb_r19_mips64), + DEFINE_GPR(r20, NULL, gcc_dwarf_r20_mips64, gcc_dwarf_r20_mips64, LLDB_INVALID_REGNUM, gdb_r20_mips64), + DEFINE_GPR(r21, NULL, gcc_dwarf_r21_mips64, gcc_dwarf_r21_mips64, LLDB_INVALID_REGNUM, gdb_r21_mips64), + DEFINE_GPR(r22, NULL, gcc_dwarf_r22_mips64, gcc_dwarf_r22_mips64, LLDB_INVALID_REGNUM, gdb_r22_mips64), + DEFINE_GPR(r23, NULL, gcc_dwarf_r23_mips64, gcc_dwarf_r23_mips64, LLDB_INVALID_REGNUM, gdb_r23_mips64), + DEFINE_GPR(r24, NULL, gcc_dwarf_r24_mips64, gcc_dwarf_r24_mips64, LLDB_INVALID_REGNUM, gdb_r24_mips64), + DEFINE_GPR(r25, NULL, gcc_dwarf_r25_mips64, gcc_dwarf_r25_mips64, LLDB_INVALID_REGNUM, gdb_r25_mips64), + DEFINE_GPR(r26, NULL, gcc_dwarf_r26_mips64, gcc_dwarf_r26_mips64, LLDB_INVALID_REGNUM, gdb_r26_mips64), + DEFINE_GPR(r27, NULL, gcc_dwarf_r27_mips64, gcc_dwarf_r27_mips64, LLDB_INVALID_REGNUM, gdb_r27_mips64), + DEFINE_GPR(gp, "r28", gcc_dwarf_gp_mips64, gcc_dwarf_gp_mips64, LLDB_INVALID_REGNUM, gdb_gp_mips64), + DEFINE_GPR(sp, "r29", gcc_dwarf_sp_mips64, gcc_dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, gdb_sp_mips64), + DEFINE_GPR(r30, NULL, gcc_dwarf_r30_mips64, gcc_dwarf_r30_mips64, LLDB_INVALID_REGNUM, gdb_r30_mips64), + DEFINE_GPR(ra, "r31", gcc_dwarf_ra_mips64, gcc_dwarf_ra_mips64, LLDB_INVALID_REGNUM, gdb_ra_mips64), + DEFINE_GPR(sr, NULL, gcc_dwarf_sr_mips64, gcc_dwarf_sr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(mullo, NULL, gcc_dwarf_lo_mips64, gcc_dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(mulhi, NULL, gcc_dwarf_hi_mips64, gcc_dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(badvaddr, NULL, gcc_dwarf_bad_mips64, gcc_dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(cause, NULL, gcc_dwarf_cause_mips64, gcc_dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(pc, "pc", gcc_dwarf_pc_mips64, gcc_dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + DEFINE_GPR(ic, NULL, gcc_dwarf_ic_mips64, gcc_dwarf_ic_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(dummy, NULL, gcc_dwarf_dummy_mips64, gcc_dwarf_dummy_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +}; +static_assert((sizeof(g_register_infos_mips64) / sizeof(g_register_infos_mips64[0])) == k_num_registers_mips64, + "g_register_infos_mips64 has wrong number of register infos"); + +#undef DEFINE_GPR + +#endif // DECLARE_REGISTER_INFOS_MIPS64_STRUCT + +#undef GPR_OFFSET + diff --git a/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h b/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h new file mode 100644 index 000000000000..1bab88cd5727 --- /dev/null +++ b/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h @@ -0,0 +1,409 @@ +//===-- RegisterInfos_x86_64.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +#include "llvm/Support/Compiler.h" + +// Computes the offset of the given GPR in the user data area. +#define GPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(GPR, regname)) + +// Computes the offset of the given FPR in the extended data area. +#define FPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FXSAVE, regname)) + +// Computes the offset of the YMM register assembled from register halves. +#define YMM_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(YMM, regname)) + +#ifdef DECLARE_REGISTER_INFOS_X86_64_STRUCT + +// Number of bytes needed to represent a FPR. +#define FPR_SIZE(reg) sizeof(((FXSAVE*)NULL)->reg) + +// Number of bytes needed to represent the i'th FP register. +#define FP_SIZE sizeof(((MMSReg*)NULL)->bytes) + +// Number of bytes needed to represent an XMM register. +#define XMM_SIZE sizeof(XMMReg) + +// Number of bytes needed to represent a YMM register. +#define YMM_SIZE sizeof(YMMReg) + +// RegisterKind: GCC, DWARF, Generic, GDB, LLDB + +// Note that the size and offset will be updated by platform-specific classes. +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { #reg, alt, sizeof(GPR::reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_x86_64 }, NULL, NULL } + +#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ + { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, fpu_##name##_x86_64 }, NULL, NULL } + +#define DEFINE_FP_ST(reg, i) \ + { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ + eEncodingVector, eFormatVectorOfUInt8, \ + { gcc_dwarf_st##i##_x86_64, gcc_dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, fpu_st##i##_x86_64 }, \ + NULL, NULL } + +#define DEFINE_FP_MM(reg, i) \ + { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ + eEncodingUint, eFormatHex, \ + { gcc_dwarf_mm##i##_x86_64, gcc_dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, fpu_mm##i##_x86_64 }, \ + NULL, NULL } + +#define DEFINE_XMM(reg, i) \ + { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \ + eEncodingVector, eFormatVectorOfUInt8, \ + { gcc_dwarf_##reg##i##_x86_64, gcc_dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##_x86_64, fpu_##reg##i##_x86_64}, \ + NULL, NULL } + +#define DEFINE_YMM(reg, i) \ + { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(reg[i]), \ + eEncodingVector, eFormatVectorOfUInt8, \ + { gcc_dwarf_##reg##i##h_x86_64, gcc_dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##h_x86_64, fpu_##reg##i##_x86_64 }, \ + NULL, NULL } + +#define DEFINE_DR(reg, i) \ + { #reg#i, NULL, DR_SIZE, DR_OFFSET(i), eEncodingUint, eFormatHex, \ + { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL } + +#define DEFINE_GPR_PSEUDO_32(reg32, reg64) \ + { #reg32, NULL, 4, GPR_OFFSET(reg64), eEncodingUint, \ + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg32##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } +#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ + { #reg16, NULL, 2, GPR_OFFSET(reg64), eEncodingUint, \ + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg16##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } +#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ + { #reg8, NULL, 1, GPR_OFFSET(reg64)+1, eEncodingUint, \ + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } +#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ + { #reg8, NULL, 1, GPR_OFFSET(reg64), eEncodingUint, \ + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } + +static RegisterInfo +g_register_infos_x86_64[] = +{ + // General purpose registers. GCC, DWARF, Generic, GDB + DEFINE_GPR(rax, NULL, gcc_dwarf_rax_x86_64, gcc_dwarf_rax_x86_64, LLDB_INVALID_REGNUM, gdb_rax_x86_64), + DEFINE_GPR(rbx, NULL, gcc_dwarf_rbx_x86_64, gcc_dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, gdb_rbx_x86_64), + DEFINE_GPR(rcx, "arg4", gcc_dwarf_rcx_x86_64, gcc_dwarf_rcx_x86_64, LLDB_INVALID_REGNUM, gdb_rcx_x86_64), + DEFINE_GPR(rdx, "arg3", gcc_dwarf_rdx_x86_64, gcc_dwarf_rdx_x86_64, LLDB_INVALID_REGNUM, gdb_rdx_x86_64), + DEFINE_GPR(rdi, "arg1", gcc_dwarf_rdi_x86_64, gcc_dwarf_rdi_x86_64, LLDB_INVALID_REGNUM, gdb_rdi_x86_64), + DEFINE_GPR(rsi, "arg2", gcc_dwarf_rsi_x86_64, gcc_dwarf_rsi_x86_64, LLDB_INVALID_REGNUM, gdb_rsi_x86_64), + DEFINE_GPR(rbp, "fp", gcc_dwarf_rbp_x86_64, gcc_dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, gdb_rbp_x86_64), + DEFINE_GPR(rsp, "sp", gcc_dwarf_rsp_x86_64, gcc_dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, gdb_rsp_x86_64), + DEFINE_GPR(r8, "arg5", gcc_dwarf_r8_x86_64, gcc_dwarf_r8_x86_64, LLDB_INVALID_REGNUM, gdb_r8_x86_64), + DEFINE_GPR(r9, "arg6", gcc_dwarf_r9_x86_64, gcc_dwarf_r9_x86_64, LLDB_INVALID_REGNUM, gdb_r9_x86_64), + DEFINE_GPR(r10, NULL, gcc_dwarf_r10_x86_64, gcc_dwarf_r10_x86_64, LLDB_INVALID_REGNUM, gdb_r10_x86_64), + DEFINE_GPR(r11, NULL, gcc_dwarf_r11_x86_64, gcc_dwarf_r11_x86_64, LLDB_INVALID_REGNUM, gdb_r11_x86_64), + DEFINE_GPR(r12, NULL, gcc_dwarf_r12_x86_64, gcc_dwarf_r12_x86_64, LLDB_INVALID_REGNUM, gdb_r12_x86_64), + DEFINE_GPR(r13, NULL, gcc_dwarf_r13_x86_64, gcc_dwarf_r13_x86_64, LLDB_INVALID_REGNUM, gdb_r13_x86_64), + DEFINE_GPR(r14, NULL, gcc_dwarf_r14_x86_64, gcc_dwarf_r14_x86_64, LLDB_INVALID_REGNUM, gdb_r14_x86_64), + DEFINE_GPR(r15, NULL, gcc_dwarf_r15_x86_64, gcc_dwarf_r15_x86_64, LLDB_INVALID_REGNUM, gdb_r15_x86_64), + DEFINE_GPR(rip, "pc", gcc_dwarf_rip_x86_64, gcc_dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, gdb_rip_x86_64), + DEFINE_GPR(rflags, "flags", gcc_dwarf_rflags_x86_64, gcc_dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, gdb_rflags_x86_64), + DEFINE_GPR(cs, NULL, gcc_dwarf_cs_x86_64, gcc_dwarf_cs_x86_64, LLDB_INVALID_REGNUM, gdb_cs_x86_64), + DEFINE_GPR(fs, NULL, gcc_dwarf_fs_x86_64, gcc_dwarf_fs_x86_64, LLDB_INVALID_REGNUM, gdb_fs_x86_64), + DEFINE_GPR(gs, NULL, gcc_dwarf_gs_x86_64, gcc_dwarf_gs_x86_64, LLDB_INVALID_REGNUM, gdb_gs_x86_64), + DEFINE_GPR(ss, NULL, gcc_dwarf_ss_x86_64, gcc_dwarf_ss_x86_64, LLDB_INVALID_REGNUM, gdb_ss_x86_64), + DEFINE_GPR(ds, NULL, gcc_dwarf_ds_x86_64, gcc_dwarf_ds_x86_64, LLDB_INVALID_REGNUM, gdb_ds_x86_64), + DEFINE_GPR(es, NULL, gcc_dwarf_es_x86_64, gcc_dwarf_es_x86_64, LLDB_INVALID_REGNUM, gdb_es_x86_64), + + DEFINE_GPR_PSEUDO_32(eax, rax), + DEFINE_GPR_PSEUDO_32(ebx, rbx), + DEFINE_GPR_PSEUDO_32(ecx, rcx), + DEFINE_GPR_PSEUDO_32(edx, rdx), + DEFINE_GPR_PSEUDO_32(edi, rdi), + DEFINE_GPR_PSEUDO_32(esi, rsi), + DEFINE_GPR_PSEUDO_32(ebp, rbp), + DEFINE_GPR_PSEUDO_32(esp, rsp), + DEFINE_GPR_PSEUDO_32(r8d, r8), + DEFINE_GPR_PSEUDO_32(r9d, r9), + DEFINE_GPR_PSEUDO_32(r10d, r10), + DEFINE_GPR_PSEUDO_32(r11d, r11), + DEFINE_GPR_PSEUDO_32(r12d, r12), + DEFINE_GPR_PSEUDO_32(r13d, r13), + DEFINE_GPR_PSEUDO_32(r14d, r14), + DEFINE_GPR_PSEUDO_32(r15d, r15), + DEFINE_GPR_PSEUDO_16(ax, rax), + DEFINE_GPR_PSEUDO_16(bx, rbx), + DEFINE_GPR_PSEUDO_16(cx, rcx), + DEFINE_GPR_PSEUDO_16(dx, rdx), + DEFINE_GPR_PSEUDO_16(di, rdi), + DEFINE_GPR_PSEUDO_16(si, rsi), + DEFINE_GPR_PSEUDO_16(bp, rbp), + DEFINE_GPR_PSEUDO_16(sp, rsp), + DEFINE_GPR_PSEUDO_16(r8w, r8), + DEFINE_GPR_PSEUDO_16(r9w, r9), + DEFINE_GPR_PSEUDO_16(r10w, r10), + DEFINE_GPR_PSEUDO_16(r11w, r11), + DEFINE_GPR_PSEUDO_16(r12w, r12), + DEFINE_GPR_PSEUDO_16(r13w, r13), + DEFINE_GPR_PSEUDO_16(r14w, r14), + DEFINE_GPR_PSEUDO_16(r15w, r15), + DEFINE_GPR_PSEUDO_8H(ah, rax), + DEFINE_GPR_PSEUDO_8H(bh, rbx), + DEFINE_GPR_PSEUDO_8H(ch, rcx), + DEFINE_GPR_PSEUDO_8H(dh, rdx), + DEFINE_GPR_PSEUDO_8L(al, rax), + DEFINE_GPR_PSEUDO_8L(bl, rbx), + DEFINE_GPR_PSEUDO_8L(cl, rcx), + DEFINE_GPR_PSEUDO_8L(dl, rdx), + DEFINE_GPR_PSEUDO_8L(dil, rdi), + DEFINE_GPR_PSEUDO_8L(sil, rsi), + DEFINE_GPR_PSEUDO_8L(bpl, rbp), + DEFINE_GPR_PSEUDO_8L(spl, rsp), + DEFINE_GPR_PSEUDO_8L(r8l, r8), + DEFINE_GPR_PSEUDO_8L(r9l, r9), + DEFINE_GPR_PSEUDO_8L(r10l, r10), + DEFINE_GPR_PSEUDO_8L(r11l, r11), + DEFINE_GPR_PSEUDO_8L(r12l, r12), + DEFINE_GPR_PSEUDO_8L(r13l, r13), + DEFINE_GPR_PSEUDO_8L(r14l, r14), + DEFINE_GPR_PSEUDO_8L(r15l, r15), + + // i387 Floating point registers. GCC, DWARF, Generic, GDB + DEFINE_FPR(fctrl, fctrl, gcc_dwarf_fctrl_x86_64, gcc_dwarf_fctrl_x86_64, LLDB_INVALID_REGNUM, gdb_fctrl_x86_64), + DEFINE_FPR(fstat, fstat, gcc_dwarf_fstat_x86_64, gcc_dwarf_fstat_x86_64, LLDB_INVALID_REGNUM, gdb_fstat_x86_64), + DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftag_x86_64), + DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop_x86_64), + DEFINE_FPR(fiseg, ptr.i386.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_x86_64), + DEFINE_FPR(fioff, ptr.i386.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_x86_64), + DEFINE_FPR(foseg, ptr.i386.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_x86_64), + DEFINE_FPR(fooff, ptr.i386.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_x86_64), + DEFINE_FPR(mxcsr, mxcsr, gcc_dwarf_mxcsr_x86_64, gcc_dwarf_mxcsr_x86_64, LLDB_INVALID_REGNUM, gdb_mxcsr_x86_64), + DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + + // FP registers. + DEFINE_FP_ST(st, 0), + DEFINE_FP_ST(st, 1), + DEFINE_FP_ST(st, 2), + DEFINE_FP_ST(st, 3), + DEFINE_FP_ST(st, 4), + DEFINE_FP_ST(st, 5), + DEFINE_FP_ST(st, 6), + DEFINE_FP_ST(st, 7), + DEFINE_FP_MM(mm, 0), + DEFINE_FP_MM(mm, 1), + DEFINE_FP_MM(mm, 2), + DEFINE_FP_MM(mm, 3), + DEFINE_FP_MM(mm, 4), + DEFINE_FP_MM(mm, 5), + DEFINE_FP_MM(mm, 6), + DEFINE_FP_MM(mm, 7), + + // XMM registers + DEFINE_XMM(xmm, 0), + DEFINE_XMM(xmm, 1), + DEFINE_XMM(xmm, 2), + DEFINE_XMM(xmm, 3), + DEFINE_XMM(xmm, 4), + DEFINE_XMM(xmm, 5), + DEFINE_XMM(xmm, 6), + DEFINE_XMM(xmm, 7), + DEFINE_XMM(xmm, 8), + DEFINE_XMM(xmm, 9), + DEFINE_XMM(xmm, 10), + DEFINE_XMM(xmm, 11), + DEFINE_XMM(xmm, 12), + DEFINE_XMM(xmm, 13), + DEFINE_XMM(xmm, 14), + DEFINE_XMM(xmm, 15), + + // Copy of YMM registers assembled from xmm and ymmh + DEFINE_YMM(ymm, 0), + DEFINE_YMM(ymm, 1), + DEFINE_YMM(ymm, 2), + DEFINE_YMM(ymm, 3), + DEFINE_YMM(ymm, 4), + DEFINE_YMM(ymm, 5), + DEFINE_YMM(ymm, 6), + DEFINE_YMM(ymm, 7), + DEFINE_YMM(ymm, 8), + DEFINE_YMM(ymm, 9), + DEFINE_YMM(ymm, 10), + DEFINE_YMM(ymm, 11), + DEFINE_YMM(ymm, 12), + DEFINE_YMM(ymm, 13), + DEFINE_YMM(ymm, 14), + DEFINE_YMM(ymm, 15), + + // Debug registers for lldb internal use + DEFINE_DR(dr, 0), + DEFINE_DR(dr, 1), + DEFINE_DR(dr, 2), + DEFINE_DR(dr, 3), + DEFINE_DR(dr, 4), + DEFINE_DR(dr, 5), + DEFINE_DR(dr, 6), + DEFINE_DR(dr, 7) +}; +static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[0])) == k_num_registers_x86_64, + "g_register_infos_x86_64 has wrong number of register infos"); + +#undef FPR_SIZE +#undef FP_SIZE +#undef XMM_SIZE +#undef YMM_SIZE +#undef DEFINE_GPR +#undef DEFINE_FPR +#undef DEFINE_FP +#undef DEFINE_XMM +#undef DEFINE_YMM +#undef DEFINE_DR +#undef DEFINE_GPR_PSEUDO_32 +#undef DEFINE_GPR_PSEUDO_16 +#undef DEFINE_GPR_PSEUDO_8H +#undef DEFINE_GPR_PSEUDO_8L + +#endif // DECLARE_REGISTER_INFOS_X86_64_STRUCT + + +#ifdef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS + +#define UPDATE_GPR_INFO(reg, reg64) \ +do { \ + g_register_infos[gpr_##reg##_i386].byte_offset = GPR_OFFSET(reg64); \ +} while(false); + +#define UPDATE_GPR_INFO_8H(reg, reg64) \ +do { \ + g_register_infos[gpr_##reg##_i386].byte_offset = GPR_OFFSET(reg64) + 1; \ +} while(false); + +#define UPDATE_FPR_INFO(reg, reg64) \ +do { \ + g_register_infos[fpu_##reg##_i386].byte_offset = FPR_OFFSET(reg64); \ +} while(false); + +#define UPDATE_FP_INFO(reg, i) \ +do { \ + g_register_infos[fpu_##reg##i##_i386].byte_offset = FPR_OFFSET(stmm[i]); \ +} while(false); + +#define UPDATE_XMM_INFO(reg, i) \ +do { \ + g_register_infos[fpu_##reg##i##_i386].byte_offset = FPR_OFFSET(reg[i]); \ +} while(false); + +#define UPDATE_YMM_INFO(reg, i) \ +do { \ + g_register_infos[fpu_##reg##i##_i386].byte_offset = YMM_OFFSET(reg[i]); \ +} while(false); + +#define UPDATE_DR_INFO(reg_index) \ +do { \ + g_register_infos[dr##reg_index##_i386].byte_offset = DR_OFFSET(reg_index); \ +} while(false); + + // Update the register offsets + UPDATE_GPR_INFO(eax, rax); + UPDATE_GPR_INFO(ebx, rbx); + UPDATE_GPR_INFO(ecx, rcx); + UPDATE_GPR_INFO(edx, rdx); + UPDATE_GPR_INFO(edi, rdi); + UPDATE_GPR_INFO(esi, rsi); + UPDATE_GPR_INFO(ebp, rbp); + UPDATE_GPR_INFO(esp, rsp); + UPDATE_GPR_INFO(eip, rip); + UPDATE_GPR_INFO(eflags, rflags); + UPDATE_GPR_INFO(cs, cs); + UPDATE_GPR_INFO(fs, fs); + UPDATE_GPR_INFO(gs, gs); + UPDATE_GPR_INFO(ss, ss); + UPDATE_GPR_INFO(ds, ds); + UPDATE_GPR_INFO(es, es); + + UPDATE_GPR_INFO(ax, rax); + UPDATE_GPR_INFO(bx, rbx); + UPDATE_GPR_INFO(cx, rcx); + UPDATE_GPR_INFO(dx, rdx); + UPDATE_GPR_INFO(di, rdi); + UPDATE_GPR_INFO(si, rsi); + UPDATE_GPR_INFO(bp, rbp); + UPDATE_GPR_INFO(sp, rsp); + UPDATE_GPR_INFO_8H(ah, rax); + UPDATE_GPR_INFO_8H(bh, rbx); + UPDATE_GPR_INFO_8H(ch, rcx); + UPDATE_GPR_INFO_8H(dh, rdx); + UPDATE_GPR_INFO(al, rax); + UPDATE_GPR_INFO(bl, rbx); + UPDATE_GPR_INFO(cl, rcx); + UPDATE_GPR_INFO(dl, rdx); + + UPDATE_FPR_INFO(fctrl, fctrl); + UPDATE_FPR_INFO(fstat, fstat); + UPDATE_FPR_INFO(ftag, ftag); + UPDATE_FPR_INFO(fop, fop); + UPDATE_FPR_INFO(fiseg, ptr.i386.fiseg); + UPDATE_FPR_INFO(fioff, ptr.i386.fioff); + UPDATE_FPR_INFO(fooff, ptr.i386.fooff); + UPDATE_FPR_INFO(foseg, ptr.i386.foseg); + UPDATE_FPR_INFO(mxcsr, mxcsr); + UPDATE_FPR_INFO(mxcsrmask, mxcsrmask); + + UPDATE_FP_INFO(st, 0); + UPDATE_FP_INFO(st, 1); + UPDATE_FP_INFO(st, 2); + UPDATE_FP_INFO(st, 3); + UPDATE_FP_INFO(st, 4); + UPDATE_FP_INFO(st, 5); + UPDATE_FP_INFO(st, 6); + UPDATE_FP_INFO(st, 7); + UPDATE_FP_INFO(mm, 0); + UPDATE_FP_INFO(mm, 1); + UPDATE_FP_INFO(mm, 2); + UPDATE_FP_INFO(mm, 3); + UPDATE_FP_INFO(mm, 4); + UPDATE_FP_INFO(mm, 5); + UPDATE_FP_INFO(mm, 6); + UPDATE_FP_INFO(mm, 7); + + UPDATE_XMM_INFO(xmm, 0); + UPDATE_XMM_INFO(xmm, 1); + UPDATE_XMM_INFO(xmm, 2); + UPDATE_XMM_INFO(xmm, 3); + UPDATE_XMM_INFO(xmm, 4); + UPDATE_XMM_INFO(xmm, 5); + UPDATE_XMM_INFO(xmm, 6); + UPDATE_XMM_INFO(xmm, 7); + + UPDATE_YMM_INFO(ymm, 0); + UPDATE_YMM_INFO(ymm, 1); + UPDATE_YMM_INFO(ymm, 2); + UPDATE_YMM_INFO(ymm, 3); + UPDATE_YMM_INFO(ymm, 4); + UPDATE_YMM_INFO(ymm, 5); + UPDATE_YMM_INFO(ymm, 6); + UPDATE_YMM_INFO(ymm, 7); + + UPDATE_DR_INFO(0); + UPDATE_DR_INFO(1); + UPDATE_DR_INFO(2); + UPDATE_DR_INFO(3); + UPDATE_DR_INFO(4); + UPDATE_DR_INFO(5); + UPDATE_DR_INFO(6); + UPDATE_DR_INFO(7); + +#undef UPDATE_GPR_INFO +#undef UPDATE_GPR_INFO_8H +#undef UPDATE_FPR_INFO +#undef UPDATE_FP_INFO +#undef UPDATE_XMM_INFO +#undef UPDATE_YMM_INFO +#undef UPDATE_DR_INFO + +#endif // UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS + +#undef GPR_OFFSET +#undef FPR_OFFSET +#undef YMM_OFFSET |