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