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