1 //===-- NativeRegisterContextLinux_arm.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 "NativeRegisterContextLinux_arm.h" 11 12 #include "lldb/lldb-private-forward.h" 13 #include "lldb/Core/DataBufferHeap.h" 14 #include "lldb/Core/Error.h" 15 #include "lldb/Core/RegisterValue.h" 16 #include "lldb/Host/common/NativeProcessProtocol.h" 17 #include "lldb/Host/common/NativeThreadProtocol.h" 18 #include "Plugins/Process/Linux/NativeProcessLinux.h" 19 20 #define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr)) 21 22 using namespace lldb; 23 using namespace lldb_private; 24 using namespace lldb_private::process_linux; 25 26 // arm general purpose registers. 27 static const uint32_t g_gpr_regnums_arm[] = 28 { 29 gpr_r0_arm, 30 gpr_r1_arm, 31 gpr_r2_arm, 32 gpr_r3_arm, 33 gpr_r4_arm, 34 gpr_r5_arm, 35 gpr_r6_arm, 36 gpr_r7_arm, 37 gpr_r8_arm, 38 gpr_r9_arm, 39 gpr_r10_arm, 40 gpr_r11_arm, 41 gpr_r12_arm, 42 gpr_sp_arm, 43 gpr_lr_arm, 44 gpr_pc_arm, 45 gpr_cpsr_arm, 46 LLDB_INVALID_REGNUM // register sets need to end with this flag 47 }; 48 static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == k_num_gpr_registers_arm, \ 49 "g_gpr_regnums_arm has wrong number of register infos"); 50 51 // arm floating point registers. 52 static const uint32_t g_fpu_regnums_arm[] = 53 { 54 fpu_s0_arm, 55 fpu_s1_arm, 56 fpu_s2_arm, 57 fpu_s3_arm, 58 fpu_s4_arm, 59 fpu_s5_arm, 60 fpu_s6_arm, 61 fpu_s7_arm, 62 fpu_s8_arm, 63 fpu_s9_arm, 64 fpu_s10_arm, 65 fpu_s11_arm, 66 fpu_s12_arm, 67 fpu_s13_arm, 68 fpu_s14_arm, 69 fpu_s15_arm, 70 fpu_s16_arm, 71 fpu_s17_arm, 72 fpu_s18_arm, 73 fpu_s19_arm, 74 fpu_s20_arm, 75 fpu_s21_arm, 76 fpu_s22_arm, 77 fpu_s23_arm, 78 fpu_s24_arm, 79 fpu_s25_arm, 80 fpu_s26_arm, 81 fpu_s27_arm, 82 fpu_s28_arm, 83 fpu_s29_arm, 84 fpu_s30_arm, 85 fpu_s31_arm, 86 fpu_fpscr_arm, 87 LLDB_INVALID_REGNUM // register sets need to end with this flag 88 }; 89 static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == k_num_fpr_registers_arm, \ 90 "g_fpu_regnums_arm has wrong number of register infos"); 91 92 namespace { 93 // Number of register sets provided by this context. 94 enum 95 { 96 k_num_register_sets = 2 97 }; 98 } 99 100 // Register sets for arm. 101 static const RegisterSet 102 g_reg_sets_arm[k_num_register_sets] = 103 { 104 { "General Purpose Registers", "gpr", k_num_gpr_registers_arm, g_gpr_regnums_arm }, 105 { "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm } 106 }; 107 108 NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm ( 109 NativeThreadProtocol &native_thread, 110 uint32_t concrete_frame_idx, 111 RegisterInfoInterface *reg_info_interface_p) : 112 NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p) 113 { 114 switch (reg_info_interface_p->m_target_arch.GetMachine()) 115 { 116 case llvm::Triple::arm: 117 m_reg_info.num_registers = k_num_registers_arm; 118 m_reg_info.num_gpr_registers = k_num_gpr_registers_arm; 119 m_reg_info.num_fpr_registers = k_num_fpr_registers_arm; 120 m_reg_info.last_gpr = k_last_gpr_arm; 121 m_reg_info.first_fpr = k_first_fpr_arm; 122 m_reg_info.last_fpr = k_last_fpr_arm; 123 m_reg_info.first_fpr_v = fpu_s0_arm; 124 m_reg_info.last_fpr_v = fpu_s31_arm; 125 m_reg_info.gpr_flags = gpr_cpsr_arm; 126 break; 127 default: 128 assert(false && "Unhandled target architecture."); 129 break; 130 } 131 132 ::memset(&m_fpr, 0, sizeof (m_fpr)); 133 ::memset(&m_gpr_arm, 0, sizeof (m_gpr_arm)); 134 } 135 136 uint32_t 137 NativeRegisterContextLinux_arm::GetRegisterSetCount () const 138 { 139 return k_num_register_sets; 140 } 141 142 uint32_t 143 NativeRegisterContextLinux_arm::GetUserRegisterCount() const 144 { 145 uint32_t count = 0; 146 for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) 147 count += g_reg_sets_arm[set_index].num_registers; 148 return count; 149 } 150 151 const RegisterSet * 152 NativeRegisterContextLinux_arm::GetRegisterSet (uint32_t set_index) const 153 { 154 if (set_index < k_num_register_sets) 155 return &g_reg_sets_arm[set_index]; 156 157 return nullptr; 158 } 159 160 Error 161 NativeRegisterContextLinux_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) 162 { 163 Error error; 164 165 if (!reg_info) 166 { 167 error.SetErrorString ("reg_info NULL"); 168 return error; 169 } 170 171 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 172 173 if (IsFPR(reg)) 174 { 175 if (!ReadFPR()) 176 { 177 error.SetErrorString ("failed to read floating point register"); 178 return error; 179 } 180 } 181 else 182 { 183 uint32_t full_reg = reg; 184 bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); 185 186 if (is_subreg) 187 { 188 // Read the full aligned 64-bit register. 189 full_reg = reg_info->invalidate_regs[0]; 190 } 191 192 error = ReadRegisterRaw(full_reg, reg_value); 193 194 if (error.Success ()) 195 { 196 // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. 197 if (is_subreg && (reg_info->byte_offset & 0x1)) 198 reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); 199 200 // If our return byte size was greater than the return value reg size, then 201 // use the type specified by reg_info rather than the uint64_t default 202 if (reg_value.GetByteSize() > reg_info->byte_size) 203 reg_value.SetType(reg_info); 204 } 205 return error; 206 } 207 208 // Get pointer to m_fpr variable and set the data from it. 209 assert (reg_info->byte_offset < sizeof m_fpr); 210 uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; 211 switch (reg_info->byte_size) 212 { 213 case 2: 214 reg_value.SetUInt16(*(uint16_t *)src); 215 break; 216 case 4: 217 reg_value.SetUInt32(*(uint32_t *)src); 218 break; 219 case 8: 220 reg_value.SetUInt64(*(uint64_t *)src); 221 break; 222 default: 223 assert(false && "Unhandled data size."); 224 error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); 225 break; 226 } 227 228 return error; 229 } 230 231 Error 232 NativeRegisterContextLinux_arm::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) 233 { 234 if (!reg_info) 235 return Error ("reg_info NULL"); 236 237 const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; 238 if (reg_index == LLDB_INVALID_REGNUM) 239 return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); 240 241 if (IsGPR(reg_index)) 242 return WriteRegisterRaw(reg_index, reg_value); 243 244 if (IsFPR(reg_index)) 245 { 246 // Get pointer to m_fpr variable and set the data to it. 247 assert (reg_info->byte_offset < sizeof(m_fpr)); 248 uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset; 249 switch (reg_info->byte_size) 250 { 251 case 2: 252 *(uint16_t *)dst = reg_value.GetAsUInt16(); 253 break; 254 case 4: 255 *(uint32_t *)dst = reg_value.GetAsUInt32(); 256 break; 257 case 8: 258 *(uint64_t *)dst = reg_value.GetAsUInt64(); 259 break; 260 default: 261 assert(false && "Unhandled data size."); 262 return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); 263 } 264 265 if (!WriteFPR()) 266 { 267 return Error ("NativeRegisterContextLinux_arm::WriteRegister: WriteFPR failed"); 268 } 269 270 return Error (); 271 } 272 273 return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); 274 } 275 276 Error 277 NativeRegisterContextLinux_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) 278 { 279 Error error; 280 281 data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); 282 if (!data_sp) 283 return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, (uint64_t)REG_CONTEXT_SIZE); 284 285 if (!ReadGPR ()) 286 { 287 error.SetErrorString ("ReadGPR() failed"); 288 return error; 289 } 290 291 if (!ReadFPR ()) 292 { 293 error.SetErrorString ("ReadFPR() failed"); 294 return error; 295 } 296 297 uint8_t *dst = data_sp->GetBytes (); 298 if (dst == nullptr) 299 { 300 error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", (uint64_t)REG_CONTEXT_SIZE); 301 return error; 302 } 303 304 ::memcpy (dst, &m_gpr_arm, GetGPRSize()); 305 dst += GetGPRSize(); 306 ::memcpy (dst, &m_fpr, sizeof(m_fpr)); 307 308 return error; 309 } 310 311 Error 312 NativeRegisterContextLinux_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) 313 { 314 Error error; 315 316 if (!data_sp) 317 { 318 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); 319 return error; 320 } 321 322 if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) 323 { 324 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, (uint64_t)REG_CONTEXT_SIZE, data_sp->GetByteSize ()); 325 return error; 326 } 327 328 329 uint8_t *src = data_sp->GetBytes (); 330 if (src == nullptr) 331 { 332 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); 333 return error; 334 } 335 ::memcpy (&m_gpr_arm, src, GetRegisterInfoInterface ().GetGPRSize ()); 336 337 if (!WriteGPR ()) 338 { 339 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__); 340 return error; 341 } 342 343 src += GetRegisterInfoInterface ().GetGPRSize (); 344 ::memcpy (&m_fpr, src, sizeof(m_fpr)); 345 346 if (!WriteFPR ()) 347 { 348 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__); 349 return error; 350 } 351 352 return error; 353 } 354 355 Error 356 NativeRegisterContextLinux_arm::WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value) 357 { 358 Error error; 359 360 uint32_t reg_to_write = reg_index; 361 RegisterValue value_to_write = reg_value; 362 363 // Check if this is a subregister of a full register. 364 const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); 365 if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) 366 { 367 RegisterValue full_value; 368 uint32_t full_reg = reg_info->invalidate_regs[0]; 369 const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); 370 371 // Read the full register. 372 error = ReadRegister(full_reg_info, full_value); 373 if (error.Fail ()) 374 return error; 375 376 lldb::ByteOrder byte_order = GetByteOrder(); 377 uint8_t dst[RegisterValue::kMaxRegisterByteSize]; 378 379 // Get the bytes for the full register. 380 const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, 381 dst, 382 sizeof(dst), 383 byte_order, 384 error); 385 if (error.Success() && dest_size) 386 { 387 uint8_t src[RegisterValue::kMaxRegisterByteSize]; 388 389 // Get the bytes for the source data. 390 const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); 391 if (error.Success() && src_size && (src_size < dest_size)) 392 { 393 // Copy the src bytes to the destination. 394 memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); 395 // Set this full register as the value to write. 396 value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); 397 value_to_write.SetType(full_reg_info); 398 reg_to_write = full_reg; 399 } 400 } 401 } 402 403 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 404 if (!process_sp) 405 { 406 error.SetErrorString ("NativeProcessProtocol is NULL"); 407 return error; 408 } 409 410 const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write); 411 assert (register_to_write_info_p && "register to write does not have valid RegisterInfo"); 412 if (!register_to_write_info_p) 413 { 414 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write); 415 return error; 416 } 417 418 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 419 return process_p->WriteRegisterValue(m_thread.GetID(), 420 register_to_write_info_p->byte_offset, 421 register_to_write_info_p->name, 422 value_to_write); 423 } 424 425 Error 426 NativeRegisterContextLinux_arm::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value) 427 { 428 Error error; 429 const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index); 430 if (!reg_info) 431 { 432 error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index); 433 return error; 434 } 435 436 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 437 if (!process_sp) 438 { 439 error.SetErrorString ("NativeProcessProtocol is NULL"); 440 return error; 441 } 442 443 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 444 return process_p->ReadRegisterValue(m_thread.GetID(), 445 reg_info->byte_offset, 446 reg_info->name, 447 reg_info->byte_size, 448 reg_value); 449 } 450 451 bool 452 NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const 453 { 454 return reg <= m_reg_info.last_gpr; // GPR's come first. 455 } 456 457 bool 458 NativeRegisterContextLinux_arm::ReadGPR() 459 { 460 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 461 if (!process_sp) 462 return false; 463 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 464 465 return process_p->ReadGPR (m_thread.GetID (), &m_gpr_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success(); 466 } 467 468 bool 469 NativeRegisterContextLinux_arm::WriteGPR() 470 { 471 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 472 if (!process_sp) 473 return false; 474 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 475 476 return process_p->WriteGPR (m_thread.GetID (), &m_gpr_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success(); 477 } 478 479 bool 480 NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const 481 { 482 return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); 483 } 484 485 bool 486 NativeRegisterContextLinux_arm::ReadFPR () 487 { 488 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 489 if (!process_sp) 490 return false; 491 492 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 493 return process_p->ReadFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); 494 } 495 496 bool 497 NativeRegisterContextLinux_arm::WriteFPR () 498 { 499 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 500 if (!process_sp) 501 return false; 502 503 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 504 return process_p->WriteFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); 505 } 506 507 lldb::ByteOrder 508 NativeRegisterContextLinux_arm::GetByteOrder() const 509 { 510 // Get the target process whose privileged thread was used for the register read. 511 lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; 512 513 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 514 if (!process_sp) 515 return byte_order; 516 517 if (!process_sp->GetByteOrder (byte_order)) 518 { 519 // FIXME log here 520 } 521 522 return byte_order; 523 } 524 525 size_t 526 NativeRegisterContextLinux_arm::GetGPRSize() const 527 { 528 return GetRegisterInfoInterface().GetGPRSize(); 529 } 530