LLDB  mainline
StopInfoMachException.cpp
Go to the documentation of this file.
1 //===-- StopInfoMachException.cpp -------------------------------*- C++ -*-===//
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 
12 #if defined(__APPLE__)
13 // Needed for the EXC_RESOURCE interpretation macros
14 #include <kern/exc_resource.h>
15 #endif
16 
18 #include "lldb/Symbol/Symbol.h"
21 #include "lldb/Target/Process.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/Thread.h"
25 #include "lldb/Target/ThreadPlan.h"
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
32 const char *StopInfoMachException::GetDescription() {
33  if (m_description.empty() && m_value != 0) {
34  ExecutionContext exe_ctx(m_thread_wp.lock());
35  Target *target = exe_ctx.GetTargetPtr();
36  const llvm::Triple::ArchType cpu =
37  target ? target->GetArchitecture().GetMachine()
38  : llvm::Triple::UnknownArch;
39 
40  const char *exc_desc = NULL;
41  const char *code_label = "code";
42  const char *code_desc = NULL;
43  const char *subcode_label = "subcode";
44  const char *subcode_desc = NULL;
45 
46 #if defined(__APPLE__)
47  char code_desc_buf[32];
48  char subcode_desc_buf[32];
49 #endif
50 
51  switch (m_value) {
52  case 1: // EXC_BAD_ACCESS
53  exc_desc = "EXC_BAD_ACCESS";
54  subcode_label = "address";
55  switch (cpu) {
56  case llvm::Triple::x86:
57  case llvm::Triple::x86_64:
58  switch (m_exc_code) {
59  case 0xd:
60  code_desc = "EXC_I386_GPFLT";
61  m_exc_data_count = 1;
62  break;
63  }
64  break;
65  case llvm::Triple::arm:
66  case llvm::Triple::thumb:
67  switch (m_exc_code) {
68  case 0x101:
69  code_desc = "EXC_ARM_DA_ALIGN";
70  break;
71  case 0x102:
72  code_desc = "EXC_ARM_DA_DEBUG";
73  break;
74  }
75  break;
76 
77  case llvm::Triple::ppc:
78  case llvm::Triple::ppc64:
79  switch (m_exc_code) {
80  case 0x101:
81  code_desc = "EXC_PPC_VM_PROT_READ";
82  break;
83  case 0x102:
84  code_desc = "EXC_PPC_BADSPACE";
85  break;
86  case 0x103:
87  code_desc = "EXC_PPC_UNALIGNED";
88  break;
89  }
90  break;
91 
92  default:
93  break;
94  }
95  break;
96 
97  case 2: // EXC_BAD_INSTRUCTION
98  exc_desc = "EXC_BAD_INSTRUCTION";
99  switch (cpu) {
100  case llvm::Triple::x86:
101  case llvm::Triple::x86_64:
102  if (m_exc_code == 1)
103  code_desc = "EXC_I386_INVOP";
104  break;
105 
106  case llvm::Triple::ppc:
107  case llvm::Triple::ppc64:
108  switch (m_exc_code) {
109  case 1:
110  code_desc = "EXC_PPC_INVALID_SYSCALL";
111  break;
112  case 2:
113  code_desc = "EXC_PPC_UNIPL_INST";
114  break;
115  case 3:
116  code_desc = "EXC_PPC_PRIVINST";
117  break;
118  case 4:
119  code_desc = "EXC_PPC_PRIVREG";
120  break;
121  case 5:
122  code_desc = "EXC_PPC_TRACE";
123  break;
124  case 6:
125  code_desc = "EXC_PPC_PERFMON";
126  break;
127  }
128  break;
129 
130  case llvm::Triple::arm:
131  case llvm::Triple::thumb:
132  if (m_exc_code == 1)
133  code_desc = "EXC_ARM_UNDEFINED";
134  break;
135 
136  default:
137  break;
138  }
139  break;
140 
141  case 3: // EXC_ARITHMETIC
142  exc_desc = "EXC_ARITHMETIC";
143  switch (cpu) {
144  case llvm::Triple::x86:
145  case llvm::Triple::x86_64:
146  switch (m_exc_code) {
147  case 1:
148  code_desc = "EXC_I386_DIV";
149  break;
150  case 2:
151  code_desc = "EXC_I386_INTO";
152  break;
153  case 3:
154  code_desc = "EXC_I386_NOEXT";
155  break;
156  case 4:
157  code_desc = "EXC_I386_EXTOVR";
158  break;
159  case 5:
160  code_desc = "EXC_I386_EXTERR";
161  break;
162  case 6:
163  code_desc = "EXC_I386_EMERR";
164  break;
165  case 7:
166  code_desc = "EXC_I386_BOUND";
167  break;
168  case 8:
169  code_desc = "EXC_I386_SSEEXTERR";
170  break;
171  }
172  break;
173 
174  case llvm::Triple::ppc:
175  case llvm::Triple::ppc64:
176  switch (m_exc_code) {
177  case 1:
178  code_desc = "EXC_PPC_OVERFLOW";
179  break;
180  case 2:
181  code_desc = "EXC_PPC_ZERO_DIVIDE";
182  break;
183  case 3:
184  code_desc = "EXC_PPC_FLT_INEXACT";
185  break;
186  case 4:
187  code_desc = "EXC_PPC_FLT_ZERO_DIVIDE";
188  break;
189  case 5:
190  code_desc = "EXC_PPC_FLT_UNDERFLOW";
191  break;
192  case 6:
193  code_desc = "EXC_PPC_FLT_OVERFLOW";
194  break;
195  case 7:
196  code_desc = "EXC_PPC_FLT_NOT_A_NUMBER";
197  break;
198  }
199  break;
200 
201  default:
202  break;
203  }
204  break;
205 
206  case 4: // EXC_EMULATION
207  exc_desc = "EXC_EMULATION";
208  break;
209 
210  case 5: // EXC_SOFTWARE
211  exc_desc = "EXC_SOFTWARE";
212  if (m_exc_code == 0x10003) {
213  subcode_desc = "EXC_SOFT_SIGNAL";
214  subcode_label = "signo";
215  }
216  break;
217 
218  case 6: // EXC_BREAKPOINT
219  {
220  exc_desc = "EXC_BREAKPOINT";
221  switch (cpu) {
222  case llvm::Triple::x86:
223  case llvm::Triple::x86_64:
224  switch (m_exc_code) {
225  case 1:
226  code_desc = "EXC_I386_SGL";
227  break;
228  case 2:
229  code_desc = "EXC_I386_BPT";
230  break;
231  }
232  break;
233 
234  case llvm::Triple::ppc:
235  case llvm::Triple::ppc64:
236  switch (m_exc_code) {
237  case 1:
238  code_desc = "EXC_PPC_BREAKPOINT";
239  break;
240  }
241  break;
242 
243  case llvm::Triple::arm:
244  case llvm::Triple::thumb:
245  switch (m_exc_code) {
246  case 0x101:
247  code_desc = "EXC_ARM_DA_ALIGN";
248  break;
249  case 0x102:
250  code_desc = "EXC_ARM_DA_DEBUG";
251  break;
252  case 1:
253  code_desc = "EXC_ARM_BREAKPOINT";
254  break;
255  // FIXME temporary workaround, exc_code 0 does not really mean
256  // EXC_ARM_BREAKPOINT
257  case 0:
258  code_desc = "EXC_ARM_BREAKPOINT";
259  break;
260  }
261  break;
262 
263  default:
264  break;
265  }
266  } break;
267 
268  case 7:
269  exc_desc = "EXC_SYSCALL";
270  break;
271 
272  case 8:
273  exc_desc = "EXC_MACH_SYSCALL";
274  break;
275 
276  case 9:
277  exc_desc = "EXC_RPC_ALERT";
278  break;
279 
280  case 10:
281  exc_desc = "EXC_CRASH";
282  break;
283  case 11:
284  exc_desc = "EXC_RESOURCE";
285 #if defined(__APPLE__)
286  {
287  int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(m_exc_code);
288 
289  code_label = "limit";
290  code_desc = code_desc_buf;
291  subcode_label = "observed";
292  subcode_desc = subcode_desc_buf;
293 
294  switch (resource_type) {
295  case RESOURCE_TYPE_CPU:
296  exc_desc = "EXC_RESOURCE RESOURCE_TYPE_CPU";
297  snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%",
298  (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code));
299  snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%",
300  (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED(m_exc_subcode));
301  break;
302  case RESOURCE_TYPE_WAKEUPS:
303  exc_desc = "EXC_RESOURCE RESOURCE_TYPE_WAKEUPS";
304  snprintf(code_desc_buf, sizeof(code_desc_buf), "%d w/s",
305  (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_PERMITTED(m_exc_code));
306  snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s",
307  (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED(m_exc_subcode));
308  break;
309  case RESOURCE_TYPE_MEMORY:
310  exc_desc = "EXC_RESOURCE RESOURCE_TYPE_MEMORY";
311  snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
312  (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code));
313  subcode_desc = nullptr;
314  subcode_label = "unused";
315  break;
316  case RESOURCE_TYPE_IO:
317  exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO";
318  snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
319  (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code));
320  snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB",
321  (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode));;
322  break;
323  }
324  }
325 #endif
326  break;
327  case 12:
328  exc_desc = "EXC_GUARD";
329  break;
330  }
331 
332  StreamString strm;
333 
334  if (exc_desc)
335  strm.PutCString(exc_desc);
336  else
337  strm.Printf("EXC_??? (%" PRIu64 ")", m_value);
338 
339  if (m_exc_data_count >= 1) {
340  if (code_desc)
341  strm.Printf(" (%s=%s", code_label, code_desc);
342  else
343  strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code);
344  }
345 
346  if (m_exc_data_count >= 2) {
347  if (subcode_desc)
348  strm.Printf(", %s=%s", subcode_label, subcode_desc);
349  else
350  strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode);
351  }
352 
353  if (m_exc_data_count > 0)
354  strm.PutChar(')');
355 
356  m_description = strm.GetString();
357  }
358  return m_description.c_str();
359 }
360 
361 StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
362  Thread &thread, uint32_t exc_type, uint32_t exc_data_count,
363  uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code,
364  bool pc_already_adjusted, bool adjust_pc_if_needed) {
365  if (exc_type != 0) {
366  uint32_t pc_decrement = 0;
367  ExecutionContext exe_ctx(thread.shared_from_this());
368  Target *target = exe_ctx.GetTargetPtr();
369  const llvm::Triple::ArchType cpu =
370  target ? target->GetArchitecture().GetMachine()
371  : llvm::Triple::UnknownArch;
372 
373  switch (exc_type) {
374  case 1: // EXC_BAD_ACCESS
375  break;
376 
377  case 2: // EXC_BAD_INSTRUCTION
378  switch (cpu) {
379  case llvm::Triple::ppc:
380  case llvm::Triple::ppc64:
381  switch (exc_code) {
382  case 1: // EXC_PPC_INVALID_SYSCALL
383  case 2: // EXC_PPC_UNIPL_INST
384  case 3: // EXC_PPC_PRIVINST
385  case 4: // EXC_PPC_PRIVREG
386  break;
387  case 5: // EXC_PPC_TRACE
388  return StopInfo::CreateStopReasonToTrace(thread);
389  case 6: // EXC_PPC_PERFMON
390  break;
391  }
392  break;
393 
394  default:
395  break;
396  }
397  break;
398 
399  case 3: // EXC_ARITHMETIC
400  case 4: // EXC_EMULATION
401  break;
402 
403  case 5: // EXC_SOFTWARE
404  if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
405  {
406  if (exc_sub_code == 5) {
407  // On MacOSX, a SIGTRAP can signify that a process has called exec,
408  // so we should check with our dynamic loader to verify.
409  ProcessSP process_sp(thread.GetProcess());
410  if (process_sp) {
411  DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader();
412  if (dynamic_loader && dynamic_loader->ProcessDidExec()) {
413  // The program was re-exec'ed
414  return StopInfo::CreateStopReasonWithExec(thread);
415  }
416  // if (!process_did_exec)
417  // {
418  // // We have a SIGTRAP, make sure we
419  // didn't exec by checking
420  // // for the PC being at
421  // "_dyld_start"...
422  // lldb::StackFrameSP frame_sp
423  // (thread.GetStackFrameAtIndex(0));
424  // if (frame_sp)
425  // {
426  // const Symbol *symbol =
427  // frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
428  // if (symbol)
429  // {
430  // if (symbol->GetName() ==
431  // ConstString("_dyld_start"))
432  // process_did_exec = true;
433  // }
434  // }
435  // }
436  }
437  }
438  return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code);
439  }
440  break;
441 
442  case 6: // EXC_BREAKPOINT
443  {
444  bool is_actual_breakpoint = false;
445  bool is_trace_if_actual_breakpoint_missing = false;
446  switch (cpu) {
447  case llvm::Triple::x86:
448  case llvm::Triple::x86_64:
449  if (exc_code == 1) // EXC_I386_SGL
450  {
451  if (!exc_sub_code) {
452  // This looks like a plain trap.
453  // Have to check if there is a breakpoint here as well. When you
454  // single-step onto a trap, the single step stops you not to trap.
455  // Since we also do that check below, let's just use that logic.
456  is_actual_breakpoint = true;
457  is_trace_if_actual_breakpoint_missing = true;
458  } else {
459 
460  // It's a watchpoint, then.
461  // The exc_sub_code indicates the data break address.
462  lldb::WatchpointSP wp_sp;
463  if (target)
464  wp_sp = target->GetWatchpointList().FindByAddress(
465  (lldb::addr_t)exc_sub_code);
466  if (wp_sp && wp_sp->IsEnabled()) {
467  // Debugserver may piggyback the hardware index of the fired
468  // watchpoint in the exception data. Set the hardware index if
469  // that's the case.
470  if (exc_data_count >= 3)
471  wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
472  return StopInfo::CreateStopReasonWithWatchpointID(thread,
473  wp_sp->GetID());
474  }
475  }
476  } else if (exc_code == 2 || // EXC_I386_BPT
477  exc_code == 3) // EXC_I386_BPTFLT
478  {
479  // KDP returns EXC_I386_BPTFLT for trace breakpoints
480  if (exc_code == 3)
481  is_trace_if_actual_breakpoint_missing = true;
482 
483  is_actual_breakpoint = true;
484  if (!pc_already_adjusted)
485  pc_decrement = 1;
486  }
487  break;
488 
489  case llvm::Triple::ppc:
490  case llvm::Triple::ppc64:
491  is_actual_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT
492  break;
493 
494  case llvm::Triple::arm:
495  case llvm::Triple::thumb:
496  if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
497  {
498  // It's a watchpoint, then, if the exc_sub_code indicates a
499  // known/enabled data break address from our watchpoint list.
500  lldb::WatchpointSP wp_sp;
501  if (target)
502  wp_sp = target->GetWatchpointList().FindByAddress(
503  (lldb::addr_t)exc_sub_code);
504  if (wp_sp && wp_sp->IsEnabled()) {
505  // Debugserver may piggyback the hardware index of the fired
506  // watchpoint in the exception data. Set the hardware index if
507  // that's the case.
508  if (exc_data_count >= 3)
509  wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
510  return StopInfo::CreateStopReasonWithWatchpointID(thread,
511  wp_sp->GetID());
512  } else {
513  is_actual_breakpoint = true;
514  is_trace_if_actual_breakpoint_missing = true;
515  }
516  } else if (exc_code == 1) // EXC_ARM_BREAKPOINT
517  {
518  is_actual_breakpoint = true;
519  is_trace_if_actual_breakpoint_missing = true;
520  } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel
521  // is currently returning this so accept it
522  // as indicating a breakpoint until the
523  // kernel is fixed
524  {
525  is_actual_breakpoint = true;
526  is_trace_if_actual_breakpoint_missing = true;
527  }
528  break;
529 
530  case llvm::Triple::aarch64: {
531  if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT
532  {
533  // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0
534  // is set
535  is_actual_breakpoint = false;
536  is_trace_if_actual_breakpoint_missing = true;
537  }
538  if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
539  {
540  // It's a watchpoint, then, if the exc_sub_code indicates a
541  // known/enabled data break address from our watchpoint list.
542  lldb::WatchpointSP wp_sp;
543  if (target)
544  wp_sp = target->GetWatchpointList().FindByAddress(
545  (lldb::addr_t)exc_sub_code);
546  if (wp_sp && wp_sp->IsEnabled()) {
547  // Debugserver may piggyback the hardware index of the fired
548  // watchpoint in the exception data. Set the hardware index if
549  // that's the case.
550  if (exc_data_count >= 3)
551  wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
552  return StopInfo::CreateStopReasonWithWatchpointID(thread,
553  wp_sp->GetID());
554  }
555  // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as
556  // EXC_BAD_ACCESS
557  if (thread.GetTemporaryResumeState() == eStateStepping)
558  return StopInfo::CreateStopReasonToTrace(thread);
559  }
560  // It looks like exc_sub_code has the 4 bytes of the instruction that
561  // triggered the exception, i.e. our breakpoint opcode
562  is_actual_breakpoint = exc_code == 1;
563  break;
564  }
565 
566  default:
567  break;
568  }
569 
570  if (is_actual_breakpoint) {
571  RegisterContextSP reg_ctx_sp(thread.GetRegisterContext());
572  addr_t pc = reg_ctx_sp->GetPC() - pc_decrement;
573 
574  ProcessSP process_sp(thread.CalculateProcess());
575 
576  lldb::BreakpointSiteSP bp_site_sp;
577  if (process_sp)
578  bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
579  if (bp_site_sp && bp_site_sp->IsEnabled()) {
580  // Update the PC if we were asked to do so, but only do so if we find
581  // a breakpoint that we know about cause this could be a trap
582  // instruction in the code
583  if (pc_decrement > 0 && adjust_pc_if_needed)
584  reg_ctx_sp->SetPC(pc);
585 
586  // If the breakpoint is for this thread, then we'll report the hit,
587  // but if it is for another thread, we can just report no reason. We
588  // don't need to worry about stepping over the breakpoint here, that
589  // will be taken care of when the thread resumes and notices that
590  // there's a breakpoint under the pc. If we have an operating system
591  // plug-in, we might have set a thread specific breakpoint using the
592  // operating system thread ID, so we can't make any assumptions about
593  // the thread ID so we must always report the breakpoint regardless
594  // of the thread.
595  if (bp_site_sp->ValidForThisThread(&thread) ||
596  thread.GetProcess()->GetOperatingSystem() != NULL)
597  return StopInfo::CreateStopReasonWithBreakpointSiteID(
598  thread, bp_site_sp->GetID());
599  else if (is_trace_if_actual_breakpoint_missing)
600  return StopInfo::CreateStopReasonToTrace(thread);
601  else
602  return StopInfoSP();
603  }
604 
605  // Don't call this a trace if we weren't single stepping this thread.
606  if (is_trace_if_actual_breakpoint_missing &&
608  return StopInfo::CreateStopReasonToTrace(thread);
609  }
610  }
611  } break;
612 
613  case 7: // EXC_SYSCALL
614  case 8: // EXC_MACH_SYSCALL
615  case 9: // EXC_RPC_ALERT
616  case 10: // EXC_CRASH
617  break;
618  }
619 
620  return StopInfoSP(new StopInfoMachException(
621  thread, exc_type, exc_data_count, exc_code, exc_sub_code));
622  }
623  return StopInfoSP();
624 }
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
const ArchSpec & GetArchitecture() const
Definition: Target.h:941
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:49
virtual bool ProcessDidExec()
Helper function that can be used to detect when a process has called exec and is now a new and differ...
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
llvm::StringRef GetString() const
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb::ProcessSP CalculateProcess() override
Definition: Thread.cpp:1592
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
Process or thread is in the process of stepping and can not be examined.
lldb::ProcessSP GetProcess() const
Definition: Thread.h:154
A plug-in interface definition class for dynamic loaders.
Definition: DynamicLoader.h:64
size_t PutChar(char ch)
Definition: Stream.cpp:103
uint64_t addr_t
Definition: lldb-types.h:83
Definition: SBAddress.h:15
lldb::StateType GetTemporaryResumeState() const
Definition: Thread.h:1127
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:726