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