================ @@ -633,171 +613,142 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( } break; + // [exc_type, exc_code, exc_sub_code, exc_sub_sub_code] + // + // Instruction step: + // [6, 1, 0] + // Intel KDP [6, 3, ??] + // armv7 [6, 0x102, <stop-pc>] Same as software breakpoint! + // + // Software breakpoint: + // x86 [6, 2, 0] + // Intel KDP [6, 2, <bp-addr + 1>] + // arm64 [6, 1, <bp-addr>] + // armv7 [6, 0x102, <bp-addr>] Same as instruction step! + // + // Hardware breakpoint: + // x86 [6, 1, <bp-addr>, 0] + // x86/Rosetta not implemented, see software breakpoint + // arm64 [6, 1, <bp-addr>] + // armv7 not implemented, see software breakpoint + // + // Hardware watchpoint: + // x86 [6, 1, <accessed-addr>, 0] (both Intel hw and Rosetta) + // arm64 [6, 0x102, <accessed-addr>, 0] + // armv7 [6, 0x102, <accessed-addr>, 0] + // + // arm64 BRK instruction (imm arg not reflected in the ME) + // [ 6, 1, <addr-of-BRK-insn>] + // + // In order of codes mach exceptions: + // [6, 1, 0] - instruction step + // [6, 1, <bp-addr>] - hardware breakpoint or watchpoint + // + // [6, 2, 0] - software breakpoint + // [6, 2, <bp-addr + 1>] - software breakpoint + // + // [6, 3] - instruction step + // + // [6, 0x102, <stop-pc>] armv7 instruction step + // [6, 0x102, <bp-addr>] armv7 software breakpoint + // [6, 0x102, <accessed-addr>, 0] arm64/armv7 watchpoint case 6: // EXC_BREAKPOINT { - bool is_actual_breakpoint = false; - bool is_trace_if_actual_breakpoint_missing = false; - switch (cpu) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - if (exc_code == 1) // EXC_I386_SGL - { - if (!exc_sub_code) { - // This looks like a plain trap. - // Have to check if there is a breakpoint here as well. When you - // single-step onto a trap, the single step stops you not to trap. - // Since we also do that check below, let's just use that logic. - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } else { - if (StopInfoSP stop_info = - GetStopInfoForHardwareBP(thread, target, exc_data_count, - exc_sub_code, exc_sub_sub_code)) - return stop_info; - } - } else if (exc_code == 2 || // EXC_I386_BPT - exc_code == 3) // EXC_I386_BPTFLT - { - // KDP returns EXC_I386_BPTFLT for trace breakpoints - if (exc_code == 3) - is_trace_if_actual_breakpoint_missing = true; - - is_actual_breakpoint = true; - if (!pc_already_adjusted) - pc_decrement = 1; - } - break; - - case llvm::Triple::arm: - case llvm::Triple::thumb: - if (exc_code == 0x102) // EXC_ARM_DA_DEBUG - { - // LWP_TODO: We need to find the WatchpointResource that matches - // the address, and evaluate its Watchpoints. - - // It's a watchpoint, then, if the exc_sub_code indicates a - // known/enabled data break address from our watchpoint list. - lldb::WatchpointSP wp_sp; - if (target) - wp_sp = target->GetWatchpointList().FindByAddress( - (lldb::addr_t)exc_sub_code); - if (wp_sp && wp_sp->IsEnabled()) { - return StopInfo::CreateStopReasonWithWatchpointID(thread, - wp_sp->GetID()); - } else { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } - } else if (exc_code == 1) // EXC_ARM_BREAKPOINT - { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel - // is currently returning this so accept it - // as indicating a breakpoint until the - // kernel is fixed - { - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - } - break; + bool stopped_by_hitting_breakpoint = false; + bool stopped_by_completing_stepi = false; + bool stopped_watchpoint = false; + std::optional<addr_t> value; + + // exc_code 1 + if (exc_code == 1 && exc_sub_code == 0) + stopped_by_completing_stepi = true; + if (exc_code == 1 && exc_sub_code != 0) { + stopped_by_hitting_breakpoint = true; + stopped_watchpoint = true; + value = exc_sub_code; + } - case llvm::Triple::aarch64_32: - case llvm::Triple::aarch64: { - // xnu describes three things with type EXC_BREAKPOINT: - // - // exc_code 0x102 [EXC_ARM_DA_DEBUG], exc_sub_code addr-of-insn - // Watchpoint access. exc_sub_code is the address of the - // instruction which trigged the watchpoint trap. - // debugserver may add the watchpoint number that was triggered - // in exc_sub_sub_code. - // - // exc_code 1 [EXC_ARM_BREAKPOINT], exc_sub_code 0 - // Instruction step has completed. - // - // exc_code 1 [EXC_ARM_BREAKPOINT], exc_sub_code address-of-instruction - // Software breakpoint instruction executed. - - if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT - { - // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0 - // is set - is_actual_breakpoint = true; - is_trace_if_actual_breakpoint_missing = true; - if (thread.GetTemporaryResumeState() != eStateStepping) - not_stepping_but_got_singlestep_exception = true; - } - if (exc_code == 0x102) // EXC_ARM_DA_DEBUG - { - // LWP_TODO: We need to find the WatchpointResource that matches - // the address, and evaluate its Watchpoints. - - // It's a watchpoint, then, if the exc_sub_code indicates a - // known/enabled data break address from our watchpoint list. - lldb::WatchpointSP wp_sp; - if (target) - wp_sp = target->GetWatchpointList().FindByAddress( - (lldb::addr_t)exc_sub_code); - if (wp_sp && wp_sp->IsEnabled()) { - return StopInfo::CreateStopReasonWithWatchpointID(thread, - wp_sp->GetID()); - } - // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as - // EXC_BAD_ACCESS - if (thread.GetTemporaryResumeState() == eStateStepping) - return StopInfo::CreateStopReasonToTrace(thread); - } - // It looks like exc_sub_code has the 4 bytes of the instruction that - // triggered the exception, i.e. our breakpoint opcode - is_actual_breakpoint = exc_code == 1; - break; + // exc_code 2 + if (exc_code == 2 && exc_sub_code == 0) + stopped_by_hitting_breakpoint = true; + if (exc_code == 2 && exc_sub_code != 0) { + stopped_by_hitting_breakpoint = true; + // Intel KDP software breakpoint + if (!pc_already_adjusted) ---------------- jasonmolenda wrote:
We set `pc_decrement` here and later it's applied only if `adjust_pc_if_needed` (although that one doesn't look at `pc_already_adjusted` - this is so confusingly implemented. I carried all of this logic over from the original, and didn't test x86 KDP debugging so I was reticent to change much.) https://github.com/llvm/llvm-project/pull/96260 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits