1 //===-- EmulationStateARM.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 #include "EmulationStateARM.h" 10 11 #include "lldb/Interpreter/OptionValueArray.h" 12 #include "lldb/Interpreter/OptionValueDictionary.h" 13 #include "lldb/Target/RegisterContext.h" 14 #include "lldb/Target/StackFrame.h" 15 #include "lldb/Utility/RegisterValue.h" 16 #include "lldb/Utility/Scalar.h" 17 18 #include "Utility/ARM_DWARF_Registers.h" 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() { 24 ClearPseudoRegisters(); 25 } 26 27 EmulationStateARM::~EmulationStateARM() = default; 28 29 bool EmulationStateARM::LoadPseudoRegistersFromFrame(StackFrame &frame) { 30 RegisterContext *reg_ctx = frame.GetRegisterContext().get(); 31 bool success = true; 32 uint32_t reg_num; 33 34 for (int i = dwarf_r0; i < dwarf_r0 + 17; ++i) { 35 reg_num = 36 reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i); 37 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); 38 RegisterValue reg_value; 39 if (reg_ctx->ReadRegister(reg_info, reg_value)) { 40 m_gpr[i - dwarf_r0] = reg_value.GetAsUInt32(); 41 } else 42 success = false; 43 } 44 45 for (int i = dwarf_d0; i < dwarf_d0 + 32; ++i) { 46 reg_num = 47 reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i); 48 RegisterValue reg_value; 49 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); 50 51 if (reg_ctx->ReadRegister(reg_info, reg_value)) { 52 uint64_t value = reg_value.GetAsUInt64(); 53 uint32_t idx = i - dwarf_d0; 54 if (i < 16) { 55 m_vfp_regs.s_regs[idx * 2] = (uint32_t)value; 56 m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32); 57 } else 58 m_vfp_regs.d_regs[idx - 16] = value; 59 } else 60 success = false; 61 } 62 63 return success; 64 } 65 66 bool EmulationStateARM::StorePseudoRegisterValue(uint32_t reg_num, 67 uint64_t value) { 68 if (reg_num <= dwarf_cpsr) 69 m_gpr[reg_num - dwarf_r0] = (uint32_t)value; 70 else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) { 71 uint32_t idx = reg_num - dwarf_s0; 72 m_vfp_regs.s_regs[idx] = (uint32_t)value; 73 } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) { 74 uint32_t idx = reg_num - dwarf_d0; 75 if (idx < 16) { 76 m_vfp_regs.s_regs[idx * 2] = (uint32_t)value; 77 m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32); 78 } else 79 m_vfp_regs.d_regs[idx - 16] = value; 80 } else 81 return false; 82 83 return true; 84 } 85 86 uint64_t EmulationStateARM::ReadPseudoRegisterValue(uint32_t reg_num, 87 bool &success) { 88 uint64_t value = 0; 89 success = true; 90 91 if (reg_num <= dwarf_cpsr) 92 value = m_gpr[reg_num - dwarf_r0]; 93 else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) { 94 uint32_t idx = reg_num - dwarf_s0; 95 value = m_vfp_regs.d_regs[idx]; 96 } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) { 97 uint32_t idx = reg_num - dwarf_d0; 98 if (idx < 16) 99 value = (uint64_t)m_vfp_regs.s_regs[idx * 2] | 100 ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] << 32); 101 else 102 value = m_vfp_regs.d_regs[idx - 16]; 103 } else 104 success = false; 105 106 return value; 107 } 108 109 void EmulationStateARM::ClearPseudoRegisters() { 110 for (int i = 0; i < 17; ++i) 111 m_gpr[i] = 0; 112 113 for (int i = 0; i < 32; ++i) 114 m_vfp_regs.s_regs[i] = 0; 115 116 for (int i = 0; i < 16; ++i) 117 m_vfp_regs.d_regs[i] = 0; 118 } 119 120 void EmulationStateARM::ClearPseudoMemory() { m_memory.clear(); } 121 122 bool EmulationStateARM::StoreToPseudoAddress(lldb::addr_t p_address, 123 uint32_t value) { 124 m_memory[p_address] = value; 125 return true; 126 } 127 128 uint32_t EmulationStateARM::ReadFromPseudoAddress(lldb::addr_t p_address, 129 bool &success) { 130 std::map<lldb::addr_t, uint32_t>::iterator pos; 131 uint32_t ret_val = 0; 132 133 success = true; 134 pos = m_memory.find(p_address); 135 if (pos != m_memory.end()) 136 ret_val = pos->second; 137 else 138 success = false; 139 140 return ret_val; 141 } 142 143 size_t EmulationStateARM::ReadPseudoMemory( 144 EmulateInstruction *instruction, void *baton, 145 const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst, 146 size_t length) { 147 if (!baton) 148 return 0; 149 150 bool success = true; 151 EmulationStateARM *pseudo_state = (EmulationStateARM *)baton; 152 if (length <= 4) { 153 uint32_t value = pseudo_state->ReadFromPseudoAddress(addr, success); 154 if (!success) 155 return 0; 156 157 if (endian::InlHostByteOrder() == lldb::eByteOrderBig) 158 value = llvm::ByteSwap_32(value); 159 *((uint32_t *)dst) = value; 160 } else if (length == 8) { 161 uint32_t value1 = pseudo_state->ReadFromPseudoAddress(addr, success); 162 if (!success) 163 return 0; 164 165 uint32_t value2 = pseudo_state->ReadFromPseudoAddress(addr + 4, success); 166 if (!success) 167 return 0; 168 169 if (endian::InlHostByteOrder() == lldb::eByteOrderBig) { 170 value1 = llvm::ByteSwap_32(value1); 171 value2 = llvm::ByteSwap_32(value2); 172 } 173 ((uint32_t *)dst)[0] = value1; 174 ((uint32_t *)dst)[1] = value2; 175 } else 176 success = false; 177 178 if (success) 179 return length; 180 181 return 0; 182 } 183 184 size_t EmulationStateARM::WritePseudoMemory( 185 EmulateInstruction *instruction, void *baton, 186 const EmulateInstruction::Context &context, lldb::addr_t addr, 187 const void *dst, size_t length) { 188 if (!baton) 189 return 0; 190 191 EmulationStateARM *pseudo_state = (EmulationStateARM *)baton; 192 193 if (length <= 4) { 194 uint32_t value; 195 memcpy (&value, dst, sizeof (uint32_t)); 196 if (endian::InlHostByteOrder() == lldb::eByteOrderBig) 197 value = llvm::ByteSwap_32(value); 198 199 pseudo_state->StoreToPseudoAddress(addr, value); 200 return length; 201 } else if (length == 8) { 202 uint32_t value1; 203 uint32_t value2; 204 memcpy (&value1, dst, sizeof (uint32_t)); 205 memcpy(&value2, static_cast<const uint8_t *>(dst) + sizeof(uint32_t), 206 sizeof(uint32_t)); 207 if (endian::InlHostByteOrder() == lldb::eByteOrderBig) { 208 value1 = llvm::ByteSwap_32(value1); 209 value2 = llvm::ByteSwap_32(value2); 210 } 211 212 pseudo_state->StoreToPseudoAddress(addr, value1); 213 pseudo_state->StoreToPseudoAddress(addr + 4, value2); 214 return length; 215 } 216 217 return 0; 218 } 219 220 bool EmulationStateARM::ReadPseudoRegister( 221 EmulateInstruction *instruction, void *baton, 222 const lldb_private::RegisterInfo *reg_info, 223 lldb_private::RegisterValue ®_value) { 224 if (!baton || !reg_info) 225 return false; 226 227 bool success = true; 228 EmulationStateARM *pseudo_state = (EmulationStateARM *)baton; 229 const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF]; 230 assert(dwarf_reg_num != LLDB_INVALID_REGNUM); 231 uint64_t reg_uval = 232 pseudo_state->ReadPseudoRegisterValue(dwarf_reg_num, success); 233 234 if (success) 235 success = reg_value.SetUInt(reg_uval, reg_info->byte_size); 236 return success; 237 } 238 239 bool EmulationStateARM::WritePseudoRegister( 240 EmulateInstruction *instruction, void *baton, 241 const EmulateInstruction::Context &context, 242 const lldb_private::RegisterInfo *reg_info, 243 const lldb_private::RegisterValue ®_value) { 244 if (!baton || !reg_info) 245 return false; 246 247 EmulationStateARM *pseudo_state = (EmulationStateARM *)baton; 248 const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF]; 249 assert(dwarf_reg_num != LLDB_INVALID_REGNUM); 250 return pseudo_state->StorePseudoRegisterValue(dwarf_reg_num, 251 reg_value.GetAsUInt64()); 252 } 253 254 bool EmulationStateARM::CompareState(EmulationStateARM &other_state, 255 Stream *out_stream) { 256 bool match = true; 257 258 for (int i = 0; match && i < 17; ++i) { 259 if (m_gpr[i] != other_state.m_gpr[i]) { 260 match = false; 261 out_stream->Printf("r%d: 0x%x != 0x%x\n", i, m_gpr[i], 262 other_state.m_gpr[i]); 263 } 264 } 265 266 for (int i = 0; match && i < 32; ++i) { 267 if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i]) { 268 match = false; 269 out_stream->Printf("s%d: 0x%x != 0x%x\n", i, m_vfp_regs.s_regs[i], 270 other_state.m_vfp_regs.s_regs[i]); 271 } 272 } 273 274 for (int i = 0; match && i < 16; ++i) { 275 if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i]) { 276 match = false; 277 out_stream->Printf("d%d: 0x%" PRIx64 " != 0x%" PRIx64 "\n", i + 16, 278 m_vfp_regs.d_regs[i], 279 other_state.m_vfp_regs.d_regs[i]); 280 } 281 } 282 283 // other_state is the expected state. If it has memory, check it. 284 if (!other_state.m_memory.empty() && m_memory != other_state.m_memory) { 285 match = false; 286 out_stream->Printf("memory does not match\n"); 287 out_stream->Printf("got memory:\n"); 288 for (auto p : m_memory) 289 out_stream->Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second); 290 out_stream->Printf("expected memory:\n"); 291 for (auto p : other_state.m_memory) 292 out_stream->Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second); 293 } 294 295 return match; 296 } 297 298 bool EmulationStateARM::LoadRegistersStateFromDictionary( 299 OptionValueDictionary *reg_dict, char kind, int first_reg, int num) { 300 StreamString sstr; 301 for (int i = 0; i < num; ++i) { 302 sstr.Clear(); 303 sstr.Printf("%c%d", kind, i); 304 OptionValueSP value_sp = 305 reg_dict->GetValueForKey(ConstString(sstr.GetString())); 306 if (value_sp.get() == nullptr) 307 return false; 308 uint64_t reg_value = value_sp->GetUInt64Value(); 309 StorePseudoRegisterValue(first_reg + i, reg_value); 310 } 311 312 return true; 313 } 314 315 bool EmulationStateARM::LoadStateFromDictionary( 316 OptionValueDictionary *test_data) { 317 static ConstString memory_key("memory"); 318 static ConstString registers_key("registers"); 319 320 if (!test_data) 321 return false; 322 323 OptionValueSP value_sp = test_data->GetValueForKey(memory_key); 324 325 // Load memory, if present. 326 327 if (value_sp.get() != nullptr) { 328 static ConstString address_key("address"); 329 static ConstString data_key("data"); 330 uint64_t start_address = 0; 331 332 OptionValueDictionary *mem_dict = value_sp->GetAsDictionary(); 333 value_sp = mem_dict->GetValueForKey(address_key); 334 if (value_sp.get() == nullptr) 335 return false; 336 else 337 start_address = value_sp->GetUInt64Value(); 338 339 value_sp = mem_dict->GetValueForKey(data_key); 340 OptionValueArray *mem_array = value_sp->GetAsArray(); 341 if (!mem_array) 342 return false; 343 344 uint32_t num_elts = mem_array->GetSize(); 345 uint32_t address = (uint32_t)start_address; 346 347 for (uint32_t i = 0; i < num_elts; ++i) { 348 value_sp = mem_array->GetValueAtIndex(i); 349 if (value_sp.get() == nullptr) 350 return false; 351 uint64_t value = value_sp->GetUInt64Value(); 352 StoreToPseudoAddress(address, value); 353 address = address + 4; 354 } 355 } 356 357 value_sp = test_data->GetValueForKey(registers_key); 358 if (value_sp.get() == nullptr) 359 return false; 360 361 // Load General Registers 362 363 OptionValueDictionary *reg_dict = value_sp->GetAsDictionary(); 364 if (!LoadRegistersStateFromDictionary(reg_dict, 'r', dwarf_r0, 16)) 365 return false; 366 367 static ConstString cpsr_name("cpsr"); 368 value_sp = reg_dict->GetValueForKey(cpsr_name); 369 if (value_sp.get() == nullptr) 370 return false; 371 StorePseudoRegisterValue(dwarf_cpsr, value_sp->GetUInt64Value()); 372 373 // Load s/d Registers 374 // To prevent you giving both types in a state and overwriting 375 // one or the other, we'll expect to get either all S registers, 376 // or all D registers. Not a mix of the two. 377 bool found_s_registers = 378 LoadRegistersStateFromDictionary(reg_dict, 's', dwarf_s0, 32); 379 bool found_d_registers = 380 LoadRegistersStateFromDictionary(reg_dict, 'd', dwarf_d0, 32); 381 382 return found_s_registers != found_d_registers; 383 } 384