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