LLDB  mainline
StopInfoMachException.cpp
Go to the documentation of this file.
1 //===-- StopInfoMachException.cpp -----------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 
11 #include "lldb/lldb-forward.h"
12 
13 #if defined(__APPLE__)
14 // Needed for the EXC_RESOURCE interpretation macros
15 #include <kern/exc_resource.h>
16 #endif
17 
19 #include "lldb/Symbol/Symbol.h"
20 #include "lldb/Target/ABI.h"
23 #include "lldb/Target/Process.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/Thread.h"
27 #include "lldb/Target/ThreadPlan.h"
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 /// Information about a pointer-authentication related instruction.
37  bool IsLoad;
38  bool DoesBranch;
39 };
40 
41 /// Get any pointer-authentication related information about the instruction
42 /// at address \p at_addr.
43 static llvm::Optional<PtrauthInstructionInfo>
45  const Address &at_addr) {
46  const char *plugin_name = nullptr;
47  const char *flavor = nullptr;
48  AddressRange range_bounds(at_addr, 4);
49  const bool prefer_file_cache = true;
50  DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
51  arch, plugin_name, flavor, target, range_bounds, prefer_file_cache);
52  if (!disassembler_sp)
53  return llvm::None;
54 
55  InstructionList &insn_list = disassembler_sp->GetInstructionList();
56  InstructionSP insn = insn_list.GetInstructionAtIndex(0);
57  if (!insn)
58  return llvm::None;
59 
60  return PtrauthInstructionInfo{insn->IsAuthenticated(), insn->IsLoad(),
61  insn->DoesBranch()};
62 }
63 
64 /// Describe the load address of \p addr using the format filename:line:col.
65 static void DescribeAddressBriefly(Stream &strm, const Address &addr,
66  Target &target) {
67  strm.Printf("at address=0x%" PRIx64, addr.GetLoadAddress(&target));
68  StreamString s;
69  if (addr.GetDescription(s, target, eDescriptionLevelBrief))
70  strm.Printf(" %s", s.GetString().data());
71  strm.Printf(".\n");
72 }
73 
74 bool StopInfoMachException::DeterminePtrauthFailure(ExecutionContext &exe_ctx) {
75  bool IsBreakpoint = m_value == 6; // EXC_BREAKPOINT
76  bool IsBadAccess = m_value == 1; // EXC_BAD_ACCESS
77  if (!IsBreakpoint && !IsBadAccess)
78  return false;
79 
80  // Check that we have a live process.
81  if (!exe_ctx.HasProcessScope() || !exe_ctx.HasThreadScope() ||
82  !exe_ctx.HasTargetScope())
83  return false;
84 
85  Thread &thread = *exe_ctx.GetThreadPtr();
86  StackFrameSP current_frame = thread.GetStackFrameAtIndex(0);
87  if (!current_frame)
88  return false;
89 
90  Target &target = *exe_ctx.GetTargetPtr();
91  Process &process = *exe_ctx.GetProcessPtr();
92  ABISP abi_sp = process.GetABI();
93  const ArchSpec &arch = target.GetArchitecture();
94  assert(abi_sp && "Missing ABI info");
95 
96  // Check for a ptrauth-enabled target.
97  const bool ptrauth_enabled_target =
98  arch.GetCore() == ArchSpec::eCore_arm_arm64e;
99  if (!ptrauth_enabled_target)
100  return false;
101 
102  // Set up a stream we can write a diagnostic into.
103  StreamString strm;
104  auto emit_ptrauth_prologue = [&](uint64_t at_address) {
105  strm.Printf("EXC_BAD_ACCESS (code=%" PRIu64 ", address=0x%" PRIx64 ")\n",
106  m_exc_code, at_address);
107  strm.Printf("Note: Possible pointer authentication failure detected.\n");
108  };
109 
110  // Check if we have a "brk 0xc47x" trap, where the value that failed to
111  // authenticate is in x16.
112  Address current_address = current_frame->GetFrameCodeAddress();
113  if (IsBreakpoint) {
114  RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
115  if (!reg_ctx)
116  return false;
117 
118  const RegisterInfo *X16Info = reg_ctx->GetRegisterInfoByName("x16");
119  RegisterValue X16Val;
120  if (!reg_ctx->ReadRegister(X16Info, X16Val))
121  return false;
122  uint64_t bad_address = X16Val.GetAsUInt64();
123 
124  uint64_t fixed_bad_address = abi_sp->FixCodeAddress(bad_address);
125  Address brk_address;
126  if (!target.ResolveLoadAddress(fixed_bad_address, brk_address))
127  return false;
128 
129  auto brk_ptrauth_info =
130  GetPtrauthInstructionInfo(target, arch, current_address);
131  if (brk_ptrauth_info && brk_ptrauth_info->IsAuthenticated) {
132  emit_ptrauth_prologue(bad_address);
133  strm.Printf("Found value that failed to authenticate ");
134  DescribeAddressBriefly(strm, brk_address, target);
135  m_description = std::string(strm.GetString());
136  return true;
137  }
138  return false;
139  }
140 
141  assert(IsBadAccess && "Handle EXC_BAD_ACCESS only after this point");
142 
143  // Check that we have the "bad address" from an EXC_BAD_ACCESS.
144  if (m_exc_data_count < 2)
145  return false;
146 
147  // Ok, we know the Target is valid and that it describes a ptrauth-enabled
148  // device. Now, we need to determine whether this exception was caused by a
149  // ptrauth failure.
150 
151  uint64_t bad_address = m_exc_subcode;
152  uint64_t fixed_bad_address = abi_sp->FixCodeAddress(bad_address);
153  uint64_t current_pc = current_address.GetLoadAddress(&target);
154 
155  // Detect: LDRAA, LDRAB (Load Register, with pointer authentication).
156  //
157  // If an authenticated load results in an exception, the instruction at the
158  // current PC should be one of LDRAx.
159  if (bad_address != current_pc && fixed_bad_address != current_pc) {
160  auto ptrauth_info =
161  GetPtrauthInstructionInfo(target, arch, current_address);
162  if (ptrauth_info && ptrauth_info->IsAuthenticated && ptrauth_info->IsLoad) {
163  emit_ptrauth_prologue(bad_address);
164  strm.Printf("Found authenticated load instruction ");
165  DescribeAddressBriefly(strm, current_address, target);
166  m_description = std::string(strm.GetString());
167  return true;
168  }
169  }
170 
171  // Detect: BLRAA, BLRAAZ, BLRAB, BLRABZ (Branch with Link to Register, with
172  // pointer authentication).
173  //
174  // TODO: Detect: BRAA, BRAAZ, BRAB, BRABZ (Branch to Register, with pointer
175  // authentication). At a minimum, this requires call site info support for
176  // indirect calls.
177  //
178  // If an authenticated call or tail call results in an exception, stripping
179  // the bad address should give the current PC, which points to the address
180  // we tried to branch to.
181  if (bad_address != current_pc && fixed_bad_address == current_pc) {
182  if (StackFrameSP parent_frame = thread.GetStackFrameAtIndex(1)) {
183  addr_t return_pc =
184  parent_frame->GetFrameCodeAddress().GetLoadAddress(&target);
185  Address blr_address;
186  if (!target.ResolveLoadAddress(return_pc - 4, blr_address))
187  return false;
188 
189  auto blr_ptrauth_info =
190  GetPtrauthInstructionInfo(target, arch, blr_address);
191  if (blr_ptrauth_info && blr_ptrauth_info->IsAuthenticated &&
192  blr_ptrauth_info->DoesBranch) {
193  emit_ptrauth_prologue(bad_address);
194  strm.Printf("Found authenticated indirect branch ");
195  DescribeAddressBriefly(strm, blr_address, target);
196  m_description = std::string(strm.GetString());
197  return true;
198  }
199  }
200  }
201 
202  // TODO: Detect: RETAA, RETAB (Return from subroutine, with pointer
203  // authentication).
204  //
205  // Is there a motivating, non-malicious code snippet that corrupts LR?
206 
207  return false;
208 }
209 
210 const char *StopInfoMachException::GetDescription() {
211  if (!m_description.empty())
212  return m_description.c_str();
213  if (GetValue() == eStopReasonInvalid)
214  return "invalid stop reason!";
215 
216  ExecutionContext exe_ctx(m_thread_wp.lock());
217  Target *target = exe_ctx.GetTargetPtr();
218  const llvm::Triple::ArchType cpu =
219  target ? target->GetArchitecture().GetMachine()
220  : llvm::Triple::UnknownArch;
221 
222  const char *exc_desc = nullptr;
223  const char *code_label = "code";
224  const char *code_desc = nullptr;
225  const char *subcode_label = "subcode";
226  const char *subcode_desc = nullptr;
227 
228 #if defined(__APPLE__)
229  char code_desc_buf[32];
230  char subcode_desc_buf[32];
231 #endif
232 
233  switch (m_value) {
234  case 1: // EXC_BAD_ACCESS
235  exc_desc = "EXC_BAD_ACCESS";
236  subcode_label = "address";
237  switch (cpu) {
238  case llvm::Triple::x86:
239  case llvm::Triple::x86_64:
240  switch (m_exc_code) {
241  case 0xd:
242  code_desc = "EXC_I386_GPFLT";
243  m_exc_data_count = 1;
244  break;
245  }
246  break;
247  case llvm::Triple::arm:
248  case llvm::Triple::thumb:
249  switch (m_exc_code) {
250  case 0x101:
251  code_desc = "EXC_ARM_DA_ALIGN";
252  break;
253  case 0x102:
254  code_desc = "EXC_ARM_DA_DEBUG";
255  break;
256  }
257  break;
258 
259  case llvm::Triple::aarch64:
260  if (DeterminePtrauthFailure(exe_ctx))
261  return m_description.c_str();
262  break;
263 
264  default:
265  break;
266  }
267  break;
268 
269  case 2: // EXC_BAD_INSTRUCTION
270  exc_desc = "EXC_BAD_INSTRUCTION";
271  switch (cpu) {
272  case llvm::Triple::x86:
273  case llvm::Triple::x86_64:
274  if (m_exc_code == 1)
275  code_desc = "EXC_I386_INVOP";
276  break;
277 
278  case llvm::Triple::arm:
279  case llvm::Triple::thumb:
280  if (m_exc_code == 1)
281  code_desc = "EXC_ARM_UNDEFINED";
282  break;
283 
284  default:
285  break;
286  }
287  break;
288 
289  case 3: // EXC_ARITHMETIC
290  exc_desc = "EXC_ARITHMETIC";
291  switch (cpu) {
292  case llvm::Triple::x86:
293  case llvm::Triple::x86_64:
294  switch (m_exc_code) {
295  case 1:
296  code_desc = "EXC_I386_DIV";
297  break;
298  case 2:
299  code_desc = "EXC_I386_INTO";
300  break;
301  case 3:
302  code_desc = "EXC_I386_NOEXT";
303  break;
304  case 4:
305  code_desc = "EXC_I386_EXTOVR";
306  break;
307  case 5:
308  code_desc = "EXC_I386_EXTERR";
309  break;
310  case 6:
311  code_desc = "EXC_I386_EMERR";
312  break;
313  case 7:
314  code_desc = "EXC_I386_BOUND";
315  break;
316  case 8:
317  code_desc = "EXC_I386_SSEEXTERR";
318  break;
319  }
320  break;
321 
322  default:
323  break;
324  }
325  break;
326 
327  case 4: // EXC_EMULATION
328  exc_desc = "EXC_EMULATION";
329  break;
330 
331  case 5: // EXC_SOFTWARE
332  exc_desc = "EXC_SOFTWARE";
333  if (m_exc_code == 0x10003) {
334  subcode_desc = "EXC_SOFT_SIGNAL";
335  subcode_label = "signo";
336  }
337  break;
338 
339  case 6: // EXC_BREAKPOINT
340  {
341  exc_desc = "EXC_BREAKPOINT";
342  switch (cpu) {
343  case llvm::Triple::x86:
344  case llvm::Triple::x86_64:
345  switch (m_exc_code) {
346  case 1:
347  code_desc = "EXC_I386_SGL";
348  break;
349  case 2:
350  code_desc = "EXC_I386_BPT";
351  break;
352  }
353  break;
354 
355  case llvm::Triple::arm:
356  case llvm::Triple::thumb:
357  switch (m_exc_code) {
358  case 0x101:
359  code_desc = "EXC_ARM_DA_ALIGN";
360  break;
361  case 0x102:
362  code_desc = "EXC_ARM_DA_DEBUG";
363  break;
364  case 1:
365  code_desc = "EXC_ARM_BREAKPOINT";
366  break;
367  // FIXME temporary workaround, exc_code 0 does not really mean
368  // EXC_ARM_BREAKPOINT
369  case 0:
370  code_desc = "EXC_ARM_BREAKPOINT";
371  break;
372  }
373  break;
374 
375  case llvm::Triple::aarch64:
376  if (DeterminePtrauthFailure(exe_ctx))
377  return m_description.c_str();
378  break;
379 
380  default:
381  break;
382  }
383  } break;
384 
385  case 7:
386  exc_desc = "EXC_SYSCALL";
387  break;
388 
389  case 8:
390  exc_desc = "EXC_MACH_SYSCALL";
391  break;
392 
393  case 9:
394  exc_desc = "EXC_RPC_ALERT";
395  break;
396 
397  case 10:
398  exc_desc = "EXC_CRASH";
399  break;
400  case 11:
401  exc_desc = "EXC_RESOURCE";
402 #if defined(__APPLE__)
403  {
404  int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(m_exc_code);
405 
406  code_label = "limit";
407  code_desc = code_desc_buf;
408  subcode_label = "observed";
409  subcode_desc = subcode_desc_buf;
410 
411  switch (resource_type) {
412  case RESOURCE_TYPE_CPU:
413  exc_desc = "EXC_RESOURCE RESOURCE_TYPE_CPU";
414  snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%",
415  (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code));
416  snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%",
417  (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED(
418  m_exc_subcode));
419  break;
420  case RESOURCE_TYPE_WAKEUPS:
421  exc_desc = "EXC_RESOURCE RESOURCE_TYPE_WAKEUPS";
422  snprintf(
423  code_desc_buf, sizeof(code_desc_buf), "%d w/s",
424  (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_PERMITTED(m_exc_code));
425  snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s",
426  (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED(
427  m_exc_subcode));
428  break;
429  case RESOURCE_TYPE_MEMORY:
430  exc_desc = "EXC_RESOURCE RESOURCE_TYPE_MEMORY";
431  snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
432  (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code));
433  subcode_desc = nullptr;
434  subcode_label = "unused";
435  break;
436 #if defined(RESOURCE_TYPE_IO)
437  // RESOURCE_TYPE_IO is introduced in macOS SDK 10.12.
438  case RESOURCE_TYPE_IO:
439  exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO";
440  snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
441  (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code));
442  snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB",
443  (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode));
444  ;
445  break;
446 #endif
447  }
448  }
449 #endif
450  break;
451  case 12:
452  exc_desc = "EXC_GUARD";
453  break;
454  }
455 
456  StreamString strm;
457 
458  if (exc_desc)
459  strm.PutCString(exc_desc);
460  else
461  strm.Printf("EXC_??? (%" PRIu64 ")", m_value);
462 
463  if (m_exc_data_count >= 1) {
464  if (code_desc)
465  strm.Printf(" (%s=%s", code_label, code_desc);
466  else
467  strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code);
468  }
469 
470  if (m_exc_data_count >= 2) {
471  if (subcode_desc)
472  strm.Printf(", %s=%s", subcode_label, subcode_desc);
473  else
474  strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode);
475  }
476 
477  if (m_exc_data_count > 0)
478  strm.PutChar(')');
479 
480  m_description = std::string(strm.GetString());
481  return m_description.c_str();
482 }
483 
484 static StopInfoSP GetStopInfoForHardwareBP(Thread &thread, Target *target,
485  uint32_t exc_data_count,
486  uint64_t exc_sub_code,
487  uint64_t exc_sub_sub_code) {
488  // Try hardware watchpoint.
489  if (target) {
490  // The exc_sub_code indicates the data break address.
491  lldb::WatchpointSP wp_sp =
492  target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code);
493  if (wp_sp && wp_sp->IsEnabled()) {
494  // Debugserver may piggyback the hardware index of the fired watchpoint
495  // in the exception data. Set the hardware index if that's the case.
496  if (exc_data_count >= 3)
497  wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
498  return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
499  }
500  }
501 
502  // Try hardware breakpoint.
503  ProcessSP process_sp(thread.GetProcess());
504  if (process_sp) {
505  // The exc_sub_code indicates the data break address.
506  lldb::BreakpointSiteSP bp_sp =
507  process_sp->GetBreakpointSiteList().FindByAddress(
508  (lldb::addr_t)exc_sub_code);
509  if (bp_sp && bp_sp->IsEnabled()) {
510  // Debugserver may piggyback the hardware index of the fired breakpoint
511  // in the exception data. Set the hardware index if that's the case.
512  if (exc_data_count >= 3)
513  bp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
514  return StopInfo::CreateStopReasonWithBreakpointSiteID(thread,
515  bp_sp->GetID());
516  }
517  }
518 
519  return nullptr;
520 }
521 
522 StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
523  Thread &thread, uint32_t exc_type, uint32_t exc_data_count,
524  uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code,
525  bool pc_already_adjusted, bool adjust_pc_if_needed) {
526  if (exc_type == 0)
527  return StopInfoSP();
528 
529  uint32_t pc_decrement = 0;
530  ExecutionContext exe_ctx(thread.shared_from_this());
531  Target *target = exe_ctx.GetTargetPtr();
532  const llvm::Triple::ArchType cpu =
533  target ? target->GetArchitecture().GetMachine()
534  : llvm::Triple::UnknownArch;
535 
536  switch (exc_type) {
537  case 1: // EXC_BAD_ACCESS
538  case 2: // EXC_BAD_INSTRUCTION
539  case 3: // EXC_ARITHMETIC
540  case 4: // EXC_EMULATION
541  break;
542 
543  case 5: // EXC_SOFTWARE
544  if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
545  {
546  if (exc_sub_code == 5) {
547  // On MacOSX, a SIGTRAP can signify that a process has called exec,
548  // so we should check with our dynamic loader to verify.
549  ProcessSP process_sp(thread.GetProcess());
550  if (process_sp) {
551  DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader();
552  if (dynamic_loader && dynamic_loader->ProcessDidExec()) {
553  // The program was re-exec'ed
554  return StopInfo::CreateStopReasonWithExec(thread);
555  }
556  }
557  }
558  return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code);
559  }
560  break;
561 
562  case 6: // EXC_BREAKPOINT
563  {
564  bool is_actual_breakpoint = false;
565  bool is_trace_if_actual_breakpoint_missing = false;
566  switch (cpu) {
567  case llvm::Triple::x86:
568  case llvm::Triple::x86_64:
569  if (exc_code == 1) // EXC_I386_SGL
570  {
571  if (!exc_sub_code) {
572  // This looks like a plain trap.
573  // Have to check if there is a breakpoint here as well. When you
574  // single-step onto a trap, the single step stops you not to trap.
575  // Since we also do that check below, let's just use that logic.
576  is_actual_breakpoint = true;
577  is_trace_if_actual_breakpoint_missing = true;
578  } else {
579  if (StopInfoSP stop_info =
580  GetStopInfoForHardwareBP(thread, target, exc_data_count,
581  exc_sub_code, exc_sub_sub_code))
582  return stop_info;
583  }
584  } else if (exc_code == 2 || // EXC_I386_BPT
585  exc_code == 3) // EXC_I386_BPTFLT
586  {
587  // KDP returns EXC_I386_BPTFLT for trace breakpoints
588  if (exc_code == 3)
589  is_trace_if_actual_breakpoint_missing = true;
590 
591  is_actual_breakpoint = true;
592  if (!pc_already_adjusted)
593  pc_decrement = 1;
594  }
595  break;
596 
597  case llvm::Triple::arm:
598  case llvm::Triple::thumb:
599  if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
600  {
601  // It's a watchpoint, then, if the exc_sub_code indicates a
602  // known/enabled data break address from our watchpoint list.
603  lldb::WatchpointSP wp_sp;
604  if (target)
605  wp_sp = target->GetWatchpointList().FindByAddress(
606  (lldb::addr_t)exc_sub_code);
607  if (wp_sp && wp_sp->IsEnabled()) {
608  // Debugserver may piggyback the hardware index of the fired
609  // watchpoint in the exception data. Set the hardware index if
610  // that's the case.
611  if (exc_data_count >= 3)
612  wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
613  return StopInfo::CreateStopReasonWithWatchpointID(thread,
614  wp_sp->GetID());
615  } else {
616  is_actual_breakpoint = true;
617  is_trace_if_actual_breakpoint_missing = true;
618  }
619  } else if (exc_code == 1) // EXC_ARM_BREAKPOINT
620  {
621  is_actual_breakpoint = true;
622  is_trace_if_actual_breakpoint_missing = true;
623  } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel
624  // is currently returning this so accept it
625  // as indicating a breakpoint until the
626  // kernel is fixed
627  {
628  is_actual_breakpoint = true;
629  is_trace_if_actual_breakpoint_missing = true;
630  }
631  break;
632 
633  case llvm::Triple::aarch64_32:
634  case llvm::Triple::aarch64: {
635  if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT
636  {
637  // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0
638  // is set
639  is_actual_breakpoint = false;
640  is_trace_if_actual_breakpoint_missing = true;
641  }
642  if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
643  {
644  // It's a watchpoint, then, if the exc_sub_code indicates a
645  // known/enabled data break address from our watchpoint list.
646  lldb::WatchpointSP wp_sp;
647  if (target)
648  wp_sp = target->GetWatchpointList().FindByAddress(
649  (lldb::addr_t)exc_sub_code);
650  if (wp_sp && wp_sp->IsEnabled()) {
651  // Debugserver may piggyback the hardware index of the fired
652  // watchpoint in the exception data. Set the hardware index if
653  // that's the case.
654  if (exc_data_count >= 3)
655  wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
656  return StopInfo::CreateStopReasonWithWatchpointID(thread,
657  wp_sp->GetID());
658  }
659  // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as
660  // EXC_BAD_ACCESS
661  if (thread.GetTemporaryResumeState() == eStateStepping)
662  return StopInfo::CreateStopReasonToTrace(thread);
663  }
664  // It looks like exc_sub_code has the 4 bytes of the instruction that
665  // triggered the exception, i.e. our breakpoint opcode
666  is_actual_breakpoint = exc_code == 1;
667  break;
668  }
669 
670  default:
671  break;
672  }
673 
674  if (is_actual_breakpoint) {
675  RegisterContextSP reg_ctx_sp(thread.GetRegisterContext());
676  addr_t pc = reg_ctx_sp->GetPC() - pc_decrement;
677 
678  ProcessSP process_sp(thread.CalculateProcess());
679 
680  lldb::BreakpointSiteSP bp_site_sp;
681  if (process_sp)
682  bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
683  if (bp_site_sp && bp_site_sp->IsEnabled()) {
684  // Update the PC if we were asked to do so, but only do so if we find
685  // a breakpoint that we know about cause this could be a trap
686  // instruction in the code
687  if (pc_decrement > 0 && adjust_pc_if_needed)
688  reg_ctx_sp->SetPC(pc);
689 
690  // If the breakpoint is for this thread, then we'll report the hit,
691  // but if it is for another thread, we can just report no reason. We
692  // don't need to worry about stepping over the breakpoint here, that
693  // will be taken care of when the thread resumes and notices that
694  // there's a breakpoint under the pc. If we have an operating system
695  // plug-in, we might have set a thread specific breakpoint using the
696  // operating system thread ID, so we can't make any assumptions about
697  // the thread ID so we must always report the breakpoint regardless
698  // of the thread.
699  if (bp_site_sp->ValidForThisThread(thread) ||
700  thread.GetProcess()->GetOperatingSystem() != nullptr)
701  return StopInfo::CreateStopReasonWithBreakpointSiteID(
702  thread, bp_site_sp->GetID());
703  else if (is_trace_if_actual_breakpoint_missing)
704  return StopInfo::CreateStopReasonToTrace(thread);
705  else
706  return StopInfoSP();
707  }
708 
709  // Don't call this a trace if we weren't single stepping this thread.
710  if (is_trace_if_actual_breakpoint_missing &&
712  return StopInfo::CreateStopReasonToTrace(thread);
713  }
714  }
715  } break;
716 
717  case 7: // EXC_SYSCALL
718  case 8: // EXC_MACH_SYSCALL
719  case 9: // EXC_RPC_ALERT
720  case 10: // EXC_CRASH
721  break;
722  }
723 
724  return StopInfoSP(new StopInfoMachException(thread, exc_type, exc_data_count,
725  exc_code, exc_sub_code));
726 }
lldb_private::ExecutionContext
Definition: ExecutionContext.h:292
lldb_private::ArchSpec
Definition: ArchSpec.h:33
lldb_private::ExecutionContext::HasTargetScope
bool HasTargetScope() const
Returns true the ExecutionContext object contains a valid target.
Definition: ExecutionContext.cpp:381
lldb_private::ArchSpec::GetMachine
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:667
lldb_private::RegisterValue
Definition: RegisterValue.h:28
lldb_private::ExecutionContext::GetProcessPtr
Process * GetProcessPtr() const
Returns a pointer to the process object.
Definition: ExecutionContext.cpp:208
lldb_private::ArchSpec::GetCore
Core GetCore() const
Definition: ArchSpec.h:423
StopInfoMachException.h
lldb_private::RegisterContext::ReadRegister
virtual bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
lldb_private::Process
Definition: Process.h:340
GetStopInfoForHardwareBP
static StopInfoSP GetStopInfoForHardwareBP(Thread &thread, Target *target, uint32_t exc_data_count, uint64_t exc_sub_code, uint64_t exc_sub_sub_code)
Definition: StopInfoMachException.cpp:484
lldb::eStopReasonInvalid
@ eStopReasonInvalid
Definition: lldb-enumerations.h:240
lldb_private::InstructionList::GetInstructionAtIndex
lldb::InstructionSP GetInstructionAtIndex(size_t idx) const
Definition: Disassembler.cpp:946
lldb_private::Stream
Definition: Stream.h:28
lldb_private::Target::GetWatchpointList
WatchpointList & GetWatchpointList()
Definition: Target.h:720
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
pc
@ pc
Definition: CompactUnwindInfo.cpp:1250
lldb_private::Target::ResolveLoadAddress
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow)
Definition: Target.cpp:2818
lldb_private::Target
Definition: Target.h:450
lldb_private::ExecutionContext::GetThreadPtr
Thread * GetThreadPtr() const
Returns a pointer to the thread object.
Definition: ExecutionContext.h:399
ABI.h
lldb_private::StreamString::GetString
llvm::StringRef GetString() const
Definition: StreamString.cpp:51
Process.h
lldb_private::RegisterValue::GetAsUInt64
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
Definition: RegisterValue.cpp:563
lldb_private::StopInfoMachException
Definition: StopInfoMachException.h:18
Target.h
lldb_private::Thread::GetProcess
lldb::ProcessSP GetProcess() const
Definition: Thread.h:152
lldb_private::Thread::CalculateProcess
lldb::ProcessSP CalculateProcess() override
Definition: Thread.cpp:1397
lldb_private::InstructionList
Definition: Disassembler.h:267
lldb_private::ExecutionContext::GetRegisterContext
RegisterContext * GetRegisterContext() const
Definition: ExecutionContext.cpp:192
PtrauthInstructionInfo::IsLoad
bool IsLoad
Definition: StopInfoMachException.cpp:37
Watchpoint.h
UnixSignals.h
lldb_private::Thread
Definition: Thread.h:60
lldb_private::DynamicLoader::ProcessDidExec
virtual bool ProcessDidExec()
Helper function that can be used to detect when a process has called exec and is now a new and differ...
Definition: DynamicLoader.h:89
StreamString.h
lldb_private::Thread::GetTemporaryResumeState
lldb::StateType GetTemporaryResumeState() const
Definition: Thread.h:1154
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::AddressRange
Definition: AddressRange.h:25
lldb_private::DynamicLoader
Definition: DynamicLoader.h:52
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
Thread.h
lldb_private::Stream::PutChar
size_t PutChar(char ch)
Definition: Stream.cpp:104
lldb_private::RegisterContext
Definition: RegisterContext.h:17
lldb_private::ExecutionContext::HasThreadScope
bool HasThreadScope() const
Returns true the ExecutionContext object contains a valid target, process, and thread.
Definition: ExecutionContext.cpp:389
lldb_private::UserID::GetID
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:47
ThreadPlan.h
Symbol.h
lldb::eStateStepping
@ eStateStepping
Process or thread is in the process of stepping and can not be examined.
Definition: lldb-enumerations.h:86
lldb_private::Target::GetArchitecture
const ArchSpec & GetArchitecture() const
Definition: Target.h:966
uint32_t
lldb_private::Address
Definition: Address.h:59
lldb_private::Address::GetDescription
bool GetDescription(Stream &s, Target &target, lldb::DescriptionLevel level) const
Write a description of this object to a Stream.
Definition: Address.cpp:392
PtrauthInstructionInfo::IsAuthenticated
bool IsAuthenticated
Definition: StopInfoMachException.cpp:36
lldb_private::Address::GetLoadAddress
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition: Address.cpp:310
PtrauthInstructionInfo::DoesBranch
bool DoesBranch
Definition: StopInfoMachException.cpp:38
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
lldb-forward.h
PtrauthInstructionInfo
Information about a pointer-authentication related instruction.
Definition: StopInfoMachException.cpp:35
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
GetPtrauthInstructionInfo
static llvm::Optional< PtrauthInstructionInfo > GetPtrauthInstructionInfo(Target &target, const ArchSpec &arch, const Address &at_addr)
Get any pointer-authentication related information about the instruction at address at_addr.
Definition: StopInfoMachException.cpp:44
lldb_private::Process::GetABI
const lldb::ABISP & GetABI()
Definition: Process.cpp:1475
lldb_private::Stream::PutCString
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:63
lldb_private::Thread::GetStackFrameAtIndex
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:397
lldb_private::Thread::GetRegisterContext
virtual lldb::RegisterContextSP GetRegisterContext()=0
DynamicLoader.h
lldb_private::ExecutionContext::HasProcessScope
bool HasProcessScope() const
Returns true the ExecutionContext object contains a valid target and process.
Definition: ExecutionContext.cpp:385
DescribeAddressBriefly
static void DescribeAddressBriefly(Stream &strm, const Address &addr, Target &target)
Describe the load address of addr using the format filename:line:col.
Definition: StopInfoMachException.cpp:65
lldb
Definition: SBAddress.h:15
RegisterContext.h
lldb_private::ExecutionContext::GetTargetPtr
Target * GetTargetPtr() const
Returns a pointer to the target object.
Definition: ExecutionContext.cpp:200
ExecutionContext.h
lldb::eDescriptionLevelBrief
@ eDescriptionLevelBrief
Definition: lldb-enumerations.h:208
lldb_private::WatchpointList::FindByAddress
const lldb::WatchpointSP FindByAddress(lldb::addr_t addr) const
Returns a shared pointer to the watchpoint at address addr - const version.
Definition: WatchpointList.cpp:52
lldb_private::RegisterContext::GetRegisterInfoByName
const RegisterInfo * GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx=0)
Definition: RegisterContext.cpp:52