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