1 //===-- RegisterContextPOSIX_arm64.cpp --------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include <cstring> 11 #include <errno.h> 12 #include <stdint.h> 13 14 #include "lldb/Core/DataBufferHeap.h" 15 #include "lldb/Core/DataExtractor.h" 16 #include "lldb/Core/RegisterValue.h" 17 #include "lldb/Core/Scalar.h" 18 #include "lldb/Target/Target.h" 19 #include "lldb/Target/Thread.h" 20 #include "lldb/Host/Endian.h" 21 #include "llvm/Support/Compiler.h" 22 23 #include "RegisterContextPOSIX_arm64.h" 24 #include "Plugins/Process/elf-core/ProcessElfCore.h" 25 26 // ARM64 general purpose registers. 27 const uint32_t g_gpr_regnums_arm64[] = 28 { 29 gpr_x0_arm64, 30 gpr_x1_arm64, 31 gpr_x2_arm64, 32 gpr_x3_arm64, 33 gpr_x4_arm64, 34 gpr_x5_arm64, 35 gpr_x6_arm64, 36 gpr_x7_arm64, 37 gpr_x8_arm64, 38 gpr_x9_arm64, 39 gpr_x10_arm64, 40 gpr_x11_arm64, 41 gpr_x12_arm64, 42 gpr_x13_arm64, 43 gpr_x14_arm64, 44 gpr_x15_arm64, 45 gpr_x16_arm64, 46 gpr_x17_arm64, 47 gpr_x18_arm64, 48 gpr_x19_arm64, 49 gpr_x20_arm64, 50 gpr_x21_arm64, 51 gpr_x22_arm64, 52 gpr_x23_arm64, 53 gpr_x24_arm64, 54 gpr_x25_arm64, 55 gpr_x26_arm64, 56 gpr_x27_arm64, 57 gpr_x28_arm64, 58 gpr_fp_arm64, 59 gpr_lr_arm64, 60 gpr_sp_arm64, 61 gpr_pc_arm64, 62 gpr_cpsr_arm64, 63 LLDB_INVALID_REGNUM // register sets need to end with this flag 64 }; 65 static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, \ 66 "g_gpr_regnums_arm64 has wrong number of register infos"); 67 68 // ARM64 floating point registers. 69 static const uint32_t g_fpu_regnums_arm64[] = 70 { 71 fpu_v0_arm64, 72 fpu_v1_arm64, 73 fpu_v2_arm64, 74 fpu_v3_arm64, 75 fpu_v4_arm64, 76 fpu_v5_arm64, 77 fpu_v6_arm64, 78 fpu_v7_arm64, 79 fpu_v8_arm64, 80 fpu_v9_arm64, 81 fpu_v10_arm64, 82 fpu_v11_arm64, 83 fpu_v12_arm64, 84 fpu_v13_arm64, 85 fpu_v14_arm64, 86 fpu_v15_arm64, 87 fpu_v16_arm64, 88 fpu_v17_arm64, 89 fpu_v18_arm64, 90 fpu_v19_arm64, 91 fpu_v20_arm64, 92 fpu_v21_arm64, 93 fpu_v22_arm64, 94 fpu_v23_arm64, 95 fpu_v24_arm64, 96 fpu_v25_arm64, 97 fpu_v26_arm64, 98 fpu_v27_arm64, 99 fpu_v28_arm64, 100 fpu_v29_arm64, 101 fpu_v30_arm64, 102 fpu_v31_arm64, 103 fpu_fpsr_arm64, 104 fpu_fpcr_arm64, 105 LLDB_INVALID_REGNUM // register sets need to end with this flag 106 }; 107 static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, \ 108 "g_fpu_regnums_arm64 has wrong number of register infos"); 109 110 // Number of register sets provided by this context. 111 enum 112 { 113 k_num_register_sets = 2 114 }; 115 116 // Register sets for ARM64. 117 static const lldb_private::RegisterSet 118 g_reg_sets_arm64[k_num_register_sets] = 119 { 120 { "General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64 }, 121 { "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 } 122 }; 123 124 bool RegisterContextPOSIX_arm64::IsGPR(unsigned reg) 125 { 126 return reg <= m_reg_info.last_gpr; // GPR's come first. 127 } 128 129 bool RegisterContextPOSIX_arm64::IsFPR(unsigned reg) 130 { 131 return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); 132 } 133 134 RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(lldb_private::Thread &thread, 135 uint32_t concrete_frame_idx, 136 lldb_private::RegisterInfoInterface *register_info) 137 : lldb_private::RegisterContext(thread, concrete_frame_idx) 138 { 139 m_register_info_ap.reset(register_info); 140 141 switch (register_info->m_target_arch.GetMachine()) 142 { 143 case llvm::Triple::aarch64: 144 m_reg_info.num_registers = k_num_registers_arm64; 145 m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; 146 m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; 147 m_reg_info.last_gpr = k_last_gpr_arm64; 148 m_reg_info.first_fpr = k_first_fpr_arm64; 149 m_reg_info.last_fpr = k_last_fpr_arm64; 150 m_reg_info.first_fpr_v = fpu_v0_arm64; 151 m_reg_info.last_fpr_v = fpu_v31_arm64; 152 m_reg_info.gpr_flags = gpr_cpsr_arm64; 153 break; 154 default: 155 assert(false && "Unhandled target architecture."); 156 break; 157 } 158 159 ::memset(&m_fpr, 0, sizeof m_fpr); 160 161 // elf-core yet to support ReadFPR() 162 lldb::ProcessSP base = CalculateProcess(); 163 if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) 164 return; 165 } 166 167 RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64() 168 { 169 } 170 171 void 172 RegisterContextPOSIX_arm64::Invalidate() 173 { 174 } 175 176 void 177 RegisterContextPOSIX_arm64::InvalidateAllRegisters() 178 { 179 } 180 181 unsigned 182 RegisterContextPOSIX_arm64::GetRegisterOffset(unsigned reg) 183 { 184 assert(reg < m_reg_info.num_registers && "Invalid register number."); 185 return GetRegisterInfo()[reg].byte_offset; 186 } 187 188 unsigned 189 RegisterContextPOSIX_arm64::GetRegisterSize(unsigned reg) 190 { 191 assert(reg < m_reg_info.num_registers && "Invalid register number."); 192 return GetRegisterInfo()[reg].byte_size; 193 } 194 195 size_t 196 RegisterContextPOSIX_arm64::GetRegisterCount() 197 { 198 size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers; 199 return num_registers; 200 } 201 202 size_t 203 RegisterContextPOSIX_arm64::GetGPRSize() 204 { 205 return m_register_info_ap->GetGPRSize (); 206 } 207 208 const lldb_private::RegisterInfo * 209 RegisterContextPOSIX_arm64::GetRegisterInfo() 210 { 211 // Commonly, this method is overridden and g_register_infos is copied and specialized. 212 // So, use GetRegisterInfo() rather than g_register_infos in this scope. 213 return m_register_info_ap->GetRegisterInfo (); 214 } 215 216 const lldb_private::RegisterInfo * 217 RegisterContextPOSIX_arm64::GetRegisterInfoAtIndex(size_t reg) 218 { 219 if (reg < m_reg_info.num_registers) 220 return &GetRegisterInfo()[reg]; 221 else 222 return NULL; 223 } 224 225 size_t 226 RegisterContextPOSIX_arm64::GetRegisterSetCount() 227 { 228 size_t sets = 0; 229 for (size_t set = 0; set < k_num_register_sets; ++set) 230 { 231 if (IsRegisterSetAvailable(set)) 232 ++sets; 233 } 234 235 return sets; 236 } 237 238 const lldb_private::RegisterSet * 239 RegisterContextPOSIX_arm64::GetRegisterSet(size_t set) 240 { 241 if (IsRegisterSetAvailable(set)) 242 { 243 switch (m_register_info_ap->m_target_arch.GetMachine()) 244 { 245 case llvm::Triple::aarch64: 246 return &g_reg_sets_arm64[set]; 247 default: 248 assert(false && "Unhandled target architecture."); 249 return NULL; 250 } 251 } 252 return NULL; 253 } 254 255 const char * 256 RegisterContextPOSIX_arm64::GetRegisterName(unsigned reg) 257 { 258 assert(reg < m_reg_info.num_registers && "Invalid register offset."); 259 return GetRegisterInfo()[reg].name; 260 } 261 262 lldb::ByteOrder 263 RegisterContextPOSIX_arm64::GetByteOrder() 264 { 265 // Get the target process whose privileged thread was used for the register read. 266 lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; 267 lldb_private::Process *process = CalculateProcess().get(); 268 269 if (process) 270 byte_order = process->GetByteOrder(); 271 return byte_order; 272 } 273 274 bool 275 RegisterContextPOSIX_arm64::IsRegisterSetAvailable(size_t set_index) 276 { 277 return set_index < k_num_register_sets; 278 } 279 280 281 // Used when parsing DWARF and EH frame information and any other 282 // object file sections that contain register numbers in them. 283 uint32_t 284 RegisterContextPOSIX_arm64::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, 285 uint32_t num) 286 { 287 const uint32_t num_regs = GetRegisterCount(); 288 289 assert (kind < lldb::kNumRegisterKinds); 290 for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) 291 { 292 const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx); 293 294 if (reg_info->kinds[kind] == num) 295 return reg_idx; 296 } 297 298 return LLDB_INVALID_REGNUM; 299 } 300