Index: lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h =================================================================== --- lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -69,9 +69,13 @@ Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override; + // The two following methods are probably not necessary and probably + // will never be called. Nevertheless, we implement them right now + // to reduce the differences between different platforms and reduce + // the risk of the lack of implementation actually breaking something, + // at least for the time being. Status GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec) override; - Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) override; Index: lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp =================================================================== --- lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -213,7 +213,7 @@ LLDB_LOG(log, "got SIGTRAP, pid = {0}, lwpid = {1}, si_code = {2}", pid, info.psi_lwpid, info.psi_siginfo.si_code); - NativeThreadNetBSD* thread = nullptr; + NativeThreadNetBSD *thread = nullptr; if (info.psi_lwpid > 0) { for (const auto &t : m_threads) { @@ -224,8 +224,7 @@ static_cast(t.get())->SetStoppedWithNoReason(); } if (!thread) - LLDB_LOG(log, - "thread not found in m_threads, pid = {0}, LWP = {1}", pid, + LLDB_LOG(log, "thread not found in m_threads, pid = {0}, LWP = {1}", pid, info.psi_lwpid); } @@ -266,30 +265,27 @@ } switch (pst.pe_report_event) { - case PTRACE_LWP_CREATE: { - LLDB_LOG(log, - "monitoring new thread, pid = {0}, LWP = {1}", pid, - pst.pe_lwp); - NativeThreadNetBSD& t = AddThread(pst.pe_lwp); - error = t.CopyWatchpointsFrom( - static_cast(*GetCurrentThread())); - if (error.Fail()) { - LLDB_LOG(log, - "failed to copy watchpoints to new thread {0}: {1}", - pst.pe_lwp, error); - SetState(StateType::eStateInvalid); - return; - } - } break; - case PTRACE_LWP_EXIT: - LLDB_LOG(log, - "removing exited thread, pid = {0}, LWP = {1}", pid, - pst.pe_lwp); - RemoveThread(pst.pe_lwp); - break; + case PTRACE_LWP_CREATE: { + LLDB_LOG(log, "monitoring new thread, pid = {0}, LWP = {1}", pid, + pst.pe_lwp); + NativeThreadNetBSD &t = AddThread(pst.pe_lwp); + error = t.CopyWatchpointsFrom( + static_cast(*GetCurrentThread())); + if (error.Fail()) { + LLDB_LOG(log, "failed to copy watchpoints to new thread {0}: {1}", + pst.pe_lwp, error); + SetState(StateType::eStateInvalid); + return; + } + } break; + case PTRACE_LWP_EXIT: + LLDB_LOG(log, "removing exited thread, pid = {0}, LWP = {1}", pid, + pst.pe_lwp); + RemoveThread(pst.pe_lwp); + break; } - error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast(1), 0); + error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast(1), 0); if (error.Fail()) SetState(StateType::eStateInvalid); return; @@ -301,12 +297,13 @@ auto ®ctx = static_cast( thread->GetRegisterContext()); uint32_t wp_index = LLDB_INVALID_INDEX32; - Status error = regctx.GetWatchpointHitIndex(wp_index, - (uintptr_t)info.psi_siginfo.si_addr); + Status error = regctx.GetWatchpointHitIndex( + wp_index, (uintptr_t)info.psi_siginfo.si_addr); if (error.Fail()) LLDB_LOG(log, "received error while checking for watchpoint hits, pid = " - "{0}, LWP = {1}, error = {2}", pid, info.psi_lwpid, error); + "{0}, LWP = {1}, error = {2}", + pid, info.psi_lwpid, error); if (wp_index != LLDB_INVALID_INDEX32) { thread->SetStoppedByWatchpoint(wp_index); regctx.ClearWatchpointHit(wp_index); @@ -494,16 +491,14 @@ signal = siginfo->psi_siginfo.si_signo; } - ret = PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast(1), - signal); + ret = + PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast(1), signal); if (ret.Success()) SetState(eStateRunning, true); return ret; } -Status NativeProcessNetBSD::Halt() { - return PtraceWrapper(PT_STOP, GetID()); -} +Status NativeProcessNetBSD::Halt() { return PtraceWrapper(PT_STOP, GetID()); } Status NativeProcessNetBSD::Detach() { Status error; @@ -667,8 +662,8 @@ if (vm[i].kve_path[0]) info.SetName(vm[i].kve_path); - m_mem_region_cache.emplace_back( - info, FileSpec(info.GetName().GetCString())); + m_mem_region_cache.emplace_back(info, + FileSpec(info.GetName().GetCString())); } free(vm); @@ -706,21 +701,47 @@ Status NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec) { - return Status("Unimplemented"); + Status error = PopulateMemoryRegionCache(); + if (error.Fail()) + return error; + + FileSpec module_file_spec(module_path); + FileSystem::Instance().Resolve(module_file_spec); + + file_spec.Clear(); + for (const auto &it : m_mem_region_cache) { + if (it.second.GetFilename() == module_file_spec.GetFilename()) { + file_spec = it.second; + return Status(); + } + } + return Status("Module file (%s) not found in process' memory map!", + module_file_spec.GetFilename().AsCString()); } Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) { load_addr = LLDB_INVALID_ADDRESS; - return Status(); + Status error = PopulateMemoryRegionCache(); + if (error.Fail()) + return error; + + FileSpec file(file_name); + for (const auto &it : m_mem_region_cache) { + if (it.second == file) { + load_addr = it.first.GetRange().GetRangeBase(); + return Status(); + } + } + return Status("No load address found for file %s.", file_name.str().c_str()); } void NativeProcessNetBSD::SigchldHandler() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // Process all pending waitpid notifications. int status; - ::pid_t wait_pid = - llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WALLSIG | WNOHANG); + ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, + WALLSIG | WNOHANG); if (wait_pid == 0) return; // We are done. @@ -802,8 +823,8 @@ int wstatus; // Need to use WALLSIG otherwise we receive an error with errno=ECHLD At this // point we should have a thread stopped if waitpid succeeds. - if ((wstatus = llvm::sys::RetryAfterSignal(-1, waitpid, - m_pid, nullptr, WALLSIG)) < 0) + if ((wstatus = llvm::sys::RetryAfterSignal(-1, waitpid, m_pid, nullptr, + WALLSIG)) < 0) return Status(errno, eErrorTypePOSIX); // Initialize threads and tracing status @@ -911,7 +932,8 @@ Status NativeProcessNetBSD::SetupTrace() { // Enable event reporting ptrace_event_t events; - Status status = PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events)); + Status status = + PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events)); if (status.Fail()) return status; // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN? Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h =================================================================== --- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h +++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h @@ -18,6 +18,8 @@ #include // clang-format on +#include + #include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h" #include "Plugins/Process/Utility/RegisterContext_x86.h" #include "Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h" @@ -53,18 +55,34 @@ private: // Private member types. - enum { GPRegSet, XStateRegSet, DBRegSet }; + enum RegSetKind { + GPRegSet, + FPRegSet, + DBRegSet, + MaxRegularRegSet = DBRegSet, + YMMRegSet, + MPXRegSet, + MaxRegSet = MPXRegSet, + }; // Private member variables. - struct reg m_gpr; - struct xstate m_xstate; - struct dbreg m_dbr; + std::array m_gpr; + std::array m_xstate; + std::array m_dbr; + std::array m_regset_offsets; + + llvm::Optional GetSetForNativeRegNum(uint32_t reg_num) const; + + Status ReadRegisterSet(RegSetKind set); + Status WriteRegisterSet(RegSetKind set); - int GetSetForNativeRegNum(int reg_num) const; - int GetDR(int num) const; + uint8_t *GetOffsetRegSetData(RegSetKind set, size_t reg_offset); - Status ReadRegisterSet(uint32_t set); - Status WriteRegisterSet(uint32_t set); + struct YMMSplitPtr { + void *xmm; + void *ymm_hi; + }; + llvm::Optional GetYMMSplitReg(uint32_t reg); }; } // namespace process_netbsd Index: lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp =================================================================== --- lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -36,6 +36,10 @@ using namespace lldb_private; using namespace lldb_private::process_netbsd; +// Private namespace. + +namespace { +// x86 64-bit general purpose registers. static const uint32_t g_gpr_regnums_x86_64[] = { lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64, @@ -81,41 +85,58 @@ k_num_gpr_registers_x86_64, "g_gpr_regnums_x86_64 has wrong number of register infos"); -// x86 64-bit registers available via XState. -static const uint32_t g_xstate_regnums_x86_64[] = { - lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64, lldb_fop_x86_64, - lldb_fiseg_x86_64, lldb_fioff_x86_64, lldb_fip_x86_64, lldb_foseg_x86_64, - lldb_fooff_x86_64, lldb_fdp_x86_64, lldb_mxcsr_x86_64, - lldb_mxcsrmask_x86_64, lldb_st0_x86_64, lldb_st1_x86_64, lldb_st2_x86_64, - lldb_st3_x86_64, lldb_st4_x86_64, lldb_st5_x86_64, lldb_st6_x86_64, - lldb_st7_x86_64, lldb_mm0_x86_64, lldb_mm1_x86_64, lldb_mm2_x86_64, - lldb_mm3_x86_64, lldb_mm4_x86_64, lldb_mm5_x86_64, lldb_mm6_x86_64, - lldb_mm7_x86_64, lldb_xmm0_x86_64, lldb_xmm1_x86_64, lldb_xmm2_x86_64, - lldb_xmm3_x86_64, lldb_xmm4_x86_64, lldb_xmm5_x86_64, lldb_xmm6_x86_64, - lldb_xmm7_x86_64, lldb_xmm8_x86_64, lldb_xmm9_x86_64, lldb_xmm10_x86_64, - lldb_xmm11_x86_64, lldb_xmm12_x86_64, lldb_xmm13_x86_64, lldb_xmm14_x86_64, - lldb_xmm15_x86_64, lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, - lldb_ymm3_x86_64, lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, - lldb_ymm7_x86_64, lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, - lldb_ymm11_x86_64, lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, - lldb_ymm15_x86_64, +// x86 64-bit floating point registers. +static const uint32_t g_fpu_regnums_x86_64[] = { + lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64, + lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64, + lldb_fip_x86_64, lldb_foseg_x86_64, lldb_fooff_x86_64, + lldb_fdp_x86_64, lldb_mxcsr_x86_64, lldb_mxcsrmask_x86_64, + lldb_st0_x86_64, lldb_st1_x86_64, lldb_st2_x86_64, + lldb_st3_x86_64, lldb_st4_x86_64, lldb_st5_x86_64, + lldb_st6_x86_64, lldb_st7_x86_64, lldb_mm0_x86_64, + lldb_mm1_x86_64, lldb_mm2_x86_64, lldb_mm3_x86_64, + lldb_mm4_x86_64, lldb_mm5_x86_64, lldb_mm6_x86_64, + lldb_mm7_x86_64, lldb_xmm0_x86_64, lldb_xmm1_x86_64, + lldb_xmm2_x86_64, lldb_xmm3_x86_64, lldb_xmm4_x86_64, + lldb_xmm5_x86_64, lldb_xmm6_x86_64, lldb_xmm7_x86_64, + lldb_xmm8_x86_64, lldb_xmm9_x86_64, lldb_xmm10_x86_64, + lldb_xmm11_x86_64, lldb_xmm12_x86_64, lldb_xmm13_x86_64, + lldb_xmm14_x86_64, lldb_xmm15_x86_64, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) - + 1 == + 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[] = { + lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64, + lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64, + lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64, + lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - + 1 == + k_num_avx_registers_x86_64, + "g_avx_regnums_x86_64 has wrong number of register infos"); + +static const uint32_t g_mpx_regnums_x86_64[] = { // Note: we currently do not provide them but this is needed to avoid // unnamed groups in SBFrame::GetRegisterContext(). - lldb_bnd0_x86_64, lldb_bnd1_x86_64, lldb_bnd2_x86_64, lldb_bnd3_x86_64, - lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64, + lldb_bnd0_x86_64, lldb_bnd1_x86_64, lldb_bnd2_x86_64, + lldb_bnd3_x86_64, lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert((sizeof(g_xstate_regnums_x86_64) / - sizeof(g_xstate_regnums_x86_64[0])) - +static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) - 1 == - k_num_fpr_registers_x86_64 + k_num_avx_registers_x86_64 + - k_num_mpx_registers_x86_64, - "g_xstate_regnums_x86_64 has wrong number of register infos"); + k_num_mpx_registers_x86_64, + "g_mpx_regnums_x86_64 has wrong number of register infos"); // x86 debug registers. static const uint32_t g_dbr_regnums_x86_64[] = { - lldb_dr0_x86_64, lldb_dr1_x86_64, lldb_dr2_x86_64, lldb_dr3_x86_64, - lldb_dr4_x86_64, lldb_dr5_x86_64, lldb_dr6_x86_64, lldb_dr7_x86_64, + lldb_dr0_x86_64, lldb_dr1_x86_64, lldb_dr2_x86_64, lldb_dr3_x86_64, + lldb_dr4_x86_64, lldb_dr5_x86_64, lldb_dr6_x86_64, lldb_dr7_x86_64, LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert((sizeof(g_dbr_regnums_x86_64) / sizeof(g_dbr_regnums_x86_64[0])) - @@ -124,7 +145,7 @@ "g_dbr_regnums_x86_64 has wrong number of register infos"); // x86 32-bit general purpose registers. -static const uint32_t g_gpr_regnums_i386[] = { +const uint32_t g_gpr_regnums_i386[] = { lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386, lldb_edx_i386, lldb_edi_i386, lldb_esi_i386, lldb_ebp_i386, lldb_esp_i386, lldb_eip_i386, lldb_eflags_i386, lldb_cs_i386, lldb_fs_i386, @@ -140,8 +161,8 @@ k_num_gpr_registers_i386, "g_gpr_regnums_i386 has wrong number of register infos"); -// x86 32-bit registers available via XState. -static const uint32_t g_xstate_regnums_i386[] = { +// x86 32-bit floating point registers. +const uint32_t g_fpu_regnums_i386[] = { lldb_fctrl_i386, lldb_fstat_i386, lldb_ftag_i386, lldb_fop_i386, lldb_fiseg_i386, lldb_fioff_i386, lldb_foseg_i386, lldb_fooff_i386, lldb_mxcsr_i386, lldb_mxcsrmask_i386, lldb_st0_i386, lldb_st1_i386, @@ -151,23 +172,39 @@ lldb_mm6_i386, lldb_mm7_i386, lldb_xmm0_i386, lldb_xmm1_i386, lldb_xmm2_i386, lldb_xmm3_i386, lldb_xmm4_i386, lldb_xmm5_i386, lldb_xmm6_i386, lldb_xmm7_i386, - lldb_ymm0_i386, lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386, - lldb_ymm4_i386, lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) - + 1 == + k_num_fpr_registers_i386, + "g_fpu_regnums_i386 has wrong number of register infos"); + +static const uint32_t g_avx_regnums_i386[] = { + lldb_ymm0_i386, lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386, + lldb_ymm4_i386, lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - + 1 == + k_num_avx_registers_i386, + "g_avx_regnums_i386 has wrong number of register infos"); + +static const uint32_t g_mpx_regnums_i386[] = { // Note: we currently do not provide them but this is needed to avoid // unnamed groups in SBFrame::GetRegisterContext(). - lldb_bnd0_i386, lldb_bnd1_i386, lldb_bnd2_i386, - lldb_bnd3_i386, lldb_bndcfgu_i386, lldb_bndstatus_i386, + lldb_bnd0_i386, lldb_bnd1_i386, lldb_bnd2_i386, + lldb_bnd3_i386, lldb_bndcfgu_i386, lldb_bndstatus_i386, LLDB_INVALID_REGNUM // register sets need to end with this flag }; -static_assert((sizeof(g_xstate_regnums_i386) / sizeof(g_xstate_regnums_i386[0])) - +static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) - 1 == - k_num_fpr_registers_i386 + k_num_avx_registers_i386 + k_num_mpx_registers_i386, - "g_xstate_regnums_i386 has wrong number of register infos"); + k_num_mpx_registers_i386, + "g_mpx_regnums_i386 has wrong number of register infos"); // x86 debug registers. static const uint32_t g_dbr_regnums_i386[] = { - lldb_dr0_i386, lldb_dr1_i386, lldb_dr2_i386, lldb_dr3_i386, - lldb_dr4_i386, lldb_dr5_i386, lldb_dr6_i386, lldb_dr7_i386, + lldb_dr0_i386, lldb_dr1_i386, lldb_dr2_i386, lldb_dr3_i386, + lldb_dr4_i386, lldb_dr5_i386, lldb_dr6_i386, lldb_dr7_i386, LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert((sizeof(g_dbr_regnums_i386) / sizeof(g_dbr_regnums_i386[0])) - @@ -175,33 +212,38 @@ k_num_dbr_registers_i386, "g_dbr_regnums_i386 has wrong number of register infos"); - // Number of register sets provided by this context. -enum { k_num_register_sets = 4 }; +enum { k_num_register_sets = 5 }; // Register sets for x86 32-bit. static const RegisterSet g_reg_sets_i386[k_num_register_sets] = { {"General Purpose Registers", "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386}, - {"Extended State Registers", "xstate", - k_num_avx_registers_i386 + k_num_mpx_registers_i386, - g_xstate_regnums_i386}, - {"Debug Registers", "dbr", k_num_dbr_registers_i386, - g_dbr_regnums_i386}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_i386, + g_fpu_regnums_i386}, + {"Debug Registers", "dbr", k_num_dbr_registers_i386, g_dbr_regnums_i386}, + {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386, + g_avx_regnums_i386}, + {"Memory Protection Extensions", "mpx", k_num_mpx_registers_i386, + g_mpx_regnums_i386}, }; // Register sets for x86 64-bit. 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}, - {"Extended State Registers", "xstate", - k_num_avx_registers_x86_64 + k_num_mpx_registers_x86_64, - g_xstate_regnums_x86_64}, + {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, + g_fpu_regnums_x86_64}, {"Debug Registers", "dbr", k_num_dbr_registers_x86_64, g_dbr_regnums_x86_64}, + {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, + g_avx_regnums_x86_64}, + {"Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64, + g_mpx_regnums_x86_64}, }; #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize()) +} // namespace NativeRegisterContextNetBSD * NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( @@ -219,8 +261,8 @@ } else { assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host"); - // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 - // register context. + // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the + // x86_64 register context. return new RegisterContextNetBSD_x86_64(target_arch); } } @@ -229,18 +271,31 @@ const ArchSpec &target_arch, NativeThreadProtocol &native_thread) : NativeRegisterContextRegisterInfo( native_thread, CreateRegisterInfoInterface(target_arch)), - m_gpr(), m_xstate(), m_dbr() {} + m_regset_offsets({0}) { + assert(m_gpr.size() == GetRegisterInfoInterface().GetGPRSize()); + std::array first_regnos; -// CONSIDER after local and llgs debugging are merged, register set support can -// be moved into a base x86-64 class with IsRegisterSetAvailable made virtual. -uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const { - uint32_t sets = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { - if (GetSetForNativeRegNum(set_index) != -1) - ++sets; + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::x86: + first_regnos[FPRegSet] = lldb_fctrl_i386; + first_regnos[DBRegSet] = lldb_dr0_i386; + break; + case llvm::Triple::x86_64: + first_regnos[FPRegSet] = lldb_fctrl_x86_64; + first_regnos[DBRegSet] = lldb_dr0_x86_64; + break; + default: + llvm_unreachable("Unhandled target architecture."); } - return sets; + for (int i : {FPRegSet, DBRegSet}) + m_regset_offsets[i] = GetRegisterInfoInterface() + .GetRegisterInfo()[first_regnos[i]] + .byte_offset; +} + +uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const { + return k_num_register_sets; } const RegisterSet * @@ -255,133 +310,21 @@ } } -static constexpr int RegNumX86ToX86_64(int regnum) { - switch (regnum) { - case lldb_eax_i386: - return lldb_rax_x86_64; - case lldb_ebx_i386: - return lldb_rbx_x86_64; - case lldb_ecx_i386: - return lldb_rcx_x86_64; - case lldb_edx_i386: - return lldb_rdx_x86_64; - case lldb_edi_i386: - return lldb_rdi_x86_64; - case lldb_esi_i386: - return lldb_rsi_x86_64; - case lldb_ebp_i386: - return lldb_rbp_x86_64; - case lldb_esp_i386: - return lldb_rsp_x86_64; - case lldb_eip_i386: - return lldb_rip_x86_64; - case lldb_eflags_i386: - return lldb_rflags_x86_64; - case lldb_cs_i386: - return lldb_cs_x86_64; - case lldb_fs_i386: - return lldb_fs_x86_64; - case lldb_gs_i386: - return lldb_gs_x86_64; - case lldb_ss_i386: - return lldb_ss_x86_64; - case lldb_ds_i386: - return lldb_ds_x86_64; - case lldb_es_i386: - return lldb_es_x86_64; - case lldb_fctrl_i386: - return lldb_fctrl_x86_64; - case lldb_fstat_i386: - return lldb_fstat_x86_64; - case lldb_ftag_i386: - return lldb_ftag_x86_64; - case lldb_fop_i386: - return lldb_fop_x86_64; - case lldb_fiseg_i386: - return lldb_fiseg_x86_64; - case lldb_fioff_i386: - return lldb_fioff_x86_64; - case lldb_foseg_i386: - return lldb_foseg_x86_64; - case lldb_fooff_i386: - return lldb_fooff_x86_64; - case lldb_mxcsr_i386: - return lldb_mxcsr_x86_64; - case lldb_mxcsrmask_i386: - return lldb_mxcsrmask_x86_64; - case lldb_st0_i386: - case lldb_st1_i386: - case lldb_st2_i386: - case lldb_st3_i386: - case lldb_st4_i386: - case lldb_st5_i386: - case lldb_st6_i386: - case lldb_st7_i386: - return lldb_st0_x86_64 + regnum - lldb_st0_i386; - case lldb_mm0_i386: - case lldb_mm1_i386: - case lldb_mm2_i386: - case lldb_mm3_i386: - case lldb_mm4_i386: - case lldb_mm5_i386: - case lldb_mm6_i386: - case lldb_mm7_i386: - return lldb_mm0_x86_64 + regnum - lldb_mm0_i386; - case lldb_xmm0_i386: - case lldb_xmm1_i386: - case lldb_xmm2_i386: - case lldb_xmm3_i386: - case lldb_xmm4_i386: - case lldb_xmm5_i386: - case lldb_xmm6_i386: - case lldb_xmm7_i386: - return lldb_xmm0_x86_64 + regnum - lldb_xmm0_i386; - case lldb_ymm0_i386: - case lldb_ymm1_i386: - case lldb_ymm2_i386: - case lldb_ymm3_i386: - case lldb_ymm4_i386: - case lldb_ymm5_i386: - case lldb_ymm6_i386: - case lldb_ymm7_i386: - return lldb_ymm0_x86_64 + regnum - lldb_ymm0_i386; - case lldb_bnd0_i386: - case lldb_bnd1_i386: - case lldb_bnd2_i386: - case lldb_bnd3_i386: - return lldb_bnd0_x86_64 + regnum - lldb_bnd0_i386; - case lldb_bndcfgu_i386: - return lldb_bndcfgu_x86_64; - case lldb_bndstatus_i386: - return lldb_bndstatus_x86_64; - case lldb_dr0_i386: - case lldb_dr1_i386: - case lldb_dr2_i386: - case lldb_dr3_i386: - case lldb_dr4_i386: - case lldb_dr5_i386: - case lldb_dr6_i386: - case lldb_dr7_i386: - return lldb_dr0_x86_64 + regnum - lldb_dr0_i386; - default: - llvm_unreachable("Unhandled i386 register."); - } -} - -int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( - int reg_num) const { +llvm::Optional +NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( + uint32_t reg_num) const { switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { case llvm::Triple::x86: if (reg_num >= k_first_gpr_i386 && reg_num <= k_last_gpr_i386) return GPRegSet; if (reg_num >= k_first_fpr_i386 && reg_num <= k_last_fpr_i386) - return XStateRegSet; + return FPRegSet; if (reg_num >= k_first_avx_i386 && reg_num <= k_last_avx_i386) - return XStateRegSet; // AVX + return YMMRegSet; if (reg_num >= k_first_mpxr_i386 && reg_num <= k_last_mpxr_i386) - return -1; // MPXR + return llvm::None; // MPXR if (reg_num >= k_first_mpxc_i386 && reg_num <= k_last_mpxc_i386) - return -1; // MPXC + return llvm::None; // MPXC if (reg_num >= k_first_dbr_i386 && reg_num <= k_last_dbr_i386) return DBRegSet; // DBR break; @@ -389,13 +332,13 @@ if (reg_num >= k_first_gpr_x86_64 && reg_num <= k_last_gpr_x86_64) return GPRegSet; if (reg_num >= k_first_fpr_x86_64 && reg_num <= k_last_fpr_x86_64) - return XStateRegSet; + return FPRegSet; if (reg_num >= k_first_avx_x86_64 && reg_num <= k_last_avx_x86_64) - return XStateRegSet; // AVX + return YMMRegSet; if (reg_num >= k_first_mpxr_x86_64 && reg_num <= k_last_mpxr_x86_64) - return -1; // MPXR + return llvm::None; // MPXR if (reg_num >= k_first_mpxc_x86_64 && reg_num <= k_last_mpxc_x86_64) - return -1; // MPXC + return llvm::None; // MPXC if (reg_num >= k_first_dbr_x86_64 && reg_num <= k_last_dbr_x86_64) return DBRegSet; // DBR break; @@ -406,27 +349,33 @@ llvm_unreachable("Register does not belong to any register set"); } -Status NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) { +Status NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(RegSetKind set) { switch (set) { case GPRegSet: - return DoRegisterSet(PT_GETREGS, &m_gpr); + return DoRegisterSet(PT_GETREGS, m_gpr.data()); case DBRegSet: - return DoRegisterSet(PT_GETDBREGS, &m_dbr); - case XStateRegSet: { - struct iovec iov = {&m_xstate, sizeof(m_xstate)}; - return DoRegisterSet(PT_GETXSTATE, &iov); + return DoRegisterSet(PT_GETDBREGS, m_dbr.data()); + case FPRegSet: + case YMMRegSet: + case MPXRegSet: { + struct iovec iov = {m_xstate.data(), m_xstate.size()}; + Status ret = DoRegisterSet(PT_GETXSTATE, &iov); + assert(reinterpret_cast(m_xstate.data())->xs_rfbm & XCR0_X87); + return ret; } } llvm_unreachable("NativeRegisterContextNetBSD_x86_64::ReadRegisterSet"); } -Status NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) { +Status NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(RegSetKind set) { switch (set) { case GPRegSet: - return DoRegisterSet(PT_SETREGS, &m_gpr); + return DoRegisterSet(PT_SETREGS, m_gpr.data()); case DBRegSet: - return DoRegisterSet(PT_SETDBREGS, &m_dbr); - case XStateRegSet: { + return DoRegisterSet(PT_SETDBREGS, m_dbr.data()); + case FPRegSet: + case YMMRegSet: + case MPXRegSet: { struct iovec iov = {&m_xstate, sizeof(m_xstate)}; return DoRegisterSet(PT_SETXSTATE, &iov); } @@ -454,8 +403,8 @@ return error; } - int set = GetSetForNativeRegNum(reg); - if (set == -1) { + llvm::Optional opt_set = GetSetForNativeRegNum(reg); + if (!opt_set) { // This is likely an internal register for lldb use only and should not be // directly queried. error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", @@ -463,271 +412,39 @@ return error; } - switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { - case llvm::Triple::x86_64: - break; - case llvm::Triple::x86: - reg = RegNumX86ToX86_64(reg); - break; - default: - llvm_unreachable("Unhandled target architecture."); - } - + RegSetKind set = opt_set.getValue(); error = ReadRegisterSet(set); if (error.Fail()) return error; - switch (reg) { -#if defined(__x86_64__) - case lldb_rax_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_RAX]; - break; - case lldb_rbx_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_RBX]; - break; - case lldb_rcx_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_RCX]; - break; - case lldb_rdx_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_RDX]; - break; - case lldb_rdi_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_RDI]; - break; - case lldb_rsi_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_RSI]; - break; - case lldb_rbp_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_RBP]; - break; - case lldb_rsp_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_RSP]; - break; - case lldb_r8_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_R8]; - break; - case lldb_r9_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_R9]; - break; - case lldb_r10_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_R10]; - break; - case lldb_r11_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_R11]; - break; - case lldb_r12_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_R12]; - break; - case lldb_r13_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_R13]; - break; - case lldb_r14_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_R14]; - break; - case lldb_r15_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_R15]; - break; - case lldb_rip_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_RIP]; - break; - case lldb_rflags_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_RFLAGS]; - break; - case lldb_cs_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_CS]; - break; - case lldb_fs_x86_64: - reg_value = (uint16_t)m_gpr.regs[_REG_FS]; - break; - case lldb_gs_x86_64: - reg_value = (uint16_t)m_gpr.regs[_REG_GS]; - break; - case lldb_ss_x86_64: - reg_value = (uint64_t)m_gpr.regs[_REG_SS]; - break; - case lldb_ds_x86_64: - reg_value = (uint16_t)m_gpr.regs[_REG_DS]; - break; - case lldb_es_x86_64: - reg_value = (uint16_t)m_gpr.regs[_REG_ES]; - break; -#else - case lldb_rax_x86_64: - reg_value = (uint32_t)m_gpr.r_eax; - break; - case lldb_rbx_x86_64: - reg_value = (uint32_t)m_gpr.r_ebx; - break; - case lldb_rcx_x86_64: - reg_value = (uint32_t)m_gpr.r_ecx; - break; - case lldb_rdx_x86_64: - reg_value = (uint32_t)m_gpr.r_edx; - break; - case lldb_rdi_x86_64: - reg_value = (uint32_t)m_gpr.r_edi; - break; - case lldb_rsi_x86_64: - reg_value = (uint32_t)m_gpr.r_esi; - break; - case lldb_rsp_x86_64: - reg_value = (uint32_t)m_gpr.r_esp; - break; - case lldb_rbp_x86_64: - reg_value = (uint32_t)m_gpr.r_ebp; - break; - case lldb_rip_x86_64: - reg_value = (uint32_t)m_gpr.r_eip; - break; - case lldb_rflags_x86_64: - reg_value = (uint32_t)m_gpr.r_eflags; - break; - case lldb_cs_x86_64: - reg_value = (uint32_t)m_gpr.r_cs; - break; - case lldb_fs_x86_64: - reg_value = (uint16_t)m_gpr.r_fs; - break; - case lldb_gs_x86_64: - reg_value = (uint16_t)m_gpr.r_gs; - break; - case lldb_ss_x86_64: - reg_value = (uint32_t)m_gpr.r_ss; - break; - case lldb_ds_x86_64: - reg_value = (uint16_t)m_gpr.r_ds; - break; - case lldb_es_x86_64: - reg_value = (uint16_t)m_gpr.r_es; - break; -#endif - case lldb_fctrl_x86_64: - reg_value = (uint16_t)m_xstate.xs_fxsave.fx_cw; - break; - case lldb_fstat_x86_64: - reg_value = (uint16_t)m_xstate.xs_fxsave.fx_sw; - break; - case lldb_ftag_x86_64: { - llvm::ArrayRef st_regs{ - reinterpret_cast(m_xstate.xs_fxsave.fx_87_ac), 8}; - reg_value = (uint16_t)AbridgedToFullTagWord( - m_xstate.xs_fxsave.fx_tw, m_xstate.xs_fxsave.fx_sw, st_regs); + switch (set) { + case GPRegSet: + case FPRegSet: + case DBRegSet: { + void *data = GetOffsetRegSetData(set, reg_info->byte_offset); + FXSAVE *fpr = reinterpret_cast(m_xstate.data() + + offsetof(xstate, xs_fxsave)); + if (data == &fpr->ftag) // ftag + reg_value.SetUInt16( + AbridgedToFullTagWord(fpr->ftag, fpr->fstat, fpr->stmm)); + else + reg_value.SetBytes(data, reg_info->byte_size, endian::InlHostByteOrder()); break; } - case lldb_fop_x86_64: - reg_value = (uint64_t)m_xstate.xs_fxsave.fx_opcode; - break; - case lldb_fiseg_x86_64: - reg_value = (uint32_t)m_xstate.xs_fxsave.fx_ip.fa_32.fa_seg; - break; - case lldb_fioff_x86_64: - reg_value = (uint32_t)m_xstate.xs_fxsave.fx_ip.fa_32.fa_off; - break; - case lldb_fip_x86_64: - reg_value = (uint64_t)m_xstate.xs_fxsave.fx_ip.fa_64; - break; - case lldb_foseg_x86_64: - reg_value = (uint32_t)m_xstate.xs_fxsave.fx_dp.fa_32.fa_seg; - break; - case lldb_fooff_x86_64: - reg_value = (uint32_t)m_xstate.xs_fxsave.fx_dp.fa_32.fa_off; - break; - case lldb_fdp_x86_64: - reg_value = (uint64_t)m_xstate.xs_fxsave.fx_dp.fa_64; - break; - case lldb_mxcsr_x86_64: - reg_value = (uint32_t)m_xstate.xs_fxsave.fx_mxcsr; - break; - case lldb_mxcsrmask_x86_64: - reg_value = (uint32_t)m_xstate.xs_fxsave.fx_mxcsr_mask; - break; - case lldb_st0_x86_64: - case lldb_st1_x86_64: - case lldb_st2_x86_64: - case lldb_st3_x86_64: - case lldb_st4_x86_64: - case lldb_st5_x86_64: - case lldb_st6_x86_64: - case lldb_st7_x86_64: - reg_value.SetBytes(&m_xstate.xs_fxsave.fx_87_ac[reg - lldb_st0_x86_64], - reg_info->byte_size, endian::InlHostByteOrder()); - break; - case lldb_mm0_x86_64: - case lldb_mm1_x86_64: - case lldb_mm2_x86_64: - case lldb_mm3_x86_64: - case lldb_mm4_x86_64: - case lldb_mm5_x86_64: - case lldb_mm6_x86_64: - case lldb_mm7_x86_64: - reg_value.SetBytes(&m_xstate.xs_fxsave.fx_87_ac[reg - lldb_mm0_x86_64], - reg_info->byte_size, endian::InlHostByteOrder()); - break; - case lldb_xmm0_x86_64: - case lldb_xmm1_x86_64: - case lldb_xmm2_x86_64: - case lldb_xmm3_x86_64: - case lldb_xmm4_x86_64: - case lldb_xmm5_x86_64: - case lldb_xmm6_x86_64: - case lldb_xmm7_x86_64: - case lldb_xmm8_x86_64: - case lldb_xmm9_x86_64: - case lldb_xmm10_x86_64: - case lldb_xmm11_x86_64: - case lldb_xmm12_x86_64: - case lldb_xmm13_x86_64: - case lldb_xmm14_x86_64: - case lldb_xmm15_x86_64: - if (!(m_xstate.xs_rfbm & XCR0_SSE)) { + case YMMRegSet: { + llvm::Optional ymm_reg = GetYMMSplitReg(reg); + if (!ymm_reg) { error.SetErrorStringWithFormat( "register \"%s\" not supported by CPU/kernel", reg_info->name); } else { - reg_value.SetBytes(&m_xstate.xs_fxsave.fx_xmm[reg - lldb_xmm0_x86_64], - reg_info->byte_size, endian::InlHostByteOrder()); - } - break; - case lldb_ymm0_x86_64: - case lldb_ymm1_x86_64: - case lldb_ymm2_x86_64: - case lldb_ymm3_x86_64: - case lldb_ymm4_x86_64: - case lldb_ymm5_x86_64: - case lldb_ymm6_x86_64: - case lldb_ymm7_x86_64: - case lldb_ymm8_x86_64: - case lldb_ymm9_x86_64: - case lldb_ymm10_x86_64: - case lldb_ymm11_x86_64: - case lldb_ymm12_x86_64: - case lldb_ymm13_x86_64: - case lldb_ymm14_x86_64: - case lldb_ymm15_x86_64: - if (!(m_xstate.xs_rfbm & XCR0_SSE) || - !(m_xstate.xs_rfbm & XCR0_YMM_Hi128)) { - error.SetErrorStringWithFormat( - "register \"%s\" not supported by CPU/kernel", reg_info->name); - } else { - uint32_t reg_index = reg - lldb_ymm0_x86_64; - YMMReg ymm = - XStateToYMM(m_xstate.xs_fxsave.fx_xmm[reg_index].xmm_bytes, - m_xstate.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes); + YMMReg ymm = XStateToYMM(ymm_reg->xmm, ymm_reg->ymm_hi); reg_value.SetBytes(ymm.bytes, reg_info->byte_size, endian::InlHostByteOrder()); } break; - case lldb_dr0_x86_64: - case lldb_dr1_x86_64: - case lldb_dr2_x86_64: - case lldb_dr3_x86_64: - case lldb_dr4_x86_64: - case lldb_dr5_x86_64: - case lldb_dr6_x86_64: - case lldb_dr7_x86_64: - reg_value = (uint64_t)m_dbr.dr[reg - lldb_dr0_x86_64]; - break; - default: - llvm_unreachable("Reading unknown/unsupported register"); + } + case MPXRegSet: + llvm_unreachable("MPX regset should have returned error"); } return error; @@ -753,8 +470,8 @@ return error; } - int set = GetSetForNativeRegNum(reg); - if (set == -1) { + llvm::Optional opt_set = GetSetForNativeRegNum(reg); + if (!opt_set) { // This is likely an internal register for lldb use only and should not be // directly queried. error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", @@ -762,277 +479,52 @@ return error; } - uint64_t new_xstate_bv = XCR0_X87; // the most common case - - switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { - case llvm::Triple::x86_64: - break; - case llvm::Triple::x86: - reg = RegNumX86ToX86_64(reg); - break; - default: - llvm_unreachable("Unhandled target architecture."); - } + RegSetKind set = opt_set.getValue(); + uint64_t new_xstate_bv = 0; error = ReadRegisterSet(set); if (error.Fail()) return error; - switch (reg) { -#if defined(__x86_64__) - case lldb_rax_x86_64: - m_gpr.regs[_REG_RAX] = reg_value.GetAsUInt64(); - break; - case lldb_rbx_x86_64: - m_gpr.regs[_REG_RBX] = reg_value.GetAsUInt64(); - break; - case lldb_rcx_x86_64: - m_gpr.regs[_REG_RCX] = reg_value.GetAsUInt64(); - break; - case lldb_rdx_x86_64: - m_gpr.regs[_REG_RDX] = reg_value.GetAsUInt64(); - break; - case lldb_rdi_x86_64: - m_gpr.regs[_REG_RDI] = reg_value.GetAsUInt64(); - break; - case lldb_rsi_x86_64: - m_gpr.regs[_REG_RSI] = reg_value.GetAsUInt64(); - break; - case lldb_rbp_x86_64: - m_gpr.regs[_REG_RBP] = reg_value.GetAsUInt64(); - break; - case lldb_rsp_x86_64: - m_gpr.regs[_REG_RSP] = reg_value.GetAsUInt64(); - break; - case lldb_r8_x86_64: - m_gpr.regs[_REG_R8] = reg_value.GetAsUInt64(); - break; - case lldb_r9_x86_64: - m_gpr.regs[_REG_R9] = reg_value.GetAsUInt64(); - break; - case lldb_r10_x86_64: - m_gpr.regs[_REG_R10] = reg_value.GetAsUInt64(); - break; - case lldb_r11_x86_64: - m_gpr.regs[_REG_R11] = reg_value.GetAsUInt64(); - break; - case lldb_r12_x86_64: - m_gpr.regs[_REG_R12] = reg_value.GetAsUInt64(); - break; - case lldb_r13_x86_64: - m_gpr.regs[_REG_R13] = reg_value.GetAsUInt64(); - break; - case lldb_r14_x86_64: - m_gpr.regs[_REG_R14] = reg_value.GetAsUInt64(); - break; - case lldb_r15_x86_64: - m_gpr.regs[_REG_R15] = reg_value.GetAsUInt64(); - break; - case lldb_rip_x86_64: - m_gpr.regs[_REG_RIP] = reg_value.GetAsUInt64(); - break; - case lldb_rflags_x86_64: - m_gpr.regs[_REG_RFLAGS] = reg_value.GetAsUInt64(); - break; - case lldb_cs_x86_64: - m_gpr.regs[_REG_CS] = reg_value.GetAsUInt64(); - break; - case lldb_fs_x86_64: - m_gpr.regs[_REG_FS] = reg_value.GetAsUInt16(); - break; - case lldb_gs_x86_64: - m_gpr.regs[_REG_GS] = reg_value.GetAsUInt16(); - break; - case lldb_ss_x86_64: - m_gpr.regs[_REG_SS] = reg_value.GetAsUInt64(); - break; - case lldb_ds_x86_64: - m_gpr.regs[_REG_DS] = reg_value.GetAsUInt16(); - break; - case lldb_es_x86_64: - m_gpr.regs[_REG_ES] = reg_value.GetAsUInt16(); - break; -#else - case lldb_rax_x86_64: - m_gpr.r_eax = reg_value.GetAsUInt32(); - break; - case lldb_rbx_x86_64: - m_gpr.r_ebx = reg_value.GetAsUInt32(); - break; - case lldb_rcx_x86_64: - m_gpr.r_ecx = reg_value.GetAsUInt32(); - break; - case lldb_rdx_x86_64: - m_gpr.r_edx = reg_value.GetAsUInt32(); - break; - case lldb_rdi_x86_64: - m_gpr.r_edi = reg_value.GetAsUInt32(); - break; - case lldb_rsi_x86_64: - m_gpr.r_esi = reg_value.GetAsUInt32(); - break; - case lldb_rsp_x86_64: - m_gpr.r_esp = reg_value.GetAsUInt32(); - break; - case lldb_rbp_x86_64: - m_gpr.r_ebp = reg_value.GetAsUInt32(); - break; - case lldb_rip_x86_64: - m_gpr.r_eip = reg_value.GetAsUInt32(); - break; - case lldb_rflags_x86_64: - m_gpr.r_eflags = reg_value.GetAsUInt32(); - break; - case lldb_cs_x86_64: - m_gpr.r_cs = reg_value.GetAsUInt32(); - break; - case lldb_fs_x86_64: - m_gpr.r_fs = reg_value.GetAsUInt16(); - break; - case lldb_gs_x86_64: - m_gpr.r_gs = reg_value.GetAsUInt16(); - break; - case lldb_ss_x86_64: - m_gpr.r_ss = reg_value.GetAsUInt32(); - break; - case lldb_ds_x86_64: - m_gpr.r_ds = reg_value.GetAsUInt16(); - break; - case lldb_es_x86_64: - m_gpr.r_es = reg_value.GetAsUInt16(); - break; -#endif - case lldb_fctrl_x86_64: - m_xstate.xs_fxsave.fx_cw = reg_value.GetAsUInt16(); - break; - case lldb_fstat_x86_64: - m_xstate.xs_fxsave.fx_sw = reg_value.GetAsUInt16(); - break; - case lldb_ftag_x86_64: - m_xstate.xs_fxsave.fx_tw = FullToAbridgedTagWord(reg_value.GetAsUInt16()); - break; - case lldb_fop_x86_64: - m_xstate.xs_fxsave.fx_opcode = reg_value.GetAsUInt16(); - break; - case lldb_fiseg_x86_64: - m_xstate.xs_fxsave.fx_ip.fa_32.fa_seg = reg_value.GetAsUInt32(); - break; - case lldb_fioff_x86_64: - m_xstate.xs_fxsave.fx_ip.fa_32.fa_off = reg_value.GetAsUInt32(); - break; - case lldb_fip_x86_64: - m_xstate.xs_fxsave.fx_ip.fa_64 = reg_value.GetAsUInt64(); - break; - case lldb_foseg_x86_64: - m_xstate.xs_fxsave.fx_dp.fa_32.fa_seg = reg_value.GetAsUInt32(); - break; - case lldb_fooff_x86_64: - m_xstate.xs_fxsave.fx_dp.fa_32.fa_off = reg_value.GetAsUInt32(); - break; - case lldb_fdp_x86_64: - m_xstate.xs_fxsave.fx_dp.fa_64 = reg_value.GetAsUInt64(); - break; - case lldb_mxcsr_x86_64: - m_xstate.xs_fxsave.fx_mxcsr = reg_value.GetAsUInt32(); - new_xstate_bv = XCR0_SSE; - break; - case lldb_mxcsrmask_x86_64: - m_xstate.xs_fxsave.fx_mxcsr_mask = reg_value.GetAsUInt32(); - new_xstate_bv = XCR0_SSE; - break; - case lldb_st0_x86_64: - case lldb_st1_x86_64: - case lldb_st2_x86_64: - case lldb_st3_x86_64: - case lldb_st4_x86_64: - case lldb_st5_x86_64: - case lldb_st6_x86_64: - case lldb_st7_x86_64: - ::memcpy(&m_xstate.xs_fxsave.fx_87_ac[reg - lldb_st0_x86_64], - reg_value.GetBytes(), reg_value.GetByteSize()); - break; - case lldb_mm0_x86_64: - case lldb_mm1_x86_64: - case lldb_mm2_x86_64: - case lldb_mm3_x86_64: - case lldb_mm4_x86_64: - case lldb_mm5_x86_64: - case lldb_mm6_x86_64: - case lldb_mm7_x86_64: - ::memcpy(&m_xstate.xs_fxsave.fx_87_ac[reg - lldb_mm0_x86_64], + switch (set) { + case GPRegSet: + case DBRegSet: + ::memcpy(GetOffsetRegSetData(set, reg_info->byte_offset), reg_value.GetBytes(), reg_value.GetByteSize()); break; - case lldb_xmm0_x86_64: - case lldb_xmm1_x86_64: - case lldb_xmm2_x86_64: - case lldb_xmm3_x86_64: - case lldb_xmm4_x86_64: - case lldb_xmm5_x86_64: - case lldb_xmm6_x86_64: - case lldb_xmm7_x86_64: - case lldb_xmm8_x86_64: - case lldb_xmm9_x86_64: - case lldb_xmm10_x86_64: - case lldb_xmm11_x86_64: - case lldb_xmm12_x86_64: - case lldb_xmm13_x86_64: - case lldb_xmm14_x86_64: - case lldb_xmm15_x86_64: - if (!(m_xstate.xs_rfbm & XCR0_SSE)) { - error.SetErrorStringWithFormat( - "register \"%s\" not supported by CPU/kernel", reg_info->name); - } else { - ::memcpy(&m_xstate.xs_fxsave.fx_xmm[reg - lldb_xmm0_x86_64], - reg_value.GetBytes(), reg_value.GetByteSize()); - new_xstate_bv = XCR0_SSE; - } + case FPRegSet: { + void *data = GetOffsetRegSetData(set, reg_info->byte_offset); + FXSAVE *fpr = reinterpret_cast(m_xstate.data() + + offsetof(xstate, xs_fxsave)); + if (data == &fpr->ftag) // ftag + fpr->ftag = FullToAbridgedTagWord(reg_value.GetAsUInt16()); + else + ::memcpy(data, reg_value.GetBytes(), reg_value.GetByteSize()); + if (data >= &fpr->xmm) + new_xstate_bv |= XCR0_SSE; + else + new_xstate_bv |= XCR0_X87; break; - case lldb_ymm0_x86_64: - case lldb_ymm1_x86_64: - case lldb_ymm2_x86_64: - case lldb_ymm3_x86_64: - case lldb_ymm4_x86_64: - case lldb_ymm5_x86_64: - case lldb_ymm6_x86_64: - case lldb_ymm7_x86_64: - case lldb_ymm8_x86_64: - case lldb_ymm9_x86_64: - case lldb_ymm10_x86_64: - case lldb_ymm11_x86_64: - case lldb_ymm12_x86_64: - case lldb_ymm13_x86_64: - case lldb_ymm14_x86_64: - case lldb_ymm15_x86_64: - if (!(m_xstate.xs_rfbm & XCR0_SSE) || - !(m_xstate.xs_rfbm & XCR0_YMM_Hi128)) { + } + case YMMRegSet: { + llvm::Optional ymm_reg = GetYMMSplitReg(reg); + if (!ymm_reg) { error.SetErrorStringWithFormat( "register \"%s\" not supported by CPU/kernel", reg_info->name); } else { - uint32_t reg_index = reg - lldb_ymm0_x86_64; YMMReg ymm; ::memcpy(ymm.bytes, reg_value.GetBytes(), reg_value.GetByteSize()); - YMMToXState(ymm, m_xstate.xs_fxsave.fx_xmm[reg_index].xmm_bytes, - m_xstate.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes); - new_xstate_bv = XCR0_SSE | XCR0_YMM_Hi128; + YMMToXState(ymm, ymm_reg->xmm, ymm_reg->ymm_hi); + new_xstate_bv |= XCR0_SSE | XCR0_YMM_Hi128; } break; - case lldb_dr0_x86_64: - case lldb_dr1_x86_64: - case lldb_dr2_x86_64: - case lldb_dr3_x86_64: - case lldb_dr4_x86_64: - case lldb_dr5_x86_64: - case lldb_dr6_x86_64: - case lldb_dr7_x86_64: - m_dbr.dr[reg - lldb_dr0_x86_64] = reg_value.GetAsUInt64(); - break; - default: - llvm_unreachable("Reading unknown/unsupported register"); + } + case MPXRegSet: + llvm_unreachable("MPX regset should have returned error"); } - if (set == XStateRegSet) - m_xstate.xs_xstate_bv |= new_xstate_bv; - + if (new_xstate_bv != 0) + reinterpret_cast(m_xstate.data())->xs_xstate_bv |= new_xstate_bv; return WriteRegisterSet(set); } @@ -1046,7 +538,7 @@ return error; uint8_t *dst = data_sp->GetBytes(); - ::memcpy(dst, &m_gpr, GetRegisterInfoInterface().GetGPRSize()); + ::memcpy(dst, m_gpr.data(), GetRegisterInfoInterface().GetGPRSize()); dst += GetRegisterInfoInterface().GetGPRSize(); return error; @@ -1079,7 +571,7 @@ __FUNCTION__); return error; } - ::memcpy(&m_gpr, src, GetRegisterInfoInterface().GetGPRSize()); + ::memcpy(m_gpr.data(), src, GetRegisterInfoInterface().GetGPRSize()); error = WriteRegisterSet(GPRegSet); if (error.Fail()) @@ -1089,25 +581,15 @@ return error; } -int NativeRegisterContextNetBSD_x86_64::GetDR(int num) const { - assert(num >= 0 && num <= 7); - switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { - case llvm::Triple::x86: - return lldb_dr0_i386 + num; - case llvm::Triple::x86_64: - return lldb_dr0_x86_64 + num; - default: - llvm_unreachable("Unhandled target architecture."); - } -} - llvm::Error NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom( NativeRegisterContextNetBSD &source) { - auto &r_source = static_cast(source); - Status res = r_source.ReadRegisterSet(DBRegSet); + auto &r_source = static_cast(source); + // NB: This implicitly reads the whole dbreg set. + RegisterValue dr7; + Status res = r_source.ReadRegister(GetDR(7), dr7); if (!res.Fail()) { // copy dbregs only if any watchpoints were set - if ((r_source.m_dbr.dr[7] & 0xFF) == 0) + if ((dr7.GetAsUInt64() & 0xFF) == 0) return llvm::Error::success(); m_dbr = r_source.m_dbr; @@ -1116,4 +598,49 @@ return res.ToError(); } +uint8_t * +NativeRegisterContextNetBSD_x86_64::GetOffsetRegSetData(RegSetKind set, + size_t reg_offset) { + uint8_t *base; + switch (set) { + case GPRegSet: + base = m_gpr.data(); + break; + case FPRegSet: + base = m_xstate.data() + offsetof(xstate, xs_fxsave); + break; + case DBRegSet: + base = m_dbr.data(); + break; + case YMMRegSet: + llvm_unreachable("GetRegSetData() is unsuitable for this regset."); + case MPXRegSet: + llvm_unreachable("MPX regset should have returned error"); + } + assert(reg_offset >= m_regset_offsets[set]); + return base + (reg_offset - m_regset_offsets[set]); +} + +llvm::Optional +NativeRegisterContextNetBSD_x86_64::GetYMMSplitReg(uint32_t reg) { + auto xst = reinterpret_cast(m_xstate.data()); + if (!(xst->xs_rfbm & XCR0_SSE) || !(xst->xs_rfbm & XCR0_YMM_Hi128)) + return llvm::None; + + uint32_t reg_index; + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::x86: + reg_index = reg - lldb_ymm0_i386; + break; + case llvm::Triple::x86_64: + reg_index = reg - lldb_ymm0_x86_64; + break; + default: + llvm_unreachable("Unhandled target architecture."); + } + + return YMMSplitPtr{&xst->xs_fxsave.fx_xmm[reg_index], + &xst->xs_ymm_hi128.xs_ymm[reg_index]}; +} + #endif // defined(__x86_64__)