1 //===-- RegisterContextOpenBSDKernel_arm64.cpp ----------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #if defined(__OpenBSD__) 10 #include <sys/types.h> 11 #include <sys/time.h> 12 #define _KERNEL 13 #include <machine/cpu.h> 14 #undef _KERNEL 15 #include <machine/pcb.h> 16 #include <frame.h> 17 #endif 18 19 #include "RegisterContextOpenBSDKernel_arm64.h" 20 #include "Plugins/Process/Utility/lldb-arm64-register-enums.h" 21 22 #include "lldb/Target/Process.h" 23 #include "lldb/Target/Thread.h" 24 #include "lldb/Utility/RegisterValue.h" 25 #include "llvm/Support/Endian.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 RegisterContextOpenBSDKernel_arm64::RegisterContextOpenBSDKernel_arm64( 31 Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up, 32 lldb::addr_t pcb_addr) 33 : RegisterContextPOSIX_arm64(thread, std::move(register_info_up)), 34 m_pcb_addr(pcb_addr) {} 35 36 bool RegisterContextOpenBSDKernel_arm64::ReadGPR() { return true; } 37 38 bool RegisterContextOpenBSDKernel_arm64::ReadFPR() { return true; } 39 40 bool RegisterContextOpenBSDKernel_arm64::WriteGPR() { 41 assert(0); 42 return false; 43 } 44 45 bool RegisterContextOpenBSDKernel_arm64::WriteFPR() { 46 assert(0); 47 return false; 48 } 49 50 bool RegisterContextOpenBSDKernel_arm64::ReadRegister( 51 const RegisterInfo *reg_info, RegisterValue &value) { 52 if (m_pcb_addr == LLDB_INVALID_ADDRESS) 53 return false; 54 55 #ifdef __aarch64__ 56 Status error; 57 struct pcb pcb; 58 size_t rd = m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), 59 error); 60 if (rd != sizeof(pcb)) 61 return false; 62 63 /* 64 Usually pcb is written in `cpu_switchto` function. This function writes 65 registers as same as the structure of `swichframe` in the stack. 66 We read the frame if it is. 67 */ 68 struct switchframe sf; 69 rd = m_thread.GetProcess()->ReadMemory(pcb.pcb_sp, &sf, sizeof(sf), error); 70 if (rd != sizeof(sf)) 71 return false; 72 73 uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 74 switch (reg) { 75 #define REG(x) \ 76 case gpr_##x##_arm64: \ 77 value = (u_int64_t)sf.sf_##x; \ 78 return true; 79 80 REG(x19); 81 REG(x20); 82 REG(x21); 83 REG(x22); 84 REG(x23); 85 REG(x24); 86 REG(x25); 87 REG(x26); 88 REG(x27); 89 REG(x28); 90 case gpr_fp_arm64: 91 value = (u_int64_t)sf.sf_x29; 92 return true; 93 case gpr_sp_arm64: 94 value = (u_int64_t)(pcb.pcb_sp + sizeof(sf)); 95 return true; 96 case gpr_pc_arm64: 97 value = (u_int64_t)sf.sf_lr; 98 return true; 99 } 100 #endif 101 return false; 102 } 103 104 bool RegisterContextOpenBSDKernel_arm64::WriteRegister( 105 const RegisterInfo *reg_info, const RegisterValue &value) { 106 return false; 107 } 108