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 const RegisterSet * 143 NativeRegisterContextLinux_arm::GetRegisterSet (uint32_t set_index) const 144 { 145 if (set_index < k_num_register_sets) 146 return &g_reg_sets_arm[set_index]; 147 148 return nullptr; 149 } 150 151 Error 152 NativeRegisterContextLinux_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) 153 { 154 Error error; 155 156 if (!reg_info) 157 { 158 error.SetErrorString ("reg_info NULL"); 159 return error; 160 } 161 162 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 163 164 if (IsFPR(reg)) 165 { 166 if (!ReadFPR()) 167 { 168 error.SetErrorString ("failed to read floating point register"); 169 return error; 170 } 171 } 172 else 173 { 174 uint32_t full_reg = reg; 175 bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); 176 177 if (is_subreg) 178 { 179 // Read the full aligned 64-bit register. 180 full_reg = reg_info->invalidate_regs[0]; 181 } 182 183 error = ReadRegisterRaw(full_reg, reg_value); 184 185 if (error.Success ()) 186 { 187 // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. 188 if (is_subreg && (reg_info->byte_offset & 0x1)) 189 reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); 190 191 // If our return byte size was greater than the return value reg size, then 192 // use the type specified by reg_info rather than the uint64_t default 193 if (reg_value.GetByteSize() > reg_info->byte_size) 194 reg_value.SetType(reg_info); 195 } 196 return error; 197 } 198 199 // Get pointer to m_fpr variable and set the data from it. 200 assert (reg_info->byte_offset < sizeof m_fpr); 201 uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset; 202 switch (reg_info->byte_size) 203 { 204 case 2: 205 reg_value.SetUInt16(*(uint16_t *)src); 206 break; 207 case 4: 208 reg_value.SetUInt32(*(uint32_t *)src); 209 break; 210 case 8: 211 reg_value.SetUInt64(*(uint64_t *)src); 212 break; 213 default: 214 assert(false && "Unhandled data size."); 215 error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size); 216 break; 217 } 218 219 return error; 220 } 221 222 Error 223 NativeRegisterContextLinux_arm::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) 224 { 225 if (!reg_info) 226 return Error ("reg_info NULL"); 227 228 const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; 229 if (reg_index == LLDB_INVALID_REGNUM) 230 return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>"); 231 232 if (IsGPR(reg_index)) 233 return WriteRegisterRaw(reg_index, reg_value); 234 235 if (IsFPR(reg_index)) 236 { 237 // Get pointer to m_fpr variable and set the data to it. 238 assert (reg_info->byte_offset < sizeof(m_fpr)); 239 uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset; 240 switch (reg_info->byte_size) 241 { 242 case 2: 243 *(uint16_t *)dst = reg_value.GetAsUInt16(); 244 break; 245 case 4: 246 *(uint32_t *)dst = reg_value.GetAsUInt32(); 247 break; 248 case 8: 249 *(uint64_t *)dst = reg_value.GetAsUInt64(); 250 break; 251 default: 252 assert(false && "Unhandled data size."); 253 return Error ("unhandled register data size %" PRIu32, reg_info->byte_size); 254 } 255 256 if (!WriteFPR()) 257 { 258 return Error ("NativeRegisterContextLinux_arm::WriteRegister: WriteFPR failed"); 259 } 260 261 return Error (); 262 } 263 264 return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); 265 } 266 267 Error 268 NativeRegisterContextLinux_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp) 269 { 270 Error error; 271 272 data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); 273 if (!data_sp) 274 return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, (uint64_t)REG_CONTEXT_SIZE); 275 276 if (!ReadGPR ()) 277 { 278 error.SetErrorString ("ReadGPR() failed"); 279 return error; 280 } 281 282 if (!ReadFPR ()) 283 { 284 error.SetErrorString ("ReadFPR() failed"); 285 return error; 286 } 287 288 uint8_t *dst = data_sp->GetBytes (); 289 if (dst == nullptr) 290 { 291 error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", (uint64_t)REG_CONTEXT_SIZE); 292 return error; 293 } 294 295 ::memcpy (dst, &m_gpr_arm, GetGPRSize()); 296 dst += GetGPRSize(); 297 ::memcpy (dst, &m_fpr, sizeof(m_fpr)); 298 299 return error; 300 } 301 302 Error 303 NativeRegisterContextLinux_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) 304 { 305 Error error; 306 307 if (!data_sp) 308 { 309 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); 310 return error; 311 } 312 313 if (data_sp->GetByteSize () != REG_CONTEXT_SIZE) 314 { 315 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 ()); 316 return error; 317 } 318 319 320 uint8_t *src = data_sp->GetBytes (); 321 if (src == nullptr) 322 { 323 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); 324 return error; 325 } 326 ::memcpy (&m_gpr_arm, src, GetRegisterInfoInterface ().GetGPRSize ()); 327 328 if (!WriteGPR ()) 329 { 330 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__); 331 return error; 332 } 333 334 src += GetRegisterInfoInterface ().GetGPRSize (); 335 ::memcpy (&m_fpr, src, sizeof(m_fpr)); 336 337 if (!WriteFPR ()) 338 { 339 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__); 340 return error; 341 } 342 343 return error; 344 } 345 346 Error 347 NativeRegisterContextLinux_arm::WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value) 348 { 349 Error error; 350 351 uint32_t reg_to_write = reg_index; 352 RegisterValue value_to_write = reg_value; 353 354 // Check if this is a subregister of a full register. 355 const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); 356 if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) 357 { 358 RegisterValue full_value; 359 uint32_t full_reg = reg_info->invalidate_regs[0]; 360 const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); 361 362 // Read the full register. 363 error = ReadRegister(full_reg_info, full_value); 364 if (error.Fail ()) 365 return error; 366 367 lldb::ByteOrder byte_order = GetByteOrder(); 368 uint8_t dst[RegisterValue::kMaxRegisterByteSize]; 369 370 // Get the bytes for the full register. 371 const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info, 372 dst, 373 sizeof(dst), 374 byte_order, 375 error); 376 if (error.Success() && dest_size) 377 { 378 uint8_t src[RegisterValue::kMaxRegisterByteSize]; 379 380 // Get the bytes for the source data. 381 const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error); 382 if (error.Success() && src_size && (src_size < dest_size)) 383 { 384 // Copy the src bytes to the destination. 385 memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size); 386 // Set this full register as the value to write. 387 value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); 388 value_to_write.SetType(full_reg_info); 389 reg_to_write = full_reg; 390 } 391 } 392 } 393 394 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 395 if (!process_sp) 396 { 397 error.SetErrorString ("NativeProcessProtocol is NULL"); 398 return error; 399 } 400 401 const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write); 402 assert (register_to_write_info_p && "register to write does not have valid RegisterInfo"); 403 if (!register_to_write_info_p) 404 { 405 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write); 406 return error; 407 } 408 409 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 410 return process_p->WriteRegisterValue(m_thread.GetID(), 411 register_to_write_info_p->byte_offset, 412 register_to_write_info_p->name, 413 value_to_write); 414 } 415 416 Error 417 NativeRegisterContextLinux_arm::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value) 418 { 419 Error error; 420 const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index); 421 if (!reg_info) 422 { 423 error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index); 424 return error; 425 } 426 427 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 428 if (!process_sp) 429 { 430 error.SetErrorString ("NativeProcessProtocol is NULL"); 431 return error; 432 } 433 434 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 435 return process_p->ReadRegisterValue(m_thread.GetID(), 436 reg_info->byte_offset, 437 reg_info->name, 438 reg_info->byte_size, 439 reg_value); 440 } 441 442 bool 443 NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const 444 { 445 return reg <= m_reg_info.last_gpr; // GPR's come first. 446 } 447 448 bool 449 NativeRegisterContextLinux_arm::ReadGPR() 450 { 451 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 452 if (!process_sp) 453 return false; 454 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 455 456 return process_p->ReadGPR (m_thread.GetID (), &m_gpr_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success(); 457 } 458 459 bool 460 NativeRegisterContextLinux_arm::WriteGPR() 461 { 462 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 463 if (!process_sp) 464 return false; 465 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 466 467 return process_p->WriteGPR (m_thread.GetID (), &m_gpr_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success(); 468 } 469 470 bool 471 NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const 472 { 473 return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); 474 } 475 476 bool 477 NativeRegisterContextLinux_arm::ReadFPR () 478 { 479 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 480 if (!process_sp) 481 return false; 482 483 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 484 return process_p->ReadFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); 485 } 486 487 bool 488 NativeRegisterContextLinux_arm::WriteFPR () 489 { 490 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 491 if (!process_sp) 492 return false; 493 494 NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ()); 495 return process_p->WriteFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success(); 496 } 497 498 lldb::ByteOrder 499 NativeRegisterContextLinux_arm::GetByteOrder() const 500 { 501 // Get the target process whose privileged thread was used for the register read. 502 lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; 503 504 NativeProcessProtocolSP process_sp (m_thread.GetProcess ()); 505 if (!process_sp) 506 return byte_order; 507 508 if (!process_sp->GetByteOrder (byte_order)) 509 { 510 // FIXME log here 511 } 512 513 return byte_order; 514 } 515 516 size_t 517 NativeRegisterContextLinux_arm::GetGPRSize() const 518 { 519 return GetRegisterInfoInterface().GetGPRSize(); 520 } 521