DNBArchImpl.cpp revision e350394e5b4bd5c32f70951a035a889bfd0194e4
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 63//#define DNB_ARCH_MACH_ARM_DEBUG_SW_STEP 1 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 return new DNBArchMachARM (thread); 121} 122 123const uint8_t * const 124DNBArchMachARM::SoftwareBreakpointOpcode (nub_size_t byte_size) 125{ 126 switch (byte_size) 127 { 128 case 2: return g_thumb_breakpooint_opcode; 129 case 4: return g_arm_breakpoint_opcode; 130 } 131 return NULL; 132} 133 134uint32_t 135DNBArchMachARM::GetCPUType() 136{ 137 return CPU_TYPE_ARM; 138} 139 140uint64_t 141DNBArchMachARM::GetPC(uint64_t failValue) 142{ 143 // Get program counter 144 if (GetGPRState(false) == KERN_SUCCESS) 145 return m_state.context.gpr.__pc; 146 return failValue; 147} 148 149kern_return_t 150DNBArchMachARM::SetPC(uint64_t value) 151{ 152 // Get program counter 153 kern_return_t err = GetGPRState(false); 154 if (err == KERN_SUCCESS) 155 { 156 m_state.context.gpr.__pc = value; 157 err = SetGPRState(); 158 } 159 return err == KERN_SUCCESS; 160} 161 162uint64_t 163DNBArchMachARM::GetSP(uint64_t failValue) 164{ 165 // Get stack pointer 166 if (GetGPRState(false) == KERN_SUCCESS) 167 return m_state.context.gpr.__sp; 168 return failValue; 169} 170 171kern_return_t 172DNBArchMachARM::GetGPRState(bool force) 173{ 174 int set = e_regSetGPR; 175 // Check if we have valid cached registers 176 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) 177 return KERN_SUCCESS; 178 179 // Read the registers from our thread 180 mach_msg_type_number_t count = ARM_THREAD_STATE_COUNT; 181 kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count); 182 uint32_t *r = &m_state.context.gpr.__r[0]; 183 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", 184 m_thread->ThreadID(), 185 ARM_THREAD_STATE, 186 ARM_THREAD_STATE_COUNT, 187 kret, 188 count, 189 r[0], 190 r[1], 191 r[2], 192 r[3], 193 r[4], 194 r[5], 195 r[6], 196 r[7], 197 r[8], 198 r[9], 199 r[10], 200 r[11], 201 r[12], 202 r[13], 203 r[14], 204 r[15], 205 r[16]); 206 m_state.SetError(set, Read, kret); 207 return kret; 208} 209 210kern_return_t 211DNBArchMachARM::GetVFPState(bool force) 212{ 213 int set = e_regSetVFP; 214 // Check if we have valid cached registers 215 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) 216 return KERN_SUCCESS; 217 218 // Read the registers from our thread 219 mach_msg_type_number_t count = ARM_VFP_STATE_COUNT; 220 kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, &count); 221 if (DNBLogEnabledForAny (LOG_THREAD)) 222 { 223 uint32_t *r = &m_state.context.vfp.__r[0]; 224 DNBLogThreaded ("thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count => %u)", 225 m_thread->ThreadID(), 226 ARM_THREAD_STATE, 227 ARM_THREAD_STATE_COUNT, 228 kret, 229 count); 230 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]); 231 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]); 232 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]); 233 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]); 234 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]); 235 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]); 236 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]); 237 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]); 238 } 239 m_state.SetError(set, Read, kret); 240 return kret; 241} 242 243kern_return_t 244DNBArchMachARM::GetEXCState(bool force) 245{ 246 int set = e_regSetEXC; 247 // Check if we have valid cached registers 248 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) 249 return KERN_SUCCESS; 250 251 // Read the registers from our thread 252 mach_msg_type_number_t count = ARM_EXCEPTION_STATE_COUNT; 253 kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count); 254 m_state.SetError(set, Read, kret); 255 return kret; 256} 257 258static void 259DumpDBGState(const DNBArchMachARM::DBG& dbg) 260{ 261 uint32_t i = 0; 262 for (i=0; i<16; i++) 263 DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }", 264 i, i, dbg.__bvr[i], dbg.__bcr[i], 265 i, i, dbg.__wvr[i], dbg.__wcr[i]); 266} 267 268kern_return_t 269DNBArchMachARM::GetDBGState(bool force) 270{ 271 int set = e_regSetDBG; 272 273 // Check if we have valid cached registers 274 if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) 275 return KERN_SUCCESS; 276 277 // Read the registers from our thread 278 mach_msg_type_number_t count = ARM_DEBUG_STATE_COUNT; 279 kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, &count); 280 m_state.SetError(set, Read, kret); 281 return kret; 282} 283 284kern_return_t 285DNBArchMachARM::SetGPRState() 286{ 287 int set = e_regSetGPR; 288 kern_return_t kret = ::thread_set_state(m_thread->ThreadID(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, ARM_THREAD_STATE_COUNT); 289 m_state.SetError(set, Write, kret); // Set the current write error for this register set 290 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently 291 return kret; // Return the error code 292} 293 294kern_return_t 295DNBArchMachARM::SetVFPState() 296{ 297 int set = e_regSetVFP; 298 kern_return_t kret = ::thread_set_state (m_thread->ThreadID(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, ARM_VFP_STATE_COUNT); 299 m_state.SetError(set, Write, kret); // Set the current write error for this register set 300 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently 301 return kret; // Return the error code 302} 303 304kern_return_t 305DNBArchMachARM::SetEXCState() 306{ 307 int set = e_regSetEXC; 308 kern_return_t kret = ::thread_set_state (m_thread->ThreadID(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, ARM_EXCEPTION_STATE_COUNT); 309 m_state.SetError(set, Write, kret); // Set the current write error for this register set 310 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently 311 return kret; // Return the error code 312} 313 314kern_return_t 315DNBArchMachARM::SetDBGState() 316{ 317 int set = e_regSetDBG; 318 kern_return_t kret = ::thread_set_state (m_thread->ThreadID(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT); 319 m_state.SetError(set, Write, kret); // Set the current write error for this register set 320 m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently 321 return kret; // Return the error code 322} 323 324void 325DNBArchMachARM::ThreadWillResume() 326{ 327 // Do we need to step this thread? If so, let the mach thread tell us so. 328 if (m_thread->IsStepping()) 329 { 330 bool step_handled = false; 331 // This is the primary thread, let the arch do anything it needs 332 if (NumSupportedHardwareBreakpoints() > 0) 333 { 334#if defined (DNB_ARCH_MACH_ARM_DEBUG_SW_STEP) 335 bool half_step = m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS; 336#endif 337 step_handled = EnableHardwareSingleStep(true) == KERN_SUCCESS; 338#if defined (DNB_ARCH_MACH_ARM_DEBUG_SW_STEP) 339 if (!half_step) 340 step_handled = false; 341#endif 342 } 343 344 if (!step_handled) 345 { 346 SetSingleStepSoftwareBreakpoints(); 347 } 348 } 349 350 // Reset the method of debug entry field of the DSCR, if necessary, before we resume. 351 if (HasWatchpointOccurred()) 352 { 353 ClearWatchpointOccurred(); 354 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() ClearWatchpointOccurred() called"); 355 } 356} 357 358bool 359DNBArchMachARM::ThreadDidStop() 360{ 361 bool success = true; 362 363 m_state.InvalidateRegisterSetState (e_regSetALL); 364 365 // Are we stepping a single instruction? 366 if (GetGPRState(true) == KERN_SUCCESS) 367 { 368 // We are single stepping, was this the primary thread? 369 if (m_thread->IsStepping()) 370 { 371#if defined (DNB_ARCH_MACH_ARM_DEBUG_SW_STEP) 372 success = EnableHardwareSingleStep(false) == KERN_SUCCESS; 373 // Hardware single step must work if we are going to test software 374 // single step functionality 375 assert(success); 376 if (m_hw_single_chained_step_addr == INVALID_NUB_ADDRESS && m_sw_single_step_next_pc != INVALID_NUB_ADDRESS) 377 { 378 uint32_t sw_step_next_pc = m_sw_single_step_next_pc & 0xFFFFFFFEu; 379 bool sw_step_next_pc_is_thumb = (m_sw_single_step_next_pc & 1) != 0; 380 bool actual_next_pc_is_thumb = (m_state.context.gpr.__cpsr & 0x20) != 0; 381 if (m_state.context.gpr.__pc != sw_step_next_pc) 382 { 383 DNBLogError("curr pc = 0x%8.8x - calculated single step target PC was incorrect: 0x%8.8x != 0x%8.8x", m_state.context.gpr.__pc, sw_step_next_pc, m_state.context.gpr.__pc); 384 exit(1); 385 } 386 if (actual_next_pc_is_thumb != sw_step_next_pc_is_thumb) 387 { 388 DNBLogError("curr pc = 0x%8.8x - calculated single step calculated mode mismatch: sw single mode = %s != %s", 389 m_state.context.gpr.__pc, 390 actual_next_pc_is_thumb ? "Thumb" : "ARM", 391 sw_step_next_pc_is_thumb ? "Thumb" : "ARM"); 392 exit(1); 393 } 394 m_sw_single_step_next_pc = INVALID_NUB_ADDRESS; 395 } 396#else 397 // Are we software single stepping? 398 if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_break_id) || m_sw_single_step_itblock_break_count) 399 { 400 // Remove any software single stepping breakpoints that we have set 401 402 // Do we have a normal software single step breakpoint? 403 if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_break_id)) 404 { 405 DNBLogThreadedIf(LOG_STEP, "%s: removing software single step breakpoint (breakID=%d)", __FUNCTION__, m_sw_single_step_break_id); 406 success = m_thread->Process()->DisableBreakpoint(m_sw_single_step_break_id, true); 407 m_sw_single_step_break_id = INVALID_NUB_BREAK_ID; 408 } 409 410 // Do we have any Thumb IT breakpoints? 411 if (m_sw_single_step_itblock_break_count > 0) 412 { 413 // See if we hit one of our Thumb IT breakpoints? 414 DNBBreakpoint *step_bp = m_thread->Process()->Breakpoints().FindByAddress(m_state.context.gpr.__pc); 415 416 if (step_bp) 417 { 418 // We did hit our breakpoint, tell the breakpoint it was 419 // hit so that it can run its callback routine and fixup 420 // the PC. 421 DNBLogThreadedIf(LOG_STEP, "%s: IT software single step breakpoint hit (breakID=%u)", __FUNCTION__, step_bp->GetID()); 422 step_bp->BreakpointHit(m_thread->Process()->ProcessID(), m_thread->ThreadID()); 423 } 424 425 // Remove all Thumb IT breakpoints 426 for (int i = 0; i < m_sw_single_step_itblock_break_count; i++) 427 { 428 if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i])) 429 { 430 DNBLogThreadedIf(LOG_STEP, "%s: removing IT software single step breakpoint (breakID=%d)", __FUNCTION__, m_sw_single_step_itblock_break_id[i]); 431 success = m_thread->Process()->DisableBreakpoint(m_sw_single_step_itblock_break_id[i], true); 432 m_sw_single_step_itblock_break_id[i] = INVALID_NUB_BREAK_ID; 433 } 434 } 435 m_sw_single_step_itblock_break_count = 0; 436 437#if defined (USE_ARM_DISASSEMBLER_FRAMEWORK) 438 439 // Decode instructions up to the current PC to ensure the internal decoder state is valid for the IT block 440 // The decoder has to decode each instruction in the IT block even if it is not executed so that 441 // the fields are correctly updated 442 DecodeITBlockInstructions(m_state.context.gpr.__pc); 443#endif 444 } 445 446 } 447 else 448 success = EnableHardwareSingleStep(false) == KERN_SUCCESS; 449#endif 450 } 451 else 452 { 453 // The MachThread will automatically restore the suspend count 454 // in ThreadDidStop(), so we don't need to do anything here if 455 // we weren't the primary thread the last time 456 } 457 } 458 return success; 459} 460 461bool 462DNBArchMachARM::NotifyException(MachException::Data& exc) 463{ 464 switch (exc.exc_type) 465 { 466 default: 467 break; 468 case EXC_BREAKPOINT: 469 if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) 470 { 471 // exc_code = EXC_ARM_WATCHPOINT 472 // 473 // Check whether this corresponds to a watchpoint hit event. 474 // If yes, set the exc_sub_code to the data break address. 475 if (!HasWatchpointOccurred()) 476 break; 477 nub_addr_t addr = 0; 478 uint32_t hw_index = GetHardwareWatchpointHit(addr); 479 if (hw_index != INVALID_NUB_HW_INDEX) 480 { 481 exc.exc_data[1] = addr; 482 // Piggyback the hw_index in the exc.data. 483 exc.exc_data.push_back(hw_index); 484 } 485 486 return true; 487 } 488 break; 489 } 490 return false; 491} 492 493bool 494DNBArchMachARM::StepNotComplete () 495{ 496 if (m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS) 497 { 498 kern_return_t kret = KERN_INVALID_ARGUMENT; 499 kret = GetGPRState(false); 500 if (kret == KERN_SUCCESS) 501 { 502 if (m_state.context.gpr.__pc == m_hw_single_chained_step_addr) 503 { 504 DNBLogThreadedIf(LOG_STEP, "Need to step some more at 0x%8.8x", m_hw_single_chained_step_addr); 505 return true; 506 } 507 } 508 } 509 510 m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; 511 return false; 512} 513 514 515#if defined (USE_ARM_DISASSEMBLER_FRAMEWORK) 516 517void 518DNBArchMachARM::DecodeITBlockInstructions(nub_addr_t curr_pc) 519 520{ 521 uint16_t opcode16; 522 uint32_t opcode32; 523 nub_addr_t next_pc_in_itblock; 524 nub_addr_t pc_in_itblock = m_last_decode_pc; 525 526 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: last_decode_pc=0x%8.8x", __FUNCTION__, m_last_decode_pc); 527 528 // Decode IT block instruction from the instruction following the m_last_decoded_instruction at 529 // PC m_last_decode_pc upto and including the instruction at curr_pc 530 if (m_thread->Process()->Task().ReadMemory(pc_in_itblock, 2, &opcode16) == 2) 531 { 532 opcode32 = opcode16; 533 pc_in_itblock += 2; 534 // Check for 32 bit thumb opcode and read the upper 16 bits if needed 535 if (((opcode32 & 0xE000) == 0xE000) && opcode32 & 0x1800) 536 { 537 // Adjust 'next_pc_in_itblock' to point to the default next Thumb instruction for 538 // a 32 bit Thumb opcode 539 // Read bits 31:16 of a 32 bit Thumb opcode 540 if (m_thread->Process()->Task().ReadMemory(pc_in_itblock, 2, &opcode16) == 2) 541 { 542 pc_in_itblock += 2; 543 // 32 bit thumb opcode 544 opcode32 = (opcode32 << 16) | opcode16; 545 } 546 else 547 { 548 DNBLogError("%s: Unable to read opcode bits 31:16 for a 32 bit thumb opcode at pc=0x%8.8llx", __FUNCTION__, (uint64_t)pc_in_itblock); 549 } 550 } 551 } 552 else 553 { 554 DNBLogError("%s: Error reading 16-bit Thumb instruction at pc=0x%8.8x", __FUNCTION__, pc_in_itblock); 555 } 556 557 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: pc_in_itblock=0x%8.8x, curr_pc=0x%8.8x", __FUNCTION__, pc_in_itblock, curr_pc); 558 559 next_pc_in_itblock = pc_in_itblock; 560 while (next_pc_in_itblock <= curr_pc) 561 { 562 arm_error_t decodeError; 563 564 m_last_decode_pc = pc_in_itblock; 565 decodeError = DecodeInstructionUsingDisassembler(pc_in_itblock, m_state.context.gpr.__cpsr, &m_last_decode_arm, &m_last_decode_thumb, &next_pc_in_itblock); 566 567 pc_in_itblock = next_pc_in_itblock; 568 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: next_pc_in_itblock=0x%8.8x", __FUNCTION__, next_pc_in_itblock); 569 } 570} 571#endif 572 573// Set the single step bit in the processor status register. 574kern_return_t 575DNBArchMachARM::EnableHardwareSingleStep (bool enable) 576{ 577 DNBError err; 578 DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable); 579 580 err = GetGPRState(false); 581 582 if (err.Fail()) 583 { 584 err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__); 585 return err.Error(); 586 } 587 588 err = GetDBGState(false); 589 590 if (err.Fail()) 591 { 592 err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__); 593 return err.Error(); 594 } 595 596 const uint32_t i = 0; 597 if (enable) 598 { 599 m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; 600 601 // Save our previous state 602 m_dbg_save = m_state.dbg; 603 // Set a breakpoint that will stop when the PC doesn't match the current one! 604 m_state.dbg.__bvr[i] = m_state.context.gpr.__pc & 0xFFFFFFFCu; // Set the current PC as the breakpoint address 605 m_state.dbg.__bcr[i] = BCR_M_IMVA_MISMATCH | // Stop on address mismatch 606 S_USER | // Stop only in user mode 607 BCR_ENABLE; // Enable this breakpoint 608 if (m_state.context.gpr.__cpsr & 0x20) 609 { 610 // Thumb breakpoint 611 if (m_state.context.gpr.__pc & 2) 612 m_state.dbg.__bcr[i] |= BAS_IMVA_2_3; 613 else 614 m_state.dbg.__bcr[i] |= BAS_IMVA_0_1; 615 616 uint16_t opcode; 617 if (sizeof(opcode) == m_thread->Process()->Task().ReadMemory(m_state.context.gpr.__pc, sizeof(opcode), &opcode)) 618 { 619 if (((opcode & 0xE000) == 0xE000) && opcode & 0x1800) 620 { 621 // 32 bit thumb opcode... 622 if (m_state.context.gpr.__pc & 2) 623 { 624 // We can't take care of a 32 bit thumb instruction single step 625 // with just IVA mismatching. We will need to chain an extra 626 // hardware single step in order to complete this single step... 627 m_hw_single_chained_step_addr = m_state.context.gpr.__pc + 2; 628 } 629 else 630 { 631 // Extend the number of bits to ignore for the mismatch 632 m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; 633 } 634 } 635 } 636 } 637 else 638 { 639 // ARM breakpoint 640 m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; // Stop when any address bits change 641 } 642 643 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]); 644 645 for (uint32_t j=i+1; j<16; ++j) 646 { 647 // Disable all others 648 m_state.dbg.__bvr[j] = 0; 649 m_state.dbg.__bcr[j] = 0; 650 } 651 } 652 else 653 { 654 // Just restore the state we had before we did single stepping 655 m_state.dbg = m_dbg_save; 656 } 657 658 return SetDBGState(); 659} 660 661// return 1 if bit "BIT" is set in "value" 662static inline uint32_t bit(uint32_t value, uint32_t bit) 663{ 664 return (value >> bit) & 1u; 665} 666 667// return the bitfield "value[msbit:lsbit]". 668static inline uint32_t bits(uint32_t value, uint32_t msbit, uint32_t lsbit) 669{ 670 assert(msbit >= lsbit); 671 uint32_t shift_left = sizeof(value) * 8 - 1 - msbit; 672 value <<= shift_left; // shift anything above the msbit off of the unsigned edge 673 value >>= shift_left + lsbit; // shift it back again down to the lsbit (including undoing any shift from above) 674 return value; // return our result 675} 676 677bool 678DNBArchMachARM::ConditionPassed(uint8_t condition, uint32_t cpsr) 679{ 680 uint32_t cpsr_n = bit(cpsr, 31); // Negative condition code flag 681 uint32_t cpsr_z = bit(cpsr, 30); // Zero condition code flag 682 uint32_t cpsr_c = bit(cpsr, 29); // Carry condition code flag 683 uint32_t cpsr_v = bit(cpsr, 28); // Overflow condition code flag 684 685 switch (condition) { 686 case COND_EQ: // (0x0) 687 if (cpsr_z == 1) return true; 688 break; 689 case COND_NE: // (0x1) 690 if (cpsr_z == 0) return true; 691 break; 692 case COND_CS: // (0x2) 693 if (cpsr_c == 1) return true; 694 break; 695 case COND_CC: // (0x3) 696 if (cpsr_c == 0) return true; 697 break; 698 case COND_MI: // (0x4) 699 if (cpsr_n == 1) return true; 700 break; 701 case COND_PL: // (0x5) 702 if (cpsr_n == 0) return true; 703 break; 704 case COND_VS: // (0x6) 705 if (cpsr_v == 1) return true; 706 break; 707 case COND_VC: // (0x7) 708 if (cpsr_v == 0) return true; 709 break; 710 case COND_HI: // (0x8) 711 if ((cpsr_c == 1) && (cpsr_z == 0)) return true; 712 break; 713 case COND_LS: // (0x9) 714 if ((cpsr_c == 0) || (cpsr_z == 1)) return true; 715 break; 716 case COND_GE: // (0xA) 717 if (cpsr_n == cpsr_v) return true; 718 break; 719 case COND_LT: // (0xB) 720 if (cpsr_n != cpsr_v) return true; 721 break; 722 case COND_GT: // (0xC) 723 if ((cpsr_z == 0) && (cpsr_n == cpsr_v)) return true; 724 break; 725 case COND_LE: // (0xD) 726 if ((cpsr_z == 1) || (cpsr_n != cpsr_v)) return true; 727 break; 728 default: 729 return true; 730 break; 731 } 732 733 return false; 734} 735 736#if defined (USE_ARM_DISASSEMBLER_FRAMEWORK) 737 738bool 739DNBArchMachARM::ComputeNextPC(nub_addr_t currentPC, arm_decoded_instruction_t decodedInstruction, bool currentPCIsThumb, nub_addr_t *targetPC) 740{ 741 nub_addr_t myTargetPC, addressWherePCLives; 742 pid_t mypid; 743 744 uint32_t cpsr_c = bit(m_state.context.gpr.__cpsr, 29); // Carry condition code flag 745 746 uint32_t firstOperand=0, secondOperand=0, shiftAmount=0, secondOperandAfterShift=0, immediateValue=0; 747 uint32_t halfwords=0, baseAddress=0, immediateOffset=0, addressOffsetFromRegister=0, addressOffsetFromRegisterAfterShift; 748 uint32_t baseAddressIndex=INVALID_NUB_HW_INDEX; 749 uint32_t firstOperandIndex=INVALID_NUB_HW_INDEX; 750 uint32_t secondOperandIndex=INVALID_NUB_HW_INDEX; 751 uint32_t addressOffsetFromRegisterIndex=INVALID_NUB_HW_INDEX; 752 uint32_t shiftRegisterIndex=INVALID_NUB_HW_INDEX; 753 uint16_t registerList16, registerList16NoPC; 754 uint8_t registerList8; 755 uint32_t numRegistersToLoad=0; 756 757 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: instruction->code=%d", __FUNCTION__, decodedInstruction.instruction->code); 758 759 // Get the following in this switch statement: 760 // - firstOperand, secondOperand, immediateValue, shiftAmount: For arithmetic, logical and move instructions 761 // - baseAddress, immediateOffset, shiftAmount: For LDR 762 // - numRegistersToLoad: For LDM and POP instructions 763 switch (decodedInstruction.instruction->code) 764 { 765 // Arithmetic operations that can change the PC 766 case ARM_INST_ADC: 767 case ARM_INST_ADCS: 768 case ARM_INST_ADD: 769 case ARM_INST_ADDS: 770 case ARM_INST_AND: 771 case ARM_INST_ANDS: 772 case ARM_INST_ASR: 773 case ARM_INST_ASRS: 774 case ARM_INST_BIC: 775 case ARM_INST_BICS: 776 case ARM_INST_EOR: 777 case ARM_INST_EORS: 778 case ARM_INST_ORR: 779 case ARM_INST_ORRS: 780 case ARM_INST_RSB: 781 case ARM_INST_RSBS: 782 case ARM_INST_RSC: 783 case ARM_INST_RSCS: 784 case ARM_INST_SBC: 785 case ARM_INST_SBCS: 786 case ARM_INST_SUB: 787 case ARM_INST_SUBS: 788 switch (decodedInstruction.addressMode) 789 { 790 case ARM_ADDR_DATA_IMM: 791 if (decodedInstruction.numOperands != 3) 792 { 793 DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 794 return false; 795 } 796 797 if (decodedInstruction.op[0].value != PC_REG) 798 { 799 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 800 return false; 801 } 802 803 // Get firstOperand register value (at index=1) 804 firstOperandIndex = decodedInstruction.op[1].value; // first operand register index 805 firstOperand = m_state.context.gpr.__r[firstOperandIndex]; 806 807 // Get immediateValue (at index=2) 808 immediateValue = decodedInstruction.op[2].value; 809 810 break; 811 812 case ARM_ADDR_DATA_REG: 813 if (decodedInstruction.numOperands != 3) 814 { 815 DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 816 return false; 817 } 818 819 if (decodedInstruction.op[0].value != PC_REG) 820 { 821 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 822 return false; 823 } 824 825 // Get firstOperand register value (at index=1) 826 firstOperandIndex = decodedInstruction.op[1].value; // first operand register index 827 firstOperand = m_state.context.gpr.__r[firstOperandIndex]; 828 829 // Get secondOperand register value (at index=2) 830 secondOperandIndex = decodedInstruction.op[2].value; // second operand register index 831 secondOperand = m_state.context.gpr.__r[secondOperandIndex]; 832 833 break; 834 835 case ARM_ADDR_DATA_SCALED_IMM: 836 if (decodedInstruction.numOperands != 4) 837 { 838 DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 839 return false; 840 } 841 842 if (decodedInstruction.op[0].value != PC_REG) 843 { 844 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 845 return false; 846 } 847 848 // Get firstOperand register value (at index=1) 849 firstOperandIndex = decodedInstruction.op[1].value; // first operand register index 850 firstOperand = m_state.context.gpr.__r[firstOperandIndex]; 851 852 // Get secondOperand register value (at index=2) 853 secondOperandIndex = decodedInstruction.op[2].value; // second operand register index 854 secondOperand = m_state.context.gpr.__r[secondOperandIndex]; 855 856 // Get shiftAmount as immediate value (at index=3) 857 shiftAmount = decodedInstruction.op[3].value; 858 859 break; 860 861 862 case ARM_ADDR_DATA_SCALED_REG: 863 if (decodedInstruction.numOperands != 4) 864 { 865 DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 866 return false; 867 } 868 869 if (decodedInstruction.op[0].value != PC_REG) 870 { 871 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 872 return false; 873 } 874 875 // Get firstOperand register value (at index=1) 876 firstOperandIndex = decodedInstruction.op[1].value; // first operand register index 877 firstOperand = m_state.context.gpr.__r[firstOperandIndex]; 878 879 // Get secondOperand register value (at index=2) 880 secondOperandIndex = decodedInstruction.op[2].value; // second operand register index 881 secondOperand = m_state.context.gpr.__r[secondOperandIndex]; 882 883 // Get shiftAmount from register (at index=3) 884 shiftRegisterIndex = decodedInstruction.op[3].value; // second operand register index 885 shiftAmount = m_state.context.gpr.__r[shiftRegisterIndex]; 886 887 break; 888 889 case THUMB_ADDR_HR_HR: 890 if (decodedInstruction.numOperands != 2) 891 { 892 DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 893 return false; 894 } 895 896 if (decodedInstruction.op[0].value != PC_REG) 897 { 898 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 899 return false; 900 } 901 902 // Get firstOperand register value (at index=0) 903 firstOperandIndex = decodedInstruction.op[0].value; // first operand register index 904 firstOperand = m_state.context.gpr.__r[firstOperandIndex]; 905 906 // Get secondOperand register value (at index=1) 907 secondOperandIndex = decodedInstruction.op[1].value; // second operand register index 908 secondOperand = m_state.context.gpr.__r[secondOperandIndex]; 909 910 break; 911 912 default: 913 break; 914 } 915 break; 916 917 // Logical shifts and move operations that can change the PC 918 case ARM_INST_LSL: 919 case ARM_INST_LSLS: 920 case ARM_INST_LSR: 921 case ARM_INST_LSRS: 922 case ARM_INST_MOV: 923 case ARM_INST_MOVS: 924 case ARM_INST_MVN: 925 case ARM_INST_MVNS: 926 case ARM_INST_ROR: 927 case ARM_INST_RORS: 928 case ARM_INST_RRX: 929 case ARM_INST_RRXS: 930 // In these cases, the firstOperand is always 0, as if it does not exist 931 switch (decodedInstruction.addressMode) 932 { 933 case ARM_ADDR_DATA_IMM: 934 if (decodedInstruction.numOperands != 2) 935 { 936 DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 937 return false; 938 } 939 940 if (decodedInstruction.op[0].value != PC_REG) 941 { 942 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 943 return false; 944 } 945 946 // Get immediateValue (at index=1) 947 immediateValue = decodedInstruction.op[1].value; 948 949 break; 950 951 case ARM_ADDR_DATA_REG: 952 if (decodedInstruction.numOperands != 2) 953 { 954 DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 955 return false; 956 } 957 958 if (decodedInstruction.op[0].value != PC_REG) 959 { 960 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 961 return false; 962 } 963 964 // Get secondOperand register value (at index=1) 965 secondOperandIndex = decodedInstruction.op[1].value; // second operand register index 966 secondOperand = m_state.context.gpr.__r[secondOperandIndex]; 967 968 break; 969 970 case ARM_ADDR_DATA_SCALED_IMM: 971 if (decodedInstruction.numOperands != 3) 972 { 973 DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 974 return false; 975 } 976 977 if (decodedInstruction.op[0].value != PC_REG) 978 { 979 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 980 return false; 981 } 982 983 // Get secondOperand register value (at index=1) 984 secondOperandIndex = decodedInstruction.op[2].value; // second operand register index 985 secondOperand = m_state.context.gpr.__r[secondOperandIndex]; 986 987 // Get shiftAmount as immediate value (at index=2) 988 shiftAmount = decodedInstruction.op[2].value; 989 990 break; 991 992 993 case ARM_ADDR_DATA_SCALED_REG: 994 if (decodedInstruction.numOperands != 3) 995 { 996 DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 997 return false; 998 } 999 1000 if (decodedInstruction.op[0].value != PC_REG) 1001 { 1002 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 1003 return false; 1004 } 1005 1006 // Get secondOperand register value (at index=1) 1007 secondOperandIndex = decodedInstruction.op[1].value; // second operand register index 1008 secondOperand = m_state.context.gpr.__r[secondOperandIndex]; 1009 1010 // Get shiftAmount from register (at index=2) 1011 shiftRegisterIndex = decodedInstruction.op[2].value; // second operand register index 1012 shiftAmount = m_state.context.gpr.__r[shiftRegisterIndex]; 1013 1014 break; 1015 1016 case THUMB_ADDR_HR_HR: 1017 if (decodedInstruction.numOperands != 2) 1018 { 1019 DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 1020 return false; 1021 } 1022 1023 if (decodedInstruction.op[0].value != PC_REG) 1024 { 1025 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 1026 return false; 1027 } 1028 1029 // Get secondOperand register value (at index=1) 1030 secondOperandIndex = decodedInstruction.op[1].value; // second operand register index 1031 secondOperand = m_state.context.gpr.__r[secondOperandIndex]; 1032 1033 break; 1034 1035 default: 1036 break; 1037 } 1038 1039 break; 1040 1041 // Simple branches, used to hop around within a routine 1042 case ARM_INST_B: 1043 *targetPC = decodedInstruction.targetPC; // Known targetPC 1044 return true; 1045 break; 1046 1047 // Branch-and-link, used to call ARM subroutines 1048 case ARM_INST_BL: 1049 *targetPC = decodedInstruction.targetPC; // Known targetPC 1050 return true; 1051 break; 1052 1053 // Branch-and-link with exchange, used to call opposite-mode subroutines 1054 case ARM_INST_BLX: 1055 if ((decodedInstruction.addressMode == ARM_ADDR_BRANCH_IMM) || 1056 (decodedInstruction.addressMode == THUMB_ADDR_UNCOND)) 1057 { 1058 *targetPC = decodedInstruction.targetPC; // Known targetPC 1059 return true; 1060 } 1061 else // addressMode == ARM_ADDR_BRANCH_REG 1062 { 1063 // Unknown target unless we're branching to the PC itself, 1064 // although this may not work properly with BLX 1065 if (decodedInstruction.op[REG_RD].value == PC_REG) 1066 { 1067 // this should (almost) never happen 1068 *targetPC = decodedInstruction.targetPC; // Known targetPC 1069 return true; 1070 } 1071 1072 // Get the branch address and return 1073 if (decodedInstruction.numOperands != 1) 1074 { 1075 DNBLogError("Expected 1 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 1076 return false; 1077 } 1078 1079 // Get branch address in register (at index=0) 1080 *targetPC = m_state.context.gpr.__r[decodedInstruction.op[0].value]; 1081 return true; 1082 } 1083 break; 1084 1085 // Branch with exchange, used to hop to opposite-mode code 1086 // Branch to Jazelle code, used to execute Java; included here since it 1087 // acts just like BX unless the Jazelle unit is active and JPC is 1088 // already loaded into it. 1089 case ARM_INST_BX: 1090 case ARM_INST_BXJ: 1091 // Unknown target unless we're branching to the PC itself, 1092 // although this can never switch to Thumb mode and is 1093 // therefore pretty much useless 1094 if (decodedInstruction.op[REG_RD].value == PC_REG) 1095 { 1096 // this should (almost) never happen 1097 *targetPC = decodedInstruction.targetPC; // Known targetPC 1098 return true; 1099 } 1100 1101 // Get the branch address and return 1102 if (decodedInstruction.numOperands != 1) 1103 { 1104 DNBLogError("Expected 1 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 1105 return false; 1106 } 1107 1108 // Get branch address in register (at index=0) 1109 *targetPC = m_state.context.gpr.__r[decodedInstruction.op[0].value]; 1110 return true; 1111 break; 1112 1113 // Compare and branch on zero/non-zero (Thumb-16 only) 1114 // Unusual condition check built into the instruction 1115 case ARM_INST_CBZ: 1116 case ARM_INST_CBNZ: 1117 // Branch address is known at compile time 1118 // Get the branch address and return 1119 if (decodedInstruction.numOperands != 2) 1120 { 1121 DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 1122 return false; 1123 } 1124 1125 // Get branch address as an immediate value (at index=1) 1126 *targetPC = decodedInstruction.op[1].value; 1127 return true; 1128 break; 1129 1130 // Load register can be used to load PC, usually with a function pointer 1131 case ARM_INST_LDR: 1132 if (decodedInstruction.op[REG_RD].value != PC_REG) 1133 { 1134 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 1135 return false; 1136 } 1137 switch (decodedInstruction.addressMode) 1138 { 1139 case ARM_ADDR_LSWUB_IMM: 1140 case ARM_ADDR_LSWUB_IMM_PRE: 1141 case ARM_ADDR_LSWUB_IMM_POST: 1142 if (decodedInstruction.numOperands != 3) 1143 { 1144 DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 1145 return false; 1146 } 1147 1148 // Get baseAddress from register (at index=1) 1149 baseAddressIndex = decodedInstruction.op[1].value; 1150 baseAddress = m_state.context.gpr.__r[baseAddressIndex]; 1151 1152 // Get immediateOffset (at index=2) 1153 immediateOffset = decodedInstruction.op[2].value; 1154 break; 1155 1156 case ARM_ADDR_LSWUB_REG: 1157 case ARM_ADDR_LSWUB_REG_PRE: 1158 case ARM_ADDR_LSWUB_REG_POST: 1159 if (decodedInstruction.numOperands != 3) 1160 { 1161 DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 1162 return false; 1163 } 1164 1165 // Get baseAddress from register (at index=1) 1166 baseAddressIndex = decodedInstruction.op[1].value; 1167 baseAddress = m_state.context.gpr.__r[baseAddressIndex]; 1168 1169 // Get immediateOffset from register (at index=2) 1170 addressOffsetFromRegisterIndex = decodedInstruction.op[2].value; 1171 addressOffsetFromRegister = m_state.context.gpr.__r[addressOffsetFromRegisterIndex]; 1172 1173 break; 1174 1175 case ARM_ADDR_LSWUB_SCALED: 1176 case ARM_ADDR_LSWUB_SCALED_PRE: 1177 case ARM_ADDR_LSWUB_SCALED_POST: 1178 if (decodedInstruction.numOperands != 4) 1179 { 1180 DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 1181 return false; 1182 } 1183 1184 // Get baseAddress from register (at index=1) 1185 baseAddressIndex = decodedInstruction.op[1].value; 1186 baseAddress = m_state.context.gpr.__r[baseAddressIndex]; 1187 1188 // Get immediateOffset from register (at index=2) 1189 addressOffsetFromRegisterIndex = decodedInstruction.op[2].value; 1190 addressOffsetFromRegister = m_state.context.gpr.__r[addressOffsetFromRegisterIndex]; 1191 1192 // Get shiftAmount (at index=3) 1193 shiftAmount = decodedInstruction.op[3].value; 1194 1195 break; 1196 1197 default: 1198 break; 1199 } 1200 break; 1201 1202 // 32b load multiple operations can load the PC along with everything else, 1203 // usually to return from a function call 1204 case ARM_INST_LDMDA: 1205 case ARM_INST_LDMDB: 1206 case ARM_INST_LDMIA: 1207 case ARM_INST_LDMIB: 1208 if (decodedInstruction.op[LDM_REGLIST].value & PC_REGLIST_BIT) 1209 { 1210 if (decodedInstruction.numOperands != 2) 1211 { 1212 DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands); 1213 return false; 1214 } 1215 1216 // Get baseAddress from register (at index=0) 1217 baseAddressIndex = decodedInstruction.op[0].value; 1218 baseAddress = m_state.context.gpr.__r[baseAddressIndex]; 1219 1220 // Get registerList from register (at index=1) 1221 registerList16 = (uint16_t)decodedInstruction.op[1].value; 1222 1223 // Count number of registers to load in the multiple register list excluding the PC 1224 registerList16NoPC = registerList16&0x3FFF; // exclude the PC 1225 numRegistersToLoad=0; 1226 for (int i = 0; i < 16; i++) 1227 { 1228 if (registerList16NoPC & 0x1) numRegistersToLoad++; 1229 registerList16NoPC = registerList16NoPC >> 1; 1230 } 1231 } 1232 else 1233 { 1234 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value); 1235 return false; 1236 } 1237 break; 1238 1239 // Normal 16-bit LD multiple can't touch R15, but POP can 1240 case ARM_INST_POP: // Can also get the PC & updates SP 1241 // Get baseAddress from SP (at index=0) 1242 baseAddress = m_state.context.gpr.__sp; 1243 1244 if (decodedInstruction.thumb16b) 1245 { 1246 // Get registerList from register (at index=0) 1247 registerList8 = (uint8_t)decodedInstruction.op[0].value; 1248 1249 // Count number of registers to load in the multiple register list 1250 numRegistersToLoad=0; 1251 for (int i = 0; i < 8; i++) 1252 { 1253 if (registerList8 & 0x1) numRegistersToLoad++; 1254 registerList8 = registerList8 >> 1; 1255 } 1256 } 1257 else 1258 { 1259 // Get registerList from register (at index=0) 1260 registerList16 = (uint16_t)decodedInstruction.op[0].value; 1261 1262 // Count number of registers to load in the multiple register list excluding the PC 1263 registerList16NoPC = registerList16&0x3FFF; // exclude the PC 1264 numRegistersToLoad=0; 1265 for (int i = 0; i < 16; i++) 1266 { 1267 if (registerList16NoPC & 0x1) numRegistersToLoad++; 1268 registerList16NoPC = registerList16NoPC >> 1; 1269 } 1270 } 1271 break; 1272 1273 // 16b TBB and TBH instructions load a jump address from a table 1274 case ARM_INST_TBB: 1275 case ARM_INST_TBH: 1276 // Get baseAddress from register (at index=0) 1277 baseAddressIndex = decodedInstruction.op[0].value; 1278 baseAddress = m_state.context.gpr.__r[baseAddressIndex]; 1279 1280 // Get immediateOffset from register (at index=1) 1281 addressOffsetFromRegisterIndex = decodedInstruction.op[1].value; 1282 addressOffsetFromRegister = m_state.context.gpr.__r[addressOffsetFromRegisterIndex]; 1283 break; 1284 1285 // ThumbEE branch-to-handler instructions: Jump to handlers at some offset 1286 // from a special base pointer register (which is unknown at disassembly time) 1287 case ARM_INST_HB: 1288 case ARM_INST_HBP: 1289// TODO: ARM_INST_HB, ARM_INST_HBP 1290 break; 1291 1292 case ARM_INST_HBL: 1293 case ARM_INST_HBLP: 1294// TODO: ARM_INST_HBL, ARM_INST_HBLP 1295 break; 1296 1297 // Breakpoint and software interrupt jump to interrupt handler (always ARM) 1298 case ARM_INST_BKPT: 1299 case ARM_INST_SMC: 1300 case ARM_INST_SVC: 1301 1302 // Return from exception, obviously modifies PC [interrupt only!] 1303 case ARM_INST_RFEDA: 1304 case ARM_INST_RFEDB: 1305 case ARM_INST_RFEIA: 1306 case ARM_INST_RFEIB: 1307 1308 // Other instructions either can't change R15 or are "undefined" if you do, 1309 // so no sane compiler should ever generate them & we don't care here. 1310 // Also, R15 can only legally be used in a read-only manner for the 1311 // various ARM addressing mode (to get PC-relative addressing of constants), 1312 // but can NOT be used with any of the update modes. 1313 default: 1314 DNBLogError("%s should not be called for instruction code %d!", __FUNCTION__, decodedInstruction.instruction->code); 1315 return false; 1316 break; 1317 } 1318 1319 // Adjust PC if PC is one of the input operands 1320 if (baseAddressIndex == PC_REG) 1321 { 1322 if (currentPCIsThumb) 1323 baseAddress += 4; 1324 else 1325 baseAddress += 8; 1326 } 1327 1328 if (firstOperandIndex == PC_REG) 1329 { 1330 if (currentPCIsThumb) 1331 firstOperand += 4; 1332 else 1333 firstOperand += 8; 1334 } 1335 1336 if (secondOperandIndex == PC_REG) 1337 { 1338 if (currentPCIsThumb) 1339 secondOperand += 4; 1340 else 1341 secondOperand += 8; 1342 } 1343 1344 if (addressOffsetFromRegisterIndex == PC_REG) 1345 { 1346 if (currentPCIsThumb) 1347 addressOffsetFromRegister += 4; 1348 else 1349 addressOffsetFromRegister += 8; 1350 } 1351 1352 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, 1353 "%s: firstOperand=%8.8x, secondOperand=%8.8x, immediateValue = %d, shiftAmount = %d, baseAddress = %8.8x, addressOffsetFromRegister = %8.8x, immediateOffset = %d, numRegistersToLoad = %d", 1354 __FUNCTION__, 1355 firstOperand, 1356 secondOperand, 1357 immediateValue, 1358 shiftAmount, 1359 baseAddress, 1360 addressOffsetFromRegister, 1361 immediateOffset, 1362 numRegistersToLoad); 1363 1364 1365 // Calculate following values after applying shiftAmount: 1366 // - immediateOffsetAfterShift, secondOperandAfterShift 1367 1368 switch (decodedInstruction.scaleMode) 1369 { 1370 case ARM_SCALE_NONE: 1371 addressOffsetFromRegisterAfterShift = addressOffsetFromRegister; 1372 secondOperandAfterShift = secondOperand; 1373 break; 1374 1375 case ARM_SCALE_LSL: // Logical shift left 1376 addressOffsetFromRegisterAfterShift = addressOffsetFromRegister << shiftAmount; 1377 secondOperandAfterShift = secondOperand << shiftAmount; 1378 break; 1379 1380 case ARM_SCALE_LSR: // Logical shift right 1381 addressOffsetFromRegisterAfterShift = addressOffsetFromRegister >> shiftAmount; 1382 secondOperandAfterShift = secondOperand >> shiftAmount; 1383 break; 1384 1385 case ARM_SCALE_ASR: // Arithmetic shift right 1386 asm("mov %0, %1, asr %2" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister), "r" (shiftAmount)); 1387 asm("mov %0, %1, asr %2" : "=r" (secondOperandAfterShift) : "r" (secondOperand), "r" (shiftAmount)); 1388 break; 1389 1390 case ARM_SCALE_ROR: // Rotate right 1391 asm("mov %0, %1, ror %2" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister), "r" (shiftAmount)); 1392 asm("mov %0, %1, ror %2" : "=r" (secondOperandAfterShift) : "r" (secondOperand), "r" (shiftAmount)); 1393 break; 1394 1395 case ARM_SCALE_RRX: // Rotate right, pulling in carry (1-bit shift only) 1396 asm("mov %0, %1, rrx" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister)); 1397 asm("mov %0, %1, rrx" : "=r" (secondOperandAfterShift) : "r" (secondOperand)); 1398 break; 1399 } 1400 1401 // Emulate instruction to calculate targetPC 1402 // All branches are already handled in the first switch statement. A branch should not reach this switch 1403 switch (decodedInstruction.instruction->code) 1404 { 1405 // Arithmetic operations that can change the PC 1406 case ARM_INST_ADC: 1407 case ARM_INST_ADCS: 1408 // Add with Carry 1409 *targetPC = firstOperand + (secondOperandAfterShift + immediateValue) + cpsr_c; 1410 break; 1411 1412 case ARM_INST_ADD: 1413 case ARM_INST_ADDS: 1414 *targetPC = firstOperand + (secondOperandAfterShift + immediateValue); 1415 break; 1416 1417 case ARM_INST_AND: 1418 case ARM_INST_ANDS: 1419 *targetPC = firstOperand & (secondOperandAfterShift + immediateValue); 1420 break; 1421 1422 case ARM_INST_ASR: 1423 case ARM_INST_ASRS: 1424 asm("mov %0, %1, asr %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue)); 1425 *targetPC = myTargetPC; 1426 break; 1427 1428 case ARM_INST_BIC: 1429 case ARM_INST_BICS: 1430 asm("bic %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue)); 1431 *targetPC = myTargetPC; 1432 break; 1433 1434 case ARM_INST_EOR: 1435 case ARM_INST_EORS: 1436 asm("eor %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue)); 1437 *targetPC = myTargetPC; 1438 break; 1439 1440 case ARM_INST_ORR: 1441 case ARM_INST_ORRS: 1442 asm("orr %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue)); 1443 *targetPC = myTargetPC; 1444 break; 1445 1446 case ARM_INST_RSB: 1447 case ARM_INST_RSBS: 1448 asm("rsb %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue)); 1449 *targetPC = myTargetPC; 1450 break; 1451 1452 case ARM_INST_RSC: 1453 case ARM_INST_RSCS: 1454 myTargetPC = secondOperandAfterShift - (firstOperand + !cpsr_c); 1455 *targetPC = myTargetPC; 1456 break; 1457 1458 case ARM_INST_SBC: 1459 case ARM_INST_SBCS: 1460 asm("sbc %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue + !cpsr_c)); 1461 *targetPC = myTargetPC; 1462 break; 1463 1464 case ARM_INST_SUB: 1465 case ARM_INST_SUBS: 1466 asm("sub %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue)); 1467 *targetPC = myTargetPC; 1468 break; 1469 1470 // Logical shifts and move operations that can change the PC 1471 case ARM_INST_LSL: 1472 case ARM_INST_LSLS: 1473 case ARM_INST_LSR: 1474 case ARM_INST_LSRS: 1475 case ARM_INST_MOV: 1476 case ARM_INST_MOVS: 1477 case ARM_INST_ROR: 1478 case ARM_INST_RORS: 1479 case ARM_INST_RRX: 1480 case ARM_INST_RRXS: 1481 myTargetPC = secondOperandAfterShift + immediateValue; 1482 *targetPC = myTargetPC; 1483 break; 1484 1485 case ARM_INST_MVN: 1486 case ARM_INST_MVNS: 1487 myTargetPC = !(secondOperandAfterShift + immediateValue); 1488 *targetPC = myTargetPC; 1489 break; 1490 1491 // Load register can be used to load PC, usually with a function pointer 1492 case ARM_INST_LDR: 1493 switch (decodedInstruction.addressMode) { 1494 case ARM_ADDR_LSWUB_IMM_POST: 1495 case ARM_ADDR_LSWUB_REG_POST: 1496 case ARM_ADDR_LSWUB_SCALED_POST: 1497 addressWherePCLives = baseAddress; 1498 break; 1499 1500 case ARM_ADDR_LSWUB_IMM: 1501 case ARM_ADDR_LSWUB_REG: 1502 case ARM_ADDR_LSWUB_SCALED: 1503 case ARM_ADDR_LSWUB_IMM_PRE: 1504 case ARM_ADDR_LSWUB_REG_PRE: 1505 case ARM_ADDR_LSWUB_SCALED_PRE: 1506 addressWherePCLives = baseAddress + (addressOffsetFromRegisterAfterShift + immediateOffset); 1507 break; 1508 1509 default: 1510 break; 1511 } 1512 1513 mypid = m_thread->ProcessID(); 1514 if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) != sizeof(nub_addr_t)) 1515 { 1516 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives); 1517 return false; 1518 } 1519 1520 *targetPC = myTargetPC; 1521 break; 1522 1523 // 32b load multiple operations can load the PC along with everything else, 1524 // usually to return from a function call 1525 case ARM_INST_LDMDA: 1526 mypid = m_thread->ProcessID(); 1527 addressWherePCLives = baseAddress; 1528 if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) != sizeof(nub_addr_t)) 1529 { 1530 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives); 1531 return false; 1532 } 1533 1534 *targetPC = myTargetPC; 1535 break; 1536 1537 case ARM_INST_LDMDB: 1538 mypid = m_thread->ProcessID(); 1539 addressWherePCLives = baseAddress - 4; 1540 if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) != sizeof(nub_addr_t)) 1541 { 1542 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives); 1543 return false; 1544 } 1545 1546 *targetPC = myTargetPC; 1547 break; 1548 1549 case ARM_INST_LDMIB: 1550 mypid = m_thread->ProcessID(); 1551 addressWherePCLives = baseAddress + numRegistersToLoad*4 + 4; 1552 if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) != sizeof(nub_addr_t)) 1553 { 1554 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives); 1555 return false; 1556 } 1557 1558 *targetPC = myTargetPC; 1559 break; 1560 1561 case ARM_INST_LDMIA: // same as pop 1562 // Normal 16-bit LD multiple can't touch R15, but POP can 1563 case ARM_INST_POP: // Can also get the PC & updates SP 1564 mypid = m_thread->ProcessID(); 1565 addressWherePCLives = baseAddress + numRegistersToLoad*4; 1566 if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) != sizeof(nub_addr_t)) 1567 { 1568 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives); 1569 return false; 1570 } 1571 1572 *targetPC = myTargetPC; 1573 break; 1574 1575 // 16b TBB and TBH instructions load a jump address from a table 1576 case ARM_INST_TBB: 1577 mypid = m_thread->ProcessID(); 1578 addressWherePCLives = baseAddress + addressOffsetFromRegisterAfterShift; 1579 if (DNBProcessMemoryRead(mypid, addressWherePCLives, 1, &halfwords) != 1) 1580 { 1581 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the TBB instruction!", addressWherePCLives); 1582 return false; 1583 } 1584 // add 4 to currentPC since we are in Thumb mode and then add 2*halfwords 1585 *targetPC = (currentPC + 4) + 2*halfwords; 1586 break; 1587 1588 case ARM_INST_TBH: 1589 mypid = m_thread->ProcessID(); 1590 addressWherePCLives = ((baseAddress + (addressOffsetFromRegisterAfterShift << 1)) & ~0x1); 1591 if (DNBProcessMemoryRead(mypid, addressWherePCLives, 2, &halfwords) != 2) 1592 { 1593 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the TBH instruction!", addressWherePCLives); 1594 return false; 1595 } 1596 // add 4 to currentPC since we are in Thumb mode and then add 2*halfwords 1597 *targetPC = (currentPC + 4) + 2*halfwords; 1598 break; 1599 1600 // ThumbEE branch-to-handler instructions: Jump to handlers at some offset 1601 // from a special base pointer register (which is unknown at disassembly time) 1602 case ARM_INST_HB: 1603 case ARM_INST_HBP: 1604 // TODO: ARM_INST_HB, ARM_INST_HBP 1605 break; 1606 1607 case ARM_INST_HBL: 1608 case ARM_INST_HBLP: 1609 // TODO: ARM_INST_HBL, ARM_INST_HBLP 1610 break; 1611 1612 // Breakpoint and software interrupt jump to interrupt handler (always ARM) 1613 case ARM_INST_BKPT: 1614 case ARM_INST_SMC: 1615 case ARM_INST_SVC: 1616 // TODO: ARM_INST_BKPT, ARM_INST_SMC, ARM_INST_SVC 1617 break; 1618 1619 // Return from exception, obviously modifies PC [interrupt only!] 1620 case ARM_INST_RFEDA: 1621 case ARM_INST_RFEDB: 1622 case ARM_INST_RFEIA: 1623 case ARM_INST_RFEIB: 1624 // TODO: ARM_INST_RFEDA, ARM_INST_RFEDB, ARM_INST_RFEIA, ARM_INST_RFEIB 1625 break; 1626 1627 // Other instructions either can't change R15 or are "undefined" if you do, 1628 // so no sane compiler should ever generate them & we don't care here. 1629 // Also, R15 can only legally be used in a read-only manner for the 1630 // various ARM addressing mode (to get PC-relative addressing of constants), 1631 // but can NOT be used with any of the update modes. 1632 default: 1633 DNBLogError("%s should not be called for instruction code %d!", __FUNCTION__, decodedInstruction.instruction->code); 1634 return false; 1635 break; 1636 } 1637 1638 return true; 1639} 1640 1641void 1642DNBArchMachARM::EvaluateNextInstructionForSoftwareBreakpointSetup(nub_addr_t currentPC, uint32_t cpsr, bool currentPCIsThumb, nub_addr_t *nextPC, bool *nextPCIsThumb) 1643{ 1644 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "DNBArchMachARM::EvaluateNextInstructionForSoftwareBreakpointSetup() called"); 1645 1646 nub_addr_t targetPC = INVALID_NUB_ADDRESS; 1647 uint32_t registerValue; 1648 arm_error_t decodeError; 1649 nub_addr_t currentPCInITBlock, nextPCInITBlock; 1650 int i; 1651 bool last_decoded_instruction_executes = true; 1652 1653 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: default nextPC=0x%8.8x (%s)", __FUNCTION__, *nextPC, *nextPCIsThumb ? "Thumb" : "ARM"); 1654 1655 // Update *nextPC and *nextPCIsThumb for special cases 1656 if (m_last_decode_thumb.itBlockRemaining) // we are in an IT block 1657 { 1658 // Set the nextPC to the PC of the instruction which will execute in the IT block 1659 // If none of the instruction execute in the IT block based on the condition flags, 1660 // then point to the instruction immediately following the IT block 1661 const int itBlockRemaining = m_last_decode_thumb.itBlockRemaining; 1662 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: itBlockRemaining=%8.8x", __FUNCTION__, itBlockRemaining); 1663 1664 // Determine the PC at which the next instruction resides 1665 if (m_last_decode_arm.thumb16b) 1666 currentPCInITBlock = currentPC + 2; 1667 else 1668 currentPCInITBlock = currentPC + 4; 1669 1670 for (i = 0; i < itBlockRemaining; i++) 1671 { 1672 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: currentPCInITBlock=%8.8x", __FUNCTION__, currentPCInITBlock); 1673 decodeError = DecodeInstructionUsingDisassembler(currentPCInITBlock, cpsr, &m_last_decode_arm, &m_last_decode_thumb, &nextPCInITBlock); 1674 1675 if (decodeError != ARM_SUCCESS) 1676 DNBLogError("unable to disassemble instruction at 0x%8.8llx", (uint64_t)currentPCInITBlock); 1677 1678 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: condition=%d", __FUNCTION__, m_last_decode_arm.condition); 1679 if (ConditionPassed(m_last_decode_arm.condition, cpsr)) 1680 { 1681 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition codes matched for instruction %d", __FUNCTION__, i); 1682 break; // break from the for loop 1683 } 1684 else 1685 { 1686 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition codes DID NOT matched for instruction %d", __FUNCTION__, i); 1687 } 1688 1689 // update currentPC and nextPCInITBlock 1690 currentPCInITBlock = nextPCInITBlock; 1691 } 1692 1693 if (i == itBlockRemaining) // We came out of the IT block without executing any instructions 1694 last_decoded_instruction_executes = false; 1695 1696 *nextPC = currentPCInITBlock; 1697 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: After IT block step-through: *nextPC=%8.8x", __FUNCTION__, *nextPC); 1698 } 1699 1700 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, 1701 "%s: cpsr = %8.8x, thumb16b = %d, thumb = %d, branch = %d, conditional = %d, knownTarget = %d, links = %d, canSwitchMode = %d, doesSwitchMode = %d", 1702 __FUNCTION__, 1703 cpsr, 1704 m_last_decode_arm.thumb16b, 1705 m_last_decode_arm.thumb, 1706 m_last_decode_arm.branch, 1707 m_last_decode_arm.conditional, 1708 m_last_decode_arm.knownTarget, 1709 m_last_decode_arm.links, 1710 m_last_decode_arm.canSwitchMode, 1711 m_last_decode_arm.doesSwitchMode); 1712 1713 1714 if (last_decoded_instruction_executes && // Was this a conditional instruction that did execute? 1715 m_last_decode_arm.branch && // Can this instruction change the PC? 1716 (m_last_decode_arm.instruction->code != ARM_INST_SVC)) // If this instruction is not an SVC instruction 1717 { 1718 // Set targetPC. Compute if needed. 1719 if (m_last_decode_arm.knownTarget) 1720 { 1721 // Fixed, known PC-relative 1722 targetPC = m_last_decode_arm.targetPC; 1723 } 1724 else 1725 { 1726 // if targetPC is not known at compile time (PC-relative target), compute targetPC 1727 if (!ComputeNextPC(currentPC, m_last_decode_arm, currentPCIsThumb, &targetPC)) 1728 { 1729 DNBLogError("%s: Unable to compute targetPC for instruction at 0x%8.8llx", __FUNCTION__, (uint64_t)currentPC); 1730 targetPC = INVALID_NUB_ADDRESS; 1731 } 1732 } 1733 1734 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: targetPC=0x%8.8x, cpsr=0x%8.8x, condition=0x%hhx", __FUNCTION__, targetPC, cpsr, m_last_decode_arm.condition); 1735 1736 // Refine nextPC computation 1737 if ((m_last_decode_arm.instruction->code == ARM_INST_CBZ) || 1738 (m_last_decode_arm.instruction->code == ARM_INST_CBNZ)) 1739 { 1740 // Compare and branch on zero/non-zero (Thumb-16 only) 1741 // Unusual condition check built into the instruction 1742 registerValue = m_state.context.gpr.__r[m_last_decode_arm.op[REG_RD].value]; 1743 1744 if (m_last_decode_arm.instruction->code == ARM_INST_CBZ) 1745 { 1746 if (registerValue == 0) 1747 *nextPC = targetPC; 1748 } 1749 else 1750 { 1751 if (registerValue != 0) 1752 *nextPC = targetPC; 1753 } 1754 } 1755 else if (m_last_decode_arm.conditional) // Is the change conditional on flag results? 1756 { 1757 if (ConditionPassed(m_last_decode_arm.condition, cpsr)) // conditions match 1758 { 1759 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition matched!", __FUNCTION__); 1760 *nextPC = targetPC; 1761 } 1762 else 1763 { 1764 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition did not match!", __FUNCTION__); 1765 } 1766 } 1767 else 1768 { 1769 *nextPC = targetPC; 1770 } 1771 1772 // Refine nextPCIsThumb computation 1773 if (m_last_decode_arm.doesSwitchMode) 1774 { 1775 *nextPCIsThumb = !currentPCIsThumb; 1776 } 1777 else if (m_last_decode_arm.canSwitchMode) 1778 { 1779 // Legal to switch ARM <--> Thumb mode with this branch 1780 // dependent on bit[0] of targetPC 1781 *nextPCIsThumb = (*nextPC & 1u) != 0; 1782 } 1783 else 1784 { 1785 *nextPCIsThumb = currentPCIsThumb; 1786 } 1787 } 1788 1789 DNBLogThreadedIf(LOG_STEP, "%s: calculated nextPC=0x%8.8x (%s)", __FUNCTION__, *nextPC, *nextPCIsThumb ? "Thumb" : "ARM"); 1790} 1791 1792 1793arm_error_t 1794DNBArchMachARM::DecodeInstructionUsingDisassembler(nub_addr_t curr_pc, uint32_t curr_cpsr, arm_decoded_instruction_t *decodedInstruction, thumb_static_data_t *thumbStaticData, nub_addr_t *next_pc) 1795{ 1796 1797 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: pc=0x%8.8x, cpsr=0x%8.8x", __FUNCTION__, curr_pc, curr_cpsr); 1798 1799 const uint32_t isetstate_mask = MASK_CPSR_T | MASK_CPSR_J; 1800 const uint32_t curr_isetstate = curr_cpsr & isetstate_mask; 1801 uint32_t opcode32; 1802 nub_addr_t nextPC = curr_pc; 1803 arm_error_t decodeReturnCode = ARM_SUCCESS; 1804 1805 m_last_decode_pc = curr_pc; 1806 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: last_decode_pc=0x%8.8x", __FUNCTION__, m_last_decode_pc); 1807 1808 switch (curr_isetstate) { 1809 case 0x0: // ARM Instruction 1810 // Read the ARM opcode 1811 if (m_thread->Process()->Task().ReadMemory(curr_pc, 4, &opcode32) != 4) 1812 { 1813 DNBLogError("unable to read opcode bits 31:0 for an ARM opcode at 0x%8.8llx", (uint64_t)curr_pc); 1814 decodeReturnCode = ARM_ERROR; 1815 } 1816 else 1817 { 1818 nextPC += 4; 1819 decodeReturnCode = ArmDisassembler((uint64_t)curr_pc, opcode32, false, decodedInstruction, NULL, 0, NULL, 0); 1820 1821 if (decodeReturnCode != ARM_SUCCESS) 1822 DNBLogError("Unable to decode ARM instruction 0x%8.8x at 0x%8.8llx", opcode32, (uint64_t)curr_pc); 1823 } 1824 break; 1825 1826 case 0x20: // Thumb Instruction 1827 uint16_t opcode16; 1828 // Read the a 16 bit Thumb opcode 1829 if (m_thread->Process()->Task().ReadMemory(curr_pc, 2, &opcode16) != 2) 1830 { 1831 DNBLogError("unable to read opcode bits 15:0 for a thumb opcode at 0x%8.8llx", (uint64_t)curr_pc); 1832 decodeReturnCode = ARM_ERROR; 1833 } 1834 else 1835 { 1836 nextPC += 2; 1837 opcode32 = opcode16; 1838 1839 decodeReturnCode = ThumbDisassembler((uint64_t)curr_pc, opcode16, false, false, thumbStaticData, decodedInstruction, NULL, 0, NULL, 0); 1840 1841 switch (decodeReturnCode) { 1842 case ARM_SKIP: 1843 // 32 bit thumb opcode 1844 nextPC += 2; 1845 if (m_thread->Process()->Task().ReadMemory(curr_pc+2, 2, &opcode16) != 2) 1846 { 1847 DNBLogError("unable to read opcode bits 15:0 for a thumb opcode at 0x%8.8llx", (uint64_t)curr_pc+2); 1848 } 1849 else 1850 { 1851 opcode32 = (opcode32 << 16) | opcode16; 1852 1853 decodeReturnCode = ThumbDisassembler((uint64_t)(curr_pc+2), opcode16, false, false, thumbStaticData, decodedInstruction, NULL, 0, NULL, 0); 1854 1855 if (decodeReturnCode != ARM_SUCCESS) 1856 DNBLogError("Unable to decode 2nd half of Thumb instruction 0x%8.4hx at 0x%8.8llx", opcode16, (uint64_t)curr_pc+2); 1857 break; 1858 } 1859 break; 1860 1861 case ARM_SUCCESS: 1862 // 16 bit thumb opcode; at this point we are done decoding the opcode 1863 break; 1864 1865 default: 1866 DNBLogError("Unable to decode Thumb instruction 0x%8.4hx at 0x%8.8llx", opcode16, (uint64_t)curr_pc); 1867 decodeReturnCode = ARM_ERROR; 1868 break; 1869 } 1870 } 1871 break; 1872 1873 default: 1874 break; 1875 } 1876 1877 if (next_pc) 1878 *next_pc = nextPC; 1879 1880 return decodeReturnCode; 1881} 1882 1883#endif 1884 1885nub_bool_t 1886DNBArchMachARM::BreakpointHit (nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *baton) 1887{ 1888 nub_addr_t bkpt_pc = (nub_addr_t)baton; 1889 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); 1890 1891 DNBRegisterValue pc_value; 1892 DNBThreadGetRegisterValueByID (pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_PC, &pc_value); 1893 pc_value.value.uint32 = bkpt_pc; 1894 return DNBThreadSetRegisterValueByID (pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_PC, &pc_value); 1895} 1896 1897// Set the single step bit in the processor status register. 1898kern_return_t 1899DNBArchMachARM::SetSingleStepSoftwareBreakpoints() 1900{ 1901 DNBError err; 1902 1903#if defined (USE_ARM_DISASSEMBLER_FRAMEWORK) 1904 err = GetGPRState(false); 1905 1906 if (err.Fail()) 1907 { 1908 err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__); 1909 return err.Error(); 1910 } 1911 1912 nub_addr_t curr_pc = m_state.context.gpr.__pc; 1913 uint32_t curr_cpsr = m_state.context.gpr.__cpsr; 1914 nub_addr_t next_pc = curr_pc; 1915 1916 bool curr_pc_is_thumb = (m_state.context.gpr.__cpsr & 0x20) != 0; 1917 bool next_pc_is_thumb = curr_pc_is_thumb; 1918 1919 uint32_t curr_itstate = ((curr_cpsr & 0x6000000) >> 25) | ((curr_cpsr & 0xFC00) >> 8); 1920 bool inITBlock = (curr_itstate & 0xF) ? 1 : 0; 1921 bool lastInITBlock = ((curr_itstate & 0xF) == 0x8) ? 1 : 0; 1922 1923 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: curr_pc=0x%8.8x (%s), curr_itstate=0x%x, inITBlock=%d, lastInITBlock=%d", __FUNCTION__, curr_pc, curr_pc_is_thumb ? "Thumb" : "ARM", curr_itstate, inITBlock, lastInITBlock); 1924 1925 // If the instruction is not in the IT block, then decode using the Disassembler and compute next_pc 1926 if (!inITBlock) 1927 { 1928 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Decoding an instruction NOT in the IT block", __FUNCTION__); 1929 1930 arm_error_t decodeReturnCode = DecodeInstructionUsingDisassembler(curr_pc, curr_cpsr, &m_last_decode_arm, &m_last_decode_thumb, &next_pc); 1931 1932 if (decodeReturnCode != ARM_SUCCESS) 1933 { 1934 err = KERN_INVALID_ARGUMENT; 1935 DNBLogError("DNBArchMachARM::SetSingleStepSoftwareBreakpoints: Unable to disassemble instruction at 0x%8.8llx", (uint64_t)curr_pc); 1936 } 1937 } 1938 else 1939 { 1940 next_pc = curr_pc + ((m_last_decode_arm.thumb16b) ? 2 : 4); 1941 } 1942 1943 // Instruction is NOT in the IT block OR 1944 if (!inITBlock) 1945 { 1946 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: normal instruction", __FUNCTION__); 1947 EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.context.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb); 1948 } 1949 else if (inITBlock && !m_last_decode_arm.setsFlags) 1950 { 1951 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: IT instruction that doesn't set flags", __FUNCTION__); 1952 EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.context.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb); 1953 } 1954 else if (lastInITBlock && m_last_decode_arm.branch) 1955 { 1956 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: IT instruction which last in the IT block and is a branch", __FUNCTION__); 1957 EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.context.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb); 1958 } 1959 else 1960 { 1961 // Instruction is in IT block and can modify the CPSR flags 1962 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: IT instruction that sets flags", __FUNCTION__); 1963 1964 // NOTE: When this point of code is reached, the instruction at curr_pc has already been decoded 1965 // inside the function ThreadDidStop(). Therefore m_last_decode_arm, m_last_decode_thumb 1966 // reflect the decoded instruction at curr_pc 1967 1968 // If we find an instruction inside the IT block which will set/modify the condition flags (NZCV bits in CPSR), 1969 // we set breakpoints at all remaining instructions inside the IT block starting from the instruction immediately 1970 // following this one AND a breakpoint at the instruction immediately following the IT block. We do this because 1971 // we cannot determine the next_pc until the instruction at which we are currently stopped executes. Hence we 1972 // insert (m_last_decode_thumb.itBlockRemaining+1) 16-bit Thumb breakpoints at consecutive memory locations 1973 // starting at addrOfNextInstructionInITBlock. We record these breakpoints in class variable m_sw_single_step_itblock_break_id[], 1974 // and also record the total number of IT breakpoints set in the variable 'm_sw_single_step_itblock_break_count'. 1975 1976 // The instructions inside the IT block, which are replaced by the 16-bit Thumb breakpoints (opcode=0xDEFE) 1977 // instructions, can be either Thumb-16 or Thumb-32. When a Thumb-32 instruction (say, inst#1) is replaced Thumb 1978 // by a 16-bit breakpoint (OS only supports 16-bit breakpoints in Thumb mode and 32-bit breakpoints in ARM mode), the 1979 // breakpoint for the next instruction (say instr#2) is saved in the upper half of this Thumb-32 (instr#1) 1980 // instruction. Hence if the execution stops at Breakpoint2 corresponding to instr#2, the PC is offset by 16-bits. 1981 // We therefore have to keep track of PC of each instruction in the IT block that is being replaced with the 16-bit 1982 // Thumb breakpoint, to ensure that when the breakpoint is hit, the PC is adjusted to the correct value. We save 1983 // the actual PC corresponding to each instruction in the IT block by associating a call back with each breakpoint 1984 // we set and passing it as a baton. When the breakpoint hits and the callback routine is called, the routine 1985 // adjusts the PC based on the baton that is passed to it. 1986 1987 nub_addr_t addrOfNextInstructionInITBlock, pcInITBlock, nextPCInITBlock, bpAddressInITBlock; 1988 uint16_t opcode16; 1989 uint32_t opcode32; 1990 1991 addrOfNextInstructionInITBlock = (m_last_decode_arm.thumb16b) ? curr_pc + 2 : curr_pc + 4; 1992 1993 pcInITBlock = addrOfNextInstructionInITBlock; 1994 1995 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: itBlockRemaining=%d", __FUNCTION__, m_last_decode_thumb.itBlockRemaining); 1996 1997 m_sw_single_step_itblock_break_count = 0; 1998 for (int i = 0; i <= m_last_decode_thumb.itBlockRemaining; i++) 1999 { 2000 if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i])) 2001 { 2002 DNBLogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Array m_sw_single_step_itblock_break_id should not contain any valid breakpoint IDs at this point. But found a valid breakID=%d at index=%d", m_sw_single_step_itblock_break_id[i], i); 2003 } 2004 else 2005 { 2006 nextPCInITBlock = pcInITBlock; 2007 // Compute nextPCInITBlock based on opcode present at pcInITBlock 2008 if (m_thread->Process()->Task().ReadMemory(pcInITBlock, 2, &opcode16) == 2) 2009 { 2010 opcode32 = opcode16; 2011 nextPCInITBlock += 2; 2012 2013 // Check for 32 bit thumb opcode and read the upper 16 bits if needed 2014 if (((opcode32 & 0xE000) == 0xE000) && (opcode32 & 0x1800)) 2015 { 2016 // Adjust 'next_pc_in_itblock' to point to the default next Thumb instruction for 2017 // a 32 bit Thumb opcode 2018 // Read bits 31:16 of a 32 bit Thumb opcode 2019 if (m_thread->Process()->Task().ReadMemory(pcInITBlock+2, 2, &opcode16) == 2) 2020 { 2021 // 32 bit thumb opcode 2022 opcode32 = (opcode32 << 16) | opcode16; 2023 nextPCInITBlock += 2; 2024 } 2025 else 2026 { 2027 DNBLogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Unable to read opcode bits 31:16 for a 32 bit thumb opcode at pc=0x%8.8llx", (uint64_t)nextPCInITBlock); 2028 } 2029 } 2030 } 2031 else 2032 { 2033 DNBLogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Error reading 16-bit Thumb instruction at pc=0x%8.8x", nextPCInITBlock); 2034 } 2035 2036 2037 // Set breakpoint and associate a callback function with it 2038 bpAddressInITBlock = addrOfNextInstructionInITBlock + 2*i; 2039 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Setting IT breakpoint[%d] at address: 0x%8.8x", __FUNCTION__, i, bpAddressInITBlock); 2040 2041 m_sw_single_step_itblock_break_id[i] = m_thread->Process()->CreateBreakpoint(bpAddressInITBlock, 2, false, m_thread->ThreadID()); 2042 if (!NUB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i])) 2043 err = KERN_INVALID_ARGUMENT; 2044 else 2045 { 2046 DNBLogThreadedIf(LOG_STEP, "%s: Set IT breakpoint[%i]=%d set at 0x%8.8x for instruction at 0x%8.8x", __FUNCTION__, i, m_sw_single_step_itblock_break_id[i], bpAddressInITBlock, pcInITBlock); 2047 2048 // Set the breakpoint callback for these special IT breakpoints 2049 // so that if one of these breakpoints gets hit, it knows to 2050 // update the PC to the original address of the conditional 2051 // IT instruction. 2052 DNBBreakpointSetCallback(m_thread->ProcessID(), m_sw_single_step_itblock_break_id[i], DNBArchMachARM::BreakpointHit, (void*)pcInITBlock); 2053 m_sw_single_step_itblock_break_count++; 2054 } 2055 } 2056 2057 pcInITBlock = nextPCInITBlock; 2058 } 2059 2060 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Set %u IT software single breakpoints.", __FUNCTION__, m_sw_single_step_itblock_break_count); 2061 2062 } 2063 2064 DNBLogThreadedIf(LOG_STEP, "%s: next_pc=0x%8.8x (%s)", __FUNCTION__, next_pc, next_pc_is_thumb ? "Thumb" : "ARM"); 2065 2066 if (next_pc & 0x1) 2067 { 2068 assert(next_pc_is_thumb); 2069 } 2070 2071 if (next_pc_is_thumb) 2072 { 2073 next_pc &= ~0x1; 2074 } 2075 else 2076 { 2077 assert((next_pc & 0x3) == 0); 2078 } 2079 2080 if (!inITBlock || (inITBlock && !m_last_decode_arm.setsFlags) || (lastInITBlock && m_last_decode_arm.branch)) 2081 { 2082 err = KERN_SUCCESS; 2083 2084#if defined DNB_ARCH_MACH_ARM_DEBUG_SW_STEP 2085 m_sw_single_step_next_pc = next_pc; 2086 if (next_pc_is_thumb) 2087 m_sw_single_step_next_pc |= 1; // Set bit zero if the next PC is expected to be Thumb 2088#else 2089 const DNBBreakpoint *bp = m_thread->Process()->Breakpoints().FindByAddress(next_pc); 2090 2091 if (bp == NULL) 2092 { 2093 m_sw_single_step_break_id = m_thread->Process()->CreateBreakpoint(next_pc, next_pc_is_thumb ? 2 : 4, false, m_thread->ThreadID()); 2094 if (!NUB_BREAK_ID_IS_VALID(m_sw_single_step_break_id)) 2095 err = KERN_INVALID_ARGUMENT; 2096 DNBLogThreadedIf(LOG_STEP, "%s: software single step breakpoint with breakID=%d set at 0x%8.8x", __FUNCTION__, m_sw_single_step_break_id, next_pc); 2097 } 2098#endif 2099 } 2100#else 2101 err.LogThreaded("%s: ARMDisassembler.framework support is disabled", __FUNCTION__); 2102#endif 2103 return err.Error(); 2104} 2105 2106uint32_t 2107DNBArchMachARM::NumSupportedHardwareBreakpoints() 2108{ 2109 // Set the init value to something that will let us know that we need to 2110 // autodetect how many breakpoints are supported dynamically... 2111 static uint32_t g_num_supported_hw_breakpoints = UINT_MAX; 2112 if (g_num_supported_hw_breakpoints == UINT_MAX) 2113 { 2114 // Set this to zero in case we can't tell if there are any HW breakpoints 2115 g_num_supported_hw_breakpoints = 0; 2116 2117 size_t len; 2118 uint32_t n = 0; 2119 len = sizeof (n); 2120 if (::sysctlbyname("hw.optional.breakpoint", &n, &len, NULL, 0) == 0) 2121 { 2122 g_num_supported_hw_breakpoints = n; 2123 DNBLogThreadedIf(LOG_THREAD, "hw.optional.breakpoint=%u", n); 2124 } 2125 else 2126 { 2127 // Read the DBGDIDR to get the number of available hardware breakpoints 2128 // However, in some of our current armv7 processors, hardware 2129 // breakpoints/watchpoints were not properly connected. So detect those 2130 // cases using a field in a sysctl. For now we are using "hw.cpusubtype" 2131 // field to distinguish CPU architectures. This is a hack until we can 2132 // get <rdar://problem/6372672> fixed, at which point we will switch to 2133 // using a different sysctl string that will tell us how many BRPs 2134 // are available to us directly without having to read DBGDIDR. 2135 uint32_t register_DBGDIDR; 2136 2137 asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); 2138 uint32_t numBRPs = bits(register_DBGDIDR, 27, 24); 2139 // Zero is reserved for the BRP count, so don't increment it if it is zero 2140 if (numBRPs > 0) 2141 numBRPs++; 2142 DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, numBRPs); 2143 2144 if (numBRPs > 0) 2145 { 2146 uint32_t cpusubtype; 2147 len = sizeof(cpusubtype); 2148 // TODO: remove this hack and change to using hw.optional.xx when implmented 2149 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) 2150 { 2151 DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=%d", cpusubtype); 2152 if (cpusubtype == CPU_SUBTYPE_ARM_V7) 2153 DNBLogThreadedIf(LOG_THREAD, "Hardware breakpoints disabled for armv7 (rdar://problem/6372672)"); 2154 else 2155 g_num_supported_hw_breakpoints = numBRPs; 2156 } 2157 } 2158 } 2159 } 2160 return g_num_supported_hw_breakpoints; 2161} 2162 2163 2164uint32_t 2165DNBArchMachARM::NumSupportedHardwareWatchpoints() 2166{ 2167 // Set the init value to something that will let us know that we need to 2168 // autodetect how many watchpoints are supported dynamically... 2169 static uint32_t g_num_supported_hw_watchpoints = UINT_MAX; 2170 if (g_num_supported_hw_watchpoints == UINT_MAX) 2171 { 2172 // Set this to zero in case we can't tell if there are any HW breakpoints 2173 g_num_supported_hw_watchpoints = 0; 2174 2175 2176 size_t len; 2177 uint32_t n = 0; 2178 len = sizeof (n); 2179 if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) 2180 { 2181 g_num_supported_hw_watchpoints = n; 2182 DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n); 2183 } 2184 else 2185 { 2186 // Read the DBGDIDR to get the number of available hardware breakpoints 2187 // However, in some of our current armv7 processors, hardware 2188 // breakpoints/watchpoints were not properly connected. So detect those 2189 // cases using a field in a sysctl. For now we are using "hw.cpusubtype" 2190 // field to distinguish CPU architectures. This is a hack until we can 2191 // get <rdar://problem/6372672> fixed, at which point we will switch to 2192 // using a different sysctl string that will tell us how many WRPs 2193 // are available to us directly without having to read DBGDIDR. 2194 2195 uint32_t register_DBGDIDR; 2196 asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); 2197 uint32_t numWRPs = bits(register_DBGDIDR, 31, 28) + 1; 2198 DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, numWRPs); 2199 2200 if (numWRPs > 0) 2201 { 2202 uint32_t cpusubtype; 2203 size_t len; 2204 len = sizeof(cpusubtype); 2205 // TODO: remove this hack and change to using hw.optional.xx when implmented 2206 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) 2207 { 2208 DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype); 2209 2210 if (cpusubtype == CPU_SUBTYPE_ARM_V7) 2211 DNBLogThreadedIf(LOG_THREAD, "Hardware watchpoints disabled for armv7 (rdar://problem/6372672)"); 2212 else 2213 g_num_supported_hw_watchpoints = numWRPs; 2214 } 2215 } 2216 } 2217 } 2218 return g_num_supported_hw_watchpoints; 2219} 2220 2221 2222uint32_t 2223DNBArchMachARM::EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size) 2224{ 2225 // Make sure our address isn't bogus 2226 if (addr & 1) 2227 return INVALID_NUB_HW_INDEX; 2228 2229 kern_return_t kret = GetDBGState(false); 2230 2231 if (kret == KERN_SUCCESS) 2232 { 2233 const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); 2234 uint32_t i; 2235 for (i=0; i<num_hw_breakpoints; ++i) 2236 { 2237 if ((m_state.dbg.__bcr[i] & BCR_ENABLE) == 0) 2238 break; // We found an available hw breakpoint slot (in i) 2239 } 2240 2241 // See if we found an available hw breakpoint slot above 2242 if (i < num_hw_breakpoints) 2243 { 2244 // Make sure bits 1:0 are clear in our address 2245 m_state.dbg.__bvr[i] = addr & ~((nub_addr_t)3); 2246 2247 if (size == 2 || addr & 2) 2248 { 2249 uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1; 2250 2251 // We have a thumb breakpoint 2252 // We have an ARM breakpoint 2253 m_state.dbg.__bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch 2254 byte_addr_select | // Set the correct byte address select so we only trigger on the correct opcode 2255 S_USER | // Which modes should this breakpoint stop in? 2256 BCR_ENABLE; // Enable this hardware breakpoint 2257 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %zu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)", 2258 (uint64_t)addr, 2259 size, 2260 i, 2261 i, 2262 m_state.dbg.__bvr[i], 2263 m_state.dbg.__bcr[i]); 2264 } 2265 else if (size == 4) 2266 { 2267 // We have an ARM breakpoint 2268 m_state.dbg.__bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch 2269 BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA 2270 S_USER | // Which modes should this breakpoint stop in? 2271 BCR_ENABLE; // Enable this hardware breakpoint 2272 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %zu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)", 2273 (uint64_t)addr, 2274 size, 2275 i, 2276 i, 2277 m_state.dbg.__bvr[i], 2278 m_state.dbg.__bcr[i]); 2279 } 2280 2281 kret = SetDBGState(); 2282 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint() SetDBGState() => 0x%8.8x.", kret); 2283 2284 if (kret == KERN_SUCCESS) 2285 return i; 2286 } 2287 else 2288 { 2289 DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint(addr = 0x%8.8llx, size = %zu) => all hardware breakpoint resources are being used.", (uint64_t)addr, size); 2290 } 2291 } 2292 2293 return INVALID_NUB_HW_INDEX; 2294} 2295 2296bool 2297DNBArchMachARM::DisableHardwareBreakpoint (uint32_t hw_index) 2298{ 2299 kern_return_t kret = GetDBGState(false); 2300 2301 const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); 2302 if (kret == KERN_SUCCESS) 2303 { 2304 if (hw_index < num_hw_points) 2305 { 2306 m_state.dbg.__bcr[hw_index] = 0; 2307 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x BCR%u = 0x%8.8x", 2308 hw_index, 2309 hw_index, 2310 m_state.dbg.__bvr[hw_index], 2311 hw_index, 2312 m_state.dbg.__bcr[hw_index]); 2313 2314 kret = SetDBGState(); 2315 2316 if (kret == KERN_SUCCESS) 2317 return true; 2318 } 2319 } 2320 return false; 2321} 2322 2323uint32_t 2324DNBArchMachARM::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write) 2325{ 2326 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %zu, read = %u, write = %u)", (uint64_t)addr, size, read, write); 2327 2328 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); 2329 2330 // Can't watch zero bytes 2331 if (size == 0) 2332 return INVALID_NUB_HW_INDEX; 2333 2334 // We must watch for either read or write 2335 if (read == false && write == false) 2336 return INVALID_NUB_HW_INDEX; 2337 2338 // Can't watch more than 4 bytes per WVR/WCR pair 2339 if (size > 4) 2340 return INVALID_NUB_HW_INDEX; 2341 2342 // We can only watch up to four bytes that follow a 4 byte aligned address 2343 // per watchpoint register pair. Since we can only watch until the next 4 2344 // byte boundary, we need to make sure we can properly encode this. 2345 2346 // addr_word_offset = addr % 4, i.e, is in set([0, 1, 2, 3]) 2347 // 2348 // +---+---+---+---+ 2349 // | 0 | 1 | 2 | 3 | 2350 // +---+---+---+---+ 2351 // ^ 2352 // | 2353 // word address (4-byte aligned) = addr & 0xFFFFFFFC => goes into WVR 2354 // 2355 // examples: 2356 // 1. addr_word_offset = 1, size = 1 to watch a uint_8 => byte_mask = (0b0001 << 1) = 0b0010 2357 // 2. addr_word_offset = 2, size = 2 to watch a uint_16 => byte_mask = (0b0011 << 2) = 0b1100 2358 // 2359 // where byte_mask goes into WCR[8:5] 2360 2361 uint32_t addr_word_offset = addr % 4; 2362 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset); 2363 2364 uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset; 2365 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask); 2366 if (byte_mask > 0xfu) 2367 return INVALID_NUB_HW_INDEX; 2368 2369 // Read the debug state 2370 kern_return_t kret = GetDBGState(false); 2371 2372 if (kret == KERN_SUCCESS) 2373 { 2374 // Check to make sure we have the needed hardware support 2375 uint32_t i = 0; 2376 2377 for (i=0; i<num_hw_watchpoints; ++i) 2378 { 2379 if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0) 2380 break; // We found an available hw watchpoint slot (in i) 2381 } 2382 2383 // See if we found an available hw watchpoint slot above 2384 if (i < num_hw_watchpoints) 2385 { 2386 // Make the byte_mask into a valid Byte Address Select mask 2387 uint32_t byte_address_select = byte_mask << 5; 2388 // Make sure bits 1:0 are clear in our address 2389 m_state.dbg.__wvr[i] = addr & ~((nub_addr_t)3); // DVA (Data Virtual Address) 2390 m_state.dbg.__wcr[i] = byte_address_select | // Which bytes that follow the DVA that we will watch 2391 S_USER | // Stop only in user mode 2392 (read ? WCR_LOAD : 0) | // Stop on read access? 2393 (write ? WCR_STORE : 0) | // Stop on write access? 2394 WCR_ENABLE; // Enable this watchpoint; 2395 2396 kret = SetDBGState(); 2397 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret); 2398 2399 if (kret == KERN_SUCCESS) 2400 return i; 2401 } 2402 else 2403 { 2404 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); 2405 } 2406 } 2407 return INVALID_NUB_HW_INDEX; 2408} 2409 2410bool 2411DNBArchMachARM::DisableHardwareWatchpoint (uint32_t hw_index) 2412{ 2413 kern_return_t kret = GetDBGState(false); 2414 2415 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); 2416 if (kret == KERN_SUCCESS) 2417 { 2418 if (hw_index < num_hw_points) 2419 { 2420 m_state.dbg.__wcr[hw_index] = 0; 2421 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::DisableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x WCR%u = 0x%8.8x", 2422 hw_index, 2423 hw_index, 2424 m_state.dbg.__wvr[hw_index], 2425 hw_index, 2426 m_state.dbg.__wcr[hw_index]); 2427 2428 kret = SetDBGState(); 2429 2430 if (kret == KERN_SUCCESS) 2431 return true; 2432 } 2433 } 2434 return false; 2435} 2436 2437// {0} -> __bvr[16], {0} -> __bcr[16], {0} --> __wvr[16], {0} -> __wcr{16} 2438DNBArchMachARM::DBG DNBArchMachARM::Global_Debug_State = {{0},{0},{0},{0}}; 2439bool DNBArchMachARM::Valid_Global_Debug_State = false; 2440 2441// Use this callback from MachThread, which in turn was called from MachThreadList, to update 2442// the global view of the hardware watchpoint state, so that when new thread comes along, they 2443// get to inherit the existing hardware watchpoint state. 2444void 2445DNBArchMachARM::HardwareWatchpointStateChanged () 2446{ 2447 Global_Debug_State = m_state.dbg; 2448 Valid_Global_Debug_State = true; 2449} 2450 2451// Iterate through the debug registers; return the index of the first hit. 2452uint32_t 2453DNBArchMachARM::GetHardwareWatchpointHit(nub_addr_t &addr) 2454{ 2455 // Read the debug state 2456 kern_return_t kret = GetDBGState(true); 2457 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret); 2458 if (kret == KERN_SUCCESS) 2459 { 2460 DBG &debug_state = m_state.dbg; 2461 uint32_t i, num = NumSupportedHardwareWatchpoints(); 2462 for (i = 0; i < num; ++i) 2463 { 2464 // FIXME: IsWatchpointHit() currently returns the first enabled watchpoint, 2465 // instead of finding the watchpoint that actually triggered. 2466 if (IsWatchpointHit(debug_state, i)) 2467 { 2468 addr = GetWatchAddress(debug_state, i); 2469 DNBLogThreadedIf(LOG_WATCHPOINTS, 2470 "DNBArchMachARM::GetHardwareWatchpointHit() found => %u (addr = 0x%llx).", 2471 i, 2472 (uint64_t)addr); 2473 return i; 2474 } 2475 } 2476 } 2477 return INVALID_NUB_HW_INDEX; 2478} 2479 2480// ThreadWillResume() calls this to clear bits[5:2] (Method of entry bits) of 2481// the Debug Status and Control Register (DSCR). 2482// 2483// b0010 = a watchpoint occurred 2484// b0000 is the reset value 2485void 2486DNBArchMachARM::ClearWatchpointOccurred() 2487{ 2488 // See also IsWatchpointHit(). 2489 uint32_t register_DBGDSCR; 2490 asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR)); 2491 if (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED) 2492 { 2493 uint32_t mask = ~(0xF << 2); 2494 register_DBGDSCR &= mask; 2495 asm("mcr p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR)); 2496 } 2497 return; 2498} 2499 2500// NotifyException() calls this to double check that a watchpoint has occurred 2501// by inspecting the bits[5:2] field of the Debug Status and Control Register 2502// (DSCR). 2503// 2504// b0010 = a watchpoint occurred 2505bool 2506DNBArchMachARM::HasWatchpointOccurred() 2507{ 2508 // See also IsWatchpointHit(). 2509 uint32_t register_DBGDSCR; 2510 asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR)); 2511 return (bits(register_DBGDSCR, 5, 2) == WATCHPOINT_OCCURRED); 2512} 2513 2514// FIXME: IsWatchpointHit() currently returns the first enabled watchpoint, 2515// instead of finding the watchpoint that actually triggered. 2516bool 2517DNBArchMachARM::IsWatchpointHit(const DBG &debug_state, uint32_t hw_index) 2518{ 2519 // Watchpoint Control Registers, bitfield definitions 2520 // ... 2521 // Bits Value Description 2522 // [0] 0 Watchpoint disabled 2523 // 1 Watchpoint enabled. 2524 return (debug_state.__wcr[hw_index] & 1u); 2525} 2526 2527nub_addr_t 2528DNBArchMachARM::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) 2529{ 2530 // Watchpoint Value Registers, bitfield definitions 2531 // Bits Description 2532 // [31:2] Watchpoint address 2533 return bits(debug_state.__wvr[hw_index], 31, 2); 2534} 2535 2536//---------------------------------------------------------------------- 2537// Register information defintions for 32 bit ARMV6. 2538//---------------------------------------------------------------------- 2539enum gpr_regnums 2540{ 2541 gpr_r0 = 0, 2542 gpr_r1, 2543 gpr_r2, 2544 gpr_r3, 2545 gpr_r4, 2546 gpr_r5, 2547 gpr_r6, 2548 gpr_r7, 2549 gpr_r8, 2550 gpr_r9, 2551 gpr_r10, 2552 gpr_r11, 2553 gpr_r12, 2554 gpr_sp, 2555 gpr_lr, 2556 gpr_pc, 2557 gpr_cpsr 2558}; 2559 2560enum 2561{ 2562 vfp_s0 = 0, 2563 vfp_s1, 2564 vfp_s2, 2565 vfp_s3, 2566 vfp_s4, 2567 vfp_s5, 2568 vfp_s6, 2569 vfp_s7, 2570 vfp_s8, 2571 vfp_s9, 2572 vfp_s10, 2573 vfp_s11, 2574 vfp_s12, 2575 vfp_s13, 2576 vfp_s14, 2577 vfp_s15, 2578 vfp_s16, 2579 vfp_s17, 2580 vfp_s18, 2581 vfp_s19, 2582 vfp_s20, 2583 vfp_s21, 2584 vfp_s22, 2585 vfp_s23, 2586 vfp_s24, 2587 vfp_s25, 2588 vfp_s26, 2589 vfp_s27, 2590 vfp_s28, 2591 vfp_s29, 2592 vfp_s30, 2593 vfp_s31, 2594 vfp_d0, 2595 vfp_d1, 2596 vfp_d2, 2597 vfp_d3, 2598 vfp_d4, 2599 vfp_d5, 2600 vfp_d6, 2601 vfp_d7, 2602 vfp_d8, 2603 vfp_d9, 2604 vfp_d10, 2605 vfp_d11, 2606 vfp_d12, 2607 vfp_d13, 2608 vfp_d14, 2609 vfp_d15, 2610 vfp_d16, 2611 vfp_d17, 2612 vfp_d18, 2613 vfp_d19, 2614 vfp_d20, 2615 vfp_d21, 2616 vfp_d22, 2617 vfp_d23, 2618 vfp_d24, 2619 vfp_d25, 2620 vfp_d26, 2621 vfp_d27, 2622 vfp_d28, 2623 vfp_d29, 2624 vfp_d30, 2625 vfp_d31, 2626 vfp_fpscr 2627}; 2628 2629enum 2630{ 2631 exc_exception, 2632 exc_fsr, 2633 exc_far, 2634}; 2635 2636enum 2637{ 2638 gdb_r0 = 0, 2639 gdb_r1, 2640 gdb_r2, 2641 gdb_r3, 2642 gdb_r4, 2643 gdb_r5, 2644 gdb_r6, 2645 gdb_r7, 2646 gdb_r8, 2647 gdb_r9, 2648 gdb_r10, 2649 gdb_r11, 2650 gdb_r12, 2651 gdb_sp, 2652 gdb_lr, 2653 gdb_pc, 2654 gdb_f0, 2655 gdb_f1, 2656 gdb_f2, 2657 gdb_f3, 2658 gdb_f4, 2659 gdb_f5, 2660 gdb_f6, 2661 gdb_f7, 2662 gdb_f8, 2663 gdb_cpsr, 2664 gdb_s0, 2665 gdb_s1, 2666 gdb_s2, 2667 gdb_s3, 2668 gdb_s4, 2669 gdb_s5, 2670 gdb_s6, 2671 gdb_s7, 2672 gdb_s8, 2673 gdb_s9, 2674 gdb_s10, 2675 gdb_s11, 2676 gdb_s12, 2677 gdb_s13, 2678 gdb_s14, 2679 gdb_s15, 2680 gdb_s16, 2681 gdb_s17, 2682 gdb_s18, 2683 gdb_s19, 2684 gdb_s20, 2685 gdb_s21, 2686 gdb_s22, 2687 gdb_s23, 2688 gdb_s24, 2689 gdb_s25, 2690 gdb_s26, 2691 gdb_s27, 2692 gdb_s28, 2693 gdb_s29, 2694 gdb_s30, 2695 gdb_s31, 2696 gdb_fpscr, 2697 gdb_d0, 2698 gdb_d1, 2699 gdb_d2, 2700 gdb_d3, 2701 gdb_d4, 2702 gdb_d5, 2703 gdb_d6, 2704 gdb_d7, 2705 gdb_d8, 2706 gdb_d9, 2707 gdb_d10, 2708 gdb_d11, 2709 gdb_d12, 2710 gdb_d13, 2711 gdb_d14, 2712 gdb_d15 2713}; 2714 2715#define GPR_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::GPR, __r[idx])) 2716#define GPR_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::GPR, __##reg)) 2717#define VFP_S_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::FPU, __r[(idx)]) + offsetof (DNBArchMachARM::Context, vfp)) 2718#define VFP_D_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX ((idx) * 2)) 2719#define VFP_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::FPU, __##reg) + offsetof (DNBArchMachARM::Context, vfp)) 2720#define EXC_OFFSET(reg) (offsetof (DNBArchMachARM::EXC, __##reg) + offsetof (DNBArchMachARM::Context, exc)) 2721 2722// These macros will auto define the register name, alt name, register size, 2723// register offset, encoding, format and native register. This ensures that 2724// the register state structures are defined correctly and have the correct 2725// sizes and offsets. 2726#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, gdb_##reg } 2727#define DEFINE_GPR_NAME(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_NAME(reg), gcc_##reg, dwarf_##reg, gen, gdb_##reg } 2728//#define FLOAT_FORMAT Float 2729#define FLOAT_FORMAT Hex 2730#define DEFINE_VFP_S_IDX(idx) { e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, FLOAT_FORMAT, 4, VFP_S_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, INVALID_NUB_REGNUM, gdb_s##idx } 2731//#define DEFINE_VFP_D_IDX(idx) { e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, Float, 8, VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_d##idx, INVALID_NUB_REGNUM, gdb_d##idx } 2732#define DEFINE_VFP_D_IDX(idx) { e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, FLOAT_FORMAT, 8, VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_d##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM } 2733 2734// General purpose registers 2735const DNBRegisterInfo 2736DNBArchMachARM::g_gpr_registers[] = 2737{ 2738 DEFINE_GPR_IDX ( 0, r0,"arg1", GENERIC_REGNUM_ARG1 ), 2739 DEFINE_GPR_IDX ( 1, r1,"arg2", GENERIC_REGNUM_ARG2 ), 2740 DEFINE_GPR_IDX ( 2, r2,"arg3", GENERIC_REGNUM_ARG3 ), 2741 DEFINE_GPR_IDX ( 3, r3,"arg4", GENERIC_REGNUM_ARG4 ), 2742 DEFINE_GPR_IDX ( 4, r4, NULL, INVALID_NUB_REGNUM ), 2743 DEFINE_GPR_IDX ( 5, r5, NULL, INVALID_NUB_REGNUM ), 2744 DEFINE_GPR_IDX ( 6, r6, NULL, INVALID_NUB_REGNUM ), 2745 DEFINE_GPR_IDX ( 7, r7, "fp", GENERIC_REGNUM_FP ), 2746 DEFINE_GPR_IDX ( 8, r8, NULL, INVALID_NUB_REGNUM ), 2747 DEFINE_GPR_IDX ( 9, r9, NULL, INVALID_NUB_REGNUM ), 2748 DEFINE_GPR_IDX (10, r10, NULL, INVALID_NUB_REGNUM ), 2749 DEFINE_GPR_IDX (11, r11, NULL, INVALID_NUB_REGNUM ), 2750 DEFINE_GPR_IDX (12, r12, NULL, INVALID_NUB_REGNUM ), 2751 DEFINE_GPR_NAME (sp, "r13", GENERIC_REGNUM_SP ), 2752 DEFINE_GPR_NAME (lr, "r14", GENERIC_REGNUM_RA ), 2753 DEFINE_GPR_NAME (pc, "r15", GENERIC_REGNUM_PC ), 2754 DEFINE_GPR_NAME (cpsr, "flags", GENERIC_REGNUM_FLAGS ) 2755}; 2756 2757// Floating point registers 2758const DNBRegisterInfo 2759DNBArchMachARM::g_vfp_registers[] = 2760{ 2761 DEFINE_VFP_S_IDX ( 0), 2762 DEFINE_VFP_S_IDX ( 1), 2763 DEFINE_VFP_S_IDX ( 2), 2764 DEFINE_VFP_S_IDX ( 3), 2765 DEFINE_VFP_S_IDX ( 4), 2766 DEFINE_VFP_S_IDX ( 5), 2767 DEFINE_VFP_S_IDX ( 6), 2768 DEFINE_VFP_S_IDX ( 7), 2769 DEFINE_VFP_S_IDX ( 8), 2770 DEFINE_VFP_S_IDX ( 9), 2771 DEFINE_VFP_S_IDX (10), 2772 DEFINE_VFP_S_IDX (11), 2773 DEFINE_VFP_S_IDX (12), 2774 DEFINE_VFP_S_IDX (13), 2775 DEFINE_VFP_S_IDX (14), 2776 DEFINE_VFP_S_IDX (15), 2777 DEFINE_VFP_S_IDX (16), 2778 DEFINE_VFP_S_IDX (17), 2779 DEFINE_VFP_S_IDX (18), 2780 DEFINE_VFP_S_IDX (19), 2781 DEFINE_VFP_S_IDX (20), 2782 DEFINE_VFP_S_IDX (21), 2783 DEFINE_VFP_S_IDX (22), 2784 DEFINE_VFP_S_IDX (23), 2785 DEFINE_VFP_S_IDX (24), 2786 DEFINE_VFP_S_IDX (25), 2787 DEFINE_VFP_S_IDX (26), 2788 DEFINE_VFP_S_IDX (27), 2789 DEFINE_VFP_S_IDX (28), 2790 DEFINE_VFP_S_IDX (29), 2791 DEFINE_VFP_S_IDX (30), 2792 DEFINE_VFP_S_IDX (31), 2793 DEFINE_VFP_D_IDX (0), 2794 DEFINE_VFP_D_IDX (1), 2795 DEFINE_VFP_D_IDX (2), 2796 DEFINE_VFP_D_IDX (3), 2797 DEFINE_VFP_D_IDX (4), 2798 DEFINE_VFP_D_IDX (5), 2799 DEFINE_VFP_D_IDX (6), 2800 DEFINE_VFP_D_IDX (7), 2801 DEFINE_VFP_D_IDX (8), 2802 DEFINE_VFP_D_IDX (9), 2803 DEFINE_VFP_D_IDX (10), 2804 DEFINE_VFP_D_IDX (11), 2805 DEFINE_VFP_D_IDX (12), 2806 DEFINE_VFP_D_IDX (13), 2807 DEFINE_VFP_D_IDX (14), 2808 DEFINE_VFP_D_IDX (15), 2809 DEFINE_VFP_D_IDX (16), 2810 DEFINE_VFP_D_IDX (17), 2811 DEFINE_VFP_D_IDX (18), 2812 DEFINE_VFP_D_IDX (19), 2813 DEFINE_VFP_D_IDX (20), 2814 DEFINE_VFP_D_IDX (21), 2815 DEFINE_VFP_D_IDX (22), 2816 DEFINE_VFP_D_IDX (23), 2817 DEFINE_VFP_D_IDX (24), 2818 DEFINE_VFP_D_IDX (25), 2819 DEFINE_VFP_D_IDX (26), 2820 DEFINE_VFP_D_IDX (27), 2821 DEFINE_VFP_D_IDX (28), 2822 DEFINE_VFP_D_IDX (29), 2823 DEFINE_VFP_D_IDX (30), 2824 DEFINE_VFP_D_IDX (31), 2825 { e_regSetVFP, vfp_fpscr, "fpscr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpscr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gdb_fpscr } 2826}; 2827 2828// Exception registers 2829 2830const DNBRegisterInfo 2831DNBArchMachARM::g_exc_registers[] = 2832{ 2833 { e_regSetVFP, exc_exception , "exception" , NULL, Uint, Hex, 4, EXC_OFFSET(exception) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }, 2834 { e_regSetVFP, exc_fsr , "fsr" , NULL, Uint, Hex, 4, EXC_OFFSET(fsr) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }, 2835 { e_regSetVFP, exc_far , "far" , NULL, Uint, Hex, 4, EXC_OFFSET(far) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM } 2836}; 2837 2838// Number of registers in each register set 2839const size_t DNBArchMachARM::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); 2840const size_t DNBArchMachARM::k_num_vfp_registers = sizeof(g_vfp_registers)/sizeof(DNBRegisterInfo); 2841const size_t DNBArchMachARM::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); 2842const size_t DNBArchMachARM::k_num_all_registers = k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers; 2843 2844//---------------------------------------------------------------------- 2845// Register set definitions. The first definitions at register set index 2846// of zero is for all registers, followed by other registers sets. The 2847// register information for the all register set need not be filled in. 2848//---------------------------------------------------------------------- 2849const DNBRegisterSetInfo 2850DNBArchMachARM::g_reg_sets[] = 2851{ 2852 { "ARM Registers", NULL, k_num_all_registers }, 2853 { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, 2854 { "Floating Point Registers", g_vfp_registers, k_num_vfp_registers }, 2855 { "Exception State Registers", g_exc_registers, k_num_exc_registers } 2856}; 2857// Total number of register sets for this architecture 2858const size_t DNBArchMachARM::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); 2859 2860 2861const DNBRegisterSetInfo * 2862DNBArchMachARM::GetRegisterSetInfo(nub_size_t *num_reg_sets) 2863{ 2864 *num_reg_sets = k_num_register_sets; 2865 return g_reg_sets; 2866} 2867 2868bool 2869DNBArchMachARM::GetRegisterValue(int set, int reg, DNBRegisterValue *value) 2870{ 2871 if (set == REGISTER_SET_GENERIC) 2872 { 2873 switch (reg) 2874 { 2875 case GENERIC_REGNUM_PC: // Program Counter 2876 set = e_regSetGPR; 2877 reg = gpr_pc; 2878 break; 2879 2880 case GENERIC_REGNUM_SP: // Stack Pointer 2881 set = e_regSetGPR; 2882 reg = gpr_sp; 2883 break; 2884 2885 case GENERIC_REGNUM_FP: // Frame Pointer 2886 set = e_regSetGPR; 2887 reg = gpr_r7; // is this the right reg? 2888 break; 2889 2890 case GENERIC_REGNUM_RA: // Return Address 2891 set = e_regSetGPR; 2892 reg = gpr_lr; 2893 break; 2894 2895 case GENERIC_REGNUM_FLAGS: // Processor flags register 2896 set = e_regSetGPR; 2897 reg = gpr_cpsr; 2898 break; 2899 2900 default: 2901 return false; 2902 } 2903 } 2904 2905 if (GetRegisterState(set, false) != KERN_SUCCESS) 2906 return false; 2907 2908 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 2909 if (regInfo) 2910 { 2911 value->info = *regInfo; 2912 switch (set) 2913 { 2914 case e_regSetGPR: 2915 if (reg < k_num_gpr_registers) 2916 { 2917 value->value.uint32 = m_state.context.gpr.__r[reg]; 2918 return true; 2919 } 2920 break; 2921 2922 case e_regSetVFP: 2923 if (reg <= vfp_s31) 2924 { 2925 value->value.uint32 = m_state.context.vfp.__r[reg]; 2926 return true; 2927 } 2928 else if (reg <= vfp_d31) 2929 { 2930 uint32_t d_reg_idx = reg - vfp_d0; 2931 uint32_t s_reg_idx = d_reg_idx * 2; 2932 value->value.v_sint32[0] = m_state.context.vfp.__r[s_reg_idx + 0]; 2933 value->value.v_sint32[1] = m_state.context.vfp.__r[s_reg_idx + 1]; 2934 return true; 2935 } 2936 else if (reg == vfp_fpscr) 2937 { 2938 value->value.uint32 = m_state.context.vfp.__fpscr; 2939 return true; 2940 } 2941 break; 2942 2943 case e_regSetEXC: 2944 if (reg < k_num_exc_registers) 2945 { 2946 value->value.uint32 = (&m_state.context.exc.__exception)[reg]; 2947 return true; 2948 } 2949 break; 2950 } 2951 } 2952 return false; 2953} 2954 2955bool 2956DNBArchMachARM::SetRegisterValue(int set, int reg, const DNBRegisterValue *value) 2957{ 2958 if (set == REGISTER_SET_GENERIC) 2959 { 2960 switch (reg) 2961 { 2962 case GENERIC_REGNUM_PC: // Program Counter 2963 set = e_regSetGPR; 2964 reg = gpr_pc; 2965 break; 2966 2967 case GENERIC_REGNUM_SP: // Stack Pointer 2968 set = e_regSetGPR; 2969 reg = gpr_sp; 2970 break; 2971 2972 case GENERIC_REGNUM_FP: // Frame Pointer 2973 set = e_regSetGPR; 2974 reg = gpr_r7; 2975 break; 2976 2977 case GENERIC_REGNUM_RA: // Return Address 2978 set = e_regSetGPR; 2979 reg = gpr_lr; 2980 break; 2981 2982 case GENERIC_REGNUM_FLAGS: // Processor flags register 2983 set = e_regSetGPR; 2984 reg = gpr_cpsr; 2985 break; 2986 2987 default: 2988 return false; 2989 } 2990 } 2991 2992 if (GetRegisterState(set, false) != KERN_SUCCESS) 2993 return false; 2994 2995 bool success = false; 2996 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 2997 if (regInfo) 2998 { 2999 switch (set) 3000 { 3001 case e_regSetGPR: 3002 if (reg < k_num_gpr_registers) 3003 { 3004 m_state.context.gpr.__r[reg] = value->value.uint32; 3005 success = true; 3006 } 3007 break; 3008 3009 case e_regSetVFP: 3010 if (reg <= vfp_s31) 3011 { 3012 m_state.context.vfp.__r[reg] = value->value.uint32; 3013 success = true; 3014 } 3015 else if (reg <= vfp_d31) 3016 { 3017 uint32_t d_reg_idx = reg - vfp_d0; 3018 uint32_t s_reg_idx = d_reg_idx * 2; 3019 m_state.context.vfp.__r[s_reg_idx + 0] = value->value.v_sint32[0]; 3020 m_state.context.vfp.__r[s_reg_idx + 1] = value->value.v_sint32[1]; 3021 success = true; 3022 } 3023 else if (reg == vfp_fpscr) 3024 { 3025 m_state.context.vfp.__fpscr = value->value.uint32; 3026 success = true; 3027 } 3028 break; 3029 3030 case e_regSetEXC: 3031 if (reg < k_num_exc_registers) 3032 { 3033 (&m_state.context.exc.__exception)[reg] = value->value.uint32; 3034 success = true; 3035 } 3036 break; 3037 } 3038 3039 } 3040 if (success) 3041 return SetRegisterState(set) == KERN_SUCCESS; 3042 return false; 3043} 3044 3045kern_return_t 3046DNBArchMachARM::GetRegisterState(int set, bool force) 3047{ 3048 switch (set) 3049 { 3050 case e_regSetALL: return GetGPRState(force) | 3051 GetVFPState(force) | 3052 GetEXCState(force) | 3053 GetDBGState(force); 3054 case e_regSetGPR: return GetGPRState(force); 3055 case e_regSetVFP: return GetVFPState(force); 3056 case e_regSetEXC: return GetEXCState(force); 3057 case e_regSetDBG: return GetDBGState(force); 3058 default: break; 3059 } 3060 return KERN_INVALID_ARGUMENT; 3061} 3062 3063kern_return_t 3064DNBArchMachARM::SetRegisterState(int set) 3065{ 3066 // Make sure we have a valid context to set. 3067 kern_return_t err = GetRegisterState(set, false); 3068 if (err != KERN_SUCCESS) 3069 return err; 3070 3071 switch (set) 3072 { 3073 case e_regSetALL: return SetGPRState() | 3074 SetVFPState() | 3075 SetEXCState() | 3076 SetDBGState(); 3077 case e_regSetGPR: return SetGPRState(); 3078 case e_regSetVFP: return SetVFPState(); 3079 case e_regSetEXC: return SetEXCState(); 3080 case e_regSetDBG: return SetDBGState(); 3081 default: break; 3082 } 3083 return KERN_INVALID_ARGUMENT; 3084} 3085 3086bool 3087DNBArchMachARM::RegisterSetStateIsValid (int set) const 3088{ 3089 return m_state.RegsAreValid(set); 3090} 3091 3092 3093nub_size_t 3094DNBArchMachARM::GetRegisterContext (void *buf, nub_size_t buf_len) 3095{ 3096 nub_size_t size = sizeof (m_state.context); 3097 3098 if (buf && buf_len) 3099 { 3100 if (size > buf_len) 3101 size = buf_len; 3102 3103 bool force = false; 3104 if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force)) 3105 return 0; 3106 ::memcpy (buf, &m_state.context, size); 3107 } 3108 DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size); 3109 // Return the size of the register context even if NULL was passed in 3110 return size; 3111} 3112 3113nub_size_t 3114DNBArchMachARM::SetRegisterContext (const void *buf, nub_size_t buf_len) 3115{ 3116 nub_size_t size = sizeof (m_state.context); 3117 if (buf == NULL || buf_len == 0) 3118 size = 0; 3119 3120 if (size) 3121 { 3122 if (size > buf_len) 3123 size = buf_len; 3124 3125 ::memcpy (&m_state.context, buf, size); 3126 SetGPRState(); 3127 SetVFPState(); 3128 SetEXCState(); 3129 } 3130 DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size); 3131 return size; 3132} 3133 3134 3135#endif // #if defined (__arm__) 3136 3137