180814287SRaphael Isemann //===-- NativeRegisterContextWindows_arm.cpp ------------------------------===// 2a59444a3SMartin Storsjo // 3a59444a3SMartin Storsjo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a59444a3SMartin Storsjo // See https://llvm.org/LICENSE.txt for license information. 5a59444a3SMartin Storsjo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a59444a3SMartin Storsjo // 7a59444a3SMartin Storsjo //===----------------------------------------------------------------------===// 8a59444a3SMartin Storsjo 9a59444a3SMartin Storsjo #if defined(__arm__) || defined(_M_ARM) 10a59444a3SMartin Storsjo 11a59444a3SMartin Storsjo #include "NativeRegisterContextWindows_arm.h" 12a59444a3SMartin Storsjo #include "NativeThreadWindows.h" 13a59444a3SMartin Storsjo #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" 14a59444a3SMartin Storsjo #include "ProcessWindowsLog.h" 15a59444a3SMartin Storsjo #include "lldb/Host/HostInfo.h" 16a59444a3SMartin Storsjo #include "lldb/Host/HostThread.h" 17a59444a3SMartin Storsjo #include "lldb/Host/windows/HostThreadWindows.h" 18a59444a3SMartin Storsjo #include "lldb/Host/windows/windows.h" 19a59444a3SMartin Storsjo 20a59444a3SMartin Storsjo #include "lldb/Utility/Log.h" 21a59444a3SMartin Storsjo #include "lldb/Utility/RegisterValue.h" 22a59444a3SMartin Storsjo #include "llvm/ADT/STLExtras.h" 23a59444a3SMartin Storsjo 24a59444a3SMartin Storsjo using namespace lldb; 25a59444a3SMartin Storsjo using namespace lldb_private; 26a59444a3SMartin Storsjo 27a59444a3SMartin Storsjo #define REG_CONTEXT_SIZE sizeof(::CONTEXT) 28a59444a3SMartin Storsjo 29a59444a3SMartin Storsjo namespace { 30a59444a3SMartin Storsjo static const uint32_t g_gpr_regnums_arm[] = { 31a59444a3SMartin Storsjo gpr_r0_arm, gpr_r1_arm, gpr_r2_arm, gpr_r3_arm, gpr_r4_arm, 32a59444a3SMartin Storsjo gpr_r5_arm, gpr_r6_arm, gpr_r7_arm, gpr_r8_arm, gpr_r9_arm, 33a59444a3SMartin Storsjo gpr_r10_arm, gpr_r11_arm, gpr_r12_arm, gpr_sp_arm, gpr_lr_arm, 34a59444a3SMartin Storsjo gpr_pc_arm, gpr_cpsr_arm, 35a59444a3SMartin Storsjo LLDB_INVALID_REGNUM // Register set must be terminated with this flag 36a59444a3SMartin Storsjo }; 37a59444a3SMartin Storsjo static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == 38a59444a3SMartin Storsjo k_num_gpr_registers_arm, 39a59444a3SMartin Storsjo "g_gpr_regnums_arm has wrong number of register infos"); 40a59444a3SMartin Storsjo 41a59444a3SMartin Storsjo static const uint32_t g_fpr_regnums_arm[] = { 42a59444a3SMartin Storsjo fpu_s0_arm, fpu_s1_arm, fpu_s2_arm, fpu_s3_arm, fpu_s4_arm, 43a59444a3SMartin Storsjo fpu_s5_arm, fpu_s6_arm, fpu_s7_arm, fpu_s8_arm, fpu_s9_arm, 44a59444a3SMartin Storsjo fpu_s10_arm, fpu_s11_arm, fpu_s12_arm, fpu_s13_arm, fpu_s14_arm, 45a59444a3SMartin Storsjo fpu_s15_arm, fpu_s16_arm, fpu_s17_arm, fpu_s18_arm, fpu_s19_arm, 46a59444a3SMartin Storsjo fpu_s20_arm, fpu_s21_arm, fpu_s22_arm, fpu_s23_arm, fpu_s24_arm, 47a59444a3SMartin Storsjo fpu_s25_arm, fpu_s26_arm, fpu_s27_arm, fpu_s28_arm, fpu_s29_arm, 48a59444a3SMartin Storsjo fpu_s30_arm, fpu_s31_arm, 49a59444a3SMartin Storsjo 50a59444a3SMartin Storsjo fpu_d0_arm, fpu_d1_arm, fpu_d2_arm, fpu_d3_arm, fpu_d4_arm, 51a59444a3SMartin Storsjo fpu_d5_arm, fpu_d6_arm, fpu_d7_arm, fpu_d8_arm, fpu_d9_arm, 52a59444a3SMartin Storsjo fpu_d10_arm, fpu_d11_arm, fpu_d12_arm, fpu_d13_arm, fpu_d14_arm, 53a59444a3SMartin Storsjo fpu_d15_arm, fpu_d16_arm, fpu_d17_arm, fpu_d18_arm, fpu_d19_arm, 54a59444a3SMartin Storsjo fpu_d20_arm, fpu_d21_arm, fpu_d22_arm, fpu_d23_arm, fpu_d24_arm, 55a59444a3SMartin Storsjo fpu_d25_arm, fpu_d26_arm, fpu_d27_arm, fpu_d28_arm, fpu_d29_arm, 56a59444a3SMartin Storsjo fpu_d30_arm, fpu_d31_arm, 57a59444a3SMartin Storsjo 58a59444a3SMartin Storsjo fpu_q0_arm, fpu_q1_arm, fpu_q2_arm, fpu_q3_arm, fpu_q4_arm, 59a59444a3SMartin Storsjo fpu_q5_arm, fpu_q6_arm, fpu_q7_arm, fpu_q8_arm, fpu_q9_arm, 60a59444a3SMartin Storsjo fpu_q10_arm, fpu_q11_arm, fpu_q12_arm, fpu_q13_arm, fpu_q14_arm, 61a59444a3SMartin Storsjo fpu_q15_arm, 62a59444a3SMartin Storsjo 63a59444a3SMartin Storsjo fpu_fpscr_arm, 64a59444a3SMartin Storsjo LLDB_INVALID_REGNUM // Register set must be terminated with this flag 65a59444a3SMartin Storsjo }; 66a59444a3SMartin Storsjo static_assert(((sizeof g_fpr_regnums_arm / sizeof g_fpr_regnums_arm[0]) - 1) == 67a59444a3SMartin Storsjo k_num_fpr_registers_arm, 68a59444a3SMartin Storsjo "g_fpu_regnums_arm has wrong number of register infos"); 69a59444a3SMartin Storsjo 70a59444a3SMartin Storsjo static const RegisterSet g_reg_sets_arm[] = { 7147b76631SJoe Loser {"General Purpose Registers", "gpr", std::size(g_gpr_regnums_arm) - 1, 7247b76631SJoe Loser g_gpr_regnums_arm}, 7347b76631SJoe Loser {"Floating Point Registers", "fpr", std::size(g_fpr_regnums_arm) - 1, 7447b76631SJoe Loser g_fpr_regnums_arm}, 75a59444a3SMartin Storsjo }; 76a59444a3SMartin Storsjo 77a59444a3SMartin Storsjo enum { k_num_register_sets = 2 }; 78a59444a3SMartin Storsjo 79a59444a3SMartin Storsjo } // namespace 80a59444a3SMartin Storsjo 81a59444a3SMartin Storsjo static RegisterInfoInterface * 82a59444a3SMartin Storsjo CreateRegisterInfoInterface(const ArchSpec &target_arch) { 83b4133a21SMartin Storsjö assert((HostInfo::GetArchitecture().GetAddressByteSize() == 4) && 84b4133a21SMartin Storsjö "Register setting path assumes this is a 32-bit host"); 85a59444a3SMartin Storsjo return new RegisterInfoPOSIX_arm(target_arch); 86a59444a3SMartin Storsjo } 87a59444a3SMartin Storsjo 88a59444a3SMartin Storsjo static Status GetThreadContextHelper(lldb::thread_t thread_handle, 89a59444a3SMartin Storsjo PCONTEXT context_ptr, 90a59444a3SMartin Storsjo const DWORD control_flag) { 916730df47SPavel Labath Log *log = GetLog(WindowsLog::Registers); 92a59444a3SMartin Storsjo Status error; 93a59444a3SMartin Storsjo 94a59444a3SMartin Storsjo memset(context_ptr, 0, sizeof(::CONTEXT)); 95a59444a3SMartin Storsjo context_ptr->ContextFlags = control_flag; 96a59444a3SMartin Storsjo if (!::GetThreadContext(thread_handle, context_ptr)) { 97*6ae657b0SAdrian Prantl error = Status(GetLastError(), eErrorTypeWin32); 98a59444a3SMartin Storsjo LLDB_LOG(log, "{0} GetThreadContext failed with error {1}", __FUNCTION__, 99a59444a3SMartin Storsjo error); 100a59444a3SMartin Storsjo return error; 101a59444a3SMartin Storsjo } 102a59444a3SMartin Storsjo return Status(); 103a59444a3SMartin Storsjo } 104a59444a3SMartin Storsjo 105a59444a3SMartin Storsjo static Status SetThreadContextHelper(lldb::thread_t thread_handle, 106a59444a3SMartin Storsjo PCONTEXT context_ptr) { 1076730df47SPavel Labath Log *log = GetLog(WindowsLog::Registers); 108a59444a3SMartin Storsjo Status error; 109a59444a3SMartin Storsjo // It's assumed that the thread has stopped. 110a59444a3SMartin Storsjo if (!::SetThreadContext(thread_handle, context_ptr)) { 111*6ae657b0SAdrian Prantl error = Status(GetLastError(), eErrorTypeWin32); 112a59444a3SMartin Storsjo LLDB_LOG(log, "{0} SetThreadContext failed with error {1}", __FUNCTION__, 113a59444a3SMartin Storsjo error); 114a59444a3SMartin Storsjo return error; 115a59444a3SMartin Storsjo } 116a59444a3SMartin Storsjo return Status(); 117a59444a3SMartin Storsjo } 118a59444a3SMartin Storsjo 119a59444a3SMartin Storsjo std::unique_ptr<NativeRegisterContextWindows> 120a59444a3SMartin Storsjo NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows( 121a59444a3SMartin Storsjo const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { 122a59444a3SMartin Storsjo // TODO: Register context for a WoW64 application? 123a59444a3SMartin Storsjo 124a59444a3SMartin Storsjo // Register context for a native 64-bit application. 125a59444a3SMartin Storsjo return std::make_unique<NativeRegisterContextWindows_arm>(target_arch, 126a59444a3SMartin Storsjo native_thread); 127a59444a3SMartin Storsjo } 128a59444a3SMartin Storsjo 129a59444a3SMartin Storsjo NativeRegisterContextWindows_arm::NativeRegisterContextWindows_arm( 130a59444a3SMartin Storsjo const ArchSpec &target_arch, NativeThreadProtocol &native_thread) 131a59444a3SMartin Storsjo : NativeRegisterContextWindows(native_thread, 132a59444a3SMartin Storsjo CreateRegisterInfoInterface(target_arch)) {} 133a59444a3SMartin Storsjo 134a59444a3SMartin Storsjo bool NativeRegisterContextWindows_arm::IsGPR(uint32_t reg_index) const { 135a59444a3SMartin Storsjo return (reg_index >= k_first_gpr_arm && reg_index <= k_last_gpr_arm); 136a59444a3SMartin Storsjo } 137a59444a3SMartin Storsjo 138a59444a3SMartin Storsjo bool NativeRegisterContextWindows_arm::IsFPR(uint32_t reg_index) const { 139a59444a3SMartin Storsjo return (reg_index >= k_first_fpr_arm && reg_index <= k_last_fpr_arm); 140a59444a3SMartin Storsjo } 141a59444a3SMartin Storsjo 142a59444a3SMartin Storsjo uint32_t NativeRegisterContextWindows_arm::GetRegisterSetCount() const { 143a59444a3SMartin Storsjo return k_num_register_sets; 144a59444a3SMartin Storsjo } 145a59444a3SMartin Storsjo 146a59444a3SMartin Storsjo const RegisterSet * 147a59444a3SMartin Storsjo NativeRegisterContextWindows_arm::GetRegisterSet(uint32_t set_index) const { 148a59444a3SMartin Storsjo if (set_index >= k_num_register_sets) 149a59444a3SMartin Storsjo return nullptr; 150a59444a3SMartin Storsjo return &g_reg_sets_arm[set_index]; 151a59444a3SMartin Storsjo } 152a59444a3SMartin Storsjo 153a59444a3SMartin Storsjo Status NativeRegisterContextWindows_arm::GPRRead(const uint32_t reg, 154a59444a3SMartin Storsjo RegisterValue ®_value) { 155a59444a3SMartin Storsjo ::CONTEXT tls_context; 156a59444a3SMartin Storsjo DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER; 157a59444a3SMartin Storsjo Status error = 158a59444a3SMartin Storsjo GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag); 159a59444a3SMartin Storsjo if (error.Fail()) 160a59444a3SMartin Storsjo return error; 161a59444a3SMartin Storsjo 162a59444a3SMartin Storsjo switch (reg) { 163a59444a3SMartin Storsjo case gpr_r0_arm: 164a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R0); 165a59444a3SMartin Storsjo break; 166a59444a3SMartin Storsjo case gpr_r1_arm: 167a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R1); 168a59444a3SMartin Storsjo break; 169a59444a3SMartin Storsjo case gpr_r2_arm: 170a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R2); 171a59444a3SMartin Storsjo break; 172a59444a3SMartin Storsjo case gpr_r3_arm: 173a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R3); 174a59444a3SMartin Storsjo break; 175a59444a3SMartin Storsjo case gpr_r4_arm: 176a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R4); 177a59444a3SMartin Storsjo break; 178a59444a3SMartin Storsjo case gpr_r5_arm: 179a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R5); 180a59444a3SMartin Storsjo break; 181a59444a3SMartin Storsjo case gpr_r6_arm: 182a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R6); 183a59444a3SMartin Storsjo break; 184a59444a3SMartin Storsjo case gpr_r7_arm: 185a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R7); 186a59444a3SMartin Storsjo break; 187a59444a3SMartin Storsjo case gpr_r8_arm: 188a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R8); 189a59444a3SMartin Storsjo break; 190a59444a3SMartin Storsjo case gpr_r9_arm: 191a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R9); 192a59444a3SMartin Storsjo break; 193a59444a3SMartin Storsjo case gpr_r10_arm: 194a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R10); 195a59444a3SMartin Storsjo break; 196a59444a3SMartin Storsjo case gpr_r11_arm: 197a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R11); 198a59444a3SMartin Storsjo break; 199a59444a3SMartin Storsjo case gpr_r12_arm: 200a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.R12); 201a59444a3SMartin Storsjo break; 202a59444a3SMartin Storsjo case gpr_sp_arm: 203a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.Sp); 204a59444a3SMartin Storsjo break; 205a59444a3SMartin Storsjo case gpr_lr_arm: 206a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.Lr); 207a59444a3SMartin Storsjo break; 208a59444a3SMartin Storsjo case gpr_pc_arm: 209a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.Pc); 210a59444a3SMartin Storsjo break; 211a59444a3SMartin Storsjo case gpr_cpsr_arm: 212a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.Cpsr); 213a59444a3SMartin Storsjo break; 214a59444a3SMartin Storsjo } 215a59444a3SMartin Storsjo 216a59444a3SMartin Storsjo return error; 217a59444a3SMartin Storsjo } 218a59444a3SMartin Storsjo 219a59444a3SMartin Storsjo Status 220a59444a3SMartin Storsjo NativeRegisterContextWindows_arm::GPRWrite(const uint32_t reg, 221a59444a3SMartin Storsjo const RegisterValue ®_value) { 222a59444a3SMartin Storsjo ::CONTEXT tls_context; 223a59444a3SMartin Storsjo DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER; 224a59444a3SMartin Storsjo auto thread_handle = GetThreadHandle(); 225a59444a3SMartin Storsjo Status error = 226a59444a3SMartin Storsjo GetThreadContextHelper(thread_handle, &tls_context, context_flag); 227a59444a3SMartin Storsjo if (error.Fail()) 228a59444a3SMartin Storsjo return error; 229a59444a3SMartin Storsjo 230a59444a3SMartin Storsjo switch (reg) { 231a59444a3SMartin Storsjo case gpr_r0_arm: 232a59444a3SMartin Storsjo tls_context.R0 = reg_value.GetAsUInt32(); 233a59444a3SMartin Storsjo break; 234a59444a3SMartin Storsjo case gpr_r1_arm: 235a59444a3SMartin Storsjo tls_context.R1 = reg_value.GetAsUInt32(); 236a59444a3SMartin Storsjo break; 237a59444a3SMartin Storsjo case gpr_r2_arm: 238a59444a3SMartin Storsjo tls_context.R2 = reg_value.GetAsUInt32(); 239a59444a3SMartin Storsjo break; 240a59444a3SMartin Storsjo case gpr_r3_arm: 241a59444a3SMartin Storsjo tls_context.R3 = reg_value.GetAsUInt32(); 242a59444a3SMartin Storsjo break; 243a59444a3SMartin Storsjo case gpr_r4_arm: 244a59444a3SMartin Storsjo tls_context.R4 = reg_value.GetAsUInt32(); 245a59444a3SMartin Storsjo break; 246a59444a3SMartin Storsjo case gpr_r5_arm: 247a59444a3SMartin Storsjo tls_context.R5 = reg_value.GetAsUInt32(); 248a59444a3SMartin Storsjo break; 249a59444a3SMartin Storsjo case gpr_r6_arm: 250a59444a3SMartin Storsjo tls_context.R6 = reg_value.GetAsUInt32(); 251a59444a3SMartin Storsjo break; 252a59444a3SMartin Storsjo case gpr_r7_arm: 253a59444a3SMartin Storsjo tls_context.R7 = reg_value.GetAsUInt32(); 254a59444a3SMartin Storsjo break; 255a59444a3SMartin Storsjo case gpr_r8_arm: 256a59444a3SMartin Storsjo tls_context.R8 = reg_value.GetAsUInt32(); 257a59444a3SMartin Storsjo break; 258a59444a3SMartin Storsjo case gpr_r9_arm: 259a59444a3SMartin Storsjo tls_context.R9 = reg_value.GetAsUInt32(); 260a59444a3SMartin Storsjo break; 261a59444a3SMartin Storsjo case gpr_r10_arm: 262a59444a3SMartin Storsjo tls_context.R10 = reg_value.GetAsUInt32(); 263a59444a3SMartin Storsjo break; 264a59444a3SMartin Storsjo case gpr_r11_arm: 265a59444a3SMartin Storsjo tls_context.R11 = reg_value.GetAsUInt32(); 266a59444a3SMartin Storsjo break; 267a59444a3SMartin Storsjo case gpr_r12_arm: 268a59444a3SMartin Storsjo tls_context.R12 = reg_value.GetAsUInt32(); 269a59444a3SMartin Storsjo break; 270a59444a3SMartin Storsjo case gpr_sp_arm: 271a59444a3SMartin Storsjo tls_context.Sp = reg_value.GetAsUInt32(); 272a59444a3SMartin Storsjo break; 273a59444a3SMartin Storsjo case gpr_lr_arm: 274a59444a3SMartin Storsjo tls_context.Lr = reg_value.GetAsUInt32(); 275a59444a3SMartin Storsjo break; 276a59444a3SMartin Storsjo case gpr_pc_arm: 277a59444a3SMartin Storsjo tls_context.Pc = reg_value.GetAsUInt32(); 278a59444a3SMartin Storsjo break; 279a59444a3SMartin Storsjo case gpr_cpsr_arm: 280a59444a3SMartin Storsjo tls_context.Cpsr = reg_value.GetAsUInt32(); 281a59444a3SMartin Storsjo break; 282a59444a3SMartin Storsjo } 283a59444a3SMartin Storsjo 284a59444a3SMartin Storsjo return SetThreadContextHelper(thread_handle, &tls_context); 285a59444a3SMartin Storsjo } 286a59444a3SMartin Storsjo 287a59444a3SMartin Storsjo Status NativeRegisterContextWindows_arm::FPRRead(const uint32_t reg, 288a59444a3SMartin Storsjo RegisterValue ®_value) { 289a59444a3SMartin Storsjo ::CONTEXT tls_context; 290a59444a3SMartin Storsjo DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT; 291a59444a3SMartin Storsjo Status error = 292a59444a3SMartin Storsjo GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag); 293a59444a3SMartin Storsjo if (error.Fail()) 294a59444a3SMartin Storsjo return error; 295a59444a3SMartin Storsjo 296a59444a3SMartin Storsjo switch (reg) { 297a59444a3SMartin Storsjo case fpu_s0_arm: 298a59444a3SMartin Storsjo case fpu_s1_arm: 299a59444a3SMartin Storsjo case fpu_s2_arm: 300a59444a3SMartin Storsjo case fpu_s3_arm: 301a59444a3SMartin Storsjo case fpu_s4_arm: 302a59444a3SMartin Storsjo case fpu_s5_arm: 303a59444a3SMartin Storsjo case fpu_s6_arm: 304a59444a3SMartin Storsjo case fpu_s7_arm: 305a59444a3SMartin Storsjo case fpu_s8_arm: 306a59444a3SMartin Storsjo case fpu_s9_arm: 307a59444a3SMartin Storsjo case fpu_s10_arm: 308a59444a3SMartin Storsjo case fpu_s11_arm: 309a59444a3SMartin Storsjo case fpu_s12_arm: 310a59444a3SMartin Storsjo case fpu_s13_arm: 311a59444a3SMartin Storsjo case fpu_s14_arm: 312a59444a3SMartin Storsjo case fpu_s15_arm: 313a59444a3SMartin Storsjo case fpu_s16_arm: 314a59444a3SMartin Storsjo case fpu_s17_arm: 315a59444a3SMartin Storsjo case fpu_s18_arm: 316a59444a3SMartin Storsjo case fpu_s19_arm: 317a59444a3SMartin Storsjo case fpu_s20_arm: 318a59444a3SMartin Storsjo case fpu_s21_arm: 319a59444a3SMartin Storsjo case fpu_s22_arm: 320a59444a3SMartin Storsjo case fpu_s23_arm: 321a59444a3SMartin Storsjo case fpu_s24_arm: 322a59444a3SMartin Storsjo case fpu_s25_arm: 323a59444a3SMartin Storsjo case fpu_s26_arm: 324a59444a3SMartin Storsjo case fpu_s27_arm: 325a59444a3SMartin Storsjo case fpu_s28_arm: 326a59444a3SMartin Storsjo case fpu_s29_arm: 327a59444a3SMartin Storsjo case fpu_s30_arm: 328a59444a3SMartin Storsjo case fpu_s31_arm: 329a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.S[reg - fpu_s0_arm], 330a59444a3SMartin Storsjo RegisterValue::eTypeFloat); 331a59444a3SMartin Storsjo break; 332a59444a3SMartin Storsjo 333a59444a3SMartin Storsjo case fpu_d0_arm: 334a59444a3SMartin Storsjo case fpu_d1_arm: 335a59444a3SMartin Storsjo case fpu_d2_arm: 336a59444a3SMartin Storsjo case fpu_d3_arm: 337a59444a3SMartin Storsjo case fpu_d4_arm: 338a59444a3SMartin Storsjo case fpu_d5_arm: 339a59444a3SMartin Storsjo case fpu_d6_arm: 340a59444a3SMartin Storsjo case fpu_d7_arm: 341a59444a3SMartin Storsjo case fpu_d8_arm: 342a59444a3SMartin Storsjo case fpu_d9_arm: 343a59444a3SMartin Storsjo case fpu_d10_arm: 344a59444a3SMartin Storsjo case fpu_d11_arm: 345a59444a3SMartin Storsjo case fpu_d12_arm: 346a59444a3SMartin Storsjo case fpu_d13_arm: 347a59444a3SMartin Storsjo case fpu_d14_arm: 348a59444a3SMartin Storsjo case fpu_d15_arm: 349a59444a3SMartin Storsjo case fpu_d16_arm: 350a59444a3SMartin Storsjo case fpu_d17_arm: 351a59444a3SMartin Storsjo case fpu_d18_arm: 352a59444a3SMartin Storsjo case fpu_d19_arm: 353a59444a3SMartin Storsjo case fpu_d20_arm: 354a59444a3SMartin Storsjo case fpu_d21_arm: 355a59444a3SMartin Storsjo case fpu_d22_arm: 356a59444a3SMartin Storsjo case fpu_d23_arm: 357a59444a3SMartin Storsjo case fpu_d24_arm: 358a59444a3SMartin Storsjo case fpu_d25_arm: 359a59444a3SMartin Storsjo case fpu_d26_arm: 360a59444a3SMartin Storsjo case fpu_d27_arm: 361a59444a3SMartin Storsjo case fpu_d28_arm: 362a59444a3SMartin Storsjo case fpu_d29_arm: 363a59444a3SMartin Storsjo case fpu_d30_arm: 364a59444a3SMartin Storsjo case fpu_d31_arm: 365a59444a3SMartin Storsjo reg_value.SetUInt64(tls_context.D[reg - fpu_d0_arm], 366a59444a3SMartin Storsjo RegisterValue::eTypeDouble); 367a59444a3SMartin Storsjo break; 368a59444a3SMartin Storsjo 369a59444a3SMartin Storsjo case fpu_q0_arm: 370a59444a3SMartin Storsjo case fpu_q1_arm: 371a59444a3SMartin Storsjo case fpu_q2_arm: 372a59444a3SMartin Storsjo case fpu_q3_arm: 373a59444a3SMartin Storsjo case fpu_q4_arm: 374a59444a3SMartin Storsjo case fpu_q5_arm: 375a59444a3SMartin Storsjo case fpu_q6_arm: 376a59444a3SMartin Storsjo case fpu_q7_arm: 377a59444a3SMartin Storsjo case fpu_q8_arm: 378a59444a3SMartin Storsjo case fpu_q9_arm: 379a59444a3SMartin Storsjo case fpu_q10_arm: 380a59444a3SMartin Storsjo case fpu_q11_arm: 381a59444a3SMartin Storsjo case fpu_q12_arm: 382a59444a3SMartin Storsjo case fpu_q13_arm: 383a59444a3SMartin Storsjo case fpu_q14_arm: 384a59444a3SMartin Storsjo case fpu_q15_arm: 385a59444a3SMartin Storsjo reg_value.SetBytes(&tls_context.Q[reg - fpu_q0_arm], 16, 386a59444a3SMartin Storsjo endian::InlHostByteOrder()); 387a59444a3SMartin Storsjo break; 388a59444a3SMartin Storsjo 389a59444a3SMartin Storsjo case fpu_fpscr_arm: 390a59444a3SMartin Storsjo reg_value.SetUInt32(tls_context.Fpscr); 391a59444a3SMartin Storsjo break; 392a59444a3SMartin Storsjo } 393a59444a3SMartin Storsjo 394a59444a3SMartin Storsjo return error; 395a59444a3SMartin Storsjo } 396a59444a3SMartin Storsjo 397a59444a3SMartin Storsjo Status 398a59444a3SMartin Storsjo NativeRegisterContextWindows_arm::FPRWrite(const uint32_t reg, 399a59444a3SMartin Storsjo const RegisterValue ®_value) { 400a59444a3SMartin Storsjo ::CONTEXT tls_context; 401a59444a3SMartin Storsjo DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT; 402a59444a3SMartin Storsjo auto thread_handle = GetThreadHandle(); 403a59444a3SMartin Storsjo Status error = 404a59444a3SMartin Storsjo GetThreadContextHelper(thread_handle, &tls_context, context_flag); 405a59444a3SMartin Storsjo if (error.Fail()) 406a59444a3SMartin Storsjo return error; 407a59444a3SMartin Storsjo 408a59444a3SMartin Storsjo switch (reg) { 409a59444a3SMartin Storsjo case fpu_s0_arm: 410a59444a3SMartin Storsjo case fpu_s1_arm: 411a59444a3SMartin Storsjo case fpu_s2_arm: 412a59444a3SMartin Storsjo case fpu_s3_arm: 413a59444a3SMartin Storsjo case fpu_s4_arm: 414a59444a3SMartin Storsjo case fpu_s5_arm: 415a59444a3SMartin Storsjo case fpu_s6_arm: 416a59444a3SMartin Storsjo case fpu_s7_arm: 417a59444a3SMartin Storsjo case fpu_s8_arm: 418a59444a3SMartin Storsjo case fpu_s9_arm: 419a59444a3SMartin Storsjo case fpu_s10_arm: 420a59444a3SMartin Storsjo case fpu_s11_arm: 421a59444a3SMartin Storsjo case fpu_s12_arm: 422a59444a3SMartin Storsjo case fpu_s13_arm: 423a59444a3SMartin Storsjo case fpu_s14_arm: 424a59444a3SMartin Storsjo case fpu_s15_arm: 425a59444a3SMartin Storsjo case fpu_s16_arm: 426a59444a3SMartin Storsjo case fpu_s17_arm: 427a59444a3SMartin Storsjo case fpu_s18_arm: 428a59444a3SMartin Storsjo case fpu_s19_arm: 429a59444a3SMartin Storsjo case fpu_s20_arm: 430a59444a3SMartin Storsjo case fpu_s21_arm: 431a59444a3SMartin Storsjo case fpu_s22_arm: 432a59444a3SMartin Storsjo case fpu_s23_arm: 433a59444a3SMartin Storsjo case fpu_s24_arm: 434a59444a3SMartin Storsjo case fpu_s25_arm: 435a59444a3SMartin Storsjo case fpu_s26_arm: 436a59444a3SMartin Storsjo case fpu_s27_arm: 437a59444a3SMartin Storsjo case fpu_s28_arm: 438a59444a3SMartin Storsjo case fpu_s29_arm: 439a59444a3SMartin Storsjo case fpu_s30_arm: 440a59444a3SMartin Storsjo case fpu_s31_arm: 441a59444a3SMartin Storsjo tls_context.S[reg - fpu_s0_arm] = reg_value.GetAsUInt32(); 442a59444a3SMartin Storsjo break; 443a59444a3SMartin Storsjo 444a59444a3SMartin Storsjo case fpu_d0_arm: 445a59444a3SMartin Storsjo case fpu_d1_arm: 446a59444a3SMartin Storsjo case fpu_d2_arm: 447a59444a3SMartin Storsjo case fpu_d3_arm: 448a59444a3SMartin Storsjo case fpu_d4_arm: 449a59444a3SMartin Storsjo case fpu_d5_arm: 450a59444a3SMartin Storsjo case fpu_d6_arm: 451a59444a3SMartin Storsjo case fpu_d7_arm: 452a59444a3SMartin Storsjo case fpu_d8_arm: 453a59444a3SMartin Storsjo case fpu_d9_arm: 454a59444a3SMartin Storsjo case fpu_d10_arm: 455a59444a3SMartin Storsjo case fpu_d11_arm: 456a59444a3SMartin Storsjo case fpu_d12_arm: 457a59444a3SMartin Storsjo case fpu_d13_arm: 458a59444a3SMartin Storsjo case fpu_d14_arm: 459a59444a3SMartin Storsjo case fpu_d15_arm: 460a59444a3SMartin Storsjo case fpu_d16_arm: 461a59444a3SMartin Storsjo case fpu_d17_arm: 462a59444a3SMartin Storsjo case fpu_d18_arm: 463a59444a3SMartin Storsjo case fpu_d19_arm: 464a59444a3SMartin Storsjo case fpu_d20_arm: 465a59444a3SMartin Storsjo case fpu_d21_arm: 466a59444a3SMartin Storsjo case fpu_d22_arm: 467a59444a3SMartin Storsjo case fpu_d23_arm: 468a59444a3SMartin Storsjo case fpu_d24_arm: 469a59444a3SMartin Storsjo case fpu_d25_arm: 470a59444a3SMartin Storsjo case fpu_d26_arm: 471a59444a3SMartin Storsjo case fpu_d27_arm: 472a59444a3SMartin Storsjo case fpu_d28_arm: 473a59444a3SMartin Storsjo case fpu_d29_arm: 474a59444a3SMartin Storsjo case fpu_d30_arm: 475a59444a3SMartin Storsjo case fpu_d31_arm: 476a59444a3SMartin Storsjo tls_context.D[reg - fpu_d0_arm] = reg_value.GetAsUInt64(); 477a59444a3SMartin Storsjo break; 478a59444a3SMartin Storsjo 479a59444a3SMartin Storsjo case fpu_q0_arm: 480a59444a3SMartin Storsjo case fpu_q1_arm: 481a59444a3SMartin Storsjo case fpu_q2_arm: 482a59444a3SMartin Storsjo case fpu_q3_arm: 483a59444a3SMartin Storsjo case fpu_q4_arm: 484a59444a3SMartin Storsjo case fpu_q5_arm: 485a59444a3SMartin Storsjo case fpu_q6_arm: 486a59444a3SMartin Storsjo case fpu_q7_arm: 487a59444a3SMartin Storsjo case fpu_q8_arm: 488a59444a3SMartin Storsjo case fpu_q9_arm: 489a59444a3SMartin Storsjo case fpu_q10_arm: 490a59444a3SMartin Storsjo case fpu_q11_arm: 491a59444a3SMartin Storsjo case fpu_q12_arm: 492a59444a3SMartin Storsjo case fpu_q13_arm: 493a59444a3SMartin Storsjo case fpu_q14_arm: 494a59444a3SMartin Storsjo case fpu_q15_arm: 495a59444a3SMartin Storsjo memcpy(&tls_context.Q[reg - fpu_q0_arm], reg_value.GetBytes(), 16); 496a59444a3SMartin Storsjo break; 497a59444a3SMartin Storsjo 498a59444a3SMartin Storsjo case fpu_fpscr_arm: 499a59444a3SMartin Storsjo tls_context.Fpscr = reg_value.GetAsUInt32(); 500a59444a3SMartin Storsjo break; 501a59444a3SMartin Storsjo } 502a59444a3SMartin Storsjo 503a59444a3SMartin Storsjo return SetThreadContextHelper(thread_handle, &tls_context); 504a59444a3SMartin Storsjo } 505a59444a3SMartin Storsjo 506a59444a3SMartin Storsjo Status 507a59444a3SMartin Storsjo NativeRegisterContextWindows_arm::ReadRegister(const RegisterInfo *reg_info, 508a59444a3SMartin Storsjo RegisterValue ®_value) { 509a59444a3SMartin Storsjo Status error; 510a59444a3SMartin Storsjo if (!reg_info) { 5110642cd76SAdrian Prantl error = Status::FromErrorString("reg_info NULL"); 512a59444a3SMartin Storsjo return error; 513a59444a3SMartin Storsjo } 514a59444a3SMartin Storsjo 515a59444a3SMartin Storsjo const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 516a59444a3SMartin Storsjo if (reg == LLDB_INVALID_REGNUM) { 517a59444a3SMartin Storsjo // This is likely an internal register for lldb use only and should not be 518a59444a3SMartin Storsjo // directly queried. 5190642cd76SAdrian Prantl error = Status::FromErrorStringWithFormat( 5200642cd76SAdrian Prantl "register \"%s\" is an internal-only lldb " 521a59444a3SMartin Storsjo "register, cannot read directly", 522a59444a3SMartin Storsjo reg_info->name); 523a59444a3SMartin Storsjo return error; 524a59444a3SMartin Storsjo } 525a59444a3SMartin Storsjo 526a59444a3SMartin Storsjo if (IsGPR(reg)) 527a59444a3SMartin Storsjo return GPRRead(reg, reg_value); 528a59444a3SMartin Storsjo 529a59444a3SMartin Storsjo if (IsFPR(reg)) 530a59444a3SMartin Storsjo return FPRRead(reg, reg_value); 531a59444a3SMartin Storsjo 5320642cd76SAdrian Prantl return Status::FromErrorString("unimplemented"); 533a59444a3SMartin Storsjo } 534a59444a3SMartin Storsjo 535a59444a3SMartin Storsjo Status NativeRegisterContextWindows_arm::WriteRegister( 536a59444a3SMartin Storsjo const RegisterInfo *reg_info, const RegisterValue ®_value) { 537a59444a3SMartin Storsjo Status error; 538a59444a3SMartin Storsjo 539a59444a3SMartin Storsjo if (!reg_info) { 5400642cd76SAdrian Prantl error = Status::FromErrorString("reg_info NULL"); 541a59444a3SMartin Storsjo return error; 542a59444a3SMartin Storsjo } 543a59444a3SMartin Storsjo 544a59444a3SMartin Storsjo const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 545a59444a3SMartin Storsjo if (reg == LLDB_INVALID_REGNUM) { 546a59444a3SMartin Storsjo // This is likely an internal register for lldb use only and should not be 547a59444a3SMartin Storsjo // directly written. 5480642cd76SAdrian Prantl error = Status::FromErrorStringWithFormat( 5490642cd76SAdrian Prantl "register \"%s\" is an internal-only lldb " 550a59444a3SMartin Storsjo "register, cannot write directly", 551a59444a3SMartin Storsjo reg_info->name); 552a59444a3SMartin Storsjo return error; 553a59444a3SMartin Storsjo } 554a59444a3SMartin Storsjo 555a59444a3SMartin Storsjo if (IsGPR(reg)) 556a59444a3SMartin Storsjo return GPRWrite(reg, reg_value); 557a59444a3SMartin Storsjo 558a59444a3SMartin Storsjo if (IsFPR(reg)) 559a59444a3SMartin Storsjo return FPRWrite(reg, reg_value); 560a59444a3SMartin Storsjo 5610642cd76SAdrian Prantl return Status::FromErrorString("unimplemented"); 562a59444a3SMartin Storsjo } 563a59444a3SMartin Storsjo 564a59444a3SMartin Storsjo Status NativeRegisterContextWindows_arm::ReadAllRegisterValues( 565c2f64601SJonas Devlieghere lldb::WritableDataBufferSP &data_sp) { 566a59444a3SMartin Storsjo const size_t data_size = REG_CONTEXT_SIZE; 567a59444a3SMartin Storsjo data_sp = std::make_shared<DataBufferHeap>(data_size, 0); 568a59444a3SMartin Storsjo ::CONTEXT tls_context; 569a59444a3SMartin Storsjo Status error = 570a59444a3SMartin Storsjo GetThreadContextHelper(GetThreadHandle(), &tls_context, CONTEXT_ALL); 571a59444a3SMartin Storsjo if (error.Fail()) 572a59444a3SMartin Storsjo return error; 573a59444a3SMartin Storsjo 574a59444a3SMartin Storsjo uint8_t *dst = data_sp->GetBytes(); 575a59444a3SMartin Storsjo ::memcpy(dst, &tls_context, data_size); 576a59444a3SMartin Storsjo return error; 577a59444a3SMartin Storsjo } 578a59444a3SMartin Storsjo 579a59444a3SMartin Storsjo Status NativeRegisterContextWindows_arm::WriteAllRegisterValues( 580a59444a3SMartin Storsjo const lldb::DataBufferSP &data_sp) { 581a59444a3SMartin Storsjo Status error; 582a59444a3SMartin Storsjo const size_t data_size = REG_CONTEXT_SIZE; 583a59444a3SMartin Storsjo if (!data_sp) { 5840642cd76SAdrian Prantl error = Status::FromErrorStringWithFormat( 585a59444a3SMartin Storsjo "NativeRegisterContextWindows_arm::%s invalid data_sp provided", 586a59444a3SMartin Storsjo __FUNCTION__); 587a59444a3SMartin Storsjo return error; 588a59444a3SMartin Storsjo } 589a59444a3SMartin Storsjo 590a59444a3SMartin Storsjo if (data_sp->GetByteSize() != data_size) { 5910642cd76SAdrian Prantl error = Status::FromErrorStringWithFormatv( 592a59444a3SMartin Storsjo "data_sp contained mismatched data size, expected {0}, actual {1}", 593a59444a3SMartin Storsjo data_size, data_sp->GetByteSize()); 594a59444a3SMartin Storsjo return error; 595a59444a3SMartin Storsjo } 596a59444a3SMartin Storsjo 597a59444a3SMartin Storsjo ::CONTEXT tls_context; 598a59444a3SMartin Storsjo memcpy(&tls_context, data_sp->GetBytes(), data_size); 599a59444a3SMartin Storsjo return SetThreadContextHelper(GetThreadHandle(), &tls_context); 600a59444a3SMartin Storsjo } 601a59444a3SMartin Storsjo 602a59444a3SMartin Storsjo Status NativeRegisterContextWindows_arm::IsWatchpointHit(uint32_t wp_index, 603a59444a3SMartin Storsjo bool &is_hit) { 6040642cd76SAdrian Prantl return Status::FromErrorString("unimplemented"); 605a59444a3SMartin Storsjo } 606a59444a3SMartin Storsjo 607a59444a3SMartin Storsjo Status NativeRegisterContextWindows_arm::GetWatchpointHitIndex( 608a59444a3SMartin Storsjo uint32_t &wp_index, lldb::addr_t trap_addr) { 6090642cd76SAdrian Prantl return Status::FromErrorString("unimplemented"); 610a59444a3SMartin Storsjo } 611a59444a3SMartin Storsjo 612a59444a3SMartin Storsjo Status NativeRegisterContextWindows_arm::IsWatchpointVacant(uint32_t wp_index, 613a59444a3SMartin Storsjo bool &is_vacant) { 6140642cd76SAdrian Prantl return Status::FromErrorString("unimplemented"); 615a59444a3SMartin Storsjo } 616a59444a3SMartin Storsjo 617a59444a3SMartin Storsjo Status NativeRegisterContextWindows_arm::SetHardwareWatchpointWithIndex( 618a59444a3SMartin Storsjo lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) { 6190642cd76SAdrian Prantl return Status::FromErrorString("unimplemented"); 620a59444a3SMartin Storsjo } 621a59444a3SMartin Storsjo 622a59444a3SMartin Storsjo bool NativeRegisterContextWindows_arm::ClearHardwareWatchpoint( 623a59444a3SMartin Storsjo uint32_t wp_index) { 624a59444a3SMartin Storsjo return false; 625a59444a3SMartin Storsjo } 626a59444a3SMartin Storsjo 627a59444a3SMartin Storsjo Status NativeRegisterContextWindows_arm::ClearAllHardwareWatchpoints() { 6280642cd76SAdrian Prantl return Status::FromErrorString("unimplemented"); 629a59444a3SMartin Storsjo } 630a59444a3SMartin Storsjo 631a59444a3SMartin Storsjo uint32_t NativeRegisterContextWindows_arm::SetHardwareWatchpoint( 632a59444a3SMartin Storsjo lldb::addr_t addr, size_t size, uint32_t watch_flags) { 633a59444a3SMartin Storsjo return LLDB_INVALID_INDEX32; 634a59444a3SMartin Storsjo } 635a59444a3SMartin Storsjo 636a59444a3SMartin Storsjo lldb::addr_t 637a59444a3SMartin Storsjo NativeRegisterContextWindows_arm::GetWatchpointAddress(uint32_t wp_index) { 638a59444a3SMartin Storsjo return LLDB_INVALID_ADDRESS; 639a59444a3SMartin Storsjo } 640a59444a3SMartin Storsjo 641a59444a3SMartin Storsjo uint32_t NativeRegisterContextWindows_arm::NumSupportedHardwareWatchpoints() { 642a59444a3SMartin Storsjo // Not implemented 643a59444a3SMartin Storsjo return 0; 644a59444a3SMartin Storsjo } 645a59444a3SMartin Storsjo 646a59444a3SMartin Storsjo #endif // defined(__arm__) || defined(_M_ARM) 647