DNBArchImpl.cpp revision b649f7f34951e7495b33dbb4c2e240866941bb37
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 // Are we software single stepping? 426 if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_break_id) || m_sw_single_step_itblock_break_count) 427 { 428 // Remove any software single stepping breakpoints that we have set 429 430 // Do we have a normal software single step breakpoint? 431 if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_break_id)) 432 { 433 DNBLogThreadedIf(LOG_STEP, "%s: removing software single step breakpoint (breakID=%d)", __FUNCTION__, m_sw_single_step_break_id); 434 success = m_thread->Process()->DisableBreakpoint(m_sw_single_step_break_id, true); 435 m_sw_single_step_break_id = INVALID_NUB_BREAK_ID; 436 } 437 438 // Do we have any Thumb IT breakpoints? 439 if (m_sw_single_step_itblock_break_count > 0) 440 { 441 // See if we hit one of our Thumb IT breakpoints? 442 DNBBreakpoint *step_bp = m_thread->Process()->Breakpoints().FindByAddress(m_state.context.gpr.__pc); 443 444 if (step_bp) 445 { 446 // We did hit our breakpoint, tell the breakpoint it was 447 // hit so that it can run its callback routine and fixup 448 // the PC. 449 DNBLogThreadedIf(LOG_STEP, "%s: IT software single step breakpoint hit (breakID=%u)", __FUNCTION__, step_bp->GetID()); 450 step_bp->BreakpointHit(m_thread->Process()->ProcessID(), m_thread->ThreadID()); 451 } 452 453 // Remove all Thumb IT breakpoints 454 for (int i = 0; i < m_sw_single_step_itblock_break_count; i++) 455 { 456 if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i])) 457 { 458 DNBLogThreadedIf(LOG_STEP, "%s: removing IT software single step breakpoint (breakID=%d)", __FUNCTION__, m_sw_single_step_itblock_break_id[i]); 459 success = m_thread->Process()->DisableBreakpoint(m_sw_single_step_itblock_break_id[i], true); 460 m_sw_single_step_itblock_break_id[i] = INVALID_NUB_BREAK_ID; 461 } 462 } 463 m_sw_single_step_itblock_break_count = 0; 464 465 } 466 467 } 468 else 469 success = EnableHardwareSingleStep(false) == KERN_SUCCESS; 470 } 471 else 472 { 473 // The MachThread will automatically restore the suspend count 474 // in ThreadDidStop(), so we don't need to do anything here if 475 // we weren't the primary thread the last time 476 } 477 } 478 return success; 479} 480 481bool 482DNBArchMachARM::NotifyException(MachException::Data& exc) 483{ 484 switch (exc.exc_type) 485 { 486 default: 487 break; 488 case EXC_BREAKPOINT: 489 if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG) 490 { 491 // exc_code = EXC_ARM_DA_DEBUG 492 // 493 // Check whether this corresponds to a watchpoint hit event. 494 // If yes, retrieve the exc_sub_code as the data break address. 495 if (!HasWatchpointOccurred()) 496 break; 497 498 // The data break address is passed as exc_data[1]. 499 nub_addr_t addr = exc.exc_data[1]; 500 // Find the hardware index with the side effect of possibly massaging the 501 // addr to return the starting address as seen from the debugger side. 502 uint32_t hw_index = GetHardwareWatchpointHit(addr); 503 if (hw_index != INVALID_NUB_HW_INDEX) 504 { 505 m_watchpoint_did_occur = true; 506 m_watchpoint_hw_index = hw_index; 507 exc.exc_data[1] = addr; 508 // Piggyback the hw_index in the exc.data. 509 exc.exc_data.push_back(hw_index); 510 } 511 512 return true; 513 } 514 break; 515 } 516 return false; 517} 518 519bool 520DNBArchMachARM::StepNotComplete () 521{ 522 if (m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS) 523 { 524 kern_return_t kret = KERN_INVALID_ARGUMENT; 525 kret = GetGPRState(false); 526 if (kret == KERN_SUCCESS) 527 { 528 if (m_state.context.gpr.__pc == m_hw_single_chained_step_addr) 529 { 530 DNBLogThreadedIf(LOG_STEP, "Need to step some more at 0x%8.8x", m_hw_single_chained_step_addr); 531 return true; 532 } 533 } 534 } 535 536 m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; 537 return false; 538} 539 540 541// Set the single step bit in the processor status register. 542kern_return_t 543DNBArchMachARM::EnableHardwareSingleStep (bool enable) 544{ 545 DNBError err; 546 DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable); 547 548 err = GetGPRState(false); 549 550 if (err.Fail()) 551 { 552 err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__); 553 return err.Error(); 554 } 555 556 err = GetDBGState(false); 557 558 if (err.Fail()) 559 { 560 err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__); 561 return err.Error(); 562 } 563 564 const uint32_t i = 0; 565 if (enable) 566 { 567 m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; 568 569 // Save our previous state 570 m_dbg_save = m_state.dbg; 571 // Set a breakpoint that will stop when the PC doesn't match the current one! 572 m_state.dbg.__bvr[i] = m_state.context.gpr.__pc & 0xFFFFFFFCu; // Set the current PC as the breakpoint address 573 m_state.dbg.__bcr[i] = BCR_M_IMVA_MISMATCH | // Stop on address mismatch 574 S_USER | // Stop only in user mode 575 BCR_ENABLE; // Enable this breakpoint 576 if (m_state.context.gpr.__cpsr & 0x20) 577 { 578 // Thumb breakpoint 579 if (m_state.context.gpr.__pc & 2) 580 m_state.dbg.__bcr[i] |= BAS_IMVA_2_3; 581 else 582 m_state.dbg.__bcr[i] |= BAS_IMVA_0_1; 583 584 uint16_t opcode; 585 if (sizeof(opcode) == m_thread->Process()->Task().ReadMemory(m_state.context.gpr.__pc, sizeof(opcode), &opcode)) 586 { 587 if (((opcode & 0xE000) == 0xE000) && opcode & 0x1800) 588 { 589 // 32 bit thumb opcode... 590 if (m_state.context.gpr.__pc & 2) 591 { 592 // We can't take care of a 32 bit thumb instruction single step 593 // with just IVA mismatching. We will need to chain an extra 594 // hardware single step in order to complete this single step... 595 m_hw_single_chained_step_addr = m_state.context.gpr.__pc + 2; 596 } 597 else 598 { 599 // Extend the number of bits to ignore for the mismatch 600 m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; 601 } 602 } 603 } 604 } 605 else 606 { 607 // ARM breakpoint 608 m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; // Stop when any address bits change 609 } 610 611 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]); 612 613 for (uint32_t j=i+1; j<16; ++j) 614 { 615 // Disable all others 616 m_state.dbg.__bvr[j] = 0; 617 m_state.dbg.__bcr[j] = 0; 618 } 619 } 620 else 621 { 622 // Just restore the state we had before we did single stepping 623 m_state.dbg = m_dbg_save; 624 } 625 626 return SetDBGState(); 627} 628 629// return 1 if bit "BIT" is set in "value" 630static inline uint32_t bit(uint32_t value, uint32_t bit) 631{ 632 return (value >> bit) & 1u; 633} 634 635// return the bitfield "value[msbit:lsbit]". 636static inline uint32_t bits(uint32_t value, uint32_t msbit, uint32_t lsbit) 637{ 638 assert(msbit >= lsbit); 639 uint32_t shift_left = sizeof(value) * 8 - 1 - msbit; 640 value <<= shift_left; // shift anything above the msbit off of the unsigned edge 641 value >>= (shift_left + lsbit); // shift it back again down to the lsbit (including undoing any shift from above) 642 return value; // return our result 643} 644 645bool 646DNBArchMachARM::ConditionPassed(uint8_t condition, uint32_t cpsr) 647{ 648 uint32_t cpsr_n = bit(cpsr, 31); // Negative condition code flag 649 uint32_t cpsr_z = bit(cpsr, 30); // Zero condition code flag 650 uint32_t cpsr_c = bit(cpsr, 29); // Carry condition code flag 651 uint32_t cpsr_v = bit(cpsr, 28); // Overflow condition code flag 652 653 switch (condition) { 654 case COND_EQ: // (0x0) 655 if (cpsr_z == 1) return true; 656 break; 657 case COND_NE: // (0x1) 658 if (cpsr_z == 0) return true; 659 break; 660 case COND_CS: // (0x2) 661 if (cpsr_c == 1) return true; 662 break; 663 case COND_CC: // (0x3) 664 if (cpsr_c == 0) return true; 665 break; 666 case COND_MI: // (0x4) 667 if (cpsr_n == 1) return true; 668 break; 669 case COND_PL: // (0x5) 670 if (cpsr_n == 0) return true; 671 break; 672 case COND_VS: // (0x6) 673 if (cpsr_v == 1) return true; 674 break; 675 case COND_VC: // (0x7) 676 if (cpsr_v == 0) return true; 677 break; 678 case COND_HI: // (0x8) 679 if ((cpsr_c == 1) && (cpsr_z == 0)) return true; 680 break; 681 case COND_LS: // (0x9) 682 if ((cpsr_c == 0) || (cpsr_z == 1)) return true; 683 break; 684 case COND_GE: // (0xA) 685 if (cpsr_n == cpsr_v) return true; 686 break; 687 case COND_LT: // (0xB) 688 if (cpsr_n != cpsr_v) return true; 689 break; 690 case COND_GT: // (0xC) 691 if ((cpsr_z == 0) && (cpsr_n == cpsr_v)) return true; 692 break; 693 case COND_LE: // (0xD) 694 if ((cpsr_z == 1) || (cpsr_n != cpsr_v)) return true; 695 break; 696 default: 697 return true; 698 break; 699 } 700 701 return false; 702} 703 704nub_bool_t 705DNBArchMachARM::BreakpointHit (nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *baton) 706{ 707 nub_addr_t bkpt_pc = (nub_addr_t)baton; 708 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s(pid = %i, tid = %4.4x, breakID = %u, baton = %p): Setting PC to 0x%8.8x", __FUNCTION__, pid, tid, breakID, baton, bkpt_pc); 709 710 DNBRegisterValue pc_value; 711 DNBThreadGetRegisterValueByID (pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_PC, &pc_value); 712 pc_value.value.uint32 = bkpt_pc; 713 return DNBThreadSetRegisterValueByID (pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_PC, &pc_value); 714} 715 716uint32_t 717DNBArchMachARM::NumSupportedHardwareBreakpoints() 718{ 719 // Set the init value to something that will let us know that we need to 720 // autodetect how many breakpoints are supported dynamically... 721 static uint32_t g_num_supported_hw_breakpoints = UINT_MAX; 722 if (g_num_supported_hw_breakpoints == UINT_MAX) 723 { 724 // Set this to zero in case we can't tell if there are any HW breakpoints 725 g_num_supported_hw_breakpoints = 0; 726 727 size_t len; 728 uint32_t n = 0; 729 len = sizeof (n); 730 if (::sysctlbyname("hw.optional.breakpoint", &n, &len, NULL, 0) == 0) 731 { 732 g_num_supported_hw_breakpoints = n; 733 DNBLogThreadedIf(LOG_THREAD, "hw.optional.breakpoint=%u", n); 734 } 735 else 736 { 737 // Read the DBGDIDR to get the number of available hardware breakpoints 738 // However, in some of our current armv7 processors, hardware 739 // breakpoints/watchpoints were not properly connected. So detect those 740 // cases using a field in a sysctl. For now we are using "hw.cpusubtype" 741 // field to distinguish CPU architectures. This is a hack until we can 742 // get <rdar://problem/6372672> fixed, at which point we will switch to 743 // using a different sysctl string that will tell us how many BRPs 744 // are available to us directly without having to read DBGDIDR. 745 uint32_t register_DBGDIDR; 746 747 asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); 748 uint32_t numBRPs = bits(register_DBGDIDR, 27, 24); 749 // Zero is reserved for the BRP count, so don't increment it if it is zero 750 if (numBRPs > 0) 751 numBRPs++; 752 DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, numBRPs); 753 754 if (numBRPs > 0) 755 { 756 uint32_t cpusubtype; 757 len = sizeof(cpusubtype); 758 // TODO: remove this hack and change to using hw.optional.xx when implmented 759 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) 760 { 761 DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=%d", cpusubtype); 762 if (cpusubtype == CPU_SUBTYPE_ARM_V7) 763 DNBLogThreadedIf(LOG_THREAD, "Hardware breakpoints disabled for armv7 (rdar://problem/6372672)"); 764 else 765 g_num_supported_hw_breakpoints = numBRPs; 766 } 767 } 768 } 769 } 770 return g_num_supported_hw_breakpoints; 771} 772 773 774uint32_t 775DNBArchMachARM::NumSupportedHardwareWatchpoints() 776{ 777 // Set the init value to something that will let us know that we need to 778 // autodetect how many watchpoints are supported dynamically... 779 static uint32_t g_num_supported_hw_watchpoints = UINT_MAX; 780 if (g_num_supported_hw_watchpoints == UINT_MAX) 781 { 782 // Set this to zero in case we can't tell if there are any HW breakpoints 783 g_num_supported_hw_watchpoints = 0; 784 785 786 size_t len; 787 uint32_t n = 0; 788 len = sizeof (n); 789 if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) 790 { 791 g_num_supported_hw_watchpoints = n; 792 DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n); 793 } 794 else 795 { 796 // Read the DBGDIDR to get the number of available hardware breakpoints 797 // However, in some of our current armv7 processors, hardware 798 // breakpoints/watchpoints were not properly connected. So detect those 799 // cases using a field in a sysctl. For now we are using "hw.cpusubtype" 800 // field to distinguish CPU architectures. This is a hack until we can 801 // get <rdar://problem/6372672> fixed, at which point we will switch to 802 // using a different sysctl string that will tell us how many WRPs 803 // are available to us directly without having to read DBGDIDR. 804 805 uint32_t register_DBGDIDR; 806 asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); 807 uint32_t numWRPs = bits(register_DBGDIDR, 31, 28) + 1; 808 DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, numWRPs); 809 810 if (numWRPs > 0) 811 { 812 uint32_t cpusubtype; 813 size_t len; 814 len = sizeof(cpusubtype); 815 // TODO: remove this hack and change to using hw.optional.xx when implmented 816 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) 817 { 818 DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype); 819 820 if (cpusubtype == CPU_SUBTYPE_ARM_V7) 821 DNBLogThreadedIf(LOG_THREAD, "Hardware watchpoints disabled for armv7 (rdar://problem/6372672)"); 822 else 823 g_num_supported_hw_watchpoints = numWRPs; 824 } 825 } 826 } 827 } 828 return g_num_supported_hw_watchpoints; 829} 830 831 832uint32_t 833DNBArchMachARM::EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size) 834{ 835 // Make sure our address isn't bogus 836 if (addr & 1) 837 return INVALID_NUB_HW_INDEX; 838 839 kern_return_t kret = GetDBGState(false); 840 841 if (kret == KERN_SUCCESS) 842 { 843 const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); 844 uint32_t i; 845 for (i=0; i<num_hw_breakpoints; ++i) 846 { 847 if ((m_state.dbg.__bcr[i] & BCR_ENABLE) == 0) 848 break; // We found an available hw breakpoint slot (in i) 849 } 850 851 // See if we found an available hw breakpoint slot above 852 if (i < num_hw_breakpoints) 853 { 854 // Make sure bits 1:0 are clear in our address 855 m_state.dbg.__bvr[i] = addr & ~((nub_addr_t)3); 856 857 if (size == 2 || addr & 2) 858 { 859 uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1; 860 861 // We have a thumb breakpoint 862 // We have an ARM breakpoint 863 m_state.dbg.__bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch 864 byte_addr_select | // Set the correct byte address select so we only trigger on the correct opcode 865 S_USER | // Which modes should this breakpoint stop in? 866 BCR_ENABLE; // Enable this hardware breakpoint 867 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)", 868 (uint64_t)addr, 869 (uint64_t)size, 870 i, 871 i, 872 m_state.dbg.__bvr[i], 873 m_state.dbg.__bcr[i]); 874 } 875 else if (size == 4) 876 { 877 // We have an ARM breakpoint 878 m_state.dbg.__bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch 879 BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA 880 S_USER | // Which modes should this breakpoint stop in? 881 BCR_ENABLE; // Enable this hardware breakpoint 882 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)", 883 (uint64_t)addr, 884 (uint64_t)size, 885 i, 886 i, 887 m_state.dbg.__bvr[i], 888 m_state.dbg.__bcr[i]); 889 } 890 891 kret = SetDBGState(); 892 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint() SetDBGState() => 0x%8.8x.", kret); 893 894 if (kret == KERN_SUCCESS) 895 return i; 896 } 897 else 898 { 899 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint(addr = 0x%8.8llx, size = %llu) => all hardware breakpoint resources are being used.", (uint64_t)addr, (uint64_t)size); 900 } 901 } 902 903 return INVALID_NUB_HW_INDEX; 904} 905 906bool 907DNBArchMachARM::DisableHardwareBreakpoint (uint32_t hw_index) 908{ 909 kern_return_t kret = GetDBGState(false); 910 911 const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); 912 if (kret == KERN_SUCCESS) 913 { 914 if (hw_index < num_hw_points) 915 { 916 m_state.dbg.__bcr[hw_index] = 0; 917 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x BCR%u = 0x%8.8x", 918 hw_index, 919 hw_index, 920 m_state.dbg.__bvr[hw_index], 921 hw_index, 922 m_state.dbg.__bcr[hw_index]); 923 924 kret = SetDBGState(); 925 926 if (kret == KERN_SUCCESS) 927 return true; 928 } 929 } 930 return false; 931} 932 933// This stores the lo->hi mappings. It's safe to initialize to all 0's 934// since hi > lo and therefore LoHi[i] cannot be 0. 935static uint32_t LoHi[16] = { 0 }; 936 937uint32_t 938DNBArchMachARM::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write) 939{ 940 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %llu, read = %u, write = %u)", (uint64_t)addr, (uint64_t)size, read, write); 941 942 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); 943 944 // Can't watch zero bytes 945 if (size == 0) 946 return INVALID_NUB_HW_INDEX; 947 948 // We must watch for either read or write 949 if (read == false && write == false) 950 return INVALID_NUB_HW_INDEX; 951 952 // Divide-and-conquer for size == 8. 953 if (size == 8) 954 { 955 uint32_t lo = EnableHardwareWatchpoint(addr, 4, read, write); 956 if (lo == INVALID_NUB_HW_INDEX) 957 return INVALID_NUB_HW_INDEX; 958 uint32_t hi = EnableHardwareWatchpoint(addr+4, 4, read, write); 959 if (hi == INVALID_NUB_HW_INDEX) 960 { 961 DisableHardwareWatchpoint(lo); 962 return INVALID_NUB_HW_INDEX; 963 } 964 // Tag this lo->hi mapping in our database. 965 LoHi[lo] = hi; 966 return lo; 967 } 968 969 // Otherwise, can't watch more than 4 bytes per WVR/WCR pair 970 if (size > 4) 971 return INVALID_NUB_HW_INDEX; 972 973 // We can only watch up to four bytes that follow a 4 byte aligned address 974 // per watchpoint register pair. Since we can only watch until the next 4 975 // byte boundary, we need to make sure we can properly encode this. 976 977 // addr_word_offset = addr % 4, i.e, is in set([0, 1, 2, 3]) 978 // 979 // +---+---+---+---+ 980 // | 0 | 1 | 2 | 3 | 981 // +---+---+---+---+ 982 // ^ 983 // | 984 // word address (4-byte aligned) = addr & 0xFFFFFFFC => goes into WVR 985 // 986 // examples: 987 // 1. addr_word_offset = 1, size = 1 to watch a uint_8 => byte_mask = (0b0001 << 1) = 0b0010 988 // 2. addr_word_offset = 2, size = 2 to watch a uint_16 => byte_mask = (0b0011 << 2) = 0b1100 989 // 990 // where byte_mask goes into WCR[8:5] 991 992 uint32_t addr_word_offset = addr % 4; 993 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset); 994 995 uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset; 996 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask); 997 if (byte_mask > 0xfu) 998 return INVALID_NUB_HW_INDEX; 999 1000 // Read the debug state 1001 kern_return_t kret = GetDBGState(false); 1002 1003 if (kret == KERN_SUCCESS) 1004 { 1005 // Check to make sure we have the needed hardware support 1006 uint32_t i = 0; 1007 1008 for (i=0; i<num_hw_watchpoints; ++i) 1009 { 1010 if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0) 1011 break; // We found an available hw watchpoint slot (in i) 1012 } 1013 1014 // See if we found an available hw watchpoint slot above 1015 if (i < num_hw_watchpoints) 1016 { 1017 //DumpDBGState(m_state.dbg); 1018 1019 // Make the byte_mask into a valid Byte Address Select mask 1020 uint32_t byte_address_select = byte_mask << 5; 1021 // Make sure bits 1:0 are clear in our address 1022 m_state.dbg.__wvr[i] = addr & ~((nub_addr_t)3); // DVA (Data Virtual Address) 1023 m_state.dbg.__wcr[i] = byte_address_select | // Which bytes that follow the DVA that we will watch 1024 S_USER | // Stop only in user mode 1025 (read ? WCR_LOAD : 0) | // Stop on read access? 1026 (write ? WCR_STORE : 0) | // Stop on write access? 1027 WCR_ENABLE; // Enable this watchpoint; 1028 1029 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]); 1030 1031 kret = SetDBGState(); 1032 //DumpDBGState(m_state.dbg); 1033 1034 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret); 1035 1036 if (kret == KERN_SUCCESS) 1037 return i; 1038 } 1039 else 1040 { 1041 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); 1042 } 1043 } 1044 return INVALID_NUB_HW_INDEX; 1045} 1046 1047bool 1048DNBArchMachARM::EnableHardwareWatchpoint0 (uint32_t hw_index, bool Delegate) 1049{ 1050 kern_return_t kret = GetDBGState(false); 1051 if (kret != KERN_SUCCESS) 1052 return false; 1053 1054 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); 1055 if (hw_index >= num_hw_points) 1056 return false; 1057 1058 if (Delegate && LoHi[hw_index]) { 1059 // Enable lo and hi watchpoint hardware indexes. 1060 return EnableHardwareWatchpoint0(hw_index, false) && 1061 EnableHardwareWatchpoint0(LoHi[hw_index], false); 1062 } 1063 1064 m_state.dbg.__wcr[hw_index] |= (nub_addr_t)WCR_ENABLE; 1065 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x", 1066 hw_index, 1067 hw_index, 1068 m_state.dbg.__wvr[hw_index], 1069 hw_index, 1070 m_state.dbg.__wcr[hw_index]); 1071 1072 kret = SetDBGState(); 1073 1074 return (kret == KERN_SUCCESS); 1075} 1076 1077bool 1078DNBArchMachARM::DisableHardwareWatchpoint (uint32_t hw_index) 1079{ 1080 return DisableHardwareWatchpoint0(hw_index, true); 1081} 1082bool 1083DNBArchMachARM::DisableHardwareWatchpoint0 (uint32_t hw_index, bool Delegate) 1084{ 1085 kern_return_t kret = GetDBGState(false); 1086 if (kret != KERN_SUCCESS) 1087 return false; 1088 1089 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); 1090 if (hw_index >= num_hw_points) 1091 return false; 1092 1093 if (Delegate && LoHi[hw_index]) { 1094 // Disable lo and hi watchpoint hardware indexes. 1095 return DisableHardwareWatchpoint0(hw_index, false) && 1096 DisableHardwareWatchpoint0(LoHi[hw_index], false); 1097 } 1098 1099 m_state.dbg.__wcr[hw_index] &= ~((nub_addr_t)WCR_ENABLE); 1100 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::DisableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x", 1101 hw_index, 1102 hw_index, 1103 m_state.dbg.__wvr[hw_index], 1104 hw_index, 1105 m_state.dbg.__wcr[hw_index]); 1106 1107 kret = SetDBGState(); 1108 1109 return (kret == KERN_SUCCESS); 1110} 1111 1112// {0} -> __bvr[16], {0} -> __bcr[16], {0} --> __wvr[16], {0} -> __wcr{16} 1113DNBArchMachARM::DBG DNBArchMachARM::Global_Debug_State = {{0},{0},{0},{0}}; 1114bool DNBArchMachARM::Valid_Global_Debug_State = false; 1115 1116// Use this callback from MachThread, which in turn was called from MachThreadList, to update 1117// the global view of the hardware watchpoint state, so that when new thread comes along, they 1118// get to inherit the existing hardware watchpoint state. 1119void 1120DNBArchMachARM::HardwareWatchpointStateChanged () 1121{ 1122 Global_Debug_State = m_state.dbg; 1123 Valid_Global_Debug_State = true; 1124} 1125 1126// Returns -1 if the trailing bit patterns are not one of: 1127// { 0b???1, 0b??10, 0b?100, 0b1000 }. 1128static inline 1129int32_t 1130LowestBitSet(uint32_t val) 1131{ 1132 for (unsigned i = 0; i < 4; ++i) { 1133 if (bit(val, i)) 1134 return i; 1135 } 1136 return -1; 1137} 1138 1139// Iterate through the debug registers; return the index of the first watchpoint whose address matches. 1140// As a side effect, the starting address as understood by the debugger is returned which could be 1141// different from 'addr' passed as an in/out argument. 1142uint32_t 1143DNBArchMachARM::GetHardwareWatchpointHit(nub_addr_t &addr) 1144{ 1145 // Read the debug state 1146 kern_return_t kret = GetDBGState(true); 1147 //DumpDBGState(m_state.dbg); 1148 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret); 1149 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() addr = 0x%llx", (uint64_t)addr); 1150 1151 // This is the watchpoint value to match against, i.e., word address. 1152 nub_addr_t wp_val = addr & ~((nub_addr_t)3); 1153 if (kret == KERN_SUCCESS) 1154 { 1155 DBG &debug_state = m_state.dbg; 1156 uint32_t i, num = NumSupportedHardwareWatchpoints(); 1157 for (i = 0; i < num; ++i) 1158 { 1159 nub_addr_t wp_addr = GetWatchAddress(debug_state, i); 1160 DNBLogThreadedIf(LOG_WATCHPOINTS, 1161 "DNBArchMachARM::GetHardwareWatchpointHit() slot: %u (addr = 0x%llx).", 1162 i, (uint64_t)wp_addr); 1163 if (wp_val == wp_addr) { 1164 uint32_t byte_mask = bits(debug_state.__wcr[i], 8, 5); 1165 1166 // Sanity check the byte_mask, first. 1167 if (LowestBitSet(byte_mask) < 0) 1168 continue; 1169 1170 // Compute the starting address (from the point of view of the debugger). 1171 addr = wp_addr + LowestBitSet(byte_mask); 1172 return i; 1173 } 1174 } 1175 } 1176 return INVALID_NUB_HW_INDEX; 1177} 1178 1179// ThreadWillResume() calls this to clear bits[5:2] (Method of entry bits) of 1180// the Debug Status and Control Register (DSCR). 1181// 1182// b0010 = a watchpoint occurred 1183// b0000 is the reset value 1184void 1185DNBArchMachARM::ClearWatchpointOccurred() 1186{ 1187 uint32_t register_DBGDSCR; 1188 asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR)); 1189 if (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED) 1190 { 1191 uint32_t mask = ~(0xF << 2); 1192 register_DBGDSCR &= mask; 1193 asm("mcr p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR)); 1194 } 1195 return; 1196} 1197 1198// NotifyException() calls this to double check that a watchpoint has occurred 1199// by inspecting the bits[5:2] field of the Debug Status and Control Register 1200// (DSCR). 1201// 1202// b0010 = a watchpoint occurred 1203bool 1204DNBArchMachARM::HasWatchpointOccurred() 1205{ 1206 uint32_t register_DBGDSCR; 1207 asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR)); 1208 return (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED); 1209} 1210 1211bool 1212DNBArchMachARM::IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index) 1213{ 1214 // Watchpoint Control Registers, bitfield definitions 1215 // ... 1216 // Bits Value Description 1217 // [0] 0 Watchpoint disabled 1218 // 1 Watchpoint enabled. 1219 return (debug_state.__wcr[hw_index] & 1u); 1220} 1221 1222nub_addr_t 1223DNBArchMachARM::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) 1224{ 1225 // Watchpoint Value Registers, bitfield definitions 1226 // Bits Description 1227 // [31:2] Watchpoint value (word address, i.e., 4-byte aligned) 1228 // [1:0] RAZ/SBZP 1229 return bits(debug_state.__wvr[hw_index], 31, 0); 1230} 1231 1232//---------------------------------------------------------------------- 1233// Register information defintions for 32 bit ARMV7. 1234//---------------------------------------------------------------------- 1235enum gpr_regnums 1236{ 1237 gpr_r0 = 0, 1238 gpr_r1, 1239 gpr_r2, 1240 gpr_r3, 1241 gpr_r4, 1242 gpr_r5, 1243 gpr_r6, 1244 gpr_r7, 1245 gpr_r8, 1246 gpr_r9, 1247 gpr_r10, 1248 gpr_r11, 1249 gpr_r12, 1250 gpr_sp, 1251 gpr_lr, 1252 gpr_pc, 1253 gpr_cpsr 1254}; 1255 1256enum 1257{ 1258 vfp_s0 = 17, // match the g_gdb_register_map_arm table in RNBRemote.cpp 1259 vfp_s1, 1260 vfp_s2, 1261 vfp_s3, 1262 vfp_s4, 1263 vfp_s5, 1264 vfp_s6, 1265 vfp_s7, 1266 vfp_s8, 1267 vfp_s9, 1268 vfp_s10, 1269 vfp_s11, 1270 vfp_s12, 1271 vfp_s13, 1272 vfp_s14, 1273 vfp_s15, 1274 vfp_s16, 1275 vfp_s17, 1276 vfp_s18, 1277 vfp_s19, 1278 vfp_s20, 1279 vfp_s21, 1280 vfp_s22, 1281 vfp_s23, 1282 vfp_s24, 1283 vfp_s25, 1284 vfp_s26, 1285 vfp_s27, 1286 vfp_s28, 1287 vfp_s29, 1288 vfp_s30, 1289 vfp_s31 1290}; 1291 1292enum 1293{ 1294 vfp_d0 = 49, // match the g_gdb_register_map_arm table in RNBRemote.cpp 1295 vfp_d1, 1296 vfp_d2, 1297 vfp_d3, 1298 vfp_d4, 1299 vfp_d5, 1300 vfp_d6, 1301 vfp_d7, 1302 vfp_d8, 1303 vfp_d9, 1304 vfp_d10, 1305 vfp_d11, 1306 vfp_d12, 1307 vfp_d13, 1308 vfp_d14, 1309 vfp_d15, 1310 vfp_d16, 1311 vfp_d17, 1312 vfp_d18, 1313 vfp_d19, 1314 vfp_d20, 1315 vfp_d21, 1316 vfp_d22, 1317 vfp_d23, 1318 vfp_d24, 1319 vfp_d25, 1320 vfp_d26, 1321 vfp_d27, 1322 vfp_d28, 1323 vfp_d29, 1324 vfp_d30, 1325 vfp_d31 1326}; 1327 1328enum 1329{ 1330 vfp_q0 = 81, // match the g_gdb_register_map_arm table in RNBRemote.cpp 1331 vfp_q1, 1332 vfp_q2, 1333 vfp_q3, 1334 vfp_q4, 1335 vfp_q5, 1336 vfp_q6, 1337 vfp_q7, 1338 vfp_q8, 1339 vfp_q9, 1340 vfp_q10, 1341 vfp_q11, 1342 vfp_q12, 1343 vfp_q13, 1344 vfp_q14, 1345 vfp_q15, 1346 vfp_fpscr 1347}; 1348 1349enum 1350{ 1351 exc_exception, 1352 exc_fsr, 1353 exc_far, 1354}; 1355 1356#define GPR_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::GPR, __r[idx])) 1357#define GPR_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::GPR, __##reg)) 1358 1359#define EXC_OFFSET(reg) (offsetof (DNBArchMachARM::EXC, __##reg) + offsetof (DNBArchMachARM::Context, exc)) 1360 1361// These macros will auto define the register name, alt name, register size, 1362// register offset, encoding, format and native register. This ensures that 1363// the register state structures are defined correctly and have the correct 1364// sizes and offsets. 1365#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} 1366#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} 1367 1368// In case we are debugging to a debug target that the ability to 1369// change into the protected modes with folded registers (ABT, IRQ, 1370// FIQ, SYS, USR, etc..), we should invalidate r8-r14 if the CPSR 1371// gets modified. 1372 1373uint32_t g_invalidate_cpsr[] = { 1374 gpr_r8, 1375 gpr_r9, 1376 gpr_r10, 1377 gpr_r11, 1378 gpr_r12, 1379 gpr_sp, 1380 gpr_lr, 1381 INVALID_NUB_REGNUM }; 1382 1383// General purpose registers 1384const DNBRegisterInfo 1385DNBArchMachARM::g_gpr_registers[] = 1386{ 1387 DEFINE_GPR_IDX ( 0, r0,"arg1", GENERIC_REGNUM_ARG1 ), 1388 DEFINE_GPR_IDX ( 1, r1,"arg2", GENERIC_REGNUM_ARG2 ), 1389 DEFINE_GPR_IDX ( 2, r2,"arg3", GENERIC_REGNUM_ARG3 ), 1390 DEFINE_GPR_IDX ( 3, r3,"arg4", GENERIC_REGNUM_ARG4 ), 1391 DEFINE_GPR_IDX ( 4, r4, NULL, INVALID_NUB_REGNUM ), 1392 DEFINE_GPR_IDX ( 5, r5, NULL, INVALID_NUB_REGNUM ), 1393 DEFINE_GPR_IDX ( 6, r6, NULL, INVALID_NUB_REGNUM ), 1394 DEFINE_GPR_IDX ( 7, r7, "fp", GENERIC_REGNUM_FP ), 1395 DEFINE_GPR_IDX ( 8, r8, NULL, INVALID_NUB_REGNUM ), 1396 DEFINE_GPR_IDX ( 9, r9, NULL, INVALID_NUB_REGNUM ), 1397 DEFINE_GPR_IDX (10, r10, NULL, INVALID_NUB_REGNUM ), 1398 DEFINE_GPR_IDX (11, r11, NULL, INVALID_NUB_REGNUM ), 1399 DEFINE_GPR_IDX (12, r12, NULL, INVALID_NUB_REGNUM ), 1400 DEFINE_GPR_NAME (sp, "r13", GENERIC_REGNUM_SP, NULL), 1401 DEFINE_GPR_NAME (lr, "r14", GENERIC_REGNUM_RA, NULL), 1402 DEFINE_GPR_NAME (pc, "r15", GENERIC_REGNUM_PC, NULL), 1403 DEFINE_GPR_NAME (cpsr, "flags", GENERIC_REGNUM_FLAGS, g_invalidate_cpsr) 1404}; 1405 1406uint32_t g_contained_q0[] {vfp_q0, INVALID_NUB_REGNUM }; 1407uint32_t g_contained_q1[] {vfp_q1, INVALID_NUB_REGNUM }; 1408uint32_t g_contained_q2[] {vfp_q2, INVALID_NUB_REGNUM }; 1409uint32_t g_contained_q3[] {vfp_q3, INVALID_NUB_REGNUM }; 1410uint32_t g_contained_q4[] {vfp_q4, INVALID_NUB_REGNUM }; 1411uint32_t g_contained_q5[] {vfp_q5, INVALID_NUB_REGNUM }; 1412uint32_t g_contained_q6[] {vfp_q6, INVALID_NUB_REGNUM }; 1413uint32_t g_contained_q7[] {vfp_q7, INVALID_NUB_REGNUM }; 1414uint32_t g_contained_q8[] {vfp_q8, INVALID_NUB_REGNUM }; 1415uint32_t g_contained_q9[] {vfp_q9, INVALID_NUB_REGNUM }; 1416uint32_t g_contained_q10[] {vfp_q10, INVALID_NUB_REGNUM }; 1417uint32_t g_contained_q11[] {vfp_q11, INVALID_NUB_REGNUM }; 1418uint32_t g_contained_q12[] {vfp_q12, INVALID_NUB_REGNUM }; 1419uint32_t g_contained_q13[] {vfp_q13, INVALID_NUB_REGNUM }; 1420uint32_t g_contained_q14[] {vfp_q14, INVALID_NUB_REGNUM }; 1421uint32_t g_contained_q15[] {vfp_q15, INVALID_NUB_REGNUM }; 1422 1423uint32_t g_invalidate_q0[] {vfp_q0, vfp_d0, vfp_d1, vfp_s0, vfp_s1, vfp_s2, vfp_s3, INVALID_NUB_REGNUM }; 1424uint32_t g_invalidate_q1[] {vfp_q1, vfp_d2, vfp_d3, vfp_s4, vfp_s5, vfp_s6, vfp_s7, INVALID_NUB_REGNUM }; 1425uint32_t g_invalidate_q2[] {vfp_q2, vfp_d4, vfp_d5, vfp_s8, vfp_s9, vfp_s10, vfp_s11, INVALID_NUB_REGNUM }; 1426uint32_t g_invalidate_q3[] {vfp_q3, vfp_d6, vfp_d7, vfp_s12, vfp_s13, vfp_s14, vfp_s15, INVALID_NUB_REGNUM }; 1427uint32_t g_invalidate_q4[] {vfp_q4, vfp_d8, vfp_d9, vfp_s16, vfp_s17, vfp_s18, vfp_s19, INVALID_NUB_REGNUM }; 1428uint32_t g_invalidate_q5[] {vfp_q5, vfp_d10, vfp_d11, vfp_s20, vfp_s21, vfp_s22, vfp_s23, INVALID_NUB_REGNUM }; 1429uint32_t g_invalidate_q6[] {vfp_q6, vfp_d12, vfp_d13, vfp_s24, vfp_s25, vfp_s26, vfp_s27, INVALID_NUB_REGNUM }; 1430uint32_t g_invalidate_q7[] {vfp_q7, vfp_d14, vfp_d15, vfp_s28, vfp_s29, vfp_s30, vfp_s31, INVALID_NUB_REGNUM }; 1431uint32_t g_invalidate_q8[] {vfp_q8, vfp_d16, vfp_d17, INVALID_NUB_REGNUM }; 1432uint32_t g_invalidate_q9[] {vfp_q9, vfp_d18, vfp_d19, INVALID_NUB_REGNUM }; 1433uint32_t g_invalidate_q10[] {vfp_q10, vfp_d20, vfp_d21, INVALID_NUB_REGNUM }; 1434uint32_t g_invalidate_q11[] {vfp_q11, vfp_d22, vfp_d23, INVALID_NUB_REGNUM }; 1435uint32_t g_invalidate_q12[] {vfp_q12, vfp_d24, vfp_d25, INVALID_NUB_REGNUM }; 1436uint32_t g_invalidate_q13[] {vfp_q13, vfp_d26, vfp_d27, INVALID_NUB_REGNUM }; 1437uint32_t g_invalidate_q14[] {vfp_q14, vfp_d28, vfp_d29, INVALID_NUB_REGNUM }; 1438uint32_t g_invalidate_q15[] {vfp_q15, vfp_d30, vfp_d31, INVALID_NUB_REGNUM }; 1439 1440#define VFP_S_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::FPU, __r[(idx)]) + offsetof (DNBArchMachARM::Context, vfp)) 1441#define VFP_D_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX ((idx) * 2)) 1442#define VFP_Q_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX ((idx) * 4)) 1443 1444#define VFP_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::FPU, __##reg) + offsetof (DNBArchMachARM::Context, vfp)) 1445 1446#define FLOAT_FORMAT Float 1447 1448#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 1449#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 1450#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 1451 1452// Floating point registers 1453const DNBRegisterInfo 1454DNBArchMachARM::g_vfp_registers[] = 1455{ 1456 { DEFINE_VFP_S_IDX ( 0), g_contained_q0, g_invalidate_q0 }, 1457 { DEFINE_VFP_S_IDX ( 1), g_contained_q0, g_invalidate_q0 }, 1458 { DEFINE_VFP_S_IDX ( 2), g_contained_q0, g_invalidate_q0 }, 1459 { DEFINE_VFP_S_IDX ( 3), g_contained_q0, g_invalidate_q0 }, 1460 { DEFINE_VFP_S_IDX ( 4), g_contained_q1, g_invalidate_q1 }, 1461 { DEFINE_VFP_S_IDX ( 5), g_contained_q1, g_invalidate_q1 }, 1462 { DEFINE_VFP_S_IDX ( 6), g_contained_q1, g_invalidate_q1 }, 1463 { DEFINE_VFP_S_IDX ( 7), g_contained_q1, g_invalidate_q1 }, 1464 { DEFINE_VFP_S_IDX ( 8), g_contained_q2, g_invalidate_q2 }, 1465 { DEFINE_VFP_S_IDX ( 9), g_contained_q2, g_invalidate_q2 }, 1466 { DEFINE_VFP_S_IDX (10), g_contained_q2, g_invalidate_q2 }, 1467 { DEFINE_VFP_S_IDX (11), g_contained_q2, g_invalidate_q2 }, 1468 { DEFINE_VFP_S_IDX (12), g_contained_q3, g_invalidate_q3 }, 1469 { DEFINE_VFP_S_IDX (13), g_contained_q3, g_invalidate_q3 }, 1470 { DEFINE_VFP_S_IDX (14), g_contained_q3, g_invalidate_q3 }, 1471 { DEFINE_VFP_S_IDX (15), g_contained_q3, g_invalidate_q3 }, 1472 { DEFINE_VFP_S_IDX (16), g_contained_q4, g_invalidate_q4 }, 1473 { DEFINE_VFP_S_IDX (17), g_contained_q4, g_invalidate_q4 }, 1474 { DEFINE_VFP_S_IDX (18), g_contained_q4, g_invalidate_q4 }, 1475 { DEFINE_VFP_S_IDX (19), g_contained_q4, g_invalidate_q4 }, 1476 { DEFINE_VFP_S_IDX (20), g_contained_q5, g_invalidate_q5 }, 1477 { DEFINE_VFP_S_IDX (21), g_contained_q5, g_invalidate_q5 }, 1478 { DEFINE_VFP_S_IDX (22), g_contained_q5, g_invalidate_q5 }, 1479 { DEFINE_VFP_S_IDX (23), g_contained_q5, g_invalidate_q5 }, 1480 { DEFINE_VFP_S_IDX (24), g_contained_q6, g_invalidate_q6 }, 1481 { DEFINE_VFP_S_IDX (25), g_contained_q6, g_invalidate_q6 }, 1482 { DEFINE_VFP_S_IDX (26), g_contained_q6, g_invalidate_q6 }, 1483 { DEFINE_VFP_S_IDX (27), g_contained_q6, g_invalidate_q6 }, 1484 { DEFINE_VFP_S_IDX (28), g_contained_q7, g_invalidate_q7 }, 1485 { DEFINE_VFP_S_IDX (29), g_contained_q7, g_invalidate_q7 }, 1486 { DEFINE_VFP_S_IDX (30), g_contained_q7, g_invalidate_q7 }, 1487 { DEFINE_VFP_S_IDX (31), g_contained_q7, g_invalidate_q7 }, 1488 1489 { DEFINE_VFP_D_IDX (0), g_contained_q0, g_invalidate_q0 }, 1490 { DEFINE_VFP_D_IDX (1), g_contained_q0, g_invalidate_q0 }, 1491 { DEFINE_VFP_D_IDX (2), g_contained_q1, g_invalidate_q1 }, 1492 { DEFINE_VFP_D_IDX (3), g_contained_q1, g_invalidate_q1 }, 1493 { DEFINE_VFP_D_IDX (4), g_contained_q2, g_invalidate_q2 }, 1494 { DEFINE_VFP_D_IDX (5), g_contained_q2, g_invalidate_q2 }, 1495 { DEFINE_VFP_D_IDX (6), g_contained_q3, g_invalidate_q3 }, 1496 { DEFINE_VFP_D_IDX (7), g_contained_q3, g_invalidate_q3 }, 1497 { DEFINE_VFP_D_IDX (8), g_contained_q4, g_invalidate_q4 }, 1498 { DEFINE_VFP_D_IDX (9), g_contained_q4, g_invalidate_q4 }, 1499 { DEFINE_VFP_D_IDX (10), g_contained_q5, g_invalidate_q5 }, 1500 { DEFINE_VFP_D_IDX (11), g_contained_q5, g_invalidate_q5 }, 1501 { DEFINE_VFP_D_IDX (12), g_contained_q6, g_invalidate_q6 }, 1502 { DEFINE_VFP_D_IDX (13), g_contained_q6, g_invalidate_q6 }, 1503 { DEFINE_VFP_D_IDX (14), g_contained_q7, g_invalidate_q7 }, 1504 { DEFINE_VFP_D_IDX (15), g_contained_q7, g_invalidate_q7 }, 1505 { DEFINE_VFP_D_IDX (16), g_contained_q8, g_invalidate_q8 }, 1506 { DEFINE_VFP_D_IDX (17), g_contained_q8, g_invalidate_q8 }, 1507 { DEFINE_VFP_D_IDX (18), g_contained_q9, g_invalidate_q9 }, 1508 { DEFINE_VFP_D_IDX (19), g_contained_q9, g_invalidate_q9 }, 1509 { DEFINE_VFP_D_IDX (20), g_contained_q10, g_invalidate_q10 }, 1510 { DEFINE_VFP_D_IDX (21), g_contained_q10, g_invalidate_q10 }, 1511 { DEFINE_VFP_D_IDX (22), g_contained_q11, g_invalidate_q11 }, 1512 { DEFINE_VFP_D_IDX (23), g_contained_q11, g_invalidate_q11 }, 1513 { DEFINE_VFP_D_IDX (24), g_contained_q12, g_invalidate_q12 }, 1514 { DEFINE_VFP_D_IDX (25), g_contained_q12, g_invalidate_q12 }, 1515 { DEFINE_VFP_D_IDX (26), g_contained_q13, g_invalidate_q13 }, 1516 { DEFINE_VFP_D_IDX (27), g_contained_q13, g_invalidate_q13 }, 1517 { DEFINE_VFP_D_IDX (28), g_contained_q14, g_invalidate_q14 }, 1518 { DEFINE_VFP_D_IDX (29), g_contained_q14, g_invalidate_q14 }, 1519 { DEFINE_VFP_D_IDX (30), g_contained_q15, g_invalidate_q15 }, 1520 { DEFINE_VFP_D_IDX (31), g_contained_q15, g_invalidate_q15 }, 1521 1522 { DEFINE_VFP_Q_IDX (0), NULL, g_invalidate_q0 }, 1523 { DEFINE_VFP_Q_IDX (1), NULL, g_invalidate_q1 }, 1524 { DEFINE_VFP_Q_IDX (2), NULL, g_invalidate_q2 }, 1525 { DEFINE_VFP_Q_IDX (3), NULL, g_invalidate_q3 }, 1526 { DEFINE_VFP_Q_IDX (4), NULL, g_invalidate_q4 }, 1527 { DEFINE_VFP_Q_IDX (5), NULL, g_invalidate_q5 }, 1528 { DEFINE_VFP_Q_IDX (6), NULL, g_invalidate_q6 }, 1529 { DEFINE_VFP_Q_IDX (7), NULL, g_invalidate_q7 }, 1530 { DEFINE_VFP_Q_IDX (8), NULL, g_invalidate_q8 }, 1531 { DEFINE_VFP_Q_IDX (9), NULL, g_invalidate_q9 }, 1532 { DEFINE_VFP_Q_IDX (10), NULL, g_invalidate_q10 }, 1533 { DEFINE_VFP_Q_IDX (11), NULL, g_invalidate_q11 }, 1534 { DEFINE_VFP_Q_IDX (12), NULL, g_invalidate_q12 }, 1535 { DEFINE_VFP_Q_IDX (13), NULL, g_invalidate_q13 }, 1536 { DEFINE_VFP_Q_IDX (14), NULL, g_invalidate_q14 }, 1537 { DEFINE_VFP_Q_IDX (15), NULL, g_invalidate_q15 }, 1538 1539 { 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 } 1540}; 1541 1542// Exception registers 1543 1544const DNBRegisterInfo 1545DNBArchMachARM::g_exc_registers[] = 1546{ 1547 { e_regSetVFP, exc_exception , "exception" , NULL, Uint, Hex, 4, EXC_OFFSET(exception) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }, 1548 { e_regSetVFP, exc_fsr , "fsr" , NULL, Uint, Hex, 4, EXC_OFFSET(fsr) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }, 1549 { e_regSetVFP, exc_far , "far" , NULL, Uint, Hex, 4, EXC_OFFSET(far) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM } 1550}; 1551 1552// Number of registers in each register set 1553const size_t DNBArchMachARM::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); 1554const size_t DNBArchMachARM::k_num_vfp_registers = sizeof(g_vfp_registers)/sizeof(DNBRegisterInfo); 1555const size_t DNBArchMachARM::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); 1556const size_t DNBArchMachARM::k_num_all_registers = k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers; 1557 1558//---------------------------------------------------------------------- 1559// Register set definitions. The first definitions at register set index 1560// of zero is for all registers, followed by other registers sets. The 1561// register information for the all register set need not be filled in. 1562//---------------------------------------------------------------------- 1563const DNBRegisterSetInfo 1564DNBArchMachARM::g_reg_sets[] = 1565{ 1566 { "ARM Registers", NULL, k_num_all_registers }, 1567 { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, 1568 { "Floating Point Registers", g_vfp_registers, k_num_vfp_registers }, 1569 { "Exception State Registers", g_exc_registers, k_num_exc_registers } 1570}; 1571// Total number of register sets for this architecture 1572const size_t DNBArchMachARM::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); 1573 1574 1575const DNBRegisterSetInfo * 1576DNBArchMachARM::GetRegisterSetInfo(nub_size_t *num_reg_sets) 1577{ 1578 *num_reg_sets = k_num_register_sets; 1579 return g_reg_sets; 1580} 1581 1582bool 1583DNBArchMachARM::GetRegisterValue(int set, int reg, DNBRegisterValue *value) 1584{ 1585 if (set == REGISTER_SET_GENERIC) 1586 { 1587 switch (reg) 1588 { 1589 case GENERIC_REGNUM_PC: // Program Counter 1590 set = e_regSetGPR; 1591 reg = gpr_pc; 1592 break; 1593 1594 case GENERIC_REGNUM_SP: // Stack Pointer 1595 set = e_regSetGPR; 1596 reg = gpr_sp; 1597 break; 1598 1599 case GENERIC_REGNUM_FP: // Frame Pointer 1600 set = e_regSetGPR; 1601 reg = gpr_r7; // is this the right reg? 1602 break; 1603 1604 case GENERIC_REGNUM_RA: // Return Address 1605 set = e_regSetGPR; 1606 reg = gpr_lr; 1607 break; 1608 1609 case GENERIC_REGNUM_FLAGS: // Processor flags register 1610 set = e_regSetGPR; 1611 reg = gpr_cpsr; 1612 break; 1613 1614 default: 1615 return false; 1616 } 1617 } 1618 1619 if (GetRegisterState(set, false) != KERN_SUCCESS) 1620 return false; 1621 1622 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 1623 if (regInfo) 1624 { 1625 value->info = *regInfo; 1626 switch (set) 1627 { 1628 case e_regSetGPR: 1629 if (reg < k_num_gpr_registers) 1630 { 1631 value->value.uint32 = m_state.context.gpr.__r[reg]; 1632 return true; 1633 } 1634 break; 1635 1636 case e_regSetVFP: 1637 // "reg" is an index into the floating point register set at this point. 1638 // We need to translate it up so entry 0 in the fp reg set is the same as vfp_s0 1639 // in the enumerated values for case statement below. 1640 reg += vfp_s0; 1641 if (reg >= vfp_s0 && reg <= vfp_s31) 1642 { 1643 value->value.uint32 = m_state.context.vfp.__r[reg - vfp_s0]; 1644 return true; 1645 } 1646 else if (reg >= vfp_d0 && reg <= vfp_d31) 1647 { 1648 uint32_t d_reg_idx = reg - vfp_d0; 1649 uint32_t s_reg_idx = d_reg_idx * 2; 1650 value->value.v_sint32[0] = m_state.context.vfp.__r[s_reg_idx + 0]; 1651 value->value.v_sint32[1] = m_state.context.vfp.__r[s_reg_idx + 1]; 1652 return true; 1653 } 1654 else if (reg >= vfp_q0 && reg <= vfp_q15) 1655 { 1656 uint32_t s_reg_idx = (reg - vfp_q0) * 4; 1657 memcpy (&value->value.v_uint8, (uint8_t *) &m_state.context.vfp.__r[s_reg_idx], 16); 1658 return true; 1659 } 1660 1661 else if (reg == vfp_fpscr) 1662 { 1663 value->value.uint32 = m_state.context.vfp.__fpscr; 1664 return true; 1665 } 1666 break; 1667 1668 case e_regSetEXC: 1669 if (reg < k_num_exc_registers) 1670 { 1671 value->value.uint32 = (&m_state.context.exc.__exception)[reg]; 1672 return true; 1673 } 1674 break; 1675 } 1676 } 1677 return false; 1678} 1679 1680bool 1681DNBArchMachARM::SetRegisterValue(int set, int reg, const DNBRegisterValue *value) 1682{ 1683 if (set == REGISTER_SET_GENERIC) 1684 { 1685 switch (reg) 1686 { 1687 case GENERIC_REGNUM_PC: // Program Counter 1688 set = e_regSetGPR; 1689 reg = gpr_pc; 1690 break; 1691 1692 case GENERIC_REGNUM_SP: // Stack Pointer 1693 set = e_regSetGPR; 1694 reg = gpr_sp; 1695 break; 1696 1697 case GENERIC_REGNUM_FP: // Frame Pointer 1698 set = e_regSetGPR; 1699 reg = gpr_r7; 1700 break; 1701 1702 case GENERIC_REGNUM_RA: // Return Address 1703 set = e_regSetGPR; 1704 reg = gpr_lr; 1705 break; 1706 1707 case GENERIC_REGNUM_FLAGS: // Processor flags register 1708 set = e_regSetGPR; 1709 reg = gpr_cpsr; 1710 break; 1711 1712 default: 1713 return false; 1714 } 1715 } 1716 1717 if (GetRegisterState(set, false) != KERN_SUCCESS) 1718 return false; 1719 1720 bool success = false; 1721 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 1722 if (regInfo) 1723 { 1724 switch (set) 1725 { 1726 case e_regSetGPR: 1727 if (reg < k_num_gpr_registers) 1728 { 1729 m_state.context.gpr.__r[reg] = value->value.uint32; 1730 success = true; 1731 } 1732 break; 1733 1734 case e_regSetVFP: 1735 // "reg" is an index into the floating point register set at this point. 1736 // We need to translate it up so entry 0 in the fp reg set is the same as vfp_s0 1737 // in the enumerated values for case statement below. 1738 reg += vfp_s0; 1739 1740 if (reg >= vfp_s0 && reg <= vfp_s31) 1741 { 1742 m_state.context.vfp.__r[reg - vfp_s0] = value->value.uint32; 1743 success = true; 1744 } 1745 else if (reg >= vfp_d0 && reg <= vfp_d31) 1746 { 1747 uint32_t d_reg_idx = reg - vfp_d0; 1748 uint32_t s_reg_idx = d_reg_idx * 2; 1749 m_state.context.vfp.__r[s_reg_idx + 0] = value->value.v_sint32[0]; 1750 m_state.context.vfp.__r[s_reg_idx + 1] = value->value.v_sint32[1]; 1751 success = true; 1752 } 1753 else if (reg >= vfp_q0 && reg <= vfp_q15) 1754 { 1755 uint32_t s_reg_idx = (reg - vfp_q0) * 4; 1756 memcpy ((uint8_t *) &m_state.context.vfp.__r[s_reg_idx], &value->value.v_uint8, 16); 1757 return true; 1758 } 1759 else if (reg == vfp_fpscr) 1760 { 1761 m_state.context.vfp.__fpscr = value->value.uint32; 1762 success = true; 1763 } 1764 break; 1765 1766 case e_regSetEXC: 1767 if (reg < k_num_exc_registers) 1768 { 1769 (&m_state.context.exc.__exception)[reg] = value->value.uint32; 1770 success = true; 1771 } 1772 break; 1773 } 1774 1775 } 1776 if (success) 1777 return SetRegisterState(set) == KERN_SUCCESS; 1778 return false; 1779} 1780 1781kern_return_t 1782DNBArchMachARM::GetRegisterState(int set, bool force) 1783{ 1784 switch (set) 1785 { 1786 case e_regSetALL: return GetGPRState(force) | 1787 GetVFPState(force) | 1788 GetEXCState(force) | 1789 GetDBGState(force); 1790 case e_regSetGPR: return GetGPRState(force); 1791 case e_regSetVFP: return GetVFPState(force); 1792 case e_regSetEXC: return GetEXCState(force); 1793 case e_regSetDBG: return GetDBGState(force); 1794 default: break; 1795 } 1796 return KERN_INVALID_ARGUMENT; 1797} 1798 1799kern_return_t 1800DNBArchMachARM::SetRegisterState(int set) 1801{ 1802 // Make sure we have a valid context to set. 1803 kern_return_t err = GetRegisterState(set, false); 1804 if (err != KERN_SUCCESS) 1805 return err; 1806 1807 switch (set) 1808 { 1809 case e_regSetALL: return SetGPRState() | 1810 SetVFPState() | 1811 SetEXCState() | 1812 SetDBGState(); 1813 case e_regSetGPR: return SetGPRState(); 1814 case e_regSetVFP: return SetVFPState(); 1815 case e_regSetEXC: return SetEXCState(); 1816 case e_regSetDBG: return SetDBGState(); 1817 default: break; 1818 } 1819 return KERN_INVALID_ARGUMENT; 1820} 1821 1822bool 1823DNBArchMachARM::RegisterSetStateIsValid (int set) const 1824{ 1825 return m_state.RegsAreValid(set); 1826} 1827 1828 1829nub_size_t 1830DNBArchMachARM::GetRegisterContext (void *buf, nub_size_t buf_len) 1831{ 1832 nub_size_t size = sizeof (m_state.context); 1833 1834 if (buf && buf_len) 1835 { 1836 if (size > buf_len) 1837 size = buf_len; 1838 1839 bool force = false; 1840 if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force)) 1841 return 0; 1842 ::memcpy (buf, &m_state.context, size); 1843 } 1844 DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::GetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size); 1845 // Return the size of the register context even if NULL was passed in 1846 return size; 1847} 1848 1849nub_size_t 1850DNBArchMachARM::SetRegisterContext (const void *buf, nub_size_t buf_len) 1851{ 1852 nub_size_t size = sizeof (m_state.context); 1853 if (buf == NULL || buf_len == 0) 1854 size = 0; 1855 1856 if (size) 1857 { 1858 if (size > buf_len) 1859 size = buf_len; 1860 1861 ::memcpy (&m_state.context, buf, size); 1862 SetGPRState(); 1863 SetVFPState(); 1864 SetEXCState(); 1865 } 1866 DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size); 1867 return size; 1868} 1869 1870 1871#endif // #if defined (__arm__) 1872 1873