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 =
414  "EXC_RESOURCE (RESOURCE_TYPE_CPU: CPU usage monitor tripped)";
415  snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%",
416  (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code));
417  snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%",
418  (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED(
419  m_exc_subcode));
420  break;
421  case RESOURCE_TYPE_WAKEUPS:
422  exc_desc = "EXC_RESOURCE (RESOURCE_TYPE_WAKEUPS: idle wakeups monitor "
423  "tripped)";
424  snprintf(
425  code_desc_buf, sizeof(code_desc_buf), "%d w/s",
426  (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_PERMITTED(m_exc_code));
427  snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s",
428  (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED(
429  m_exc_subcode));
430  break;
431  case RESOURCE_TYPE_MEMORY:
432  exc_desc = "EXC_RESOURCE (RESOURCE_TYPE_MEMORY: high watermark memory "
433  "limit exceeded)";
434  snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
435  (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code));
436  subcode_desc = nullptr;
437  subcode_label = nullptr;
438  break;
439 #if defined(RESOURCE_TYPE_IO)
440  // RESOURCE_TYPE_IO is introduced in macOS SDK 10.12.
441  case RESOURCE_TYPE_IO:
442  exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO";
443  snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
444  (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code));
445  snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB",
446  (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode));
447  ;
448  break;
449 #endif
450  }
451  }
452 #endif
453  break;
454  case 12:
455  exc_desc = "EXC_GUARD";
456  break;
457  }
458 
459  StreamString strm;
460 
461  if (exc_desc)
462  strm.PutCString(exc_desc);
463  else
464  strm.Printf("EXC_??? (%" PRIu64 ")", m_value);
465 
466  if (m_exc_data_count >= 1) {
467  if (code_desc)
468  strm.Printf(" (%s=%s", code_label, code_desc);
469  else
470  strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code);
471  }
472 
473  if (m_exc_data_count >= 2) {
474  if (subcode_label && subcode_desc)
475  strm.Printf(", %s=%s", subcode_label, subcode_desc);
476  else if (subcode_label)
477  strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode);
478  }
479 
480  if (m_exc_data_count > 0)
481  strm.PutChar(')');
482 
483  m_description = std::string(strm.GetString());
484  return m_description.c_str();
485 }
486 
487 static StopInfoSP GetStopInfoForHardwareBP(Thread &thread, Target *target,
488  uint32_t exc_data_count,
489  uint64_t exc_sub_code,
490  uint64_t exc_sub_sub_code) {
491  // Try hardware watchpoint.
492  if (target) {
493  // The exc_sub_code indicates the data break address.
494  lldb::WatchpointSP wp_sp =
495  target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code);
496  if (wp_sp && wp_sp->IsEnabled()) {
497  // Debugserver may piggyback the hardware index of the fired watchpoint
498  // in the exception data. Set the hardware index if that's the case.
499  if (exc_data_count >= 3)
500  wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
501  return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
502  }
503  }
504 
505  // Try hardware breakpoint.
506  ProcessSP process_sp(thread.GetProcess());
507  if (process_sp) {
508  // The exc_sub_code indicates the data break address.
509  lldb::BreakpointSiteSP bp_sp =
510  process_sp->GetBreakpointSiteList().FindByAddress(
511  (lldb::addr_t)exc_sub_code);
512  if (bp_sp && bp_sp->IsEnabled()) {
513  // Debugserver may piggyback the hardware index of the fired breakpoint
514  // in the exception data. Set the hardware index if that's the case.
515  if (exc_data_count >= 3)
516  bp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
517  return StopInfo::CreateStopReasonWithBreakpointSiteID(thread,
518  bp_sp->GetID());
519  }
520  }
521 
522  return nullptr;
523 }
524 
525 #if defined(__APPLE__)
526 const char *
527 StopInfoMachException::MachException::Name(exception_type_t exc_type) {
528  switch (exc_type) {
529  case EXC_BAD_ACCESS:
530  return "EXC_BAD_ACCESS";
531  case EXC_BAD_INSTRUCTION:
532  return "EXC_BAD_INSTRUCTION";
533  case EXC_ARITHMETIC:
534  return "EXC_ARITHMETIC";
535  case EXC_EMULATION:
536  return "EXC_EMULATION";
537  case EXC_SOFTWARE:
538  return "EXC_SOFTWARE";
539  case EXC_BREAKPOINT:
540  return "EXC_BREAKPOINT";
541  case EXC_SYSCALL:
542  return "EXC_SYSCALL";
543  case EXC_MACH_SYSCALL:
544  return "EXC_MACH_SYSCALL";
545  case EXC_RPC_ALERT:
546  return "EXC_RPC_ALERT";
547 #ifdef EXC_CRASH
548  case EXC_CRASH:
549  return "EXC_CRASH";
550 #endif
551  case EXC_RESOURCE:
552  return "EXC_RESOURCE";
553 #ifdef EXC_GUARD
554  case EXC_GUARD:
555  return "EXC_GUARD";
556 #endif
557 #ifdef EXC_CORPSE_NOTIFY
558  case EXC_CORPSE_NOTIFY:
559  return "EXC_CORPSE_NOTIFY";
560 #endif
561 #ifdef EXC_CORPSE_VARIANT_BIT
562  case EXC_CORPSE_VARIANT_BIT:
563  return "EXC_CORPSE_VARIANT_BIT";
564 #endif
565  default:
566  break;
567  }
568  return NULL;
569 }
570 
571 llvm::Optional<exception_type_t>
572 StopInfoMachException::MachException::ExceptionCode(const char *name) {
573  return llvm::StringSwitch<llvm::Optional<exception_type_t>>(name)
574  .Case("EXC_BAD_ACCESS", EXC_BAD_ACCESS)
575  .Case("EXC_BAD_INSTRUCTION", EXC_BAD_INSTRUCTION)
576  .Case("EXC_ARITHMETIC", EXC_ARITHMETIC)
577  .Case("EXC_EMULATION", EXC_EMULATION)
578  .Case("EXC_SOFTWARE", EXC_SOFTWARE)
579  .Case("EXC_BREAKPOINT", EXC_BREAKPOINT)
580  .Case("EXC_SYSCALL", EXC_SYSCALL)
581  .Case("EXC_MACH_SYSCALL", EXC_MACH_SYSCALL)
582  .Case("EXC_RPC_ALERT", EXC_RPC_ALERT)
583 #ifdef EXC_CRASH
584  .Case("EXC_CRASH", EXC_CRASH)
585 #endif
586  .Case("EXC_RESOURCE", EXC_RESOURCE)
587 #ifdef EXC_GUARD
588  .Case("EXC_GUARD", EXC_GUARD)
589 #endif
590 #ifdef EXC_CORPSE_NOTIFY
591  .Case("EXC_CORPSE_NOTIFY", EXC_CORPSE_NOTIFY)
592 #endif
593  .Default(llvm::None);
594 }
595 #endif
596 
597 StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
598  Thread &thread, uint32_t exc_type, uint32_t exc_data_count,
599  uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code,
600  bool pc_already_adjusted, bool adjust_pc_if_needed) {
601  if (exc_type == 0)
602  return StopInfoSP();
603 
604  uint32_t pc_decrement = 0;
605  ExecutionContext exe_ctx(thread.shared_from_this());
606  Target *target = exe_ctx.GetTargetPtr();
607  const llvm::Triple::ArchType cpu =
608  target ? target->GetArchitecture().GetMachine()
609  : llvm::Triple::UnknownArch;
610 
611  switch (exc_type) {
612  case 1: // EXC_BAD_ACCESS
613  case 2: // EXC_BAD_INSTRUCTION
614  case 3: // EXC_ARITHMETIC
615  case 4: // EXC_EMULATION
616  break;
617 
618  case 5: // EXC_SOFTWARE
619  if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
620  {
621  if (exc_sub_code == 5) {
622  // On MacOSX, a SIGTRAP can signify that a process has called exec,
623  // so we should check with our dynamic loader to verify.
624  ProcessSP process_sp(thread.GetProcess());
625  if (process_sp) {
626  DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader();
627  if (dynamic_loader && dynamic_loader->ProcessDidExec()) {
628  // The program was re-exec'ed
629  return StopInfo::CreateStopReasonWithExec(thread);
630  }
631  }
632  }
633  return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code);
634  }
635  break;
636 
637  case 6: // EXC_BREAKPOINT
638  {
639  bool is_actual_breakpoint = false;
640  bool is_trace_if_actual_breakpoint_missing = false;
641  switch (cpu) {
642  case llvm::Triple::x86:
643  case llvm::Triple::x86_64:
644  if (exc_code == 1) // EXC_I386_SGL
645  {
646  if (!exc_sub_code) {
647  // This looks like a plain trap.
648  // Have to check if there is a breakpoint here as well. When you
649  // single-step onto a trap, the single step stops you not to trap.
650  // Since we also do that check below, let's just use that logic.
651  is_actual_breakpoint = true;
652  is_trace_if_actual_breakpoint_missing = true;
653  } else {
654  if (StopInfoSP stop_info =
655  GetStopInfoForHardwareBP(thread, target, exc_data_count,
656  exc_sub_code, exc_sub_sub_code))
657  return stop_info;
658  }
659  } else if (exc_code == 2 || // EXC_I386_BPT
660  exc_code == 3) // EXC_I386_BPTFLT
661  {
662  // KDP returns EXC_I386_BPTFLT for trace breakpoints
663  if (exc_code == 3)
664  is_trace_if_actual_breakpoint_missing = true;
665 
666  is_actual_breakpoint = true;
667  if (!pc_already_adjusted)
668  pc_decrement = 1;
669  }
670  break;
671 
672  case llvm::Triple::arm:
673  case llvm::Triple::thumb:
674  if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
675  {
676  // It's a watchpoint, then, if the exc_sub_code indicates a
677  // known/enabled data break address from our watchpoint list.
678  lldb::WatchpointSP wp_sp;
679  if (target)
680  wp_sp = target->GetWatchpointList().FindByAddress(
681  (lldb::addr_t)exc_sub_code);
682  if (wp_sp && wp_sp->IsEnabled()) {
683  // Debugserver may piggyback the hardware index of the fired
684  // watchpoint in the exception data. Set the hardware index if
685  // that's the case.
686  if (exc_data_count >= 3)
687  wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
688  return StopInfo::CreateStopReasonWithWatchpointID(thread,
689  wp_sp->GetID());
690  } else {
691  is_actual_breakpoint = true;
692  is_trace_if_actual_breakpoint_missing = true;
693  }
694  } else if (exc_code == 1) // EXC_ARM_BREAKPOINT
695  {
696  is_actual_breakpoint = true;
697  is_trace_if_actual_breakpoint_missing = true;
698  } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel
699  // is currently returning this so accept it
700  // as indicating a breakpoint until the
701  // kernel is fixed
702  {
703  is_actual_breakpoint = true;
704  is_trace_if_actual_breakpoint_missing = true;
705  }
706  break;
707 
708  case llvm::Triple::aarch64_32:
709  case llvm::Triple::aarch64: {
710  if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT
711  {
712  // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0
713  // is set
714  is_actual_breakpoint = false;
715  is_trace_if_actual_breakpoint_missing = true;
716  }
717  if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
718  {
719  // It's a watchpoint, then, if the exc_sub_code indicates a
720  // known/enabled data break address from our watchpoint list.
721  lldb::WatchpointSP wp_sp;
722  if (target)
723  wp_sp = target->GetWatchpointList().FindByAddress(
724  (lldb::addr_t)exc_sub_code);
725  if (wp_sp && wp_sp->IsEnabled()) {
726  // Debugserver may piggyback the hardware index of the fired
727  // watchpoint in the exception data. Set the hardware index if
728  // that's the case.
729  if (exc_data_count >= 3)
730  wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
731  return StopInfo::CreateStopReasonWithWatchpointID(thread,
732  wp_sp->GetID());
733  }
734  // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as
735  // EXC_BAD_ACCESS
736  if (thread.GetTemporaryResumeState() == eStateStepping)
737  return StopInfo::CreateStopReasonToTrace(thread);
738  }
739  // It looks like exc_sub_code has the 4 bytes of the instruction that
740  // triggered the exception, i.e. our breakpoint opcode
741  is_actual_breakpoint = exc_code == 1;
742  break;
743  }
744 
745  default:
746  break;
747  }
748 
749  if (is_actual_breakpoint) {
750  RegisterContextSP reg_ctx_sp(thread.GetRegisterContext());
751  addr_t pc = reg_ctx_sp->GetPC() - pc_decrement;
752 
753  ProcessSP process_sp(thread.CalculateProcess());
754 
755  lldb::BreakpointSiteSP bp_site_sp;
756  if (process_sp)
757  bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
758  if (bp_site_sp && bp_site_sp->IsEnabled()) {
759  // Update the PC if we were asked to do so, but only do so if we find
760  // a breakpoint that we know about cause this could be a trap
761  // instruction in the code
762  if (pc_decrement > 0 && adjust_pc_if_needed)
763  reg_ctx_sp->SetPC(pc);
764 
765  // If the breakpoint is for this thread, then we'll report the hit,
766  // but if it is for another thread, we can just report no reason. We
767  // don't need to worry about stepping over the breakpoint here, that
768  // will be taken care of when the thread resumes and notices that
769  // there's a breakpoint under the pc. If we have an operating system
770  // plug-in, we might have set a thread specific breakpoint using the
771  // operating system thread ID, so we can't make any assumptions about
772  // the thread ID so we must always report the breakpoint regardless
773  // of the thread.
774  if (bp_site_sp->ValidForThisThread(thread) ||
775  thread.GetProcess()->GetOperatingSystem() != nullptr)
776  return StopInfo::CreateStopReasonWithBreakpointSiteID(
777  thread, bp_site_sp->GetID());
778  else if (is_trace_if_actual_breakpoint_missing)
779  return StopInfo::CreateStopReasonToTrace(thread);
780  else
781  return StopInfoSP();
782  }
783 
784  // Don't call this a trace if we weren't single stepping this thread.
785  if (is_trace_if_actual_breakpoint_missing &&
787  return StopInfo::CreateStopReasonToTrace(thread);
788  }
789  }
790  } break;
791 
792  case 7: // EXC_SYSCALL
793  case 8: // EXC_MACH_SYSCALL
794  case 9: // EXC_RPC_ALERT
795  case 10: // EXC_CRASH
796  break;
797  }
798 
799  return StopInfoSP(new StopInfoMachException(thread, exc_type, exc_data_count,
800  exc_code, exc_sub_code));
801 }
lldb_private::ExecutionContext
Definition: ExecutionContext.h:292
lldb_private::ArchSpec
Definition: ArchSpec.h:32
lldb_private::ExecutionContext::HasTargetScope
bool HasTargetScope() const
Returns true the ExecutionContext object contains a valid target.
Definition: ExecutionContext.cpp:379
lldb_private::ArchSpec::GetMachine
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:678
lldb_private::RegisterValue
Definition: RegisterValue.h:28
lldb_private::ExecutionContext::GetProcessPtr
Process * GetProcessPtr() const
Returns a pointer to the process object.
Definition: ExecutionContext.cpp:206
lldb_private::ArchSpec::GetCore
Core GetCore() const
Definition: ArchSpec.h:442
StopInfoMachException.h
lldb_private::RegisterContext::ReadRegister
virtual bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
lldb_private::Process
Definition: Process.h:338
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:487
lldb::eStopReasonInvalid
@ eStopReasonInvalid
Definition: lldb-enumerations.h:241
lldb_private::InstructionList::GetInstructionAtIndex
lldb::InstructionSP GetInstructionAtIndex(size_t idx) const
Definition: Disassembler.cpp:981
lldb_private::Stream
Definition: Stream.h:28
lldb_private::Target::GetWatchpointList
WatchpointList & GetWatchpointList()
Definition: Target.h:740
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
pc
@ pc
Definition: CompactUnwindInfo.cpp:1251
lldb_private::Target::ResolveLoadAddress
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow)
Definition: Target.cpp:2973
lldb_private::Target
Definition: Target.h:469
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:556
lldb_private::StopInfoMachException
Definition: StopInfoMachException.h:23
Target.h
lldb_private::Thread::GetProcess
lldb::ProcessSP GetProcess() const
Definition: Thread.h:153
lldb_private::Thread::CalculateProcess
lldb::ProcessSP CalculateProcess() override
Definition: Thread.cpp:1413
lldb_private::InstructionList
Definition: Disassembler.h:283
lldb_private::ExecutionContext::GetRegisterContext
RegisterContext * GetRegisterContext() const
Definition: ExecutionContext.cpp:190
PtrauthInstructionInfo::IsLoad
bool IsLoad
Definition: StopInfoMachException.cpp:37
Watchpoint.h
UnixSignals.h
lldb_private::Thread
Definition: Thread.h:61
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:90
StreamString.h
lldb_private::Thread::GetTemporaryResumeState
lldb::StateType GetTemporaryResumeState() const
Definition: Thread.h:1160
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:387
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:87
lldb_private::Target::GetArchitecture
const ArchSpec & GetArchitecture() const
Definition: Target.h:989
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:393
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:311
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:1486
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:399
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:383
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:198
ExecutionContext.h
lldb::eDescriptionLevelBrief
@ eDescriptionLevelBrief
Definition: lldb-enumerations.h:209
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