1dda28197Spatrick //===-- StopInfoMachException.cpp -----------------------------------------===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9061da546Spatrick #include "StopInfoMachException.h" 10061da546Spatrick 11dda28197Spatrick #include "lldb/lldb-forward.h" 12061da546Spatrick 13061da546Spatrick #if defined(__APPLE__) 14061da546Spatrick // Needed for the EXC_RESOURCE interpretation macros 15061da546Spatrick #include <kern/exc_resource.h> 16061da546Spatrick #endif 17061da546Spatrick 18061da546Spatrick #include "lldb/Breakpoint/Watchpoint.h" 19061da546Spatrick #include "lldb/Symbol/Symbol.h" 20061da546Spatrick #include "lldb/Target/DynamicLoader.h" 21061da546Spatrick #include "lldb/Target/ExecutionContext.h" 22061da546Spatrick #include "lldb/Target/Process.h" 23061da546Spatrick #include "lldb/Target/RegisterContext.h" 24061da546Spatrick #include "lldb/Target/Target.h" 25061da546Spatrick #include "lldb/Target/Thread.h" 26061da546Spatrick #include "lldb/Target/ThreadPlan.h" 27061da546Spatrick #include "lldb/Target/UnixSignals.h" 28061da546Spatrick #include "lldb/Utility/StreamString.h" 29061da546Spatrick 30061da546Spatrick using namespace lldb; 31061da546Spatrick using namespace lldb_private; 32061da546Spatrick 33061da546Spatrick const char *StopInfoMachException::GetDescription() { 34061da546Spatrick if (!m_description.empty()) 35061da546Spatrick return m_description.c_str(); 36061da546Spatrick if (GetValue() == eStopReasonInvalid) 37061da546Spatrick return "invalid stop reason!"; 38061da546Spatrick 39061da546Spatrick ExecutionContext exe_ctx(m_thread_wp.lock()); 40061da546Spatrick Target *target = exe_ctx.GetTargetPtr(); 41061da546Spatrick const llvm::Triple::ArchType cpu = 42061da546Spatrick target ? target->GetArchitecture().GetMachine() 43061da546Spatrick : llvm::Triple::UnknownArch; 44061da546Spatrick 45061da546Spatrick const char *exc_desc = nullptr; 46061da546Spatrick const char *code_label = "code"; 47061da546Spatrick const char *code_desc = nullptr; 48061da546Spatrick const char *subcode_label = "subcode"; 49061da546Spatrick const char *subcode_desc = nullptr; 50061da546Spatrick 51061da546Spatrick #if defined(__APPLE__) 52061da546Spatrick char code_desc_buf[32]; 53061da546Spatrick char subcode_desc_buf[32]; 54061da546Spatrick #endif 55061da546Spatrick 56061da546Spatrick switch (m_value) { 57061da546Spatrick case 1: // EXC_BAD_ACCESS 58061da546Spatrick exc_desc = "EXC_BAD_ACCESS"; 59061da546Spatrick subcode_label = "address"; 60061da546Spatrick switch (cpu) { 61061da546Spatrick case llvm::Triple::x86: 62061da546Spatrick case llvm::Triple::x86_64: 63061da546Spatrick switch (m_exc_code) { 64061da546Spatrick case 0xd: 65061da546Spatrick code_desc = "EXC_I386_GPFLT"; 66061da546Spatrick m_exc_data_count = 1; 67061da546Spatrick break; 68061da546Spatrick } 69061da546Spatrick break; 70061da546Spatrick case llvm::Triple::arm: 71061da546Spatrick case llvm::Triple::thumb: 72061da546Spatrick switch (m_exc_code) { 73061da546Spatrick case 0x101: 74061da546Spatrick code_desc = "EXC_ARM_DA_ALIGN"; 75061da546Spatrick break; 76061da546Spatrick case 0x102: 77061da546Spatrick code_desc = "EXC_ARM_DA_DEBUG"; 78061da546Spatrick break; 79061da546Spatrick } 80061da546Spatrick break; 81061da546Spatrick 82061da546Spatrick default: 83061da546Spatrick break; 84061da546Spatrick } 85061da546Spatrick break; 86061da546Spatrick 87061da546Spatrick case 2: // EXC_BAD_INSTRUCTION 88061da546Spatrick exc_desc = "EXC_BAD_INSTRUCTION"; 89061da546Spatrick switch (cpu) { 90061da546Spatrick case llvm::Triple::x86: 91061da546Spatrick case llvm::Triple::x86_64: 92061da546Spatrick if (m_exc_code == 1) 93061da546Spatrick code_desc = "EXC_I386_INVOP"; 94061da546Spatrick break; 95061da546Spatrick 96061da546Spatrick case llvm::Triple::arm: 97061da546Spatrick case llvm::Triple::thumb: 98061da546Spatrick if (m_exc_code == 1) 99061da546Spatrick code_desc = "EXC_ARM_UNDEFINED"; 100061da546Spatrick break; 101061da546Spatrick 102061da546Spatrick default: 103061da546Spatrick break; 104061da546Spatrick } 105061da546Spatrick break; 106061da546Spatrick 107061da546Spatrick case 3: // EXC_ARITHMETIC 108061da546Spatrick exc_desc = "EXC_ARITHMETIC"; 109061da546Spatrick switch (cpu) { 110061da546Spatrick case llvm::Triple::x86: 111061da546Spatrick case llvm::Triple::x86_64: 112061da546Spatrick switch (m_exc_code) { 113061da546Spatrick case 1: 114061da546Spatrick code_desc = "EXC_I386_DIV"; 115061da546Spatrick break; 116061da546Spatrick case 2: 117061da546Spatrick code_desc = "EXC_I386_INTO"; 118061da546Spatrick break; 119061da546Spatrick case 3: 120061da546Spatrick code_desc = "EXC_I386_NOEXT"; 121061da546Spatrick break; 122061da546Spatrick case 4: 123061da546Spatrick code_desc = "EXC_I386_EXTOVR"; 124061da546Spatrick break; 125061da546Spatrick case 5: 126061da546Spatrick code_desc = "EXC_I386_EXTERR"; 127061da546Spatrick break; 128061da546Spatrick case 6: 129061da546Spatrick code_desc = "EXC_I386_EMERR"; 130061da546Spatrick break; 131061da546Spatrick case 7: 132061da546Spatrick code_desc = "EXC_I386_BOUND"; 133061da546Spatrick break; 134061da546Spatrick case 8: 135061da546Spatrick code_desc = "EXC_I386_SSEEXTERR"; 136061da546Spatrick break; 137061da546Spatrick } 138061da546Spatrick break; 139061da546Spatrick 140061da546Spatrick default: 141061da546Spatrick break; 142061da546Spatrick } 143061da546Spatrick break; 144061da546Spatrick 145061da546Spatrick case 4: // EXC_EMULATION 146061da546Spatrick exc_desc = "EXC_EMULATION"; 147061da546Spatrick break; 148061da546Spatrick 149061da546Spatrick case 5: // EXC_SOFTWARE 150061da546Spatrick exc_desc = "EXC_SOFTWARE"; 151061da546Spatrick if (m_exc_code == 0x10003) { 152061da546Spatrick subcode_desc = "EXC_SOFT_SIGNAL"; 153061da546Spatrick subcode_label = "signo"; 154061da546Spatrick } 155061da546Spatrick break; 156061da546Spatrick 157061da546Spatrick case 6: // EXC_BREAKPOINT 158061da546Spatrick { 159061da546Spatrick exc_desc = "EXC_BREAKPOINT"; 160061da546Spatrick switch (cpu) { 161061da546Spatrick case llvm::Triple::x86: 162061da546Spatrick case llvm::Triple::x86_64: 163061da546Spatrick switch (m_exc_code) { 164061da546Spatrick case 1: 165061da546Spatrick code_desc = "EXC_I386_SGL"; 166061da546Spatrick break; 167061da546Spatrick case 2: 168061da546Spatrick code_desc = "EXC_I386_BPT"; 169061da546Spatrick break; 170061da546Spatrick } 171061da546Spatrick break; 172061da546Spatrick 173061da546Spatrick case llvm::Triple::arm: 174061da546Spatrick case llvm::Triple::thumb: 175061da546Spatrick switch (m_exc_code) { 176061da546Spatrick case 0x101: 177061da546Spatrick code_desc = "EXC_ARM_DA_ALIGN"; 178061da546Spatrick break; 179061da546Spatrick case 0x102: 180061da546Spatrick code_desc = "EXC_ARM_DA_DEBUG"; 181061da546Spatrick break; 182061da546Spatrick case 1: 183061da546Spatrick code_desc = "EXC_ARM_BREAKPOINT"; 184061da546Spatrick break; 185061da546Spatrick // FIXME temporary workaround, exc_code 0 does not really mean 186061da546Spatrick // EXC_ARM_BREAKPOINT 187061da546Spatrick case 0: 188061da546Spatrick code_desc = "EXC_ARM_BREAKPOINT"; 189061da546Spatrick break; 190061da546Spatrick } 191061da546Spatrick break; 192061da546Spatrick 193061da546Spatrick default: 194061da546Spatrick break; 195061da546Spatrick } 196061da546Spatrick } break; 197061da546Spatrick 198061da546Spatrick case 7: 199061da546Spatrick exc_desc = "EXC_SYSCALL"; 200061da546Spatrick break; 201061da546Spatrick 202061da546Spatrick case 8: 203061da546Spatrick exc_desc = "EXC_MACH_SYSCALL"; 204061da546Spatrick break; 205061da546Spatrick 206061da546Spatrick case 9: 207061da546Spatrick exc_desc = "EXC_RPC_ALERT"; 208061da546Spatrick break; 209061da546Spatrick 210061da546Spatrick case 10: 211061da546Spatrick exc_desc = "EXC_CRASH"; 212061da546Spatrick break; 213061da546Spatrick case 11: 214061da546Spatrick exc_desc = "EXC_RESOURCE"; 215061da546Spatrick #if defined(__APPLE__) 216061da546Spatrick { 217061da546Spatrick int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(m_exc_code); 218061da546Spatrick 219061da546Spatrick code_label = "limit"; 220061da546Spatrick code_desc = code_desc_buf; 221061da546Spatrick subcode_label = "observed"; 222061da546Spatrick subcode_desc = subcode_desc_buf; 223061da546Spatrick 224061da546Spatrick switch (resource_type) { 225061da546Spatrick case RESOURCE_TYPE_CPU: 226061da546Spatrick exc_desc = "EXC_RESOURCE RESOURCE_TYPE_CPU"; 227061da546Spatrick snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%", 228061da546Spatrick (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code)); 229061da546Spatrick snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%", 230061da546Spatrick (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED( 231061da546Spatrick m_exc_subcode)); 232061da546Spatrick break; 233061da546Spatrick case RESOURCE_TYPE_WAKEUPS: 234061da546Spatrick exc_desc = "EXC_RESOURCE RESOURCE_TYPE_WAKEUPS"; 235061da546Spatrick snprintf( 236061da546Spatrick code_desc_buf, sizeof(code_desc_buf), "%d w/s", 237061da546Spatrick (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_PERMITTED(m_exc_code)); 238061da546Spatrick snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s", 239061da546Spatrick (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED( 240061da546Spatrick m_exc_subcode)); 241061da546Spatrick break; 242061da546Spatrick case RESOURCE_TYPE_MEMORY: 243061da546Spatrick exc_desc = "EXC_RESOURCE RESOURCE_TYPE_MEMORY"; 244061da546Spatrick snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", 245061da546Spatrick (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code)); 246061da546Spatrick subcode_desc = nullptr; 247061da546Spatrick subcode_label = "unused"; 248061da546Spatrick break; 249061da546Spatrick #if defined(RESOURCE_TYPE_IO) 250061da546Spatrick // RESOURCE_TYPE_IO is introduced in macOS SDK 10.12. 251061da546Spatrick case RESOURCE_TYPE_IO: 252061da546Spatrick exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO"; 253061da546Spatrick snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", 254061da546Spatrick (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code)); 255061da546Spatrick snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB", 256061da546Spatrick (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode)); 257061da546Spatrick ; 258061da546Spatrick break; 259061da546Spatrick #endif 260061da546Spatrick } 261061da546Spatrick } 262061da546Spatrick #endif 263061da546Spatrick break; 264061da546Spatrick case 12: 265061da546Spatrick exc_desc = "EXC_GUARD"; 266061da546Spatrick break; 267061da546Spatrick } 268061da546Spatrick 269061da546Spatrick StreamString strm; 270061da546Spatrick 271061da546Spatrick if (exc_desc) 272061da546Spatrick strm.PutCString(exc_desc); 273061da546Spatrick else 274061da546Spatrick strm.Printf("EXC_??? (%" PRIu64 ")", m_value); 275061da546Spatrick 276061da546Spatrick if (m_exc_data_count >= 1) { 277061da546Spatrick if (code_desc) 278061da546Spatrick strm.Printf(" (%s=%s", code_label, code_desc); 279061da546Spatrick else 280061da546Spatrick strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code); 281061da546Spatrick } 282061da546Spatrick 283061da546Spatrick if (m_exc_data_count >= 2) { 284061da546Spatrick if (subcode_desc) 285061da546Spatrick strm.Printf(", %s=%s", subcode_label, subcode_desc); 286061da546Spatrick else 287061da546Spatrick strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode); 288061da546Spatrick } 289061da546Spatrick 290061da546Spatrick if (m_exc_data_count > 0) 291061da546Spatrick strm.PutChar(')'); 292061da546Spatrick 293dda28197Spatrick m_description = std::string(strm.GetString()); 294061da546Spatrick return m_description.c_str(); 295061da546Spatrick } 296061da546Spatrick 297dda28197Spatrick static StopInfoSP GetStopInfoForHardwareBP(Thread &thread, Target *target, 298dda28197Spatrick uint32_t exc_data_count, 299dda28197Spatrick uint64_t exc_sub_code, 300dda28197Spatrick uint64_t exc_sub_sub_code) { 301dda28197Spatrick // Try hardware watchpoint. 302dda28197Spatrick if (target) { 303dda28197Spatrick // The exc_sub_code indicates the data break address. 304dda28197Spatrick lldb::WatchpointSP wp_sp = 305dda28197Spatrick target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code); 306dda28197Spatrick if (wp_sp && wp_sp->IsEnabled()) { 307dda28197Spatrick // Debugserver may piggyback the hardware index of the fired watchpoint 308dda28197Spatrick // in the exception data. Set the hardware index if that's the case. 309dda28197Spatrick if (exc_data_count >= 3) 310dda28197Spatrick wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); 311dda28197Spatrick return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); 312dda28197Spatrick } 313dda28197Spatrick } 314dda28197Spatrick 315dda28197Spatrick // Try hardware breakpoint. 316dda28197Spatrick ProcessSP process_sp(thread.GetProcess()); 317dda28197Spatrick if (process_sp) { 318dda28197Spatrick // The exc_sub_code indicates the data break address. 319dda28197Spatrick lldb::BreakpointSiteSP bp_sp = 320dda28197Spatrick process_sp->GetBreakpointSiteList().FindByAddress( 321dda28197Spatrick (lldb::addr_t)exc_sub_code); 322dda28197Spatrick if (bp_sp && bp_sp->IsEnabled()) { 323dda28197Spatrick // Debugserver may piggyback the hardware index of the fired breakpoint 324dda28197Spatrick // in the exception data. Set the hardware index if that's the case. 325dda28197Spatrick if (exc_data_count >= 3) 326dda28197Spatrick bp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); 327dda28197Spatrick return StopInfo::CreateStopReasonWithBreakpointSiteID(thread, 328dda28197Spatrick bp_sp->GetID()); 329dda28197Spatrick } 330dda28197Spatrick } 331dda28197Spatrick 332dda28197Spatrick return nullptr; 333dda28197Spatrick } 334dda28197Spatrick 335061da546Spatrick StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( 336061da546Spatrick Thread &thread, uint32_t exc_type, uint32_t exc_data_count, 337061da546Spatrick uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code, 338061da546Spatrick bool pc_already_adjusted, bool adjust_pc_if_needed) { 339061da546Spatrick if (exc_type == 0) 340061da546Spatrick return StopInfoSP(); 341061da546Spatrick 342061da546Spatrick uint32_t pc_decrement = 0; 343061da546Spatrick ExecutionContext exe_ctx(thread.shared_from_this()); 344061da546Spatrick Target *target = exe_ctx.GetTargetPtr(); 345061da546Spatrick const llvm::Triple::ArchType cpu = 346061da546Spatrick target ? target->GetArchitecture().GetMachine() 347061da546Spatrick : llvm::Triple::UnknownArch; 348061da546Spatrick 349061da546Spatrick switch (exc_type) { 350061da546Spatrick case 1: // EXC_BAD_ACCESS 351061da546Spatrick case 2: // EXC_BAD_INSTRUCTION 352061da546Spatrick case 3: // EXC_ARITHMETIC 353061da546Spatrick case 4: // EXC_EMULATION 354061da546Spatrick break; 355061da546Spatrick 356061da546Spatrick case 5: // EXC_SOFTWARE 357061da546Spatrick if (exc_code == 0x10003) // EXC_SOFT_SIGNAL 358061da546Spatrick { 359061da546Spatrick if (exc_sub_code == 5) { 360061da546Spatrick // On MacOSX, a SIGTRAP can signify that a process has called exec, 361061da546Spatrick // so we should check with our dynamic loader to verify. 362061da546Spatrick ProcessSP process_sp(thread.GetProcess()); 363061da546Spatrick if (process_sp) { 364061da546Spatrick DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader(); 365061da546Spatrick if (dynamic_loader && dynamic_loader->ProcessDidExec()) { 366061da546Spatrick // The program was re-exec'ed 367061da546Spatrick return StopInfo::CreateStopReasonWithExec(thread); 368061da546Spatrick } 369061da546Spatrick } 370061da546Spatrick } 371061da546Spatrick return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code); 372061da546Spatrick } 373061da546Spatrick break; 374061da546Spatrick 375061da546Spatrick case 6: // EXC_BREAKPOINT 376061da546Spatrick { 377061da546Spatrick bool is_actual_breakpoint = false; 378061da546Spatrick bool is_trace_if_actual_breakpoint_missing = false; 379061da546Spatrick switch (cpu) { 380061da546Spatrick case llvm::Triple::x86: 381061da546Spatrick case llvm::Triple::x86_64: 382061da546Spatrick if (exc_code == 1) // EXC_I386_SGL 383061da546Spatrick { 384061da546Spatrick if (!exc_sub_code) { 385061da546Spatrick // This looks like a plain trap. 386061da546Spatrick // Have to check if there is a breakpoint here as well. When you 387061da546Spatrick // single-step onto a trap, the single step stops you not to trap. 388061da546Spatrick // Since we also do that check below, let's just use that logic. 389061da546Spatrick is_actual_breakpoint = true; 390061da546Spatrick is_trace_if_actual_breakpoint_missing = true; 391061da546Spatrick } else { 392dda28197Spatrick if (StopInfoSP stop_info = 393dda28197Spatrick GetStopInfoForHardwareBP(thread, target, exc_data_count, 394dda28197Spatrick exc_sub_code, exc_sub_sub_code)) 395dda28197Spatrick return stop_info; 396061da546Spatrick } 397061da546Spatrick } else if (exc_code == 2 || // EXC_I386_BPT 398061da546Spatrick exc_code == 3) // EXC_I386_BPTFLT 399061da546Spatrick { 400061da546Spatrick // KDP returns EXC_I386_BPTFLT for trace breakpoints 401061da546Spatrick if (exc_code == 3) 402061da546Spatrick is_trace_if_actual_breakpoint_missing = true; 403061da546Spatrick 404061da546Spatrick is_actual_breakpoint = true; 405061da546Spatrick if (!pc_already_adjusted) 406061da546Spatrick pc_decrement = 1; 407061da546Spatrick } 408061da546Spatrick break; 409061da546Spatrick 410061da546Spatrick case llvm::Triple::arm: 411061da546Spatrick case llvm::Triple::thumb: 412061da546Spatrick if (exc_code == 0x102) // EXC_ARM_DA_DEBUG 413061da546Spatrick { 414061da546Spatrick // It's a watchpoint, then, if the exc_sub_code indicates a 415061da546Spatrick // known/enabled data break address from our watchpoint list. 416061da546Spatrick lldb::WatchpointSP wp_sp; 417061da546Spatrick if (target) 418061da546Spatrick wp_sp = target->GetWatchpointList().FindByAddress( 419061da546Spatrick (lldb::addr_t)exc_sub_code); 420061da546Spatrick if (wp_sp && wp_sp->IsEnabled()) { 421061da546Spatrick // Debugserver may piggyback the hardware index of the fired 422061da546Spatrick // watchpoint in the exception data. Set the hardware index if 423061da546Spatrick // that's the case. 424061da546Spatrick if (exc_data_count >= 3) 425061da546Spatrick wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); 426061da546Spatrick return StopInfo::CreateStopReasonWithWatchpointID(thread, 427061da546Spatrick wp_sp->GetID()); 428061da546Spatrick } else { 429061da546Spatrick is_actual_breakpoint = true; 430061da546Spatrick is_trace_if_actual_breakpoint_missing = true; 431061da546Spatrick } 432061da546Spatrick } else if (exc_code == 1) // EXC_ARM_BREAKPOINT 433061da546Spatrick { 434061da546Spatrick is_actual_breakpoint = true; 435061da546Spatrick is_trace_if_actual_breakpoint_missing = true; 436061da546Spatrick } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel 437061da546Spatrick // is currently returning this so accept it 438061da546Spatrick // as indicating a breakpoint until the 439061da546Spatrick // kernel is fixed 440061da546Spatrick { 441061da546Spatrick is_actual_breakpoint = true; 442061da546Spatrick is_trace_if_actual_breakpoint_missing = true; 443061da546Spatrick } 444061da546Spatrick break; 445061da546Spatrick 446061da546Spatrick case llvm::Triple::aarch64_32: 447061da546Spatrick case llvm::Triple::aarch64: { 448061da546Spatrick if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT 449061da546Spatrick { 450061da546Spatrick // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0 451061da546Spatrick // is set 452061da546Spatrick is_actual_breakpoint = false; 453061da546Spatrick is_trace_if_actual_breakpoint_missing = true; 454061da546Spatrick } 455061da546Spatrick if (exc_code == 0x102) // EXC_ARM_DA_DEBUG 456061da546Spatrick { 457061da546Spatrick // It's a watchpoint, then, if the exc_sub_code indicates a 458061da546Spatrick // known/enabled data break address from our watchpoint list. 459061da546Spatrick lldb::WatchpointSP wp_sp; 460061da546Spatrick if (target) 461061da546Spatrick wp_sp = target->GetWatchpointList().FindByAddress( 462061da546Spatrick (lldb::addr_t)exc_sub_code); 463061da546Spatrick if (wp_sp && wp_sp->IsEnabled()) { 464061da546Spatrick // Debugserver may piggyback the hardware index of the fired 465061da546Spatrick // watchpoint in the exception data. Set the hardware index if 466061da546Spatrick // that's the case. 467061da546Spatrick if (exc_data_count >= 3) 468061da546Spatrick wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); 469061da546Spatrick return StopInfo::CreateStopReasonWithWatchpointID(thread, 470061da546Spatrick wp_sp->GetID()); 471061da546Spatrick } 472061da546Spatrick // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as 473061da546Spatrick // EXC_BAD_ACCESS 474061da546Spatrick if (thread.GetTemporaryResumeState() == eStateStepping) 475061da546Spatrick return StopInfo::CreateStopReasonToTrace(thread); 476061da546Spatrick } 477061da546Spatrick // It looks like exc_sub_code has the 4 bytes of the instruction that 478061da546Spatrick // triggered the exception, i.e. our breakpoint opcode 479061da546Spatrick is_actual_breakpoint = exc_code == 1; 480061da546Spatrick break; 481061da546Spatrick } 482061da546Spatrick 483061da546Spatrick default: 484061da546Spatrick break; 485061da546Spatrick } 486061da546Spatrick 487061da546Spatrick if (is_actual_breakpoint) { 488061da546Spatrick RegisterContextSP reg_ctx_sp(thread.GetRegisterContext()); 489061da546Spatrick addr_t pc = reg_ctx_sp->GetPC() - pc_decrement; 490061da546Spatrick 491061da546Spatrick ProcessSP process_sp(thread.CalculateProcess()); 492061da546Spatrick 493061da546Spatrick lldb::BreakpointSiteSP bp_site_sp; 494061da546Spatrick if (process_sp) 495061da546Spatrick bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc); 496061da546Spatrick if (bp_site_sp && bp_site_sp->IsEnabled()) { 497061da546Spatrick // Update the PC if we were asked to do so, but only do so if we find 498061da546Spatrick // a breakpoint that we know about cause this could be a trap 499061da546Spatrick // instruction in the code 500061da546Spatrick if (pc_decrement > 0 && adjust_pc_if_needed) 501061da546Spatrick reg_ctx_sp->SetPC(pc); 502061da546Spatrick 503061da546Spatrick // If the breakpoint is for this thread, then we'll report the hit, 504061da546Spatrick // but if it is for another thread, we can just report no reason. We 505061da546Spatrick // don't need to worry about stepping over the breakpoint here, that 506061da546Spatrick // will be taken care of when the thread resumes and notices that 507061da546Spatrick // there's a breakpoint under the pc. If we have an operating system 508061da546Spatrick // plug-in, we might have set a thread specific breakpoint using the 509061da546Spatrick // operating system thread ID, so we can't make any assumptions about 510061da546Spatrick // the thread ID so we must always report the breakpoint regardless 511061da546Spatrick // of the thread. 512*be691f3bSpatrick if (bp_site_sp->ValidForThisThread(thread) || 513061da546Spatrick thread.GetProcess()->GetOperatingSystem() != nullptr) 514061da546Spatrick return StopInfo::CreateStopReasonWithBreakpointSiteID( 515061da546Spatrick thread, bp_site_sp->GetID()); 516061da546Spatrick else if (is_trace_if_actual_breakpoint_missing) 517061da546Spatrick return StopInfo::CreateStopReasonToTrace(thread); 518061da546Spatrick else 519061da546Spatrick return StopInfoSP(); 520061da546Spatrick } 521061da546Spatrick 522061da546Spatrick // Don't call this a trace if we weren't single stepping this thread. 523061da546Spatrick if (is_trace_if_actual_breakpoint_missing && 524061da546Spatrick thread.GetTemporaryResumeState() == eStateStepping) { 525061da546Spatrick return StopInfo::CreateStopReasonToTrace(thread); 526061da546Spatrick } 527061da546Spatrick } 528061da546Spatrick } break; 529061da546Spatrick 530061da546Spatrick case 7: // EXC_SYSCALL 531061da546Spatrick case 8: // EXC_MACH_SYSCALL 532061da546Spatrick case 9: // EXC_RPC_ALERT 533061da546Spatrick case 10: // EXC_CRASH 534061da546Spatrick break; 535061da546Spatrick } 536061da546Spatrick 537061da546Spatrick return StopInfoSP(new StopInfoMachException(thread, exc_type, exc_data_count, 538061da546Spatrick exc_code, exc_sub_code)); 539061da546Spatrick } 540