DNBArchImpl.cpp revision 59752d199bb19ffde140b67da147b0afa67f2e88
1//===-- DNBArchImpl.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// Created by Greg Clayton on 6/25/07. 11// 12//===----------------------------------------------------------------------===// 13 14#if defined (__arm__) 15 16#include "MacOSX/arm/DNBArchImpl.h" 17#include "MacOSX/MachProcess.h" 18#include "MacOSX/MachThread.h" 19#include "DNBBreakpoint.h" 20#include "DNBLog.h" 21#include "DNBRegisterInfo.h" 22#include "DNB.h" 23#include "ARM_GCC_Registers.h" 24#include "ARM_DWARF_Registers.h" 25 26#include <sys/sysctl.h> 27 28// BCR address match type 29#define BCR_M_IMVA_MATCH ((uint32_t)(0u << 21)) 30#define BCR_M_CONTEXT_ID_MATCH ((uint32_t)(1u << 21)) 31#define BCR_M_IMVA_MISMATCH ((uint32_t)(2u << 21)) 32#define BCR_M_RESERVED ((uint32_t)(3u << 21)) 33 34// Link a BVR/BCR or WVR/WCR pair to another 35#define E_ENABLE_LINKING ((uint32_t)(1u << 20)) 36 37// Byte Address Select 38#define BAS_IMVA_PLUS_0 ((uint32_t)(1u << 5)) 39#define BAS_IMVA_PLUS_1 ((uint32_t)(1u << 6)) 40#define BAS_IMVA_PLUS_2 ((uint32_t)(1u << 7)) 41#define BAS_IMVA_PLUS_3 ((uint32_t)(1u << 8)) 42#define BAS_IMVA_0_1 ((uint32_t)(3u << 5)) 43#define BAS_IMVA_2_3 ((uint32_t)(3u << 7)) 44#define BAS_IMVA_ALL ((uint32_t)(0xfu << 5)) 45 46// Break only in priveleged or user mode 47#define S_RSVD ((uint32_t)(0u << 1)) 48#define S_PRIV ((uint32_t)(1u << 1)) 49#define S_USER ((uint32_t)(2u << 1)) 50#define S_PRIV_USER ((S_PRIV) | (S_USER)) 51 52#define BCR_ENABLE ((uint32_t)(1u)) 53#define WCR_ENABLE ((uint32_t)(1u)) 54 55// Watchpoint load/store 56#define WCR_LOAD ((uint32_t)(1u << 3)) 57#define WCR_STORE ((uint32_t)(1u << 4)) 58 59// Definitions for the Debug Status and Control Register fields: 60// [5:2] => Method of debug entry 61//#define WATCHPOINT_OCCURRED ((uint32_t)(2u)) 62// I'm seeing this, instead. 63#define WATCHPOINT_OCCURRED ((uint32_t)(10u)) 64 65static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 }; 66static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE }; 67 68// ARM constants used during decoding 69#define REG_RD 0 70#define LDM_REGLIST 1 71#define PC_REG 15 72#define PC_REGLIST_BIT 0x8000 73 74// ARM conditions 75#define COND_EQ 0x0 76#define COND_NE 0x1 77#define COND_CS 0x2 78#define COND_HS 0x2 79#define COND_CC 0x3 80#define COND_LO 0x3 81#define COND_MI 0x4 82#define COND_PL 0x5 83#define COND_VS 0x6 84#define COND_VC 0x7 85#define COND_HI 0x8 86#define COND_LS 0x9 87#define COND_GE 0xA 88#define COND_LT 0xB 89#define COND_GT 0xC 90#define COND_LE 0xD 91#define COND_AL 0xE 92#define COND_UNCOND 0xF 93 94#define MASK_CPSR_T (1u << 5) 95#define MASK_CPSR_J (1u << 24) 96 97#define MNEMONIC_STRING_SIZE 32 98#define OPERAND_STRING_SIZE 128 99 100 101void 102DNBArchMachARM::Initialize() 103{ 104 DNBArchPluginInfo arch_plugin_info = 105 { 106 CPU_TYPE_ARM, 107 DNBArchMachARM::Create, 108 DNBArchMachARM::GetRegisterSetInfo, 109 DNBArchMachARM::SoftwareBreakpointOpcode 110 }; 111 112 // Register this arch plug-in with the main protocol class 113 DNBArchProtocol::RegisterArchPlugin (arch_plugin_info); 114} 115 116 117DNBArchProtocol * 118DNBArchMachARM::Create (MachThread *thread) 119{ 120 DNBArchMachARM *obj = new DNBArchMachARM (thread); 121 122 // When new thread comes along, it tries to inherit from the global debug state, if it is valid. 123 if (Valid_Global_Debug_State) 124 { 125 obj->m_state.dbg = Global_Debug_State; 126 kern_return_t kret = obj->SetDBGState(); 127 DNBLogThreadedIf(LOG_WATCHPOINTS, 128 "DNBArchMachARM::Create() Inherit and SetDBGState() => 0x%8.8x.", kret); 129 } 130 return obj; 131} 132 133const uint8_t * const 134DNBArchMachARM::SoftwareBreakpointOpcode (nub_size_t byte_size) 135{ 136 switch (byte_size) 137 { 138 case 2: return g_thumb_breakpooint_opcode; 139 case 4: return g_arm_breakpoint_opcode; 140 } 141 return NULL; 142} 143 144uint32_t 145DNBArchMachARM::GetCPUType() 146{ 147 return CPU_TYPE_ARM; 148} 149 150uint64_t 151DNBArchMachARM::GetPC(uint64_t failValue) 152{ 153 // Get program counter 154 if (GetGPRState(false) == KERN_SUCCESS) 155 return m_state.context.gpr.__pc; 156 return failValue; 157} 158 159kern_return_t 160DNBArchMachARM::SetPC(uint64_t value) 161{ 162 // Get program counter 163 kern_return_t err = GetGPRState(false); 164 if (err == KERN_SUCCESS) 165 { 166 m_state.context.gpr.__pc = value; 167 err = SetGPRState(); 168 } 169 return err == KERN_SUCCESS; 170} 171 172uint64_t 173DNBArchMachARM::GetSP(uint64_t failValue) 174{ 175 // Get stack pointer 176 if (GetGPRState(false) == KERN_SUCCESS) 177 return m_state.context.gpr.__sp; 178 return failValue; 179} 180 181kern_return_t 182DNBArchMachARM::GetGPRState(bool force) 183{ 184 int set = e_regSetGPR; 185 // Check if we have valid cached registers 186 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) 187 return KERN_SUCCESS; 188 189 // Read the registers from our thread 190 mach_msg_type_number_t count = ARM_THREAD_STATE_COUNT; 191 kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count); 192 uint32_t *r = &m_state.context.gpr.__r[0]; 193 DNBLogThreadedIf(LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = %u) regs r0=%8.8x r1=%8.8x r2=%8.8x r3=%8.8x r4=%8.8x r5=%8.8x r6=%8.8x r7=%8.8x r8=%8.8x r9=%8.8x r10=%8.8x r11=%8.8x s12=%8.8x sp=%8.8x lr=%8.8x pc=%8.8x cpsr=%8.8x", 194 m_thread->MachPortNumber(), 195 ARM_THREAD_STATE, 196 ARM_THREAD_STATE_COUNT, 197 kret, 198 count, 199 r[0], 200 r[1], 201 r[2], 202 r[3], 203 r[4], 204 r[5], 205 r[6], 206 r[7], 207 r[8], 208 r[9], 209 r[10], 210 r[11], 211 r[12], 212 r[13], 213 r[14], 214 r[15], 215 r[16]); 216 m_state.SetError(set, Read, kret); 217 return kret; 218} 219 220kern_return_t 221DNBArchMachARM::GetVFPState(bool force) 222{ 223 int set = e_regSetVFP; 224 // Check if we have valid cached registers 225 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) 226 return KERN_SUCCESS; 227 228 // Read the registers from our thread 229 mach_msg_type_number_t count = ARM_VFP_STATE_COUNT; 230 kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, &count); 231 if (DNBLogEnabledForAny (LOG_THREAD)) 232 { 233 uint32_t *r = &m_state.context.vfp.__r[0]; 234 DNBLogThreaded ("thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count => %u)", 235 m_thread->MachPortNumber(), 236 ARM_THREAD_STATE, 237 ARM_THREAD_STATE_COUNT, 238 kret, 239 count); 240 DNBLogThreaded(" s0=%8.8x s1=%8.8x s2=%8.8x s3=%8.8x s4=%8.8x s5=%8.8x s6=%8.8x s7=%8.8x",r[ 0],r[ 1],r[ 2],r[ 3],r[ 4],r[ 5],r[ 6],r[ 7]); 241 DNBLogThreaded(" s8=%8.8x s9=%8.8x s10=%8.8x s11=%8.8x s12=%8.8x s13=%8.8x s14=%8.8x s15=%8.8x",r[ 8],r[ 9],r[10],r[11],r[12],r[13],r[14],r[15]); 242 DNBLogThreaded(" s16=%8.8x s17=%8.8x s18=%8.8x s19=%8.8x s20=%8.8x s21=%8.8x s22=%8.8x s23=%8.8x",r[16],r[17],r[18],r[19],r[20],r[21],r[22],r[23]); 243 DNBLogThreaded(" s24=%8.8x s25=%8.8x s26=%8.8x s27=%8.8x s28=%8.8x s29=%8.8x s30=%8.8x s31=%8.8x",r[24],r[25],r[26],r[27],r[28],r[29],r[30],r[31]); 244 DNBLogThreaded(" s32=%8.8x s33=%8.8x s34=%8.8x s35=%8.8x s36=%8.8x s37=%8.8x s38=%8.8x s39=%8.8x",r[32],r[33],r[34],r[35],r[36],r[37],r[38],r[39]); 245 DNBLogThreaded(" s40=%8.8x s41=%8.8x s42=%8.8x s43=%8.8x s44=%8.8x s45=%8.8x s46=%8.8x s47=%8.8x",r[40],r[41],r[42],r[43],r[44],r[45],r[46],r[47]); 246 DNBLogThreaded(" s48=%8.8x s49=%8.8x s50=%8.8x s51=%8.8x s52=%8.8x s53=%8.8x s54=%8.8x s55=%8.8x",r[48],r[49],r[50],r[51],r[52],r[53],r[54],r[55]); 247 DNBLogThreaded(" s56=%8.8x s57=%8.8x s58=%8.8x s59=%8.8x s60=%8.8x s61=%8.8x s62=%8.8x s63=%8.8x fpscr=%8.8x",r[56],r[57],r[58],r[59],r[60],r[61],r[62],r[63],r[64]); 248 } 249 m_state.SetError(set, Read, kret); 250 return kret; 251} 252 253kern_return_t 254DNBArchMachARM::GetEXCState(bool force) 255{ 256 int set = e_regSetEXC; 257 // Check if we have valid cached registers 258 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) 259 return KERN_SUCCESS; 260 261 // Read the registers from our thread 262 mach_msg_type_number_t count = ARM_EXCEPTION_STATE_COUNT; 263 kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count); 264 m_state.SetError(set, Read, kret); 265 return kret; 266} 267 268static void 269DumpDBGState(const DNBArchMachARM::DBG& dbg) 270{ 271 uint32_t i = 0; 272 for (i=0; i<16; i++) { 273 DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }", 274 i, i, dbg.__bvr[i], dbg.__bcr[i], 275 i, i, dbg.__wvr[i], dbg.__wcr[i]); 276 } 277} 278 279kern_return_t 280DNBArchMachARM::GetDBGState(bool force) 281{ 282 int set = e_regSetDBG; 283 284 // Check if we have valid cached registers 285 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) 286 return KERN_SUCCESS; 287 288 // Read the registers from our thread 289 mach_msg_type_number_t count = ARM_DEBUG_STATE_COUNT; 290 kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, &count); 291 m_state.SetError(set, Read, kret); 292 return kret; 293} 294 295kern_return_t 296DNBArchMachARM::SetGPRState() 297{ 298 int set = e_regSetGPR; 299 kern_return_t kret = ::thread_set_state(m_thread->MachPortNumber(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, ARM_THREAD_STATE_COUNT); 300 m_state.SetError(set, Write, kret); // Set the current write error for this register set 301 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently 302 return kret; // Return the error code 303} 304 305kern_return_t 306DNBArchMachARM::SetVFPState() 307{ 308 int set = e_regSetVFP; 309 kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, ARM_VFP_STATE_COUNT); 310 m_state.SetError(set, Write, kret); // Set the current write error for this register set 311 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently 312 return kret; // Return the error code 313} 314 315kern_return_t 316DNBArchMachARM::SetEXCState() 317{ 318 int set = e_regSetEXC; 319 kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, ARM_EXCEPTION_STATE_COUNT); 320 m_state.SetError(set, Write, kret); // Set the current write error for this register set 321 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently 322 return kret; // Return the error code 323} 324 325kern_return_t 326DNBArchMachARM::SetDBGState() 327{ 328 int set = e_regSetDBG; 329 kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT); 330 m_state.SetError(set, Write, kret); // Set the current write error for this register set 331 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently 332 return kret; // Return the error code 333} 334 335void 336DNBArchMachARM::ThreadWillResume() 337{ 338 // Do we need to step this thread? If so, let the mach thread tell us so. 339 if (m_thread->IsStepping()) 340 { 341 // This is the primary thread, let the arch do anything it needs 342 if (NumSupportedHardwareBreakpoints() > 0) 343 { 344 if (EnableHardwareSingleStep(true) != KERN_SUCCESS) 345 { 346 DNBLogThreaded("DNBArchMachARM::ThreadWillResume() failed to enable hardware single step"); 347 } 348 } 349 } 350 351 // Disable the triggered watchpoint temporarily before we resume. 352 // Plus, we try to enable hardware single step to execute past the instruction which triggered our watchpoint. 353 if (m_watchpoint_did_occur) 354 { 355 if (m_watchpoint_hw_index >= 0) 356 { 357 kern_return_t kret = GetDBGState(false); 358 if (kret == KERN_SUCCESS && !IsWatchpointEnabled(m_state.dbg, m_watchpoint_hw_index)) { 359 // The watchpoint might have been disabled by the user. We don't need to do anything at all 360 // to enable hardware single stepping. 361 m_watchpoint_did_occur = false; 362 m_watchpoint_hw_index = -1; 363 return; 364 } 365 366 DisableHardwareWatchpoint0(m_watchpoint_hw_index, true); 367 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() DisableHardwareWatchpoint(%d) called", 368 m_watchpoint_hw_index); 369 370 // Enable hardware single step to move past the watchpoint-triggering instruction. 371 m_watchpoint_resume_single_step_enabled = (EnableHardwareSingleStep(true) == KERN_SUCCESS); 372 373 // If we are not able to enable single step to move past the watchpoint-triggering instruction, 374 // at least we should reset the two watchpoint member variables so that the next time around 375 // this callback function is invoked, the enclosing logical branch is skipped. 376 if (!m_watchpoint_resume_single_step_enabled) { 377 // Reset the two watchpoint member variables. 378 m_watchpoint_did_occur = false; 379 m_watchpoint_hw_index = -1; 380 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() failed to enable single step"); 381 } 382 else 383 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() succeeded to enable single step"); 384 } 385 } 386} 387 388bool 389DNBArchMachARM::ThreadDidStop() 390{ 391 bool success = true; 392 393 m_state.InvalidateRegisterSetState (e_regSetALL); 394 395 if (m_watchpoint_resume_single_step_enabled) 396 { 397 // Great! We now disable the hardware single step as well as re-enable the hardware watchpoint. 398 // See also ThreadWillResume(). 399 if (EnableHardwareSingleStep(false) == KERN_SUCCESS) 400 { 401 if (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) 402 { 403 EnableHardwareWatchpoint0(m_watchpoint_hw_index, true); 404 m_watchpoint_resume_single_step_enabled = false; 405 m_watchpoint_did_occur = false; 406 m_watchpoint_hw_index = -1; 407 } 408 else 409 { 410 DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) does not hold!"); 411 } 412 } 413 else 414 { 415 DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but unable to disable single step!"); 416 } 417 } 418 419 // Are we stepping a single instruction? 420 if (GetGPRState(true) == KERN_SUCCESS) 421 { 422 // We are single stepping, was this the primary thread? 423 if (m_thread->IsStepping()) 424 { 425 success = EnableHardwareSingleStep(false) == KERN_SUCCESS; 426 } 427 else 428 { 429 // The MachThread will automatically restore the suspend count 430 // in ThreadDidStop(), so we don't need to do anything here if 431 // we weren't the primary thread the last time 432 } 433 } 434 return success; 435} 436 437bool 438DNBArchMachARM::NotifyException(MachException::Data& exc) 439{ 440 switch (exc.exc_type) 441 { 442 default: 443 break; 444 case EXC_BREAKPOINT: 445 if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG) 446 { 447 // exc_code = EXC_ARM_DA_DEBUG 448 // 449 // Check whether this corresponds to a watchpoint hit event. 450 // If yes, retrieve the exc_sub_code as the data break address. 451 if (!HasWatchpointOccurred()) 452 break; 453 454 // The data break address is passed as exc_data[1]. 455 nub_addr_t addr = exc.exc_data[1]; 456 // Find the hardware index with the side effect of possibly massaging the 457 // addr to return the starting address as seen from the debugger side. 458 uint32_t hw_index = GetHardwareWatchpointHit(addr); 459 if (hw_index != INVALID_NUB_HW_INDEX) 460 { 461 m_watchpoint_did_occur = true; 462 m_watchpoint_hw_index = hw_index; 463 exc.exc_data[1] = addr; 464 // Piggyback the hw_index in the exc.data. 465 exc.exc_data.push_back(hw_index); 466 } 467 468 return true; 469 } 470 break; 471 } 472 return false; 473} 474 475bool 476DNBArchMachARM::StepNotComplete () 477{ 478 if (m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS) 479 { 480 kern_return_t kret = KERN_INVALID_ARGUMENT; 481 kret = GetGPRState(false); 482 if (kret == KERN_SUCCESS) 483 { 484 if (m_state.context.gpr.__pc == m_hw_single_chained_step_addr) 485 { 486 DNBLogThreadedIf(LOG_STEP, "Need to step some more at 0x%8.8x", m_hw_single_chained_step_addr); 487 return true; 488 } 489 } 490 } 491 492 m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; 493 return false; 494} 495 496 497// Set the single step bit in the processor status register. 498kern_return_t 499DNBArchMachARM::EnableHardwareSingleStep (bool enable) 500{ 501 DNBError err; 502 DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable); 503 504 err = GetGPRState(false); 505 506 if (err.Fail()) 507 { 508 err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__); 509 return err.Error(); 510 } 511 512 err = GetDBGState(false); 513 514 if (err.Fail()) 515 { 516 err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__); 517 return err.Error(); 518 } 519 520 const uint32_t i = 0; 521 if (enable) 522 { 523 m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; 524 525 // Save our previous state 526 m_dbg_save = m_state.dbg; 527 // Set a breakpoint that will stop when the PC doesn't match the current one! 528 m_state.dbg.__bvr[i] = m_state.context.gpr.__pc & 0xFFFFFFFCu; // Set the current PC as the breakpoint address 529 m_state.dbg.__bcr[i] = BCR_M_IMVA_MISMATCH | // Stop on address mismatch 530 S_USER | // Stop only in user mode 531 BCR_ENABLE; // Enable this breakpoint 532 if (m_state.context.gpr.__cpsr & 0x20) 533 { 534 // Thumb breakpoint 535 if (m_state.context.gpr.__pc & 2) 536 m_state.dbg.__bcr[i] |= BAS_IMVA_2_3; 537 else 538 m_state.dbg.__bcr[i] |= BAS_IMVA_0_1; 539 540 uint16_t opcode; 541 if (sizeof(opcode) == m_thread->Process()->Task().ReadMemory(m_state.context.gpr.__pc, sizeof(opcode), &opcode)) 542 { 543 if (((opcode & 0xE000) == 0xE000) && opcode & 0x1800) 544 { 545 // 32 bit thumb opcode... 546 if (m_state.context.gpr.__pc & 2) 547 { 548 // We can't take care of a 32 bit thumb instruction single step 549 // with just IVA mismatching. We will need to chain an extra 550 // hardware single step in order to complete this single step... 551 m_hw_single_chained_step_addr = m_state.context.gpr.__pc + 2; 552 } 553 else 554 { 555 // Extend the number of bits to ignore for the mismatch 556 m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; 557 } 558 } 559 } 560 } 561 else 562 { 563 // ARM breakpoint 564 m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; // Stop when any address bits change 565 } 566 567 DNBLogThreadedIf(LOG_STEP, "%s: BVR%u=0x%8.8x BCR%u=0x%8.8x", __FUNCTION__, i, m_state.dbg.__bvr[i], i, m_state.dbg.__bcr[i]); 568 569 for (uint32_t j=i+1; j<16; ++j) 570 { 571 // Disable all others 572 m_state.dbg.__bvr[j] = 0; 573 m_state.dbg.__bcr[j] = 0; 574 } 575 } 576 else 577 { 578 // Just restore the state we had before we did single stepping 579 m_state.dbg = m_dbg_save; 580 } 581 582 return SetDBGState(); 583} 584 585// return 1 if bit "BIT" is set in "value" 586static inline uint32_t bit(uint32_t value, uint32_t bit) 587{ 588 return (value >> bit) & 1u; 589} 590 591// return the bitfield "value[msbit:lsbit]". 592static inline uint32_t bits(uint32_t value, uint32_t msbit, uint32_t lsbit) 593{ 594 assert(msbit >= lsbit); 595 uint32_t shift_left = sizeof(value) * 8 - 1 - msbit; 596 value <<= shift_left; // shift anything above the msbit off of the unsigned edge 597 value >>= (shift_left + lsbit); // shift it back again down to the lsbit (including undoing any shift from above) 598 return value; // return our result 599} 600 601bool 602DNBArchMachARM::ConditionPassed(uint8_t condition, uint32_t cpsr) 603{ 604 uint32_t cpsr_n = bit(cpsr, 31); // Negative condition code flag 605 uint32_t cpsr_z = bit(cpsr, 30); // Zero condition code flag 606 uint32_t cpsr_c = bit(cpsr, 29); // Carry condition code flag 607 uint32_t cpsr_v = bit(cpsr, 28); // Overflow condition code flag 608 609 switch (condition) { 610 case COND_EQ: // (0x0) 611 if (cpsr_z == 1) return true; 612 break; 613 case COND_NE: // (0x1) 614 if (cpsr_z == 0) return true; 615 break; 616 case COND_CS: // (0x2) 617 if (cpsr_c == 1) return true; 618 break; 619 case COND_CC: // (0x3) 620 if (cpsr_c == 0) return true; 621 break; 622 case COND_MI: // (0x4) 623 if (cpsr_n == 1) return true; 624 break; 625 case COND_PL: // (0x5) 626 if (cpsr_n == 0) return true; 627 break; 628 case COND_VS: // (0x6) 629 if (cpsr_v == 1) return true; 630 break; 631 case COND_VC: // (0x7) 632 if (cpsr_v == 0) return true; 633 break; 634 case COND_HI: // (0x8) 635 if ((cpsr_c == 1) && (cpsr_z == 0)) return true; 636 break; 637 case COND_LS: // (0x9) 638 if ((cpsr_c == 0) || (cpsr_z == 1)) return true; 639 break; 640 case COND_GE: // (0xA) 641 if (cpsr_n == cpsr_v) return true; 642 break; 643 case COND_LT: // (0xB) 644 if (cpsr_n != cpsr_v) return true; 645 break; 646 case COND_GT: // (0xC) 647 if ((cpsr_z == 0) && (cpsr_n == cpsr_v)) return true; 648 break; 649 case COND_LE: // (0xD) 650 if ((cpsr_z == 1) || (cpsr_n != cpsr_v)) return true; 651 break; 652 default: 653 return true; 654 break; 655 } 656 657 return false; 658} 659 660uint32_t 661DNBArchMachARM::NumSupportedHardwareBreakpoints() 662{ 663 // Set the init value to something that will let us know that we need to 664 // autodetect how many breakpoints are supported dynamically... 665 static uint32_t g_num_supported_hw_breakpoints = UINT_MAX; 666 if (g_num_supported_hw_breakpoints == UINT_MAX) 667 { 668 // Set this to zero in case we can't tell if there are any HW breakpoints 669 g_num_supported_hw_breakpoints = 0; 670 671 size_t len; 672 uint32_t n = 0; 673 len = sizeof (n); 674 if (::sysctlbyname("hw.optional.breakpoint", &n, &len, NULL, 0) == 0) 675 { 676 g_num_supported_hw_breakpoints = n; 677 DNBLogThreadedIf(LOG_THREAD, "hw.optional.breakpoint=%u", n); 678 } 679 else 680 { 681 // Read the DBGDIDR to get the number of available hardware breakpoints 682 // However, in some of our current armv7 processors, hardware 683 // breakpoints/watchpoints were not properly connected. So detect those 684 // cases using a field in a sysctl. For now we are using "hw.cpusubtype" 685 // field to distinguish CPU architectures. This is a hack until we can 686 // get <rdar://problem/6372672> fixed, at which point we will switch to 687 // using a different sysctl string that will tell us how many BRPs 688 // are available to us directly without having to read DBGDIDR. 689 uint32_t register_DBGDIDR; 690 691 asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); 692 uint32_t numBRPs = bits(register_DBGDIDR, 27, 24); 693 // Zero is reserved for the BRP count, so don't increment it if it is zero 694 if (numBRPs > 0) 695 numBRPs++; 696 DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, numBRPs); 697 698 if (numBRPs > 0) 699 { 700 uint32_t cpusubtype; 701 len = sizeof(cpusubtype); 702 // TODO: remove this hack and change to using hw.optional.xx when implmented 703 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) 704 { 705 DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=%d", cpusubtype); 706 if (cpusubtype == CPU_SUBTYPE_ARM_V7) 707 DNBLogThreadedIf(LOG_THREAD, "Hardware breakpoints disabled for armv7 (rdar://problem/6372672)"); 708 else 709 g_num_supported_hw_breakpoints = numBRPs; 710 } 711 } 712 } 713 } 714 return g_num_supported_hw_breakpoints; 715} 716 717 718uint32_t 719DNBArchMachARM::NumSupportedHardwareWatchpoints() 720{ 721 // Set the init value to something that will let us know that we need to 722 // autodetect how many watchpoints are supported dynamically... 723 static uint32_t g_num_supported_hw_watchpoints = UINT_MAX; 724 if (g_num_supported_hw_watchpoints == UINT_MAX) 725 { 726 // Set this to zero in case we can't tell if there are any HW breakpoints 727 g_num_supported_hw_watchpoints = 0; 728 729 730 size_t len; 731 uint32_t n = 0; 732 len = sizeof (n); 733 if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) 734 { 735 g_num_supported_hw_watchpoints = n; 736 DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n); 737 } 738 else 739 { 740 // Read the DBGDIDR to get the number of available hardware breakpoints 741 // However, in some of our current armv7 processors, hardware 742 // breakpoints/watchpoints were not properly connected. So detect those 743 // cases using a field in a sysctl. For now we are using "hw.cpusubtype" 744 // field to distinguish CPU architectures. This is a hack until we can 745 // get <rdar://problem/6372672> fixed, at which point we will switch to 746 // using a different sysctl string that will tell us how many WRPs 747 // are available to us directly without having to read DBGDIDR. 748 749 uint32_t register_DBGDIDR; 750 asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); 751 uint32_t numWRPs = bits(register_DBGDIDR, 31, 28) + 1; 752 DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, numWRPs); 753 754 if (numWRPs > 0) 755 { 756 uint32_t cpusubtype; 757 size_t len; 758 len = sizeof(cpusubtype); 759 // TODO: remove this hack and change to using hw.optional.xx when implmented 760 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) 761 { 762 DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype); 763 764 if (cpusubtype == CPU_SUBTYPE_ARM_V7) 765 DNBLogThreadedIf(LOG_THREAD, "Hardware watchpoints disabled for armv7 (rdar://problem/6372672)"); 766 else 767 g_num_supported_hw_watchpoints = numWRPs; 768 } 769 } 770 } 771 } 772 return g_num_supported_hw_watchpoints; 773} 774 775 776uint32_t 777DNBArchMachARM::EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size) 778{ 779 // Make sure our address isn't bogus 780 if (addr & 1) 781 return INVALID_NUB_HW_INDEX; 782 783 kern_return_t kret = GetDBGState(false); 784 785 if (kret == KERN_SUCCESS) 786 { 787 const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); 788 uint32_t i; 789 for (i=0; i<num_hw_breakpoints; ++i) 790 { 791 if ((m_state.dbg.__bcr[i] & BCR_ENABLE) == 0) 792 break; // We found an available hw breakpoint slot (in i) 793 } 794 795 // See if we found an available hw breakpoint slot above 796 if (i < num_hw_breakpoints) 797 { 798 // Make sure bits 1:0 are clear in our address 799 m_state.dbg.__bvr[i] = addr & ~((nub_addr_t)3); 800 801 if (size == 2 || addr & 2) 802 { 803 uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1; 804 805 // We have a thumb breakpoint 806 // We have an ARM breakpoint 807 m_state.dbg.__bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch 808 byte_addr_select | // Set the correct byte address select so we only trigger on the correct opcode 809 S_USER | // Which modes should this breakpoint stop in? 810 BCR_ENABLE; // Enable this hardware breakpoint 811 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)", 812 (uint64_t)addr, 813 (uint64_t)size, 814 i, 815 i, 816 m_state.dbg.__bvr[i], 817 m_state.dbg.__bcr[i]); 818 } 819 else if (size == 4) 820 { 821 // We have an ARM breakpoint 822 m_state.dbg.__bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch 823 BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA 824 S_USER | // Which modes should this breakpoint stop in? 825 BCR_ENABLE; // Enable this hardware breakpoint 826 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)", 827 (uint64_t)addr, 828 (uint64_t)size, 829 i, 830 i, 831 m_state.dbg.__bvr[i], 832 m_state.dbg.__bcr[i]); 833 } 834 835 kret = SetDBGState(); 836 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint() SetDBGState() => 0x%8.8x.", kret); 837 838 if (kret == KERN_SUCCESS) 839 return i; 840 } 841 else 842 { 843 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint(addr = 0x%8.8llx, size = %llu) => all hardware breakpoint resources are being used.", (uint64_t)addr, (uint64_t)size); 844 } 845 } 846 847 return INVALID_NUB_HW_INDEX; 848} 849 850bool 851DNBArchMachARM::DisableHardwareBreakpoint (uint32_t hw_index) 852{ 853 kern_return_t kret = GetDBGState(false); 854 855 const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); 856 if (kret == KERN_SUCCESS) 857 { 858 if (hw_index < num_hw_points) 859 { 860 m_state.dbg.__bcr[hw_index] = 0; 861 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x BCR%u = 0x%8.8x", 862 hw_index, 863 hw_index, 864 m_state.dbg.__bvr[hw_index], 865 hw_index, 866 m_state.dbg.__bcr[hw_index]); 867 868 kret = SetDBGState(); 869 870 if (kret == KERN_SUCCESS) 871 return true; 872 } 873 } 874 return false; 875} 876 877// This stores the lo->hi mappings. It's safe to initialize to all 0's 878// since hi > lo and therefore LoHi[i] cannot be 0. 879static uint32_t LoHi[16] = { 0 }; 880 881uint32_t 882DNBArchMachARM::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write) 883{ 884 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %llu, read = %u, write = %u)", (uint64_t)addr, (uint64_t)size, read, write); 885 886 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); 887 888 // Can't watch zero bytes 889 if (size == 0) 890 return INVALID_NUB_HW_INDEX; 891 892 // We must watch for either read or write 893 if (read == false && write == false) 894 return INVALID_NUB_HW_INDEX; 895 896 // Divide-and-conquer for size == 8. 897 if (size == 8) 898 { 899 uint32_t lo = EnableHardwareWatchpoint(addr, 4, read, write); 900 if (lo == INVALID_NUB_HW_INDEX) 901 return INVALID_NUB_HW_INDEX; 902 uint32_t hi = EnableHardwareWatchpoint(addr+4, 4, read, write); 903 if (hi == INVALID_NUB_HW_INDEX) 904 { 905 DisableHardwareWatchpoint(lo); 906 return INVALID_NUB_HW_INDEX; 907 } 908 // Tag this lo->hi mapping in our database. 909 LoHi[lo] = hi; 910 return lo; 911 } 912 913 // Otherwise, can't watch more than 4 bytes per WVR/WCR pair 914 if (size > 4) 915 return INVALID_NUB_HW_INDEX; 916 917 // We can only watch up to four bytes that follow a 4 byte aligned address 918 // per watchpoint register pair. Since we can only watch until the next 4 919 // byte boundary, we need to make sure we can properly encode this. 920 921 // addr_word_offset = addr % 4, i.e, is in set([0, 1, 2, 3]) 922 // 923 // +---+---+---+---+ 924 // | 0 | 1 | 2 | 3 | 925 // +---+---+---+---+ 926 // ^ 927 // | 928 // word address (4-byte aligned) = addr & 0xFFFFFFFC => goes into WVR 929 // 930 // examples: 931 // 1. addr_word_offset = 1, size = 1 to watch a uint_8 => byte_mask = (0b0001 << 1) = 0b0010 932 // 2. addr_word_offset = 2, size = 2 to watch a uint_16 => byte_mask = (0b0011 << 2) = 0b1100 933 // 934 // where byte_mask goes into WCR[8:5] 935 936 uint32_t addr_word_offset = addr % 4; 937 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset); 938 939 uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset; 940 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask); 941 if (byte_mask > 0xfu) 942 return INVALID_NUB_HW_INDEX; 943 944 // Read the debug state 945 kern_return_t kret = GetDBGState(false); 946 947 if (kret == KERN_SUCCESS) 948 { 949 // Check to make sure we have the needed hardware support 950 uint32_t i = 0; 951 952 for (i=0; i<num_hw_watchpoints; ++i) 953 { 954 if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0) 955 break; // We found an available hw watchpoint slot (in i) 956 } 957 958 // See if we found an available hw watchpoint slot above 959 if (i < num_hw_watchpoints) 960 { 961 //DumpDBGState(m_state.dbg); 962 963 // Make the byte_mask into a valid Byte Address Select mask 964 uint32_t byte_address_select = byte_mask << 5; 965 // Make sure bits 1:0 are clear in our address 966 m_state.dbg.__wvr[i] = addr & ~((nub_addr_t)3); // DVA (Data Virtual Address) 967 m_state.dbg.__wcr[i] = byte_address_select | // Which bytes that follow the DVA that we will watch 968 S_USER | // Stop only in user mode 969 (read ? WCR_LOAD : 0) | // Stop on read access? 970 (write ? WCR_STORE : 0) | // Stop on write access? 971 WCR_ENABLE; // Enable this watchpoint; 972 973 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() adding watchpoint on address 0x%llx with control register value 0x%x", (uint64_t) m_state.dbg.__wvr[i], (uint32_t) m_state.dbg.__wcr[i]); 974 975 kret = SetDBGState(); 976 //DumpDBGState(m_state.dbg); 977 978 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret); 979 980 if (kret == KERN_SUCCESS) 981 return i; 982 } 983 else 984 { 985 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); 986 } 987 } 988 return INVALID_NUB_HW_INDEX; 989} 990 991bool 992DNBArchMachARM::EnableHardwareWatchpoint0 (uint32_t hw_index, bool Delegate) 993{ 994 kern_return_t kret = GetDBGState(false); 995 if (kret != KERN_SUCCESS) 996 return false; 997 998 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); 999 if (hw_index >= num_hw_points) 1000 return false; 1001 1002 if (Delegate && LoHi[hw_index]) { 1003 // Enable lo and hi watchpoint hardware indexes. 1004 return EnableHardwareWatchpoint0(hw_index, false) && 1005 EnableHardwareWatchpoint0(LoHi[hw_index], false); 1006 } 1007 1008 m_state.dbg.__wcr[hw_index] |= (nub_addr_t)WCR_ENABLE; 1009 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x", 1010 hw_index, 1011 hw_index, 1012 m_state.dbg.__wvr[hw_index], 1013 hw_index, 1014 m_state.dbg.__wcr[hw_index]); 1015 1016 kret = SetDBGState(); 1017 1018 return (kret == KERN_SUCCESS); 1019} 1020 1021bool 1022DNBArchMachARM::DisableHardwareWatchpoint (uint32_t hw_index) 1023{ 1024 return DisableHardwareWatchpoint0(hw_index, true); 1025} 1026bool 1027DNBArchMachARM::DisableHardwareWatchpoint0 (uint32_t hw_index, bool Delegate) 1028{ 1029 kern_return_t kret = GetDBGState(false); 1030 if (kret != KERN_SUCCESS) 1031 return false; 1032 1033 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); 1034 if (hw_index >= num_hw_points) 1035 return false; 1036 1037 if (Delegate && LoHi[hw_index]) { 1038 // Disable lo and hi watchpoint hardware indexes. 1039 return DisableHardwareWatchpoint0(hw_index, false) && 1040 DisableHardwareWatchpoint0(LoHi[hw_index], false); 1041 } 1042 1043 m_state.dbg.__wcr[hw_index] &= ~((nub_addr_t)WCR_ENABLE); 1044 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::DisableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x", 1045 hw_index, 1046 hw_index, 1047 m_state.dbg.__wvr[hw_index], 1048 hw_index, 1049 m_state.dbg.__wcr[hw_index]); 1050 1051 kret = SetDBGState(); 1052 1053 return (kret == KERN_SUCCESS); 1054} 1055 1056// {0} -> __bvr[16], {0} -> __bcr[16], {0} --> __wvr[16], {0} -> __wcr{16} 1057DNBArchMachARM::DBG DNBArchMachARM::Global_Debug_State = {{0},{0},{0},{0}}; 1058bool DNBArchMachARM::Valid_Global_Debug_State = false; 1059 1060// Use this callback from MachThread, which in turn was called from MachThreadList, to update 1061// the global view of the hardware watchpoint state, so that when new thread comes along, they 1062// get to inherit the existing hardware watchpoint state. 1063void 1064DNBArchMachARM::HardwareWatchpointStateChanged () 1065{ 1066 Global_Debug_State = m_state.dbg; 1067 Valid_Global_Debug_State = true; 1068} 1069 1070// Returns -1 if the trailing bit patterns are not one of: 1071// { 0b???1, 0b??10, 0b?100, 0b1000 }. 1072static inline 1073int32_t 1074LowestBitSet(uint32_t val) 1075{ 1076 for (unsigned i = 0; i < 4; ++i) { 1077 if (bit(val, i)) 1078 return i; 1079 } 1080 return -1; 1081} 1082 1083// Iterate through the debug registers; return the index of the first watchpoint whose address matches. 1084// As a side effect, the starting address as understood by the debugger is returned which could be 1085// different from 'addr' passed as an in/out argument. 1086uint32_t 1087DNBArchMachARM::GetHardwareWatchpointHit(nub_addr_t &addr) 1088{ 1089 // Read the debug state 1090 kern_return_t kret = GetDBGState(true); 1091 //DumpDBGState(m_state.dbg); 1092 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret); 1093 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() addr = 0x%llx", (uint64_t)addr); 1094 1095 // This is the watchpoint value to match against, i.e., word address. 1096 nub_addr_t wp_val = addr & ~((nub_addr_t)3); 1097 if (kret == KERN_SUCCESS) 1098 { 1099 DBG &debug_state = m_state.dbg; 1100 uint32_t i, num = NumSupportedHardwareWatchpoints(); 1101 for (i = 0; i < num; ++i) 1102 { 1103 nub_addr_t wp_addr = GetWatchAddress(debug_state, i); 1104 DNBLogThreadedIf(LOG_WATCHPOINTS, 1105 "DNBArchMachARM::GetHardwareWatchpointHit() slot: %u (addr = 0x%llx).", 1106 i, (uint64_t)wp_addr); 1107 if (wp_val == wp_addr) { 1108 uint32_t byte_mask = bits(debug_state.__wcr[i], 8, 5); 1109 1110 // Sanity check the byte_mask, first. 1111 if (LowestBitSet(byte_mask) < 0) 1112 continue; 1113 1114 // Compute the starting address (from the point of view of the debugger). 1115 addr = wp_addr + LowestBitSet(byte_mask); 1116 return i; 1117 } 1118 } 1119 } 1120 return INVALID_NUB_HW_INDEX; 1121} 1122 1123// ThreadWillResume() calls this to clear bits[5:2] (Method of entry bits) of 1124// the Debug Status and Control Register (DSCR). 1125// 1126// b0010 = a watchpoint occurred 1127// b0000 is the reset value 1128void 1129DNBArchMachARM::ClearWatchpointOccurred() 1130{ 1131 uint32_t register_DBGDSCR; 1132 asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR)); 1133 if (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED) 1134 { 1135 uint32_t mask = ~(0xF << 2); 1136 register_DBGDSCR &= mask; 1137 asm("mcr p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR)); 1138 } 1139 return; 1140} 1141 1142// NotifyException() calls this to double check that a watchpoint has occurred 1143// by inspecting the bits[5:2] field of the Debug Status and Control Register 1144// (DSCR). 1145// 1146// b0010 = a watchpoint occurred 1147bool 1148DNBArchMachARM::HasWatchpointOccurred() 1149{ 1150 uint32_t register_DBGDSCR; 1151 asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR)); 1152 return (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED); 1153} 1154 1155bool 1156DNBArchMachARM::IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index) 1157{ 1158 // Watchpoint Control Registers, bitfield definitions 1159 // ... 1160 // Bits Value Description 1161 // [0] 0 Watchpoint disabled 1162 // 1 Watchpoint enabled. 1163 return (debug_state.__wcr[hw_index] & 1u); 1164} 1165 1166nub_addr_t 1167DNBArchMachARM::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) 1168{ 1169 // Watchpoint Value Registers, bitfield definitions 1170 // Bits Description 1171 // [31:2] Watchpoint value (word address, i.e., 4-byte aligned) 1172 // [1:0] RAZ/SBZP 1173 return bits(debug_state.__wvr[hw_index], 31, 0); 1174} 1175 1176//---------------------------------------------------------------------- 1177// Register information defintions for 32 bit ARMV7. 1178//---------------------------------------------------------------------- 1179enum gpr_regnums 1180{ 1181 gpr_r0 = 0, 1182 gpr_r1, 1183 gpr_r2, 1184 gpr_r3, 1185 gpr_r4, 1186 gpr_r5, 1187 gpr_r6, 1188 gpr_r7, 1189 gpr_r8, 1190 gpr_r9, 1191 gpr_r10, 1192 gpr_r11, 1193 gpr_r12, 1194 gpr_sp, 1195 gpr_lr, 1196 gpr_pc, 1197 gpr_cpsr 1198}; 1199 1200enum 1201{ 1202 vfp_s0 = 17, // match the g_gdb_register_map_arm table in RNBRemote.cpp 1203 vfp_s1, 1204 vfp_s2, 1205 vfp_s3, 1206 vfp_s4, 1207 vfp_s5, 1208 vfp_s6, 1209 vfp_s7, 1210 vfp_s8, 1211 vfp_s9, 1212 vfp_s10, 1213 vfp_s11, 1214 vfp_s12, 1215 vfp_s13, 1216 vfp_s14, 1217 vfp_s15, 1218 vfp_s16, 1219 vfp_s17, 1220 vfp_s18, 1221 vfp_s19, 1222 vfp_s20, 1223 vfp_s21, 1224 vfp_s22, 1225 vfp_s23, 1226 vfp_s24, 1227 vfp_s25, 1228 vfp_s26, 1229 vfp_s27, 1230 vfp_s28, 1231 vfp_s29, 1232 vfp_s30, 1233 vfp_s31 1234}; 1235 1236enum 1237{ 1238 vfp_d0 = 49, // match the g_gdb_register_map_arm table in RNBRemote.cpp 1239 vfp_d1, 1240 vfp_d2, 1241 vfp_d3, 1242 vfp_d4, 1243 vfp_d5, 1244 vfp_d6, 1245 vfp_d7, 1246 vfp_d8, 1247 vfp_d9, 1248 vfp_d10, 1249 vfp_d11, 1250 vfp_d12, 1251 vfp_d13, 1252 vfp_d14, 1253 vfp_d15, 1254 vfp_d16, 1255 vfp_d17, 1256 vfp_d18, 1257 vfp_d19, 1258 vfp_d20, 1259 vfp_d21, 1260 vfp_d22, 1261 vfp_d23, 1262 vfp_d24, 1263 vfp_d25, 1264 vfp_d26, 1265 vfp_d27, 1266 vfp_d28, 1267 vfp_d29, 1268 vfp_d30, 1269 vfp_d31 1270}; 1271 1272enum 1273{ 1274 vfp_q0 = 81, // match the g_gdb_register_map_arm table in RNBRemote.cpp 1275 vfp_q1, 1276 vfp_q2, 1277 vfp_q3, 1278 vfp_q4, 1279 vfp_q5, 1280 vfp_q6, 1281 vfp_q7, 1282 vfp_q8, 1283 vfp_q9, 1284 vfp_q10, 1285 vfp_q11, 1286 vfp_q12, 1287 vfp_q13, 1288 vfp_q14, 1289 vfp_q15, 1290 vfp_fpscr 1291}; 1292 1293enum 1294{ 1295 exc_exception, 1296 exc_fsr, 1297 exc_far, 1298}; 1299 1300#define GPR_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::GPR, __r[idx])) 1301#define GPR_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::GPR, __##reg)) 1302 1303#define EXC_OFFSET(reg) (offsetof (DNBArchMachARM::EXC, __##reg) + offsetof (DNBArchMachARM::Context, exc)) 1304 1305// These macros will auto define the register name, alt name, register size, 1306// register offset, encoding, format and native register. This ensures that 1307// the register state structures are defined correctly and have the correct 1308// sizes and offsets. 1309#define DEFINE_GPR_IDX(idx, reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_IDX(idx), gcc_##reg, dwarf_##reg, gen, INVALID_NUB_REGNUM, NULL, NULL} 1310#define DEFINE_GPR_NAME(reg, alt, gen, inval) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_NAME(reg), gcc_##reg, dwarf_##reg, gen, INVALID_NUB_REGNUM, NULL, inval} 1311 1312// In case we are debugging to a debug target that the ability to 1313// change into the protected modes with folded registers (ABT, IRQ, 1314// FIQ, SYS, USR, etc..), we should invalidate r8-r14 if the CPSR 1315// gets modified. 1316 1317uint32_t g_invalidate_cpsr[] = { 1318 gpr_r8, 1319 gpr_r9, 1320 gpr_r10, 1321 gpr_r11, 1322 gpr_r12, 1323 gpr_sp, 1324 gpr_lr, 1325 INVALID_NUB_REGNUM }; 1326 1327// General purpose registers 1328const DNBRegisterInfo 1329DNBArchMachARM::g_gpr_registers[] = 1330{ 1331 DEFINE_GPR_IDX ( 0, r0,"arg1", GENERIC_REGNUM_ARG1 ), 1332 DEFINE_GPR_IDX ( 1, r1,"arg2", GENERIC_REGNUM_ARG2 ), 1333 DEFINE_GPR_IDX ( 2, r2,"arg3", GENERIC_REGNUM_ARG3 ), 1334 DEFINE_GPR_IDX ( 3, r3,"arg4", GENERIC_REGNUM_ARG4 ), 1335 DEFINE_GPR_IDX ( 4, r4, NULL, INVALID_NUB_REGNUM ), 1336 DEFINE_GPR_IDX ( 5, r5, NULL, INVALID_NUB_REGNUM ), 1337 DEFINE_GPR_IDX ( 6, r6, NULL, INVALID_NUB_REGNUM ), 1338 DEFINE_GPR_IDX ( 7, r7, "fp", GENERIC_REGNUM_FP ), 1339 DEFINE_GPR_IDX ( 8, r8, NULL, INVALID_NUB_REGNUM ), 1340 DEFINE_GPR_IDX ( 9, r9, NULL, INVALID_NUB_REGNUM ), 1341 DEFINE_GPR_IDX (10, r10, NULL, INVALID_NUB_REGNUM ), 1342 DEFINE_GPR_IDX (11, r11, NULL, INVALID_NUB_REGNUM ), 1343 DEFINE_GPR_IDX (12, r12, NULL, INVALID_NUB_REGNUM ), 1344 DEFINE_GPR_NAME (sp, "r13", GENERIC_REGNUM_SP, NULL), 1345 DEFINE_GPR_NAME (lr, "r14", GENERIC_REGNUM_RA, NULL), 1346 DEFINE_GPR_NAME (pc, "r15", GENERIC_REGNUM_PC, NULL), 1347 DEFINE_GPR_NAME (cpsr, "flags", GENERIC_REGNUM_FLAGS, g_invalidate_cpsr) 1348}; 1349 1350uint32_t g_contained_q0[] {vfp_q0, INVALID_NUB_REGNUM }; 1351uint32_t g_contained_q1[] {vfp_q1, INVALID_NUB_REGNUM }; 1352uint32_t g_contained_q2[] {vfp_q2, INVALID_NUB_REGNUM }; 1353uint32_t g_contained_q3[] {vfp_q3, INVALID_NUB_REGNUM }; 1354uint32_t g_contained_q4[] {vfp_q4, INVALID_NUB_REGNUM }; 1355uint32_t g_contained_q5[] {vfp_q5, INVALID_NUB_REGNUM }; 1356uint32_t g_contained_q6[] {vfp_q6, INVALID_NUB_REGNUM }; 1357uint32_t g_contained_q7[] {vfp_q7, INVALID_NUB_REGNUM }; 1358uint32_t g_contained_q8[] {vfp_q8, INVALID_NUB_REGNUM }; 1359uint32_t g_contained_q9[] {vfp_q9, INVALID_NUB_REGNUM }; 1360uint32_t g_contained_q10[] {vfp_q10, INVALID_NUB_REGNUM }; 1361uint32_t g_contained_q11[] {vfp_q11, INVALID_NUB_REGNUM }; 1362uint32_t g_contained_q12[] {vfp_q12, INVALID_NUB_REGNUM }; 1363uint32_t g_contained_q13[] {vfp_q13, INVALID_NUB_REGNUM }; 1364uint32_t g_contained_q14[] {vfp_q14, INVALID_NUB_REGNUM }; 1365uint32_t g_contained_q15[] {vfp_q15, INVALID_NUB_REGNUM }; 1366 1367uint32_t g_invalidate_q0[] {vfp_q0, vfp_d0, vfp_d1, vfp_s0, vfp_s1, vfp_s2, vfp_s3, INVALID_NUB_REGNUM }; 1368uint32_t g_invalidate_q1[] {vfp_q1, vfp_d2, vfp_d3, vfp_s4, vfp_s5, vfp_s6, vfp_s7, INVALID_NUB_REGNUM }; 1369uint32_t g_invalidate_q2[] {vfp_q2, vfp_d4, vfp_d5, vfp_s8, vfp_s9, vfp_s10, vfp_s11, INVALID_NUB_REGNUM }; 1370uint32_t g_invalidate_q3[] {vfp_q3, vfp_d6, vfp_d7, vfp_s12, vfp_s13, vfp_s14, vfp_s15, INVALID_NUB_REGNUM }; 1371uint32_t g_invalidate_q4[] {vfp_q4, vfp_d8, vfp_d9, vfp_s16, vfp_s17, vfp_s18, vfp_s19, INVALID_NUB_REGNUM }; 1372uint32_t g_invalidate_q5[] {vfp_q5, vfp_d10, vfp_d11, vfp_s20, vfp_s21, vfp_s22, vfp_s23, INVALID_NUB_REGNUM }; 1373uint32_t g_invalidate_q6[] {vfp_q6, vfp_d12, vfp_d13, vfp_s24, vfp_s25, vfp_s26, vfp_s27, INVALID_NUB_REGNUM }; 1374uint32_t g_invalidate_q7[] {vfp_q7, vfp_d14, vfp_d15, vfp_s28, vfp_s29, vfp_s30, vfp_s31, INVALID_NUB_REGNUM }; 1375uint32_t g_invalidate_q8[] {vfp_q8, vfp_d16, vfp_d17, INVALID_NUB_REGNUM }; 1376uint32_t g_invalidate_q9[] {vfp_q9, vfp_d18, vfp_d19, INVALID_NUB_REGNUM }; 1377uint32_t g_invalidate_q10[] {vfp_q10, vfp_d20, vfp_d21, INVALID_NUB_REGNUM }; 1378uint32_t g_invalidate_q11[] {vfp_q11, vfp_d22, vfp_d23, INVALID_NUB_REGNUM }; 1379uint32_t g_invalidate_q12[] {vfp_q12, vfp_d24, vfp_d25, INVALID_NUB_REGNUM }; 1380uint32_t g_invalidate_q13[] {vfp_q13, vfp_d26, vfp_d27, INVALID_NUB_REGNUM }; 1381uint32_t g_invalidate_q14[] {vfp_q14, vfp_d28, vfp_d29, INVALID_NUB_REGNUM }; 1382uint32_t g_invalidate_q15[] {vfp_q15, vfp_d30, vfp_d31, INVALID_NUB_REGNUM }; 1383 1384#define VFP_S_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::FPU, __r[(idx)]) + offsetof (DNBArchMachARM::Context, vfp)) 1385#define VFP_D_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX ((idx) * 2)) 1386#define VFP_Q_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX ((idx) * 4)) 1387 1388#define VFP_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::FPU, __##reg) + offsetof (DNBArchMachARM::Context, vfp)) 1389 1390#define FLOAT_FORMAT Float 1391 1392#define DEFINE_VFP_S_IDX(idx) e_regSetVFP, vfp_s##idx - vfp_s0, "s" #idx, NULL, IEEE754, FLOAT_FORMAT, 4, VFP_S_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM 1393#define DEFINE_VFP_D_IDX(idx) e_regSetVFP, vfp_d##idx - vfp_s0, "d" #idx, NULL, IEEE754, FLOAT_FORMAT, 8, VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_d##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM 1394#define DEFINE_VFP_Q_IDX(idx) e_regSetVFP, vfp_q##idx - vfp_s0, "q" #idx, NULL, Vector, VectorOfUInt8, 16, VFP_Q_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_q##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM 1395 1396// Floating point registers 1397const DNBRegisterInfo 1398DNBArchMachARM::g_vfp_registers[] = 1399{ 1400 { DEFINE_VFP_S_IDX ( 0), g_contained_q0, g_invalidate_q0 }, 1401 { DEFINE_VFP_S_IDX ( 1), g_contained_q0, g_invalidate_q0 }, 1402 { DEFINE_VFP_S_IDX ( 2), g_contained_q0, g_invalidate_q0 }, 1403 { DEFINE_VFP_S_IDX ( 3), g_contained_q0, g_invalidate_q0 }, 1404 { DEFINE_VFP_S_IDX ( 4), g_contained_q1, g_invalidate_q1 }, 1405 { DEFINE_VFP_S_IDX ( 5), g_contained_q1, g_invalidate_q1 }, 1406 { DEFINE_VFP_S_IDX ( 6), g_contained_q1, g_invalidate_q1 }, 1407 { DEFINE_VFP_S_IDX ( 7), g_contained_q1, g_invalidate_q1 }, 1408 { DEFINE_VFP_S_IDX ( 8), g_contained_q2, g_invalidate_q2 }, 1409 { DEFINE_VFP_S_IDX ( 9), g_contained_q2, g_invalidate_q2 }, 1410 { DEFINE_VFP_S_IDX (10), g_contained_q2, g_invalidate_q2 }, 1411 { DEFINE_VFP_S_IDX (11), g_contained_q2, g_invalidate_q2 }, 1412 { DEFINE_VFP_S_IDX (12), g_contained_q3, g_invalidate_q3 }, 1413 { DEFINE_VFP_S_IDX (13), g_contained_q3, g_invalidate_q3 }, 1414 { DEFINE_VFP_S_IDX (14), g_contained_q3, g_invalidate_q3 }, 1415 { DEFINE_VFP_S_IDX (15), g_contained_q3, g_invalidate_q3 }, 1416 { DEFINE_VFP_S_IDX (16), g_contained_q4, g_invalidate_q4 }, 1417 { DEFINE_VFP_S_IDX (17), g_contained_q4, g_invalidate_q4 }, 1418 { DEFINE_VFP_S_IDX (18), g_contained_q4, g_invalidate_q4 }, 1419 { DEFINE_VFP_S_IDX (19), g_contained_q4, g_invalidate_q4 }, 1420 { DEFINE_VFP_S_IDX (20), g_contained_q5, g_invalidate_q5 }, 1421 { DEFINE_VFP_S_IDX (21), g_contained_q5, g_invalidate_q5 }, 1422 { DEFINE_VFP_S_IDX (22), g_contained_q5, g_invalidate_q5 }, 1423 { DEFINE_VFP_S_IDX (23), g_contained_q5, g_invalidate_q5 }, 1424 { DEFINE_VFP_S_IDX (24), g_contained_q6, g_invalidate_q6 }, 1425 { DEFINE_VFP_S_IDX (25), g_contained_q6, g_invalidate_q6 }, 1426 { DEFINE_VFP_S_IDX (26), g_contained_q6, g_invalidate_q6 }, 1427 { DEFINE_VFP_S_IDX (27), g_contained_q6, g_invalidate_q6 }, 1428 { DEFINE_VFP_S_IDX (28), g_contained_q7, g_invalidate_q7 }, 1429 { DEFINE_VFP_S_IDX (29), g_contained_q7, g_invalidate_q7 }, 1430 { DEFINE_VFP_S_IDX (30), g_contained_q7, g_invalidate_q7 }, 1431 { DEFINE_VFP_S_IDX (31), g_contained_q7, g_invalidate_q7 }, 1432 1433 { DEFINE_VFP_D_IDX (0), g_contained_q0, g_invalidate_q0 }, 1434 { DEFINE_VFP_D_IDX (1), g_contained_q0, g_invalidate_q0 }, 1435 { DEFINE_VFP_D_IDX (2), g_contained_q1, g_invalidate_q1 }, 1436 { DEFINE_VFP_D_IDX (3), g_contained_q1, g_invalidate_q1 }, 1437 { DEFINE_VFP_D_IDX (4), g_contained_q2, g_invalidate_q2 }, 1438 { DEFINE_VFP_D_IDX (5), g_contained_q2, g_invalidate_q2 }, 1439 { DEFINE_VFP_D_IDX (6), g_contained_q3, g_invalidate_q3 }, 1440 { DEFINE_VFP_D_IDX (7), g_contained_q3, g_invalidate_q3 }, 1441 { DEFINE_VFP_D_IDX (8), g_contained_q4, g_invalidate_q4 }, 1442 { DEFINE_VFP_D_IDX (9), g_contained_q4, g_invalidate_q4 }, 1443 { DEFINE_VFP_D_IDX (10), g_contained_q5, g_invalidate_q5 }, 1444 { DEFINE_VFP_D_IDX (11), g_contained_q5, g_invalidate_q5 }, 1445 { DEFINE_VFP_D_IDX (12), g_contained_q6, g_invalidate_q6 }, 1446 { DEFINE_VFP_D_IDX (13), g_contained_q6, g_invalidate_q6 }, 1447 { DEFINE_VFP_D_IDX (14), g_contained_q7, g_invalidate_q7 }, 1448 { DEFINE_VFP_D_IDX (15), g_contained_q7, g_invalidate_q7 }, 1449 { DEFINE_VFP_D_IDX (16), g_contained_q8, g_invalidate_q8 }, 1450 { DEFINE_VFP_D_IDX (17), g_contained_q8, g_invalidate_q8 }, 1451 { DEFINE_VFP_D_IDX (18), g_contained_q9, g_invalidate_q9 }, 1452 { DEFINE_VFP_D_IDX (19), g_contained_q9, g_invalidate_q9 }, 1453 { DEFINE_VFP_D_IDX (20), g_contained_q10, g_invalidate_q10 }, 1454 { DEFINE_VFP_D_IDX (21), g_contained_q10, g_invalidate_q10 }, 1455 { DEFINE_VFP_D_IDX (22), g_contained_q11, g_invalidate_q11 }, 1456 { DEFINE_VFP_D_IDX (23), g_contained_q11, g_invalidate_q11 }, 1457 { DEFINE_VFP_D_IDX (24), g_contained_q12, g_invalidate_q12 }, 1458 { DEFINE_VFP_D_IDX (25), g_contained_q12, g_invalidate_q12 }, 1459 { DEFINE_VFP_D_IDX (26), g_contained_q13, g_invalidate_q13 }, 1460 { DEFINE_VFP_D_IDX (27), g_contained_q13, g_invalidate_q13 }, 1461 { DEFINE_VFP_D_IDX (28), g_contained_q14, g_invalidate_q14 }, 1462 { DEFINE_VFP_D_IDX (29), g_contained_q14, g_invalidate_q14 }, 1463 { DEFINE_VFP_D_IDX (30), g_contained_q15, g_invalidate_q15 }, 1464 { DEFINE_VFP_D_IDX (31), g_contained_q15, g_invalidate_q15 }, 1465 1466 { DEFINE_VFP_Q_IDX (0), NULL, g_invalidate_q0 }, 1467 { DEFINE_VFP_Q_IDX (1), NULL, g_invalidate_q1 }, 1468 { DEFINE_VFP_Q_IDX (2), NULL, g_invalidate_q2 }, 1469 { DEFINE_VFP_Q_IDX (3), NULL, g_invalidate_q3 }, 1470 { DEFINE_VFP_Q_IDX (4), NULL, g_invalidate_q4 }, 1471 { DEFINE_VFP_Q_IDX (5), NULL, g_invalidate_q5 }, 1472 { DEFINE_VFP_Q_IDX (6), NULL, g_invalidate_q6 }, 1473 { DEFINE_VFP_Q_IDX (7), NULL, g_invalidate_q7 }, 1474 { DEFINE_VFP_Q_IDX (8), NULL, g_invalidate_q8 }, 1475 { DEFINE_VFP_Q_IDX (9), NULL, g_invalidate_q9 }, 1476 { DEFINE_VFP_Q_IDX (10), NULL, g_invalidate_q10 }, 1477 { DEFINE_VFP_Q_IDX (11), NULL, g_invalidate_q11 }, 1478 { DEFINE_VFP_Q_IDX (12), NULL, g_invalidate_q12 }, 1479 { DEFINE_VFP_Q_IDX (13), NULL, g_invalidate_q13 }, 1480 { DEFINE_VFP_Q_IDX (14), NULL, g_invalidate_q14 }, 1481 { DEFINE_VFP_Q_IDX (15), NULL, g_invalidate_q15 }, 1482 1483 { e_regSetVFP, vfp_fpscr, "fpscr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpscr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL } 1484}; 1485 1486// Exception registers 1487 1488const DNBRegisterInfo 1489DNBArchMachARM::g_exc_registers[] = 1490{ 1491 { e_regSetVFP, exc_exception , "exception" , NULL, Uint, Hex, 4, EXC_OFFSET(exception) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }, 1492 { e_regSetVFP, exc_fsr , "fsr" , NULL, Uint, Hex, 4, EXC_OFFSET(fsr) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }, 1493 { e_regSetVFP, exc_far , "far" , NULL, Uint, Hex, 4, EXC_OFFSET(far) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM } 1494}; 1495 1496// Number of registers in each register set 1497const size_t DNBArchMachARM::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); 1498const size_t DNBArchMachARM::k_num_vfp_registers = sizeof(g_vfp_registers)/sizeof(DNBRegisterInfo); 1499const size_t DNBArchMachARM::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); 1500const size_t DNBArchMachARM::k_num_all_registers = k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers; 1501 1502//---------------------------------------------------------------------- 1503// Register set definitions. The first definitions at register set index 1504// of zero is for all registers, followed by other registers sets. The 1505// register information for the all register set need not be filled in. 1506//---------------------------------------------------------------------- 1507const DNBRegisterSetInfo 1508DNBArchMachARM::g_reg_sets[] = 1509{ 1510 { "ARM Registers", NULL, k_num_all_registers }, 1511 { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, 1512 { "Floating Point Registers", g_vfp_registers, k_num_vfp_registers }, 1513 { "Exception State Registers", g_exc_registers, k_num_exc_registers } 1514}; 1515// Total number of register sets for this architecture 1516const size_t DNBArchMachARM::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); 1517 1518 1519const DNBRegisterSetInfo * 1520DNBArchMachARM::GetRegisterSetInfo(nub_size_t *num_reg_sets) 1521{ 1522 *num_reg_sets = k_num_register_sets; 1523 return g_reg_sets; 1524} 1525 1526bool 1527DNBArchMachARM::GetRegisterValue(int set, int reg, DNBRegisterValue *value) 1528{ 1529 if (set == REGISTER_SET_GENERIC) 1530 { 1531 switch (reg) 1532 { 1533 case GENERIC_REGNUM_PC: // Program Counter 1534 set = e_regSetGPR; 1535 reg = gpr_pc; 1536 break; 1537 1538 case GENERIC_REGNUM_SP: // Stack Pointer 1539 set = e_regSetGPR; 1540 reg = gpr_sp; 1541 break; 1542 1543 case GENERIC_REGNUM_FP: // Frame Pointer 1544 set = e_regSetGPR; 1545 reg = gpr_r7; // is this the right reg? 1546 break; 1547 1548 case GENERIC_REGNUM_RA: // Return Address 1549 set = e_regSetGPR; 1550 reg = gpr_lr; 1551 break; 1552 1553 case GENERIC_REGNUM_FLAGS: // Processor flags register 1554 set = e_regSetGPR; 1555 reg = gpr_cpsr; 1556 break; 1557 1558 default: 1559 return false; 1560 } 1561 } 1562 1563 if (GetRegisterState(set, false) != KERN_SUCCESS) 1564 return false; 1565 1566 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 1567 if (regInfo) 1568 { 1569 value->info = *regInfo; 1570 switch (set) 1571 { 1572 case e_regSetGPR: 1573 if (reg < k_num_gpr_registers) 1574 { 1575 value->value.uint32 = m_state.context.gpr.__r[reg]; 1576 return true; 1577 } 1578 break; 1579 1580 case e_regSetVFP: 1581 // "reg" is an index into the floating point register set at this point. 1582 // We need to translate it up so entry 0 in the fp reg set is the same as vfp_s0 1583 // in the enumerated values for case statement below. 1584 reg += vfp_s0; 1585 if (reg >= vfp_s0 && reg <= vfp_s31) 1586 { 1587 value->value.uint32 = m_state.context.vfp.__r[reg - vfp_s0]; 1588 return true; 1589 } 1590 else if (reg >= vfp_d0 && reg <= vfp_d31) 1591 { 1592 uint32_t d_reg_idx = reg - vfp_d0; 1593 uint32_t s_reg_idx = d_reg_idx * 2; 1594 value->value.v_sint32[0] = m_state.context.vfp.__r[s_reg_idx + 0]; 1595 value->value.v_sint32[1] = m_state.context.vfp.__r[s_reg_idx + 1]; 1596 return true; 1597 } 1598 else if (reg >= vfp_q0 && reg <= vfp_q15) 1599 { 1600 uint32_t s_reg_idx = (reg - vfp_q0) * 4; 1601 memcpy (&value->value.v_uint8, (uint8_t *) &m_state.context.vfp.__r[s_reg_idx], 16); 1602 return true; 1603 } 1604 1605 else if (reg == vfp_fpscr) 1606 { 1607 value->value.uint32 = m_state.context.vfp.__fpscr; 1608 return true; 1609 } 1610 break; 1611 1612 case e_regSetEXC: 1613 if (reg < k_num_exc_registers) 1614 { 1615 value->value.uint32 = (&m_state.context.exc.__exception)[reg]; 1616 return true; 1617 } 1618 break; 1619 } 1620 } 1621 return false; 1622} 1623 1624bool 1625DNBArchMachARM::SetRegisterValue(int set, int reg, const DNBRegisterValue *value) 1626{ 1627 if (set == REGISTER_SET_GENERIC) 1628 { 1629 switch (reg) 1630 { 1631 case GENERIC_REGNUM_PC: // Program Counter 1632 set = e_regSetGPR; 1633 reg = gpr_pc; 1634 break; 1635 1636 case GENERIC_REGNUM_SP: // Stack Pointer 1637 set = e_regSetGPR; 1638 reg = gpr_sp; 1639 break; 1640 1641 case GENERIC_REGNUM_FP: // Frame Pointer 1642 set = e_regSetGPR; 1643 reg = gpr_r7; 1644 break; 1645 1646 case GENERIC_REGNUM_RA: // Return Address 1647 set = e_regSetGPR; 1648 reg = gpr_lr; 1649 break; 1650 1651 case GENERIC_REGNUM_FLAGS: // Processor flags register 1652 set = e_regSetGPR; 1653 reg = gpr_cpsr; 1654 break; 1655 1656 default: 1657 return false; 1658 } 1659 } 1660 1661 if (GetRegisterState(set, false) != KERN_SUCCESS) 1662 return false; 1663 1664 bool success = false; 1665 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 1666 if (regInfo) 1667 { 1668 switch (set) 1669 { 1670 case e_regSetGPR: 1671 if (reg < k_num_gpr_registers) 1672 { 1673 m_state.context.gpr.__r[reg] = value->value.uint32; 1674 success = true; 1675 } 1676 break; 1677 1678 case e_regSetVFP: 1679 // "reg" is an index into the floating point register set at this point. 1680 // We need to translate it up so entry 0 in the fp reg set is the same as vfp_s0 1681 // in the enumerated values for case statement below. 1682 reg += vfp_s0; 1683 1684 if (reg >= vfp_s0 && reg <= vfp_s31) 1685 { 1686 m_state.context.vfp.__r[reg - vfp_s0] = value->value.uint32; 1687 success = true; 1688 } 1689 else if (reg >= vfp_d0 && reg <= vfp_d31) 1690 { 1691 uint32_t d_reg_idx = reg - vfp_d0; 1692 uint32_t s_reg_idx = d_reg_idx * 2; 1693 m_state.context.vfp.__r[s_reg_idx + 0] = value->value.v_sint32[0]; 1694 m_state.context.vfp.__r[s_reg_idx + 1] = value->value.v_sint32[1]; 1695 success = true; 1696 } 1697 else if (reg >= vfp_q0 && reg <= vfp_q15) 1698 { 1699 uint32_t s_reg_idx = (reg - vfp_q0) * 4; 1700 memcpy ((uint8_t *) &m_state.context.vfp.__r[s_reg_idx], &value->value.v_uint8, 16); 1701 return true; 1702 } 1703 else if (reg == vfp_fpscr) 1704 { 1705 m_state.context.vfp.__fpscr = value->value.uint32; 1706 success = true; 1707 } 1708 break; 1709 1710 case e_regSetEXC: 1711 if (reg < k_num_exc_registers) 1712 { 1713 (&m_state.context.exc.__exception)[reg] = value->value.uint32; 1714 success = true; 1715 } 1716 break; 1717 } 1718 1719 } 1720 if (success) 1721 return SetRegisterState(set) == KERN_SUCCESS; 1722 return false; 1723} 1724 1725kern_return_t 1726DNBArchMachARM::GetRegisterState(int set, bool force) 1727{ 1728 switch (set) 1729 { 1730 case e_regSetALL: return GetGPRState(force) | 1731 GetVFPState(force) | 1732 GetEXCState(force) | 1733 GetDBGState(force); 1734 case e_regSetGPR: return GetGPRState(force); 1735 case e_regSetVFP: return GetVFPState(force); 1736 case e_regSetEXC: return GetEXCState(force); 1737 case e_regSetDBG: return GetDBGState(force); 1738 default: break; 1739 } 1740 return KERN_INVALID_ARGUMENT; 1741} 1742 1743kern_return_t 1744DNBArchMachARM::SetRegisterState(int set) 1745{ 1746 // Make sure we have a valid context to set. 1747 kern_return_t err = GetRegisterState(set, false); 1748 if (err != KERN_SUCCESS) 1749 return err; 1750 1751 switch (set) 1752 { 1753 case e_regSetALL: return SetGPRState() | 1754 SetVFPState() | 1755 SetEXCState() | 1756 SetDBGState(); 1757 case e_regSetGPR: return SetGPRState(); 1758 case e_regSetVFP: return SetVFPState(); 1759 case e_regSetEXC: return SetEXCState(); 1760 case e_regSetDBG: return SetDBGState(); 1761 default: break; 1762 } 1763 return KERN_INVALID_ARGUMENT; 1764} 1765 1766bool 1767DNBArchMachARM::RegisterSetStateIsValid (int set) const 1768{ 1769 return m_state.RegsAreValid(set); 1770} 1771 1772 1773nub_size_t 1774DNBArchMachARM::GetRegisterContext (void *buf, nub_size_t buf_len) 1775{ 1776 nub_size_t size = sizeof (m_state.context); 1777 1778 if (buf && buf_len) 1779 { 1780 if (size > buf_len) 1781 size = buf_len; 1782 1783 bool force = false; 1784 if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force)) 1785 return 0; 1786 ::memcpy (buf, &m_state.context, size); 1787 } 1788 DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::GetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size); 1789 // Return the size of the register context even if NULL was passed in 1790 return size; 1791} 1792 1793nub_size_t 1794DNBArchMachARM::SetRegisterContext (const void *buf, nub_size_t buf_len) 1795{ 1796 nub_size_t size = sizeof (m_state.context); 1797 if (buf == NULL || buf_len == 0) 1798 size = 0; 1799 1800 if (size) 1801 { 1802 if (size > buf_len) 1803 size = buf_len; 1804 1805 ::memcpy (&m_state.context, buf, size); 1806 SetGPRState(); 1807 SetVFPState(); 1808 SetEXCState(); 1809 } 1810 DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size); 1811 return size; 1812} 1813 1814 1815#endif // #if defined (__arm__) 1816 1817