232 lines · c
1//===-- RegisterContextDarwin_arm64.h -----------------------------*- C++2//-*-===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_ARM64_H11#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_ARM64_H12 13#include "lldb/Target/RegisterContext.h"14#include "lldb/lldb-private.h"15 16// Break only in privileged or user mode17#define S_RSVD ((uint32_t)(0u << 1))18#define S_PRIV ((uint32_t)(1u << 1))19#define S_USER ((uint32_t)(2u << 1))20#define S_PRIV_USER ((S_PRIV) | (S_USER))21 22#define WCR_ENABLE ((uint32_t)(1u))23 24// Watchpoint load/store25#define WCR_LOAD ((uint32_t)(1u << 3))26#define WCR_STORE ((uint32_t)(1u << 4))27 28class RegisterContextDarwin_arm64 : public lldb_private::RegisterContext {29public:30 RegisterContextDarwin_arm64(lldb_private::Thread &thread,31 uint32_t concrete_frame_idx);32 33 ~RegisterContextDarwin_arm64() override;34 35 void InvalidateAllRegisters() override;36 37 size_t GetRegisterCount() override;38 39 const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;40 41 size_t GetRegisterSetCount() override;42 43 const lldb_private::RegisterSet *GetRegisterSet(size_t set) override;44 45 bool ReadRegister(const lldb_private::RegisterInfo *reg_info,46 lldb_private::RegisterValue ®_value) override;47 48 bool WriteRegister(const lldb_private::RegisterInfo *reg_info,49 const lldb_private::RegisterValue ®_value) override;50 51 bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;52 53 bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;54 55 uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,56 uint32_t num) override;57 58 uint32_t NumSupportedHardwareWatchpoints() override;59 60 uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,61 bool write) override;62 63 bool ClearHardwareWatchpoint(uint32_t hw_index) override;64 65 // mirrors <mach/arm/thread_status.h> arm_thread_state64_t66 struct GPR {67 uint64_t x[29]; // x0-x2868 uint64_t fp; // x2969 uint64_t lr; // x3070 uint64_t sp; // x3171 uint64_t pc; // pc72 uint32_t cpsr; // cpsr73 };74 75 struct VReg {76 alignas(16) char bytes[16];77 };78 79 // mirrors <mach/arm/thread_status.h> arm_neon_state64_t80 struct FPU {81 VReg v[32];82 uint32_t fpsr;83 uint32_t fpcr;84 };85 86 // mirrors <mach/arm/thread_status.h> arm_exception_state64_t87 struct EXC {88 uint64_t far; // Virtual Fault Address89 uint32_t esr; // Exception syndrome90 uint32_t exception; // number of arm exception token91 };92 93 // mirrors <mach/arm/thread_status.h> arm_debug_state64_t94 struct DBG {95 uint64_t bvr[16];96 uint64_t bcr[16];97 uint64_t wvr[16];98 uint64_t wcr[16];99 uint64_t mdscr_el1;100 };101 102 static void LogDBGRegisters(lldb_private::Log *log, const DBG &dbg);103 104protected:105 enum {106 GPRRegSet = 6, // ARM_THREAD_STATE64107 FPURegSet = 17, // ARM_NEON_STATE64108 EXCRegSet = 7, // ARM_EXCEPTION_STATE64109 DBGRegSet = 15 // ARM_DEBUG_STATE64110 };111 112 enum {113 GPRWordCount = sizeof(GPR) / sizeof(uint32_t), // ARM_THREAD_STATE64_COUNT114 FPUWordCount = sizeof(FPU) / sizeof(uint32_t), // ARM_NEON_STATE64_COUNT115 EXCWordCount =116 sizeof(EXC) / sizeof(uint32_t), // ARM_EXCEPTION_STATE64_COUNT117 DBGWordCount = sizeof(DBG) / sizeof(uint32_t) // ARM_DEBUG_STATE64_COUNT118 };119 120 enum { Read = 0, Write = 1, kNumErrors = 2 };121 122 GPR gpr;123 FPU fpu;124 EXC exc;125 DBG dbg;126 int gpr_errs[2]; // Read/Write errors127 int fpu_errs[2]; // Read/Write errors128 int exc_errs[2]; // Read/Write errors129 int dbg_errs[2]; // Read/Write errors130 131 void InvalidateAllRegisterStates() {132 SetError(GPRRegSet, Read, -1);133 SetError(FPURegSet, Read, -1);134 SetError(EXCRegSet, Read, -1);135 }136 137 int GetError(int flavor, uint32_t err_idx) const {138 if (err_idx < kNumErrors) {139 switch (flavor) {140 // When getting all errors, just OR all values together to see if141 // we got any kind of error.142 case GPRRegSet:143 return gpr_errs[err_idx];144 case FPURegSet:145 return fpu_errs[err_idx];146 case EXCRegSet:147 return exc_errs[err_idx];148 case DBGRegSet:149 return dbg_errs[err_idx];150 default:151 break;152 }153 }154 return -1;155 }156 157 bool SetError(int flavor, uint32_t err_idx, int err) {158 if (err_idx < kNumErrors) {159 switch (flavor) {160 case GPRRegSet:161 gpr_errs[err_idx] = err;162 return true;163 164 case FPURegSet:165 fpu_errs[err_idx] = err;166 return true;167 168 case EXCRegSet:169 exc_errs[err_idx] = err;170 return true;171 172 case DBGRegSet:173 exc_errs[err_idx] = err;174 return true;175 176 default:177 break;178 }179 }180 return false;181 }182 183 bool RegisterSetIsCached(int set) const { return GetError(set, Read) == 0; }184 185 int ReadGPR(bool force);186 187 int ReadFPU(bool force);188 189 int ReadEXC(bool force);190 191 int ReadDBG(bool force);192 193 int WriteGPR();194 195 int WriteFPU();196 197 int WriteEXC();198 199 int WriteDBG();200 201 // Subclasses override these to do the actual reading.202 virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { return -1; }203 204 virtual int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) = 0;205 206 virtual int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) = 0;207 208 virtual int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) = 0;209 210 virtual int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) = 0;211 212 virtual int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) = 0;213 214 virtual int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) = 0;215 216 virtual int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg) = 0;217 218 int ReadRegisterSet(uint32_t set, bool force);219 220 int WriteRegisterSet(uint32_t set);221 222 static uint32_t GetRegisterNumber(uint32_t reg_kind, uint32_t reg_num);223 224 static int GetSetForNativeRegNum(int reg_num);225 226 static size_t GetRegisterInfosCount();227 228 static const lldb_private::RegisterInfo *GetRegisterInfos();229};230 231#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_ARM64_H232