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