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