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