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/Core/ArchSpec.h"
17 #include "lldb/Core/StreamString.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Target/Thread.h"
22 #include "lldb/Target/ThreadPlan.h"
23 #include "lldb/Target/UnixSignals.h"
24 
25 using namespace lldb;
26 using namespace lldb_private;
27 
28 const char *
29 StopInfoMachException::GetDescription ()
30 {
31     if (m_description.empty() && m_value != 0)
32     {
33         ArchSpec::CPU cpu = m_thread.GetProcess().GetTarget().GetArchitecture().GetGenericCPUType();
34 
35         const char *exc_desc = NULL;
36         const char *code_label = "code";
37         const char *code_desc = NULL;
38         const char *subcode_label = "subcode";
39         const char *subcode_desc = NULL;
40         switch (m_value)
41         {
42         case 1: // EXC_BAD_ACCESS
43             exc_desc = "EXC_BAD_ACCESS";
44             subcode_label = "address";
45             switch (cpu)
46             {
47             case ArchSpec::eCPU_arm:
48                 switch (m_exc_code)
49                 {
50                 case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
51                 case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
52                 }
53                 break;
54 
55             case ArchSpec::eCPU_ppc:
56             case ArchSpec::eCPU_ppc64:
57                 switch (m_exc_code)
58                 {
59                 case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break;
60                 case 0x102: code_desc = "EXC_PPC_BADSPACE";     break;
61                 case 0x103: code_desc = "EXC_PPC_UNALIGNED";    break;
62                 }
63                 break;
64 
65             default:
66                 break;
67             }
68             break;
69 
70         case 2: // EXC_BAD_INSTRUCTION
71             exc_desc = "EXC_BAD_INSTRUCTION";
72             switch (cpu)
73             {
74             case ArchSpec::eCPU_i386:
75             case ArchSpec::eCPU_x86_64:
76                 if (m_exc_code == 1)
77                     code_desc = "EXC_I386_INVOP";
78                 break;
79 
80             case ArchSpec::eCPU_ppc:
81             case ArchSpec::eCPU_ppc64:
82                 switch (m_exc_code)
83                 {
84                 case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break;
85                 case 2: code_desc = "EXC_PPC_UNIPL_INST"; break;
86                 case 3: code_desc = "EXC_PPC_PRIVINST"; break;
87                 case 4: code_desc = "EXC_PPC_PRIVREG"; break;
88                 case 5: code_desc = "EXC_PPC_TRACE"; break;
89                 case 6: code_desc = "EXC_PPC_PERFMON"; break;
90                 }
91                 break;
92 
93             case ArchSpec::eCPU_arm:
94                 if (m_exc_code == 1)
95                     code_desc = "EXC_ARM_UNDEFINED";
96                 break;
97 
98             default:
99                 break;
100             }
101             break;
102 
103         case 3: // EXC_ARITHMETIC
104             exc_desc = "EXC_ARITHMETIC";
105             switch (cpu)
106             {
107             case ArchSpec::eCPU_i386:
108             case ArchSpec::eCPU_x86_64:
109                 switch (m_exc_code)
110                 {
111                 case 1: code_desc = "EXC_I386_DIV"; break;
112                 case 2: code_desc = "EXC_I386_INTO"; break;
113                 case 3: code_desc = "EXC_I386_NOEXT"; break;
114                 case 4: code_desc = "EXC_I386_EXTOVR"; break;
115                 case 5: code_desc = "EXC_I386_EXTERR"; break;
116                 case 6: code_desc = "EXC_I386_EMERR"; break;
117                 case 7: code_desc = "EXC_I386_BOUND"; break;
118                 case 8: code_desc = "EXC_I386_SSEEXTERR"; break;
119                 }
120                 break;
121 
122             case ArchSpec::eCPU_ppc:
123             case ArchSpec::eCPU_ppc64:
124                 switch (m_exc_code)
125                 {
126                 case 1: code_desc = "EXC_PPC_OVERFLOW"; break;
127                 case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break;
128                 case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break;
129                 case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break;
130                 case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break;
131                 case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break;
132                 case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break;
133                 }
134                 break;
135 
136             default:
137                 break;
138             }
139             break;
140 
141         case 4: // EXC_EMULATION
142             exc_desc = "EXC_EMULATION";
143             break;
144 
145 
146         case 5: // EXC_SOFTWARE
147             exc_desc = "EXC_SOFTWARE";
148             if (m_exc_code == 0x10003)
149             {
150                 subcode_desc = "EXC_SOFT_SIGNAL";
151                 subcode_label = "signo";
152             }
153             break;
154 
155         case 6: // EXC_BREAKPOINT
156             {
157                 exc_desc = "EXC_BREAKPOINT";
158                 switch (cpu)
159                 {
160                 case ArchSpec::eCPU_i386:
161                 case ArchSpec::eCPU_x86_64:
162                     switch (m_exc_code)
163                     {
164                     case 1: subcode_desc = "EXC_I386_SGL"; break;
165                     case 2: subcode_desc = "EXC_I386_BPT"; break;
166                     }
167                     break;
168 
169                 case ArchSpec::eCPU_ppc:
170                 case ArchSpec::eCPU_ppc64:
171                     switch (m_exc_code)
172                     {
173                     case 1: subcode_desc = "EXC_PPC_BREAKPOINT"; break;
174                     }
175                     break;
176 
177                 case ArchSpec::eCPU_arm:
178                     switch (m_exc_code)
179                     {
180                     case 1: subcode_desc = "EXC_ARM_BREAKPOINT"; break;
181                     }
182                     break;
183 
184                 default:
185                     break;
186                 }
187             }
188             break;
189 
190         case 7:
191             exc_desc = "EXC_SYSCALL";
192             break;
193 
194         case 8:
195             exc_desc = "EXC_MACH_SYSCALL";
196             break;
197 
198         case 9:
199             exc_desc = "EXC_RPC_ALERT";
200             break;
201 
202         case 10:
203             exc_desc = "EXC_CRASH";
204             break;
205         }
206 
207         StreamString strm;
208 
209         if (exc_desc)
210             strm.PutCString(exc_desc);
211         else
212             strm.Printf("EXC_??? (%llu)", m_value);
213 
214         if (m_exc_data_count >= 1)
215         {
216             if (code_desc)
217                 strm.Printf(" (%s=%s", code_label, code_desc);
218             else
219                 strm.Printf(" (%s=%llu", code_label, m_exc_code);
220         }
221 
222         if (m_exc_data_count >= 2)
223         {
224             if (subcode_desc)
225                 strm.Printf(", %s=%s", subcode_label, subcode_desc);
226             else
227                 strm.Printf(", %s=0x%llx", subcode_label, m_exc_subcode);
228         }
229 
230         if (m_exc_data_count > 0)
231             strm.PutChar(')');
232 
233         m_description.swap (strm.GetString());
234     }
235     return m_description.c_str();
236 }
237 
238 
239 StopInfoSP
240 StopInfoMachException::CreateStopReasonWithMachException
241 (
242     Thread &thread,
243     uint32_t exc_type,
244     uint32_t exc_data_count,
245     uint64_t exc_code,
246     uint64_t exc_sub_code
247 )
248 {
249     if (exc_type != 0)
250     {
251         ArchSpec::CPU cpu = thread.GetProcess().GetTarget().GetArchitecture().GetGenericCPUType();
252 
253         switch (exc_type)
254         {
255         case 1: // EXC_BAD_ACCESS
256             break;
257 
258         case 2: // EXC_BAD_INSTRUCTION
259             switch (cpu)
260             {
261             case ArchSpec::eCPU_ppc:
262             case ArchSpec::eCPU_ppc64:
263                 switch (exc_code)
264                 {
265                 case 1: // EXC_PPC_INVALID_SYSCALL
266                 case 2: // EXC_PPC_UNIPL_INST
267                 case 3: // EXC_PPC_PRIVINST
268                 case 4: // EXC_PPC_PRIVREG
269                     break;
270                 case 5: // EXC_PPC_TRACE
271                     return StopInfo::CreateStopReasonToTrace (thread);
272                 case 6: // EXC_PPC_PERFMON
273                     break;
274                 }
275                 break;
276 
277             default:
278                 break;
279             }
280             break;
281 
282         case 3: // EXC_ARITHMETIC
283         case 4: // EXC_EMULATION
284             break;
285 
286         case 5: // EXC_SOFTWARE
287             if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
288                 return StopInfo::CreateStopReasonWithSignal (thread, exc_sub_code);
289             break;
290 
291         case 6: // EXC_BREAKPOINT
292             {
293                 bool is_software_breakpoint = false;
294                 switch (cpu)
295                 {
296                 case ArchSpec::eCPU_i386:
297                 case ArchSpec::eCPU_x86_64:
298                     if (exc_code == 1) // EXC_I386_SGL
299                     {
300                         return StopInfo::CreateStopReasonToTrace(thread);
301                     }
302                     else if (exc_code == 2) // EXC_I386_BPT
303                     {
304                         is_software_breakpoint = true;
305                     }
306                     break;
307 
308                 case ArchSpec::eCPU_ppc:
309                 case ArchSpec::eCPU_ppc64:
310                     is_software_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT
311                     break;
312 
313                 case ArchSpec::eCPU_arm:
314                     is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT
315                     break;
316 
317                 default:
318                     break;
319                 }
320 
321                 if (is_software_breakpoint)
322                 {
323                     addr_t pc = thread.GetRegisterContext()->GetPC();
324                     lldb::BreakpointSiteSP bp_site_sp = thread.GetProcess().GetBreakpointSiteList().FindByAddress(pc);
325                     if (bp_site_sp)
326                     {
327                         // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
328                         // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that
329                         // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
330                         if (bp_site_sp->ValidForThisThread (&thread))
331                             return StopInfo::CreateStopReasonWithBreakpointSiteID (thread, bp_site_sp->GetID());
332                         else
333                             return StopInfoSP();
334                     }
335 
336                 }
337             }
338             break;
339 
340         case 7:     // EXC_SYSCALL
341         case 8:     // EXC_MACH_SYSCALL
342         case 9:     // EXC_RPC_ALERT
343         case 10:    // EXC_CRASH
344             break;
345         }
346 
347         return StopInfoSP(new StopInfoMachException (thread, exc_type, exc_data_count, exc_code, exc_sub_code));
348     }
349     return StopInfoSP();
350 }
351