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