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